sidekick-shared 0.21.1 → 0.21.3

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 (77) hide show
  1. package/README.md +45 -45
  2. package/dist/accountManager.js +9 -7
  3. package/dist/accountRegistry.js +18 -14
  4. package/dist/accountStatus.js +4 -1
  5. package/dist/accounts.js +60 -25
  6. package/dist/aggregation/EventAggregator.d.ts +14 -11
  7. package/dist/aggregation/EventAggregator.js +68 -31
  8. package/dist/aggregation/PatternExtractor.js +5 -4
  9. package/dist/autoSwitch.js +6 -12
  10. package/dist/claudeProfiles.js +3 -3
  11. package/dist/codexProfiles.js +45 -22
  12. package/dist/codexQuota.js +44 -16
  13. package/dist/codexQuotaWatcher.js +10 -3
  14. package/dist/context/composer.js +8 -6
  15. package/dist/context/sessionContext.js +12 -9
  16. package/dist/credentialIO.js +10 -8
  17. package/dist/extractors/sessionAssets.js +9 -1
  18. package/dist/extractors/sources/claudeAssets.js +7 -1
  19. package/dist/extractors/sources/codexAssets.js +14 -3
  20. package/dist/extractors/toolCall.js +1 -4
  21. package/dist/formatters/eventHighlighter.js +148 -28
  22. package/dist/formatters/noiseClassifier.js +3 -11
  23. package/dist/formatters/sessionDump.js +22 -13
  24. package/dist/formatters/toolSummary.js +1 -3
  25. package/dist/index.d.ts +25 -23
  26. package/dist/index.js +12 -3
  27. package/dist/modelContext.js +10 -8
  28. package/dist/modelInfo.js +11 -6
  29. package/dist/multiProviderQuotaService.js +10 -7
  30. package/dist/parsers/codexParser.js +170 -103
  31. package/dist/parsers/debugLogParser.js +5 -4
  32. package/dist/parsers/openCodeParser.js +66 -48
  33. package/dist/parsers/planExtractor.js +3 -3
  34. package/dist/parsers/sessionActivityDetector.js +10 -6
  35. package/dist/parsers/sessionPathResolver.js +29 -34
  36. package/dist/parsers/subagentScanner.js +21 -20
  37. package/dist/parsers/subagentTraceParser.js +7 -4
  38. package/dist/phrases.js +11 -11
  39. package/dist/providerStatus.js +3 -4
  40. package/dist/providers/claudeCode.js +3 -1
  41. package/dist/providers/codex.js +35 -14
  42. package/dist/providers/codexDatabase.js +14 -5
  43. package/dist/providers/detect.js +10 -6
  44. package/dist/providers/openCode.d.ts +4 -4
  45. package/dist/providers/openCode.js +96 -68
  46. package/dist/providers/openCodeDatabase.js +44 -17
  47. package/dist/quota.d.ts +19 -0
  48. package/dist/quota.js +50 -8
  49. package/dist/quotaHistory.js +10 -3
  50. package/dist/quotaSnapshots.d.ts +1 -1
  51. package/dist/quotaSnapshots.js +2 -2
  52. package/dist/readers/decisions.js +1 -1
  53. package/dist/readers/notes.js +5 -3
  54. package/dist/readers/plans.js +43 -23
  55. package/dist/readers/tasks.js +1 -1
  56. package/dist/report/htmlHelpers.js +135 -16
  57. package/dist/report/htmlReportGenerator.js +38 -12
  58. package/dist/report/transcriptParser.js +8 -2
  59. package/dist/schemas/index.d.ts +4 -4
  60. package/dist/schemas/quota.js +2 -10
  61. package/dist/schemas/sessionEvent.js +20 -10
  62. package/dist/search/advancedFilter.js +3 -3
  63. package/dist/search/sessionSearch.js +10 -4
  64. package/dist/terminalSync.js +4 -2
  65. package/dist/turns/assistantTurn.js +5 -1
  66. package/dist/watchers/eventBridge.js +56 -26
  67. package/dist/watchers/factory.js +5 -2
  68. package/dist/watchers/jsonlTail.js +3 -1
  69. package/dist/watchers/jsonlWatcher.js +128 -52
  70. package/dist/watchers/providerReaderWatcher.js +3 -1
  71. package/dist/watchers/sqliteWatcher.js +52 -22
  72. package/dist/zaiQuota.d.ts +6 -6
  73. package/dist/zaiQuota.js +6 -10
  74. package/dist/zaiQuotaApi.d.ts +33 -0
  75. package/dist/zaiQuotaApi.js +279 -0
  76. package/dist/zaiQuotaWatcher.js +10 -9
  77. package/package.json +5 -2
