@obtoai/agent-bridge 0.1.0-beta.13 → 0.1.0-beta.15
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/package.json +1 -1
- package/src/external-scanner.js +34 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obtoai/agent-bridge",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.15",
|
|
4
4
|
"description": "Local consumer for the OBTO Agent Bridge. Receives bridge events over SSE and drives a coding agent (Claude Code or OpenAI Codex) on your machine.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "OBTO Inc.",
|
package/src/external-scanner.js
CHANGED
|
@@ -28,7 +28,7 @@ const CODEX_DIR = path.join(os.homedir(), '.codex', 'sessions');
|
|
|
28
28
|
|
|
29
29
|
const PREVIEW_MAX_CHARS = 200;
|
|
30
30
|
const TITLE_MAX_CHARS = 80;
|
|
31
|
-
const TAIL_READ_BYTES =
|
|
31
|
+
const TAIL_READ_BYTES = 16384; // last 16KB — covers the last message AND the late-appended ai-title record
|
|
32
32
|
const TITLE_MAX_LINES = 40; // scan up to this many lines for a real first message
|
|
33
33
|
const TITLE_MAX_BYTES = 65536; // hard ceiling per file even if MAX_LINES never reached
|
|
34
34
|
|
|
@@ -53,7 +53,30 @@ const readTail = (filePath, maxBytes = TAIL_READ_BYTES) => {
|
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
// Claude Code
|
|
56
|
+
// Claude Code writes an LLM-generated title as a `type: "ai-title"` JSONL
|
|
57
|
+
// record near the end of each session file (this is the same title VSCode's
|
|
58
|
+
// session list shows — "Analyze MongoDB MCP server architecture" style).
|
|
59
|
+
// If we find one, it beats anything we could extract from the user's first
|
|
60
|
+
// raw prompt. Scan the tail backwards to hit it fast.
|
|
61
|
+
const extractAiTitleFromTail = (jsonlTail) => {
|
|
62
|
+
if (!jsonlTail) return '';
|
|
63
|
+
const lines = jsonlTail.split(/\r?\n/);
|
|
64
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
65
|
+
const line = lines[i];
|
|
66
|
+
// Cheap pre-filter so we only JSON.parse candidate lines.
|
|
67
|
+
if (line.indexOf('ai-title') === -1 && line.indexOf('aiTitle') === -1) continue;
|
|
68
|
+
try {
|
|
69
|
+
const obj = JSON.parse(line);
|
|
70
|
+
if (obj && obj.type === 'ai-title' && typeof obj.aiTitle === 'string') {
|
|
71
|
+
const t = obj.aiTitle.trim();
|
|
72
|
+
if (t) return t.length > TITLE_MAX_CHARS ? t.slice(0, TITLE_MAX_CHARS) : t;
|
|
73
|
+
}
|
|
74
|
+
} catch (_) { /* not a JSON line — keep walking */ }
|
|
75
|
+
}
|
|
76
|
+
return '';
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
|
|
57
80
|
// "user" messages BEFORE the human's first real prompt — system reminders,
|
|
58
81
|
// IDE state, untrusted-metadata wrappers, command blocks, etc. These are
|
|
59
82
|
// noise from a label perspective. Filter them so the first PLAIN user
|
|
@@ -223,7 +246,11 @@ const scanClaude = () => {
|
|
|
223
246
|
try { stat = fs.statSync(filePath); } catch (_) { continue; }
|
|
224
247
|
const tail = readTail(filePath);
|
|
225
248
|
const lastMsg = extractLastMessage(tail);
|
|
226
|
-
|
|
249
|
+
// Prefer Claude Code's own LLM-summarized title (matches VSCode's list);
|
|
250
|
+
// fall back to first-user-message scanning if a session is too new to
|
|
251
|
+
// have an ai-title record yet.
|
|
252
|
+
let title = extractAiTitleFromTail(tail);
|
|
253
|
+
if (!title) title = extractTitleFromFile(filePath);
|
|
227
254
|
out.push({
|
|
228
255
|
source: 'claude',
|
|
229
256
|
sessionId,
|
|
@@ -296,9 +323,11 @@ const scanCodex = () => {
|
|
|
296
323
|
}
|
|
297
324
|
|
|
298
325
|
const tail = readTail(filePath);
|
|
299
|
-
const head = readHead(filePath);
|
|
300
326
|
const lastMsg = extractLastMessage(tail);
|
|
301
|
-
|
|
327
|
+
// Codex rollouts don't carry an ai-title record (as of this writing),
|
|
328
|
+
// so we just use the first-user-message fallback. If they add one
|
|
329
|
+
// later, swap in extractAiTitleFromTail like the claude path does.
|
|
330
|
+
const title = extractTitleFromFile(filePath);
|
|
302
331
|
out.push({
|
|
303
332
|
source: 'codex',
|
|
304
333
|
sessionId,
|