@modelzen/feishu-codex-bridge 0.2.2-win → 0.3.0-win.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 +183 -143
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -274,10 +274,10 @@ import { extname, join as join3 } from "path";
|
|
|
274
274
|
// src/platform/spawn.ts
|
|
275
275
|
import crossSpawn from "cross-spawn";
|
|
276
276
|
function spawnProcess(command, args = [], options = {}) {
|
|
277
|
-
return crossSpawn(command, [...args], options);
|
|
277
|
+
return crossSpawn(command, [...args], { windowsHide: true, ...options });
|
|
278
278
|
}
|
|
279
279
|
function spawnProcessSync(command, args = [], options = {}) {
|
|
280
|
-
return crossSpawn.sync(command, [...args], options);
|
|
280
|
+
return crossSpawn.sync(command, [...args], { windowsHide: true, ...options });
|
|
281
281
|
}
|
|
282
282
|
function mergeProcessEnv(base = process.env, overrides = {}) {
|
|
283
283
|
const out = { ...base };
|
|
@@ -491,7 +491,6 @@ async function listSecretIds() {
|
|
|
491
491
|
}
|
|
492
492
|
|
|
493
493
|
// src/config/secret-resolver.ts
|
|
494
|
-
import { spawn } from "child_process";
|
|
495
494
|
import { readFile as readFile4 } from "fs/promises";
|
|
496
495
|
import { join as join5 } from "path";
|
|
497
496
|
var ENV_TEMPLATE_RE = /^\$\{([A-Z][A-Z0-9_]{0,127})\}$/;
|
|
@@ -577,7 +576,10 @@ async function spawnExecProvider(pc, ref) {
|
|
|
577
576
|
if (v) env[k] = v;
|
|
578
577
|
}
|
|
579
578
|
if (pc.env) Object.assign(env, pc.env);
|
|
580
|
-
const child =
|
|
579
|
+
const child = spawnProcess(pc.command, pc.args ?? [], {
|
|
580
|
+
env,
|
|
581
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
582
|
+
});
|
|
581
583
|
let stdout = "", stderr = "", truncated = false, settled = false;
|
|
582
584
|
const timer = setTimeout(() => {
|
|
583
585
|
if (settled) return;
|
|
@@ -812,7 +814,7 @@ async function fetchGrantedScopes(base, token) {
|
|
|
812
814
|
}
|
|
813
815
|
|
|
814
816
|
// src/utils/open-url.ts
|
|
815
|
-
import { spawn
|
|
817
|
+
import { spawn } from "child_process";
|
|
816
818
|
import { platform } from "os";
|
|
817
819
|
function openUrl(url) {
|
|
818
820
|
if (!process.stdout.isTTY) return false;
|
|
@@ -832,7 +834,7 @@ function openUrl(url) {
|
|
|
832
834
|
args = [url];
|
|
833
835
|
}
|
|
834
836
|
try {
|
|
835
|
-
const child =
|
|
837
|
+
const child = spawn(cmd, args, { stdio: "ignore", detached: true });
|
|
836
838
|
child.on("error", () => {
|
|
837
839
|
});
|
|
838
840
|
child.unref();
|
|
@@ -3556,14 +3558,12 @@ function buildGroupSettingsCard(project) {
|
|
|
3556
3558
|
}
|
|
3557
3559
|
|
|
3558
3560
|
// src/service/update.ts
|
|
3559
|
-
import {
|
|
3560
|
-
import {
|
|
3561
|
-
import { dirname as dirname10, join as join11, resolve as resolve5 } from "path";
|
|
3561
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
|
|
3562
|
+
import { dirname as dirname9, join as join11, resolve as resolve5 } from "path";
|
|
3562
3563
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3563
|
-
import { promisify } from "util";
|
|
3564
3564
|
|
|
3565
3565
|
// src/service/launchd.ts
|
|
3566
|
-
import { spawn as
|
|
3566
|
+
import { spawn as spawn2, spawnSync } from "child_process";
|
|
3567
3567
|
import { existsSync as existsSync4 } from "fs";
|
|
3568
3568
|
import { mkdir as mkdir6, rm as rm2, writeFile as writeFile5 } from "fs/promises";
|
|
3569
3569
|
import { homedir as homedir3, userInfo as userInfo2 } from "os";
|
|
@@ -3741,7 +3741,7 @@ async function tailLaunchdLogs(follow) {
|
|
|
3741
3741
|
await ensureLogFiles();
|
|
3742
3742
|
const args = follow ? ["-f", serviceStdoutPath(), serviceStderrPath()] : ["-n", "100", serviceStdoutPath(), serviceStderrPath()];
|
|
3743
3743
|
await new Promise((resolvePromise, reject) => {
|
|
3744
|
-
const child =
|
|
3744
|
+
const child = spawn2("tail", args, { stdio: "inherit" });
|
|
3745
3745
|
child.on("error", reject);
|
|
3746
3746
|
child.on("close", (code) => {
|
|
3747
3747
|
if (code === 0 || follow && code === null) {
|
|
@@ -3792,126 +3792,150 @@ function launchctlError(command, result) {
|
|
|
3792
3792
|
return new Error(`${command} \u5931\u8D25\uFF08exit ${result.status ?? "unknown"}\uFF09${output ? `\uFF1A${output}` : ""}`);
|
|
3793
3793
|
}
|
|
3794
3794
|
|
|
3795
|
-
// src/service/
|
|
3796
|
-
import { spawnSync as spawnSync2 } from "child_process";
|
|
3797
|
-
import {
|
|
3798
|
-
import { mkdir as mkdir7,
|
|
3799
|
-
import {
|
|
3800
|
-
var
|
|
3795
|
+
// src/service/win-startup.ts
|
|
3796
|
+
import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
|
|
3797
|
+
import { openSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "fs";
|
|
3798
|
+
import { mkdir as mkdir7, writeFile as writeFile6 } from "fs/promises";
|
|
3799
|
+
import { join as join9 } from "path";
|
|
3800
|
+
var RUN_KEY_PATH = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
|
3801
|
+
var RUN_KEY_NAME = "feishu-codex-bridge";
|
|
3802
|
+
var SERVICE_ENV_FLAG = "FEISHU_CODEX_BRIDGE_SERVICE";
|
|
3801
3803
|
function launcherCmdPath() {
|
|
3802
3804
|
return join9(paths.appDir, "service-launcher.cmd");
|
|
3803
3805
|
}
|
|
3806
|
+
function launcherVbsPath() {
|
|
3807
|
+
return join9(paths.appDir, "service-launcher.vbs");
|
|
3808
|
+
}
|
|
3809
|
+
function servicePidFile() {
|
|
3810
|
+
return join9(paths.appDir, "service.pid");
|
|
3811
|
+
}
|
|
3804
3812
|
function buildLauncherCmd() {
|
|
3805
|
-
const nodePath = process.execPath;
|
|
3806
|
-
const cliBinPath = resolveCliBinPath();
|
|
3807
|
-
const pathEnv = process.env.PATH ?? "";
|
|
3808
3813
|
return [
|
|
3809
3814
|
"@echo off",
|
|
3810
|
-
`set "PATH=${
|
|
3811
|
-
`
|
|
3815
|
+
`set "PATH=${process.env.PATH ?? ""}"`,
|
|
3816
|
+
`set "${SERVICE_ENV_FLAG}=1"`,
|
|
3817
|
+
`"${process.execPath}" "${resolveCliBinPath()}" run >> "${serviceStdoutPath()}" 2>> "${serviceStderrPath()}"`,
|
|
3812
3818
|
""
|
|
3813
3819
|
].join("\r\n");
|
|
3814
3820
|
}
|
|
3815
|
-
function
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
};
|
|
3821
|
+
function buildLauncherVbs() {
|
|
3822
|
+
return [
|
|
3823
|
+
"' Auto-generated by feishu-codex-bridge. Do not edit.",
|
|
3824
|
+
'Set sh = CreateObject("WScript.Shell")',
|
|
3825
|
+
`sh.Run "cmd /c ""${launcherCmdPath()}""", 0, False`,
|
|
3826
|
+
""
|
|
3827
|
+
].join("\r\n");
|
|
3823
3828
|
}
|
|
3824
|
-
function
|
|
3825
|
-
const out =
|
|
3826
|
-
|
|
3829
|
+
function startNow() {
|
|
3830
|
+
const out = openSync(serviceStdoutPath(), "a");
|
|
3831
|
+
const err = openSync(serviceStderrPath(), "a");
|
|
3832
|
+
const child = spawn3(process.execPath, [resolveCliBinPath(), "run"], {
|
|
3833
|
+
detached: true,
|
|
3834
|
+
windowsHide: true,
|
|
3835
|
+
stdio: ["ignore", out, err],
|
|
3836
|
+
env: mergeProcessEnv(process.env, { [SERVICE_ENV_FLAG]: "1" })
|
|
3837
|
+
});
|
|
3838
|
+
if (child.pid) writeFileSync(servicePidFile(), String(child.pid), "utf8");
|
|
3839
|
+
child.unref();
|
|
3840
|
+
}
|
|
3841
|
+
async function installWinStartup() {
|
|
3842
|
+
await mkdir7(paths.appDir, { recursive: true });
|
|
3843
|
+
await ensureLogFiles();
|
|
3844
|
+
await writeFile6(launcherCmdPath(), buildLauncherCmd(), "utf8");
|
|
3845
|
+
await writeFile6(launcherVbsPath(), buildLauncherVbs(), "utf8");
|
|
3846
|
+
const reg = spawnSync2(
|
|
3847
|
+
"reg",
|
|
3848
|
+
["add", RUN_KEY_PATH, "/v", RUN_KEY_NAME, "/t", "REG_SZ", "/d", `wscript.exe "${launcherVbsPath()}"`, "/f"],
|
|
3849
|
+
{ encoding: "utf8" }
|
|
3850
|
+
);
|
|
3851
|
+
if (reg.status !== 0) {
|
|
3852
|
+
throw new Error(`\u5199\u5165\u767B\u5F55\u81EA\u542F\u6CE8\u518C\u8868\u9879\u5931\u8D25\uFF08exit ${reg.status ?? "unknown"}\uFF09\uFF1A${(reg.stderr || reg.stdout || "").trim()}`);
|
|
3853
|
+
}
|
|
3854
|
+
startNow();
|
|
3855
|
+
return statusWinStartup();
|
|
3856
|
+
}
|
|
3857
|
+
async function uninstallWinStartup() {
|
|
3858
|
+
spawnSync2("reg", ["delete", RUN_KEY_PATH, "/v", RUN_KEY_NAME, "/f"], { stdio: "ignore" });
|
|
3859
|
+
killService();
|
|
3860
|
+
rmSync(servicePidFile(), { force: true });
|
|
3827
3861
|
}
|
|
3828
|
-
async function
|
|
3829
|
-
|
|
3830
|
-
|
|
3862
|
+
async function restartWinStartup() {
|
|
3863
|
+
if (!isInstalled()) {
|
|
3864
|
+
throw new Error("\u767B\u5F55\u81EA\u542F\u672A\u5B89\u88C5\uFF08\u5148\u8FD0\u884C `feishu-codex-bridge start`\uFF09\u3002");
|
|
3865
|
+
}
|
|
3831
3866
|
await ensureLogFiles();
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
"ONLOGON",
|
|
3841
|
-
"/RL",
|
|
3842
|
-
"LIMITED",
|
|
3843
|
-
"/TN",
|
|
3844
|
-
WINDOWS_TASK_NAME,
|
|
3845
|
-
"/TR",
|
|
3846
|
-
`"${launcherCmdPath()}"`
|
|
3847
|
-
]);
|
|
3848
|
-
if (!create.ok) throw schtasksError("schtasks /Create", create);
|
|
3849
|
-
const run = runSchtasks(["/Run", "/TN", WINDOWS_TASK_NAME]);
|
|
3850
|
-
if (!run.ok) throw schtasksError("schtasks /Run", run);
|
|
3851
|
-
return statusSchtask();
|
|
3852
|
-
}
|
|
3853
|
-
async function uninstallSchtask() {
|
|
3854
|
-
runSchtasks(["/End", "/TN", WINDOWS_TASK_NAME]);
|
|
3855
|
-
const del = runSchtasks(["/Delete", "/F", "/TN", WINDOWS_TASK_NAME]);
|
|
3856
|
-
if (!del.ok && isTaskRegistered()) throw schtasksError("schtasks /Delete", del);
|
|
3857
|
-
if (existsSync5(launcherCmdPath())) await rm3(launcherCmdPath(), { force: true });
|
|
3858
|
-
}
|
|
3859
|
-
async function restartSchtask() {
|
|
3860
|
-
if (!isTaskRegistered()) {
|
|
3861
|
-
throw new Error(`\u8BA1\u5212\u4EFB\u52A1\u672A\u5B89\u88C5\uFF1A${WINDOWS_TASK_NAME}\uFF08\u5148\u8FD0\u884C \`feishu-codex-bridge start\`\uFF09`);
|
|
3862
|
-
}
|
|
3863
|
-
runSchtasks(["/End", "/TN", WINDOWS_TASK_NAME]);
|
|
3864
|
-
await waitUntilStopped();
|
|
3865
|
-
const run = runSchtasks(["/Run", "/TN", WINDOWS_TASK_NAME]);
|
|
3866
|
-
if (!run.ok) throw schtasksError("schtasks /Run", run);
|
|
3867
|
-
return statusSchtask();
|
|
3868
|
-
}
|
|
3869
|
-
function statusSchtask() {
|
|
3870
|
-
const installed = isTaskRegistered();
|
|
3871
|
-
const raw = installed ? describeTask() : "";
|
|
3867
|
+
killService();
|
|
3868
|
+
startNow();
|
|
3869
|
+
return statusWinStartup();
|
|
3870
|
+
}
|
|
3871
|
+
function statusWinStartup() {
|
|
3872
|
+
const installed = isInstalled();
|
|
3873
|
+
const pid = readServicePid();
|
|
3874
|
+
const running = pid !== null && pidAlive(pid);
|
|
3872
3875
|
return {
|
|
3873
|
-
platformName: "
|
|
3876
|
+
platformName: "Windows \u767B\u5F55\u81EA\u542F\uFF08HKCU Run\uFF0C\u514D\u7BA1\u7406\u5458\uFF09",
|
|
3874
3877
|
installed,
|
|
3875
|
-
running
|
|
3876
|
-
servicePath:
|
|
3878
|
+
running,
|
|
3879
|
+
servicePath: `${RUN_KEY_PATH}\\${RUN_KEY_NAME}`,
|
|
3877
3880
|
stdoutPath: serviceStdoutPath(),
|
|
3878
3881
|
stderrPath: serviceStderrPath(),
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
// `Last Result: 0` ⇒ last run succeeded. Surface it as the exit code.
|
|
3882
|
-
lastExit: raw.match(/Last Result:\s*(-?\d+)/i)?.[1],
|
|
3883
|
-
raw
|
|
3882
|
+
pid: running && pid !== null ? String(pid) : void 0,
|
|
3883
|
+
raw: ""
|
|
3884
3884
|
};
|
|
3885
3885
|
}
|
|
3886
|
-
function
|
|
3887
|
-
const
|
|
3886
|
+
function winStartupRunning() {
|
|
3887
|
+
const pid = readServicePid();
|
|
3888
|
+
return pid !== null && pidAlive(pid);
|
|
3889
|
+
}
|
|
3890
|
+
function recordServicePid() {
|
|
3891
|
+
if (process.platform !== "win32" || !process.env[SERVICE_ENV_FLAG]) return;
|
|
3892
|
+
try {
|
|
3893
|
+
writeFileSync(servicePidFile(), String(process.pid), "utf8");
|
|
3894
|
+
} catch {
|
|
3895
|
+
}
|
|
3896
|
+
process.once("exit", clearServicePid);
|
|
3897
|
+
}
|
|
3898
|
+
function clearServicePid() {
|
|
3899
|
+
if (process.platform !== "win32" || !process.env[SERVICE_ENV_FLAG]) return;
|
|
3900
|
+
try {
|
|
3901
|
+
if (readServicePid() === process.pid) rmSync(servicePidFile(), { force: true });
|
|
3902
|
+
} catch {
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
function isInstalled() {
|
|
3906
|
+
const r = spawnSync2("reg", ["query", RUN_KEY_PATH, "/v", RUN_KEY_NAME], {
|
|
3888
3907
|
stdio: ["ignore", "ignore", "ignore"]
|
|
3889
3908
|
});
|
|
3890
3909
|
return r.status === 0;
|
|
3891
3910
|
}
|
|
3892
|
-
function
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3911
|
+
function readServicePid() {
|
|
3912
|
+
try {
|
|
3913
|
+
const pid = Number.parseInt(readFileSync2(servicePidFile(), "utf8").trim(), 10);
|
|
3914
|
+
return Number.isFinite(pid) ? pid : null;
|
|
3915
|
+
} catch {
|
|
3916
|
+
return null;
|
|
3917
|
+
}
|
|
3899
3918
|
}
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3919
|
+
function pidAlive(pid) {
|
|
3920
|
+
try {
|
|
3921
|
+
process.kill(pid, 0);
|
|
3922
|
+
return true;
|
|
3923
|
+
} catch (err) {
|
|
3924
|
+
return err.code === "EPERM";
|
|
3905
3925
|
}
|
|
3906
|
-
|
|
3926
|
+
}
|
|
3927
|
+
function killService() {
|
|
3928
|
+
const pid = readServicePid();
|
|
3929
|
+
if (pid === null || !pidAlive(pid)) return;
|
|
3930
|
+
spawnSync2("taskkill", ["/pid", String(pid), "/T", "/F"], { stdio: "ignore" });
|
|
3907
3931
|
}
|
|
3908
3932
|
|
|
3909
3933
|
// src/service/systemd.ts
|
|
3910
3934
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
3911
|
-
import { existsSync as
|
|
3912
|
-
import { mkdir as mkdir8, rm as
|
|
3935
|
+
import { existsSync as existsSync5 } from "fs";
|
|
3936
|
+
import { mkdir as mkdir8, rm as rm3, writeFile as writeFile7 } from "fs/promises";
|
|
3913
3937
|
import { homedir as homedir4 } from "os";
|
|
3914
|
-
import { dirname as
|
|
3938
|
+
import { dirname as dirname8, join as join10 } from "path";
|
|
3915
3939
|
var SYSTEMD_UNIT_NAME = "feishu-codex-bridge.service";
|
|
3916
3940
|
function systemdUnitPath() {
|
|
3917
3941
|
const base = process.env.XDG_CONFIG_HOME ?? join10(homedir4(), ".config");
|
|
@@ -3969,7 +3993,7 @@ function ensureSystemdOrThrow() {
|
|
|
3969
3993
|
async function installSystemd() {
|
|
3970
3994
|
ensureSystemdOrThrow();
|
|
3971
3995
|
const unitPath = systemdUnitPath();
|
|
3972
|
-
await mkdir8(
|
|
3996
|
+
await mkdir8(dirname8(unitPath), { recursive: true });
|
|
3973
3997
|
await ensureLogFiles();
|
|
3974
3998
|
await writeFile7(unitPath, buildUnit(), "utf8");
|
|
3975
3999
|
const reload = runSystemctl(["daemon-reload"]);
|
|
@@ -3982,7 +4006,7 @@ async function uninstallSystemd() {
|
|
|
3982
4006
|
if (systemdAvailable() && unitExists()) {
|
|
3983
4007
|
runSystemctl(["disable", "--now", SYSTEMD_UNIT_NAME]);
|
|
3984
4008
|
}
|
|
3985
|
-
await
|
|
4009
|
+
await rm3(systemdUnitPath(), { force: true });
|
|
3986
4010
|
if (systemdAvailable()) runSystemctl(["daemon-reload"]);
|
|
3987
4011
|
}
|
|
3988
4012
|
async function restartSystemd() {
|
|
@@ -4012,7 +4036,7 @@ function statusSystemd() {
|
|
|
4012
4036
|
};
|
|
4013
4037
|
}
|
|
4014
4038
|
function unitExists() {
|
|
4015
|
-
return
|
|
4039
|
+
return existsSync5(systemdUnitPath());
|
|
4016
4040
|
}
|
|
4017
4041
|
function systemdActive() {
|
|
4018
4042
|
const r = spawnSync3("systemctl", ["--user", "is-active", SYSTEMD_UNIT_NAME], {
|
|
@@ -4038,10 +4062,10 @@ function getServiceAdapter() {
|
|
|
4038
4062
|
}
|
|
4039
4063
|
if (process.platform === "win32") {
|
|
4040
4064
|
return {
|
|
4041
|
-
install:
|
|
4042
|
-
uninstall:
|
|
4043
|
-
status: async () =>
|
|
4044
|
-
restart:
|
|
4065
|
+
install: installWinStartup,
|
|
4066
|
+
uninstall: uninstallWinStartup,
|
|
4067
|
+
status: async () => statusWinStartup(),
|
|
4068
|
+
restart: restartWinStartup,
|
|
4045
4069
|
logs: tailServiceLogs
|
|
4046
4070
|
};
|
|
4047
4071
|
}
|
|
@@ -4061,7 +4085,7 @@ function getServiceAdapter() {
|
|
|
4061
4085
|
function isServiceRunning() {
|
|
4062
4086
|
try {
|
|
4063
4087
|
if (process.platform === "darwin") return isLoaded();
|
|
4064
|
-
if (process.platform === "win32") return
|
|
4088
|
+
if (process.platform === "win32") return winStartupRunning();
|
|
4065
4089
|
if (process.platform === "linux") return systemdActive();
|
|
4066
4090
|
} catch {
|
|
4067
4091
|
}
|
|
@@ -4069,14 +4093,13 @@ function isServiceRunning() {
|
|
|
4069
4093
|
}
|
|
4070
4094
|
|
|
4071
4095
|
// src/service/update.ts
|
|
4072
|
-
var
|
|
4073
|
-
var NPM = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
4096
|
+
var NPM = "npm";
|
|
4074
4097
|
function pkgRoot() {
|
|
4075
|
-
return resolve5(
|
|
4098
|
+
return resolve5(dirname9(fileURLToPath4(import.meta.url)), "..");
|
|
4076
4099
|
}
|
|
4077
4100
|
function pkgJson() {
|
|
4078
4101
|
try {
|
|
4079
|
-
return JSON.parse(
|
|
4102
|
+
return JSON.parse(readFileSync3(join11(pkgRoot(), "package.json"), "utf8"));
|
|
4080
4103
|
} catch {
|
|
4081
4104
|
return {};
|
|
4082
4105
|
}
|
|
@@ -4088,7 +4111,7 @@ function packageName() {
|
|
|
4088
4111
|
return pkgJson().name ?? "@modelzen/feishu-codex-bridge";
|
|
4089
4112
|
}
|
|
4090
4113
|
function isDevSource() {
|
|
4091
|
-
return
|
|
4114
|
+
return existsSync6(join11(pkgRoot(), ".git"));
|
|
4092
4115
|
}
|
|
4093
4116
|
function isNewer(a, b) {
|
|
4094
4117
|
const pa = a.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
@@ -4100,18 +4123,31 @@ function isNewer(a, b) {
|
|
|
4100
4123
|
return false;
|
|
4101
4124
|
}
|
|
4102
4125
|
async function latestVersion() {
|
|
4103
|
-
|
|
4104
|
-
const
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4126
|
+
const v = await new Promise((resolveP) => {
|
|
4127
|
+
const child = spawnProcess(NPM, ["view", packageName(), "version"], {
|
|
4128
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
4129
|
+
});
|
|
4130
|
+
let out = "";
|
|
4131
|
+
const timer = setTimeout(() => {
|
|
4132
|
+
child.kill();
|
|
4133
|
+
resolveP(null);
|
|
4134
|
+
}, 2e4);
|
|
4135
|
+
child.stdout?.on("data", (d) => out += d);
|
|
4136
|
+
child.on("error", () => {
|
|
4137
|
+
clearTimeout(timer);
|
|
4138
|
+
resolveP(null);
|
|
4139
|
+
});
|
|
4140
|
+
child.on("close", (code) => {
|
|
4141
|
+
clearTimeout(timer);
|
|
4142
|
+
resolveP(code === 0 ? out.trim() : null);
|
|
4143
|
+
});
|
|
4144
|
+
});
|
|
4145
|
+
return v && /^\d+\.\d+\.\d+/.test(v) ? v : null;
|
|
4110
4146
|
}
|
|
4111
4147
|
async function installLatest(opts = {}) {
|
|
4112
4148
|
const target = `${packageName()}@latest`;
|
|
4113
4149
|
return await new Promise((resolveP) => {
|
|
4114
|
-
const child =
|
|
4150
|
+
const child = spawnProcess(NPM, ["install", "-g", target], {
|
|
4115
4151
|
stdio: opts.inherit ? ["ignore", "inherit", "inherit"] : ["ignore", "pipe", "pipe"]
|
|
4116
4152
|
});
|
|
4117
4153
|
let out = "";
|
|
@@ -4135,18 +4171,21 @@ async function restartDaemon() {
|
|
|
4135
4171
|
|
|
4136
4172
|
// src/project/lifecycle.ts
|
|
4137
4173
|
import { mkdir as mkdir9 } from "fs/promises";
|
|
4138
|
-
import { existsSync as
|
|
4174
|
+
import { existsSync as existsSync7 } from "fs";
|
|
4139
4175
|
import { isAbsolute as isAbsolute2, join as join12, resolve as resolve6 } from "path";
|
|
4140
4176
|
|
|
4141
4177
|
// src/project/git-info.ts
|
|
4142
|
-
import { execFile
|
|
4143
|
-
import { promisify
|
|
4144
|
-
var execFileAsync =
|
|
4178
|
+
import { execFile } from "child_process";
|
|
4179
|
+
import { promisify } from "util";
|
|
4180
|
+
var execFileAsync = promisify(execFile);
|
|
4145
4181
|
async function currentBranch(cwd) {
|
|
4146
4182
|
try {
|
|
4147
4183
|
const { stdout } = await execFileAsync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
4148
4184
|
cwd,
|
|
4149
|
-
timeout: 3e3
|
|
4185
|
+
timeout: 3e3,
|
|
4186
|
+
// Hide the console window: this runs on every inbound message, and the
|
|
4187
|
+
// Windows background service has no console of its own to inherit.
|
|
4188
|
+
windowsHide: true
|
|
4150
4189
|
});
|
|
4151
4190
|
const b = stdout.trim();
|
|
4152
4191
|
return b && b !== "HEAD" ? b : null;
|
|
@@ -4272,7 +4311,7 @@ async function onboardGroup(channel, project) {
|
|
|
4272
4311
|
async function resolveCwd(name, existingPath) {
|
|
4273
4312
|
if (existingPath) {
|
|
4274
4313
|
const cwd2 = isAbsolute2(existingPath) ? existingPath : resolve6(existingPath);
|
|
4275
|
-
if (!
|
|
4314
|
+
if (!existsSync7(cwd2)) throw new Error(`\u6587\u4EF6\u5939\u4E0D\u5B58\u5728\uFF1A${cwd2}`);
|
|
4276
4315
|
return { cwd: cwd2, blank: false };
|
|
4277
4316
|
}
|
|
4278
4317
|
const cwd = join12(paths.projectsRootDir, name);
|
|
@@ -4344,7 +4383,7 @@ async function leaveChat(channel, chatId) {
|
|
|
4344
4383
|
|
|
4345
4384
|
// src/bot/session-store.ts
|
|
4346
4385
|
import { mkdir as mkdir10, readFile as readFile8, rename as rename5, writeFile as writeFile8 } from "fs/promises";
|
|
4347
|
-
import { dirname as
|
|
4386
|
+
import { dirname as dirname10 } from "path";
|
|
4348
4387
|
var FILE_VERSION3 = 1;
|
|
4349
4388
|
async function read2() {
|
|
4350
4389
|
try {
|
|
@@ -4357,7 +4396,7 @@ async function read2() {
|
|
|
4357
4396
|
}
|
|
4358
4397
|
}
|
|
4359
4398
|
async function write2(sessions) {
|
|
4360
|
-
await mkdir10(
|
|
4399
|
+
await mkdir10(dirname10(paths.sessionsFile), { recursive: true });
|
|
4361
4400
|
const tmp = `${paths.sessionsFile}.tmp-${process.pid}`;
|
|
4362
4401
|
const body = { version: FILE_VERSION3, sessions };
|
|
4363
4402
|
await writeFile8(tmp, `${JSON.stringify(body, null, 2)}
|
|
@@ -4404,7 +4443,7 @@ async function handleDmConsole(channel, cfg, msg) {
|
|
|
4404
4443
|
}
|
|
4405
4444
|
|
|
4406
4445
|
// src/bot/media.ts
|
|
4407
|
-
import { mkdir as mkdir11, readdir as readdir2, rm as
|
|
4446
|
+
import { mkdir as mkdir11, readdir as readdir2, rm as rm4, stat as stat3 } from "fs/promises";
|
|
4408
4447
|
import { join as join13 } from "path";
|
|
4409
4448
|
var MAX_IMAGES2 = 9;
|
|
4410
4449
|
var MEDIA_TTL_MS = 60 * 6e4;
|
|
@@ -4547,7 +4586,7 @@ async function pruneOldMedia() {
|
|
|
4547
4586
|
const file = join13(paths.mediaDir, name);
|
|
4548
4587
|
try {
|
|
4549
4588
|
const st = await stat3(file);
|
|
4550
|
-
if (st.mtimeMs < cutoff) await
|
|
4589
|
+
if (st.mtimeMs < cutoff) await rm4(file, { force: true });
|
|
4551
4590
|
} catch {
|
|
4552
4591
|
}
|
|
4553
4592
|
}
|
|
@@ -5918,8 +5957,8 @@ async function startBridge(opts) {
|
|
|
5918
5957
|
}
|
|
5919
5958
|
|
|
5920
5959
|
// src/core/single-instance.ts
|
|
5921
|
-
import { mkdirSync as mkdirSync2, readFileSync as
|
|
5922
|
-
import { dirname as
|
|
5960
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
5961
|
+
import { dirname as dirname11 } from "path";
|
|
5923
5962
|
var BridgeAlreadyRunningError = class extends Error {
|
|
5924
5963
|
constructor(pid) {
|
|
5925
5964
|
super(
|
|
@@ -5941,20 +5980,20 @@ function isAlive(pid) {
|
|
|
5941
5980
|
function acquireSingleInstanceLock(appId) {
|
|
5942
5981
|
const file = paths.processesFile;
|
|
5943
5982
|
try {
|
|
5944
|
-
const rec = JSON.parse(
|
|
5983
|
+
const rec = JSON.parse(readFileSync4(file, "utf8"));
|
|
5945
5984
|
if (rec.pid && rec.pid !== process.pid && rec.appId === appId && isAlive(rec.pid)) {
|
|
5946
5985
|
throw new BridgeAlreadyRunningError(rec.pid);
|
|
5947
5986
|
}
|
|
5948
5987
|
} catch (err) {
|
|
5949
5988
|
if (err instanceof BridgeAlreadyRunningError) throw err;
|
|
5950
5989
|
}
|
|
5951
|
-
mkdirSync2(
|
|
5990
|
+
mkdirSync2(dirname11(file), { recursive: true });
|
|
5952
5991
|
const record = { pid: process.pid, appId, startedAt: Date.now() };
|
|
5953
|
-
|
|
5992
|
+
writeFileSync2(file, `${JSON.stringify(record)}
|
|
5954
5993
|
`, "utf8");
|
|
5955
5994
|
const release = () => {
|
|
5956
5995
|
try {
|
|
5957
|
-
const rec = JSON.parse(
|
|
5996
|
+
const rec = JSON.parse(readFileSync4(file, "utf8"));
|
|
5958
5997
|
if (rec.pid === process.pid) unlinkSync(file);
|
|
5959
5998
|
} catch {
|
|
5960
5999
|
}
|
|
@@ -5983,6 +6022,7 @@ async function runRun() {
|
|
|
5983
6022
|
}
|
|
5984
6023
|
throw err;
|
|
5985
6024
|
}
|
|
6025
|
+
recordServicePid();
|
|
5986
6026
|
const fallbackCwd = process.env.FEISHU_CODEX_CWD || process.cwd();
|
|
5987
6027
|
console.log("\n\u6B63\u5728\u542F\u52A8\u957F\u8FDE\u63A5 bot\u2026");
|
|
5988
6028
|
console.log("\u79C1\u804A\u6211 `/new <\u540D>` \u5EFA\u9879\u76EE\uFF1B\u5728\u9879\u76EE\u7FA4\u91CC @\u6211 \u5E72\u6D3B\u3002Ctrl+C \u9000\u51FA\u3002\n");
|
|
@@ -6038,7 +6078,7 @@ async function runLogs(follow) {
|
|
|
6038
6078
|
function installedNote() {
|
|
6039
6079
|
switch (process.platform) {
|
|
6040
6080
|
case "win32":
|
|
6041
|
-
return "\u2713 \u540E\u53F0\u670D\u52A1\u5DF2\u5B89\u88C5\u5E76\u542F\u52A8\uFF08\u767B\u5F55\u81EA\u542F\uFF1B\u6CE8\u610F
|
|
6081
|
+
return "\u2713 \u540E\u53F0\u670D\u52A1\u5DF2\u5B89\u88C5\u5E76\u542F\u52A8\uFF08\u767B\u5F55\u81EA\u542F\uFF0C\u514D\u7BA1\u7406\u5458\uFF09\u3002\n \u63D0\u793A\uFF1A\u767B\u5F55\u81EA\u542F\u5728\u4E0B\u6B21\u767B\u5F55\u751F\u6548\uFF1B\u5F53\u524D\u5DF2\u5728\u540E\u53F0\u9690\u85CF\u542F\u52A8\u3002\u6CE8\u610F Windows \u767B\u5F55\u81EA\u542F\u65E0\u5D29\u6E83\u81EA\u52A8\u62C9\u8D77\u3002";
|
|
6042
6082
|
case "linux":
|
|
6043
6083
|
return "\u2713 \u540E\u53F0\u670D\u52A1\u5DF2\u5B89\u88C5\u5E76\u542F\u52A8\uFF08\u767B\u5F55\u81EA\u542F\u3001\u5D29\u6E83\u81EA\u52A8\u62C9\u8D77\uFF09\u3002\n \u63D0\u793A\uFF1A\u6CE8\u9500\u540E\u4ECD\u4FDD\u6301\u8FD0\u884C\u9700\u6267\u884C\u4E00\u6B21 `loginctl enable-linger $USER`\u3002";
|
|
6044
6084
|
default:
|
|
@@ -6110,7 +6150,7 @@ async function runUpdate(opts = {}) {
|
|
|
6110
6150
|
}
|
|
6111
6151
|
|
|
6112
6152
|
// src/cli/commands/bot.ts
|
|
6113
|
-
import { rm as
|
|
6153
|
+
import { rm as rm5 } from "fs/promises";
|
|
6114
6154
|
async function runBotInit(name) {
|
|
6115
6155
|
if (!ensureCodex()) {
|
|
6116
6156
|
process.exitCode = 1;
|
|
@@ -6165,7 +6205,7 @@ async function runBotRm(name) {
|
|
|
6165
6205
|
}
|
|
6166
6206
|
const after = await removeBot(bot2.appId);
|
|
6167
6207
|
await removeSecret(secretKeyForApp(bot2.appId));
|
|
6168
|
-
await
|
|
6208
|
+
await rm5(botDir(bot2.appId), { recursive: true, force: true });
|
|
6169
6209
|
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`);
|
|
6170
6210
|
if (after.bots.length === 0) {
|
|
6171
6211
|
console.log(" \u5DF2\u65E0\u4EFB\u4F55\u673A\u5668\u4EBA\uFF0C`bot init` \u91CD\u65B0\u521B\u5EFA\u3002");
|
package/package.json
CHANGED