claude-codex-wechat 0.1.8 → 0.1.11

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 CHANGED
@@ -52,22 +52,47 @@ npm install -g claude-codex-wechat
52
52
  pnpm add -g claude-codex-wechat
53
53
  ```
54
54
 
55
- 安装后会得到全局命令:
55
+ 说明:
56
+
57
+ - 该包依赖 `better-sqlite3`
58
+ - 大多数常见平台会直接下载预编译二进制
59
+ - 少数环境可能需要本地编译工具链
60
+ - Node 版本要求:`>=20`
61
+
62
+ ## 快速开始
63
+
64
+ 安装后按以下顺序跑通:
56
65
 
57
66
  ```bash
58
- claude-codex-wechat help
67
+ # 1. 生成默认配置
59
68
  claude-codex-wechat init
69
+
70
+ # 2. 编辑 ~/.claude-codex-wechat/config.json,填入微信 token / accountId
71
+ # (配置说明见下方「配置」一节)
72
+
73
+ # 3. 检查环境(配置、前端产物、claude/codex 是否就绪)
60
74
  claude-codex-wechat doctor
75
+
76
+ # 4. 后台启动(首次会自动注册为系统服务并守护运行)
61
77
  claude-codex-wechat start
62
- claude-codex-wechat print-config
78
+
79
+ # 5. 查看状态 / 日志
80
+ claude-codex-wechat status
81
+ claude-codex-wechat logs
63
82
  ```
64
83
 
65
- 说明:
84
+ 启动后:
66
85
 
67
- - 该包依赖 `better-sqlite3`
68
- - 大多数常见平台会直接下载预编译二进制
69
- - 少数环境可能需要本地编译工具链
70
- - Node 版本要求:`>=20`
86
+ - 管理页:`http://127.0.0.1:8787`
87
+ - 微信侧即可直接给机器人发消息,驱动本机 `Claude Code` / `Codex CLI` 会话
88
+
89
+ 停止 / 重启 / 卸载:
90
+
91
+ ```bash
92
+ claude-codex-wechat restart
93
+ claude-codex-wechat stop
94
+ claude-codex-wechat uninstall
95
+ ```
71
96
 
72
97
  ### 从源码安装
73
98
 
@@ -188,13 +213,7 @@ pnpm build
188
213
 
189
214
  ## 生产运行
190
215
 
191
- 安装后直接后台启动即可,`start` 会把当前 CLI 注册成操作系统服务并拉起:
192
-
193
- ```bash
194
- claude-codex-wechat init # 首次:写配置,填好 token / accountId
195
- claude-codex-wechat start # 后台启动(自动安装服务)
196
- claude-codex-wechat status # 查看状态
197
- ```
216
+ 首次跑通流程见上方「快速开始」。`start` 会把当前 CLI 注册成操作系统服务并守护拉起。
198
217
 
199
218
  常用管理命令:
200
219
 
@@ -3,7 +3,7 @@ import { createRequire as __cjsCreateRequire } from 'node:module'; const require
3
3
 
4
4
  // src/cli.ts
5
5
  import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "node:fs";
6
- import { dirname as dirname11, join as join11 } from "node:path";
6
+ import { dirname as dirname12, join as join12 } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
8
 
9
9
  // src/daemon/bootstrap.ts
@@ -12,7 +12,7 @@ import { networkInterfaces } from "node:os";
12
12
  // src/daemon/server.ts
13
13
  import { mkdtempSync } from "node:fs";
14
14
  import { tmpdir as tmpdir2 } from "node:os";
15
- import { dirname as dirname9, join as join8 } from "node:path";
15
+ import { dirname as dirname10, join as join9 } from "node:path";
16
16
  import Fastify from "fastify";
17
17
 
18
18
  // src/channels/platforms.ts
