@nextclaw/nextclaw-ncp-runtime-codex-sdk 0.1.54 → 0.1.55-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/services/codex-app-server-client.service.js +242 -0
- package/dist/services/codex-app-server-client.service.js.map +1 -0
- package/dist/services/codex-app-server-ncp-agent-runtime.service.d.ts +32 -0
- package/dist/services/codex-app-server-ncp-agent-runtime.service.d.ts.map +1 -0
- package/dist/services/codex-app-server-ncp-agent-runtime.service.js +410 -0
- package/dist/services/codex-app-server-ncp-agent-runtime.service.js.map +1 -0
- package/dist/services/codex-desktop-thread-index-sync.service.d.ts +47 -0
- package/dist/services/codex-desktop-thread-index-sync.service.d.ts.map +1 -0
- package/dist/services/codex-desktop-thread-index-sync.service.js +256 -0
- package/dist/services/codex-desktop-thread-index-sync.service.js.map +1 -0
- package/dist/types/codex-app-server-runtime.types.d.ts +26 -0
- package/dist/types/codex-app-server-runtime.types.d.ts.map +1 -0
- package/dist/utils/codex-app-server-item-mapper.utils.js +67 -0
- package/dist/utils/codex-app-server-item-mapper.utils.js.map +1 -0
- package/dist/utils/codex-app-server-request.utils.js +49 -0
- package/dist/utils/codex-app-server-request.utils.js.map +1 -0
- package/dist/{codex-openai-responses-bridge-assistant-output.utils.js → utils/codex-openai-responses-bridge-assistant-output.utils.js} +2 -2
- package/dist/utils/codex-openai-responses-bridge-assistant-output.utils.js.map +1 -0
- package/dist/utils/codex-openai-responses-bridge-request.utils.js.map +1 -1
- package/dist/utils/codex-openai-responses-bridge-stream.utils.js +1 -1
- package/dist/utils/codex-openai-responses-bridge-stream.utils.js.map +1 -1
- package/dist/utils/codex-openai-responses-bridge.utils.js.map +1 -1
- package/dist/utils/codex-openai-responses-stream-writer.utils.d.ts.map +1 -1
- package/dist/utils/codex-openai-responses-stream-writer.utils.js +2 -9
- package/dist/utils/codex-openai-responses-stream-writer.utils.js.map +1 -1
- package/dist/utils/codex-openai-sse-chunks.utils.js.map +1 -1
- package/dist/utils/codex-rollout-thread-summary.utils.js +121 -0
- package/dist/utils/codex-rollout-thread-summary.utils.js.map +1 -0
- package/package.json +4 -3
- package/dist/codex-openai-responses-bridge-assistant-output.utils.js.map +0 -1
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import { CodexNcpRunEventEmitter } from "./codex-ncp-run-event-emitter.service.js";
|
|
2
|
+
import { buildCodexTurnInputFromRunInput } from "../codex-input.utils.js";
|
|
3
|
+
import { isAppServerToolLikeItem, readAppServerReasoningText, readAppServerToolArgs, readAppServerToolName, readAppServerToolResult, stringifyAppServerToolArgs } from "../utils/codex-app-server-item-mapper.utils.js";
|
|
4
|
+
import { compactObject, normalizeSandbox, splitModelRoute, toAppServerInput } from "../utils/codex-app-server-request.utils.js";
|
|
5
|
+
import { CodexAppServerClient } from "./codex-app-server-client.service.js";
|
|
6
|
+
import { CodexDesktopThreadIndexSyncService } from "./codex-desktop-thread-index-sync.service.js";
|
|
7
|
+
import { NcpEventType } from "@nextclaw/ncp";
|
|
8
|
+
//#region src/services/codex-app-server-ncp-agent-runtime.service.ts
|
|
9
|
+
var CodexAppServerNcpAgentRuntime = class {
|
|
10
|
+
eventEmitter;
|
|
11
|
+
sessionMetadata;
|
|
12
|
+
desktopThreadIndexSync;
|
|
13
|
+
clientPromise = null;
|
|
14
|
+
threadId;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.eventEmitter = new CodexNcpRunEventEmitter(config.stateManager);
|
|
18
|
+
this.desktopThreadIndexSync = resolveDesktopThreadIndexSync(config);
|
|
19
|
+
this.threadId = config.threadId?.trim() || null;
|
|
20
|
+
this.sessionMetadata = { ...config.sessionMetadata ? structuredClone(config.sessionMetadata) : {} };
|
|
21
|
+
}
|
|
22
|
+
run = async function* (input, options) {
|
|
23
|
+
const signal = options?.signal;
|
|
24
|
+
const messageId = createId("codex-message");
|
|
25
|
+
const runId = input.runId ?? createId("codex-run");
|
|
26
|
+
const textState = /* @__PURE__ */ new Set();
|
|
27
|
+
const textDeltaState = /* @__PURE__ */ new Set();
|
|
28
|
+
const reasoningState = /* @__PURE__ */ new Set();
|
|
29
|
+
const reasoningDeltaState = /* @__PURE__ */ new Set();
|
|
30
|
+
const toolState = /* @__PURE__ */ new Set();
|
|
31
|
+
yield* this.eventEmitter.emitRunStarted(input.sessionId, messageId, runId);
|
|
32
|
+
yield* this.eventEmitter.emitReadyMetadata(input.sessionId, messageId, runId);
|
|
33
|
+
const client = await this.resolveClient();
|
|
34
|
+
await this.resolveThread(client);
|
|
35
|
+
const turnInput = await this.buildTurnInput(input);
|
|
36
|
+
const turnId = readString((await client.request("turn/start", {
|
|
37
|
+
threadId: this.threadId ?? "",
|
|
38
|
+
input: toAppServerInput(turnInput),
|
|
39
|
+
...this.buildTurnOverrides()
|
|
40
|
+
})).turn?.id);
|
|
41
|
+
const abortListener = () => {
|
|
42
|
+
if (turnId && this.threadId) client.request("turn/interrupt", {
|
|
43
|
+
threadId: this.threadId,
|
|
44
|
+
turnId
|
|
45
|
+
}, 5e3).catch(() => {
|
|
46
|
+
client.dispose();
|
|
47
|
+
});
|
|
48
|
+
else client.dispose();
|
|
49
|
+
};
|
|
50
|
+
signal?.addEventListener("abort", abortListener, { once: true });
|
|
51
|
+
try {
|
|
52
|
+
while (true) {
|
|
53
|
+
if (signal?.aborted) throw toAbortError(signal.reason);
|
|
54
|
+
const next = await client.nextNotification();
|
|
55
|
+
if (next.done) return;
|
|
56
|
+
if (yield* this.handleNotification({
|
|
57
|
+
notification: next.value,
|
|
58
|
+
sessionId: input.sessionId,
|
|
59
|
+
messageId,
|
|
60
|
+
runId,
|
|
61
|
+
textState,
|
|
62
|
+
textDeltaState,
|
|
63
|
+
reasoningState,
|
|
64
|
+
reasoningDeltaState,
|
|
65
|
+
toolState
|
|
66
|
+
})) return;
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
signal?.removeEventListener("abort", abortListener);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
resolveClient = async () => {
|
|
73
|
+
if (!this.clientPromise) {
|
|
74
|
+
const client = new CodexAppServerClient(this.config);
|
|
75
|
+
this.clientPromise = client.initialize().then(() => client);
|
|
76
|
+
}
|
|
77
|
+
return this.clientPromise;
|
|
78
|
+
};
|
|
79
|
+
resolveThread = async (client) => {
|
|
80
|
+
if (this.threadId) {
|
|
81
|
+
const response = await client.request("thread/resume", {
|
|
82
|
+
threadId: this.threadId,
|
|
83
|
+
...this.buildThreadOverrides()
|
|
84
|
+
});
|
|
85
|
+
await this.updateThreadId(readString(response.thread?.id) ?? this.threadId);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const nextThreadId = readString((await client.request("thread/start", { ...this.buildThreadOverrides() })).thread?.id);
|
|
89
|
+
if (nextThreadId) await this.updateThreadId(nextThreadId);
|
|
90
|
+
};
|
|
91
|
+
buildThreadOverrides = () => {
|
|
92
|
+
const threadOptions = this.config.threadOptions;
|
|
93
|
+
const route = splitModelRoute(threadOptions?.model ?? this.config.model);
|
|
94
|
+
return compactObject({
|
|
95
|
+
cwd: threadOptions?.workingDirectory,
|
|
96
|
+
model: route.model,
|
|
97
|
+
modelProvider: route.modelProvider,
|
|
98
|
+
approvalPolicy: threadOptions?.approvalPolicy,
|
|
99
|
+
sandbox: normalizeSandbox(threadOptions?.sandboxMode),
|
|
100
|
+
config: this.config.cliConfig
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
buildTurnOverrides = () => {
|
|
104
|
+
const threadOptions = this.config.threadOptions;
|
|
105
|
+
const route = splitModelRoute(threadOptions?.model ?? this.config.model);
|
|
106
|
+
return compactObject({
|
|
107
|
+
cwd: threadOptions?.workingDirectory,
|
|
108
|
+
model: route.model,
|
|
109
|
+
effort: threadOptions?.modelReasoningEffort,
|
|
110
|
+
sandboxPolicy: normalizeSandbox(threadOptions?.sandboxMode),
|
|
111
|
+
approvalPolicy: threadOptions?.approvalPolicy
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
buildTurnInput = async (input) => {
|
|
115
|
+
if (this.config.inputBuilder) return await this.config.inputBuilder(input);
|
|
116
|
+
return await buildCodexTurnInputFromRunInput(input, { resolveAssetContentPath: this.config.resolveAssetContentPath });
|
|
117
|
+
};
|
|
118
|
+
handleNotification = async function* (params) {
|
|
119
|
+
const { messageId, notification, reasoningDeltaState, reasoningState, runId, sessionId, textDeltaState, textState, toolState } = params;
|
|
120
|
+
if (notification.method === "thread/started") {
|
|
121
|
+
await this.handleThreadStarted(notification.params);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
if (notification.method === "item/agentMessage/delta") {
|
|
125
|
+
yield* this.emitTextDelta({
|
|
126
|
+
messageId,
|
|
127
|
+
params: notification.params,
|
|
128
|
+
sessionId,
|
|
129
|
+
textDeltaState,
|
|
130
|
+
textState
|
|
131
|
+
});
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
if (notification.method === "item/reasoning/textDelta" || notification.method === "item/reasoning/summaryTextDelta") {
|
|
135
|
+
yield* this.emitReasoningDelta({
|
|
136
|
+
messageId,
|
|
137
|
+
params: notification.params,
|
|
138
|
+
reasoningDeltaState,
|
|
139
|
+
reasoningState,
|
|
140
|
+
sessionId
|
|
141
|
+
});
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (notification.method === "item/started" || notification.method === "item/completed") {
|
|
145
|
+
const item = notification.params.item;
|
|
146
|
+
if (item) yield* this.handleItemLifecycle({
|
|
147
|
+
item,
|
|
148
|
+
eventType: notification.method,
|
|
149
|
+
sessionId,
|
|
150
|
+
messageId,
|
|
151
|
+
reasoningDeltaState,
|
|
152
|
+
textState,
|
|
153
|
+
textDeltaState,
|
|
154
|
+
reasoningState,
|
|
155
|
+
toolState
|
|
156
|
+
});
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
if (notification.method === "turn/completed") {
|
|
160
|
+
yield* this.eventEmitter.emitRunCompleted(sessionId, messageId, runId);
|
|
161
|
+
await this.syncDesktopThreadIndex();
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
if (notification.method === "turn/failed") {
|
|
165
|
+
yield* this.eventEmitter.emitRunError(sessionId, messageId, runId, readString(notification.params.error) ?? "Codex turn failed.");
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
};
|
|
170
|
+
handleThreadStarted = async (params) => {
|
|
171
|
+
const threadId = readString(params.thread?.id);
|
|
172
|
+
if (threadId) await this.updateThreadId(threadId);
|
|
173
|
+
};
|
|
174
|
+
emitTextDelta = async function* (params) {
|
|
175
|
+
const { messageId, sessionId, textDeltaState, textState } = params;
|
|
176
|
+
const itemId = readString(params.params.itemId) ?? "agent-message";
|
|
177
|
+
if (!textState.has(itemId)) {
|
|
178
|
+
textState.add(itemId);
|
|
179
|
+
yield* this.eventEmitter.emitEvent({
|
|
180
|
+
type: NcpEventType.MessageTextStart,
|
|
181
|
+
payload: {
|
|
182
|
+
sessionId,
|
|
183
|
+
messageId
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
textDeltaState.add(itemId);
|
|
188
|
+
yield* this.eventEmitter.emitEvent({
|
|
189
|
+
type: NcpEventType.MessageTextDelta,
|
|
190
|
+
payload: {
|
|
191
|
+
sessionId,
|
|
192
|
+
messageId,
|
|
193
|
+
delta: readRawString(params.params.delta) ?? ""
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
};
|
|
197
|
+
emitReasoningDelta = async function* (params) {
|
|
198
|
+
const { messageId, reasoningDeltaState, reasoningState, sessionId } = params;
|
|
199
|
+
const itemId = readString(params.params.itemId) ?? "reasoning";
|
|
200
|
+
if (!reasoningState.has(itemId)) {
|
|
201
|
+
reasoningState.add(itemId);
|
|
202
|
+
yield* this.eventEmitter.emitEvent({
|
|
203
|
+
type: NcpEventType.MessageReasoningStart,
|
|
204
|
+
payload: {
|
|
205
|
+
sessionId,
|
|
206
|
+
messageId
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
reasoningDeltaState.add(itemId);
|
|
211
|
+
yield* this.eventEmitter.emitEvent({
|
|
212
|
+
type: NcpEventType.MessageReasoningDelta,
|
|
213
|
+
payload: {
|
|
214
|
+
sessionId,
|
|
215
|
+
messageId,
|
|
216
|
+
delta: readRawString(params.params.delta) ?? ""
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
handleItemLifecycle = async function* (params) {
|
|
221
|
+
const { eventType, item, messageId, reasoningDeltaState, reasoningState, sessionId, textDeltaState, textState, toolState } = params;
|
|
222
|
+
const itemId = readString(item.id) ?? createId("codex-item");
|
|
223
|
+
if (item.type === "agentMessage") {
|
|
224
|
+
yield* this.handleAgentMessageItem({
|
|
225
|
+
eventType,
|
|
226
|
+
item,
|
|
227
|
+
itemId,
|
|
228
|
+
messageId,
|
|
229
|
+
sessionId,
|
|
230
|
+
textDeltaState,
|
|
231
|
+
textState
|
|
232
|
+
});
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (item.type === "reasoning") {
|
|
236
|
+
yield* this.handleReasoningItem({
|
|
237
|
+
eventType,
|
|
238
|
+
item,
|
|
239
|
+
itemId,
|
|
240
|
+
messageId,
|
|
241
|
+
reasoningDeltaState,
|
|
242
|
+
reasoningState,
|
|
243
|
+
sessionId
|
|
244
|
+
});
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (!isAppServerToolLikeItem(item.type)) return;
|
|
248
|
+
yield* this.handleToolItem({
|
|
249
|
+
eventType,
|
|
250
|
+
item,
|
|
251
|
+
itemId,
|
|
252
|
+
messageId,
|
|
253
|
+
sessionId,
|
|
254
|
+
toolState
|
|
255
|
+
});
|
|
256
|
+
};
|
|
257
|
+
handleAgentMessageItem = async function* (params) {
|
|
258
|
+
const { eventType, item, itemId, messageId, sessionId, textDeltaState, textState } = params;
|
|
259
|
+
if (!textState.has(itemId)) {
|
|
260
|
+
textState.add(itemId);
|
|
261
|
+
yield* this.eventEmitter.emitEvent({
|
|
262
|
+
type: NcpEventType.MessageTextStart,
|
|
263
|
+
payload: {
|
|
264
|
+
sessionId,
|
|
265
|
+
messageId
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
const text = readRawString(item.text);
|
|
270
|
+
if (text && !textDeltaState.has(itemId)) yield* this.eventEmitter.emitEvent({
|
|
271
|
+
type: NcpEventType.MessageTextDelta,
|
|
272
|
+
payload: {
|
|
273
|
+
sessionId,
|
|
274
|
+
messageId,
|
|
275
|
+
delta: text
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
if (eventType === "item/completed") yield* this.eventEmitter.emitEvent({
|
|
279
|
+
type: NcpEventType.MessageTextEnd,
|
|
280
|
+
payload: {
|
|
281
|
+
sessionId,
|
|
282
|
+
messageId
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
};
|
|
286
|
+
handleReasoningItem = async function* (params) {
|
|
287
|
+
const { eventType, item, itemId, messageId, reasoningDeltaState, reasoningState, sessionId } = params;
|
|
288
|
+
const reasoningText = readAppServerReasoningText(item);
|
|
289
|
+
if (!reasoningState.has(itemId) && (eventType === "item/started" || reasoningText)) {
|
|
290
|
+
reasoningState.add(itemId);
|
|
291
|
+
yield* this.eventEmitter.emitEvent({
|
|
292
|
+
type: NcpEventType.MessageReasoningStart,
|
|
293
|
+
payload: {
|
|
294
|
+
sessionId,
|
|
295
|
+
messageId
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
if (!reasoningDeltaState.has(itemId) && reasoningText) yield* this.eventEmitter.emitEvent({
|
|
300
|
+
type: NcpEventType.MessageReasoningDelta,
|
|
301
|
+
payload: {
|
|
302
|
+
sessionId,
|
|
303
|
+
messageId,
|
|
304
|
+
delta: reasoningText
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
if (eventType === "item/completed" && reasoningState.has(itemId)) yield* this.eventEmitter.emitEvent({
|
|
308
|
+
type: NcpEventType.MessageReasoningEnd,
|
|
309
|
+
payload: {
|
|
310
|
+
sessionId,
|
|
311
|
+
messageId
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
};
|
|
315
|
+
handleToolItem = async function* (params) {
|
|
316
|
+
const { eventType, item, itemId, messageId, sessionId, toolState } = params;
|
|
317
|
+
if (!toolState.has(itemId)) {
|
|
318
|
+
toolState.add(itemId);
|
|
319
|
+
yield* this.eventEmitter.emitEvent({
|
|
320
|
+
type: NcpEventType.MessageToolCallStart,
|
|
321
|
+
payload: {
|
|
322
|
+
sessionId,
|
|
323
|
+
messageId,
|
|
324
|
+
toolCallId: itemId,
|
|
325
|
+
toolName: readAppServerToolName(item)
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
yield* this.eventEmitter.emitEvent({
|
|
329
|
+
type: NcpEventType.MessageToolCallArgs,
|
|
330
|
+
payload: {
|
|
331
|
+
sessionId,
|
|
332
|
+
toolCallId: itemId,
|
|
333
|
+
args: stringifyAppServerToolArgs(readAppServerToolArgs(item))
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
yield* this.eventEmitter.emitEvent({
|
|
337
|
+
type: NcpEventType.MessageToolCallEnd,
|
|
338
|
+
payload: {
|
|
339
|
+
sessionId,
|
|
340
|
+
toolCallId: itemId
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
if (eventType === "item/completed") yield* this.eventEmitter.emitEvent({
|
|
345
|
+
type: NcpEventType.MessageToolCallResult,
|
|
346
|
+
payload: {
|
|
347
|
+
sessionId,
|
|
348
|
+
toolCallId: itemId,
|
|
349
|
+
content: readAppServerToolResult(item)
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
};
|
|
353
|
+
updateThreadId = async (nextThreadId) => {
|
|
354
|
+
const normalizedThreadId = nextThreadId.trim();
|
|
355
|
+
if (!normalizedThreadId || normalizedThreadId === this.threadId) return;
|
|
356
|
+
this.threadId = normalizedThreadId;
|
|
357
|
+
const nextMetadata = {
|
|
358
|
+
...this.sessionMetadata,
|
|
359
|
+
session_type: "codex",
|
|
360
|
+
codex_thread_id: normalizedThreadId,
|
|
361
|
+
codex_thread_model: buildThreadModelScope(this.config)
|
|
362
|
+
};
|
|
363
|
+
this.sessionMetadata.codex_thread_id = normalizedThreadId;
|
|
364
|
+
this.sessionMetadata.codex_thread_model = nextMetadata.codex_thread_model;
|
|
365
|
+
this.sessionMetadata.session_type = "codex";
|
|
366
|
+
await this.config.setSessionMetadata?.(nextMetadata);
|
|
367
|
+
};
|
|
368
|
+
syncDesktopThreadIndex = async () => {
|
|
369
|
+
try {
|
|
370
|
+
await this.desktopThreadIndexSync?.syncThread({ threadId: this.threadId });
|
|
371
|
+
} catch (error) {
|
|
372
|
+
console.error(`[nextclaw-codex-app-server] failed to run Codex Desktop thread index sync: ${formatError(error)}`);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
};
|
|
376
|
+
function createId(prefix) {
|
|
377
|
+
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
378
|
+
}
|
|
379
|
+
function resolveDesktopThreadIndexSync(config) {
|
|
380
|
+
if (config.desktopThreadIndexSync === false) return null;
|
|
381
|
+
return config.desktopThreadIndexSync ?? new CodexDesktopThreadIndexSyncService({ env: {
|
|
382
|
+
...process.env,
|
|
383
|
+
...config.env
|
|
384
|
+
} });
|
|
385
|
+
}
|
|
386
|
+
function readString(value) {
|
|
387
|
+
if (typeof value !== "string") return;
|
|
388
|
+
const trimmed = value.trim();
|
|
389
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
390
|
+
}
|
|
391
|
+
function readRawString(value) {
|
|
392
|
+
return typeof value === "string" ? value : void 0;
|
|
393
|
+
}
|
|
394
|
+
function buildThreadModelScope(config) {
|
|
395
|
+
return readString(config.threadOptions?.model) ?? readString(config.model) ?? "__nextclaw_runtime_default__";
|
|
396
|
+
}
|
|
397
|
+
function toAbortError(reason) {
|
|
398
|
+
if (reason instanceof Error) return reason;
|
|
399
|
+
const message = typeof reason === "string" && reason.trim() ? reason.trim() : "operation aborted";
|
|
400
|
+
const error = new Error(message);
|
|
401
|
+
error.name = "AbortError";
|
|
402
|
+
return error;
|
|
403
|
+
}
|
|
404
|
+
function formatError(error) {
|
|
405
|
+
return error instanceof Error ? error.message : String(error);
|
|
406
|
+
}
|
|
407
|
+
//#endregion
|
|
408
|
+
export { CodexAppServerNcpAgentRuntime };
|
|
409
|
+
|
|
410
|
+
//# sourceMappingURL=codex-app-server-ncp-agent-runtime.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-app-server-ncp-agent-runtime.service.js","names":[],"sources":["../../src/services/codex-app-server-ncp-agent-runtime.service.ts"],"sourcesContent":["import {\n type NcpAgentRunInput,\n type NcpAgentRunOptions,\n type NcpAgentRuntime,\n type NcpEndpointEvent,\n NcpEventType,\n} from \"@nextclaw/ncp\";\nimport {\n buildCodexTurnInputFromRunInput,\n type CodexThreadInput,\n} from \"@/codex-input.utils.js\";\nimport {\n isAppServerToolLikeItem,\n readAppServerReasoningText,\n readAppServerToolArgs,\n readAppServerToolName,\n readAppServerToolResult,\n stringifyAppServerToolArgs,\n} from \"@/utils/codex-app-server-item-mapper.utils.js\";\nimport {\n compactObject,\n normalizeSandbox,\n splitModelRoute,\n toAppServerInput,\n} from \"@/utils/codex-app-server-request.utils.js\";\nimport { CodexAppServerClient } from \"./codex-app-server-client.service.js\";\nimport type {\n AppServerNotification,\n AppServerThreadItem,\n CodexAppServerNcpAgentRuntimeConfig,\n JsonObject,\n} from \"@/types/codex-app-server-runtime.types.js\";\nimport { CodexNcpRunEventEmitter } from \"./codex-ncp-run-event-emitter.service.js\";\nimport {\n CodexDesktopThreadIndexSyncService,\n type CodexDesktopThreadIndexSync,\n} from \"./codex-desktop-thread-index-sync.service.js\";\n\nexport class CodexAppServerNcpAgentRuntime implements NcpAgentRuntime {\n private readonly eventEmitter: CodexNcpRunEventEmitter;\n private readonly sessionMetadata: Record<string, unknown>;\n private readonly desktopThreadIndexSync: CodexDesktopThreadIndexSync | null;\n private clientPromise: Promise<CodexAppServerClient> | null = null;\n private threadId: string | null;\n\n constructor(private readonly config: CodexAppServerNcpAgentRuntimeConfig) {\n this.eventEmitter = new CodexNcpRunEventEmitter(config.stateManager);\n this.desktopThreadIndexSync = resolveDesktopThreadIndexSync(config);\n this.threadId = config.threadId?.trim() || null;\n this.sessionMetadata = {\n ...(config.sessionMetadata ? structuredClone(config.sessionMetadata) : {}),\n };\n }\n\n run = async function* (\n this: CodexAppServerNcpAgentRuntime,\n input: NcpAgentRunInput,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n const signal = options?.signal;\n const messageId = createId(\"codex-message\");\n const runId = (input as NcpAgentRunInput & { runId?: string }).runId ?? createId(\"codex-run\");\n const textState = new Set<string>();\n const textDeltaState = new Set<string>();\n const reasoningState = new Set<string>();\n const reasoningDeltaState = new Set<string>();\n const toolState = new Set<string>();\n\n yield* this.eventEmitter.emitRunStarted(input.sessionId, messageId, runId);\n yield* this.eventEmitter.emitReadyMetadata(input.sessionId, messageId, runId);\n\n const client = await this.resolveClient();\n await this.resolveThread(client);\n const turnInput = await this.buildTurnInput(input);\n const turn = await client.request<{ turn?: { id?: string } }>(\"turn/start\", {\n threadId: this.threadId ?? \"\",\n input: toAppServerInput(turnInput),\n ...this.buildTurnOverrides(),\n });\n const turnId = readString(turn.turn?.id);\n const abortListener = (): void => {\n if (turnId && this.threadId) {\n void client.request(\"turn/interrupt\", { threadId: this.threadId, turnId }, 5000).catch(() => {\n client.dispose();\n });\n } else {\n client.dispose();\n }\n };\n signal?.addEventListener(\"abort\", abortListener, { once: true });\n try {\n while (true) {\n if (signal?.aborted) {\n throw toAbortError(signal.reason);\n }\n const next = await client.nextNotification();\n if (next.done) {\n return;\n }\n const shouldFinish = yield* this.handleNotification({\n notification: next.value,\n sessionId: input.sessionId,\n messageId,\n runId,\n textState,\n textDeltaState,\n reasoningState,\n reasoningDeltaState,\n toolState,\n });\n if (shouldFinish) {\n return;\n }\n }\n } finally {\n signal?.removeEventListener(\"abort\", abortListener);\n }\n };\n\n private resolveClient = async (): Promise<CodexAppServerClient> => {\n if (!this.clientPromise) {\n const client = new CodexAppServerClient(this.config);\n this.clientPromise = client.initialize().then(() => client);\n }\n return this.clientPromise;\n };\n\n private resolveThread = async (client: CodexAppServerClient): Promise<void> => {\n if (this.threadId) {\n const response = await client.request<{ thread?: { id?: string } }>(\"thread/resume\", {\n threadId: this.threadId,\n ...this.buildThreadOverrides(),\n });\n await this.updateThreadId(readString(response.thread?.id) ?? this.threadId);\n return;\n }\n const response = await client.request<{ thread?: { id?: string } }>(\"thread/start\", {\n ...this.buildThreadOverrides(),\n });\n const nextThreadId = readString(response.thread?.id);\n if (nextThreadId) {\n await this.updateThreadId(nextThreadId);\n }\n };\n\n private buildThreadOverrides = (): JsonObject => {\n const threadOptions = this.config.threadOptions;\n const route = splitModelRoute(threadOptions?.model ?? this.config.model);\n return compactObject({\n cwd: threadOptions?.workingDirectory,\n model: route.model,\n modelProvider: route.modelProvider,\n approvalPolicy: threadOptions?.approvalPolicy,\n sandbox: normalizeSandbox(threadOptions?.sandboxMode),\n config: this.config.cliConfig,\n });\n };\n\n private buildTurnOverrides = (): JsonObject => {\n const threadOptions = this.config.threadOptions;\n const route = splitModelRoute(threadOptions?.model ?? this.config.model);\n return compactObject({\n cwd: threadOptions?.workingDirectory,\n model: route.model,\n effort: threadOptions?.modelReasoningEffort,\n sandboxPolicy: normalizeSandbox(threadOptions?.sandboxMode),\n approvalPolicy: threadOptions?.approvalPolicy,\n });\n };\n\n private buildTurnInput = async (input: NcpAgentRunInput): Promise<CodexThreadInput> => {\n if (this.config.inputBuilder) {\n return await this.config.inputBuilder(input);\n }\n return await buildCodexTurnInputFromRunInput(input, {\n resolveAssetContentPath: this.config.resolveAssetContentPath,\n });\n };\n\n private handleNotification = async function* (\n this: CodexAppServerNcpAgentRuntime,\n params: {\n notification: AppServerNotification;\n sessionId: string;\n messageId: string;\n runId: string;\n textState: Set<string>;\n textDeltaState: Set<string>;\n reasoningState: Set<string>;\n reasoningDeltaState: Set<string>;\n toolState: Set<string>;\n },\n ): AsyncGenerator<NcpEndpointEvent, boolean> {\n const {\n messageId,\n notification,\n reasoningDeltaState,\n reasoningState,\n runId,\n sessionId,\n textDeltaState,\n textState,\n toolState,\n } = params;\n if (notification.method === \"thread/started\") {\n await this.handleThreadStarted(notification.params);\n return false;\n }\n if (notification.method === \"item/agentMessage/delta\") {\n yield* this.emitTextDelta({\n messageId,\n params: notification.params,\n sessionId,\n textDeltaState,\n textState,\n });\n return false;\n }\n if (\n notification.method === \"item/reasoning/textDelta\" ||\n notification.method === \"item/reasoning/summaryTextDelta\"\n ) {\n yield* this.emitReasoningDelta({\n messageId,\n params: notification.params,\n reasoningDeltaState,\n reasoningState,\n sessionId,\n });\n return false;\n }\n if (notification.method === \"item/started\" || notification.method === \"item/completed\") {\n const item = notification.params.item as AppServerThreadItem | undefined;\n if (item) {\n yield* this.handleItemLifecycle({\n item,\n eventType: notification.method,\n sessionId,\n messageId,\n reasoningDeltaState,\n textState,\n textDeltaState,\n reasoningState,\n toolState,\n });\n }\n return false;\n }\n if (notification.method === \"turn/completed\") {\n yield* this.eventEmitter.emitRunCompleted(sessionId, messageId, runId);\n await this.syncDesktopThreadIndex();\n return true;\n }\n if (notification.method === \"turn/failed\") {\n yield* this.eventEmitter.emitRunError(\n sessionId,\n messageId,\n runId,\n readString(notification.params.error) ?? \"Codex turn failed.\",\n );\n return true;\n }\n return false;\n };\n\n private handleThreadStarted = async (params: JsonObject): Promise<void> => {\n const threadId = readString((params.thread as JsonObject | undefined)?.id);\n if (threadId) {\n await this.updateThreadId(threadId);\n }\n };\n\n private emitTextDelta = async function* (\n this: CodexAppServerNcpAgentRuntime,\n params: {\n params: JsonObject;\n sessionId: string;\n messageId: string;\n textState: Set<string>;\n textDeltaState: Set<string>;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const { messageId, sessionId, textDeltaState, textState } = params;\n const itemId = readString(params.params.itemId) ?? \"agent-message\";\n if (!textState.has(itemId)) {\n textState.add(itemId);\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageTextStart,\n payload: { sessionId, messageId },\n });\n }\n textDeltaState.add(itemId);\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageTextDelta,\n payload: { sessionId, messageId, delta: readRawString(params.params.delta) ?? \"\" },\n });\n };\n\n private emitReasoningDelta = async function* (\n this: CodexAppServerNcpAgentRuntime,\n params: {\n params: JsonObject;\n sessionId: string;\n messageId: string;\n reasoningState: Set<string>;\n reasoningDeltaState: Set<string>;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const { messageId, reasoningDeltaState, reasoningState, sessionId } = params;\n const itemId = readString(params.params.itemId) ?? \"reasoning\";\n if (!reasoningState.has(itemId)) {\n reasoningState.add(itemId);\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageReasoningStart,\n payload: { sessionId, messageId },\n });\n }\n reasoningDeltaState.add(itemId);\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageReasoningDelta,\n payload: { sessionId, messageId, delta: readRawString(params.params.delta) ?? \"\" },\n });\n };\n\n private handleItemLifecycle = async function* (\n this: CodexAppServerNcpAgentRuntime,\n params: {\n item: AppServerThreadItem;\n eventType: \"item/started\" | \"item/completed\";\n sessionId: string;\n messageId: string;\n textState: Set<string>;\n textDeltaState: Set<string>;\n reasoningState: Set<string>;\n reasoningDeltaState: Set<string>;\n toolState: Set<string>;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const {\n eventType,\n item,\n messageId,\n reasoningDeltaState,\n reasoningState,\n sessionId,\n textDeltaState,\n textState,\n toolState,\n } = params;\n const itemId = readString(item.id) ?? createId(\"codex-item\");\n if (item.type === \"agentMessage\") {\n yield* this.handleAgentMessageItem({\n eventType,\n item,\n itemId,\n messageId,\n sessionId,\n textDeltaState,\n textState,\n });\n return;\n }\n if (item.type === \"reasoning\") {\n yield* this.handleReasoningItem({\n eventType,\n item,\n itemId,\n messageId,\n reasoningDeltaState,\n reasoningState,\n sessionId,\n });\n return;\n }\n if (!isAppServerToolLikeItem(item.type)) {\n return;\n }\n yield* this.handleToolItem({ eventType, item, itemId, messageId, sessionId, toolState });\n };\n\n private handleAgentMessageItem = async function* (\n this: CodexAppServerNcpAgentRuntime,\n params: {\n item: AppServerThreadItem;\n itemId: string;\n eventType: \"item/started\" | \"item/completed\";\n sessionId: string;\n messageId: string;\n textState: Set<string>;\n textDeltaState: Set<string>;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const { eventType, item, itemId, messageId, sessionId, textDeltaState, textState } = params;\n if (!textState.has(itemId)) {\n textState.add(itemId);\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageTextStart,\n payload: { sessionId, messageId },\n });\n }\n const text = readRawString(item.text);\n if (text && !textDeltaState.has(itemId)) {\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageTextDelta,\n payload: { sessionId, messageId, delta: text },\n });\n }\n if (eventType === \"item/completed\") {\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageTextEnd,\n payload: { sessionId, messageId },\n });\n }\n };\n\n private handleReasoningItem = async function* (\n this: CodexAppServerNcpAgentRuntime,\n params: {\n item: AppServerThreadItem;\n itemId: string;\n eventType: \"item/started\" | \"item/completed\";\n sessionId: string;\n messageId: string;\n reasoningState: Set<string>;\n reasoningDeltaState: Set<string>;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const { eventType, item, itemId, messageId, reasoningDeltaState, reasoningState, sessionId } =\n params;\n const reasoningText = readAppServerReasoningText(item);\n const alreadyStarted = reasoningState.has(itemId);\n if (!alreadyStarted && (eventType === \"item/started\" || reasoningText)) {\n reasoningState.add(itemId);\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageReasoningStart,\n payload: { sessionId, messageId },\n });\n }\n if (!reasoningDeltaState.has(itemId) && reasoningText) {\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageReasoningDelta,\n payload: { sessionId, messageId, delta: reasoningText },\n });\n }\n if (eventType === \"item/completed\" && reasoningState.has(itemId)) {\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageReasoningEnd,\n payload: { sessionId, messageId },\n });\n }\n };\n\n private handleToolItem = async function* (\n this: CodexAppServerNcpAgentRuntime,\n params: {\n item: AppServerThreadItem;\n itemId: string;\n eventType: \"item/started\" | \"item/completed\";\n sessionId: string;\n messageId: string;\n toolState: Set<string>;\n },\n ): AsyncGenerator<NcpEndpointEvent> {\n const { eventType, item, itemId, messageId, sessionId, toolState } = params;\n if (!toolState.has(itemId)) {\n toolState.add(itemId);\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageToolCallStart,\n payload: { sessionId, messageId, toolCallId: itemId, toolName: readAppServerToolName(item) },\n });\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageToolCallArgs,\n payload: {\n sessionId,\n toolCallId: itemId,\n args: stringifyAppServerToolArgs(readAppServerToolArgs(item)),\n },\n });\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageToolCallEnd,\n payload: { sessionId, toolCallId: itemId },\n });\n }\n if (eventType === \"item/completed\") {\n yield* this.eventEmitter.emitEvent({\n type: NcpEventType.MessageToolCallResult,\n payload: { sessionId, toolCallId: itemId, content: readAppServerToolResult(item) },\n });\n }\n };\n\n private updateThreadId = async (nextThreadId: string): Promise<void> => {\n const normalizedThreadId = nextThreadId.trim();\n if (!normalizedThreadId || normalizedThreadId === this.threadId) {\n return;\n }\n this.threadId = normalizedThreadId;\n const nextMetadata = {\n ...this.sessionMetadata,\n session_type: \"codex\",\n codex_thread_id: normalizedThreadId,\n codex_thread_model: buildThreadModelScope(this.config),\n };\n this.sessionMetadata.codex_thread_id = normalizedThreadId;\n this.sessionMetadata.codex_thread_model = nextMetadata.codex_thread_model;\n this.sessionMetadata.session_type = \"codex\";\n await this.config.setSessionMetadata?.(nextMetadata);\n };\n\n private syncDesktopThreadIndex = async (): Promise<void> => {\n try {\n await this.desktopThreadIndexSync?.syncThread({ threadId: this.threadId });\n } catch (error) {\n console.error(\n `[nextclaw-codex-app-server] failed to run Codex Desktop thread index sync: ${formatError(error)}`,\n );\n }\n };\n}\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction resolveDesktopThreadIndexSync(\n config: CodexAppServerNcpAgentRuntimeConfig,\n): CodexDesktopThreadIndexSync | null {\n if (config.desktopThreadIndexSync === false) {\n return null;\n }\n return config.desktopThreadIndexSync ?? new CodexDesktopThreadIndexSyncService({\n env: { ...process.env, ...config.env },\n });\n}\n\nfunction readString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction readRawString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction buildThreadModelScope(config: CodexAppServerNcpAgentRuntimeConfig): string {\n return readString(config.threadOptions?.model) ??\n readString(config.model) ??\n \"__nextclaw_runtime_default__\";\n}\n\nfunction toAbortError(reason: unknown): Error {\n if (reason instanceof Error) {\n return reason;\n }\n const message = typeof reason === \"string\" && reason.trim() ? reason.trim() : \"operation aborted\";\n const error = new Error(message);\n error.name = \"AbortError\";\n return error;\n}\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/services/codex-desktop-thread-index-sync.service.d.ts
|
|
2
|
+
type CodexDesktopStatement = {
|
|
3
|
+
all: (...params: unknown[]) => unknown[];
|
|
4
|
+
get: (...params: unknown[]) => unknown;
|
|
5
|
+
run: (...params: unknown[]) => unknown;
|
|
6
|
+
};
|
|
7
|
+
type CodexDesktopDatabase = {
|
|
8
|
+
close: () => void;
|
|
9
|
+
exec: (sql: string) => void;
|
|
10
|
+
prepare: (sql: string) => CodexDesktopStatement;
|
|
11
|
+
};
|
|
12
|
+
type CodexDesktopDatabaseSyncCtor = new (path: string) => CodexDesktopDatabase;
|
|
13
|
+
interface CodexDesktopThreadIndexSync {
|
|
14
|
+
syncThread(params: {
|
|
15
|
+
threadId?: string | null;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
interface CodexDesktopThreadIndexSyncServiceOptions {
|
|
19
|
+
databasePath?: string;
|
|
20
|
+
env?: NodeJS.ProcessEnv;
|
|
21
|
+
homeDirectory?: string;
|
|
22
|
+
loadDatabaseSync?: () => Promise<CodexDesktopDatabaseSyncCtor>;
|
|
23
|
+
logger?: Pick<Console, "error" | "warn">;
|
|
24
|
+
sessionsDirectory?: string;
|
|
25
|
+
}
|
|
26
|
+
declare class CodexDesktopThreadIndexSyncService implements CodexDesktopThreadIndexSync {
|
|
27
|
+
private readonly databasePath?;
|
|
28
|
+
private readonly env;
|
|
29
|
+
private readonly homeDirectory;
|
|
30
|
+
private readonly loadDatabaseSync;
|
|
31
|
+
private readonly logger;
|
|
32
|
+
private readonly sessionsDirectory?;
|
|
33
|
+
constructor(options?: CodexDesktopThreadIndexSyncServiceOptions);
|
|
34
|
+
syncThread: (params: {
|
|
35
|
+
threadId?: string | null;
|
|
36
|
+
}) => Promise<void>;
|
|
37
|
+
private syncThreadIndex;
|
|
38
|
+
private insertThreadRow;
|
|
39
|
+
private updateThreadRow;
|
|
40
|
+
private resolveRolloutPath;
|
|
41
|
+
private resolveDatabasePath;
|
|
42
|
+
private resolveSessionsDirectory;
|
|
43
|
+
private resolveCodexHome;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { CodexDesktopThreadIndexSync, CodexDesktopThreadIndexSyncService, CodexDesktopThreadIndexSyncServiceOptions };
|
|
47
|
+
//# sourceMappingURL=codex-desktop-thread-index-sync.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-desktop-thread-index-sync.service.d.ts","names":[],"sources":["../../src/services/codex-desktop-thread-index-sync.service.ts"],"mappings":";KA2CK,qBAAA;EACH,GAAA,MAAS,MAAA;EACT,GAAA,MAAS,MAAA;EACT,GAAA,MAAS,MAAA;AAAA;AAAA,KAGN,oBAAA;EACH,KAAA;EACA,IAAA,GAAO,GAAA;EACP,OAAA,GAAU,GAAA,aAAgB,qBAAA;AAAA;AAAA,KAGvB,4BAAA,QAAoC,IAAA,aAAiB,oBAAA;AAAA,UAUzC,2BAAA;EACf,UAAA,CAAW,MAAA;IAAU,QAAA;EAAA,IAA6B,OAAA;AAAA;AAAA,UAGnC,yCAAA;EACf,YAAA;EACA,GAAA,GAAM,MAAA,CAAO,UAAA;EACb,aAAA;EACA,gBAAA,SAAyB,OAAA,CAAQ,4BAAA;EACjC,MAAA,GAAS,IAAA,CAAK,OAAA;EACd,iBAAA;AAAA;AAAA,cAGW,kCAAA,YAA8C,2BAAA;EAAA,iBACxC,YAAA;EAAA,iBACA,GAAA;EAAA,iBACA,aAAA;EAAA,iBACA,gBAAA;EAAA,iBACA,MAAA;EAAA,iBACA,iBAAA;cAEL,OAAA,GAAS,yCAAA;EAUrB,UAAA,GAAoB,MAAA;IAAU,QAAA;EAAA,MAA6B,OAAA;EAAA,QAiBnD,eAAA;EAAA,QA6CA,eAAA;EAAA,QA2DA,eAAA;EAAA,QA8CA,kBAAA;EAAA,QAcA,mBAAA;EAAA,QAOA,wBAAA;EAAA,QAOA,gBAAA;AAAA"}
|