@nextclaw/nextclaw-ncp-runtime-plugin-codex-sdk 0.1.7 → 0.1.8

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.
@@ -0,0 +1,13 @@
1
+ declare function resolveExternalModelProvider(params: {
2
+ explicitModelProvider?: unknown;
3
+ providerName?: string | null;
4
+ providerDisplayName?: string | null;
5
+ pluginId: string;
6
+ }): string;
7
+ declare function buildUserFacingModelRoute(params: {
8
+ externalModelProvider: string;
9
+ providerLocalModel: string;
10
+ resolvedModel: string;
11
+ }): string;
12
+
13
+ export { buildUserFacingModelRoute, resolveExternalModelProvider };
@@ -0,0 +1,38 @@
1
+ function readOptionalString(value) {
2
+ if (typeof value !== "string") {
3
+ return void 0;
4
+ }
5
+ const trimmed = value.trim();
6
+ return trimmed || void 0;
7
+ }
8
+ function isValidExternalModelProvider(value) {
9
+ return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(value);
10
+ }
11
+ function resolveExternalModelProvider(params) {
12
+ const explicitModelProvider = readOptionalString(params.explicitModelProvider);
13
+ if (explicitModelProvider) {
14
+ return explicitModelProvider;
15
+ }
16
+ const providerName = readOptionalString(params.providerName);
17
+ if (providerName && !providerName.startsWith("custom-")) {
18
+ return providerName;
19
+ }
20
+ const providerDisplayName = readOptionalString(params.providerDisplayName);
21
+ if (providerDisplayName && isValidExternalModelProvider(providerDisplayName)) {
22
+ return providerDisplayName;
23
+ }
24
+ throw new Error(
25
+ `[codex] custom provider "${providerName ?? "unknown"}" requires an external model provider id. Set plugins.entries.${params.pluginId}.config.modelProvider or use a provider display name with only letters, numbers, ".", "_" or "-".`
26
+ );
27
+ }
28
+ function buildUserFacingModelRoute(params) {
29
+ const providerLocalModel = params.providerLocalModel.trim();
30
+ if (!providerLocalModel) {
31
+ return params.resolvedModel.trim();
32
+ }
33
+ return `${params.externalModelProvider}/${providerLocalModel}`;
34
+ }
35
+ export {
36
+ buildUserFacingModelRoute,
37
+ resolveExternalModelProvider
38
+ };
package/dist/index.js CHANGED
@@ -1,16 +1,18 @@
1
1
  import {
2
2
  findProviderByModel,
3
3
  findProviderByName,
4
- getApiBase,
5
4
  buildRequestedSkillsUserPrompt,
6
- getProvider,
7
- getProviderName,
5
+ resolveProviderRuntime,
8
6
  getWorkspacePath,
9
7
  SkillsLoader
10
8
  } from "@nextclaw/core";
11
9
  import {
12
10
  CodexSdkNcpAgentRuntime
13
11
  } from "@nextclaw/nextclaw-ncp-runtime-codex-sdk";
12
+ import {
13
+ buildUserFacingModelRoute,
14
+ resolveExternalModelProvider
15
+ } from "./codex-model-provider.js";
14
16
  const PLUGIN_ID = "nextclaw-ncp-runtime-plugin-codex-sdk";
15
17
  const CODEX_RUNTIME_KIND = "codex";