@@ -372,7 +372,7 @@ async function listRecoverableClaudeSessions(env = process.env) {
372
372
  id: sessionId,
373
373
  providerId: "claude-code",
374
374
  ...cwd ? { cwd } : {},
375
- title: parsedMeta?.aiTitle ?? parsedMeta?.lastPrompt ?? fileName,
375
+ ...parsedMeta?.aiTitle ?? parsedMeta?.lastPrompt ? { title: parsedMeta?.aiTitle ?? parsedMeta?.lastPrompt } : {},
376
376
  ...parsedMeta?.sessionName ? { resumeTitle: parsedMeta.sessionName } : historyMeta?.display ? { resumeTitle: historyMeta.display } : {},
377
377
  ...historyMeta?.timestamp ? { lastActivityAt: historyMeta.timestamp } : metadata ? { lastActivityAt: Math.trunc(metadata.mtimeMs) } : {},
378
378
  ...bridgeTag ? { bridgeBindingSource: "bridge_tag", bridgeTag } : {}
@@ -880,7 +880,7 @@ async function syncCodexRolloutSessionMeta(rolloutPath) {
880
880
  }
881
881
  }
882
882
  async function delay(ms) {
883
- await new Promise((resolve) => setTimeout(resolve, ms));
883
+ await new Promise((resolve2) => setTimeout(resolve2, ms));
884
884
  }
885
885
 
886
886
  // src/session/providerAutoAttach.ts
