weacpx 0.4.0-beta.3 → 0.4.0

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 CHANGED
@@ -9898,6 +9898,22 @@ var init_registry = __esm(() => {
9898
9898
  cliProviders = new Map;
9899
9899
  });
9900
9900
 
9901
+ // src/weixin/storage/ensure-dir.ts
9902
+ import fs2 from "node:fs";
9903
+ function ensureDirSync(dir) {
9904
+ try {
9905
+ fs2.mkdirSync(dir, { recursive: true });
9906
+ return;
9907
+ } catch (err) {
9908
+ try {
9909
+ if (fs2.statSync(dir).isDirectory())
9910
+ return;
9911
+ } catch {}
9912
+ throw err;
9913
+ }
9914
+ }
9915
+ var init_ensure_dir = () => {};
9916
+
9901
9917
  // src/weixin/storage/state-dir.ts
9902
9918
  import os from "node:os";
9903
9919
  import path3 from "node:path";
@@ -9907,7 +9923,7 @@ function resolveStateDir() {
9907
9923
  var init_state_dir = () => {};
9908
9924
 
9909
9925
  // src/weixin/auth/accounts.ts
9910
- import fs2 from "node:fs";
9926
+ import fs3 from "node:fs";
9911
9927
  import path4 from "node:path";
9912
9928
  function normalizeAccountId(raw) {
9913
9929
  return raw.trim().toLowerCase().replace(/[@.]/g, "-");
@@ -9930,9 +9946,9 @@ function resolveAccountIndexPath() {
9930
9946
  function listIndexedWeixinAccountIds() {
9931
9947
  const filePath = resolveAccountIndexPath();
9932
9948
  try {
9933
- if (!fs2.existsSync(filePath))
9949
+ if (!fs3.existsSync(filePath))
9934
9950
  return [];
9935
- const raw = fs2.readFileSync(filePath, "utf-8");
9951
+ const raw = fs3.readFileSync(filePath, "utf-8");
9936
9952
  const parsed = JSON.parse(raw);
9937
9953
  if (!Array.isArray(parsed))
9938
9954
  return [];
@@ -9943,8 +9959,8 @@ function listIndexedWeixinAccountIds() {
9943
9959
  }
9944
9960
  function registerWeixinAccountId(accountId) {
9945
9961
  const dir = resolveWeixinStateDir();
9946
- fs2.mkdirSync(dir, { recursive: true });
9947
- fs2.writeFileSync(resolveAccountIndexPath(), JSON.stringify([accountId], null, 2), "utf-8");
9962
+ ensureDirSync(dir);
9963
+ fs3.writeFileSync(resolveAccountIndexPath(), JSON.stringify([accountId], null, 2), "utf-8");
9948
9964
  }
9949
9965
  function resolveAccountsDir() {
9950
9966
  return path4.join(resolveWeixinStateDir(), "accounts");
@@ -9955,9 +9971,9 @@ function resolveAccountPath(accountId) {
9955
9971
  function loadLegacyToken() {
9956
9972
  const legacyPath = path4.join(resolveStateDir(), "credentials", "openclaw-weixin", "credentials.json");
9957
9973
  try {
9958
- if (!fs2.existsSync(legacyPath))
9974
+ if (!fs3.existsSync(legacyPath))
9959
9975
  return;
9960
- const raw = fs2.readFileSync(legacyPath, "utf-8");
9976
+ const raw = fs3.readFileSync(legacyPath, "utf-8");
9961
9977
  const parsed = JSON.parse(raw);
9962
9978
  return typeof parsed.token === "string" ? parsed.token : undefined;
9963
9979
  } catch {
@@ -9966,8 +9982,8 @@ function loadLegacyToken() {
9966
9982
  }
9967
9983
  function readAccountFile(filePath) {
9968
9984
  try {
9969
- if (fs2.existsSync(filePath)) {
9970
- return JSON.parse(fs2.readFileSync(filePath, "utf-8"));
9985
+ if (fs3.existsSync(filePath)) {
9986
+ return JSON.parse(fs3.readFileSync(filePath, "utf-8"));
9971
9987
  }
9972
9988
  } catch {}
9973
9989
  return null;
@@ -9989,7 +10005,7 @@ function loadWeixinAccount(accountId) {
9989
10005
  }
9990
10006
  function saveWeixinAccount(accountId, update) {
9991
10007
  const dir = resolveAccountsDir();
9992
- fs2.mkdirSync(dir, { recursive: true });
10008
+ ensureDirSync(dir);
9993
10009
  const existing = loadWeixinAccount(accountId) ?? {};
9994
10010
  const token = update.token?.trim() || existing.token;
9995
10011
  const baseUrl = update.baseUrl?.trim() || existing.baseUrl;
@@ -10000,14 +10016,14 @@ function saveWeixinAccount(accountId, update) {
10000
10016
  ...userId ? { userId } : {}
10001
10017
  };
10002
10018
  const filePath = resolveAccountPath(accountId);
10003
- fs2.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
10019
+ fs3.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
10004
10020
  try {
10005
- fs2.chmodSync(filePath, 384);
10021
+ fs3.chmodSync(filePath, 384);
10006
10022
  } catch {}
10007
10023
  }
10008
10024
  function clearWeixinAccount(accountId) {
10009
10025
  try {
10010
- fs2.unlinkSync(resolveAccountPath(accountId));
10026
+ fs3.unlinkSync(resolveAccountPath(accountId));
10011
10027
  } catch {}
10012
10028
  }
10013
10029
  function clearAllWeixinAccounts() {
@@ -10016,7 +10032,7 @@ function clearAllWeixinAccounts() {
10016
10032
  clearWeixinAccount(id);
10017
10033
  }
10018
10034
  try {
10019
- fs2.writeFileSync(resolveAccountIndexPath(), "[]", "utf-8");
10035
+ fs3.writeFileSync(resolveAccountIndexPath(), "[]", "utf-8");
10020
10036
  } catch {}
10021
10037
  }
10022
10038
  function resolveConfigPath() {
@@ -10028,9 +10044,9 @@ function resolveConfigPath() {
10028
10044
  function loadConfigRouteTag(accountId) {
10029
10045
  try {
10030
10046
  const configPath = resolveConfigPath();
10031
- if (!fs2.existsSync(configPath))
10047
+ if (!fs3.existsSync(configPath))
10032
10048
  return;
10033
- const raw = fs2.readFileSync(configPath, "utf-8");
10049
+ const raw = fs3.readFileSync(configPath, "utf-8");
10034
10050
  const cfg = JSON.parse(raw);
10035
10051
  const channels = cfg.channels;
10036
10052
  const section = channels?.["openclaw-weixin"];
@@ -10074,11 +10090,12 @@ function resolveWeixinAccount(accountId) {
10074
10090
  }
10075
10091
  var DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com", CDN_BASE_URL = "https://novac2c.cdn.weixin.qq.com/c2c";
10076
10092
  var init_accounts = __esm(() => {
10093
+ init_ensure_dir();
10077
10094
  init_state_dir();
10078
10095
  });
10079
10096
 
10080
10097
  // src/weixin/util/logger.ts
10081
- import fs3 from "node:fs";
10098
+ import fs4 from "node:fs";
10082
10099
  import os2 from "node:os";
10083
10100
  import path5 from "node:path";
10084
10101
  function resolveMinLevel() {
@@ -10128,10 +10145,10 @@ function writeLog(level, message, accountId) {
10128
10145
  });
10129
10146
  try {
10130
10147
  if (!logDirEnsured) {
10131
- fs3.mkdirSync(MAIN_LOG_DIR, { recursive: true });
10148
+ fs4.mkdirSync(MAIN_LOG_DIR, { recursive: true });
10132
10149
  logDirEnsured = true;
10133
10150
  }
10134
- fs3.appendFileSync(resolveMainLogPath(), `${entry}
10151
+ fs4.appendFileSync(resolveMainLogPath(), `${entry}
10135
10152
  `, "utf-8");
10136
10153
  } catch {}
10137
10154
  }
@@ -12103,7 +12120,7 @@ var init_media_store = __esm(() => {
12103
12120
  });
12104
12121
 
12105
12122
  // src/channels/outbound-media-safety.ts
12106
- import fs4 from "node:fs/promises";
12123
+ import fs5 from "node:fs/promises";
12107
12124
  import path7 from "node:path";
12108
12125
  async function resolveSafeOutboundMediaPath(mediaPath, allowedRoots) {
12109
12126
  if (mediaPath.startsWith("http://") || mediaPath.startsWith("https://")) {
@@ -12114,7 +12131,7 @@ async function resolveSafeOutboundMediaPath(mediaPath, allowedRoots) {
12114
12131
  if (!realCandidate) {
12115
12132
  return null;
12116
12133
  }
12117
- const stat2 = await fs4.stat(realCandidate).catch(() => null);
12134
+ const stat2 = await fs5.stat(realCandidate).catch(() => null);
12118
12135
  if (!stat2?.isFile()) {
12119
12136
  return null;
12120
12137
  }
@@ -12128,7 +12145,7 @@ async function resolveSafeOutboundMediaPath(mediaPath, allowedRoots) {
12128
12145
  }
12129
12146
  async function realpathOrNull(filePath) {
12130
12147
  try {
12131
- return await fs4.realpath(filePath);
12148
+ return await fs5.realpath(filePath);
12132
12149
  } catch {
12133
12150
  return null;
12134
12151
  }
@@ -12824,10 +12841,10 @@ var init_cdn_upload = __esm(() => {
12824
12841
 
12825
12842
  // src/weixin/cdn/upload.ts
12826
12843
  import crypto3 from "node:crypto";
12827
- import fs5 from "node:fs/promises";
12844
+ import fs6 from "node:fs/promises";
12828
12845
  async function uploadMediaToCdn(params) {
12829
12846
  const { filePath, toUserId, opts, cdnBaseUrl, mediaType, label } = params;
12830
- const plaintext = await fs5.readFile(filePath);
12847
+ const plaintext = await fs6.readFile(filePath);
12831
12848
  const rawsize = plaintext.length;
12832
12849
  const rawfilemd5 = crypto3.createHash("md5").update(plaintext).digest("hex");
12833
12850
  const filesize = aesEcbPaddedSize(rawsize);
@@ -12947,14 +12964,14 @@ var init_send_media = __esm(() => {
12947
12964
  });
12948
12965
 
12949
12966
  // src/weixin/messaging/debug-mode.ts
12950
- import fs6 from "node:fs";
12967
+ import fs7 from "node:fs";
12951
12968
  import path10 from "node:path";
12952
12969
  function resolveDebugModePath() {
12953
12970
  return path10.join(resolveStateDir(), "openclaw-weixin", "debug-mode.json");
12954
12971
  }
12955
12972
  function loadState() {
12956
12973
  try {
12957
- const raw = fs6.readFileSync(resolveDebugModePath(), "utf-8");
12974
+ const raw = fs7.readFileSync(resolveDebugModePath(), "utf-8");
12958
12975
  const parsed = JSON.parse(raw);
12959
12976
  if (parsed && typeof parsed.accounts === "object")
12960
12977
  return parsed;
@@ -12963,8 +12980,8 @@ function loadState() {
12963
12980
  }
12964
12981
  function saveState(state) {
12965
12982
  const filePath = resolveDebugModePath();
12966
- fs6.mkdirSync(path10.dirname(filePath), { recursive: true });
12967
- fs6.writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
12983
+ ensureDirSync(path10.dirname(filePath));
12984
+ fs7.writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
12968
12985
  }
12969
12986
  function toggleDebugMode(accountId) {
12970
12987
  const state = loadState();
@@ -12978,6 +12995,7 @@ function toggleDebugMode(accountId) {
12978
12995
  return next;
12979
12996
  }
12980
12997
  var init_debug_mode = __esm(() => {
12998
+ init_ensure_dir();
12981
12999
  init_state_dir();
12982
13000
  init_logger();
12983
13001
  });
@@ -13130,7 +13148,7 @@ function normalizeMediaArray(media) {
13130
13148
 
13131
13149
  // src/weixin/messaging/handle-weixin-message-turn.ts
13132
13150
  import crypto4 from "node:crypto";
13133
- import fs7 from "node:fs/promises";
13151
+ import fs8 from "node:fs/promises";
13134
13152
  import { tmpdir } from "node:os";
13135
13153
  import path11 from "node:path";
13136
13154
  function utf8ByteLength(s) {
@@ -13230,7 +13248,7 @@ function createSaveMediaBuffer(mediaTempDir) {
13230
13248
  throw new Error(`media exceeds ${maxBytes} bytes`);
13231
13249
  }
13232
13250
  const dir = path11.join(resolveMediaTempDir(mediaTempDir), subdir ?? "");
13233
- await fs7.mkdir(dir, { recursive: true });
13251
+ await fs8.mkdir(dir, { recursive: true });
13234
13252
  let ext = ".bin";
13235
13253
  if (originalFilename) {
13236
13254
  ext = path11.extname(originalFilename) || ".bin";
@@ -13239,7 +13257,7 @@ function createSaveMediaBuffer(mediaTempDir) {
13239
13257
  }
13240
13258
  const name = `${Date.now()}-${crypto4.randomBytes(4).toString("hex")}${ext}`;
13241
13259
  const filePath = path11.join(dir, name);
13242
- await fs7.writeFile(filePath, buffer);
13260
+ await fs8.writeFile(filePath, buffer);
13243
13261
  return { path: filePath };
13244
13262
  };
13245
13263
  }
@@ -13379,7 +13397,7 @@ async function handleWeixinMessageTurn(full, deps) {
13379
13397
  continue;
13380
13398
  }
13381
13399
  try {
13382
- const buffer = await fs7.readFile(filePath);
13400
+ const buffer = await fs8.readFile(filePath);
13383
13401
  const mimeType = downloaded.fileMediaType ?? downloaded.voiceMediaType ?? defaultWeixinMime(descriptor.kind);
13384
13402
  media.push(await mediaStore.saveMediaBuffer({
13385
13403
  channelId: "weixin",
@@ -13393,7 +13411,7 @@ async function handleWeixinMessageTurn(full, deps) {
13393
13411
  maxBytes: descriptor.kind === "image" ? DEFAULT_IMAGE_MAX_BYTES : DEFAULT_ATTACHMENT_MAX_BYTES
13394
13412
  }));
13395
13413
  } finally {
13396
- await fs7.rm(filePath, { force: true }).catch(() => {});
13414
+ await fs8.rm(filePath, { force: true }).catch(() => {});
13397
13415
  }
13398
13416
  } catch (err) {
13399
13417
  deps.errLog(`media download failed: ${String(err)}`);
@@ -13565,7 +13583,7 @@ var init_handle_weixin_message_turn = __esm(() => {
13565
13583
  });
13566
13584
 
13567
13585
  // src/weixin/storage/sync-buf.ts
13568
- import fs8 from "node:fs";
13586
+ import fs9 from "node:fs";
13569
13587
  import path12 from "node:path";
13570
13588
  function resolveAccountsDir2() {
13571
13589
  return path12.join(resolveStateDir(), "openclaw-weixin", "accounts");
@@ -13578,7 +13596,7 @@ function getLegacySyncBufDefaultJsonPath() {
13578
13596
  }
13579
13597
  function readSyncBufFile(filePath) {
13580
13598
  try {
13581
- const raw = fs8.readFileSync(filePath, "utf-8");
13599
+ const raw = fs9.readFileSync(filePath, "utf-8");
13582
13600
  const data = JSON.parse(raw);
13583
13601
  if (typeof data.get_updates_buf === "string") {
13584
13602
  return data.get_updates_buf;
@@ -13602,11 +13620,12 @@ function loadGetUpdatesBuf(filePath) {
13602
13620
  }
13603
13621
  function saveGetUpdatesBuf(filePath, getUpdatesBuf) {
13604
13622
  const dir = path12.dirname(filePath);
13605
- fs8.mkdirSync(dir, { recursive: true });
13606
- fs8.writeFileSync(filePath, JSON.stringify({ get_updates_buf: getUpdatesBuf }, null, 0), "utf-8");
13623
+ ensureDirSync(dir);
13624
+ fs9.writeFileSync(filePath, JSON.stringify({ get_updates_buf: getUpdatesBuf }, null, 0), "utf-8");
13607
13625
  }
13608
13626
  var init_sync_buf = __esm(() => {
13609
13627
  init_accounts();
13628
+ init_ensure_dir();
13610
13629
  init_state_dir();
13611
13630
  });
13612
13631
 
@@ -38874,7 +38893,7 @@ async function asToolResult(action) {
38874
38893
  text: "Outbound budget exhausted; the action has been recorded as pending and will retry automatically after the next user inbound resets the quota window. No further action required."
38875
38894
  }
38876
38895
  ],
38877
- structuredContent: { status: "deferred_quota", chatKey: error2.chatKey },
38896
+ structuredContent: { status: "deferred_quota" },
38878
38897
  isError: false
38879
38898
  };
38880
38899
  }
@@ -39085,7 +39104,9 @@ function renderCoordinatorReviewContestedResultSuccess(task, decision) {
39085
39104
  }
39086
39105
  function formatToolError(error2) {
39087
39106
  const message = error2 instanceof Error ? error2.message : String(error2);
39088
- if (/ECONNREFUSED|ENOENT|server closed without a response|socket hang up|connect /i.test(message)) {
39107
+ const code = typeof error2 === "object" && error2 !== null && "code" in error2 ? error2.code : undefined;
39108
+ const isConnectionError = code === "ECONNREFUSED" || code === "ENOENT" || code === "ECONNRESET" || code === "EPIPE" || /server closed without a response|socket hang up/i.test(message);
39109
+ if (isConnectionError) {
39089
39110
  return `Failed to connect to the orchestration daemon: ${message}`;
39090
39111
  }
39091
39112
  return message;
@@ -39246,9 +39267,9 @@ function createOrchestrationTransport(endpoint, deps = {}) {
39246
39267
  sourceHandle: input.sourceHandle ?? input.coordinatorSession,
39247
39268
  targetAgent: input.targetAgent,
39248
39269
  task: input.task,
39249
- ...input.workingDirectory ? { cwd: input.workingDirectory } : {},
39250
- ...input.role ? { role: input.role } : {},
39251
- ...input.groupId ? { groupId: input.groupId } : {}
39270
+ ...input.workingDirectory !== undefined ? { cwd: input.workingDirectory } : {},
39271
+ ...input.role !== undefined ? { role: input.role } : {},
39272
+ ...input.groupId !== undefined ? { groupId: input.groupId } : {}
39252
39273
  }),
39253
39274
  createGroup: async (input) => await client.createGroup(input),
39254
39275
  getGroup: async (input) => await client.getGroup(input),
@@ -39257,10 +39278,10 @@ function createOrchestrationTransport(endpoint, deps = {}) {
39257
39278
  getTask: async (input) => await client.getTaskForCoordinator(input),
39258
39279
  listTasks: async (input) => await client.listTasks({
39259
39280
  coordinatorSession: input.coordinatorSession,
39260
- ...input.status ? { status: input.status } : {},
39281
+ ...input.status !== undefined ? { status: input.status } : {},
39261
39282
  ...input.stuck !== undefined ? { stuck: input.stuck } : {},
39262
- ...input.sort ? { sort: input.sort } : {},
39263
- ...input.order ? { order: input.order } : {}
39283
+ ...input.sort !== undefined ? { sort: input.sort } : {},
39284
+ ...input.order !== undefined ? { order: input.order } : {}
39264
39285
  }),
39265
39286
  approveTask: async (input) => await client.approveTask(input),
39266
39287
  rejectTask: async (input) => await client.rejectTask(input),
@@ -39376,9 +39397,11 @@ function installMcpStdioShutdownHooks(options) {
39376
39397
  const parentPid = options.parentPid ?? process.ppid;
39377
39398
  const parentCheckIntervalMs = options.parentCheckIntervalMs ?? parseParentCheckIntervalMs(process.env.WEACPX_MCP_PARENT_CHECK_INTERVAL_MS);
39378
39399
  let disposed = false;
39400
+ let triggered = false;
39379
39401
  const triggerShutdown = (reason, context) => {
39380
- if (disposed)
39402
+ if (disposed || triggered)
39381
39403
  return;
39404
+ triggered = true;
39382
39405
  options.onDiagnostic?.("mcp.stdio.shutdown", { reason, ...context ?? {} });
39383
39406
  options.shutdown();
39384
39407
  };
@@ -39503,18 +39526,18 @@ function sanitizeMcpClientName(input) {
39503
39526
  return normalized.length > 0 ? normalized : "mcp-host";
39504
39527
  }
39505
39528
 
39506
- // src/mcp/parse-coordinator-workspace.ts
39507
- function parseCoordinatorWorkspace(args, env = process.env) {
39529
+ // src/mcp/parse-string-flag.ts
39530
+ function parseStringFlag(args, env, options) {
39508
39531
  let fromFlag = null;
39509
39532
  for (let index = 0;index < args.length; index += 1) {
39510
- if (args[index] === "--workspace") {
39533
+ if (args[index] === options.flag) {
39511
39534
  const value = args[index + 1];
39512
39535
  if (value === undefined) {
39513
- throw new Error("--workspace requires a non-empty value");
39536
+ throw new Error(`${options.flag} requires a non-empty value`);
39514
39537
  }
39515
39538
  const trimmedValue = value.trim();
39516
39539
  if (trimmedValue.length === 0 || trimmedValue.startsWith("-")) {
39517
- throw new Error("--workspace requires a non-empty value");
39540
+ throw new Error(`${options.flag} requires a non-empty value`);
39518
39541
  }
39519
39542
  fromFlag = value;
39520
39543
  }
@@ -39523,56 +39546,32 @@ function parseCoordinatorWorkspace(args, env = process.env) {
39523
39546
  if (trimmedFlag && trimmedFlag.length > 0) {
39524
39547
  return trimmedFlag;
39525
39548
  }
39526
- const trimmedEnv = env.WEACPX_COORDINATOR_WORKSPACE?.trim();
39549
+ const trimmedEnv = env[options.envKey]?.trim();
39527
39550
  return trimmedEnv && trimmedEnv.length > 0 ? trimmedEnv : null;
39528
39551
  }
39529
39552
 
39553
+ // src/mcp/parse-coordinator-workspace.ts
39554
+ function parseCoordinatorWorkspace(args, env = process.env) {
39555
+ return parseStringFlag(args, env, {
39556
+ flag: "--workspace",
39557
+ envKey: "WEACPX_COORDINATOR_WORKSPACE"
39558
+ });
39559
+ }
39560
+
39530
39561
  // src/mcp/parse-coordinator-session.ts
39531
39562
  function parseCoordinatorSession(args, env = process.env) {
39532
- let fromFlag = null;
39533
- for (let index = 0;index < args.length; index += 1) {
39534
- if (args[index] === "--coordinator-session") {
39535
- const value = args[index + 1];
39536
- if (value === undefined) {
39537
- throw new Error("--coordinator-session requires a non-empty value");
39538
- }
39539
- const trimmedValue = value.trim();
39540
- if (trimmedValue.length === 0 || trimmedValue.startsWith("-")) {
39541
- throw new Error("--coordinator-session requires a non-empty value");
39542
- }
39543
- fromFlag = value;
39544
- }
39545
- }
39546
- const trimmedFlag = fromFlag?.trim();
39547
- if (trimmedFlag && trimmedFlag.length > 0) {
39548
- return trimmedFlag;
39549
- }
39550
- const trimmedEnv = env.WEACPX_COORDINATOR_SESSION?.trim();
39551
- return trimmedEnv && trimmedEnv.length > 0 ? trimmedEnv : null;
39563
+ return parseStringFlag(args, env, {
39564
+ flag: "--coordinator-session",
39565
+ envKey: "WEACPX_COORDINATOR_SESSION"
39566
+ });
39552
39567
  }
39553
39568
 
39554
39569
  // src/mcp/parse-source-handle.ts
39555
39570
  function parseSourceHandle(args, env = process.env) {
39556
- let fromFlag = null;
39557
- for (let index = 0;index < args.length; index += 1) {
39558
- if (args[index] === "--source-handle") {
39559
- const value = args[index + 1];
39560
- if (value === undefined) {
39561
- throw new Error("--source-handle requires a non-empty value");
39562
- }
39563
- const trimmedValue = value.trim();
39564
- if (trimmedValue.length === 0 || trimmedValue.startsWith("-")) {
39565
- throw new Error("--source-handle requires a non-empty value");
39566
- }
39567
- fromFlag = value;
39568
- }
39569
- }
39570
- const trimmedFlag = fromFlag?.trim();
39571
- if (trimmedFlag && trimmedFlag.length > 0) {
39572
- return trimmedFlag;
39573
- }
39574
- const trimmedEnv = env.WEACPX_SOURCE_HANDLE?.trim();
39575
- return trimmedEnv && trimmedEnv.length > 0 ? trimmedEnv : null;
39571
+ return parseStringFlag(args, env, {
39572
+ flag: "--source-handle",
39573
+ envKey: "WEACPX_SOURCE_HANDLE"
39574
+ });
39576
39575
  }
39577
39576
 
39578
39577
  // src/cli.ts
@@ -0,0 +1 @@
1
+ export declare function ensureDirSync(dir: string): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weacpx",
3
- "version": "0.4.0-beta.3",
3
+ "version": "0.4.0",
4
4
  "description": "使用微信 ClawBot 随时随地通过 `acpx` 控制 Claude Code、Codex 等 Agents。",
5
5
  "keywords": [
6
6
  "acpx",