@@ -21,16 +21,20 @@ function normalizeRateLimits(rateLimits) {
21
21
  if (!rateLimits?.primary && !rateLimits?.secondary)
22
22
  return undefined;
23
23
  return {
24
- primary: rateLimits.primary ? {
25
- usedPercent: rateLimits.primary.used_percent || 0,
26
- windowMinutes: rateLimits.primary.window_minutes || 0,
27
- resetsAt: rateLimits.primary.resets_at || 0,
28
- } : undefined,
29
- secondary: rateLimits.secondary ? {
30
- usedPercent: rateLimits.secondary.used_percent || 0,
31
- windowMinutes: rateLimits.secondary.window_minutes || 0,
32
- resetsAt: rateLimits.secondary.resets_at || 0,
33
- } : undefined,
24
+ primary: rateLimits.primary
25
+ ? {
26
+ usedPercent: rateLimits.primary.used_percent || 0,
27
+ windowMinutes: rateLimits.primary.window_minutes || 0,
28
+ resetsAt: rateLimits.primary.resets_at || 0,
29
+ }
30
+ : undefined,
31
+ secondary: rateLimits.secondary
32
+ ? {
33
+ usedPercent: rateLimits.secondary.used_percent || 0,
34
+ windowMinutes: rateLimits.secondary.window_minutes || 0,
35
+ resetsAt: rateLimits.secondary.resets_at || 0,
36
+ }
37
+ : undefined,
34
38
  };
35
39
  }
