@ycodium-ai/agent-claude 0.2.2544 → 0.2.2566

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/dist/index.js +540 -31
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -21153,6 +21153,492 @@ import * as NodeOS6 from "node:os";
21153
21153
  import * as NodePath6 from "node:path";
21154
21154
  import * as NodeProcess from "node:process";
21155
21155
 
21156
+ // ../../packages/ycodium-jsonl-stream/src/jsonlStream.ts
21157
+ var DEFAULT_MAX_RETAINED_CHARS = 8e6;
21158
+ var MAX_DEPTH = 128;
21159
+ var MAX_KEY_CHARS = 256;
21160
+ var MAX_BARE_CHARS = 64;
21161
+ var NUMBER_PATTERN = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/u;
21162
+ var OversizedRecordParser = class {
21163
+ #fields;
21164
+ #budget;
21165
+ #retained = 0;
21166
+ #malformed = false;
21167
+ #done = false;
21168
+ #result = void 0;
21169
+ #stack = [];
21170
+ // 词法状态。
21171
+ #inString = false;
21172
+ #stringIsKey = false;
21173
+ #escape = false;
21174
+ #unicodeLeft = 0;
21175
+ #unicodeValue = 0;
21176
+ #bare = "";
21177
+ // 当前字符串的保留规则与累积。
21178
+ #strRetain = false;
21179
+ #strCap = void 0;
21180
+ #strHead = "";
21181
+ #strTail = "";
21182
+ #strLength = 0;
21183
+ #key = "";
21184
+ #keyOverflow = false;
21185
+ // 值之间的位置。
21186
+ #expectKey = false;
21187
+ #expectColon = false;
21188
+ #expectComma = false;
21189
+ #expectValue = true;
21190
+ constructor(fields, maxRetainedChars = DEFAULT_MAX_RETAINED_CHARS) {
21191
+ this.#fields = fields;
21192
+ this.#budget = maxRetainedChars;
21193
+ }
21194
+ write(chunk) {
21195
+ if (this.#malformed) return;
21196
+ try {
21197
+ this.#consume(chunk);
21198
+ } catch (cause) {
21199
+ if (cause instanceof MalformedRecord) {
21200
+ this.#malformed = true;
21201
+ return;
21202
+ }
21203
+ throw cause;
21204
+ }
21205
+ }
21206
+ /** 完整且合法才返回记录;其余(含空行)返回 `undefined`。 */
21207
+ finish() {
21208
+ if (this.#malformed) return void 0;
21209
+ try {
21210
+ if (this.#bare.length > 0) this.#finishBare();
21211
+ } catch (cause) {
21212
+ if (cause instanceof MalformedRecord) return void 0;
21213
+ throw cause;
21214
+ }
21215
+ if (!this.#done || this.#inString || this.#result === SKIPPED) return void 0;
21216
+ return this.#result;
21217
+ }
21218
+ #fail() {
21219
+ throw new MalformedRecord();
21220
+ }
21221
+ #charge(chars) {
21222
+ this.#retained += chars;
21223
+ if (this.#retained > this.#budget) this.#fail();
21224
+ }
21225
+ #consume(chunk) {
21226
+ const n = chunk.length;
21227
+ let i = 0;
21228
+ while (i < n) {
21229
+ if (this.#inString) {
21230
+ i = this.#consumeString(chunk, i);
21231
+ continue;
21232
+ }
21233
+ const c = chunk.charCodeAt(i);
21234
+ if (this.#bare.length > 0) {
21235
+ if (isBareChar(c)) {
21236
+ if (this.#bare.length >= MAX_BARE_CHARS) this.#fail();
21237
+ this.#bare += chunk[i];
21238
+ i += 1;
21239
+ continue;
21240
+ }
21241
+ this.#finishBare();
21242
+ }
21243
+ i += 1;
21244
+ if (c === 32 || c === 9 || c === 10 || c === 13) continue;
21245
+ if (this.#done) this.#fail();
21246
+ switch (c) {
21247
+ case 123:
21248
+ this.#requireValue();
21249
+ this.#openContainer(false);
21250
+ break;
21251
+ case 91:
21252
+ this.#requireValue();
21253
+ this.#openContainer(true);
21254
+ break;
21255
+ case 125:
21256
+ this.#closeContainer(false);
21257
+ break;
21258
+ case 93:
21259
+ this.#closeContainer(true);
21260
+ break;
21261
+ case 44:
21262
+ this.#comma();
21263
+ break;
21264
+ case 58:
21265
+ if (!this.#expectColon) this.#fail();
21266
+ this.#expectColon = false;
21267
+ this.#expectValue = true;
21268
+ break;
21269
+ case 34:
21270
+ this.#openString();
21271
+ break;
21272
+ default:
21273
+ if (isBareChar(c)) {
21274
+ this.#requireValue();
21275
+ this.#bare = chunk[i - 1] ?? "";
21276
+ } else this.#fail();
21277
+ }
21278
+ }
21279
+ }
21280
+ #top() {
21281
+ return this.#stack[this.#stack.length - 1];
21282
+ }
21283
+ #requireValue() {
21284
+ if (!this.#expectValue) this.#fail();
21285
+ this.#expectValue = false;
21286
+ }
21287
+ /** 当前要读的值(刚要开始)落在什么模式;`isContainer` 决定 scalarOnly 清单项是否适用。 */
21288
+ #childMode(isContainer) {
21289
+ const parent = this.#top();
21290
+ if (parent === void 0) return this.#classify([], isContainer);
21291
+ if (parent.mode === "skip") return { mode: "skip", cap: void 0, path: [] };
21292
+ if (parent.mode === "keep") return { mode: "keep", cap: parent.cap, path: [] };
21293
+ const segment = parent.isArray ? String(parent.index) : parent.key ?? "";
21294
+ if (parent.skipValue) return { mode: "skip", cap: void 0, path: [] };
21295
+ return this.#classify([...parent.path, segment], isContainer);
21296
+ }
21297
+ #classify(path, isContainer) {
21298
+ let descend = false;
21299
+ for (const field of this.#fields) {
21300
+ const fieldPath = field.path;
21301
+ if (fieldPath.length <= path.length) {
21302
+ if (field.scalarOnly === true && (isContainer || fieldPath.length !== path.length)) {
21303
+ continue;
21304
+ }
21305
+ if (matchesPrefix(fieldPath, path, fieldPath.length)) {
21306
+ return { mode: "keep", cap: field.maxChars, path };
21307
+ }
21308
+ } else if (matchesPrefix(fieldPath, path, path.length)) {
21309
+ descend = true;
21310
+ }
21311
+ }
21312
+ return { mode: descend ? "descend" : "skip", cap: void 0, path };
21313
+ }
21314
+ #openContainer(isArray) {
21315
+ if (this.#stack.length >= MAX_DEPTH) this.#fail();
21316
+ const { mode, cap, path } = this.#childMode(true);
21317
+ const keeping = mode !== "skip";
21318
+ let target = null;
21319
+ if (keeping) {
21320
+ this.#charge(16);
21321
+ target = isArray ? [] : {};
21322
+ }
21323
+ this.#stack.push({ isArray, mode, path, cap, target, key: null, skipValue: false, index: 0 });
21324
+ this.#expectValue = isArray;
21325
+ this.#expectKey = !isArray;
21326
+ this.#expectComma = false;
21327
+ this.#expectColon = false;
21328
+ }
21329
+ #closeContainer(isArray) {
21330
+ const top = this.#top();
21331
+ if (top === void 0 || top.isArray !== isArray) this.#fail();
21332
+ if (!this.#expectComma && top.index > 0) this.#fail();
21333
+ if (this.#expectColon || !isArray && this.#expectValue) this.#fail();
21334
+ this.#stack.pop();
21335
+ this.#expectValue = false;
21336
+ this.#expectKey = false;
21337
+ this.#expectColon = false;
21338
+ this.#expectComma = true;
21339
+ this.#store(top.target ?? SKIPPED);
21340
+ }
21341
+ #comma() {
21342
+ const top = this.#top();
21343
+ if (top === void 0 || !this.#expectComma) this.#fail();
21344
+ this.#expectComma = false;
21345
+ if (top.isArray) {
21346
+ this.#expectValue = true;
21347
+ } else {
21348
+ this.#expectKey = true;
21349
+ }
21350
+ }
21351
+ /** 一个值读完:交给外层容器,或成为整条记录。 */
21352
+ #store(value) {
21353
+ const parent = this.#top();
21354
+ if (parent === void 0) {
21355
+ this.#result = value;
21356
+ this.#done = true;
21357
+ this.#expectComma = false;
21358
+ return;
21359
+ }
21360
+ this.#expectComma = true;
21361
+ if (parent.isArray) {
21362
+ parent.index += 1;
21363
+ if (parent.target !== null && value !== SKIPPED) {
21364
+ parent.target.push(value);
21365
+ this.#charge(8);
21366
+ }
21367
+ return;
21368
+ }
21369
+ parent.index += 1;
21370
+ const key = parent.key;
21371
+ parent.key = null;
21372
+ parent.skipValue = false;
21373
+ if (parent.target !== null && value !== SKIPPED && key !== null) {
21374
+ Object.defineProperty(parent.target, key, {
21375
+ value,
21376
+ enumerable: true,
21377
+ writable: true,
21378
+ configurable: true
21379
+ });
21380
+ this.#charge(key.length + 8);
21381
+ }
21382
+ }
21383
+ #openString() {
21384
+ const parent = this.#top();
21385
+ const asKey = parent !== void 0 && !parent.isArray && this.#expectKey;
21386
+ if (!asKey) this.#requireValue();
21387
+ this.#inString = true;
21388
+ this.#stringIsKey = asKey;
21389
+ this.#escape = false;
21390
+ this.#unicodeLeft = 0;
21391
+ this.#strLength = 0;
21392
+ this.#strHead = "";
21393
+ this.#strTail = "";
21394
+ this.#key = "";
21395
+ if (asKey) {
21396
+ this.#keyOverflow = false;
21397
+ this.#strRetain = true;
21398
+ this.#strCap = void 0;
21399
+ return;
21400
+ }
21401
+ const { mode, cap } = this.#childMode(false);
21402
+ this.#strRetain = mode === "keep";
21403
+ this.#strCap = cap;
21404
+ }
21405
+ /** 字符串里的一个解码后片段;按保留规则累积。 */
21406
+ #append(text) {
21407
+ if (text.length === 0) return;
21408
+ if (this.#stringIsKey) {
21409
+ if (this.#keyOverflow) return;
21410
+ this.#key += text;
21411
+ if (this.#key.length > MAX_KEY_CHARS) {
21412
+ this.#keyOverflow = true;
21413
+ this.#key = "";
21414
+ }
21415
+ return;
21416
+ }
21417
+ this.#strLength += text.length;
21418
+ if (!this.#strRetain) return;
21419
+ const cap = this.#strCap;
21420
+ if (cap === void 0) {
21421
+ this.#strHead += text;
21422
+ this.#charge(text.length);
21423
+ return;
21424
+ }
21425
+ if (this.#strHead.length < cap) {
21426
+ const room = cap - this.#strHead.length;
21427
+ this.#strHead += text.slice(0, room);
21428
+ text = text.slice(room);
21429
+ if (text.length === 0) return;
21430
+ }
21431
+ this.#strTail += text;
21432
+ if (this.#strTail.length > cap * 2) this.#strTail = this.#strTail.slice(-cap);
21433
+ }
21434
+ #consumeString(chunk, start) {
21435
+ const n = chunk.length;
21436
+ let i = start;
21437
+ while (i < n) {
21438
+ if (this.#unicodeLeft > 0) {
21439
+ const digit = hexValue(chunk.charCodeAt(i));
21440
+ if (digit < 0) this.#fail();
21441
+ this.#unicodeValue = this.#unicodeValue * 16 + digit;
21442
+ this.#unicodeLeft -= 1;
21443
+ i += 1;
21444
+ if (this.#unicodeLeft === 0) this.#append(String.fromCharCode(this.#unicodeValue));
21445
+ continue;
21446
+ }
21447
+ if (this.#escape) {
21448
+ this.#escape = false;
21449
+ const c3 = chunk[i] ?? "";
21450
+ i += 1;
21451
+ switch (c3) {
21452
+ case '"':
21453
+ case "\\":
21454
+ case "/":
21455
+ this.#append(c3);
21456
+ break;
21457
+ case "b":
21458
+ this.#append("\b");
21459
+ break;
21460
+ case "f":
21461
+ this.#append("\f");
21462
+ break;
21463
+ case "n":
21464
+ this.#append("\n");
21465
+ break;
21466
+ case "r":
21467
+ this.#append("\r");
21468
+ break;
21469
+ case "t":
21470
+ this.#append(" ");
21471
+ break;
21472
+ case "u":
21473
+ this.#unicodeLeft = 4;
21474
+ this.#unicodeValue = 0;
21475
+ break;
21476
+ default:
21477
+ this.#fail();
21478
+ }
21479
+ continue;
21480
+ }
21481
+ const runStart = i;
21482
+ while (i < n) {
21483
+ const c3 = chunk.charCodeAt(i);
21484
+ if (c3 === 34 || c3 === 92 || c3 < 32) break;
21485
+ i += 1;
21486
+ }
21487
+ if (i > runStart) this.#append(chunk.slice(runStart, i));
21488
+ if (i >= n) break;
21489
+ const c = chunk.charCodeAt(i);
21490
+ i += 1;
21491
+ if (c === 92) {
21492
+ this.#escape = true;
21493
+ } else if (c === 34) {
21494
+ this.#inString = false;
21495
+ this.#endString();
21496
+ return i;
21497
+ } else {
21498
+ this.#fail();
21499
+ }
21500
+ }
21501
+ return i;
21502
+ }
21503
+ #endString() {
21504
+ if (this.#stringIsKey) {
21505
+ const parent = this.#top();
21506
+ if (parent === void 0) this.#fail();
21507
+ parent.key = this.#key;
21508
+ parent.skipValue = this.#keyOverflow;
21509
+ this.#key = "";
21510
+ this.#expectKey = false;
21511
+ this.#expectColon = true;
21512
+ return;
21513
+ }
21514
+ if (!this.#strRetain) {
21515
+ this.#store(SKIPPED);
21516
+ return;
21517
+ }
21518
+ const cap = this.#strCap;
21519
+ let text = this.#strHead;
21520
+ if (cap !== void 0) {
21521
+ let tail = this.#strTail;
21522
+ if (tail.length > cap) tail = tail.slice(-cap);
21523
+ if (this.#strLength > text.length + tail.length) {
21524
+ if (isHighSurrogate(text.charCodeAt(text.length - 1))) text = text.slice(0, -1);
21525
+ if (isLowSurrogate(tail.charCodeAt(0))) tail = tail.slice(1);
21526
+ const omitted = this.#strLength - text.length - tail.length;
21527
+ text = `${text}
21528
+ [\u2026 ${omitted} chars omitted \u2026]
21529
+ ${tail}`;
21530
+ } else {
21531
+ text = `${text}${tail}`;
21532
+ }
21533
+ this.#charge(text.length);
21534
+ }
21535
+ this.#strHead = "";
21536
+ this.#strTail = "";
21537
+ this.#store(text);
21538
+ }
21539
+ #finishBare() {
21540
+ const text = this.#bare;
21541
+ this.#bare = "";
21542
+ const { mode } = this.#childMode(false);
21543
+ let value;
21544
+ if (text === "true") value = true;
21545
+ else if (text === "false") value = false;
21546
+ else if (text === "null") value = null;
21547
+ else if (NUMBER_PATTERN.test(text)) value = Number(text);
21548
+ else this.#fail();
21549
+ this.#store(mode === "keep" ? value : SKIPPED);
21550
+ }
21551
+ };
21552
+ var SKIPPED = /* @__PURE__ */ Symbol("skipped");
21553
+ var MalformedRecord = class extends Error {
21554
+ };
21555
+ function isBareChar(c) {
21556
+ return c >= 48 && c <= 57 || // 0-9
21557
+ c >= 97 && c <= 122 || // a-z
21558
+ c >= 65 && c <= 90 || // A-Z
21559
+ c === 43 || c === 45 || c === 46;
21560
+ }
21561
+ function hexValue(c) {
21562
+ if (c >= 48 && c <= 57) return c - 48;
21563
+ if (c >= 97 && c <= 102) return c - 97 + 10;
21564
+ if (c >= 65 && c <= 70) return c - 65 + 10;
21565
+ return -1;
21566
+ }
21567
+ var isHighSurrogate = (c) => c >= 55296 && c <= 56319;
21568
+ var isLowSurrogate = (c) => c >= 56320 && c <= 57343;
21569
+ function matchesPrefix(pattern, path, length) {
21570
+ for (let index = 0; index < length; index += 1) {
21571
+ const expected = pattern[index];
21572
+ if (expected !== "*" && expected !== path[index]) return false;
21573
+ }
21574
+ return true;
21575
+ }
21576
+ function jsonlEntryRecord(entry, accepts) {
21577
+ if ("oversized" in entry) return entry.oversized;
21578
+ if (!accepts(entry.line)) return void 0;
21579
+ try {
21580
+ return JSON.parse(entry.line);
21581
+ } catch {
21582
+ return void 0;
21583
+ }
21584
+ }
21585
+ async function* readJsonlEntries(fs2, path, options) {
21586
+ const decoder = new TextDecoder("utf-8");
21587
+ let pieces = [];
21588
+ let pending = 0;
21589
+ let parser = null;
21590
+ const startOversized = () => {
21591
+ const next = new OversizedRecordParser(options.fields, options.maxRetainedChars);
21592
+ for (const piece of pieces) next.write(piece);
21593
+ pieces = [];
21594
+ pending = 0;
21595
+ return next;
21596
+ };
21597
+ const append = (text) => {
21598
+ if (text.length === 0) return;
21599
+ if (parser !== null) {
21600
+ parser.write(text);
21601
+ return;
21602
+ }
21603
+ pieces.push(text);
21604
+ pending += text.length;
21605
+ if (pending > options.maxLineChars) parser = startOversized();
21606
+ };
21607
+ const takeLine = () => {
21608
+ if (parser !== null) {
21609
+ const record = parser.finish();
21610
+ parser = null;
21611
+ return { oversized: record };
21612
+ }
21613
+ if (pending === 0) return null;
21614
+ let line = pieces.length === 1 ? pieces[0] ?? "" : pieces.join("");
21615
+ pieces = [];
21616
+ pending = 0;
21617
+ if (line.endsWith("\r")) line = line.slice(0, -1);
21618
+ return line.length === 0 ? null : { line };
21619
+ };
21620
+ const feed = function* (text) {
21621
+ let from = 0;
21622
+ while (from <= text.length) {
21623
+ const newline = text.indexOf("\n", from);
21624
+ if (newline < 0) {
21625
+ append(text.slice(from));
21626
+ return;
21627
+ }
21628
+ append(text.slice(from, newline));
21629
+ const entry = takeLine();
21630
+ if (entry !== null) yield entry;
21631
+ from = newline + 1;
21632
+ }
21633
+ };
21634
+ for await (const chunk of fs2.createReadStream(path)) {
21635
+ yield* feed(decoder.decode(chunk, { stream: true }));
21636
+ }
21637
+ yield* feed(decoder.decode());
21638
+ const last = takeLine();
21639
+ if (last !== null) yield last;
21640
+ }
21641
+
21156
21642
  // src/sessionScope.ts
21157
21643
  var EXTENDED_LENGTH_UNC = "//?/UNC/";
21158
21644
  var EXTENDED_LENGTH = "//?/";
@@ -21182,6 +21668,34 @@ var MAX_SCANNED_FILES = 200;
21182
21668
  var MAX_ROWS = 50;
21183
21669
  var MAX_PARSED_LINE_BYTES = 1e6;
21184
21670
  var TRANSCRIPT_SUFFIX = ".jsonl";
21671
+ var DIGEST_TEXT_KEEP_CHARS = 4096;
21672
+ var fileSource = {
21673
+ createReadStream: (path) => NodeFS3.createReadStream(path)
21674
+ };
21675
+ var DIGEST_FIELDS = [
21676
+ { path: ["type"] },
21677
+ { path: ["cwd"] },
21678
+ { path: ["isSidechain"] },
21679
+ { path: ["customTitle"] },
21680
+ { path: ["aiTitle"] },
21681
+ { path: ["message", "model"] },
21682
+ { path: ["message", "content"], scalarOnly: true, maxChars: DIGEST_TEXT_KEEP_CHARS },
21683
+ { path: ["message", "content", "*", "type"] },
21684
+ { path: ["message", "content", "*", "text"], maxChars: DIGEST_TEXT_KEEP_CHARS }
21685
+ ];
21686
+ var RECORD_FIELDS = [
21687
+ { path: ["type"] },
21688
+ { path: ["uuid"] },
21689
+ { path: ["isSidechain"] },
21690
+ { path: ["isSideChain"] },
21691
+ { path: ["isMeta"] },
21692
+ { path: ["parent_tool_use_id"] },
21693
+ { path: ["timestamp"] },
21694
+ { path: ["message", "model"] },
21695
+ { path: ["message", "content"], scalarOnly: true },
21696
+ { path: ["message", "content", "*", "type"] },
21697
+ { path: ["message", "content", "*", "text"] }
21698
+ ];
21185
21699
  function truncate(value) {
21186
21700
  const trimmed = value?.trim() ?? "";
21187
21701
  if (trimmed.length === 0) return null;
@@ -21201,11 +21715,7 @@ function textFromContent(content) {
21201
21715
  }
21202
21716
  return parts.join("\n\n").trim();
21203
21717
  }
21204
- function readLines(filePath) {
21205
- const raw = NodeFS3.readFileSync(filePath, "utf8");
21206
- return raw.split(/\r?\n/);
21207
- }
21208
- function readClaudeTranscriptDigest(filePath) {
21718
+ async function readClaudeTranscriptDigest(filePath) {
21209
21719
  let cwd = null;
21210
21720
  let model = null;
21211
21721
  let preview = null;
@@ -21213,18 +21723,17 @@ function readClaudeTranscriptDigest(filePath) {
21213
21723
  let aiTitle = null;
21214
21724
  let turnCount = 0;
21215
21725
  try {
21216
- for (const line of readLines(filePath)) {
21217
- const isUser = line.includes('"type":"user"');
21218
- const wantsAssistant = model === null && line.includes('"type":"assistant"');
21219
- const isTitle = line.includes('"custom-title"') || line.includes('"ai-title"');
21220
- if (!isUser && !wantsAssistant && !isTitle) continue;
21221
- if (line.length > MAX_PARSED_LINE_BYTES) continue;
21222
- let record;
21223
- try {
21224
- record = JSON.parse(line);
21225
- } catch {
21226
- continue;
21227
- }
21726
+ const entries = readJsonlEntries(fileSource, filePath, {
21727
+ maxLineChars: MAX_PARSED_LINE_BYTES,
21728
+ fields: DIGEST_FIELDS
21729
+ });
21730
+ for await (const entry of entries) {
21731
+ const record = jsonlEntryRecord(entry, (line) => {
21732
+ const isUser = line.includes('"type":"user"');
21733
+ const wantsAssistant = model === null && line.includes('"type":"assistant"');
21734
+ const isTitle = line.includes('"custom-title"') || line.includes('"ai-title"');
21735
+ return isUser || wantsAssistant || isTitle;
21736
+ });
21228
21737
  if (!record || typeof record !== "object") continue;
21229
21738
  const typed = record;
21230
21739
  if (cwd === null && typeof typed.cwd === "string" && typed.cwd.length > 0) cwd = typed.cwd;
@@ -21322,7 +21831,7 @@ function readClaudeLiveSessionIds(configDir) {
21322
21831
  }
21323
21832
  return live;
21324
21833
  }
21325
- function scanClaudeSessions(input) {
21834
+ async function scanClaudeSessions(input) {
21326
21835
  let root;
21327
21836
  try {
21328
21837
  root = NodeFS3.statSync(input.transcriptDir);
@@ -21340,7 +21849,7 @@ function scanClaudeSessions(input) {
21340
21849
  const rows = [];
21341
21850
  for (const file of files) {
21342
21851
  if (rows.length >= MAX_ROWS) break;
21343
- const digest = readClaudeTranscriptDigest(file.path);
21852
+ const digest = await readClaudeTranscriptDigest(file.path);
21344
21853
  if (digest === null || digest.cwd === null) continue;
21345
21854
  if (!isWithinDirectory(digest.cwd, input.directory, caseInsensitive)) continue;
21346
21855
  rows.push({
@@ -21392,7 +21901,7 @@ function isRecord4(value) {
21392
21901
  function nonempty(value) {
21393
21902
  return typeof value === "string" && value.trim().length > 0 ? value : void 0;
21394
21903
  }
21395
- function readClaudeSessionRecord(input) {
21904
+ async function readClaudeSessionRecord(input) {
21396
21905
  const path = resolveTranscriptPath({
21397
21906
  transcriptDir: input.transcriptDir,
21398
21907
  sessionId: input.nativeSessionId,
@@ -21404,15 +21913,15 @@ function readClaudeSessionRecord(input) {
21404
21913
  const messages = [];
21405
21914
  const byUuid = /* @__PURE__ */ new Map();
21406
21915
  let model = null;
21407
- for (const line of readLines(path)) {
21408
- if (line.length > MAX_PARSED_LINE_BYTES) continue;
21409
- if (!line.includes('"type":"user"') && !line.includes('"type":"assistant"')) continue;
21410
- let parsed;
21411
- try {
21412
- parsed = JSON.parse(line);
21413
- } catch {
21414
- continue;
21415
- }
21916
+ const entries = readJsonlEntries(fileSource, path, {
21917
+ maxLineChars: MAX_PARSED_LINE_BYTES,
21918
+ fields: RECORD_FIELDS
21919
+ });
21920
+ for await (const entry of entries) {
21921
+ const parsed = jsonlEntryRecord(
21922
+ entry,
21923
+ (line) => line.includes('"type":"user"') || line.includes('"type":"assistant"')
21924
+ );
21416
21925
  if (!isRecord4(parsed)) continue;
21417
21926
  if (parsed.type !== "user" && parsed.type !== "assistant") continue;
21418
21927
  if (parsed.isSidechain === true || parsed.isSideChain === true || parsed.isMeta === true)
@@ -25500,7 +26009,7 @@ ${stderr}`);
25500
26009
  scan: async (input) => {
25501
26010
  const roots = resolveTranscriptRoots(input.directory);
25502
26011
  return {
25503
- candidates: scanClaudeSessions({
26012
+ candidates: await scanClaudeSessions({
25504
26013
  transcriptDir: roots.transcriptDir,
25505
26014
  configDir: roots.configDir,
25506
26015
  directory: input.directory ?? ""
@@ -25509,7 +26018,7 @@ ${stderr}`);
25509
26018
  },
25510
26019
  read: async (input) => {
25511
26020
  const roots = resolveTranscriptRoots(input.cwd);
25512
- return readClaudeSessionRecord({
26021
+ return await readClaudeSessionRecord({
25513
26022
  transcriptDir: roots.transcriptDir,
25514
26023
  nativeSessionId: input.nativeSessionId,
25515
26024
  cwd: input.cwd
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-claude",
3
- "version": "0.2.2544",
3
+ "version": "0.2.2566",
4
4
  "description": "Claude executor: Claude Code CLI via @anthropic-ai/claude-agent-sdk.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -24,7 +24,8 @@
24
24
  "@types/node": "24.12.4",
25
25
  "esbuild": "0.28.1",
26
26
  "vite-plus": "0.2.2",
27
- "@ycodium-ai/plugin-api": "0.2.2544",
27
+ "@ycodium-ai/plugin-api": "0.2.2566",
28
+ "ycodium-jsonl-stream": "0.0.0",
28
29
  "ycodium-executor-testing": "0.0.0"
29
30
  },
30
31
  "ycodium": {