claude-codex-wechat 0.1.23 → 0.1.25

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.
Files changed (2) hide show
  1. package/dist/server/cli.js +232 -142
  2. package/package.json +1 -1
@@ -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 existsSync10, readFileSync as readFileSync9 } from "node:fs";
6
- import { dirname as dirname13, join as join13 } from "node:path";
6
+ import { dirname as dirname9, join as join14 } from "node:path";
7
7
  import { fileURLToPath as fileURLToPath2 } 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 dirname11, join as join10 } from "node:path";
15
+ import { dirname as dirname7, join as join11 } from "node:path";
16
16
  import Fastify from "fastify";
17
17
 
18
18
  // src/channels/platforms.ts
@@ -151,10 +151,109 @@ function normalizeWechatConfig(raw, env) {
151
151
  }
152
152
 
153
153
  // src/daemon/configPersistence.ts
154
- import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
154
+ import { readFile, rm } from "node:fs/promises";
155
+ import { randomBytes as randomBytes2 } from "node:crypto";
156
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
157
+
158
+ // src/shared/atomicFile.ts
159
+ import { closeSync, fsyncSync, mkdirSync, openSync, renameSync, unlinkSync, writeSync } from "node:fs";
160
+ import { mkdir, open, readdir, rename, stat, unlink } from "node:fs/promises";
155
161
  import { randomBytes } from "node:crypto";
156
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
157
- import { dirname } from "node:path";
162
+ import { basename, dirname, join as join2 } from "node:path";
163
+ var FILE_MODE = 384;
164
+ function tempPathFor(path) {
165
+ return join2(dirname(path), `.${basename(path)}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`);
166
+ }
167
+ var RENAME_RETRY_CODES = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY"]);
168
+ var MAX_RENAME_RETRIES = 10;
169
+ function isRetriableRenameError(error) {
170
+ if (process.platform !== "win32") return false;
171
+ const code = error?.code ?? "";
172
+ return RENAME_RETRY_CODES.has(code);
173
+ }
174
+ function sleepSync(ms) {
175
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
176
+ }
177
+ function sleep(ms) {
178
+ return new Promise((resolve2) => {
179
+ setTimeout(resolve2, ms);
180
+ });
181
+ }
182
+ function writeFileAtomicSync(path, data) {
183
+ const tmp = tempPathFor(path);
184
+ mkdirSync(dirname(path), { recursive: true });
185
+ try {
186
+ const fd = openSync(tmp, "w", FILE_MODE);
187
+ try {
188
+ writeSync(fd, data, null, "utf8");
189
+ fsyncSync(fd);
190
+ } finally {
191
+ closeSync(fd);
192
+ }
193
+ for (let attempt = 0; ; attempt++) {
194
+ try {
195
+ renameSync(tmp, path);
196
+ return;
197
+ } catch (error) {
198
+ if (attempt >= MAX_RENAME_RETRIES || !isRetriableRenameError(error)) throw error;
199
+ sleepSync((attempt + 1) * 10);
200
+ }
201
+ }
202
+ } catch (error) {
203
+ try {
204
+ unlinkSync(tmp);
205
+ } catch {
206
+ }
207
+ throw error;
208
+ }
209
+ }
210
+ async function writeFileAtomic(path, data) {
211
+ const tmp = tempPathFor(path);
212
+ await mkdir(dirname(path), { recursive: true });
213
+ try {
214
+ const handle = await open(tmp, "w", FILE_MODE);
215
+ try {
216
+ await handle.writeFile(data, "utf8");
217
+ await handle.sync();
218
+ } finally {
219
+ await handle.close();
220
+ }
221
+ for (let attempt = 0; ; attempt++) {
222
+ try {
223
+ await rename(tmp, path);
224
+ return;
225
+ } catch (error) {
226
+ if (attempt >= MAX_RENAME_RETRIES || !isRetriableRenameError(error)) throw error;
227
+ await sleep((attempt + 1) * 10);
228
+ }
229
+ }
230
+ } catch (error) {
231
+ await unlink(tmp).catch(() => void 0);
232
+ throw error;
233
+ }
234
+ }
235
+ async function cleanupStaleTempFiles(targetPath, maxAgeMs = 36e5) {
236
+ const dir = dirname(targetPath);
237
+ const prefix = `.${basename(targetPath)}.`;
238
+ let entries;
239
+ try {
240
+ entries = await readdir(dir);
241
+ } catch {
242
+ return;
243
+ }
244
+ const now = Date.now();
245
+ await Promise.all(entries.map(async (name) => {
246
+ if (!name.startsWith(prefix) || !name.endsWith(".tmp")) return;
247
+ const full = join2(dir, name);
248
+ try {
249
+ const info = await stat(full);
250
+ if (now - info.mtimeMs >= maxAgeMs) await unlink(full);
251
+ } catch {
252
+ }
253
+ }));
254
+ }
255
+
256
+ // src/daemon/configPersistence.ts
158
257
  async function persistWechatCredentialsToConfigFile(input) {
159
258
  const currentConfig = await readConfigFile(input.configPath);
160
259
  const nextConfig = {
@@ -167,9 +266,8 @@ async function persistWechatCredentialsToConfigFile(input) {
167
266
  accountId: input.accountId
168
267
  }
169
268
  };
170
- await mkdir(dirname(input.configPath), { recursive: true });
171
- await writeFile(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
172
- `, "utf8");
269
+ await writeFileAtomic(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
270
+ `);
173
271
  }
174
272
  async function deleteConfigFile(configPath) {
175
273
  try {
@@ -190,9 +288,8 @@ function persistUpdateStatusToConfigFile(input) {
190
288
  ...input.status.lastCheckedAt !== void 0 ? { lastCheckedAt: input.status.lastCheckedAt } : {}
191
289
  }
192
290
  };
193
- mkdirSync(dirname(input.configPath), { recursive: true });
194
- writeFileSync(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
195
- `, "utf8");
291
+ writeFileAtomicSync(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
292
+ `);
196
293
  }