@@ -1061,7 +1061,7 @@ function registerChannelAdminRoutes(input) {
1061
1061
 
1062
1062
  `);
1063
1063
  while (true) {
1064
- await new Promise((resolve) => setTimeout(resolve, client.pollIntervalMs));
1064
+ await new Promise((resolve2) => setTimeout(resolve2, client.pollIntervalMs));
1065
1065
  const status = await client.pollQrCodeStatus(qr.ticket);
1066
1066
  if (status.status === "waiting") continue;
1067
1067
  if (status.status === "scanned") {
@@ -1431,6 +1431,48 @@ function normalizeSettings(input, defaultWorkspace) {
1431
1431
  };
1432
1432
  }
1433
1433
 
1434
+ // src/admin/fsBrowseRoutes.ts
1435
+ import { readdir as readdir3 } from "node:fs/promises";
1436
+ import { homedir as homedir7 } from "node:os";
1437
+ import { dirname as dirname5, join as join6, resolve } from "node:path";
1438
+
1439
+ // src/shared/expandTilde.ts
1440
+ import { homedir as homedir6 } from "node:os";
1441
+ function expandTilde(target) {
1442
+ if (!target) return target;
1443
+ if (target === "~") return homedir6();
1444
+ if (target.startsWith("~/")) return homedir6() + target.slice(1);
1445
+ return target;
1446
+ }
1447
+
1448
+ // src/admin/fsBrowseRoutes.ts
1449
+ function registerFsBrowseRoutes(input) {
1450
+ input.app.get("/api/fs/list", async (request, reply) => {
1451
+ const raw = request.query.path?.trim();
1452
+ const target = resolve(expandTilde(raw && raw.length > 0 ? raw : homedir7()) ?? homedir7());
1453
+ const keepRaw = request.query.keep?.trim();
1454
+ const keep = keepRaw && keepRaw.length > 0 ? resolve(expandTilde(keepRaw) ?? keepRaw) : null;
1455
+ const isOnKeepChain = (path) => keep !== null && (keep === path || keep.startsWith(path + "/"));
1456
+ let dirents;
1457
+ try {
1458
+ dirents = await readdir3(target, { withFileTypes: true });
1459
+ } catch {
1460
+ reply.code(400);
1461
+ return { error: "cannot_read_directory", path: target };
1462
+ }
1463
+ const entries = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => ({ name: dirent.name, path: join6(target, dirent.name), isDirectory: true })).filter((entry) => !entry.name.startsWith(".") || isOnKeepChain(entry.path)).sort((a, b) => a.name.localeCompare(b.name));
1464
+ const parent = dirname5(target);
1465
+ const isRoot = parent === target;
1466
+ const listing = {
1467
+ path: target,
1468
+ parent: isRoot ? null : parent,
1469
+ isRoot,
1470
+ entries
1471
+ };
1472
+ return listing;
1473
+ });
1474
+ }
1475
+
1434
1476
  // src/channels/weixin-direct/apiClient.ts
1435
1477
  import { randomUUID } from "node:crypto";
1436
1478
  function collectInboundItems(itemList) {
@@ -1600,7 +1642,7 @@ var WeixinDirectApiClient = class {
1600
1642
 
1601
1643
  // src/channels/weixin-direct/adapter.ts
1602
1644
  import { setTimeout as delay2 } from "node:timers/promises";
1603
- import { join as join6 } from "node:path";
1645
+ import { join as join7 } from "node:path";
1604
1646
 
1605
1647
  // src/channels/weixin-direct/typingController.ts
1606
1648
  var CONFIG_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -1865,7 +1907,7 @@ var WeixinDirectAdapter = class _WeixinDirectAdapter {
1865
1907
  continue;
1866
1908
  }
1867
1909
  const { ext, mimeType } = mediaExtAndMime(meta);
1868
- const destPath = join6(mediaDir, `${idPrefix}_${i}${ext}`);
1910
+ const destPath = join7(mediaDir, `${idPrefix}_${i}${ext}`);
1869
1911
  const maxBytes = meta.kind === "video" ? VIDEO_MAX_BYTES : void 0;
1870
1912
  const result = await downloader.download(meta.media ?? {}, { destPath, aeskeyOverride: meta.aeskey, maxBytes });
1871
1913
  if (result.ok) {
@@ -1926,7 +1968,7 @@ function chunkText(text, limit) {
1926
1968
 
1927
1969
  // src/channels/weixin-direct/mediaDownloader.ts
1928
1970
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "node:fs";
1929
- import { dirname as dirname5 } from "node:path";
1971
+ import { dirname as dirname6 } from "node:path";
1930
1972
 
1931
1973
  // src/channels/weixin-direct/mediaCrypto.ts
1932
1974
  import { createDecipheriv } from "node:crypto";
@@ -1989,7 +2031,7 @@ var WeixinMediaDownloader = class {
1989
2031
  } catch {
1990
2032
  return { ok: false, reason: "decrypt_failed" };
1991
2033
  }
1992
- mkdirSync2(dirname5(input.destPath), { recursive: true });
2034
+ mkdirSync2(dirname6(input.destPath), { recursive: true });
1993
2035
  writeFileSync2(input.destPath, plaintext);
1994
2036
  return { ok: true, localPath: input.destPath, bytes: plaintext.length };
1995
2037
  }
@@ -2174,18 +2216,9 @@ var WeixinOutboundGate = class _WeixinOutboundGate {
2174
2216
  import { spawn as spawn2 } from "node:child_process";
2175
2217
  import { randomUUID as randomUUID2 } from "node:crypto";
2176
2218
 
2177
- // src/shared/expandTilde.ts
2178
- import { homedir as homedir6 } from "node:os";
2179
- function expandTilde(target) {
2180
- if (!target) return target;
2181
- if (target === "~") return homedir6();
2182
- if (target.startsWith("~/")) return homedir6() + target.slice(1);
2183
- return target;
2184
- }
2185
-
2186
2219
  // src/shared/platform.ts
2187
2220
  import { access, constants } from "node:fs/promises";
2188
- import { delimiter, join as join7 } from "node:path";
2221
+ import { delimiter, join as join8 } from "node:path";
2189
2222
  import { tmpdir } from "node:os";
2190
2223
  import { spawn } from "node:child_process";
2191
2224
  var isWindows = process.platform === "win32";
@@ -2213,7 +2246,7 @@ async function findExecutable(command) {
2213
2246
  const dirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
2214
2247
  for (const dir of dirs) {
2215
2248
  for (const ext of extensions) {
2216
- const candidate = join7(dir, command + ext);
2249
+ const candidate = join8(dir, command + ext);
2217
2250
  if (await isExecutableFile(candidate)) return candidate;
2218
2251
  }
2219
2252
  }
@@ -2236,10 +2269,10 @@ function terminateChild(child, signal = "SIGTERM") {
2236
2269
  }
2237
2270
  }
2238
2271
  function defaultWorkspaceDir() {
2239
- return join7(tmpdir(), "project");
2272
+ return join8(tmpdir(), "project");
2240
2273
  }
2241
2274
  function statePath(filename) {
2242
- return join7(tmpdir(), filename);
2275
+ return join8(tmpdir(), filename);
2243
2276
  }
2244
2277
 
2245
2278
  // src/providers/claude-code/claudeStreamingRunner.ts
@@ -2418,10 +2451,10 @@ function defaultClaudeStreamSpawner(call) {
2418
2451
  const queue = [];
2419
2452
  let resolveNext = null;
2420
2453
  const push = (chunk) => {
2421
- const resolve = resolveNext;
2422
- if (resolve) {
2454
+ const resolve2 = resolveNext;
2455
+ if (resolve2) {
2423
2456
  resolveNext = null;
2424
- resolve(chunk);
2457
+ resolve2(chunk);
2425
2458
  } else {
2426
2459
  queue.push(chunk);
2427
2460
  }
@@ -2451,8 +2484,8 @@ function defaultClaudeStreamSpawner(call) {
2451
2484
  read() {
2452
2485
  const next = queue.shift();
2453
2486
  if (next) return Promise.resolve(next);
2454
- return new Promise((resolve) => {
2455
- resolveNext = resolve;
2487
+ return new Promise((resolve2) => {
2488
+ resolveNext = resolve2;
2456
2489
  });
2457
2490
  },
2458
2491
  close() {
@@ -2551,8 +2584,8 @@ var CodexAppServerClient = class {
2551
2584
  const id = this.nextId++;
2552
2585
  const key = String(id);
2553
2586
  const payload = { id, method, ...params !== void 0 ? { params } : {} };
2554
- const response = new Promise((resolve, reject) => {
2555
- this.pending.set(key, { resolve, reject });
2587
+ const response = new Promise((resolve2, reject) => {
2588
+ this.pending.set(key, { resolve: resolve2, reject });
2556
2589
  });
2557
2590
  this.child.stdin.write(`${JSON.stringify(payload)}
2558
2591
  `);
@@ -2704,8 +2737,8 @@ var CodexInteractiveRunner = class {
2704
2737
  const client = await this.ensureClient(session);
2705
2738
  session.pendingText = [];
2706
2739
  session.activeTurnId = void 0;
2707
- session.turnCompletedPromise = new Promise((resolve) => {
2708
- session.turnCompletedResolver = resolve;
2740
+ session.turnCompletedPromise = new Promise((resolve2) => {
2741
+ session.turnCompletedResolver = resolve2;
2709
2742
  });
2710
2743
  if (session.threadId) {
2711
2744
  await client.request("thread/resume", {
@@ -2878,7 +2911,7 @@ function createDefaultProviders(input = {}) {
2878
2911
  // src/providers/claude-code/claudeDetection.ts
2879
2912
  import { spawn as spawn4 } from "node:child_process";
2880
2913
  async function defaultCommandRunner(command, args) {
2881
- return await new Promise((resolve) => {
2914
+ return await new Promise((resolve2) => {
2882
2915
  const child = spawn4(command, args, { stdio: ["ignore", "pipe", "pipe"] });
2883
2916
  let stdout = "";
2884
2917
  let stderr = "";
@@ -2889,11 +2922,11 @@ async function defaultCommandRunner(command, args) {
2889
2922
  stderr += String(chunk);
2890
2923
  });
2891
2924
  child.on("error", (error) => {
2892
- resolve({ ok: false, code: error.code ?? "ERROR", stdout, stderr: stderr || error.message });
2925
+ resolve2({ ok: false, code: error.code ?? "ERROR", stdout, stderr: stderr || error.message });
2893
2926
  });
2894
2927
  child.on("close", (code) => {
2895
- if (code === 0) resolve({ ok: true, stdout, stderr });
2896
- else resolve({ ok: false, code: code ?? "SIGNAL", stdout, stderr });
2928
+ if (code === 0) resolve2({ ok: true, stdout, stderr });
2929
+ else resolve2({ ok: false, code: code ?? "SIGNAL", stdout, stderr });
2897
2930
  });
2898
2931
  });
2899
2932
  }
@@ -2914,7 +2947,7 @@ ${result.stderr}`) };
2914
2947
  // src/providers/codex/codexDetection.ts
