claude-codex-wechat 0.1.59 → 0.1.60

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 +71 -25
  2. package/package.json +1 -1
@@ -757,10 +757,23 @@ async function hasClaudeHistoryDisplay(input) {
757
757
  async function getClaudeNativeVersion(input) {
758
758
  const sessionPath = await findRecoverableClaudeSessionPath(input.sessionId, input.env ?? process.env);
759
759
  if (!sessionPath) return null;
760
- const metadata = await stat2(sessionPath).catch(() => null);
761
- if (!metadata?.isFile()) return null;
760
+ const content = await readFile2(sessionPath, "utf8").catch(() => null);
761
+ if (content === null) return null;
762
+ let count = 0;
763
+ let lastUuid = "";
764
+ for (const line of content.split(/\r?\n/)) {
765
+ if (!line.trim()) continue;
766
+ try {
767
+ const record = JSON.parse(line);
768
+ if ((record.type === "user" || record.type === "assistant") && typeof record.uuid === "string") {
769
+ count += 1;
770
+ lastUuid = record.uuid;
771
+ }
772
+ } catch {
773
+ }
774
+ }
762
775
  return {
763
- fingerprint: `claude:${input.sessionId}:${Math.trunc(metadata.mtimeMs)}:${metadata.size}`,
776
+ fingerprint: `claude:${input.sessionId}:conv:${count}:${lastUuid}`,
764
777
  observedAt: Date.now()
765
778
  };
766
779
  }
@@ -1017,10 +1030,23 @@ async function findRecoverableCodexSessionPath(sessionId, env = process.env) {
1017
1030
  async function getCodexNativeVersion(input) {
1018
1031
  const sessionPath = await findRecoverableCodexSessionPath(input.sessionId, input.env ?? process.env);
1019
1032
  if (!sessionPath) return null;
1020
- const metadata = await stat3(sessionPath).catch(() => null);
1021
- if (!metadata?.isFile()) return null;
1033
+ const content = await readFile3(sessionPath, "utf8").catch(() => null);
1034
+ if (content === null) return null;
1035
+ let count = 0;
1036
+ let lastTimestamp = "";
1037
+ for (const line of content.split(/\r?\n/)) {
1038
+ if (!line.trim()) continue;
1039
+ try {
1040
+ const record = JSON.parse(line);
1041
+ if (record.type === "response_item") {
1042
+ count += 1;
1043
+ lastTimestamp = typeof record.timestamp === "string" ? record.timestamp : "";
1044
+ }
1045
+ } catch {
1046
+ }
1047
+ }
1022
1048
  return {
1023
- fingerprint: `codex:${input.sessionId}:${Math.trunc(metadata.mtimeMs)}:${metadata.size}`,
1049
+ fingerprint: `codex:${input.sessionId}:conv:${count}:${lastTimestamp}`,
1024
1050
  observedAt: Date.now()
1025
1051
  };
1026
1052
  }
@@ -4617,11 +4643,10 @@ var MessageRouter = class _MessageRouter {
4617
4643
  if ((this.latestMutatingSeq.get(message.chatId) ?? 0) > seq) {
4618
4644
  return { status: "accepted" };
4619
4645
  }
4620
- const chatText = this.resolveChoiceReply(message.chatId, command.text);
4621
- if (await this.maybeSteer(message.chatId, chatText)) {
4646
+ if (await this.maybeSteer(message.chatId, command.text)) {
4622
4647
  return { status: "accepted" };
4623
4648
  }
4624
- await this.runExclusive(() => this.runChatGeneration(message, user, chatText, seq));
4649
+ await this.runExclusive(() => this.runChatGeneration(message, user, command.text, seq));
4625
4650
  return { status: "accepted" };
4626
4651
  }
4627
4652
  // 消费一次上一轮暂存的 AskUserQuestion 选项:纯序号回复翻译成对应选项文字,
@@ -4643,7 +4668,7 @@ var MessageRouter = class _MessageRouter {
4643
4668
  if (!active) return Promise.resolve(false);
4644
4669
  const provider = this.providers.get(active.providerId);
4645
4670
  if (!provider?.steerSession) return Promise.resolve(false);
4646
- return provider.steerSession(active.bridgeSessionId, text).then(() => true);
4671
+ return provider.steerSession(active.bridgeSessionId, this.resolveChoiceReply(chatId, text)).then(() => true);
4647
4672
  }
4648
4673
  // Serialize session-mutating work onto one global chain. The chain is updated
4649
4674
  // synchronously (no await before the assignment) so two non-blocking channel
@@ -4687,6 +4712,17 @@ var MessageRouter = class _MessageRouter {
4687
4712
  }).catch(() => null);
4688
4713
  if (!version || !session.lastSeenNativeFingerprint) return { ok: true };
4689
4714
  if (version.fingerprint === session.lastSeenNativeFingerprint) return { ok: true };
4715
+ if (LEGACY_NATIVE_FINGERPRINT.test(session.lastSeenNativeFingerprint)) {
4716
+ this.conversation.update({ lastSeenNativeFingerprint: version.fingerprint }, session.id);
4717
+ return { ok: true };
4718
+ }
4719
+ if (provider.attachSession) {
4720
+ try {
4721
+ await this.reattachSession(session, provider);
4722
+ return { ok: true };
4723
+ } catch {
4724
+ }
4725
+ }
4690
4726
  this.conversation.update({
4691
4727
  staleReason: "native_advanced_elsewhere",
4692
4728
  lastActivityAt: Date.now()
@@ -4696,6 +4732,27 @@ var MessageRouter = class _MessageRouter {
4696
4732
  message: "\u8BE5\u4F1A\u8BDD\u5DF2\u5728\u53E6\u4E00\u7AEF\u7EE7\u7EED\uFF0C\u5F53\u524D\u6865\u63A5\u72B6\u6001\u5DF2\u8FC7\u671F\u3002\u8BF7\u5148 /reload \u540E\u518D\u7EE7\u7EED\u3002"
4697
4733
  };
4698
4734
  }
4735
+ // 回收旧子进程并以 resume 方式重新挂载同一原生会话,使其加载另一端追加的最新历史。
4736
+ async reattachSession(current, provider) {
4737
+ if (!current.providerSessionId || !provider.attachSession) return;
4738
+ for (const [chatId, pending] of this.pendingChoices) {
4739
+ if (pending.sessionId === current.id) this.pendingChoices.delete(chatId);
4740
+ }
4741
+ this.recycleProviderProcess(current);
4742
+ const reattached = await provider.attachSession({
4743
+ candidateId: current.providerSessionId,
4744
+ bridgeSessionId: current.id,
4745
+ cwd: current.cwd
4746
+ });
4747
+ this.conversation.update({
4748
+ providerSessionId: reattached.providerSessionId ?? current.providerSessionId,
4749
+ status: reattached.status,
4750
+ lastSeenNativeFingerprint: void 0,
4751
+ lastReloadedAt: Date.now(),
4752
+ staleReason: void 0,
4753
+ lastActivityAt: Date.now()
4754
+ }, current.id);
4755
+ }
4699
4756
  async refreshNativeFingerprint(session, provider) {
4700
4757
  if (!session.providerSessionId || !provider.getNativeVersion) return;
4701
4758
  const version = await provider.getNativeVersion({
@@ -4709,7 +4766,7 @@ var MessageRouter = class _MessageRouter {
4709
4766
  lastActivityAt: Date.now()
4710
4767
  }, session.id);
4711
4768
  }
4712
- async runChatGeneration(message, user, text, seq) {
4769
+ async runChatGeneration(message, user, rawText, seq) {
4713
4770
  const superseded = () => (this.latestMutatingSeq.get(message.chatId) ?? 0) > seq;
4714
4771
  if (superseded()) return;
4715
4772
  const sessionResumeTitle = buildSessionBridgeName({
@@ -4765,6 +4822,7 @@ var MessageRouter = class _MessageRouter {
4765
4822
  await this.sendToChat({ chatId: message.chatId, kind: "status", text: freshness.message });
4766
4823
  return;
4767
4824
  }
4825
+ const text = this.resolveChoiceReply(message.chatId, rawText);
4768
4826
  const genId = ++this.generationSeq;
4769
4827
  let abortGeneration;
4770
4828
  const aborted = new Promise((resolve3) => {
@@ -4912,20 +4970,7 @@ var MessageRouter = class _MessageRouter {
4912
4970
  return;
4913
4971
  }
4914
4972
  await this.preemptActiveGeneration(chatId);
4915
- this.recycleProviderProcess(current);
4916
- const reattached = await provider.attachSession({
4917
- candidateId: current.providerSessionId,
4918
- bridgeSessionId: current.id,
4919
- cwd: current.cwd
4920
- });
4921
- this.conversation.update({
4922
- providerSessionId: reattached.providerSessionId ?? current.providerSessionId,
4923
- status: reattached.status,
4924
- lastSeenNativeFingerprint: void 0,
4925
- lastReloadedAt: Date.now(),
4926
- staleReason: void 0,
4927
- lastActivityAt: Date.now()
4928
- }, current.id);
4973
+ await this.reattachSession(current, provider);
4929
4974
  await this.sendToChat({ chatId, kind: "status", text: "\u5DF2\u91CD\u65B0\u52A0\u8F7D\u5F53\u524D\u4F1A\u8BDD\uFF0C\u53EF\u7EE7\u7EED\u5BF9\u8BDD\u3002" });
4930
4975
  return;
4931
4976
  }
@@ -5087,6 +5132,7 @@ var MessageRouter = class _MessageRouter {
5087
5132
  }
5088
5133
  }
5089
5134
  };
5135
+ var LEGACY_NATIVE_FINGERPRINT = /^(claude|codex):[^:]+:\d+:\d+$/;
5090
5136
  function summarizeResumeTitle(text) {
5091
5137
  const normalized = text.replace(/\s+/g, " ").trim();
5092
5138
  if (!normalized) return void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-codex-wechat",
3
- "version": "0.1.59",
3
+ "version": "0.1.60",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.5.0",