@ycodium-ai/plugin-session-import 0.2.2526 → 0.2.2544
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/dist/index.js +577 -26
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -171,6 +171,483 @@ import * as NodeProcess2 from "node:process";
|
|
|
171
171
|
import * as NodePath from "node:path";
|
|
172
172
|
import * as NodeProcess from "node:process";
|
|
173
173
|
|
|
174
|
+
// src/jsonlStream.ts
|
|
175
|
+
var DEFAULT_MAX_RETAINED_CHARS = 8e6;
|
|
176
|
+
var MAX_DEPTH = 128;
|
|
177
|
+
var MAX_KEY_CHARS = 256;
|
|
178
|
+
var MAX_BARE_CHARS = 64;
|
|
179
|
+
var NUMBER_PATTERN = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/u;
|
|
180
|
+
var OversizedRecordParser = class {
|
|
181
|
+
#fields;
|
|
182
|
+
#budget;
|
|
183
|
+
#retained = 0;
|
|
184
|
+
#malformed = false;
|
|
185
|
+
#done = false;
|
|
186
|
+
#result = void 0;
|
|
187
|
+
#stack = [];
|
|
188
|
+
// 词法状态。
|
|
189
|
+
#inString = false;
|
|
190
|
+
#stringIsKey = false;
|
|
191
|
+
#escape = false;
|
|
192
|
+
#unicodeLeft = 0;
|
|
193
|
+
#unicodeValue = 0;
|
|
194
|
+
#bare = "";
|
|
195
|
+
// 当前字符串的保留规则与累积。
|
|
196
|
+
#strRetain = false;
|
|
197
|
+
#strCap = void 0;
|
|
198
|
+
#strHead = "";
|
|
199
|
+
#strTail = "";
|
|
200
|
+
#strLength = 0;
|
|
201
|
+
#key = "";
|
|
202
|
+
#keyOverflow = false;
|
|
203
|
+
// 值之间的位置。
|
|
204
|
+
#expectKey = false;
|
|
205
|
+
#expectColon = false;
|
|
206
|
+
#expectComma = false;
|
|
207
|
+
#expectValue = true;
|
|
208
|
+
constructor(fields, maxRetainedChars = DEFAULT_MAX_RETAINED_CHARS) {
|
|
209
|
+
this.#fields = fields;
|
|
210
|
+
this.#budget = maxRetainedChars;
|
|
211
|
+
}
|
|
212
|
+
write(chunk) {
|
|
213
|
+
if (this.#malformed) return;
|
|
214
|
+
try {
|
|
215
|
+
this.#consume(chunk);
|
|
216
|
+
} catch (cause) {
|
|
217
|
+
if (cause instanceof MalformedRecord) {
|
|
218
|
+
this.#malformed = true;
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
throw cause;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/** 完整且合法才返回记录;其余(含空行)返回 `undefined`。 */
|
|
225
|
+
finish() {
|
|
226
|
+
if (this.#malformed) return void 0;
|
|
227
|
+
try {
|
|
228
|
+
if (this.#bare.length > 0) this.#finishBare();
|
|
229
|
+
} catch (cause) {
|
|
230
|
+
if (cause instanceof MalformedRecord) return void 0;
|
|
231
|
+
throw cause;
|
|
232
|
+
}
|
|
233
|
+
if (!this.#done || this.#inString || this.#result === SKIPPED) return void 0;
|
|
234
|
+
return this.#result;
|
|
235
|
+
}
|
|
236
|
+
#fail() {
|
|
237
|
+
throw new MalformedRecord();
|
|
238
|
+
}
|
|
239
|
+
#charge(chars) {
|
|
240
|
+
this.#retained += chars;
|
|
241
|
+
if (this.#retained > this.#budget) this.#fail();
|
|
242
|
+
}
|
|
243
|
+
#consume(chunk) {
|
|
244
|
+
const n = chunk.length;
|
|
245
|
+
let i = 0;
|
|
246
|
+
while (i < n) {
|
|
247
|
+
if (this.#inString) {
|
|
248
|
+
i = this.#consumeString(chunk, i);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const c = chunk.charCodeAt(i);
|
|
252
|
+
if (this.#bare.length > 0) {
|
|
253
|
+
if (isBareChar(c)) {
|
|
254
|
+
if (this.#bare.length >= MAX_BARE_CHARS) this.#fail();
|
|
255
|
+
this.#bare += chunk[i];
|
|
256
|
+
i += 1;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
this.#finishBare();
|
|
260
|
+
}
|
|
261
|
+
i += 1;
|
|
262
|
+
if (c === 32 || c === 9 || c === 10 || c === 13) continue;
|
|
263
|
+
if (this.#done) this.#fail();
|
|
264
|
+
switch (c) {
|
|
265
|
+
case 123:
|
|
266
|
+
this.#requireValue();
|
|
267
|
+
this.#openContainer(false);
|
|
268
|
+
break;
|
|
269
|
+
case 91:
|
|
270
|
+
this.#requireValue();
|
|
271
|
+
this.#openContainer(true);
|
|
272
|
+
break;
|
|
273
|
+
case 125:
|
|
274
|
+
this.#closeContainer(false);
|
|
275
|
+
break;
|
|
276
|
+
case 93:
|
|
277
|
+
this.#closeContainer(true);
|
|
278
|
+
break;
|
|
279
|
+
case 44:
|
|
280
|
+
this.#comma();
|
|
281
|
+
break;
|
|
282
|
+
case 58:
|
|
283
|
+
if (!this.#expectColon) this.#fail();
|
|
284
|
+
this.#expectColon = false;
|
|
285
|
+
this.#expectValue = true;
|
|
286
|
+
break;
|
|
287
|
+
case 34:
|
|
288
|
+
this.#openString();
|
|
289
|
+
break;
|
|
290
|
+
default:
|
|
291
|
+
if (isBareChar(c)) {
|
|
292
|
+
this.#requireValue();
|
|
293
|
+
this.#bare = chunk[i - 1] ?? "";
|
|
294
|
+
} else this.#fail();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
#top() {
|
|
299
|
+
return this.#stack[this.#stack.length - 1];
|
|
300
|
+
}
|
|
301
|
+
#requireValue() {
|
|
302
|
+
if (!this.#expectValue) this.#fail();
|
|
303
|
+
this.#expectValue = false;
|
|
304
|
+
}
|
|
305
|
+
/** 当前要读的值(刚要开始)落在什么模式;`isContainer` 决定 scalarOnly 清单项是否适用。 */
|
|
306
|
+
#childMode(isContainer) {
|
|
307
|
+
const parent = this.#top();
|
|
308
|
+
if (parent === void 0) return this.#classify([], isContainer);
|
|
309
|
+
if (parent.mode === "skip") return { mode: "skip", cap: void 0, path: [] };
|
|
310
|
+
if (parent.mode === "keep") return { mode: "keep", cap: parent.cap, path: [] };
|
|
311
|
+
const segment = parent.isArray ? String(parent.index) : parent.key ?? "";
|
|
312
|
+
if (parent.skipValue) return { mode: "skip", cap: void 0, path: [] };
|
|
313
|
+
return this.#classify([...parent.path, segment], isContainer);
|
|
314
|
+
}
|
|
315
|
+
#classify(path, isContainer) {
|
|
316
|
+
let descend = false;
|
|
317
|
+
for (const field of this.#fields) {
|
|
318
|
+
const fieldPath = field.path;
|
|
319
|
+
if (fieldPath.length <= path.length) {
|
|
320
|
+
if (field.scalarOnly === true && (isContainer || fieldPath.length !== path.length)) {
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
if (matchesPrefix(fieldPath, path, fieldPath.length)) {
|
|
324
|
+
return { mode: "keep", cap: field.maxChars, path };
|
|
325
|
+
}
|
|
326
|
+
} else if (matchesPrefix(fieldPath, path, path.length)) {
|
|
327
|
+
descend = true;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return { mode: descend ? "descend" : "skip", cap: void 0, path };
|
|
331
|
+
}
|
|
332
|
+
#openContainer(isArray) {
|
|
333
|
+
if (this.#stack.length >= MAX_DEPTH) this.#fail();
|
|
334
|
+
const { mode, cap, path } = this.#childMode(true);
|
|
335
|
+
const keeping = mode !== "skip";
|
|
336
|
+
let target = null;
|
|
337
|
+
if (keeping) {
|
|
338
|
+
this.#charge(16);
|
|
339
|
+
target = isArray ? [] : {};
|
|
340
|
+
}
|
|
341
|
+
this.#stack.push({ isArray, mode, path, cap, target, key: null, skipValue: false, index: 0 });
|
|
342
|
+
this.#expectValue = isArray;
|
|
343
|
+
this.#expectKey = !isArray;
|
|
344
|
+
this.#expectComma = false;
|
|
345
|
+
this.#expectColon = false;
|
|
346
|
+
}
|
|
347
|
+
#closeContainer(isArray) {
|
|
348
|
+
const top = this.#top();
|
|
349
|
+
if (top === void 0 || top.isArray !== isArray) this.#fail();
|
|
350
|
+
if (!this.#expectComma && top.index > 0) this.#fail();
|
|
351
|
+
if (this.#expectColon || !isArray && this.#expectValue) this.#fail();
|
|
352
|
+
this.#stack.pop();
|
|
353
|
+
this.#expectValue = false;
|
|
354
|
+
this.#expectKey = false;
|
|
355
|
+
this.#expectColon = false;
|
|
356
|
+
this.#expectComma = true;
|
|
357
|
+
this.#store(top.target ?? SKIPPED);
|
|
358
|
+
}
|
|
359
|
+
#comma() {
|
|
360
|
+
const top = this.#top();
|
|
361
|
+
if (top === void 0 || !this.#expectComma) this.#fail();
|
|
362
|
+
this.#expectComma = false;
|
|
363
|
+
if (top.isArray) {
|
|
364
|
+
this.#expectValue = true;
|
|
365
|
+
} else {
|
|
366
|
+
this.#expectKey = true;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
/** 一个值读完:交给外层容器,或成为整条记录。 */
|
|
370
|
+
#store(value) {
|
|
371
|
+
const parent = this.#top();
|
|
372
|
+
if (parent === void 0) {
|
|
373
|
+
this.#result = value;
|
|
374
|
+
this.#done = true;
|
|
375
|
+
this.#expectComma = false;
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
this.#expectComma = true;
|
|
379
|
+
if (parent.isArray) {
|
|
380
|
+
parent.index += 1;
|
|
381
|
+
if (parent.target !== null && value !== SKIPPED) {
|
|
382
|
+
parent.target.push(value);
|
|
383
|
+
this.#charge(8);
|
|
384
|
+
}
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
parent.index += 1;
|
|
388
|
+
const key = parent.key;
|
|
389
|
+
parent.key = null;
|
|
390
|
+
parent.skipValue = false;
|
|
391
|
+
if (parent.target !== null && value !== SKIPPED && key !== null) {
|
|
392
|
+
Object.defineProperty(parent.target, key, {
|
|
393
|
+
value,
|
|
394
|
+
enumerable: true,
|
|
395
|
+
writable: true,
|
|
396
|
+
configurable: true
|
|
397
|
+
});
|
|
398
|
+
this.#charge(key.length + 8);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
#openString() {
|
|
402
|
+
const parent = this.#top();
|
|
403
|
+
const asKey = parent !== void 0 && !parent.isArray && this.#expectKey;
|
|
404
|
+
if (!asKey) this.#requireValue();
|
|
405
|
+
this.#inString = true;
|
|
406
|
+
this.#stringIsKey = asKey;
|
|
407
|
+
this.#escape = false;
|
|
408
|
+
this.#unicodeLeft = 0;
|
|
409
|
+
this.#strLength = 0;
|
|
410
|
+
this.#strHead = "";
|
|
411
|
+
this.#strTail = "";
|
|
412
|
+
this.#key = "";
|
|
413
|
+
if (asKey) {
|
|
414
|
+
this.#keyOverflow = false;
|
|
415
|
+
this.#strRetain = true;
|
|
416
|
+
this.#strCap = void 0;
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const { mode, cap } = this.#childMode(false);
|
|
420
|
+
this.#strRetain = mode === "keep";
|
|
421
|
+
this.#strCap = cap;
|
|
422
|
+
}
|
|
423
|
+
/** 字符串里的一个解码后片段;按保留规则累积。 */
|
|
424
|
+
#append(text) {
|
|
425
|
+
if (text.length === 0) return;
|
|
426
|
+
if (this.#stringIsKey) {
|
|
427
|
+
if (this.#keyOverflow) return;
|
|
428
|
+
this.#key += text;
|
|
429
|
+
if (this.#key.length > MAX_KEY_CHARS) {
|
|
430
|
+
this.#keyOverflow = true;
|
|
431
|
+
this.#key = "";
|
|
432
|
+
}
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
this.#strLength += text.length;
|
|
436
|
+
if (!this.#strRetain) return;
|
|
437
|
+
const cap = this.#strCap;
|
|
438
|
+
if (cap === void 0) {
|
|
439
|
+
this.#strHead += text;
|
|
440
|
+
this.#charge(text.length);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
if (this.#strHead.length < cap) {
|
|
444
|
+
const room = cap - this.#strHead.length;
|
|
445
|
+
this.#strHead += text.slice(0, room);
|
|
446
|
+
text = text.slice(room);
|
|
447
|
+
if (text.length === 0) return;
|
|
448
|
+
}
|
|
449
|
+
this.#strTail += text;
|
|
450
|
+
if (this.#strTail.length > cap * 2) this.#strTail = this.#strTail.slice(-cap);
|
|
451
|
+
}
|
|
452
|
+
#consumeString(chunk, start) {
|
|
453
|
+
const n = chunk.length;
|
|
454
|
+
let i = start;
|
|
455
|
+
while (i < n) {
|
|
456
|
+
if (this.#unicodeLeft > 0) {
|
|
457
|
+
const digit = hexValue(chunk.charCodeAt(i));
|
|
458
|
+
if (digit < 0) this.#fail();
|
|
459
|
+
this.#unicodeValue = this.#unicodeValue * 16 + digit;
|
|
460
|
+
this.#unicodeLeft -= 1;
|
|
461
|
+
i += 1;
|
|
462
|
+
if (this.#unicodeLeft === 0) this.#append(String.fromCharCode(this.#unicodeValue));
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
if (this.#escape) {
|
|
466
|
+
this.#escape = false;
|
|
467
|
+
const c2 = chunk[i] ?? "";
|
|
468
|
+
i += 1;
|
|
469
|
+
switch (c2) {
|
|
470
|
+
case '"':
|
|
471
|
+
case "\\":
|
|
472
|
+
case "/":
|
|
473
|
+
this.#append(c2);
|
|
474
|
+
break;
|
|
475
|
+
case "b":
|
|
476
|
+
this.#append("\b");
|
|
477
|
+
break;
|
|
478
|
+
case "f":
|
|
479
|
+
this.#append("\f");
|
|
480
|
+
break;
|
|
481
|
+
case "n":
|
|
482
|
+
this.#append("\n");
|
|
483
|
+
break;
|
|
484
|
+
case "r":
|
|
485
|
+
this.#append("\r");
|
|
486
|
+
break;
|
|
487
|
+
case "t":
|
|
488
|
+
this.#append(" ");
|
|
489
|
+
break;
|
|
490
|
+
case "u":
|
|
491
|
+
this.#unicodeLeft = 4;
|
|
492
|
+
this.#unicodeValue = 0;
|
|
493
|
+
break;
|
|
494
|
+
default:
|
|
495
|
+
this.#fail();
|
|
496
|
+
}
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
const runStart = i;
|
|
500
|
+
while (i < n) {
|
|
501
|
+
const c2 = chunk.charCodeAt(i);
|
|
502
|
+
if (c2 === 34 || c2 === 92 || c2 < 32) break;
|
|
503
|
+
i += 1;
|
|
504
|
+
}
|
|
505
|
+
if (i > runStart) this.#append(chunk.slice(runStart, i));
|
|
506
|
+
if (i >= n) break;
|
|
507
|
+
const c = chunk.charCodeAt(i);
|
|
508
|
+
i += 1;
|
|
509
|
+
if (c === 92) {
|
|
510
|
+
this.#escape = true;
|
|
511
|
+
} else if (c === 34) {
|
|
512
|
+
this.#inString = false;
|
|
513
|
+
this.#endString();
|
|
514
|
+
return i;
|
|
515
|
+
} else {
|
|
516
|
+
this.#fail();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return i;
|
|
520
|
+
}
|
|
521
|
+
#endString() {
|
|
522
|
+
if (this.#stringIsKey) {
|
|
523
|
+
const parent = this.#top();
|
|
524
|
+
if (parent === void 0) this.#fail();
|
|
525
|
+
parent.key = this.#key;
|
|
526
|
+
parent.skipValue = this.#keyOverflow;
|
|
527
|
+
this.#key = "";
|
|
528
|
+
this.#expectKey = false;
|
|
529
|
+
this.#expectColon = true;
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
if (!this.#strRetain) {
|
|
533
|
+
this.#store(SKIPPED);
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
const cap = this.#strCap;
|
|
537
|
+
let text = this.#strHead;
|
|
538
|
+
if (cap !== void 0) {
|
|
539
|
+
let tail = this.#strTail;
|
|
540
|
+
if (tail.length > cap) tail = tail.slice(-cap);
|
|
541
|
+
if (this.#strLength > text.length + tail.length) {
|
|
542
|
+
if (isHighSurrogate(text.charCodeAt(text.length - 1))) text = text.slice(0, -1);
|
|
543
|
+
if (isLowSurrogate(tail.charCodeAt(0))) tail = tail.slice(1);
|
|
544
|
+
const omitted = this.#strLength - text.length - tail.length;
|
|
545
|
+
text = `${text}
|
|
546
|
+
[\u2026 ${omitted} chars omitted \u2026]
|
|
547
|
+
${tail}`;
|
|
548
|
+
} else {
|
|
549
|
+
text = `${text}${tail}`;
|
|
550
|
+
}
|
|
551
|
+
this.#charge(text.length);
|
|
552
|
+
}
|
|
553
|
+
this.#strHead = "";
|
|
554
|
+
this.#strTail = "";
|
|
555
|
+
this.#store(text);
|
|
556
|
+
}
|
|
557
|
+
#finishBare() {
|
|
558
|
+
const text = this.#bare;
|
|
559
|
+
this.#bare = "";
|
|
560
|
+
const { mode } = this.#childMode(false);
|
|
561
|
+
let value;
|
|
562
|
+
if (text === "true") value = true;
|
|
563
|
+
else if (text === "false") value = false;
|
|
564
|
+
else if (text === "null") value = null;
|
|
565
|
+
else if (NUMBER_PATTERN.test(text)) value = Number(text);
|
|
566
|
+
else this.#fail();
|
|
567
|
+
this.#store(mode === "keep" ? value : SKIPPED);
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
var SKIPPED = /* @__PURE__ */ Symbol("skipped");
|
|
571
|
+
var MalformedRecord = class extends Error {
|
|
572
|
+
};
|
|
573
|
+
function isBareChar(c) {
|
|
574
|
+
return c >= 48 && c <= 57 || // 0-9
|
|
575
|
+
c >= 97 && c <= 122 || // a-z
|
|
576
|
+
c >= 65 && c <= 90 || // A-Z
|
|
577
|
+
c === 43 || c === 45 || c === 46;
|
|
578
|
+
}
|
|
579
|
+
function hexValue(c) {
|
|
580
|
+
if (c >= 48 && c <= 57) return c - 48;
|
|
581
|
+
if (c >= 97 && c <= 102) return c - 97 + 10;
|
|
582
|
+
if (c >= 65 && c <= 70) return c - 65 + 10;
|
|
583
|
+
return -1;
|
|
584
|
+
}
|
|
585
|
+
var isHighSurrogate = (c) => c >= 55296 && c <= 56319;
|
|
586
|
+
var isLowSurrogate = (c) => c >= 56320 && c <= 57343;
|
|
587
|
+
function matchesPrefix(pattern, path, length) {
|
|
588
|
+
for (let index = 0; index < length; index += 1) {
|
|
589
|
+
const expected = pattern[index];
|
|
590
|
+
if (expected !== "*" && expected !== path[index]) return false;
|
|
591
|
+
}
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
async function* readJsonlEntries(fs, path, options) {
|
|
595
|
+
const decoder = new TextDecoder("utf-8");
|
|
596
|
+
let pieces = [];
|
|
597
|
+
let pending = 0;
|
|
598
|
+
let parser = null;
|
|
599
|
+
const startOversized = () => {
|
|
600
|
+
const next = new OversizedRecordParser(options.fields, options.maxRetainedChars);
|
|
601
|
+
for (const piece of pieces) next.write(piece);
|
|
602
|
+
pieces = [];
|
|
603
|
+
pending = 0;
|
|
604
|
+
return next;
|
|
605
|
+
};
|
|
606
|
+
const append = (text) => {
|
|
607
|
+
if (text.length === 0) return;
|
|
608
|
+
if (parser !== null) {
|
|
609
|
+
parser.write(text);
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
pieces.push(text);
|
|
613
|
+
pending += text.length;
|
|
614
|
+
if (pending > options.maxLineChars) parser = startOversized();
|
|
615
|
+
};
|
|
616
|
+
const takeLine = () => {
|
|
617
|
+
if (parser !== null) {
|
|
618
|
+
const record3 = parser.finish();
|
|
619
|
+
parser = null;
|
|
620
|
+
return { oversized: record3 };
|
|
621
|
+
}
|
|
622
|
+
if (pending === 0) return null;
|
|
623
|
+
let line = pieces.length === 1 ? pieces[0] ?? "" : pieces.join("");
|
|
624
|
+
pieces = [];
|
|
625
|
+
pending = 0;
|
|
626
|
+
if (line.endsWith("\r")) line = line.slice(0, -1);
|
|
627
|
+
return line.length === 0 ? null : { line };
|
|
628
|
+
};
|
|
629
|
+
const feed = function* (text) {
|
|
630
|
+
let from = 0;
|
|
631
|
+
while (from <= text.length) {
|
|
632
|
+
const newline = text.indexOf("\n", from);
|
|
633
|
+
if (newline < 0) {
|
|
634
|
+
append(text.slice(from));
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
append(text.slice(from, newline));
|
|
638
|
+
const entry = takeLine();
|
|
639
|
+
if (entry !== null) yield entry;
|
|
640
|
+
from = newline + 1;
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
for await (const chunk of fs.createReadStream(path)) {
|
|
644
|
+
yield* feed(decoder.decode(chunk, { stream: true }));
|
|
645
|
+
}
|
|
646
|
+
yield* feed(decoder.decode());
|
|
647
|
+
const last = takeLine();
|
|
648
|
+
if (last !== null) yield last;
|
|
649
|
+
}
|
|
650
|
+
|
|
174
651
|
// src/sessionScope.ts
|
|
175
652
|
var EXTENDED_LENGTH_UNC = "//?/UNC/";
|
|
176
653
|
var EXTENDED_LENGTH = "//?/";
|
|
@@ -199,6 +676,61 @@ var PREVIEW_LIMIT = 200;
|
|
|
199
676
|
var MAX_SCANNED_FILES = 200;
|
|
200
677
|
var MAX_ROWS = 50;
|
|
201
678
|
var MAX_PARSED_LINE_BYTES = 1e6;
|
|
679
|
+
var TOOL_TEXT_KEEP_CHARS = 64e3;
|
|
680
|
+
var DIGEST_TEXT_KEEP_CHARS = 4096;
|
|
681
|
+
var DIGEST_FIELDS = [
|
|
682
|
+
{ path: ["type"] },
|
|
683
|
+
{ path: ["cwd"] },
|
|
684
|
+
{ path: ["isSidechain"] },
|
|
685
|
+
{ path: ["customTitle"] },
|
|
686
|
+
{ path: ["aiTitle"] },
|
|
687
|
+
{ path: ["message", "model"] },
|
|
688
|
+
{ path: ["message", "content"], scalarOnly: true, maxChars: DIGEST_TEXT_KEEP_CHARS },
|
|
689
|
+
{ path: ["message", "content", "*", "type"] },
|
|
690
|
+
{ path: ["message", "content", "*", "text"], maxChars: DIGEST_TEXT_KEEP_CHARS }
|
|
691
|
+
];
|
|
692
|
+
var TRANSCRIPT_FIELDS = [
|
|
693
|
+
{ path: ["type"] },
|
|
694
|
+
{ path: ["uuid"] },
|
|
695
|
+
{ path: ["isSidechain"] },
|
|
696
|
+
{ path: ["isSideChain"] },
|
|
697
|
+
{ path: ["isMeta"] },
|
|
698
|
+
{ path: ["parent_tool_use_id"] },
|
|
699
|
+
{ path: ["timestamp"] },
|
|
700
|
+
{ path: ["model"] },
|
|
701
|
+
{ path: ["message", "model"] },
|
|
702
|
+
{ path: ["message", "content"], scalarOnly: true },
|
|
703
|
+
{ path: ["message", "content", "*", "type"] },
|
|
704
|
+
// 消息正文不截:它就是导入的内容。
|
|
705
|
+
{ path: ["message", "content", "*", "text"] },
|
|
706
|
+
{ path: ["message", "content", "*", "thinking"], maxChars: TOOL_TEXT_KEEP_CHARS },
|
|
707
|
+
{ path: ["message", "content", "*", "id"] },
|
|
708
|
+
{ path: ["message", "content", "*", "name"] },
|
|
709
|
+
{ path: ["message", "content", "*", "input"], maxChars: TOOL_TEXT_KEEP_CHARS },
|
|
710
|
+
{ path: ["message", "content", "*", "tool_use_id"] },
|
|
711
|
+
{ path: ["message", "content", "*", "is_error"] },
|
|
712
|
+
{ path: ["message", "content", "*", "status"] },
|
|
713
|
+
// tool_result 的 content 可能是字符串,也可能是块数组;块只认文本块。
|
|
714
|
+
{
|
|
715
|
+
path: ["message", "content", "*", "content"],
|
|
716
|
+
scalarOnly: true,
|
|
717
|
+
maxChars: TOOL_TEXT_KEEP_CHARS
|
|
718
|
+
},
|
|
719
|
+
{ path: ["message", "content", "*", "content", "*", "type"] },
|
|
720
|
+
{
|
|
721
|
+
path: ["message", "content", "*", "content", "*", "text"],
|
|
722
|
+
maxChars: TOOL_TEXT_KEEP_CHARS
|
|
723
|
+
}
|
|
724
|
+
];
|
|
725
|
+
function entryRecord(entry, accepts) {
|
|
726
|
+
if ("oversized" in entry) return entry.oversized;
|
|
727
|
+
if (!accepts(entry.line)) return void 0;
|
|
728
|
+
try {
|
|
729
|
+
return JSON.parse(entry.line);
|
|
730
|
+
} catch {
|
|
731
|
+
return void 0;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
202
734
|
var TRANSCRIPT_SUFFIX = ".jsonl";
|
|
203
735
|
function truncate(value) {
|
|
204
736
|
const trimmed = value?.trim() ?? "";
|
|
@@ -227,18 +759,17 @@ async function readClaudeTranscriptDigest(fs, filePath) {
|
|
|
227
759
|
let aiTitle = null;
|
|
228
760
|
let turnCount = 0;
|
|
229
761
|
try {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
762
|
+
const entries = readJsonlEntries(fs, filePath, {
|
|
763
|
+
maxLineChars: MAX_PARSED_LINE_BYTES,
|
|
764
|
+
fields: DIGEST_FIELDS
|
|
765
|
+
});
|
|
766
|
+
for await (const entry of entries) {
|
|
767
|
+
const record3 = entryRecord(entry, (line) => {
|
|
768
|
+
const isUser = line.includes('"type":"user"');
|
|
769
|
+
const wantsAssistant = model === null && line.includes('"type":"assistant"');
|
|
770
|
+
const isTitle = line.includes('"custom-title"') || line.includes('"ai-title"');
|
|
771
|
+
return isUser || wantsAssistant || isTitle;
|
|
772
|
+
});
|
|
242
773
|
if (!record3 || typeof record3 !== "object") continue;
|
|
243
774
|
const typed = record3;
|
|
244
775
|
if (cwd === null && typeof typed.cwd === "string" && typed.cwd.length > 0) cwd = typed.cwd;
|
|
@@ -377,14 +908,16 @@ async function readClaudeSessionRecords(input) {
|
|
|
377
908
|
throw new Error(`No transcript file for Claude session ${input.sessionId}.`);
|
|
378
909
|
}
|
|
379
910
|
const records = [];
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
911
|
+
const entries = readJsonlEntries(input.fs, path, {
|
|
912
|
+
maxLineChars: MAX_PARSED_LINE_BYTES,
|
|
913
|
+
fields: TRANSCRIPT_FIELDS
|
|
914
|
+
});
|
|
915
|
+
for await (const entry of entries) {
|
|
916
|
+
const record3 = entryRecord(
|
|
917
|
+
entry,
|
|
918
|
+
(line) => line.includes('"type":"user"') || line.includes('"type":"assistant"')
|
|
919
|
+
);
|
|
920
|
+
if (record3 !== void 0) records.push(record3);
|
|
388
921
|
}
|
|
389
922
|
return records;
|
|
390
923
|
}
|
|
@@ -573,6 +1106,14 @@ var PAGE_LIMIT = 50;
|
|
|
573
1106
|
var MAX_PAGES = 10;
|
|
574
1107
|
var MAX_ROWS2 = 50;
|
|
575
1108
|
var PREVIEW_LIMIT2 = 200;
|
|
1109
|
+
var MAX_PARSED_LINE_CHARS = 1e6;
|
|
1110
|
+
var ROLLOUT_FIELDS = [
|
|
1111
|
+
{ path: ["type"] },
|
|
1112
|
+
{ path: ["payload", "id"] },
|
|
1113
|
+
{ path: ["payload", "session_id"] },
|
|
1114
|
+
{ path: ["payload", "cwd"] },
|
|
1115
|
+
{ path: ["payload", "model"] }
|
|
1116
|
+
];
|
|
576
1117
|
function truncate2(value) {
|
|
577
1118
|
const trimmed = value?.trim() ?? "";
|
|
578
1119
|
if (trimmed.length === 0) return null;
|
|
@@ -691,13 +1232,23 @@ async function readRolloutModel(input, rolloutPath, sameDirectory) {
|
|
|
691
1232
|
let verified = false;
|
|
692
1233
|
let model = null;
|
|
693
1234
|
try {
|
|
694
|
-
|
|
695
|
-
|
|
1235
|
+
const entries = readJsonlEntries(input.fs, resolved, {
|
|
1236
|
+
maxLineChars: MAX_PARSED_LINE_CHARS,
|
|
1237
|
+
fields: ROLLOUT_FIELDS
|
|
1238
|
+
});
|
|
1239
|
+
for await (const entry of entries) {
|
|
696
1240
|
let record3;
|
|
697
|
-
|
|
698
|
-
record3 = asRecord(
|
|
699
|
-
}
|
|
700
|
-
|
|
1241
|
+
if ("oversized" in entry) {
|
|
1242
|
+
record3 = asRecord(entry.oversized);
|
|
1243
|
+
} else {
|
|
1244
|
+
if (!entry.line.includes('"session_meta"') && !entry.line.includes('"turn_context"')) {
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
try {
|
|
1248
|
+
record3 = asRecord(JSON.parse(entry.line));
|
|
1249
|
+
} catch {
|
|
1250
|
+
continue;
|
|
1251
|
+
}
|
|
701
1252
|
}
|
|
702
1253
|
const payload = asRecord(record3?.payload);
|
|
703
1254
|
if (!record3 || !payload) continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/plugin-session-import",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2544",
|
|
4
4
|
"description": "Brings a session you started in a terminal into Ycodium.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"session-import",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"effect": "4.0.0-beta.103",
|
|
21
21
|
"esbuild": "0.28.1",
|
|
22
22
|
"vite-plus": "0.2.2",
|
|
23
|
-
"@ycodium-ai/plugin-api": "0.2.
|
|
23
|
+
"@ycodium-ai/plugin-api": "0.2.2544"
|
|
24
24
|
},
|
|
25
25
|
"ycodium": {
|
|
26
26
|
"plugin": "./dist/index.js",
|