codex-session-insights 0.2.2 → 0.2.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 (2) hide show
  1. package/lib/llm-insights.js +40 -18
  2. package/package.json +2 -2
@@ -598,6 +598,7 @@ export async function estimateLlmAnalysisCost({ threadSummaries, options = {} })
598
598
  const facetModel = options.facetModel || DEFAULT_FACET_MODEL
599
599
  const fastSectionModel = options.fastSectionModel || DEFAULT_FAST_SECTION_MODEL
600
600
  const insightModel = options.insightModel || DEFAULT_INSIGHT_MODEL
601
+ const provider = options.provider || DEFAULT_PROVIDER
601
602
  const cacheRoot = resolveCacheRoot(options.cacheDir)
602
603
  const facetCacheDir = path.join(cacheRoot, 'facets')
603
604
  await fs.mkdir(facetCacheDir, { recursive: true })
@@ -619,8 +620,10 @@ export async function estimateLlmAnalysisCost({ threadSummaries, options = {} })
619
620
  let combineSummaryCalls = 0
620
621
  let estimatedFacetInputTokens = 0
621
622
  let estimatedFacetOutputTokens = 0
622
- let estimatedSummaryInputTokens = 0
623
- let estimatedSummaryOutputTokens = 0
623
+ let estimatedChunkSummaryInputTokens = 0
624
+ let estimatedChunkSummaryOutputTokens = 0
625
+ let estimatedCombineSummaryInputTokens = 0
626
+ let estimatedCombineSummaryOutputTokens = 0
624
627
  const facetSystemPrompt = buildFacetSystemPrompt(options.lang)
625
628
 
