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.
- package/lib/bridge.js +54 -9
- 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
|
-
|
|
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)
|
|
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
|
-
//
|
|
384
|
-
//
|
|
385
|
-
|
|
386
|
-
|
|
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
|
|
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