@nextclaw/nextclaw-ncp-runtime-plugin-codex-sdk 0.1.24 → 0.1.26
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 +38 -2
- package/dist/index.js +81 -104
- package/package.json +3 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Config } from '@nextclaw/core';
|
|
2
1
|
import { NcpAgentRuntime } from '@nextclaw/ncp';
|
|
3
2
|
import { RuntimeFactoryParams } from '@nextclaw/ncp-toolkit';
|
|
4
3
|
|
|
@@ -15,9 +14,45 @@ type SessionTypeDescriptor = {
|
|
|
15
14
|
} | null;
|
|
16
15
|
};
|
|
17
16
|
|
|
17
|
+
type ResolvedProviderSpec = {
|
|
18
|
+
isGateway?: boolean;
|
|
19
|
+
isLocal?: boolean;
|
|
20
|
+
supportsResponsesApi?: boolean;
|
|
21
|
+
};
|
|
22
|
+
type ResolvedProviderConfig = {
|
|
23
|
+
wireApi?: string | null;
|
|
24
|
+
extraHeaders?: Record<string, string> | null;
|
|
25
|
+
};
|
|
26
|
+
type ResolvedProviderRuntime = {
|
|
27
|
+
resolvedModel: string;
|
|
28
|
+
providerLocalModel: string;
|
|
29
|
+
provider: ResolvedProviderConfig | null;
|
|
30
|
+
providerName: string | null;
|
|
31
|
+
providerDisplayName: string | null;
|
|
32
|
+
providerSpec: ResolvedProviderSpec | null;
|
|
33
|
+
apiKey: string | null;
|
|
34
|
+
apiBase: string | null;
|
|
35
|
+
};
|
|
36
|
+
type AgentRuntimeApi = {
|
|
37
|
+
defaults: {
|
|
38
|
+
workspace?: string;
|
|
39
|
+
model?: string;
|
|
40
|
+
};
|
|
41
|
+
resolveWorkspacePath: (workspace?: string) => string;
|
|
42
|
+
resolveProviderRuntime: (model?: string) => ResolvedProviderRuntime;
|
|
43
|
+
buildRuntimeUserPrompt: (params: {
|
|
44
|
+
workspace?: string;
|
|
45
|
+
sessionKey?: string;
|
|
46
|
+
metadata?: Record<string, unknown>;
|
|
47
|
+
userMessage: string;
|
|
48
|
+
}) => string;
|
|
49
|
+
};
|
|
18
50
|
type PluginApi = {
|
|
19
|
-
config
|
|
51
|
+
config?: Record<string, unknown>;
|
|
20
52
|
pluginConfig?: Record<string, unknown>;
|
|
53
|
+
runtime: {
|
|
54
|
+
agent: AgentRuntimeApi;
|
|
55
|
+
};
|
|
21
56
|
registerNcpAgentRuntime: (registration: {
|
|
22
57
|
kind: string;
|
|
23
58
|
label?: string;
|
|
@@ -32,6 +67,7 @@ type PluginDefinition = {
|
|
|
32
67
|
configSchema: Record<string, unknown>;
|
|
33
68
|
register: (api: PluginApi) => void;
|
|
34
69
|
};
|
|
70
|
+
|
|
35
71
|
declare const plugin: PluginDefinition;
|
|
36
72
|
|
|
37
73
|
export { plugin as default };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import {
|
|
3
|
-
findProviderByModel,
|
|
4
|
-
findProviderByName,
|
|
5
|
-
resolveProviderRuntime,
|
|
6
|
-
getWorkspacePath
|
|
7
|
-
} from "@nextclaw/core";
|
|
8
2
|
import {
|
|
9
3
|
CodexSdkNcpAgentRuntime
|
|
10
4
|
} from "@nextclaw/nextclaw-ncp-runtime-codex-sdk";
|
|
@@ -97,24 +91,6 @@ function resolveCodexAccessMode(pluginConfig) {
|
|
|
97
91
|
}
|
|
98
92
|
|
|
99
93
|
// src/codex-input-builder.ts
|
|
100
|
-
import {
|
|
101
|
-
buildRequestedSkillsUserPrompt,
|
|
102
|
-
SkillsLoader
|
|
103
|
-
} from "@nextclaw/core";
|
|
104
|
-
function readString(value) {
|
|
105
|
-
if (typeof value !== "string") {
|
|
106
|
-
return void 0;
|
|
107
|
-
}
|
|
108
|
-
const trimmed = value.trim();
|
|
109
|
-
return trimmed || void 0;
|
|
110
|
-
}
|
|
111
|
-
function readRequestedSkills(metadata) {
|
|
112
|
-
const raw = metadata.requested_skills ?? metadata.requestedSkills;
|
|
113
|
-
if (!Array.isArray(raw)) {
|
|
114
|
-
return [];
|
|
115
|
-
}
|
|
116
|
-
return raw.map((entry) => readString(entry)).filter((entry) => Boolean(entry)).slice(0, 8);
|
|
117
|
-
}
|
|
118
94
|
function readUserText(input) {
|
|
119
95
|
for (let index = input.messages.length - 1; index >= 0; index -= 1) {
|
|
120
96
|
const message = input.messages[index];
|
|
@@ -128,13 +104,16 @@ function readUserText(input) {
|
|
|
128
104
|
}
|
|
129
105
|
return "";
|
|
130
106
|
}
|
|
131
|
-
function buildCodexInputBuilder(workspace) {
|
|
132
|
-
const skillsLoader = new SkillsLoader(workspace);
|
|
107
|
+
function buildCodexInputBuilder(runtimeAgent, workspace) {
|
|
133
108
|
return async (input) => {
|
|
134
109
|
const userText = readUserText(input);
|
|
135
110
|
const metadata = input.metadata && typeof input.metadata === "object" && !Array.isArray(input.metadata) ? input.metadata : {};
|
|
136
|
-
|
|
137
|
-
|
|
111
|
+
return runtimeAgent.buildRuntimeUserPrompt({
|
|
112
|
+
workspace,
|
|
113
|
+
sessionKey: input.sessionId,
|
|
114
|
+
metadata,
|
|
115
|
+
userMessage: userText
|
|
116
|
+
});
|
|
138
117
|
};
|
|
139
118
|
}
|
|
140
119
|
|
|
@@ -143,7 +122,7 @@ import { randomUUID } from "crypto";
|
|
|
143
122
|
import { createServer } from "http";
|
|
144
123
|
|
|
145
124
|
// src/codex-openai-responses-bridge-shared.ts
|
|
146
|
-
function
|
|
125
|
+
function readString(value) {
|
|
147
126
|
if (typeof value !== "string") {
|
|
148
127
|
return void 0;
|
|
149
128
|
}
|
|
@@ -201,7 +180,7 @@ function stripModelPrefix(model, prefixes) {
|
|
|
201
180
|
}
|
|
202
181
|
function resolveUpstreamModel(requestedModel, config) {
|
|
203
182
|
const prefixes = (config.modelPrefixes ?? []).filter((value) => value.trim().length > 0);
|
|
204
|
-
const model = stripModelPrefix(
|
|
183
|
+
const model = stripModelPrefix(readString(requestedModel) ?? "", prefixes) || stripModelPrefix(config.defaultModel ?? "", prefixes);
|
|
205
184
|
if (!model) {
|
|
206
185
|
throw new Error("Codex bridge could not resolve an upstream model.");
|
|
207
186
|
}
|
|
@@ -212,27 +191,27 @@ function normalizeTextPart(value) {
|
|
|
212
191
|
if (!record) {
|
|
213
192
|
return "";
|
|
214
193
|
}
|
|
215
|
-
const type =
|
|
194
|
+
const type = readString(record.type);
|
|
216
195
|
if (type !== "input_text" && type !== "output_text") {
|
|
217
196
|
return "";
|
|
218
197
|
}
|
|
219
|
-
return
|
|
198
|
+
return readString(record.text) ?? "";
|
|
220
199
|
}
|
|
221
200
|
function normalizeImageUrl(value) {
|
|
222
201
|
const record = readRecord(value);
|
|
223
|
-
if (!record ||
|
|
202
|
+
if (!record || readString(record.type) !== "input_image") {
|
|
224
203
|
return null;
|
|
225
204
|
}
|
|
226
205
|
const source = readRecord(record.source);
|
|
227
206
|
if (!source) {
|
|
228
207
|
return null;
|
|
229
208
|
}
|
|
230
|
-
if (
|
|
231
|
-
return
|
|
209
|
+
if (readString(source.type) === "url") {
|
|
210
|
+
return readString(source.url) ?? null;
|
|
232
211
|
}
|
|
233
|
-
if (
|
|
234
|
-
const mediaType =
|
|
235
|
-
const data =
|
|
212
|
+
if (readString(source.type) === "base64") {
|
|
213
|
+
const mediaType = readString(source.media_type) ?? "application/octet-stream";
|
|
214
|
+
const data = readString(source.data);
|
|
236
215
|
if (!data) {
|
|
237
216
|
return null;
|
|
238
217
|
}
|
|
@@ -288,7 +267,7 @@ function buildChatContent(content) {
|
|
|
288
267
|
}
|
|
289
268
|
const textOnly = chatContent.every((entry) => entry.type === "text");
|
|
290
269
|
if (textOnly) {
|
|
291
|
-
return chatContent.map((entry) =>
|
|
270
|
+
return chatContent.map((entry) => readString(entry.text) ?? "").join("\n");
|
|
292
271
|
}
|
|
293
272
|
return chatContent;
|
|
294
273
|
}
|
|
@@ -299,10 +278,10 @@ function readAssistantMessageText(content) {
|
|
|
299
278
|
if (!Array.isArray(content)) {
|
|
300
279
|
return "";
|
|
301
280
|
}
|
|
302
|
-
return content.filter((entry) => entry.type === "text").map((entry) =>
|
|
281
|
+
return content.filter((entry) => entry.type === "text").map((entry) => readString(entry.text) ?? "").join("\n");
|
|
303
282
|
}
|
|
304
283
|
function appendMessageInputItem(params) {
|
|
305
|
-
const role =
|
|
284
|
+
const role = readString(params.item.role);
|
|
306
285
|
const content = buildChatContent(params.item.content);
|
|
307
286
|
if (role === "assistant") {
|
|
308
287
|
const text = readAssistantMessageText(content);
|
|
@@ -321,12 +300,12 @@ function appendMessageInputItem(params) {
|
|
|
321
300
|
}
|
|
322
301
|
}
|
|
323
302
|
function appendFunctionCallItem(params) {
|
|
324
|
-
const name =
|
|
325
|
-
const argumentsText =
|
|
303
|
+
const name = readString(params.item.name);
|
|
304
|
+
const argumentsText = readString(params.item.arguments) ?? "{}";
|
|
326
305
|
if (!name) {
|
|
327
306
|
return;
|
|
328
307
|
}
|
|
329
|
-
const callId =
|
|
308
|
+
const callId = readString(params.item.call_id) ?? readString(params.item.id) ?? `call_${params.assistantToolCalls.length}`;
|
|
330
309
|
params.assistantToolCalls.push({
|
|
331
310
|
id: callId,
|
|
332
311
|
type: "function",
|
|
@@ -338,7 +317,7 @@ function appendFunctionCallItem(params) {
|
|
|
338
317
|
}
|
|
339
318
|
function appendFunctionCallOutputItem(params) {
|
|
340
319
|
params.flushAssistant();
|
|
341
|
-
const callId =
|
|
320
|
+
const callId = readString(params.item.call_id);
|
|
342
321
|
if (!callId) {
|
|
343
322
|
return;
|
|
344
323
|
}
|
|
@@ -350,7 +329,7 @@ function appendFunctionCallOutputItem(params) {
|
|
|
350
329
|
}
|
|
351
330
|
function buildOpenAiMessages(input, instructions) {
|
|
352
331
|
const messages = [];
|
|
353
|
-
const instructionText =
|
|
332
|
+
const instructionText = readString(instructions);
|
|
354
333
|
if (instructionText) {
|
|
355
334
|
messages.push({
|
|
356
335
|
role: "system",
|
|
@@ -387,7 +366,7 @@ function buildOpenAiMessages(input, instructions) {
|
|
|
387
366
|
if (!item) {
|
|
388
367
|
continue;
|
|
389
368
|
}
|
|
390
|
-
const type =
|
|
369
|
+
const type = readString(item.type);
|
|
391
370
|
if (type === "message") {
|
|
392
371
|
appendMessageInputItem({
|
|
393
372
|
messages,
|
|
@@ -420,13 +399,13 @@ function toOpenAiTools(value) {
|
|
|
420
399
|
const tools = [];
|
|
421
400
|
for (const entry of readArray(value)) {
|
|
422
401
|
const tool = readRecord(entry);
|
|
423
|
-
const type =
|
|
402
|
+
const type = readString(tool?.type);
|
|
424
403
|
const fn = readRecord(tool?.function);
|
|
425
|
-
const name =
|
|
404
|
+
const name = readString(fn?.name) ?? readString(tool?.name);
|
|
426
405
|
if (type !== "function" || !name) {
|
|
427
406
|
continue;
|
|
428
407
|
}
|
|
429
|
-
const description = (fn ?
|
|
408
|
+
const description = (fn ? readString(fn.description) : void 0) ?? readString(tool?.description);
|
|
430
409
|
const parameters = (fn ? readRecord(fn.parameters) : void 0) ?? readRecord(tool?.parameters);
|
|
431
410
|
const strict = (fn ? readBoolean(fn.strict) : void 0) ?? readBoolean(tool?.strict);
|
|
432
411
|
tools.push({
|
|
@@ -450,8 +429,8 @@ function toOpenAiToolChoice(value) {
|
|
|
450
429
|
}
|
|
451
430
|
const record = readRecord(value);
|
|
452
431
|
const fn = readRecord(record?.function);
|
|
453
|
-
const name =
|
|
454
|
-
if (
|
|
432
|
+
const name = readString(fn?.name) ?? readString(record?.name);
|
|
433
|
+
if (readString(record?.type) === "function" && name) {
|
|
455
434
|
return {
|
|
456
435
|
type: "function",
|
|
457
436
|
function: {
|
|
@@ -500,7 +479,7 @@ async function callOpenAiCompatibleUpstream(params) {
|
|
|
500
479
|
}
|
|
501
480
|
if (!upstreamResponse.ok) {
|
|
502
481
|
throw new Error(
|
|
503
|
-
|
|
482
|
+
readString(parsed.error?.message) ?? rawText.slice(0, 240) ?? `HTTP ${upstreamResponse.status}`
|
|
504
483
|
);
|
|
505
484
|
}
|
|
506
485
|
return {
|
|
@@ -522,9 +501,9 @@ function extractAssistantText(content) {
|
|
|
522
501
|
if (!record) {
|
|
523
502
|
return "";
|
|
524
503
|
}
|
|
525
|
-
const type =
|
|
504
|
+
const type = readString(record.type);
|
|
526
505
|
if (type === "text" || type === "output_text") {
|
|
527
|
-
return
|
|
506
|
+
return readString(record.text) ?? "";
|
|
528
507
|
}
|
|
529
508
|
return "";
|
|
530
509
|
}).filter(Boolean).join("");
|
|
@@ -555,12 +534,12 @@ function buildOpenResponsesOutputItems(response, responseId) {
|
|
|
555
534
|
toolCalls.forEach((entry, index) => {
|
|
556
535
|
const toolCall = readRecord(entry);
|
|
557
536
|
const fn = readRecord(toolCall?.function);
|
|
558
|
-
const name =
|
|
559
|
-
const argumentsText =
|
|
537
|
+
const name = readString(fn?.name);
|
|
538
|
+
const argumentsText = readString(fn?.arguments) ?? "{}";
|
|
560
539
|
if (!name) {
|
|
561
540
|
return;
|
|
562
541
|
}
|
|
563
|
-
const callId =
|
|
542
|
+
const callId = readString(toolCall?.id) ?? `${responseId}:call:${index}`;
|
|
564
543
|
outputItems.push({
|
|
565
544
|
type: "function_call",
|
|
566
545
|
id: `${responseId}:function:${index}`,
|
|
@@ -606,7 +585,7 @@ function cloneRecord(value) {
|
|
|
606
585
|
return structuredClone(value);
|
|
607
586
|
}
|
|
608
587
|
function buildInProgressOutputItem(item) {
|
|
609
|
-
const type =
|
|
588
|
+
const type = readString(item.type);
|
|
610
589
|
if (type === "message") {
|
|
611
590
|
return {
|
|
612
591
|
...cloneRecord(item),
|
|
@@ -624,10 +603,10 @@ function buildInProgressOutputItem(item) {
|
|
|
624
603
|
return cloneRecord(item);
|
|
625
604
|
}
|
|
626
605
|
function writeMessageOutputItemEvents(params) {
|
|
627
|
-
const itemId =
|
|
606
|
+
const itemId = readString(params.item.id);
|
|
628
607
|
const content = readArray(params.item.content);
|
|
629
|
-
const textPart = content.find((entry) =>
|
|
630
|
-
const text =
|
|
608
|
+
const textPart = content.find((entry) => readString(readRecord(entry)?.type) === "output_text");
|
|
609
|
+
const text = readString(readRecord(textPart)?.text) ?? "";
|
|
631
610
|
writeSseEvent(params.response, "response.output_item.added", {
|
|
632
611
|
type: "response.output_item.added",
|
|
633
612
|
sequence_number: nextSequenceNumber(params.sequenceState),
|
|
@@ -686,8 +665,8 @@ function writeMessageOutputItemEvents(params) {
|
|
|
686
665
|
});
|
|
687
666
|
}
|
|
688
667
|
function writeFunctionCallOutputItemEvents(params) {
|
|
689
|
-
const itemId =
|
|
690
|
-
const argumentsText =
|
|
668
|
+
const itemId = readString(params.item.id);
|
|
669
|
+
const argumentsText = readString(params.item.arguments) ?? "";
|
|
691
670
|
writeSseEvent(params.response, "response.output_item.added", {
|
|
692
671
|
type: "response.output_item.added",
|
|
693
672
|
sequence_number: nextSequenceNumber(params.sequenceState),
|
|
@@ -721,7 +700,7 @@ function writeFunctionCallOutputItemEvents(params) {
|
|
|
721
700
|
}
|
|
722
701
|
function writeResponseOutputItemEvents(params) {
|
|
723
702
|
params.outputItems.forEach((item, outputIndex) => {
|
|
724
|
-
const type =
|
|
703
|
+
const type = readString(item.type);
|
|
725
704
|
if (type === "message") {
|
|
726
705
|
writeMessageOutputItemEvents({
|
|
727
706
|
response: params.response,
|
|
@@ -950,7 +929,7 @@ function readErrorMessage(value) {
|
|
|
950
929
|
return "";
|
|
951
930
|
}
|
|
952
931
|
const record = value;
|
|
953
|
-
return
|
|
932
|
+
return readString(record.message) ?? readString(record.error) ?? "";
|
|
954
933
|
}
|
|
955
934
|
function shouldTreatResponsesProbeFailureAsUnsupported(params) {
|
|
956
935
|
const normalizedMessage = params.message.trim().toLowerCase();
|
|
@@ -1005,7 +984,7 @@ async function probeCodexResponsesApiSupport(params) {
|
|
|
1005
984
|
}
|
|
1006
985
|
const parsedRecord = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
1007
986
|
const message = readErrorMessage(parsedRecord?.error) || readErrorMessage(parsed) || rawText.slice(0, 240);
|
|
1008
|
-
const responseFailed =
|
|
987
|
+
const responseFailed = readString(parsedRecord?.status)?.toLowerCase() === "failed" || Boolean(parsedRecord?.error);
|
|
1009
988
|
if (response.ok && !responseFailed) {
|
|
1010
989
|
return true;
|
|
1011
990
|
}
|
|
@@ -1029,7 +1008,7 @@ async function resolveCodexResponsesApiSupport(params) {
|
|
|
1029
1008
|
if (params.capabilitySpec?.supportsResponsesApi === false) {
|
|
1030
1009
|
return false;
|
|
1031
1010
|
}
|
|
1032
|
-
const explicitWireApi =
|
|
1011
|
+
const explicitWireApi = readString(params.wireApi)?.toLowerCase();
|
|
1033
1012
|
if (explicitWireApi === "chat") {
|
|
1034
1013
|
return false;
|
|
1035
1014
|
}
|
|
@@ -1045,7 +1024,7 @@ async function resolveCodexResponsesApiSupport(params) {
|
|
|
1045
1024
|
}
|
|
1046
1025
|
|
|
1047
1026
|
// src/codex-session-type.ts
|
|
1048
|
-
function
|
|
1027
|
+
function readString2(value) {
|
|
1049
1028
|
if (typeof value !== "string") {
|
|
1050
1029
|
return void 0;
|
|
1051
1030
|
}
|
|
@@ -1056,7 +1035,7 @@ function readStringArray(value) {
|
|
|
1056
1035
|
if (!Array.isArray(value)) {
|
|
1057
1036
|
return void 0;
|
|
1058
1037
|
}
|
|
1059
|
-
const values = value.map((entry) =>
|
|
1038
|
+
const values = value.map((entry) => readString2(entry)).filter((entry) => Boolean(entry));
|
|
1060
1039
|
return values.length > 0 ? values : void 0;
|
|
1061
1040
|
}
|
|
1062
1041
|
function dedupeStrings(values) {
|
|
@@ -1074,7 +1053,10 @@ function resolveConfiguredCodexModels(pluginConfig) {
|
|
|
1074
1053
|
return normalizedModels;
|
|
1075
1054
|
}
|
|
1076
1055
|
function resolveRecommendedCodexModel(params) {
|
|
1077
|
-
const configuredModel =
|
|
1056
|
+
const configuredModel = readString2(params.pluginConfig.model) ?? params.defaultModel;
|
|
1057
|
+
if (!configuredModel) {
|
|
1058
|
+
return params.supportedModels?.[0] ?? null;
|
|
1059
|
+
}
|
|
1078
1060
|
if (!params.supportedModels || params.supportedModels.includes(configuredModel)) {
|
|
1079
1061
|
return configuredModel;
|
|
1080
1062
|
}
|
|
@@ -1088,7 +1070,7 @@ function createDescribeCodexSessionType(params) {
|
|
|
1088
1070
|
reason: null,
|
|
1089
1071
|
reasonMessage: null,
|
|
1090
1072
|
recommendedModel: resolveRecommendedCodexModel({
|
|
1091
|
-
|
|
1073
|
+
defaultModel: params.defaultModel,
|
|
1092
1074
|
pluginConfig: params.pluginConfig,
|
|
1093
1075
|
supportedModels
|
|
1094
1076
|
}),
|
|
@@ -1123,7 +1105,7 @@ var DeferredCodexSdkNcpAgentRuntime = class {
|
|
|
1123
1105
|
return stream();
|
|
1124
1106
|
}
|
|
1125
1107
|
};
|
|
1126
|
-
function
|
|
1108
|
+
function readString3(value) {
|
|
1127
1109
|
if (typeof value !== "string") {
|
|
1128
1110
|
return void 0;
|
|
1129
1111
|
}
|
|
@@ -1143,14 +1125,9 @@ function readStringArray2(value) {
|
|
|
1143
1125
|
if (!Array.isArray(value)) {
|
|
1144
1126
|
return void 0;
|
|
1145
1127
|
}
|
|
1146
|
-
const values = value.map((entry) =>
|
|
1128
|
+
const values = value.map((entry) => readString3(entry)).filter((entry) => Boolean(entry));
|
|
1147
1129
|
return values.length > 0 ? values : void 0;
|
|
1148
1130
|
}
|
|
1149
|
-
function resolveCodexCapabilitySpec(params) {
|
|
1150
|
-
const providerSpec = params.providerName ? findProviderByName(params.providerName) : void 0;
|
|
1151
|
-
const modelSpec = params.model ? findProviderByModel(params.model) : void 0;
|
|
1152
|
-
return providerSpec?.isGateway ? modelSpec ?? providerSpec : providerSpec ?? modelSpec;
|
|
1153
|
-
}
|
|
1154
1131
|
function readStringRecord(value) {
|
|
1155
1132
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1156
1133
|
return void 0;
|
|
@@ -1179,9 +1156,9 @@ function readThinkingLevel(value) {
|
|
|
1179
1156
|
return void 0;
|
|
1180
1157
|
}
|
|
1181
1158
|
function resolveCodexExecutionOptions(params) {
|
|
1182
|
-
const configuredWorkingDirectory =
|
|
1183
|
-
const workspace =
|
|
1184
|
-
configuredWorkingDirectory ?? params.
|
|
1159
|
+
const configuredWorkingDirectory = readString3(params.pluginConfig.workingDirectory);
|
|
1160
|
+
const workspace = params.runtimeAgent.resolveWorkspacePath(
|
|
1161
|
+
configuredWorkingDirectory ?? params.runtimeAgent.defaults.workspace
|
|
1185
1162
|
);
|
|
1186
1163
|
return {
|
|
1187
1164
|
workingDirectory: workspace,
|
|
@@ -1190,14 +1167,14 @@ function resolveCodexExecutionOptions(params) {
|
|
|
1190
1167
|
}
|
|
1191
1168
|
function resolveCodexCliConfig(params) {
|
|
1192
1169
|
const explicitConfig = readRecord2(params.pluginConfig.config);
|
|
1193
|
-
const modelProvider =
|
|
1170
|
+
const modelProvider = readString3(params.modelProviderOverride) ?? resolveExternalModelProvider({
|
|
1194
1171
|
explicitModelProvider: params.pluginConfig.modelProvider,
|
|
1195
1172
|
providerName: params.providerName,
|
|
1196
1173
|
providerDisplayName: params.providerDisplayName,
|
|
1197
1174
|
pluginId: PLUGIN_ID
|
|
1198
1175
|
});
|
|
1199
|
-
const preferredAuthMethod =
|
|
1200
|
-
const apiBase =
|
|
1176
|
+
const preferredAuthMethod = readString3(params.pluginConfig.preferredAuthMethod) ?? "apikey";
|
|
1177
|
+
const apiBase = readString3(params.pluginConfig.apiBase) ?? readString3(params.apiBase);
|
|
1201
1178
|
const config = {
|
|
1202
1179
|
model_provider: modelProvider,
|
|
1203
1180
|
preferred_auth_method: preferredAuthMethod
|
|
@@ -1218,7 +1195,7 @@ function resolveCodexCliConfig(params) {
|
|
|
1218
1195
|
};
|
|
1219
1196
|
}
|
|
1220
1197
|
function resolveCodexModel(params) {
|
|
1221
|
-
return
|
|
1198
|
+
return readString3(params.sessionMetadata.preferred_model) ?? readString3(params.sessionMetadata.model) ?? readString3(params.pluginConfig.model) ?? params.runtimeAgent.defaults.model ?? "";
|
|
1222
1199
|
}
|
|
1223
1200
|
var plugin = {
|
|
1224
1201
|
id: PLUGIN_ID,
|
|
@@ -1232,7 +1209,7 @@ var plugin = {
|
|
|
1232
1209
|
register(api) {
|
|
1233
1210
|
const pluginConfig = readRecord2(api.pluginConfig) ?? {};
|
|
1234
1211
|
const describeCodexSessionType = createDescribeCodexSessionType({
|
|
1235
|
-
|
|
1212
|
+
defaultModel: readString3(api.runtime.agent.defaults.model),
|
|
1236
1213
|
pluginConfig
|
|
1237
1214
|
});
|
|
1238
1215
|
api.registerNcpAgentRuntime({
|
|
@@ -1241,22 +1218,19 @@ var plugin = {
|
|
|
1241
1218
|
describeSessionType: describeCodexSessionType,
|
|
1242
1219
|
createRuntime: (runtimeParams) => {
|
|
1243
1220
|
return new DeferredCodexSdkNcpAgentRuntime(async () => {
|
|
1244
|
-
const nextConfig = api.config;
|
|
1245
1221
|
const model = resolveCodexModel({
|
|
1246
|
-
|
|
1222
|
+
runtimeAgent: api.runtime.agent,
|
|
1247
1223
|
pluginConfig,
|
|
1248
1224
|
sessionMetadata: runtimeParams.sessionMetadata
|
|
1249
1225
|
});
|
|
1250
|
-
const resolvedProviderRuntime = resolveProviderRuntime(
|
|
1226
|
+
const resolvedProviderRuntime = api.runtime.agent.resolveProviderRuntime(model);
|
|
1251
1227
|
const providerName = resolvedProviderRuntime.providerName;
|
|
1252
|
-
const capabilitySpec =
|
|
1253
|
-
|
|
1254
|
-
providerName
|
|
1255
|
-
});
|
|
1228
|
+
const capabilitySpec = resolvedProviderRuntime.providerSpec ?? null;
|
|
1229
|
+
const providerDisplayName = resolvedProviderRuntime.providerDisplayName;
|
|
1256
1230
|
const externalModelProvider = resolveExternalModelProvider({
|
|
1257
1231
|
explicitModelProvider: pluginConfig.modelProvider,
|
|
1258
1232
|
providerName,
|
|
1259
|
-
providerDisplayName
|
|
1233
|
+
providerDisplayName,
|
|
1260
1234
|
pluginId: PLUGIN_ID
|
|
1261
1235
|
});
|
|
1262
1236
|
const userFacingModelRoute = buildUserFacingModelRoute({
|
|
@@ -1264,8 +1238,8 @@ var plugin = {
|
|
|
1264
1238
|
providerLocalModel: resolvedProviderRuntime.providerLocalModel,
|
|
1265
1239
|
resolvedModel: resolvedProviderRuntime.resolvedModel
|
|
1266
1240
|
});
|
|
1267
|
-
const upstreamApiBase =
|
|
1268
|
-
const apiKey =
|
|
1241
|
+
const upstreamApiBase = readString3(pluginConfig.apiBase) ?? resolvedProviderRuntime.apiBase ?? void 0;
|
|
1242
|
+
const apiKey = readString3(pluginConfig.apiKey) ?? resolvedProviderRuntime.apiKey ?? void 0;
|
|
1269
1243
|
if (!apiKey) {
|
|
1270
1244
|
throw new Error(
|
|
1271
1245
|
`[codex] missing apiKey. Set plugins.entries.${PLUGIN_ID}.config.apiKey or providers.*.apiKey for model "${userFacingModelRoute}".`
|
|
@@ -1280,7 +1254,7 @@ var plugin = {
|
|
|
1280
1254
|
let codexModelProviderOverride;
|
|
1281
1255
|
const supportsResponsesApi = await resolveCodexResponsesApiSupport({
|
|
1282
1256
|
capabilitySpec,
|
|
1283
|
-
wireApi:
|
|
1257
|
+
wireApi: readString3(resolvedProviderRuntime.provider?.wireApi),
|
|
1284
1258
|
apiBase: upstreamApiBase,
|
|
1285
1259
|
apiKey,
|
|
1286
1260
|
extraHeaders: resolvedProviderRuntime.provider?.extraHeaders ?? null,
|
|
@@ -1304,7 +1278,7 @@ var plugin = {
|
|
|
1304
1278
|
);
|
|
1305
1279
|
}
|
|
1306
1280
|
const executionOptions = resolveCodexExecutionOptions({
|
|
1307
|
-
|
|
1281
|
+
runtimeAgent: api.runtime.agent,
|
|
1308
1282
|
pluginConfig
|
|
1309
1283
|
});
|
|
1310
1284
|
const accessMode = resolveCodexAccessMode(pluginConfig);
|
|
@@ -1314,20 +1288,23 @@ var plugin = {
|
|
|
1314
1288
|
apiKey,
|
|
1315
1289
|
apiBase: codexApiBase,
|
|
1316
1290
|
model: resolvedProviderRuntime.providerLocalModel,
|
|
1317
|
-
threadId:
|
|
1318
|
-
codexPathOverride:
|
|
1291
|
+
threadId: readString3(runtimeParams.sessionMetadata.codex_thread_id) ?? null,
|
|
1292
|
+
codexPathOverride: readString3(pluginConfig.codexPathOverride),
|
|
1319
1293
|
env: readStringRecord(pluginConfig.env),
|
|
1320
1294
|
cliConfig: resolveCodexCliConfig({
|
|
1321
1295
|
pluginConfig,
|
|
1322
1296
|
providerName,
|
|
1323
|
-
providerDisplayName
|
|
1297
|
+
providerDisplayName,
|
|
1324
1298
|
apiBase: codexApiBase,
|
|
1325
1299
|
modelProviderOverride: codexModelProviderOverride
|
|
1326
1300
|
}),
|
|
1327
1301
|
stateManager: runtimeParams.stateManager,
|
|
1328
1302
|
sessionMetadata: runtimeParams.sessionMetadata,
|
|
1329
1303
|
setSessionMetadata: runtimeParams.setSessionMetadata,
|
|
1330
|
-
inputBuilder: buildCodexInputBuilder(
|
|
1304
|
+
inputBuilder: buildCodexInputBuilder(
|
|
1305
|
+
api.runtime.agent,
|
|
1306
|
+
executionOptions.workingDirectory
|
|
1307
|
+
),
|
|
1331
1308
|
threadOptions: {
|
|
1332
1309
|
model,
|
|
1333
1310
|
sandboxMode: mapAccessModeToSandboxMode(accessMode),
|
|
@@ -1335,7 +1312,7 @@ var plugin = {
|
|
|
1335
1312
|
skipGitRepoCheck: executionOptions.skipGitRepoCheck,
|
|
1336
1313
|
modelReasoningEffort: thinkingLevel,
|
|
1337
1314
|
networkAccessEnabled: readBoolean2(pluginConfig.networkAccessEnabled),
|
|
1338
|
-
webSearchMode:
|
|
1315
|
+
webSearchMode: readString3(pluginConfig.webSearchMode),
|
|
1339
1316
|
webSearchEnabled: readBoolean2(pluginConfig.webSearchEnabled),
|
|
1340
1317
|
approvalPolicy: CODEX_APPROVAL_POLICY,
|
|
1341
1318
|
additionalDirectories: readStringArray2(pluginConfig.additionalDirectories)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/nextclaw-ncp-runtime-plugin-codex-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.26",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "NextClaw plugin that registers Codex SDK as an optional NCP runtime.",
|
|
6
6
|
"type": "module",
|
|
@@ -21,10 +21,9 @@
|
|
|
21
21
|
]
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@nextclaw/core": "0.11.2",
|
|
25
|
-
"@nextclaw/ncp": "0.4.0",
|
|
26
24
|
"@nextclaw/ncp-toolkit": "0.4.4",
|
|
27
|
-
"@nextclaw/nextclaw-ncp-runtime-codex-sdk": "0.1.5"
|
|
25
|
+
"@nextclaw/nextclaw-ncp-runtime-codex-sdk": "0.1.5",
|
|
26
|
+
"@nextclaw/ncp": "0.4.0"
|
|
28
27
|
},
|
|
29
28
|
"devDependencies": {
|
|
30
29
|
"@types/node": "^20.17.6",
|