@modelzen/feishu-codex-bridge 0.3.0 → 0.3.1
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.js +301 -32
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -228,6 +228,21 @@ function findBot(reg, nameOrAppId) {
|
|
|
228
228
|
function currentBot(reg) {
|
|
229
229
|
return reg.current ? reg.bots.find((b) => b.appId === reg.current) : void 0;
|
|
230
230
|
}
|
|
231
|
+
function activeBots(reg) {
|
|
232
|
+
const configured = reg.bots.some((b) => b.active !== void 0);
|
|
233
|
+
if (configured) return reg.bots.filter((b) => b.active === true);
|
|
234
|
+
const cur = currentBot(reg);
|
|
235
|
+
return cur ? [cur] : [];
|
|
236
|
+
}
|
|
237
|
+
async function setActiveBots(appIds) {
|
|
238
|
+
const reg = await loadBots();
|
|
239
|
+
const want = new Set(appIds);
|
|
240
|
+
for (const b of reg.bots) b.active = want.has(b.appId);
|
|
241
|
+
const firstActive = reg.bots.find((b) => b.active);
|
|
242
|
+
if (firstActive) reg.current = firstActive.appId;
|
|
243
|
+
await saveBots(reg);
|
|
244
|
+
return reg;
|
|
245
|
+
}
|
|
231
246
|
async function addBot(entry) {
|
|
232
247
|
const reg = await loadBots();
|
|
233
248
|
reg.bots = reg.bots.filter((b) => b.appId !== entry.appId);
|
|
@@ -236,11 +251,6 @@ async function addBot(entry) {
|
|
|
236
251
|
await saveBots(reg);
|
|
237
252
|
return reg;
|
|
238
253
|
}
|
|
239
|
-
async function setCurrent(appId) {
|
|
240
|
-
const reg = await loadBots();
|
|
241
|
-
reg.current = appId;
|
|
242
|
-
await saveBots(reg);
|
|
243
|
-
}
|
|
244
254
|
async function removeBot(appId) {
|
|
245
255
|
const reg = await loadBots();
|
|
246
256
|
reg.bots = reg.bots.filter((b) => b.appId !== appId);
|
|
@@ -1026,8 +1036,14 @@ function ensureCodex() {
|
|
|
1026
1036
|
async function ensureOnboarded(opts = {}) {
|
|
1027
1037
|
if (!ensureCodex()) return null;
|
|
1028
1038
|
const reg = await ensureRegistry();
|
|
1029
|
-
const entry = currentBot(reg);
|
|
1039
|
+
const entry = opts.bot ? findBot(reg, opts.bot) : currentBot(reg);
|
|
1030
1040
|
if (!entry) {
|
|
1041
|
+
if (opts.bot) {
|
|
1042
|
+
console.error(
|
|
1043
|
+
`\u2717 \u627E\u4E0D\u5230\u673A\u5668\u4EBA\u300C${opts.bot}\u300D\u3002\u7528 \`feishu-codex-bridge bot list\` \u67E5\u770B\u5DF2\u6CE8\u518C\u7684\u673A\u5668\u4EBA\u3002`
|
|
1044
|
+
);
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1031
1047
|
if (!opts.allowCreate) {
|
|
1032
1048
|
console.error("\u2717 \u5C1A\u672A\u914D\u7F6E\u4EFB\u4F55\u98DE\u4E66\u673A\u5668\u4EBA\u3002\u8BF7\u5148\u8FD0\u884C `feishu-codex-bridge bot init`\uFF08\u6216\u524D\u53F0 `run`\uFF09\u626B\u7801\u521B\u5EFA\u3002");
|
|
1033
1049
|
return null;
|
|
@@ -5956,6 +5972,94 @@ async function startBridge(opts) {
|
|
|
5956
5972
|
return { channel, shutdown };
|
|
5957
5973
|
}
|
|
5958
5974
|
|
|
5975
|
+
// src/bot/supervisor.ts
|
|
5976
|
+
var BACKOFF_MIN_MS = 1e3;
|
|
5977
|
+
var BACKOFF_MAX_MS = 3e4;
|
|
5978
|
+
var HEALTHY_UPTIME_MS = 6e4;
|
|
5979
|
+
var SHUTDOWN_GRACE_MS = 8e3;
|
|
5980
|
+
async function runSupervisor(bots) {
|
|
5981
|
+
const cliEntry = process.argv[1];
|
|
5982
|
+
if (!cliEntry) throw new Error("supervisor: \u65E0\u6CD5\u89E3\u6790 CLI \u5165\u53E3\uFF08process.argv[1] \u4E3A\u7A7A\uFF09");
|
|
5983
|
+
const childEnv = { ...process.env };
|
|
5984
|
+
delete childEnv[SERVICE_ENV_FLAG];
|
|
5985
|
+
let shuttingDown = false;
|
|
5986
|
+
const children = bots.map((bot2) => ({ bot: bot2, backoffMs: BACKOFF_MIN_MS, startedAt: 0 }));
|
|
5987
|
+
console.log(`
|
|
5988
|
+
\u6B63\u5728\u542F\u52A8 ${bots.length} \u4E2A\u673A\u5668\u4EBA\uFF08\u5404\u81EA\u72EC\u7ACB\u8FDB\u7A0B\uFF09\uFF1A`);
|
|
5989
|
+
for (const b of bots) console.log(` \u2022 ${b.name} (${b.appId}) [${b.tenant}]`);
|
|
5990
|
+
console.log("Ctrl+C \u9000\u51FA\uFF08\u5173\u95ED\u5168\u90E8\uFF09\u3002\n");
|
|
5991
|
+
const prefixPipe = (name, src, dst) => {
|
|
5992
|
+
if (!src) return;
|
|
5993
|
+
let buf = "";
|
|
5994
|
+
src.setEncoding("utf8");
|
|
5995
|
+
src.on("data", (chunk) => {
|
|
5996
|
+
buf += chunk;
|
|
5997
|
+
let nl;
|
|
5998
|
+
while ((nl = buf.indexOf("\n")) >= 0) {
|
|
5999
|
+
const line = buf.slice(0, nl);
|
|
6000
|
+
buf = buf.slice(nl + 1);
|
|
6001
|
+
dst.write(`\x1B[2m[${name}]\x1B[0m ${line}
|
|
6002
|
+
`);
|
|
6003
|
+
}
|
|
6004
|
+
});
|
|
6005
|
+
src.on("end", () => {
|
|
6006
|
+
if (buf) dst.write(`\x1B[2m[${name}]\x1B[0m ${buf}
|
|
6007
|
+
`);
|
|
6008
|
+
});
|
|
6009
|
+
};
|
|
6010
|
+
const spawnChild = (c) => {
|
|
6011
|
+
c.startedAt = Date.now();
|
|
6012
|
+
const proc = spawnProcess(process.execPath, [cliEntry, "run", "--bot", c.bot.appId], {
|
|
6013
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
6014
|
+
env: childEnv
|
|
6015
|
+
});
|
|
6016
|
+
c.proc = proc;
|
|
6017
|
+
log.info("supervisor", "child-start", { bot: c.bot.name, appId: c.bot.appId, pid: proc.pid ?? null });
|
|
6018
|
+
prefixPipe(c.bot.name, proc.stdout, process.stdout);
|
|
6019
|
+
prefixPipe(c.bot.name, proc.stderr, process.stderr);
|
|
6020
|
+
proc.on("exit", (code, signal) => {
|
|
6021
|
+
c.proc = void 0;
|
|
6022
|
+
if (shuttingDown) return;
|
|
6023
|
+
const uptime = Date.now() - c.startedAt;
|
|
6024
|
+
if (uptime >= HEALTHY_UPTIME_MS) c.backoffMs = BACKOFF_MIN_MS;
|
|
6025
|
+
const wait = c.backoffMs;
|
|
6026
|
+
c.backoffMs = Math.min(c.backoffMs * 2, BACKOFF_MAX_MS);
|
|
6027
|
+
log.warn("supervisor", "child-exit", { bot: c.bot.name, code, signal, restartInMs: wait });
|
|
6028
|
+
console.error(
|
|
6029
|
+
`\x1B[2m[${c.bot.name}]\x1B[0m \u8FDB\u7A0B\u9000\u51FA\uFF08code=${code ?? signal ?? "?"}\uFF09\uFF0C${Math.round(wait / 1e3)}s \u540E\u91CD\u542F\u2026`
|
|
6030
|
+
);
|
|
6031
|
+
c.restartTimer = setTimeout(() => spawnChild(c), wait);
|
|
6032
|
+
});
|
|
6033
|
+
proc.on("error", (err) => {
|
|
6034
|
+
log.fail("supervisor", err, { bot: c.bot.name, phase: "spawn" });
|
|
6035
|
+
});
|
|
6036
|
+
};
|
|
6037
|
+
for (const c of children) spawnChild(c);
|
|
6038
|
+
await new Promise((resolve7) => {
|
|
6039
|
+
const stop = (sig) => {
|
|
6040
|
+
if (shuttingDown) return;
|
|
6041
|
+
shuttingDown = true;
|
|
6042
|
+
console.log(`
|
|
6043
|
+
\u6536\u5230 ${sig}\uFF0C\u6B63\u5728\u5173\u95ED\u5168\u90E8\u673A\u5668\u4EBA\u2026`);
|
|
6044
|
+
for (const c of children) {
|
|
6045
|
+
if (c.restartTimer) clearTimeout(c.restartTimer);
|
|
6046
|
+
c.proc?.kill("SIGTERM");
|
|
6047
|
+
}
|
|
6048
|
+
const deadline = Date.now() + SHUTDOWN_GRACE_MS;
|
|
6049
|
+
const poll = setInterval(() => {
|
|
6050
|
+
const alive = children.filter((c) => c.proc && !c.proc.killed);
|
|
6051
|
+
if (alive.length === 0 || Date.now() >= deadline) {
|
|
6052
|
+
clearInterval(poll);
|
|
6053
|
+
for (const c of alive) c.proc?.kill("SIGKILL");
|
|
6054
|
+
resolve7();
|
|
6055
|
+
}
|
|
6056
|
+
}, 200);
|
|
6057
|
+
};
|
|
6058
|
+
for (const sig of ["SIGINT", "SIGTERM"]) process.once(sig, () => stop(sig));
|
|
6059
|
+
});
|
|
6060
|
+
process.exit(0);
|
|
6061
|
+
}
|
|
6062
|
+
|
|
5959
6063
|
// src/core/single-instance.ts
|
|
5960
6064
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
5961
6065
|
import { dirname as dirname11 } from "path";
|
|
@@ -6003,8 +6107,20 @@ function acquireSingleInstanceLock(appId) {
|
|
|
6003
6107
|
}
|
|
6004
6108
|
|
|
6005
6109
|
// src/cli/commands/run.ts
|
|
6006
|
-
async function runRun() {
|
|
6007
|
-
|
|
6110
|
+
async function runRun(botName) {
|
|
6111
|
+
if (botName) {
|
|
6112
|
+
await runSingle(botName);
|
|
6113
|
+
return;
|
|
6114
|
+
}
|
|
6115
|
+
const active = activeBots(await loadBots());
|
|
6116
|
+
if (active.length > 1) {
|
|
6117
|
+
await runSupervisor(active);
|
|
6118
|
+
return;
|
|
6119
|
+
}
|
|
6120
|
+
await runSingle(active[0]?.name);
|
|
6121
|
+
}
|
|
6122
|
+
async function runSingle(botName) {
|
|
6123
|
+
const ready = await ensureOnboarded({ allowCreate: !botName, bot: botName });
|
|
6008
6124
|
if (!ready) {
|
|
6009
6125
|
process.exitCode = 1;
|
|
6010
6126
|
return;
|
|
@@ -6047,14 +6163,37 @@ async function runRun() {
|
|
|
6047
6163
|
|
|
6048
6164
|
// src/cli/commands/daemon.ts
|
|
6049
6165
|
async function runStart() {
|
|
6050
|
-
const
|
|
6051
|
-
if (
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6166
|
+
const active = activeBots(await loadBots());
|
|
6167
|
+
if (active.length === 0) {
|
|
6168
|
+
const ready = await ensureOnboarded({ allowCreate: true });
|
|
6169
|
+
if (!ready) {
|
|
6170
|
+
process.exitCode = 1;
|
|
6171
|
+
return;
|
|
6172
|
+
}
|
|
6173
|
+
if (!await confirmReadyForDaemon(ready)) {
|
|
6174
|
+
process.exitCode = 1;
|
|
6175
|
+
return;
|
|
6176
|
+
}
|
|
6177
|
+
} else {
|
|
6178
|
+
if (active.length > 1) {
|
|
6179
|
+
console.log(`
|
|
6180
|
+
\u540E\u53F0\u670D\u52A1\u5C06\u6258\u7BA1 ${active.length} \u4E2A\u673A\u5668\u4EBA\uFF08supervisor \u591A\u8FDB\u7A0B\uFF0C\u5404\u81EA\u72EC\u7ACB\u8FDB\u7A0B\uFF09\uFF1A`);
|
|
6181
|
+
for (const b of active) console.log(` \u2022 ${b.name} (${b.appId}) [${b.tenant}]`);
|
|
6182
|
+
console.log("");
|
|
6183
|
+
}
|
|
6184
|
+
for (const bot2 of active) {
|
|
6185
|
+
if (active.length > 1) console.log(`
|
|
6186
|
+
\u2500\u2500\u2500\u2500 \u673A\u5668\u4EBA\u300C${bot2.name}\u300D(${bot2.appId}) \u2500\u2500\u2500\u2500`);
|
|
6187
|
+
const ready = await ensureOnboarded({ bot: bot2.appId });
|
|
6188
|
+
if (!ready) {
|
|
6189
|
+
process.exitCode = 1;
|
|
6190
|
+
return;
|
|
6191
|
+
}
|
|
6192
|
+
if (!await confirmReadyForDaemon(ready)) {
|
|
6193
|
+
process.exitCode = 1;
|
|
6194
|
+
return;
|
|
6195
|
+
}
|
|
6196
|
+
}
|
|
6058
6197
|
}
|
|
6059
6198
|
const status = await getServiceAdapter().install();
|
|
6060
6199
|
console.log(installedNote());
|
|
@@ -6151,6 +6290,98 @@ async function runUpdate(opts = {}) {
|
|
|
6151
6290
|
|
|
6152
6291
|
// src/cli/commands/bot.ts
|
|
6153
6292
|
import { rm as rm5 } from "fs/promises";
|
|
6293
|
+
|
|
6294
|
+
// src/cli/checkbox.ts
|
|
6295
|
+
import { emitKeypressEvents } from "readline";
|
|
6296
|
+
var ESC = "\x1B";
|
|
6297
|
+
var HIDE_CURSOR = `${ESC}[?25l`;
|
|
6298
|
+
var SHOW_CURSOR = `${ESC}[?25h`;
|
|
6299
|
+
var ALT_SCREEN_ON = `${ESC}[?1049h`;
|
|
6300
|
+
var ALT_SCREEN_OFF = `${ESC}[?1049l`;
|
|
6301
|
+
var HOME_AND_CLEAR = `${ESC}[H${ESC}[2J`;
|
|
6302
|
+
async function checkboxSelect(title, items) {
|
|
6303
|
+
const input2 = process.stdin;
|
|
6304
|
+
const output = process.stdout;
|
|
6305
|
+
if (!input2.isTTY) throw new Error("checkboxSelect requires an interactive TTY");
|
|
6306
|
+
const checked = items.map((it) => Boolean(it.checked));
|
|
6307
|
+
let cursor = 0;
|
|
6308
|
+
const frame = () => {
|
|
6309
|
+
const lines = [title, ""];
|
|
6310
|
+
items.forEach((it, i) => {
|
|
6311
|
+
const box = checked[i] ? "\x1B[32m[x]\x1B[0m" : "[ ]";
|
|
6312
|
+
const pointer = i === cursor ? "\x1B[36m>\x1B[0m" : " ";
|
|
6313
|
+
const label = i === cursor ? `\x1B[1m${it.label}\x1B[0m` : it.label;
|
|
6314
|
+
const hint = it.hint ? ` \x1B[2m${it.hint}\x1B[0m` : "";
|
|
6315
|
+
lines.push(`${pointer} ${box} ${label}${hint}`);
|
|
6316
|
+
});
|
|
6317
|
+
const n = checked.filter(Boolean).length;
|
|
6318
|
+
lines.push("");
|
|
6319
|
+
lines.push(`\x1B[2m${n} \u4E2A\u5DF2\u52FE\u9009 \xB7 \u2191\u2193 \u79FB\u52A8 \xB7 \u7A7A\u683C\u52FE\u9009 \xB7 a \u5168\u9009 \xB7 \u56DE\u8F66\u786E\u8BA4 \xB7 q \u53D6\u6D88\x1B[0m`);
|
|
6320
|
+
return lines.join("\r\n");
|
|
6321
|
+
};
|
|
6322
|
+
const redraw = () => {
|
|
6323
|
+
output.write(HOME_AND_CLEAR + frame());
|
|
6324
|
+
};
|
|
6325
|
+
emitKeypressEvents(input2);
|
|
6326
|
+
const wasRaw = Boolean(input2.isRaw);
|
|
6327
|
+
let restored = false;
|
|
6328
|
+
const restore = () => {
|
|
6329
|
+
if (restored) return;
|
|
6330
|
+
restored = true;
|
|
6331
|
+
output.write(`${SHOW_CURSOR}${ALT_SCREEN_OFF}`);
|
|
6332
|
+
};
|
|
6333
|
+
input2.setRawMode?.(true);
|
|
6334
|
+
input2.resume();
|
|
6335
|
+
output.write(`${ALT_SCREEN_ON}${HIDE_CURSOR}`);
|
|
6336
|
+
process.once("exit", restore);
|
|
6337
|
+
redraw();
|
|
6338
|
+
return await new Promise((resolve7) => {
|
|
6339
|
+
const cleanup = () => {
|
|
6340
|
+
input2.off("keypress", onKey);
|
|
6341
|
+
input2.setRawMode?.(wasRaw);
|
|
6342
|
+
input2.pause();
|
|
6343
|
+
process.off("exit", restore);
|
|
6344
|
+
restore();
|
|
6345
|
+
};
|
|
6346
|
+
const onKey = (_str, key) => {
|
|
6347
|
+
const name = key?.name;
|
|
6348
|
+
if (key?.ctrl && name === "c" || name === "escape" || name === "q") {
|
|
6349
|
+
cleanup();
|
|
6350
|
+
resolve7(null);
|
|
6351
|
+
return;
|
|
6352
|
+
}
|
|
6353
|
+
if (name === "return" || name === "enter") {
|
|
6354
|
+
cleanup();
|
|
6355
|
+
resolve7(checked.flatMap((on, i) => on ? [i] : []));
|
|
6356
|
+
return;
|
|
6357
|
+
}
|
|
6358
|
+
if (name === "up" || name === "k") {
|
|
6359
|
+
cursor = (cursor - 1 + items.length) % items.length;
|
|
6360
|
+
redraw();
|
|
6361
|
+
return;
|
|
6362
|
+
}
|
|
6363
|
+
if (name === "down" || name === "j") {
|
|
6364
|
+
cursor = (cursor + 1) % items.length;
|
|
6365
|
+
redraw();
|
|
6366
|
+
return;
|
|
6367
|
+
}
|
|
6368
|
+
if (name === "space") {
|
|
6369
|
+
checked[cursor] = !checked[cursor];
|
|
6370
|
+
redraw();
|
|
6371
|
+
return;
|
|
6372
|
+
}
|
|
6373
|
+
if (name === "a") {
|
|
6374
|
+
const allOn = checked.every(Boolean);
|
|
6375
|
+
for (let i = 0; i < checked.length; i++) checked[i] = !allOn;
|
|
6376
|
+
redraw();
|
|
6377
|
+
return;
|
|
6378
|
+
}
|
|
6379
|
+
};
|
|
6380
|
+
input2.on("keypress", onKey);
|
|
6381
|
+
});
|
|
6382
|
+
}
|
|
6383
|
+
|
|
6384
|
+
// src/cli/commands/bot.ts
|
|
6154
6385
|
async function runBotInit(name) {
|
|
6155
6386
|
if (!ensureCodex()) {
|
|
6156
6387
|
process.exitCode = 1;
|
|
@@ -6165,7 +6396,7 @@ async function runBotInit(name) {
|
|
|
6165
6396
|
console.log(" 1) \u4E8B\u4EF6\u4E0E\u56DE\u8C03 \u2192 \u957F\u8FDE\u63A5 \u2192 \u8BA2\u9605\uFF1Aim.message.receive_v1 / card.action.trigger / application.bot.menu_v6");
|
|
6166
6397
|
console.log(" \uFF08\u53EF\u9009\uFF09\u300C\u52A0\u8FDB\u5DF2\u6709\u7FA4\u300D\u529F\u80FD\u518D\u8BA2\u9605\uFF1Aim.chat.member.bot.added_v1 / im.chat.member.bot.deleted_v1");
|
|
6167
6398
|
console.log(" 2) \u521B\u5EFA\u5E76\u53D1\u5E03\u5E94\u7528\u7248\u672C");
|
|
6168
|
-
console.log("\n`bot list` \u67E5\u770B\u5168\u90E8\uFF1B`bot use
|
|
6399
|
+
console.log("\n`bot list` \u67E5\u770B\u5168\u90E8\uFF1B`bot use` \u52FE\u9009\u8981\u540C\u65F6\u8FDE\u63A5\u7684\u673A\u5668\u4EBA\uFF1B`run` \u524D\u53F0\u8DD1 / `start` \u540E\u53F0\u5E38\u9A7B\u3002\n");
|
|
6169
6400
|
}
|
|
6170
6401
|
async function runBotList() {
|
|
6171
6402
|
const reg = await loadBots();
|
|
@@ -6173,27 +6404,65 @@ async function runBotList() {
|
|
|
6173
6404
|
console.log("\uFF08\u8FD8\u6CA1\u6709\u6CE8\u518C\u4EFB\u4F55\u98DE\u4E66\u673A\u5668\u4EBA\u3002\u8FD0\u884C `feishu-codex-bridge bot init` \u521B\u5EFA\u3002\uFF09");
|
|
6174
6405
|
return;
|
|
6175
6406
|
}
|
|
6407
|
+
const active = new Set(activeBots(reg).map((b) => b.appId));
|
|
6176
6408
|
console.log("\n\u5DF2\u6CE8\u518C\u7684\u98DE\u4E66\u673A\u5668\u4EBA\uFF1A\n");
|
|
6177
6409
|
for (const b of reg.bots) {
|
|
6178
|
-
const
|
|
6179
|
-
console.log(`${
|
|
6410
|
+
const mark = active.has(b.appId) ? "\u2705" : "\u2B1C";
|
|
6411
|
+
console.log(`${mark} ${b.name.padEnd(16)} ${b.appId} [${b.tenant}]${b.botName ? ` ${b.botName}` : ""}`);
|
|
6180
6412
|
}
|
|
6181
|
-
console.log("\n\
|
|
6413
|
+
console.log("\n\x1B[2m`bot use` \u52FE\u9009\u8981\u540C\u65F6\u8FDE\u63A5\u7684\u673A\u5668\u4EBA\uFF0C\u6216 `bot use <\u540D> [\u540D\u2026]` \u76F4\u63A5\u6307\u5B9A\u3002\x1B[0m\n");
|
|
6182
6414
|
}
|
|
6183
|
-
async function runBotUse(
|
|
6415
|
+
async function runBotUse(names) {
|
|
6184
6416
|
const reg = await loadBots();
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
console.error(`\u2717 \u627E\u4E0D\u5230\u673A\u5668\u4EBA\u300C${name}\u300D\u3002\u5DF2\u6CE8\u518C\uFF1A${botNames(reg.bots)}`);
|
|
6417
|
+
if (reg.bots.length === 0) {
|
|
6418
|
+
console.error("\u2717 \u8FD8\u6CA1\u6709\u6CE8\u518C\u4EFB\u4F55\u98DE\u4E66\u673A\u5668\u4EBA\u3002\u5148 `feishu-codex-bridge bot init` \u521B\u5EFA\u3002");
|
|
6188
6419
|
process.exitCode = 1;
|
|
6189
6420
|
return;
|
|
6190
6421
|
}
|
|
6191
|
-
|
|
6192
|
-
|
|
6422
|
+
let appIds;
|
|
6423
|
+
if (names.length > 0) {
|
|
6424
|
+
const resolved = [];
|
|
6425
|
+
const unknown = [];
|
|
6426
|
+
for (const n of names) {
|
|
6427
|
+
const b = findBot(reg, n);
|
|
6428
|
+
if (!b) unknown.push(n);
|
|
6429
|
+
else if (!resolved.includes(b.appId)) resolved.push(b.appId);
|
|
6430
|
+
}
|
|
6431
|
+
if (unknown.length) {
|
|
6432
|
+
console.error(`\u2717 \u627E\u4E0D\u5230\u673A\u5668\u4EBA\uFF1A${unknown.join(", ")}\u3002\u5DF2\u6CE8\u518C\uFF1A${botNames(reg.bots)}`);
|
|
6433
|
+
process.exitCode = 1;
|
|
6434
|
+
return;
|
|
6435
|
+
}
|
|
6436
|
+
appIds = resolved;
|
|
6437
|
+
} else {
|
|
6438
|
+
if (!process.stdin.isTTY) {
|
|
6439
|
+
const cur = activeBots(reg).map((b) => b.name).join(", ") || "\uFF08\u7A7A\uFF09";
|
|
6440
|
+
console.log(`\u5F53\u524D\u6D3B\u8DC3\u673A\u5668\u4EBA\uFF1A${cur}`);
|
|
6441
|
+
console.log("\uFF08\u975E\u4EA4\u4E92\u5F0F\u7EC8\u7AEF\uFF0C\u65E0\u6CD5\u5F39\u52FE\u9009\u6846\u3002\u7528 `bot use <\u540D> [\u540D\u2026]` \u76F4\u63A5\u6307\u5B9A\u8981\u540C\u65F6\u8FDE\u63A5\u7684\u673A\u5668\u4EBA\u3002\uFF09");
|
|
6442
|
+
return;
|
|
6443
|
+
}
|
|
6444
|
+
const activeSet = new Set(activeBots(reg).map((b) => b.appId));
|
|
6445
|
+
const items = reg.bots.map((b) => ({
|
|
6446
|
+
label: b.name,
|
|
6447
|
+
hint: `${b.appId} [${b.tenant}]${b.botName ? ` ${b.botName}` : ""}`,
|
|
6448
|
+
checked: activeSet.has(b.appId)
|
|
6449
|
+
}));
|
|
6450
|
+
const picked = await checkboxSelect("\u9009\u62E9\u8981\u540C\u65F6\u8FDE\u63A5\u7684\u673A\u5668\u4EBA\uFF08\u7A7A\u683C\u52FE\u9009\uFF0C\u56DE\u8F66\u786E\u8BA4\uFF09\uFF1A", items);
|
|
6451
|
+
if (picked === null) {
|
|
6452
|
+
console.log("\u5DF2\u53D6\u6D88\uFF0C\u672A\u6539\u52A8\u3002");
|
|
6453
|
+
return;
|
|
6454
|
+
}
|
|
6455
|
+
appIds = picked.map((i) => reg.bots[i]?.appId).filter((id) => Boolean(id));
|
|
6456
|
+
}
|
|
6457
|
+
await setActiveBots(appIds);
|
|
6458
|
+
const chosen = appIds.map((id) => reg.bots.find((b) => b.appId === id)?.name ?? id);
|
|
6459
|
+
if (chosen.length === 0) {
|
|
6460
|
+
console.log("\u2713 \u5DF2\u6E05\u7A7A\u6D3B\u8DC3\u673A\u5668\u4EBA\u2014\u2014`run` / `start` \u6682\u4E0D\u8FDE\u63A5\u4EFB\u4F55 bot\u3002`bot use` \u91CD\u65B0\u52FE\u9009\u3002");
|
|
6193
6461
|
return;
|
|
6194
6462
|
}
|
|
6195
|
-
|
|
6196
|
-
|
|
6463
|
+
console.log(
|
|
6464
|
+
`\u2713 \u6D3B\u8DC3\u673A\u5668\u4EBA\uFF08${chosen.length} \u4E2A\uFF09\u2192 ${chosen.join(", ")}\u3002\u524D\u53F0\u91CD\u8DD1 \`run\` \u751F\u6548${chosen.length > 1 ? "\uFF08\u591A\u8FDB\u7A0B\u6258\u7BA1\uFF09" : ""}\uFF1B\u540E\u53F0\u8BF7 \`restart\`\u3002`
|
|
6465
|
+
);
|
|
6197
6466
|
}
|
|
6198
6467
|
async function runBotRm(name) {
|
|
6199
6468
|
const reg = await loadBots();
|
|
@@ -6278,8 +6547,8 @@ function readStdin() {
|
|
|
6278
6547
|
// src/cli/index.ts
|
|
6279
6548
|
var program = new Command();
|
|
6280
6549
|
program.name("feishu-codex-bridge").description("\u628A\u98DE\u4E66/Lark \u6865\u63A5\u5230\u672C\u673A Codex\uFF08\u9879\u76EE=\u7FA4, \u8BDD\u9898=\u4F1A\u8BDD\uFF09").version(bridgeVersion());
|
|
6281
|
-
program.command("run").description("\u524D\u53F0\u542F\u52A8
|
|
6282
|
-
await runRun();
|
|
6550
|
+
program.command("run").description("\u524D\u53F0\u542F\u52A8\u6D3B\u8DC3\u673A\u5668\u4EBA\uFF08\u591A\u4E2A\u5219\u5404\u81EA\u72EC\u7ACB\u8FDB\u7A0B\uFF1B\u6CA1\u914D\u7F6E\u5219\u5148\u626B\u7801 init\uFF1BCtrl+C \u4F18\u96C5\u9000\u51FA\uFF09").option("--bot <name>", "\u53EA\u542F\u52A8\u6307\u5B9A\u7684\u4E00\u4E2A\u673A\u5668\u4EBA\uFF08\u540D\u5B57\u6216 appId\uFF09").action(async (options) => {
|
|
6551
|
+
await runRun(options.bot);
|
|
6283
6552
|
});
|
|
6284
6553
|
program.command("start").description("\u540E\u53F0 daemon \u542F\u52A8\uFF08\u88C5 launchd \u5F00\u673A\u81EA\u542F\uFF1B\u6CA1\u914D\u7F6E\u5219\u5148\u626B\u7801 init\uFF09").action(async () => {
|
|
6285
6554
|
await runStart();
|
|
@@ -6306,8 +6575,8 @@ bot.command("init [name]").description("\u6CE8\u518C\u4E00\u4E2A\u98DE\u4E66\u67
|
|
|
6306
6575
|
bot.command("list").description("\u5217\u51FA\u5DF2\u6CE8\u518C\u7684\u98DE\u4E66\u673A\u5668\u4EBA").action(async () => {
|
|
6307
6576
|
await runBotList();
|
|
6308
6577
|
});
|
|
6309
|
-
bot.command("use
|
|
6310
|
-
await runBotUse(
|
|
6578
|
+
bot.command("use [names...]").description("\u52FE\u9009/\u6307\u5B9A\u8981\u540C\u65F6\u8FDE\u63A5\u7684\u673A\u5668\u4EBA\uFF08\u591A\u9009\uFF09\uFF1B\u65E0\u53C2\u6570\u5F39\u4EA4\u4E92\u5F0F\u52FE\u9009\u6846").action(async (names) => {
|
|
6579
|
+
await runBotUse(names ?? []);
|
|
6311
6580
|
});
|
|
6312
6581
|
bot.command("rm <name>").description("\u79FB\u9664\u4E00\u4E2A\u673A\u5668\u4EBA\u914D\u7F6E").action(async (name) => {
|
|
6313
6582
|
await runBotRm(name);
|