@jrkropp/codex-js 0.1.1 → 0.1.3
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/CHANGELOG.md +8 -0
- package/dist/ClientNotification-B6-FhXQf.d.ts +5 -0
- package/dist/{DynamicToolCallResponse-D2OVpa4p.d.ts → DynamicToolCallResponse-82DFjES2.d.ts} +1 -1
- package/dist/DynamicToolSpec-CfnhqAYK.d.ts +29 -0
- package/dist/PermissionsRequestApprovalResponse-DxzPPDRb.d.ts +55 -0
- package/dist/ProviderStatusBanner-BlP6lzwE.d.ts +441 -0
- package/dist/ServerRequest-B5cKVJjr.d.ts +2181 -0
- package/dist/{session-BO6EZNK7.d.ts → ThreadResumeResponse-DvmE1juU.d.ts} +3 -290
- package/dist/ToolRequestUserInputQuestion-CeZa5X1J.d.ts +23 -0
- package/dist/{ToolRequestUserInputResponse-Bxjlpgho.d.ts → ToolRequestUserInputResponse-zcPLwbiK.d.ts} +1 -1
- package/dist/TurnSteerResponse-0kBCfplh.d.ts +209 -0
- package/dist/WebSearchToolConfig-D3ep0625.d.ts +18 -0
- package/dist/chat-runtime-B6azJyKo.d.ts +381 -0
- package/dist/chunk-2DZRMCI2.js +1258 -0
- package/dist/chunk-2DZRMCI2.js.map +1 -0
- package/dist/chunk-4DPLJPB5.js +396 -0
- package/dist/chunk-4DPLJPB5.js.map +1 -0
- package/dist/chunk-5JMJ6OI5.js +3 -0
- package/dist/chunk-5JMJ6OI5.js.map +1 -0
- package/dist/chunk-6ZMJ34KE.js +1153 -0
- package/dist/chunk-6ZMJ34KE.js.map +1 -0
- package/dist/chunk-CGBS37IU.js +128 -0
- package/dist/chunk-CGBS37IU.js.map +1 -0
- package/dist/chunk-DCMKA2A6.js +18 -0
- package/dist/chunk-DCMKA2A6.js.map +1 -0
- package/dist/chunk-DYLHN3HG.js +937 -0
- package/dist/chunk-DYLHN3HG.js.map +1 -0
- package/dist/chunk-ILXA6HLX.js +1973 -0
- package/dist/chunk-ILXA6HLX.js.map +1 -0
- package/dist/{chunk-TZBLUZ2X.js → chunk-LWQNX4LI.js} +7811 -12696
- package/dist/chunk-LWQNX4LI.js.map +1 -0
- package/dist/{chunk-FFASNDXU.js → chunk-NCI4MAWZ.js} +317 -1967
- package/dist/chunk-NCI4MAWZ.js.map +1 -0
- package/dist/chunk-O44XP7LH.js +214 -0
- package/dist/chunk-O44XP7LH.js.map +1 -0
- package/dist/chunk-PST3ZWX2.js +555 -0
- package/dist/chunk-PST3ZWX2.js.map +1 -0
- package/dist/chunk-SYPHCDRD.js +1133 -0
- package/dist/chunk-SYPHCDRD.js.map +1 -0
- package/dist/chunk-V4BMZWBM.js +2401 -0
- package/dist/chunk-V4BMZWBM.js.map +1 -0
- package/dist/chunk-YHVCFD2D.js +117 -0
- package/dist/chunk-YHVCFD2D.js.map +1 -0
- package/dist/chunk-Z63UPBS3.js +152 -0
- package/dist/chunk-Z63UPBS3.js.map +1 -0
- package/dist/client/index.d.ts +16 -111
- package/dist/client/index.js +13 -1
- package/dist/codex-rs/app-server/index.d.ts +161 -0
- package/dist/codex-rs/app-server/index.js +13 -0
- package/dist/codex-rs/app-server/index.js.map +1 -0
- package/dist/codex-rs/app-server-protocol/index.d.ts +1722 -0
- package/dist/codex-rs/app-server-protocol/index.js +6 -0
- package/dist/codex-rs/app-server-protocol/index.js.map +1 -0
- package/dist/codex-rs/app-server-protocol/protocol.d.ts +19 -0
- package/dist/codex-rs/app-server-protocol/protocol.js +4 -0
- package/dist/codex-rs/app-server-protocol/protocol.js.map +1 -0
- package/dist/codex-rs/codex-api/index.d.ts +104 -0
- package/dist/codex-rs/codex-api/index.js +11 -0
- package/dist/codex-rs/codex-api/index.js.map +1 -0
- package/dist/codex-rs/config/index.d.ts +88 -0
- package/dist/codex-rs/config/index.js +4 -0
- package/dist/codex-rs/config/index.js.map +1 -0
- package/dist/codex-rs/core/config/index.d.ts +61 -0
- package/dist/codex-rs/core/config/index.js +5 -0
- package/dist/codex-rs/core/config/index.js.map +1 -0
- package/dist/codex-rs/core/index.d.ts +1393 -0
- package/dist/codex-rs/core/index.js +11 -0
- package/dist/codex-rs/core/index.js.map +1 -0
- package/dist/codex-rs/model-provider/index.d.ts +2 -0
- package/dist/codex-rs/model-provider/index.js +4 -0
- package/dist/codex-rs/model-provider/index.js.map +1 -0
- package/dist/codex-rs/models-manager/index.d.ts +2 -0
- package/dist/codex-rs/models-manager/index.js +4 -0
- package/dist/codex-rs/models-manager/index.js.map +1 -0
- package/dist/codex-rs/parity.d.ts +26 -0
- package/dist/codex-rs/parity.js +3 -0
- package/dist/codex-rs/parity.js.map +1 -0
- package/dist/codex-rs/thread-store/index.d.ts +5 -0
- package/dist/codex-rs/thread-store/index.js +4 -0
- package/dist/codex-rs/thread-store/index.js.map +1 -0
- package/dist/codex-rs/unsupported.d.ts +15 -0
- package/dist/codex-rs/unsupported.js +22 -0
- package/dist/codex-rs/unsupported.js.map +1 -0
- package/dist/codex-rs/utils/output-truncation.d.ts +21 -0
- package/dist/codex-rs/utils/output-truncation.js +4 -0
- package/dist/codex-rs/utils/output-truncation.js.map +1 -0
- package/dist/codex-rs/utils/string.d.ts +7 -0
- package/dist/codex-rs/utils/string.js +3 -0
- package/dist/codex-rs/utils/string.js.map +1 -0
- package/dist/common-CTyph5x8.d.ts +40 -0
- package/dist/event-mapping-CbISdQ1D.d.ts +43 -0
- package/dist/history-CfM-4V7b.d.ts +1654 -0
- package/dist/index-77U_Oc-a.d.ts +63 -0
- package/dist/index-CoDZosq0.d.ts +261 -0
- package/dist/index.d.ts +18 -8
- package/dist/index.js +16 -2
- package/dist/lib-nXlaKiS-.d.ts +48 -0
- package/dist/live-thread-BMvlflzM.d.ts +30 -0
- package/dist/merge-B_AWVmnI.d.ts +24 -0
- package/dist/mod-DYVLSWO4.d.ts +91 -0
- package/dist/plan-mode-Cv6KWb_S.d.ts +14 -0
- package/dist/proposed-plan-DpN1ma0Y.d.ts +53 -0
- package/dist/protocol-mpBcYHrm.d.ts +1655 -0
- package/dist/react/index.d.ts +20 -53
- package/dist/react/index.js +16 -2
- package/dist/{remote-DMPfepa9.d.ts → remote-ClZbq9KN.d.ts} +3 -1
- package/dist/rendered-thread-AOxw3V5b.d.ts +29 -0
- package/dist/responses_websocket-BhxSgCzK.d.ts +183 -0
- package/dist/runtime-Cm6ml53h.d.ts +528 -0
- package/dist/server/index.d.ts +29 -1999
- package/dist/server/index.js +13 -1
- package/dist/session-BRYzi8OT.d.ts +46 -0
- package/dist/shadcn/index.d.ts +1 -1
- package/dist/{sidebar-DT2XoitN.d.ts → sidebar-DMMij22z.d.ts} +1 -1
- package/dist/spec_plan_types-CmsJ-Tfn.d.ts +260 -0
- package/dist/{store-H2cQxdpe.d.ts → store-AGRxhgQ3.d.ts} +2 -1
- package/dist/t3code/apps/web/components/chat.d.ts +508 -0
- package/dist/t3code/apps/web/components/chat.js +12 -0
- package/dist/t3code/apps/web/components/chat.js.map +1 -0
- package/dist/t3code/apps/web/index.d.ts +12 -0
- package/dist/t3code/apps/web/index.js +13 -0
- package/dist/t3code/apps/web/index.js.map +1 -0
- package/dist/testing/index.d.ts +9 -91
- package/dist/testing/index.js +13 -1
- package/dist/thread-history-builder-zW0zeqcS.d.ts +58 -0
- package/dist/thread_event_store-C0zYzukG.d.ts +77 -0
- package/dist/types-BTeabLYr.d.ts +126 -0
- package/package.json +152 -88
- package/dist/chat-runtime-CMli5dzJ.d.ts +0 -748
- package/dist/chunk-FFASNDXU.js.map +0 -1
- package/dist/chunk-TZBLUZ2X.js.map +0 -1
- package/dist/thread_event_store-BIS0qzhi.d.ts +0 -3843
|
@@ -0,0 +1,2401 @@
|
|
|
1
|
+
import { asThreadId, SteerInputErrorKind, EmptyMcpConnectionManager, SteerInputError, defaultSessionConfiguration, Session, RegularTask, runTurn, CompactTask, run_compact_task } from './chunk-LWQNX4LI.js';
|
|
2
|
+
import { ThreadSortKey, SortDirection, ThreadMemoryMode, ThreadEventPersistenceMode, LiveThread } from './chunk-CGBS37IU.js';
|
|
3
|
+
import { clientRequestExperimentalReason, clientRequestSerializationScope, appServerTurnFromCoreTurn, threadTokenUsageFromTokenUsageInfo, threadHistoryToAppServerThread, buildThreadResumeResponseFromHistory, eventMsgToAppServerEvents, serverRequestResolvedNotification } from './chunk-2DZRMCI2.js';
|
|
4
|
+
import { ThreadHistoryBuilder } from './chunk-DYLHN3HG.js';
|
|
5
|
+
import { builtinCollaborationModePresets, normalizeCollaborationMode } from './chunk-SYPHCDRD.js';
|
|
6
|
+
import { BaseInstructions } from './chunk-O44XP7LH.js';
|
|
7
|
+
|
|
8
|
+
// src/upstream/codex-rs/app-server-transport/src/transport/mod.ts
|
|
9
|
+
function parseJsonRpcTransportPayload(payload) {
|
|
10
|
+
let value;
|
|
11
|
+
if (typeof payload === "string") {
|
|
12
|
+
try {
|
|
13
|
+
value = JSON.parse(payload);
|
|
14
|
+
} catch {
|
|
15
|
+
return {
|
|
16
|
+
error: jsonRpcParseError("Parse error"),
|
|
17
|
+
id: null,
|
|
18
|
+
type: "invalid"
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
} else if (payload instanceof ArrayBuffer || ArrayBuffer.isView(payload)) {
|
|
22
|
+
const bytes = payload instanceof ArrayBuffer ? new Uint8Array(payload) : new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength);
|
|
23
|
+
try {
|
|
24
|
+
value = JSON.parse(new TextDecoder().decode(bytes));
|
|
25
|
+
} catch {
|
|
26
|
+
return {
|
|
27
|
+
error: jsonRpcParseError("Parse error"),
|
|
28
|
+
id: null,
|
|
29
|
+
type: "invalid"
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
value = payload;
|
|
34
|
+
}
|
|
35
|
+
return parseJsonRpcMessage(value);
|
|
36
|
+
}
|
|
37
|
+
function parseJsonRpcMessage(value) {
|
|
38
|
+
if (!isRecord(value)) {
|
|
39
|
+
return {
|
|
40
|
+
error: jsonRpcInvalidRequestError("Invalid JSON-RPC message"),
|
|
41
|
+
id: null,
|
|
42
|
+
type: "invalid"
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const candidateId = requestIdFromValue(value.id);
|
|
46
|
+
const id = candidateId ?? null;
|
|
47
|
+
if (typeof value.method === "string") {
|
|
48
|
+
if (candidateId !== null) {
|
|
49
|
+
return {
|
|
50
|
+
message: jsonRpcRequest(value.method, candidateId, value.params),
|
|
51
|
+
type: "ok"
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (Object.prototype.hasOwnProperty.call(value, "id")) {
|
|
55
|
+
return {
|
|
56
|
+
error: jsonRpcInvalidRequestError("Invalid JSON-RPC request id"),
|
|
57
|
+
id: null,
|
|
58
|
+
type: "invalid"
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
message: jsonRpcNotification(value.method, value.params),
|
|
63
|
+
type: "ok"
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (Object.prototype.hasOwnProperty.call(value, "error")) {
|
|
67
|
+
if (!isJsonRpcErrorError(value.error)) {
|
|
68
|
+
return {
|
|
69
|
+
error: jsonRpcInvalidRequestError("Invalid JSON-RPC error object"),
|
|
70
|
+
id,
|
|
71
|
+
type: "invalid"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
message: { error: value.error, id },
|
|
76
|
+
type: "ok"
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (Object.prototype.hasOwnProperty.call(value, "result")) {
|
|
80
|
+
if (candidateId === null) {
|
|
81
|
+
return {
|
|
82
|
+
error: jsonRpcInvalidRequestError("Invalid JSON-RPC response id"),
|
|
83
|
+
id: null,
|
|
84
|
+
type: "invalid"
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
message: { id: candidateId, result: value.result },
|
|
89
|
+
type: "ok"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
error: jsonRpcInvalidRequestError("Invalid JSON-RPC message"),
|
|
94
|
+
id,
|
|
95
|
+
type: "invalid"
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function parseServerTransportPayload(payload) {
|
|
99
|
+
const parsed = parseJsonRpcTransportPayload(payload);
|
|
100
|
+
if (parsed.type === "invalid") {
|
|
101
|
+
return parsed;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
message: serverTransportMessage(parsed.message),
|
|
105
|
+
type: "ok"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function parseClientTransportPayload(payload) {
|
|
109
|
+
const parsed = parseJsonRpcTransportPayload(payload);
|
|
110
|
+
if (parsed.type === "invalid") {
|
|
111
|
+
return parsed;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
message: clientTransportMessage(parsed.message),
|
|
115
|
+
type: "ok"
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function serializeOutgoingMessage(message) {
|
|
119
|
+
return JSON.stringify(message);
|
|
120
|
+
}
|
|
121
|
+
function serializeJsonRpcResponse(id, result) {
|
|
122
|
+
return serializeOutgoingMessage({ id, result });
|
|
123
|
+
}
|
|
124
|
+
function serializeJsonRpcError(id, error) {
|
|
125
|
+
return JSON.stringify({ error, id });
|
|
126
|
+
}
|
|
127
|
+
function queuedOutgoingMessage(message, writeComplete) {
|
|
128
|
+
return { message, writeComplete };
|
|
129
|
+
}
|
|
130
|
+
function jsonRpcParseError(message) {
|
|
131
|
+
return { code: -32700, message };
|
|
132
|
+
}
|
|
133
|
+
function jsonRpcInvalidRequestError(message) {
|
|
134
|
+
return { code: -32600, message };
|
|
135
|
+
}
|
|
136
|
+
function jsonRpcInternalError(message) {
|
|
137
|
+
return { code: -32603, message };
|
|
138
|
+
}
|
|
139
|
+
function serverTransportMessage(message) {
|
|
140
|
+
if (isRequest(message)) {
|
|
141
|
+
return { request: message, type: "client_request" };
|
|
142
|
+
}
|
|
143
|
+
if (isNotification(message)) {
|
|
144
|
+
return {
|
|
145
|
+
notification: message,
|
|
146
|
+
type: "client_notification"
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (isError(message)) {
|
|
150
|
+
return { error: message, type: "error" };
|
|
151
|
+
}
|
|
152
|
+
return { response: message, type: "response" };
|
|
153
|
+
}
|
|
154
|
+
function clientTransportMessage(message) {
|
|
155
|
+
if (isRequest(message)) {
|
|
156
|
+
return { request: message, type: "server_request" };
|
|
157
|
+
}
|
|
158
|
+
if (isNotification(message)) {
|
|
159
|
+
return {
|
|
160
|
+
notification: message,
|
|
161
|
+
type: "server_notification"
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (isError(message)) {
|
|
165
|
+
return { error: message, type: "error" };
|
|
166
|
+
}
|
|
167
|
+
return { response: message, type: "response" };
|
|
168
|
+
}
|
|
169
|
+
function jsonRpcRequest(method, id, params) {
|
|
170
|
+
return params === void 0 ? { id, method } : { id, method, params };
|
|
171
|
+
}
|
|
172
|
+
function jsonRpcNotification(method, params) {
|
|
173
|
+
return params === void 0 ? { method } : { method, params };
|
|
174
|
+
}
|
|
175
|
+
function isRequest(message) {
|
|
176
|
+
return typeof message.method === "string" && Object.prototype.hasOwnProperty.call(message, "id");
|
|
177
|
+
}
|
|
178
|
+
function isNotification(message) {
|
|
179
|
+
return typeof message.method === "string" && !Object.prototype.hasOwnProperty.call(message, "id");
|
|
180
|
+
}
|
|
181
|
+
function isError(message) {
|
|
182
|
+
return Object.prototype.hasOwnProperty.call(message, "error");
|
|
183
|
+
}
|
|
184
|
+
function requestIdFromValue(value) {
|
|
185
|
+
return typeof value === "string" || typeof value === "number" ? value : null;
|
|
186
|
+
}
|
|
187
|
+
function isJsonRpcErrorError(value) {
|
|
188
|
+
return isRecord(value) && typeof value.code === "number" && typeof value.message === "string";
|
|
189
|
+
}
|
|
190
|
+
function isRecord(value) {
|
|
191
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// src/upstream/codex-rs/app-server/src/outgoing_message.ts
|
|
195
|
+
var OutgoingMessageSender = class {
|
|
196
|
+
nextServerRequestId = 0;
|
|
197
|
+
requestIdToCallback = /* @__PURE__ */ new Map();
|
|
198
|
+
requestContexts = /* @__PURE__ */ new Map();
|
|
199
|
+
sendMessage;
|
|
200
|
+
constructor(options) {
|
|
201
|
+
this.sendMessage = options.send;
|
|
202
|
+
}
|
|
203
|
+
threadScoped(threadId) {
|
|
204
|
+
return new ThreadScopedOutgoingMessageSender(this, threadId, []);
|
|
205
|
+
}
|
|
206
|
+
threadScopedForConnections(threadId, connectionIds) {
|
|
207
|
+
return new ThreadScopedOutgoingMessageSender(this, threadId, connectionIds);
|
|
208
|
+
}
|
|
209
|
+
async sendServerNotification(notification, context, threadId, connectionIds) {
|
|
210
|
+
await this.sendMessage(notification, {
|
|
211
|
+
connectionIds,
|
|
212
|
+
context,
|
|
213
|
+
threadId: serverNotificationThreadId(notification) ?? threadId
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
async sendRequest(request, threadId = serverRequestThreadId(request), context, connectionIds) {
|
|
217
|
+
return this.sendRequestWithHandle(request, threadId, context, connectionIds).result;
|
|
218
|
+
}
|
|
219
|
+
sendRequestWithHandle(request, threadId = serverRequestThreadId(request), context, connectionIds) {
|
|
220
|
+
const requestWithId = request.id === void 0 ? { ...request, id: this.nextRequestId() } : request;
|
|
221
|
+
let rejectResult = () => {
|
|
222
|
+
};
|
|
223
|
+
const result = new Promise((resolve, reject) => {
|
|
224
|
+
rejectResult = reject;
|
|
225
|
+
this.requestIdToCallback.set(requestWithId.id, {
|
|
226
|
+
callback: (entry) => {
|
|
227
|
+
if (entry.type === "ok") {
|
|
228
|
+
resolve(entry.result);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
reject(entry.error);
|
|
232
|
+
},
|
|
233
|
+
connectionIds: connectionIds ?? null,
|
|
234
|
+
request: requestWithId,
|
|
235
|
+
threadId
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
void Promise.resolve(
|
|
239
|
+
this.sendMessage(requestWithId, {
|
|
240
|
+
connectionIds,
|
|
241
|
+
context,
|
|
242
|
+
threadId: threadId ?? void 0
|
|
243
|
+
})
|
|
244
|
+
).catch((error) => {
|
|
245
|
+
this.requestIdToCallback.delete(requestWithId.id);
|
|
246
|
+
rejectResult(error);
|
|
247
|
+
});
|
|
248
|
+
return { request: requestWithId, result };
|
|
249
|
+
}
|
|
250
|
+
registerRequestContext(requestContext) {
|
|
251
|
+
this.requestContexts.set(connectionRequestKey(requestContext), requestContext);
|
|
252
|
+
}
|
|
253
|
+
requestContext(requestId) {
|
|
254
|
+
return this.requestContexts.get(connectionRequestKey(requestId)) ?? null;
|
|
255
|
+
}
|
|
256
|
+
async sendResponse(requestId, result, context) {
|
|
257
|
+
this.requestContexts.delete(connectionRequestKey(requestId));
|
|
258
|
+
await this.sendMessage(
|
|
259
|
+
{ id: requestId.requestId, result },
|
|
260
|
+
{ connectionIds: [requestId.connectionId], context }
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
async sendError(requestId, error, context) {
|
|
264
|
+
this.requestContexts.delete(connectionRequestKey(requestId));
|
|
265
|
+
await this.sendMessage(
|
|
266
|
+
{ error, id: requestId.requestId },
|
|
267
|
+
{ connectionIds: [requestId.connectionId], context }
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
async notifyClientResponse(id, result) {
|
|
271
|
+
const entry = this.takeRequestCallback(id);
|
|
272
|
+
entry?.callback({ result, type: "ok" });
|
|
273
|
+
}
|
|
274
|
+
async notifyClientError(id, error) {
|
|
275
|
+
const entry = this.takeRequestCallback(id);
|
|
276
|
+
entry?.callback({ error, type: "error" });
|
|
277
|
+
}
|
|
278
|
+
cancelRequest(id) {
|
|
279
|
+
return this.takeRequestCallback(id) !== null;
|
|
280
|
+
}
|
|
281
|
+
connectionClosed(connectionId) {
|
|
282
|
+
for (const [requestKey, requestContext] of this.requestContexts) {
|
|
283
|
+
if (requestContext.connectionId === connectionId) {
|
|
284
|
+
this.requestContexts.delete(requestKey);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
cancelRequestsForThread(threadId, error) {
|
|
289
|
+
for (const [requestId, entry] of this.requestIdToCallback) {
|
|
290
|
+
if (entry.threadId !== threadId) {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
this.requestIdToCallback.delete(requestId);
|
|
294
|
+
if (error) {
|
|
295
|
+
entry.callback({ error, type: "error" });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
pendingRequestsForThread(threadId) {
|
|
300
|
+
return Array.from(this.requestIdToCallback.values()).filter((entry) => entry.threadId === threadId).map((entry) => entry.request).sort((left, right) => String(left.id).localeCompare(String(right.id)));
|
|
301
|
+
}
|
|
302
|
+
nextRequestId() {
|
|
303
|
+
const id = this.nextServerRequestId;
|
|
304
|
+
this.nextServerRequestId += 1;
|
|
305
|
+
return id;
|
|
306
|
+
}
|
|
307
|
+
takeRequestCallback(id) {
|
|
308
|
+
const entry = this.requestIdToCallback.get(id) ?? null;
|
|
309
|
+
this.requestIdToCallback.delete(id);
|
|
310
|
+
return entry;
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
var ThreadScopedOutgoingMessageSender = class {
|
|
314
|
+
constructor(outgoing, threadId, connectionIds = []) {
|
|
315
|
+
this.outgoing = outgoing;
|
|
316
|
+
this.threadId = threadId;
|
|
317
|
+
this.connectionIds = connectionIds;
|
|
318
|
+
}
|
|
319
|
+
outgoing;
|
|
320
|
+
threadId;
|
|
321
|
+
connectionIds;
|
|
322
|
+
sendRequest(request, context) {
|
|
323
|
+
return this.outgoing.sendRequest(
|
|
324
|
+
request,
|
|
325
|
+
this.threadId,
|
|
326
|
+
context,
|
|
327
|
+
this.connectionIds.length > 0 ? this.connectionIds : void 0
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
sendServerNotification(notification, context) {
|
|
331
|
+
return this.outgoing.sendServerNotification(
|
|
332
|
+
notification,
|
|
333
|
+
context,
|
|
334
|
+
this.threadId,
|
|
335
|
+
this.connectionIds.length > 0 ? this.connectionIds : void 0
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
sendResponse(requestId, result, context) {
|
|
339
|
+
return this.outgoing.sendResponse(requestId, result, context);
|
|
340
|
+
}
|
|
341
|
+
sendError(requestId, error, context) {
|
|
342
|
+
return this.outgoing.sendError(requestId, error, context);
|
|
343
|
+
}
|
|
344
|
+
abortPendingServerRequests(error) {
|
|
345
|
+
this.outgoing.cancelRequestsForThread(this.threadId, error);
|
|
346
|
+
}
|
|
347
|
+
pendingRequests() {
|
|
348
|
+
return this.outgoing.pendingRequestsForThread(this.threadId);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
function outgoingMessageToAppServerEvent(message) {
|
|
352
|
+
if (isServerNotification(message)) {
|
|
353
|
+
return {
|
|
354
|
+
notification: message,
|
|
355
|
+
type: "server_notification"
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
if (isServerRequest(message)) {
|
|
359
|
+
return { request: message, type: "server_request" };
|
|
360
|
+
}
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
function serverNotificationThreadId(notification) {
|
|
364
|
+
const params = notification.params;
|
|
365
|
+
if (typeof params?.threadId === "string") {
|
|
366
|
+
return params.threadId;
|
|
367
|
+
}
|
|
368
|
+
const thread = params?.thread;
|
|
369
|
+
if (typeof thread?.id === "string") {
|
|
370
|
+
return thread.id;
|
|
371
|
+
}
|
|
372
|
+
const turn = params?.turn;
|
|
373
|
+
if (typeof turn?.threadId === "string") {
|
|
374
|
+
return turn.threadId;
|
|
375
|
+
}
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
function serverRequestThreadId(request) {
|
|
379
|
+
const params = request.params;
|
|
380
|
+
return typeof params?.threadId === "string" ? params.threadId : null;
|
|
381
|
+
}
|
|
382
|
+
function connectionRequestKey(requestId) {
|
|
383
|
+
return `${requestId.connectionId}:${String(requestId.requestId)}`;
|
|
384
|
+
}
|
|
385
|
+
function isServerRequest(message) {
|
|
386
|
+
return typeof message.method === "string" && Object.prototype.hasOwnProperty.call(message, "id");
|
|
387
|
+
}
|
|
388
|
+
function isServerNotification(message) {
|
|
389
|
+
return typeof message.method === "string" && !Object.prototype.hasOwnProperty.call(message, "id");
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/upstream/codex-rs/app-server/src/request_processors/request_errors.ts
|
|
393
|
+
var CodexAppServerRequestError = class extends Error {
|
|
394
|
+
constructor(error, status = 400) {
|
|
395
|
+
super(error.message);
|
|
396
|
+
this.error = error;
|
|
397
|
+
this.status = status;
|
|
398
|
+
this.name = "CodexAppServerRequestError";
|
|
399
|
+
}
|
|
400
|
+
error;
|
|
401
|
+
status;
|
|
402
|
+
};
|
|
403
|
+
function unsupportedMethodError(method, requestId) {
|
|
404
|
+
return {
|
|
405
|
+
code: -32601,
|
|
406
|
+
data: { requestId },
|
|
407
|
+
message: `Unsupported Codex App Server method: ${method}`
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
function errorToJsonRpcError(error) {
|
|
411
|
+
if (typeof error === "object" && error !== null && typeof error.code === "number" && typeof error.message === "string") {
|
|
412
|
+
return error;
|
|
413
|
+
}
|
|
414
|
+
return {
|
|
415
|
+
code: -32e3,
|
|
416
|
+
message: error instanceof Error ? error.message : "Codex App Server request failed."
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/upstream/codex-rs/app-server/src/connection_rpc_gate.ts
|
|
421
|
+
var ConnectionRpcGateClosedError = class extends Error {
|
|
422
|
+
constructor() {
|
|
423
|
+
super("Codex App Server connection is closed.");
|
|
424
|
+
this.name = "ConnectionRpcGateClosedError";
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
var ConnectionRpcGate = class {
|
|
428
|
+
accepting = true;
|
|
429
|
+
inFlight = 0;
|
|
430
|
+
shutdownWaiters = /* @__PURE__ */ new Set();
|
|
431
|
+
isAccepting() {
|
|
432
|
+
return this.accepting;
|
|
433
|
+
}
|
|
434
|
+
async run(work) {
|
|
435
|
+
if (!this.accepting) {
|
|
436
|
+
throw new ConnectionRpcGateClosedError();
|
|
437
|
+
}
|
|
438
|
+
this.inFlight += 1;
|
|
439
|
+
try {
|
|
440
|
+
return await work();
|
|
441
|
+
} finally {
|
|
442
|
+
this.inFlight -= 1;
|
|
443
|
+
if (!this.accepting && this.inFlight === 0) {
|
|
444
|
+
for (const resolve of this.shutdownWaiters) {
|
|
445
|
+
resolve();
|
|
446
|
+
}
|
|
447
|
+
this.shutdownWaiters.clear();
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
async shutdown() {
|
|
452
|
+
this.accepting = false;
|
|
453
|
+
if (this.inFlight === 0) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
await new Promise((resolve) => {
|
|
457
|
+
this.shutdownWaiters.add(resolve);
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
// src/upstream/codex-rs/app-server/src/request_serialization.ts
|
|
463
|
+
var RequestSerializationQueues = class {
|
|
464
|
+
tails = /* @__PURE__ */ new Map();
|
|
465
|
+
async enqueue(key, work) {
|
|
466
|
+
const previous = this.tails.get(key) ?? Promise.resolve();
|
|
467
|
+
const current = previous.catch(() => void 0).then(() => work());
|
|
468
|
+
const tail = current.catch(() => void 0).finally(() => {
|
|
469
|
+
if (this.tails.get(key) === tail) {
|
|
470
|
+
this.tails.delete(key);
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
this.tails.set(
|
|
474
|
+
key,
|
|
475
|
+
tail
|
|
476
|
+
);
|
|
477
|
+
return current;
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
function requestSerializationQueueKeyFromScope(connectionId, scope) {
|
|
481
|
+
switch (scope.type) {
|
|
482
|
+
case "global":
|
|
483
|
+
return `global:${scope.key}`;
|
|
484
|
+
case "thread":
|
|
485
|
+
return `thread:${scope.threadId}`;
|
|
486
|
+
case "threadPath":
|
|
487
|
+
return `thread-path:${scope.path}`;
|
|
488
|
+
case "commandExecProcess":
|
|
489
|
+
return `connection:${connectionId}:command-exec-process:${scope.processId}`;
|
|
490
|
+
case "process":
|
|
491
|
+
return `connection:${connectionId}:process:${scope.processHandle}`;
|
|
492
|
+
case "fuzzyFileSearchSession":
|
|
493
|
+
return `fuzzy-file-search-session:${scope.sessionId}`;
|
|
494
|
+
case "fsWatch":
|
|
495
|
+
return `connection:${connectionId}:fs-watch:${scope.watchId}`;
|
|
496
|
+
case "mcpOauth":
|
|
497
|
+
return `mcp-oauth:${scope.serverName}`;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// src/upstream/codex-rs/app-server/src/message_processor.ts
|
|
502
|
+
var CodexAppServerConnectionSessionState = class {
|
|
503
|
+
rpcGate = new ConnectionRpcGate();
|
|
504
|
+
initializedState = null;
|
|
505
|
+
constructor(initializedState) {
|
|
506
|
+
this.initializedState = initializedState ?? null;
|
|
507
|
+
}
|
|
508
|
+
initialized() {
|
|
509
|
+
return this.initializedState !== null;
|
|
510
|
+
}
|
|
511
|
+
initialize(state) {
|
|
512
|
+
if (this.initializedState) {
|
|
513
|
+
throw invalidRequest("Already initialized");
|
|
514
|
+
}
|
|
515
|
+
this.initializedState = state;
|
|
516
|
+
}
|
|
517
|
+
experimentalApiEnabled() {
|
|
518
|
+
return this.initializedState?.experimentalApiEnabled ?? false;
|
|
519
|
+
}
|
|
520
|
+
optedOutNotificationMethods() {
|
|
521
|
+
return this.initializedState?.optedOutNotificationMethods ?? /* @__PURE__ */ new Set();
|
|
522
|
+
}
|
|
523
|
+
appServerClientName() {
|
|
524
|
+
return this.initializedState?.appServerClientName ?? null;
|
|
525
|
+
}
|
|
526
|
+
clientVersion() {
|
|
527
|
+
return this.initializedState?.clientVersion ?? null;
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
var CODEX_APP_SERVER_DEFERRED_RESPONSE = {
|
|
531
|
+
__codexAppServerDeferredResponse: true
|
|
532
|
+
};
|
|
533
|
+
function codexAppServerDeferredResponse() {
|
|
534
|
+
return CODEX_APP_SERVER_DEFERRED_RESPONSE;
|
|
535
|
+
}
|
|
536
|
+
var CodexAppServerMessageProcessor = class {
|
|
537
|
+
connectionId;
|
|
538
|
+
requestSerializationQueues;
|
|
539
|
+
session;
|
|
540
|
+
handlers;
|
|
541
|
+
initializeResponse;
|
|
542
|
+
outgoing;
|
|
543
|
+
constructor(options) {
|
|
544
|
+
this.connectionId = options.connectionId ?? defaultConnectionId();
|
|
545
|
+
this.handlers = options.handlers;
|
|
546
|
+
this.initializeResponse = options.initializeResponse;
|
|
547
|
+
this.outgoing = options.outgoing;
|
|
548
|
+
this.requestSerializationQueues = options.requestSerializationQueues ?? new RequestSerializationQueues();
|
|
549
|
+
this.session = options.session ?? new CodexAppServerConnectionSessionState();
|
|
550
|
+
}
|
|
551
|
+
async processClientRequest(request, context) {
|
|
552
|
+
if (request.method === "initialize") {
|
|
553
|
+
return this.initialize(request.params, context);
|
|
554
|
+
}
|
|
555
|
+
if (!this.session.initialized()) {
|
|
556
|
+
throw invalidRequest("Not initialized");
|
|
557
|
+
}
|
|
558
|
+
const experimentalReason = clientRequestExperimentalReason(request);
|
|
559
|
+
if (experimentalReason && !this.session.experimentalApiEnabled()) {
|
|
560
|
+
throw invalidRequest(experimentalRequiredMessage(experimentalReason));
|
|
561
|
+
}
|
|
562
|
+
const scope = clientRequestSerializationScope(request);
|
|
563
|
+
const run = () => this.session.rpcGate.run(
|
|
564
|
+
() => this.handleInitializedClientRequest(request, context)
|
|
565
|
+
);
|
|
566
|
+
try {
|
|
567
|
+
if (!scope) {
|
|
568
|
+
return await run();
|
|
569
|
+
}
|
|
570
|
+
return await this.requestSerializationQueues.enqueue(
|
|
571
|
+
requestSerializationQueueKeyFromScope(this.connectionId, scope),
|
|
572
|
+
run
|
|
573
|
+
);
|
|
574
|
+
} catch (error) {
|
|
575
|
+
if (error instanceof ConnectionRpcGateClosedError) {
|
|
576
|
+
throw new CodexAppServerRequestError(
|
|
577
|
+
{
|
|
578
|
+
code: -32e3,
|
|
579
|
+
message: error.message
|
|
580
|
+
},
|
|
581
|
+
499
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
throw error;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
async processConnectionRequest(request, context) {
|
|
588
|
+
if (!this.outgoing) {
|
|
589
|
+
const result = await this.processClientRequest(request, context);
|
|
590
|
+
return { result, type: "response" };
|
|
591
|
+
}
|
|
592
|
+
const requestId = this.connectionRequestId(request.id);
|
|
593
|
+
this.outgoing.registerRequestContext({
|
|
594
|
+
connectionId: requestId.connectionId,
|
|
595
|
+
requestId: requestId.requestId
|
|
596
|
+
});
|
|
597
|
+
try {
|
|
598
|
+
const result = await this.processClientRequest(request, context);
|
|
599
|
+
if (isCodexAppServerDeferredResponse(result)) {
|
|
600
|
+
return { type: "deferred" };
|
|
601
|
+
}
|
|
602
|
+
await this.outgoing.sendResponse(requestId, result);
|
|
603
|
+
return { result, type: "response" };
|
|
604
|
+
} catch (error) {
|
|
605
|
+
const responseError = error instanceof CodexAppServerRequestError ? error.error : {
|
|
606
|
+
code: -32e3,
|
|
607
|
+
message: error instanceof Error ? error.message : "Codex App Server request failed."
|
|
608
|
+
};
|
|
609
|
+
await this.outgoing.sendError(requestId, responseError);
|
|
610
|
+
return { error: responseError, type: "error" };
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
async shutdown() {
|
|
614
|
+
await this.session.rpcGate.shutdown();
|
|
615
|
+
}
|
|
616
|
+
connectionClosed() {
|
|
617
|
+
this.outgoing?.connectionClosed(this.connectionId);
|
|
618
|
+
return this.shutdown();
|
|
619
|
+
}
|
|
620
|
+
async initialize(params, context) {
|
|
621
|
+
validateClientInfo(params.clientInfo);
|
|
622
|
+
const capabilities = params.capabilities;
|
|
623
|
+
this.session.initialize({
|
|
624
|
+
appServerClientName: params.clientInfo.name,
|
|
625
|
+
clientVersion: params.clientInfo.version,
|
|
626
|
+
experimentalApiEnabled: capabilities?.experimentalApi ?? false,
|
|
627
|
+
optedOutNotificationMethods: new Set(
|
|
628
|
+
capabilities?.optOutNotificationMethods ?? []
|
|
629
|
+
)
|
|
630
|
+
});
|
|
631
|
+
if (this.handlers.initialize) {
|
|
632
|
+
return this.handlers.initialize(params, context, this.session);
|
|
633
|
+
}
|
|
634
|
+
return this.defaultInitializeResponse();
|
|
635
|
+
}
|
|
636
|
+
async handleInitializedClientRequest(request, context) {
|
|
637
|
+
switch (request.method) {
|
|
638
|
+
case "thread/start":
|
|
639
|
+
return this.handlers.threadStart(request.params, context);
|
|
640
|
+
case "thread/resume":
|
|
641
|
+
return this.handlers.threadResume(request.params, context);
|
|
642
|
+
case "thread/list":
|
|
643
|
+
if (this.handlers.threadList) {
|
|
644
|
+
return this.handlers.threadList(request.params, context);
|
|
645
|
+
}
|
|
646
|
+
break;
|
|
647
|
+
case "thread/read":
|
|
648
|
+
if (this.handlers.threadRead) {
|
|
649
|
+
return this.handlers.threadRead(request.params, context);
|
|
650
|
+
}
|
|
651
|
+
break;
|
|
652
|
+
case "thread/name/set":
|
|
653
|
+
if (this.handlers.threadNameSet) {
|
|
654
|
+
return this.handlers.threadNameSet(request.params, context);
|
|
655
|
+
}
|
|
656
|
+
break;
|
|
657
|
+
case "thread/archive":
|
|
658
|
+
if (this.handlers.threadArchive) {
|
|
659
|
+
return this.handlers.threadArchive(request.params, context);
|
|
660
|
+
}
|
|
661
|
+
break;
|
|
662
|
+
case "thread/unarchive":
|
|
663
|
+
if (this.handlers.threadUnarchive) {
|
|
664
|
+
return this.handlers.threadUnarchive(request.params, context);
|
|
665
|
+
}
|
|
666
|
+
break;
|
|
667
|
+
case "thread/metadata/update":
|
|
668
|
+
if (this.handlers.threadMetadataUpdate) {
|
|
669
|
+
return this.handlers.threadMetadataUpdate(request.params, context);
|
|
670
|
+
}
|
|
671
|
+
break;
|
|
672
|
+
case "turn/start":
|
|
673
|
+
return this.handlers.turnStart(request.params, context);
|
|
674
|
+
case "turn/steer":
|
|
675
|
+
return this.handlers.turnSteer(request.params, context);
|
|
676
|
+
case "turn/interrupt":
|
|
677
|
+
return this.handlers.turnInterrupt(request.params, context);
|
|
678
|
+
case "thread/compact/start":
|
|
679
|
+
return this.handlers.threadCompactStart(request.params, context);
|
|
680
|
+
case "collaborationMode/list":
|
|
681
|
+
if (this.handlers.collaborationModeList) {
|
|
682
|
+
return this.handlers.collaborationModeList(request.params, context);
|
|
683
|
+
}
|
|
684
|
+
return {
|
|
685
|
+
data: builtinCollaborationModePresets().map(
|
|
686
|
+
appServerCollaborationModeMask
|
|
687
|
+
)
|
|
688
|
+
};
|
|
689
|
+
case "config/mcpServer/reload":
|
|
690
|
+
if (this.handlers.configMcpServerReload) {
|
|
691
|
+
return this.handlers.configMcpServerReload(request.params, context);
|
|
692
|
+
}
|
|
693
|
+
break;
|
|
694
|
+
case "mcpServerStatus/list":
|
|
695
|
+
if (this.handlers.mcpServerStatusList) {
|
|
696
|
+
return this.handlers.mcpServerStatusList(
|
|
697
|
+
request.params,
|
|
698
|
+
context,
|
|
699
|
+
this.requestContext(request.id)
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
break;
|
|
703
|
+
case "mcpServer/resource/read":
|
|
704
|
+
if (this.handlers.mcpResourceRead) {
|
|
705
|
+
return this.handlers.mcpResourceRead(
|
|
706
|
+
request.params,
|
|
707
|
+
context,
|
|
708
|
+
this.requestContext(request.id)
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
break;
|
|
712
|
+
case "mcpServer/tool/call":
|
|
713
|
+
if (this.handlers.mcpServerToolCall) {
|
|
714
|
+
return this.handlers.mcpServerToolCall(
|
|
715
|
+
request.params,
|
|
716
|
+
context,
|
|
717
|
+
this.requestContext(request.id)
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
break;
|
|
721
|
+
case "mcpServer/oauth/login":
|
|
722
|
+
if (this.handlers.mcpServerOauthLogin) {
|
|
723
|
+
return this.handlers.mcpServerOauthLogin(request.params, context);
|
|
724
|
+
}
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
throw new CodexAppServerRequestError(
|
|
728
|
+
unsupportedMethodError(request.method, request.id),
|
|
729
|
+
404
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
defaultInitializeResponse() {
|
|
733
|
+
const response = typeof this.initializeResponse === "function" ? this.initializeResponse() : this.initializeResponse;
|
|
734
|
+
return response ?? {
|
|
735
|
+
codexHome: "/",
|
|
736
|
+
platformFamily: platformFamily(),
|
|
737
|
+
platformOs: platformOs(),
|
|
738
|
+
userAgent: "codex-js"
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
connectionRequestId(requestId) {
|
|
742
|
+
return {
|
|
743
|
+
connectionId: this.connectionId,
|
|
744
|
+
requestId
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
requestContext(requestId) {
|
|
748
|
+
if (!this.outgoing) {
|
|
749
|
+
return void 0;
|
|
750
|
+
}
|
|
751
|
+
return {
|
|
752
|
+
connectionId: this.connectionId,
|
|
753
|
+
outgoing: this.outgoing,
|
|
754
|
+
requestId: this.connectionRequestId(requestId),
|
|
755
|
+
session: this.session
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
function isCodexAppServerDeferredResponse(value) {
|
|
760
|
+
return typeof value === "object" && value !== null && value.__codexAppServerDeferredResponse === true;
|
|
761
|
+
}
|
|
762
|
+
function validateClientInfo(clientInfo) {
|
|
763
|
+
if (!clientInfo.name || /[\r\n]/u.test(clientInfo.name)) {
|
|
764
|
+
throw invalidRequest(
|
|
765
|
+
`Invalid clientInfo.name: '${clientInfo.name}'. Must be a valid HTTP header value.`
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
function invalidRequest(message) {
|
|
770
|
+
return new CodexAppServerRequestError(
|
|
771
|
+
{ code: -32600, message },
|
|
772
|
+
400
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
function experimentalRequiredMessage(reason) {
|
|
776
|
+
return `Experimental API capability is required for ${reason}.`;
|
|
777
|
+
}
|
|
778
|
+
function defaultConnectionId() {
|
|
779
|
+
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
|
780
|
+
}
|
|
781
|
+
function platformFamily() {
|
|
782
|
+
const navigatorPlatform = globalThis.navigator?.platform;
|
|
783
|
+
if (navigatorPlatform?.toLowerCase().includes("win")) {
|
|
784
|
+
return "windows";
|
|
785
|
+
}
|
|
786
|
+
return "unix";
|
|
787
|
+
}
|
|
788
|
+
function platformOs() {
|
|
789
|
+
const navigatorPlatform = globalThis.navigator?.platform?.toLowerCase();
|
|
790
|
+
if (navigatorPlatform?.includes("mac")) {
|
|
791
|
+
return "macos";
|
|
792
|
+
}
|
|
793
|
+
if (navigatorPlatform?.includes("win")) {
|
|
794
|
+
return "windows";
|
|
795
|
+
}
|
|
796
|
+
if (navigatorPlatform?.includes("linux")) {
|
|
797
|
+
return "linux";
|
|
798
|
+
}
|
|
799
|
+
return "unknown";
|
|
800
|
+
}
|
|
801
|
+
function appServerCollaborationModeMask(mask) {
|
|
802
|
+
return {
|
|
803
|
+
name: mask.name,
|
|
804
|
+
mode: mask.mode ?? null,
|
|
805
|
+
model: mask.model ?? null,
|
|
806
|
+
reasoning_effort: mask.reasoning_effort === void 0 ? null : mask.reasoning_effort
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// src/upstream/codex-rs/app-server/src/request_processors/common.ts
|
|
811
|
+
function appServerUserInputToCoreUserInput(input) {
|
|
812
|
+
switch (input.type) {
|
|
813
|
+
case "text":
|
|
814
|
+
return {
|
|
815
|
+
type: "text",
|
|
816
|
+
text: input.text,
|
|
817
|
+
text_elements: (input.text_elements ?? []).map((element) => ({
|
|
818
|
+
byte_range: element.byteRange,
|
|
819
|
+
placeholder: element.placeholder ?? void 0
|
|
820
|
+
}))
|
|
821
|
+
};
|
|
822
|
+
case "image":
|
|
823
|
+
return { type: "image", image_url: input.url };
|
|
824
|
+
case "localImage":
|
|
825
|
+
return { type: "local_image", path: input.path };
|
|
826
|
+
case "skill":
|
|
827
|
+
return { type: "skill", name: input.name, path: input.path };
|
|
828
|
+
case "mention":
|
|
829
|
+
return { type: "mention", name: input.name, path: input.path };
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
function threadIdFromStartParams(params) {
|
|
833
|
+
const maybeThreadId = params.threadId;
|
|
834
|
+
return asThreadId(typeof maybeThreadId === "string" ? maybeThreadId : defaultId());
|
|
835
|
+
}
|
|
836
|
+
function defaultId() {
|
|
837
|
+
const crypto = globalThis.crypto;
|
|
838
|
+
return crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}`;
|
|
839
|
+
}
|
|
840
|
+
function valueOrNull(value) {
|
|
841
|
+
return value === void 0 ? null : value;
|
|
842
|
+
}
|
|
843
|
+
function approvalPolicyString(value) {
|
|
844
|
+
return typeof value === "string" ? value : null;
|
|
845
|
+
}
|
|
846
|
+
function jsonRpcError(message, code, status) {
|
|
847
|
+
throw new CodexAppServerRequestError(
|
|
848
|
+
{ code, message },
|
|
849
|
+
status
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
function steerErrorCode(kind) {
|
|
853
|
+
switch (kind) {
|
|
854
|
+
case SteerInputErrorKind.EmptyInput:
|
|
855
|
+
return -32602;
|
|
856
|
+
case SteerInputErrorKind.NoActiveTurn:
|
|
857
|
+
return -32012;
|
|
858
|
+
case SteerInputErrorKind.ExpectedTurnMismatch:
|
|
859
|
+
return -32013;
|
|
860
|
+
case SteerInputErrorKind.ActiveTurnNotSteerable:
|
|
861
|
+
return -32015;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// src/upstream/codex-rs/app-server/src/request_processors/mcp_processor.ts
|
|
866
|
+
var MCP_TOOL_THREAD_ID_META_KEY = "threadId";
|
|
867
|
+
var McpRequestProcessor = class {
|
|
868
|
+
constructor(options) {
|
|
869
|
+
this.options = options;
|
|
870
|
+
}
|
|
871
|
+
options;
|
|
872
|
+
async mcpServerRefresh(_params, context) {
|
|
873
|
+
await this.options.reloadMcpServers?.({ context });
|
|
874
|
+
return {};
|
|
875
|
+
}
|
|
876
|
+
async mcpServerStatusList(params, context, request) {
|
|
877
|
+
if (request) {
|
|
878
|
+
this.runDeferred(
|
|
879
|
+
request,
|
|
880
|
+
context,
|
|
881
|
+
() => this.mcpServerStatusListResponse(params)
|
|
882
|
+
);
|
|
883
|
+
return codexAppServerDeferredResponse();
|
|
884
|
+
}
|
|
885
|
+
return this.mcpServerStatusListResponse(params);
|
|
886
|
+
}
|
|
887
|
+
async mcpServerStatusListResponse(params) {
|
|
888
|
+
const detail = params.detail ?? "full";
|
|
889
|
+
const statuses = await this.manager().list_server_statuses({ detail });
|
|
890
|
+
const total = statuses.length;
|
|
891
|
+
const limit = Math.min(Math.max(params.limit ?? total, 1), total);
|
|
892
|
+
const start = params.cursor ? parseCursor(params.cursor) : 0;
|
|
893
|
+
if (start > total) {
|
|
894
|
+
jsonRpcError(
|
|
895
|
+
`cursor ${start} exceeds total MCP servers ${total}`,
|
|
896
|
+
-32600,
|
|
897
|
+
400
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
const end = Math.min(start + limit, total);
|
|
901
|
+
return {
|
|
902
|
+
data: statuses.slice(start, end).map(
|
|
903
|
+
(status) => appServerMcpServerStatus(status, detail)
|
|
904
|
+
),
|
|
905
|
+
nextCursor: end < total ? String(end) : null
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
async mcpResourceRead(params, context, request) {
|
|
909
|
+
if (request) {
|
|
910
|
+
this.runDeferred(
|
|
911
|
+
request,
|
|
912
|
+
context,
|
|
913
|
+
() => this.mcpResourceReadResponse(params)
|
|
914
|
+
);
|
|
915
|
+
return codexAppServerDeferredResponse();
|
|
916
|
+
}
|
|
917
|
+
return this.mcpResourceReadResponse(params);
|
|
918
|
+
}
|
|
919
|
+
async mcpResourceReadResponse(params) {
|
|
920
|
+
if (params.threadId) {
|
|
921
|
+
await this.loadThread(params.threadId);
|
|
922
|
+
}
|
|
923
|
+
const response = await this.manager().read_resource({
|
|
924
|
+
thread_id: params.threadId ? asThreadId(params.threadId) : null,
|
|
925
|
+
server_name: params.server,
|
|
926
|
+
uri: params.uri
|
|
927
|
+
});
|
|
928
|
+
return {
|
|
929
|
+
contents: response.contents.map(
|
|
930
|
+
(content) => appServerResourceContent(content, params.uri)
|
|
931
|
+
)
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
async mcpServerToolCall(params, context, request) {
|
|
935
|
+
if (request) {
|
|
936
|
+
this.runDeferred(
|
|
937
|
+
request,
|
|
938
|
+
context,
|
|
939
|
+
() => this.mcpServerToolCallResponse(params)
|
|
940
|
+
);
|
|
941
|
+
return codexAppServerDeferredResponse();
|
|
942
|
+
}
|
|
943
|
+
return this.mcpServerToolCallResponse(params);
|
|
944
|
+
}
|
|
945
|
+
async mcpServerToolCallResponse(params) {
|
|
946
|
+
const threadId = await this.loadThread(params.threadId);
|
|
947
|
+
const response = await this.manager().call_tool({
|
|
948
|
+
arguments: params.arguments,
|
|
949
|
+
meta: with_mcp_tool_call_thread_id_meta(params._meta, threadId),
|
|
950
|
+
server_name: params.server,
|
|
951
|
+
thread_id: threadId,
|
|
952
|
+
tool_name: params.tool
|
|
953
|
+
});
|
|
954
|
+
return appServerMcpToolCallResponse(response);
|
|
955
|
+
}
|
|
956
|
+
async mcpServerOauthLogin(params, context) {
|
|
957
|
+
if (!this.options.mcpServerOauthLogin) {
|
|
958
|
+
jsonRpcError("MCP OAuth login is unavailable.", -32600, 400);
|
|
959
|
+
}
|
|
960
|
+
return this.options.mcpServerOauthLogin({ context, params });
|
|
961
|
+
}
|
|
962
|
+
manager() {
|
|
963
|
+
return this.options.mcpConnectionManager ?? EmptyMcpConnectionManager.instance;
|
|
964
|
+
}
|
|
965
|
+
runDeferred(request, context, work) {
|
|
966
|
+
const promise = (async () => {
|
|
967
|
+
try {
|
|
968
|
+
await request.outgoing.sendResponse(
|
|
969
|
+
request.requestId,
|
|
970
|
+
await work(),
|
|
971
|
+
context
|
|
972
|
+
);
|
|
973
|
+
} catch (error) {
|
|
974
|
+
await request.outgoing.sendError(
|
|
975
|
+
request.requestId,
|
|
976
|
+
jsonRpcErrorFromUnknown(error),
|
|
977
|
+
context
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
})();
|
|
981
|
+
if (this.options.runInBackground) {
|
|
982
|
+
this.options.runInBackground(promise, { context });
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
async loadThread(threadIdString) {
|
|
987
|
+
let threadId;
|
|
988
|
+
try {
|
|
989
|
+
threadId = asThreadId(threadIdString);
|
|
990
|
+
} catch (error) {
|
|
991
|
+
jsonRpcError(
|
|
992
|
+
`invalid thread id: ${error instanceof Error ? error.message : String(error)}`,
|
|
993
|
+
-32600,
|
|
994
|
+
400
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
try {
|
|
998
|
+
await this.options.store.readThread({
|
|
999
|
+
thread_id: threadId,
|
|
1000
|
+
include_archived: false,
|
|
1001
|
+
include_history: false
|
|
1002
|
+
});
|
|
1003
|
+
} catch {
|
|
1004
|
+
jsonRpcError(`thread not found: ${threadId}`, -32600, 400);
|
|
1005
|
+
}
|
|
1006
|
+
return threadId;
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
function parseCursor(cursor) {
|
|
1010
|
+
if (!/^\d+$/u.test(cursor)) {
|
|
1011
|
+
jsonRpcError(`invalid cursor: ${cursor}`, -32600, 400);
|
|
1012
|
+
}
|
|
1013
|
+
const parsed = Number.parseInt(cursor, 10);
|
|
1014
|
+
return parsed;
|
|
1015
|
+
}
|
|
1016
|
+
function appServerMcpServerStatus(status, detail) {
|
|
1017
|
+
return {
|
|
1018
|
+
authStatus: status.authStatus ?? status.auth_status ?? "unsupported",
|
|
1019
|
+
name: status.name,
|
|
1020
|
+
resources: detail === "toolsAndAuthOnly" ? [] : (status.resources ?? []).map(appServerResource),
|
|
1021
|
+
resourceTemplates: detail === "toolsAndAuthOnly" ? [] : (status.resource_templates ?? []).map(appServerResourceTemplate),
|
|
1022
|
+
tools: Object.fromEntries(
|
|
1023
|
+
(status.tools ?? []).map((tool) => [tool.name, appServerTool(tool)])
|
|
1024
|
+
)
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
function appServerTool(tool) {
|
|
1028
|
+
return omitUndefined({
|
|
1029
|
+
name: tool.name,
|
|
1030
|
+
title: tool.title ?? void 0,
|
|
1031
|
+
description: tool.description ?? void 0,
|
|
1032
|
+
inputSchema: tool.input_schema ?? { type: "object" }
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
function appServerResource(resource) {
|
|
1036
|
+
return omitUndefined({
|
|
1037
|
+
uri: resource.uri,
|
|
1038
|
+
name: resource.name ?? resource.uri,
|
|
1039
|
+
description: resource.description ?? void 0,
|
|
1040
|
+
mimeType: resource.mime_type ?? void 0
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
function appServerResourceTemplate(template) {
|
|
1044
|
+
return omitUndefined({
|
|
1045
|
+
uriTemplate: template.uri_template,
|
|
1046
|
+
name: template.name ?? template.uri_template,
|
|
1047
|
+
title: void 0,
|
|
1048
|
+
description: template.description ?? void 0,
|
|
1049
|
+
mimeType: template.mime_type ?? void 0
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
function appServerResourceContent(content, fallbackUri) {
|
|
1053
|
+
if (!isRecord2(content)) {
|
|
1054
|
+
return { uri: fallbackUri, text: String(content) };
|
|
1055
|
+
}
|
|
1056
|
+
const uri = typeof content.uri === "string" ? content.uri : fallbackUri;
|
|
1057
|
+
const mimeType = typeof content.mimeType === "string" ? content.mimeType : typeof content.mime_type === "string" ? content.mime_type : void 0;
|
|
1058
|
+
if (typeof content.blob === "string") {
|
|
1059
|
+
return omitUndefined({
|
|
1060
|
+
uri,
|
|
1061
|
+
mimeType,
|
|
1062
|
+
blob: content.blob,
|
|
1063
|
+
_meta: content._meta
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
return omitUndefined({
|
|
1067
|
+
uri,
|
|
1068
|
+
mimeType,
|
|
1069
|
+
text: typeof content.text === "string" ? content.text : JSON.stringify(content),
|
|
1070
|
+
_meta: content._meta
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
function appServerMcpToolCallResponse(response) {
|
|
1074
|
+
const output = response.output;
|
|
1075
|
+
const record = isRecord2(output) ? output : {};
|
|
1076
|
+
const structuredContent = record.structuredContent ?? record.structured_content ?? void 0;
|
|
1077
|
+
const isError2 = record.isError ?? record.is_error ?? void 0;
|
|
1078
|
+
return omitUndefined({
|
|
1079
|
+
content: Array.isArray(record.content) ? record.content : [],
|
|
1080
|
+
structuredContent,
|
|
1081
|
+
isError: typeof isError2 === "boolean" ? isError2 : void 0,
|
|
1082
|
+
_meta: record._meta
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
function with_mcp_tool_call_thread_id_meta(meta, threadId) {
|
|
1086
|
+
if (meta === void 0) {
|
|
1087
|
+
return { [MCP_TOOL_THREAD_ID_META_KEY]: threadId };
|
|
1088
|
+
}
|
|
1089
|
+
if (isRecord2(meta)) {
|
|
1090
|
+
return {
|
|
1091
|
+
...meta,
|
|
1092
|
+
[MCP_TOOL_THREAD_ID_META_KEY]: threadId
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
return meta;
|
|
1096
|
+
}
|
|
1097
|
+
function jsonRpcErrorFromUnknown(error) {
|
|
1098
|
+
if (error instanceof CodexAppServerRequestError) {
|
|
1099
|
+
return error.error;
|
|
1100
|
+
}
|
|
1101
|
+
return {
|
|
1102
|
+
code: -32e3,
|
|
1103
|
+
message: error instanceof Error ? error.message : "Codex App Server request failed."
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
function omitUndefined(record) {
|
|
1107
|
+
return Object.fromEntries(
|
|
1108
|
+
Object.entries(record).filter(([, value]) => value !== void 0)
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
1111
|
+
function isRecord2(value) {
|
|
1112
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// src/upstream/codex-rs/app-server/src/request_processors/token_usage_replay.ts
|
|
1116
|
+
function latest_token_usage_turn_id_from_rollout_items(rolloutItems, turns) {
|
|
1117
|
+
const builder = new ThreadHistoryBuilder();
|
|
1118
|
+
let tokenUsageTurnOwner = null;
|
|
1119
|
+
for (const item of rolloutItems) {
|
|
1120
|
+
if (item.type === "event_msg" && item.payload.type === "token_count") {
|
|
1121
|
+
const turn = builder.active_turn_snapshot();
|
|
1122
|
+
tokenUsageTurnOwner = turn ? {
|
|
1123
|
+
id: appServerTurnFromCoreTurn(turn).id,
|
|
1124
|
+
position: builder.active_turn_position()
|
|
1125
|
+
} : null;
|
|
1126
|
+
}
|
|
1127
|
+
builder.handle_rollout_item(item);
|
|
1128
|
+
}
|
|
1129
|
+
if (!tokenUsageTurnOwner) {
|
|
1130
|
+
return null;
|
|
1131
|
+
}
|
|
1132
|
+
if (turns.some((turn) => turn.id === tokenUsageTurnOwner.id)) {
|
|
1133
|
+
return tokenUsageTurnOwner.id;
|
|
1134
|
+
}
|
|
1135
|
+
return tokenUsageTurnOwner.position === null ? null : turns[tokenUsageTurnOwner.position]?.id ?? null;
|
|
1136
|
+
}
|
|
1137
|
+
function latest_token_usage_turn_id(thread) {
|
|
1138
|
+
return [...thread.turns].reverse().find((turn) => turn.status === "completed" || turn.status === "failed")?.id ?? thread.turns.at(-1)?.id ?? "";
|
|
1139
|
+
}
|
|
1140
|
+
function last_token_info_from_rollout_items(rolloutItems) {
|
|
1141
|
+
for (let index = rolloutItems.length - 1; index >= 0; index -= 1) {
|
|
1142
|
+
const item = rolloutItems[index];
|
|
1143
|
+
if (item?.type === "event_msg" && item.payload.type === "token_count" && item.payload.info) {
|
|
1144
|
+
return item.payload.info;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
function thread_token_usage_updated_notification_from_info(input) {
|
|
1150
|
+
const params = {
|
|
1151
|
+
threadId: String(input.threadId),
|
|
1152
|
+
turnId: input.tokenUsageTurnId ?? latest_token_usage_turn_id(input.thread),
|
|
1153
|
+
tokenUsage: threadTokenUsageFromTokenUsageInfo(input.tokenUsageInfo)
|
|
1154
|
+
};
|
|
1155
|
+
return {
|
|
1156
|
+
method: "thread/tokenUsage/updated",
|
|
1157
|
+
params
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
function thread_token_usage_updated_notification_from_rollout_items(input) {
|
|
1161
|
+
const tokenUsageInfo = last_token_info_from_rollout_items(input.rolloutItems);
|
|
1162
|
+
if (!tokenUsageInfo) {
|
|
1163
|
+
return null;
|
|
1164
|
+
}
|
|
1165
|
+
return thread_token_usage_updated_notification_from_info({
|
|
1166
|
+
thread: input.thread,
|
|
1167
|
+
threadId: input.threadId,
|
|
1168
|
+
tokenUsageInfo,
|
|
1169
|
+
tokenUsageTurnId: latest_token_usage_turn_id_from_rollout_items(
|
|
1170
|
+
input.rolloutItems,
|
|
1171
|
+
input.thread.turns
|
|
1172
|
+
)
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
// src/upstream/codex-rs/app-server/src/request_processors/thread_processor.ts
|
|
1177
|
+
var THREAD_LIST_DEFAULT_LIMIT = 25;
|
|
1178
|
+
var THREAD_LIST_MAX_LIMIT = 100;
|
|
1179
|
+
var ThreadRequestProcessor = class {
|
|
1180
|
+
constructor(options) {
|
|
1181
|
+
this.options = options;
|
|
1182
|
+
}
|
|
1183
|
+
options;
|
|
1184
|
+
async threadStart(params, context) {
|
|
1185
|
+
const liveThread = await this.ensureLiveThread(params, context);
|
|
1186
|
+
const response = await this.readThreadResponse(liveThread.threadId);
|
|
1187
|
+
await this.options.emit(
|
|
1188
|
+
liveThread.threadId,
|
|
1189
|
+
{
|
|
1190
|
+
type: "server_notification",
|
|
1191
|
+
notification: {
|
|
1192
|
+
method: "thread/started",
|
|
1193
|
+
params: { thread: response.thread }
|
|
1194
|
+
}
|
|
1195
|
+
},
|
|
1196
|
+
context
|
|
1197
|
+
);
|
|
1198
|
+
return response;
|
|
1199
|
+
}
|
|
1200
|
+
async threadResume(params, context) {
|
|
1201
|
+
const threadId = asThreadId(params.threadId);
|
|
1202
|
+
const { history, response } = await this.readThreadResponseWithHistory(threadId);
|
|
1203
|
+
const replay = thread_token_usage_updated_notification_from_rollout_items({
|
|
1204
|
+
rolloutItems: history.items,
|
|
1205
|
+
thread: response.thread,
|
|
1206
|
+
threadId
|
|
1207
|
+
});
|
|
1208
|
+
if (replay) {
|
|
1209
|
+
await this.options.emit(threadId, {
|
|
1210
|
+
notification: replay,
|
|
1211
|
+
type: "server_notification"
|
|
1212
|
+
}, context);
|
|
1213
|
+
}
|
|
1214
|
+
return response;
|
|
1215
|
+
}
|
|
1216
|
+
async threadCompactStart(params, context) {
|
|
1217
|
+
const threadId = asThreadId(params.threadId);
|
|
1218
|
+
let runtimeSession = this.options.sessions.get(threadId);
|
|
1219
|
+
if (runtimeSession?.session.activeTurn) {
|
|
1220
|
+
throw jsonRpcError("Wait for the active turn to finish before compacting.", -32014, 409);
|
|
1221
|
+
}
|
|
1222
|
+
const submission = {
|
|
1223
|
+
id: `compact-${defaultId()}`,
|
|
1224
|
+
op: { type: "compact" }
|
|
1225
|
+
};
|
|
1226
|
+
if (!runtimeSession) {
|
|
1227
|
+
const session = await this.options.createSession(threadId, params, context, submission);
|
|
1228
|
+
runtimeSession = {
|
|
1229
|
+
abortController: null,
|
|
1230
|
+
runPromise: null,
|
|
1231
|
+
session
|
|
1232
|
+
};
|
|
1233
|
+
this.options.sessions.set(threadId, runtimeSession);
|
|
1234
|
+
}
|
|
1235
|
+
await this.options.taskRunner.startCompactTask({
|
|
1236
|
+
context,
|
|
1237
|
+
params,
|
|
1238
|
+
runtimeSession,
|
|
1239
|
+
submission,
|
|
1240
|
+
threadId
|
|
1241
|
+
});
|
|
1242
|
+
return {};
|
|
1243
|
+
}
|
|
1244
|
+
async threadList(params) {
|
|
1245
|
+
const pageSize = Math.max(
|
|
1246
|
+
1,
|
|
1247
|
+
Math.min(params.limit ?? THREAD_LIST_DEFAULT_LIMIT, THREAD_LIST_MAX_LIMIT)
|
|
1248
|
+
);
|
|
1249
|
+
const page = await this.options.store.listThreads({
|
|
1250
|
+
allowed_sources: params.sourceKinds?.length ? params.sourceKinds : [],
|
|
1251
|
+
archived: params.archived ?? false,
|
|
1252
|
+
cursor: params.cursor ?? null,
|
|
1253
|
+
cwd_filters: cwdFilters(params.cwd),
|
|
1254
|
+
model_providers: params.modelProviders ?? null,
|
|
1255
|
+
page_size: pageSize,
|
|
1256
|
+
search_term: params.searchTerm ?? null,
|
|
1257
|
+
sort_direction: params.sortDirection === "asc" ? SortDirection.Asc : SortDirection.Desc,
|
|
1258
|
+
sort_key: params.sortKey === "updated_at" ? ThreadSortKey.UpdatedAt : ThreadSortKey.CreatedAt,
|
|
1259
|
+
use_state_db_only: params.useStateDbOnly ?? false
|
|
1260
|
+
});
|
|
1261
|
+
return {
|
|
1262
|
+
backwardsCursor: null,
|
|
1263
|
+
data: page.items.map(
|
|
1264
|
+
(thread) => threadHistoryToAppServerThread({
|
|
1265
|
+
history: { items: [], thread_id: thread.thread_id },
|
|
1266
|
+
thread
|
|
1267
|
+
})
|
|
1268
|
+
),
|
|
1269
|
+
nextCursor: page.next_cursor ?? null
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
async threadRead(params) {
|
|
1273
|
+
const threadId = asThreadId(params.threadId);
|
|
1274
|
+
const storedThread = await this.options.store.readThread({
|
|
1275
|
+
thread_id: threadId,
|
|
1276
|
+
include_archived: true,
|
|
1277
|
+
include_history: params.includeTurns
|
|
1278
|
+
});
|
|
1279
|
+
const history = params.includeTurns ? storedThread.history ?? await this.options.store.loadHistory({
|
|
1280
|
+
thread_id: threadId,
|
|
1281
|
+
include_archived: true
|
|
1282
|
+
}) : { items: [], thread_id: threadId };
|
|
1283
|
+
return {
|
|
1284
|
+
thread: threadHistoryToAppServerThread({
|
|
1285
|
+
history,
|
|
1286
|
+
thread: storedThread
|
|
1287
|
+
})
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
async threadNameSet(params, context) {
|
|
1291
|
+
const threadId = asThreadId(params.threadId);
|
|
1292
|
+
const name = normalizeThreadName(params.name);
|
|
1293
|
+
if (!name) {
|
|
1294
|
+
jsonRpcError("thread name must not be empty", -32600, 400);
|
|
1295
|
+
}
|
|
1296
|
+
await this.options.store.updateThreadMetadata({
|
|
1297
|
+
thread_id: threadId,
|
|
1298
|
+
include_archived: false,
|
|
1299
|
+
patch: { name }
|
|
1300
|
+
});
|
|
1301
|
+
await this.options.emit(
|
|
1302
|
+
threadId,
|
|
1303
|
+
{
|
|
1304
|
+
type: "server_notification",
|
|
1305
|
+
notification: {
|
|
1306
|
+
method: "thread/name/updated",
|
|
1307
|
+
params: { threadId, threadName: name }
|
|
1308
|
+
}
|
|
1309
|
+
},
|
|
1310
|
+
context
|
|
1311
|
+
);
|
|
1312
|
+
return {};
|
|
1313
|
+
}
|
|
1314
|
+
async threadArchive(params, context) {
|
|
1315
|
+
const threadId = asThreadId(params.threadId);
|
|
1316
|
+
await this.options.store.archiveThread({ thread_id: threadId });
|
|
1317
|
+
await this.options.emit(
|
|
1318
|
+
threadId,
|
|
1319
|
+
{
|
|
1320
|
+
type: "server_notification",
|
|
1321
|
+
notification: {
|
|
1322
|
+
method: "thread/archived",
|
|
1323
|
+
params: { threadId }
|
|
1324
|
+
}
|
|
1325
|
+
},
|
|
1326
|
+
context
|
|
1327
|
+
);
|
|
1328
|
+
return {};
|
|
1329
|
+
}
|
|
1330
|
+
async threadUnarchive(params, context) {
|
|
1331
|
+
const threadId = asThreadId(params.threadId);
|
|
1332
|
+
const storedThread = await this.options.store.unarchiveThread({
|
|
1333
|
+
thread_id: threadId
|
|
1334
|
+
});
|
|
1335
|
+
await this.options.emit(
|
|
1336
|
+
threadId,
|
|
1337
|
+
{
|
|
1338
|
+
type: "server_notification",
|
|
1339
|
+
notification: {
|
|
1340
|
+
method: "thread/unarchived",
|
|
1341
|
+
params: { threadId }
|
|
1342
|
+
}
|
|
1343
|
+
},
|
|
1344
|
+
context
|
|
1345
|
+
);
|
|
1346
|
+
return {
|
|
1347
|
+
thread: threadHistoryToAppServerThread({
|
|
1348
|
+
history: { items: [], thread_id: threadId },
|
|
1349
|
+
thread: storedThread
|
|
1350
|
+
})
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
1353
|
+
async threadMetadataUpdate(params) {
|
|
1354
|
+
const threadId = asThreadId(params.threadId);
|
|
1355
|
+
if (!params.gitInfo || params.gitInfo.sha === void 0 && params.gitInfo.branch === void 0 && params.gitInfo.originUrl === void 0) {
|
|
1356
|
+
jsonRpcError("gitInfo must include at least one field", -32600, 400);
|
|
1357
|
+
}
|
|
1358
|
+
const storedThread = await this.options.store.updateThreadMetadata({
|
|
1359
|
+
thread_id: threadId,
|
|
1360
|
+
include_archived: true,
|
|
1361
|
+
patch: {
|
|
1362
|
+
git_info: {
|
|
1363
|
+
branch: normalizeOptionalGitField(params.gitInfo.branch, "gitInfo.branch"),
|
|
1364
|
+
origin_url: normalizeOptionalGitField(
|
|
1365
|
+
params.gitInfo.originUrl,
|
|
1366
|
+
"gitInfo.originUrl"
|
|
1367
|
+
),
|
|
1368
|
+
sha: normalizeOptionalGitField(params.gitInfo.sha, "gitInfo.sha")
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
return {
|
|
1373
|
+
thread: threadHistoryToAppServerThread({
|
|
1374
|
+
history: { items: [], thread_id: threadId },
|
|
1375
|
+
thread: storedThread
|
|
1376
|
+
})
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
async readThreadResponse(threadId) {
|
|
1380
|
+
return (await this.readThreadResponseWithHistory(threadId)).response;
|
|
1381
|
+
}
|
|
1382
|
+
async readThreadResponseWithHistory(threadId) {
|
|
1383
|
+
const thread = await this.options.store.readThread({
|
|
1384
|
+
thread_id: threadId,
|
|
1385
|
+
include_archived: false,
|
|
1386
|
+
include_history: false
|
|
1387
|
+
});
|
|
1388
|
+
const history = await this.options.store.loadHistory({
|
|
1389
|
+
thread_id: threadId,
|
|
1390
|
+
include_archived: false
|
|
1391
|
+
});
|
|
1392
|
+
return {
|
|
1393
|
+
history,
|
|
1394
|
+
response: buildThreadResumeResponseFromHistory({ history, thread }),
|
|
1395
|
+
thread
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
async createThreadParams(params, context) {
|
|
1399
|
+
const threadId = threadIdFromStartParams(params);
|
|
1400
|
+
if (this.options.buildCreateThreadParams) {
|
|
1401
|
+
return this.options.buildCreateThreadParams({ context, params, threadId });
|
|
1402
|
+
}
|
|
1403
|
+
const dynamicTools = await this.options.resolveDynamicTools?.({ context, params, threadId }) ?? [];
|
|
1404
|
+
return {
|
|
1405
|
+
base_instructions: {
|
|
1406
|
+
text: params.baseInstructions ?? BaseInstructions.default().text
|
|
1407
|
+
},
|
|
1408
|
+
dynamic_tools: dynamicTools,
|
|
1409
|
+
event_persistence_mode: ThreadEventPersistenceMode.Limited,
|
|
1410
|
+
metadata: {
|
|
1411
|
+
cwd: params.cwd ?? "/",
|
|
1412
|
+
memory_mode: ThreadMemoryMode.Disabled,
|
|
1413
|
+
model: params.model ?? "gpt-5.5",
|
|
1414
|
+
model_provider: params.modelProvider ?? "openai"
|
|
1415
|
+
},
|
|
1416
|
+
source: "appServer",
|
|
1417
|
+
thread_id: threadId,
|
|
1418
|
+
thread_source: typeof params.threadSource === "string" ? params.threadSource : null
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
async ensureLiveThread(params, context) {
|
|
1422
|
+
const createParams = await this.createThreadParams(params, context);
|
|
1423
|
+
validateDynamicToolSpecs(createParams.dynamic_tools);
|
|
1424
|
+
try {
|
|
1425
|
+
await this.options.store.readThread({
|
|
1426
|
+
thread_id: createParams.thread_id,
|
|
1427
|
+
include_archived: false,
|
|
1428
|
+
include_history: false
|
|
1429
|
+
});
|
|
1430
|
+
return LiveThread.resume(this.options.store, {
|
|
1431
|
+
thread_id: createParams.thread_id,
|
|
1432
|
+
include_archived: false,
|
|
1433
|
+
metadata: createParams.metadata,
|
|
1434
|
+
event_persistence_mode: createParams.event_persistence_mode
|
|
1435
|
+
});
|
|
1436
|
+
} catch {
|
|
1437
|
+
return LiveThread.create(this.options.store, createParams);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
function validateDynamicToolSpecs(tools) {
|
|
1442
|
+
for (const tool of tools) {
|
|
1443
|
+
if (tool.defer_loading && !tool.namespace) {
|
|
1444
|
+
jsonRpcError(
|
|
1445
|
+
`Dynamic tool ${tool.name} uses defer_loading and must include a namespace.`,
|
|
1446
|
+
-32600,
|
|
1447
|
+
400
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
const invalidName = invalidResponsesApiToolName(tool.name) ? tool.name : tool.namespace && invalidResponsesApiToolName(tool.namespace) ? tool.namespace : null;
|
|
1451
|
+
if (invalidName) {
|
|
1452
|
+
jsonRpcError(
|
|
1453
|
+
`Dynamic tool ${invalidName} is not supported by the Responses API. Tool names and namespaces may only contain letters, numbers, underscores, and hyphens.`,
|
|
1454
|
+
-32600,
|
|
1455
|
+
400
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
function invalidResponsesApiToolName(value) {
|
|
1461
|
+
return !/^[A-Za-z0-9_-]+$/.test(value);
|
|
1462
|
+
}
|
|
1463
|
+
function cwdFilters(value) {
|
|
1464
|
+
if (typeof value === "string") {
|
|
1465
|
+
return [value];
|
|
1466
|
+
}
|
|
1467
|
+
if (Array.isArray(value)) {
|
|
1468
|
+
return value;
|
|
1469
|
+
}
|
|
1470
|
+
return null;
|
|
1471
|
+
}
|
|
1472
|
+
function normalizeThreadName(value) {
|
|
1473
|
+
const name = value.trim().replace(/\s+/gu, " ");
|
|
1474
|
+
return name ? name : null;
|
|
1475
|
+
}
|
|
1476
|
+
function normalizeOptionalGitField(value, field) {
|
|
1477
|
+
if (value === void 0 || value === null) {
|
|
1478
|
+
return value;
|
|
1479
|
+
}
|
|
1480
|
+
const trimmed = value.trim();
|
|
1481
|
+
if (!trimmed) {
|
|
1482
|
+
jsonRpcError(`${field} must not be empty`, -32600, 400);
|
|
1483
|
+
}
|
|
1484
|
+
return trimmed;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
// src/upstream/codex-rs/app-server/src/request_processors/turn_processor.ts
|
|
1488
|
+
var TurnRequestProcessor = class {
|
|
1489
|
+
constructor(options) {
|
|
1490
|
+
this.options = options;
|
|
1491
|
+
}
|
|
1492
|
+
options;
|
|
1493
|
+
async turnStart(params, context) {
|
|
1494
|
+
const threadId = asThreadId(params.threadId);
|
|
1495
|
+
const input = params.input.map(appServerUserInputToCoreUserInput);
|
|
1496
|
+
const collaborationModeInput = params.collaborationMode ?? params.collaboration_mode;
|
|
1497
|
+
const collaborationMode = collaborationModeInput ? normalizeCollaborationMode({
|
|
1498
|
+
collaborationMode: collaborationModeInput,
|
|
1499
|
+
model: valueOrNull(params.model) ?? "gpt-5.5",
|
|
1500
|
+
reasoningEffort: valueOrNull(params.effort) ?? null
|
|
1501
|
+
}) : void 0;
|
|
1502
|
+
const submission = {
|
|
1503
|
+
id: params.clientMessageId ?? defaultId(),
|
|
1504
|
+
op: {
|
|
1505
|
+
type: "user_input_with_turn_context",
|
|
1506
|
+
items: input,
|
|
1507
|
+
cwd: valueOrNull(params.cwd) ?? void 0,
|
|
1508
|
+
approval_policy: approvalPolicyString(params.approvalPolicy) ?? void 0,
|
|
1509
|
+
approvals_reviewer: valueOrNull(params.approvalsReviewer) ?? void 0,
|
|
1510
|
+
sandbox_policy: valueOrNull(params.sandboxPolicy) ?? void 0,
|
|
1511
|
+
model: valueOrNull(params.model) ?? void 0,
|
|
1512
|
+
effort: valueOrNull(params.effort) ?? void 0,
|
|
1513
|
+
summary: valueOrNull(params.summary) ?? void 0,
|
|
1514
|
+
service_tier: valueOrNull(params.serviceTier) ?? void 0,
|
|
1515
|
+
collaboration_mode: collaborationMode,
|
|
1516
|
+
personality: valueOrNull(params.personality) ?? void 0,
|
|
1517
|
+
final_output_json_schema: valueOrNull(params.outputSchema) ?? void 0
|
|
1518
|
+
}
|
|
1519
|
+
};
|
|
1520
|
+
const runtimeSession = await this.sessionForTurn(threadId, params, submission, context);
|
|
1521
|
+
if (runtimeSession.session.activeTurn) {
|
|
1522
|
+
throw jsonRpcError("A Codex turn is already active for this thread.", -32011, 409);
|
|
1523
|
+
}
|
|
1524
|
+
const turn = await this.options.taskRunner.startRegularTask({
|
|
1525
|
+
context,
|
|
1526
|
+
items: input,
|
|
1527
|
+
params,
|
|
1528
|
+
runtimeSession,
|
|
1529
|
+
submission,
|
|
1530
|
+
threadId
|
|
1531
|
+
});
|
|
1532
|
+
return {
|
|
1533
|
+
turn: {
|
|
1534
|
+
id: turn.sub_id,
|
|
1535
|
+
items: [],
|
|
1536
|
+
itemsView: "notLoaded",
|
|
1537
|
+
status: "inProgress",
|
|
1538
|
+
error: null,
|
|
1539
|
+
startedAt: Math.floor(Date.now() / 1e3),
|
|
1540
|
+
completedAt: null,
|
|
1541
|
+
durationMs: null
|
|
1542
|
+
}
|
|
1543
|
+
};
|
|
1544
|
+
}
|
|
1545
|
+
async turnSteer(params, context) {
|
|
1546
|
+
const threadId = asThreadId(params.threadId);
|
|
1547
|
+
const runtimeSession = this.options.sessions.get(threadId);
|
|
1548
|
+
if (!runtimeSession) {
|
|
1549
|
+
throw jsonRpcError("No active Codex turn is available for steering.", -32012, 409);
|
|
1550
|
+
}
|
|
1551
|
+
try {
|
|
1552
|
+
const turnId = await runtimeSession.session.steer_input(
|
|
1553
|
+
params.input.map(appServerUserInputToCoreUserInput),
|
|
1554
|
+
params.expectedTurnId
|
|
1555
|
+
);
|
|
1556
|
+
return { turnId };
|
|
1557
|
+
} catch (error) {
|
|
1558
|
+
if (error instanceof SteerInputError) {
|
|
1559
|
+
throw jsonRpcError(error.message, steerErrorCode(error.kind), 409);
|
|
1560
|
+
}
|
|
1561
|
+
this.options.onRuntimeError?.(error, { context, threadId });
|
|
1562
|
+
throw error;
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
async turnInterrupt(params) {
|
|
1566
|
+
const threadId = asThreadId(params.threadId);
|
|
1567
|
+
const runtimeSession = this.options.sessions.get(threadId);
|
|
1568
|
+
if (!runtimeSession?.session.activeTurn) {
|
|
1569
|
+
return {};
|
|
1570
|
+
}
|
|
1571
|
+
const activeTask = runtimeSession.session.activeTurn.firstTask();
|
|
1572
|
+
if (activeTask && activeTask.sub_id !== params.turnId) {
|
|
1573
|
+
throw jsonRpcError(
|
|
1574
|
+
`Expected active turn ${params.turnId}, but current active turn is ${activeTask.sub_id}.`,
|
|
1575
|
+
-32013,
|
|
1576
|
+
409
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
runtimeSession.abortController?.abort();
|
|
1580
|
+
await runtimeSession.session.abortActiveTurn("interrupted");
|
|
1581
|
+
return {};
|
|
1582
|
+
}
|
|
1583
|
+
async sessionForTurn(threadId, params, submission, context) {
|
|
1584
|
+
const existing = this.options.sessions.get(threadId);
|
|
1585
|
+
if (existing) {
|
|
1586
|
+
return existing;
|
|
1587
|
+
}
|
|
1588
|
+
const session = await this.options.createSession(threadId, params, context, submission);
|
|
1589
|
+
const runtimeSession = {
|
|
1590
|
+
abortController: null,
|
|
1591
|
+
runPromise: null,
|
|
1592
|
+
session
|
|
1593
|
+
};
|
|
1594
|
+
this.options.sessions.set(threadId, runtimeSession);
|
|
1595
|
+
return runtimeSession;
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1598
|
+
|
|
1599
|
+
// src/upstream/codex-rs/app-server/src/dynamic_tools.ts
|
|
1600
|
+
function coreDynamicToolResponseFromAppServerResponse(value) {
|
|
1601
|
+
const response = decodeDynamicToolCallResponse(value);
|
|
1602
|
+
return {
|
|
1603
|
+
content_items: response.contentItems.map(coreDynamicToolCallOutputContentItem),
|
|
1604
|
+
success: response.success
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
function decodeDynamicToolCallResponse(value) {
|
|
1608
|
+
if (!isDynamicToolCallResponse(value)) {
|
|
1609
|
+
return fallbackDynamicToolCallResponse("dynamic tool response was invalid");
|
|
1610
|
+
}
|
|
1611
|
+
return value;
|
|
1612
|
+
}
|
|
1613
|
+
function fallbackDynamicToolCallResponse(message) {
|
|
1614
|
+
return {
|
|
1615
|
+
contentItems: [{ text: message, type: "inputText" }],
|
|
1616
|
+
success: false
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
function coreDynamicToolCallOutputContentItem(item) {
|
|
1620
|
+
switch (item.type) {
|
|
1621
|
+
case "inputText":
|
|
1622
|
+
return { text: item.text, type: "inputText" };
|
|
1623
|
+
case "inputImage":
|
|
1624
|
+
return { imageUrl: item.imageUrl, type: "inputImage" };
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
function isDynamicToolCallResponse(value) {
|
|
1628
|
+
if (typeof value !== "object" || value === null) {
|
|
1629
|
+
return false;
|
|
1630
|
+
}
|
|
1631
|
+
const candidate = value;
|
|
1632
|
+
return typeof candidate.success === "boolean" && Array.isArray(candidate.contentItems) && candidate.contentItems.every(isDynamicToolCallOutputContentItem);
|
|
1633
|
+
}
|
|
1634
|
+
function isDynamicToolCallOutputContentItem(value) {
|
|
1635
|
+
if (typeof value !== "object" || value === null) {
|
|
1636
|
+
return false;
|
|
1637
|
+
}
|
|
1638
|
+
const item = value;
|
|
1639
|
+
if (item.type === "inputText") {
|
|
1640
|
+
return typeof item.text === "string";
|
|
1641
|
+
}
|
|
1642
|
+
if (item.type === "inputImage") {
|
|
1643
|
+
return typeof item.imageUrl === "string";
|
|
1644
|
+
}
|
|
1645
|
+
return false;
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
// src/upstream/codex-rs/app-server/src/server_request_response.ts
|
|
1649
|
+
function submissionFromServerRequestResult(input) {
|
|
1650
|
+
const target = input.target ?? targetFromServerRequest(input.request);
|
|
1651
|
+
const request = input.request;
|
|
1652
|
+
if (isSubmissionOp(input.result)) {
|
|
1653
|
+
throw unsupportedServerRequestResponse(request);
|
|
1654
|
+
}
|
|
1655
|
+
if (target?.type === "request_permissions") {
|
|
1656
|
+
return {
|
|
1657
|
+
id: `server-request-response-${String(input.requestId)}`,
|
|
1658
|
+
op: {
|
|
1659
|
+
id: target.callId,
|
|
1660
|
+
response: corePermissionsResponse(
|
|
1661
|
+
input.result
|
|
1662
|
+
),
|
|
1663
|
+
type: "request_permissions_response"
|
|
1664
|
+
}
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
if (target?.type === "dynamic_tool") {
|
|
1668
|
+
return {
|
|
1669
|
+
id: `server-request-response-${String(input.requestId)}`,
|
|
1670
|
+
op: {
|
|
1671
|
+
id: target.callId,
|
|
1672
|
+
response: coreDynamicToolResponse(input.result),
|
|
1673
|
+
type: "dynamic_tool_response"
|
|
1674
|
+
}
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1677
|
+
if (target?.type === "mcp_elicitation") {
|
|
1678
|
+
return {
|
|
1679
|
+
id: `server-request-response-${String(input.requestId)}`,
|
|
1680
|
+
op: {
|
|
1681
|
+
id: target.requestId,
|
|
1682
|
+
response: coreMcpElicitationResponse(
|
|
1683
|
+
input.result
|
|
1684
|
+
),
|
|
1685
|
+
server_name: target.serverName,
|
|
1686
|
+
type: "mcp_server_elicitation_response"
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
if (target?.type === "user_input") {
|
|
1691
|
+
return {
|
|
1692
|
+
id: `server-request-response-${String(input.requestId)}`,
|
|
1693
|
+
op: {
|
|
1694
|
+
id: target.responseId,
|
|
1695
|
+
response: coreToolRequestUserInputResponse(
|
|
1696
|
+
input.result
|
|
1697
|
+
),
|
|
1698
|
+
type: "user_input_answer"
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
throw unsupportedServerRequestResponse(request);
|
|
1703
|
+
}
|
|
1704
|
+
function coreDynamicToolResponse(response) {
|
|
1705
|
+
return coreDynamicToolResponseFromAppServerResponse(response);
|
|
1706
|
+
}
|
|
1707
|
+
function corePermissionsResponse(response) {
|
|
1708
|
+
return {
|
|
1709
|
+
permissions: response.permissions,
|
|
1710
|
+
scope: response.scope,
|
|
1711
|
+
strict_auto_review: response.strictAutoReview
|
|
1712
|
+
};
|
|
1713
|
+
}
|
|
1714
|
+
function coreMcpElicitationResponse(response) {
|
|
1715
|
+
return {
|
|
1716
|
+
action: response.action,
|
|
1717
|
+
content: response.content ?? void 0,
|
|
1718
|
+
meta: response._meta ?? void 0
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
function submissionFromServerRequestError(input) {
|
|
1722
|
+
const target = input.target ?? targetFromServerRequest(input.request);
|
|
1723
|
+
const requestId = String(input.requestId);
|
|
1724
|
+
if (target?.type === "dynamic_tool") {
|
|
1725
|
+
return {
|
|
1726
|
+
id: `server-request-rejection-${requestId}`,
|
|
1727
|
+
op: {
|
|
1728
|
+
id: target.callId,
|
|
1729
|
+
response: {
|
|
1730
|
+
content_items: [
|
|
1731
|
+
{
|
|
1732
|
+
text: input.error.message,
|
|
1733
|
+
type: "inputText"
|
|
1734
|
+
}
|
|
1735
|
+
],
|
|
1736
|
+
success: false
|
|
1737
|
+
},
|
|
1738
|
+
type: "dynamic_tool_response"
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
if (target?.type === "request_permissions") {
|
|
1743
|
+
return {
|
|
1744
|
+
id: `server-request-rejection-${requestId}`,
|
|
1745
|
+
op: {
|
|
1746
|
+
id: target.callId,
|
|
1747
|
+
response: {
|
|
1748
|
+
permissions: {}
|
|
1749
|
+
},
|
|
1750
|
+
type: "request_permissions_response"
|
|
1751
|
+
}
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1754
|
+
if (target?.type === "user_input") {
|
|
1755
|
+
return {
|
|
1756
|
+
id: `server-request-rejection-${requestId}`,
|
|
1757
|
+
op: {
|
|
1758
|
+
id: target.responseId,
|
|
1759
|
+
response: { answers: {} },
|
|
1760
|
+
type: "user_input_answer"
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
if (target?.type === "mcp_elicitation") {
|
|
1765
|
+
return {
|
|
1766
|
+
id: `server-request-rejection-${requestId}`,
|
|
1767
|
+
op: {
|
|
1768
|
+
id: target.requestId,
|
|
1769
|
+
response: {
|
|
1770
|
+
action: "cancel",
|
|
1771
|
+
content: void 0,
|
|
1772
|
+
meta: void 0
|
|
1773
|
+
},
|
|
1774
|
+
server_name: target.serverName,
|
|
1775
|
+
type: "mcp_server_elicitation_response"
|
|
1776
|
+
}
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1779
|
+
throw unsupportedServerRequestResponse(input.request);
|
|
1780
|
+
}
|
|
1781
|
+
function coreToolRequestUserInputResponse(response) {
|
|
1782
|
+
const answers = {};
|
|
1783
|
+
for (const [key, value] of Object.entries(response.answers)) {
|
|
1784
|
+
if (value) {
|
|
1785
|
+
answers[key] = value;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
return { answers };
|
|
1789
|
+
}
|
|
1790
|
+
function isServerRequestResponseSubmission(submission) {
|
|
1791
|
+
return submission.op.type === "dynamic_tool_response" || submission.op.type === "mcp_server_elicitation_response" || submission.op.type === "request_permissions_response" || submission.op.type === "user_input_answer";
|
|
1792
|
+
}
|
|
1793
|
+
function isSubmissionOp(value) {
|
|
1794
|
+
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string" && isServerRequestResponseSubmission({ op: value });
|
|
1795
|
+
}
|
|
1796
|
+
function targetFromServerRequest(request) {
|
|
1797
|
+
if (!request) {
|
|
1798
|
+
return null;
|
|
1799
|
+
}
|
|
1800
|
+
switch (request.method) {
|
|
1801
|
+
case "item/tool/requestUserInput":
|
|
1802
|
+
return {
|
|
1803
|
+
type: "user_input",
|
|
1804
|
+
responseId: request.params.turnId
|
|
1805
|
+
};
|
|
1806
|
+
case "item/permissions/requestApproval":
|
|
1807
|
+
return {
|
|
1808
|
+
type: "request_permissions",
|
|
1809
|
+
callId: request.params.itemId
|
|
1810
|
+
};
|
|
1811
|
+
case "item/tool/call":
|
|
1812
|
+
return { type: "dynamic_tool", callId: request.params.callId };
|
|
1813
|
+
case "mcpServer/elicitation/request":
|
|
1814
|
+
return "elicitationId" in request.params ? {
|
|
1815
|
+
type: "mcp_elicitation",
|
|
1816
|
+
serverName: request.params.serverName,
|
|
1817
|
+
requestId: request.params.elicitationId
|
|
1818
|
+
} : null;
|
|
1819
|
+
default:
|
|
1820
|
+
return null;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
function unsupportedServerRequestResponse(request) {
|
|
1824
|
+
throw new Error(
|
|
1825
|
+
`Unsupported Codex server-request response: ${request?.method ?? "unknown"}`
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
// src/upstream/codex-rs/app-server/src/session_factory.ts
|
|
1830
|
+
var CodexSessionFactory = class {
|
|
1831
|
+
constructor(options) {
|
|
1832
|
+
this.options = options;
|
|
1833
|
+
}
|
|
1834
|
+
options;
|
|
1835
|
+
createSession = async (input) => {
|
|
1836
|
+
const eventSink = (event) => this.options.emitCoreEvent(input.threadId, event, input.context);
|
|
1837
|
+
if (this.options.createSession) {
|
|
1838
|
+
return this.options.createSession({ ...input, eventSink });
|
|
1839
|
+
}
|
|
1840
|
+
const thread = await this.options.store.readThread({
|
|
1841
|
+
thread_id: input.threadId,
|
|
1842
|
+
include_archived: false,
|
|
1843
|
+
include_history: false
|
|
1844
|
+
});
|
|
1845
|
+
const history = await this.options.store.loadHistory({
|
|
1846
|
+
thread_id: input.threadId,
|
|
1847
|
+
include_archived: false
|
|
1848
|
+
});
|
|
1849
|
+
const overrides = await this.options.buildSessionConfiguration?.({
|
|
1850
|
+
context: input.context,
|
|
1851
|
+
params: input.params,
|
|
1852
|
+
thread
|
|
1853
|
+
});
|
|
1854
|
+
const configuration = defaultSessionConfiguration({
|
|
1855
|
+
approval_policy: "approvalPolicy" in input.params ? approvalPolicyString(input.params.approvalPolicy) ?? "never" : "never",
|
|
1856
|
+
approvals_reviewer: "approvalsReviewer" in input.params ? valueOrNull(input.params.approvalsReviewer) ?? "user" : "user",
|
|
1857
|
+
base_instructions: { text: "" },
|
|
1858
|
+
cwd: "cwd" in input.params ? valueOrNull(input.params.cwd) ?? thread.cwd : thread.cwd,
|
|
1859
|
+
developer_instructions: "developerInstructions" in input.params ? input.params.developerInstructions ?? null : null,
|
|
1860
|
+
model: "model" in input.params ? valueOrNull(input.params.model) ?? thread.model ?? "gpt-5.5" : thread.model ?? "gpt-5.5",
|
|
1861
|
+
provider: "modelProvider" in input.params ? valueOrNull(input.params.modelProvider) ?? thread.model_provider : thread.model_provider,
|
|
1862
|
+
reasoning_effort: "effort" in input.params ? input.params.effort ?? null : null,
|
|
1863
|
+
service_tier: "serviceTier" in input.params ? valueOrNull(input.params.serviceTier) ?? null : null,
|
|
1864
|
+
session_source: "appServer",
|
|
1865
|
+
...overrides ?? {}
|
|
1866
|
+
});
|
|
1867
|
+
if (!configuration.base_instructions.text) {
|
|
1868
|
+
configuration.base_instructions = {
|
|
1869
|
+
text: "baseInstructions" in input.params && input.params.baseInstructions ? input.params.baseInstructions : BaseInstructions.default().text
|
|
1870
|
+
};
|
|
1871
|
+
}
|
|
1872
|
+
return new Session({
|
|
1873
|
+
threadId: input.threadId,
|
|
1874
|
+
configuration,
|
|
1875
|
+
liveThread: await LiveThread.resume(this.options.store, {
|
|
1876
|
+
thread_id: input.threadId,
|
|
1877
|
+
include_archived: false,
|
|
1878
|
+
metadata: {
|
|
1879
|
+
cwd: thread.cwd,
|
|
1880
|
+
memory_mode: ThreadMemoryMode.Disabled,
|
|
1881
|
+
model_provider: thread.model_provider
|
|
1882
|
+
},
|
|
1883
|
+
event_persistence_mode: ThreadEventPersistenceMode.Limited
|
|
1884
|
+
}),
|
|
1885
|
+
initialHistory: history.items,
|
|
1886
|
+
rolloutPath: thread.rollout_path ?? null,
|
|
1887
|
+
forkedFromId: thread.forked_from_id ?? null,
|
|
1888
|
+
threadName: thread.name ?? null,
|
|
1889
|
+
threadSource: thread.thread_source ?? null,
|
|
1890
|
+
eventSink,
|
|
1891
|
+
mcpConnectionManager: this.options.mcpConnectionManager
|
|
1892
|
+
});
|
|
1893
|
+
};
|
|
1894
|
+
};
|
|
1895
|
+
|
|
1896
|
+
// src/upstream/codex-rs/app-server/src/session_task_runner.ts
|
|
1897
|
+
var CodexSessionTaskRunner = class {
|
|
1898
|
+
constructor(options) {
|
|
1899
|
+
this.options = options;
|
|
1900
|
+
}
|
|
1901
|
+
options;
|
|
1902
|
+
modelClients = /* @__PURE__ */ new Map();
|
|
1903
|
+
async startRegularTask(input) {
|
|
1904
|
+
const turn = await input.runtimeSession.session.startTurn(input.submission);
|
|
1905
|
+
const history = await this.options.store.loadHistory({
|
|
1906
|
+
thread_id: input.threadId,
|
|
1907
|
+
include_archived: false
|
|
1908
|
+
});
|
|
1909
|
+
const abortController = new AbortController();
|
|
1910
|
+
const modelClient = await this.modelClient({
|
|
1911
|
+
context: input.context,
|
|
1912
|
+
session: input.runtimeSession.session,
|
|
1913
|
+
threadId: input.threadId
|
|
1914
|
+
});
|
|
1915
|
+
const task = RegularTask.new({
|
|
1916
|
+
history: history.items,
|
|
1917
|
+
submission: input.submission,
|
|
1918
|
+
run_turn: async (taskInput) => {
|
|
1919
|
+
const result = await runTurn({
|
|
1920
|
+
history: taskInput.history,
|
|
1921
|
+
modelClient,
|
|
1922
|
+
session: taskInput.session,
|
|
1923
|
+
signal: taskInput.signal,
|
|
1924
|
+
submission: taskInput.submission,
|
|
1925
|
+
turn: taskInput.turn
|
|
1926
|
+
});
|
|
1927
|
+
return {
|
|
1928
|
+
last_agent_message: result.lastAgentMessage,
|
|
1929
|
+
steps: result.steps
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
});
|
|
1933
|
+
this.spawnTask({
|
|
1934
|
+
abortController,
|
|
1935
|
+
context: input.context,
|
|
1936
|
+
input: input.items,
|
|
1937
|
+
runtimeSession: input.runtimeSession,
|
|
1938
|
+
task,
|
|
1939
|
+
threadId: input.threadId,
|
|
1940
|
+
turn
|
|
1941
|
+
});
|
|
1942
|
+
return turn;
|
|
1943
|
+
}
|
|
1944
|
+
async startCompactTask(input) {
|
|
1945
|
+
const history = await this.options.store.loadHistory({
|
|
1946
|
+
thread_id: input.threadId,
|
|
1947
|
+
include_archived: false
|
|
1948
|
+
});
|
|
1949
|
+
const abortController = new AbortController();
|
|
1950
|
+
const turn = await input.runtimeSession.session.startCompactTurn(input.submission);
|
|
1951
|
+
const modelClient = await this.modelClient({
|
|
1952
|
+
context: input.context,
|
|
1953
|
+
session: input.runtimeSession.session,
|
|
1954
|
+
threadId: input.threadId
|
|
1955
|
+
});
|
|
1956
|
+
const task = new CompactTask({
|
|
1957
|
+
history: history.items,
|
|
1958
|
+
submission: input.submission,
|
|
1959
|
+
run_compact_task: async (taskInput) => {
|
|
1960
|
+
const result = await run_compact_task({
|
|
1961
|
+
modelClient,
|
|
1962
|
+
session: taskInput.session,
|
|
1963
|
+
history: taskInput.history,
|
|
1964
|
+
submission: taskInput.submission,
|
|
1965
|
+
turn: taskInput.turn,
|
|
1966
|
+
signal: taskInput.signal,
|
|
1967
|
+
completeTurn: false
|
|
1968
|
+
});
|
|
1969
|
+
return {
|
|
1970
|
+
last_agent_message: null,
|
|
1971
|
+
steps: 1,
|
|
1972
|
+
message: result.summary
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
});
|
|
1976
|
+
this.spawnTask({
|
|
1977
|
+
abortController,
|
|
1978
|
+
context: input.context,
|
|
1979
|
+
input: [],
|
|
1980
|
+
runtimeSession: input.runtimeSession,
|
|
1981
|
+
task,
|
|
1982
|
+
threadId: input.threadId,
|
|
1983
|
+
turn
|
|
1984
|
+
});
|
|
1985
|
+
return turn;
|
|
1986
|
+
}
|
|
1987
|
+
spawnTask(input) {
|
|
1988
|
+
input.runtimeSession.abortController = input.abortController;
|
|
1989
|
+
input.runtimeSession.runPromise = input.runtimeSession.session.spawn_task({
|
|
1990
|
+
abortController: input.abortController,
|
|
1991
|
+
input: input.input,
|
|
1992
|
+
task: input.task,
|
|
1993
|
+
turnContext: input.turn
|
|
1994
|
+
}).catch((error) => {
|
|
1995
|
+
this.options.onRuntimeError?.(error, {
|
|
1996
|
+
context: input.context,
|
|
1997
|
+
threadId: input.threadId
|
|
1998
|
+
});
|
|
1999
|
+
}).finally(() => {
|
|
2000
|
+
input.runtimeSession.abortController = null;
|
|
2001
|
+
input.runtimeSession.runPromise = null;
|
|
2002
|
+
});
|
|
2003
|
+
this.options.runInBackground?.(input.runtimeSession.runPromise, {
|
|
2004
|
+
context: input.context,
|
|
2005
|
+
threadId: input.threadId
|
|
2006
|
+
});
|
|
2007
|
+
}
|
|
2008
|
+
async modelClient(input) {
|
|
2009
|
+
const cacheKey = this.options.modelClientCacheKey?.(input) ?? String(input.threadId);
|
|
2010
|
+
const existing = this.modelClients.get(cacheKey);
|
|
2011
|
+
if (existing) {
|
|
2012
|
+
return existing;
|
|
2013
|
+
}
|
|
2014
|
+
const created = await this.options.createModelClient(input);
|
|
2015
|
+
this.modelClients.set(cacheKey, created);
|
|
2016
|
+
return created;
|
|
2017
|
+
}
|
|
2018
|
+
};
|
|
2019
|
+
|
|
2020
|
+
// src/upstream/codex-rs/app-server/src/thread_state.ts
|
|
2021
|
+
var ThreadState = class {
|
|
2022
|
+
pendingInterrupts = [];
|
|
2023
|
+
turnSummary = { lastError: null, startedAt: null };
|
|
2024
|
+
lastTerminalTurnId = null;
|
|
2025
|
+
experimentalRawEvents = false;
|
|
2026
|
+
listenerGeneration = 0;
|
|
2027
|
+
currentTurnHistory = new ThreadHistoryBuilder();
|
|
2028
|
+
listenerActive = false;
|
|
2029
|
+
setListener() {
|
|
2030
|
+
this.listenerGeneration = this.listenerGeneration + 1 >>> 0;
|
|
2031
|
+
this.listenerActive = true;
|
|
2032
|
+
return this.listenerGeneration;
|
|
2033
|
+
}
|
|
2034
|
+
clearListener() {
|
|
2035
|
+
this.listenerActive = false;
|
|
2036
|
+
this.currentTurnHistory.reset();
|
|
2037
|
+
}
|
|
2038
|
+
hasListener() {
|
|
2039
|
+
return this.listenerActive;
|
|
2040
|
+
}
|
|
2041
|
+
setExperimentalRawEvents(enabled) {
|
|
2042
|
+
this.experimentalRawEvents = enabled;
|
|
2043
|
+
}
|
|
2044
|
+
activeTurnSnapshot() {
|
|
2045
|
+
const turn = this.currentTurnHistory.active_turn_snapshot();
|
|
2046
|
+
return turn ? appServerTurnFromCoreTurn(turn) : null;
|
|
2047
|
+
}
|
|
2048
|
+
trackCurrentTurnEvent(eventTurnId, event) {
|
|
2049
|
+
if (event.type === "turn_started") {
|
|
2050
|
+
this.turnSummary.startedAt = event.started_at ?? null;
|
|
2051
|
+
}
|
|
2052
|
+
if (event.type === "error") {
|
|
2053
|
+
this.turnSummary.lastError = { message: event.message };
|
|
2054
|
+
}
|
|
2055
|
+
this.currentTurnHistory.handle_event(event, eventTurnId);
|
|
2056
|
+
if (event.type === "turn_complete" || event.type === "turn_aborted") {
|
|
2057
|
+
this.lastTerminalTurnId = eventTurnId;
|
|
2058
|
+
const terminalTurn = this.currentTurnHistory.finish().find((turn) => turn.id === eventTurnId) ?? null;
|
|
2059
|
+
this.currentTurnHistory.reset();
|
|
2060
|
+
return {
|
|
2061
|
+
activeTurn: null,
|
|
2062
|
+
terminalTurn: terminalTurn ? appServerTurnFromCoreTurn(terminalTurn) : null
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
2065
|
+
return {
|
|
2066
|
+
activeTurn: this.activeTurnSnapshot(),
|
|
2067
|
+
terminalTurn: null
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
2070
|
+
};
|
|
2071
|
+
var ThreadStateManager = class {
|
|
2072
|
+
liveConnections = /* @__PURE__ */ new Set();
|
|
2073
|
+
threads = /* @__PURE__ */ new Map();
|
|
2074
|
+
threadIdsByConnection = /* @__PURE__ */ new Map();
|
|
2075
|
+
connectionInitialized(connectionId) {
|
|
2076
|
+
this.liveConnections.add(connectionId);
|
|
2077
|
+
}
|
|
2078
|
+
threadState(threadId) {
|
|
2079
|
+
const entry = this.threadEntry(threadId);
|
|
2080
|
+
return entry.state;
|
|
2081
|
+
}
|
|
2082
|
+
removeThreadState(threadId) {
|
|
2083
|
+
const entry = this.threads.get(threadId);
|
|
2084
|
+
entry?.state.clearListener();
|
|
2085
|
+
this.threads.delete(threadId);
|
|
2086
|
+
for (const [connectionId, threadIds] of this.threadIdsByConnection) {
|
|
2087
|
+
threadIds.delete(threadId);
|
|
2088
|
+
if (threadIds.size === 0) {
|
|
2089
|
+
this.threadIdsByConnection.delete(connectionId);
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
clearAllListeners() {
|
|
2094
|
+
for (const entry of this.threads.values()) {
|
|
2095
|
+
entry.state.clearListener();
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
subscribedConnectionIds(threadId) {
|
|
2099
|
+
return Array.from(this.threads.get(threadId)?.connectionIds ?? []);
|
|
2100
|
+
}
|
|
2101
|
+
tryEnsureConnectionSubscribed(threadId, connectionId, experimentalRawEvents = false) {
|
|
2102
|
+
if (!this.liveConnections.has(connectionId)) {
|
|
2103
|
+
return null;
|
|
2104
|
+
}
|
|
2105
|
+
const threadIds = this.threadIdsByConnection.get(connectionId);
|
|
2106
|
+
if (threadIds) {
|
|
2107
|
+
threadIds.add(threadId);
|
|
2108
|
+
} else {
|
|
2109
|
+
this.threadIdsByConnection.set(connectionId, /* @__PURE__ */ new Set([threadId]));
|
|
2110
|
+
}
|
|
2111
|
+
const entry = this.threadEntry(threadId);
|
|
2112
|
+
entry.connectionIds.add(connectionId);
|
|
2113
|
+
if (experimentalRawEvents) {
|
|
2114
|
+
entry.state.setExperimentalRawEvents(true);
|
|
2115
|
+
}
|
|
2116
|
+
return entry.state;
|
|
2117
|
+
}
|
|
2118
|
+
unsubscribeConnectionFromThread(threadId, connectionId) {
|
|
2119
|
+
const entry = this.threads.get(threadId);
|
|
2120
|
+
const threadIds = this.threadIdsByConnection.get(connectionId);
|
|
2121
|
+
if (!entry || !threadIds?.has(threadId)) {
|
|
2122
|
+
return false;
|
|
2123
|
+
}
|
|
2124
|
+
entry.connectionIds.delete(connectionId);
|
|
2125
|
+
threadIds.delete(threadId);
|
|
2126
|
+
if (threadIds.size === 0) {
|
|
2127
|
+
this.threadIdsByConnection.delete(connectionId);
|
|
2128
|
+
}
|
|
2129
|
+
return true;
|
|
2130
|
+
}
|
|
2131
|
+
removeConnection(connectionId) {
|
|
2132
|
+
this.liveConnections.delete(connectionId);
|
|
2133
|
+
const threadIds = Array.from(this.threadIdsByConnection.get(connectionId) ?? []);
|
|
2134
|
+
this.threadIdsByConnection.delete(connectionId);
|
|
2135
|
+
const emptyThreadIds = [];
|
|
2136
|
+
for (const threadId of threadIds) {
|
|
2137
|
+
const entry = this.threads.get(threadId);
|
|
2138
|
+
entry?.connectionIds.delete(connectionId);
|
|
2139
|
+
if (entry && entry.connectionIds.size === 0) {
|
|
2140
|
+
emptyThreadIds.push(threadId);
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
return emptyThreadIds;
|
|
2144
|
+
}
|
|
2145
|
+
threadEntry(threadId) {
|
|
2146
|
+
const existing = this.threads.get(threadId);
|
|
2147
|
+
if (existing) {
|
|
2148
|
+
return existing;
|
|
2149
|
+
}
|
|
2150
|
+
const entry = {
|
|
2151
|
+
connectionIds: /* @__PURE__ */ new Set(),
|
|
2152
|
+
state: new ThreadState()
|
|
2153
|
+
};
|
|
2154
|
+
this.threads.set(threadId, entry);
|
|
2155
|
+
return entry;
|
|
2156
|
+
}
|
|
2157
|
+
};
|
|
2158
|
+
|
|
2159
|
+
// src/upstream/codex-rs/app-server/src/bespoke_event_handling.ts
|
|
2160
|
+
function apply_bespoke_event_handling(msg, context) {
|
|
2161
|
+
return eventMsgToAppServerEvents(msg, context);
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
// src/upstream/codex-rs/app-server/src/runtime.ts
|
|
2165
|
+
function createCodexAppServerRuntime(options) {
|
|
2166
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
2167
|
+
const serverRequestTargets = /* @__PURE__ */ new Map();
|
|
2168
|
+
const threadStateManager = new ThreadStateManager();
|
|
2169
|
+
const requestSerializationQueues = new RequestSerializationQueues();
|
|
2170
|
+
const sendOutgoingMessage = options.sendOutgoingMessage ?? options.eventSink;
|
|
2171
|
+
const outgoing = new OutgoingMessageSender({
|
|
2172
|
+
send: async (message, messageContext) => {
|
|
2173
|
+
if (options.sendOutgoingTransportMessage) {
|
|
2174
|
+
await options.sendOutgoingTransportMessage(message, {
|
|
2175
|
+
connectionIds: messageContext.connectionIds,
|
|
2176
|
+
context: messageContext.context,
|
|
2177
|
+
threadId: messageContext.threadId
|
|
2178
|
+
});
|
|
2179
|
+
return;
|
|
2180
|
+
}
|
|
2181
|
+
const event = outgoingMessageToAppServerEvent(message);
|
|
2182
|
+
if (event && sendOutgoingMessage) {
|
|
2183
|
+
await sendOutgoingMessage(event, {
|
|
2184
|
+
context: messageContext.context,
|
|
2185
|
+
threadId: messageContext.threadId ?? threadIdFromAppServerEvent(event)
|
|
2186
|
+
});
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
});
|
|
2190
|
+
async function emit(threadId, event, context) {
|
|
2191
|
+
if (event.type === "server_notification") {
|
|
2192
|
+
await outgoing.sendServerNotification(event.notification, context, threadId);
|
|
2193
|
+
return;
|
|
2194
|
+
}
|
|
2195
|
+
if (event.type === "server_request") {
|
|
2196
|
+
const handle = outgoing.sendRequestWithHandle(
|
|
2197
|
+
event.request,
|
|
2198
|
+
threadId,
|
|
2199
|
+
context
|
|
2200
|
+
);
|
|
2201
|
+
const coreTarget = "coreTarget" in event ? event.coreTarget : void 0;
|
|
2202
|
+
if (coreTarget) {
|
|
2203
|
+
serverRequestTargets.set(
|
|
2204
|
+
serverRequestTargetKey(threadId, handle.request.id),
|
|
2205
|
+
coreTarget
|
|
2206
|
+
);
|
|
2207
|
+
}
|
|
2208
|
+
void handle.result.catch((error) => {
|
|
2209
|
+
options.onRuntimeError?.(error, { context, threadId });
|
|
2210
|
+
});
|
|
2211
|
+
return;
|
|
2212
|
+
}
|
|
2213
|
+
await sendOutgoingMessage?.(event, { context, threadId });
|
|
2214
|
+
}
|
|
2215
|
+
function emitCoreEvent(threadId, event, context) {
|
|
2216
|
+
if (event.msg.type === "session_configured") {
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2219
|
+
const threadState = threadStateManager.threadState(threadId);
|
|
2220
|
+
const tracked = threadState.trackCurrentTurnEvent(event.id, event.msg);
|
|
2221
|
+
const protocolEvents = apply_bespoke_event_handling(event.msg, {
|
|
2222
|
+
activeTurn: tracked.activeTurn,
|
|
2223
|
+
terminalTurn: tracked.terminalTurn,
|
|
2224
|
+
threadId,
|
|
2225
|
+
turnId: "turn_id" in event.msg && typeof event.msg.turn_id === "string" ? event.msg.turn_id : event.id
|
|
2226
|
+
});
|
|
2227
|
+
for (const protocolEvent of protocolEvents) {
|
|
2228
|
+
void emit(threadId, protocolEvent, context);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
const sessionFactory = new CodexSessionFactory({
|
|
2232
|
+
buildSessionConfiguration: options.buildSessionConfiguration,
|
|
2233
|
+
createSession: options.createSession,
|
|
2234
|
+
emitCoreEvent,
|
|
2235
|
+
mcpConnectionManager: options.mcpConnectionManager,
|
|
2236
|
+
store: options.store
|
|
2237
|
+
});
|
|
2238
|
+
const createSession = (threadId, params, context, submission) => sessionFactory.createSession({ context, params, submission, threadId });
|
|
2239
|
+
const taskRunner = new CodexSessionTaskRunner({
|
|
2240
|
+
createModelClient: options.createModelClient,
|
|
2241
|
+
modelClientCacheKey: options.modelClientCacheKey,
|
|
2242
|
+
onRuntimeError: options.onRuntimeError,
|
|
2243
|
+
runInBackground: options.runInBackground,
|
|
2244
|
+
store: options.store
|
|
2245
|
+
});
|
|
2246
|
+
const threadProcessor = new ThreadRequestProcessor({
|
|
2247
|
+
buildCreateThreadParams: options.buildCreateThreadParams,
|
|
2248
|
+
createSession,
|
|
2249
|
+
emit,
|
|
2250
|
+
resolveDynamicTools: options.resolveDynamicTools,
|
|
2251
|
+
sessions,
|
|
2252
|
+
store: options.store,
|
|
2253
|
+
taskRunner
|
|
2254
|
+
});
|
|
2255
|
+
const turnProcessor = new TurnRequestProcessor({
|
|
2256
|
+
createSession,
|
|
2257
|
+
onRuntimeError: options.onRuntimeError,
|
|
2258
|
+
sessions,
|
|
2259
|
+
taskRunner
|
|
2260
|
+
});
|
|
2261
|
+
const mcpProcessor = new McpRequestProcessor({
|
|
2262
|
+
mcpConnectionManager: options.mcpConnectionManager,
|
|
2263
|
+
mcpServerOauthLogin: options.mcpServerOauthLogin,
|
|
2264
|
+
reloadMcpServers: options.reloadMcpServers,
|
|
2265
|
+
runInBackground: options.runConnectionBackground,
|
|
2266
|
+
store: options.store
|
|
2267
|
+
});
|
|
2268
|
+
const methodHandlers = {
|
|
2269
|
+
configMcpServerReload: (params, context) => mcpProcessor.mcpServerRefresh(params, context),
|
|
2270
|
+
mcpResourceRead: (params, context, request) => mcpProcessor.mcpResourceRead(params, context, request),
|
|
2271
|
+
mcpServerOauthLogin: (params, context) => mcpProcessor.mcpServerOauthLogin(params, context),
|
|
2272
|
+
mcpServerStatusList: (params, context, request) => mcpProcessor.mcpServerStatusList(params, context, request),
|
|
2273
|
+
mcpServerToolCall: (params, context, request) => mcpProcessor.mcpServerToolCall(params, context, request),
|
|
2274
|
+
threadStart: (params, context) => threadProcessor.threadStart(params, context),
|
|
2275
|
+
threadResume: (params, context) => threadProcessor.threadResume(params, context),
|
|
2276
|
+
threadList: (params) => threadProcessor.threadList(params),
|
|
2277
|
+
threadRead: (params) => threadProcessor.threadRead(params),
|
|
2278
|
+
threadNameSet: (params, context) => threadProcessor.threadNameSet(params, context),
|
|
2279
|
+
threadArchive: (params, context) => threadProcessor.threadArchive(params, context),
|
|
2280
|
+
threadUnarchive: (params, context) => threadProcessor.threadUnarchive(params, context),
|
|
2281
|
+
threadMetadataUpdate: (params) => threadProcessor.threadMetadataUpdate(params),
|
|
2282
|
+
threadCompactStart: (params, context) => threadProcessor.threadCompactStart(params, context),
|
|
2283
|
+
turnStart: (params, context) => turnProcessor.turnStart(params, context),
|
|
2284
|
+
turnSteer: (params, context) => turnProcessor.turnSteer(params, context),
|
|
2285
|
+
turnInterrupt: (params) => turnProcessor.turnInterrupt(params)
|
|
2286
|
+
};
|
|
2287
|
+
function createMessageProcessor(input) {
|
|
2288
|
+
return new CodexAppServerMessageProcessor({
|
|
2289
|
+
connectionId: input.connectionId,
|
|
2290
|
+
handlers: input.initialize ? { ...methodHandlers, initialize: input.initialize } : methodHandlers,
|
|
2291
|
+
initializeResponse: input.initializeResponse,
|
|
2292
|
+
outgoing,
|
|
2293
|
+
requestSerializationQueues,
|
|
2294
|
+
session: input.session
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
async function resolveServerRequest(params) {
|
|
2298
|
+
const threadId = asThreadId(String(params.threadId));
|
|
2299
|
+
const targetKey = serverRequestTargetKey(threadId, params.requestId);
|
|
2300
|
+
const request = outgoing.pendingRequestsForThread(threadId).find(
|
|
2301
|
+
(candidate) => candidate.id === params.requestId
|
|
2302
|
+
) ?? null;
|
|
2303
|
+
if (!request) {
|
|
2304
|
+
serverRequestTargets.delete(targetKey);
|
|
2305
|
+
}
|
|
2306
|
+
const target = request ? serverRequestResponseTarget(serverRequestTargets.get(targetKey) ?? null) : null;
|
|
2307
|
+
const submission = submissionFromServerRequestResult({
|
|
2308
|
+
request,
|
|
2309
|
+
requestId: params.requestId,
|
|
2310
|
+
result: params.result,
|
|
2311
|
+
target
|
|
2312
|
+
});
|
|
2313
|
+
await submitServerRequestResponse(threadId, submission);
|
|
2314
|
+
serverRequestTargets.delete(targetKey);
|
|
2315
|
+
await outgoing.notifyClientResponse(params.requestId, params.result);
|
|
2316
|
+
await emit(threadId, serverRequestResolvedNotification({
|
|
2317
|
+
requestId: params.requestId,
|
|
2318
|
+
threadId
|
|
2319
|
+
}));
|
|
2320
|
+
}
|
|
2321
|
+
async function connectionClosed(connectionId) {
|
|
2322
|
+
const emptyThreadIds = threadStateManager.removeConnection(connectionId);
|
|
2323
|
+
outgoing.connectionClosed(connectionId);
|
|
2324
|
+
for (const threadId of emptyThreadIds) {
|
|
2325
|
+
threadStateManager.removeThreadState(threadId);
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
function connectionInitialized(connectionId) {
|
|
2329
|
+
threadStateManager.connectionInitialized(connectionId);
|
|
2330
|
+
}
|
|
2331
|
+
async function rejectServerRequest(params) {
|
|
2332
|
+
const threadId = asThreadId(String(params.threadId));
|
|
2333
|
+
const targetKey = serverRequestTargetKey(threadId, params.requestId);
|
|
2334
|
+
const request = outgoing.pendingRequestsForThread(threadId).find(
|
|
2335
|
+
(candidate) => candidate.id === params.requestId
|
|
2336
|
+
) ?? null;
|
|
2337
|
+
if (!request) {
|
|
2338
|
+
serverRequestTargets.delete(targetKey);
|
|
2339
|
+
}
|
|
2340
|
+
const target = request ? serverRequestResponseTarget(serverRequestTargets.get(targetKey) ?? null) : null;
|
|
2341
|
+
const submission = submissionFromServerRequestError({
|
|
2342
|
+
error: params.error,
|
|
2343
|
+
request,
|
|
2344
|
+
requestId: params.requestId,
|
|
2345
|
+
target
|
|
2346
|
+
});
|
|
2347
|
+
await submitServerRequestResponse(threadId, submission);
|
|
2348
|
+
serverRequestTargets.delete(targetKey);
|
|
2349
|
+
await outgoing.notifyClientError(params.requestId, params.error);
|
|
2350
|
+
await emit(threadId, serverRequestResolvedNotification({
|
|
2351
|
+
requestId: params.requestId,
|
|
2352
|
+
threadId
|
|
2353
|
+
}));
|
|
2354
|
+
}
|
|
2355
|
+
async function submitServerRequestResponse(threadId, submission) {
|
|
2356
|
+
if (!isServerRequestResponseSubmission(submission)) {
|
|
2357
|
+
throw new Error("Only server-request response submissions can be routed through CodexAppServerRuntime.");
|
|
2358
|
+
}
|
|
2359
|
+
const runtimeSession = sessions.get(threadId);
|
|
2360
|
+
if (!runtimeSession) {
|
|
2361
|
+
throw new Error("Codex thread has no active turn for this server request response.");
|
|
2362
|
+
}
|
|
2363
|
+
await runtimeSession.session.submit_with_id(submission);
|
|
2364
|
+
}
|
|
2365
|
+
return {
|
|
2366
|
+
connectionClosed,
|
|
2367
|
+
connectionInitialized,
|
|
2368
|
+
createMessageProcessor,
|
|
2369
|
+
methodHandlers,
|
|
2370
|
+
rejectServerRequest,
|
|
2371
|
+
resolveServerRequest
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
function serverRequestTargetKey(threadId, requestId) {
|
|
2375
|
+
return `${threadId}:${String(requestId)}`;
|
|
2376
|
+
}
|
|
2377
|
+
function serverRequestResponseTarget(target) {
|
|
2378
|
+
if (!target) {
|
|
2379
|
+
return null;
|
|
2380
|
+
}
|
|
2381
|
+
return target;
|
|
2382
|
+
}
|
|
2383
|
+
function threadIdFromAppServerEvent(event) {
|
|
2384
|
+
if (event.type === "server_notification") {
|
|
2385
|
+
const threadId = event.notification.params.threadId;
|
|
2386
|
+
if (typeof threadId === "string") {
|
|
2387
|
+
return asThreadId(threadId);
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
if (event.type === "server_request") {
|
|
2391
|
+
const threadId = event.request.params.threadId;
|
|
2392
|
+
if (typeof threadId === "string") {
|
|
2393
|
+
return asThreadId(threadId);
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
return asThreadId("00000000-0000-4000-8000-000000000000");
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
export { CodexAppServerConnectionSessionState, CodexAppServerMessageProcessor, CodexAppServerRequestError, CodexSessionFactory, CodexSessionTaskRunner, ConnectionRpcGate, ConnectionRpcGateClosedError, McpRequestProcessor, OutgoingMessageSender, RequestSerializationQueues, ThreadRequestProcessor, ThreadScopedOutgoingMessageSender, ThreadState, ThreadStateManager, TurnRequestProcessor, appServerUserInputToCoreUserInput, apply_bespoke_event_handling, approvalPolicyString, codexAppServerDeferredResponse, coreDynamicToolResponseFromAppServerResponse, createCodexAppServerRuntime, decodeDynamicToolCallResponse, defaultId, errorToJsonRpcError, fallbackDynamicToolCallResponse, isServerRequestResponseSubmission, jsonRpcError, jsonRpcInternalError, jsonRpcInvalidRequestError, jsonRpcParseError, last_token_info_from_rollout_items, latest_token_usage_turn_id, latest_token_usage_turn_id_from_rollout_items, outgoingMessageToAppServerEvent, parseClientTransportPayload, parseJsonRpcMessage, parseJsonRpcTransportPayload, parseServerTransportPayload, queuedOutgoingMessage, requestSerializationQueueKeyFromScope, serializeJsonRpcError, serializeJsonRpcResponse, serializeOutgoingMessage, steerErrorCode, submissionFromServerRequestError, submissionFromServerRequestResult, threadIdFromStartParams, thread_token_usage_updated_notification_from_info, thread_token_usage_updated_notification_from_rollout_items, unsupportedMethodError, valueOrNull };
|
|
2400
|
+
//# sourceMappingURL=chunk-V4BMZWBM.js.map
|
|
2401
|
+
//# sourceMappingURL=chunk-V4BMZWBM.js.map
|