197
294
  async function persistBridgeDefaultsToConfigFile(input) {
198
295
  const currentConfig = await readConfigFile(input.configPath);
@@ -215,9 +312,8 @@ async function persistBridgeDefaultsToConfigFile(input) {
215
312
  }
216
313
  } : {}
217
314
  };
218
- await mkdir(dirname(input.configPath), { recursive: true });
219
- await writeFile(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
220
- `, "utf8");
315
+ await writeFileAtomic(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
316
+ `);
221
317
  }
222
318
  function ensureRelayAuthTokenSync(input) {
223
319
  const currentConfig = readConfigFileSync(input.configPath);
@@ -225,7 +321,7 @@ function ensureRelayAuthTokenSync(input) {
225
321
  const currentRelay = isRecord(currentTunnel?.relay) ? currentTunnel.relay : void 0;
226
322
  const existing = typeof currentRelay?.authToken === "string" && currentRelay.authToken.trim() ? currentRelay.authToken.trim() : "";
227
323
  if (existing) return existing;
228
- const authToken = `clrt_${randomBytes(12).toString("hex")}`;
324
+ const authToken = `clrt_${randomBytes2(12).toString("hex")}`;
229
325
  const nextConfig = {
230
326
  ...currentConfig,
231
327
  tunnel: {
@@ -236,9 +332,8 @@ function ensureRelayAuthTokenSync(input) {
236
332
  }
237
333
  }
238
334
  };
239
- mkdirSync(dirname(input.configPath), { recursive: true });
240
- writeFileSync(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
241
- `, "utf8");
335
+ writeFileAtomicSync(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
336
+ `);
242
337
  return authToken;
243
338
  }
244
339
  async function persistProviderCommandsToConfigFile(input) {
@@ -248,9 +343,8 @@ async function persistProviderCommandsToConfigFile(input) {
248
343
  ...currentConfig,
249
344
  providers: normalizedProviders
250
345
  };
251
- await mkdir(dirname(input.configPath), { recursive: true });
252
- await writeFile(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
253
- `, "utf8");
346
+ await writeFileAtomic(input.configPath, `${JSON.stringify(nextConfig, null, 2)}
347
+ `);
254
348
  }
255
349
  async function readConfigFile(path) {
256
350
  try {
@@ -290,8 +384,7 @@ function normalizeProvidersForPersistence(providers) {
290
384
  }
291
385
 
292
386
  // src/channels/weixin-direct/weixinStateStore.ts
293
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
294
- import { dirname as dirname2 } from "node:path";
387
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
295
388
  var PUSH_QUOTA_LIMIT = 10;
296
389
  var PUSH_WINDOW_MS = 24 * 60 * 60 * 1e3;
297
390
  var FileWeixinStateStore = class {
@@ -397,16 +490,15 @@ var FileWeixinStateStore = class {
397
490
  ...state,
398
491
  bridge: { ...state.bridge ?? {}, weixinChannel: channel }
399
492
  };
400
- mkdirSync2(dirname2(this.configPath), { recursive: true });
401
- writeFileSync2(this.configPath, `${JSON.stringify(next, null, 2)}
402
- `, "utf8");
493
+ writeFileAtomicSync(this.configPath, `${JSON.stringify(next, null, 2)}
494
+ `);
403
495
  }
404
496
  };
405
497
 
406
498
  // src/providers/claude-code/nativeSessions.ts
407
- import { appendFile, mkdir as mkdir2, readdir, readFile as readFile2, stat, writeFile as writeFile2 } from "node:fs/promises";
499
+ import { appendFile, mkdir as mkdir2, readdir as readdir2, readFile as readFile2, stat as stat2, writeFile } from "node:fs/promises";
408
500
  import { homedir as homedir2 } from "node:os";
409
- import { basename, dirname as dirname3, join as join2 } from "node:path";
501
+ import { basename as basename2, dirname as dirname2, join as join3 } from "node:path";
410
502
 
411
503
  // src/session/sessionBridgeTag.ts
412
504
  function buildSessionBridgeName(input) {
@@ -433,27 +525,27 @@ function parseSessionBridgeName(value) {
433
525
 
434
526
  // src/providers/claude-code/nativeSessions.ts
435
527
  function resolveClaudeConfigDir(env = process.env) {
436
- return join2(env.HOME || homedir2(), ".claude");
528
+ return join3(env.HOME || homedir2(), ".claude");
437
529
  }
438
530
  async function listRecoverableClaudeSessions(env = process.env) {
439
- const projectsDir = join2(resolveClaudeConfigDir(env), "projects");
531
+ const projectsDir = join3(resolveClaudeConfigDir(env), "projects");
440
532
  const historyIndex = await readClaudeHistoryIndex(env);
441
533
  const candidates = [];
442
534
  try {
443
- const projectEntries = await readdir(projectsDir, { withFileTypes: true });
535
+ const projectEntries = await readdir2(projectsDir, { withFileTypes: true });
444
536
  for (const entry of projectEntries) {
445
537
  if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
446
- const projectDir = join2(projectsDir, String(entry.name));
447
- const sessionEntries = await readdir(projectDir, { withFileTypes: true }).catch(() => []);
538
+ const projectDir = join3(projectsDir, String(entry.name));
539
+ const sessionEntries = await readdir2(projectDir, { withFileTypes: true }).catch(() => []);
448
540
  for (const sessionEntry of sessionEntries) {
449
541
  if (!sessionEntry.isFile() || sessionEntry.isSymbolicLink()) continue;
450
542
  const fileName = String(sessionEntry.name);
451
543
  if (!fileName.endsWith(".jsonl")) continue;
452
- const filePath = join2(projectDir, fileName);
453
- const metadata = await stat(filePath).catch(() => null);
544
+ const filePath = join3(projectDir, fileName);
545
+ const metadata = await stat2(filePath).catch(() => null);
454
546
  const parsedMeta = await readClaudeSessionMetadata(filePath).catch(() => null);
455
- const historyMeta = historyIndex.get(basename(fileName, ".jsonl"));
456
- const sessionId = basename(fileName, ".jsonl");
547
+ const historyMeta = historyIndex.get(basename2(fileName, ".jsonl"));
548
+ const sessionId = basename2(fileName, ".jsonl");
457
549
  const bridgeTag = historyMeta?.bridgeTag ?? parseSessionBridgeName(parsedMeta?.sessionName);
458
550
  const cwd = parsedMeta?.cwd ?? historyMeta?.project;
459
551
  candidates.push({
@@ -475,14 +567,14 @@ async function listRecoverableClaudeSessions(env = process.env) {
475
567
  async function findRecoverableClaudeSessionPath(sessionId, env = process.env) {
476
568
  const trimmed = sessionId.trim();
477
569
  if (!trimmed || trimmed.includes("/") || trimmed.includes("\\")) return null;
478
- const projectsDir = join2(resolveClaudeConfigDir(env), "projects");
570
+ const projectsDir = join3(resolveClaudeConfigDir(env), "projects");
479
571
  try {
480
- const projectEntries = await readdir(projectsDir, { withFileTypes: true });
572
+ const projectEntries = await readdir2(projectsDir, { withFileTypes: true });
481
573
  for (const entry of projectEntries) {
482
574
  if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
483
- const sessionPath = join2(projectsDir, String(entry.name), `${trimmed}.jsonl`);
575
+ const sessionPath = join3(projectsDir, String(entry.name), `${trimmed}.jsonl`);
484
576
  try {
485
- const metadata = await stat(sessionPath);
577
+ const metadata = await stat2(sessionPath);
486
578
  if (metadata.isFile()) return sessionPath;
487
579
  } catch {
488
580
  }
@@ -528,7 +620,7 @@ async function hasClaudeSessionBridgeMetadata(input) {
528
620
  }
529
621
  async function hasClaudeHistoryDisplay(input) {
530
622
  const env = input.env ?? process.env;
531
- const historyPath = join2(resolveClaudeConfigDir(env), "history.jsonl");
623
+ const historyPath = join3(resolveClaudeConfigDir(env), "history.jsonl");
532
624
  try {
533
625
  const content = await readFile2(historyPath, "utf8");
534
626
  for (const line of content.split(/\r?\n/)) {
@@ -583,7 +675,7 @@ async function readClaudeSessionMetadata(filePath) {
583
675
  return { aiTitle, lastPrompt, sessionName, cwd };
584
676
  }
585
677
  async function readClaudeHistoryIndex(env) {
586
- const historyPath = join2(resolveClaudeConfigDir(env), "history.jsonl");
678
+ const historyPath = join3(resolveClaudeConfigDir(env), "history.jsonl");
587
679
  const index = /* @__PURE__ */ new Map();
588
680
  try {
589
681
  const content = await readFile2(historyPath, "utf8");
@@ -608,7 +700,7 @@ async function readClaudeHistoryIndex(env) {
608
700
  return index;
609
701
  }
610
702
  async function upsertClaudeHistoryDisplay(input) {
611
- const historyPath = join2(resolveClaudeConfigDir(input.env), "history.jsonl");
703
+ const historyPath = join3(resolveClaudeConfigDir(input.env), "history.jsonl");
612
704
  const lines = [];
613
705
  let replaced = false;
614
706
  let changed = false;
@@ -647,8 +739,8 @@ async function upsertClaudeHistoryDisplay(input) {
647
739
  }));
648
740
  }
649
741
  if (!changed) return false;
650
- await mkdir2(dirname3(historyPath), { recursive: true });
651
- await writeFile2(historyPath, `${lines.join("\n")}
742
+ await mkdir2(dirname2(historyPath), { recursive: true });
743
+ await writeFile(historyPath, `${lines.join("\n")}
652
744
  `, "utf8");
653
745
  return true;
654
746
  }
@@ -679,7 +771,7 @@ async function normalizeClaudeSessionFileForResume(sessionPath) {
679
771
  nextLines.push(line);
680
772
  }
681
773
  if (sawSdkCliEntrypoint && !hasPermissionMode) {
682
- const sessionId = basename(sessionPath, ".jsonl");
774
+ const sessionId = basename2(sessionPath, ".jsonl");
683
775
  nextLines.unshift(JSON.stringify({
684
776
  type: "permission-mode",
685
777
  permissionMode: "bypassPermissions",
@@ -688,26 +780,26 @@ async function normalizeClaudeSessionFileForResume(sessionPath) {
688
780
  changed = true;
689
781
  }
690
782
  if (!changed) return false;
691
- await writeFile2(sessionPath, `${nextLines.join("\n")}
783
+ await writeFile(sessionPath, `${nextLines.join("\n")}
692
784
  `, "utf8");
693
785
  return true;
694
786
  }
695
787
 
696
788
  // src/providers/codex/nativeSessions.ts
697
789
  import Database from "better-sqlite3";
698
- import { readdir as readdir2, readFile as readFile3, stat as stat2 } from "node:fs/promises";
790
+ import { readdir as readdir3, readFile as readFile3, stat as stat3 } from "node:fs/promises";
699
791
  import { existsSync as existsSync4 } from "node:fs";
700
792
  import { homedir as homedir3 } from "node:os";
701
- import { basename as basename2, join as join3 } from "node:path";
793
+ import { basename as basename3, join as join4 } from "node:path";
702
794
  function resolveCodexSessionsRoot(env = process.env) {
703
- return join3(env.CODEX_HOME || join3(env.HOME || homedir3(), ".codex"), "sessions");
795
+ return join4(env.CODEX_HOME || join4(env.HOME || homedir3(), ".codex"), "sessions");
704
796
  }
705
797
  function isMatchingCodexRolloutFile(name) {
706
798
  return name.startsWith("rollout-") && name.endsWith(".jsonl");
707
799
  }
708
800
  function extractCodexSessionId(name) {
709
801
  if (!isMatchingCodexRolloutFile(name)) return null;
710
- const withoutExt = basename2(name, ".jsonl");
802
+ const withoutExt = basename3(name, ".jsonl");
711
803
  const match = withoutExt.match(/^rollout-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-(.+)$/);
712
804
  if (!match?.[1]) return null;
713
805
  return match[1];
@@ -719,11 +811,11 @@ async function listRecoverableCodexSessions(env = process.env) {
719
811
  const candidates = [];
720
812
  async function walk(currentDir, depth) {
721
813
  if (depth > 8) return;
722
- const entries = await readdir2(currentDir, { withFileTypes: true }).catch(() => []);
814
+ const entries = await readdir3(currentDir, { withFileTypes: true }).catch(() => []);
723
815
  for (const entry of entries) {
724
816
  if (entry.isSymbolicLink()) continue;
725
817
  const name = String(entry.name);
726
- const path = join3(currentDir, name);
818
+ const path = join4(currentDir, name);
727
819
  if (entry.isDirectory()) {
728
820
  await walk(path, depth + 1);
729
821
  continue;
@@ -755,11 +847,11 @@ async function findRecoverableCodexSessionPath(sessionId, env = process.env) {
755
847
  if (!trimmed || trimmed.includes("/") || trimmed.includes("\\")) return null;
756
848
  async function walk(currentDir, depth) {
757
849
  if (depth > 8) return null;
758
- const entries = await readdir2(currentDir, { withFileTypes: true }).catch(() => []);
850
+ const entries = await readdir3(currentDir, { withFileTypes: true }).catch(() => []);
759
851
  for (const entry of entries) {
760
852
  if (entry.isSymbolicLink()) continue;
761
853
  const name = String(entry.name);
762
- const path = join3(currentDir, name);
854
+ const path = join4(currentDir, name);
763
855
  if (entry.isDirectory()) {
764
856
  const found = await walk(path, depth + 1);
765
857
  if (found) return found;
@@ -773,7 +865,7 @@ async function findRecoverableCodexSessionPath(sessionId, env = process.env) {
773
865
  return await walk(root, 0);
774
866
  }
775
867
  async function readCodexSessionIndex(env) {
776
- const indexPath = join3(env.CODEX_HOME || join3(env.HOME || homedir3(), ".codex"), "session_index.jsonl");
868
+ const indexPath = join4(env.CODEX_HOME || join4(env.HOME || homedir3(), ".codex"), "session_index.jsonl");
777
869
  const index = /* @__PURE__ */ new Map();
778
870
  try {
779
871
  const content = await readFile3(indexPath, "utf8");
@@ -796,7 +888,7 @@ async function readCodexSessionIndex(env) {
796
888
  return index;
797
889
  }
798
890
  function readCodexThreadMetadata(env) {
799
- const dbPath = join3(env.CODEX_HOME || join3(env.HOME || homedir3(), ".codex"), "state_5.sqlite");
891
+ const dbPath = join4(env.CODEX_HOME || join4(env.HOME || homedir3(), ".codex"), "state_5.sqlite");
800
892
  const metadata = /* @__PURE__ */ new Map();
801
893
  if (!existsSync4(dbPath)) return metadata;
802
894
  let db = null;
@@ -841,7 +933,7 @@ async function readCodexSessionMeta(filePath) {
841
933
  } catch {
842
934
  }
843
935
  }
844
- const metadata = await stat2(filePath).catch(() => null);
936
+ const metadata = await stat3(filePath).catch(() => null);
845
937
  return {
846
938
  cwd,
847
939
  lastActivityAt: metadata ? Math.trunc(metadata.mtimeMs) : void 0
@@ -855,11 +947,11 @@ async function readCodexSessionMeta(filePath) {
855
947
  import { nanoid } from "nanoid";
856
948
 
857
949
  // src/providers/codex/sessionIndex.ts
858
- import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
950
+ import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
859
951
  import { homedir as homedir4 } from "node:os";
860
- import { dirname as dirname4, join as join4 } from "node:path";
952
+ import { dirname as dirname3, join as join5 } from "node:path";
861
953
  function resolveCodexIndexPath(env = process.env) {
862
- return join4(env.CODEX_HOME || join4(env.HOME || homedir4(), ".codex"), "session_index.jsonl");
954
+ return join5(env.CODEX_HOME || join5(env.HOME || homedir4(), ".codex"), "session_index.jsonl");
863
955
  }
864
956
  async function upsertCodexSessionIndexEntry(input, env = process.env) {
865
957
  const indexPath = resolveCodexIndexPath(env);
@@ -895,19 +987,19 @@ async function upsertCodexSessionIndexEntry(input, env = process.env) {
895
987
  updated_at: input.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
896
988
  }));
897
989
  }
898
- await mkdir3(dirname4(indexPath), { recursive: true });
899
- await writeFile3(indexPath, `${lines.join("\n")}
990
+ await mkdir3(dirname3(indexPath), { recursive: true });
991
+ await writeFile2(indexPath, `${lines.join("\n")}
900
992
  `, "utf8");
901
993
  }
902
994
 
903
995
  // src/providers/codex/nativeThreads.ts
904
996
  import Database2 from "better-sqlite3";
905
997
  import { existsSync as existsSync5 } from "node:fs";
906
- import { readFile as readFile5, writeFile as writeFile4 } from "node:fs/promises";
998
+ import { readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
907
999
  import { homedir as homedir5 } from "node:os";
908
- import { join as join5 } from "node:path";
1000
+ import { join as join6 } from "node:path";
909
1001
  function resolveCodexStateDbPath(env = process.env) {
910
- return join5(env.CODEX_HOME || join5(env.HOME || homedir5(), ".codex"), "state_5.sqlite");
1002
+ return join6(env.CODEX_HOME || join6(env.HOME || homedir5(), ".codex"), "state_5.sqlite");
911
1003
  }
912
1004
  async function syncCodexThreadForResume(input) {
913
1005
  const env = input.env ?? process.env;
@@ -963,7 +1055,7 @@ async function syncCodexRolloutSessionMeta(rolloutPath) {
963
1055
  payload.originator = "codex-tui";
964
1056
  first.payload = payload;
965
1057
  lines[0] = JSON.stringify(first);
966
- await writeFile4(rolloutPath, lines.join("\n"), "utf8");
1058
+ await writeFile3(rolloutPath, lines.join("\n"), "utf8");
967
1059
  } catch {
968
1060
  }
969
1061
  }
@@ -1568,9 +1660,9 @@ function normalizeSettings(input, defaultWorkspace) {
1568
1660
  }
1569
1661
 
1570
1662
  // src/admin/fsBrowseRoutes.ts
1571
- import { readdir as readdir3 } from "node:fs/promises";
1663
+ import { readdir as readdir4 } from "node:fs/promises";
1572
1664
  import { homedir as homedir7 } from "node:os";
1573
- import { dirname as dirname5, join as join6, resolve } from "node:path";
1665
+ import { dirname as dirname4, join as join7, resolve } from "node:path";
1574
1666
 
1575
1667
  // src/shared/expandTilde.ts
1576
1668
  import { homedir as homedir6 } from "node:os";
@@ -1591,13 +1683,13 @@ function registerFsBrowseRoutes(input) {
1591
1683
  const isOnKeepChain = (path) => keep !== null && (keep === path || keep.startsWith(path + "/"));
1592
1684
  let dirents;
1593
1685
  try {
1594
- dirents = await readdir3(target, { withFileTypes: true });
1686
+ dirents = await readdir4(target, { withFileTypes: true });
1595
1687
  } catch {
1596
1688
  reply.code(400);
1597
1689
  return { error: "cannot_read_directory", path: target };
1598
1690
  }
1599
- 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));
1600
- const parent = dirname5(target);
1691
+ const entries = dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => ({ name: dirent.name, path: join7(target, dirent.name), isDirectory: true })).filter((entry) => !entry.name.startsWith(".") || isOnKeepChain(entry.path)).sort((a, b) => a.name.localeCompare(b.name));
1692
+ const parent = dirname4(target);
1601
1693
  const isRoot = parent === target;
1602
1694
  const listing = {
1603
1695
  path: target,
@@ -1778,7 +1870,7 @@ var WeixinDirectApiClient = class {
1778
1870
 
1779
1871
  // src/channels/weixin-direct/adapter.ts
1780
1872
  import { setTimeout as delay2 } from "node:timers/promises";
1781
- import { join as join7 } from "node:path";
1873
+ import { join as join8 } from "node:path";
1782
1874
 
1783
1875
  // src/channels/weixin-direct/typingController.ts
1784
1876
  var CONFIG_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
@@ -2043,7 +2135,7 @@ var WeixinDirectAdapter = class _WeixinDirectAdapter {
2043
2135
  continue;
2044
2136
  }
2045
2137
  const { ext, mimeType } = mediaExtAndMime(meta);
2046
- const destPath = join7(mediaDir, `${idPrefix}_${i}${ext}`);
2138
+ const destPath = join8(mediaDir, `${idPrefix}_${i}${ext}`);
2047
2139
  const maxBytes = meta.kind === "video" ? VIDEO_MAX_BYTES : void 0;
2048
2140
  const result = await downloader.download(meta.media ?? {}, { destPath, aeskeyOverride: meta.aeskey, maxBytes });
2049
2141
  if (result.ok) {
@@ -2103,8 +2195,8 @@ function chunkText(text, limit) {
2103
2195
  }
2104
2196
 
2105
2197
  // src/channels/weixin-direct/mediaDownloader.ts
2106
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
2107
- import { dirname as dirname6 } from "node:path";
2198
+ import { mkdirSync as mkdirSync2, writeFileSync } from "node:fs";
2199
+ import { dirname as dirname5 } from "node:path";
2108
2200
 
2109
2201
  // src/channels/weixin-direct/mediaCrypto.ts
2110
2202
  import { createDecipheriv } from "node:crypto";
@@ -2167,8 +2259,8 @@ var WeixinMediaDownloader = class {
2167
2259
  } catch {
2168
2260
  return { ok: false, reason: "decrypt_failed" };
2169
2261
  }
2170
- mkdirSync3(dirname6(input.destPath), { recursive: true });
2171
- writeFileSync3(input.destPath, plaintext);
2262
+ mkdirSync2(dirname5(input.destPath), { recursive: true });
2263
+ writeFileSync(input.destPath, plaintext);
2172
2264
  return { ok: true, localPath: input.destPath, bytes: plaintext.length };
2173
2265
  }
2174
2266
  };
@@ -2354,7 +2446,7 @@ import { randomUUID as randomUUID2 } from "node:crypto";
2354
2446
 
2355
2447
  // src/shared/platform.ts
2356
2448
  import { access, constants } from "node:fs/promises";
2357
- import { delimiter, join as join8 } from "node:path";
2449
+ import { delimiter, join as join9 } from "node:path";
2358
2450
  import { tmpdir } from "node:os";
2359
2451
  import { spawn } from "node:child_process";
2360
2452
  var isWindows = process.platform === "win32";
@@ -2382,7 +2474,7 @@ async function findExecutable(command) {
2382
2474
  const dirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
2383
2475
  for (const dir of dirs) {
2384
2476
  for (const ext of extensions) {
2385
- const candidate = join8(dir, command + ext);
2477
+ const candidate = join9(dir, command + ext);
2386
2478
  if (await isExecutableFile(candidate)) return candidate;
2387
2479
  }
2388
2480
  }
@@ -2405,13 +2497,13 @@ function terminateChild(child, signal = "SIGTERM") {
2405
2497
  }
2406
2498
  }
2407
2499
  function defaultWorkspaceDir() {
2408
- return join8(tmpdir(), "project");
2500
+ return join9(tmpdir(), "project");
2409
2501
  }
2410
2502
  function useShellForCli() {
2411
2503
  return isWindows;
2412
2504
  }
2413
2505
  function statePath(filename) {
2414
- return join8(tmpdir(), filename);
2506
+ return join9(tmpdir(), filename);
2415
2507
  }
2416
2508
 
2417
2509
  // src/providers/claude-code/assistantContent.ts
@@ -3399,8 +3491,7 @@ function buildBridgeCommandHelpMarkdown(input) {
3399
3491
  }
3400
3492
 
3401
3493
  // src/session/currentConversationStore.ts
3402
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
3403
- import { dirname as dirname7 } from "node:path";
3494
+ import { existsSync as existsSync6, readFileSync as readFileSync4 } from "node:fs";
3404
3495
  import { nanoid as nanoid2 } from "nanoid";
3405
3496
  var CurrentConversationStore = class {
3406
3497
  constructor(configPath, defaults) {
@@ -3482,9 +3573,8 @@ var CurrentConversationStore = class {
3482
3573
  this.writeState(state);
3483
3574
  }
3484
3575
  writeState(state) {
3485
- mkdirSync4(dirname7(this.configPath), { recursive: true });
3486
- writeFileSync4(this.configPath, `${JSON.stringify(state, null, 2)}
3487
- `, "utf8");
3576
+ writeFileAtomicSync(this.configPath, `${JSON.stringify(state, null, 2)}
3577
+ `);
3488
3578
  }
3489
3579
  };
3490
3580
 
@@ -4017,8 +4107,7 @@ function composeInboundText(content) {
4017
4107
  }
4018
4108
 
4019
4109
  // src/storage/lastProviderSessionStore.ts
4020
- import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
4021
- import { dirname as dirname8 } from "node:path";
4110
+ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
4022
4111
  var LastProviderSessionStore = class {
4023
4112
  constructor(configPath) {
4024
4113
  this.configPath = configPath;
@@ -4049,15 +4138,13 @@ var LastProviderSessionStore = class {
4049
4138
  return raw && typeof raw === "object" ? raw : {};
4050
4139
  }
4051
4140
  writeState(state) {
4052
- mkdirSync5(dirname8(this.configPath), { recursive: true });
4053
- writeFileSync5(this.configPath, `${JSON.stringify(state, null, 2)}
4054
- `, "utf8");
4141
+ writeFileAtomicSync(this.configPath, `${JSON.stringify(state, null, 2)}
4142
+ `);
4055
4143
  }
4056
4144
  };
4057
4145
 
4058
4146
  // src/storage/runtimeUserStore.ts
4059
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync8 } from "node:fs";
4060
- import { dirname as dirname9 } from "node:path";
4147
+ import { readFileSync as readFileSync6, existsSync as existsSync8 } from "node:fs";
4061
4148
  import { nanoid as nanoid3 } from "nanoid";
4062
4149
  var RuntimeUserStore = class {
4063
4150
  constructor(configPath) {
@@ -4122,9 +4209,8 @@ var RuntimeUserStore = class {
4122
4209
  return raw && typeof raw === "object" ? raw : {};
4123
4210
  }
4124
4211
  writeState(state) {
4125
- mkdirSync6(dirname9(this.configPath), { recursive: true });
4126
- writeFileSync6(this.configPath, `${JSON.stringify(state, null, 2)}
4127
- `, "utf8");
4212
+ writeFileAtomicSync(this.configPath, `${JSON.stringify(state, null, 2)}
4213
+ `);
4128
4214
  }
4129
4215
  };
4130
4216
 
@@ -4452,12 +4538,12 @@ var RelayTunnelRouter = class {
4452
4538
 
4453
4539
  // src/shared/version.ts
4454
4540
  import { readFileSync as readFileSync7 } from "node:fs";
4455
- import { dirname as dirname10, join as join9 } from "node:path";
4541
+ import { dirname as dirname6, join as join10 } from "node:path";
4456
4542
  import { fileURLToPath } from "node:url";
4457
4543
  function readClientVersion() {
4458
4544
  try {
4459
- const here2 = dirname10(fileURLToPath(import.meta.url));
4460
- const pkg = JSON.parse(readFileSync7(join9(here2, "..", "..", "package.json"), "utf8"));
4545
+ const here2 = dirname6(fileURLToPath(import.meta.url));
4546
+ const pkg = JSON.parse(readFileSync7(join10(here2, "..", "..", "package.json"), "utf8"));
4461
4547
  return typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
4462
4548
  } catch {
4463
4549
  return "0.0.0";
@@ -4476,7 +4562,7 @@ function readUpdateStatusBestEffort(configPath) {
4476
4562
  function createDaemonServer(options = {}) {
4477
4563
  const app = Fastify({ logger: true });
4478
4564
  const events = new BridgeEventHub();
4479
- const configPath = options.configPath ?? process.env.BRIDGE_CONFIG ?? join10(mkdtempSync(join10(tmpdir2(), "claude-codex-wechat-")), "config.json");
4565
+ const configPath = options.configPath ?? process.env.BRIDGE_CONFIG ?? join11(mkdtempSync(join11(tmpdir2(), "claude-codex-wechat-")), "config.json");
4480
4566
  const persistedConfig = loadBridgeConfig(configPath);
4481
4567
  const bridgeDefaults = {
4482
4568
  defaultProvider: options.bridgeDefaults?.defaultProvider ?? persistedConfig.bridge?.defaultProvider ?? "claude-code",
@@ -4533,7 +4619,7 @@ function createDaemonServer(options = {}) {
4533
4619
  });
4534
4620
  }
4535
4621
  const weixinStateStore = configPath ? new FileWeixinStateStore(configPath) : void 0;
4536
- const weixinMediaDir = configPath ? join10(dirname11(configPath), "media") : void 0;
4622
+ const weixinMediaDir = configPath ? join11(dirname7(configPath), "media") : void 0;
4537
4623
  const managedWechatChannel = options.channel ? null : new ManagedWeixinDirectAdapter(options.wechat, weixinStateStore, weixinMediaDir);
4538
4624
  const channel = options.channel ?? managedWechatChannel;
4539
4625
  const weixinOutboundGate = managedWechatChannel && weixinStateStore ? new WeixinOutboundGate({
@@ -4770,6 +4856,7 @@ async function startDaemon(options) {
4770
4856
  const port = options.port ?? Number(process.env.BRIDGE_PORT ?? 8787);
4771
4857
  const host = options.host ?? "0.0.0.0";
4772
4858
  const configPath = options.configPath ?? process.env.BRIDGE_CONFIG ?? defaultConfigPath();
4859
+ await cleanupStaleTempFiles(configPath).catch(() => void 0);
4773
4860
  const config = loadBridgeConfig(configPath);
4774
4861
  const providerCommands = await resolveProviderCommands(config.providers);
4775
4862
  await persistProviderCommandsToConfigFile({
@@ -4824,7 +4911,7 @@ async function resolveProviderCommands(providers) {
4824
4911
 
4825
4912
  // src/daemon/staticFrontend.ts
4826
4913
  import { readFileSync as readFileSync8 } from "node:fs";
4827
- import { join as join11 } from "node:path";
4914
+ import { join as join12 } from "node:path";
4828
4915
  import fastifyStatic from "@fastify/static";
4829
4916
  function attachStaticFrontend(webRoot2) {
4830
4917
  return async (app) => {
@@ -4832,7 +4919,7 @@ function attachStaticFrontend(webRoot2) {
4832
4919
  root: webRoot2,
4833
4920
  wildcard: false
4834
4921
  });
4835
- const indexHtml = readFileSync8(join11(webRoot2, "index.html"), "utf8");
4922
+ const indexHtml = readFileSync8(join12(webRoot2, "index.html"), "utf8");
4836
4923
  app.setNotFoundHandler((request, reply) => {
4837
4924
  if (request.url.startsWith("/api")) {
4838
4925
  reply.code(404).send({ error: "not_found" });
@@ -4844,10 +4931,10 @@ function attachStaticFrontend(webRoot2) {
4844
4931
  }
4845
4932
 
4846
4933
  // src/daemon/service.ts
4847
- import { existsSync as existsSync9, statSync, openSync, closeSync, watchFile } from "node:fs";
4848
- import { mkdir as mkdir4, readFile as readFile6, rm as rm2, writeFile as writeFile5 } from "node:fs/promises";
4934
+ import { existsSync as existsSync9, statSync, openSync as openSync2, closeSync as closeSync2, watchFile } from "node:fs";
4935
+ import { mkdir as mkdir4, readFile as readFile6, rm as rm2, writeFile as writeFile4 } from "node:fs/promises";
4849
4936
  import { homedir as homedir8 } from "node:os";
4850
- import { dirname as dirname12, join as join12 } from "node:path";
4937
+ import { dirname as dirname8, join as join13 } from "node:path";
4851
4938
  import { createReadStream } from "node:fs";
4852
4939
  import { execFile, spawn as spawn7 } from "node:child_process";
4853
4940
  import { createInterface } from "node:readline";
@@ -4856,19 +4943,20 @@ var execFileAsync = promisify(execFile);
4856
4943
  async function installService(context) {
4857
4944
  if (process.platform === "darwin") {
4858
4945
  const spec = buildLaunchdSpec(context);
4859
- await mkdir4(dirname12(spec.plistPath), { recursive: true });
4860
- await mkdir4(dirname12(spec.stdoutPath), { recursive: true });
4861
- await writeFile5(spec.plistPath, renderLaunchdPlist(spec), "utf8");
4862
- await runLaunchctl(["unload", spec.plistPath]).catch(() => void 0);
4863
- await runLaunchctl(["load", spec.plistPath]);
4864
- await runLaunchctl(["kickstart", "-k", `gui/${process.getuid?.() ?? 0}/${spec.label}`]);
4946
+ await mkdir4(dirname8(spec.plistPath), { recursive: true });
4947
+ await mkdir4(dirname8(spec.stdoutPath), { recursive: true });
4948
+ await writeFile4(spec.plistPath, renderLaunchdPlist(spec), "utf8");
4949
+ const guiDomain = `gui/${process.getuid?.() ?? 0}`;
4950
+ await runLaunchctl(["bootout", guiDomain, spec.plistPath]).catch(() => void 0);
4951
+ await runLaunchctl(["bootstrap", guiDomain, spec.plistPath]);
4952
+ await runLaunchctl(["kickstart", "-k", `${guiDomain}/${spec.label}`]);
4865
4953
  return await readServiceStatus(context);
4866
4954
  }
4867
4955
  if (process.platform === "linux") {
4868
4956
  const spec = buildSystemdUserSpec(context);
4869
- await mkdir4(dirname12(spec.unitPath), { recursive: true });
4870
- await mkdir4(dirname12(spec.stdoutPath), { recursive: true });
4871
- await writeFile5(spec.unitPath, renderSystemdUnit(spec), "utf8");
4957
+ await mkdir4(dirname8(spec.unitPath), { recursive: true });
4958
+ await mkdir4(dirname8(spec.stdoutPath), { recursive: true });
4959
+ await writeFile4(spec.unitPath, renderSystemdUnit(spec), "utf8");
4872
4960
  await runSystemctl(["--user", "daemon-reload"]);
4873
4961
  await runSystemctl(["--user", "enable", "--now", spec.unitName]);
4874
4962
  return await readServiceStatus(context);
@@ -4882,8 +4970,9 @@ async function startService(context) {
4882
4970
  if (process.platform === "darwin") {
4883
4971
  const spec = buildLaunchdSpec(context);
4884
4972
  await ensureFileExists(spec.plistPath, "service_not_installed");
4885
- await runLaunchctl(["load", spec.plistPath]).catch(() => void 0);
4886
- await runLaunchctl(["kickstart", "-k", `gui/${process.getuid?.() ?? 0}/${spec.label}`]);
4973
+ const guiDomain = `gui/${process.getuid?.() ?? 0}`;
4974
+ await runLaunchctl(["bootstrap", guiDomain, spec.plistPath]).catch(() => void 0);
4975
+ await runLaunchctl(["kickstart", "-k", `${guiDomain}/${spec.label}`]);
4887
4976
  return await readServiceStatus(context);
4888
4977
  }
4889
4978
  if (process.platform === "linux") {
@@ -4954,8 +5043,9 @@ async function restartService(context) {
4954
5043
  if (process.platform === "darwin") {
4955
5044
  const spec = buildLaunchdSpec(context);
4956
5045
  await ensureFileExists(spec.plistPath, "service_not_installed");
4957
- await runLaunchctl(["load", spec.plistPath]).catch(() => void 0);
4958
- await runLaunchctl(["kickstart", "-k", `gui/${process.getuid?.() ?? 0}/${spec.label}`]);
5046
+ const guiDomain = `gui/${process.getuid?.() ?? 0}`;
5047
+ await runLaunchctl(["bootstrap", guiDomain, spec.plistPath]).catch(() => void 0);
5048
+ await runLaunchctl(["kickstart", "-k", `${guiDomain}/${spec.label}`]);
4959
5049
  return await readServiceStatus(context);
4960
5050
  }
4961
5051
  if (process.platform === "linux") {
@@ -5034,37 +5124,37 @@ async function readServiceStatus(context) {
5034
5124
  throw new Error("service_status_not_supported_on_this_platform");
5035
5125
  }
5036
5126
  function buildLaunchdSpec(context) {
5037
- const stateDir = join12(homedir8(), ".claude-codex-wechat");
5127
+ const stateDir = join13(homedir8(), ".claude-codex-wechat");
5038
5128
  return {
5039
5129
  label: "com.claude-codex-wechat",
5040
- plistPath: join12(homedir8(), "Library", "LaunchAgents", "com.claude-codex-wechat.plist"),
5130
+ plistPath: join13(homedir8(), "Library", "LaunchAgents", "com.claude-codex-wechat.plist"),
5041
5131
  programArgs: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "__daemon"],
5042
5132
  workingDirectory: homedir8(),
5043
- stdoutPath: join12(stateDir, "logs", "service.stdout.log"),
5044
- stderrPath: join12(stateDir, "logs", "service.stderr.log"),
5133
+ stdoutPath: join13(stateDir, "logs", "service.stdout.log"),
5134
+ stderrPath: join13(stateDir, "logs", "service.stderr.log"),
5045
5135
  environment: buildServiceEnvironment(context)
5046
5136
  };
5047
5137
  }
5048
5138
  function buildSystemdUserSpec(context) {
5049
- const stateDir = join12(homedir8(), ".claude-codex-wechat");
5139
+ const stateDir = join13(homedir8(), ".claude-codex-wechat");
5050
5140
  return {
5051
5141
  unitName: "claude-codex-wechat.service",
5052
- unitPath: join12(homedir8(), ".config", "systemd", "user", "claude-codex-wechat.service"),
5142
+ unitPath: join13(homedir8(), ".config", "systemd", "user", "claude-codex-wechat.service"),
5053
5143
  execStart: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "__daemon"],
5054
5144
  workingDirectory: homedir8(),
5055
- stdoutPath: join12(stateDir, "logs", "service.stdout.log"),
5056
- stderrPath: join12(stateDir, "logs", "service.stderr.log"),
5145
+ stdoutPath: join13(stateDir, "logs", "service.stdout.log"),
5146
+ stderrPath: join13(stateDir, "logs", "service.stderr.log"),
5057
5147
  environment: buildServiceEnvironment(context)
5058
5148
  };
5059
5149
  }
5060
5150
  function buildProcessSpec(context) {
5061
- const stateDir = join12(homedir8(), ".claude-codex-wechat");
5151
+ const stateDir = join13(homedir8(), ".claude-codex-wechat");
5062
5152
  return {
5063
- pidPath: join12(stateDir, "service.pid"),
5153
+ pidPath: join13(stateDir, "service.pid"),
5064
5154
  command: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "__daemon"],
5065
5155
  workingDirectory: homedir8(),
5066
- stdoutPath: join12(stateDir, "logs", "service.stdout.log"),
5067
- stderrPath: join12(stateDir, "logs", "service.stderr.log"),
5156
+ stdoutPath: join13(stateDir, "logs", "service.stdout.log"),
5157
+ stderrPath: join13(stateDir, "logs", "service.stderr.log"),
5068
5158
  environment: buildServiceEnvironment(context)
5069
5159
  };
5070
5160
  }
@@ -5185,8 +5275,8 @@ async function readPidFile(pidPath) {
5185
5275
  }
5186
5276
  }
5187
5277
  async function writePidFile(pidPath, pid) {
5188
- await mkdir4(dirname12(pidPath), { recursive: true });
5189
- await writeFile5(pidPath, `${pid}
5278
+ await mkdir4(dirname8(pidPath), { recursive: true });
5279
+ await writeFile4(pidPath, `${pid}
5190
5280
  `, "utf8");
5191
5281
  }
5192
5282
  async function removePidFile(pidPath) {
@@ -5200,9 +5290,9 @@ async function killPid(pid) {
5200
5290
  process.kill(pid, "SIGTERM");
5201
5291
  }
5202
5292
  async function spawnDetachedDaemon(spec) {
5203
- await mkdir4(dirname12(spec.stdoutPath), { recursive: true });
5204
- const outFd = openSync(spec.stdoutPath, "a");
5205
- const errFd = openSync(spec.stderrPath, "a");
5293
+ await mkdir4(dirname8(spec.stdoutPath), { recursive: true });
5294
+ const outFd = openSync2(spec.stdoutPath, "a");
5295
+ const errFd = openSync2(spec.stderrPath, "a");
5206
5296
  try {
5207
5297
  const [command, ...args] = spec.command;
5208
5298
  const child = spawn7(command, args, {
@@ -5221,8 +5311,8 @@ async function spawnDetachedDaemon(spec) {
5221
5311
  child.unref();
5222
5312
  return child.pid;
5223
5313
  } finally {
5224
- closeSync(outFd);
5225
- closeSync(errFd);
5314
+ closeSync2(outFd);
5315
+ closeSync2(errFd);
5226
5316
  }
5227
5317
  }
5228
5318
  async function ensureFileExists(path, errorCode) {
@@ -5286,8 +5376,8 @@ function fileSizeHint(path) {
5286
5376
  }
5287
5377
 
5288
5378
  // src/cli.ts
5289
- var here = dirname13(fileURLToPath2(import.meta.url));
5290
- var webRoot = join13(here, "..", "web");
5379
+ var here = dirname9(fileURLToPath2(import.meta.url));
5380
+ var webRoot = join14(here, "..", "web");
5291
5381
  async function main() {
5292
5382
  const command = process.argv[2];
5293
5383
  switch (command) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-codex-wechat",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.5.0",