36
40
  /**
@@ -62,7 +66,9 @@ function normalizeCodexToolInput(canonicalToolName, rawToolName, input) {
62
66
  const normalized = { ...input };
63
67
  normalized._sidekickRawToolName = rawToolName;
64
68
  // Codex exec_command uses cmd; monitor expects command for Bash context extraction.
65
- if (canonicalToolName === 'Bash' && typeof normalized.cmd === 'string' && normalized.command === undefined) {
69
+ if (canonicalToolName === 'Bash' &&
70
+ typeof normalized.cmd === 'string' &&
71
+ normalized.command === undefined) {
66
72
  normalized.command = normalized.cmd;
67
73
  }
68
74
  // request_user_input currently emits questions; keep as-is (compatible with AskUserQuestion extractor).
@@ -181,7 +187,8 @@ class CodexRolloutParser {
181
187
  const text = payload.base_instructions?.text?.trim();
182
188
  if (!text)
183
189
  return [];
184
- return [{
190
+ return [
191
+ {
185
192
  type: 'system',
186
193
  message: {
187
194
  role: 'system',
@@ -190,7 +197,8 @@ class CodexRolloutParser {
190
197
  content: [{ type: 'text', text }],
191
198
  },
192
199
  timestamp,
193
- }];
200
+ },
201
+ ];
194
202
  }
195
203
  handleResponseItem(timestamp, payload) {
196
204
  // payload IS the item directly (no .item wrapper)
@@ -220,7 +228,8 @@ class CodexRolloutParser {
220
228
  if (!text)
221
229
  return [];
222
230
  if (item.role === 'user') {
223
- return [{
231
+ return [
232
+ {
224
233
  type: 'user',
225
234
  message: {
226
235
  role: 'user',
@@ -228,10 +237,12 @@ class CodexRolloutParser {
228
237
  content: [{ type: 'text', text }],
229
238
  },
230
239
  timestamp,
231
- }];
240
+ },
241
+ ];
232
242
  }
233
243
  if (item.role === 'assistant') {
234
- return [{
244
+ return [
245
+ {
235
246
  type: 'assistant',
236
247
  message: {
237
248
  role: 'assistant',
@@ -240,10 +251,12 @@ class CodexRolloutParser {
240
251
  content: [{ type: 'text', text }],
241
252
  },
242
253
  timestamp,
243
- }];
254
+ },
255
+ ];
244
256
  }
245
257
  if (item.role === 'developer' || item.role === 'system') {
246
- return [{
258
+ return [
259
+ {
247
260
  type: 'system',
248
261
  message: {
249
262
  role: item.role,
@@ -252,17 +265,19 @@ class CodexRolloutParser {
252
265
  content: [{ type: 'text', text }],
253
266
  },
254
267
  timestamp,
255
- }];
268
+ },
269
+ ];
256
270
  }
257
271
  return [];
258
272
  }
259
273
  handleReasoning(timestamp, item) {
260
274
  const summaryTexts = (item.summary || [])
261
- .filter(s => s.type === 'summary_text' && s.text)
262
- .map(s => s.text);
275
+ .filter((s) => s.type === 'summary_text' && s.text)
276
+ .map((s) => s.text);
263
277
  if (summaryTexts.length === 0)
264
278
  return [];
265
- return [{
279
+ return [
280
+ {
266
281
  type: 'assistant',
267
282
  message: {
268
283
  role: 'assistant',
@@ -271,7 +286,8 @@ class CodexRolloutParser {
271
286
  content: [{ type: 'thinking', thinking: summaryTexts.join('\n') }],
272
287
  },
273
288
  timestamp,
274
- }];
289
+ },
290
+ ];
275
291
  }
276
292
  handleFunctionCall(timestamp, item) {
277
293
  let parsedArgs = {};
@@ -284,49 +300,59 @@ class CodexRolloutParser {
284
300
  const canonicalName = normalizeCodexToolName(item.name);
285
301
  const normalizedInput = normalizeCodexToolInput(canonicalName, item.name, parsedArgs);
286
302
  this.emittedToolUseIds.add(item.call_id);
287
- return [{
303
+ return [
304
+ {
288
305
  type: 'assistant',
289
306
  message: {
290
307
  role: 'assistant',
291
308
  id: item.id,
292
309
  model: this.currentModel || undefined,
293
- content: [{
310
+ content: [
311
+ {
294
312
  type: 'tool_use',
295
313
  id: item.call_id,
296
314
  name: canonicalName,
297
315
  input: normalizedInput,
298
- }],
316
+ },
317
+ ],
299
318
  },
300
319
  timestamp,
301
- }];
320
+ },
321
+ ];
302
322
  }
303
323
  handleFunctionCallOutput(timestamp, item) {
304
324
  const isError = parsePlainTextFailure(item.output);
305
- return [{
325
+ return [
326
+ {
306
327
  type: 'user',
307
328
  message: {
308
329
  role: 'user',
309
330
  id: `${item.call_id}:result`,
310
- content: [{
331
+ content: [
332
+ {
311
333
  type: 'tool_result',
312
334
  tool_use_id: item.call_id,
313
335
  content: item.output,
314
336
  is_error: isError,
315
- }],
337
+ },
338
+ ],
316
339
  },
317
340
  timestamp,
318
- }];
341
+ },
342
+ ];
319
343
  }
320
344
  handleLocalShellCall(timestamp, item) {
321
345
  const command = item.action?.command?.join(' ') || '';
322
346
  this.emittedToolUseIds.add(item.call_id);
323
- return [{
347
+ return [
348
+ {
324
349
  type: 'assistant',
325
350
  message: {
326
351
  role: 'assistant',
327
352
  id: item.id,
328
353
  model: this.currentModel || undefined,
329
- content: [{
354
+ content: [
355
+ {
330
356
  type: 'tool_use',
331
357
  id: item.call_id,
332
358
  name: 'Bash',
@@ -335,28 +361,31 @@ class CodexRolloutParser {
335
361
  workdir: item.action?.workdir,
336
362
  _sidekickRawToolName: 'local_shell_call',
337
363
  },
338
- }],
364
+ },
365
+ ],
339
366
  },
340
367
  timestamp,
341
- }];
368
+ },
369
+ ];
342
370
  }
343
371
  handleCustomToolCall(timestamp, item) {
344
372
  if (item.name === 'apply_patch') {
345
373
  const filePaths = extractPatchFilePaths(item.input);
346
374
  if (filePaths.length === 0)
347
375
  return [];
348
- const toolUseIds = filePaths.map(fp => `${item.call_id}-${fp}`);
376
+ const toolUseIds = filePaths.map((fp) => `${item.call_id}-${fp}`);
349
377
  this.patchExpandedToolUseIds.set(item.call_id, toolUseIds);
350
378
  for (const id of toolUseIds) {
351
379
  this.emittedToolUseIds.add(id);
352
380
  }
353
- return filePaths.map(fp => ({
381
+ return filePaths.map((fp) => ({
354
382
  type: 'assistant',
355
383
  message: {
356
384
  role: 'assistant',
357
385
  id: `${item.call_id}-${fp}`,
358
386
  model: this.currentModel || undefined,
359
- content: [{
387
+ content: [
388
+ {
360
389
  type: 'tool_use',
361
390
  id: `${item.call_id}-${fp}`,
362
391
  name: 'Edit',
@@ -364,7 +393,8 @@ class CodexRolloutParser {
364
393
  file_path: fp,
365
394
  _sidekickRawToolName: 'apply_patch',
366
395
  },
367
- }],
396
+ },
397
+ ],
368
398
  },
369
399
  timestamp,
370
400
  }));
@@ -380,21 +410,25 @@ class CodexRolloutParser {
380
410
  const canonicalName = normalizeCodexToolName(item.name);
381
411
  const normalizedInput = normalizeCodexToolInput(canonicalName, item.name, parsedInput);
382
412
  this.emittedToolUseIds.add(item.call_id);
383
- return [{
413
+ return [
414
+ {
384
415
  type: 'assistant',
385
416
  message: {
386
417
  role: 'assistant',
387
418
  id: item.call_id,
388
419
  model: this.currentModel || undefined,
389
- content: [{
420
+ content: [
421
+ {
390
422
  type: 'tool_use',
391
423
  id: item.call_id,
392
424
  name: canonicalName,
393
425
  input: normalizedInput,
394
- }],
426
+ },
427
+ ],
395
428
  },
396
429
  timestamp,
397
- }];
430
+ },
431
+ ];
398
432
  }
399
433
  handleCustomToolCallOutput(timestamp, item) {
400
434
  let isError = false;
@@ -411,24 +445,27 @@ class CodexRolloutParser {
411
445
  }
412
446
  const toolUseIds = this.patchExpandedToolUseIds.get(item.call_id) ?? [item.call_id];
413
447
  this.patchExpandedToolUseIds.delete(item.call_id);
414
- return toolUseIds.map(toolUseId => ({
448
+ return toolUseIds.map((toolUseId) => ({
415
449
  type: 'user',
416
450
  message: {
417
451
  role: 'user',
418
452
  id: `${toolUseId}:result`,
419
- content: [{
453
+ content: [
454
+ {
420
455
  type: 'tool_result',
421
456
  tool_use_id: toolUseId,
422
457
  content: item.output,
423
458
  is_error: isError,
424
459
  duration,
425
- }],
460
+ },
461
+ ],
426
462
  },
427
463
  timestamp,
428
464
  }));
429
465
  }
430
466
  handleCompacted(timestamp, payload) {
431
- return [{
467
+ return [
468
+ {
432
469
  type: 'summary',
433
470
  message: {
434
471
  role: 'assistant',
@@ -436,7 +473,8 @@ class CodexRolloutParser {
436
473
  content: payload.summary || 'Context compacted',
437
474
  },
438
475
  timestamp,
439
- }];
476
+ },
477
+ ];
440
478
  }
441
479
  handleTurnContext(payload) {
442
480
  if (payload.model) {
@@ -489,7 +527,8 @@ class CodexRolloutParser {
489
527
  role: 'assistant',
490
528
  id: `exec-${e.call_id}`,
491
529
  model: this.currentModel || undefined,
492
- content: [{
530
+ content: [
531
+ {
493
532
  type: 'tool_use',
494
533
  id: e.call_id,
495
534
  name: 'Bash',
@@ -498,7 +537,8 @@ class CodexRolloutParser {
498
537
  workdir: pending?.workdir,
499
538
  _sidekickRawToolName: 'exec_command',
500
539
  },
501
- }],
540
+ },
541
+ ],
502
542
  },
503
543
  timestamp: pending?.timestamp || timestamp,
504
544
  });
@@ -509,13 +549,15 @@ class CodexRolloutParser {
509
549
  message: {
510
550
  role: 'user',
511
551
  id: `exec-${e.call_id}:result`,
512
- content: [{
552
+ content: [
553
+ {
513
554
  type: 'tool_result',
514
555
  tool_use_id: e.call_id,
515
556
  content: output,
516
557
  is_error: e.exit_code !== 0,
517
558
  duration: e.duration_ms,
518
- }],
559
+ },
560
+ ],
519
561
  },
520
562
  timestamp,
521
563
  });
@@ -546,7 +588,8 @@ class CodexRolloutParser {
546
588
  role: 'assistant',
547
589
  id: `mcp-${e.call_id}`,
548
590
  model: this.currentModel || undefined,
549
- content: [{
591
+ content: [
592
+ {
550
593
  type: 'tool_use',
551
594
  id: e.call_id,
552
595
  name: normalizeCodexToolName(toolName),
@@ -555,7 +598,8 @@ class CodexRolloutParser {
555
598
  _sidekickRawToolName: toolName,
556
599
  _sidekickMcpServerName: pendingMcp?.server_name,
557
600
  },
558
- }],
601
+ },
602
+ ],
559
603
  },
560
604
  timestamp: pendingMcp?.timestamp || timestamp,
561
605
  });
@@ -565,13 +609,15 @@ class CodexRolloutParser {
565
609
  message: {
566
610
  role: 'user',
567
611
  id: `mcp-${e.call_id}:result`,
568
- content: [{
612
+ content: [
613
+ {
569
614
  type: 'tool_result',
570
615
  tool_use_id: e.call_id,
571
616
  content: e.result || '',
572
617
  is_error: e.is_error || false,
573
618
  duration: e.duration_ms,
574
- }],
619
+ },
620
+ ],
575
621
  },
576
622
  timestamp,
577
623
  });
@@ -579,20 +625,25 @@ class CodexRolloutParser {
579
625
  }
580
626
  case 'error': {
581
627
  const e = event;
582
- return [{
628
+ return [
629
+ {
583
630
  type: 'assistant',
584
631
  message: {
585
632
  role: 'assistant',
586
633
  id: `error-${timestamp}`,
587
634
  model: this.currentModel || undefined,
588
- content: [{ type: 'text', text: `[Error${e.code ? ` (${e.code})` : ''}] ${e.message}` }],
635
+ content: [
636
+ { type: 'text', text: `[Error${e.code ? ` (${e.code})` : ''}] ${e.message}` },
637
+ ],
589
638
  },
590
639
  timestamp,
591
- }];
640
+ },
641
+ ];
592
642
  }
593
643
  case 'context_compacted': {
594
644
  const e = event;
595
- return [{
645
+ return [
646
+ {
596
647
  type: 'summary',
597
648
  message: {
598
649
  role: 'assistant',
@@ -600,20 +651,23 @@ class CodexRolloutParser {
600
651
  content: e.summary || 'Context compacted',
601
652
  },
602
653
  timestamp,
603
- }];
654
+ },
655
+ ];
604
656
  }
605
657
  case 'patch_applied': {
606
658
  const e = event;
607
659
  if (!e.file_path)
608
660
  return [];
609
661
  const patchId = `patch-${timestamp}-${e.file_path}`;
610
- return [{
662
+ return [
663
+ {
611
664
  type: 'assistant',
612
665
  message: {
613
666
  role: 'assistant',
614
667
  id: patchId,
615
668
  model: this.currentModel || undefined,
616
- content: [{
669
+ content: [
670
+ {
617
671
  type: 'tool_use',
618
672
  id: patchId,
619
673
  name: 'Edit',
@@ -623,49 +677,56 @@ class CodexRolloutParser {
623
677
  deletions: e.deletions ?? 0,
624
678
  _sidekickRawToolName: 'patch_applied',
625
679
  },
626
- }],
680
+ },
681
+ ],
627
682
  },
628
683
  timestamp,
629
- }];
684
+ },
685
+ ];
630
686
  }
631
687
  case 'turn_started':
632
688
  case 'turn_complete':
633
- case 'task_started':
634
- {
635
- const collaborationMode = event.collaboration_mode_kind;
636
- if (collaborationMode !== 'plan' || this.inPlanMode)
637
- return [];
638
- this.inPlanMode = true;
639
- return [{
640
- type: 'assistant',
641
- message: {
642
- role: 'assistant',
643
- id: `plan-enter-${timestamp}`,
644
- model: this.currentModel || undefined,
645
- content: [{
646
- type: 'tool_use',
647
- id: `plan-enter-${timestamp}`,
648
- name: 'EnterPlanMode',
649
- input: {
650
- source: 'codex_task_started',
651
- _sidekickRawToolName: 'task_started',
652
- },
653
- }],
654
- },
655
- timestamp,
656
- }];
657
- }
689
+ case 'task_started': {
690
+ const collaborationMode = event.collaboration_mode_kind;
691
+ if (collaborationMode !== 'plan' || this.inPlanMode)
692
+ return [];
693
+ this.inPlanMode = true;
694
+ return [
695
+ {
696
+ type: 'assistant',
697
+ message: {
698
+ role: 'assistant',
699
+ id: `plan-enter-${timestamp}`,
700
+ model: this.currentModel || undefined,
701
+ content: [
702
+ {
703
+ type: 'tool_use',
704
+ id: `plan-enter-${timestamp}`,
705
+ name: 'EnterPlanMode',
706
+ input: {
707
+ source: 'codex_task_started',
708
+ _sidekickRawToolName: 'task_started',
709
+ },
710
+ },
711
+ ],
712
+ },
713
+ timestamp,
714
+ },
715
+ ];
716
+ }
658
717
  case 'task_complete':
659
718
  if (!this.inPlanMode)
660
719
  return [];
661
720
  this.inPlanMode = false;
662
- return [{
721
+ return [
722
+ {
663
723
  type: 'assistant',
664
724
  message: {
665
725
  role: 'assistant',
666
726
  id: `plan-exit-${timestamp}`,
667
727
  model: this.currentModel || undefined,
668
- content: [{
728
+ content: [
729
+ {
669
730
  type: 'tool_use',
670
731
  id: `plan-exit-${timestamp}`,
671
732
  name: 'ExitPlanMode',
@@ -673,10 +734,12 @@ class CodexRolloutParser {
673
734
  source: 'codex_task_complete',
674
735
  _sidekickRawToolName: 'task_complete',
675
736
  },
676
- }],
737
+ },
738
+ ],
677
739
  },
678
740
  timestamp,
679
- }];
741
+ },
742
+ ];
680
743
  case 'turn_aborted':
681
744
  case 'agent_reasoning':
682
745
  case 'agent_message':
@@ -691,17 +754,20 @@ class CodexRolloutParser {
691
754
  const normalizedRateLimits = normalizeRateLimits(rateLimits);
692
755
  if (!usage && !normalizedRateLimits)
693
756
  return [];
694
- const mappedUsage = usage ? {
695
- input_tokens: usage.input_tokens || 0,
696
- output_tokens: usage.output_tokens || 0,
697
- cache_read_input_tokens: usage.cached_input_tokens || 0,
698
- cache_creation_input_tokens: 0,
699
- reasoning_tokens: usage.reasoning_output_tokens || 0,
700
- } : undefined;
757
+ const mappedUsage = usage
758
+ ? {
759
+ input_tokens: usage.input_tokens || 0,
760
+ output_tokens: usage.output_tokens || 0,
761
+ cache_read_input_tokens: usage.cached_input_tokens || 0,
762
+ cache_creation_input_tokens: 0,
763
+ reasoning_tokens: usage.reasoning_output_tokens || 0,
764
+ }
765
+ : undefined;
701
766
  if (usage) {
702
767
  this.lastTokenUsage = usage;
703
768
  }
704
- return [{
769
+ return [
770
+ {
705
771
  type: 'system',
706
772
  message: {
707
773
  role: 'system',
@@ -713,7 +779,8 @@ class CodexRolloutParser {
713
779
  },
714
780
  timestamp,
715
781
  rateLimits: normalizedRateLimits,
716
- }];
782
+ },
783
+ ];
717
784
  }
718
785
  }
719
786
  exports.CodexRolloutParser = CodexRolloutParser;
@@ -103,7 +103,7 @@ function parseDebugLog(content) {
103
103
  */
104
104
  function filterByLevel(entries, minLevel) {
105
105
  const minOrder = LEVEL_ORDER[minLevel];
106
- return entries.filter(e => LEVEL_ORDER[e.level] >= minOrder);
106
+ return entries.filter((e) => LEVEL_ORDER[e.level] >= minOrder);
107
107
  }
108
108
  /**
109
109
  * Collapses consecutive identical log messages into single entries with counts.
@@ -138,9 +138,10 @@ function discoverDebugLogs() {
138
138
  try {
139
139
  if (!fs.existsSync(debugDir))
140
140
  return [];
141
- return fs.readdirSync(debugDir)
142
- .filter(f => f.endsWith('.log') || f.endsWith('.txt'))
143
- .map(name => {
141
+ return fs
142
+ .readdirSync(debugDir)
143
+ .filter((f) => f.endsWith('.log') || f.endsWith('.txt'))
144
+ .map((name) => {
144
145
  const fullPath = path.join(debugDir, name);
145
146
  try {
146
147
  const stat = fs.statSync(fullPath);