@react-grab/codex 0.0.97 → 0.1.0-beta.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/dist/cli.cjs +7908 -6540
- package/dist/cli.js +7905 -6540
- package/dist/client.cjs +384 -198
- package/dist/client.d.cts +5 -17
- package/dist/client.d.ts +5 -17
- package/dist/client.global.js +2 -5
- package/dist/client.js +384 -198
- package/dist/handler.cjs +7523 -0
- package/dist/handler.d.cts +9 -0
- package/dist/handler.d.ts +9 -0
- package/dist/handler.js +7512 -0
- package/package.json +8 -12
- package/dist/server.cjs +0 -221
- package/dist/server.d.cts +0 -13
- package/dist/server.d.ts +0 -13
- package/dist/server.js +0 -211
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-grab/codex",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"react-grab-codex": "./dist/cli.cjs"
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
"import": "./dist/client.js",
|
|
12
12
|
"require": "./dist/client.cjs"
|
|
13
13
|
},
|
|
14
|
-
"./
|
|
15
|
-
"types": "./dist/
|
|
16
|
-
"import": "./dist/
|
|
17
|
-
"require": "./dist/
|
|
14
|
+
"./handler": {
|
|
15
|
+
"types": "./dist/handler.d.ts",
|
|
16
|
+
"import": "./dist/handler.js",
|
|
17
|
+
"require": "./dist/handler.cjs"
|
|
18
18
|
},
|
|
19
19
|
"./dist/*": "./dist/*.js",
|
|
20
20
|
"./dist/*.js": "./dist/*.js"
|
|
@@ -26,16 +26,12 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^22.10.7",
|
|
28
28
|
"tsup": "^8.4.0",
|
|
29
|
-
"@react-grab/utils": "0.0.
|
|
29
|
+
"@react-grab/utils": "0.1.0-beta.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@hono/node-server": "^1.19.6",
|
|
33
|
-
"execa": "^9.6.0",
|
|
34
32
|
"@openai/codex-sdk": "^0.66.0",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"picocolors": "^1.1.1",
|
|
38
|
-
"react-grab": "0.0.97"
|
|
33
|
+
"@react-grab/relay": "0.1.0-beta.0",
|
|
34
|
+
"react-grab": "0.1.0-beta.0"
|
|
39
35
|
},
|
|
40
36
|
"scripts": {
|
|
41
37
|
"dev": "tsup --watch",
|
package/dist/server.cjs
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var codexSdk = require('@openai/codex-sdk');
|
|
4
|
-
var fkill = require('fkill');
|
|
5
|
-
var hono = require('hono');
|
|
6
|
-
var cors = require('hono/cors');
|
|
7
|
-
var streaming = require('hono/streaming');
|
|
8
|
-
var nodeServer = require('@hono/node-server');
|
|
9
|
-
var pc = require('picocolors');
|
|
10
|
-
var url = require('url');
|
|
11
|
-
|
|
12
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
13
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
-
|
|
15
|
-
var fkill__default = /*#__PURE__*/_interopDefault(fkill);
|
|
16
|
-
var pc__default = /*#__PURE__*/_interopDefault(pc);
|
|
17
|
-
|
|
18
|
-
// src/server.ts
|
|
19
|
-
|
|
20
|
-
// src/constants.ts
|
|
21
|
-
var DEFAULT_PORT = 7567;
|
|
22
|
-
var COMPLETED_STATUS = "Completed successfully";
|
|
23
|
-
|
|
24
|
-
// ../utils/dist/server.js
|
|
25
|
-
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
26
|
-
var VERSION = "0.0.97";
|
|
27
|
-
try {
|
|
28
|
-
fetch(
|
|
29
|
-
`https://www.react-grab.com/api/version?source=codex&t=${Date.now()}`
|
|
30
|
-
).catch(() => {
|
|
31
|
-
});
|
|
32
|
-
} catch {
|
|
33
|
-
}
|
|
34
|
-
var codexInstance = null;
|
|
35
|
-
var threadMap = /* @__PURE__ */ new Map();
|
|
36
|
-
var abortControllers = /* @__PURE__ */ new Map();
|
|
37
|
-
var lastThreadId;
|
|
38
|
-
var getCodexInstance = () => {
|
|
39
|
-
if (!codexInstance) {
|
|
40
|
-
codexInstance = new codexSdk.Codex();
|
|
41
|
-
}
|
|
42
|
-
return codexInstance;
|
|
43
|
-
};
|
|
44
|
-
var getOrCreateThread = (sessionId, options) => {
|
|
45
|
-
const codex = getCodexInstance();
|
|
46
|
-
if (sessionId && threadMap.has(sessionId)) {
|
|
47
|
-
return { thread: threadMap.get(sessionId).thread, isExisting: true };
|
|
48
|
-
}
|
|
49
|
-
const thread = codex.startThread({
|
|
50
|
-
workingDirectory: options?.workingDirectory ?? process.env.REACT_GRAB_CWD ?? process.cwd()
|
|
51
|
-
});
|
|
52
|
-
return { thread, isExisting: false };
|
|
53
|
-
};
|
|
54
|
-
var formatStreamEvent = (event) => {
|
|
55
|
-
switch (event.type) {
|
|
56
|
-
case "item.completed":
|
|
57
|
-
if (event.item?.type === "agent_message" && event.item.text) {
|
|
58
|
-
return event.item.text;
|
|
59
|
-
}
|
|
60
|
-
if (event.item?.type === "command_execution" && event.item.command) {
|
|
61
|
-
return `Executed: ${event.item.command}`;
|
|
62
|
-
}
|
|
63
|
-
return void 0;
|
|
64
|
-
case "turn.completed":
|
|
65
|
-
return void 0;
|
|
66
|
-
default:
|
|
67
|
-
return void 0;
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
var runAgent = async function* (prompt, options) {
|
|
71
|
-
const sessionId = options?.sessionId;
|
|
72
|
-
const abortController = new AbortController();
|
|
73
|
-
if (sessionId) {
|
|
74
|
-
abortControllers.set(sessionId, abortController);
|
|
75
|
-
}
|
|
76
|
-
const isAborted = () => {
|
|
77
|
-
if (options?.signal?.aborted) return true;
|
|
78
|
-
if (abortController.signal.aborted) return true;
|
|
79
|
-
return false;
|
|
80
|
-
};
|
|
81
|
-
try {
|
|
82
|
-
yield { type: "status", content: "Thinking\u2026" };
|
|
83
|
-
const { thread } = getOrCreateThread(sessionId, {
|
|
84
|
-
...options,
|
|
85
|
-
workingDirectory: options?.workingDirectory ?? options?.cwd
|
|
86
|
-
});
|
|
87
|
-
if (sessionId && thread.id) {
|
|
88
|
-
lastThreadId = thread.id;
|
|
89
|
-
}
|
|
90
|
-
const { events } = await thread.runStreamed(prompt);
|
|
91
|
-
for await (const event of events) {
|
|
92
|
-
if (isAborted()) break;
|
|
93
|
-
const statusText = formatStreamEvent(event);
|
|
94
|
-
if (statusText && !isAborted()) {
|
|
95
|
-
yield { type: "status", content: statusText };
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (sessionId && !isAborted() && thread.id) {
|
|
99
|
-
threadMap.set(sessionId, { thread, threadId: thread.id });
|
|
100
|
-
}
|
|
101
|
-
if (!isAborted()) {
|
|
102
|
-
yield { type: "status", content: COMPLETED_STATUS };
|
|
103
|
-
yield { type: "done", content: "" };
|
|
104
|
-
}
|
|
105
|
-
} catch (error) {
|
|
106
|
-
if (!isAborted()) {
|
|
107
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
108
|
-
yield { type: "error", content: errorMessage };
|
|
109
|
-
yield { type: "done", content: "" };
|
|
110
|
-
}
|
|
111
|
-
} finally {
|
|
112
|
-
if (sessionId) {
|
|
113
|
-
abortControllers.delete(sessionId);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
var createServer = () => {
|
|
118
|
-
const honoApplication = new hono.Hono();
|
|
119
|
-
honoApplication.use("*", cors.cors());
|
|
120
|
-
honoApplication.post("/agent", async (context) => {
|
|
121
|
-
const requestBody = await context.req.json();
|
|
122
|
-
const { content, prompt, options, sessionId } = requestBody;
|
|
123
|
-
const isFollowUp = Boolean(sessionId && threadMap.has(sessionId));
|
|
124
|
-
const contentItems = Array.isArray(content) ? content : [content];
|
|
125
|
-
return streaming.streamSSE(context, async (stream) => {
|
|
126
|
-
if (isFollowUp) {
|
|
127
|
-
for await (const message of runAgent(prompt, {
|
|
128
|
-
...options,
|
|
129
|
-
sessionId
|
|
130
|
-
})) {
|
|
131
|
-
if (message.type === "error") {
|
|
132
|
-
await stream.writeSSE({
|
|
133
|
-
data: `Error: ${message.content}`,
|
|
134
|
-
event: "error"
|
|
135
|
-
});
|
|
136
|
-
} else {
|
|
137
|
-
await stream.writeSSE({
|
|
138
|
-
data: message.content,
|
|
139
|
-
event: message.type
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
for (let i = 0; i < contentItems.length; i++) {
|
|
146
|
-
const elementContent = contentItems[i];
|
|
147
|
-
const formattedPrompt = `User Request: ${prompt}
|
|
148
|
-
|
|
149
|
-
Context:
|
|
150
|
-
${elementContent}`;
|
|
151
|
-
if (contentItems.length > 1) {
|
|
152
|
-
await stream.writeSSE({
|
|
153
|
-
data: `Processing element ${i + 1} of ${contentItems.length}...`,
|
|
154
|
-
event: "status"
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
for await (const message of runAgent(formattedPrompt, {
|
|
158
|
-
...options,
|
|
159
|
-
sessionId
|
|
160
|
-
})) {
|
|
161
|
-
if (message.type === "error") {
|
|
162
|
-
await stream.writeSSE({
|
|
163
|
-
data: `Error: ${message.content}`,
|
|
164
|
-
event: "error"
|
|
165
|
-
});
|
|
166
|
-
} else {
|
|
167
|
-
await stream.writeSSE({
|
|
168
|
-
data: message.content,
|
|
169
|
-
event: message.type
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
honoApplication.post("/abort/:sessionId", (context) => {
|
|
177
|
-
const { sessionId } = context.req.param();
|
|
178
|
-
const abortController = abortControllers.get(sessionId);
|
|
179
|
-
if (abortController) {
|
|
180
|
-
abortController.abort();
|
|
181
|
-
abortControllers.delete(sessionId);
|
|
182
|
-
}
|
|
183
|
-
return context.json({ status: "ok" });
|
|
184
|
-
});
|
|
185
|
-
honoApplication.post("/undo", async (context) => {
|
|
186
|
-
if (!lastThreadId) {
|
|
187
|
-
return context.json({ status: "error", message: "No thread to undo" });
|
|
188
|
-
}
|
|
189
|
-
try {
|
|
190
|
-
const codex = getCodexInstance();
|
|
191
|
-
const thread = codex.resumeThread(lastThreadId);
|
|
192
|
-
await thread.run("Please undo the last change you made.");
|
|
193
|
-
return context.json({ status: "ok" });
|
|
194
|
-
} catch (error) {
|
|
195
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
196
|
-
return context.json({ status: "error", message: errorMessage });
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
honoApplication.get("/health", (context) => {
|
|
200
|
-
return context.json({ status: "ok", provider: "codex" });
|
|
201
|
-
});
|
|
202
|
-
return honoApplication;
|
|
203
|
-
};
|
|
204
|
-
var startServer = async (port = DEFAULT_PORT) => {
|
|
205
|
-
await fkill__default.default(`:${port}`, { force: true, silent: true }).catch(() => {
|
|
206
|
-
});
|
|
207
|
-
await sleep(100);
|
|
208
|
-
const honoApplication = createServer();
|
|
209
|
-
nodeServer.serve({ fetch: honoApplication.fetch, port });
|
|
210
|
-
console.log(
|
|
211
|
-
`${pc__default.default.magenta("\u273F")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION)} ${pc__default.default.dim("(Codex)")}`
|
|
212
|
-
);
|
|
213
|
-
console.log(`- Local: ${pc__default.default.cyan(`http://localhost:${port}`)}`);
|
|
214
|
-
};
|
|
215
|
-
if ((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('server.cjs', document.baseURI).href)) === url.pathToFileURL(process.argv[1]).href) {
|
|
216
|
-
startServer(DEFAULT_PORT).catch(console.error);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
exports.createServer = createServer;
|
|
220
|
-
exports.runAgent = runAgent;
|
|
221
|
-
exports.startServer = startServer;
|
package/dist/server.d.cts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import * as hono_types from 'hono/types';
|
|
2
|
-
import { Hono } from 'hono';
|
|
3
|
-
import { AgentCoreOptions, AgentMessage } from '@react-grab/utils/server';
|
|
4
|
-
|
|
5
|
-
interface CodexAgentOptions extends AgentCoreOptions {
|
|
6
|
-
model?: string;
|
|
7
|
-
workingDirectory?: string;
|
|
8
|
-
}
|
|
9
|
-
declare const runAgent: (prompt: string, options?: CodexAgentOptions) => AsyncGenerator<AgentMessage>;
|
|
10
|
-
declare const createServer: () => Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
11
|
-
declare const startServer: (port?: number) => Promise<void>;
|
|
12
|
-
|
|
13
|
-
export { type CodexAgentOptions, createServer, runAgent, startServer };
|
package/dist/server.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import * as hono_types from 'hono/types';
|
|
2
|
-
import { Hono } from 'hono';
|
|
3
|
-
import { AgentCoreOptions, AgentMessage } from '@react-grab/utils/server';
|
|
4
|
-
|
|
5
|
-
interface CodexAgentOptions extends AgentCoreOptions {
|
|
6
|
-
model?: string;
|
|
7
|
-
workingDirectory?: string;
|
|
8
|
-
}
|
|
9
|
-
declare const runAgent: (prompt: string, options?: CodexAgentOptions) => AsyncGenerator<AgentMessage>;
|
|
10
|
-
declare const createServer: () => Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
11
|
-
declare const startServer: (port?: number) => Promise<void>;
|
|
12
|
-
|
|
13
|
-
export { type CodexAgentOptions, createServer, runAgent, startServer };
|
package/dist/server.js
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { Codex } from '@openai/codex-sdk';
|
|
2
|
-
import fkill from 'fkill';
|
|
3
|
-
import { Hono } from 'hono';
|
|
4
|
-
import { cors } from 'hono/cors';
|
|
5
|
-
import { streamSSE } from 'hono/streaming';
|
|
6
|
-
import { serve } from '@hono/node-server';
|
|
7
|
-
import pc from 'picocolors';
|
|
8
|
-
import { pathToFileURL } from 'url';
|
|
9
|
-
|
|
10
|
-
// src/server.ts
|
|
11
|
-
|
|
12
|
-
// src/constants.ts
|
|
13
|
-
var DEFAULT_PORT = 7567;
|
|
14
|
-
var COMPLETED_STATUS = "Completed successfully";
|
|
15
|
-
|
|
16
|
-
// ../utils/dist/server.js
|
|
17
|
-
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
|
-
var VERSION = "0.0.97";
|
|
19
|
-
try {
|
|
20
|
-
fetch(
|
|
21
|
-
`https://www.react-grab.com/api/version?source=codex&t=${Date.now()}`
|
|
22
|
-
).catch(() => {
|
|
23
|
-
});
|
|
24
|
-
} catch {
|
|
25
|
-
}
|
|
26
|
-
var codexInstance = null;
|
|
27
|
-
var threadMap = /* @__PURE__ */ new Map();
|
|
28
|
-
var abortControllers = /* @__PURE__ */ new Map();
|
|
29
|
-
var lastThreadId;
|
|
30
|
-
var getCodexInstance = () => {
|
|
31
|
-
if (!codexInstance) {
|
|
32
|
-
codexInstance = new Codex();
|
|
33
|
-
}
|
|
34
|
-
return codexInstance;
|
|
35
|
-
};
|
|
36
|
-
var getOrCreateThread = (sessionId, options) => {
|
|
37
|
-
const codex = getCodexInstance();
|
|
38
|
-
if (sessionId && threadMap.has(sessionId)) {
|
|
39
|
-
return { thread: threadMap.get(sessionId).thread, isExisting: true };
|
|
40
|
-
}
|
|
41
|
-
const thread = codex.startThread({
|
|
42
|
-
workingDirectory: options?.workingDirectory ?? process.env.REACT_GRAB_CWD ?? process.cwd()
|
|
43
|
-
});
|
|
44
|
-
return { thread, isExisting: false };
|
|
45
|
-
};
|
|
46
|
-
var formatStreamEvent = (event) => {
|
|
47
|
-
switch (event.type) {
|
|
48
|
-
case "item.completed":
|
|
49
|
-
if (event.item?.type === "agent_message" && event.item.text) {
|
|
50
|
-
return event.item.text;
|
|
51
|
-
}
|
|
52
|
-
if (event.item?.type === "command_execution" && event.item.command) {
|
|
53
|
-
return `Executed: ${event.item.command}`;
|
|
54
|
-
}
|
|
55
|
-
return void 0;
|
|
56
|
-
case "turn.completed":
|
|
57
|
-
return void 0;
|
|
58
|
-
default:
|
|
59
|
-
return void 0;
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
var runAgent = async function* (prompt, options) {
|
|
63
|
-
const sessionId = options?.sessionId;
|
|
64
|
-
const abortController = new AbortController();
|
|
65
|
-
if (sessionId) {
|
|
66
|
-
abortControllers.set(sessionId, abortController);
|
|
67
|
-
}
|
|
68
|
-
const isAborted = () => {
|
|
69
|
-
if (options?.signal?.aborted) return true;
|
|
70
|
-
if (abortController.signal.aborted) return true;
|
|
71
|
-
return false;
|
|
72
|
-
};
|
|
73
|
-
try {
|
|
74
|
-
yield { type: "status", content: "Thinking\u2026" };
|
|
75
|
-
const { thread } = getOrCreateThread(sessionId, {
|
|
76
|
-
...options,
|
|
77
|
-
workingDirectory: options?.workingDirectory ?? options?.cwd
|
|
78
|
-
});
|
|
79
|
-
if (sessionId && thread.id) {
|
|
80
|
-
lastThreadId = thread.id;
|
|
81
|
-
}
|
|
82
|
-
const { events } = await thread.runStreamed(prompt);
|
|
83
|
-
for await (const event of events) {
|
|
84
|
-
if (isAborted()) break;
|
|
85
|
-
const statusText = formatStreamEvent(event);
|
|
86
|
-
if (statusText && !isAborted()) {
|
|
87
|
-
yield { type: "status", content: statusText };
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
if (sessionId && !isAborted() && thread.id) {
|
|
91
|
-
threadMap.set(sessionId, { thread, threadId: thread.id });
|
|
92
|
-
}
|
|
93
|
-
if (!isAborted()) {
|
|
94
|
-
yield { type: "status", content: COMPLETED_STATUS };
|
|
95
|
-
yield { type: "done", content: "" };
|
|
96
|
-
}
|
|
97
|
-
} catch (error) {
|
|
98
|
-
if (!isAborted()) {
|
|
99
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
100
|
-
yield { type: "error", content: errorMessage };
|
|
101
|
-
yield { type: "done", content: "" };
|
|
102
|
-
}
|
|
103
|
-
} finally {
|
|
104
|
-
if (sessionId) {
|
|
105
|
-
abortControllers.delete(sessionId);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
var createServer = () => {
|
|
110
|
-
const honoApplication = new Hono();
|
|
111
|
-
honoApplication.use("*", cors());
|
|
112
|
-
honoApplication.post("/agent", async (context) => {
|
|
113
|
-
const requestBody = await context.req.json();
|
|
114
|
-
const { content, prompt, options, sessionId } = requestBody;
|
|
115
|
-
const isFollowUp = Boolean(sessionId && threadMap.has(sessionId));
|
|
116
|
-
const contentItems = Array.isArray(content) ? content : [content];
|
|
117
|
-
return streamSSE(context, async (stream) => {
|
|
118
|
-
if (isFollowUp) {
|
|
119
|
-
for await (const message of runAgent(prompt, {
|
|
120
|
-
...options,
|
|
121
|
-
sessionId
|
|
122
|
-
})) {
|
|
123
|
-
if (message.type === "error") {
|
|
124
|
-
await stream.writeSSE({
|
|
125
|
-
data: `Error: ${message.content}`,
|
|
126
|
-
event: "error"
|
|
127
|
-
});
|
|
128
|
-
} else {
|
|
129
|
-
await stream.writeSSE({
|
|
130
|
-
data: message.content,
|
|
131
|
-
event: message.type
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
for (let i = 0; i < contentItems.length; i++) {
|
|
138
|
-
const elementContent = contentItems[i];
|
|
139
|
-
const formattedPrompt = `User Request: ${prompt}
|
|
140
|
-
|
|
141
|
-
Context:
|
|
142
|
-
${elementContent}`;
|
|
143
|
-
if (contentItems.length > 1) {
|
|
144
|
-
await stream.writeSSE({
|
|
145
|
-
data: `Processing element ${i + 1} of ${contentItems.length}...`,
|
|
146
|
-
event: "status"
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
for await (const message of runAgent(formattedPrompt, {
|
|
150
|
-
...options,
|
|
151
|
-
sessionId
|
|
152
|
-
})) {
|
|
153
|
-
if (message.type === "error") {
|
|
154
|
-
await stream.writeSSE({
|
|
155
|
-
data: `Error: ${message.content}`,
|
|
156
|
-
event: "error"
|
|
157
|
-
});
|
|
158
|
-
} else {
|
|
159
|
-
await stream.writeSSE({
|
|
160
|
-
data: message.content,
|
|
161
|
-
event: message.type
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
honoApplication.post("/abort/:sessionId", (context) => {
|
|
169
|
-
const { sessionId } = context.req.param();
|
|
170
|
-
const abortController = abortControllers.get(sessionId);
|
|
171
|
-
if (abortController) {
|
|
172
|
-
abortController.abort();
|
|
173
|
-
abortControllers.delete(sessionId);
|
|
174
|
-
}
|
|
175
|
-
return context.json({ status: "ok" });
|
|
176
|
-
});
|
|
177
|
-
honoApplication.post("/undo", async (context) => {
|
|
178
|
-
if (!lastThreadId) {
|
|
179
|
-
return context.json({ status: "error", message: "No thread to undo" });
|
|
180
|
-
}
|
|
181
|
-
try {
|
|
182
|
-
const codex = getCodexInstance();
|
|
183
|
-
const thread = codex.resumeThread(lastThreadId);
|
|
184
|
-
await thread.run("Please undo the last change you made.");
|
|
185
|
-
return context.json({ status: "ok" });
|
|
186
|
-
} catch (error) {
|
|
187
|
-
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
188
|
-
return context.json({ status: "error", message: errorMessage });
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
honoApplication.get("/health", (context) => {
|
|
192
|
-
return context.json({ status: "ok", provider: "codex" });
|
|
193
|
-
});
|
|
194
|
-
return honoApplication;
|
|
195
|
-
};
|
|
196
|
-
var startServer = async (port = DEFAULT_PORT) => {
|
|
197
|
-
await fkill(`:${port}`, { force: true, silent: true }).catch(() => {
|
|
198
|
-
});
|
|
199
|
-
await sleep(100);
|
|
200
|
-
const honoApplication = createServer();
|
|
201
|
-
serve({ fetch: honoApplication.fetch, port });
|
|
202
|
-
console.log(
|
|
203
|
-
`${pc.magenta("\u273F")} ${pc.bold("React Grab")} ${pc.gray(VERSION)} ${pc.dim("(Codex)")}`
|
|
204
|
-
);
|
|
205
|
-
console.log(`- Local: ${pc.cyan(`http://localhost:${port}`)}`);
|
|
206
|
-
};
|
|
207
|
-
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
208
|
-
startServer(DEFAULT_PORT).catch(console.error);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export { createServer, runAgent, startServer };
|