codex-session-insights 0.1.0 → 0.2.0
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/README.md +4 -2
- package/lib/cli.js +22 -22
- package/lib/codex-data.js +42 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,8 +108,8 @@ npx codex-session-insights --provider openai --api-key $OPENAI_API_KEY
|
|
|
108
108
|
Current default analysis plan:
|
|
109
109
|
|
|
110
110
|
- `days`: `30`
|
|
111
|
-
- `limit`: `
|
|
112
|
-
- `facet-limit`: `
|
|
111
|
+
- `limit`: `200`
|
|
112
|
+
- `facet-limit`: `50`
|
|
113
113
|
- `provider`: `codex-cli`
|
|
114
114
|
- `facet-model`: `gpt-5.4-mini`
|
|
115
115
|
- `fast-section-model`: `gpt-5.4-mini`
|
|
@@ -120,6 +120,8 @@ Current default analysis plan:
|
|
|
120
120
|
|
|
121
121
|
Important behavior defaults:
|
|
122
122
|
|
|
123
|
+
- `limit` means the target number of substantive threads to include in the report, not just the first 50 indexed threads
|
|
124
|
+
- `facet-limit` means the max number of uncached per-thread facet analyses to run in a single report
|
|
123
125
|
- Report language follows a best-effort system locale check
|
|
124
126
|
- Main-thread analysis is the default; sub-agent threads are excluded unless you pass `--include-subagents`
|
|
125
127
|
- The CLI shows an estimate before running in interactive terminals
|
package/lib/cli.js
CHANGED
|
@@ -141,7 +141,7 @@ function parseArgs(argv) {
|
|
|
141
141
|
jsonPath: null,
|
|
142
142
|
htmlPath: null,
|
|
143
143
|
days: 30,
|
|
144
|
-
limit:
|
|
144
|
+
limit: 200,
|
|
145
145
|
preview: 50,
|
|
146
146
|
provider: 'codex-cli',
|
|
147
147
|
codexBin: null,
|
|
@@ -154,7 +154,7 @@ function parseArgs(argv) {
|
|
|
154
154
|
insightModel: null,
|
|
155
155
|
insightEffort: null,
|
|
156
156
|
cacheDir: null,
|
|
157
|
-
facetLimit:
|
|
157
|
+
facetLimit: 50,
|
|
158
158
|
lang: detectSystemLanguage(),
|
|
159
159
|
includeArchived: false,
|
|
160
160
|
includeSubagents: false,
|
|
@@ -330,7 +330,7 @@ Options:
|
|
|
330
330
|
--json-path <path> Exact path for report.json
|
|
331
331
|
--html-path <path> Exact path for report.html
|
|
332
332
|
--days <n> Only include threads updated in the last N days (default: 30)
|
|
333
|
-
--limit <n>
|
|
333
|
+
--limit <n> Target number of substantive threads to include (default: 200)
|
|
334
334
|
--preview <n> Number of threads to embed in the HTML report (default: 50)
|
|
335
335
|
--provider <name> Model provider: codex-cli or openai (default: codex-cli)
|
|
336
336
|
--codex-bin <path> Override the Codex CLI binary path for provider=codex-cli
|
|
@@ -344,7 +344,7 @@ Options:
|
|
|
344
344
|
Reasoning effort for lower-risk sections
|
|
345
345
|
--insight-model <name> Model for final report generation
|
|
346
346
|
--insight-effort <level> Reasoning effort for higher-risk sections
|
|
347
|
-
--facet-limit <n> Max uncached
|
|
347
|
+
--facet-limit <n> Max uncached thread facets to analyze (default: 50)
|
|
348
348
|
--cache-dir <path> Cache directory for session-meta and facet caches
|
|
349
349
|
--lang <code> Report language: en or zh-CN (default: system language)
|
|
350
350
|
--include-archived Include archived threads
|
|
@@ -657,8 +657,8 @@ function inferScopePreset(days) {
|
|
|
657
657
|
|
|
658
658
|
function inferDepthPreset(options) {
|
|
659
659
|
if (options.limit === 20 && options.facetLimit === 8) return 'conservative'
|
|
660
|
-
if (options.limit ===
|
|
661
|
-
if (options.limit ===
|
|
660
|
+
if (options.limit === 200 && options.facetLimit === 50) return 'standard'
|
|
661
|
+
if (options.limit === 400 && options.facetLimit === 50) return 'deep'
|
|
662
662
|
return 'custom'
|
|
663
663
|
}
|
|
664
664
|
|
|
@@ -682,8 +682,8 @@ function inferQualityPreset(options) {
|
|
|
682
682
|
|
|
683
683
|
function applyScopePreset(options, preset) {
|
|
684
684
|
if (preset === 'conservative') return { ...options, limit: 20, facetLimit: 8 }
|
|
685
|
-
if (preset === 'deep') return { ...options, limit:
|
|
686
|
-
return { ...options, limit:
|
|
685
|
+
if (preset === 'deep') return { ...options, limit: 400, facetLimit: 50 }
|
|
686
|
+
return { ...options, limit: 200, facetLimit: 50 }
|
|
687
687
|
}
|
|
688
688
|
|
|
689
689
|
function applyQualityPreset(options, preset) {
|
|
@@ -833,17 +833,17 @@ function getUiText(lang) {
|
|
|
833
833
|
scopeCustom: '自定义天数',
|
|
834
834
|
customDaysQuestion: '输入要分析的天数',
|
|
835
835
|
depthQuestion: '选择分析深度:',
|
|
836
|
-
depthConservative: '保守(20
|
|
837
|
-
depthStandard: '标准(
|
|
838
|
-
depthDeep: '深度(
|
|
836
|
+
depthConservative: '保守(20 个有效线程 / 8 个 facets)',
|
|
837
|
+
depthStandard: '标准(200 个有效线程 / 50 个 facets)',
|
|
838
|
+
depthDeep: '深度(400 个有效线程 / 50 个 facets)',
|
|
839
839
|
depthCustom: '自定义',
|
|
840
|
-
limitQuestion: '
|
|
841
|
-
facetLimitQuestion: '
|
|
840
|
+
limitQuestion: '输入目标有效线程数',
|
|
841
|
+
facetLimitQuestion: '输入最大新增 facet 数',
|
|
842
842
|
languageQuestion: '选择报告语言:',
|
|
843
843
|
outputDirQuestion: '输出目录',
|
|
844
844
|
openBrowserQuestion: '生成后自动打开浏览器?',
|
|
845
845
|
qualityQuestion: '选择分析质量预设:',
|
|
846
|
-
qualityCheaper: '更省(尽量用
|
|
846
|
+
qualityCheaper: '更省(尽量用 gpt-5.4-mini)',
|
|
847
847
|
qualityBalanced: '平衡',
|
|
848
848
|
qualityHigher: '更高质量(更多使用 gpt-5.4)',
|
|
849
849
|
yesDefault: '[Y/n]',
|
|
@@ -860,7 +860,7 @@ function getUiText(lang) {
|
|
|
860
860
|
toWord: '到',
|
|
861
861
|
likelyWord: '左右',
|
|
862
862
|
plannedCallsLabel: '预计调用数',
|
|
863
|
-
substantiveThreadsLabel: '
|
|
863
|
+
substantiveThreadsLabel: '纳入报告线程',
|
|
864
864
|
uncachedFacetsLabel: '未缓存 facets',
|
|
865
865
|
longTranscriptsLabel: '长 transcript',
|
|
866
866
|
inputEstimateLabel: '输入',
|
|
@@ -891,17 +891,17 @@ function getUiText(lang) {
|
|
|
891
891
|
scopeCustom: 'Custom days',
|
|
892
892
|
customDaysQuestion: 'Enter number of days to analyze',
|
|
893
893
|
depthQuestion: 'Choose analysis depth:',
|
|
894
|
-
depthConservative: 'Conservative (20 threads / 8 facets)',
|
|
895
|
-
depthStandard: 'Standard (
|
|
896
|
-
depthDeep: 'Deep (
|
|
894
|
+
depthConservative: 'Conservative (20 substantive threads / 8 facets)',
|
|
895
|
+
depthStandard: 'Standard (200 substantive threads / 50 facets)',
|
|
896
|
+
depthDeep: 'Deep (400 substantive threads / 50 facets)',
|
|
897
897
|
depthCustom: 'Custom',
|
|
898
|
-
limitQuestion: 'Enter
|
|
899
|
-
facetLimitQuestion: 'Enter max facet extraction count',
|
|
898
|
+
limitQuestion: 'Enter target substantive thread count',
|
|
899
|
+
facetLimitQuestion: 'Enter max new facet extraction count',
|
|
900
900
|
languageQuestion: 'Choose report language:',
|
|
901
901
|
outputDirQuestion: 'Output directory',
|
|
902
902
|
openBrowserQuestion: 'Open the report in your browser after generation?',
|
|
903
903
|
qualityQuestion: 'Choose quality preset:',
|
|
904
|
-
qualityCheaper: 'Cheaper (more
|
|
904
|
+
qualityCheaper: 'Cheaper (more gpt-5.4-mini)',
|
|
905
905
|
qualityBalanced: 'Balanced',
|
|
906
906
|
qualityHigher: 'Higher quality (more gpt-5.4)',
|
|
907
907
|
yesDefault: '[Y/n]',
|
|
@@ -918,7 +918,7 @@ function getUiText(lang) {
|
|
|
918
918
|
toWord: 'to',
|
|
919
919
|
likelyWord: 'likely',
|
|
920
920
|
plannedCallsLabel: 'planned calls',
|
|
921
|
-
substantiveThreadsLabel: '
|
|
921
|
+
substantiveThreadsLabel: 'threads in report',
|
|
922
922
|
uncachedFacetsLabel: 'uncached facets',
|
|
923
923
|
longTranscriptsLabel: 'long transcripts',
|
|
924
924
|
inputEstimateLabel: 'input',
|
package/lib/codex-data.js
CHANGED
|
@@ -44,6 +44,7 @@ export async function loadThreads({
|
|
|
44
44
|
codexHome,
|
|
45
45
|
sinceEpochSeconds,
|
|
46
46
|
limit,
|
|
47
|
+
offset,
|
|
47
48
|
includeArchived,
|
|
48
49
|
includeSubagents,
|
|
49
50
|
}) {
|
|
@@ -66,6 +67,7 @@ export async function loadThreads({
|
|
|
66
67
|
where.length ? `where ${where.join(' and ')}` : '',
|
|
67
68
|
'order by updated_at desc',
|
|
68
69
|
limit ? `limit ${Number(limit)}` : '',
|
|
70
|
+
offset ? `offset ${Number(offset)}` : '',
|
|
69
71
|
';',
|
|
70
72
|
]
|
|
71
73
|
.filter(Boolean)
|
|
@@ -115,11 +117,15 @@ export async function loadRolloutEvents(rolloutPath) {
|
|
|
115
117
|
return events
|
|
116
118
|
}
|
|
117
119
|
|
|
120
|
+
export function isSubstantiveThread(thread) {
|
|
121
|
+
if (thread.userMessages < 2) return false
|
|
122
|
+
if (thread.durationMinutes < 1) return false
|
|
123
|
+
return Boolean(String(thread.transcriptForAnalysis || '').trim())
|
|
124
|
+
}
|
|
125
|
+
|
|
118
126
|
export function filterSubstantiveThreads(threadSummaries) {
|
|
119
127
|
return [...threadSummaries]
|
|
120
|
-
.filter(
|
|
121
|
-
.filter(thread => thread.durationMinutes >= 1)
|
|
122
|
-
.filter(thread => Boolean(String(thread.transcriptForAnalysis || '').trim()))
|
|
128
|
+
.filter(isSubstantiveThread)
|
|
123
129
|
.sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt))
|
|
124
130
|
}
|
|
125
131
|
|
|
@@ -440,14 +446,43 @@ export function summarizeThread(thread, events) {
|
|
|
440
446
|
}
|
|
441
447
|
|
|
442
448
|
export async function collectThreadSummaries(options) {
|
|
443
|
-
const threads = await loadThreads(options)
|
|
444
449
|
const cacheDir = resolveSessionMetaCacheDir(options.cacheDir)
|
|
445
450
|
await fs.mkdir(cacheDir, { recursive: true })
|
|
446
451
|
|
|
452
|
+
const substantiveTarget = Number(options.limit ?? 0)
|
|
453
|
+
const pageSize = substantiveTarget > 0 ? substantiveTarget : 200
|
|
447
454
|
const summaries = []
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
455
|
+
let offset = 0
|
|
456
|
+
let substantiveCount = 0
|
|
457
|
+
|
|
458
|
+
while (true) {
|
|
459
|
+
const threads = await loadThreads({
|
|
460
|
+
...options,
|
|
461
|
+
limit: pageSize,
|
|
462
|
+
offset,
|
|
463
|
+
})
|
|
464
|
+
if (!threads.length) break
|
|
465
|
+
|
|
466
|
+
for (const thread of threads) {
|
|
467
|
+
const summary = await loadCachedOrFreshSummary(thread, cacheDir)
|
|
468
|
+
summaries.push(summary)
|
|
469
|
+
if (isSubstantiveThread(summary)) {
|
|
470
|
+
substantiveCount += 1
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (substantiveTarget > 0 && substantiveCount >= substantiveTarget) {
|
|
475
|
+
break
|
|
476
|
+
}
|
|
477
|
+
if (threads.length < pageSize) {
|
|
478
|
+
break
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
offset += threads.length
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (substantiveTarget > 0) {
|
|
485
|
+
return filterSubstantiveThreads(summaries).slice(0, substantiveTarget)
|
|
451
486
|
}
|
|
452
487
|
return summaries
|
|
453
488
|
}
|