@modelzen/feishu-codex-bridge 0.4.1 → 0.4.2
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 +146 -87
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2950,7 +2950,14 @@ function card(elements, opts = {}) {
|
|
|
2950
2950
|
obj.header = {
|
|
2951
2951
|
template: opts.header.template ?? "blue",
|
|
2952
2952
|
title: { tag: "plain_text", content: opts.header.title },
|
|
2953
|
-
...opts.header.subtitle ? { subtitle: { tag: "plain_text", content: opts.header.subtitle } } : {}
|
|
2953
|
+
...opts.header.subtitle ? { subtitle: { tag: "plain_text", content: opts.header.subtitle } } : {},
|
|
2954
|
+
...opts.header.textTags?.length ? {
|
|
2955
|
+
text_tag_list: opts.header.textTags.map((t) => ({
|
|
2956
|
+
tag: "text_tag",
|
|
2957
|
+
text: { tag: "plain_text", content: t.text },
|
|
2958
|
+
color: t.color
|
|
2959
|
+
}))
|
|
2960
|
+
} : {}
|
|
2954
2961
|
};
|
|
2955
2962
|
}
|
|
2956
2963
|
return obj;
|
|
@@ -3025,6 +3032,27 @@ function actions(items, elementId) {
|
|
|
3025
3032
|
columns: items.map((it) => ({ tag: "column", width: "auto", elements: [it] }))
|
|
3026
3033
|
};
|
|
3027
3034
|
}
|
|
3035
|
+
function actionsFixed(items, width, elementId) {
|
|
3036
|
+
return {
|
|
3037
|
+
tag: "column_set",
|
|
3038
|
+
...elementId ? { element_id: elementId } : {},
|
|
3039
|
+
flex_mode: "flow",
|
|
3040
|
+
horizontal_spacing: "8px",
|
|
3041
|
+
columns: items.map((it) => ({ tag: "column", width: "auto", elements: [{ ...it, width, size: "large" }] }))
|
|
3042
|
+
};
|
|
3043
|
+
}
|
|
3044
|
+
function splitRow(left, right, elementId) {
|
|
3045
|
+
return {
|
|
3046
|
+
tag: "column_set",
|
|
3047
|
+
...elementId ? { element_id: elementId } : {},
|
|
3048
|
+
flex_mode: "none",
|
|
3049
|
+
horizontal_spacing: "medium",
|
|
3050
|
+
columns: [
|
|
3051
|
+
{ tag: "column", width: "auto", vertical_align: "center", elements: [left] },
|
|
3052
|
+
{ tag: "column", width: "weighted", weight: 1, vertical_align: "center", elements: [right] }
|
|
3053
|
+
]
|
|
3054
|
+
};
|
|
3055
|
+
}
|
|
3028
3056
|
function button(label, value, type = "default") {
|
|
3029
3057
|
return {
|
|
3030
3058
|
tag: "button",
|
|
@@ -3033,11 +3061,12 @@ function button(label, value, type = "default") {
|
|
|
3033
3061
|
behaviors: [{ type: "callback", value }]
|
|
3034
3062
|
};
|
|
3035
3063
|
}
|
|
3036
|
-
function linkButton(label, url, type = "default") {
|
|
3064
|
+
function linkButton(label, url, type = "default", size) {
|
|
3037
3065
|
return {
|
|
3038
3066
|
tag: "button",
|
|
3039
3067
|
text: { tag: "plain_text", content: label },
|
|
3040
3068
|
type,
|
|
3069
|
+
...size ? { size } : {},
|
|
3041
3070
|
behaviors: [{ type: "open_url", default_url: url }]
|
|
3042
3071
|
};
|
|
3043
3072
|
}
|
|
@@ -3295,6 +3324,8 @@ function openChatUrl(chatId) {
|
|
|
3295
3324
|
return `https://applink.feishu.cn/client/chat/open?openChatId=${encodeURIComponent(chatId)}`;
|
|
3296
3325
|
}
|
|
3297
3326
|
var REPO = "https://github.com/modelzen/feishu-codex-bridge";
|
|
3327
|
+
var MENU_BTN_W_TOP = "152px";
|
|
3328
|
+
var MENU_BTN_W_BOT = "112px";
|
|
3298
3329
|
var DM = {
|
|
3299
3330
|
menu: "dm.menu",
|
|
3300
3331
|
newProject: "dm.newProject",
|
|
@@ -3351,24 +3382,47 @@ var GS = {
|
|
|
3351
3382
|
function kindLabel(kind) {
|
|
3352
3383
|
return kind === "single" ? "\u{1F4AC} \u5355\u4F1A\u8BDD\u7FA4" : "\u{1F465} \u591A\u8BDD\u9898\u7FA4";
|
|
3353
3384
|
}
|
|
3354
|
-
function buildDmMenuCard() {
|
|
3385
|
+
function buildDmMenuCard(opts = {}) {
|
|
3386
|
+
const { webConsoleUrl: webConsoleUrl2, version } = opts;
|
|
3355
3387
|
return card(
|
|
3356
3388
|
[
|
|
3357
3389
|
md("\u79C1\u804A\u7528\u4E8E**\u5EFA\u9879\u76EE\u548C\u7BA1\u7406**\uFF1B\u5177\u4F53\u4EFB\u52A1\u8BF7\u5230\u9879\u76EE\u7FA4\u91CC @\u6211\u3002"),
|
|
3358
3390
|
hr(),
|
|
3359
|
-
|
|
3391
|
+
// 两行按钮固定宽度、左对齐;两行宽度配平后总长相等、右边缘对齐(见 MENU_BTN_W_*)。
|
|
3392
|
+
actionsFixed([
|
|
3360
3393
|
button("\u2795 \u65B0\u5EFA\u9879\u76EE", { a: DM.newProject }, "primary"),
|
|
3361
3394
|
button("\u{1F4C1} \u9879\u76EE\u5217\u8868", { a: DM.projects }),
|
|
3362
3395
|
button("\u2699\uFE0F \u8BBE\u7F6E", { a: DM.settings })
|
|
3363
|
-
]),
|
|
3364
|
-
|
|
3396
|
+
], MENU_BTN_W_TOP),
|
|
3397
|
+
actionsFixed([
|
|
3365
3398
|
button("\u{1F4CA} \u7528\u91CF", { a: DM.usage }),
|
|
3366
3399
|
button("\u{1FA7A} \u8BCA\u65AD", { a: DM.doctor }),
|
|
3367
3400
|
button("\u{1F504} \u91CD\u8FDE", { a: DM.reconnect }),
|
|
3368
|
-
button("\u2B06\uFE0F \
|
|
3369
|
-
])
|
|
3401
|
+
button("\u2B06\uFE0F \u66F4\u65B0", { a: DM.update })
|
|
3402
|
+
], MENU_BTN_W_BOT),
|
|
3403
|
+
// 🌐 网页控制台:刻意低调——小号按钮靠左 + 右侧灰字说明;仅在 daemon 本机控制台
|
|
3404
|
+
// 在跑(webConsoleUrl 有值)时出现。按钮直接开 127.0.0.1 控制台——只有运行 bridge
|
|
3405
|
+
// 的这台机器打得开;其它电脑/手机点了会打不开(本机回环地址,飞书也分不出点击设备
|
|
3406
|
+
// 是不是本机),右侧文字已说明,按用户决定不另做处理。
|
|
3407
|
+
...webConsoleUrl2 ? [
|
|
3408
|
+
hr(),
|
|
3409
|
+
splitRow(
|
|
3410
|
+
linkButton("\u{1F310} \u7F51\u9875\u63A7\u5236\u53F0", webConsoleUrl2, "default", "small"),
|
|
3411
|
+
note("\u4EC5\u5728**\u8FD0\u884C bridge \u7684\u8FD9\u53F0\u7535\u8111**\u4E0A\u80FD\u6253\u5F00\uFF08\u672C\u673A\u5730\u5740\uFF09\u3002")
|
|
3412
|
+
)
|
|
3413
|
+
] : []
|
|
3370
3414
|
],
|
|
3371
|
-
{
|
|
3415
|
+
{
|
|
3416
|
+
header: {
|
|
3417
|
+
title: "\u{1F916} Codex Bridge \u7BA1\u7406\u53F0",
|
|
3418
|
+
template: "blue",
|
|
3419
|
+
textTags: version ? [{ text: `v${version}`, color: "green" }] : void 0
|
|
3420
|
+
},
|
|
3421
|
+
// 这张卡可能内嵌带 token 的本机控制台直达链接(pc_url),且按钮全是管理员专属的
|
|
3422
|
+
// dm.* 回调——转发出去既无意义、又会把 token 链接一并带走。loopback 已使转发副本
|
|
3423
|
+
// 在他人设备上不可用,这里再加一道:禁止转发。
|
|
3424
|
+
forward: false
|
|
3425
|
+
}
|
|
3372
3426
|
);
|
|
3373
3427
|
}
|
|
3374
3428
|
var backToMenu = () => actions([button("\u2B05\uFE0F \u83DC\u5355", { a: DM.menu })]);
|
|
@@ -6751,6 +6805,71 @@ function buildUsageShareCard(data, opts = {}) {
|
|
|
6751
6805
|
});
|
|
6752
6806
|
}
|
|
6753
6807
|
|
|
6808
|
+
// src/web/discovery.ts
|
|
6809
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
6810
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
6811
|
+
import { dirname as dirname10 } from "path";
|
|
6812
|
+
function publishWebConsole(rec, file = paths.webConsoleFile) {
|
|
6813
|
+
mkdirSync2(dirname10(file), { recursive: true });
|
|
6814
|
+
try {
|
|
6815
|
+
unlinkSync(file);
|
|
6816
|
+
} catch {
|
|
6817
|
+
}
|
|
6818
|
+
writeFileSync2(file, `${JSON.stringify(rec, null, 2)}
|
|
6819
|
+
`, { mode: 384 });
|
|
6820
|
+
}
|
|
6821
|
+
function readWebConsole(file = paths.webConsoleFile) {
|
|
6822
|
+
try {
|
|
6823
|
+
const rec = JSON.parse(readFileSync5(file, "utf8"));
|
|
6824
|
+
if (typeof rec.port !== "number" || typeof rec.token !== "string" || rec.token === "" || typeof rec.pid !== "number") {
|
|
6825
|
+
return void 0;
|
|
6826
|
+
}
|
|
6827
|
+
if (!isAlive(rec.pid)) return void 0;
|
|
6828
|
+
return rec;
|
|
6829
|
+
} catch {
|
|
6830
|
+
return void 0;
|
|
6831
|
+
}
|
|
6832
|
+
}
|
|
6833
|
+
function webConsoleUrl(file = paths.webConsoleFile) {
|
|
6834
|
+
const rec = readWebConsole(file);
|
|
6835
|
+
if (!rec) return void 0;
|
|
6836
|
+
return `http://127.0.0.1:${rec.port}/?token=${encodeURIComponent(rec.token)}`;
|
|
6837
|
+
}
|
|
6838
|
+
function clearWebConsole(file = paths.webConsoleFile) {
|
|
6839
|
+
try {
|
|
6840
|
+
const rec = JSON.parse(readFileSync5(file, "utf8"));
|
|
6841
|
+
if (rec.pid === process.pid) unlinkSync(file);
|
|
6842
|
+
} catch {
|
|
6843
|
+
}
|
|
6844
|
+
}
|
|
6845
|
+
function stableWebConsoleToken(file = paths.webTokenFile) {
|
|
6846
|
+
try {
|
|
6847
|
+
const t = readFileSync5(file, "utf8").trim();
|
|
6848
|
+
if (t) return t;
|
|
6849
|
+
} catch {
|
|
6850
|
+
}
|
|
6851
|
+
const token = randomUUID3();
|
|
6852
|
+
try {
|
|
6853
|
+
mkdirSync2(dirname10(file), { recursive: true });
|
|
6854
|
+
try {
|
|
6855
|
+
unlinkSync(file);
|
|
6856
|
+
} catch {
|
|
6857
|
+
}
|
|
6858
|
+
writeFileSync2(file, `${token}
|
|
6859
|
+
`, { mode: 384 });
|
|
6860
|
+
} catch {
|
|
6861
|
+
}
|
|
6862
|
+
return token;
|
|
6863
|
+
}
|
|
6864
|
+
function isAlive(pid) {
|
|
6865
|
+
try {
|
|
6866
|
+
process.kill(pid, 0);
|
|
6867
|
+
return true;
|
|
6868
|
+
} catch (err) {
|
|
6869
|
+
return err.code === "EPERM";
|
|
6870
|
+
}
|
|
6871
|
+
}
|
|
6872
|
+
|
|
6754
6873
|
// src/project/lifecycle.ts
|
|
6755
6874
|
import { mkdir as mkdir10 } from "fs/promises";
|
|
6756
6875
|
import { existsSync as existsSync9 } from "fs";
|
|
@@ -7019,8 +7138,8 @@ async function leaveChat(channel, chatId) {
|
|
|
7019
7138
|
|
|
7020
7139
|
// src/bot/session-store.ts
|
|
7021
7140
|
import { mkdir as mkdir11, readFile as readFile10, rename as rename5, writeFile as writeFile9 } from "fs/promises";
|
|
7022
|
-
import { randomUUID as
|
|
7023
|
-
import { dirname as
|
|
7141
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
7142
|
+
import { dirname as dirname11 } from "path";
|
|
7024
7143
|
var FILE_VERSION3 = 2;
|
|
7025
7144
|
var LEGACY_V1_SESSION_FIELD = "codexThreadId";
|
|
7026
7145
|
function migrate(raw) {
|
|
@@ -7056,8 +7175,8 @@ function withLock2(fn) {
|
|
|
7056
7175
|
return run;
|
|
7057
7176
|
}
|
|
7058
7177
|
async function write2(sessions) {
|
|
7059
|
-
await mkdir11(
|
|
7060
|
-
const tmp = `${paths.sessionsFile}.tmp-${process.pid}-${
|
|
7178
|
+
await mkdir11(dirname11(paths.sessionsFile), { recursive: true });
|
|
7179
|
+
const tmp = `${paths.sessionsFile}.tmp-${process.pid}-${randomUUID4()}`;
|
|
7061
7180
|
const body = { version: FILE_VERSION3, sessions };
|
|
7062
7181
|
await writeFile9(tmp, `${JSON.stringify(body, null, 2)}
|
|
7063
7182
|
`, "utf8");
|
|
@@ -7101,7 +7220,7 @@ async function handleDmConsole(channel, cfg, msg) {
|
|
|
7101
7220
|
await channel.send(msg.chatId, { markdown: "\u26D4 \u4EC5\u7BA1\u7406\u5458\u53EF\u5728\u79C1\u804A\u91CC\u7BA1\u7406\u9879\u76EE\u3002" }, { replyTo: msg.messageId }).catch(() => void 0);
|
|
7102
7221
|
return;
|
|
7103
7222
|
}
|
|
7104
|
-
await sendManagedCard(channel, msg.chatId, buildDmMenuCard(), msg.messageId).catch(
|
|
7223
|
+
await sendManagedCard(channel, msg.chatId, buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() }), msg.messageId).catch(
|
|
7105
7224
|
(err) => log.fail("console", err, { cmd: "menu-send" })
|
|
7106
7225
|
);
|
|
7107
7226
|
});
|
|
@@ -8863,7 +8982,7 @@ function createOrchestrator(channel, cfg, fallbackCwd) {
|
|
|
8863
8982
|
patch(evt, buildSettingsCard(cfg));
|
|
8864
8983
|
}
|
|
8865
8984
|
const freshMenu = (evt) => {
|
|
8866
|
-
patch(evt, buildDmMenuCard());
|
|
8985
|
+
patch(evt, buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() }));
|
|
8867
8986
|
};
|
|
8868
8987
|
const runUsage = (evt, force) => {
|
|
8869
8988
|
if (!dmAdmin(evt.operator?.openId)) return;
|
|
@@ -9213,7 +9332,7 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
9213
9332
|
const name = typeof value.n === "string" ? value.n : "";
|
|
9214
9333
|
patch(evt, async () => {
|
|
9215
9334
|
const p = await getProjectByName(name);
|
|
9216
|
-
if (!p) return buildDmMenuCard();
|
|
9335
|
+
if (!p) return buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() });
|
|
9217
9336
|
return buildAllowlistCard(p, await namesWithOperator(evt, p.allowedUsers ?? []));
|
|
9218
9337
|
});
|
|
9219
9338
|
}).on(DM.addAllowedForm, ({ evt, value }) => {
|
|
@@ -9245,7 +9364,7 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
9245
9364
|
patch(evt, async () => {
|
|
9246
9365
|
await updateProject(name, (p) => ({ allowedUsers: (p.allowedUsers ?? []).filter((x) => x !== id) }));
|
|
9247
9366
|
const fresh = await getProjectByName(name);
|
|
9248
|
-
if (!fresh) return buildDmMenuCard();
|
|
9367
|
+
if (!fresh) return buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() });
|
|
9249
9368
|
return buildAllowlistCard(fresh, await namesWithOperator(evt, fresh.allowedUsers ?? []));
|
|
9250
9369
|
});
|
|
9251
9370
|
}).on(DM.projectSettings, ({ evt, value }) => {
|
|
@@ -9253,14 +9372,14 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
9253
9372
|
const name = typeof value.n === "string" ? value.n : "";
|
|
9254
9373
|
patch(evt, async () => {
|
|
9255
9374
|
const p = await getProjectByName(name);
|
|
9256
|
-
return p ? buildProjectSettingsCard(p, backendDisplayName(p.backend)) : buildDmMenuCard();
|
|
9375
|
+
return p ? buildProjectSettingsCard(p, backendDisplayName(p.backend)) : buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() });
|
|
9257
9376
|
});
|
|
9258
9377
|
}).on(DM.projectTopics, ({ evt, value }) => {
|
|
9259
9378
|
if (!dmAdmin(evt.operator?.openId)) return;
|
|
9260
9379
|
const name = typeof value.n === "string" ? value.n : "";
|
|
9261
9380
|
patch(evt, async () => {
|
|
9262
9381
|
const p = await getProjectByName(name);
|
|
9263
|
-
if (!p) return buildDmMenuCard();
|
|
9382
|
+
if (!p) return buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() });
|
|
9264
9383
|
const sessions2 = (await listSessions()).filter((s) => s.chatId === p.chatId);
|
|
9265
9384
|
return buildProjectTopicsCard(p, sessions2);
|
|
9266
9385
|
});
|
|
@@ -9270,7 +9389,7 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
9270
9389
|
const on = value.v === "on";
|
|
9271
9390
|
patch(evt, async () => {
|
|
9272
9391
|
const r = await performSetNoMention({ projectName: name, on });
|
|
9273
|
-
if (!r.ok) return buildDmMenuCard();
|
|
9392
|
+
if (!r.ok) return buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() });
|
|
9274
9393
|
return buildProjectSettingsCard(r.project, backendDisplayName(r.project.backend));
|
|
9275
9394
|
});
|
|
9276
9395
|
}).on(DM.setAutoCompactDm, ({ evt, value }) => {
|
|
@@ -9279,7 +9398,7 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
9279
9398
|
const on = value.v === "on";
|
|
9280
9399
|
patch(evt, async () => {
|
|
9281
9400
|
const r = await performSetAutoCompact({ projectName: name, on, evictLiveSessionsForChat });
|
|
9282
|
-
if (!r.ok) return buildDmMenuCard();
|
|
9401
|
+
if (!r.ok) return buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() });
|
|
9283
9402
|
log.info("console", "project-autocompact", { project: name, on });
|
|
9284
9403
|
return buildProjectSettingsCard(r.project, backendDisplayName(r.project.backend));
|
|
9285
9404
|
});
|
|
@@ -9288,7 +9407,7 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
9288
9407
|
const name = typeof value.n === "string" ? value.n : "";
|
|
9289
9408
|
patch(evt, async () => {
|
|
9290
9409
|
const p = await getProjectByName(name);
|
|
9291
|
-
return p ? buildPermissionCard(p) : buildDmMenuCard();
|
|
9410
|
+
return p ? buildPermissionCard(p) : buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() });
|
|
9292
9411
|
});
|
|
9293
9412
|
}).on(DM.permissionSubmit, ({ evt, value, formValue }) => {
|
|
9294
9413
|
if (!dmAdmin(evt.operator?.openId)) return;
|
|
@@ -10089,7 +10208,7 @@ ${tail}` }, { replyTo: evt.messageId }).catch(() => void 0);
|
|
|
10089
10208
|
}).catch(() => void 0);
|
|
10090
10209
|
return;
|
|
10091
10210
|
}
|
|
10092
|
-
await sendManagedCard(channel, op, buildDmMenuCard(), void 0, false, "open_id").catch(
|
|
10211
|
+
await sendManagedCard(channel, op, buildDmMenuCard({ webConsoleUrl: webConsoleUrl(), version: bridgeVersion() }), void 0, false, "open_id").catch(
|
|
10093
10212
|
(err) => log.fail("console", err, { cmd: "menu-card" })
|
|
10094
10213
|
);
|
|
10095
10214
|
};
|
|
@@ -10355,7 +10474,7 @@ function withOwnerAdmin(base, ownerOpenId) {
|
|
|
10355
10474
|
|
|
10356
10475
|
// src/admin/host.ts
|
|
10357
10476
|
import { readdir as readdir4, stat as stat4 } from "fs/promises";
|
|
10358
|
-
import { dirname as
|
|
10477
|
+
import { dirname as dirname12, join as join18, resolve as resolve7 } from "path";
|
|
10359
10478
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
10360
10479
|
import { arch, platform as platform2, release } from "os";
|
|
10361
10480
|
function toDaemonStatus(opts) {
|
|
@@ -10407,7 +10526,7 @@ async function collectHostDoctor(logsDir2 = join18(paths.appDir, "logs")) {
|
|
|
10407
10526
|
};
|
|
10408
10527
|
}
|
|
10409
10528
|
function resolveCliBinPath3() {
|
|
10410
|
-
const distDir =
|
|
10529
|
+
const distDir = dirname12(fileURLToPath5(import.meta.url));
|
|
10411
10530
|
return resolve7(distDir, "..", "bin", "feishu-codex-bridge.mjs");
|
|
10412
10531
|
}
|
|
10413
10532
|
function buildDaemonControlCommand(action, binPath = resolveCliBinPath3(), nodePath = process.execPath) {
|
|
@@ -10457,7 +10576,7 @@ function createAdminService(deps = {}) {
|
|
|
10457
10576
|
try {
|
|
10458
10577
|
const raw = await readFile11(botPaths(botId).processesFile, "utf8");
|
|
10459
10578
|
const rec = JSON.parse(raw);
|
|
10460
|
-
if (typeof rec.pid === "number" &&
|
|
10579
|
+
if (typeof rec.pid === "number" && isAlive2(rec.pid)) {
|
|
10461
10580
|
return { running: true, pid: rec.pid, startedAt: rec.startedAt };
|
|
10462
10581
|
}
|
|
10463
10582
|
} catch {
|
|
@@ -10853,7 +10972,7 @@ async function probeAllBackends() {
|
|
|
10853
10972
|
function createReadonlyAdminService(deps = {}) {
|
|
10854
10973
|
return createAdminService({ startDaemon: deps.startDaemon, applyUpdate: deps.applyUpdate, readonlyPreview: true });
|
|
10855
10974
|
}
|
|
10856
|
-
function
|
|
10975
|
+
function isAlive2(pid) {
|
|
10857
10976
|
try {
|
|
10858
10977
|
process.kill(pid, 0);
|
|
10859
10978
|
return true;
|
|
@@ -10862,66 +10981,6 @@ function isAlive(pid) {
|
|
|
10862
10981
|
}
|
|
10863
10982
|
}
|
|
10864
10983
|
|
|
10865
|
-
// src/web/discovery.ts
|
|
10866
|
-
import { randomUUID as randomUUID4 } from "crypto";
|
|
10867
|
-
import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
10868
|
-
import { dirname as dirname12 } from "path";
|
|
10869
|
-
function publishWebConsole(rec, file = paths.webConsoleFile) {
|
|
10870
|
-
mkdirSync2(dirname12(file), { recursive: true });
|
|
10871
|
-
try {
|
|
10872
|
-
unlinkSync(file);
|
|
10873
|
-
} catch {
|
|
10874
|
-
}
|
|
10875
|
-
writeFileSync2(file, `${JSON.stringify(rec, null, 2)}
|
|
10876
|
-
`, { mode: 384 });
|
|
10877
|
-
}
|
|
10878
|
-
function readWebConsole(file = paths.webConsoleFile) {
|
|
10879
|
-
try {
|
|
10880
|
-
const rec = JSON.parse(readFileSync5(file, "utf8"));
|
|
10881
|
-
if (typeof rec.port !== "number" || typeof rec.token !== "string" || rec.token === "" || typeof rec.pid !== "number") {
|
|
10882
|
-
return void 0;
|
|
10883
|
-
}
|
|
10884
|
-
if (!isAlive2(rec.pid)) return void 0;
|
|
10885
|
-
return rec;
|
|
10886
|
-
} catch {
|
|
10887
|
-
return void 0;
|
|
10888
|
-
}
|
|
10889
|
-
}
|
|
10890
|
-
function clearWebConsole(file = paths.webConsoleFile) {
|
|
10891
|
-
try {
|
|
10892
|
-
const rec = JSON.parse(readFileSync5(file, "utf8"));
|
|
10893
|
-
if (rec.pid === process.pid) unlinkSync(file);
|
|
10894
|
-
} catch {
|
|
10895
|
-
}
|
|
10896
|
-
}
|
|
10897
|
-
function stableWebConsoleToken(file = paths.webTokenFile) {
|
|
10898
|
-
try {
|
|
10899
|
-
const t = readFileSync5(file, "utf8").trim();
|
|
10900
|
-
if (t) return t;
|
|
10901
|
-
} catch {
|
|
10902
|
-
}
|
|
10903
|
-
const token = randomUUID4();
|
|
10904
|
-
try {
|
|
10905
|
-
mkdirSync2(dirname12(file), { recursive: true });
|
|
10906
|
-
try {
|
|
10907
|
-
unlinkSync(file);
|
|
10908
|
-
} catch {
|
|
10909
|
-
}
|
|
10910
|
-
writeFileSync2(file, `${token}
|
|
10911
|
-
`, { mode: 384 });
|
|
10912
|
-
} catch {
|
|
10913
|
-
}
|
|
10914
|
-
return token;
|
|
10915
|
-
}
|
|
10916
|
-
function isAlive2(pid) {
|
|
10917
|
-
try {
|
|
10918
|
-
process.kill(pid, 0);
|
|
10919
|
-
return true;
|
|
10920
|
-
} catch (err) {
|
|
10921
|
-
return err.code === "EPERM";
|
|
10922
|
-
}
|
|
10923
|
-
}
|
|
10924
|
-
|
|
10925
10984
|
// src/cli/commands/daemon-control.ts
|
|
10926
10985
|
function spawnDaemonControl(action) {
|
|
10927
10986
|
const { command, args } = buildDaemonControlCommand(action);
|