sidekick-shared 0.23.1 → 0.24.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 +115 -37
- package/dist/aggregation/EventAggregator.d.ts +5 -1
- package/dist/aggregation/EventAggregator.js +64 -131
- package/dist/aggregation/types.d.ts +3 -0
- package/dist/browser.d.ts +6 -0
- package/dist/browser.js +10 -1
- package/dist/context/sessionContext.js +8 -6
- package/dist/extractors/tokenUsage.js +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +23 -7
- package/dist/modelInfo.d.ts +17 -7
- package/dist/modelInfo.js +5 -2
- package/dist/node.d.ts +4 -0
- package/dist/node.js +8 -1
- package/dist/observedSessionCollector.d.ts +68 -0
- package/dist/observedSessionCollector.js +178 -0
- package/dist/parsers/codexParser.js +21 -6
- package/dist/parsers/openCodeParser.js +22 -1
- package/dist/parsers/subagentTraceParser.js +11 -5
- package/dist/providers/claudeCode.js +45 -1
- package/dist/providers/codex.js +17 -7
- package/dist/report/transcriptParser.d.ts +3 -11
- package/dist/report/transcriptParser.js +69 -154
- package/dist/schemas/index.d.ts +7 -1
- package/dist/schemas/index.js +18 -2
- package/dist/schemas/observedSessionV1.d.ts +32 -1
- package/dist/schemas/observedSessionV1.js +11 -1
- package/dist/schemas/sessionEvent.d.ts +353 -12
- package/dist/schemas/sessionEvent.js +76 -14
- package/dist/schemas/tokenEstimation.d.ts +14 -0
- package/dist/schemas/tokenEstimation.js +10 -0
- package/dist/schemas/transcript.d.ts +24 -0
- package/dist/schemas/transcript.js +81 -0
- package/dist/schemas/usageNormalization.d.ts +55 -0
- package/dist/schemas/usageNormalization.js +41 -0
- package/dist/sessionTranscripts.d.ts +16 -0
- package/dist/sessionTranscripts.js +47 -0
- package/dist/tokenEstimation.d.ts +24 -0
- package/dist/tokenEstimation.js +62 -0
- package/dist/transcript.d.ts +92 -0
- package/dist/transcript.js +240 -0
- package/dist/types/observedSessionV1.d.ts +3 -1
- package/dist/types/observedSessionV1.js +14 -1
- package/dist/types/sessionEvent.d.ts +65 -7
- package/dist/usageNormalization.d.ts +69 -0
- package/dist/usageNormalization.js +100 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,9 @@ Types, parsers, providers, readers, formatters, aggregation, search, reporting,
|
|
|
9
9
|
|
|
10
10
|
## Recent additions
|
|
11
11
|
|
|
12
|
+
- **Canonical usage and pricing** — provider-specific counters normalize into disjoint input/cache/output/reasoning categories with `normalizeProviderUsage()`; `calculateNormalizedUsageCost()` prevents cache/reasoning double counting and reports pricing provenance.
|
|
13
|
+
- **Transcripts and resilient collection** — `projectSessionTranscript()` is browser-safe; Node consumers can use `listRecentSessions()`, `readSessionTranscript()`, and `ObservedSessionCollector` across Claude Code, Codex, and OpenCode readers.
|
|
14
|
+
- **Shared token estimation** — `estimateTextTokens()` / `estimateSerializedTokens()` provide an injectable exact-counter path and the stable tokenizer-free `sidekick-fallback-v1` heuristic.
|
|
12
15
|
- **Observed-session V1 contracts** — versioned provider-neutral `ObservedAgentSessionV1` / `ProviderCapabilitiesV1` / `PendingUserRequestV1` shapes with `createProviderSessionAdapterV1()` adapters and matching Zod schemas in [`sidekick-shared/schemas`](#supported-import-paths).
|
|
13
16
|
- **Atomic writers** — `addTask()`, `completeTask()`, `addDecision()`, and `addNote()` merge into the shared task/decision/note stores atomically, so concurrent CLI and extension captures are never lost.
|
|
14
17
|
- **Doctor report** — `runDoctor()` builds a typed cross-provider health report (project identity, sessions, accounts, providers, dependencies); `formatHealthReport()` renders it for terminals.
|
|
@@ -27,40 +30,40 @@ npm install sidekick-shared
|
|
|
27
30
|
|
|
28
31
|
## API Overview
|
|
29
32
|
|
|
30
|
-
| Module | Description
|
|
31
|
-
| ------------------------------- |
|
|
32
|
-
| **Types** | Session events, OpenCode/Codex format types, persistence schemas (tasks, decisions, notes, plans, historical data)
|
|
33
|
-
| **Paths** | Config directory resolution, project data paths, workspace encoding
|
|
34
|
-
| **Readers** | Read tasks, decisions, notes, history, handoff, and plans from `~/.config/sidekick/`
|
|
35
|
-
| **Writers** | Atomic persistence writers — `atomicWriteJson()` / `updateJsonStoreAtomic()` plus lock-coordinated capture helpers `addTask()`, `completeTask()`, `addDecision()`, `addNote()` that merge into the shared stores without clobbering concurrent writers
|
|
36
|
-
| **Providers** | Session provider abstraction with Claude Code, OpenCode, and Codex implementations; auto-detection via filesystem
|
|
37
|
-
| **Observed Sessions (V1)** | Versioned provider-neutral observation contracts — `createProviderSessionAdapterV1()` / `derivePendingUserRequestV1()` with `ObservedAgentSessionV1`, `ProviderCapabilitiesV1`, `PendingUserRequestV1`, `SessionEvidenceRefV1`, and provenance/confidence wrapper types (Zod schemas in `sidekick-shared/schemas`)
|
|
38
|
-
| **Parsers** | JSONL event parsing, OpenCode/Codex format normalization, subagent scanning, session path resolution, debug log parsing
|
|
39
|
-
| **Watchers** | Live session file watching with event bridging, plus `createJsonlTail()` for raw incremental JSONL consumers
|
|
40
|
-
| **Formatters** | Display helpers (`formatTokenCount()`, `formatDurationMs()`), tool summary, noise classification, session dump (text/markdown/JSON), event highlighting
|
|
41
|
-
| **Search** | Cross-session full-text search, advanced filtering (substring, fuzzy, regex, date)
|
|
42
|
-
| **Aggregation** | Event aggregation, frequency tracking, activity heatmaps, pattern extraction
|
|
43
|
-
| **Analytics** | Session-quality scoring (beta) with factor contributions and weekly trends (`scoreSessionQuality()`, `calculateQualityTrend()`), code-impact metrics including cost per changed line and per-model churn/cost (`calculateCodeImpact()`), and reported-vs-heuristic compaction accounting (`calculateCompactionLedger()`, `formatCompactionLedger()`)
|
|
44
|
-
| **Error History** | Shared error taxonomy (`categorizeError()`, `extractErrorMessage()`) plus append-only per-project failure history (`appendErrorHistory()`, `readErrorHistory()`, `getTopFailingTools()`) behind per-tool/hour/model error rollups
|
|
45
|
-
| **Session Context** | Provider-neutral context evidence snapshots (`buildSessionContextSnapshot()`, `calculateSessionContextPressure()`, `createSessionContextProjector()`, `readSessionContextSnapshot()`): layered evidence sources, low/medium/high context pressure, and observed capabilities (tools, MCP servers, permission mode, rate limits)
|
|
46
|
-
| **Assistant Turns** | Browser-safe timeline/process/answer projection for provider-normalized assistant turns (`segmentAssistantTurn()`, `assistantTurnEventsFromSessionEvents()`), including interleaved reasoning, compact tool groups, and Claude `Task` subagent refs without prompt leakage
|
|
47
|
-
| **Report** | Self-contained HTML session report generation
|
|
48
|
-
| **Credentials** | Claude Max OAuth credential reading from `~/.claude/.credentials.json`
|
|
49
|
-
| **Quota** | Claude Max subscription quota fetching (5-hour and 7-day windows), Codex rate-limit extraction from event streams (plus Codex reset credits via `fetchCodexResetCreditsFromApi()`, attached to quota state by `fetchCodexQuotaFromApi()`), and authoritative z.ai Coding Plan quota fetching via `resolveZaiQuota()` / `fetchZaiQuotaFromApi()` (reads z.ai's `api/monitor/usage/quota/limit` endpoint with cached-snapshot fallback). The deprecated observed-traffic z.ai estimator exports were removed in 0.23.0 — `resolveZaiQuota()` is the single z.ai quota API
|
|
50
|
-
| **Provider Status** | API health checking via status.claude.com and status.openai.com (indicator, components, incidents)
|
|
51
|
-
| **Doctor** | Typed cross-provider health diagnostics — `runDoctor()` checks project identity, sessions, accounts, providers, and dependencies into a `HealthReport`; `formatHealthReport()` renders it and `getSessionDiagnostics()` exposes the per-provider session probe
|
|
52
|
-
| **Schemas** | Zod schemas for runtime validation of data crossing process/IPC boundaries — JSONL session events (`sessionEventSchema`, `messageUsageSchema`, `sessionMessageSchema`), assistant turns, observed-session V1 records, quota, account status, and quota history — plus `extractSessionEvents()` to unwrap `progress`-wrapped events. Also published fs-free via the [`sidekick-shared/schemas`](#supported-import-paths) subpath
|
|
53
|
-
| **Extractors** | Pure functions for single-event processing: `extractTokenUsage()`, `extractToolCall()` (top-level `tool_use`), `extractToolCalls()` (assistant content blocks), plus Node-only session asset extraction (`gatherAssetsForCwd()`, `readClaudeAssets()`, `readCodexAssets()`) for URLs, file paths, commands, and plans
|
|
54
|
-
| **Model Info & Pricing** | Model family parsing (Anthropic / OpenAI / Google, including legacy `claude-3-opus-…` and `claude-3-5-sonnet-…` IDs), context-window lookup (including Fable 5 / Opus 4.8 / Opus 4.7 / Sonnet 4.7 1M and GPT-5.x variants), pricing tables with optional LiteLLM hydration,
|
|
55
|
-
| **Quota Polling** | `QuotaPoller` class with exponential backoff, active/idle intervals, and cached fallback
|
|
56
|
-
| **Multi-Provider Quota** | `MultiProviderQuotaService` orchestrates Claude polling + peak-hours + account labels + Codex/z.ai quota updates behind one typed event stream. `CodexQuotaWatcher` watches the active Codex rollout for live rate limits with snapshot fallback; z.ai quota uses the API resolver with snapshot fallback
|
|
57
|
-
| **Accounts** | Multi-provider account registry (v2) with per-provider active account, save/switch/remove, v1 migration, `ensureDefaultAccounts()` for first-run bootstrap of the active system Claude/Codex credentials as a "Default" saved account, `getActiveAccountStatus()` for a single-pass active-account read across providers, and live-first `resolveActiveClaudeAccount()` / `resolveActiveCodexAccount()` that report the currently logged-in account (self-healing the saved pointer) for display
|
|
58
|
-
| **Account Management 2.0** | Provider-neutral acquisition + switching: `beginAccountLogin()` / `getAccountLoginStatus()` / `finalizeAccountLogin()` / `spawnAccountLogin()` drive a TTY-less, profile-isolated login that doesn't disturb the active account until finalization; `listAllAccounts()` and `switchAccount()` expose a shared switcher across Claude and Codex. Claude accounts get canonical profile homes with account-scoped macOS keychain suffixes and startup migration from legacy flat backups
|
|
59
|
-
| **Terminal sync & auto-switch** | Opt-in terminal profile pointers, shell-hook/launcher helpers, and a default-off `AutoSwitchController` (`decideAutoSwitch()`) that moves to a healthier saved account when quota crosses a configured threshold
|
|
60
|
-
| **Codex Profiles** | Codex account lifecycle — prepare, finalize, switch, remove — switching atomically swaps the profile's backed-up credentials into the system `~/.codex/auth.json`, with rotated-token staleness protection, one-time dual-home migration, and legacy multi-home session monitoring
|
|
61
|
-
| **Quota Snapshots** | Persistent quota caching per provider/account for offline fallback
|
|
62
|
-
| **Statusline** | Cache-only one-line account/quota/burn footer — `formatStatusline()`, `selectStatuslineAccount()`, `BurnRateCalculator`, and `estimateTimeToQuota()`, also published via the [`sidekick-shared/statusline`](#supported-import-paths) subpath for fast per-prompt rendering
|
|
63
|
-
| **Phrases** | Curated humorous phrases for loading/idle states, available as a flat `ALL_PHRASES` array or grouped via `PHRASE_CATEGORIES` for category-aware UI
|
|
33
|
+
| Module | Description |
|
|
34
|
+
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
35
|
+
| **Types** | Session events, OpenCode/Codex format types, persistence schemas (tasks, decisions, notes, plans, historical data) |
|
|
36
|
+
| **Paths** | Config directory resolution, project data paths, workspace encoding |
|
|
37
|
+
| **Readers** | Read tasks, decisions, notes, history, handoff, and plans from `~/.config/sidekick/` |
|
|
38
|
+
| **Writers** | Atomic persistence writers — `atomicWriteJson()` / `updateJsonStoreAtomic()` plus lock-coordinated capture helpers `addTask()`, `completeTask()`, `addDecision()`, `addNote()` that merge into the shared stores without clobbering concurrent writers |
|
|
39
|
+
| **Providers** | Session provider abstraction with Claude Code, OpenCode, and Codex implementations; auto-detection via filesystem |
|
|
40
|
+
| **Observed Sessions (V1)** | Versioned provider-neutral observation contracts — `createProviderSessionAdapterV1()` / `derivePendingUserRequestV1()` with `ObservedAgentSessionV1`, `ProviderCapabilitiesV1`, `PendingUserRequestV1`, `SessionEvidenceRefV1`, and provenance/confidence wrapper types (Zod schemas in `sidekick-shared/schemas`) |
|
|
41
|
+
| **Parsers** | JSONL event parsing, OpenCode/Codex format normalization, subagent scanning, session path resolution, debug log parsing |
|
|
42
|
+
| **Watchers** | Live session file watching with event bridging, plus `createJsonlTail()` for raw incremental JSONL consumers |
|
|
43
|
+
| **Formatters** | Display helpers (`formatTokenCount()`, `formatDurationMs()`), tool summary, noise classification, session dump (text/markdown/JSON), event highlighting |
|
|
44
|
+
| **Search** | Cross-session full-text search, advanced filtering (substring, fuzzy, regex, date) |
|
|
45
|
+
| **Aggregation** | Event aggregation, frequency tracking, activity heatmaps, pattern extraction |
|
|
46
|
+
| **Analytics** | Session-quality scoring (beta) with factor contributions and weekly trends (`scoreSessionQuality()`, `calculateQualityTrend()`), code-impact metrics including cost per changed line and per-model churn/cost (`calculateCodeImpact()`), and reported-vs-heuristic compaction accounting (`calculateCompactionLedger()`, `formatCompactionLedger()`) |
|
|
47
|
+
| **Error History** | Shared error taxonomy (`categorizeError()`, `extractErrorMessage()`) plus append-only per-project failure history (`appendErrorHistory()`, `readErrorHistory()`, `getTopFailingTools()`) behind per-tool/hour/model error rollups |
|
|
48
|
+
| **Session Context** | Provider-neutral context evidence snapshots (`buildSessionContextSnapshot()`, `calculateSessionContextPressure()`, `createSessionContextProjector()`, `readSessionContextSnapshot()`): layered evidence sources, low/medium/high context pressure, and observed capabilities (tools, MCP servers, permission mode, rate limits) |
|
|
49
|
+
| **Assistant Turns** | Browser-safe timeline/process/answer projection for provider-normalized assistant turns (`segmentAssistantTurn()`, `assistantTurnEventsFromSessionEvents()`), including interleaved reasoning, compact tool groups, and Claude `Task` subagent refs without prompt leakage |
|
|
50
|
+
| **Report** | Self-contained HTML session report generation |
|
|
51
|
+
| **Credentials** | Claude Max OAuth credential reading from `~/.claude/.credentials.json` |
|
|
52
|
+
| **Quota** | Claude Max subscription quota fetching (5-hour and 7-day windows), Codex rate-limit extraction from event streams (plus Codex reset credits via `fetchCodexResetCreditsFromApi()`, attached to quota state by `fetchCodexQuotaFromApi()`), and authoritative z.ai Coding Plan quota fetching via `resolveZaiQuota()` / `fetchZaiQuotaFromApi()` (reads z.ai's `api/monitor/usage/quota/limit` endpoint with cached-snapshot fallback). The deprecated observed-traffic z.ai estimator exports were removed in 0.23.0 — `resolveZaiQuota()` is the single z.ai quota API |
|
|
53
|
+
| **Provider Status** | API health checking via status.claude.com and status.openai.com (indicator, components, incidents) |
|
|
54
|
+
| **Doctor** | Typed cross-provider health diagnostics — `runDoctor()` checks project identity, sessions, accounts, providers, and dependencies into a `HealthReport`; `formatHealthReport()` renders it and `getSessionDiagnostics()` exposes the per-provider session probe |
|
|
55
|
+
| **Schemas** | Zod schemas for runtime validation of data crossing process/IPC boundaries — JSONL session events (`sessionEventSchema`, `messageUsageSchema`, `sessionMessageSchema`), assistant turns, observed-session V1 records, quota, account status, and quota history — plus `extractSessionEvents()` to unwrap `progress`-wrapped events. Also published fs-free via the [`sidekick-shared/schemas`](#supported-import-paths) subpath |
|
|
56
|
+
| **Extractors** | Pure functions for single-event processing: `extractTokenUsage()`, `extractToolCall()` (top-level `tool_use`), `extractToolCalls()` (assistant content blocks), plus Node-only session asset extraction (`gatherAssetsForCwd()`, `readClaudeAssets()`, `readCodexAssets()`) for URLs, file paths, commands, and plans |
|
|
57
|
+
| **Model Info & Pricing** | Model family parsing (Anthropic / OpenAI / Google, including legacy `claude-3-opus-…` and `claude-3-5-sonnet-…` IDs), context-window lookup (including Fable 5 / Opus 4.8 / Opus 4.7 / Sonnet 4.7 1M and GPT-5.x variants), pricing tables with optional LiteLLM hydration, normalized non-double-counting cost (`calculateNormalizedUsageCost()`, fed by `normalizeProviderUsage()` / `extractNormalizedUsage()`), legacy cost helpers retained but deprecated (`calculateCost()`, `calculateCostWithProvenance()`), `mergeCostSources()`, and display helpers (`shortModelName()`, `getModelDisplayInfo()`, `compareModelIds()`, `sortModelIds()`, `formatCost()`) |
|
|
58
|
+
| **Quota Polling** | `QuotaPoller` class with exponential backoff, active/idle intervals, and cached fallback |
|
|
59
|
+
| **Multi-Provider Quota** | `MultiProviderQuotaService` orchestrates Claude polling + peak-hours + account labels + Codex/z.ai quota updates behind one typed event stream. `CodexQuotaWatcher` watches the active Codex rollout for live rate limits with snapshot fallback; z.ai quota uses the API resolver with snapshot fallback |
|
|
60
|
+
| **Accounts** | Multi-provider account registry (v2) with per-provider active account, save/switch/remove, v1 migration, `ensureDefaultAccounts()` for first-run bootstrap of the active system Claude/Codex credentials as a "Default" saved account, `getActiveAccountStatus()` for a single-pass active-account read across providers, and live-first `resolveActiveClaudeAccount()` / `resolveActiveCodexAccount()` that report the currently logged-in account (self-healing the saved pointer) for display |
|
|
61
|
+
| **Account Management 2.0** | Provider-neutral acquisition + switching: `beginAccountLogin()` / `getAccountLoginStatus()` / `finalizeAccountLogin()` / `spawnAccountLogin()` drive a TTY-less, profile-isolated login that doesn't disturb the active account until finalization; `listAllAccounts()` and `switchAccount()` expose a shared switcher across Claude and Codex. Claude accounts get canonical profile homes with account-scoped macOS keychain suffixes and startup migration from legacy flat backups |
|
|
62
|
+
| **Terminal sync & auto-switch** | Opt-in terminal profile pointers, shell-hook/launcher helpers, and a default-off `AutoSwitchController` (`decideAutoSwitch()`) that moves to a healthier saved account when quota crosses a configured threshold |
|
|
63
|
+
| **Codex Profiles** | Codex account lifecycle — prepare, finalize, switch, remove — switching atomically swaps the profile's backed-up credentials into the system `~/.codex/auth.json`, with rotated-token staleness protection, one-time dual-home migration, and legacy multi-home session monitoring |
|
|
64
|
+
| **Quota Snapshots** | Persistent quota caching per provider/account for offline fallback |
|
|
65
|
+
| **Statusline** | Cache-only one-line account/quota/burn footer — `formatStatusline()`, `selectStatuslineAccount()`, `BurnRateCalculator`, and `estimateTimeToQuota()`, also published via the [`sidekick-shared/statusline`](#supported-import-paths) subpath for fast per-prompt rendering |
|
|
66
|
+
| **Phrases** | Curated humorous phrases for loading/idle states, available as a flat `ALL_PHRASES` array or grouped via `PHRASE_CATEGORIES` for category-aware UI |
|
|
64
67
|
|
|
65
68
|
## Supported import paths
|
|
66
69
|
|
|
@@ -69,8 +72,8 @@ npm install sidekick-shared
|
|
|
69
72
|
| Path | Runtime | What it exposes |
|
|
70
73
|
| ------------------------------ | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
71
74
|
| `sidekick-shared` | Node (CLI, extension host) | Full public API (readers, providers, parsers, pricing, …). |
|
|
72
|
-
| `sidekick-shared/browser` | **Browser / webview** | Pure helpers:
|
|
73
|
-
| `sidekick-shared/node` | Node only | LiteLLM pricing
|
|
75
|
+
| `sidekick-shared/browser` | **Browser / webview** | Pure helpers: usage normalization/pricing, token estimation, transcript and assistant-turn projection, model/context math. |
|
|
76
|
+
| `sidekick-shared/node` | Node only | LiteLLM pricing hydration, recent-session/transcript reads, and resilient observed-session collection (`fs` + providers). |
|
|
74
77
|
| `sidekick-shared/phrases` | Any runtime | Phrase arrays + `getRandomPhrase()`. |
|
|
75
78
|
| `sidekick-shared/modelContext` | Any runtime | Direct access to the context-window module. |
|
|
76
79
|
| `sidekick-shared/modelInfo` | Any runtime | Direct access to model parsing and cost math. |
|
|
@@ -87,7 +90,10 @@ import {
|
|
|
87
90
|
getModelContextWindowSize,
|
|
88
91
|
DEFAULT_CONTEXT_WINDOW,
|
|
89
92
|
parseModelId,
|
|
90
|
-
|
|
93
|
+
normalizeProviderUsage,
|
|
94
|
+
calculateNormalizedUsageCost,
|
|
95
|
+
estimateTextTokens,
|
|
96
|
+
projectSessionTranscript,
|
|
91
97
|
formatCost,
|
|
92
98
|
formatTokenCount,
|
|
93
99
|
formatDurationMs,
|
|
@@ -105,6 +111,78 @@ import { hydratePricingCatalog } from 'sidekick-shared/node';
|
|
|
105
111
|
await hydratePricingCatalog({ cacheDir: '~/.config/sidekick' });
|
|
106
112
|
```
|
|
107
113
|
|
|
114
|
+
### Normalize and price provider usage
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { normalizeProviderUsage, calculateNormalizedUsageCost } from 'sidekick-shared/browser';
|
|
118
|
+
|
|
119
|
+
const usage = normalizeProviderUsage({
|
|
120
|
+
semantics: 'openai',
|
|
121
|
+
provider: 'openai',
|
|
122
|
+
model: 'gpt-4o',
|
|
123
|
+
inputTokens: 1_000,
|
|
124
|
+
cacheReadTokens: 300,
|
|
125
|
+
outputTokens: 200,
|
|
126
|
+
reasoningTokens: 40,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// uncached=700, cacheRead=300, billableOutput=200, total=1200.
|
|
130
|
+
// Reasoning remains visible but is not counted twice because OpenAI includes it in output.
|
|
131
|
+
const priced = calculateNormalizedUsageCost({ usage });
|
|
132
|
+
// { costUsd: number | null, source: 'provider-reported' | 'model-catalog' | ... }
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
For `SessionEvent`s, `extractNormalizedUsage(event)` prefers the parser-attached `message.normalizedUsage` and falls back to normalizing the event's raw `usage` with `sidekick` semantics.
|
|
136
|
+
|
|
137
|
+
Anthropic cache-read and cache-write counters are additive to `inputTokens`. OpenAI/Codex cached input is a subset of `inputTokens`. Provider-reported costs, including zero, are authoritative; an unknown model returns `costUsd: null` with `source: 'unpriced'`.
|
|
138
|
+
|
|
139
|
+
`calculateCost()`, `calculateCostWithPricing()`, `calculateCostWithProvenance()`, `CostTokenUsage`, and `CostProvenanceInput` remain available for compatibility but are deprecated. Their legacy contract always adds `reasoningTokens` to output and cannot express inclusion semantics.
|
|
140
|
+
|
|
141
|
+
### Estimate tokens without a base tokenizer dependency
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { estimateTextTokens } from 'sidekick-shared/browser';
|
|
145
|
+
|
|
146
|
+
const estimate = estimateTextTokens(sourceCode, {
|
|
147
|
+
model: 'claude-sonnet-4-6',
|
|
148
|
+
exactCounter: optionalModelCounter,
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`sidekick-fallback-v1` counts Latin/source-code text at 3.5 characters per token, CJK code points at one token, emoji at two, and other non-ASCII code points at one. Empty input is zero. An injected finite, nonnegative exact result takes precedence.
|
|
153
|
+
|
|
154
|
+
### Read canonical session history
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { CodexProvider, listRecentSessions, readSessionTranscript } from 'sidekick-shared';
|
|
158
|
+
|
|
159
|
+
const provider = new CodexProvider();
|
|
160
|
+
const [recent] = listRecentSessions(provider, workspacePath, { limit: 10 });
|
|
161
|
+
const transcript = readSessionTranscript(provider, recent.sessionPath, {
|
|
162
|
+
fidelity: 'full', // default is bounded 2,000-character snippets
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The same API works with `ClaudeCodeProvider` and `OpenCodeProvider`. It covers provider sessions discoverable by those readers. Remote Claude SDK-only history and Codex history entries whose rollout file has disappeared are not synthesized.
|
|
167
|
+
|
|
168
|
+
For an already-open incremental Codex rollout, keep one `CodexRolloutParser` per stream and pass each parsed `SessionEvent[]` batch to `projectSessionTranscript()` (or append the events to an existing projection). This preserves parser state for paired tool calls, model context, and cumulative token deltas; consumers should not convert raw `response_item` rows themselves.
|
|
169
|
+
|
|
170
|
+
### Collect observed sessions with isolation and retry
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import { ObservedSessionCollector, observedSessionSourceFromProvider } from 'sidekick-shared/node';
|
|
174
|
+
|
|
175
|
+
const collector = new ObservedSessionCollector({
|
|
176
|
+
sources: providers.map((provider) => observedSessionSourceFromProvider(provider, workspacePath)),
|
|
177
|
+
onObservation: ({ value }) => consume(value),
|
|
178
|
+
onDiagnostic: (diagnostic) => log(diagnostic),
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
await collector.collect(); // scheduling remains the host's responsibility
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Discovery and reads are isolated, retries use bounded 30-second-to-5-minute exponential backoff, file changes bypass delay, duplicate identical failures are suppressed, and recovery emits a content-free diagnostic. Clock and fingerprint callbacks are injectable for deterministic hosts/tests.
|
|
185
|
+
|
|
108
186
|
## Usage Examples
|
|
109
187
|
|
|
110
188
|
### Detect the active session provider
|
|
@@ -14,7 +14,7 @@ import type { SerializedFrequencyState } from './FrequencyTracker';
|
|
|
14
14
|
import type { SerializedHeatmapState } from './HeatmapTracker';
|
|
15
15
|
import type { SerializedPatternState } from './PatternExtractor';
|
|
16
16
|
/** Schema version for serialized snapshots. */
|
|
17
|
-
export declare const SNAPSHOT_SCHEMA_VERSION =
|
|
17
|
+
export declare const SNAPSHOT_SCHEMA_VERSION = 4;
|
|
18
18
|
/**
|
|
19
19
|
* JSON-serializable snapshot of EventAggregator state.
|
|
20
20
|
* Used by session snapshot sidecar files for fast resume.
|
|
@@ -26,6 +26,8 @@ export interface SerializedAggregatorState {
|
|
|
26
26
|
output: number;
|
|
27
27
|
cacheWrite: number;
|
|
28
28
|
cacheRead: number;
|
|
29
|
+
reasoning: number;
|
|
30
|
+
total: number;
|
|
29
31
|
reportedCost: number;
|
|
30
32
|
};
|
|
31
33
|
modelUsage: Array<[
|
|
@@ -96,6 +98,8 @@ export declare class EventAggregator {
|
|
|
96
98
|
private outputTokens;
|
|
97
99
|
private cacheWriteTokens;
|
|
98
100
|
private cacheReadTokens;
|
|
101
|
+
private reasoningTokens;
|
|
102
|
+
private totalTokens;
|
|
99
103
|
private reportedCost;
|
|
100
104
|
private modelUsage;
|
|
101
105
|
private currentContextSize;
|