@nextclaw/nextclaw-ncp-runtime-codex-sdk 0.1.0 → 0.1.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 +3 -1
- package/dist/index.js +49 -24
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CodexOptions, ThreadOptions } from '@openai/codex-sdk';
|
|
2
|
-
import { NcpAgentRuntime, NcpAgentRunInput, NcpAgentRunOptions, NcpEndpointEvent } from '@nextclaw/ncp';
|
|
2
|
+
import { NcpAgentRuntime, NcpAgentRunInput, NcpAgentConversationStateManager, NcpAgentRunOptions, NcpEndpointEvent } from '@nextclaw/ncp';
|
|
3
3
|
|
|
4
4
|
type CodexSdkNcpAgentRuntimeConfig = {
|
|
5
5
|
sessionId: string;
|
|
@@ -14,6 +14,7 @@ type CodexSdkNcpAgentRuntimeConfig = {
|
|
|
14
14
|
sessionMetadata?: Record<string, unknown>;
|
|
15
15
|
setSessionMetadata?: (nextMetadata: Record<string, unknown>) => void;
|
|
16
16
|
inputBuilder?: (input: NcpAgentRunInput) => Promise<string> | string;
|
|
17
|
+
stateManager?: NcpAgentConversationStateManager;
|
|
17
18
|
};
|
|
18
19
|
declare class CodexSdkNcpAgentRuntime implements NcpAgentRuntime {
|
|
19
20
|
private readonly config;
|
|
@@ -26,6 +27,7 @@ declare class CodexSdkNcpAgentRuntime implements NcpAgentRuntime {
|
|
|
26
27
|
private getCodex;
|
|
27
28
|
private resolveThread;
|
|
28
29
|
private buildTurnInput;
|
|
30
|
+
private emitEvent;
|
|
29
31
|
private updateThreadId;
|
|
30
32
|
}
|
|
31
33
|
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
NcpEventType
|
|
4
|
+
} from "@nextclaw/ncp";
|
|
3
5
|
import {
|
|
4
6
|
mapCodexItemEvent
|
|
5
7
|
} from "./codex-sdk-ncp-event-mapper.js";
|
|
@@ -30,6 +32,25 @@ function toAbortError(reason) {
|
|
|
30
32
|
error.name = "AbortError";
|
|
31
33
|
return error;
|
|
32
34
|
}
|
|
35
|
+
function buildCliEnv(config) {
|
|
36
|
+
const env = {
|
|
37
|
+
...config.env ?? {}
|
|
38
|
+
};
|
|
39
|
+
if (config.apiKey.trim()) {
|
|
40
|
+
env.OPENAI_API_KEY = config.apiKey;
|
|
41
|
+
}
|
|
42
|
+
if (config.apiBase?.trim()) {
|
|
43
|
+
env.OPENAI_BASE_URL = config.apiBase.trim();
|
|
44
|
+
}
|
|
45
|
+
return Object.keys(env).length > 0 ? env : void 0;
|
|
46
|
+
}
|
|
47
|
+
function normalizeThreadOptions(options, model) {
|
|
48
|
+
return {
|
|
49
|
+
...options,
|
|
50
|
+
skipGitRepoCheck: options?.skipGitRepoCheck ?? true,
|
|
51
|
+
...model ? { model } : {}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
33
54
|
class CodexSdkNcpAgentRuntime {
|
|
34
55
|
constructor(config) {
|
|
35
56
|
this.config = config;
|
|
@@ -48,15 +69,15 @@ class CodexSdkNcpAgentRuntime {
|
|
|
48
69
|
const itemTextById = /* @__PURE__ */ new Map();
|
|
49
70
|
const toolStateById = /* @__PURE__ */ new Map();
|
|
50
71
|
let finished = false;
|
|
51
|
-
yield {
|
|
72
|
+
yield* this.emitEvent({
|
|
52
73
|
type: NcpEventType.RunStarted,
|
|
53
74
|
payload: {
|
|
54
75
|
sessionId: input.sessionId,
|
|
55
76
|
messageId,
|
|
56
77
|
runId
|
|
57
78
|
}
|
|
58
|
-
};
|
|
59
|
-
yield {
|
|
79
|
+
});
|
|
80
|
+
yield* this.emitEvent({
|
|
60
81
|
type: NcpEventType.RunMetadata,
|
|
61
82
|
payload: {
|
|
62
83
|
sessionId: input.sessionId,
|
|
@@ -69,7 +90,7 @@ class CodexSdkNcpAgentRuntime {
|
|
|
69
90
|
supportsAbort: true
|
|
70
91
|
}
|
|
71
92
|
}
|
|
72
|
-
};
|
|
93
|
+
});
|
|
73
94
|
const thread = await this.resolveThread();
|
|
74
95
|
const turnInput = await this.buildTurnInput(input);
|
|
75
96
|
const streamed = await thread.runStreamed(turnInput, {
|
|
@@ -85,7 +106,7 @@ class CodexSdkNcpAgentRuntime {
|
|
|
85
106
|
continue;
|
|
86
107
|
}
|
|
87
108
|
if (event.type === "turn.failed") {
|
|
88
|
-
yield {
|
|
109
|
+
yield* this.emitEvent({
|
|
89
110
|
type: NcpEventType.RunError,
|
|
90
111
|
payload: {
|
|
91
112
|
sessionId: input.sessionId,
|
|
@@ -93,12 +114,12 @@ class CodexSdkNcpAgentRuntime {
|
|
|
93
114
|
runId,
|
|
94
115
|
error: event.error.message
|
|
95
116
|
}
|
|
96
|
-
};
|
|
117
|
+
});
|
|
97
118
|
finished = true;
|
|
98
119
|
return;
|
|
99
120
|
}
|
|
100
121
|
if (event.type === "error") {
|
|
101
|
-
yield {
|
|
122
|
+
yield* this.emitEvent({
|
|
102
123
|
type: NcpEventType.RunError,
|
|
103
124
|
payload: {
|
|
104
125
|
sessionId: input.sessionId,
|
|
@@ -106,22 +127,24 @@ class CodexSdkNcpAgentRuntime {
|
|
|
106
127
|
runId,
|
|
107
128
|
error: event.message
|
|
108
129
|
}
|
|
109
|
-
};
|
|
130
|
+
});
|
|
110
131
|
finished = true;
|
|
111
132
|
return;
|
|
112
133
|
}
|
|
113
134
|
if (event.type === "item.started" || event.type === "item.updated" || event.type === "item.completed") {
|
|
114
|
-
|
|
135
|
+
for await (const mappedEvent of mapCodexItemEvent({
|
|
115
136
|
sessionId: input.sessionId,
|
|
116
137
|
messageId,
|
|
117
138
|
event,
|
|
118
139
|
itemTextById,
|
|
119
140
|
toolStateById
|
|
120
|
-
})
|
|
141
|
+
})) {
|
|
142
|
+
yield* this.emitEvent(mappedEvent);
|
|
143
|
+
}
|
|
121
144
|
continue;
|
|
122
145
|
}
|
|
123
146
|
if (event.type === "turn.completed") {
|
|
124
|
-
yield {
|
|
147
|
+
yield* this.emitEvent({
|
|
125
148
|
type: NcpEventType.RunMetadata,
|
|
126
149
|
payload: {
|
|
127
150
|
sessionId: input.sessionId,
|
|
@@ -132,21 +155,21 @@ class CodexSdkNcpAgentRuntime {
|
|
|
132
155
|
sessionId: input.sessionId
|
|
133
156
|
}
|
|
134
157
|
}
|
|
135
|
-
};
|
|
136
|
-
yield {
|
|
158
|
+
});
|
|
159
|
+
yield* this.emitEvent({
|
|
137
160
|
type: NcpEventType.RunFinished,
|
|
138
161
|
payload: {
|
|
139
162
|
sessionId: input.sessionId,
|
|
140
163
|
messageId,
|
|
141
164
|
runId
|
|
142
165
|
}
|
|
143
|
-
};
|
|
166
|
+
});
|
|
144
167
|
finished = true;
|
|
145
168
|
return;
|
|
146
169
|
}
|
|
147
170
|
}
|
|
148
171
|
if (!finished) {
|
|
149
|
-
yield {
|
|
172
|
+
yield* this.emitEvent({
|
|
150
173
|
type: NcpEventType.RunMetadata,
|
|
151
174
|
payload: {
|
|
152
175
|
sessionId: input.sessionId,
|
|
@@ -157,15 +180,15 @@ class CodexSdkNcpAgentRuntime {
|
|
|
157
180
|
sessionId: input.sessionId
|
|
158
181
|
}
|
|
159
182
|
}
|
|
160
|
-
};
|
|
161
|
-
yield {
|
|
183
|
+
});
|
|
184
|
+
yield* this.emitEvent({
|
|
162
185
|
type: NcpEventType.RunFinished,
|
|
163
186
|
payload: {
|
|
164
187
|
sessionId: input.sessionId,
|
|
165
188
|
messageId,
|
|
166
189
|
runId
|
|
167
190
|
}
|
|
168
|
-
};
|
|
191
|
+
});
|
|
169
192
|
}
|
|
170
193
|
} catch (error) {
|
|
171
194
|
if (options?.signal?.aborted) {
|
|
@@ -176,12 +199,13 @@ class CodexSdkNcpAgentRuntime {
|
|
|
176
199
|
}
|
|
177
200
|
async getCodex() {
|
|
178
201
|
if (!this.codexPromise) {
|
|
202
|
+
const env = buildCliEnv(this.config);
|
|
179
203
|
this.codexPromise = codexLoader.loadCodexConstructor().then(
|
|
180
204
|
(Ctor) => new Ctor({
|
|
181
205
|
apiKey: this.config.apiKey,
|
|
182
206
|
baseUrl: this.config.apiBase,
|
|
183
207
|
...this.config.codexPathOverride ? { codexPathOverride: this.config.codexPathOverride } : {},
|
|
184
|
-
...
|
|
208
|
+
...env ? { env } : {},
|
|
185
209
|
...this.config.cliConfig ? { config: this.config.cliConfig } : {}
|
|
186
210
|
})
|
|
187
211
|
);
|
|
@@ -193,10 +217,7 @@ class CodexSdkNcpAgentRuntime {
|
|
|
193
217
|
return this.thread;
|
|
194
218
|
}
|
|
195
219
|
const codex = await this.getCodex();
|
|
196
|
-
const threadOptions =
|
|
197
|
-
...this.config.threadOptions,
|
|
198
|
-
...this.config.model ? { model: this.config.model } : {}
|
|
199
|
-
};
|
|
220
|
+
const threadOptions = normalizeThreadOptions(this.config.threadOptions, this.config.model);
|
|
200
221
|
this.thread = this.threadId ? codex.resumeThread(this.threadId, threadOptions) : codex.startThread(threadOptions);
|
|
201
222
|
return this.thread;
|
|
202
223
|
}
|
|
@@ -206,6 +227,10 @@ class CodexSdkNcpAgentRuntime {
|
|
|
206
227
|
}
|
|
207
228
|
return readUserText(input);
|
|
208
229
|
}
|
|
230
|
+
async *emitEvent(event) {
|
|
231
|
+
await this.config.stateManager?.dispatch(event);
|
|
232
|
+
yield event;
|
|
233
|
+
}
|
|
209
234
|
updateThreadId(nextThreadId) {
|
|
210
235
|
const normalizedThreadId = nextThreadId.trim();
|
|
211
236
|
if (!normalizedThreadId || normalizedThreadId === this.threadId) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/nextclaw-ncp-runtime-codex-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Optional NCP runtime adapter backed by OpenAI Codex SDK.",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@openai/codex-sdk": "^0.107.0",
|
|
20
|
-
"@nextclaw/ncp": "0.3.
|
|
20
|
+
"@nextclaw/ncp": "0.3.1"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node": "^20.17.6",
|