@axhub/genie 0.2.5 → 0.2.7
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.
- package/dist/assets/App-BWSqiXAT.js +220 -0
- package/dist/assets/App-DrlLKa8f.css +1 -0
- package/dist/assets/ReviewApp-nz3mbArg.js +1 -0
- package/dist/assets/{_basePickBy-CFRQvihx.js → _basePickBy-C19AekOu.js} +1 -1
- package/dist/assets/{_baseUniq-Dhh8nCvs.js → _baseUniq-JsnevLw_.js} +1 -1
- package/dist/assets/{arc-DQ0v3dU4.js → arc-BLpcuBlf.js} +1 -1
- package/dist/assets/architectureDiagram-2XIMDMQ5-CarjBOOv.js +36 -0
- package/dist/assets/{blockDiagram-WCTKOSBZ-Bbxhj5KC.js → blockDiagram-WCTKOSBZ-DQBLwsUS.js} +3 -3
- package/dist/assets/c4Diagram-IC4MRINW-CGobwBIj.js +10 -0
- package/dist/assets/channel-DkFNxV_H.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-DlvtrM0q.js → chunk-4BX2VUAB-De63kbgc.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DJUSHyTa.js → chunk-55IACEB6-DtTDDdM9.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-C6Ch-htf.js → chunk-FMBD7UC4-DHuwd8tw.js} +1 -1
- package/dist/assets/{chunk-JSJVCQXG-DzQIht58.js → chunk-JSJVCQXG-BgytFtmO.js} +1 -1
- package/dist/assets/{chunk-KX2RTZJC-C05jARMH.js → chunk-KX2RTZJC-nZdp86aN.js} +1 -1
- package/dist/assets/chunk-NQ4KR5QH-CMH6EDP2.js +220 -0
- package/dist/assets/{chunk-QZHKN3VN-jxti9HTX.js → chunk-QZHKN3VN-DvUQ3mnO.js} +1 -1
- package/dist/assets/chunk-WL4C6EOR-Dn7db_6t.js +189 -0
- package/dist/assets/classDiagram-VBA2DB6C-DtwCEe8S.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-DtwCEe8S.js +1 -0
- package/dist/assets/clone-C0lCEIEO.js +1 -0
- package/dist/assets/cose-bilkent-S5V4N54A-DD_nzqsz.js +1 -0
- package/dist/assets/cytoscape.esm-5J0xJHOV.js +321 -0
- package/dist/assets/{dagre-KLK3FWXG-DJ3dNSYk.js → dagre-KLK3FWXG-CHYIvW47.js} +1 -1
- package/dist/assets/diagram-E7M64L7V-TVdvHtGc.js +24 -0
- package/dist/assets/{diagram-IFDJBPK2-Da6K4aP-.js → diagram-IFDJBPK2-Dzsiln_C.js} +1 -1
- package/dist/assets/{diagram-P4PSJMXO-vZZKB92A.js → diagram-P4PSJMXO-DKnGbUpE.js} +1 -1
- package/dist/assets/erDiagram-INFDFZHY-5Kw0bByo.js +70 -0
- package/dist/assets/{flowDiagram-PKNHOUZH-DUV13pHi.js → flowDiagram-PKNHOUZH-BAZ2-jKp.js} +4 -4
- package/dist/assets/ganttDiagram-A5KZAMGK-CsADFkcq.js +292 -0
- package/dist/assets/{gitGraphDiagram-K3NZZRJ6-BZ5gW69I.js → gitGraphDiagram-K3NZZRJ6-BflpyjGy.js} +1 -1
- package/dist/assets/{graph-BbvHswRd.js → graph-suelaXFh.js} +1 -1
- package/dist/assets/highlighted-body-OFNGDK62-CZrBMazC.js +1 -0
- package/dist/assets/index-B01NxbUv.css +1 -0
- package/dist/assets/index-DW5pGgQ_.js +2 -0
- package/dist/assets/{infoDiagram-LFFYTUFH-8auUIPKW.js → infoDiagram-LFFYTUFH-pfD1FA3p.js} +1 -1
- package/dist/assets/ishikawaDiagram-PHBUUO56-ndm9snwO.js +70 -0
- package/dist/assets/journeyDiagram-4ABVD52K-HgF2t7z5.js +139 -0
- package/dist/assets/{kanban-definition-K7BYSVSG-Bappd2YO.js → kanban-definition-K7BYSVSG-FWinmur1.js} +5 -5
- package/dist/assets/{layout-BmbfFZKy.js → layout-vcz43XvZ.js} +1 -1
- package/dist/assets/{linear-WZnF-PT6.js → linear-le4gc0vx.js} +1 -1
- package/dist/assets/mermaid-GHXKKRXX-CK8m3lad.js +870 -0
- package/dist/assets/mindmap-definition-YRQLILUH-CNq9SKj4.js +68 -0
- package/dist/assets/{pieDiagram-SKSYHLDU-uxjlAy1t.js → pieDiagram-SKSYHLDU-C7PKDh3b.js} +2 -2
- package/dist/assets/quadrantDiagram-337W2JSQ-B7FnztNO.js +7 -0
- package/dist/assets/requirementDiagram-Z7DCOOCP-Bl_BM2Th.js +73 -0
- package/dist/assets/{sankeyDiagram-WA2Y5GQK-2-FHHM-R.js → sankeyDiagram-WA2Y5GQK-4gulcOP4.js} +3 -3
- package/dist/assets/sequenceDiagram-2WXFIKYE-VEuJDwyJ.js +145 -0
- package/dist/assets/{stateDiagram-RAJIS63D-DoW8U53H.js → stateDiagram-RAJIS63D-CB4Vl7qM.js} +1 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-C85ucl39.js +1 -0
- package/dist/assets/timeline-definition-YZTLITO2-BPGKhi7f.js +61 -0
- package/dist/assets/{treemap-KZPCXAKY-ajdAP-72.js → treemap-KZPCXAKY-DZSEE6Hz.js} +58 -58
- package/dist/assets/vendor-codemirror-CyOKkaQZ.js +31 -0
- package/dist/assets/vendor-react-CP4yFTs7.js +8 -0
- package/dist/assets/vendor-xterm-DfcmCpbH.js +66 -0
- package/dist/assets/{vennDiagram-LZ73GAT5-C9If0AT0.js → vennDiagram-LZ73GAT5-8E_G06fI.js} +4 -4
- package/dist/assets/xychartDiagram-JWTSCODW-CbBk50-O.js +7 -0
- package/dist/favicon.png +0 -0
- package/dist/icons/icon-128x128.png +0 -0
- package/dist/icons/icon-144x144.png +0 -0
- package/dist/icons/icon-152x152.png +0 -0
- package/dist/icons/icon-192x192.png +0 -0
- package/dist/icons/icon-384x384.png +0 -0
- package/dist/icons/icon-512x512.png +0 -0
- package/dist/icons/icon-72x72.png +0 -0
- package/dist/icons/icon-96x96.png +0 -0
- package/dist/index.html +4 -5
- package/dist/logo-128.png +0 -0
- package/dist/logo-256.png +0 -0
- package/dist/logo-32.png +0 -0
- package/dist/logo-512.png +0 -0
- package/dist/logo-64.png +0 -0
- package/package.json +2 -1
- package/server/_legacy-providers/README.md +30 -0
- package/server/_legacy-providers/claude-sdk.js +956 -0
- package/server/_legacy-providers/gemini-cli.js +368 -0
- package/server/_legacy-providers/openai-codex.js +705 -0
- package/server/_legacy-providers/opencode-cli.js +674 -0
- package/server/acp-runtime/client.js +1805 -0
- package/server/acp-runtime/client.test.js +688 -0
- package/server/acp-runtime/index.js +419 -0
- package/server/acp-runtime/registry.js +45 -0
- package/server/acp-runtime/session-store.js +254 -0
- package/server/acp-runtime/session-store.test.js +89 -0
- package/server/channels/runtime/AgentRuntimeAdapter.js +21 -70
- package/server/claude-sdk.js +24 -944
- package/server/cli.js +11 -5
- package/server/external-agent/service.js +77 -63
- package/server/gemini-cli.js +23 -360
- package/server/index.js +54 -46
- package/server/openai-codex.js +24 -698
- package/server/opencode-cli.js +70 -640
- package/server/routes/agent.js +2 -0
- package/server/routes/codex.js +5 -5
- package/server/routes/git.js +3 -20
- package/server/routes/mcp.js +18 -34
- package/server/routes/session-core.js +44 -10
- package/server/session-core/abortSession.js +2 -18
- package/server/session-core/eventStore.js +5 -1
- package/server/session-core/providerAdapters.js +98 -10
- package/server/session-core/providerDiscovery.js +2 -2
- package/server/session-core/runtimeState.js +16 -17
- package/server/session-core/runtimeWriter.js +19 -12
- package/server/utils/codexPath.js +3 -1
- package/server/utils/spawnCommand.js +7 -0
- package/shared/conversationEvents.js +347 -10
- package/shared/conversationEvents.test.js +403 -0
- package/dist/assets/App-BxazfNJn.js +0 -484
- package/dist/assets/App-qxJ8_QYu.css +0 -32
- package/dist/assets/ReviewApp-CsqTAlGU.js +0 -1
- package/dist/assets/architectureDiagram-2XIMDMQ5-DmUHdvQH.js +0 -36
- package/dist/assets/c4Diagram-IC4MRINW-BOivDlQU.js +0 -10
- package/dist/assets/channel-Cj8xVD0X.js +0 -1
- package/dist/assets/chunk-NQ4KR5QH-Ci-n7jfu.js +0 -220
- package/dist/assets/chunk-WL4C6EOR-C559Mk71.js +0 -189
- package/dist/assets/classDiagram-VBA2DB6C-CI2zklxw.js +0 -1
- package/dist/assets/classDiagram-v2-RAHNMMFH-CI2zklxw.js +0 -1
- package/dist/assets/clone-BEVqubrI.js +0 -1
- package/dist/assets/cose-bilkent-S5V4N54A-DNO9ncXL.js +0 -1
- package/dist/assets/cytoscape.esm-2ZfV8NB5.js +0 -331
- package/dist/assets/diagram-E7M64L7V-Ba_LGLun.js +0 -24
- package/dist/assets/erDiagram-INFDFZHY-Csb8dFdP.js +0 -70
- package/dist/assets/ganttDiagram-A5KZAMGK-B5Kv9Wfz.js +0 -292
- package/dist/assets/highlighted-body-TPN3WLV5-DZJajMGm.js +0 -1
- package/dist/assets/index-BFX9lxRB.css +0 -1
- package/dist/assets/index-BiErUGrv.js +0 -2
- package/dist/assets/ishikawaDiagram-PHBUUO56-JmsNlo2I.js +0 -70
- package/dist/assets/journeyDiagram-4ABVD52K-Cuudv7Vv.js +0 -139
- package/dist/assets/mermaid-O7DHMXV3-D-2fQRvw.js +0 -988
- package/dist/assets/mindmap-definition-YRQLILUH-BQHnzzud.js +0 -68
- package/dist/assets/quadrantDiagram-337W2JSQ-DpwZU-f_.js +0 -7
- package/dist/assets/requirementDiagram-Z7DCOOCP-C_9ClOWm.js +0 -73
- package/dist/assets/sequenceDiagram-2WXFIKYE-egns-0XI.js +0 -145
- package/dist/assets/stateDiagram-v2-FVOUBMTO-BoFZZ4Ds.js +0 -1
- package/dist/assets/timeline-definition-YZTLITO2-chPa8ppH.js +0 -61
- package/dist/assets/vendor-codemirror-Dz7_EqNA.js +0 -39
- package/dist/assets/vendor-react-Cpt6D04s.js +0 -59
- package/dist/assets/vendor-xterm-DfaPXD3y.js +0 -66
- package/dist/assets/xychartDiagram-JWTSCODW-DD42U6Or.js +0 -7
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from 'child_process';
|
|
2
|
+
import crossSpawn from 'cross-spawn';
|
|
3
|
+
|
|
4
|
+
export function spawnCommand(command, args = [], options = {}) {
|
|
5
|
+
const spawnImpl = process.platform === 'win32' ? crossSpawn : nodeSpawn;
|
|
6
|
+
return spawnImpl(command, args, options);
|
|
7
|
+
}
|
|
@@ -16,6 +16,7 @@ export const CONVERSATION_EVENT_KINDS = {
|
|
|
16
16
|
ASSISTANT_TEXT_START: 'assistant_text_start',
|
|
17
17
|
ASSISTANT_TEXT_DELTA: 'assistant_text_delta',
|
|
18
18
|
ASSISTANT_TEXT_END: 'assistant_text_end',
|
|
19
|
+
ASSISTANT_CONTENT_BLOCK: 'assistant_content_block',
|
|
19
20
|
REASONING_START: 'reasoning_start',
|
|
20
21
|
REASONING_DELTA: 'reasoning_delta',
|
|
21
22
|
REASONING_END: 'reasoning_end',
|
|
@@ -23,6 +24,9 @@ export const CONVERSATION_EVENT_KINDS = {
|
|
|
23
24
|
TOOL_CALL_INPUT: 'tool_call_input',
|
|
24
25
|
TOOL_CALL_END: 'tool_call_end',
|
|
25
26
|
TOOL_RESULT: 'tool_result',
|
|
27
|
+
PLAN_UPDATE: 'plan_update',
|
|
28
|
+
MODE_UPDATE: 'mode_update',
|
|
29
|
+
AVAILABLE_COMMANDS_UPDATE: 'available_commands_update',
|
|
26
30
|
APPROVAL_REQUEST: 'approval_request',
|
|
27
31
|
APPROVAL_RESOLVED: 'approval_resolved',
|
|
28
32
|
ARTIFACT_CREATED: 'artifact_created',
|
|
@@ -236,6 +240,167 @@ function stringifyToolContent(value) {
|
|
|
236
240
|
}
|
|
237
241
|
}
|
|
238
242
|
|
|
243
|
+
function cloneJsonValue(value) {
|
|
244
|
+
if (value == null) {
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
return JSON.parse(JSON.stringify(value));
|
|
250
|
+
} catch {
|
|
251
|
+
return value;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function normalizeMessageContentBlocks(value) {
|
|
256
|
+
if (!Array.isArray(value)) {
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return value
|
|
261
|
+
.filter((item) => item && typeof item === 'object')
|
|
262
|
+
.map((item) => cloneJsonValue(item));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function getConversationEventClientRequestId(event) {
|
|
266
|
+
const rawValue = event?.extensions?.clientRequestId || event?.payload?.clientRequestId || null;
|
|
267
|
+
return typeof rawValue === 'string' && rawValue.trim()
|
|
268
|
+
? rawValue.trim()
|
|
269
|
+
: null;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function getTimelineMessageClientRequestId(message) {
|
|
273
|
+
const rawValue = message?.clientRequestId || message?.extensions?.clientRequestId || null;
|
|
274
|
+
return typeof rawValue === 'string' && rawValue.trim()
|
|
275
|
+
? rawValue.trim()
|
|
276
|
+
: null;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function buildComparableUserMessageContentBlocks(message = {}) {
|
|
280
|
+
const imageBlocks = Array.isArray(message?.images)
|
|
281
|
+
? message.images.map((image) => ({
|
|
282
|
+
type: 'image',
|
|
283
|
+
data: image?.data || image?.image || '',
|
|
284
|
+
mimeType: image?.mimeType || 'application/octet-stream',
|
|
285
|
+
name: image?.name || image?.filename || ''
|
|
286
|
+
}))
|
|
287
|
+
: [];
|
|
288
|
+
|
|
289
|
+
return [
|
|
290
|
+
...imageBlocks,
|
|
291
|
+
...normalizeMessageContentBlocks(message?.contentBlocks)
|
|
292
|
+
];
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function findMatchingOptimisticUserMessageIndex(messages, event, payload = {}) {
|
|
296
|
+
const clientRequestId = getConversationEventClientRequestId(event);
|
|
297
|
+
if (!clientRequestId) {
|
|
298
|
+
return -1;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const expectedContentBlocks = JSON.stringify(normalizeMessageContentBlocks(payload.contentBlocks));
|
|
302
|
+
|
|
303
|
+
return findLatestTimelineMessageIndex(messages, (message) => {
|
|
304
|
+
if (String(message?.type || '').trim().toLowerCase() !== 'user') {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (getTimelineMessageClientRequestId(message) !== clientRequestId) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (String(message?.content || '') !== String(payload.text || '')) {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const actualContentBlocks = JSON.stringify(buildComparableUserMessageContentBlocks(message));
|
|
317
|
+
return actualContentBlocks === expectedContentBlocks;
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function normalizeAcpModeState(value) {
|
|
322
|
+
if (!value || typeof value !== 'object') {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const availableModes = Array.isArray(value.availableModes)
|
|
327
|
+
? value.availableModes
|
|
328
|
+
.filter((mode) => mode && typeof mode === 'object' && String(mode.id || '').trim())
|
|
329
|
+
.map((mode) => ({
|
|
330
|
+
id: String(mode.id).trim(),
|
|
331
|
+
name: String(mode.name || mode.id || '').trim() || String(mode.id).trim(),
|
|
332
|
+
description: mode.description == null ? null : String(mode.description)
|
|
333
|
+
}))
|
|
334
|
+
: [];
|
|
335
|
+
const currentModeId = typeof value.currentModeId === 'string' && value.currentModeId.trim()
|
|
336
|
+
? value.currentModeId.trim()
|
|
337
|
+
: null;
|
|
338
|
+
|
|
339
|
+
if (!availableModes.length && !currentModeId) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
availableModes,
|
|
345
|
+
currentModeId: currentModeId || availableModes[0]?.id || null
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function normalizeAcpAvailableCommands(value) {
|
|
350
|
+
const commands = Array.isArray(value?.availableCommands)
|
|
351
|
+
? value.availableCommands
|
|
352
|
+
: Array.isArray(value)
|
|
353
|
+
? value
|
|
354
|
+
: [];
|
|
355
|
+
|
|
356
|
+
return commands
|
|
357
|
+
.filter((command) => command && typeof command === 'object' && String(command.name || '').trim())
|
|
358
|
+
.map((command) => ({
|
|
359
|
+
name: String(command.name).trim(),
|
|
360
|
+
description: command.description == null ? '' : String(command.description),
|
|
361
|
+
input: command.input && typeof command.input === 'object' ? cloneJsonValue(command.input) : null,
|
|
362
|
+
source: 'acp',
|
|
363
|
+
namespace: 'acp',
|
|
364
|
+
type: 'acp'
|
|
365
|
+
}));
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function mergeToolCallSnapshot(existingSnapshot = null, payload = {}) {
|
|
369
|
+
const nextSnapshot = existingSnapshot && typeof existingSnapshot === 'object'
|
|
370
|
+
? { ...existingSnapshot }
|
|
371
|
+
: {};
|
|
372
|
+
|
|
373
|
+
if (payload.title != null) {
|
|
374
|
+
nextSnapshot.title = String(payload.title);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (payload.kind != null) {
|
|
378
|
+
nextSnapshot.kind = String(payload.kind);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (payload.status != null) {
|
|
382
|
+
nextSnapshot.status = String(payload.status);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (payload.rawInput !== undefined) {
|
|
386
|
+
nextSnapshot.rawInput = cloneJsonValue(payload.rawInput);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (payload.rawOutput !== undefined) {
|
|
390
|
+
nextSnapshot.rawOutput = cloneJsonValue(payload.rawOutput);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (Array.isArray(payload.contentBlocks)) {
|
|
394
|
+
nextSnapshot.content = cloneJsonValue(payload.contentBlocks);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (Array.isArray(payload.locations)) {
|
|
398
|
+
nextSnapshot.locations = cloneJsonValue(payload.locations);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return Object.keys(nextSnapshot).length > 0 ? nextSnapshot : null;
|
|
402
|
+
}
|
|
403
|
+
|
|
239
404
|
function collectClaudeToolResults(rawMessages) {
|
|
240
405
|
const toolResults = new Map();
|
|
241
406
|
for (const msg of rawMessages || []) {
|
|
@@ -279,7 +444,6 @@ function ensureStreamingTextMessage(messages, {
|
|
|
279
444
|
}) {
|
|
280
445
|
const index = findLatestTimelineMessageIndex(messages, (message) => (
|
|
281
446
|
message?.eventMessageId === messageId &&
|
|
282
|
-
!!message?.isStreaming &&
|
|
283
447
|
!message.isToolUse &&
|
|
284
448
|
!!message.isThinking === !!isThinking
|
|
285
449
|
));
|
|
@@ -310,6 +474,40 @@ function ensureStreamingTextMessage(messages, {
|
|
|
310
474
|
return { messages, index: messages.length - 1 };
|
|
311
475
|
}
|
|
312
476
|
|
|
477
|
+
function ensureConversationMessage(messages, {
|
|
478
|
+
messageId,
|
|
479
|
+
timestamp,
|
|
480
|
+
provider,
|
|
481
|
+
role = 'assistant'
|
|
482
|
+
}) {
|
|
483
|
+
const index = findLatestTimelineMessageIndex(messages, (message) => (
|
|
484
|
+
message?.eventMessageId === messageId &&
|
|
485
|
+
!message.isToolUse &&
|
|
486
|
+
!message.isThinking &&
|
|
487
|
+
String(message?.type || '').trim().toLowerCase() === String(role || 'assistant').trim().toLowerCase()
|
|
488
|
+
));
|
|
489
|
+
|
|
490
|
+
if (index >= 0) {
|
|
491
|
+
const existing = { ...messages[index] };
|
|
492
|
+
if (provider) existing.provider = provider;
|
|
493
|
+
if (timestamp && !existing.timestamp) existing.timestamp = timestamp;
|
|
494
|
+
messages[index] = existing;
|
|
495
|
+
return { messages, index };
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
messages.push({
|
|
499
|
+
type: role,
|
|
500
|
+
content: '',
|
|
501
|
+
timestamp,
|
|
502
|
+
provider,
|
|
503
|
+
isStreaming: false,
|
|
504
|
+
eventMessageId: messageId,
|
|
505
|
+
contentBlocks: []
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
return { messages, index: messages.length - 1 };
|
|
509
|
+
}
|
|
510
|
+
|
|
313
511
|
function ensureToolMessage(messages, {
|
|
314
512
|
toolCallId,
|
|
315
513
|
toolName,
|
|
@@ -458,14 +656,41 @@ export function applyConversationEventToTimelineMessages(messages = [], event, s
|
|
|
458
656
|
const payload = event.payload || {};
|
|
459
657
|
|
|
460
658
|
switch (event.kind) {
|
|
461
|
-
case CONVERSATION_EVENT_KINDS.USER_MESSAGE:
|
|
659
|
+
case CONVERSATION_EVENT_KINDS.USER_MESSAGE: {
|
|
660
|
+
const clientRequestId = getConversationEventClientRequestId(event);
|
|
661
|
+
const optimisticIndex = findMatchingOptimisticUserMessageIndex(nextMessages, event, payload);
|
|
662
|
+
const normalizedContentBlocks = normalizeMessageContentBlocks(payload.contentBlocks);
|
|
663
|
+
|
|
664
|
+
if (optimisticIndex >= 0) {
|
|
665
|
+
const existingMessage = nextMessages[optimisticIndex] || {};
|
|
666
|
+
const nextContentBlocks = Array.isArray(existingMessage.images) && existingMessage.images.length > 0
|
|
667
|
+
? normalizedContentBlocks.filter((block) => block?.type !== 'image')
|
|
668
|
+
: normalizedContentBlocks;
|
|
669
|
+
|
|
670
|
+
nextMessages[optimisticIndex] = {
|
|
671
|
+
...existingMessage,
|
|
672
|
+
type: 'user',
|
|
673
|
+
content: payload.text || existingMessage.content || '',
|
|
674
|
+
timestamp: existingMessage.timestamp || timestamp,
|
|
675
|
+
provider,
|
|
676
|
+
contentBlocks: nextContentBlocks,
|
|
677
|
+
clientRequestId: clientRequestId || existingMessage.clientRequestId || null,
|
|
678
|
+
eventId: event.eventId || existingMessage.eventId,
|
|
679
|
+
id: existingMessage.id || event.eventId || existingMessage.id
|
|
680
|
+
};
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
|
|
462
684
|
nextMessages.push({
|
|
463
685
|
type: 'user',
|
|
464
686
|
content: payload.text || '',
|
|
465
687
|
timestamp,
|
|
466
|
-
provider
|
|
688
|
+
provider,
|
|
689
|
+
contentBlocks: normalizedContentBlocks,
|
|
690
|
+
clientRequestId
|
|
467
691
|
});
|
|
468
692
|
break;
|
|
693
|
+
}
|
|
469
694
|
|
|
470
695
|
case CONVERSATION_EVENT_KINDS.ASSISTANT_TEXT_START: {
|
|
471
696
|
const messageId = payload.messageId || event.extensions?.messageId || createEventId('assistant_text');
|
|
@@ -496,6 +721,26 @@ export function applyConversationEventToTimelineMessages(messages = [], event, s
|
|
|
496
721
|
break;
|
|
497
722
|
}
|
|
498
723
|
|
|
724
|
+
case CONVERSATION_EVENT_KINDS.ASSISTANT_CONTENT_BLOCK: {
|
|
725
|
+
const messageId = payload.messageId || event.extensions?.messageId || createEventId('assistant_content');
|
|
726
|
+
const { index } = ensureConversationMessage(nextMessages, {
|
|
727
|
+
messageId,
|
|
728
|
+
timestamp,
|
|
729
|
+
provider,
|
|
730
|
+
role: 'assistant'
|
|
731
|
+
});
|
|
732
|
+
const target = { ...nextMessages[index] };
|
|
733
|
+
const nextBlocks = Array.isArray(target.contentBlocks) ? [...target.contentBlocks] : [];
|
|
734
|
+
if (payload.contentBlock && typeof payload.contentBlock === 'object') {
|
|
735
|
+
nextBlocks.push(cloneJsonValue(payload.contentBlock));
|
|
736
|
+
}
|
|
737
|
+
target.contentBlocks = nextBlocks;
|
|
738
|
+
target.provider = target.provider || provider;
|
|
739
|
+
target.timestamp = target.timestamp || timestamp;
|
|
740
|
+
nextMessages[index] = target;
|
|
741
|
+
break;
|
|
742
|
+
}
|
|
743
|
+
|
|
499
744
|
case CONVERSATION_EVENT_KINDS.REASONING_START: {
|
|
500
745
|
const messageId = payload.messageId || event.extensions?.messageId || createEventId('reasoning');
|
|
501
746
|
ensureStreamingTextMessage(nextMessages, { messageId, timestamp, provider, isThinking: true });
|
|
@@ -534,7 +779,11 @@ export function applyConversationEventToTimelineMessages(messages = [], event, s
|
|
|
534
779
|
timestamp,
|
|
535
780
|
provider
|
|
536
781
|
});
|
|
537
|
-
nextMessages[index] = {
|
|
782
|
+
nextMessages[index] = {
|
|
783
|
+
...nextMessages[index],
|
|
784
|
+
toolName: payload.toolName || nextMessages[index].toolName,
|
|
785
|
+
acpToolCall: mergeToolCallSnapshot(nextMessages[index].acpToolCall, payload)
|
|
786
|
+
};
|
|
538
787
|
break;
|
|
539
788
|
}
|
|
540
789
|
|
|
@@ -548,8 +797,13 @@ export function applyConversationEventToTimelineMessages(messages = [], event, s
|
|
|
548
797
|
});
|
|
549
798
|
nextMessages[index] = {
|
|
550
799
|
...nextMessages[index],
|
|
551
|
-
toolInput:
|
|
552
|
-
|
|
800
|
+
toolInput: payload.input !== undefined
|
|
801
|
+
? stringifyToolContent(payload.input)
|
|
802
|
+
: payload.rawInput !== undefined
|
|
803
|
+
? stringifyToolContent(payload.rawInput)
|
|
804
|
+
: nextMessages[index].toolInput,
|
|
805
|
+
provider: nextMessages[index].provider || provider,
|
|
806
|
+
acpToolCall: mergeToolCallSnapshot(nextMessages[index].acpToolCall, payload)
|
|
553
807
|
};
|
|
554
808
|
break;
|
|
555
809
|
}
|
|
@@ -563,7 +817,12 @@ export function applyConversationEventToTimelineMessages(messages = [], event, s
|
|
|
563
817
|
timestamp,
|
|
564
818
|
provider
|
|
565
819
|
});
|
|
566
|
-
nextMessages[index] = {
|
|
820
|
+
nextMessages[index] = {
|
|
821
|
+
...nextMessages[index],
|
|
822
|
+
toolName: payload.toolName || nextMessages[index].toolName,
|
|
823
|
+
toolEndedAt: timestamp,
|
|
824
|
+
acpToolCall: mergeToolCallSnapshot(nextMessages[index].acpToolCall, payload)
|
|
825
|
+
};
|
|
567
826
|
break;
|
|
568
827
|
}
|
|
569
828
|
|
|
@@ -578,17 +837,44 @@ export function applyConversationEventToTimelineMessages(messages = [], event, s
|
|
|
578
837
|
nextMessages[index] = {
|
|
579
838
|
...nextMessages[index],
|
|
580
839
|
toolResult: {
|
|
581
|
-
content: stringifyToolContent(payload.content
|
|
840
|
+
content: stringifyToolContent(payload.content ?? ''),
|
|
582
841
|
isError: !!payload.isError,
|
|
583
842
|
toolUseResult: payload.toolUseResult || null,
|
|
843
|
+
rawOutput: payload.rawOutput,
|
|
844
|
+
contentBlocks: Array.isArray(payload.contentBlocks) ? cloneJsonValue(payload.contentBlocks) : null,
|
|
845
|
+
status: payload.status || null,
|
|
584
846
|
timestamp
|
|
585
847
|
},
|
|
586
848
|
toolError: !!payload.isError,
|
|
587
|
-
|
|
849
|
+
toolEndedAt: nextMessages[index].toolEndedAt || timestamp,
|
|
850
|
+
provider: nextMessages[index].provider || provider,
|
|
851
|
+
acpToolCall: mergeToolCallSnapshot(nextMessages[index].acpToolCall, payload)
|
|
588
852
|
};
|
|
589
853
|
break;
|
|
590
854
|
}
|
|
591
855
|
|
|
856
|
+
case CONVERSATION_EVENT_KINDS.PLAN_UPDATE: {
|
|
857
|
+
const planEntries = Array.isArray(payload.entries) ? cloneJsonValue(payload.entries) : [];
|
|
858
|
+
const index = findLatestTimelineMessageIndex(nextMessages, (message) => !!message?.isPlanUpdate);
|
|
859
|
+
const nextPlanMessage = {
|
|
860
|
+
...(index >= 0 ? nextMessages[index] : {}),
|
|
861
|
+
id: (index >= 0 ? nextMessages[index]?.id : null) || `plan:${event.sessionId || provider}`,
|
|
862
|
+
type: 'assistant',
|
|
863
|
+
content: String(payload.message || 'Plan updated'),
|
|
864
|
+
timestamp,
|
|
865
|
+
provider,
|
|
866
|
+
isPlanUpdate: true,
|
|
867
|
+
planEntries
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
if (index >= 0) {
|
|
871
|
+
nextMessages[index] = nextPlanMessage;
|
|
872
|
+
} else {
|
|
873
|
+
nextMessages.push(nextPlanMessage);
|
|
874
|
+
}
|
|
875
|
+
break;
|
|
876
|
+
}
|
|
877
|
+
|
|
592
878
|
case CONVERSATION_EVENT_KINDS.APPROVAL_REQUEST:
|
|
593
879
|
if (payload.message) {
|
|
594
880
|
nextMessages.push({
|
|
@@ -641,6 +927,8 @@ export function applyConversationEventToTimelineMessages(messages = [], event, s
|
|
|
641
927
|
break;
|
|
642
928
|
|
|
643
929
|
case CONVERSATION_EVENT_KINDS.SESSION_STATE_CHANGED:
|
|
930
|
+
case CONVERSATION_EVENT_KINDS.MODE_UPDATE:
|
|
931
|
+
case CONVERSATION_EVENT_KINDS.AVAILABLE_COMMANDS_UPDATE:
|
|
644
932
|
case CONVERSATION_EVENT_KINDS.ARTIFACT_CREATED:
|
|
645
933
|
default:
|
|
646
934
|
break;
|
|
@@ -661,6 +949,39 @@ export function conversationEventsToTimelineMessages(events = [], sessionProvide
|
|
|
661
949
|
);
|
|
662
950
|
}
|
|
663
951
|
|
|
952
|
+
export function extractAcpSessionMetadataFromConversationEvents(events = []) {
|
|
953
|
+
const metadata = {
|
|
954
|
+
modeState: null,
|
|
955
|
+
availableCommands: []
|
|
956
|
+
};
|
|
957
|
+
|
|
958
|
+
for (const event of Array.isArray(events) ? events : []) {
|
|
959
|
+
if (!isConversationEvent(event)) {
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
if (event.kind === CONVERSATION_EVENT_KINDS.MODE_UPDATE) {
|
|
964
|
+
const nextModeState = normalizeAcpModeState(event.payload || {});
|
|
965
|
+
if (nextModeState) {
|
|
966
|
+
metadata.modeState = metadata.modeState
|
|
967
|
+
? {
|
|
968
|
+
availableModes: nextModeState.availableModes.length > 0
|
|
969
|
+
? nextModeState.availableModes
|
|
970
|
+
: metadata.modeState.availableModes,
|
|
971
|
+
currentModeId: nextModeState.currentModeId || metadata.modeState.currentModeId || null
|
|
972
|
+
}
|
|
973
|
+
: nextModeState;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
if (event.kind === CONVERSATION_EVENT_KINDS.AVAILABLE_COMMANDS_UPDATE) {
|
|
978
|
+
metadata.availableCommands = normalizeAcpAvailableCommands(event.payload || {});
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
return metadata;
|
|
983
|
+
}
|
|
984
|
+
|
|
664
985
|
function inferRealtimeMessageId(payload, provider, sessionId, kindPrefix = 'assistant_text') {
|
|
665
986
|
const data = payload?.data || {};
|
|
666
987
|
const idCandidate =
|
|
@@ -736,7 +1057,7 @@ export function normalizeRealtimePayloadToConversationEvents(payload, fallbackPr
|
|
|
736
1057
|
const rawRef = { type: payload.type };
|
|
737
1058
|
|
|
738
1059
|
if (payload.type === 'session-created') {
|
|
739
|
-
|
|
1060
|
+
const events = [
|
|
740
1061
|
createConversationEvent({
|
|
741
1062
|
kind: CONVERSATION_EVENT_KINDS.SESSION_STATE_CHANGED,
|
|
742
1063
|
provider,
|
|
@@ -746,6 +1067,22 @@ export function normalizeRealtimePayloadToConversationEvents(payload, fallbackPr
|
|
|
746
1067
|
rawRef
|
|
747
1068
|
})
|
|
748
1069
|
];
|
|
1070
|
+
|
|
1071
|
+
const initialModeState = normalizeAcpModeState(payload.modes || null);
|
|
1072
|
+
if (initialModeState) {
|
|
1073
|
+
events.push(
|
|
1074
|
+
createConversationEvent({
|
|
1075
|
+
kind: CONVERSATION_EVENT_KINDS.MODE_UPDATE,
|
|
1076
|
+
provider,
|
|
1077
|
+
sessionId,
|
|
1078
|
+
timestamp,
|
|
1079
|
+
payload: initialModeState,
|
|
1080
|
+
rawRef
|
|
1081
|
+
})
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
return events;
|
|
749
1086
|
}
|
|
750
1087
|
|
|
751
1088
|
if (payload.type === 'claude-permission-request') {
|