weacpx 0.4.0 → 0.4.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/README.md +3 -0
- package/dist/cli.js +734 -273
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2648,7 +2648,7 @@ class DaemonController {
|
|
|
2648
2648
|
status
|
|
2649
2649
|
};
|
|
2650
2650
|
}
|
|
2651
|
-
async start() {
|
|
2651
|
+
async start(options = {}) {
|
|
2652
2652
|
const current = await this.getStatus();
|
|
2653
2653
|
if (current.state === "running") {
|
|
2654
2654
|
return { state: "already-running", pid: current.pid };
|
|
@@ -2657,7 +2657,7 @@ class DaemonController {
|
|
|
2657
2657
|
throw new Error(`weacpx daemon process is already running (pid ${current.pid}) but status metadata is missing`);
|
|
2658
2658
|
}
|
|
2659
2659
|
await this.statusStore.clear();
|
|
2660
|
-
const pid = await this.deps.spawnDetached();
|
|
2660
|
+
const pid = await this.deps.spawnDetached(options);
|
|
2661
2661
|
await this.writePid(pid);
|
|
2662
2662
|
await this.waitForStartupMetadata(pid);
|
|
2663
2663
|
return { state: "started", pid };
|
|
@@ -2782,12 +2782,12 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
2782
2782
|
function createDaemonController(paths, options) {
|
|
2783
2783
|
return new DaemonController(paths, {
|
|
2784
2784
|
isProcessRunning: options.isProcessRunning ?? defaultIsProcessRunning2,
|
|
2785
|
-
spawnDetached: async () => {
|
|
2785
|
+
spawnDetached: async (spawnOptions) => {
|
|
2786
2786
|
await mkdir4(paths.runtimeDir, { recursive: true });
|
|
2787
2787
|
const stdoutHandle = await open(paths.stdoutLog, "a");
|
|
2788
2788
|
const stderrHandle = await open(paths.stderrLog, "a");
|
|
2789
2789
|
try {
|
|
2790
|
-
return await (options.spawnProcess ?? defaultSpawnProcess)(buildSpawnRequest(paths, options, stdoutHandle.fd, stderrHandle.fd));
|
|
2790
|
+
return await (options.spawnProcess ?? defaultSpawnProcess)(buildSpawnRequest(paths, options, stdoutHandle.fd, stderrHandle.fd, spawnOptions));
|
|
2791
2791
|
} finally {
|
|
2792
2792
|
await stdoutHandle.close();
|
|
2793
2793
|
await stderrHandle.close();
|
|
@@ -2804,7 +2804,7 @@ function defaultIsProcessRunning2(pid) {
|
|
|
2804
2804
|
return false;
|
|
2805
2805
|
}
|
|
2806
2806
|
}
|
|
2807
|
-
function buildSpawnRequest(paths, options, stdoutFd, stderrFd) {
|
|
2807
|
+
function buildSpawnRequest(paths, options, stdoutFd, stderrFd, spawnOptions = {}) {
|
|
2808
2808
|
const platform = options.platform ?? process.platform;
|
|
2809
2809
|
if (platform === "win32") {
|
|
2810
2810
|
return {
|
|
@@ -2825,7 +2825,8 @@ function buildSpawnRequest(paths, options, stdoutFd, stderrFd) {
|
|
|
2825
2825
|
WEACPX_DAEMON_ARG1: "run",
|
|
2826
2826
|
WEACPX_DAEMON_CWD: options.cwd,
|
|
2827
2827
|
WEACPX_DAEMON_STDOUT: paths.stdoutLog,
|
|
2828
|
-
WEACPX_DAEMON_STDERR: paths.stderrLog
|
|
2828
|
+
WEACPX_DAEMON_STDERR: paths.stderrLog,
|
|
2829
|
+
...spawnOptions.firstRunOnboarding ? { WEACPX_FIRST_RUN_ONBOARDING: spawnOptions.firstRunOnboarding } : {}
|
|
2829
2830
|
},
|
|
2830
2831
|
stdio: ["ignore", "pipe", "ignore"],
|
|
2831
2832
|
windowsHide: true
|
|
@@ -2839,7 +2840,10 @@ function buildSpawnRequest(paths, options, stdoutFd, stderrFd) {
|
|
|
2839
2840
|
options: {
|
|
2840
2841
|
cwd: options.cwd,
|
|
2841
2842
|
detached: true,
|
|
2842
|
-
env:
|
|
2843
|
+
env: {
|
|
2844
|
+
...options.env,
|
|
2845
|
+
...spawnOptions.firstRunOnboarding ? { WEACPX_FIRST_RUN_ONBOARDING: spawnOptions.firstRunOnboarding } : {}
|
|
2846
|
+
},
|
|
2843
2847
|
stdio: ["ignore", stdoutFd, stderrFd]
|
|
2844
2848
|
}
|
|
2845
2849
|
};
|
|
@@ -9829,74 +9833,58 @@ var init_state_store = __esm(() => {
|
|
|
9829
9833
|
init_types();
|
|
9830
9834
|
});
|
|
9831
9835
|
|
|
9832
|
-
// src/
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9836
|
+
// src/config/agent-templates.ts
|
|
9837
|
+
function getAgentTemplate(name) {
|
|
9838
|
+
const template = TEMPLATES[name];
|
|
9839
|
+
if (!template) {
|
|
9840
|
+
return null;
|
|
9841
|
+
}
|
|
9842
|
+
return {
|
|
9843
|
+
...template
|
|
9844
|
+
};
|
|
9845
|
+
}
|
|
9846
|
+
function listAgentTemplates() {
|
|
9847
|
+
return Object.keys(TEMPLATES);
|
|
9848
|
+
}
|
|
9849
|
+
var TEMPLATES;
|
|
9850
|
+
var init_agent_templates = __esm(() => {
|
|
9851
|
+
TEMPLATES = {
|
|
9852
|
+
codex: {
|
|
9853
|
+
driver: "codex"
|
|
9846
9854
|
},
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
if (config2.id !== "weixin")
|
|
9850
|
-
issues.push({ kind: "invalid-config", message: "weixin channel id must be weixin" });
|
|
9851
|
-
if (config2.type !== "weixin")
|
|
9852
|
-
issues.push({ kind: "invalid-config", message: "weixin channel type must be weixin" });
|
|
9853
|
-
return issues;
|
|
9855
|
+
claude: {
|
|
9856
|
+
driver: "claude"
|
|
9854
9857
|
},
|
|
9855
|
-
|
|
9856
|
-
|
|
9858
|
+
opencode: {
|
|
9859
|
+
driver: "opencode"
|
|
9857
9860
|
},
|
|
9858
|
-
|
|
9859
|
-
|
|
9861
|
+
gemini: {
|
|
9862
|
+
driver: "gemini"
|
|
9860
9863
|
}
|
|
9861
9864
|
};
|
|
9862
9865
|
});
|
|
9863
9866
|
|
|
9864
|
-
// src/
|
|
9865
|
-
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
if (
|
|
9870
|
-
|
|
9871
|
-
if (
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
}
|
|
9876
|
-
function hasChannelCliProvider(type) {
|
|
9877
|
-
bootstrapBuiltinChannelCliProviders();
|
|
9878
|
-
return cliProviders.has(type);
|
|
9879
|
-
}
|
|
9880
|
-
function bootstrapBuiltinChannelCliProviders() {
|
|
9881
|
-
if (builtinProvidersRegistered)
|
|
9882
|
-
return;
|
|
9883
|
-
builtinProvidersRegistered = true;
|
|
9884
|
-
if (!cliProviders.has(weixinCliProvider.type))
|
|
9885
|
-
registerChannelCliProvider(weixinCliProvider);
|
|
9886
|
-
}
|
|
9887
|
-
function listChannelCliProviders() {
|
|
9888
|
-
bootstrapBuiltinChannelCliProviders();
|
|
9889
|
-
return Array.from(cliProviders.values());
|
|
9867
|
+
// src/plugins/plugin-home.ts
|
|
9868
|
+
import { mkdir as mkdir6, writeFile as writeFile5 } from "node:fs/promises";
|
|
9869
|
+
import { homedir as homedir3 } from "node:os";
|
|
9870
|
+
import { join as join3 } from "node:path";
|
|
9871
|
+
function resolvePluginHome(input = {}) {
|
|
9872
|
+
if (input.pluginHome?.trim())
|
|
9873
|
+
return input.pluginHome;
|
|
9874
|
+
if (process.env.WEACPX_PLUGIN_HOME?.trim())
|
|
9875
|
+
return process.env.WEACPX_PLUGIN_HOME;
|
|
9876
|
+
const home = input.home ?? process.env.HOME ?? homedir3();
|
|
9877
|
+
return join3(home, ".weacpx", "plugins");
|
|
9890
9878
|
}
|
|
9891
|
-
function
|
|
9892
|
-
|
|
9893
|
-
|
|
9879
|
+
async function ensurePluginHome(pluginHome) {
|
|
9880
|
+
await mkdir6(pluginHome, { recursive: true, mode: 448 });
|
|
9881
|
+
await writeFile5(join3(pluginHome, "package.json"), JSON.stringify({ private: true, type: "module" }, null, 2) + `
|
|
9882
|
+
`, { flag: "wx" }).catch((error2) => {
|
|
9883
|
+
if (error2.code !== "EEXIST")
|
|
9884
|
+
throw error2;
|
|
9885
|
+
});
|
|
9894
9886
|
}
|
|
9895
|
-
var
|
|
9896
|
-
var init_registry = __esm(() => {
|
|
9897
|
-
init_weixin_provider();
|
|
9898
|
-
cliProviders = new Map;
|
|
9899
|
-
});
|
|
9887
|
+
var init_plugin_home = () => {};
|
|
9900
9888
|
|
|
9901
9889
|
// src/weixin/storage/ensure-dir.ts
|
|
9902
9890
|
import fs2 from "node:fs";
|
|
@@ -11984,7 +11972,7 @@ var init_types2 = __esm(() => {
|
|
|
11984
11972
|
});
|
|
11985
11973
|
|
|
11986
11974
|
// src/channels/media-store.ts
|
|
11987
|
-
import { access as access2, mkdir as
|
|
11975
|
+
import { access as access2, mkdir as mkdir7, readdir, rm as rm4, stat, writeFile as writeFile6 } from "node:fs/promises";
|
|
11988
11976
|
import path6 from "node:path";
|
|
11989
11977
|
|
|
11990
11978
|
class RuntimeMediaStore {
|
|
@@ -12002,13 +11990,13 @@ class RuntimeMediaStore {
|
|
|
12002
11990
|
const safeMessageId = safePathSegment(input.messageId || "message");
|
|
12003
11991
|
const baseFileName = sanitizeMediaFileName(input.fileName ?? "attachment", input.mimeType);
|
|
12004
11992
|
const dir = path6.join(this.rootDir, input.channelId, safeChatKey, safeMessageId);
|
|
12005
|
-
await
|
|
11993
|
+
await mkdir7(dir, { recursive: true });
|
|
12006
11994
|
const resolvedRoot = path6.resolve(this.rootDir);
|
|
12007
11995
|
const resolvedFile = path6.resolve(path6.join(dir, await uniqueFileName(dir, baseFileName)));
|
|
12008
11996
|
if (!isPathInside(resolvedFile, resolvedRoot)) {
|
|
12009
11997
|
throw new Error("media path escapes runtime media root");
|
|
12010
11998
|
}
|
|
12011
|
-
await
|
|
11999
|
+
await writeFile6(resolvedFile, input.buffer);
|
|
12012
12000
|
return {
|
|
12013
12001
|
kind: input.kind,
|
|
12014
12002
|
filePath: resolvedFile,
|
|
@@ -14167,16 +14155,16 @@ var init_deliver_coordinator_message = __esm(() => {
|
|
|
14167
14155
|
});
|
|
14168
14156
|
|
|
14169
14157
|
// src/weixin/monitor/consumer-lock.ts
|
|
14170
|
-
import { mkdir as
|
|
14171
|
-
import { dirname as dirname6, join as
|
|
14172
|
-
import { homedir as
|
|
14158
|
+
import { mkdir as mkdir8, open as open2, readFile as readFile6, rm as rm5 } from "node:fs/promises";
|
|
14159
|
+
import { dirname as dirname6, join as join4 } from "node:path";
|
|
14160
|
+
import { homedir as homedir4 } from "node:os";
|
|
14173
14161
|
function createWeixinConsumerLock(options = {}) {
|
|
14174
|
-
const lockFilePath = options.lockFilePath ??
|
|
14162
|
+
const lockFilePath = options.lockFilePath ?? join4(homedir4(), ".weacpx", "runtime", "weixin-consumer.lock.json");
|
|
14175
14163
|
const isProcessRunning = options.isProcessRunning ?? defaultIsProcessRunning4;
|
|
14176
14164
|
const onDiagnostic = options.onDiagnostic;
|
|
14177
14165
|
return {
|
|
14178
14166
|
async acquire(meta2) {
|
|
14179
|
-
await
|
|
14167
|
+
await mkdir8(dirname6(lockFilePath), { recursive: true });
|
|
14180
14168
|
while (true) {
|
|
14181
14169
|
try {
|
|
14182
14170
|
const handle = await open2(lockFilePath, "wx");
|
|
@@ -14569,27 +14557,74 @@ var init_create_channel = __esm(() => {
|
|
|
14569
14557
|
channelFactories = new Map;
|
|
14570
14558
|
});
|
|
14571
14559
|
|
|
14572
|
-
// src/
|
|
14573
|
-
|
|
14574
|
-
|
|
14575
|
-
|
|
14576
|
-
|
|
14577
|
-
|
|
14578
|
-
|
|
14579
|
-
|
|
14580
|
-
|
|
14581
|
-
|
|
14582
|
-
|
|
14560
|
+
// src/channels/cli/weixin-provider.ts
|
|
14561
|
+
var weixinCliProvider;
|
|
14562
|
+
var init_weixin_provider = __esm(() => {
|
|
14563
|
+
weixinCliProvider = {
|
|
14564
|
+
type: "weixin",
|
|
14565
|
+
displayName: "Weixin",
|
|
14566
|
+
supportsLogin: true,
|
|
14567
|
+
parseAddArgs(args) {
|
|
14568
|
+
if (args.length > 0)
|
|
14569
|
+
return { ok: false, message: `unknown weixin options: ${args.join(" ")}` };
|
|
14570
|
+
return { ok: true, input: {} };
|
|
14571
|
+
},
|
|
14572
|
+
buildDefaultConfig(_input) {
|
|
14573
|
+
return { id: "weixin", type: "weixin", enabled: true };
|
|
14574
|
+
},
|
|
14575
|
+
validateConfig(config2) {
|
|
14576
|
+
const issues = [];
|
|
14577
|
+
if (config2.id !== "weixin")
|
|
14578
|
+
issues.push({ kind: "invalid-config", message: "weixin channel id must be weixin" });
|
|
14579
|
+
if (config2.type !== "weixin")
|
|
14580
|
+
issues.push({ kind: "invalid-config", message: "weixin channel type must be weixin" });
|
|
14581
|
+
return issues;
|
|
14582
|
+
},
|
|
14583
|
+
renderSummary(config2) {
|
|
14584
|
+
return [`type: ${config2.type}`, `enabled: ${config2.enabled}`];
|
|
14585
|
+
},
|
|
14586
|
+
async promptForMissingFields(input, _io) {
|
|
14587
|
+
return input;
|
|
14588
|
+
}
|
|
14589
|
+
};
|
|
14590
|
+
});
|
|
14591
|
+
|
|
14592
|
+
// src/channels/cli/registry.ts
|
|
14593
|
+
function registerChannelCliProvider(provider) {
|
|
14594
|
+
const type = provider.type.trim();
|
|
14595
|
+
if (!type)
|
|
14596
|
+
throw new Error("channel CLI provider type must be non-empty");
|
|
14597
|
+
if (type.includes(":"))
|
|
14598
|
+
throw new Error("channel CLI provider type must not contain ':'");
|
|
14599
|
+
if (cliProviders.has(type)) {
|
|
14600
|
+
throw new Error(`channel CLI provider is already registered: ${type}`);
|
|
14601
|
+
}
|
|
14602
|
+
cliProviders.set(type, provider);
|
|
14583
14603
|
}
|
|
14584
|
-
|
|
14585
|
-
|
|
14586
|
-
|
|
14587
|
-
`, { flag: "wx" }).catch((error2) => {
|
|
14588
|
-
if (error2.code !== "EEXIST")
|
|
14589
|
-
throw error2;
|
|
14590
|
-
});
|
|
14604
|
+
function hasChannelCliProvider(type) {
|
|
14605
|
+
bootstrapBuiltinChannelCliProviders();
|
|
14606
|
+
return cliProviders.has(type);
|
|
14591
14607
|
}
|
|
14592
|
-
|
|
14608
|
+
function bootstrapBuiltinChannelCliProviders() {
|
|
14609
|
+
if (builtinProvidersRegistered)
|
|
14610
|
+
return;
|
|
14611
|
+
builtinProvidersRegistered = true;
|
|
14612
|
+
if (!cliProviders.has(weixinCliProvider.type))
|
|
14613
|
+
registerChannelCliProvider(weixinCliProvider);
|
|
14614
|
+
}
|
|
14615
|
+
function listChannelCliProviders() {
|
|
14616
|
+
bootstrapBuiltinChannelCliProviders();
|
|
14617
|
+
return Array.from(cliProviders.values());
|
|
14618
|
+
}
|
|
14619
|
+
function getChannelCliProvider(type) {
|
|
14620
|
+
bootstrapBuiltinChannelCliProviders();
|
|
14621
|
+
return cliProviders.get(type) ?? null;
|
|
14622
|
+
}
|
|
14623
|
+
var cliProviders, builtinProvidersRegistered = false;
|
|
14624
|
+
var init_registry = __esm(() => {
|
|
14625
|
+
init_weixin_provider();
|
|
14626
|
+
cliProviders = new Map;
|
|
14627
|
+
});
|
|
14593
14628
|
|
|
14594
14629
|
// src/channels/plugin.ts
|
|
14595
14630
|
function registerChannelPlugin(plugin) {
|
|
@@ -14852,7 +14887,7 @@ var init_bootstrap = __esm(() => {
|
|
|
14852
14887
|
|
|
14853
14888
|
// src/logging/app-logger.ts
|
|
14854
14889
|
import { appendFile, mkdir as mkdir9, readdir as readdir2, rename, rm as rm6, stat as stat2 } from "node:fs/promises";
|
|
14855
|
-
import { basename, dirname as
|
|
14890
|
+
import { basename, dirname as dirname8, join as join9 } from "node:path";
|
|
14856
14891
|
function createNoopAppLogger() {
|
|
14857
14892
|
return {
|
|
14858
14893
|
debug: async () => {},
|
|
@@ -14892,7 +14927,7 @@ function createAppLogger(options) {
|
|
|
14892
14927
|
return;
|
|
14893
14928
|
}
|
|
14894
14929
|
const line = formatLogLine(now(), level, event, message, context);
|
|
14895
|
-
await mkdir9(
|
|
14930
|
+
await mkdir9(dirname8(options.filePath), { recursive: true });
|
|
14896
14931
|
await rotateIfNeeded(options.filePath, Buffer.byteLength(line), options.maxSizeBytes, options.maxFiles);
|
|
14897
14932
|
await appendFile(options.filePath, line, "utf8");
|
|
14898
14933
|
}
|
|
@@ -14930,7 +14965,7 @@ async function rotateIfNeeded(filePath, incomingSize, maxSizeBytes, maxFiles) {
|
|
|
14930
14965
|
await rename(filePath, `${filePath}.1`);
|
|
14931
14966
|
}
|
|
14932
14967
|
async function cleanupExpiredRotatedLogs(filePath, retentionDays, now) {
|
|
14933
|
-
const parentDir =
|
|
14968
|
+
const parentDir = dirname8(filePath);
|
|
14934
14969
|
const prefix = `${basename(filePath)}.`;
|
|
14935
14970
|
const cutoff = now().getTime() - retentionDays * 24 * 60 * 60 * 1000;
|
|
14936
14971
|
let files = [];
|
|
@@ -14946,7 +14981,7 @@ async function cleanupExpiredRotatedLogs(filePath, retentionDays, now) {
|
|
|
14946
14981
|
if (!file.startsWith(prefix) || !/^\d+$/.test(file.slice(prefix.length))) {
|
|
14947
14982
|
continue;
|
|
14948
14983
|
}
|
|
14949
|
-
const candidate =
|
|
14984
|
+
const candidate = join9(parentDir, file);
|
|
14950
14985
|
const details = await stat2(candidate);
|
|
14951
14986
|
if (details.mtime.getTime() < cutoff) {
|
|
14952
14987
|
await rm6(candidate, { force: true });
|
|
@@ -14981,7 +15016,7 @@ var init_app_logger = __esm(() => {
|
|
|
14981
15016
|
});
|
|
14982
15017
|
|
|
14983
15018
|
// src/transport/acpx-session-index.ts
|
|
14984
|
-
import { readFile as
|
|
15019
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
14985
15020
|
import { homedir as homedir5 } from "node:os";
|
|
14986
15021
|
import { resolve as resolve2 } from "node:path";
|
|
14987
15022
|
async function resolveSessionAgentCommandFromIndex(session) {
|
|
@@ -14990,7 +15025,7 @@ async function resolveSessionAgentCommandFromIndex(session) {
|
|
|
14990
15025
|
return;
|
|
14991
15026
|
}
|
|
14992
15027
|
try {
|
|
14993
|
-
const raw = await
|
|
15028
|
+
const raw = await readFile10(resolve2(home, ".acpx", "sessions", "index.json"), "utf8");
|
|
14994
15029
|
const parsed = JSON.parse(raw);
|
|
14995
15030
|
const targetCwd = resolve2(session.cwd);
|
|
14996
15031
|
const match = parsed.entries?.find((entry) => entry.name === session.transportSession && entry.cwd === targetCwd && typeof entry.agentCommand === "string" && entry.agentCommand.trim().length > 0);
|
|
@@ -17304,37 +17339,6 @@ function isPartialPromptOutputError(message) {
|
|
|
17304
17339
|
return message.includes("未收到最终回复");
|
|
17305
17340
|
}
|
|
17306
17341
|
|
|
17307
|
-
// src/config/agent-templates.ts
|
|
17308
|
-
function getAgentTemplate(name) {
|
|
17309
|
-
const template = TEMPLATES[name];
|
|
17310
|
-
if (!template) {
|
|
17311
|
-
return null;
|
|
17312
|
-
}
|
|
17313
|
-
return {
|
|
17314
|
-
...template
|
|
17315
|
-
};
|
|
17316
|
-
}
|
|
17317
|
-
function listAgentTemplates() {
|
|
17318
|
-
return Object.keys(TEMPLATES);
|
|
17319
|
-
}
|
|
17320
|
-
var TEMPLATES;
|
|
17321
|
-
var init_agent_templates = __esm(() => {
|
|
17322
|
-
TEMPLATES = {
|
|
17323
|
-
codex: {
|
|
17324
|
-
driver: "codex"
|
|
17325
|
-
},
|
|
17326
|
-
claude: {
|
|
17327
|
-
driver: "claude"
|
|
17328
|
-
},
|
|
17329
|
-
opencode: {
|
|
17330
|
-
driver: "opencode"
|
|
17331
|
-
},
|
|
17332
|
-
gemini: {
|
|
17333
|
-
driver: "gemini"
|
|
17334
|
-
}
|
|
17335
|
-
};
|
|
17336
|
-
});
|
|
17337
|
-
|
|
17338
17342
|
// src/commands/handlers/agent-handler.ts
|
|
17339
17343
|
function handleAgents(context) {
|
|
17340
17344
|
return { text: context.config ? renderAgents(context.config) : "No config loaded." };
|
|
@@ -17790,11 +17794,11 @@ var init_session_recovery_handler = __esm(() => {
|
|
|
17790
17794
|
});
|
|
17791
17795
|
|
|
17792
17796
|
// src/recovery/auto-install-optional-dep.ts
|
|
17793
|
-
import { spawn as
|
|
17797
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
17794
17798
|
import { createWriteStream } from "node:fs";
|
|
17795
17799
|
import { mkdir as mkdir10 } from "node:fs/promises";
|
|
17796
17800
|
import { homedir as homedir6 } from "node:os";
|
|
17797
|
-
import { join as
|
|
17801
|
+
import { join as join10 } from "node:path";
|
|
17798
17802
|
async function autoInstallOptionalDep(pkg, parentPackages, options = {}) {
|
|
17799
17803
|
const runCli = options.runCli ?? defaultRunCli;
|
|
17800
17804
|
const openLog = options.openLog ?? defaultLogSink;
|
|
@@ -17873,7 +17877,7 @@ function tail(text, lines) {
|
|
|
17873
17877
|
}
|
|
17874
17878
|
var PRECISE_TIMEOUT_MS = 90000, GLOBAL_TIMEOUT_MS = 90000, TAIL_LINES = 10, PRECISE_COMMANDS, defaultRunCli = async (cmd, args, options) => {
|
|
17875
17879
|
return await new Promise((resolve3) => {
|
|
17876
|
-
const child =
|
|
17880
|
+
const child = spawn5(cmd, args, {
|
|
17877
17881
|
cwd: options.cwd,
|
|
17878
17882
|
stdio: ["ignore", "pipe", "pipe"],
|
|
17879
17883
|
shell: process.platform === "win32"
|
|
@@ -17909,10 +17913,10 @@ ${err.message}`, reason: "spawn" });
|
|
|
17909
17913
|
});
|
|
17910
17914
|
});
|
|
17911
17915
|
}, defaultLogSink = async () => {
|
|
17912
|
-
const dir =
|
|
17916
|
+
const dir = join10(homedir6(), ".weacpx", "logs");
|
|
17913
17917
|
await mkdir10(dir, { recursive: true });
|
|
17914
17918
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "").replace(/-/g, "");
|
|
17915
|
-
const path13 =
|
|
17919
|
+
const path13 = join10(dir, `auto-install-${timestamp}.log`);
|
|
17916
17920
|
const stream = createWriteStream(path13, { flags: "a" });
|
|
17917
17921
|
return {
|
|
17918
17922
|
path: path13,
|
|
@@ -17934,11 +17938,11 @@ var init_auto_install_optional_dep = __esm(() => {
|
|
|
17934
17938
|
});
|
|
17935
17939
|
|
|
17936
17940
|
// src/recovery/discover-parent-package-paths.ts
|
|
17937
|
-
import { spawn as
|
|
17941
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
17938
17942
|
import { createRequire as createRequire3 } from "node:module";
|
|
17939
17943
|
import { access as access3 } from "node:fs/promises";
|
|
17940
17944
|
import { homedir as homedir7 } from "node:os";
|
|
17941
|
-
import { dirname as
|
|
17945
|
+
import { dirname as dirname9, join as join11 } from "node:path";
|
|
17942
17946
|
function deriveParentPackageName(platformPackage) {
|
|
17943
17947
|
return platformPackage.replace(/-(?:linux|darwin|win32|windows|freebsd|openbsd|sunos|aix)(?:-(?:x64|arm64|ia32|arm|ppc64|s390x))?(?:-(?:baseline|musl|gnu|gnueabihf|musleabihf|msvc))?$/, "");
|
|
17944
17948
|
}
|
|
@@ -17951,7 +17955,7 @@ async function discoverParentPackagePaths(platformPackage, seedPath, deps = {})
|
|
|
17951
17955
|
const queryRoot = deps.queryPackageManagerRoot ?? defaultQueryPackageManagerRoot;
|
|
17952
17956
|
const parentName = deriveParentPackageName(platformPackage);
|
|
17953
17957
|
const rawCandidates = [];
|
|
17954
|
-
const bunGlobalRoot = env.BUN_INSTALL ?
|
|
17958
|
+
const bunGlobalRoot = env.BUN_INSTALL ? join11(env.BUN_INSTALL, "install", "global", "node_modules") : join11(home, ".bun", "install", "global", "node_modules");
|
|
17955
17959
|
const [npmRoot, pnpmRoot, yarnRoot] = await Promise.all([
|
|
17956
17960
|
queryRoot("npm"),
|
|
17957
17961
|
queryRoot("pnpm"),
|
|
@@ -17974,20 +17978,20 @@ async function discoverParentPackagePaths(platformPackage, seedPath, deps = {})
|
|
|
17974
17978
|
if (resolved)
|
|
17975
17979
|
rawCandidates.push({ path: resolved, manager: classify(resolved) });
|
|
17976
17980
|
}
|
|
17977
|
-
rawCandidates.push({ path:
|
|
17981
|
+
rawCandidates.push({ path: join11(bunGlobalRoot, parentName), manager: "bun" });
|
|
17978
17982
|
if (npmRoot)
|
|
17979
|
-
rawCandidates.push({ path:
|
|
17983
|
+
rawCandidates.push({ path: join11(npmRoot, parentName), manager: "npm" });
|
|
17980
17984
|
if (pnpmRoot)
|
|
17981
|
-
rawCandidates.push({ path:
|
|
17985
|
+
rawCandidates.push({ path: join11(pnpmRoot, parentName), manager: "pnpm" });
|
|
17982
17986
|
if (yarnRoot)
|
|
17983
|
-
rawCandidates.push({ path:
|
|
17987
|
+
rawCandidates.push({ path: join11(yarnRoot, parentName), manager: "yarn" });
|
|
17984
17988
|
const seen = new Set;
|
|
17985
17989
|
const verified = [];
|
|
17986
17990
|
for (const candidate of rawCandidates) {
|
|
17987
17991
|
if (seen.has(candidate.path))
|
|
17988
17992
|
continue;
|
|
17989
17993
|
seen.add(candidate.path);
|
|
17990
|
-
if (await fsExists(
|
|
17994
|
+
if (await fsExists(join11(candidate.path, "package.json"))) {
|
|
17991
17995
|
verified.push(candidate);
|
|
17992
17996
|
}
|
|
17993
17997
|
}
|
|
@@ -18011,7 +18015,7 @@ function defaultResolveFromCwd(name, cwd) {
|
|
|
18011
18015
|
const pkgJson = require2.resolve(`${name}/package.json`, {
|
|
18012
18016
|
paths: [cwd, ...require2.resolve.paths(name) ?? []]
|
|
18013
18017
|
});
|
|
18014
|
-
return
|
|
18018
|
+
return dirname9(pkgJson);
|
|
18015
18019
|
} catch {
|
|
18016
18020
|
return null;
|
|
18017
18021
|
}
|
|
@@ -18028,7 +18032,7 @@ async function defaultQueryPackageManagerRoot(tool) {
|
|
|
18028
18032
|
};
|
|
18029
18033
|
let child;
|
|
18030
18034
|
try {
|
|
18031
|
-
child =
|
|
18035
|
+
child = spawn6(spec.cmd, spec.args, {
|
|
18032
18036
|
stdio: ["ignore", "pipe", "pipe"],
|
|
18033
18037
|
shell: process.platform === "win32"
|
|
18034
18038
|
});
|
|
@@ -18058,7 +18062,7 @@ async function defaultQueryPackageManagerRoot(tool) {
|
|
|
18058
18062
|
const trimmed = stdout2.trim().split(/\r?\n/).pop()?.trim() ?? "";
|
|
18059
18063
|
if (!trimmed)
|
|
18060
18064
|
return done(null);
|
|
18061
|
-
done(spec.postfix ?
|
|
18065
|
+
done(spec.postfix ? join11(trimmed, spec.postfix) : trimmed);
|
|
18062
18066
|
});
|
|
18063
18067
|
});
|
|
18064
18068
|
}
|
|
@@ -22624,6 +22628,7 @@ async function runConsole(paths, deps) {
|
|
|
22624
22628
|
let heartbeatTimer = null;
|
|
22625
22629
|
let gcResetTimer = null;
|
|
22626
22630
|
let consumerLockAcquired = false;
|
|
22631
|
+
let daemonRuntimeStarted = false;
|
|
22627
22632
|
const shutdownController = new AbortController;
|
|
22628
22633
|
const signalHandler = () => {
|
|
22629
22634
|
shutdownController.abort();
|
|
@@ -22632,6 +22637,9 @@ async function runConsole(paths, deps) {
|
|
|
22632
22637
|
addProcessListener("SIGTERM", signalHandler);
|
|
22633
22638
|
try {
|
|
22634
22639
|
runtime = await deps.buildApp(paths);
|
|
22640
|
+
if (deps.afterBuild) {
|
|
22641
|
+
await deps.afterBuild(runtime);
|
|
22642
|
+
}
|
|
22635
22643
|
try {
|
|
22636
22644
|
await runtime.orchestration.service.purgeExpiredResetCoordinators({
|
|
22637
22645
|
cutoffDays: 7,
|
|
@@ -22639,20 +22647,6 @@ async function runConsole(paths, deps) {
|
|
|
22639
22647
|
});
|
|
22640
22648
|
} catch {}
|
|
22641
22649
|
consumerLock = deps.consumerLock ?? deps.consumerLockFactory?.(runtime);
|
|
22642
|
-
if (deps.daemonRuntime) {
|
|
22643
|
-
await deps.daemonRuntime.start({
|
|
22644
|
-
configPath: paths.configPath,
|
|
22645
|
-
statePath: paths.statePath
|
|
22646
|
-
});
|
|
22647
|
-
await runtime.orchestration.server.start();
|
|
22648
|
-
heartbeatTimer = setIntervalFn(() => {
|
|
22649
|
-
deps.daemonRuntime?.heartbeat().catch(() => {});
|
|
22650
|
-
}, deps.heartbeatIntervalMs ?? 30000);
|
|
22651
|
-
const runtimeForGc = runtime;
|
|
22652
|
-
gcResetTimer = setIntervalFn(() => {
|
|
22653
|
-
runtimeForGc.orchestration.service.purgeExpiredResetCoordinators({ cutoffDays: 7, trigger: "interval" }).catch(() => {});
|
|
22654
|
-
}, 86400000);
|
|
22655
|
-
}
|
|
22656
22650
|
if (consumerLock) {
|
|
22657
22651
|
const lockMeta = {
|
|
22658
22652
|
pid: processPid,
|
|
@@ -22700,6 +22694,24 @@ async function runConsole(paths, deps) {
|
|
|
22700
22694
|
throw error2;
|
|
22701
22695
|
}
|
|
22702
22696
|
}
|
|
22697
|
+
if (deps.beforeReady) {
|
|
22698
|
+
await deps.beforeReady(runtime);
|
|
22699
|
+
}
|
|
22700
|
+
if (deps.daemonRuntime) {
|
|
22701
|
+
await deps.daemonRuntime.start({
|
|
22702
|
+
configPath: paths.configPath,
|
|
22703
|
+
statePath: paths.statePath
|
|
22704
|
+
});
|
|
22705
|
+
daemonRuntimeStarted = true;
|
|
22706
|
+
await runtime.orchestration.server.start();
|
|
22707
|
+
heartbeatTimer = setIntervalFn(() => {
|
|
22708
|
+
deps.daemonRuntime?.heartbeat().catch(() => {});
|
|
22709
|
+
}, deps.heartbeatIntervalMs ?? 30000);
|
|
22710
|
+
const runtimeForGc = runtime;
|
|
22711
|
+
gcResetTimer = setIntervalFn(() => {
|
|
22712
|
+
runtimeForGc.orchestration.service.purgeExpiredResetCoordinators({ cutoffDays: 7, trigger: "interval" }).catch(() => {});
|
|
22713
|
+
}, 86400000);
|
|
22714
|
+
}
|
|
22703
22715
|
await deps.channels.startAll({
|
|
22704
22716
|
agent: runtime.agent,
|
|
22705
22717
|
abortSignal: shutdownController.signal,
|
|
@@ -22718,7 +22730,8 @@ async function runConsole(paths, deps) {
|
|
|
22718
22730
|
consumerLock,
|
|
22719
22731
|
consumerLockAcquired,
|
|
22720
22732
|
processPid,
|
|
22721
|
-
channels: deps.channels
|
|
22733
|
+
channels: deps.channels,
|
|
22734
|
+
daemonRuntimeStarted
|
|
22722
22735
|
});
|
|
22723
22736
|
}
|
|
22724
22737
|
}
|
|
@@ -22753,7 +22766,7 @@ async function runCleanupSequence(input) {
|
|
|
22753
22766
|
cleanupError ??= error2;
|
|
22754
22767
|
}
|
|
22755
22768
|
}
|
|
22756
|
-
if (input.daemonRuntime) {
|
|
22769
|
+
if (input.daemonRuntime && input.daemonRuntimeStarted) {
|
|
22757
22770
|
try {
|
|
22758
22771
|
await input.daemonRuntime.stop();
|
|
22759
22772
|
} catch (error2) {
|
|
@@ -22803,8 +22816,8 @@ function encodeBridgeSessionNoteEvent(event) {
|
|
|
22803
22816
|
}
|
|
22804
22817
|
|
|
22805
22818
|
// src/transport/acpx-bridge/acpx-bridge-client.ts
|
|
22806
|
-
import { spawn as
|
|
22807
|
-
import { fileURLToPath as
|
|
22819
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
22820
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
22808
22821
|
import { createInterface } from "node:readline";
|
|
22809
22822
|
|
|
22810
22823
|
class AcpxBridgeClient {
|
|
@@ -22924,12 +22937,12 @@ function buildBridgeSpawnSpec(options) {
|
|
|
22924
22937
|
};
|
|
22925
22938
|
}
|
|
22926
22939
|
async function spawnAcpxBridgeClient(options = {}) {
|
|
22927
|
-
const bridgeEntryPath = options.bridgeEntryPath ??
|
|
22940
|
+
const bridgeEntryPath = options.bridgeEntryPath ?? fileURLToPath3(new URL("../../bridge/bridge-main.ts", import.meta.url));
|
|
22928
22941
|
const spawnSpec = buildBridgeSpawnSpec({
|
|
22929
22942
|
execPath: process.execPath,
|
|
22930
22943
|
bridgeEntryPath
|
|
22931
22944
|
});
|
|
22932
|
-
const child =
|
|
22945
|
+
const child = spawn7(spawnSpec.command, spawnSpec.args, {
|
|
22933
22946
|
cwd: options.cwd ?? process.cwd(),
|
|
22934
22947
|
env: {
|
|
22935
22948
|
...process.env,
|
|
@@ -23743,12 +23756,12 @@ var init_streaming_prompt = __esm(() => {
|
|
|
23743
23756
|
|
|
23744
23757
|
// src/transport/acpx-cli/node-pty-helper.ts
|
|
23745
23758
|
import { chmod as chmodFs } from "node:fs/promises";
|
|
23746
|
-
import { dirname as
|
|
23759
|
+
import { dirname as dirname10, join as join12 } from "node:path";
|
|
23747
23760
|
function resolveNodePtyHelperPath(packageJsonPath, platform, arch) {
|
|
23748
23761
|
if (platform === "win32") {
|
|
23749
23762
|
return null;
|
|
23750
23763
|
}
|
|
23751
|
-
return
|
|
23764
|
+
return join12(dirname10(packageJsonPath), "prebuilds", `${platform}-${arch}`, "spawn-helper");
|
|
23752
23765
|
}
|
|
23753
23766
|
async function ensureNodePtyHelperExecutable(helperPath, chmod2 = chmodFs) {
|
|
23754
23767
|
if (!helperPath) {
|
|
@@ -23767,10 +23780,10 @@ var init_node_pty_helper = () => {};
|
|
|
23767
23780
|
|
|
23768
23781
|
// src/transport/acpx-queue-owner-launcher.ts
|
|
23769
23782
|
import { createHash as createHash3 } from "node:crypto";
|
|
23770
|
-
import { spawn as
|
|
23771
|
-
import { readFile as
|
|
23783
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
23784
|
+
import { readFile as readFile11, unlink } from "node:fs/promises";
|
|
23772
23785
|
import { homedir as homedir8 } from "node:os";
|
|
23773
|
-
import { join as
|
|
23786
|
+
import { join as join13 } from "node:path";
|
|
23774
23787
|
function buildWeacpxMcpServerSpec(input) {
|
|
23775
23788
|
const { command, args } = splitCommandLine(input.weacpxCommand);
|
|
23776
23789
|
return {
|
|
@@ -23900,7 +23913,7 @@ function stringEnv(env) {
|
|
|
23900
23913
|
}
|
|
23901
23914
|
async function defaultQueueOwnerSpawner(command, args, options) {
|
|
23902
23915
|
await new Promise((resolve3, reject) => {
|
|
23903
|
-
const child =
|
|
23916
|
+
const child = spawn8(command, args, {
|
|
23904
23917
|
detached: true,
|
|
23905
23918
|
stdio: "ignore",
|
|
23906
23919
|
env: options.env,
|
|
@@ -23922,7 +23935,7 @@ async function terminateAcpxQueueOwner(sessionId) {
|
|
|
23922
23935
|
const lockPath = queueLockFilePath(sessionId);
|
|
23923
23936
|
let owner;
|
|
23924
23937
|
try {
|
|
23925
|
-
owner = JSON.parse(await
|
|
23938
|
+
owner = JSON.parse(await readFile11(lockPath, "utf8"));
|
|
23926
23939
|
} catch {
|
|
23927
23940
|
return;
|
|
23928
23941
|
}
|
|
@@ -23932,7 +23945,7 @@ async function terminateAcpxQueueOwner(sessionId) {
|
|
|
23932
23945
|
await unlink(lockPath).catch(() => {});
|
|
23933
23946
|
}
|
|
23934
23947
|
function queueLockFilePath(sessionId) {
|
|
23935
|
-
return
|
|
23948
|
+
return join13(homedir8(), ".acpx", "queues", `${shortHash(sessionId, 24)}.lock`);
|
|
23936
23949
|
}
|
|
23937
23950
|
function shortHash(value, length) {
|
|
23938
23951
|
return createHash3("sha256").update(value).digest("hex").slice(0, length);
|
|
@@ -23971,12 +23984,12 @@ function permissionModeToFlag(permissionMode) {
|
|
|
23971
23984
|
|
|
23972
23985
|
// src/transport/acpx-cli/acpx-cli-transport.ts
|
|
23973
23986
|
import { createRequire as createRequire5 } from "node:module";
|
|
23974
|
-
import { spawn as
|
|
23987
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
23975
23988
|
import { spawn as spawnPty } from "node-pty";
|
|
23976
23989
|
async function defaultRunner(command, args, options) {
|
|
23977
23990
|
return await new Promise((resolve3, reject) => {
|
|
23978
23991
|
const spawnSpec = resolveSpawnCommand(command, args);
|
|
23979
|
-
const child =
|
|
23992
|
+
const child = spawn9(spawnSpec.command, spawnSpec.args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
23980
23993
|
let stdout2 = "";
|
|
23981
23994
|
let stderr = "";
|
|
23982
23995
|
const onAbort = () => {
|
|
@@ -24223,7 +24236,7 @@ ${baseText}` : "" };
|
|
|
24223
24236
|
}
|
|
24224
24237
|
async runStreamingPrompt(command, args, reply, formatToolCalls = false, toolEventMode = "text", replyContext, onSegment, onToolEvent) {
|
|
24225
24238
|
const hooks = this.streamingHooks;
|
|
24226
|
-
const doSpawn = hooks.spawnPrompt ?? ((cmd, spawnArgs) =>
|
|
24239
|
+
const doSpawn = hooks.spawnPrompt ?? ((cmd, spawnArgs) => spawn9(cmd, spawnArgs, { stdio: ["ignore", "pipe", "pipe"] }));
|
|
24227
24240
|
const setIntervalFn = hooks.setIntervalFn ?? ((fn, delay) => setInterval(fn, delay));
|
|
24228
24241
|
const clearIntervalFn = hooks.clearIntervalFn ?? ((timer) => clearInterval(timer));
|
|
24229
24242
|
const maxSegmentWaitMs = hooks.maxSegmentWaitMs ?? 30000;
|
|
@@ -24583,8 +24596,8 @@ __export(exports_main, {
|
|
|
24583
24596
|
});
|
|
24584
24597
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
24585
24598
|
import { homedir as homedir9 } from "node:os";
|
|
24586
|
-
import { dirname as
|
|
24587
|
-
import { fileURLToPath as
|
|
24599
|
+
import { dirname as dirname11, join as join14 } from "node:path";
|
|
24600
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
24588
24601
|
function startProgressHeartbeat(orchestration, config2, logger2, channel) {
|
|
24589
24602
|
const thresholdSeconds = config2.orchestration.progressHeartbeatSeconds;
|
|
24590
24603
|
if (thresholdSeconds <= 0) {
|
|
@@ -24989,6 +25002,7 @@ async function buildApp(paths, deps = {}) {
|
|
|
24989
25002
|
configStore,
|
|
24990
25003
|
logger: logger2,
|
|
24991
25004
|
quota,
|
|
25005
|
+
transport,
|
|
24992
25006
|
orchestration: {
|
|
24993
25007
|
service: orchestration,
|
|
24994
25008
|
server: orchestrationServer,
|
|
@@ -25038,8 +25052,8 @@ async function main() {
|
|
|
25038
25052
|
}
|
|
25039
25053
|
}
|
|
25040
25054
|
async function prepareChannelMedia(configPath, config2) {
|
|
25041
|
-
const runtimeDir =
|
|
25042
|
-
const mediaRootDir =
|
|
25055
|
+
const runtimeDir = join14(dirname11(configPath), "runtime");
|
|
25056
|
+
const mediaRootDir = join14(runtimeDir, "media");
|
|
25043
25057
|
const mediaStore = new RuntimeMediaStore({ rootDir: mediaRootDir });
|
|
25044
25058
|
await mediaStore.cleanupExpired().catch((error2) => {
|
|
25045
25059
|
console.error("[weacpx] media cleanup failed:", error2 instanceof Error ? error2.message : String(error2));
|
|
@@ -25053,7 +25067,7 @@ function resolveRuntimePaths() {
|
|
|
25053
25067
|
throw new Error("Unable to resolve the current user home directory");
|
|
25054
25068
|
}
|
|
25055
25069
|
const configPath = process.env.WEACPX_CONFIG ?? `${home}/.weacpx/config.json`;
|
|
25056
|
-
const runtimeDir =
|
|
25070
|
+
const runtimeDir = join14(dirname11(configPath), "runtime");
|
|
25057
25071
|
return {
|
|
25058
25072
|
configPath,
|
|
25059
25073
|
statePath: process.env.WEACPX_STATE ?? `${home}/.weacpx/state.json`,
|
|
@@ -25062,14 +25076,14 @@ function resolveRuntimePaths() {
|
|
|
25062
25076
|
}
|
|
25063
25077
|
function resolveBridgeEntryPath() {
|
|
25064
25078
|
if (import.meta.url.includes("/dist/")) {
|
|
25065
|
-
return
|
|
25079
|
+
return fileURLToPath4(new URL("./bridge/bridge-main.js", import.meta.url));
|
|
25066
25080
|
}
|
|
25067
|
-
return
|
|
25081
|
+
return fileURLToPath4(new URL("./bridge/bridge-main.ts", import.meta.url));
|
|
25068
25082
|
}
|
|
25069
25083
|
function resolveAppLogPath(configPath) {
|
|
25070
|
-
const rootDir =
|
|
25071
|
-
const runtimeDir =
|
|
25072
|
-
return
|
|
25084
|
+
const rootDir = dirname11(configPath);
|
|
25085
|
+
const runtimeDir = join14(rootDir, "runtime");
|
|
25086
|
+
return join14(runtimeDir, "app.log");
|
|
25073
25087
|
}
|
|
25074
25088
|
function resolveOrchestrationSocketPathFromConfigPath(configPath) {
|
|
25075
25089
|
const runtimeDir = resolveRuntimeDirFromConfigPath(configPath);
|
|
@@ -25106,7 +25120,7 @@ var init_main = __esm(async () => {
|
|
|
25106
25120
|
});
|
|
25107
25121
|
|
|
25108
25122
|
// src/doctor/checks/acpx-check.ts
|
|
25109
|
-
import { spawn as
|
|
25123
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
25110
25124
|
async function checkAcpx(options = {}) {
|
|
25111
25125
|
const runtimePaths = (options.resolveRuntimePaths ?? resolveRuntimePaths)();
|
|
25112
25126
|
try {
|
|
@@ -25153,7 +25167,7 @@ function buildDetails(metadata, version2, verbose) {
|
|
|
25153
25167
|
async function defaultRunVersion(command) {
|
|
25154
25168
|
const spawnSpec = resolveSpawnCommand(command, ["--version"]);
|
|
25155
25169
|
return await new Promise((resolve3, reject) => {
|
|
25156
|
-
const child =
|
|
25170
|
+
const child = spawn10(spawnSpec.command, spawnSpec.args, {
|
|
25157
25171
|
stdio: ["ignore", "pipe", "pipe"]
|
|
25158
25172
|
});
|
|
25159
25173
|
let stdout2 = "";
|
|
@@ -25291,7 +25305,7 @@ var init_config_check = __esm(async () => {
|
|
|
25291
25305
|
});
|
|
25292
25306
|
|
|
25293
25307
|
// src/doctor/checks/daemon-check.ts
|
|
25294
|
-
import { fileURLToPath as
|
|
25308
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
25295
25309
|
import { homedir as homedir10 } from "node:os";
|
|
25296
25310
|
async function checkDaemon(options = {}) {
|
|
25297
25311
|
const home = options.home ?? process.env.HOME ?? homedir10();
|
|
@@ -25381,7 +25395,7 @@ function defaultIsProcessRunning5(pid) {
|
|
|
25381
25395
|
}
|
|
25382
25396
|
}
|
|
25383
25397
|
function resolveCliEntryPath() {
|
|
25384
|
-
return process.argv[1] ??
|
|
25398
|
+
return process.argv[1] ?? fileURLToPath5(import.meta.url);
|
|
25385
25399
|
}
|
|
25386
25400
|
function formatError5(error2) {
|
|
25387
25401
|
return error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -25443,7 +25457,7 @@ async function checkOrchestrationHealth(options) {
|
|
|
25443
25457
|
// src/doctor/checks/runtime-check.ts
|
|
25444
25458
|
import { constants } from "node:fs";
|
|
25445
25459
|
import { access as access4, stat as stat3 } from "node:fs/promises";
|
|
25446
|
-
import { dirname as
|
|
25460
|
+
import { dirname as dirname12 } from "node:path";
|
|
25447
25461
|
import { homedir as homedir11 } from "node:os";
|
|
25448
25462
|
async function checkRuntime(options = {}) {
|
|
25449
25463
|
const home = options.home ?? process.env.HOME ?? homedir11();
|
|
@@ -25540,7 +25554,7 @@ async function checkFileCreatable(label, path14, probe, platform) {
|
|
|
25540
25554
|
detail: `${label}: ${path14} (unusable: ${formatError6(error2)})`
|
|
25541
25555
|
};
|
|
25542
25556
|
}
|
|
25543
|
-
const parentCheck = await checkCreatableAncestorDirectory(
|
|
25557
|
+
const parentCheck = await checkCreatableAncestorDirectory(dirname12(path14), probe, platform);
|
|
25544
25558
|
if (!parentCheck.ok) {
|
|
25545
25559
|
return {
|
|
25546
25560
|
ok: false,
|
|
@@ -25576,7 +25590,7 @@ async function checkCreatableAncestorDirectory(path14, probe, platform) {
|
|
|
25576
25590
|
blockingPath: path14
|
|
25577
25591
|
};
|
|
25578
25592
|
}
|
|
25579
|
-
const parent =
|
|
25593
|
+
const parent = dirname12(path14);
|
|
25580
25594
|
if (parent === path14) {
|
|
25581
25595
|
return {
|
|
25582
25596
|
ok: false,
|
|
@@ -25999,7 +26013,7 @@ var init_render_doctor = __esm(() => {
|
|
|
25999
26013
|
|
|
26000
26014
|
// src/doctor/doctor.ts
|
|
26001
26015
|
import { homedir as homedir12 } from "node:os";
|
|
26002
|
-
import { join as
|
|
26016
|
+
import { join as join15 } from "node:path";
|
|
26003
26017
|
async function runDoctor(options = {}, deps = {}) {
|
|
26004
26018
|
const home = deps.home ?? process.env.HOME ?? homedir12();
|
|
26005
26019
|
const runtimePaths = resolveDoctorRuntimePaths(home, deps.resolveRuntimePaths);
|
|
@@ -26052,8 +26066,8 @@ function resolveDoctorRuntimePaths(home, resolver) {
|
|
|
26052
26066
|
return resolveRuntimePaths();
|
|
26053
26067
|
}
|
|
26054
26068
|
return {
|
|
26055
|
-
configPath:
|
|
26056
|
-
statePath:
|
|
26069
|
+
configPath: join15(home, ".weacpx", "config.json"),
|
|
26070
|
+
statePath: join15(home, ".weacpx", "state.json")
|
|
26057
26071
|
};
|
|
26058
26072
|
}
|
|
26059
26073
|
function depsUseExplicitRuntimeOverrides() {
|
|
@@ -26159,7 +26173,7 @@ init_daemon_files();
|
|
|
26159
26173
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
26160
26174
|
import { homedir as homedir13 } from "node:os";
|
|
26161
26175
|
import { sep } from "node:path";
|
|
26162
|
-
import { fileURLToPath as
|
|
26176
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
26163
26177
|
|
|
26164
26178
|
// src/daemon/daemon-runtime.ts
|
|
26165
26179
|
init_daemon_status();
|
|
@@ -39577,6 +39591,372 @@ function parseSourceHandle(args, env = process.env) {
|
|
|
39577
39591
|
// src/cli.ts
|
|
39578
39592
|
init_workspace_path();
|
|
39579
39593
|
init_state_store();
|
|
39594
|
+
|
|
39595
|
+
// src/onboarding.ts
|
|
39596
|
+
init_workspace_path();
|
|
39597
|
+
init_agent_templates();
|
|
39598
|
+
function isFirstUse(config2, state) {
|
|
39599
|
+
return Object.keys(state.sessions ?? {}).length === 0 && Object.keys(config2.workspaces ?? {}).length === 0 && (config2.plugins ?? []).length === 0;
|
|
39600
|
+
}
|
|
39601
|
+
async function maybeRunFirstUseOnboarding(input) {
|
|
39602
|
+
if (!isFirstUse(input.config, input.state))
|
|
39603
|
+
return { created: false };
|
|
39604
|
+
if (!input.deps.isInteractive())
|
|
39605
|
+
return { created: false };
|
|
39606
|
+
const cwd = normalizeWorkspacePath(input.deps.cwd());
|
|
39607
|
+
const workspaceName = allocateName(sanitizeName(basenameForWorkspacePath(cwd), "workspace"), input.config.workspaces);
|
|
39608
|
+
const yes = (await input.deps.promptText(`检测到首次使用 weacpx。是否将当前目录创建为工作区「${workspaceName}」?[Y/n] `)).trim().toLowerCase();
|
|
39609
|
+
if (yes === "n" || yes === "no")
|
|
39610
|
+
return { created: false };
|
|
39611
|
+
const templateNames = listAgentTemplates();
|
|
39612
|
+
input.deps.print("请选择要添加并创建初始会话的 Agent:");
|
|
39613
|
+
for (let index = 0;index < templateNames.length; index += 1) {
|
|
39614
|
+
input.deps.print(`${index + 1}. ${templateNames[index]}`);
|
|
39615
|
+
}
|
|
39616
|
+
const answer = (await input.deps.promptText("输入数字或名称(默认 1):")).trim();
|
|
39617
|
+
const agentName = resolveTemplateChoice(answer, templateNames);
|
|
39618
|
+
if (!agentName) {
|
|
39619
|
+
input.deps.print("未选择有效 Agent,已跳过首次初始化。");
|
|
39620
|
+
return { created: false };
|
|
39621
|
+
}
|
|
39622
|
+
const template = getAgentTemplate(agentName);
|
|
39623
|
+
if (!template)
|
|
39624
|
+
return { created: false };
|
|
39625
|
+
const workspaceExisted = Boolean(input.config.workspaces[workspaceName]);
|
|
39626
|
+
const agentExisted = Boolean(input.config.agents[agentName]);
|
|
39627
|
+
input.config.workspaces[workspaceName] = { cwd };
|
|
39628
|
+
input.config.agents[agentName] = template;
|
|
39629
|
+
await input.saveConfig(input.config);
|
|
39630
|
+
const alias = `${workspaceName}:${agentName}`;
|
|
39631
|
+
input.deps.print(`已创建工作区「${workspaceName}」,正在创建初始会话「${alias}」...`);
|
|
39632
|
+
return {
|
|
39633
|
+
created: true,
|
|
39634
|
+
workspace: workspaceName,
|
|
39635
|
+
agent: agentName,
|
|
39636
|
+
alias,
|
|
39637
|
+
rollback: { workspaceExisted, agentExisted }
|
|
39638
|
+
};
|
|
39639
|
+
}
|
|
39640
|
+
function resolveTemplateChoice(answer, names) {
|
|
39641
|
+
if (!answer)
|
|
39642
|
+
return names[0] ?? null;
|
|
39643
|
+
const index = Number.parseInt(answer, 10);
|
|
39644
|
+
if (Number.isFinite(index) && index >= 1 && index <= names.length)
|
|
39645
|
+
return names[index - 1];
|
|
39646
|
+
return names.includes(answer) ? answer : null;
|
|
39647
|
+
}
|
|
39648
|
+
function allocateName(base, existing) {
|
|
39649
|
+
if (!existing[base])
|
|
39650
|
+
return base;
|
|
39651
|
+
let suffix = 2;
|
|
39652
|
+
while (existing[`${base}-${suffix}`])
|
|
39653
|
+
suffix += 1;
|
|
39654
|
+
return `${base}-${suffix}`;
|
|
39655
|
+
}
|
|
39656
|
+
function sanitizeName(input, fallback) {
|
|
39657
|
+
const sanitized = input.trim().replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
39658
|
+
return sanitized || fallback;
|
|
39659
|
+
}
|
|
39660
|
+
|
|
39661
|
+
// src/cli-update.ts
|
|
39662
|
+
init_plugin_home();
|
|
39663
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
39664
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
39665
|
+
import { dirname as dirname7, join as join6 } from "node:path";
|
|
39666
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
39667
|
+
|
|
39668
|
+
// src/plugins/package-manager.ts
|
|
39669
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
39670
|
+
async function defaultRunCommand(command, args, options) {
|
|
39671
|
+
await new Promise((resolve, reject) => {
|
|
39672
|
+
const child = spawn3(command, args, { cwd: options.cwd, stdio: "inherit" });
|
|
39673
|
+
child.on("error", reject);
|
|
39674
|
+
child.on("exit", (code) => {
|
|
39675
|
+
if (code === 0)
|
|
39676
|
+
resolve();
|
|
39677
|
+
else
|
|
39678
|
+
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
39679
|
+
});
|
|
39680
|
+
});
|
|
39681
|
+
}
|
|
39682
|
+
async function silentRun(command, args, options) {
|
|
39683
|
+
await new Promise((resolve, reject) => {
|
|
39684
|
+
const child = spawn3(command, args, { cwd: options.cwd, stdio: "ignore" });
|
|
39685
|
+
child.on("error", reject);
|
|
39686
|
+
child.on("exit", (code) => {
|
|
39687
|
+
if (code === 0)
|
|
39688
|
+
resolve();
|
|
39689
|
+
else
|
|
39690
|
+
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
39691
|
+
});
|
|
39692
|
+
});
|
|
39693
|
+
}
|
|
39694
|
+
async function detectPackageManager(runCommand) {
|
|
39695
|
+
const override = process.env.WEACPX_PACKAGE_MANAGER?.trim().toLowerCase();
|
|
39696
|
+
if (override === "bun" || override === "npm")
|
|
39697
|
+
return override;
|
|
39698
|
+
const probe = runCommand ?? silentRun;
|
|
39699
|
+
try {
|
|
39700
|
+
await probe("bun", ["--version"], { cwd: process.cwd() });
|
|
39701
|
+
return "bun";
|
|
39702
|
+
} catch {
|
|
39703
|
+
return "npm";
|
|
39704
|
+
}
|
|
39705
|
+
}
|
|
39706
|
+
async function installPluginPackage(input) {
|
|
39707
|
+
const runCommand = input.runCommand ?? defaultRunCommand;
|
|
39708
|
+
const packageManager = input.packageManager ?? await detectPackageManager();
|
|
39709
|
+
const spec = input.version ? `${input.packageName}@${input.version}` : input.packageName;
|
|
39710
|
+
if (packageManager === "bun") {
|
|
39711
|
+
await runCommand("bun", ["add", spec], { cwd: input.pluginHome });
|
|
39712
|
+
return;
|
|
39713
|
+
}
|
|
39714
|
+
await runCommand("npm", ["install", spec], { cwd: input.pluginHome });
|
|
39715
|
+
}
|
|
39716
|
+
async function updatePluginPackage(input) {
|
|
39717
|
+
await installPluginPackage(input);
|
|
39718
|
+
}
|
|
39719
|
+
async function removePluginPackage(input) {
|
|
39720
|
+
const runCommand = input.runCommand ?? defaultRunCommand;
|
|
39721
|
+
const packageManager = input.packageManager ?? await detectPackageManager();
|
|
39722
|
+
if (packageManager === "bun") {
|
|
39723
|
+
await runCommand("bun", ["remove", input.packageName], { cwd: input.pluginHome });
|
|
39724
|
+
return;
|
|
39725
|
+
}
|
|
39726
|
+
await runCommand("npm", ["uninstall", input.packageName], { cwd: input.pluginHome });
|
|
39727
|
+
}
|
|
39728
|
+
|
|
39729
|
+
// src/cli-update.ts
|
|
39730
|
+
init_plugin_loader();
|
|
39731
|
+
init_validate_plugin();
|
|
39732
|
+
async function handleUpdateCli(args, deps) {
|
|
39733
|
+
let all = false;
|
|
39734
|
+
const explicitTargets = [];
|
|
39735
|
+
for (const arg of args) {
|
|
39736
|
+
if (arg === "--all")
|
|
39737
|
+
all = true;
|
|
39738
|
+
else
|
|
39739
|
+
explicitTargets.push(arg);
|
|
39740
|
+
}
|
|
39741
|
+
if (all && explicitTargets.length > 0)
|
|
39742
|
+
return null;
|
|
39743
|
+
if (explicitTargets.length > 1)
|
|
39744
|
+
return null;
|
|
39745
|
+
const config2 = await deps.loadConfig();
|
|
39746
|
+
const packageName = deps.packageName ?? await readPackageName();
|
|
39747
|
+
const latestOf = deps.getLatestVersion ?? getLatestNpmVersion;
|
|
39748
|
+
const targets = [
|
|
39749
|
+
{
|
|
39750
|
+
kind: "self",
|
|
39751
|
+
name: packageName,
|
|
39752
|
+
currentVersion: deps.readCurrentVersion(),
|
|
39753
|
+
latestVersion: await latestOf(packageName)
|
|
39754
|
+
}
|
|
39755
|
+
];
|
|
39756
|
+
for (const plugin of config2.plugins ?? []) {
|
|
39757
|
+
targets.push({
|
|
39758
|
+
kind: "plugin",
|
|
39759
|
+
name: plugin.name,
|
|
39760
|
+
currentVersion: plugin.version,
|
|
39761
|
+
pinned: Boolean(plugin.version),
|
|
39762
|
+
latestVersion: await latestOf(plugin.name)
|
|
39763
|
+
});
|
|
39764
|
+
}
|
|
39765
|
+
deps.print("可更新项:");
|
|
39766
|
+
for (let index = 0;index < targets.length; index += 1) {
|
|
39767
|
+
const target = targets[index];
|
|
39768
|
+
deps.print(`${index + 1}. ${formatTarget(target)}`);
|
|
39769
|
+
}
|
|
39770
|
+
const unavailable = targets.filter((target) => !target.latestVersion || target.kind === "plugin" && !target.pinned);
|
|
39771
|
+
if (all && unavailable.length > 0) {
|
|
39772
|
+
deps.print(`以下项目无法检查最新版本,已取消更新:${unavailable.map((target) => target.name).join(", ")}`);
|
|
39773
|
+
return 1;
|
|
39774
|
+
}
|
|
39775
|
+
const candidates = targets.filter((target) => target.latestVersion && (target.kind !== "plugin" || target.pinned) && target.currentVersion !== target.latestVersion);
|
|
39776
|
+
const selected = await selectTargets(targets, candidates, { all, explicitTarget: explicitTargets[0], deps });
|
|
39777
|
+
if (!selected.ok) {
|
|
39778
|
+
deps.print(selected.message);
|
|
39779
|
+
return selected.exitCode;
|
|
39780
|
+
}
|
|
39781
|
+
if (selected.targets.length === 0) {
|
|
39782
|
+
deps.print("没有需要更新的项目。");
|
|
39783
|
+
return 0;
|
|
39784
|
+
}
|
|
39785
|
+
const selfUpdater = deps.updateSelf ?? defaultUpdateSelf;
|
|
39786
|
+
const pluginHome = deps.pluginHome ?? resolvePluginHome();
|
|
39787
|
+
const pluginUpdater = deps.updatePlugin ?? (async (input) => {
|
|
39788
|
+
await ensurePluginHome(pluginHome);
|
|
39789
|
+
await updatePluginPackage({ ...input, pluginHome });
|
|
39790
|
+
});
|
|
39791
|
+
const validatePlugin = deps.validatePlugin ?? validatePluginDefault;
|
|
39792
|
+
const updatedPlugins = [...config2.plugins ?? []];
|
|
39793
|
+
for (const target of selected.targets) {
|
|
39794
|
+
try {
|
|
39795
|
+
if (target.kind === "self") {
|
|
39796
|
+
if (!all && !explicitTargets[0]) {
|
|
39797
|
+
if (!deps.isInteractive()) {
|
|
39798
|
+
deps.print("更新 weacpx 本体需要确认;非交互模式请使用 `weacpx update --all` 或 `weacpx update weacpx`。");
|
|
39799
|
+
return 1;
|
|
39800
|
+
}
|
|
39801
|
+
const answer = (await deps.promptText("确认更新 weacpx 本体?[y/N] ")).trim().toLowerCase();
|
|
39802
|
+
if (answer !== "y" && answer !== "yes") {
|
|
39803
|
+
deps.print("已取消更新 weacpx 本体。");
|
|
39804
|
+
continue;
|
|
39805
|
+
}
|
|
39806
|
+
}
|
|
39807
|
+
await selfUpdater(target.name);
|
|
39808
|
+
deps.print(`weacpx 已更新:${target.latestVersion ?? "latest"}`);
|
|
39809
|
+
continue;
|
|
39810
|
+
}
|
|
39811
|
+
const existing = updatedPlugins.find((plugin) => plugin.name === target.name);
|
|
39812
|
+
const previousVersion = existing?.version;
|
|
39813
|
+
const updateInput = target.latestVersion ? { packageName: target.name, version: target.latestVersion } : { packageName: target.name };
|
|
39814
|
+
await pluginUpdater(updateInput);
|
|
39815
|
+
try {
|
|
39816
|
+
await validatePlugin(target.name, pluginHome);
|
|
39817
|
+
} catch (validationError) {
|
|
39818
|
+
if (previousVersion) {
|
|
39819
|
+
try {
|
|
39820
|
+
await pluginUpdater({ packageName: target.name, version: previousVersion });
|
|
39821
|
+
} catch (rollbackError) {
|
|
39822
|
+
deps.print(`回滚 ${target.name} 到 ${previousVersion} 失败:${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`);
|
|
39823
|
+
}
|
|
39824
|
+
}
|
|
39825
|
+
throw validationError;
|
|
39826
|
+
}
|
|
39827
|
+
if (!existing)
|
|
39828
|
+
throw new Error(`配置中没有找到插件 ${target.name}`);
|
|
39829
|
+
if (existing && target.latestVersion)
|
|
39830
|
+
existing.version = target.latestVersion;
|
|
39831
|
+
deps.print(`插件 ${target.name} 已更新:${target.latestVersion ?? "latest"}`);
|
|
39832
|
+
} catch (error2) {
|
|
39833
|
+
deps.print(`${target.name} 更新失败:${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
39834
|
+
return 1;
|
|
39835
|
+
}
|
|
39836
|
+
}
|
|
39837
|
+
if (selected.targets.some((target) => target.kind === "plugin")) {
|
|
39838
|
+
config2.plugins = updatedPlugins;
|
|
39839
|
+
await deps.saveConfig(config2);
|
|
39840
|
+
}
|
|
39841
|
+
return 0;
|
|
39842
|
+
}
|
|
39843
|
+
function formatTarget(target) {
|
|
39844
|
+
const current = target.currentVersion ?? "未锁定";
|
|
39845
|
+
const latest = target.latestVersion ?? "无法检查";
|
|
39846
|
+
const label = target.kind === "self" ? "weacpx" : `插件 ${target.name}`;
|
|
39847
|
+
return `${label} (${current} -> ${latest})`;
|
|
39848
|
+
}
|
|
39849
|
+
async function selectTargets(targets, candidates, input) {
|
|
39850
|
+
if (input.explicitTarget) {
|
|
39851
|
+
const target = targets.find((entry) => entry.name === input.explicitTarget || input.explicitTarget === "weacpx" && entry.kind === "self");
|
|
39852
|
+
if (!target)
|
|
39853
|
+
return { ok: false, message: `没有找到更新项:${input.explicitTarget}`, exitCode: 1 };
|
|
39854
|
+
if (!target.latestVersion)
|
|
39855
|
+
return { ok: false, message: `${target.name} 无法检查最新版本,已跳过。`, exitCode: 1 };
|
|
39856
|
+
if (target.kind === "plugin" && !target.pinned)
|
|
39857
|
+
return { ok: false, message: `${target.name} 未记录当前版本;请先使用 \`weacpx plugin update ${target.name}\` 或显式选择版本。`, exitCode: 1 };
|
|
39858
|
+
if (target.currentVersion === target.latestVersion)
|
|
39859
|
+
return { ok: true, targets: [] };
|
|
39860
|
+
return { ok: true, targets: [target] };
|
|
39861
|
+
}
|
|
39862
|
+
if (input.all || targets.length === 1)
|
|
39863
|
+
return { ok: true, targets: candidates };
|
|
39864
|
+
if (!input.deps.isInteractive()) {
|
|
39865
|
+
return { ok: false, message: "检测到已安装插件;非交互模式请使用 `weacpx update --all` 或 `weacpx update <name>`。", exitCode: 1 };
|
|
39866
|
+
}
|
|
39867
|
+
const answer = (await input.deps.promptText("请选择要更新的项目(数字,逗号分隔,a=全部,回车取消):")).trim().toLowerCase();
|
|
39868
|
+
if (!answer)
|
|
39869
|
+
return { ok: true, targets: [] };
|
|
39870
|
+
if (answer === "a" || answer === "all")
|
|
39871
|
+
return { ok: true, targets: candidates };
|
|
39872
|
+
const selected = [];
|
|
39873
|
+
for (const part of answer.split(",")) {
|
|
39874
|
+
const index = Number.parseInt(part.trim(), 10);
|
|
39875
|
+
if (!Number.isFinite(index) || index < 1 || index > targets.length) {
|
|
39876
|
+
return { ok: false, message: `无效选择:${part.trim()}`, exitCode: 1 };
|
|
39877
|
+
}
|
|
39878
|
+
const target = targets[index - 1];
|
|
39879
|
+
if (!target.latestVersion)
|
|
39880
|
+
return { ok: false, message: `${target.name} 无法检查最新版本,已跳过。`, exitCode: 1 };
|
|
39881
|
+
if (target.kind === "plugin" && !target.pinned)
|
|
39882
|
+
return { ok: false, message: `${target.name} 未记录当前版本;请先使用 \`weacpx plugin update ${target.name}\` 或显式选择版本。`, exitCode: 1 };
|
|
39883
|
+
if (target.currentVersion === target.latestVersion)
|
|
39884
|
+
continue;
|
|
39885
|
+
if (!selected.includes(target))
|
|
39886
|
+
selected.push(target);
|
|
39887
|
+
}
|
|
39888
|
+
return { ok: true, targets: selected };
|
|
39889
|
+
}
|
|
39890
|
+
async function getLatestNpmVersion(packageName) {
|
|
39891
|
+
const result = await runCapture("npm", ["view", packageName, "version", "--json"]);
|
|
39892
|
+
if (result.code !== 0)
|
|
39893
|
+
return null;
|
|
39894
|
+
const raw = result.stdout.trim();
|
|
39895
|
+
if (!raw)
|
|
39896
|
+
return null;
|
|
39897
|
+
try {
|
|
39898
|
+
const parsed = JSON.parse(raw);
|
|
39899
|
+
return typeof parsed === "string" ? parsed : null;
|
|
39900
|
+
} catch {
|
|
39901
|
+
return raw.replace(/^"|"$/g, "") || null;
|
|
39902
|
+
}
|
|
39903
|
+
}
|
|
39904
|
+
async function defaultUpdateSelf(packageName) {
|
|
39905
|
+
const manager = process.env.WEACPX_PACKAGE_MANAGER?.trim().toLowerCase() === "bun" ? "bun" : "npm";
|
|
39906
|
+
if (manager === "bun") {
|
|
39907
|
+
await runInherit("bun", ["add", "-g", packageName]);
|
|
39908
|
+
return;
|
|
39909
|
+
}
|
|
39910
|
+
await runInherit("npm", ["install", "-g", packageName]);
|
|
39911
|
+
}
|
|
39912
|
+
async function runCapture(command, args) {
|
|
39913
|
+
return await new Promise((resolve, reject) => {
|
|
39914
|
+
const child = spawn4(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
39915
|
+
let stdout2 = "";
|
|
39916
|
+
let stderr = "";
|
|
39917
|
+
child.stdout.setEncoding("utf8");
|
|
39918
|
+
child.stderr.setEncoding("utf8");
|
|
39919
|
+
child.stdout.on("data", (chunk) => {
|
|
39920
|
+
stdout2 += chunk;
|
|
39921
|
+
});
|
|
39922
|
+
child.stderr.on("data", (chunk) => {
|
|
39923
|
+
stderr += chunk;
|
|
39924
|
+
});
|
|
39925
|
+
child.on("error", reject);
|
|
39926
|
+
child.on("close", (code) => resolve({ code: code ?? 1, stdout: stdout2, stderr }));
|
|
39927
|
+
});
|
|
39928
|
+
}
|
|
39929
|
+
async function runInherit(command, args) {
|
|
39930
|
+
await new Promise((resolve, reject) => {
|
|
39931
|
+
const child = spawn4(command, args, { stdio: "inherit" });
|
|
39932
|
+
child.on("error", reject);
|
|
39933
|
+
child.on("exit", (code) => {
|
|
39934
|
+
if (code === 0)
|
|
39935
|
+
resolve();
|
|
39936
|
+
else
|
|
39937
|
+
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
39938
|
+
});
|
|
39939
|
+
});
|
|
39940
|
+
}
|
|
39941
|
+
async function readPackageName() {
|
|
39942
|
+
try {
|
|
39943
|
+
const here = dirname7(fileURLToPath2(import.meta.url));
|
|
39944
|
+
for (const candidate of [join6(here, "..", "package.json"), join6(here, "..", "..", "package.json")]) {
|
|
39945
|
+
try {
|
|
39946
|
+
const parsed = JSON.parse(await readFile7(candidate, "utf8"));
|
|
39947
|
+
if (typeof parsed.name === "string" && parsed.name.trim())
|
|
39948
|
+
return parsed.name.trim();
|
|
39949
|
+
} catch {}
|
|
39950
|
+
}
|
|
39951
|
+
} catch {}
|
|
39952
|
+
return "weacpx";
|
|
39953
|
+
}
|
|
39954
|
+
async function validatePluginDefault(packageName, pluginHome) {
|
|
39955
|
+
const moduleValue = await importPluginFromHome(packageName, pluginHome);
|
|
39956
|
+
validateWeacpxPlugin(moduleValue, packageName);
|
|
39957
|
+
}
|
|
39958
|
+
|
|
39959
|
+
// src/cli.ts
|
|
39580
39960
|
init_version();
|
|
39581
39961
|
|
|
39582
39962
|
// src/channels/cli/channel-cli.ts
|
|
@@ -40186,71 +40566,8 @@ async function setChannelAccountEnabled(type, accountId, enabled, rawArgs, deps)
|
|
|
40186
40566
|
|
|
40187
40567
|
// src/plugins/plugin-cli.ts
|
|
40188
40568
|
init_plugin_home();
|
|
40189
|
-
import { readFile as
|
|
40190
|
-
import { isAbsolute, join as
|
|
40191
|
-
|
|
40192
|
-
// src/plugins/package-manager.ts
|
|
40193
|
-
import { spawn as spawn3 } from "node:child_process";
|
|
40194
|
-
async function defaultRunCommand(command, args, options) {
|
|
40195
|
-
await new Promise((resolve, reject) => {
|
|
40196
|
-
const child = spawn3(command, args, { cwd: options.cwd, stdio: "inherit" });
|
|
40197
|
-
child.on("error", reject);
|
|
40198
|
-
child.on("exit", (code) => {
|
|
40199
|
-
if (code === 0)
|
|
40200
|
-
resolve();
|
|
40201
|
-
else
|
|
40202
|
-
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
40203
|
-
});
|
|
40204
|
-
});
|
|
40205
|
-
}
|
|
40206
|
-
async function silentRun(command, args, options) {
|
|
40207
|
-
await new Promise((resolve, reject) => {
|
|
40208
|
-
const child = spawn3(command, args, { cwd: options.cwd, stdio: "ignore" });
|
|
40209
|
-
child.on("error", reject);
|
|
40210
|
-
child.on("exit", (code) => {
|
|
40211
|
-
if (code === 0)
|
|
40212
|
-
resolve();
|
|
40213
|
-
else
|
|
40214
|
-
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
40215
|
-
});
|
|
40216
|
-
});
|
|
40217
|
-
}
|
|
40218
|
-
async function detectPackageManager(runCommand) {
|
|
40219
|
-
const override = process.env.WEACPX_PACKAGE_MANAGER?.trim().toLowerCase();
|
|
40220
|
-
if (override === "bun" || override === "npm")
|
|
40221
|
-
return override;
|
|
40222
|
-
const probe = runCommand ?? silentRun;
|
|
40223
|
-
try {
|
|
40224
|
-
await probe("bun", ["--version"], { cwd: process.cwd() });
|
|
40225
|
-
return "bun";
|
|
40226
|
-
} catch {
|
|
40227
|
-
return "npm";
|
|
40228
|
-
}
|
|
40229
|
-
}
|
|
40230
|
-
async function installPluginPackage(input) {
|
|
40231
|
-
const runCommand = input.runCommand ?? defaultRunCommand;
|
|
40232
|
-
const packageManager = input.packageManager ?? await detectPackageManager();
|
|
40233
|
-
const spec = input.version ? `${input.packageName}@${input.version}` : input.packageName;
|
|
40234
|
-
if (packageManager === "bun") {
|
|
40235
|
-
await runCommand("bun", ["add", spec], { cwd: input.pluginHome });
|
|
40236
|
-
return;
|
|
40237
|
-
}
|
|
40238
|
-
await runCommand("npm", ["install", spec], { cwd: input.pluginHome });
|
|
40239
|
-
}
|
|
40240
|
-
async function updatePluginPackage(input) {
|
|
40241
|
-
await installPluginPackage(input);
|
|
40242
|
-
}
|
|
40243
|
-
async function removePluginPackage(input) {
|
|
40244
|
-
const runCommand = input.runCommand ?? defaultRunCommand;
|
|
40245
|
-
const packageManager = input.packageManager ?? await detectPackageManager();
|
|
40246
|
-
if (packageManager === "bun") {
|
|
40247
|
-
await runCommand("bun", ["remove", input.packageName], { cwd: input.pluginHome });
|
|
40248
|
-
return;
|
|
40249
|
-
}
|
|
40250
|
-
await runCommand("npm", ["uninstall", input.packageName], { cwd: input.pluginHome });
|
|
40251
|
-
}
|
|
40252
|
-
|
|
40253
|
-
// src/plugins/plugin-cli.ts
|
|
40569
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
40570
|
+
import { isAbsolute, join as join8, resolve } from "node:path";
|
|
40254
40571
|
init_plugin_loader();
|
|
40255
40572
|
init_validate_plugin();
|
|
40256
40573
|
|
|
@@ -40259,14 +40576,14 @@ init_channel_scope();
|
|
|
40259
40576
|
init_plugin_loader();
|
|
40260
40577
|
init_validate_plugin();
|
|
40261
40578
|
init_known_plugins();
|
|
40262
|
-
import { readFile as
|
|
40263
|
-
import { join as
|
|
40579
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
40580
|
+
import { join as join7 } from "node:path";
|
|
40264
40581
|
function suggestedPluginPackageForChannel(type) {
|
|
40265
40582
|
return findKnownPluginByChannel(type)?.packageName ?? `<npm-package-that-provides-${type}>`;
|
|
40266
40583
|
}
|
|
40267
40584
|
async function readDependencyEntries(pluginHome) {
|
|
40268
40585
|
try {
|
|
40269
|
-
const raw = await
|
|
40586
|
+
const raw = await readFile8(join7(pluginHome, "package.json"), "utf8");
|
|
40270
40587
|
const parsed = JSON.parse(raw);
|
|
40271
40588
|
const out = {};
|
|
40272
40589
|
for (const [name, value] of Object.entries(parsed.dependencies ?? {})) {
|
|
@@ -40368,7 +40685,7 @@ function looksLikePath(spec) {
|
|
|
40368
40685
|
}
|
|
40369
40686
|
async function readDependencyEntries2(pluginHome) {
|
|
40370
40687
|
try {
|
|
40371
|
-
const raw = await
|
|
40688
|
+
const raw = await readFile9(join8(pluginHome, "package.json"), "utf8");
|
|
40372
40689
|
const parsed = JSON.parse(raw);
|
|
40373
40690
|
const out = {};
|
|
40374
40691
|
for (const [name, value] of Object.entries(parsed.dependencies ?? {})) {
|
|
@@ -40394,7 +40711,7 @@ async function resolveLocalPluginName(installSpec, pluginHome, namesBeforeInstal
|
|
|
40394
40711
|
return name;
|
|
40395
40712
|
}
|
|
40396
40713
|
try {
|
|
40397
|
-
const raw = await
|
|
40714
|
+
const raw = await readFile9(join8(installSpec, "package.json"), "utf8");
|
|
40398
40715
|
const parsed = JSON.parse(raw);
|
|
40399
40716
|
if (typeof parsed.name === "string" && parsed.name.trim())
|
|
40400
40717
|
return parsed.name.trim();
|
|
@@ -40923,6 +41240,7 @@ var HELP_LINES = [
|
|
|
40923
41240
|
"weacpx status - 查看状态",
|
|
40924
41241
|
"weacpx stop - 停止服务",
|
|
40925
41242
|
"weacpx restart - 重启后台服务",
|
|
41243
|
+
"weacpx update [--all|<name>] - 更新 weacpx 和已安装插件",
|
|
40926
41244
|
"weacpx channel|ch list|show|add|rm|enable|disable [--account <id>] - 管理消息频道(多 bot 用 --account)",
|
|
40927
41245
|
"weacpx plugin list|add|update|remove|enable|disable|doctor|known - 管理插件",
|
|
40928
41246
|
"weacpx doctor - 运行诊断",
|
|
@@ -40958,8 +41276,28 @@ async function runCli(args, deps = {}) {
|
|
|
40958
41276
|
await (deps.logout ?? defaultLogout)();
|
|
40959
41277
|
return 0;
|
|
40960
41278
|
case "run":
|
|
40961
|
-
|
|
41279
|
+
const onboarding = await runOnboardingBeforeStart({
|
|
41280
|
+
print,
|
|
41281
|
+
cwd: deps.cwd ?? (() => process.cwd()),
|
|
41282
|
+
isInteractive: deps.isInteractive,
|
|
41283
|
+
promptText: deps.promptText
|
|
41284
|
+
});
|
|
41285
|
+
await (deps.run ?? defaultRun)({ firstRunOnboarding: onboarding ?? undefined });
|
|
40962
41286
|
return 0;
|
|
41287
|
+
case "update": {
|
|
41288
|
+
const result = await (deps.update ?? ((subArgs) => defaultUpdate(subArgs, {
|
|
41289
|
+
print,
|
|
41290
|
+
isInteractive: deps.isInteractive,
|
|
41291
|
+
promptText: deps.promptText,
|
|
41292
|
+
overrides: deps.updateCliDeps
|
|
41293
|
+
})))(args.slice(1));
|
|
41294
|
+
if (result === null) {
|
|
41295
|
+
for (const line of HELP_LINES)
|
|
41296
|
+
print(line);
|
|
41297
|
+
return 1;
|
|
41298
|
+
}
|
|
41299
|
+
return result;
|
|
41300
|
+
}
|
|
40963
41301
|
case "doctor": {
|
|
40964
41302
|
const parsed = parseDoctorArgs(args.slice(1));
|
|
40965
41303
|
if (!parsed.ok) {
|
|
@@ -41025,7 +41363,22 @@ async function runCli(args, deps = {}) {
|
|
|
41025
41363
|
case "start": {
|
|
41026
41364
|
const controller = deps.controller ?? createDefaultController();
|
|
41027
41365
|
try {
|
|
41028
|
-
const
|
|
41366
|
+
const status = await controller.getStatus();
|
|
41367
|
+
if (status.state === "running") {
|
|
41368
|
+
print("weacpx 已在后台运行");
|
|
41369
|
+
print(`PID: ${status.pid}`);
|
|
41370
|
+
return 0;
|
|
41371
|
+
}
|
|
41372
|
+
if (status.state === "indeterminate") {
|
|
41373
|
+
throw new Error(`weacpx daemon process is already running (pid ${status.pid}) but status metadata is missing`);
|
|
41374
|
+
}
|
|
41375
|
+
const onboarding2 = await runOnboardingBeforeStart({
|
|
41376
|
+
print,
|
|
41377
|
+
cwd: deps.cwd ?? (() => process.cwd()),
|
|
41378
|
+
isInteractive: deps.isInteractive,
|
|
41379
|
+
promptText: deps.promptText
|
|
41380
|
+
});
|
|
41381
|
+
const result = await controller.start({ firstRunOnboarding: onboarding2 ?? undefined });
|
|
41029
41382
|
if (result.state === "already-running") {
|
|
41030
41383
|
print("weacpx 已在后台运行");
|
|
41031
41384
|
print(`PID: ${result.pid}`);
|
|
@@ -41094,6 +41447,44 @@ async function runCli(args, deps = {}) {
|
|
|
41094
41447
|
return 1;
|
|
41095
41448
|
}
|
|
41096
41449
|
}
|
|
41450
|
+
async function defaultUpdate(args, input) {
|
|
41451
|
+
const store = await createCliConfigStore();
|
|
41452
|
+
const deps = {
|
|
41453
|
+
loadConfig: async () => await store.load(),
|
|
41454
|
+
saveConfig: async (config2) => await store.save(config2),
|
|
41455
|
+
readCurrentVersion: readVersion,
|
|
41456
|
+
print: input.print,
|
|
41457
|
+
isInteractive: input.isInteractive ?? (() => Boolean(process.stdin.isTTY && process.stdout.isTTY)),
|
|
41458
|
+
promptText: input.promptText ?? defaultPromptText,
|
|
41459
|
+
...input.overrides
|
|
41460
|
+
};
|
|
41461
|
+
return await handleUpdateCli(args, deps);
|
|
41462
|
+
}
|
|
41463
|
+
async function runOnboardingBeforeStart(input) {
|
|
41464
|
+
const runtimePaths = (await init_main().then(() => exports_main)).resolveRuntimePaths();
|
|
41465
|
+
await ensureConfigExists(runtimePaths.configPath);
|
|
41466
|
+
const configStore = new ConfigStore(runtimePaths.configPath);
|
|
41467
|
+
const stateStore = new StateStore(runtimePaths.statePath);
|
|
41468
|
+
const config2 = await configStore.load();
|
|
41469
|
+
const state = await stateStore.load();
|
|
41470
|
+
const result = await maybeRunFirstUseOnboarding({
|
|
41471
|
+
config: config2,
|
|
41472
|
+
state,
|
|
41473
|
+
saveConfig: async (next) => await configStore.save(next),
|
|
41474
|
+
deps: {
|
|
41475
|
+
print: input.print,
|
|
41476
|
+
cwd: input.cwd,
|
|
41477
|
+
isInteractive: input.isInteractive ?? (() => Boolean(process.stdin.isTTY && process.stdout.isTTY)),
|
|
41478
|
+
promptText: input.promptText ?? defaultPromptText
|
|
41479
|
+
}
|
|
41480
|
+
});
|
|
41481
|
+
return result.created ? {
|
|
41482
|
+
alias: result.alias,
|
|
41483
|
+
agent: result.agent,
|
|
41484
|
+
workspace: result.workspace,
|
|
41485
|
+
rollback: result.rollback
|
|
41486
|
+
} : null;
|
|
41487
|
+
}
|
|
41097
41488
|
async function handleWorkspaceCli(args, deps) {
|
|
41098
41489
|
const subcommand = args[0];
|
|
41099
41490
|
switch (subcommand) {
|
|
@@ -41189,7 +41580,7 @@ async function defaultLoadConfiguredPluginsForChannelCli() {
|
|
|
41189
41580
|
const { loadConfiguredPlugins: loadConfiguredPlugins2 } = await Promise.resolve().then(() => (init_plugin_loader(), exports_plugin_loader));
|
|
41190
41581
|
await loadConfiguredPlugins2({ plugins: config2.plugins });
|
|
41191
41582
|
}
|
|
41192
|
-
async function defaultRun() {
|
|
41583
|
+
async function defaultRun(options = {}) {
|
|
41193
41584
|
const [{ buildApp: buildApp2, resolveRuntimePaths: resolveRuntimePaths2, prepareChannelMedia: prepareChannelMedia2 }, { runConsole: runConsole2 }] = await Promise.all([
|
|
41194
41585
|
init_main().then(() => exports_main),
|
|
41195
41586
|
Promise.resolve().then(() => (init_run_console(), exports_run_console))
|
|
@@ -41207,11 +41598,15 @@ async function defaultRun() {
|
|
|
41207
41598
|
const channelRegistry = new MessageChannelRegistry2(createMessageChannels2(config2.channels, channelDeps));
|
|
41208
41599
|
const lockCreators = channelRegistry.createConsumerLocks();
|
|
41209
41600
|
const firstLockCreator = lockCreators[0];
|
|
41601
|
+
const firstRunOnboarding = options.firstRunOnboarding ?? decodeFirstRunOnboarding(process.env.WEACPX_FIRST_RUN_ONBOARDING);
|
|
41210
41602
|
await runConsole2(runtimePaths, {
|
|
41211
41603
|
buildApp: (paths) => buildApp2(paths, {
|
|
41212
41604
|
defaultLoggingLevel: resolveCliEntryPath2().includes(`${sep}src${sep}`) ? "debug" : "info",
|
|
41213
41605
|
channel: channelRegistry
|
|
41214
41606
|
}),
|
|
41607
|
+
beforeReady: firstRunOnboarding ? async (runtime) => {
|
|
41608
|
+
await createFirstRunSession(runtime, firstRunOnboarding);
|
|
41609
|
+
} : undefined,
|
|
41215
41610
|
channels: channelRegistry,
|
|
41216
41611
|
daemonRuntime,
|
|
41217
41612
|
...firstLockCreator ? {
|
|
@@ -41224,6 +41619,42 @@ async function defaultRun() {
|
|
|
41224
41619
|
} : {}
|
|
41225
41620
|
});
|
|
41226
41621
|
}
|
|
41622
|
+
async function createFirstRunSession(runtime, plan) {
|
|
41623
|
+
const session = runtime.sessions.resolveSession(plan.alias, plan.agent, plan.workspace, plan.alias);
|
|
41624
|
+
try {
|
|
41625
|
+
await runtime.transport.ensureSession(session);
|
|
41626
|
+
const exists = await runtime.transport.hasSession(session);
|
|
41627
|
+
if (!exists) {
|
|
41628
|
+
throw new Error(`first-run onboarding failed to create transport session: ${plan.alias}`);
|
|
41629
|
+
}
|
|
41630
|
+
await runtime.sessions.attachSession(plan.alias, plan.agent, plan.workspace, session.transportSession);
|
|
41631
|
+
} catch (error2) {
|
|
41632
|
+
await rollbackFirstRunConfig(runtime, plan);
|
|
41633
|
+
throw error2;
|
|
41634
|
+
}
|
|
41635
|
+
await runtime.logger.info("onboarding.session_created", "created first-run transport session", {
|
|
41636
|
+
alias: plan.alias,
|
|
41637
|
+
agent: plan.agent,
|
|
41638
|
+
workspace: plan.workspace
|
|
41639
|
+
});
|
|
41640
|
+
}
|
|
41641
|
+
async function rollbackFirstRunConfig(runtime, plan) {
|
|
41642
|
+
try {
|
|
41643
|
+
const config2 = await runtime.configStore.load();
|
|
41644
|
+
if (!plan.rollback.workspaceExisted && config2.workspaces[plan.workspace]) {
|
|
41645
|
+
delete config2.workspaces[plan.workspace];
|
|
41646
|
+
}
|
|
41647
|
+
if (!plan.rollback.agentExisted && config2.agents[plan.agent]) {
|
|
41648
|
+
delete config2.agents[plan.agent];
|
|
41649
|
+
}
|
|
41650
|
+
await runtime.configStore.save(config2);
|
|
41651
|
+
} catch (error2) {
|
|
41652
|
+
await runtime.logger.error("onboarding.rollback_failed", "failed to roll back first-run config", {
|
|
41653
|
+
alias: plan.alias,
|
|
41654
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
41655
|
+
});
|
|
41656
|
+
}
|
|
41657
|
+
}
|
|
41227
41658
|
async function defaultDoctor(options) {
|
|
41228
41659
|
const { main: main3 } = await init_doctor2().then(() => exports_doctor);
|
|
41229
41660
|
return await main3(options);
|
|
@@ -41408,12 +41839,42 @@ async function defaultPromptSecret(message) {
|
|
|
41408
41839
|
}
|
|
41409
41840
|
function createDefaultController() {
|
|
41410
41841
|
const daemonPaths = resolveDaemonPaths({ home: requireHome2() });
|
|
41411
|
-
|
|
41842
|
+
const controller = createDaemonController(daemonPaths, {
|
|
41412
41843
|
processExecPath: process.execPath,
|
|
41413
41844
|
cliEntryPath: resolveCliEntryPath2(),
|
|
41414
41845
|
cwd: process.cwd(),
|
|
41415
41846
|
env: process.env
|
|
41416
41847
|
});
|
|
41848
|
+
return {
|
|
41849
|
+
getStatus: () => controller.getStatus(),
|
|
41850
|
+
stop: () => controller.stop(),
|
|
41851
|
+
start: (options) => controller.start({
|
|
41852
|
+
...options?.firstRunOnboarding ? { firstRunOnboarding: encodeFirstRunOnboarding(options.firstRunOnboarding) } : {}
|
|
41853
|
+
})
|
|
41854
|
+
};
|
|
41855
|
+
}
|
|
41856
|
+
function encodeFirstRunOnboarding(plan) {
|
|
41857
|
+
return Buffer.from(JSON.stringify(plan), "utf8").toString("base64url");
|
|
41858
|
+
}
|
|
41859
|
+
function decodeFirstRunOnboarding(raw) {
|
|
41860
|
+
if (!raw)
|
|
41861
|
+
return null;
|
|
41862
|
+
try {
|
|
41863
|
+
const parsed = JSON.parse(Buffer.from(raw, "base64url").toString("utf8"));
|
|
41864
|
+
if (typeof parsed.alias === "string" && typeof parsed.agent === "string" && typeof parsed.workspace === "string") {
|
|
41865
|
+
const rollback = typeof parsed.rollback === "object" && parsed.rollback !== null ? parsed.rollback : {};
|
|
41866
|
+
return {
|
|
41867
|
+
alias: parsed.alias,
|
|
41868
|
+
agent: parsed.agent,
|
|
41869
|
+
workspace: parsed.workspace,
|
|
41870
|
+
rollback: {
|
|
41871
|
+
workspaceExisted: rollback.workspaceExisted === true,
|
|
41872
|
+
agentExisted: rollback.agentExisted === true
|
|
41873
|
+
}
|
|
41874
|
+
};
|
|
41875
|
+
}
|
|
41876
|
+
} catch {}
|
|
41877
|
+
return null;
|
|
41417
41878
|
}
|
|
41418
41879
|
function requireHome2() {
|
|
41419
41880
|
const home = process.env.HOME ?? homedir13();
|
|
@@ -41436,7 +41897,7 @@ function resolveCliEntryPath2() {
|
|
|
41436
41897
|
if (process.argv[1]) {
|
|
41437
41898
|
return process.argv[1];
|
|
41438
41899
|
}
|
|
41439
|
-
return
|
|
41900
|
+
return fileURLToPath6(import.meta.url);
|
|
41440
41901
|
}
|
|
41441
41902
|
function parseDoctorArgs(args) {
|
|
41442
41903
|
const options = {};
|