@nextclaw/nextclaw-ncp-runtime-plugin-codex-sdk 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NextClaw contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @nextclaw/nextclaw-ncp-runtime-plugin-codex-sdk
2
+
3
+ Plugin package that registers the `codex` NCP session type for NextClaw.
4
+
5
+ It composes the pure runtime library from `@nextclaw/nextclaw-ncp-runtime-codex-sdk` and exposes it through the standard plugin system.
6
+
7
+ ## Build
8
+
9
+ ```bash
10
+ pnpm -C packages/extensions/nextclaw-ncp-runtime-plugin-codex-sdk build
11
+ ```
@@ -0,0 +1,23 @@
1
+ import { Config } from '@nextclaw/core';
2
+ import { NcpAgentRuntime } from '@nextclaw/ncp';
3
+ import { RuntimeFactoryParams } from '@nextclaw/ncp-toolkit';
4
+
5
+ type PluginApi = {
6
+ config: Config;
7
+ pluginConfig?: Record<string, unknown>;
8
+ registerNcpAgentRuntime: (registration: {
9
+ kind: string;
10
+ label?: string;
11
+ createRuntime: (params: RuntimeFactoryParams) => NcpAgentRuntime;
12
+ }) => void;
13
+ };
14
+ type PluginDefinition = {
15
+ id: string;
16
+ name: string;
17
+ description: string;
18
+ configSchema: Record<string, unknown>;
19
+ register: (api: PluginApi) => void;
20
+ };
21
+ declare const plugin: PluginDefinition;
22
+
23
+ export { plugin as default };
package/dist/index.js ADDED
@@ -0,0 +1,168 @@
1
+ import {
2
+ getApiBase,
3
+ getProvider,
4
+ getWorkspacePath,
5
+ SkillsLoader
6
+ } from "@nextclaw/core";
7
+ import {
8
+ CodexSdkNcpAgentRuntime
9
+ } from "@nextclaw/nextclaw-ncp-runtime-codex-sdk";
10
+ const PLUGIN_ID = "nextclaw-ncp-runtime-plugin-codex-sdk";
11
+ const CODEX_RUNTIME_KIND = "codex";
12
+ function readString(value) {
13
+ if (typeof value !== "string") {
14
+ return void 0;
15
+ }
16
+ const trimmed = value.trim();
17
+ return trimmed || void 0;
18
+ }
19
+ function readBoolean(value) {
20
+ return typeof value === "boolean" ? value : void 0;
21
+ }
22
+ function readRecord(value) {
23
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
24
+ return void 0;
25
+ }
26
+ return value;
27
+ }
28
+ function readStringArray(value) {
29
+ if (!Array.isArray(value)) {
30
+ return void 0;
31
+ }
32
+ const values = value.map((entry) => readString(entry)).filter((entry) => Boolean(entry));
33
+ return values.length > 0 ? values : void 0;
34
+ }
35
+ function readStringRecord(value) {
36
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
37
+ return void 0;
38
+ }
39
+ const out = {};
40
+ for (const [entryKey, entryValue] of Object.entries(value)) {
41
+ if (typeof entryValue !== "string") {
42
+ continue;
43
+ }
44
+ const normalized = entryValue.trim();
45
+ if (!normalized) {
46
+ continue;
47
+ }
48
+ out[entryKey] = normalized;
49
+ }
50
+ return Object.keys(out).length > 0 ? out : void 0;
51
+ }
52
+ function readThinkingLevel(value) {
53
+ if (typeof value !== "string") {
54
+ return void 0;
55
+ }
56
+ const normalized = value.trim().toLowerCase();
57
+ if (normalized === "minimal" || normalized === "low" || normalized === "medium" || normalized === "high" || normalized === "xhigh") {
58
+ return normalized;
59
+ }
60
+ return void 0;
61
+ }
62
+ function readRequestedSkills(metadata) {
63
+ const raw = metadata.requested_skills ?? metadata.requestedSkills;
64
+ if (!Array.isArray(raw)) {
65
+ return [];
66
+ }
67
+ return raw.map((entry) => readString(entry)).filter((entry) => Boolean(entry)).slice(0, 8);
68
+ }
69
+ function readUserText(input) {
70
+ for (let index = input.messages.length - 1; index >= 0; index -= 1) {
71
+ const message = input.messages[index];
72
+ if (message?.role !== "user") {
73
+ continue;
74
+ }
75
+ const text = message.parts.filter((part) => part.type === "text").map((part) => part.text).join("").trim();
76
+ if (text) {
77
+ return text;
78
+ }
79
+ }
80
+ return "";
81
+ }
82
+ function buildCodexInputBuilder(workspace) {
83
+ const skillsLoader = new SkillsLoader(workspace);
84
+ return async (input) => {
85
+ const userText = readUserText(input);
86
+ const metadata = input.metadata && typeof input.metadata === "object" && !Array.isArray(input.metadata) ? input.metadata : {};
87
+ const requestedSkills = readRequestedSkills(metadata);
88
+ const requestedSkillsContent = skillsLoader.loadSkillsForContext(requestedSkills);
89
+ if (requestedSkillsContent.trim().length === 0) {
90
+ return userText;
91
+ }
92
+ return [
93
+ "## Requested Skills",
94
+ `Selected skill names: ${requestedSkills.join(", ")}`,
95
+ requestedSkillsContent,
96
+ "## User Message",
97
+ userText
98
+ ].join("\n\n");
99
+ };
100
+ }
101
+ function resolveCodexModel(params) {
102
+ return readString(params.sessionMetadata.preferred_model) ?? readString(params.sessionMetadata.model) ?? readString(params.pluginConfig.model) ?? params.config.agents.defaults.model;
103
+ }
104
+ const plugin = {
105
+ id: PLUGIN_ID,
106
+ name: "NextClaw Codex NCP Runtime",
107
+ description: "Registers NCP session type `codex` backed by OpenAI Codex SDK.",
108
+ configSchema: {
109
+ type: "object",
110
+ additionalProperties: true,
111
+ properties: {}
112
+ },
113
+ register(api) {
114
+ const pluginConfig = readRecord(api.pluginConfig) ?? {};
115
+ api.registerNcpAgentRuntime({
116
+ kind: CODEX_RUNTIME_KIND,
117
+ label: "Codex",
118
+ createRuntime: (runtimeParams) => {
119
+ const nextConfig = api.config;
120
+ const model = resolveCodexModel({
121
+ config: nextConfig,
122
+ pluginConfig,
123
+ sessionMetadata: runtimeParams.sessionMetadata
124
+ });
125
+ const provider = getProvider(nextConfig, model);
126
+ const apiKey = readString(pluginConfig.apiKey) ?? provider?.apiKey ?? void 0;
127
+ if (!apiKey) {
128
+ throw new Error(
129
+ `[codex] missing apiKey. Set plugins.entries.${PLUGIN_ID}.config.apiKey or providers.*.apiKey for model "${model}".`
130
+ );
131
+ }
132
+ const workspace = getWorkspacePath(
133
+ readString(pluginConfig.workingDirectory) ?? nextConfig.agents.defaults.workspace
134
+ );
135
+ const thinkingLevel = readThinkingLevel(runtimeParams.sessionMetadata.preferred_thinking) ?? readThinkingLevel(runtimeParams.sessionMetadata.thinking) ?? void 0;
136
+ return new CodexSdkNcpAgentRuntime({
137
+ sessionId: runtimeParams.sessionId,
138
+ apiKey,
139
+ apiBase: readString(pluginConfig.apiBase) ?? getApiBase(nextConfig, model) ?? void 0,
140
+ model,
141
+ threadId: readString(runtimeParams.sessionMetadata.codex_thread_id) ?? null,
142
+ codexPathOverride: readString(pluginConfig.codexPathOverride),
143
+ env: readStringRecord(pluginConfig.env),
144
+ cliConfig: readRecord(pluginConfig.config),
145
+ sessionMetadata: runtimeParams.sessionMetadata,
146
+ setSessionMetadata: runtimeParams.setSessionMetadata,
147
+ inputBuilder: buildCodexInputBuilder(workspace),
148
+ threadOptions: {
149
+ model,
150
+ sandboxMode: readString(pluginConfig.sandboxMode),
151
+ workingDirectory: workspace,
152
+ skipGitRepoCheck: readBoolean(pluginConfig.skipGitRepoCheck),
153
+ modelReasoningEffort: thinkingLevel,
154
+ networkAccessEnabled: readBoolean(pluginConfig.networkAccessEnabled),
155
+ webSearchMode: readString(pluginConfig.webSearchMode),
156
+ webSearchEnabled: readBoolean(pluginConfig.webSearchEnabled),
157
+ approvalPolicy: readString(pluginConfig.approvalPolicy),
158
+ additionalDirectories: readStringArray(pluginConfig.additionalDirectories)
159
+ }
160
+ });
161
+ }
162
+ });
163
+ }
164
+ };
165
+ var index_default = plugin;
166
+ export {
167
+ index_default as default
168
+ };
@@ -0,0 +1,98 @@
1
+ {
2
+ "id": "nextclaw-ncp-runtime-plugin-codex-sdk",
3
+ "kind": "agent-runtime",
4
+ "name": "NextClaw Codex NCP Runtime",
5
+ "description": "Registers NCP session type `codex` backed by OpenAI Codex SDK.",
6
+ "version": "0.1.0",
7
+ "configSchema": {
8
+ "type": "object",
9
+ "additionalProperties": true,
10
+ "properties": {
11
+ "apiKey": {
12
+ "type": "string"
13
+ },
14
+ "apiBase": {
15
+ "type": "string"
16
+ },
17
+ "model": {
18
+ "type": "string"
19
+ },
20
+ "workingDirectory": {
21
+ "type": "string"
22
+ },
23
+ "sandboxMode": {
24
+ "type": "string",
25
+ "enum": ["read-only", "workspace-write", "danger-full-access"]
26
+ },
27
+ "skipGitRepoCheck": {
28
+ "type": "boolean"
29
+ },
30
+ "networkAccessEnabled": {
31
+ "type": "boolean"
32
+ },
33
+ "webSearchMode": {
34
+ "type": "string",
35
+ "enum": ["disabled", "cached", "live"]
36
+ },
37
+ "webSearchEnabled": {
38
+ "type": "boolean"
39
+ },
40
+ "approvalPolicy": {
41
+ "type": "string",
42
+ "enum": ["never", "on-request", "on-failure", "untrusted"]
43
+ },
44
+ "codexPathOverride": {
45
+ "type": "string"
46
+ },
47
+ "additionalDirectories": {
48
+ "type": "array",
49
+ "items": {
50
+ "type": "string"
51
+ }
52
+ },
53
+ "env": {
54
+ "type": "object",
55
+ "additionalProperties": {
56
+ "type": "string"
57
+ }
58
+ },
59
+ "config": {
60
+ "type": "object",
61
+ "additionalProperties": true
62
+ }
63
+ }
64
+ },
65
+ "uiHints": {
66
+ "apiKey": {
67
+ "label": "Codex API Key",
68
+ "help": "Optional. Falls back to the selected provider API key when omitted.",
69
+ "sensitive": true
70
+ },
71
+ "apiBase": {
72
+ "label": "Codex API Base"
73
+ },
74
+ "model": {
75
+ "label": "Default Model"
76
+ },
77
+ "workingDirectory": {
78
+ "label": "Working Directory",
79
+ "advanced": true
80
+ },
81
+ "sandboxMode": {
82
+ "label": "Sandbox Mode",
83
+ "advanced": true
84
+ },
85
+ "approvalPolicy": {
86
+ "label": "Approval Policy",
87
+ "advanced": true
88
+ },
89
+ "networkAccessEnabled": {
90
+ "label": "Enable Network",
91
+ "advanced": true
92
+ },
93
+ "webSearchEnabled": {
94
+ "label": "Enable Web Search",
95
+ "advanced": true
96
+ }
97
+ }
98
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@nextclaw/nextclaw-ncp-runtime-plugin-codex-sdk",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "NextClaw plugin that registers Codex SDK as an optional NCP runtime.",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "openclaw.plugin.json",
16
+ "README.md"
17
+ ],
18
+ "openclaw": {
19
+ "extensions": [
20
+ "dist/index.js"
21
+ ]
22
+ },
23
+ "dependencies": {
24
+ "@nextclaw/nextclaw-ncp-runtime-codex-sdk": "0.1.0",
25
+ "@nextclaw/ncp": "0.3.0",
26
+ "@nextclaw/ncp-toolkit": "0.3.0",
27
+ "@nextclaw/core": "0.9.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^20.17.6",
31
+ "tsup": "^8.3.5",
32
+ "typescript": "^5.6.3"
33
+ },
34
+ "scripts": {
35
+ "build": "tsup --config tsup.config.ts",
36
+ "lint": "eslint .",
37
+ "tsc": "tsc -p tsconfig.json"
38
+ }
39
+ }