2915
2948
  import { spawn as spawn5 } from "node:child_process";
2916
2949
  async function defaultCodexCommandRunner(command, args) {
2917
- return await new Promise((resolve) => {
2950
+ return await new Promise((resolve2) => {
2918
2951
  const child = spawn5(command, args, { stdio: ["ignore", "pipe", "pipe"] });
2919
2952
  let stdout = "";
2920
2953
  let stderr = "";
@@ -2925,11 +2958,11 @@ async function defaultCodexCommandRunner(command, args) {
2925
2958
  stderr += String(chunk);
2926
2959
  });
2927
2960
  child.on("error", (error) => {
2928
- resolve({ ok: false, code: error.code ?? "ERROR", stdout, stderr: stderr || error.message });
2961
+ resolve2({ ok: false, code: error.code ?? "ERROR", stdout, stderr: stderr || error.message });
2929
2962
  });
2930
2963
  child.on("close", (code) => {
2931
- if (code === 0) resolve({ ok: true, stdout, stderr });
2932
- else resolve({ ok: false, code: code ?? "SIGNAL", stdout, stderr });
2964
+ if (code === 0) resolve2({ ok: true, stdout, stderr });
2965
+ else resolve2({ ok: false, code: code ?? "SIGNAL", stdout, stderr });
2933
2966
  });
2934
2967
  });
2935
2968
  }
@@ -3060,7 +3093,7 @@ function buildBridgeCommandHelpMarkdown() {
3060
3093
 
3061
3094
  // src/session/currentConversationStore.ts
3062
3095
  import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
3063
- import { dirname as dirname6 } from "node:path";
3096
+ import { dirname as dirname7 } from "node:path";
3064
3097
  import { nanoid as nanoid2 } from "nanoid";
3065
3098
  var CurrentConversationStore = class {
3066
3099
  constructor(configPath, defaults) {
@@ -3142,7 +3175,7 @@ var CurrentConversationStore = class {
3142
3175
  this.writeState(state);
3143
3176
  }
3144
3177
  writeState(state) {
3145
- mkdirSync3(dirname6(this.configPath), { recursive: true });
3178
+ mkdirSync3(dirname7(this.configPath), { recursive: true });
3146
3179
  writeFileSync3(this.configPath, `${JSON.stringify(state, null, 2)}
3147
3180
  `, "utf8");
3148
3181
  }
@@ -3350,8 +3383,8 @@ var MessageRouter = class _MessageRouter {
3350
3383
  }
3351
3384
  const genId = ++this.generationSeq;
3352
3385
  let abortGeneration;
3353
- const aborted = new Promise((resolve) => {
3354
- abortGeneration = () => resolve("aborted");
3386
+ const aborted = new Promise((resolve2) => {
3387
+ abortGeneration = () => resolve2("aborted");
3355
3388
  });
3356
3389
  this.activeGenerations.set(message.chatId, {
3357
3390
  genId,
@@ -3576,7 +3609,7 @@ var MessageRouter = class _MessageRouter {
3576
3609
  }
3577
3610
  }
3578
3611
  formatSessionLine(candidate) {
3579
- const title = candidate.resumeTitle ?? candidate.title ?? candidate.id;
3612
+ const title = candidate.resumeTitle ?? candidate.title ?? `\u672A\u547D\u540D\u4F1A\u8BDD \xB7 ${candidate.id.slice(0, 8)}`;
3580
3613
  const cwd = candidate.cwd ? ` \xB7 ${candidate.cwd}` : "";
3581
3614
  const when = candidate.lastActivityAt ? ` \xB7 ${formatRelativeTime(candidate.lastActivityAt)}` : "";
3582
3615
  return `${title}${cwd}${when}`;
@@ -3649,7 +3682,7 @@ function composeInboundText(content) {
3649
3682
 
3650
3683
  // src/storage/lastProviderSessionStore.ts
3651
3684
  import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
3652
- import { dirname as dirname7 } from "node:path";
3685
+ import { dirname as dirname8 } from "node:path";
3653
3686
  var LastProviderSessionStore = class {
3654
3687
  constructor(configPath) {
3655
3688
  this.configPath = configPath;
@@ -3680,7 +3713,7 @@ var LastProviderSessionStore = class {
3680
3713
  return raw && typeof raw === "object" ? raw : {};
3681
3714
  }
3682
3715
  writeState(state) {
3683
- mkdirSync4(dirname7(this.configPath), { recursive: true });
3716
+ mkdirSync4(dirname8(this.configPath), { recursive: true });
3684
3717
  writeFileSync4(this.configPath, `${JSON.stringify(state, null, 2)}
3685
3718
  `, "utf8");
3686
3719
  }
@@ -3688,7 +3721,7 @@ var LastProviderSessionStore = class {
3688
3721
 
3689
3722
  // src/storage/runtimeUserStore.ts
3690
3723
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync7 } from "node:fs";
3691
- import { dirname as dirname8 } from "node:path";
3724
+ import { dirname as dirname9 } from "node:path";
3692
3725
  import { nanoid as nanoid3 } from "nanoid";
3693
3726
  var RuntimeUserStore = class {
3694
3727
  constructor(configPath) {
@@ -3753,7 +3786,7 @@ var RuntimeUserStore = class {
3753
3786
  return raw && typeof raw === "object" ? raw : {};
3754
3787
  }
3755
3788
  writeState(state) {
3756
- mkdirSync5(dirname8(this.configPath), { recursive: true });
3789
+ mkdirSync5(dirname9(this.configPath), { recursive: true });
3757
3790
  writeFileSync5(this.configPath, `${JSON.stringify(state, null, 2)}
3758
3791
  `, "utf8");
3759
3792
  }
@@ -3784,7 +3817,7 @@ function createDaemonServer(options = {}) {
3784
3817
  defaultProvider: options.bridgeDefaults?.defaultProvider ?? "claude-code",
3785
3818
  defaultWorkspace: options.bridgeDefaults?.defaultWorkspace ?? process.cwd()
3786
3819
  };
3787
- const configPath = options.configPath ?? process.env.BRIDGE_CONFIG ?? join8(mkdtempSync(join8(tmpdir2(), "claude-codex-wechat-")), "config.json");
3820
+ const configPath = options.configPath ?? process.env.BRIDGE_CONFIG ?? join9(mkdtempSync(join9(tmpdir2(), "claude-codex-wechat-")), "config.json");
3788
3821
  const conversation = new CurrentConversationStore(configPath, {
3789
3822
  defaultCwd: bridgeDefaults.defaultWorkspace,
3790
3823
  defaultProviderId: bridgeDefaults.defaultProvider
@@ -3817,7 +3850,7 @@ function createDaemonServer(options = {}) {
3817
3850
  });
3818
3851
  }
3819
3852
  const weixinStateStore = configPath ? new FileWeixinStateStore(configPath) : void 0;
3820
- const weixinMediaDir = configPath ? join8(dirname9(configPath), "media") : void 0;
3853
+ const weixinMediaDir = configPath ? join9(dirname10(configPath), "media") : void 0;
3821
3854
  const managedWechatChannel = options.channel ? null : new ManagedWeixinDirectAdapter(options.wechat, weixinStateStore, weixinMediaDir);
3822
3855
  const channel = options.channel ?? managedWechatChannel;
3823
3856
  const weixinOutboundGate = managedWechatChannel && weixinStateStore ? new WeixinOutboundGate({
@@ -3907,6 +3940,7 @@ function createDaemonServer(options = {}) {
3907
3940
  defaults: bridgeDefaults,
3908
3941
  configPath
3909
3942
  });
3943
+ registerFsBrowseRoutes({ app });
3910
3944
  app.get("/api/status", async () => ({
3911
3945
  ok: true,
3912
3946
  sessions: conversation.getCurrent() ? [conversation.getCurrent()] : []
@@ -3991,7 +4025,7 @@ async function resolveProviderCommands(providers) {
3991
4025
 
3992
4026
  // src/daemon/staticFrontend.ts
3993
4027
  import { readFileSync as readFileSync6 } from "node:fs";
3994
- import { join as join9 } from "node:path";
4028
+ import { join as join10 } from "node:path";
3995
4029
  import fastifyStatic from "@fastify/static";
3996
4030
  function attachStaticFrontend(webRoot2) {
3997
4031
  return async (app) => {
@@ -3999,7 +4033,7 @@ function attachStaticFrontend(webRoot2) {
3999
4033
  root: webRoot2,
4000
4034
  wildcard: false
4001
4035
  });
4002
- const indexHtml = readFileSync6(join9(webRoot2, "index.html"), "utf8");
4036
+ const indexHtml = readFileSync6(join10(webRoot2, "index.html"), "utf8");
4003
4037
  app.setNotFoundHandler((request, reply) => {
4004
4038
  if (request.url.startsWith("/api")) {
4005
4039
  reply.code(404).send({ error: "not_found" });
@@ -4013,8 +4047,8 @@ function attachStaticFrontend(webRoot2) {
4013
4047
  // src/daemon/service.ts
4014
4048
  import { existsSync as existsSync8, statSync } from "node:fs";
4015
4049
  import { mkdir as mkdir4, readFile as readFile6, rm as rm2, writeFile as writeFile5 } from "node:fs/promises";
4016
- import { homedir as homedir7 } from "node:os";
4017
- import { dirname as dirname10, join as join10 } from "node:path";
4050
+ import { homedir as homedir8 } from "node:os";
4051
+ import { dirname as dirname11, join as join11 } from "node:path";
4018
4052
  import { createReadStream } from "node:fs";
4019
4053
  import { execFile, spawn as spawn6 } from "node:child_process";
4020
4054
  import { createInterface } from "node:readline";
@@ -4023,8 +4057,8 @@ var execFileAsync = promisify(execFile);
4023
4057
  async function installService(context) {
4024
4058
  if (process.platform === "darwin") {
4025
4059
  const spec = buildLaunchdSpec(context);
4026
- await mkdir4(dirname10(spec.plistPath), { recursive: true });
4027
- await mkdir4(dirname10(spec.stdoutPath), { recursive: true });
4060
+ await mkdir4(dirname11(spec.plistPath), { recursive: true });
4061
+ await mkdir4(dirname11(spec.stdoutPath), { recursive: true });
4028
4062
  await writeFile5(spec.plistPath, renderLaunchdPlist(spec), "utf8");
4029
4063
  await runLaunchctl(["unload", spec.plistPath]).catch(() => void 0);
4030
4064
  await runLaunchctl(["load", spec.plistPath]);
@@ -4033,8 +4067,8 @@ async function installService(context) {
4033
4067
  }
4034
4068
  if (process.platform === "linux") {
4035
4069
  const spec = buildSystemdUserSpec(context);
4036
- await mkdir4(dirname10(spec.unitPath), { recursive: true });
4037
- await mkdir4(dirname10(spec.stdoutPath), { recursive: true });
4070
+ await mkdir4(dirname11(spec.unitPath), { recursive: true });
4071
+ await mkdir4(dirname11(spec.stdoutPath), { recursive: true });
4038
4072
  await writeFile5(spec.unitPath, renderSystemdUnit(spec), "utf8");
4039
4073
  await runSystemctl(["--user", "daemon-reload"]);
4040
4074
  await runSystemctl(["--user", "enable", "--now", spec.unitName]);
@@ -4156,33 +4190,33 @@ async function readServiceStatus(context) {
4156
4190
  throw new Error("service_status_not_supported_on_this_platform");
4157
4191
  }
4158
4192
  function buildLaunchdSpec(context) {
4159
- const stateDir = join10(homedir7(), ".claude-codex-wechat");
4193
+ const stateDir = join11(homedir8(), ".claude-codex-wechat");
4160
4194
  return {
4161
4195
  label: "com.claude-codex-wechat",
4162
- plistPath: join10(homedir7(), "Library", "LaunchAgents", "com.claude-codex-wechat.plist"),
4196
+ plistPath: join11(homedir8(), "Library", "LaunchAgents", "com.claude-codex-wechat.plist"),
4163
4197
  programArgs: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "__daemon"],
4164
- workingDirectory: homedir7(),
4165
- stdoutPath: join10(stateDir, "logs", "service.stdout.log"),
4166
- stderrPath: join10(stateDir, "logs", "service.stderr.log"),
4198
+ workingDirectory: homedir8(),
4199
+ stdoutPath: join11(stateDir, "logs", "service.stdout.log"),
4200
+ stderrPath: join11(stateDir, "logs", "service.stderr.log"),
4167
4201
  environment: buildServiceEnvironment(context)
4168
4202
  };
4169
4203
  }
4170
4204
  function buildSystemdUserSpec(context) {
4171
- const stateDir = join10(homedir7(), ".claude-codex-wechat");
4205
+ const stateDir = join11(homedir8(), ".claude-codex-wechat");
4172
4206
  return {
4173
4207
  unitName: "claude-codex-wechat.service",
4174
- unitPath: join10(homedir7(), ".config", "systemd", "user", "claude-codex-wechat.service"),
4208
+ unitPath: join11(homedir8(), ".config", "systemd", "user", "claude-codex-wechat.service"),
4175
4209
  execStart: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "__daemon"],
4176
- workingDirectory: homedir7(),
4177
- stdoutPath: join10(stateDir, "logs", "service.stdout.log"),
4178
- stderrPath: join10(stateDir, "logs", "service.stderr.log"),
4210
+ workingDirectory: homedir8(),
4211
+ stdoutPath: join11(stateDir, "logs", "service.stdout.log"),
4212
+ stderrPath: join11(stateDir, "logs", "service.stderr.log"),
4179
4213
  environment: buildServiceEnvironment(context)
4180
4214
  };
4181
4215
  }
4182
4216
  function buildServiceEnvironment(context) {
4183
4217
  const env = {
4184
4218
  PATH: process.env.PATH ?? "",
4185
- HOME: process.env.HOME ?? homedir7()
4219
+ HOME: process.env.HOME ?? homedir8()
4186
4220
  };
4187
4221
  const configPath = context.configPath ?? process.env.BRIDGE_CONFIG;
4188
4222
  const port = context.port ?? Number(process.env.BRIDGE_PORT ?? 8787);
@@ -4304,8 +4338,8 @@ async function tailFiles(paths) {
4304
4338
  child.stdout.on("data", (chunk) => {
4305
4339
  process.stdout.write(String(chunk));
4306
4340
  });
4307
- await new Promise((resolve, reject) => {
4308
- child.on("exit", () => resolve());
4341
+ await new Promise((resolve2, reject) => {
4342
+ child.on("exit", () => resolve2());
4309
4343
  child.on("error", reject);
4310
4344
  }).finally(() => {
4311
4345
  for (const reader of readers) reader.close();
@@ -4320,8 +4354,8 @@ function fileSizeHint(path) {
4320
4354
  }
4321
4355
 
4322
4356
  // src/cli.ts
4323
- var here = dirname11(fileURLToPath(import.meta.url));
4324
- var webRoot = join11(here, "..", "web");
4357
+ var here = dirname12(fileURLToPath(import.meta.url));
4358
+ var webRoot = join12(here, "..", "web");
4325
4359
  async function main() {
4326
4360
  const command = process.argv[2];
4327
4361
  switch (command) {
@@ -4414,7 +4448,7 @@ async function cmdDaemon() {
4414
4448
  }
4415
4449
  function cmdInit() {
4416
4450
  const configPath = process.env.BRIDGE_CONFIG ?? defaultConfigPath();
4417
- const dir = dirname11(configPath);
4451
+ const dir = dirname12(configPath);
4418
4452
  mkdirSync6(dir, { recursive: true });
4419
4453
  if (existsSync9(configPath)) {
4420
4454
  console.log(`\u914D\u7F6E\u5DF2\u5B58\u5728\uFF0C\u672A\u8986\u76D6: ${configPath}`);