@meetopenbot/codex 1.0.10 → 1.0.12
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.js +178 -534
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,543 +1,187 @@
|
|
|
1
|
-
//
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const options = this._threadOptions;
|
|
59
|
-
const { prompt, images } = normalizeInput(input);
|
|
60
|
-
const generator = this._exec.run({
|
|
61
|
-
input: prompt,
|
|
62
|
-
baseUrl: this._options.baseUrl,
|
|
63
|
-
apiKey: this._options.apiKey,
|
|
64
|
-
threadId: this._id,
|
|
65
|
-
images,
|
|
66
|
-
model: options?.model,
|
|
67
|
-
sandboxMode: options?.sandboxMode,
|
|
68
|
-
workingDirectory: options?.workingDirectory,
|
|
69
|
-
skipGitRepoCheck: options?.skipGitRepoCheck,
|
|
70
|
-
outputSchemaFile: schemaPath,
|
|
71
|
-
modelReasoningEffort: options?.modelReasoningEffort,
|
|
72
|
-
signal: turnOptions.signal,
|
|
73
|
-
networkAccessEnabled: options?.networkAccessEnabled,
|
|
74
|
-
webSearchMode: options?.webSearchMode,
|
|
75
|
-
webSearchEnabled: options?.webSearchEnabled,
|
|
76
|
-
approvalPolicy: options?.approvalPolicy,
|
|
77
|
-
additionalDirectories: options?.additionalDirectories
|
|
78
|
-
});
|
|
79
|
-
try {
|
|
80
|
-
for await (const item of generator) {
|
|
81
|
-
let parsed;
|
|
82
|
-
try {
|
|
83
|
-
parsed = JSON.parse(item);
|
|
84
|
-
} catch (error) {
|
|
85
|
-
throw new Error(`Failed to parse item: ${item}`, { cause: error });
|
|
86
|
-
}
|
|
87
|
-
if (parsed.type === "thread.started") {
|
|
88
|
-
this._id = parsed.thread_id;
|
|
89
|
-
}
|
|
90
|
-
yield parsed;
|
|
1
|
+
// index.ts
|
|
2
|
+
import {
|
|
3
|
+
definePlugin,
|
|
4
|
+
shouldHandleInvoke,
|
|
5
|
+
agentOutput,
|
|
6
|
+
uiWidget
|
|
7
|
+
} from "@meetopenbot/plugin-sdk";
|
|
8
|
+
import {
|
|
9
|
+
Codex
|
|
10
|
+
} from "@openai/codex-sdk";
|
|
11
|
+
var codex_default = definePlugin({
|
|
12
|
+
id: "codex",
|
|
13
|
+
name: "Codex",
|
|
14
|
+
description: "Codex integration tools for OpenBot",
|
|
15
|
+
configSchema: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
apiKey: { type: "string", description: "Codex API Key", format: "password" },
|
|
19
|
+
baseURL: { type: "string", description: "Custom OpenAI-compatible endpoint" },
|
|
20
|
+
codexPathOverride: { type: "string", description: "Path to codex CLI" },
|
|
21
|
+
model: { type: "string", description: "Model to use", default: "gpt-5-codex" },
|
|
22
|
+
workingDirectory: { type: "string", description: "Working directory for Codex" },
|
|
23
|
+
skipGitRepoCheck: { type: "boolean", description: "Skip git repo check", default: true },
|
|
24
|
+
sandboxMode: {
|
|
25
|
+
type: "string",
|
|
26
|
+
enum: ["workspace-read", "workspace-write", "full-read", "full-write"],
|
|
27
|
+
description: "Sandbox mode",
|
|
28
|
+
default: "workspace-write"
|
|
29
|
+
},
|
|
30
|
+
approvalPolicy: {
|
|
31
|
+
type: "string",
|
|
32
|
+
enum: ["always", "never", "automatic"],
|
|
33
|
+
description: "Approval policy",
|
|
34
|
+
default: "never"
|
|
35
|
+
},
|
|
36
|
+
networkAccessEnabled: { type: "boolean", description: "Enable network access" },
|
|
37
|
+
webSearchMode: {
|
|
38
|
+
type: "string",
|
|
39
|
+
enum: ["always", "never", "automatic"],
|
|
40
|
+
description: "Web search mode"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
factory: (context) => {
|
|
45
|
+
const config = context.config;
|
|
46
|
+
const env = globalThis?.process?.env || {};
|
|
47
|
+
const apiKey = config.apiKey ?? env.CODEX_API_KEY ?? env.OPENAI_API_KEY;
|
|
48
|
+
const codexPathOverride = config.codexPathOverride ?? env.CODEX_PATH ?? env.CODEX_CLI_PATH;
|
|
49
|
+
const model = config.model?.split("/").pop() || "gpt-5-codex";
|
|
50
|
+
let client;
|
|
51
|
+
const getClient = () => {
|
|
52
|
+
if (!client) {
|
|
53
|
+
client = new Codex({
|
|
54
|
+
apiKey,
|
|
55
|
+
...codexPathOverride && { codexPathOverride },
|
|
56
|
+
...config.baseURL && { baseUrl: config.baseURL }
|
|
57
|
+
});
|
|
91
58
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
59
|
+
return client;
|
|
60
|
+
};
|
|
61
|
+
let thread = null;
|
|
62
|
+
const getThread = (state, meta) => {
|
|
63
|
+
if (thread) return thread;
|
|
64
|
+
const workingDirectory = config.workingDirectory || state?.channelDetails?.cwd || globalThis?.process?.cwd() || "/tmp";
|
|
65
|
+
const threadOptions = {
|
|
66
|
+
model,
|
|
67
|
+
workingDirectory,
|
|
68
|
+
skipGitRepoCheck: config.skipGitRepoCheck ?? true,
|
|
69
|
+
sandboxMode: config.sandboxMode ?? "workspace-write",
|
|
70
|
+
approvalPolicy: config.approvalPolicy ?? "never",
|
|
71
|
+
...typeof config.networkAccessEnabled === "boolean" && {
|
|
72
|
+
networkAccessEnabled: config.networkAccessEnabled
|
|
73
|
+
},
|
|
74
|
+
...config.webSearchMode && {
|
|
75
|
+
webSearchMode: config.webSearchMode
|
|
107
76
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (turnFailure) {
|
|
117
|
-
throw new Error(turnFailure.message);
|
|
118
|
-
}
|
|
119
|
-
return { items, finalResponse, usage };
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
function normalizeInput(input) {
|
|
123
|
-
if (typeof input === "string") {
|
|
124
|
-
return { prompt: input, images: [] };
|
|
125
|
-
}
|
|
126
|
-
const promptParts = [];
|
|
127
|
-
const images = [];
|
|
128
|
-
for (const item of input) {
|
|
129
|
-
if (item.type === "text") {
|
|
130
|
-
promptParts.push(item.text);
|
|
131
|
-
} else if (item.type === "local_image") {
|
|
132
|
-
images.push(item.path);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return { prompt: promptParts.join("\n\n"), images };
|
|
136
|
-
}
|
|
137
|
-
var INTERNAL_ORIGINATOR_ENV = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE";
|
|
138
|
-
var TYPESCRIPT_SDK_ORIGINATOR = "codex_sdk_ts";
|
|
139
|
-
var CODEX_NPM_NAME = "@openai/codex";
|
|
140
|
-
var PLATFORM_PACKAGE_BY_TARGET = {
|
|
141
|
-
"x86_64-unknown-linux-musl": "@openai/codex-linux-x64",
|
|
142
|
-
"aarch64-unknown-linux-musl": "@openai/codex-linux-arm64",
|
|
143
|
-
"x86_64-apple-darwin": "@openai/codex-darwin-x64",
|
|
144
|
-
"aarch64-apple-darwin": "@openai/codex-darwin-arm64",
|
|
145
|
-
"x86_64-pc-windows-msvc": "@openai/codex-win32-x64",
|
|
146
|
-
"aarch64-pc-windows-msvc": "@openai/codex-win32-arm64"
|
|
147
|
-
};
|
|
148
|
-
var moduleRequire = createRequire(import.meta.url);
|
|
149
|
-
var CodexExec = class {
|
|
150
|
-
executablePath;
|
|
151
|
-
envOverride;
|
|
152
|
-
configOverrides;
|
|
153
|
-
constructor(executablePath = null, env, configOverrides) {
|
|
154
|
-
this.executablePath = executablePath || findCodexPath();
|
|
155
|
-
this.envOverride = env;
|
|
156
|
-
this.configOverrides = configOverrides;
|
|
157
|
-
}
|
|
158
|
-
async *run(args) {
|
|
159
|
-
const commandArgs = ["exec", "--experimental-json"];
|
|
160
|
-
if (this.configOverrides) {
|
|
161
|
-
for (const override of serializeConfigOverrides(this.configOverrides)) {
|
|
162
|
-
commandArgs.push("--config", override);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
if (args.model) {
|
|
166
|
-
commandArgs.push("--model", args.model);
|
|
167
|
-
}
|
|
168
|
-
if (args.sandboxMode) {
|
|
169
|
-
commandArgs.push("--sandbox", args.sandboxMode);
|
|
170
|
-
}
|
|
171
|
-
if (args.workingDirectory) {
|
|
172
|
-
commandArgs.push("--cd", args.workingDirectory);
|
|
173
|
-
}
|
|
174
|
-
if (args.additionalDirectories?.length) {
|
|
175
|
-
for (const dir of args.additionalDirectories) {
|
|
176
|
-
commandArgs.push("--add-dir", dir);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (args.skipGitRepoCheck) {
|
|
180
|
-
commandArgs.push("--skip-git-repo-check");
|
|
181
|
-
}
|
|
182
|
-
if (args.outputSchemaFile) {
|
|
183
|
-
commandArgs.push("--output-schema", args.outputSchemaFile);
|
|
184
|
-
}
|
|
185
|
-
if (args.modelReasoningEffort) {
|
|
186
|
-
commandArgs.push("--config", `model_reasoning_effort="${args.modelReasoningEffort}"`);
|
|
187
|
-
}
|
|
188
|
-
if (args.networkAccessEnabled !== void 0) {
|
|
189
|
-
commandArgs.push(
|
|
190
|
-
"--config",
|
|
191
|
-
`sandbox_workspace_write.network_access=${args.networkAccessEnabled}`
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
if (args.webSearchMode) {
|
|
195
|
-
commandArgs.push("--config", `web_search="${args.webSearchMode}"`);
|
|
196
|
-
} else if (args.webSearchEnabled === true) {
|
|
197
|
-
commandArgs.push("--config", `web_search="live"`);
|
|
198
|
-
} else if (args.webSearchEnabled === false) {
|
|
199
|
-
commandArgs.push("--config", `web_search="disabled"`);
|
|
200
|
-
}
|
|
201
|
-
if (args.approvalPolicy) {
|
|
202
|
-
commandArgs.push("--config", `approval_policy="${args.approvalPolicy}"`);
|
|
203
|
-
}
|
|
204
|
-
if (args.threadId) {
|
|
205
|
-
commandArgs.push("resume", args.threadId);
|
|
206
|
-
}
|
|
207
|
-
if (args.images?.length) {
|
|
208
|
-
for (const image of args.images) {
|
|
209
|
-
commandArgs.push("--image", image);
|
|
77
|
+
};
|
|
78
|
+
const threadId = state?.threadId || meta?.threadId;
|
|
79
|
+
thread = threadId ? getClient().resumeThread(threadId, threadOptions) : getClient().startThread(threadOptions);
|
|
80
|
+
if (!threadId && state) {
|
|
81
|
+
state.threadId = thread.id;
|
|
210
82
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
|
|
83
|
+
return thread;
|
|
84
|
+
};
|
|
85
|
+
return (builder) => {
|
|
86
|
+
builder.on("agent:invoke", async function* (event, ctx) {
|
|
87
|
+
if (!shouldHandleInvoke(event, context.agentId)) return;
|
|
88
|
+
const { content } = event.data || {};
|
|
89
|
+
if (!content) {
|
|
90
|
+
yield agentOutput({
|
|
91
|
+
agentId: context.agentId,
|
|
92
|
+
content: "No content provided.",
|
|
93
|
+
threadId: event.meta?.threadId
|
|
94
|
+
});
|
|
95
|
+
return;
|
|
219
96
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const exitPromise = new Promise(
|
|
254
|
-
(resolve) => {
|
|
255
|
-
child.once("exit", (code, signal) => {
|
|
256
|
-
resolve({ code, signal });
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
);
|
|
260
|
-
const rl = readline.createInterface({
|
|
261
|
-
input: child.stdout,
|
|
262
|
-
crlfDelay: Infinity
|
|
263
|
-
});
|
|
264
|
-
try {
|
|
265
|
-
for await (const line of rl) {
|
|
266
|
-
yield line;
|
|
267
|
-
}
|
|
268
|
-
if (spawnError) throw spawnError;
|
|
269
|
-
const { code, signal } = await exitPromise;
|
|
270
|
-
if (code !== 0 || signal) {
|
|
271
|
-
const stderrBuffer = Buffer.concat(stderrChunks);
|
|
272
|
-
const detail = signal ? `signal ${signal}` : `code ${code ?? 1}`;
|
|
273
|
-
throw new Error(`Codex Exec exited with ${detail}: ${stderrBuffer.toString("utf8")}`);
|
|
274
|
-
}
|
|
275
|
-
} finally {
|
|
276
|
-
rl.close();
|
|
277
|
-
child.removeAllListeners();
|
|
278
|
-
try {
|
|
279
|
-
if (!child.killed) child.kill();
|
|
280
|
-
} catch {
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
};
|
|
285
|
-
function serializeConfigOverrides(configOverrides) {
|
|
286
|
-
const overrides = [];
|
|
287
|
-
flattenConfigOverrides(configOverrides, "", overrides);
|
|
288
|
-
return overrides;
|
|
289
|
-
}
|
|
290
|
-
function flattenConfigOverrides(value, prefix, overrides) {
|
|
291
|
-
if (!isPlainObject(value)) {
|
|
292
|
-
if (prefix) {
|
|
293
|
-
overrides.push(`${prefix}=${toTomlValue(value, prefix)}`);
|
|
294
|
-
return;
|
|
295
|
-
} else {
|
|
296
|
-
throw new Error("Codex config overrides must be a plain object");
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
const entries = Object.entries(value);
|
|
300
|
-
if (!prefix && entries.length === 0) {
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
if (prefix && entries.length === 0) {
|
|
304
|
-
overrides.push(`${prefix}={}`);
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
for (const [key, child] of entries) {
|
|
308
|
-
if (!key) {
|
|
309
|
-
throw new Error("Codex config override keys must be non-empty strings");
|
|
310
|
-
}
|
|
311
|
-
if (child === void 0) {
|
|
312
|
-
continue;
|
|
313
|
-
}
|
|
314
|
-
const path3 = prefix ? `${prefix}.${key}` : key;
|
|
315
|
-
if (isPlainObject(child)) {
|
|
316
|
-
flattenConfigOverrides(child, path3, overrides);
|
|
317
|
-
} else {
|
|
318
|
-
overrides.push(`${path3}=${toTomlValue(child, path3)}`);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
function toTomlValue(value, path3) {
|
|
323
|
-
if (typeof value === "string") {
|
|
324
|
-
return JSON.stringify(value);
|
|
325
|
-
} else if (typeof value === "number") {
|
|
326
|
-
if (!Number.isFinite(value)) {
|
|
327
|
-
throw new Error(`Codex config override at ${path3} must be a finite number`);
|
|
328
|
-
}
|
|
329
|
-
return `${value}`;
|
|
330
|
-
} else if (typeof value === "boolean") {
|
|
331
|
-
return value ? "true" : "false";
|
|
332
|
-
} else if (Array.isArray(value)) {
|
|
333
|
-
const rendered = value.map((item, index) => toTomlValue(item, `${path3}[${index}]`));
|
|
334
|
-
return `[${rendered.join(", ")}]`;
|
|
335
|
-
} else if (isPlainObject(value)) {
|
|
336
|
-
const parts = [];
|
|
337
|
-
for (const [key, child] of Object.entries(value)) {
|
|
338
|
-
if (!key) {
|
|
339
|
-
throw new Error("Codex config override keys must be non-empty strings");
|
|
340
|
-
}
|
|
341
|
-
if (child === void 0) {
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
parts.push(`${formatTomlKey(key)} = ${toTomlValue(child, `${path3}.${key}`)}`);
|
|
345
|
-
}
|
|
346
|
-
return `{${parts.join(", ")}}`;
|
|
347
|
-
} else if (value === null) {
|
|
348
|
-
throw new Error(`Codex config override at ${path3} cannot be null`);
|
|
349
|
-
} else {
|
|
350
|
-
const typeName = typeof value;
|
|
351
|
-
throw new Error(`Unsupported Codex config override value at ${path3}: ${typeName}`);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
var TOML_BARE_KEY = /^[A-Za-z0-9_-]+$/;
|
|
355
|
-
function formatTomlKey(key) {
|
|
356
|
-
return TOML_BARE_KEY.test(key) ? key : JSON.stringify(key);
|
|
357
|
-
}
|
|
358
|
-
function isPlainObject(value) {
|
|
359
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
360
|
-
}
|
|
361
|
-
function findCodexPath() {
|
|
362
|
-
const { platform, arch } = process;
|
|
363
|
-
let targetTriple = null;
|
|
364
|
-
switch (platform) {
|
|
365
|
-
case "linux":
|
|
366
|
-
case "android":
|
|
367
|
-
switch (arch) {
|
|
368
|
-
case "x64":
|
|
369
|
-
targetTriple = "x86_64-unknown-linux-musl";
|
|
370
|
-
break;
|
|
371
|
-
case "arm64":
|
|
372
|
-
targetTriple = "aarch64-unknown-linux-musl";
|
|
373
|
-
break;
|
|
374
|
-
default:
|
|
375
|
-
break;
|
|
376
|
-
}
|
|
377
|
-
break;
|
|
378
|
-
case "darwin":
|
|
379
|
-
switch (arch) {
|
|
380
|
-
case "x64":
|
|
381
|
-
targetTriple = "x86_64-apple-darwin";
|
|
382
|
-
break;
|
|
383
|
-
case "arm64":
|
|
384
|
-
targetTriple = "aarch64-apple-darwin";
|
|
385
|
-
break;
|
|
386
|
-
default:
|
|
387
|
-
break;
|
|
388
|
-
}
|
|
389
|
-
break;
|
|
390
|
-
case "win32":
|
|
391
|
-
switch (arch) {
|
|
392
|
-
case "x64":
|
|
393
|
-
targetTriple = "x86_64-pc-windows-msvc";
|
|
394
|
-
break;
|
|
395
|
-
case "arm64":
|
|
396
|
-
targetTriple = "aarch64-pc-windows-msvc";
|
|
397
|
-
break;
|
|
398
|
-
default:
|
|
399
|
-
break;
|
|
400
|
-
}
|
|
401
|
-
break;
|
|
402
|
-
default:
|
|
403
|
-
break;
|
|
404
|
-
}
|
|
405
|
-
if (!targetTriple) {
|
|
406
|
-
throw new Error(`Unsupported platform: ${platform} (${arch})`);
|
|
407
|
-
}
|
|
408
|
-
const platformPackage = PLATFORM_PACKAGE_BY_TARGET[targetTriple];
|
|
409
|
-
if (!platformPackage) {
|
|
410
|
-
throw new Error(`Unsupported target triple: ${targetTriple}`);
|
|
411
|
-
}
|
|
412
|
-
let vendorRoot;
|
|
413
|
-
try {
|
|
414
|
-
const codexPackageJsonPath = moduleRequire.resolve(`${CODEX_NPM_NAME}/package.json`);
|
|
415
|
-
const codexRequire = createRequire(codexPackageJsonPath);
|
|
416
|
-
const platformPackageJsonPath = codexRequire.resolve(`${platformPackage}/package.json`);
|
|
417
|
-
vendorRoot = path2.join(path2.dirname(platformPackageJsonPath), "vendor");
|
|
418
|
-
} catch {
|
|
419
|
-
throw new Error(
|
|
420
|
-
`Unable to locate Codex CLI binaries. Ensure ${CODEX_NPM_NAME} is installed with optional dependencies.`
|
|
421
|
-
);
|
|
422
|
-
}
|
|
423
|
-
const archRoot = path2.join(vendorRoot, targetTriple);
|
|
424
|
-
const codexBinaryName = process.platform === "win32" ? "codex.exe" : "codex";
|
|
425
|
-
const binaryPath = path2.join(archRoot, "codex", codexBinaryName);
|
|
426
|
-
return binaryPath;
|
|
427
|
-
}
|
|
428
|
-
var Codex = class {
|
|
429
|
-
exec;
|
|
430
|
-
options;
|
|
431
|
-
constructor(options = {}) {
|
|
432
|
-
const { codexPathOverride, env, config } = options;
|
|
433
|
-
this.exec = new CodexExec(codexPathOverride, env, config);
|
|
434
|
-
this.options = options;
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Starts a new conversation with an agent.
|
|
438
|
-
* @returns A new thread instance.
|
|
439
|
-
*/
|
|
440
|
-
startThread(options = {}) {
|
|
441
|
-
return new Thread(this.exec, this.options, options);
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Resumes a conversation with an agent based on the thread id.
|
|
445
|
-
* Threads are persisted in ~/.codex/sessions.
|
|
446
|
-
*
|
|
447
|
-
* @param id The id of the thread to resume.
|
|
448
|
-
* @returns A new thread instance.
|
|
449
|
-
*/
|
|
450
|
-
resumeThread(id, options = {}) {
|
|
451
|
-
return new Thread(this.exec, this.options, options, id);
|
|
452
|
-
}
|
|
453
|
-
};
|
|
97
|
+
try {
|
|
98
|
+
const turn = await getThread(ctx?.state, event.meta).runStreamed(content);
|
|
99
|
+
for await (const chunk of turn.events) {
|
|
100
|
+
if (chunk.type === "item.completed") {
|
|
101
|
+
const { item } = chunk;
|
|
102
|
+
if (item.type === "agent_message") {
|
|
103
|
+
yield agentOutput({
|
|
104
|
+
agentId: context.agentId,
|
|
105
|
+
content: item.text,
|
|
106
|
+
threadId: event.meta?.threadId
|
|
107
|
+
});
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
let title = "";
|
|
111
|
+
let body = "";
|
|
112
|
+
switch (item.type) {
|
|
113
|
+
case "reasoning":
|
|
114
|
+
title = "Reasoning";
|
|
115
|
+
body = item.text;
|
|
116
|
+
break;
|
|
117
|
+
case "command_execution":
|
|
118
|
+
title = "Command Execution";
|
|
119
|
+
body = `Executing: ${item.command}`;
|
|
120
|
+
break;
|
|
121
|
+
case "file_change":
|
|
122
|
+
title = "File Change";
|
|
123
|
+
body = item.changes.map((change) => `${change.path}: ${change.kind || change.action}`).join("\n");
|
|
124
|
+
break;
|
|
125
|
+
case "mcp_tool_call":
|
|
126
|
+
title = `Tool: ${item.tool}`;
|
|
127
|
+
body = `Arguments: ${JSON.stringify(item.arguments, null, 2)}`;
|
|
128
|
+
if (item.result) {
|
|
129
|
+
body += `
|
|
454
130
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
}
|
|
498
|
-
try {
|
|
499
|
-
const turn = await getThread(ctx?.state).runStreamed(content);
|
|
500
|
-
for await (const chunk of turn.events) {
|
|
501
|
-
if (chunk.type === "item.completed") {
|
|
502
|
-
if (chunk.item.type === "agent_message") {
|
|
503
|
-
yield { type: "agent:output", data: { content: chunk.item.text } };
|
|
504
|
-
}
|
|
505
|
-
if (chunk.item.type === "reasoning") {
|
|
506
|
-
yield { type: "agent:output", data: { content: chunk.item.text } };
|
|
507
|
-
}
|
|
508
|
-
if (chunk.item.type === "command_execution") {
|
|
509
|
-
yield { type: "agent:output", data: { content: chunk.item.command } };
|
|
510
|
-
}
|
|
511
|
-
if (chunk.item.type === "file_change") {
|
|
512
|
-
yield { type: "agent:output", data: { content: chunk.item.changes.map((change) => `${change.path}: ${change.action}`).join("\n") } };
|
|
513
|
-
}
|
|
514
|
-
if (chunk.item.type === "error") {
|
|
515
|
-
yield { type: "agent:output", data: { content: `Error: ${chunk.item.message}` } };
|
|
516
|
-
}
|
|
517
|
-
if (chunk.item.type === "todo_list") {
|
|
518
|
-
yield { type: "agent:output", data: { content: chunk.item.items.map((item) => `- ${item.text} (${item.completed ? "completed" : "pending"})`).join("\n") } };
|
|
519
|
-
}
|
|
520
|
-
if (chunk.item.type === "web_search") {
|
|
521
|
-
yield { type: "agent:output", data: { content: `Query: ${chunk.item.query}` } };
|
|
131
|
+
Result: ${JSON.stringify(
|
|
132
|
+
item.result.structured_content || item.result.content,
|
|
133
|
+
null,
|
|
134
|
+
2
|
|
135
|
+
)}`;
|
|
136
|
+
}
|
|
137
|
+
if (item.error) {
|
|
138
|
+
body += `
|
|
139
|
+
|
|
140
|
+
Error: ${item.error.message}`;
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
case "web_search":
|
|
144
|
+
title = "Web Search";
|
|
145
|
+
body = `Searching: ${item.query}`;
|
|
146
|
+
break;
|
|
147
|
+
case "todo_list":
|
|
148
|
+
title = "Todo List";
|
|
149
|
+
body = item.items.map(
|
|
150
|
+
(todo) => `- ${todo.text} (${todo.completed ? "completed" : "pending"})`
|
|
151
|
+
).join("\n");
|
|
152
|
+
break;
|
|
153
|
+
case "error":
|
|
154
|
+
title = "Error";
|
|
155
|
+
body = item.message;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
if (title && body) {
|
|
159
|
+
yield uiWidget({
|
|
160
|
+
agentId: context.agentId,
|
|
161
|
+
threadId: event.meta?.threadId,
|
|
162
|
+
widget: {
|
|
163
|
+
kind: "message",
|
|
164
|
+
title,
|
|
165
|
+
body,
|
|
166
|
+
// @ts-ignore
|
|
167
|
+
variant: "basic",
|
|
168
|
+
display: "collapsed"
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
522
173
|
}
|
|
174
|
+
} catch (error) {
|
|
175
|
+
yield agentOutput({
|
|
176
|
+
agentId: context.agentId,
|
|
177
|
+
content: `Error: ${error?.message || "Codex request failed."}`,
|
|
178
|
+
threadId: event.meta?.threadId
|
|
179
|
+
});
|
|
523
180
|
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
data: { content: `Error: ${error?.message || "Codex request failed."}` }
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
});
|
|
532
|
-
};
|
|
533
|
-
var plugin = {
|
|
534
|
-
id: "codex",
|
|
535
|
-
name: "Codex",
|
|
536
|
-
description: "Codex integration tools for OpenBot",
|
|
537
|
-
kind: "runtime",
|
|
538
|
-
factory: (options) => codexPlugin(options)
|
|
539
|
-
};
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
});
|
|
540
185
|
export {
|
|
541
|
-
|
|
542
|
-
plugin
|
|
186
|
+
codex_default as default
|
|
543
187
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meetopenbot/codex",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Codex tools plugin for OpenBot",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
"assets"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "esbuild index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --external
|
|
18
|
+
"build": "esbuild index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --external:@meetopenbot/plugin-sdk --external:@openai/codex-sdk --external:zod",
|
|
19
19
|
"prepublishOnly": "npm run build"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@
|
|
23
|
-
"
|
|
22
|
+
"@meetopenbot/plugin-sdk": "^0.1.2",
|
|
23
|
+
"@openai/codex-sdk": "^0.138.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^25.6.0",
|
|
27
27
|
"esbuild": "^0.21.0",
|
|
28
|
-
"zod": "^
|
|
28
|
+
"zod": "^4.4.3"
|
|
29
29
|
}
|
|
30
|
-
}
|
|
30
|
+
}
|