diff --git a/apps/www/content/3.components/1.chatbot/context.md b/apps/www/content/3.components/1.chatbot/context.md new file mode 100644 index 0000000..081df57 --- /dev/null +++ b/apps/www/content/3.components/1.chatbot/context.md @@ -0,0 +1,700 @@ +--- +title: Context +description: A compound component system for displaying AI model context window usage, token consumption, and cost estimation. +icon: lucide:layers +--- + +The `Context` component provides a comprehensive view of AI model usage through a compound component system. It displays context window utilization, token consumption breakdown (input, output, reasoning, cache), and cost estimation in an interactive hover card interface. + +:::ComponentLoader{label="Preivew" componentName="Context"} +::: + +## Install using CLI + +:::tabs{variant="card"} + ::div{label="ai-elements-vue"} + ```sh + npx ai-elements-vue@latest add context + ``` + :: + ::div{label="shadcn-vue"} + + ```sh + npx shadcn-vue@latest add https://registry.ai-elements-vue.com/context.json + ``` + :: +::: + +## Install Manually + +Copy and paste the following files into the same folder. + +:::code-group +```vue [Context.vue] height=260 collapse + + + + + + + +``` + +```vue [ContextIcon.vue] height=260 collapse + + + + + + + + +``` + +```vue [ContextTrigger.vue] height=260 collapse + + + + + + + + + {{ renderedPercent }} + + + + + +``` + +```vue [ContextContent.vue] height=260 collapse + + + + + + + +``` + +```vue [ContextContentHeader.vue] height=260 collapse + + + + + + + + + {{ displayPct }} + + {{ used }} / {{ total }} + + + + + + + + +``` + +```vue [ContextContentBody.vue] height=260 collapse + + + + + + + +``` + +```vue [ContextContentFooter.vue] height=260 collapse + + + + + + + + Total cost + {{ totalCost }} + + + +``` + +```vue [ContextInputUsage.vue] height=260 collapse + + + + + + + Input + + + +``` + +```vue [ContextOutputUsage.vue] height=260 collapse + + + + + + Output + + + +``` + +```vue [ContextReasoningUsage.vue] height=260 collapse + + + + + + Reasoning + + + +``` + +```vue [ContextCacheUsage.vue] height=260 collapse + + + + + + Cache + + + +``` + +```vue [TokensWithCost.vue] height=260 collapse + + + + + {{ formattedTokens }} + + • {{ costText }} + + + +``` + +```ts [context.ts] height=260 collapse +import type { LanguageModelUsage } from 'ai' +import type { ComputedRef, InjectionKey } from 'vue' +import { inject } from 'vue' + +export type ModelId = string + +export interface ContextContextValue { + usedTokens: ComputedRef + maxTokens: ComputedRef + usage: ComputedRef + modelId: ComputedRef +} + +export const ContextKey: InjectionKey + = Symbol('ContextContext') + +export function useContextValue(): ContextContextValue { + const context = inject(ContextKey) + if (!context) { + throw new Error('Context components must be used within Context') + } + return context +} +``` + +```ts [index.ts] height=260 collapse +export { default as Context } from './Context.vue' +export { default as ContextCacheUsage } from './ContextCacheUsage.vue' +export { default as ContextContent } from './ContextContent.vue' +export { default as ContextContentBody } from './ContextContentBody.vue' +export { default as ContextContentFooter } from './ContextContentFooter.vue' +export { default as ContextContentHeader } from './ContextContentHeader.vue' +export { default as ContextIcon } from './ContextIcon.vue' +export { default as ContextInputUsage } from './ContextInputUsage.vue' +export { default as ContextOutputUsage } from './ContextOutputUsage.vue' +export { default as ContextReasoningUsage } from './ContextReasoningUsage.vue' +export { default as ContextTrigger } from './ContextTrigger.vue' +export { default as TokensWithCost } from './TokensWithCost.vue' +``` +::: + +## Component Architecture + +The Context component uses a compound component pattern with Vue's `provide/inject` API for data sharing: + +1. **``** - Root provider component that holds all context data +2. **``** - Interactive trigger element (default: button with percentage) +3. **``** - Hover card content container +4. **``** - Header section with progress visualization +5. **``** - Body section for usage breakdowns +6. **``** - Footer section for total cost +7. **Usage Components** - Individual token usage displays (Input, Output, Reasoning, Cache) + +## Token Formatting + +The component uses `Intl.NumberFormat` with compact notation for automatic formatting: + +- Under 1,000: Shows exact count (e.g., "842") +- 1,000+: Shows with K suffix (e.g., "32K") +- 1,000,000+: Shows with M suffix (e.g., "1.5M") +- 1,000,000,000+: Shows with B suffix (e.g., "2.1B") + +## Cost Calculation + +When a `modelId` is provided, the component automatically calculates costs using the `tokenlens` library: + +- **Input tokens**: Cost based on model's input pricing +- **Output tokens**: Cost based on model's output pricing +- **Reasoning tokens**: Special pricing for reasoning-capable models +- **Cached tokens**: Reduced pricing for cached input tokens +- **Total cost**: Sum of all token type costs + +Costs are formatted using `Intl.NumberFormat` with USD currency. + +## Styling + +The component uses Tailwind CSS classes and follows your design system: + +- Progress indicator uses `currentColor` for theme adaptation +- Hover card has customizable width and padding +- Footer has a secondary background for visual separation +- All text sizes use the `text-xs` class for consistency +- Muted foreground colors for secondary information + +## Features + +- **Compound Component Architecture:** Flexible composition of context display elements +- **Visual Progress Indicator:** Circular SVG progress ring showing context usage percentage +- **Token Breakdown:** Detailed view of input, output, reasoning, and cached tokens +- **Cost Estimation:** Real-time cost calculation using the tokenlens library +- **Intelligent Formatting:** Automatic token count formatting (K, M, B suffixes) +- **Interactive Hover Card:** Detailed information revealed on hover +- **Context Provider Pattern:** Clean data flow through Vue’s p`rovide/inject` API +- **TypeScript Support:** Full type definitions for all components +- **Accessible Design:** Proper ARIA labels and semantic HTML +- **Theme Integration:** Uses currentColor for automatic theme adaptation + +## Props + +### `` + +:::field-group + ::field{name="maxTokens" type="number" } + The total context window size in tokens. + :: + + ::field{name="usedTokens" type="number"} + The number of tokens currently used. + :: + + ::field{name="usage" type="LanguageModelUsage"} + Detailed token usage breakdown from the AI SDK (input, output, reasoning, cached tokens). + :: + + ::field{name="modelId" type="string"} + Model identifier for cost calculation (e.g., "openai:gpt-4", "anthropic:claude-3-opus"). + :: +::: + +### `` + +:::field-group + ::field{name="class" type="string"} + Additional CSS classes to apply to the component. + :: +::: + +### `` + +:::field-group + ::field{name="class" type="string"} + Additional CSS classes to apply to the component. + :: +::: + +### `` + +:::field-group + ::field{name="class" type="string"} + Additional CSS classes to apply to the component. + :: +::: + +### `` + +:::field-group + ::field{name="class" type="string"} + Additional CSS classes to apply to the component. + :: +::: + +### Usage Components + +All usage components (`ContextInputUsage`, `ContextOutputUsage`, `ContextReasoningUsage`, `ContextCacheUsage`) share the same props: + +:::field-group + ::field{name="class" type="string"} + Additional CSS classes to apply to the component. + :: +::: diff --git a/apps/www/plugins/ai-elements.ts b/apps/www/plugins/ai-elements.ts index eaa2a75..85a6203 100644 --- a/apps/www/plugins/ai-elements.ts +++ b/apps/www/plugins/ai-elements.ts @@ -7,6 +7,7 @@ import { Checkpoint, CodeBlock, CodeBlockDark, + Context, Confirmation, ConfirmationAccepted, ConfirmationRejected, @@ -78,6 +79,7 @@ export default defineNuxtPlugin((nuxtApp) => { vueApp.component('CodeBlockDark', CodeBlockDark) vueApp.component('Checkpoint', Checkpoint) vueApp.component('Workflow', Workflow) + vueApp.component('Context', Context) vueApp.component('Confirmation', Confirmation) vueApp.component('ConfirmationAccepted', ConfirmationAccepted) vueApp.component('ConfirmationRejected', ConfirmationRejected) diff --git a/packages/elements/package.json b/packages/elements/package.json index 1bd9c4b..c6efb76 100644 --- a/packages/elements/package.json +++ b/packages/elements/package.json @@ -18,6 +18,7 @@ "motion-v": "^1.7.3", "shiki": "^3.14.0", "streamdown-vue": "^1.0.21", + "tokenlens": "^1.3.1", "vue": "^3.5.22", "vue-stick-to-bottom": "^0.1.0" }, diff --git a/packages/elements/src/context/Context.vue b/packages/elements/src/context/Context.vue new file mode 100644 index 0000000..93b84f6 --- /dev/null +++ b/packages/elements/src/context/Context.vue @@ -0,0 +1,29 @@ + + + + + + + diff --git a/packages/elements/src/context/ContextCacheUsage.vue b/packages/elements/src/context/ContextCacheUsage.vue new file mode 100644 index 0000000..b94eb8e --- /dev/null +++ b/packages/elements/src/context/ContextCacheUsage.vue @@ -0,0 +1,46 @@ + + + + + + Cache + + + diff --git a/packages/elements/src/context/ContextContent.vue b/packages/elements/src/context/ContextContent.vue new file mode 100644 index 0000000..a4167df --- /dev/null +++ b/packages/elements/src/context/ContextContent.vue @@ -0,0 +1,20 @@ + + + + + + + diff --git a/packages/elements/src/context/ContextContentBody.vue b/packages/elements/src/context/ContextContentBody.vue new file mode 100644 index 0000000..966e67e --- /dev/null +++ b/packages/elements/src/context/ContextContentBody.vue @@ -0,0 +1,14 @@ + + + + + + + diff --git a/packages/elements/src/context/ContextContentFooter.vue b/packages/elements/src/context/ContextContentFooter.vue new file mode 100644 index 0000000..bc338ec --- /dev/null +++ b/packages/elements/src/context/ContextContentFooter.vue @@ -0,0 +1,50 @@ + + + + + + + + Total cost + {{ totalCost }} + + + diff --git a/packages/elements/src/context/ContextContentHeader.vue b/packages/elements/src/context/ContextContentHeader.vue new file mode 100644 index 0000000..f14f589 --- /dev/null +++ b/packages/elements/src/context/ContextContentHeader.vue @@ -0,0 +1,50 @@ + + + + + + + + + {{ displayPct }} + + {{ used }} / {{ total }} + + + + + + + + diff --git a/packages/elements/src/context/ContextIcon.vue b/packages/elements/src/context/ContextIcon.vue new file mode 100644 index 0000000..0dc8ac3 --- /dev/null +++ b/packages/elements/src/context/ContextIcon.vue @@ -0,0 +1,62 @@ + + + + + + + + diff --git a/packages/elements/src/context/ContextInputUsage.vue b/packages/elements/src/context/ContextInputUsage.vue new file mode 100644 index 0000000..5c862b0 --- /dev/null +++ b/packages/elements/src/context/ContextInputUsage.vue @@ -0,0 +1,47 @@ + + + + + + + Input + + + diff --git a/packages/elements/src/context/ContextOutputUsage.vue b/packages/elements/src/context/ContextOutputUsage.vue new file mode 100644 index 0000000..7a48141 --- /dev/null +++ b/packages/elements/src/context/ContextOutputUsage.vue @@ -0,0 +1,46 @@ + + + + + + Output + + + diff --git a/packages/elements/src/context/ContextReasoningUsage.vue b/packages/elements/src/context/ContextReasoningUsage.vue new file mode 100644 index 0000000..a240199 --- /dev/null +++ b/packages/elements/src/context/ContextReasoningUsage.vue @@ -0,0 +1,49 @@ + + + + + + Reasoning + + + diff --git a/packages/elements/src/context/ContextTrigger.vue b/packages/elements/src/context/ContextTrigger.vue new file mode 100644 index 0000000..563a068 --- /dev/null +++ b/packages/elements/src/context/ContextTrigger.vue @@ -0,0 +1,33 @@ + + + + + + + + + {{ renderedPercent }} + + + + + diff --git a/packages/elements/src/context/TokensWithCost.vue b/packages/elements/src/context/TokensWithCost.vue new file mode 100644 index 0000000..46eff1c --- /dev/null +++ b/packages/elements/src/context/TokensWithCost.vue @@ -0,0 +1,25 @@ + + + + + {{ formattedTokens }} + + • {{ costText }} + + + diff --git a/packages/elements/src/context/context.ts b/packages/elements/src/context/context.ts new file mode 100644 index 0000000..8491a0c --- /dev/null +++ b/packages/elements/src/context/context.ts @@ -0,0 +1,23 @@ +import type { LanguageModelUsage } from 'ai' +import type { ComputedRef, InjectionKey } from 'vue' +import { inject } from 'vue' + +export type ModelId = string + +export interface ContextContextValue { + usedTokens: ComputedRef + maxTokens: ComputedRef + usage: ComputedRef + modelId: ComputedRef +} + +export const ContextKey: InjectionKey + = Symbol('ContextContext') + +export function useContextValue(): ContextContextValue { + const context = inject(ContextKey) + if (!context) { + throw new Error('Context components must be used within Context') + } + return context +} diff --git a/packages/elements/src/context/index.ts b/packages/elements/src/context/index.ts new file mode 100644 index 0000000..017452b --- /dev/null +++ b/packages/elements/src/context/index.ts @@ -0,0 +1,12 @@ +export { default as Context } from './Context.vue' +export { default as ContextCacheUsage } from './ContextCacheUsage.vue' +export { default as ContextContent } from './ContextContent.vue' +export { default as ContextContentBody } from './ContextContentBody.vue' +export { default as ContextContentFooter } from './ContextContentFooter.vue' +export { default as ContextContentHeader } from './ContextContentHeader.vue' +export { default as ContextIcon } from './ContextIcon.vue' +export { default as ContextInputUsage } from './ContextInputUsage.vue' +export { default as ContextOutputUsage } from './ContextOutputUsage.vue' +export { default as ContextReasoningUsage } from './ContextReasoningUsage.vue' +export { default as ContextTrigger } from './ContextTrigger.vue' +export { default as TokensWithCost } from './TokensWithCost.vue' diff --git a/packages/elements/src/index.ts b/packages/elements/src/index.ts index 03fa0fa..7634bc1 100644 --- a/packages/elements/src/index.ts +++ b/packages/elements/src/index.ts @@ -4,6 +4,7 @@ export * from './branch' export * from './chain-of-thought' export * from './checkpoint' export * from './code-block' +export * from './context' export * from './confirmation' export * from './conversation' export * from './image' diff --git a/packages/examples/src/context.vue b/packages/examples/src/context.vue new file mode 100644 index 0000000..72d82be --- /dev/null +++ b/packages/examples/src/context.vue @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/examples/src/index.ts b/packages/examples/src/index.ts index 01abec2..e7c0beb 100644 --- a/packages/examples/src/index.ts +++ b/packages/examples/src/index.ts @@ -6,6 +6,7 @@ export { default as ChainOfThought } from './chain-of-thought.vue' export { default as Checkpoint } from './checkpoint.vue' export { default as CodeBlockDark } from './code-block-dark.vue' export { default as CodeBlock } from './code-block.vue' +export { default as Context } from './context.vue' export { default as ConfirmationAccepted } from './confirmation-accepted.vue' export { default as ConfirmationRejected } from './confirmation-rejected.vue' export { default as ConfirmationRequest } from './confirmation-request.vue' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fdb6d75..7ecaf46 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,6 +128,9 @@ importers: streamdown-vue: specifier: ^1.0.21 version: 1.0.21(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3)) + tokenlens: + specifier: ^1.3.1 + version: 1.3.1 vue: specifier: ^3.5.22 version: 3.5.22(typescript@5.9.3) @@ -1542,7 +1545,6 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@oxc-parser/binding-linux-arm64-musl@0.78.0': resolution: {integrity: sha512-VBdPB2N37A+M49zPV8ziiFywlgE3VX3AnR+zT1cIdQyKDoFM3uGPtjmtRe1qw6KhFF5YtxInzb0v3E3VkSdhuQ==} @@ -1570,7 +1572,6 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@oxc-parser/binding-linux-riscv64-gnu@0.78.0': resolution: {integrity: sha512-743OajvLP/fJm2d2da4/vqLMfki6XxfXizbUfPzEAXJMH0vEjf63s4gf55SBuy6hpmXOdCW5k4L6AoS+E89qtw==} @@ -1654,7 +1655,6 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@oxc-parser/binding-linux-x64-musl@0.78.0': resolution: {integrity: sha512-ctEL662Oe9Gaqf/48lsVZzAMcAcXIWsddZy59kGH7592rJBaXxmQhkOnnVEeJF25k4JMbCCdYwGsgI7WtC+Fdg==} @@ -1675,14 +1675,12 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@oxc-parser/binding-linux-x64-musl@0.95.0': resolution: {integrity: sha512-bWnrLfGDcx/fab0+UQnFbVFbiykof/btImbYf+cI2pU/1Egb2x+OKSmM5Qt0nEUiIpM5fgJmYXxTopybSZOKYA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@oxc-parser/binding-wasm32-wasi@0.78.0': resolution: {integrity: sha512-Pq0uT2CuN3J7Tv3KLuO7Sh4C7zTuqdJl0IDg3zB5keKx0BSbaEWewJL2CUNYUlG8txf+sMpUV+bkAIS5MEcKAw==} @@ -1884,14 +1882,12 @@ packages: engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] '@oxc-transform/binding-linux-arm64-gnu@0.95.0': resolution: {integrity: sha512-NLdrFuEHlmbiC1M1WESFV4luUcB/84GXi+cbnRXhgMjIW/CThRVJ989eTJy59QivkVlLcJSKTiKiKCt0O6TTlQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] '@oxc-transform/binding-linux-arm64-musl@0.78.0': resolution: {integrity: sha512-dr9J1uRo6ssDtuqx7s9GeePEDXlQOf4jk8/Tke9x5PCSJim5goMebEoAikuPf0jMhMNc05Kow0eOPLX1EmwsFQ==} @@ -1905,14 +1901,12 @@ packages: engines: {node: '>=14.0.0'} cpu: [arm64] os: [linux] - libc: [musl] '@oxc-transform/binding-linux-arm64-musl@0.95.0': resolution: {integrity: sha512-GL0ffCPW8JlFI0/jeSgCY665yDdojHxA0pbYG+k8oEHOWCYZUZK9AXL+r0oerNEWYJ8CRB+L5Yq87ZtU/YUitw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] '@oxc-transform/binding-linux-riscv64-gnu@0.78.0': resolution: {integrity: sha512-ALNvBi1l+17moTS2BtVZRxR0D1BGyR7iddNUJkHxEegvNzHyGJTZ60b0IXdvpCTH+CKUNsM40KxCVdzHca6VJQ==} @@ -1926,14 +1920,12 @@ packages: engines: {node: '>=14.0.0'} cpu: [riscv64] os: [linux] - libc: [glibc] '@oxc-transform/binding-linux-riscv64-gnu@0.95.0': resolution: {integrity: sha512-tbH7LaClSmN3YFVo1UjMSe7D6gkb5f+CMIbj9i873UUZomVRmAjC4ygioObfzM+sj/tX0WoTXx5L1YOfQkHL6Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] - libc: [glibc] '@oxc-transform/binding-linux-s390x-gnu@0.78.0': resolution: {integrity: sha512-s0r4cz6zZqr7SqfoUinn27B/mp1aiFVUsbsI4vomc7DtZkLpBSnSOAomZBlb0OSLbR9n2YPXm1033XR5W+ezWg==} @@ -1947,14 +1939,12 @@ packages: engines: {node: '>=14.0.0'} cpu: [s390x] os: [linux] - libc: [glibc] '@oxc-transform/binding-linux-s390x-gnu@0.95.0': resolution: {integrity: sha512-8jMqiURWa0iTiPMg7BWaln89VdhhWzNlPyKM90NaFVVhBIKCr2UEhrQWdpBw/E9C8uWf/4VabBEhfPMK+0yS4w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] '@oxc-transform/binding-linux-x64-gnu@0.78.0': resolution: {integrity: sha512-nH9y61/1oyCQfUjtKHEnnMPBJZOhH+G2QqSAD7sCH35Iz78UA+bKVjHnlfnhBedy1xWCNwlboNclaBTHYAgNeA==} @@ -1968,14 +1958,12 @@ packages: engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] - libc: [glibc] '@oxc-transform/binding-linux-x64-gnu@0.95.0': resolution: {integrity: sha512-D5ULJ2uWipsTgfvHIvqmnGkCtB3Fyt2ZN7APRjVO+wLr+HtmnaWddKsLdrRWX/m/6nQ2xQdoQekdJrokYK9LtQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] '@oxc-transform/binding-linux-x64-musl@0.78.0': resolution: {integrity: sha512-Yo+pmsW49QNo4F4RoqOhfRxN9851Td/nc93ESQbzav9vhriipPRvZRVusG5t126inAgjlprFbOet5TXSWKd92A==} @@ -1989,14 +1977,12 @@ packages: engines: {node: '>=14.0.0'} cpu: [x64] os: [linux] - libc: [musl] '@oxc-transform/binding-linux-x64-musl@0.95.0': resolution: {integrity: sha512-DmCGU+FzRezES5wVAGVimZGzYIjMOapXbWpxuz8M8p3nMrfdBEQ5/tpwBp2vRlIohhABy4vhHJByl4c64ENCGQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] '@oxc-transform/binding-wasm32-wasi@0.78.0': resolution: {integrity: sha512-djA47tsuUwNPHqcxre+EMD/wBBaP+TP6kQt2ioC6XElRldHCEGBUsVidrS5rgN4O7SyKx/DuJ528locJKTDSPw==} @@ -2648,6 +2634,18 @@ packages: peerDependencies: vue: ^2.7.0 || ^3.0.0 + '@tokenlens/core@1.3.0': + resolution: {integrity: sha512-d8YNHNC+q10bVpi95fELJwJyPVf1HfvBEI18eFQxRSZTdByXrP+f/ZtlhSzkx0Jl0aEmYVeBA5tPeeYRioLViQ==} + + '@tokenlens/fetch@1.3.0': + resolution: {integrity: sha512-RONDRmETYly9xO8XMKblmrZjKSwCva4s5ebJwQNfNlChZoA5kplPoCgnWceHnn1J1iRjLVlrCNB43ichfmGBKQ==} + + '@tokenlens/helpers@1.3.1': + resolution: {integrity: sha512-t6yL8N6ES8337E6eVSeH4hCKnPdWkZRFpupy9w5E66Q9IeqQ9IO7XQ6gh12JKjvWiRHuyyJ8MBP5I549Cr41EQ==} + + '@tokenlens/models@1.3.0': + resolution: {integrity: sha512-9mx7ZGeewW4ndXAiD7AT1bbCk4OpJeortbjHHyNkgap+pMPPn1chY6R5zqe1ggXIUzZ2l8VOAKfPqOvpcrisJw==} + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -6965,6 +6963,9 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + tokenlens@1.3.1: + resolution: {integrity: sha512-7oxmsS5PNCX3z+b+z07hL5vCzlgHKkCGrEQjQmWl5l+v5cUrtL7S1cuST4XThaL1XyjbTX8J5hfP0cjDJRkaLA==} + toml-eslint-parser@0.10.0: resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -10312,6 +10313,21 @@ snapshots: '@tanstack/virtual-core': 3.13.12 vue: 3.5.22(typescript@5.9.3) + '@tokenlens/core@1.3.0': {} + + '@tokenlens/fetch@1.3.0': + dependencies: + '@tokenlens/core': 1.3.0 + + '@tokenlens/helpers@1.3.1': + dependencies: + '@tokenlens/core': 1.3.0 + '@tokenlens/fetch': 1.3.0 + + '@tokenlens/models@1.3.0': + dependencies: + '@tokenlens/core': 1.3.0 + '@trysound/sax@0.2.0': optional: true @@ -16152,6 +16168,13 @@ snapshots: toidentifier@1.0.1: {} + tokenlens@1.3.1: + dependencies: + '@tokenlens/core': 1.3.0 + '@tokenlens/fetch': 1.3.0 + '@tokenlens/helpers': 1.3.1 + '@tokenlens/models': 1.3.0 + toml-eslint-parser@0.10.0: dependencies: eslint-visitor-keys: 3.4.3
{{ displayPct }}
+ {{ used }} / {{ total }} +