codesesh 1.0.2 → 1.0.4
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 +18 -10
- package/dist/chunk-3SXCTDD6.js +326 -0
- package/dist/chunk-3SXCTDD6.js.map +1 -0
- package/dist/chunk-BYB77UAJ.js +6054 -0
- package/dist/chunk-BYB77UAJ.js.map +1 -0
- package/dist/{chunk-PROMURPM.js → chunk-G4HRD3AR.js} +13 -8
- package/dist/chunk-G4HRD3AR.js.map +1 -0
- package/dist/chunk-MBZ4VV4C.js +670 -0
- package/dist/chunk-MBZ4VV4C.js.map +1 -0
- package/dist/chunk-QH2HOXJH.js +2 -0
- package/dist/chunk-RF3EEWPH.js +17 -0
- package/dist/chunk-RF3EEWPH.js.map +1 -0
- package/dist/chunk-W4PZHL2C.js +2035 -0
- package/dist/chunk-W4PZHL2C.js.map +1 -0
- package/dist/chunk-YCUN52HA.js +8422 -0
- package/dist/chunk-YCUN52HA.js.map +1 -0
- package/dist/discovery-K3GLISI6.js +102 -0
- package/dist/discovery-K3GLISI6.js.map +1 -0
- package/dist/index.js +3016 -1392
- package/dist/index.js.map +1 -1
- package/dist/project-identity-worker.js +29 -0
- package/dist/project-identity-worker.js.map +1 -0
- package/dist/scan-refresh-worker.js +129 -139
- package/dist/scan-refresh-worker.js.map +1 -1
- package/dist/search-index-worker.js +39 -13
- package/dist/search-index-worker.js.map +1 -1
- package/dist/smart-tag-worker.js +8 -5
- package/dist/smart-tag-worker.js.map +1 -1
- package/dist/web/assets/InteractiveReceipt-Dk50TBsH.js +1 -0
- package/dist/web/assets/OverviewScreen-5hvQVp4H.js +1 -0
- package/dist/web/assets/{PrismHighlighter-BZkkX0AU.js → PrismHighlighter-B1a2dPJO.js} +2 -2
- package/dist/web/assets/Projects-Cy_v2yep.js +1 -0
- package/dist/web/assets/SearchResultsPanel-DfheEwpz.js +1 -0
- package/dist/web/assets/SessionDetail-DRI8R3st.js +53 -0
- package/dist/web/assets/api-GP9UCedC.js +1 -0
- package/dist/web/assets/contract-xJyW5u7a.js +2 -0
- package/dist/web/assets/index-Bd-YkWkZ.css +1 -0
- package/dist/web/assets/index-DEjvzumm.js +1410 -0
- package/dist/web/assets/panel-ND0J63d3.js +1 -0
- package/dist/web/assets/{session-indexes-0oT5HSS5.js → session-indexes-BsgjUoc1.js} +2 -2
- package/dist/web/assets/utils-C7BqyxxV.js +1 -0
- package/dist/web/index.html +7 -11
- package/package.json +4 -10
- package/dist/chunk-PROMURPM.js.map +0 -1
- package/dist/chunk-VAUC2W7I.js +0 -16119
- package/dist/chunk-VAUC2W7I.js.map +0 -1
- package/dist/dist-6QTGTYZT.js +0 -175
- package/dist/web/assets/ErrorBoundary-D11tWzfn.js +0 -1
- package/dist/web/assets/InteractiveReceipt-DYGyHeZd.js +0 -1
- package/dist/web/assets/OverviewScreen-DriPmCam.js +0 -1
- package/dist/web/assets/Projects-BPDIcUBK.js +0 -1
- package/dist/web/assets/SearchFilterBar-Bx73B5e9.js +0 -1
- package/dist/web/assets/SearchResultsPanel-A6_3TPhW.js +0 -1
- package/dist/web/assets/SessionDetail-BnpvDwtH.js +0 -54
- package/dist/web/assets/SmartTagChips-ux6idUGJ.js +0 -1
- package/dist/web/assets/agents-BkRP_ww3.js +0 -1
- package/dist/web/assets/code-metrics-UYFsCC7E.js +0 -1
- package/dist/web/assets/contract-V6QuD0UY.js +0 -1
- package/dist/web/assets/index-99ZxpV2y.js +0 -1410
- package/dist/web/assets/index-B2RqUgZ5.css +0 -1
- package/dist/web/assets/panel-C-gc79Gz.js +0 -1
- package/dist/web/assets/session-title-DdtlxtlR.js +0 -1
- package/dist/web/assets/utils-DgUgu15E.js +0 -1
- /package/dist/{dist-6QTGTYZT.js.map → chunk-QH2HOXJH.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../core/src/analytics/cost-attribution.ts","../../core/src/analytics/dashboard.ts","../../core/src/analytics/projects.ts"],"sourcesContent":["import type { CostSource, SessionHead } from \"../types/session.js\";\nimport {\n getSessionReferenceKey,\n type SessionTree,\n type SessionTreeNode,\n} from \"../contract/index.js\";\nimport type {\n DashboardCostFacts,\n MessageCostFact,\n SessionCostSummary,\n SessionModelCostFact,\n} from \"./cost-facts.js\";\n\nconst COST_ABSOLUTE_TOLERANCE = 1e-8;\nconst COST_RELATIVE_TOLERANCE = 1e-6;\n\ninterface MetricFactIndex {\n messagesBySession: Map<string, MessageCostFact[]>;\n summariesBySession: Map<string, SessionCostSummary>;\n}\n\nexport interface AttributedCost {\n entry: SessionTreeNode;\n time: number;\n cost: number;\n source: CostSource;\n modelCosts: SessionModelCostFact[];\n}\n\nexport interface CostAttributionOptions {\n from?: number;\n to: number;\n facts?: DashboardCostFacts | null;\n matchesEntry?: (session: SessionHead) => boolean;\n}\n\nexport interface AttributedUsage {\n entry: SessionTreeNode;\n time: number;\n messages: number;\n totalTokens: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreateTokens: number;\n}\n\nexport type UsageAttributionOptions = CostAttributionOptions;\n\nfunction indexFacts(facts: DashboardCostFacts | null | undefined): MetricFactIndex {\n const messagesBySession = new Map<string, MessageCostFact[]>();\n const summariesBySession = new Map<string, SessionCostSummary>();\n if (!facts) return { messagesBySession, summariesBySession };\n\n for (const summary of facts.sessions) {\n summariesBySession.set(getSessionReferenceKey(summary.reference), summary);\n }\n for (const message of facts.messages) {\n const key = getSessionReferenceKey(message.reference);\n const messages = messagesBySession.get(key);\n if (messages) messages.push(message);\n else messagesBySession.set(key, [message]);\n }\n return { messagesBySession, summariesBySession };\n}\n\nfunction nonNegative(value: number | undefined): number {\n return Math.max(0, Number(value ?? 0));\n}\n\nfunction costsReconcile(left: number, right: number): boolean {\n const tolerance = Math.max(\n COST_ABSOLUTE_TOLERANCE,\n Math.max(Math.abs(left), Math.abs(right)) * COST_RELATIVE_TOLERANCE,\n );\n return Math.abs(left - right) <= tolerance;\n}\n\nfunction hasDetailedCost(session: SessionHead, summary: SessionCostSummary | undefined): boolean {\n const totalCost = Math.max(0, session.stats.total_cost);\n return (\n totalCost > 0 &&\n summary != null &&\n summary.untimedMessageCost <= COST_ABSOLUTE_TOLERANCE &&\n costsReconcile(summary.messageCost, totalCost)\n );\n}\n\nfunction hasDetailedMessages(\n session: SessionHead,\n summary: SessionCostSummary | undefined,\n): boolean {\n return (\n summary != null &&\n summary.untimedMessageCount === 0 &&\n summary.messageCount === nonNegative(session.stats.message_count)\n );\n}\n\n// Provider payloads disagree on whether reasoning is already included in output.\nfunction detailedOutputIncludesReasoning(\n session: SessionHead,\n summary: SessionCostSummary | undefined,\n): boolean | null {\n if (!summary) return null;\n const stats = session.stats;\n const sessionInput = nonNegative(stats.total_input_tokens);\n const sessionOutput = nonNegative(stats.total_output_tokens);\n const sessionCacheRead = nonNegative(stats.total_cache_read_tokens);\n const sessionCacheCreate = nonNegative(stats.total_cache_create_tokens);\n const sessionTotal = nonNegative(stats.total_tokens ?? sessionInput + sessionOutput);\n const outputIncludesReasoning = summary.outputTokens + summary.reasoningTokens;\n const outputMatches = summary.outputTokens === sessionOutput;\n const outputWithReasoningMatches = outputIncludesReasoning === sessionOutput;\n const effectiveOutput = outputMatches\n ? summary.outputTokens\n : outputWithReasoningMatches\n ? outputIncludesReasoning\n : null;\n\n if (\n effectiveOutput == null ||\n summary.inputTokens !== sessionInput ||\n summary.cacheReadTokens !== sessionCacheRead ||\n summary.cacheCreateTokens !== sessionCacheCreate ||\n summary.inputTokens + effectiveOutput !== sessionTotal ||\n summary.untimedInputTokens > 0 ||\n summary.untimedOutputTokens > 0 ||\n summary.untimedReasoningTokens > 0 ||\n summary.untimedCacheReadTokens > 0 ||\n summary.untimedCacheCreateTokens > 0\n ) {\n return null;\n }\n return !outputMatches && outputWithReasoningMatches;\n}\n\nfunction isInWindow(time: number, from: number | undefined, to: number): boolean {\n return (from == null || time >= from) && time <= to;\n}\n\nfunction resolvedCostSource(session: SessionHead, source?: CostSource): CostSource {\n return source ?? session.stats.cost_source ?? \"recorded\";\n}\n\nfunction fallbackModelCosts(\n summary: SessionCostSummary | undefined,\n totalCost: number,\n): SessionModelCostFact[] {\n if (!summary) return [];\n const modelTotal = summary.modelCosts.reduce((sum, model) => sum + model.cost, 0);\n return modelTotal > totalCost && !costsReconcile(modelTotal, totalCost) ? [] : summary.modelCosts;\n}\n\nexport function visitAttributedCosts(\n tree: SessionTree,\n options: CostAttributionOptions,\n visit: (attributed: AttributedCost) => void,\n): void {\n const factIndex = indexFacts(options.facts);\n const factsAvailable = options.facts != null;\n\n for (const entry of tree.entries) {\n if (options.matchesEntry && !options.matchesEntry(entry.session)) continue;\n const fallbackTime = entry.session.time_updated ?? entry.session.time_created;\n const pending = [entry];\n\n while (pending.length > 0) {\n const node = pending.pop()!;\n for (const child of node.children) pending.push(child);\n\n const session = node.session;\n const totalCost = Math.max(0, session.stats.total_cost);\n if (totalCost <= 0) continue;\n const key = getSessionReferenceKey(session.reference);\n const summary = factIndex.summariesBySession.get(key);\n\n if (factsAvailable && hasDetailedCost(session, summary)) {\n for (const message of factIndex.messagesBySession.get(key) ?? []) {\n if (!isInWindow(message.time, options.from, options.to) || message.cost <= 0) continue;\n const source = resolvedCostSource(session, message.costSource);\n visit({\n entry,\n time: message.time,\n cost: message.cost,\n source,\n modelCosts: message.model\n ? [\n {\n model: message.model,\n cost: message.cost,\n costRecorded: source === \"recorded\" ? message.cost : 0,\n },\n ]\n : [],\n });\n }\n continue;\n }\n\n if (!isInWindow(fallbackTime, options.from, options.to)) continue;\n visit({\n entry,\n time: fallbackTime,\n cost: totalCost,\n source: resolvedCostSource(session),\n modelCosts: factsAvailable ? fallbackModelCosts(summary, totalCost) : [],\n });\n }\n }\n}\n\nexport function visitAttributedUsage(\n tree: SessionTree,\n options: UsageAttributionOptions,\n visit: (attributed: AttributedUsage) => void,\n): void {\n const factIndex = indexFacts(options.facts);\n const factsAvailable = options.facts != null;\n\n for (const entry of tree.entries) {\n if (options.matchesEntry && !options.matchesEntry(entry.session)) continue;\n const fallbackTime = entry.session.time_updated ?? entry.session.time_created;\n const pending = [entry];\n\n while (pending.length > 0) {\n const node = pending.pop()!;\n for (const child of node.children) pending.push(child);\n\n const session = node.session;\n const key = getSessionReferenceKey(session.reference);\n const summary = factIndex.summariesBySession.get(key);\n const detailedMessages = factsAvailable && hasDetailedMessages(session, summary);\n const outputIncludesReasoning = factsAvailable\n ? detailedOutputIncludesReasoning(session, summary)\n : null;\n const detailedTokens = outputIncludesReasoning != null;\n\n if (detailedMessages || detailedTokens) {\n for (const message of factIndex.messagesBySession.get(key) ?? []) {\n if (!isInWindow(message.time, options.from, options.to)) continue;\n const outputTokens = detailedTokens\n ? message.outputTokens + (outputIncludesReasoning ? message.reasoningTokens : 0)\n : 0;\n visit({\n entry,\n time: message.time,\n messages: detailedMessages ? 1 : 0,\n totalTokens: detailedTokens ? message.inputTokens + outputTokens : 0,\n inputTokens: detailedTokens ? message.inputTokens : 0,\n outputTokens,\n cacheReadTokens: detailedTokens ? message.cacheReadTokens : 0,\n cacheCreateTokens: detailedTokens ? message.cacheCreateTokens : 0,\n });\n }\n }\n\n if (!isInWindow(fallbackTime, options.from, options.to)) continue;\n if (!detailedMessages) {\n visit({\n entry,\n time: fallbackTime,\n messages: nonNegative(session.stats.message_count),\n totalTokens: 0,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreateTokens: 0,\n });\n }\n if (!detailedTokens) {\n const inputTokens = nonNegative(session.stats.total_input_tokens);\n const outputTokens = nonNegative(session.stats.total_output_tokens);\n visit({\n entry,\n time: fallbackTime,\n messages: 0,\n totalTokens: nonNegative(session.stats.total_tokens ?? inputTokens + outputTokens),\n inputTokens,\n outputTokens,\n cacheReadTokens: nonNegative(session.stats.total_cache_read_tokens),\n cacheCreateTokens: nonNegative(session.stats.total_cache_create_tokens),\n });\n }\n }\n }\n}\n","/**\n * Dashboard analytics — pure aggregation over SessionHead[] with no HTTP or DB\n * coupling. The handler parses request params and supplies file-activity; this\n * module owns the domain math: per-agent metrics, daily buckets, model\n * distribution, project ranking and the recent-sessions window.\n *\n * Metrics are *inclusive*: the unit of work is a top-level node (root or\n * orphan) and every descendant's stats roll into it. See contract/session-tree.\n */\nimport type { AgentInfo } from \"../types/index.js\";\nimport type { CostSource, ProjectIdentityKind, SessionHead } from \"../types/session.js\";\nimport type {\n DashboardAgentStat,\n DashboardAggregate,\n DashboardDailyBucket,\n DashboardData,\n DashboardPreviousTotals,\n DashboardProjectRollup,\n DashboardProjectStat,\n DashboardRecentSession,\n DashboardTotals,\n ModelCostEntry,\n ModelDistributionEntry,\n SessionTree,\n SessionTreeNode,\n} from \"../contract/index.js\";\nimport {\n addCalendarDays,\n buildSessionTree,\n countCalendarDays,\n filterSessionTreeEntriesByActivityWindow,\n getProjectIdentityKey,\n getSessionAgentKey,\n toCalendarDayKey,\n} from \"../contract/index.js\";\nimport type { DashboardCostFacts } from \"./cost-facts.js\";\nimport { visitAttributedCosts, visitAttributedUsage } from \"./cost-attribution.js\";\n\nexport type {\n DashboardAgentStat,\n DashboardAggregate,\n DashboardDailyBucket,\n DashboardData,\n DashboardPreviousTotals,\n DashboardProjectRollup,\n DashboardProjectStat,\n DashboardRecentSession,\n DashboardTotals,\n ModelDistributionEntry,\n};\n\nexport const DASHBOARD_RECENT_LIMIT = 10;\nexport const DASHBOARD_PROJECT_LIMIT = 12;\nexport const PROJECT_SPARKLINE_DAYS = 14;\nconst MODEL_COST_LIMIT = 20;\n\nexport interface DashboardScope {\n agent?: string;\n projectKind?: ProjectIdentityKind;\n projectKey?: string;\n}\n\ninterface DashboardAgentAggregate {\n name: string;\n sessions: number;\n messages: number;\n tokens: number;\n cost: number;\n}\n\ninterface DashboardProjectAggregate {\n identityKind: ProjectIdentityKind;\n identityKey: string;\n displayName: string;\n sessions: number;\n messages: number;\n tokens: number;\n cost: number;\n hasEstimatedCost: boolean;\n agentSessions: Map<string, number>;\n sparkline: number[];\n}\n\ninterface DashboardRecentCandidate {\n session: SessionHead;\n activity: number;\n}\n\ninterface DashboardAccumulator {\n sessions: number;\n messages: number;\n tokens: number;\n cost: number;\n costRecorded: number;\n costEstimated: number;\n cacheReadTokens: number;\n hasEstimatedCost: boolean;\n agents: Map<string, DashboardAgentAggregate>;\n agentKeys: Set<string>;\n daily: Map<string, DashboardDailyBucket>;\n models: Map<string, { tokens: number; sessions: number }>;\n modelCosts: Map<string, ModelCostEntry>;\n projects: Map<string, DashboardProjectAggregate>;\n projectKeys: Set<string>;\n /** Calendar day key → sparkline slot; anchored at the window's `to`. */\n sparklineSlots: Map<string, number>;\n /** Activity-desc, capped at DASHBOARD_RECENT_LIMIT; index 0 is the latest entry. */\n recent: DashboardRecentCandidate[];\n}\n\nexport interface DashboardOptions {\n byAgentNames: string[];\n scope: DashboardScope;\n from?: number;\n to: number;\n agentInfoMap?: Map<string, AgentInfo>;\n /** Immediately preceding window of equal length; drives `totals.previous`. */\n compare?: { from: number; to: number };\n /** Message-level cost and usage facts; null/undefined keeps session-activity fallback behavior. */\n costFacts?: DashboardCostFacts | null;\n}\n\n// --- SessionHead domain helpers (shared with other handlers via re-export) ---\n\nexport function getTotalTokens(stats: SessionHead[\"stats\"]): number {\n return stats.total_tokens ?? stats.total_input_tokens + stats.total_output_tokens;\n}\n\nexport function getSessionAgentName(session: SessionHead): string {\n return getSessionAgentKey(session);\n}\n\nexport function getSessionActivityTime(session: SessionHead): number {\n return session.time_updated ?? session.time_created;\n}\n\nfunction matchesScope(session: SessionHead, scope: DashboardScope): boolean {\n if (scope.agent && getSessionAgentName(session) !== scope.agent) return false;\n if (scope.projectKind == null && scope.projectKey == null) return true;\n const identity = session.project_identity;\n // A half-specified scope matches nothing: identity fields are never undefined.\n return (\n identity != null && identity.kind === scope.projectKind && identity.key === scope.projectKey\n );\n}\n\n/** Top-level nodes (roots ∪ orphans) inside the window that match the scope. */\nfunction scopedEntries(\n tree: SessionTree,\n scope: DashboardScope,\n from: number | undefined,\n to: number,\n): SessionTreeNode[] {\n return filterSessionTreeEntriesByActivityWindow(tree, from, to).filter((node) =>\n matchesScope(node.session, scope),\n );\n}\n\nfunction emptyDailyBucket(date: string): DashboardDailyBucket {\n return {\n date,\n sessions: 0,\n messages: 0,\n cost: 0,\n input: 0,\n output: 0,\n cache_read: 0,\n cache_create: 0,\n };\n}\n\nfunction createAccumulator(\n byAgentNames: string[],\n scope: DashboardScope,\n to: number,\n): DashboardAccumulator {\n const agents = new Map<string, DashboardAgentAggregate>();\n for (const name of byAgentNames) {\n const key = name.toLowerCase();\n if (scope.agent && key !== scope.agent) continue;\n agents.set(key, { name, sessions: 0, messages: 0, tokens: 0, cost: 0 });\n }\n\n const sparklineSlots = new Map<string, number>();\n for (let slot = 0; slot < PROJECT_SPARKLINE_DAYS; slot += 1) {\n const day = addCalendarDays(to, slot - (PROJECT_SPARKLINE_DAYS - 1));\n sparklineSlots.set(toCalendarDayKey(day), slot);\n }\n\n return {\n sessions: 0,\n messages: 0,\n tokens: 0,\n cost: 0,\n costRecorded: 0,\n costEstimated: 0,\n cacheReadTokens: 0,\n hasEstimatedCost: false,\n agents,\n agentKeys: new Set(),\n daily: new Map(),\n models: new Map(),\n modelCosts: new Map(),\n projects: new Map(),\n projectKeys: new Set(),\n sparklineSlots,\n recent: [],\n };\n}\n\nfunction foldModelUsage(node: SessionTreeNode, into: Map<string, number>): void {\n if (node.session.model_usage) {\n for (const [model, tokens] of Object.entries(node.session.model_usage)) {\n into.set(model, (into.get(model) ?? 0) + tokens);\n }\n }\n for (const child of node.children) foldModelUsage(child, into);\n}\n\nfunction getOrCreateProject(\n session: SessionHead,\n acc: DashboardAccumulator,\n): DashboardProjectAggregate | undefined {\n const identity = session.project_identity;\n if (!identity) return undefined;\n\n const key = getProjectIdentityKey(identity);\n let project = acc.projects.get(key);\n if (!project) {\n project = {\n identityKind: identity.kind,\n identityKey: identity.key,\n displayName: identity.displayName,\n sessions: 0,\n messages: 0,\n tokens: 0,\n cost: 0,\n hasEstimatedCost: false,\n agentSessions: new Map(),\n sparkline: Array.from({ length: PROJECT_SPARKLINE_DAYS }, () => 0),\n };\n acc.projects.set(key, project);\n }\n return project;\n}\n\nfunction trackProjectActivity(\n node: SessionTreeNode,\n acc: DashboardAccumulator,\n agentKey: string,\n): void {\n const identity = node.session.project_identity;\n const project = getOrCreateProject(node.session, acc);\n if (!identity || !project) return;\n\n project.sessions += 1;\n project.agentSessions.set(agentKey, (project.agentSessions.get(agentKey) ?? 0) + 1);\n acc.projectKeys.add(getProjectIdentityKey(identity));\n}\n\n/** Fold activity metrics for one top-level node and its inclusive subtree. */\nfunction accumulateActivity(node: SessionTreeNode, acc: DashboardAccumulator): void {\n const session = node.session;\n const activity = getSessionActivityTime(session);\n const agentKey = getSessionAgentName(session);\n\n acc.sessions += 1;\n acc.agentKeys.add(agentKey);\n\n const metric = acc.agents.get(agentKey);\n if (metric) {\n metric.sessions += 1;\n }\n\n const dayKey = toCalendarDayKey(activity);\n let bucket = acc.daily.get(dayKey);\n if (!bucket) {\n bucket = emptyDailyBucket(dayKey);\n acc.daily.set(dayKey, bucket);\n }\n bucket.sessions += 1;\n\n const usage = new Map<string, number>();\n foldModelUsage(node, usage);\n for (const [model, tokens] of usage) {\n const entry = acc.models.get(model);\n if (entry) {\n entry.tokens += tokens;\n entry.sessions += 1;\n } else {\n acc.models.set(model, { tokens, sessions: 1 });\n }\n }\n\n trackProjectActivity(node, acc, agentKey);\n\n let recentIndex = acc.recent.length;\n for (let i = 0; i < acc.recent.length; i += 1) {\n if (activity > acc.recent[i]!.activity) {\n recentIndex = i;\n break;\n }\n }\n if (recentIndex < DASHBOARD_RECENT_LIMIT) {\n acc.recent.splice(recentIndex, 0, { session, activity });\n if (acc.recent.length > DASHBOARD_RECENT_LIMIT) acc.recent.pop();\n }\n}\n\nfunction addUsage(\n acc: DashboardAccumulator,\n entry: SessionTreeNode,\n time: number,\n usage: {\n messages: number;\n totalTokens: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreateTokens: number;\n },\n): void {\n const { messages, totalTokens, inputTokens, outputTokens, cacheReadTokens, cacheCreateTokens } =\n usage;\n if (\n messages <= 0 &&\n totalTokens <= 0 &&\n inputTokens <= 0 &&\n outputTokens <= 0 &&\n cacheReadTokens <= 0 &&\n cacheCreateTokens <= 0\n ) {\n return;\n }\n\n acc.messages += messages;\n acc.tokens += totalTokens;\n acc.cacheReadTokens += cacheReadTokens;\n\n const agentKey = getSessionAgentName(entry.session);\n let metric = acc.agents.get(agentKey);\n if (!metric) {\n metric = { name: agentKey, sessions: 0, messages: 0, tokens: 0, cost: 0 };\n acc.agents.set(agentKey, metric);\n }\n metric.messages += messages;\n metric.tokens += totalTokens;\n\n const dayKey = toCalendarDayKey(time);\n let bucket = acc.daily.get(dayKey);\n if (!bucket) {\n bucket = emptyDailyBucket(dayKey);\n acc.daily.set(dayKey, bucket);\n }\n bucket.messages += messages;\n bucket.input += Math.max(0, inputTokens - cacheReadTokens - cacheCreateTokens);\n bucket.output += outputTokens;\n bucket.cache_read += cacheReadTokens;\n bucket.cache_create += cacheCreateTokens;\n\n const project = getOrCreateProject(entry.session, acc);\n if (!project) return;\n project.messages += messages;\n project.tokens += totalTokens;\n}\n\nfunction accumulateUsage(\n tree: SessionTree,\n scope: DashboardScope,\n acc: DashboardAccumulator,\n from: number | undefined,\n to: number,\n costFacts: DashboardCostFacts | null | undefined,\n): void {\n visitAttributedUsage(\n tree,\n { from, to, facts: costFacts, matchesEntry: (session) => matchesScope(session, scope) },\n ({ entry, time, ...usage }) => addUsage(acc, entry, time, usage),\n );\n}\n\nfunction addModelCost(\n acc: DashboardAccumulator,\n model: string | undefined,\n cost: number,\n recordedCost: number,\n): void {\n if (!model || cost <= 0) return;\n const recorded = Math.max(0, Math.min(cost, recordedCost));\n const current = acc.modelCosts.get(model);\n if (current) {\n current.cost += cost;\n current.costRecorded += recorded;\n current.costEstimated += cost - recorded;\n return;\n }\n acc.modelCosts.set(model, {\n model,\n cost,\n costRecorded: recorded,\n costEstimated: cost - recorded,\n });\n}\n\nfunction addCost(\n acc: DashboardAccumulator,\n entry: SessionTreeNode,\n time: number,\n cost: number,\n source: CostSource,\n): void {\n if (cost <= 0) return;\n acc.cost += cost;\n if (source === \"recorded\") acc.costRecorded += cost;\n else {\n acc.costEstimated += cost;\n acc.hasEstimatedCost = true;\n }\n\n const agentKey = getSessionAgentName(entry.session);\n let metric = acc.agents.get(agentKey);\n if (!metric) {\n metric = { name: agentKey, sessions: 0, messages: 0, tokens: 0, cost: 0 };\n acc.agents.set(agentKey, metric);\n }\n metric.cost += cost;\n\n const dayKey = toCalendarDayKey(time);\n let bucket = acc.daily.get(dayKey);\n if (!bucket) {\n bucket = emptyDailyBucket(dayKey);\n acc.daily.set(dayKey, bucket);\n }\n bucket.cost += cost;\n\n const project = getOrCreateProject(entry.session, acc);\n if (!project) return;\n project.cost += cost;\n if (source === \"estimated\") project.hasEstimatedCost = true;\n const slot = acc.sparklineSlots.get(dayKey);\n if (slot != null) project.sparkline[slot]! += cost;\n}\n\nfunction accumulateCosts(\n tree: SessionTree,\n scope: DashboardScope,\n acc: DashboardAccumulator,\n from: number | undefined,\n to: number,\n costFacts: DashboardCostFacts | null | undefined,\n): void {\n visitAttributedCosts(\n tree,\n { from, to, facts: costFacts, matchesEntry: (session) => matchesScope(session, scope) },\n ({ entry, time, cost, source, modelCosts }) => {\n addCost(acc, entry, time, cost, source);\n for (const model of modelCosts) {\n addModelCost(acc, model.model, model.cost, model.costRecorded);\n }\n },\n );\n}\n\nfunction toPreviousTotals(acc: DashboardAccumulator): DashboardPreviousTotals {\n return { sessions: acc.sessions, messages: acc.messages, tokens: acc.tokens, cost: acc.cost };\n}\n\nfunction toProjectStat(project: DashboardProjectAggregate): DashboardProjectStat {\n return {\n identityKind: project.identityKind,\n identityKey: project.identityKey,\n displayName: project.displayName,\n sessions: project.sessions,\n messages: project.messages,\n tokens: project.tokens,\n cost: project.cost,\n cost_source:\n project.cost > 0 ? (project.hasEstimatedCost ? \"estimated\" : \"recorded\") : undefined,\n agents: [...project.agentSessions.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([agentKey]) => agentKey),\n sparkline: project.sparkline,\n };\n}\n\n/**\n * Aggregate sessions into dashboard metrics, daily buckets, model distribution,\n * project ranking and the recent-sessions window. Pure — no HTTP, no DB.\n */\nexport function buildDashboard(\n sessions: SessionHead[],\n options: DashboardOptions,\n): DashboardAggregate {\n const { byAgentNames, scope, from, to, agentInfoMap, compare, costFacts } = options;\n const tree = buildSessionTree(sessions);\n const costFactsAvailable = costFacts != null;\n\n const acc = createAccumulator(byAgentNames, scope, to);\n if (from != null) {\n const bucketDays = countCalendarDays(from, to);\n for (let i = 0; i < bucketDays; i += 1) {\n const key = toCalendarDayKey(addCalendarDays(from, i));\n acc.daily.set(key, emptyDailyBucket(key));\n }\n }\n for (const node of scopedEntries(tree, scope, from, to)) accumulateActivity(node, acc);\n accumulateUsage(tree, scope, acc, from, to, costFacts);\n accumulateCosts(tree, scope, acc, from, to, costFacts);\n\n let previous: DashboardPreviousTotals | undefined;\n if (compare) {\n const compareAcc = createAccumulator(byAgentNames, scope, compare.to);\n for (const node of scopedEntries(tree, scope, compare.from, compare.to)) {\n accumulateActivity(node, compareAcc);\n }\n accumulateUsage(tree, scope, compareAcc, compare.from, compare.to, costFacts);\n accumulateCosts(tree, scope, compareAcc, compare.from, compare.to, costFacts);\n previous = toPreviousTotals(compareAcc);\n }\n\n const perAgent: DashboardAgentStat[] = [...acc.agents.values()]\n .map((metrics) => {\n const info = agentInfoMap?.get(metrics.name);\n return {\n name: metrics.name,\n displayName: info?.displayName ?? metrics.name,\n icon: info?.icon ?? \"\",\n iconColored: info?.iconColored,\n sessions: metrics.sessions,\n messages: metrics.messages,\n tokens: metrics.tokens,\n cost: metrics.cost,\n };\n })\n .filter((item) => item.sessions > 0 || item.messages > 0 || item.tokens > 0 || item.cost > 0)\n .sort((a, b) => b.sessions - a.sessions || b.cost - a.cost);\n\n const dailyActivity = [...acc.daily.values()].sort((a, b) => a.date.localeCompare(b.date));\n const modelDistribution: ModelDistributionEntry[] = [...acc.models.entries()]\n .map(([model, { tokens, sessions: count }]) => ({ model, tokens, sessions: count }))\n .sort((a, b) => b.tokens - a.tokens);\n const modelCost = costFactsAvailable\n ? [...acc.modelCosts.values()].sort((a, b) => b.cost - a.cost).slice(0, MODEL_COST_LIMIT)\n : null;\n\n const rankedProjects = [...acc.projects.values()].sort((a, b) => b.cost - a.cost);\n const perProject = rankedProjects.slice(0, DASHBOARD_PROJECT_LIMIT).map(toProjectStat);\n const projectRollup = rankedProjects\n .slice(DASHBOARD_PROJECT_LIMIT)\n .reduce<DashboardProjectRollup>(\n (rollup, project) => ({\n projects: rollup.projects + 1,\n sessions: rollup.sessions + project.sessions,\n tokens: rollup.tokens + project.tokens,\n cost: rollup.cost + project.cost,\n }),\n { projects: 0, sessions: 0, tokens: 0, cost: 0 },\n );\n\n const recentSessions: DashboardRecentSession[] = acc.recent.map(({ session }) => ({\n reference: session.reference,\n session,\n }));\n\n const latest = acc.recent[0];\n return {\n totals: {\n sessions: acc.sessions,\n messages: acc.messages,\n tokens: acc.tokens,\n cost: acc.cost,\n costRecorded: acc.costRecorded,\n costEstimated: acc.costEstimated,\n cacheReadTokens: acc.cacheReadTokens,\n cost_source: acc.cost > 0 ? (acc.hasEstimatedCost ? \"estimated\" : \"recorded\") : undefined,\n latestActivity: latest?.activity || undefined,\n latestActivityProject: latest?.session.project_identity?.displayName,\n latestActivityAgent: latest ? getSessionAgentName(latest.session) : undefined,\n previous,\n },\n scopeCounts: { projects: acc.projectKeys.size, agents: acc.agentKeys.size },\n perAgent,\n dailyActivity,\n modelDistribution,\n modelCost,\n perProject,\n projectRollup,\n recentSessions,\n };\n}\n","/**\n * Project analytics — pure aggregation over SessionHead[], the project-level\n * counterpart to dashboard.ts. No HTTP, no DB: the caller supplies the groups\n * and the sessions, this module owns the arithmetic.\n *\n * Metrics are inclusive of sub-sessions and `sessionCount` is recomputed from\n * the sessions actually handed in, so a windowed caller gets windowed counts\n * instead of the cache-wide count carried by ProjectGroup.\n */\nimport type { ProjectGroup, SessionHead } from \"../types/index.js\";\nimport type {\n ApiProjectAgentStat,\n ApiProjectGroup,\n ApiProjectSummary,\n SessionTree,\n SessionTreeNode,\n} from \"../contract/index.js\";\nimport { getProjectIdentityKey } from \"../contract/project-identity.js\";\nimport {\n buildSessionTree,\n filterSessionTreeEntriesByActivityWindow,\n} from \"../contract/session-tree.js\";\nimport { getSessionAgentName } from \"./dashboard.js\";\nimport type { DashboardCostFacts } from \"./cost-facts.js\";\nimport { visitAttributedCosts, visitAttributedUsage } from \"./cost-attribution.js\";\n\ninterface ProjectMetrics {\n sessions: number;\n messages: number;\n tokens: number;\n cost: number;\n hasEstimatedCost: boolean;\n agentStats: Map<string, ApiProjectAgentStat>;\n}\n\nexport function summarizeProjects(projects: readonly ApiProjectGroup[]): ApiProjectSummary {\n const summary: ApiProjectSummary = {\n projects: projects.length,\n sessions: 0,\n tokens: 0,\n cost: 0,\n latestActivity: null,\n };\n\n for (const project of projects) {\n summary.sessions += project.sessionCount;\n summary.tokens += project.tokens;\n summary.cost += project.cost;\n if (project.lastActivity != null) {\n summary.latestActivity =\n summary.latestActivity == null\n ? project.lastActivity\n : Math.max(summary.latestActivity, project.lastActivity);\n }\n }\n\n return summary;\n}\n\nfunction emptyMetrics(): ProjectMetrics {\n return {\n sessions: 0,\n messages: 0,\n tokens: 0,\n cost: 0,\n hasEstimatedCost: false,\n agentStats: new Map(),\n };\n}\n\n/**\n * Fold per-session totals into the project groups they belong to. Sessions with\n * no resolved project identity contribute to nothing.\n */\nexport function attachProjectMetrics(\n projects: ProjectGroup[],\n sessions: SessionHead[],\n): ApiProjectGroup[] {\n const tree = buildSessionTree(sessions);\n return attachProjectMetricsToEntries(projects, tree, tree.entries);\n}\n\nexport function attachProjectMetricsFromTree(\n projects: ProjectGroup[],\n tree: SessionTree,\n from?: number,\n to?: number,\n costFacts?: DashboardCostFacts | null,\n): ApiProjectGroup[] {\n return attachProjectMetricsToEntries(\n projects,\n tree,\n filterSessionTreeEntriesByActivityWindow(tree, from, to),\n from,\n to,\n costFacts,\n );\n}\n\nfunction attachProjectMetricsToEntries(\n projects: ProjectGroup[],\n tree: SessionTree,\n entries: SessionTreeNode[],\n from?: number,\n to?: number,\n costFacts?: DashboardCostFacts | null,\n): ApiProjectGroup[] {\n const metrics = new Map<string, ProjectMetrics>();\n\n for (const node of entries) {\n const identity = node.session.project_identity;\n if (!identity) continue;\n\n const key = getProjectIdentityKey(identity);\n let current = metrics.get(key);\n if (!current) {\n current = emptyMetrics();\n metrics.set(key, current);\n }\n\n current.sessions += 1;\n\n const agentName = getSessionAgentName(node.session);\n const agent = current.agentStats.get(agentName);\n if (agent) {\n agent.sessions += 1;\n } else {\n current.agentStats.set(agentName, {\n name: agentName,\n sessions: 1,\n messages: 0,\n tokens: 0,\n cost: 0,\n });\n }\n }\n\n visitAttributedUsage(\n tree,\n { from, to: to ?? Number.POSITIVE_INFINITY, facts: costFacts },\n ({ entry, messages, totalTokens }) => {\n const identity = entry.session.project_identity;\n if (!identity) return;\n const key = getProjectIdentityKey(identity);\n let current = metrics.get(key);\n if (!current) {\n current = emptyMetrics();\n metrics.set(key, current);\n }\n current.messages += messages;\n current.tokens += totalTokens;\n\n const agentName = getSessionAgentName(entry.session);\n const agent = current.agentStats.get(agentName);\n if (agent) {\n agent.messages += messages;\n agent.tokens += totalTokens;\n } else {\n current.agentStats.set(agentName, {\n name: agentName,\n sessions: 0,\n messages,\n tokens: totalTokens,\n cost: 0,\n });\n }\n },\n );\n\n visitAttributedCosts(\n tree,\n { from, to: to ?? Number.POSITIVE_INFINITY, facts: costFacts },\n ({ entry, cost, source }) => {\n const identity = entry.session.project_identity;\n if (!identity) return;\n const key = getProjectIdentityKey(identity);\n let current = metrics.get(key);\n if (!current) {\n current = emptyMetrics();\n metrics.set(key, current);\n }\n current.cost += cost;\n if (source === \"estimated\") current.hasEstimatedCost = true;\n\n const agentName = getSessionAgentName(entry.session);\n const agent = current.agentStats.get(agentName);\n if (agent) agent.cost += cost;\n else {\n current.agentStats.set(agentName, {\n name: agentName,\n sessions: 0,\n messages: 0,\n tokens: 0,\n cost,\n });\n }\n },\n );\n\n return projects.map((project) => {\n const metric = metrics.get(\n getProjectIdentityKey({ kind: project.identityKind, key: project.identityKey }),\n );\n return {\n ...project,\n sessionCount: metric?.sessions ?? 0,\n messages: metric?.messages ?? 0,\n tokens: metric?.tokens ?? 0,\n cost: metric?.cost ?? 0,\n cost_source:\n metric && metric.cost > 0\n ? metric.hasEstimatedCost\n ? \"estimated\"\n : \"recorded\"\n : undefined,\n agentStats: [...(metric?.agentStats.values() ?? [])].sort((a, b) => b.sessions - a.sessions),\n };\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/scan-refresh-error.ts
|
|
4
|
+
var AGENT_UNAVAILABLE_DURING_SCAN_ERROR_CODE = "agent-unavailable-during-scan";
|
|
5
|
+
var AgentUnavailableDuringScanError = class extends Error {
|
|
6
|
+
code = AGENT_UNAVAILABLE_DURING_SCAN_ERROR_CODE;
|
|
7
|
+
constructor(agentName) {
|
|
8
|
+
super(`Agent ${agentName} became unavailable during scan`);
|
|
9
|
+
this.name = "AgentUnavailableDuringScanError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
AGENT_UNAVAILABLE_DURING_SCAN_ERROR_CODE,
|
|
15
|
+
AgentUnavailableDuringScanError
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=chunk-RF3EEWPH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/scan-refresh-error.ts"],"sourcesContent":["export const AGENT_UNAVAILABLE_DURING_SCAN_ERROR_CODE = \"agent-unavailable-during-scan\";\n\nexport type ScanRefreshWorkerErrorCode = typeof AGENT_UNAVAILABLE_DURING_SCAN_ERROR_CODE;\n\nexport class AgentUnavailableDuringScanError extends Error {\n readonly code = AGENT_UNAVAILABLE_DURING_SCAN_ERROR_CODE;\n\n constructor(agentName: string) {\n super(`Agent ${agentName} became unavailable during scan`);\n this.name = \"AgentUnavailableDuringScanError\";\n }\n}\n"],"mappings":";;;AAAO,IAAM,2CAA2C;AAIjD,IAAM,kCAAN,cAA8C,MAAM;AAAA,EAChD,OAAO;AAAA,EAEhB,YAAY,WAAmB;AAC7B,UAAM,SAAS,SAAS,iCAAiC;AACzD,SAAK,OAAO;AAAA,EACd;AACF;","names":[]}
|