claude-bridge-cli 2.0.18 → 2.0.20

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/lib/bridge.js +34 -3
  2. package/package.json +1 -1
package/lib/bridge.js CHANGED
@@ -443,7 +443,7 @@ function searchSessions(query, limit = 30) {
443
443
  const snippetEnd = Math.min(content.length, idx + q.length + 80);
444
444
  const snippet = content.slice(snippetStart, snippetEnd).replace(/\n/g, " ").trim();
445
445
 
446
- let aiTitle = "", msgCount = 0, realCwd = "";
446
+ let aiTitle = "", customTitle = "", msgCount = 0, realCwd = "";
447
447
  try {
448
448
  const lines = content.split("\n").filter(Boolean);
449
449
  msgCount = lines.length;
@@ -454,11 +454,18 @@ function searchSessions(query, limit = 30) {
454
454
  if (obj.type === "result" && obj.result?.metadata?.title?.value) {
455
455
  aiTitle = obj.result.metadata.title.value;
456
456
  }
457
- if (obj.type === "ai-title" && obj.title) aiTitle = obj.title;
458
- if (obj.type === "custom-title" && obj.title) aiTitle = obj.title;
457
+ // The records carry `aiTitle` / `customTitle` NOT `title`. Reading
458
+ // obj.title (as this did) matched nothing, so every search result
459
+ // rendered untitled and renames were invisible here even though the
460
+ // session LIST resolved them correctly. Track the two separately:
461
+ // a user rename must WIN, because the CLI re-appends its ai-title
462
+ // after every turn and last-record-wins would revert it.
463
+ if (obj.type === "ai-title") aiTitle = obj.aiTitle || obj.title || aiTitle;
464
+ if (obj.type === "custom-title") customTitle = obj.customTitle || obj.title || customTitle;
459
465
  } catch {}
460
466
  }
461
467
  } catch {}
468
+ aiTitle = customTitle || aiTitle;
462
469
 
463
470
  results.push({
464
471
  id, project,
@@ -780,6 +787,7 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
780
787
  // anything INTO the Files drawer it's now told about.
781
788
  "--add-dir", path.join(dataDir(), "images")];
782
789
  let resumeCwd = null;
790
+ let divergedFrom = null; // set if the CLI answers under a different session
783
791
  if (session_id) {
784
792
  const existing = scanSessionFiles().find(s => s.id === session_id);
785
793
  if (existing) {
@@ -837,6 +845,14 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
837
845
  const bin = isCmdShim ? process.env.COMSPEC || "cmd.exe" : config.claudeBin;
838
846
  const fullArgs = isCmdShim ? ["/c", config.claudeBin, ...args] : args;
839
847
 
848
+ // Opt-in spawn tracing (CLAUDE_BRIDGE_DEBUG=1). Nothing recorded WHAT the
849
+ // bridge actually ran, so when a turn misbehaved there was no evidence to
850
+ // separate "we built the wrong command" from "the CLI ignored it" — a
851
+ // resume regression took hours to narrow with no way to see the argv.
852
+ if (process.env.CLAUDE_BRIDGE_DEBUG) {
853
+ console.error("[bridge] spawn bin=%s cwd=%s args=%s",
854
+ bin, effCwd, JSON.stringify(fullArgs));
855
+ }
840
856
  const proc = spawn(bin, fullArgs, {
841
857
  cwd: effCwd,
842
858
  timeout: config.timeout,
@@ -864,6 +880,17 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
864
880
  const finalText = result.result || result.assistantMessage || "";
865
881
  writeCompletionMarker(sid, finalText);
866
882
  if (session_id && session_id !== sid) writeCompletionMarker(session_id, finalText);
883
+ // The CLI answered under a DIFFERENT session than we asked to resume:
884
+ // the turn's history is not where the user is looking, and the session
885
+ // they see can never update again. This was handled silently, so the
886
+ // symptom reaching the user was "Claude keeps repeating its last reply"
887
+ // with nothing anywhere to explain it. Never swallow it again — log it,
888
+ // and hand it to the client so the UI can say so.
889
+ if (session_id && session_id !== sid) {
890
+ console.error("[bridge] WARNING resume diverged: asked=%s answered=%s "
891
+ + "(the turn was written to a different session)", session_id, sid);
892
+ divergedFrom = session_id;
893
+ }
867
894
  if (images && images.length && session_id === "pending" && sid !== "pending") {
868
895
  const oldDir = path.join(dataDir(), "images", "pending");
869
896
  const newDir = path.join(dataDir(), "images", sid);
@@ -885,6 +912,10 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
885
912
  duration_ms: result.duration_ms || null,
886
913
  context: result.context || null,
887
914
  permission_denials,
915
+ // Non-null when the CLI answered under a different session than the
916
+ // one we asked to resume. The client shows the conversation it is
917
+ // displaying will not receive this turn, and where the turn went.
918
+ resume_diverged_from: divergedFrom,
888
919
  });
889
920
  } catch {
890
921
  if (stdout.trim()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-bridge-cli",
3
- "version": "2.0.18",
3
+ "version": "2.0.20",
4
4
  "description": "Use Claude Code from your browser. Runs a local server that connects your browser tools to the Claude CLI.",
5
5
  "main": "lib/bridge.js",
6
6
  "bin": {