sidekick-shared 0.27.6 → 0.28.1
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/CHANGELOG.md +34 -0
- package/README.md +59 -18
- package/dist/browser.d.ts +13 -2
- package/dist/browser.js +30 -2
- package/dist/claudePaths.d.ts +11 -0
- package/dist/claudePaths.js +61 -0
- package/dist/claudeProfiles.d.ts +2 -9
- package/dist/claudeProfiles.js +10 -25
- package/dist/codexPaths.d.ts +22 -0
- package/dist/codexPaths.js +67 -0
- package/dist/codexProfiles.d.ts +1 -4
- package/dist/codexProfiles.js +5 -43
- package/dist/doctor.js +2 -2
- package/dist/esm/accountChangeSignal.js +15 -0
- package/dist/esm/accountChanges.js +152 -0
- package/dist/esm/accountHealth.js +288 -0
- package/dist/esm/accountLaunch.js +145 -0
- package/dist/esm/accountLease.js +60 -0
- package/dist/esm/accountManager.js +606 -0
- package/dist/esm/accountRegistry.js +214 -0
- package/dist/esm/accountStatus.js +51 -0
- package/dist/esm/accountSwitch.js +74 -0
- package/dist/esm/accountSync.js +156 -0
- package/dist/esm/accountSyncTypes.js +4 -0
- package/dist/esm/accounts.js +1291 -0
- package/dist/esm/aggregation/EventAggregator.js +2034 -0
- package/dist/esm/aggregation/FrequencyTracker.js +69 -0
- package/dist/esm/aggregation/HeatmapTracker.js +89 -0
- package/dist/esm/aggregation/PatternExtractor.js +168 -0
- package/dist/esm/aggregation/costProvenance.js +31 -0
- package/dist/esm/aggregation/snapshot.js +161 -0
- package/dist/esm/aggregation/types.js +5 -0
- package/dist/esm/analytics/codeImpact.js +18 -0
- package/dist/esm/analytics/compactionLedger.js +37 -0
- package/dist/esm/analytics/qualityScore.js +112 -0
- package/dist/esm/autoSwitch.js +185 -0
- package/dist/esm/browser.js +34 -0
- package/dist/esm/claudeCredentialDoctor.js +239 -0
- package/dist/esm/claudeCredentialLedger.js +91 -0
- package/dist/esm/claudeCredentials.js +111 -0
- package/dist/esm/claudeLiveGuard.js +43 -0
- package/dist/esm/claudePaths.js +22 -0
- package/dist/esm/claudeProfiles.js +142 -0
- package/dist/esm/claudeRefreshLock.js +106 -0
- package/dist/esm/codexAuth.js +101 -0
- package/dist/esm/codexCredentialDoctor.js +265 -0
- package/dist/esm/codexCredentialStore.js +164 -0
- package/dist/esm/codexKeepAlive.js +112 -0
- package/dist/esm/codexPaths.js +172 -0
- package/dist/esm/codexProfiles.js +1251 -0
- package/dist/esm/codexQuota.js +564 -0
- package/dist/esm/codexQuotaWatcher.js +363 -0
- package/dist/esm/context/composer.js +71 -0
- package/dist/esm/context/sessionContext.js +546 -0
- package/dist/esm/credentialIO.js +283 -0
- package/dist/esm/credentials.js +49 -0
- package/dist/esm/doctor.js +305 -0
- package/dist/esm/ensureDefaultAccounts.js +62 -0
- package/dist/esm/errorHistory.js +56 -0
- package/dist/esm/extractors/errorTaxonomy.js +43 -0
- package/dist/esm/extractors/gatherAssets.js +32 -0
- package/dist/esm/extractors/sessionAssets.js +176 -0
- package/dist/esm/extractors/sources/claudeAssets.js +158 -0
- package/dist/esm/extractors/sources/codexAssets.js +234 -0
- package/dist/esm/extractors/tokenUsage.js +41 -0
- package/dist/esm/extractors/toolCall.js +142 -0
- package/dist/esm/failingTools.js +65 -0
- package/dist/esm/fileHead.js +27 -0
- package/dist/esm/formatters/eventHighlighter.js +332 -0
- package/dist/esm/formatters/noiseClassifier.js +209 -0
- package/dist/esm/formatters/sessionDump.js +328 -0
- package/dist/esm/formatters/toolSummary.js +226 -0
- package/dist/esm/formatting.js +82 -0
- package/dist/esm/handoffUrl.js +23 -0
- package/dist/esm/historicalStore.js +305 -0
- package/dist/esm/humanPrompt.js +88 -0
- package/dist/esm/index.js +213 -0
- package/dist/esm/keepAlive.js +189 -0
- package/dist/esm/liveCredentialGuard.js +33 -0
- package/dist/esm/modelAliases.js +51 -0
- package/dist/esm/modelCatalog.js +139 -0
- package/dist/esm/modelContext.js +280 -0
- package/dist/esm/modelInfo.js +832 -0
- package/dist/esm/multiProviderQuotaService.js +450 -0
- package/dist/esm/node.js +46 -0
- package/dist/esm/observedContextWindows.js +165 -0
- package/dist/esm/observedSessionCollector.js +939 -0
- package/dist/esm/parsers/changelogParser.js +71 -0
- package/dist/esm/parsers/codexHistory.js +89 -0
- package/dist/esm/parsers/codexParser.js +906 -0
- package/dist/esm/parsers/debugLogParser.js +126 -0
- package/dist/esm/parsers/jsonl.js +66 -0
- package/dist/esm/parsers/mcpToolName.js +28 -0
- package/dist/esm/parsers/openCodeParser.js +625 -0
- package/dist/esm/parsers/planExtractor.js +335 -0
- package/dist/esm/parsers/sessionActivityDetector.js +246 -0
- package/dist/esm/parsers/sessionPathResolver.js +713 -0
- package/dist/esm/parsers/subagentScanner.js +360 -0
- package/dist/esm/parsers/subagentStatsCache.js +45 -0
- package/dist/esm/parsers/subagentTraceParser.js +325 -0
- package/dist/esm/paths.js +134 -0
- package/dist/esm/peakHours.js +194 -0
- package/dist/esm/phrases.js +1330 -0
- package/dist/esm/pricingCatalog.js +247 -0
- package/dist/esm/processDetection.js +200 -0
- package/dist/esm/projectMigration.js +59 -0
- package/dist/esm/promptHistory.js +1221 -0
- package/dist/esm/providerFailure.js +362 -0
- package/dist/esm/providerIds.js +6 -0
- package/dist/esm/providerQuota.js +1 -0
- package/dist/esm/providerServiceStatus.js +145 -0
- package/dist/esm/providerServiceStatusTypes.js +1 -0
- package/dist/esm/providerStatus.js +117 -0
- package/dist/esm/providers/claudeCode.js +575 -0
- package/dist/esm/providers/claudeListing.js +121 -0
- package/dist/esm/providers/codex.js +1034 -0
- package/dist/esm/providers/codexDatabase.js +297 -0
- package/dist/esm/providers/codexRollouts.js +215 -0
- package/dist/esm/providers/detect.js +185 -0
- package/dist/esm/providers/diagnostics.js +83 -0
- package/dist/esm/providers/directoryListingCache.js +206 -0
- package/dist/esm/providers/factory.js +54 -0
- package/dist/esm/providers/openCode.js +2008 -0
- package/dist/esm/providers/openCodeDatabase.js +419 -0
- package/dist/esm/providers/rolloutWalker.js +252 -0
- package/dist/esm/providers/types.js +12 -0
- package/dist/esm/quota.js +182 -0
- package/dist/esm/quotaHistory.js +364 -0
- package/dist/esm/quotaPoller.js +230 -0
- package/dist/esm/quotaPresentation.js +97 -0
- package/dist/esm/quotaResolver.js +231 -0
- package/dist/esm/quotaSnapshots.js +130 -0
- package/dist/esm/quotaThresholds.js +85 -0
- package/dist/esm/readers/decisions.js +24 -0
- package/dist/esm/readers/handoff.js +20 -0
- package/dist/esm/readers/helpers.js +27 -0
- package/dist/esm/readers/history.js +9 -0
- package/dist/esm/readers/notes.js +48 -0
- package/dist/esm/readers/plans.js +225 -0
- package/dist/esm/readers/tasks.js +19 -0
- package/dist/esm/report/htmlHelpers.js +280 -0
- package/dist/esm/report/htmlReportGenerator.js +704 -0
- package/dist/esm/report/index.js +7 -0
- package/dist/esm/report/logo.js +2 -0
- package/dist/esm/report/openBrowser.js +19 -0
- package/dist/esm/report/sessionReportInputs.js +33 -0
- package/dist/esm/report/transcriptParser.js +83 -0
- package/dist/esm/report/types.js +4 -0
- package/dist/esm/schemas/accountManager.js +204 -0
- package/dist/esm/schemas/accountStatus.js +25 -0
- package/dist/esm/schemas/assistantTurn.js +74 -0
- package/dist/esm/schemas/index.js +25 -0
- package/dist/esm/schemas/observedSessionV1.js +77 -0
- package/dist/esm/schemas/providerFailure.js +37 -0
- package/dist/esm/schemas/quota.js +132 -0
- package/dist/esm/schemas/quotaHistory.js +40 -0
- package/dist/esm/schemas/sessionEvent.js +216 -0
- package/dist/esm/schemas/stateFile.js +75 -0
- package/dist/esm/schemas/tokenEstimation.js +7 -0
- package/dist/esm/schemas/transcript.js +86 -0
- package/dist/esm/schemas/usageNormalization.js +38 -0
- package/dist/esm/search/advancedFilter.js +197 -0
- package/dist/esm/search/sessionSearch.js +66 -0
- package/dist/esm/sessionFingerprint.js +40 -0
- package/dist/esm/sessionMonitor.js +198 -0
- package/dist/esm/sessionPreviews.js +522 -0
- package/dist/esm/sessionPromptHistory.js +254 -0
- package/dist/esm/sessionPromptSignals.js +364 -0
- package/dist/esm/sessionStats.js +160 -0
- package/dist/esm/sessionTokenTotals.js +98 -0
- package/dist/esm/sessionTranscripts.js +49 -0
- package/dist/esm/stateFile.js +119 -0
- package/dist/esm/statusline/BurnRateCalculator.js +40 -0
- package/dist/esm/statusline/claudeStatuslinePayload.js +148 -0
- package/dist/esm/statusline/formatter.js +122 -0
- package/dist/esm/statusline/index.js +8 -0
- package/dist/esm/terminalSync.js +95 -0
- package/dist/esm/testing/credentialGuard.js +222 -0
- package/dist/esm/testing/index.js +12 -0
- package/dist/esm/testing/sessionLogFixtures.js +128 -0
- package/dist/esm/tokenEstimation.js +67 -0
- package/dist/esm/tokenSummary.js +113 -0
- package/dist/esm/toolCategory.js +82 -0
- package/dist/esm/transcript.js +257 -0
- package/dist/esm/turns/assistantTurn.js +373 -0
- package/dist/esm/types/codex.js +23 -0
- package/dist/esm/types/decisionLog.js +5 -0
- package/dist/esm/types/historicalData.js +47 -0
- package/dist/esm/types/knowledgeNote.js +15 -0
- package/dist/esm/types/observedSessionV1.js +257 -0
- package/dist/esm/types/opencode.js +12 -0
- package/dist/esm/types/plan.js +7 -0
- package/dist/esm/types/sessionEvent.js +10 -0
- package/dist/esm/types/taskPersistence.js +12 -0
- package/dist/esm/usage/billingBlocks.js +148 -0
- package/dist/esm/usage/claudeUsageDedupe.js +189 -0
- package/dist/esm/usage/importSessionHistory.js +84 -0
- package/dist/esm/usage/subagentUsage.js +18 -0
- package/dist/esm/usage/usageEvents.js +402 -0
- package/dist/esm/usage/usageReports.js +202 -0
- package/dist/esm/usageNormalization.js +95 -0
- package/dist/esm/watchers/eventBridge.js +219 -0
- package/dist/esm/watchers/factory.js +63 -0
- package/dist/esm/watchers/jsonlTail.js +289 -0
- package/dist/esm/watchers/jsonlWatcher.js +435 -0
- package/dist/esm/watchers/providerReaderWatcher.js +118 -0
- package/dist/esm/watchers/sqliteWatcher.js +285 -0
- package/dist/esm/watchers/types.js +4 -0
- package/dist/esm/workspaceRoots.js +56 -0
- package/dist/esm/writers/atomic.js +375 -0
- package/dist/esm/writers/decisions.js +51 -0
- package/dist/esm/writers/notes.js +46 -0
- package/dist/esm/writers/tasks.js +63 -0
- package/dist/esm/zaiQuota.js +323 -0
- package/dist/esm/zaiQuotaApi.js +271 -0
- package/dist/esm/zaiQuotaWatcher.js +265 -0
- package/dist/fileHead.d.ts +22 -0
- package/dist/fileHead.js +33 -0
- package/dist/index.d.ts +16 -7
- package/dist/index.js +49 -15
- package/dist/node.d.ts +13 -1
- package/dist/node.js +43 -2
- package/dist/parsers/codexHistory.js +2 -2
- package/dist/parsers/codexParser.d.ts +12 -0
- package/dist/parsers/codexParser.js +34 -12
- package/dist/parsers/debugLogParser.js +2 -2
- package/dist/parsers/sessionPathResolver.js +5 -4
- package/dist/promptHistory.d.ts +32 -0
- package/dist/promptHistory.js +115 -59
- package/dist/providerFailure.d.ts +12 -6
- package/dist/providerFailure.js +45 -0
- package/dist/providers/claudeCode.js +7 -99
- package/dist/providers/claudeListing.d.ts +22 -0
- package/dist/providers/claudeListing.js +158 -0
- package/dist/providers/codex.d.ts +3 -1
- package/dist/providers/codex.js +26 -227
- package/dist/providers/codexRollouts.d.ts +44 -0
- package/dist/providers/codexRollouts.js +261 -0
- package/dist/providers/detect.js +4 -4
- package/dist/readers/plans.js +3 -3
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.js +7 -2
- package/dist/schemas/providerFailure.d.ts +154 -0
- package/dist/schemas/providerFailure.js +40 -0
- package/dist/sessionPromptHistory.d.ts +12 -7
- package/dist/sessionPromptHistory.js +15 -3
- package/dist/sessionPromptSignals.d.ts +9 -0
- package/dist/sessionPromptSignals.js +13 -0
- package/dist/testing/credentialGuard.d.ts +23 -0
- package/dist/testing/credentialGuard.js +258 -0
- package/dist/testing/index.d.ts +14 -0
- package/dist/testing/index.js +22 -0
- package/dist/testing/sessionLogFixtures.d.ts +28 -0
- package/dist/testing/sessionLogFixtures.js +169 -0
- package/dist/tokenEstimation.d.ts +2 -0
- package/dist/tokenEstimation.js +21 -11
- package/dist/toolCategory.d.ts +18 -0
- package/dist/toolCategory.js +86 -0
- package/dist/types/codex.d.ts +4 -0
- package/dist/usage/usageEvents.d.ts +16 -0
- package/dist/usage/usageEvents.js +53 -9
- package/dist/watchers/jsonlTail.d.ts +26 -1
- package/dist/watchers/jsonlTail.js +136 -28
- package/dist/watchers/jsonlWatcher.js +7 -0
- package/dist/watchers/providerReaderWatcher.js +1 -0
- package/dist/watchers/types.d.ts +6 -0
- package/dist/workspaceRoots.d.ts +23 -0
- package/dist/workspaceRoots.js +93 -0
- package/package.json +22 -2
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyword-based semantic syntax highlighting for session event text.
|
|
3
|
+
*
|
|
4
|
+
* Applies cascading word-by-word colorization based on keyword categories:
|
|
5
|
+
* errors=red, success=green, warnings=yellow, actions=cyan, numbers=blue,
|
|
6
|
+
* URLs/paths=magenta, HTTP status codes and methods colored by semantics.
|
|
7
|
+
*
|
|
8
|
+
* Supports blessed (CLI), ANSI (terminal), and HTML (VS Code webview) output formats.
|
|
9
|
+
*
|
|
10
|
+
* @module formatters/eventHighlighter
|
|
11
|
+
*/
|
|
12
|
+
const BLESSED_COLORS = {
|
|
13
|
+
red: ['{red-fg}', '{/red-fg}'],
|
|
14
|
+
green: ['{green-fg}', '{/green-fg}'],
|
|
15
|
+
yellow: ['{yellow-fg}', '{/yellow-fg}'],
|
|
16
|
+
cyan: ['{cyan-fg}', '{/cyan-fg}'],
|
|
17
|
+
blue: ['{blue-fg}', '{/blue-fg}'],
|
|
18
|
+
magenta: ['{magenta-fg}', '{/magenta-fg}'],
|
|
19
|
+
grey: ['{grey-fg}', '{/grey-fg}'],
|
|
20
|
+
white: ['{white-fg}', '{/white-fg}'],
|
|
21
|
+
};
|
|
22
|
+
const ANSI_COLORS = {
|
|
23
|
+
red: ['\x1b[31m', '\x1b[0m'],
|
|
24
|
+
green: ['\x1b[32m', '\x1b[0m'],
|
|
25
|
+
yellow: ['\x1b[33m', '\x1b[0m'],
|
|
26
|
+
cyan: ['\x1b[36m', '\x1b[0m'],
|
|
27
|
+
blue: ['\x1b[34m', '\x1b[0m'],
|
|
28
|
+
magenta: ['\x1b[35m', '\x1b[0m'],
|
|
29
|
+
grey: ['\x1b[90m', '\x1b[0m'],
|
|
30
|
+
white: ['\x1b[37m', '\x1b[0m'],
|
|
31
|
+
};
|
|
32
|
+
const HTML_COLORS = {
|
|
33
|
+
red: ['<span class="sk-hl-error">', '</span>'],
|
|
34
|
+
green: ['<span class="sk-hl-success">', '</span>'],
|
|
35
|
+
yellow: ['<span class="sk-hl-warning">', '</span>'],
|
|
36
|
+
cyan: ['<span class="sk-hl-action">', '</span>'],
|
|
37
|
+
blue: ['<span class="sk-hl-number">', '</span>'],
|
|
38
|
+
magenta: ['<span class="sk-hl-path">', '</span>'],
|
|
39
|
+
grey: ['<span class="sk-hl-muted">', '</span>'],
|
|
40
|
+
white: ['<span class="sk-hl-default">', '</span>'],
|
|
41
|
+
};
|
|
42
|
+
function getColors(format) {
|
|
43
|
+
switch (format) {
|
|
44
|
+
case 'blessed':
|
|
45
|
+
return BLESSED_COLORS;
|
|
46
|
+
case 'ansi':
|
|
47
|
+
return ANSI_COLORS;
|
|
48
|
+
case 'html':
|
|
49
|
+
return HTML_COLORS;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const ERROR_KEYWORDS = new Set([
|
|
53
|
+
'error',
|
|
54
|
+
'errors',
|
|
55
|
+
'err',
|
|
56
|
+
'fail',
|
|
57
|
+
'failed',
|
|
58
|
+
'failure',
|
|
59
|
+
'failures',
|
|
60
|
+
'fatal',
|
|
61
|
+
'panic',
|
|
62
|
+
'crash',
|
|
63
|
+
'crashed',
|
|
64
|
+
'exception',
|
|
65
|
+
'exceptions',
|
|
66
|
+
'critical',
|
|
67
|
+
'alert',
|
|
68
|
+
'abort',
|
|
69
|
+
'aborted',
|
|
70
|
+
'denied',
|
|
71
|
+
'forbidden',
|
|
72
|
+
'rejected',
|
|
73
|
+
'invalid',
|
|
74
|
+
'illegal',
|
|
75
|
+
'corrupt',
|
|
76
|
+
'corrupted',
|
|
77
|
+
'broken',
|
|
78
|
+
'bug',
|
|
79
|
+
'segfault',
|
|
80
|
+
'timeout',
|
|
81
|
+
'timedout',
|
|
82
|
+
'timed-out',
|
|
83
|
+
'deadlock',
|
|
84
|
+
'overflow',
|
|
85
|
+
'underflow',
|
|
86
|
+
'null',
|
|
87
|
+
'undefined',
|
|
88
|
+
'nan',
|
|
89
|
+
'unhandled',
|
|
90
|
+
'uncaught',
|
|
91
|
+
'unreachable',
|
|
92
|
+
'missing',
|
|
93
|
+
'notfound',
|
|
94
|
+
'not-found',
|
|
95
|
+
'unavailable',
|
|
96
|
+
'disconnected',
|
|
97
|
+
'dropped',
|
|
98
|
+
]);
|
|
99
|
+
const SUCCESS_KEYWORDS = new Set([
|
|
100
|
+
'success',
|
|
101
|
+
'successful',
|
|
102
|
+
'succeeded',
|
|
103
|
+
'ok',
|
|
104
|
+
'done',
|
|
105
|
+
'complete',
|
|
106
|
+
'completed',
|
|
107
|
+
'passed',
|
|
108
|
+
'pass',
|
|
109
|
+
'resolved',
|
|
110
|
+
'fixed',
|
|
111
|
+
'ready',
|
|
112
|
+
'active',
|
|
113
|
+
'running',
|
|
114
|
+
'started',
|
|
115
|
+
'created',
|
|
116
|
+
'connected',
|
|
117
|
+
'established',
|
|
118
|
+
'accepted',
|
|
119
|
+
'approved',
|
|
120
|
+
'merged',
|
|
121
|
+
'deployed',
|
|
122
|
+
'installed',
|
|
123
|
+
'loaded',
|
|
124
|
+
'enabled',
|
|
125
|
+
'healthy',
|
|
126
|
+
'valid',
|
|
127
|
+
'verified',
|
|
128
|
+
]);
|
|
129
|
+
const WARNING_KEYWORDS = new Set([
|
|
130
|
+
'warn',
|
|
131
|
+
'warning',
|
|
132
|
+
'warnings',
|
|
133
|
+
'caution',
|
|
134
|
+
'deprecated',
|
|
135
|
+
'slow',
|
|
136
|
+
'retry',
|
|
137
|
+
'retrying',
|
|
138
|
+
'retries',
|
|
139
|
+
'pending',
|
|
140
|
+
'waiting',
|
|
141
|
+
'queued',
|
|
142
|
+
'stale',
|
|
143
|
+
'expired',
|
|
144
|
+
'expiring',
|
|
145
|
+
'limited',
|
|
146
|
+
'throttled',
|
|
147
|
+
'throttling',
|
|
148
|
+
'degraded',
|
|
149
|
+
'unstable',
|
|
150
|
+
'flaky',
|
|
151
|
+
'skipped',
|
|
152
|
+
'skip',
|
|
153
|
+
'ignored',
|
|
154
|
+
'unknown',
|
|
155
|
+
'unrecognized',
|
|
156
|
+
]);
|
|
157
|
+
const ACTION_KEYWORDS = new Set([
|
|
158
|
+
'read',
|
|
159
|
+
'write',
|
|
160
|
+
'edit',
|
|
161
|
+
'delete',
|
|
162
|
+
'create',
|
|
163
|
+
'update',
|
|
164
|
+
'insert',
|
|
165
|
+
'remove',
|
|
166
|
+
'add',
|
|
167
|
+
'modify',
|
|
168
|
+
'patch',
|
|
169
|
+
'merge',
|
|
170
|
+
'push',
|
|
171
|
+
'pull',
|
|
172
|
+
'fetch',
|
|
173
|
+
'send',
|
|
174
|
+
'receive',
|
|
175
|
+
'request',
|
|
176
|
+
'response',
|
|
177
|
+
'query',
|
|
178
|
+
'search',
|
|
179
|
+
'find',
|
|
180
|
+
'list',
|
|
181
|
+
'get',
|
|
182
|
+
'set',
|
|
183
|
+
'put',
|
|
184
|
+
'post',
|
|
185
|
+
'build',
|
|
186
|
+
'compile',
|
|
187
|
+
'test',
|
|
188
|
+
'deploy',
|
|
189
|
+
'install',
|
|
190
|
+
'run',
|
|
191
|
+
'execute',
|
|
192
|
+
'start',
|
|
193
|
+
'stop',
|
|
194
|
+
'restart',
|
|
195
|
+
'init',
|
|
196
|
+
'initialize',
|
|
197
|
+
'configure',
|
|
198
|
+
'spawn',
|
|
199
|
+
'call',
|
|
200
|
+
'invoke',
|
|
201
|
+
]);
|
|
202
|
+
const HTTP_METHODS = new Map([
|
|
203
|
+
['GET', 'green'],
|
|
204
|
+
['HEAD', 'green'],
|
|
205
|
+
['OPTIONS', 'green'],
|
|
206
|
+
['POST', 'yellow'],
|
|
207
|
+
['PUT', 'yellow'],
|
|
208
|
+
['PATCH', 'yellow'],
|
|
209
|
+
['DELETE', 'red'],
|
|
210
|
+
]);
|
|
211
|
+
// ── Patterns ──
|
|
212
|
+
const NUMBER_PATTERN = /^-?\d+(\.\d+)?(%|ms|s|m|h|d|k|K|M|G|T|B)?$/;
|
|
213
|
+
const PATH_PATTERN = /^[.~]?\/[\w./-]+|^[\w-]+\/[\w./-]+|^[\w-]+\.[\w.]+$/;
|
|
214
|
+
const URL_PATTERN = /^https?:\/\//;
|
|
215
|
+
/**
|
|
216
|
+
* Classify an HTTP status code by color.
|
|
217
|
+
* Returns null if the word is not a status code.
|
|
218
|
+
*/
|
|
219
|
+
function httpStatusColor(word) {
|
|
220
|
+
if (!/^\d{3}$/.test(word))
|
|
221
|
+
return null;
|
|
222
|
+
const code = parseInt(word, 10);
|
|
223
|
+
if (code >= 200 && code < 300)
|
|
224
|
+
return 'green';
|
|
225
|
+
if (code >= 300 && code < 400)
|
|
226
|
+
return 'yellow';
|
|
227
|
+
if (code >= 400)
|
|
228
|
+
return 'red';
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Determine the color for a single word based on keyword categories.
|
|
233
|
+
* Priority: errors > warnings > success > HTTP > actions > paths > numbers
|
|
234
|
+
*/
|
|
235
|
+
function classifyWord(word) {
|
|
236
|
+
const lower = word.toLowerCase();
|
|
237
|
+
// Strip common punctuation for keyword matching
|
|
238
|
+
const stripped = lower.replace(/[.,;:!?()[\]{}'"]+$/g, '').replace(/^['"([\]{}]+/, '');
|
|
239
|
+
if (ERROR_KEYWORDS.has(stripped))
|
|
240
|
+
return 'red';
|
|
241
|
+
if (WARNING_KEYWORDS.has(stripped))
|
|
242
|
+
return 'yellow';
|
|
243
|
+
if (SUCCESS_KEYWORDS.has(stripped))
|
|
244
|
+
return 'green';
|
|
245
|
+
// HTTP methods
|
|
246
|
+
const httpMethod = HTTP_METHODS.get(word.toUpperCase());
|
|
247
|
+
if (httpMethod)
|
|
248
|
+
return httpMethod;
|
|
249
|
+
// HTTP status codes
|
|
250
|
+
const statusColor = httpStatusColor(stripped);
|
|
251
|
+
if (statusColor)
|
|
252
|
+
return statusColor;
|
|
253
|
+
if (ACTION_KEYWORDS.has(stripped))
|
|
254
|
+
return 'cyan';
|
|
255
|
+
// Paths and URLs
|
|
256
|
+
if (URL_PATTERN.test(word) || PATH_PATTERN.test(word))
|
|
257
|
+
return 'magenta';
|
|
258
|
+
// Numbers
|
|
259
|
+
if (NUMBER_PATTERN.test(stripped))
|
|
260
|
+
return 'blue';
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
// ── LRU cache for highlighted results ──
|
|
264
|
+
const CACHE_MAX = 500;
|
|
265
|
+
const highlightCache = new Map();
|
|
266
|
+
function cacheKey(text, format) {
|
|
267
|
+
return `${format}:${text}`;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Apply keyword-based semantic highlighting to text.
|
|
271
|
+
*
|
|
272
|
+
* Splits text on whitespace and colors each word based on keyword category.
|
|
273
|
+
* Words not matching any category pass through uncolored.
|
|
274
|
+
*
|
|
275
|
+
* @param text - The text to highlight.
|
|
276
|
+
* @param format - Output format: 'blessed' (CLI), 'ansi' (terminal), or 'html' (webview).
|
|
277
|
+
* @returns The highlighted text with format-appropriate tags.
|
|
278
|
+
*/
|
|
279
|
+
export function highlight(text, format) {
|
|
280
|
+
if (!text)
|
|
281
|
+
return text;
|
|
282
|
+
const key = cacheKey(text, format);
|
|
283
|
+
const cached = highlightCache.get(key);
|
|
284
|
+
if (cached !== undefined)
|
|
285
|
+
return cached;
|
|
286
|
+
const colors = getColors(format);
|
|
287
|
+
const words = text.split(/(\s+)/); // Split preserving whitespace
|
|
288
|
+
const parts = [];
|
|
289
|
+
for (const segment of words) {
|
|
290
|
+
// Preserve whitespace segments as-is
|
|
291
|
+
if (/^\s+$/.test(segment)) {
|
|
292
|
+
parts.push(segment);
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const color = classifyWord(segment);
|
|
296
|
+
if (color) {
|
|
297
|
+
const [open, close] = colors[color];
|
|
298
|
+
parts.push(`${open}${segment}${close}`);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
parts.push(segment);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const result = parts.join('');
|
|
305
|
+
// LRU cache: evict oldest if full
|
|
306
|
+
if (highlightCache.size >= CACHE_MAX) {
|
|
307
|
+
const first = highlightCache.keys().next().value;
|
|
308
|
+
if (first !== undefined)
|
|
309
|
+
highlightCache.delete(first);
|
|
310
|
+
}
|
|
311
|
+
highlightCache.set(key, result);
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* CSS class definitions for HTML highlight format.
|
|
316
|
+
* Include this in webview stylesheets.
|
|
317
|
+
*/
|
|
318
|
+
export const HIGHLIGHT_CSS = `
|
|
319
|
+
.sk-hl-error { color: var(--vscode-charts-red, #f44747); }
|
|
320
|
+
.sk-hl-success { color: var(--vscode-charts-green, #89d185); }
|
|
321
|
+
.sk-hl-warning { color: var(--vscode-charts-yellow, #cca700); }
|
|
322
|
+
.sk-hl-action { color: var(--vscode-charts-blue, #4fc1ff); }
|
|
323
|
+
.sk-hl-number { color: var(--vscode-charts-purple, #b180d7); }
|
|
324
|
+
.sk-hl-path { color: var(--vscode-charts-orange, #cca700); }
|
|
325
|
+
.sk-hl-muted { opacity: 0.6; }
|
|
326
|
+
.sk-hl-default { }
|
|
327
|
+
.sk-search-match { background-color: var(--vscode-editor-findMatchHighlightBackground, rgba(234, 92, 0, 0.33)); }
|
|
328
|
+
`;
|
|
329
|
+
/** Clear the highlight cache (for testing or memory pressure). */
|
|
330
|
+
export function clearHighlightCache() {
|
|
331
|
+
highlightCache.clear();
|
|
332
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Noise classification pipeline for session events.
|
|
3
|
+
*
|
|
4
|
+
* Multi-layer classification system that filters system noise, sidechains,
|
|
5
|
+
* synthetic messages, and soft noise (system-reminder tags, empty outputs).
|
|
6
|
+
* Inspired by tail-claude's noise filtering.
|
|
7
|
+
*
|
|
8
|
+
* @module formatters/noiseClassifier
|
|
9
|
+
*/
|
|
10
|
+
// ── Hard Noise Detection ──
|
|
11
|
+
/** Hard noise types that should be dropped entirely from display. */
|
|
12
|
+
const HARD_NOISE_EVENT_TYPES = new Set(['file-history-snapshot', 'queue-operation', 'progress']);
|
|
13
|
+
const SYNTHETIC_MODEL_PREFIX = '<synthetic>';
|
|
14
|
+
/**
|
|
15
|
+
* Determines if an event is "hard noise" and should be dropped entirely.
|
|
16
|
+
*
|
|
17
|
+
* Hard noise includes:
|
|
18
|
+
* - System-type events (non-content)
|
|
19
|
+
* - Specific infrastructure event types (file-history-snapshot, queue-operation, progress)
|
|
20
|
+
* - Sidechain/subagent events (when filtering to main conversation)
|
|
21
|
+
* - Synthetic model entries (model starts with `<synthetic>`)
|
|
22
|
+
*/
|
|
23
|
+
export function isHardNoise(event) {
|
|
24
|
+
// Sidechain events are noise for the main timeline
|
|
25
|
+
if (event.isSidechain)
|
|
26
|
+
return true;
|
|
27
|
+
// Check for known noise event types in raw data
|
|
28
|
+
const rawType = event.type;
|
|
29
|
+
if (HARD_NOISE_EVENT_TYPES.has(rawType))
|
|
30
|
+
return true;
|
|
31
|
+
// Synthetic model entries
|
|
32
|
+
if (event.message?.model?.startsWith(SYNTHETIC_MODEL_PREFIX))
|
|
33
|
+
return true;
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* FollowEvent variant of hard noise detection.
|
|
38
|
+
*/
|
|
39
|
+
export function isHardNoiseFollowEvent(event) {
|
|
40
|
+
// System events that are just infrastructure
|
|
41
|
+
if (event.type === 'system') {
|
|
42
|
+
const summary = event.summary?.toLowerCase() ?? '';
|
|
43
|
+
// Keep "Session ended" type system events
|
|
44
|
+
if (summary.includes('session ended') || summary.includes('session started')) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
// Token count events from Codex are noise for timeline display
|
|
48
|
+
if (summary.startsWith('tokens:') || summary.startsWith('model:')) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
// ── Soft Noise Detection ──
|
|
55
|
+
const SYSTEM_REMINDER_PATTERN = /<system-reminder>[\s\S]*?<\/system-reminder>/;
|
|
56
|
+
const COMMAND_CAVEAT_PATTERNS = [
|
|
57
|
+
/IMPORTANT:.*?(?:never|always|must|should)/i,
|
|
58
|
+
/Note:.*?(?:do not|don't|avoid)/i,
|
|
59
|
+
];
|
|
60
|
+
const INTERRUPTION_MARKERS = ['interrupted by user', 'operation cancelled', 'aborted'];
|
|
61
|
+
/**
|
|
62
|
+
* Checks for soft noise that can be hidden but not dropped.
|
|
63
|
+
*
|
|
64
|
+
* Soft noise includes:
|
|
65
|
+
* - system-reminder XML tags in content
|
|
66
|
+
* - Command caveats (IMPORTANT/Note instructions)
|
|
67
|
+
* - Empty tool outputs
|
|
68
|
+
* - User interruption markers
|
|
69
|
+
*
|
|
70
|
+
* @returns A reason string if soft noise is detected, null otherwise.
|
|
71
|
+
*/
|
|
72
|
+
export function getSoftNoiseReason(event) {
|
|
73
|
+
const content = extractContent(event);
|
|
74
|
+
if (content && SYSTEM_REMINDER_PATTERN.test(content)) {
|
|
75
|
+
return 'system-reminder';
|
|
76
|
+
}
|
|
77
|
+
for (const pattern of COMMAND_CAVEAT_PATTERNS) {
|
|
78
|
+
if (content && pattern.test(content)) {
|
|
79
|
+
return 'command-caveat';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Empty tool results
|
|
83
|
+
if (event.type === 'tool_result') {
|
|
84
|
+
const output = event.result?.output;
|
|
85
|
+
if (output === '' || output === undefined || output === null) {
|
|
86
|
+
return 'empty-tool-output';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Interruption markers
|
|
90
|
+
if (content) {
|
|
91
|
+
for (const marker of INTERRUPTION_MARKERS) {
|
|
92
|
+
if (content.toLowerCase().includes(marker)) {
|
|
93
|
+
return 'interruption';
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
// ── Message Classification ──
|
|
100
|
+
/**
|
|
101
|
+
* Classifies a SessionEvent into semantic message categories.
|
|
102
|
+
*
|
|
103
|
+
* Categories:
|
|
104
|
+
* - `user` — human prompts
|
|
105
|
+
* - `ai` — assistant responses (text or tool calls)
|
|
106
|
+
* - `system` — tool results, compaction, infrastructure
|
|
107
|
+
* - `teammate` — teammate/subagent messages (from `<teammate-message>` blocks)
|
|
108
|
+
* - `compact` — compaction/summary events
|
|
109
|
+
*/
|
|
110
|
+
export function classifyMessage(event) {
|
|
111
|
+
switch (event.type) {
|
|
112
|
+
case 'user': {
|
|
113
|
+
const content = extractContent(event);
|
|
114
|
+
// Check for teammate messages
|
|
115
|
+
if (content && content.includes('<teammate-message>')) {
|
|
116
|
+
return 'teammate';
|
|
117
|
+
}
|
|
118
|
+
return 'user';
|
|
119
|
+
}
|
|
120
|
+
case 'assistant':
|
|
121
|
+
return 'ai';
|
|
122
|
+
case 'summary':
|
|
123
|
+
return 'compact';
|
|
124
|
+
case 'tool_use':
|
|
125
|
+
return 'ai';
|
|
126
|
+
case 'tool_result':
|
|
127
|
+
return 'system';
|
|
128
|
+
default:
|
|
129
|
+
return 'system';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* FollowEvent variant of message classification.
|
|
134
|
+
*/
|
|
135
|
+
export function classifyFollowEvent(event) {
|
|
136
|
+
switch (event.type) {
|
|
137
|
+
case 'user':
|
|
138
|
+
return 'user';
|
|
139
|
+
case 'assistant':
|
|
140
|
+
return 'ai';
|
|
141
|
+
case 'tool_use':
|
|
142
|
+
return 'ai';
|
|
143
|
+
case 'tool_result':
|
|
144
|
+
return 'system';
|
|
145
|
+
case 'summary':
|
|
146
|
+
return 'compact';
|
|
147
|
+
case 'system':
|
|
148
|
+
return 'system';
|
|
149
|
+
default:
|
|
150
|
+
return 'system';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// ── Merge Detection ──
|
|
154
|
+
/**
|
|
155
|
+
* Determines if the current event should be merged with the previous one.
|
|
156
|
+
*
|
|
157
|
+
* Consecutive assistant text messages (without tool calls between them)
|
|
158
|
+
* can be merged into a single display entry.
|
|
159
|
+
*/
|
|
160
|
+
export function shouldMergeWithPrevious(current, previous) {
|
|
161
|
+
if (!previous)
|
|
162
|
+
return false;
|
|
163
|
+
// Merge consecutive assistant text messages
|
|
164
|
+
if (current.type === 'assistant' && previous.type === 'assistant') {
|
|
165
|
+
// Don't merge if either has tool_use content blocks
|
|
166
|
+
const currentContent = current.message?.content;
|
|
167
|
+
const previousContent = previous.message?.content;
|
|
168
|
+
if (hasToolUseBlocks(currentContent) || hasToolUseBlocks(previousContent)) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
// ── Full Classification ──
|
|
176
|
+
/**
|
|
177
|
+
* Performs full noise classification on a SessionEvent.
|
|
178
|
+
* Combines hard noise detection, soft noise detection, and message classification.
|
|
179
|
+
*/
|
|
180
|
+
export function classifyNoise(event) {
|
|
181
|
+
return {
|
|
182
|
+
isHardNoise: isHardNoise(event),
|
|
183
|
+
softNoiseReason: getSoftNoiseReason(event),
|
|
184
|
+
messageClassification: classifyMessage(event),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// ── Helpers ──
|
|
188
|
+
function extractContent(event) {
|
|
189
|
+
const content = event.message?.content;
|
|
190
|
+
if (!content)
|
|
191
|
+
return null;
|
|
192
|
+
if (typeof content === 'string')
|
|
193
|
+
return content;
|
|
194
|
+
if (Array.isArray(content)) {
|
|
195
|
+
const texts = [];
|
|
196
|
+
for (const block of content) {
|
|
197
|
+
if (block.type === 'text' && typeof block.text === 'string') {
|
|
198
|
+
texts.push(block.text);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return texts.length > 0 ? texts.join('\n') : null;
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
function hasToolUseBlocks(content) {
|
|
206
|
+
if (!Array.isArray(content))
|
|
207
|
+
return false;
|
|
208
|
+
return content.some((b) => b.type === 'tool_use');
|
|
209
|
+
}
|