@axhub/genie 0.2.10 → 0.2.12
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/api-docs.html +2 -2
- package/dist/assets/App-Clb2COtW.js +274 -0
- package/dist/assets/ImagePlaygroundPage-DqhMSbM8.js +106 -0
- package/dist/assets/ImagePlaygroundPage-MEn3NN80.css +1 -0
- package/dist/assets/ReviewApp-CDcLYe-u.js +1 -0
- package/dist/assets/{_basePickBy-DVVb07UV.js → _basePickBy-jUZsM51q.js} +1 -1
- package/dist/assets/{_baseUniq-BtbziL5G.js → _baseUniq-BXglE6_v.js} +1 -1
- package/dist/assets/{arc-BsCC8yBD.js → arc-D-oFCFBv.js} +1 -1
- package/dist/assets/{architectureDiagram-2XIMDMQ5-woFp6eNI.js → architectureDiagram-2XIMDMQ5-DC8bAnQt.js} +1 -1
- package/dist/assets/{blockDiagram-WCTKOSBZ-ya8VAc2k.js → blockDiagram-WCTKOSBZ-C4semIRc.js} +1 -1
- package/dist/assets/{c4Diagram-IC4MRINW-CY1dZmIZ.js → c4Diagram-IC4MRINW-FHj1QO3y.js} +1 -1
- package/dist/assets/channel-BF4woPXX.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-CR1lAd74.js → chunk-4BX2VUAB-D-LjsQ_s.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-CP98WcFC.js → chunk-55IACEB6-DI3j_d7A.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-D9c7ijAB.js → chunk-FMBD7UC4-BEVnaLFN.js} +1 -1
- package/dist/assets/{chunk-JSJVCQXG-DQAGYOn-.js → chunk-JSJVCQXG-CSxpcErk.js} +1 -1
- package/dist/assets/{chunk-KX2RTZJC-BbTXiDq7.js → chunk-KX2RTZJC-BbuhDN4h.js} +1 -1
- package/dist/assets/{chunk-NQ4KR5QH-BI6AX0dr.js → chunk-NQ4KR5QH-C3x61XQa.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-DB3V2Ifo.js → chunk-QZHKN3VN-DxWOFtPh.js} +1 -1
- package/dist/assets/{chunk-WL4C6EOR-DhzTthv6.js → chunk-WL4C6EOR-Bt2OauD2.js} +1 -1
- package/dist/assets/classDiagram-VBA2DB6C-D2kHlnQ7.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-D2kHlnQ7.js +1 -0
- package/dist/assets/clone-CqBvwCJW.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-BQ09ZE2j.js → cose-bilkent-S5V4N54A-Dexadrue.js} +1 -1
- package/dist/assets/{dagre-KLK3FWXG-Dc2ueD_R.js → dagre-KLK3FWXG-F9U4X2xC.js} +1 -1
- package/dist/assets/{diagram-E7M64L7V-DP-LsQoL.js → diagram-E7M64L7V-B3V17aH3.js} +1 -1
- package/dist/assets/{diagram-IFDJBPK2-Cg6r42cB.js → diagram-IFDJBPK2-CdHAmLL1.js} +1 -1
- package/dist/assets/{diagram-P4PSJMXO-aHsfoUZE.js → diagram-P4PSJMXO-CrTNfk8K.js} +1 -1
- package/dist/assets/{erDiagram-INFDFZHY-qBXJ4aAz.js → erDiagram-INFDFZHY-vDh9SWK9.js} +1 -1
- package/dist/assets/{flowDiagram-PKNHOUZH-D_13emJM.js → flowDiagram-PKNHOUZH-DpltMg7L.js} +1 -1
- package/dist/assets/{ganttDiagram-A5KZAMGK-BvIcOLwz.js → ganttDiagram-A5KZAMGK-COTk2xur.js} +1 -1
- package/dist/assets/{gitGraphDiagram-K3NZZRJ6-ad0vvNcU.js → gitGraphDiagram-K3NZZRJ6-BNV7bvvj.js} +1 -1
- package/dist/assets/{graph-CeJCMjan.js → graph-Dkeg9oys.js} +1 -1
- package/dist/assets/{highlighted-body-TPN3WLV5-B_novwSz.js → highlighted-body-TPN3WLV5-DaiQEBwR.js} +1 -1
- package/dist/assets/index-DgGmiqsP.css +1 -0
- package/dist/assets/index-DvA901Vs.js +2 -0
- package/dist/assets/{infoDiagram-LFFYTUFH-lOxAqb3m.js → infoDiagram-LFFYTUFH-CZioW3Gt.js} +1 -1
- package/dist/assets/{ishikawaDiagram-PHBUUO56-DIr-51gj.js → ishikawaDiagram-PHBUUO56-BbqR3i1B.js} +1 -1
- package/dist/assets/{journeyDiagram-4ABVD52K-CYcIW0ZU.js → journeyDiagram-4ABVD52K-wfb-WHzl.js} +1 -1
- package/dist/assets/{kanban-definition-K7BYSVSG-C1ZK616a.js → kanban-definition-K7BYSVSG-B3c4y3VN.js} +1 -1
- package/dist/assets/{layout-CI2RM-v6.js → layout-Xr9Z2VGF.js} +1 -1
- package/dist/assets/{linear-DE7bISck.js → linear-JBmzAJtl.js} +1 -1
- package/dist/assets/{mermaid-O7DHMXV3-XxAJo8EK.js → mermaid-O7DHMXV3-fDuyNLKe.js} +238 -220
- package/dist/assets/{mindmap-definition-YRQLILUH-Dz6EFjmn.js → mindmap-definition-YRQLILUH-B5NTN_jD.js} +1 -1
- package/dist/assets/{pieDiagram-SKSYHLDU-DPpEzUed.js → pieDiagram-SKSYHLDU-CuO98GVu.js} +1 -1
- package/dist/assets/{quadrantDiagram-337W2JSQ-xdoXNet7.js → quadrantDiagram-337W2JSQ-LL3f4vLf.js} +1 -1
- package/dist/assets/{requirementDiagram-Z7DCOOCP-DUq8H3CL.js → requirementDiagram-Z7DCOOCP-Di-2O6LH.js} +1 -1
- package/dist/assets/{sankeyDiagram-WA2Y5GQK-CmqEUxRu.js → sankeyDiagram-WA2Y5GQK-9lHqrXqR.js} +1 -1
- package/dist/assets/{sequenceDiagram-2WXFIKYE-DhtXRNiH.js → sequenceDiagram-2WXFIKYE-BQu-SoGr.js} +1 -1
- package/dist/assets/{stateDiagram-RAJIS63D-Dj0HOlbN.js → stateDiagram-RAJIS63D-BUxvd2BC.js} +1 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-CDVexTiR.js +1 -0
- package/dist/assets/{timeline-definition-YZTLITO2-DUuJzZB5.js → timeline-definition-YZTLITO2-oP47UEU6.js} +1 -1
- package/dist/assets/{treemap-KZPCXAKY-DpYBQ0qr.js → treemap-KZPCXAKY-BRjDo2aE.js} +1 -1
- package/dist/assets/{vendor-codemirror-CMHSJ_9p.js → vendor-codemirror-BiCeS-y4.js} +1 -1
- package/dist/assets/{vendor-react-xmA_f8ig.js → vendor-react-DVlYPmi3.js} +1 -1
- package/dist/assets/{vennDiagram-LZ73GAT5-DpePUyOd.js → vennDiagram-LZ73GAT5-DrRqcDqo.js} +1 -1
- package/dist/assets/{xychartDiagram-JWTSCODW-Cfp1I4_U.js → xychartDiagram-JWTSCODW-DUXrymAi.js} +1 -1
- package/dist/index.html +4 -4
- package/package.json +25 -6
- package/scripts/refresh-acp-default-capabilities.mjs +160 -0
- package/server/acp-runtime/client.js +1137 -181
- package/server/acp-runtime/command-overrides.js +48 -0
- package/server/acp-runtime/index.js +576 -16
- package/server/acp-runtime/registry.js +6 -4
- package/server/acp-runtime/session-store.js +235 -92
- package/server/database/db.js +12 -3
- package/server/external-agent/ws.js +212 -11
- package/server/index.js +156 -53
- package/server/projects-watcher-config.js +4 -0
- package/server/projects.js +485 -125
- package/server/routes/cc-connect.js +5 -4
- package/server/routes/codex.js +24 -0
- package/server/routes/commands.js +166 -10
- package/server/routes/runs.js +641 -0
- package/server/routes/session-core.js +357 -109
- package/server/session-core/eventStore.js +0 -121
- package/server/session-core/providerAdapters.js +644 -163
- package/server/session-core/providerDiscovery.js +66 -38
- package/server/session-core/runRegistry.js +244 -0
- package/server/session-core/runtimeState.js +75 -3
- package/server/session-core/runtimeWriter.js +132 -10
- package/server/utils/codexImagePlayground.js +479 -0
- package/server/utils/localTerminal.js +56 -0
- package/server/utils/shellCommand.js +70 -0
- package/shared/acpCapabilities.js +393 -0
- package/shared/acpDefaultCapabilities.generated.json +141 -0
- package/shared/conversationEvents.js +425 -121
- package/dist/assets/App-CYCCsgwf.js +0 -264
- package/dist/assets/ReviewApp-0srHIXwb.js +0 -1
- package/dist/assets/channel-BMhScXFe.js +0 -1
- package/dist/assets/classDiagram-VBA2DB6C-CMIxlWcT.js +0 -1
- package/dist/assets/classDiagram-v2-RAHNMMFH-CMIxlWcT.js +0 -1
- package/dist/assets/clone-BPqOt4r3.js +0 -1
- package/dist/assets/index-C514cLyb.js +0 -2
- package/dist/assets/index-h1DBl_g3.css +0 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-C9utf5gv.js +0 -1
|
@@ -1,209 +1,690 @@
|
|
|
1
|
-
import { normalizeLegacyHistoryEntries, SUPPORTED_PROVIDERS } from '../../shared/conversationEvents.js';
|
|
2
|
-
import { mergeConversationEventHistories, readMirroredConversationEvents } from './eventStore.js';
|
|
3
1
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
isConversationEvent,
|
|
3
|
+
SUPPORTED_PROVIDERS
|
|
4
|
+
} from '../../shared/conversationEvents.js';
|
|
5
|
+
import {
|
|
6
|
+
disposeManagedAgentClient,
|
|
7
|
+
getOrStartAgentClient,
|
|
8
|
+
isAgentSessionActive,
|
|
9
|
+
retainSessionAgentClient,
|
|
10
|
+
shouldSkipGeminiAutomaticAcpStartup
|
|
11
|
+
} from '../acp-runtime/index.js';
|
|
12
|
+
import { mergeAgentCommandOverrides } from '../acp-runtime/command-overrides.js';
|
|
13
13
|
import {
|
|
14
14
|
findAcpSessionRecord,
|
|
15
|
-
listAcpSessions
|
|
15
|
+
listAcpSessions,
|
|
16
|
+
touchAcpSessionRecord
|
|
16
17
|
} from '../acp-runtime/session-store.js';
|
|
17
|
-
import { mergeSessionLists } from './sessionListMerge.js';
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
function getAgentCommandOverrides(options = {}) {
|
|
20
|
+
return mergeAgentCommandOverrides(
|
|
21
|
+
process.env.AXHUB_ACP_COMMAND_OVERRIDES,
|
|
22
|
+
options.agentCommandOverrides
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function createAcpReplayWriter() {
|
|
27
|
+
const events = [];
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
events,
|
|
31
|
+
send(payload) {
|
|
32
|
+
if (payload?.type === 'conversation-event' && isConversationEvent(payload.event)) {
|
|
33
|
+
events.push(payload.event);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
setSessionId() {},
|
|
37
|
+
getSessionId() {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const acpSessionEventCache = new Map();
|
|
44
|
+
|
|
45
|
+
function createSessionEventCacheKey(provider, sessionId) {
|
|
46
|
+
const normalizedProvider = normalizeProvider(provider);
|
|
47
|
+
const normalizedSessionId = normalizeSessionId(sessionId);
|
|
48
|
+
if (!normalizedProvider || !normalizedSessionId) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return `${normalizedProvider}:${normalizedSessionId}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function cloneJsonValue(value) {
|
|
55
|
+
if (value === undefined) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return JSON.parse(JSON.stringify(value));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function normalizeComparableText(value) {
|
|
63
|
+
return String(value || '').replace(/\r\n/g, '\n').trim();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getEventMessageId(event) {
|
|
67
|
+
const rawValue = event?.payload?.messageId || event?.extensions?.messageId || null;
|
|
68
|
+
return typeof rawValue === 'string' && rawValue.trim() ? rawValue.trim() : null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getUserMessageText(event) {
|
|
72
|
+
return event?.kind === 'user_message'
|
|
73
|
+
? normalizeComparableText(event?.payload?.text)
|
|
74
|
+
: '';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isReplayEvent(event) {
|
|
78
|
+
return Boolean(
|
|
79
|
+
event?.extensions?.runtimeReplay === true ||
|
|
80
|
+
event?.rawRef?.sourceType === 'acp-session-loaded-replay'
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getReplayOriginalTimestamp(event) {
|
|
85
|
+
const rawValue = event?.extensions?.originalTimestamp || event?.payload?.originalTimestamp || null;
|
|
86
|
+
if (typeof rawValue !== 'string' || !rawValue.trim()) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const parsed = Date.parse(rawValue);
|
|
91
|
+
return Number.isFinite(parsed) ? rawValue : null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function getEventSortTime(event) {
|
|
95
|
+
const replayTimestamp = isReplayEvent(event) ? getReplayOriginalTimestamp(event) : null;
|
|
96
|
+
const parsed = Date.parse(replayTimestamp || event?.timestamp || '');
|
|
97
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getEventOrderRank(event) {
|
|
101
|
+
if (event?.kind === 'user_message') {
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
104
|
+
if (
|
|
105
|
+
event?.kind === 'assistant_text_start' ||
|
|
106
|
+
event?.kind === 'assistant_text_delta' ||
|
|
107
|
+
event?.kind === 'assistant_text_end' ||
|
|
108
|
+
event?.kind === 'reasoning_start' ||
|
|
109
|
+
event?.kind === 'reasoning_delta' ||
|
|
110
|
+
event?.kind === 'reasoning_end'
|
|
111
|
+
) {
|
|
112
|
+
return 1;
|
|
113
|
+
}
|
|
114
|
+
if (event?.kind === 'tool_call_start' || event?.kind === 'tool_call_input') {
|
|
115
|
+
return 2;
|
|
116
|
+
}
|
|
117
|
+
if (event?.kind === 'tool_call_end' || event?.kind === 'tool_result') {
|
|
118
|
+
return 3;
|
|
119
|
+
}
|
|
120
|
+
return 4;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function buildEventSignature(event) {
|
|
124
|
+
return JSON.stringify({
|
|
125
|
+
kind: event.kind,
|
|
126
|
+
provider: event.provider,
|
|
127
|
+
sessionId: event.sessionId,
|
|
128
|
+
payload: event.payload || {},
|
|
129
|
+
extensions: event.extensions || {},
|
|
130
|
+
rawRef: event.rawRef || null
|
|
131
|
+
});
|
|
22
132
|
}
|
|
23
133
|
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
event
|
|
134
|
+
function getEventTieBreakerKey(event) {
|
|
135
|
+
if (event?.kind === 'user_message') {
|
|
136
|
+
return getUserMessageText(event);
|
|
137
|
+
}
|
|
138
|
+
if (
|
|
139
|
+
event?.kind === 'assistant_text_start' ||
|
|
27
140
|
event?.kind === 'assistant_text_delta' ||
|
|
28
|
-
event?.kind === '
|
|
141
|
+
event?.kind === 'assistant_text_end' ||
|
|
142
|
+
event?.kind === 'reasoning_start' ||
|
|
29
143
|
event?.kind === 'reasoning_delta' ||
|
|
30
|
-
event?.kind === '
|
|
31
|
-
|
|
32
|
-
event?.
|
|
33
|
-
|
|
34
|
-
|
|
144
|
+
event?.kind === 'reasoning_end'
|
|
145
|
+
) {
|
|
146
|
+
return typeof event?.payload?.messageId === 'string' ? event.payload.messageId : '';
|
|
147
|
+
}
|
|
148
|
+
return '';
|
|
35
149
|
}
|
|
36
150
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
151
|
+
function createEventIdentityKey(event) {
|
|
152
|
+
if (event?.eventId) {
|
|
153
|
+
return `id:${event.eventId}`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return `signature:${buildEventSignature(event)}`;
|
|
157
|
+
}
|
|
42
158
|
|
|
43
|
-
|
|
44
|
-
|
|
159
|
+
function findNearestUserTextBeforeIndex(events = [], index = -1) {
|
|
160
|
+
for (let i = index - 1; i >= 0; i -= 1) {
|
|
161
|
+
const userText = getUserMessageText(events[i]);
|
|
162
|
+
if (userText) {
|
|
163
|
+
return userText;
|
|
164
|
+
}
|
|
45
165
|
}
|
|
46
166
|
|
|
47
|
-
return
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
167
|
+
return '';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function shouldTreatUserMessagesAsDuplicates(leftEvent, rightEvent) {
|
|
171
|
+
if (leftEvent?.kind !== 'user_message' || rightEvent?.kind !== 'user_message') {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const leftText = getUserMessageText(leftEvent);
|
|
176
|
+
const rightText = getUserMessageText(rightEvent);
|
|
177
|
+
if (!leftText || leftText !== rightText) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const leftClientRequestId = leftEvent?.extensions?.clientRequestId || null;
|
|
182
|
+
const rightClientRequestId = rightEvent?.extensions?.clientRequestId || null;
|
|
183
|
+
if (leftClientRequestId && rightClientRequestId && leftClientRequestId === rightClientRequestId) {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return isReplayEvent(leftEvent) || isReplayEvent(rightEvent);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function collectAssistantTextGroups(events = []) {
|
|
191
|
+
const groupsByMessageId = new Map();
|
|
192
|
+
const groups = [];
|
|
193
|
+
let lastUserText = '';
|
|
194
|
+
|
|
195
|
+
const ensureGroup = (event) => {
|
|
196
|
+
const messageId = getEventMessageId(event) || `anonymous:${groups.length}`;
|
|
197
|
+
let group = groupsByMessageId.get(messageId);
|
|
198
|
+
if (!group) {
|
|
199
|
+
group = {
|
|
200
|
+
messageId,
|
|
201
|
+
userText: lastUserText,
|
|
202
|
+
events: [],
|
|
203
|
+
text: '',
|
|
204
|
+
};
|
|
205
|
+
groupsByMessageId.set(messageId, group);
|
|
206
|
+
groups.push(group);
|
|
207
|
+
}
|
|
208
|
+
return group;
|
|
51
209
|
};
|
|
210
|
+
|
|
211
|
+
for (const event of Array.isArray(events) ? events : []) {
|
|
212
|
+
if (!isConversationEvent(event)) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const userText = getUserMessageText(event);
|
|
217
|
+
if (userText) {
|
|
218
|
+
lastUserText = userText;
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (
|
|
223
|
+
event.kind !== 'assistant_text_start' &&
|
|
224
|
+
event.kind !== 'assistant_text_delta' &&
|
|
225
|
+
event.kind !== 'assistant_text_end'
|
|
226
|
+
) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const group = ensureGroup(event);
|
|
231
|
+
group.events.push(event);
|
|
232
|
+
if (event.kind === 'assistant_text_delta') {
|
|
233
|
+
group.text += String(event.payload?.text || '');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return groups
|
|
238
|
+
.map((group) => ({
|
|
239
|
+
...group,
|
|
240
|
+
text: normalizeComparableText(group.text),
|
|
241
|
+
}))
|
|
242
|
+
.filter((group) => group.text);
|
|
52
243
|
}
|
|
53
244
|
|
|
54
|
-
function
|
|
245
|
+
function findMatchingUserEventIndex(events, userText) {
|
|
246
|
+
const normalizedUserText = normalizeComparableText(userText);
|
|
247
|
+
if (!normalizedUserText) {
|
|
248
|
+
return -1;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return events.findIndex((event) => getUserMessageText(event) === normalizedUserText);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function insertEventsAfterMatchingUser(events, userText, eventsToInsert) {
|
|
255
|
+
const insertIndex = findMatchingUserEventIndex(events, userText);
|
|
256
|
+
if (insertIndex < 0) {
|
|
257
|
+
return [...events, ...eventsToInsert];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return [
|
|
261
|
+
...events.slice(0, insertIndex + 1),
|
|
262
|
+
...eventsToInsert,
|
|
263
|
+
...events.slice(insertIndex + 1),
|
|
264
|
+
];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function relocateCachedAssistantGroupsAfterMatchingUsers(events = [], cachedEvents = []) {
|
|
268
|
+
let relocatedEvents = Array.isArray(events) ? events : [];
|
|
269
|
+
|
|
270
|
+
for (const cachedGroup of collectAssistantTextGroups(cachedEvents)) {
|
|
271
|
+
const normalizedUserText = normalizeComparableText(cachedGroup.userText);
|
|
272
|
+
if (!normalizedUserText) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const groupKeys = new Set(
|
|
277
|
+
cachedGroup.events.map(createEventIdentityKey).filter(Boolean)
|
|
278
|
+
);
|
|
279
|
+
if (groupKeys.size === 0) {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const groupIndexes = [];
|
|
284
|
+
relocatedEvents.forEach((event, index) => {
|
|
285
|
+
if (groupKeys.has(createEventIdentityKey(event))) {
|
|
286
|
+
groupIndexes.push(index);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
if (groupIndexes.length === 0) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const firstGroupIndex = groupIndexes[0];
|
|
294
|
+
if (findNearestUserTextBeforeIndex(relocatedEvents, firstGroupIndex) === normalizedUserText) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const groupIndexSet = new Set(groupIndexes);
|
|
299
|
+
const groupEvents = groupIndexes.map((index) => relocatedEvents[index]);
|
|
300
|
+
const eventsWithoutGroup = relocatedEvents.filter((_, index) => !groupIndexSet.has(index));
|
|
301
|
+
relocatedEvents = insertEventsAfterMatchingUser(
|
|
302
|
+
eventsWithoutGroup,
|
|
303
|
+
normalizedUserText,
|
|
304
|
+
groupEvents
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return relocatedEvents;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function mergeCachedAssistantReplayEvents(currentEvents = [], cachedEvents = []) {
|
|
312
|
+
const normalizedCurrentEvents = (Array.isArray(currentEvents) ? currentEvents : []).filter(isConversationEvent);
|
|
313
|
+
const normalizedCachedEvents = (Array.isArray(cachedEvents) ? cachedEvents : []).filter(isConversationEvent);
|
|
314
|
+
|
|
315
|
+
if (normalizedCurrentEvents.length === 0) {
|
|
316
|
+
return normalizedCachedEvents.map(cloneJsonValue);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let mergedEvents = normalizedCurrentEvents.map(cloneJsonValue);
|
|
320
|
+
const mergedEventIds = new Set(
|
|
321
|
+
mergedEvents.map((event) => event.eventId).filter(Boolean)
|
|
322
|
+
);
|
|
323
|
+
const mergedEventSignatures = new Set(
|
|
324
|
+
mergedEvents.map(buildEventSignature)
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
for (const cachedEvent of normalizedCachedEvents) {
|
|
328
|
+
if (cachedEvent?.eventId && mergedEventIds.has(cachedEvent.eventId)) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (
|
|
333
|
+
cachedEvent.kind === 'user_message' &&
|
|
334
|
+
mergedEvents.some((event) => shouldTreatUserMessagesAsDuplicates(event, cachedEvent))
|
|
335
|
+
) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const signature = buildEventSignature(cachedEvent);
|
|
340
|
+
if (mergedEventSignatures.has(signature)) {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
mergedEvents.push(cloneJsonValue(cachedEvent));
|
|
345
|
+
if (cachedEvent?.eventId) {
|
|
346
|
+
mergedEventIds.add(cachedEvent.eventId);
|
|
347
|
+
}
|
|
348
|
+
mergedEventSignatures.add(signature);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
mergedEvents = mergedEvents.map((event, index) => ({ event, index }));
|
|
352
|
+
mergedEvents.sort((leftEntry, rightEntry) => {
|
|
353
|
+
const left = leftEntry.event;
|
|
354
|
+
const right = rightEntry.event;
|
|
355
|
+
const leftTime = getEventSortTime(left);
|
|
356
|
+
const rightTime = getEventSortTime(right);
|
|
357
|
+
if (leftTime !== rightTime) {
|
|
358
|
+
return leftTime - rightTime;
|
|
359
|
+
}
|
|
360
|
+
const rankDelta = getEventOrderRank(left) - getEventOrderRank(right);
|
|
361
|
+
if (rankDelta !== 0) {
|
|
362
|
+
const leftKey = getEventTieBreakerKey(left);
|
|
363
|
+
const rightKey = getEventTieBreakerKey(right);
|
|
364
|
+
if (leftKey && rightKey && leftKey === rightKey) {
|
|
365
|
+
return rankDelta;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return leftEntry.index - rightEntry.index;
|
|
369
|
+
});
|
|
370
|
+
mergedEvents = mergedEvents.map((entry) => entry.event);
|
|
371
|
+
mergedEvents = relocateCachedAssistantGroupsAfterMatchingUsers(
|
|
372
|
+
mergedEvents,
|
|
373
|
+
normalizedCachedEvents
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
const currentAssistantTexts = new Set(
|
|
377
|
+
collectAssistantTextGroups(mergedEvents)
|
|
378
|
+
.map((group) => group.text)
|
|
379
|
+
.filter(Boolean)
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
for (const cachedGroup of collectAssistantTextGroups(normalizedCachedEvents)) {
|
|
383
|
+
if (currentAssistantTexts.has(cachedGroup.text)) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
mergedEvents = insertEventsAfterMatchingUser(
|
|
388
|
+
mergedEvents,
|
|
389
|
+
cachedGroup.userText,
|
|
390
|
+
cachedGroup.events.map(cloneJsonValue)
|
|
391
|
+
);
|
|
392
|
+
currentAssistantTexts.add(cachedGroup.text);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return mergedEvents;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function readCachedSessionEvents(provider, sessionId) {
|
|
399
|
+
const cacheKey = createSessionEventCacheKey(provider, sessionId);
|
|
400
|
+
if (!cacheKey) {
|
|
401
|
+
return [];
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return (acpSessionEventCache.get(cacheKey) || []).map(cloneJsonValue);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function rememberSessionEvents(provider, sessionId, events = []) {
|
|
408
|
+
const cacheKey = createSessionEventCacheKey(provider, sessionId);
|
|
409
|
+
if (!cacheKey) {
|
|
410
|
+
return Array.isArray(events) ? events : [];
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const mergedEvents = mergeCachedAssistantReplayEvents(events, acpSessionEventCache.get(cacheKey) || []);
|
|
414
|
+
acpSessionEventCache.set(cacheKey, mergedEvents.map(cloneJsonValue));
|
|
415
|
+
return mergedEvents.map(cloneJsonValue);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function paginateEventsFromTail(events = [], limit = null, offset = 0) {
|
|
55
419
|
const normalizedEvents = Array.isArray(events) ? events : [];
|
|
420
|
+
const normalizedLimit = limit === null ? null : Math.max(0, Number(limit) || 0);
|
|
421
|
+
const normalizedOffset = Math.max(0, Number(offset) || 0);
|
|
422
|
+
const total = normalizedEvents.length;
|
|
423
|
+
|
|
424
|
+
if (normalizedLimit === null) {
|
|
425
|
+
return {
|
|
426
|
+
events: normalizedEvents,
|
|
427
|
+
total,
|
|
428
|
+
hasMore: false,
|
|
429
|
+
offset: 0,
|
|
430
|
+
limit: null
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const endIndex = Math.max(0, total - normalizedOffset);
|
|
435
|
+
const startIndex = Math.max(0, endIndex - normalizedLimit);
|
|
436
|
+
const paginatedEvents = normalizedEvents.slice(startIndex, endIndex);
|
|
437
|
+
|
|
56
438
|
return {
|
|
57
|
-
events:
|
|
58
|
-
total
|
|
59
|
-
hasMore:
|
|
60
|
-
offset:
|
|
61
|
-
limit:
|
|
439
|
+
events: paginatedEvents,
|
|
440
|
+
total,
|
|
441
|
+
hasMore: total > normalizedOffset + paginatedEvents.length,
|
|
442
|
+
offset: normalizedOffset,
|
|
443
|
+
limit: normalizedLimit
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function createEventLoadResult(events = [], source = 'acp', options = {}) {
|
|
448
|
+
return {
|
|
449
|
+
...paginateEventsFromTail(events, options.limit, options.offset),
|
|
62
450
|
source
|
|
63
451
|
};
|
|
64
452
|
}
|
|
65
453
|
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
454
|
+
function getLastEventTimestamp(events = []) {
|
|
455
|
+
const timestamps = (Array.isArray(events) ? events : [])
|
|
456
|
+
.map((event) => Date.parse(event?.timestamp || ''))
|
|
457
|
+
.filter(Number.isFinite);
|
|
458
|
+
if (timestamps.length === 0) {
|
|
69
459
|
return null;
|
|
70
460
|
}
|
|
461
|
+
return new Date(Math.max(...timestamps)).toISOString();
|
|
462
|
+
}
|
|
71
463
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
464
|
+
function getLastUserEventTimestamp(events = []) {
|
|
465
|
+
const timestamps = (Array.isArray(events) ? events : [])
|
|
466
|
+
.filter((event) => event?.kind === 'user_message')
|
|
467
|
+
.map((event) => Date.parse(event?.timestamp || ''))
|
|
468
|
+
.filter(Number.isFinite);
|
|
469
|
+
if (timestamps.length === 0) {
|
|
470
|
+
return null;
|
|
75
471
|
}
|
|
472
|
+
return new Date(Math.max(...timestamps)).toISOString();
|
|
473
|
+
}
|
|
76
474
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
475
|
+
function isAcpMissingResourceError(error) {
|
|
476
|
+
const message = String(error?.message || error || '').trim().toLowerCase();
|
|
477
|
+
return message === 'resource not found'
|
|
478
|
+
|| message.includes('resource not found')
|
|
479
|
+
|| message.includes('session not found');
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function getSessionActivityTime(session) {
|
|
483
|
+
return new Date(
|
|
484
|
+
session?.lastActivity
|
|
485
|
+
|| session?.updatedAt
|
|
486
|
+
|| session?.updated_at
|
|
487
|
+
|| session?.createdAt
|
|
488
|
+
|| session?.created_at
|
|
489
|
+
|| 0
|
|
490
|
+
).getTime();
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function normalizeSessionId(value) {
|
|
494
|
+
const normalized = String(value || '').trim();
|
|
495
|
+
return normalized || null;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
function normalizeProvider(value) {
|
|
499
|
+
return String(value || '').trim().toLowerCase();
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const GENERIC_ACP_SESSION_TITLE_PATTERN = /^ACP Session\b/i;
|
|
503
|
+
|
|
504
|
+
function isProbeLikeAcpSession(session) {
|
|
505
|
+
if (!session || session.source !== 'acp') {
|
|
506
|
+
return false;
|
|
91
507
|
}
|
|
92
508
|
|
|
93
|
-
|
|
509
|
+
const lastPromptAt = String(session?.lastPromptAt || '').trim();
|
|
510
|
+
if (lastPromptAt) {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const title = String(session?.title || '').trim();
|
|
515
|
+
const summary = String(session?.summary || '').trim();
|
|
516
|
+
|
|
517
|
+
return GENERIC_ACP_SESSION_TITLE_PATTERN.test(title)
|
|
518
|
+
|| GENERIC_ACP_SESSION_TITLE_PATTERN.test(summary);
|
|
94
519
|
}
|
|
95
520
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
getSessions(projectName, limit, offset),
|
|
101
|
-
listAcpSessions({ provider: 'claude', projectPath: projectPath || null })
|
|
102
|
-
]);
|
|
103
|
-
return mergeSessionLists(
|
|
104
|
-
(result?.sessions || []).map((session) => ({ ...session, provider: 'claude', source: 'legacy' })),
|
|
105
|
-
acpSessions,
|
|
106
|
-
{ fallbackProvider: 'claude' }
|
|
107
|
-
);
|
|
108
|
-
},
|
|
109
|
-
async loadEvents({ projectName, sessionId, limit = null, offset = 0 }) {
|
|
110
|
-
const acpResult = await loadAcpEvents(
|
|
111
|
-
'claude',
|
|
112
|
-
sessionId,
|
|
113
|
-
() => getSessionMessages(projectName, sessionId, limit, offset),
|
|
114
|
-
);
|
|
115
|
-
if (acpResult) {
|
|
116
|
-
return acpResult;
|
|
117
|
-
}
|
|
521
|
+
function createSnapshotOverlay(snapshot) {
|
|
522
|
+
if (!snapshot || typeof snapshot !== 'object') {
|
|
523
|
+
return {};
|
|
524
|
+
}
|
|
118
525
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const [sessions, acpSessions] = await Promise.all([
|
|
126
|
-
getCodexSessions(projectPath, { limit }),
|
|
127
|
-
listAcpSessions({ provider: 'codex', projectPath: projectPath || null })
|
|
128
|
-
]);
|
|
129
|
-
return mergeSessionLists(
|
|
130
|
-
sessions.map((session) => ({ ...session, provider: 'codex', source: 'legacy' })),
|
|
131
|
-
acpSessions,
|
|
132
|
-
{ fallbackProvider: 'codex' }
|
|
133
|
-
);
|
|
134
|
-
},
|
|
135
|
-
async loadEvents({ sessionId, limit = null, offset = 0 }) {
|
|
136
|
-
const acpResult = await loadAcpEvents(
|
|
137
|
-
'codex',
|
|
138
|
-
sessionId,
|
|
139
|
-
() => getCodexSessionMessages(sessionId, limit, offset),
|
|
140
|
-
);
|
|
141
|
-
if (acpResult) {
|
|
142
|
-
return acpResult;
|
|
143
|
-
}
|
|
526
|
+
const overlay = {};
|
|
527
|
+
const copyIfPresent = (targetKey, sourceKey = targetKey) => {
|
|
528
|
+
if (snapshot[sourceKey] !== undefined && snapshot[sourceKey] !== null) {
|
|
529
|
+
overlay[targetKey] = snapshot[sourceKey];
|
|
530
|
+
}
|
|
531
|
+
};
|
|
144
532
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
sessions.map((session) => ({ ...session, provider: 'gemini', source: 'legacy' })),
|
|
157
|
-
acpSessions,
|
|
158
|
-
{ fallbackProvider: 'gemini' }
|
|
159
|
-
);
|
|
160
|
-
},
|
|
161
|
-
async loadEvents({ sessionId, limit = null, offset = 0 }) {
|
|
162
|
-
const acpResult = await loadAcpEvents(
|
|
163
|
-
'gemini',
|
|
164
|
-
sessionId,
|
|
165
|
-
() => getGeminiSessionMessages(sessionId, limit, offset),
|
|
166
|
-
);
|
|
167
|
-
if (acpResult) {
|
|
168
|
-
return acpResult;
|
|
169
|
-
}
|
|
533
|
+
copyIfPresent('title');
|
|
534
|
+
copyIfPresent('summary');
|
|
535
|
+
copyIfPresent('model');
|
|
536
|
+
copyIfPresent('createdAt');
|
|
537
|
+
copyIfPresent('updatedAt');
|
|
538
|
+
copyIfPresent('lastActivity');
|
|
539
|
+
copyIfPresent('lastPromptAt');
|
|
540
|
+
copyIfPresent('closedAt');
|
|
541
|
+
copyIfPresent('isClosed');
|
|
542
|
+
copyIfPresent('projectPath');
|
|
543
|
+
copyIfPresent('cwd', 'projectPath');
|
|
170
544
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
545
|
+
return overlay;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
async function listAcpSessionsWithSnapshotOverlay(provider, options = {}) {
|
|
549
|
+
const { projectPath, limit = 50 } = options;
|
|
550
|
+
const snapshots = await listAcpSessions({ provider, projectPath: projectPath || null });
|
|
551
|
+
const sessions = snapshots
|
|
552
|
+
.map((session) => ({
|
|
553
|
+
...session,
|
|
554
|
+
...createSnapshotOverlay(session),
|
|
555
|
+
provider,
|
|
556
|
+
__provider: provider,
|
|
557
|
+
source: 'acp',
|
|
558
|
+
runtime: 'acp'
|
|
559
|
+
}))
|
|
560
|
+
.filter((session) => !isProbeLikeAcpSession(session))
|
|
561
|
+
.sort((left, right) => getSessionActivityTime(right) - getSessionActivityTime(left));
|
|
562
|
+
|
|
563
|
+
return limit > 0 ? sessions.slice(0, limit) : sessions;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
async function loadAcpEvents(provider, sessionId, options = {}) {
|
|
567
|
+
const record = await findAcpSessionRecord(sessionId, provider);
|
|
568
|
+
const projectPath = record?.projectPath || options.projectPath || null;
|
|
569
|
+
const cachedEvents = readCachedSessionEvents(provider, sessionId);
|
|
570
|
+
if (isAgentSessionActive(provider, sessionId)) {
|
|
571
|
+
return createEventLoadResult(cachedEvents, 'acp', options);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if (!projectPath) {
|
|
575
|
+
return createEventLoadResult(cachedEvents, 'acp', options);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (await shouldSkipGeminiAutomaticAcpStartup(provider, options)) {
|
|
579
|
+
return createEventLoadResult(cachedEvents, 'acp', options);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const writer = createAcpReplayWriter();
|
|
583
|
+
const { client, reused } = await getOrStartAgentClient({
|
|
584
|
+
agentKey: provider,
|
|
585
|
+
writer,
|
|
586
|
+
projectPath,
|
|
587
|
+
sessionId,
|
|
588
|
+
options: {
|
|
589
|
+
agentCommandOverrides: getAgentCommandOverrides(options)
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
let shouldRetainClient = false;
|
|
593
|
+
const shouldDisposeOnFailure = reused !== 'session';
|
|
594
|
+
|
|
595
|
+
try {
|
|
596
|
+
if (!client.canLoadSession()) {
|
|
597
|
+
return createEventLoadResult(cachedEvents, 'acp', options);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
let response;
|
|
601
|
+
try {
|
|
602
|
+
response = await client.loadSession(sessionId, { suppressReplayUpdates: false });
|
|
603
|
+
} catch (error) {
|
|
604
|
+
if (isAcpMissingResourceError(error)) {
|
|
605
|
+
return createEventLoadResult(cachedEvents, 'acp', options);
|
|
195
606
|
}
|
|
607
|
+
console.warn(`Could not replay ${provider} ACP session ${sessionId}:`, error.message);
|
|
608
|
+
return createEventLoadResult(cachedEvents, 'acp', options);
|
|
609
|
+
}
|
|
610
|
+
shouldRetainClient = true;
|
|
611
|
+
|
|
612
|
+
const mergedEvents = rememberSessionEvents(provider, sessionId, writer.events);
|
|
613
|
+
await touchAcpSessionRecord({
|
|
614
|
+
provider,
|
|
615
|
+
sessionId,
|
|
616
|
+
projectPath,
|
|
617
|
+
title: record?.title || sessionId,
|
|
618
|
+
summary: record?.summary || null,
|
|
619
|
+
model: record?.model || client.model || null,
|
|
620
|
+
lastActivity: getLastEventTimestamp(mergedEvents) || record?.lastActivity || new Date().toISOString(),
|
|
621
|
+
lastPromptAt: getLastUserEventTimestamp(mergedEvents) || record?.lastPromptAt || null,
|
|
622
|
+
isClosed: record?.isClosed ?? false
|
|
623
|
+
});
|
|
624
|
+
const result = createEventLoadResult(mergedEvents, 'acp', options);
|
|
196
625
|
|
|
197
|
-
|
|
198
|
-
|
|
626
|
+
if (response?.tokenUsage) {
|
|
627
|
+
result.tokenUsage = response.tokenUsage;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return result;
|
|
631
|
+
} finally {
|
|
632
|
+
if (shouldRetainClient) {
|
|
633
|
+
retainSessionAgentClient({
|
|
634
|
+
provider,
|
|
635
|
+
sessionId,
|
|
636
|
+
client,
|
|
637
|
+
metadata: {
|
|
638
|
+
projectPath
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
} else if (shouldDisposeOnFailure) {
|
|
642
|
+
await disposeManagedAgentClient({
|
|
643
|
+
provider,
|
|
644
|
+
sessionId,
|
|
645
|
+
projectPath,
|
|
646
|
+
client
|
|
647
|
+
});
|
|
648
|
+
} else {
|
|
649
|
+
retainSessionAgentClient({
|
|
650
|
+
provider,
|
|
651
|
+
sessionId,
|
|
652
|
+
client,
|
|
653
|
+
metadata: {
|
|
654
|
+
projectPath
|
|
655
|
+
}
|
|
656
|
+
});
|
|
199
657
|
}
|
|
200
658
|
}
|
|
201
|
-
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function createProviderAdapter(provider) {
|
|
662
|
+
return {
|
|
663
|
+
async listSessions({ projectPath, limit = 50, agentCommandOverrides = {} } = {}) {
|
|
664
|
+
try {
|
|
665
|
+
return await listAcpSessionsWithSnapshotOverlay(provider, { projectPath, limit, agentCommandOverrides });
|
|
666
|
+
} catch (error) {
|
|
667
|
+
console.warn(`Could not load ${provider} ACP sessions for project ${projectPath}:`, error.message);
|
|
668
|
+
return [];
|
|
669
|
+
}
|
|
670
|
+
},
|
|
671
|
+
async loadEvents({ sessionId, projectPath, limit = null, offset = 0, agentCommandOverrides = {} } = {}) {
|
|
672
|
+
return loadAcpEvents(provider, sessionId, { projectPath, limit, offset, agentCommandOverrides });
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const PROVIDER_ADAPTERS = SUPPORTED_PROVIDERS.reduce((adapters, provider) => {
|
|
678
|
+
adapters[provider] = createProviderAdapter(provider);
|
|
679
|
+
return adapters;
|
|
680
|
+
}, {});
|
|
202
681
|
|
|
203
682
|
export function getProviderAdapter(provider) {
|
|
204
|
-
const normalizedProvider =
|
|
683
|
+
const normalizedProvider = normalizeProvider(provider);
|
|
205
684
|
if (!SUPPORTED_PROVIDERS.includes(normalizedProvider)) {
|
|
206
685
|
throw new Error(`Unsupported provider: ${provider}`);
|
|
207
686
|
}
|
|
208
687
|
return PROVIDER_ADAPTERS[normalizedProvider];
|
|
209
688
|
}
|
|
689
|
+
|
|
690
|
+
export const __test__rememberSessionEvents = rememberSessionEvents;
|