claude-bridge-cli 1.2.9 → 1.3.1

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 +54 -9
  2. package/package.json +1 -1
package/lib/bridge.js CHANGED
@@ -281,6 +281,33 @@ function searchSessions(query, limit = 30) {
281
281
 
282
282
  // ── Session messages ──
283
283
 
284
+ const INTERNAL_USER_PATTERNS = [
285
+ "<system-reminder>", "<command-name>", "<command-message>",
286
+ "<local-command-stdout>", "<command-stderr>", "<local-command-stderr>",
287
+ "Caveat: The messages below were generated by",
288
+ ];
289
+
290
+ function extractUserText(content) {
291
+ // Only extract type:"text" parts. tool_result records don't have a text
292
+ // part so they return empty string and get filtered out.
293
+ if (typeof content === "string") return content;
294
+ if (Array.isArray(content)) {
295
+ for (const part of content) {
296
+ if (part && typeof part === "object" && part.type === "text") {
297
+ return part.text || "";
298
+ }
299
+ }
300
+ }
301
+ return "";
302
+ }
303
+
304
+ function shouldSkipUserText(text) {
305
+ if (!text) return true;
306
+ const t = text.replace(/^\s+/, "");
307
+ if (INTERNAL_USER_PATTERNS.some(p => t.startsWith(p))) return true;
308
+ return false;
309
+ }
310
+
284
311
  function getSessionMessages(sessionId) {
285
312
  const base = projectsDir();
286
313
  let dirs;
@@ -292,8 +319,12 @@ function getSessionMessages(sessionId) {
292
319
  for (const line of fs.readFileSync(filePath, "utf8").split("\n").filter(Boolean)) {
293
320
  try {
294
321
  const obj = JSON.parse(line);
322
+ // Skip transcript-only and meta records (replays, recaps)
323
+ if (obj.isMeta === true) continue;
324
+ if (obj.isVisibleInTranscriptOnly === true) continue;
295
325
  if (obj.type === "user" && obj.message?.content) {
296
- let text = typeof obj.message.content === "string" ? obj.message.content : JSON.stringify(obj.message.content);
326
+ const text = extractUserText(obj.message.content);
327
+ if (shouldSkipUserText(text)) continue;
297
328
  const split = splitUserTextAndImages(text);
298
329
  messages.push({
299
330
  role: "user",
@@ -304,7 +335,14 @@ function getSessionMessages(sessionId) {
304
335
  } else if (obj.type === "assistant" && obj.message?.content) {
305
336
  const parts = Array.isArray(obj.message.content) ? obj.message.content : [obj.message.content];
306
337
  const text = parts.map(p => typeof p === "string" ? p : p.text || "").join("");
307
- if (text) messages.push({ role: "assistant", text, timestamp: obj.timestamp });
338
+ if (!text) continue;
339
+ // Merge consecutive assistant turns into one (tool_use cycles)
340
+ if (messages.length && messages[messages.length - 1].role === "assistant") {
341
+ messages[messages.length - 1].text = (messages[messages.length - 1].text + "\n" + text).trim();
342
+ messages[messages.length - 1].timestamp = obj.timestamp || messages[messages.length - 1].timestamp;
343
+ } else {
344
+ messages.push({ role: "assistant", text, timestamp: obj.timestamp });
345
+ }
308
346
  } else if (obj.type === "result" && obj.result?.assistantMessage) {
309
347
  const text = typeof obj.result.assistantMessage === "string" ? obj.result.assistantMessage : "";
310
348
  if (text) messages.push({ role: "assistant", text, timestamp: obj.timestamp });
@@ -380,10 +418,16 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
380
418
  const isWin = process.platform === "win32";
381
419
  const isCmdShim = isWin && config.claudeBin.endsWith(".cmd");
382
420
 
383
- // Write prompt to temp file avoids Windows 8K arg limit and stdin
384
- // piping issues through cmd.exe. Works on all platforms.
385
- const tmpFile = path.join(os.tmpdir(), `claude-prompt-${Date.now()}-${Math.random().toString(36).slice(2)}.txt`);
386
- fs.writeFileSync(tmpFile, finalPrompt, "utf8");
421
+ // Only fall back to @file syntax for prompts that would exceed Windows
422
+ // cmd.exe's ~8K arg limit. Direct -p means the JSONL stores the actual
423
+ // prompt text (so session history shows the real user messages, not
424
+ // temp-file paths). Threshold is conservative: 6000 chars.
425
+ const useTempFile = finalPrompt.length > 6000;
426
+ let tmpFile = null;
427
+ if (useTempFile) {
428
+ tmpFile = path.join(os.tmpdir(), `claude-prompt-${Date.now()}-${Math.random().toString(36).slice(2)}.txt`);
429
+ fs.writeFileSync(tmpFile, finalPrompt, "utf8");
430
+ }
387
431
 
388
432
  const settings = JSON.stringify({
389
433
  permissions: {
@@ -393,7 +437,8 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
393
437
  deny: ["AskUserQuestion"],
394
438
  }
395
439
  });
396
- const args = ["-p", `@${tmpFile}`, "--output-format", "json",
440
+ const promptArg = useTempFile ? `@${tmpFile}` : finalPrompt;
441
+ const args = ["-p", promptArg, "--output-format", "json",
397
442
  "--settings", settings, "--permission-mode", "acceptEdits"];
398
443
  let resumeCwd = null;
399
444
  if (session_id) {
@@ -435,7 +480,7 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
435
480
  if (session_id) running.set(session_id, proc);
436
481
 
437
482
  proc.on("close", (code) => {
438
- try { fs.unlinkSync(tmpFile); } catch {}
483
+ if (tmpFile) { try { fs.unlinkSync(tmpFile); } catch {} }
439
484
  if (session_id) running.delete(session_id);
440
485
  try {
441
486
  const result = JSON.parse(stdout);
@@ -462,7 +507,7 @@ function askClaude(config, { prompt, session_id, images, cwd, plan_mode, allow_t
462
507
  });
463
508
 
464
509
  proc.on("error", (err) => {
465
- try { fs.unlinkSync(tmpFile); } catch {}
510
+ if (tmpFile) { try { fs.unlinkSync(tmpFile); } catch {} }
466
511
  if (session_id) running.delete(session_id);
467
512
  resolve({ error: err.message });
468
513
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-bridge-cli",
3
- "version": "1.2.9",
3
+ "version": "1.3.1",
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": {