626
629
  for (const job of uncachedFacetJobs) {
@@ -628,7 +631,7 @@ export async function estimateLlmAnalysisCost({ threadSummaries, options = {} })
628
631
  const transcriptChars = transcript.length
629
632
  if (!transcriptChars) {
630
633
  estimatedFacetInputTokens += estimateModelInputTokens({
631
- provider: options.provider || DEFAULT_PROVIDER,
634
+ provider,
632
635
  systemPrompt: facetSystemPrompt,
633
636
  userPrompt: buildFacetExtractionPrompt(job.thread, `${job.thread.title || '(untitled)'}\n${job.thread.firstUserMessage || ''}`.trim(), options.lang),
634
637
  schema: FACET_SCHEMA,
@@ -640,7 +643,7 @@ export async function estimateLlmAnalysisCost({ threadSummaries, options = {} })
640
643
 
641
644
  if (transcriptChars <= LONG_TRANSCRIPT_THRESHOLD) {
642
645
  estimatedFacetInputTokens += estimateModelInputTokens({
643
- provider: options.provider || DEFAULT_PROVIDER,
646
+ provider,
644
647
  systemPrompt: facetSystemPrompt,
645
648
  userPrompt: buildFacetExtractionPrompt(job.thread, transcript, options.lang),
646
649
  schema: FACET_SCHEMA,
@@ -653,28 +656,28 @@ export async function estimateLlmAnalysisCost({ threadSummaries, options = {} })
653
656
  const chunks = chunkText(transcript, TRANSCRIPT_CHUNK_SIZE)
654
657
  chunkSummaryCalls += chunks.length
655
658
  for (const chunk of chunks) {
656
- estimatedSummaryInputTokens += estimateModelInputTokens({
657
- provider: options.provider || DEFAULT_PROVIDER,
659
+ estimatedChunkSummaryInputTokens += estimateModelInputTokens({
660
+ provider,
658
661
  systemPrompt: `${FACET_TRANSCRIPT_SUMMARY_DIRECTIVE}\n\nPreserve user goal, outcome, friction, command/tool issues, and what the assistant actually achieved.`,
659
662
  userPrompt: `Chunk 1 of ${chunks.length}\n\n${chunk}`,
660
663
  structured: false,
661
664
  })
662
- estimatedSummaryOutputTokens += 260
665
+ estimatedChunkSummaryOutputTokens += 260
663
666
  }
664
667
  const combinedSummaryChars = chunks.length * 1100
665
668
  if (combinedSummaryChars > LONG_TRANSCRIPT_THRESHOLD) {
666
669
  combineSummaryCalls += 1
667
- estimatedSummaryInputTokens += estimateModelInputTokens({
668
- provider: options.provider || DEFAULT_PROVIDER,
670
+ estimatedCombineSummaryInputTokens += estimateModelInputTokens({
671
+ provider,
669
672
  systemPrompt:
670
673
  'Combine these coding-session chunk summaries into one compact transcript summary. Keep only material signal for later facet extraction. Do not carry boilerplate, stack traces, or command details.',
671
674
  userPrompt: makePlaceholderText(combinedSummaryChars, 'Chunk summaries'),
672
675
  structured: false,
673
676
  })
674
- estimatedSummaryOutputTokens += 320
677
+ estimatedCombineSummaryOutputTokens += 320
675
678
  }
676
679
  estimatedFacetInputTokens += estimateModelInputTokens({
677
- provider: options.provider || DEFAULT_PROVIDER,
680
+ provider,
678
681
  systemPrompt: facetSystemPrompt,
679
682
  userPrompt: buildFacetExtractionPrompt(
680
683
  job.thread,
@@ -693,14 +696,25 @@ export async function estimateLlmAnalysisCost({ threadSummaries, options = {} })
693
696
  const estimatedSectionInputs = estimateSectionInputs(candidateThreads, facetJobs, options)
694
697
  const fastSectionCalls = SECTION_DEFS.filter(section => section.modelTier === 'fast').length
695
698
  const fullSectionCalls = SECTION_DEFS.filter(section => section.modelTier !== 'fast').length
696
- const estimatedFastSectionInputTokens = SECTION_DEFS.filter(section => section.modelTier === 'fast')
699
+ let estimatedFastSectionInputTokens = SECTION_DEFS.filter(section => section.modelTier === 'fast')
697
700
  .reduce((sum, section) => sum + estimatedSectionInputs[section.contextKind] + 500, 0)
698
701
  const estimatedFastSectionOutputTokens = fastSectionCalls * 500
699
- const estimatedFullSectionInputTokens = SECTION_DEFS.filter(section => section.modelTier !== 'fast')
702
+ let estimatedFullSectionInputTokens = SECTION_DEFS.filter(section => section.modelTier !== 'fast')
700
703
  .reduce((sum, section) => sum + estimatedSectionInputs[section.contextKind] + 650, 0)
701
704
  const estimatedFullSectionOutputTokens = fullSectionCalls * 700
702
- const estimatedAtAGlanceInputTokens = estimatedSectionInputs.at_a_glance + 2200
705
+ let estimatedAtAGlanceInputTokens = estimatedSectionInputs.at_a_glance + 2200
703
706
  const estimatedAtAGlanceOutputTokens = 260
707
+ const estimatedSummaryInputTokens =
708
+ estimatedChunkSummaryInputTokens + estimatedCombineSummaryInputTokens
709
+ const estimatedSummaryOutputTokens =
710
+ estimatedChunkSummaryOutputTokens + estimatedCombineSummaryOutputTokens
711
+
712
+ estimatedFacetInputTokens += estimateCodexCliFreshOverhead(provider, facetModel, uncachedFacetJobs.length)
713
+ estimatedChunkSummaryInputTokens += estimateCodexCliFreshOverhead(provider, facetModel, chunkSummaryCalls)
714
+ estimatedCombineSummaryInputTokens += estimateCodexCliFreshOverhead(provider, facetModel, combineSummaryCalls)
715
+ estimatedFastSectionInputTokens += estimateCodexCliFreshOverhead(provider, fastSectionModel, fastSectionCalls)
716
+ estimatedFullSectionInputTokens += estimateCodexCliFreshOverhead(provider, insightModel, fullSectionCalls)
717
+ estimatedAtAGlanceInputTokens += estimateCodexCliFreshOverhead(provider, insightModel, 1)
704
718
 
705
719
  const byStage = [
706
720
  buildEstimateBucket(
@@ -713,16 +727,16 @@ export async function estimateLlmAnalysisCost({ threadSummaries, options = {} })
713
727
  buildEstimateBucket(
714
728
  'transcript_summary:chunk',
715
729
  chunkSummaryCalls,
716
- estimatedSummaryInputTokens - (combineSummaryCalls ? estimateTokensFromChars(combineSummaryCalls * 1100) + combineSummaryCalls * 180 : 0),
730
+ estimatedChunkSummaryInputTokens,
717
731
  0,
718
- estimatedSummaryOutputTokens - combineSummaryCalls * 320,
732
+ estimatedChunkSummaryOutputTokens,
719
733
  ),
720
734
  buildEstimateBucket(
721
735
  'transcript_summary:combine',
722
736
  combineSummaryCalls,
723
- combineSummaryCalls ? estimateTokensFromChars(combineSummaryCalls * 1100) + combineSummaryCalls * 180 : 0,
737
+ estimatedCombineSummaryInputTokens,
724
738
  0,
725
- combineSummaryCalls * 320,
739
+ estimatedCombineSummaryOutputTokens,
726
740
  ),
727
741
  buildEstimateBucket(
728
742
  'section:fast',
@@ -822,6 +836,14 @@ export async function estimateLlmAnalysisCost({ threadSummaries, options = {} })
822
836
  }
823
837
  }
824
838
 
839
+ function estimateCodexCliFreshOverhead(provider, model, calls) {
840
+ if (provider !== 'codex-cli' || !calls) return 0
841
+ const normalized = String(model || '').trim()
842
+ if (normalized === 'gpt-5.4') return calls * 25_000
843
+ if (normalized === 'gpt-5.4-mini' || normalized === 'gpt-5.3-codex-spark') return calls * 4_500
844
+ return calls * 8_000
845
+ }
846
+
825
847
  async function planFacetJobs(threadSummaries, { cacheDir, model, uncachedLimit }) {
826
848
  const jobs = []
827
849
  let uncachedCount = 0
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "codex-session-insights",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Generate a report analyzing your Codex sessions.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "codex-session-insights": "./bin/codex-insights.js"
7
+ "codex-session-insights": "bin/codex-insights.js"
8
8
  },
9
9
  "files": [
10
10
  "bin",