@modelprofile.com/mcp-crossharness 5.0.0
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/.smartconfig.json +34 -0
- package/cli.js +4 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.connection.codex.d.ts +66 -0
- package/dist_ts/classes.connection.codex.js +941 -0
- package/dist_ts/classes.connection.opencode.d.ts +34 -0
- package/dist_ts/classes.connection.opencode.js +365 -0
- package/dist_ts/classes.connectionregistry.d.ts +32 -0
- package/dist_ts/classes.connectionregistry.js +246 -0
- package/dist_ts/classes.dispatchregistry.d.ts +39 -0
- package/dist_ts/classes.dispatchregistry.js +177 -0
- package/dist_ts/classes.mcpserver.d.ts +21 -0
- package/dist_ts/classes.mcpserver.js +276 -0
- package/dist_ts/helpers.d.ts +4 -0
- package/dist_ts/helpers.js +17 -0
- package/dist_ts/index.d.ts +5 -0
- package/dist_ts/index.js +9 -0
- package/dist_ts/interfaces.d.ts +57 -0
- package/dist_ts/interfaces.js +2 -0
- package/dist_ts/plugins.d.ts +17 -0
- package/dist_ts/plugins.js +14 -0
- package/license.md +21 -0
- package/package.json +51 -0
- package/readme.hints.md +52 -0
- package/readme.md +204 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.connection.codex.ts +1120 -0
- package/ts/classes.connection.opencode.ts +443 -0
- package/ts/classes.connectionregistry.ts +309 -0
- package/ts/classes.dispatchregistry.ts +216 -0
- package/ts/classes.mcpserver.ts +363 -0
- package/ts/helpers.ts +20 -0
- package/ts/index.ts +10 -0
- package/ts/interfaces.ts +71 -0
- package/ts/plugins.ts +30 -0
|
@@ -0,0 +1,941 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import * as helpers from './helpers.js';
|
|
3
|
+
import { commitinfo } from './00_commitinfo_data.js';
|
|
4
|
+
const appServerVersion = '0.146.0';
|
|
5
|
+
const maxSocketMessageBytes = 4 * 1024 * 1024;
|
|
6
|
+
const maxSocketBufferedBytes = 4 * 1024 * 1024;
|
|
7
|
+
const maxTurnTextChars = 1024 * 1024;
|
|
8
|
+
const maxTurnDeltaChunks = 4096;
|
|
9
|
+
const maxEarlyNotifications = 100;
|
|
10
|
+
const maxQueuedSends = 100;
|
|
11
|
+
const maxQueuedSendsPerThread = 10;
|
|
12
|
+
export class CodexConnection {
|
|
13
|
+
connectionId;
|
|
14
|
+
serverUrl;
|
|
15
|
+
directory;
|
|
16
|
+
onClosing;
|
|
17
|
+
onClosed;
|
|
18
|
+
harness = 'codex';
|
|
19
|
+
state = 'connecting';
|
|
20
|
+
connectedAt = new Date().toISOString();
|
|
21
|
+
serverVersion;
|
|
22
|
+
socket;
|
|
23
|
+
requestCounter = 0;
|
|
24
|
+
pendingRequests = new Map();
|
|
25
|
+
pendingTurns = new Set();
|
|
26
|
+
threadQueues = new Map();
|
|
27
|
+
activeThreads = new Set();
|
|
28
|
+
queuedSends = 0;
|
|
29
|
+
queuedSendsByThread = new Map();
|
|
30
|
+
connectStarted = false;
|
|
31
|
+
constructor(connectionId, serverUrl, directory, onClosing, onClosed) {
|
|
32
|
+
this.connectionId = connectionId;
|
|
33
|
+
this.serverUrl = serverUrl;
|
|
34
|
+
this.directory = directory;
|
|
35
|
+
this.onClosing = onClosing;
|
|
36
|
+
this.onClosed = onClosed;
|
|
37
|
+
}
|
|
38
|
+
async connect() {
|
|
39
|
+
if (this.connectStarted) {
|
|
40
|
+
throw new Error(`Codex connection ${this.connectionId} has already been started`);
|
|
41
|
+
}
|
|
42
|
+
this.connectStarted = true;
|
|
43
|
+
const headers = {};
|
|
44
|
+
const token = process.env.CODEX_REMOTE_TOKEN;
|
|
45
|
+
if (token)
|
|
46
|
+
headers.authorization = `Bearer ${token}`;
|
|
47
|
+
const socket = new plugins.WsWebSocket(this.serverUrl, {
|
|
48
|
+
perMessageDeflate: false,
|
|
49
|
+
headers,
|
|
50
|
+
followRedirects: false,
|
|
51
|
+
maxPayload: maxSocketMessageBytes,
|
|
52
|
+
});
|
|
53
|
+
this.socket = socket;
|
|
54
|
+
socket.on('message', (data) => this.handleMessage(data.toString()));
|
|
55
|
+
socket.on('error', (error) => this.handleSocketFailure(error));
|
|
56
|
+
socket.on('close', () => this.handleSocketClose());
|
|
57
|
+
await new Promise((resolve, reject) => {
|
|
58
|
+
const cleanup = () => {
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
socket.off('open', handleOpen);
|
|
61
|
+
socket.off('error', handleError);
|
|
62
|
+
socket.off('close', handleClose);
|
|
63
|
+
};
|
|
64
|
+
const handleOpen = () => {
|
|
65
|
+
cleanup();
|
|
66
|
+
resolve();
|
|
67
|
+
};
|
|
68
|
+
const handleError = (errorArg) => {
|
|
69
|
+
cleanup();
|
|
70
|
+
reject(errorArg);
|
|
71
|
+
};
|
|
72
|
+
const handleClose = () => {
|
|
73
|
+
cleanup();
|
|
74
|
+
reject(new Error('Codex server WebSocket closed during handshake'));
|
|
75
|
+
};
|
|
76
|
+
const timer = setTimeout(() => {
|
|
77
|
+
cleanup();
|
|
78
|
+
socket.terminate();
|
|
79
|
+
reject(new Error('Codex server WebSocket handshake timed out'));
|
|
80
|
+
}, 5000);
|
|
81
|
+
socket.once('open', handleOpen);
|
|
82
|
+
socket.once('error', handleError);
|
|
83
|
+
socket.once('close', handleClose);
|
|
84
|
+
});
|
|
85
|
+
try {
|
|
86
|
+
const initialized = await this.request('initialize', {
|
|
87
|
+
clientInfo: {
|
|
88
|
+
name: 'mcp-crossharness',
|
|
89
|
+
title: 'mcp-crossharness',
|
|
90
|
+
version: commitinfo.version,
|
|
91
|
+
},
|
|
92
|
+
capabilities: {
|
|
93
|
+
experimentalApi: false,
|
|
94
|
+
requestAttestation: false,
|
|
95
|
+
},
|
|
96
|
+
}, 5000, true);
|
|
97
|
+
if (!helpers.isRecord(initialized) || typeof initialized.userAgent !== 'string') {
|
|
98
|
+
throw new Error(`Codex server returned an invalid initialize response (expected app-server ${appServerVersion})`);
|
|
99
|
+
}
|
|
100
|
+
this.serverVersion = initialized.userAgent.match(/\/(\d+\.\d+\.\d+[^\s]*)/)?.[1];
|
|
101
|
+
if (this.state !== 'connecting' || socket.readyState !== plugins.WsWebSocket.OPEN) {
|
|
102
|
+
throw new Error('Codex server connection closed during initialization');
|
|
103
|
+
}
|
|
104
|
+
this.sendNotification('initialized');
|
|
105
|
+
this.state = 'connected';
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
socket.terminate();
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
getInfo() {
|
|
113
|
+
return {
|
|
114
|
+
connectionId: this.connectionId,
|
|
115
|
+
harness: this.harness,
|
|
116
|
+
serverUrl: this.serverUrl,
|
|
117
|
+
directory: this.directory,
|
|
118
|
+
state: this.state,
|
|
119
|
+
connectedAt: this.connectedAt,
|
|
120
|
+
serverVersion: this.serverVersion,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
async getStatus() {
|
|
124
|
+
if (this.state !== 'connected') {
|
|
125
|
+
return { ...this.getInfo(), healthy: false, detail: `connection is ${this.state}` };
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const response = await this.request('thread/loaded/list', {}, 5000);
|
|
129
|
+
const healthy = helpers.isRecord(response) && Array.isArray(response.data);
|
|
130
|
+
return {
|
|
131
|
+
...this.getInfo(),
|
|
132
|
+
healthy,
|
|
133
|
+
detail: healthy ? 'Codex app-server answered thread/loaded/list' : 'invalid health response',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
return { ...this.getInfo(), healthy: false, detail: helpers.errorMessage(error) };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async listChats(limitArg) {
|
|
141
|
+
const payload = await this.request('thread/list', {
|
|
142
|
+
limit: limitArg,
|
|
143
|
+
sortKey: 'updated_at',
|
|
144
|
+
sortDirection: 'desc',
|
|
145
|
+
archived: false,
|
|
146
|
+
cwd: this.directory,
|
|
147
|
+
});
|
|
148
|
+
if (!helpers.isRecord(payload) || !Array.isArray(payload.data)) {
|
|
149
|
+
throw new Error('Codex server returned an invalid thread list');
|
|
150
|
+
}
|
|
151
|
+
return payload.data.map((entry) => {
|
|
152
|
+
const thread = this.parseThread(entry);
|
|
153
|
+
this.assertThreadIdentity(thread, thread.id);
|
|
154
|
+
return {
|
|
155
|
+
harness: this.harness,
|
|
156
|
+
chatId: thread.id,
|
|
157
|
+
title: thread.name ?? thread.preview ?? '(untitled)',
|
|
158
|
+
directory: thread.cwd,
|
|
159
|
+
updatedAt: new Date(thread.updatedAt * 1000).toISOString(),
|
|
160
|
+
isActive: helpers.isRecord(thread.status) && thread.status.type === 'active',
|
|
161
|
+
meta: thread.modelProvider ? { modelProvider: thread.modelProvider } : undefined,
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
async readChat(chatIdArg, limitArg, maxCharsArg) {
|
|
166
|
+
this.assertChatId(chatIdArg);
|
|
167
|
+
const thread = await this.readThread(chatIdArg, true);
|
|
168
|
+
const messages = [];
|
|
169
|
+
for (const turn of thread.turns) {
|
|
170
|
+
if (!helpers.isRecord(turn) || !Array.isArray(turn.items))
|
|
171
|
+
continue;
|
|
172
|
+
for (const item of turn.items) {
|
|
173
|
+
if (!helpers.isRecord(item) || typeof item.type !== 'string')
|
|
174
|
+
continue;
|
|
175
|
+
if (item.type === 'userMessage' && Array.isArray(item.content)) {
|
|
176
|
+
const text = item.content
|
|
177
|
+
.filter((content) => helpers.isRecord(content) && content.type === 'text')
|
|
178
|
+
.map((content) => String(content.text ?? ''))
|
|
179
|
+
.join('\n')
|
|
180
|
+
.trim();
|
|
181
|
+
if (text)
|
|
182
|
+
messages.push({ role: 'user', text: helpers.truncateText(text, maxCharsArg) });
|
|
183
|
+
}
|
|
184
|
+
else if (item.type === 'agentMessage' && typeof item.text === 'string') {
|
|
185
|
+
messages.push({ role: 'assistant', text: helpers.truncateText(item.text, maxCharsArg) });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const limited = messages.slice(-limitArg);
|
|
190
|
+
return {
|
|
191
|
+
harness: this.harness,
|
|
192
|
+
chatId: chatIdArg,
|
|
193
|
+
title: thread.name ?? thread.preview ?? '(untitled)',
|
|
194
|
+
directory: thread.cwd,
|
|
195
|
+
totalMessages: messages.length,
|
|
196
|
+
messages: limited,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
async sendMessage(chatIdArg, messageArg, timeoutSecondsArg, signalArg) {
|
|
200
|
+
this.assertChatId(chatIdArg);
|
|
201
|
+
if (messageArg.length > maxTurnTextChars) {
|
|
202
|
+
throw new Error('Codex message exceeds the 1 MiB character limit');
|
|
203
|
+
}
|
|
204
|
+
const threadQueueSize = this.queuedSendsByThread.get(chatIdArg) ?? 0;
|
|
205
|
+
if (this.queuedSends >= maxQueuedSends || threadQueueSize >= maxQueuedSendsPerThread) {
|
|
206
|
+
throw new Error('Codex send queue is full');
|
|
207
|
+
}
|
|
208
|
+
this.queuedSends++;
|
|
209
|
+
this.queuedSendsByThread.set(chatIdArg, threadQueueSize + 1);
|
|
210
|
+
const deadline = Date.now() + timeoutSecondsArg * 1000;
|
|
211
|
+
try {
|
|
212
|
+
return await this.enqueueThreadSend(chatIdArg, deadline, timeoutSecondsArg, signalArg, () => this.sendMessageInner(chatIdArg, messageArg, deadline, timeoutSecondsArg, signalArg));
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
this.queuedSends--;
|
|
216
|
+
const remainingForThread = (this.queuedSendsByThread.get(chatIdArg) ?? 1) - 1;
|
|
217
|
+
if (remainingForThread > 0)
|
|
218
|
+
this.queuedSendsByThread.set(chatIdArg, remainingForThread);
|
|
219
|
+
else
|
|
220
|
+
this.queuedSendsByThread.delete(chatIdArg);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async sendMessageInner(chatIdArg, messageArg, deadlineArg, timeoutSecondsArg, signalArg) {
|
|
224
|
+
await this.readThread(chatIdArg, false, this.remainingSendMs(deadlineArg, timeoutSecondsArg), signalArg);
|
|
225
|
+
const resumed = await this.request('thread/resume', { threadId: chatIdArg }, this.remainingSendMs(deadlineArg, timeoutSecondsArg), false, signalArg);
|
|
226
|
+
if (!helpers.isRecord(resumed) ||
|
|
227
|
+
!helpers.isRecord(resumed.thread) ||
|
|
228
|
+
typeof resumed.cwd !== 'string') {
|
|
229
|
+
throw new Error('Codex server returned an invalid thread/resume response');
|
|
230
|
+
}
|
|
231
|
+
const resumedThread = this.parseThread(resumed.thread);
|
|
232
|
+
this.assertThreadIdentity(resumedThread, chatIdArg);
|
|
233
|
+
if (resumed.cwd !== this.directory) {
|
|
234
|
+
throw new Error(`Codex thread ${chatIdArg} resumed outside the connection directory`);
|
|
235
|
+
}
|
|
236
|
+
const turnTimeoutMs = this.remainingSendMs(deadlineArg, timeoutSecondsArg);
|
|
237
|
+
if (signalArg?.aborted)
|
|
238
|
+
throw this.abortError(signalArg.reason);
|
|
239
|
+
return new Promise((resolve, reject) => {
|
|
240
|
+
const turn = {
|
|
241
|
+
threadId: chatIdArg,
|
|
242
|
+
agentText: '',
|
|
243
|
+
deltaChunks: [],
|
|
244
|
+
deltaChars: 0,
|
|
245
|
+
earlyNotifications: new Map(),
|
|
246
|
+
earlyNotificationCount: 0,
|
|
247
|
+
earlyNotificationChars: 0,
|
|
248
|
+
resolve,
|
|
249
|
+
reject,
|
|
250
|
+
timer: setTimeout(() => void this.timeoutTurn(turn, timeoutSecondsArg), turnTimeoutMs),
|
|
251
|
+
};
|
|
252
|
+
this.pendingTurns.add(turn);
|
|
253
|
+
void this.request('turn/start', {
|
|
254
|
+
threadId: chatIdArg,
|
|
255
|
+
clientUserMessageId: plugins.crypto.randomUUID(),
|
|
256
|
+
input: [{ type: 'text', text: messageArg, text_elements: [] }],
|
|
257
|
+
cwd: this.directory,
|
|
258
|
+
}, turnTimeoutMs)
|
|
259
|
+
.then((result) => {
|
|
260
|
+
if (!this.pendingTurns.has(turn))
|
|
261
|
+
return;
|
|
262
|
+
let turnId;
|
|
263
|
+
try {
|
|
264
|
+
turnId = this.extractTurnId(result);
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
this.failUncertainTurnStart(turn, error);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
this.bindTurnId(turn, turnId);
|
|
271
|
+
})
|
|
272
|
+
.catch((error) => this.failUncertainTurnStart(turn, error));
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
enqueueThreadSend(threadIdArg, deadlineArg, timeoutSecondsArg, signalArg, taskArg) {
|
|
276
|
+
return new Promise((resolve, reject) => {
|
|
277
|
+
const entry = {
|
|
278
|
+
deadline: deadlineArg,
|
|
279
|
+
timeoutSeconds: timeoutSecondsArg,
|
|
280
|
+
task: taskArg,
|
|
281
|
+
resolve,
|
|
282
|
+
reject,
|
|
283
|
+
signal: signalArg,
|
|
284
|
+
};
|
|
285
|
+
if (signalArg?.aborted) {
|
|
286
|
+
reject(this.abortError(signalArg.reason));
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const queue = this.threadQueues.get(threadIdArg) ?? [];
|
|
290
|
+
queue.push(entry);
|
|
291
|
+
this.threadQueues.set(threadIdArg, queue);
|
|
292
|
+
entry.timer = setTimeout(() => this.timeoutQueuedSend(threadIdArg, entry), Math.max(0, deadlineArg - Date.now()));
|
|
293
|
+
if (signalArg) {
|
|
294
|
+
entry.abortHandler = () => this.cancelThreadSend(threadIdArg, entry);
|
|
295
|
+
signalArg.addEventListener('abort', entry.abortHandler, { once: true });
|
|
296
|
+
}
|
|
297
|
+
this.drainThreadQueue(threadIdArg);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
async close(reasonArg = 'connection disconnected') {
|
|
301
|
+
if (this.state === 'closed')
|
|
302
|
+
return;
|
|
303
|
+
if (this.state !== 'closing') {
|
|
304
|
+
this.state = 'closing';
|
|
305
|
+
this.rejectAll(new Error(reasonArg));
|
|
306
|
+
this.onClosing?.();
|
|
307
|
+
this.onClosing = undefined;
|
|
308
|
+
}
|
|
309
|
+
await this.closeSocket();
|
|
310
|
+
this.finishClosed();
|
|
311
|
+
}
|
|
312
|
+
async readThread(chatIdArg, includeTurnsArg, timeoutMsArg = 30000, signalArg) {
|
|
313
|
+
const payload = await this.request('thread/read', {
|
|
314
|
+
threadId: chatIdArg,
|
|
315
|
+
includeTurns: includeTurnsArg,
|
|
316
|
+
}, timeoutMsArg, false, signalArg);
|
|
317
|
+
if (!helpers.isRecord(payload) || !helpers.isRecord(payload.thread)) {
|
|
318
|
+
throw new Error('Codex server returned an invalid thread');
|
|
319
|
+
}
|
|
320
|
+
const thread = this.parseThread(payload.thread);
|
|
321
|
+
this.assertThreadIdentity(thread, chatIdArg);
|
|
322
|
+
return thread;
|
|
323
|
+
}
|
|
324
|
+
parseThread(valueArg) {
|
|
325
|
+
if (!helpers.isRecord(valueArg) ||
|
|
326
|
+
typeof valueArg.id !== 'string' ||
|
|
327
|
+
typeof valueArg.cwd !== 'string' ||
|
|
328
|
+
typeof valueArg.updatedAt !== 'number' ||
|
|
329
|
+
!Array.isArray(valueArg.turns)) {
|
|
330
|
+
throw new Error('Codex server returned an invalid thread');
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
id: valueArg.id,
|
|
334
|
+
cwd: valueArg.cwd,
|
|
335
|
+
updatedAt: valueArg.updatedAt,
|
|
336
|
+
turns: valueArg.turns,
|
|
337
|
+
preview: typeof valueArg.preview === 'string' ? valueArg.preview : undefined,
|
|
338
|
+
name: typeof valueArg.name === 'string' || valueArg.name === null ? valueArg.name : undefined,
|
|
339
|
+
modelProvider: typeof valueArg.modelProvider === 'string' ? valueArg.modelProvider : undefined,
|
|
340
|
+
status: valueArg.status,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
assertThreadIdentity(threadArg, chatIdArg) {
|
|
344
|
+
if (threadArg.id !== chatIdArg) {
|
|
345
|
+
throw new Error(`Codex server returned a different thread for ${chatIdArg}`);
|
|
346
|
+
}
|
|
347
|
+
if (threadArg.cwd !== this.directory) {
|
|
348
|
+
throw new Error(`Codex thread ${chatIdArg} is outside the connection directory`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
request(methodArg, paramsArg, timeoutMsArg = 30000, allowConnectingArg = false, signalArg) {
|
|
352
|
+
if (!allowConnectingArg && this.state !== 'connected') {
|
|
353
|
+
return Promise.reject(new Error(`Codex connection ${this.connectionId} is ${this.state}`));
|
|
354
|
+
}
|
|
355
|
+
const socket = this.socket;
|
|
356
|
+
if (!socket || socket.readyState !== plugins.WsWebSocket.OPEN) {
|
|
357
|
+
return Promise.reject(new Error('Codex server WebSocket is not open'));
|
|
358
|
+
}
|
|
359
|
+
if (this.pendingRequests.size >= 256) {
|
|
360
|
+
return Promise.reject(new Error('Codex connection has too many active requests'));
|
|
361
|
+
}
|
|
362
|
+
if (signalArg?.aborted)
|
|
363
|
+
return Promise.reject(this.abortError(signalArg.reason));
|
|
364
|
+
return new Promise((resolve, reject) => {
|
|
365
|
+
const id = ++this.requestCounter;
|
|
366
|
+
const timer = setTimeout(() => {
|
|
367
|
+
const pending = this.pendingRequests.get(id);
|
|
368
|
+
if (!pending)
|
|
369
|
+
return;
|
|
370
|
+
this.pendingRequests.delete(id);
|
|
371
|
+
this.clearPendingRequestResources(pending);
|
|
372
|
+
reject(new Error(`Codex request timed out: ${methodArg}`));
|
|
373
|
+
}, timeoutMsArg);
|
|
374
|
+
const pending = { resolve, reject, timer, signal: signalArg };
|
|
375
|
+
if (signalArg) {
|
|
376
|
+
pending.abortHandler = () => {
|
|
377
|
+
if (!this.pendingRequests.delete(id))
|
|
378
|
+
return;
|
|
379
|
+
this.clearPendingRequestResources(pending);
|
|
380
|
+
reject(this.abortError(signalArg.reason));
|
|
381
|
+
};
|
|
382
|
+
signalArg.addEventListener('abort', pending.abortHandler, { once: true });
|
|
383
|
+
}
|
|
384
|
+
this.pendingRequests.set(id, pending);
|
|
385
|
+
const failSend = (errorArg) => {
|
|
386
|
+
const current = this.pendingRequests.get(id);
|
|
387
|
+
if (!current)
|
|
388
|
+
return;
|
|
389
|
+
this.pendingRequests.delete(id);
|
|
390
|
+
this.clearPendingRequestResources(current);
|
|
391
|
+
current.reject(errorArg);
|
|
392
|
+
};
|
|
393
|
+
try {
|
|
394
|
+
this.sendFrame({ id, method: methodArg, params: paramsArg });
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
failSend(error instanceof Error ? error : new Error(String(error)));
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
sendNotification(methodArg, paramsArg) {
|
|
402
|
+
this.sendFrame(paramsArg === undefined
|
|
403
|
+
? { method: methodArg }
|
|
404
|
+
: { method: methodArg, params: paramsArg });
|
|
405
|
+
}
|
|
406
|
+
sendFrame(frameArg) {
|
|
407
|
+
const socket = this.socket;
|
|
408
|
+
const payload = JSON.stringify(frameArg);
|
|
409
|
+
const payloadBytes = Buffer.byteLength(payload, 'utf8');
|
|
410
|
+
if (!socket || socket.readyState !== plugins.WsWebSocket.OPEN) {
|
|
411
|
+
const error = new Error('Codex server WebSocket is not open');
|
|
412
|
+
this.handleSocketFailure(error);
|
|
413
|
+
throw error;
|
|
414
|
+
}
|
|
415
|
+
if (socket.bufferedAmount + payloadBytes > maxSocketBufferedBytes) {
|
|
416
|
+
const error = new Error('Codex WebSocket send buffer exceeded the 4 MiB limit');
|
|
417
|
+
this.handleSocketFailure(error);
|
|
418
|
+
throw error;
|
|
419
|
+
}
|
|
420
|
+
try {
|
|
421
|
+
socket.send(payload, (error) => {
|
|
422
|
+
if (error)
|
|
423
|
+
this.handleSocketFailure(error);
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
const sendError = error instanceof Error ? error : new Error(String(error));
|
|
428
|
+
this.handleSocketFailure(sendError);
|
|
429
|
+
throw sendError;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
handleMessage(rawArg) {
|
|
433
|
+
const message = helpers.parseJson(rawArg);
|
|
434
|
+
if (!helpers.isRecord(message))
|
|
435
|
+
return;
|
|
436
|
+
if (message.id !== undefined && typeof message.method === 'string') {
|
|
437
|
+
this.respondToServerRequest(message);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (typeof message.id === 'number' && this.pendingRequests.has(message.id)) {
|
|
441
|
+
const pending = this.pendingRequests.get(message.id);
|
|
442
|
+
this.pendingRequests.delete(message.id);
|
|
443
|
+
this.clearPendingRequestResources(pending);
|
|
444
|
+
if (message.error !== undefined) {
|
|
445
|
+
pending.reject(new Error(`Codex server rejected request: ${JSON.stringify(message.error).slice(0, 4000)}`));
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
pending.resolve(message.result);
|
|
449
|
+
}
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
if (typeof message.method === 'string') {
|
|
453
|
+
if (!helpers.isRecord(message.params)) {
|
|
454
|
+
if (message.method === 'turn/completed') {
|
|
455
|
+
this.handleSocketFailure(new Error('Codex returned malformed turn/completed params'));
|
|
456
|
+
}
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
this.handleNotification(message.method, message.params);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
handleNotification(methodArg, paramsArg) {
|
|
463
|
+
if (methodArg === 'turn/completed') {
|
|
464
|
+
if (!helpers.isRecord(paramsArg.turn) ||
|
|
465
|
+
typeof paramsArg.turn.id !== 'string' ||
|
|
466
|
+
(paramsArg.turnId !== undefined && paramsArg.turnId !== paramsArg.turn.id)) {
|
|
467
|
+
this.handleSocketFailure(new Error('Codex returned malformed turn/completed identity'));
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
const threadId = typeof paramsArg.threadId === 'string' ? paramsArg.threadId : undefined;
|
|
472
|
+
const turnId = typeof paramsArg.turnId === 'string'
|
|
473
|
+
? paramsArg.turnId
|
|
474
|
+
: helpers.isRecord(paramsArg.turn) && typeof paramsArg.turn.id === 'string'
|
|
475
|
+
? paramsArg.turn.id
|
|
476
|
+
: undefined;
|
|
477
|
+
if (!threadId || !turnId) {
|
|
478
|
+
if (methodArg === 'turn/completed') {
|
|
479
|
+
this.handleSocketFailure(new Error('Codex returned malformed turn/completed identity'));
|
|
480
|
+
}
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
const turn = [...this.pendingTurns].find((candidate) => candidate.threadId === threadId && candidate.turnId === turnId);
|
|
484
|
+
if (!turn) {
|
|
485
|
+
const unbound = [...this.pendingTurns].filter((candidate) => candidate.threadId === threadId && !candidate.turnId);
|
|
486
|
+
if (unbound.length === 1)
|
|
487
|
+
this.bufferEarlyNotification(unbound[0], turnId, methodArg, paramsArg);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
this.handleTurnNotification(turn, methodArg, paramsArg);
|
|
491
|
+
}
|
|
492
|
+
handleTurnNotification(turnArg, methodArg, paramsArg) {
|
|
493
|
+
if (methodArg === 'turn/completed' && !helpers.isRecord(paramsArg.turn)) {
|
|
494
|
+
this.handleSocketFailure(new Error('Codex returned malformed turn/completed payload'));
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (methodArg === 'item/agentMessage/delta' && typeof paramsArg.delta === 'string') {
|
|
498
|
+
this.appendTurnDelta(turnArg, paramsArg.delta);
|
|
499
|
+
}
|
|
500
|
+
else if (methodArg === 'item/completed' && helpers.isRecord(paramsArg.item)) {
|
|
501
|
+
if (paramsArg.item.type === 'agentMessage' && typeof paramsArg.item.text === 'string') {
|
|
502
|
+
if (paramsArg.item.text.length > maxTurnTextChars) {
|
|
503
|
+
this.handleSocketFailure(new Error('Codex turn output exceeded the response limit'));
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
turnArg.agentText = paramsArg.item.text;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
else if (methodArg === 'turn/completed' && helpers.isRecord(paramsArg.turn)) {
|
|
510
|
+
const status = paramsArg.turn.status;
|
|
511
|
+
if (turnArg.timeoutError) {
|
|
512
|
+
if (status !== 'completed' && status !== 'interrupted' && status !== 'failed') {
|
|
513
|
+
this.handleSocketFailure(new Error('Codex returned a non-terminal status in turn/completed'));
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
turnArg.terminalObserved = true;
|
|
517
|
+
this.rejectTimedOutTurnIfSafe(turnArg);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (status === 'completed') {
|
|
521
|
+
this.completeTurn(turnArg);
|
|
522
|
+
}
|
|
523
|
+
else if (status === 'interrupted' || status === 'failed') {
|
|
524
|
+
const turnError = helpers.isRecord(paramsArg.turn.error)
|
|
525
|
+
? String(paramsArg.turn.error.message ?? status)
|
|
526
|
+
: String(status);
|
|
527
|
+
this.failTurn(turnArg, new Error(`Codex turn ${status}: ${turnError}`));
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
this.handleSocketFailure(new Error('Codex returned a non-terminal status in turn/completed'));
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
bindTurnId(turnArg, turnIdArg) {
|
|
535
|
+
if (!this.pendingTurns.has(turnArg))
|
|
536
|
+
return;
|
|
537
|
+
if (turnArg.turnId && turnArg.turnId !== turnIdArg) {
|
|
538
|
+
this.failTurn(turnArg, new Error('Codex turn identity changed during dispatch'));
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
const collision = [...this.pendingTurns].find((candidate) => candidate !== turnArg && candidate.turnId === turnIdArg);
|
|
542
|
+
if (collision) {
|
|
543
|
+
this.handleSocketFailure(new Error('Codex reused a turn id across concurrent sends'));
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
turnArg.turnId = turnIdArg;
|
|
547
|
+
const buffered = turnArg.earlyNotifications.get(turnIdArg) ?? [];
|
|
548
|
+
turnArg.earlyNotifications.clear();
|
|
549
|
+
turnArg.earlyNotificationCount = 0;
|
|
550
|
+
turnArg.earlyNotificationChars = 0;
|
|
551
|
+
for (const notification of buffered) {
|
|
552
|
+
if (!this.pendingTurns.has(turnArg))
|
|
553
|
+
break;
|
|
554
|
+
this.handleTurnNotification(turnArg, notification.method, notification.params);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
extractTurnId(valueArg) {
|
|
558
|
+
if (!helpers.isRecord(valueArg) || !helpers.isRecord(valueArg.turn) || typeof valueArg.turn.id !== 'string') {
|
|
559
|
+
throw new Error('Codex server returned an invalid turn/start response');
|
|
560
|
+
}
|
|
561
|
+
return valueArg.turn.id;
|
|
562
|
+
}
|
|
563
|
+
completeTurn(turnArg) {
|
|
564
|
+
if (!this.settleTurn(turnArg))
|
|
565
|
+
return;
|
|
566
|
+
const reply = (turnArg.agentText || turnArg.deltaChunks.join('')).trim();
|
|
567
|
+
if (!reply) {
|
|
568
|
+
turnArg.reject(new Error('Codex turn completed without assistant text'));
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
turnArg.resolve({
|
|
572
|
+
harness: this.harness,
|
|
573
|
+
chatId: turnArg.threadId,
|
|
574
|
+
reply,
|
|
575
|
+
via: `ws:${this.serverUrl}`,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
failTurn(turnArg, errorArg) {
|
|
579
|
+
if (!this.settleTurn(turnArg))
|
|
580
|
+
return;
|
|
581
|
+
turnArg.reject(errorArg instanceof Error ? errorArg : new Error(String(errorArg)));
|
|
582
|
+
}
|
|
583
|
+
async timeoutTurn(turnArg, timeoutSecondsArg) {
|
|
584
|
+
if (!this.pendingTurns.has(turnArg) || turnArg.timeoutError)
|
|
585
|
+
return;
|
|
586
|
+
const timeoutError = new Error(`Codex turn timed out after ${timeoutSecondsArg}s; Crossharness did not retry`);
|
|
587
|
+
turnArg.timeoutError = timeoutError;
|
|
588
|
+
const turnId = turnArg.turnId;
|
|
589
|
+
if (!turnId) {
|
|
590
|
+
const fatalError = new Error(`${timeoutError.message}; no turn id was available to interrupt safely, so the connection was closed`);
|
|
591
|
+
this.handleSocketFailure(fatalError);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
try {
|
|
595
|
+
await this.request('turn/interrupt', { threadId: turnArg.threadId, turnId }, 3000);
|
|
596
|
+
if (!this.pendingTurns.has(turnArg))
|
|
597
|
+
return;
|
|
598
|
+
turnArg.interruptAcknowledged = true;
|
|
599
|
+
if (turnArg.terminalObserved) {
|
|
600
|
+
this.rejectTimedOutTurnIfSafe(turnArg);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
turnArg.terminalTimer = setTimeout(() => {
|
|
604
|
+
if (!this.pendingTurns.has(turnArg))
|
|
605
|
+
return;
|
|
606
|
+
this.handleSocketFailure(new Error(`${timeoutError.message}; the interrupted turn did not report terminal completion, so the connection was closed`));
|
|
607
|
+
}, 3000);
|
|
608
|
+
turnArg.terminalTimer.unref();
|
|
609
|
+
}
|
|
610
|
+
catch (error) {
|
|
611
|
+
const fatalError = new Error(`${timeoutError.message}; turn/interrupt was not acknowledged, so the connection was closed: ${helpers.errorMessage(error)}`, { cause: error });
|
|
612
|
+
this.handleSocketFailure(fatalError);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
async cancelActiveTurn(turnArg, errorArg) {
|
|
616
|
+
if (!this.pendingTurns.has(turnArg) || turnArg.timeoutError)
|
|
617
|
+
return;
|
|
618
|
+
turnArg.timeoutError = errorArg;
|
|
619
|
+
const turnId = turnArg.turnId;
|
|
620
|
+
if (!turnId) {
|
|
621
|
+
this.handleSocketFailure(new Error(`${errorArg.message}; no turn id was available to interrupt safely, so the connection was closed`));
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
try {
|
|
625
|
+
await this.request('turn/interrupt', { threadId: turnArg.threadId, turnId }, 3000);
|
|
626
|
+
if (!this.pendingTurns.has(turnArg))
|
|
627
|
+
return;
|
|
628
|
+
turnArg.interruptAcknowledged = true;
|
|
629
|
+
if (turnArg.terminalObserved) {
|
|
630
|
+
this.rejectTimedOutTurnIfSafe(turnArg);
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
turnArg.terminalTimer = setTimeout(() => {
|
|
634
|
+
if (!this.pendingTurns.has(turnArg))
|
|
635
|
+
return;
|
|
636
|
+
this.handleSocketFailure(new Error(`${errorArg.message}; the interrupted turn did not report terminal completion, so the connection was closed`));
|
|
637
|
+
}, 3000);
|
|
638
|
+
turnArg.terminalTimer.unref();
|
|
639
|
+
}
|
|
640
|
+
catch (error) {
|
|
641
|
+
this.handleSocketFailure(new Error(`${errorArg.message}; turn/interrupt was not acknowledged, so the connection was closed: ${helpers.errorMessage(error)}`, { cause: error }));
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
timeoutQueuedSend(threadIdArg, entryArg) {
|
|
645
|
+
if (this.activeThreads.has(threadIdArg)) {
|
|
646
|
+
const queue = this.threadQueues.get(threadIdArg);
|
|
647
|
+
if (queue?.[0] === entryArg)
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
const queue = this.threadQueues.get(threadIdArg);
|
|
651
|
+
if (!queue)
|
|
652
|
+
return;
|
|
653
|
+
const index = queue.indexOf(entryArg);
|
|
654
|
+
if (index < 0)
|
|
655
|
+
return;
|
|
656
|
+
queue.splice(index, 1);
|
|
657
|
+
this.clearQueueEntryResources(entryArg);
|
|
658
|
+
entryArg.reject(new Error(`Codex send timed out after ${entryArg.timeoutSeconds}s while queued; no message was delivered`));
|
|
659
|
+
if (queue.length === 0 && !this.activeThreads.has(threadIdArg)) {
|
|
660
|
+
this.threadQueues.delete(threadIdArg);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
cancelThreadSend(threadIdArg, entryArg) {
|
|
664
|
+
const queue = this.threadQueues.get(threadIdArg);
|
|
665
|
+
if (!queue)
|
|
666
|
+
return;
|
|
667
|
+
const index = queue.indexOf(entryArg);
|
|
668
|
+
if (index < 0)
|
|
669
|
+
return;
|
|
670
|
+
if (index === 0 && this.activeThreads.has(threadIdArg)) {
|
|
671
|
+
const turn = [...this.pendingTurns].find((candidate) => candidate.threadId === threadIdArg);
|
|
672
|
+
if (turn)
|
|
673
|
+
void this.cancelActiveTurn(turn, this.abortError(entryArg.signal?.reason));
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
queue.splice(index, 1);
|
|
677
|
+
this.clearQueueEntryResources(entryArg);
|
|
678
|
+
entryArg.reject(this.abortError(entryArg.signal?.reason));
|
|
679
|
+
if (queue.length === 0 && !this.activeThreads.has(threadIdArg)) {
|
|
680
|
+
this.threadQueues.delete(threadIdArg);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
drainThreadQueue(threadIdArg) {
|
|
684
|
+
if (this.activeThreads.has(threadIdArg))
|
|
685
|
+
return;
|
|
686
|
+
const queue = this.threadQueues.get(threadIdArg);
|
|
687
|
+
const entry = queue?.[0];
|
|
688
|
+
if (!queue || !entry) {
|
|
689
|
+
this.threadQueues.delete(threadIdArg);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
if (entry.deadline <= Date.now()) {
|
|
693
|
+
this.timeoutQueuedSend(threadIdArg, entry);
|
|
694
|
+
this.drainThreadQueue(threadIdArg);
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
this.activeThreads.add(threadIdArg);
|
|
698
|
+
if (entry.timer)
|
|
699
|
+
clearTimeout(entry.timer);
|
|
700
|
+
void entry.task().then(entry.resolve, entry.reject).finally(() => {
|
|
701
|
+
this.clearQueueEntryResources(entry);
|
|
702
|
+
this.activeThreads.delete(threadIdArg);
|
|
703
|
+
const currentQueue = this.threadQueues.get(threadIdArg);
|
|
704
|
+
if (currentQueue?.[0] === entry)
|
|
705
|
+
currentQueue.shift();
|
|
706
|
+
if (currentQueue?.length === 0)
|
|
707
|
+
this.threadQueues.delete(threadIdArg);
|
|
708
|
+
this.drainThreadQueue(threadIdArg);
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
appendTurnDelta(turnArg, deltaArg) {
|
|
712
|
+
if (turnArg.deltaChunks.length >= maxTurnDeltaChunks) {
|
|
713
|
+
this.handleSocketFailure(new Error('Codex turn output exceeded the delta chunk limit'));
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
if (turnArg.deltaChars + deltaArg.length > maxTurnTextChars) {
|
|
717
|
+
this.handleSocketFailure(new Error('Codex turn output exceeded the response limit'));
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
turnArg.deltaChunks.push(deltaArg);
|
|
721
|
+
turnArg.deltaChars += deltaArg.length;
|
|
722
|
+
}
|
|
723
|
+
remainingSendMs(deadlineArg, timeoutSecondsArg) {
|
|
724
|
+
const remainingMs = deadlineArg - Date.now();
|
|
725
|
+
if (remainingMs <= 0) {
|
|
726
|
+
throw new Error(`Codex send timed out after ${timeoutSecondsArg}s before turn/start; no message was delivered`);
|
|
727
|
+
}
|
|
728
|
+
return remainingMs;
|
|
729
|
+
}
|
|
730
|
+
clearQueueEntryResources(entryArg) {
|
|
731
|
+
if (entryArg.timer)
|
|
732
|
+
clearTimeout(entryArg.timer);
|
|
733
|
+
if (entryArg.abortHandler) {
|
|
734
|
+
entryArg.signal?.removeEventListener('abort', entryArg.abortHandler);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
clearPendingRequestResources(pendingArg) {
|
|
738
|
+
clearTimeout(pendingArg.timer);
|
|
739
|
+
if (pendingArg.abortHandler) {
|
|
740
|
+
pendingArg.signal?.removeEventListener('abort', pendingArg.abortHandler);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
abortError(reasonArg) {
|
|
744
|
+
return reasonArg instanceof Error ? reasonArg : new Error('operation cancelled');
|
|
745
|
+
}
|
|
746
|
+
assertChatId(chatIdArg) {
|
|
747
|
+
if (!chatIdArg || chatIdArg.length > 1024) {
|
|
748
|
+
throw new Error('Codex chatId must contain 1-1024 characters');
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
bufferEarlyNotification(turnArg, turnIdArg, methodArg, paramsArg) {
|
|
752
|
+
const notification = this.normalizeEarlyNotification(methodArg, paramsArg);
|
|
753
|
+
if (!notification)
|
|
754
|
+
return;
|
|
755
|
+
turnArg.earlyNotificationCount++;
|
|
756
|
+
if (turnArg.earlyNotificationCount > maxEarlyNotifications) {
|
|
757
|
+
this.handleSocketFailure(new Error('Codex sent too many turn notifications before acknowledging turn/start'));
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
const notificationChars = JSON.stringify(notification).length;
|
|
761
|
+
turnArg.earlyNotificationChars += notificationChars;
|
|
762
|
+
if (turnArg.earlyNotificationChars > maxTurnTextChars) {
|
|
763
|
+
this.handleSocketFailure(new Error('Codex buffered turn notifications exceeded the response limit'));
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
const notifications = turnArg.earlyNotifications.get(turnIdArg) ?? [];
|
|
767
|
+
notifications.push(notification);
|
|
768
|
+
turnArg.earlyNotifications.set(turnIdArg, notifications);
|
|
769
|
+
}
|
|
770
|
+
normalizeEarlyNotification(methodArg, paramsArg) {
|
|
771
|
+
if (methodArg === 'item/agentMessage/delta' && typeof paramsArg.delta === 'string') {
|
|
772
|
+
return { method: methodArg, params: { delta: paramsArg.delta } };
|
|
773
|
+
}
|
|
774
|
+
if (methodArg === 'item/completed' && helpers.isRecord(paramsArg.item)) {
|
|
775
|
+
const item = paramsArg.item;
|
|
776
|
+
if (item.type === 'agentMessage' && typeof item.text === 'string') {
|
|
777
|
+
return { method: methodArg, params: { item: { type: item.type, text: item.text } } };
|
|
778
|
+
}
|
|
779
|
+
return undefined;
|
|
780
|
+
}
|
|
781
|
+
if (methodArg === 'turn/completed' && helpers.isRecord(paramsArg.turn)) {
|
|
782
|
+
const turn = paramsArg.turn;
|
|
783
|
+
return {
|
|
784
|
+
method: methodArg,
|
|
785
|
+
params: {
|
|
786
|
+
turn: {
|
|
787
|
+
status: turn.status,
|
|
788
|
+
error: helpers.isRecord(turn.error) ? { message: turn.error.message } : turn.error,
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
return undefined;
|
|
794
|
+
}
|
|
795
|
+
failUncertainTurnStart(turnArg, errorArg) {
|
|
796
|
+
if (!this.pendingTurns.has(turnArg))
|
|
797
|
+
return;
|
|
798
|
+
const fatalError = new Error(`Codex turn/start outcome is uncertain, so the connection was closed: ${helpers.errorMessage(errorArg)}`, { cause: errorArg });
|
|
799
|
+
this.handleSocketFailure(fatalError);
|
|
800
|
+
}
|
|
801
|
+
rejectTimedOutTurnIfSafe(turnArg) {
|
|
802
|
+
const error = turnArg.timeoutError;
|
|
803
|
+
if (!error ||
|
|
804
|
+
!turnArg.interruptAcknowledged ||
|
|
805
|
+
!turnArg.terminalObserved ||
|
|
806
|
+
!this.settleTurn(turnArg)) {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
turnArg.reject(error);
|
|
810
|
+
}
|
|
811
|
+
settleTurn(turnArg) {
|
|
812
|
+
if (!this.pendingTurns.delete(turnArg))
|
|
813
|
+
return false;
|
|
814
|
+
clearTimeout(turnArg.timer);
|
|
815
|
+
if (turnArg.terminalTimer)
|
|
816
|
+
clearTimeout(turnArg.terminalTimer);
|
|
817
|
+
turnArg.earlyNotifications.clear();
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
820
|
+
respondToServerRequest(messageArg) {
|
|
821
|
+
const method = String(messageArg.method);
|
|
822
|
+
let result;
|
|
823
|
+
switch (method) {
|
|
824
|
+
case 'item/commandExecution/requestApproval':
|
|
825
|
+
case 'item/fileChange/requestApproval':
|
|
826
|
+
result = { decision: 'decline' };
|
|
827
|
+
break;
|
|
828
|
+
case 'item/tool/requestUserInput':
|
|
829
|
+
result = { answers: {} };
|
|
830
|
+
break;
|
|
831
|
+
case 'mcpServer/elicitation/request':
|
|
832
|
+
result = { action: 'decline', content: null, _meta: null };
|
|
833
|
+
break;
|
|
834
|
+
case 'item/permissions/requestApproval':
|
|
835
|
+
result = { permissions: {}, scope: 'turn' };
|
|
836
|
+
break;
|
|
837
|
+
case 'applyPatchApproval':
|
|
838
|
+
case 'execCommandApproval':
|
|
839
|
+
result = { decision: 'abort' };
|
|
840
|
+
break;
|
|
841
|
+
default:
|
|
842
|
+
try {
|
|
843
|
+
this.sendFrame({
|
|
844
|
+
id: messageArg.id,
|
|
845
|
+
error: { code: -32601, message: `Crossharness does not implement ${method}` },
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
catch { }
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
try {
|
|
852
|
+
this.sendFrame({ id: messageArg.id, result });
|
|
853
|
+
}
|
|
854
|
+
catch { }
|
|
855
|
+
}
|
|
856
|
+
handleSocketFailure(errorArg) {
|
|
857
|
+
if (this.state === 'closed')
|
|
858
|
+
return;
|
|
859
|
+
if (this.state !== 'closing') {
|
|
860
|
+
this.state = 'closing';
|
|
861
|
+
this.rejectAll(errorArg);
|
|
862
|
+
this.onClosing?.();
|
|
863
|
+
this.onClosing = undefined;
|
|
864
|
+
}
|
|
865
|
+
const socket = this.socket;
|
|
866
|
+
if (socket && socket.readyState !== plugins.WsWebSocket.CLOSED) {
|
|
867
|
+
socket.terminate();
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
this.finishClosed();
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
handleSocketClose() {
|
|
874
|
+
if (this.state !== 'closing' && this.state !== 'closed') {
|
|
875
|
+
this.state = 'closing';
|
|
876
|
+
this.rejectAll(new Error('Codex server connection closed'));
|
|
877
|
+
this.onClosing?.();
|
|
878
|
+
this.onClosing = undefined;
|
|
879
|
+
}
|
|
880
|
+
this.finishClosed();
|
|
881
|
+
}
|
|
882
|
+
finishClosed() {
|
|
883
|
+
if (this.state === 'closed')
|
|
884
|
+
return;
|
|
885
|
+
this.state = 'closed';
|
|
886
|
+
this.onClosed?.();
|
|
887
|
+
this.onClosing = undefined;
|
|
888
|
+
this.onClosed = undefined;
|
|
889
|
+
}
|
|
890
|
+
rejectAll(errorArg) {
|
|
891
|
+
for (const pending of this.pendingRequests.values()) {
|
|
892
|
+
this.clearPendingRequestResources(pending);
|
|
893
|
+
pending.reject(errorArg);
|
|
894
|
+
}
|
|
895
|
+
this.pendingRequests.clear();
|
|
896
|
+
for (const turn of [...this.pendingTurns])
|
|
897
|
+
this.failTurn(turn, errorArg);
|
|
898
|
+
for (const [threadId, queue] of this.threadQueues) {
|
|
899
|
+
const activeOffset = this.activeThreads.has(threadId) ? 1 : 0;
|
|
900
|
+
for (const entry of queue.slice(activeOffset)) {
|
|
901
|
+
this.clearQueueEntryResources(entry);
|
|
902
|
+
entry.reject(errorArg);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
this.threadQueues.clear();
|
|
906
|
+
}
|
|
907
|
+
async closeSocket() {
|
|
908
|
+
const socket = this.socket;
|
|
909
|
+
if (!socket || socket.readyState === plugins.WsWebSocket.CLOSED)
|
|
910
|
+
return;
|
|
911
|
+
await new Promise((resolve) => {
|
|
912
|
+
let settled = false;
|
|
913
|
+
const finish = () => {
|
|
914
|
+
if (settled)
|
|
915
|
+
return;
|
|
916
|
+
settled = true;
|
|
917
|
+
clearTimeout(timer);
|
|
918
|
+
socket.off('close', finish);
|
|
919
|
+
resolve();
|
|
920
|
+
};
|
|
921
|
+
const timer = setTimeout(() => {
|
|
922
|
+
socket.terminate();
|
|
923
|
+
finish();
|
|
924
|
+
}, 1000);
|
|
925
|
+
socket.once('close', finish);
|
|
926
|
+
try {
|
|
927
|
+
if (socket.readyState === plugins.WsWebSocket.CONNECTING) {
|
|
928
|
+
socket.terminate();
|
|
929
|
+
}
|
|
930
|
+
else {
|
|
931
|
+
socket.close();
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
catch {
|
|
935
|
+
socket.terminate();
|
|
936
|
+
finish();
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jb25uZWN0aW9uLmNvZGV4LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5jb25uZWN0aW9uLmNvZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUdyRCxNQUFNLGdCQUFnQixHQUFHLFNBQVMsQ0FBQztBQUNuQyxNQUFNLHFCQUFxQixHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQzlDLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDL0MsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ3JDLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDO0FBQ2hDLE1BQU0scUJBQXFCLEdBQUcsR0FBRyxDQUFDO0FBQ2xDLE1BQU0sY0FBYyxHQUFHLEdBQUcsQ0FBQztBQUMzQixNQUFNLHVCQUF1QixHQUFHLEVBQUUsQ0FBQztBQXVEbkMsTUFBTSxPQUFPLGVBQWU7SUFnQlI7SUFDQTtJQUNBO0lBQ1I7SUFDQTtJQW5CTSxPQUFPLEdBQUcsT0FBZ0IsQ0FBQztJQUNwQyxLQUFLLEdBQWdDLFlBQVksQ0FBQztJQUNqRCxXQUFXLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN2QyxhQUFhLENBQXFCO0lBQ2xDLE1BQU0sQ0FBdUQ7SUFDN0QsY0FBYyxHQUFHLENBQUMsQ0FBQztJQUNuQixlQUFlLEdBQUcsSUFBSSxHQUFHLEVBQTJCLENBQUM7SUFDckQsWUFBWSxHQUFHLElBQUksR0FBRyxFQUFnQixDQUFDO0lBQ3ZDLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBK0IsQ0FBQztJQUN0RCxhQUFhLEdB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
|