@openai-lite/codex-feishu 0.1.5 → 0.1.6
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/package.json +1 -1
- package/src/commands/daemon.js +7 -0
- package/src/lib/app_server_client.js +41 -15
- package/src/lib/daemon_control.js +20 -2
package/package.json
CHANGED
package/src/commands/daemon.js
CHANGED
|
@@ -5944,6 +5944,13 @@ export async function runDaemon() {
|
|
|
5944
5944
|
signal: info.signal ?? null,
|
|
5945
5945
|
});
|
|
5946
5946
|
});
|
|
5947
|
+
app.on("error", async (err) => {
|
|
5948
|
+
await appendEvent(store, {
|
|
5949
|
+
source: "app_server",
|
|
5950
|
+
type: "error",
|
|
5951
|
+
error: err?.message ?? String(err),
|
|
5952
|
+
});
|
|
5953
|
+
});
|
|
5947
5954
|
|
|
5948
5955
|
try {
|
|
5949
5956
|
await app.ensureStarted();
|
|
@@ -2,6 +2,17 @@ import { EventEmitter, once } from "node:events";
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import readline from "node:readline";
|
|
4
4
|
|
|
5
|
+
function getCodexSpawnOptions(base = {}) {
|
|
6
|
+
if (process.platform === "win32") {
|
|
7
|
+
return {
|
|
8
|
+
...base,
|
|
9
|
+
// Windows commonly resolves codex via codex.cmd; shell mode keeps it executable.
|
|
10
|
+
shell: true,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
return base;
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
function normalizeJsonRpcPayload(payload) {
|
|
6
17
|
if (!payload || typeof payload !== "object") {
|
|
7
18
|
return null;
|
|
@@ -77,10 +88,14 @@ async function probeSubcommand(codexBin, args, timeoutMs = 2_500) {
|
|
|
77
88
|
let stdout = "";
|
|
78
89
|
let stderr = "";
|
|
79
90
|
let timer = null;
|
|
80
|
-
const child = spawn(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
const child = spawn(
|
|
92
|
+
codexBin,
|
|
93
|
+
args,
|
|
94
|
+
getCodexSpawnOptions({
|
|
95
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
96
|
+
env: process.env,
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
84
99
|
child.stdout.on("data", (chunk) => {
|
|
85
100
|
stdout += chunk.toString("utf8");
|
|
86
101
|
});
|
|
@@ -135,7 +150,10 @@ async function probeSubcommand(codexBin, args, timeoutMs = 2_500) {
|
|
|
135
150
|
export class AppServerClient extends EventEmitter {
|
|
136
151
|
constructor(options = {}) {
|
|
137
152
|
super();
|
|
138
|
-
this.codexBin =
|
|
153
|
+
this.codexBin =
|
|
154
|
+
options.codexBin ||
|
|
155
|
+
process.env.CODEX_BIN ||
|
|
156
|
+
(process.platform === "win32" ? "codex.cmd" : "codex");
|
|
139
157
|
this.transport = options.transport || process.env.CODEX_FEISHU_TRANSPORT || "auto";
|
|
140
158
|
this.protoCwd = options.protoCwd || process.env.CODEX_FEISHU_CWD || process.cwd();
|
|
141
159
|
this.protoModel = options.protoModel || process.env.CODEX_FEISHU_MODEL || "gpt-5.3-codex";
|
|
@@ -236,11 +254,15 @@ export class AppServerClient extends EventEmitter {
|
|
|
236
254
|
}
|
|
237
255
|
|
|
238
256
|
async startLegacyAppServer() {
|
|
239
|
-
const child = spawn(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
257
|
+
const child = spawn(
|
|
258
|
+
this.codexBin,
|
|
259
|
+
["app-server", "--listen", "stdio://"],
|
|
260
|
+
getCodexSpawnOptions({
|
|
261
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
262
|
+
env: process.env,
|
|
263
|
+
cwd: this.protoCwd,
|
|
264
|
+
}),
|
|
265
|
+
);
|
|
244
266
|
this.process = child;
|
|
245
267
|
|
|
246
268
|
child.on("error", (err) => {
|
|
@@ -309,11 +331,15 @@ export class AppServerClient extends EventEmitter {
|
|
|
309
331
|
}
|
|
310
332
|
|
|
311
333
|
async startProto() {
|
|
312
|
-
const child = spawn(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
334
|
+
const child = spawn(
|
|
335
|
+
this.codexBin,
|
|
336
|
+
["proto"],
|
|
337
|
+
getCodexSpawnOptions({
|
|
338
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
339
|
+
env: process.env,
|
|
340
|
+
cwd: this.protoCwd,
|
|
341
|
+
}),
|
|
342
|
+
);
|
|
317
343
|
this.process = child;
|
|
318
344
|
this.protoReady = {};
|
|
319
345
|
|
|
@@ -56,6 +56,22 @@ async function isDaemonRpcResponsive(timeoutMs = 1000) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
async function readLogTail(logPath, maxLines = 60) {
|
|
60
|
+
try {
|
|
61
|
+
const text = await readTextIfExists(logPath);
|
|
62
|
+
if (!text) {
|
|
63
|
+
return "";
|
|
64
|
+
}
|
|
65
|
+
const lines = text
|
|
66
|
+
.split(/\r?\n/)
|
|
67
|
+
.filter((line) => line.trim().length > 0)
|
|
68
|
+
.slice(-maxLines);
|
|
69
|
+
return lines.join("\n");
|
|
70
|
+
} catch {
|
|
71
|
+
return "";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
59
75
|
async function stopByPid(pid, timeoutMs = 3000) {
|
|
60
76
|
if (!isPidAlive(pid)) {
|
|
61
77
|
return { action: "already_stopped", pid };
|
|
@@ -201,7 +217,7 @@ export async function restartDaemonDetached() {
|
|
|
201
217
|
for (const cliEntry of candidateEntries) {
|
|
202
218
|
attempts.push([process.execPath, [cliEntry, "daemon"]]);
|
|
203
219
|
}
|
|
204
|
-
attempts.push(["
|
|
220
|
+
attempts.push(["cmd.exe", ["/d", "/s", "/c", "codex-feishu daemon"]]);
|
|
205
221
|
} else {
|
|
206
222
|
attempts.push(["codex-feishu", ["daemon"]]);
|
|
207
223
|
for (const cliEntry of candidateEntries) {
|
|
@@ -234,8 +250,10 @@ export async function restartDaemonDetached() {
|
|
|
234
250
|
failedAttempts.push(`${cmd} ${args.join(" ")} => ${startResult.error}`);
|
|
235
251
|
}
|
|
236
252
|
if (!startResult.ok) {
|
|
253
|
+
const logTail = await readLogTail(logPath, 80);
|
|
237
254
|
const details = failedAttempts.length > 0 ? `; attempts: ${failedAttempts.join(" | ")}` : "";
|
|
238
|
-
|
|
255
|
+
const logHint = logTail ? `; daemon.log tail:\n${logTail}` : "";
|
|
256
|
+
throw new Error(`failed to start daemon in background: ${startResult.error}${details}${logHint}`);
|
|
239
257
|
}
|
|
240
258
|
|
|
241
259
|
if (startResult.pid) {
|