@modelzen/feishu-codex-bridge 0.1.5 → 0.1.7
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 +217 -13
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2764,6 +2764,27 @@ function connLabel(state) {
|
|
|
2764
2764
|
return state;
|
|
2765
2765
|
}
|
|
2766
2766
|
}
|
|
2767
|
+
function scopeStatusText(i) {
|
|
2768
|
+
if (i.missingScopes === void 0) return "\u672A\u80FD\u81EA\u52A8\u68C0\u67E5\uFF08\u51ED\u8BC1\u5931\u6548\u6216\u7F51\u7EDC\u95EE\u9898\uFF09";
|
|
2769
|
+
if (i.missingScopes.length === 0) return "\u5FC5\u9700\u6743\u9650\u9F50\u5168";
|
|
2770
|
+
return `\u7F3A\u5931 ${i.missingScopes.length} \u9879\uFF1A${i.missingScopes.join(" ")}`;
|
|
2771
|
+
}
|
|
2772
|
+
function scopeDiagnosis(i) {
|
|
2773
|
+
if (i.missingScopes === void 0) {
|
|
2774
|
+
return [
|
|
2775
|
+
md("- \u98DE\u4E66\u6743\u9650\uFF1A\u26A0\uFE0F \u65E0\u6CD5\u81EA\u52A8\u68C0\u67E5\uFF08\u51ED\u8BC1\u5931\u6548\u6216\u7F51\u7EDC\u4E0D\u901A\uFF09"),
|
|
2776
|
+
actions([linkButton("\u{1F511} \u53BB\u6743\u9650\u9875\u6838\u5BF9", i.scopeGrantUrl)])
|
|
2777
|
+
];
|
|
2778
|
+
}
|
|
2779
|
+
if (i.missingScopes.length === 0) {
|
|
2780
|
+
return [md("- \u98DE\u4E66\u6743\u9650\uFF1A\u2705 \u5FC5\u9700\u6743\u9650\u5DF2\u5168\u90E8\u5F00\u901A")];
|
|
2781
|
+
}
|
|
2782
|
+
return [
|
|
2783
|
+
md(`- \u98DE\u4E66\u6743\u9650\uFF1A\u274C \u7F3A ${i.missingScopes.length} \u9879 \u2014\u2014 \u5F00\u901A\u524D\u76F8\u5173\u529F\u80FD\uFF08\u6536\u53D1\u6D88\u606F / \u5361\u7247 / \u5EFA\u7FA4\u7B49\uFF09\u4E0D\u53EF\u7528`),
|
|
2784
|
+
note(`\u5F85\u5F00\u901A\uFF1A${i.missingScopes.join("\u3000")}`),
|
|
2785
|
+
actions([linkButton("\u{1F511} \u4E00\u952E\u53BB\u5F00\u901A\u8FD9\u4E9B\u6743\u9650", i.scopeGrantUrl)])
|
|
2786
|
+
];
|
|
2787
|
+
}
|
|
2767
2788
|
function codexDiagnosePrompt(i) {
|
|
2768
2789
|
return [
|
|
2769
2790
|
"\u6211\u5728\u7528 feishu-codex-bridge\uFF08\u98DE\u4E66 \u2194 \u672C\u5730 Codex \u6865\u63A5\uFF09\u9047\u5230\u95EE\u9898\uFF0C\u8BF7\u5E2E\u6211\u5B9A\u4F4D\u539F\u56E0\u5E76\u7ED9\u51FA\u4FEE\u590D\u6B65\u9AA4\u3002",
|
|
@@ -2778,6 +2799,7 @@ function codexDiagnosePrompt(i) {
|
|
|
2778
2799
|
"\u3010\u8FD0\u884C\u5FEB\u7167\u3011",
|
|
2779
2800
|
`- codex \u53EF\u7528\uFF1A${i.codexOk ? "\u662F" : "\u5426"}`,
|
|
2780
2801
|
`- \u98DE\u4E66\u957F\u8FDE\u63A5\uFF1A${i.conn}`,
|
|
2802
|
+
`- \u98DE\u4E66\u6743\u9650\uFF1A${scopeStatusText(i)}`,
|
|
2781
2803
|
"",
|
|
2782
2804
|
"\u3010\u8BF7\u4F60\u505A\u7684\u4E8B\u3011",
|
|
2783
2805
|
"1. \u8BFB\u53D6\u5E76\u5206\u6790\u65E5\u5FD7\uFF0C\u627E\u51FA\u6700\u8FD1\u7684\u62A5\u9519\u6216\u5F02\u5E38\u5806\u6808\uFF1A",
|
|
@@ -2794,6 +2816,7 @@ function codexDiagnosePrompt(i) {
|
|
|
2794
2816
|
}
|
|
2795
2817
|
function buildDoctorCard(i) {
|
|
2796
2818
|
const prompt = codexDiagnosePrompt(i);
|
|
2819
|
+
const hasProblem = !i.codexOk || i.missingScopes !== void 0 && i.missingScopes.length > 0;
|
|
2797
2820
|
return card(
|
|
2798
2821
|
[
|
|
2799
2822
|
md("**\u521D\u6B65\u8BCA\u65AD**"),
|
|
@@ -2801,6 +2824,7 @@ function buildDoctorCard(i) {
|
|
|
2801
2824
|
`- Codex\uFF1A${i.codexOk ? `\u2705 \u53EF\u7528${i.codexVer ? `\uFF08${i.codexVer}\uFF09` : ""}` : "\u274C \u4E0D\u53EF\u7528\uFF08\u68C0\u67E5 CODEX_BIN / PATH\uFF09"}`
|
|
2802
2825
|
),
|
|
2803
2826
|
md(`- \u98DE\u4E66\u957F\u8FDE\u63A5\uFF1A${connLabel(i.conn)}`),
|
|
2827
|
+
...scopeDiagnosis(i),
|
|
2804
2828
|
note(`bridge v${i.bridgeVer}\u3000\xB7\u3000Node ${i.node}\u3000\xB7\u3000${i.platform}`),
|
|
2805
2829
|
hr(),
|
|
2806
2830
|
md("**\u65E5\u5FD7\u8DEF\u5F84**"),
|
|
@@ -2815,7 +2839,7 @@ function buildDoctorCard(i) {
|
|
|
2815
2839
|
linkButton("\u{1F41E} \u63D0 Issue", `${REPO}/issues`)
|
|
2816
2840
|
])
|
|
2817
2841
|
],
|
|
2818
|
-
{ header: { title: "\u{1FA7A} \u8BCA\u65AD", template:
|
|
2842
|
+
{ header: { title: "\u{1FA7A} \u8BCA\u65AD", template: hasProblem ? "orange" : "blue" } }
|
|
2819
2843
|
);
|
|
2820
2844
|
}
|
|
2821
2845
|
function buildNewProjectFormCard(opts = {}) {
|
|
@@ -3504,6 +3528,156 @@ async function handleDmConsole(channel, cfg, msg) {
|
|
|
3504
3528
|
});
|
|
3505
3529
|
}
|
|
3506
3530
|
|
|
3531
|
+
// src/bot/media.ts
|
|
3532
|
+
import { mkdir as mkdir8, readdir as readdir2, rm as rm3, stat as stat2 } from "fs/promises";
|
|
3533
|
+
import { join as join10 } from "path";
|
|
3534
|
+
var MAX_IMAGES = 9;
|
|
3535
|
+
var MEDIA_TTL_MS = 60 * 6e4;
|
|
3536
|
+
var EXT_BY_CONTENT_TYPE = {
|
|
3537
|
+
"image/png": "png",
|
|
3538
|
+
"image/jpeg": "jpg",
|
|
3539
|
+
"image/jpg": "jpg",
|
|
3540
|
+
"image/gif": "gif",
|
|
3541
|
+
"image/webp": "webp",
|
|
3542
|
+
"image/bmp": "bmp",
|
|
3543
|
+
"image/heic": "heic",
|
|
3544
|
+
"image/heif": "heif",
|
|
3545
|
+
"image/tiff": "tiff"
|
|
3546
|
+
};
|
|
3547
|
+
function messageHasImages(msg) {
|
|
3548
|
+
if ((msg.resources ?? []).some((r) => r.type === "image")) return true;
|
|
3549
|
+
return msg.rawContentType === "merge_forward";
|
|
3550
|
+
}
|
|
3551
|
+
async function collectInboundImages(channel, msg) {
|
|
3552
|
+
let refs;
|
|
3553
|
+
try {
|
|
3554
|
+
refs = await gatherRefs(channel, msg);
|
|
3555
|
+
} catch (err) {
|
|
3556
|
+
log.warn("intake", "image-gather-failed", { err: String(err) });
|
|
3557
|
+
return [];
|
|
3558
|
+
}
|
|
3559
|
+
if (refs.length === 0) return [];
|
|
3560
|
+
await pruneOldMedia();
|
|
3561
|
+
try {
|
|
3562
|
+
await mkdir8(paths.mediaDir, { recursive: true });
|
|
3563
|
+
} catch {
|
|
3564
|
+
}
|
|
3565
|
+
const out = [];
|
|
3566
|
+
let index = 0;
|
|
3567
|
+
for (const ref of refs.slice(0, MAX_IMAGES)) {
|
|
3568
|
+
const path = await downloadOne(channel, ref, index++);
|
|
3569
|
+
if (path) out.push(path);
|
|
3570
|
+
}
|
|
3571
|
+
log.info("intake", "images", { found: refs.length, downloaded: out.length });
|
|
3572
|
+
return out;
|
|
3573
|
+
}
|
|
3574
|
+
async function gatherRefs(channel, msg) {
|
|
3575
|
+
const refs = [];
|
|
3576
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3577
|
+
const add = (messageId, fileKey) => {
|
|
3578
|
+
if (!fileKey || seen.has(fileKey)) return;
|
|
3579
|
+
seen.add(fileKey);
|
|
3580
|
+
refs.push({ messageId, fileKey });
|
|
3581
|
+
};
|
|
3582
|
+
for (const r of msg.resources ?? []) {
|
|
3583
|
+
if (r.type === "image") add(msg.messageId, r.fileKey);
|
|
3584
|
+
}
|
|
3585
|
+
if (msg.rawContentType === "merge_forward") {
|
|
3586
|
+
const items = await fetchSubMessages(channel, msg.messageId);
|
|
3587
|
+
for (const sub of items) {
|
|
3588
|
+
if (!sub.message_id || sub.message_id === msg.messageId) continue;
|
|
3589
|
+
for (const key of imageKeysFromContent(sub.msg_type, sub.body?.content)) {
|
|
3590
|
+
add(sub.message_id, key);
|
|
3591
|
+
}
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
return refs;
|
|
3595
|
+
}
|
|
3596
|
+
async function fetchSubMessages(channel, messageId) {
|
|
3597
|
+
try {
|
|
3598
|
+
const res = await channel.rawClient.im.v1.message.get({ path: { message_id: messageId } });
|
|
3599
|
+
return res.data?.items ?? [];
|
|
3600
|
+
} catch (err) {
|
|
3601
|
+
log.warn("intake", "submessages-failed", { messageId, err: String(err) });
|
|
3602
|
+
return [];
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
function imageKeysFromContent(msgType, content) {
|
|
3606
|
+
if (!content) return [];
|
|
3607
|
+
let parsed;
|
|
3608
|
+
try {
|
|
3609
|
+
parsed = JSON.parse(content);
|
|
3610
|
+
} catch {
|
|
3611
|
+
return [];
|
|
3612
|
+
}
|
|
3613
|
+
if (msgType === "image") {
|
|
3614
|
+
const key = parsed?.image_key;
|
|
3615
|
+
return key ? [key] : [];
|
|
3616
|
+
}
|
|
3617
|
+
const keys = [];
|
|
3618
|
+
walkForImageKeys(parsed, keys);
|
|
3619
|
+
return keys;
|
|
3620
|
+
}
|
|
3621
|
+
function walkForImageKeys(node, out) {
|
|
3622
|
+
if (!node || typeof node !== "object") return;
|
|
3623
|
+
if (Array.isArray(node)) {
|
|
3624
|
+
for (const child of node) walkForImageKeys(child, out);
|
|
3625
|
+
return;
|
|
3626
|
+
}
|
|
3627
|
+
const obj = node;
|
|
3628
|
+
if (obj.tag === "img" && typeof obj.image_key === "string") out.push(obj.image_key);
|
|
3629
|
+
for (const k of Object.keys(obj)) walkForImageKeys(obj[k], out);
|
|
3630
|
+
}
|
|
3631
|
+
async function downloadOne(channel, ref, index) {
|
|
3632
|
+
try {
|
|
3633
|
+
const res = await channel.rawClient.im.v1.messageResource.get({
|
|
3634
|
+
path: { message_id: ref.messageId, file_key: ref.fileKey },
|
|
3635
|
+
params: { type: "image" }
|
|
3636
|
+
});
|
|
3637
|
+
const ext = extFromHeaders(res.headers);
|
|
3638
|
+
const file = join10(paths.mediaDir, `${safeName(ref.fileKey)}-${index}.${ext}`);
|
|
3639
|
+
await res.writeFile(file);
|
|
3640
|
+
return file;
|
|
3641
|
+
} catch (err) {
|
|
3642
|
+
log.warn("intake", "image-download-failed", { fileKey: ref.fileKey.slice(0, 24), err: String(err) });
|
|
3643
|
+
return void 0;
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3646
|
+
function extFromHeaders(headers) {
|
|
3647
|
+
const ct = readHeader(headers, "content-type");
|
|
3648
|
+
if (ct) {
|
|
3649
|
+
const base = ct.split(";")[0]?.trim().toLowerCase();
|
|
3650
|
+
if (base && EXT_BY_CONTENT_TYPE[base]) return EXT_BY_CONTENT_TYPE[base];
|
|
3651
|
+
}
|
|
3652
|
+
return "png";
|
|
3653
|
+
}
|
|
3654
|
+
function readHeader(headers, name) {
|
|
3655
|
+
if (!headers || typeof headers !== "object") return void 0;
|
|
3656
|
+
const h = headers;
|
|
3657
|
+
const raw = typeof h.get === "function" ? h.get(name) : h[name] ?? h[name.toLowerCase()];
|
|
3658
|
+
return typeof raw === "string" ? raw : Array.isArray(raw) ? String(raw[0]) : void 0;
|
|
3659
|
+
}
|
|
3660
|
+
function safeName(fileKey) {
|
|
3661
|
+
return fileKey.replace(/[^a-zA-Z0-9_-]/g, "").slice(-40) || "img";
|
|
3662
|
+
}
|
|
3663
|
+
async function pruneOldMedia() {
|
|
3664
|
+
let entries;
|
|
3665
|
+
try {
|
|
3666
|
+
entries = await readdir2(paths.mediaDir);
|
|
3667
|
+
} catch {
|
|
3668
|
+
return;
|
|
3669
|
+
}
|
|
3670
|
+
const cutoff = Date.now() - MEDIA_TTL_MS;
|
|
3671
|
+
for (const name of entries) {
|
|
3672
|
+
const file = join10(paths.mediaDir, name);
|
|
3673
|
+
try {
|
|
3674
|
+
const st = await stat2(file);
|
|
3675
|
+
if (st.mtimeMs < cutoff) await rm3(file, { force: true });
|
|
3676
|
+
} catch {
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
}
|
|
3680
|
+
|
|
3507
3681
|
// src/bot/comments.ts
|
|
3508
3682
|
var SUPPORTED_FILE_TYPES = /* @__PURE__ */ new Set(["doc", "docx", "sheet", "file"]);
|
|
3509
3683
|
var REPLY_MAX_CHARS = 2e3;
|
|
@@ -3898,19 +4072,34 @@ function createOrchestrator(channel, cfg, fallbackCwd) {
|
|
|
3898
4072
|
async function handleTurn(msg, text, sessionKey, flat, project) {
|
|
3899
4073
|
const existing = active.get(sessionKey);
|
|
3900
4074
|
if (existing) {
|
|
3901
|
-
|
|
3902
|
-
|
|
4075
|
+
const images = messageHasImages(msg) ? await collectInboundImages(channel, msg) : void 0;
|
|
4076
|
+
const cur = active.get(sessionKey);
|
|
4077
|
+
if (!cur) {
|
|
4078
|
+
startReservedRun(msg, text, sessionKey, flat, project, images);
|
|
4079
|
+
return;
|
|
4080
|
+
}
|
|
4081
|
+
if (getPendingPolicy(cfg) === "steer" && cur.run && cur.thread) {
|
|
4082
|
+
const tid = cur.run.turnId();
|
|
3903
4083
|
if (tid) {
|
|
3904
4084
|
try {
|
|
3905
|
-
await
|
|
3906
|
-
log.info("intake", "steer", { tid });
|
|
4085
|
+
await cur.thread.steer({ text, images }, tid);
|
|
4086
|
+
log.info("intake", "steer", { tid, images: images?.length ?? 0 });
|
|
3907
4087
|
return;
|
|
3908
4088
|
} catch (err) {
|
|
3909
4089
|
log.warn("intake", "steer-failed", { err: String(err) });
|
|
3910
4090
|
}
|
|
3911
4091
|
}
|
|
3912
4092
|
}
|
|
3913
|
-
|
|
4093
|
+
cur.queue.push({ text, images });
|
|
4094
|
+
log.info("intake", "queued", { depth: cur.queue.length });
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
4097
|
+
startReservedRun(msg, text, sessionKey, flat, project);
|
|
4098
|
+
}
|
|
4099
|
+
function startReservedRun(msg, text, sessionKey, flat, project, preloadedImages) {
|
|
4100
|
+
const existing = active.get(sessionKey);
|
|
4101
|
+
if (existing) {
|
|
4102
|
+
existing.queue.push({ text, images: preloadedImages });
|
|
3914
4103
|
log.info("intake", "queued", { depth: existing.queue.length });
|
|
3915
4104
|
return;
|
|
3916
4105
|
}
|
|
@@ -3919,6 +4108,7 @@ function createOrchestrator(channel, cfg, fallbackCwd) {
|
|
|
3919
4108
|
void withTrace({ chatId: msg.chatId, msgId: msg.messageId }, async () => {
|
|
3920
4109
|
const reaction = runReaction(msg.messageId, !sema.hasFree());
|
|
3921
4110
|
try {
|
|
4111
|
+
const images = preloadedImages ?? (messageHasImages(msg) ? await collectInboundImages(channel, msg) : void 0);
|
|
3922
4112
|
let thread = await resolveThread(sessionKey, msg.chatId);
|
|
3923
4113
|
if (!thread) {
|
|
3924
4114
|
const cwd = project?.cwd ?? fallbackCwd;
|
|
@@ -3943,6 +4133,7 @@ function createOrchestrator(channel, cfg, fallbackCwd) {
|
|
|
3943
4133
|
flat,
|
|
3944
4134
|
thread,
|
|
3945
4135
|
firstText: text,
|
|
4136
|
+
images,
|
|
3946
4137
|
knownThreadId: sessionKey,
|
|
3947
4138
|
requesterOpenId: msg.senderId
|
|
3948
4139
|
},
|
|
@@ -3995,7 +4186,8 @@ function createOrchestrator(channel, cfg, fallbackCwd) {
|
|
|
3995
4186
|
return;
|
|
3996
4187
|
}
|
|
3997
4188
|
const firstText = text || "\u4F60\u597D\uFF0C\u6211\u4EEC\u5F00\u59CB\u5427\u3002";
|
|
3998
|
-
|
|
4189
|
+
const images = messageHasImages(msg) ? await collectInboundImages(channel, msg) : void 0;
|
|
4190
|
+
log.info("card", "start", { project: project?.name ?? "(unregistered)", model, effort, images: images?.length ?? 0 });
|
|
3999
4191
|
await launchRun(
|
|
4000
4192
|
{
|
|
4001
4193
|
chatId: msg.chatId,
|
|
@@ -4003,6 +4195,7 @@ function createOrchestrator(channel, cfg, fallbackCwd) {
|
|
|
4003
4195
|
replyInThread: true,
|
|
4004
4196
|
thread,
|
|
4005
4197
|
firstText,
|
|
4198
|
+
images,
|
|
4006
4199
|
model,
|
|
4007
4200
|
effort,
|
|
4008
4201
|
cwd,
|
|
@@ -4202,6 +4395,10 @@ function createOrchestrator(channel, cfg, fallbackCwd) {
|
|
|
4202
4395
|
}).on(DM.doctor, async ({ evt }) => {
|
|
4203
4396
|
if (!dmAdmin(evt.operator?.openId)) return;
|
|
4204
4397
|
const codexBin = resolveCodexBin();
|
|
4398
|
+
const app = cfg.accounts.app;
|
|
4399
|
+
const secret = await getSecret(secretKeyForApp(app.id)).catch(() => void 0);
|
|
4400
|
+
const scopeCheck = secret ? await validateAppCredentials(app.id, secret, app.tenant).catch(() => void 0) : void 0;
|
|
4401
|
+
const missingScopes = scopeCheck?.missingScopes;
|
|
4205
4402
|
const info = {
|
|
4206
4403
|
codexOk: await backend.isAvailable().catch(() => false),
|
|
4207
4404
|
codexVer: codexBin ? codexVersion(codexBin) : null,
|
|
@@ -4211,7 +4408,14 @@ function createOrchestrator(channel, cfg, fallbackCwd) {
|
|
|
4211
4408
|
platform: `${process.platform}-${process.arch}`,
|
|
4212
4409
|
logStdout: serviceStdoutPath(),
|
|
4213
4410
|
logStderr: serviceStderrPath(),
|
|
4214
|
-
configFile: paths.configFile
|
|
4411
|
+
configFile: paths.configFile,
|
|
4412
|
+
missingScopes,
|
|
4413
|
+
// 缺失时预选缺失项(精准开通);查不到/全开通时预选全部必需 scope 供核对。
|
|
4414
|
+
scopeGrantUrl: buildScopeGrantUrl(
|
|
4415
|
+
app.id,
|
|
4416
|
+
app.tenant,
|
|
4417
|
+
missingScopes && missingScopes.length ? missingScopes : void 0
|
|
4418
|
+
)
|
|
4215
4419
|
};
|
|
4216
4420
|
await sendManagedCard(channel, evt.chatId, buildDoctorCard(info), evt.messageId).catch(
|
|
4217
4421
|
(err) => log.fail("console", err, { cmd: "doctor" })
|
|
@@ -4397,14 +4601,14 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
4397
4601
|
};
|
|
4398
4602
|
let curCardKey;
|
|
4399
4603
|
try {
|
|
4400
|
-
let
|
|
4604
|
+
let turnInput = { text: opts.firstText, images: opts.images };
|
|
4401
4605
|
let replyTo = opts.replyTo;
|
|
4402
4606
|
let replyInThread = opts.flat ? false : opts.replyInThread ?? Boolean(opts.knownThreadId);
|
|
4403
4607
|
for (; ; ) {
|
|
4404
4608
|
const rec = topicThreadId ? await getSession(topicThreadId) : void 0;
|
|
4405
4609
|
const turnModel = rec?.model ?? opts.model;
|
|
4406
4610
|
const turnEffort = rec?.effort ?? opts.effort;
|
|
4407
|
-
const run = opts.thread.runStreamed(
|
|
4611
|
+
const run = opts.thread.runStreamed(turnInput, { model: turnModel, effort: turnEffort });
|
|
4408
4612
|
state.run = run;
|
|
4409
4613
|
const render = new RunRender();
|
|
4410
4614
|
render.showTools = getShowToolCalls(cfg);
|
|
@@ -4491,7 +4695,7 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
4491
4695
|
log.info("card", "final", { terminal: render.terminal() });
|
|
4492
4696
|
if (killed) break;
|
|
4493
4697
|
if (state.queue.length === 0) break;
|
|
4494
|
-
|
|
4698
|
+
turnInput = state.queue.shift();
|
|
4495
4699
|
}
|
|
4496
4700
|
} catch (err) {
|
|
4497
4701
|
log.fail("intake", err);
|
|
@@ -4855,7 +5059,7 @@ async function runUpdate(opts = {}) {
|
|
|
4855
5059
|
}
|
|
4856
5060
|
|
|
4857
5061
|
// src/cli/commands/bot.ts
|
|
4858
|
-
import { rm as
|
|
5062
|
+
import { rm as rm4 } from "fs/promises";
|
|
4859
5063
|
async function runBotInit(name) {
|
|
4860
5064
|
if (!ensureCodex()) {
|
|
4861
5065
|
process.exitCode = 1;
|
|
@@ -4909,7 +5113,7 @@ async function runBotRm(name) {
|
|
|
4909
5113
|
}
|
|
4910
5114
|
const after = await removeBot(bot2.appId);
|
|
4911
5115
|
await removeSecret(secretKeyForApp(bot2.appId));
|
|
4912
|
-
await
|
|
5116
|
+
await rm4(botDir(bot2.appId), { recursive: true, force: true });
|
|
4913
5117
|
console.log(`\u2713 \u5DF2\u79FB\u9664\u673A\u5668\u4EBA\u300C${bot2.name}\u300D(${bot2.appId})\uFF1A\u6CE8\u518C\u8868 + \u5BC6\u94A5 + \u72B6\u6001\u76EE\u5F55(projects/sessions)\u3002`);
|
|
4914
5118
|
if (after.bots.length === 0) {
|
|
4915
5119
|
console.log(" \u5DF2\u65E0\u4EFB\u4F55\u673A\u5668\u4EBA\uFF0C`bot init` \u91CD\u65B0\u521B\u5EFA\u3002");
|