16
18
  function readString(value) {
@@ -80,7 +82,12 @@ function resolveCodexExecutionOptions(params) {
80
82
  }
81
83
  function resolveCodexCliConfig(params) {
82
84
  const explicitConfig = readRecord(params.pluginConfig.config);
83
- const modelProvider = readString(params.pluginConfig.modelProvider) ?? readString(params.providerName) ?? "openai";
85
+ const modelProvider = resolveExternalModelProvider({
86
+ explicitModelProvider: params.pluginConfig.modelProvider,
87
+ providerName: params.providerName,
88
+ providerDisplayName: params.providerDisplayName,
89
+ pluginId: PLUGIN_ID
90
+ });
84
91
  const preferredAuthMethod = readString(params.pluginConfig.preferredAuthMethod) ?? "apikey";
85
92
  const apiBase = readString(params.pluginConfig.apiBase) ?? readString(params.apiBase);
86
93
  const config = {
@@ -102,18 +109,6 @@ function resolveCodexCliConfig(params) {
102
109
  ...explicitConfig ?? {}
103
110
  };
104
111
  }
105
- function stripProviderPrefix(model, providerName) {
106
- const normalizedModel = model.trim();
107
- const normalizedProvider = providerName?.trim().toLowerCase();
108
- if (!normalizedModel || !normalizedProvider) {
109
- return normalizedModel;
110
- }
111
- const prefix = `${normalizedProvider}/`;
112
- if (!normalizedModel.toLowerCase().startsWith(prefix)) {
113
- return normalizedModel;
114
- }
115
- return normalizedModel.slice(prefix.length);
116
- }
117
112
  function readRequestedSkills(metadata) {
118
113
  const raw = metadata.requested_skills ?? metadata.requestedSkills;
119
114
  if (!Array.isArray(raw)) {
@@ -167,23 +162,34 @@ const plugin = {
167
162
  pluginConfig,
168
163
  sessionMetadata: runtimeParams.sessionMetadata
169
164
  });
170
- const provider = getProvider(nextConfig, model);
171
- const providerName = getProviderName(nextConfig, model);
165
+ const resolvedProviderRuntime = resolveProviderRuntime(nextConfig, model);
166
+ const providerName = resolvedProviderRuntime.providerName;
172
167
  const capabilitySpec = resolveCodexCapabilitySpec({
173
168
  model,
174
169
  providerName
175
170
  });
176
- const apiBase = readString(pluginConfig.apiBase) ?? getApiBase(nextConfig, model) ?? void 0;
177
- const apiKey = readString(pluginConfig.apiKey) ?? provider?.apiKey ?? void 0;
171
+ const externalModelProvider = resolveExternalModelProvider({
172
+ explicitModelProvider: pluginConfig.modelProvider,
173
+ providerName,
174
+ providerDisplayName: resolvedProviderRuntime.providerDisplayName,
175
+ pluginId: PLUGIN_ID
176
+ });
177
+ const userFacingModelRoute = buildUserFacingModelRoute({
178
+ externalModelProvider,
179
+ providerLocalModel: resolvedProviderRuntime.providerLocalModel,
180
+ resolvedModel: resolvedProviderRuntime.resolvedModel
181
+ });
182
+ const apiBase = readString(pluginConfig.apiBase) ?? resolvedProviderRuntime.apiBase ?? void 0;
183
+ const apiKey = readString(pluginConfig.apiKey) ?? resolvedProviderRuntime.apiKey ?? void 0;
178
184
  if (!apiKey) {
179
185
  throw new Error(
180
- `[codex] missing apiKey. Set plugins.entries.${PLUGIN_ID}.config.apiKey or providers.*.apiKey for model "${model}".`
186
+ `[codex] missing apiKey. Set plugins.entries.${PLUGIN_ID}.config.apiKey or providers.*.apiKey for model "${userFacingModelRoute}".`
181
187
  );
182
188
  }
183
189
  if (capabilitySpec?.supportsResponsesApi === false) {
184
- const capabilityProviderName = capabilitySpec.displayName ?? capabilitySpec.name ?? providerName ?? "provider";
190
+ const capabilityProviderName = capabilitySpec.displayName ?? capabilitySpec.name ?? resolvedProviderRuntime.providerDisplayName ?? externalModelProvider;
185
191
  throw new Error(
186
- `[codex] model "${model}" is routed through "${capabilityProviderName}", which does not support the Responses API. Codex SDK currently only supports models available through the Responses API.`
192
+ `[codex] model "${userFacingModelRoute}" is routed through "${capabilityProviderName}", which does not support the Responses API. Codex SDK currently only supports models available through the Responses API.`
187
193
  );
188
194
  }
189
195
  const executionOptions = resolveCodexExecutionOptions({
@@ -195,14 +201,14 @@ const plugin = {
195
201
  sessionId: runtimeParams.sessionId,
196
202
  apiKey,
197
203
  apiBase,
198
- model: stripProviderPrefix(model, providerName),
204
+ model: resolvedProviderRuntime.providerLocalModel,
199
205
  threadId: readString(runtimeParams.sessionMetadata.codex_thread_id) ?? null,
200
206
  codexPathOverride: readString(pluginConfig.codexPathOverride),
201
207
  env: readStringRecord(pluginConfig.env),
202
208
  cliConfig: resolveCodexCliConfig({
203
209
  pluginConfig,
204
- model,
205
210
  providerName,
211
+ providerDisplayName: resolvedProviderRuntime.providerDisplayName,
206
212
  apiBase
207
213
  }),
208
214
  stateManager: runtimeParams.stateManager,
@@ -17,6 +17,9 @@
17
17
  "model": {
18
18
  "type": "string"
19
19
  },
20
+ "modelProvider": {
21
+ "type": "string"
22
+ },
20
23
  "workingDirectory": {
21
24
  "type": "string"
22
25
  },
@@ -74,6 +77,11 @@
74
77
  "model": {
75
78
  "label": "Default Model"
76
79
  },
80
+ "modelProvider": {
81
+ "label": "External Model Provider",
82
+ "help": "Optional override for the provider id exposed to Codex SDK. Recommended for custom providers whose display name is not the actual upstream provider id.",
83
+ "advanced": true
84
+ },
77
85
  "workingDirectory": {
78
86
  "label": "Working Directory",
79
87
  "advanced": true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/nextclaw-ncp-runtime-plugin-codex-sdk",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
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,10 @@
21
21
  ]
22
22
  },
23
23
  "dependencies": {
24
- "@nextclaw/core": "0.9.5",
24
+ "@nextclaw/core": "0.9.6",
25
25
  "@nextclaw/ncp": "0.3.1",
26
- "@nextclaw/ncp-toolkit": "0.4.1",
27
- "@nextclaw/nextclaw-ncp-runtime-codex-sdk": "0.1.1"
26
+ "@nextclaw/nextclaw-ncp-runtime-codex-sdk": "0.1.1",
27
+ "@nextclaw/ncp-toolkit": "0.4.1"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^20.17.6",