claude-bridge-cli 2.0.17 → 2.0.19

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 +31 -4
  2. package/package.json +1 -1
package/lib/bridge.js CHANGED
@@ -178,6 +178,23 @@ function sanitizeAnyFilename(name) {
178
178
  .replace(/^[._ ]+|[._ ]+$/g, "");
179
179
  return (base || "upload.bin").slice(0, 200);
180
180
  }
181
+ // Tell Claude about this session's file-exchange folder. The Files drawer
182
+ // lists exactly this directory and lets the user download from it, but nothing
183
+ // ever TOLD Claude it exists — so "put that file here on the extension" was
184
+ // unanswerable and it guessed at local paths instead. Empty string when there
185
+ // is no session id yet (nothing to point at).
186
+ function filesDrawerPrompt(sid) {
187
+ if (!sid || !/^[A-Za-z0-9._-]+$/.test(sid)) return "";
188
+ const dir = path.join(dataDir(), "images", sid);
189
+ return "\n\nFILE EXCHANGE WITH THE USER'S UI: the directory " + dir +
190
+ " is this session's shared folder. Anything you write there appears immediately " +
191
+ "in the user's 'Files' drawer (they can preview/download it), and files they " +
192
+ "attach arrive there too. When the user asks to 'see/put/send a file here', 'in " +
193
+ "the extension', 'in the app', or 'in the chat' — COPY it into that directory " +
194
+ "(keep the original where it is) and say it's in the Files drawer. Use plain, " +
195
+ "safe filenames. It is a transfer folder, not storage: files older than " +
196
+ FILE_PRUNE_DAYS + " days are pruned, so never treat it as the only copy.";
197
+ }
181
198
  function sessionFilesDir(sid) {
182
199
  if (!/^[A-Za-z0-9._-]+$/.test(sid || "")) throw new Error("bad session id");
183
200
  return path.join(dataDir(), "images", sid);
@@ -426,7 +443,7 @@ function searchSessions(query, limit = 30) {
426
443
  const snippetEnd = Math.min(content.length, idx + q.length + 80);
427
444
  const snippet = content.slice(snippetStart, snippetEnd).replace(/\n/g, " ").trim();
428
445
 
429
- let aiTitle = "", msgCount = 0, realCwd = "";
446
+ let aiTitle = "", customTitle = "", msgCount = 0, realCwd = "";
430
447
  try {
431
448
  const lines = content.split("\n").filter(Boolean);
432
449
  msgCount = lines.length;
@@ -437,11 +454,18 @@ function searchSessions(query, limit = 30) {
437
454
  if (obj.type === "result" && obj.result?.metadata?.title?.value) {
438
455
  aiTitle = obj.result.metadata.title.value;
439
456
  }
440
- if (obj.type === "ai-title" && obj.title) aiTitle = obj.title;
441
- 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;
442
465
  } catch {}
443
466
  }
444
467
  } catch {}
468
+ aiTitle = customTitle || aiTitle;
445
469
 
446
470
  results.push({
447
471
  id, project,
@@ -758,7 +782,10 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
758
782
  const promptArg = useTempFile ? `@${tmpFile}` : finalPrompt;
759
783
  const args = ["-p", promptArg, "--output-format", "json",
760
784
  "--settings", settings, "--permission-mode", "acceptEdits",
761
- "--append-system-prompt", ATOMIC_TURN_PROMPT];
785
+ "--append-system-prompt", ATOMIC_TURN_PROMPT + filesDrawerPrompt(session_id),
786
+ // Grant write access to the file-exchange root, else Claude cannot put
787
+ // anything INTO the Files drawer it's now told about.
788
+ "--add-dir", path.join(dataDir(), "images")];
762
789
  let resumeCwd = null;
763
790
  if (session_id) {
764
791
  const existing = scanSessionFiles().find(s => s.id === session_id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-bridge-cli",
3
- "version": "2.0.17",
3
+ "version": "2.0.19",
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": {