@kunal_dutt/token-lens 0.2.48 → 0.2.50
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 +5 -1
- package/dist-helper/core.js +3 -3
- package/package.json +1 -1
- package/server.mjs +90 -72
- package/token-lens-helper.zip +0 -0
- package/token-lens.mcpb +0 -0
package/README.md
CHANGED
|
@@ -57,7 +57,11 @@ Token Lens never asks for it. Instead it offers **Token Lens Helper**, a small
|
|
|
57
57
|
native Mac app set up from the chat only when you agree (say yes when Claude
|
|
58
58
|
offers it, or click **Set up Token Lens Helper** in the Token Lens card): you turn
|
|
59
59
|
it on once in System Settings > Privacy & Security > Accessibility. It reads only
|
|
60
|
-
the message box and chat of
|
|
60
|
+
the message box and chat of the AI app in front (Claude, ChatGPT, Perplexity,
|
|
61
|
+
Copilot, Gemini, Grok, DeepSeek or Le Chat) or of an AI chat site open in Safari,
|
|
62
|
+
Chrome, Edge, Arc, Brave, Vivaldi, Opera or Firefox (chatgpt.com, claude.ai,
|
|
63
|
+
gemini.google.com, perplexity.ai, chat.deepseek.com, chat.mistral.ai, grok.com,
|
|
64
|
+
copilot.microsoft.com), never your other tabs, and runs
|
|
61
65
|
Token Lens's own optimizer inside itself, with no model calls. While you type, a
|
|
62
66
|
**Shorten** button appears just above the message box when a shorter prompt says
|
|
63
67
|
the same thing; one click swaps it in (only if the box still holds the draft it
|
package/dist-helper/core.js
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
}
|
|
48
48
|
})(globalThis);
|
|
49
49
|
|
|
50
|
-
"use strict";(()=>{var Ra=Object.defineProperty;var Pa=(i,e,a)=>e in i?Ra(i,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[e]=a;var m=(i,e,a)=>Pa(i,typeof e!="symbol"?e+"":e,a);function J(i,e,a,n){let r=n&&n>0?n:a.contextWindow,t=(i+e)/r,o=t>=.95?"full":t>=.8?"hot":t>=.5?"warm":"ok";return{conversationTokens:i,promptTokens:e,window:r,ratio:t,zone:o,longChat:i>=4e4}}function De(i,e){return i!=="auto"?i:e.zone==="hot"||e.zone==="full"?"aggressive":"balanced"}var za={coding:"the files and functions involved, the current state of the code (only the parts still changing, verbatim), and what is left to build",debugging:"the bug, what has been ruled out, the most likely cause, and the exact error message",writing:"the audience, tone, the current outline, and any passages I approved (verbatim)",editing:"the style rules we settled on and which parts are already done",analysis:"the dataset's shape, the findings so far with their numbers, and the next questions",research:"the question, the answers found so far with their sources, and what is still open"},z="Optional: the new chat only knows what the brief keeps, so later answers can differ. Check the brief before you rely on it.";function Ne(i){return["Write a handoff brief of this conversation that I can paste into a new chat to continue without the history.",`Cover: ${za[i]??"the goal, the decisions made, and the current state"}; plus open questions and my preferences.`,"Use terse bullets, under 250 words, and nothing else."].join(" ")}var q=i=>i.toLocaleString("en-US");function fe(i){let{profile:e,task:a,signals:n,promptTokens:r,usage:t,text:o}=i,s=[];if(a==="coding"&&n.pastedTokens>1500&&s.push({id:"paste-less-code",text:`About ${q(n.pastedTokens)} tokens of pasted code. Paste only the functions involved.`,saves:"input"}),a==="debugging"&&n.hasLogs&&n.pastedTokens>800&&s.push({id:"trim-logs",text:"Long log pasted. The first error and its stack are usually enough; Optimize collapses repeated lines and library frames.",saves:"input"}),a==="analysis"&&n.hasData&&n.pastedTokens>2e3&&s.push({id:"sample-data",text:"Large table pasted. The header plus ~20 sample rows and a description of the rest is usually enough; or attach the file instead.",saves:"input"}),n.pastedTokens>t.window*.4&&s.push({id:"split-material",text:`The pasted material is ${Math.round(n.pastedTokens/t.window*100)}% of ${e.label}'s context. Split it into parts or paste only what's needed.`,saves:"input"}),e.family==="anthropic"&&n.pastedTokens>300&&!/<[a-z][\w-]*>/i.test(o))for(let d of e.notes??[])s.push({id:"family-note",text:d,saves:"input"});t.zone==="hot"||t.zone==="full"?s.push({id:"handoff",text:`This chat fills about ${Math.round(t.ratio*100)}% of ${e.label}'s context. Older messages will be dropped or compacted soon. Hand off to a new chat. ${z}`,saves:"input"}):(t.longChat||t.zone==="warm")&&s.push({id:"handoff",text:`Every new message re-reads about ${q(t.conversationTokens)} tokens of history. A handoff brief and a new chat cut that. ${z}`,saves:"input"});let l=e.pricing?.longContext,u=t.conversationTokens+r;return l&&e.pricing&&u>=l.aboveTokens*.85&&s.push({id:"price-threshold",text:u>l.aboveTokens?`This message reads \u2248${q(u)} tokens, past ${q(l.aboveTokens)}, so ${e.label} bills all of it at $${l.inputPerMTok}/M instead of $${e.pricing.inputPerMTok}/M. Continuing from a handoff brief in a new chat brings it back under. ${z}`:`This chat is \u2248${q(u)} tokens; past ${q(l.aboveTokens)}, ${e.label} bills every message at $${l.inputPerMTok}/M instead of $${e.pricing.inputPerMTok}/M. Hand off to a new chat before then. ${z}`,saves:"input"}),s}var R="<|endoftext|>",I="<|fim_prefix|>",M="<|fim_middle|>",x="<|fim_suffix|>",B="<|im_start|>",F="<|im_end|>",j="<|im_sep|>",D="<|endofprompt|>",ve="<|startoftext|>",$="<|start|>",Y="<|end|>",X="<|message|>",Q="<|channel|>",Z="<|return|>",ee="<|constrain|>",ae="<|call|>";var Le=i=>i<=127;function ye(i){if(i.length===0)return!1;let e=i.charCodeAt(i.length-1);return e>=55296&&e<=56319}function Ia(i){let e=0;for(;e<i.length;){let a=i[e],n=0,r=0;if(a<=127)n=1,r=a;else if((a&224)===192){if(n=2,r=a&31,a<=193)return!1}else if((a&240)===224)n=3,r=a&15;else if((a&248)===240){if(n=4,r=a&7,a>244)return!1}else return!1;if(e+n>i.length)return!1;for(let t=1;t<n;t++){let o=i[e+t];if(o===void 0||(o&192)!==128)return!1;r=r<<6|o&63}if(n===2&&r<128||n===3&&r<2048||n===4&&r<65536||r>=55296&&r<=57343||r>1114111)return!1;e+=n}return!0}var Ma=new TextDecoder("utf8",{fatal:!1});function Oe(i){if(Ia(i))return Ma.decode(i)}function Be(i,e){let a=Math.min(i.length,e.length);for(let n=0;n<a;n++)if(i[n]!==e[n])return i[n]-e[n];return i.length-e.length}function Fe(i){let e=0;return i.forEach(a=>{e=Math.max(e,a)}),e}function we(i){return i.replace(/[$()*+.?[\\\]^{|}]/g,"\\$&")}function Se(i){let e=[...i].map(we).join("|");return new RegExp(`(${e})`)}var te=new Uint8Array(0),H=new TextDecoder("utf8"),qe=class{constructor({bytePairRankDecoder:i,specialTokensEncoder:e,tokenSplitRegex:a,mergeCacheSize:n=1e5}){m(this,"mergeableBytePairRankCount");m(this,"bytePairRankDecoder");m(this,"bytePairNonUtfRankDecoder",new Map);m(this,"bytePairNonUtfSortedEncoder");m(this,"bytePairStringRankEncoder");m(this,"tokenSplitRegex");m(this,"specialTokensEncoder");m(this,"specialTokensDecoder");m(this,"specialTokenPatternRegex");m(this,"textEncoder",new TextEncoder);m(this,"mergeCache");m(this,"mergeCacheSize");this.bytePairRankDecoder=i,this.bytePairStringRankEncoder=new Map,this.mergeCacheSize=n,n>0&&(this.mergeCache=new Map),this.mergeableBytePairRankCount=Object.keys(i).length;let r=[];i.forEach((o,s)=>{if(typeof o=="string"){this.bytePairStringRankEncoder.set(o,s);return}let l=new Uint8Array(o);r.push([l,s]),this.bytePairNonUtfRankDecoder.set(s,l)}),this.bytePairNonUtfSortedEncoder=r.sort((o,s)=>Be(o[0],s[0])),this.specialTokensEncoder=e??new Map,this.specialTokensDecoder=e?new Map([...e].map(([o,s])=>[s,o])):new Map,this.tokenSplitRegex=a;let t=[...this.specialTokensEncoder.keys()].map(we).join("|");try{this.specialTokenPatternRegex=new RegExp(t,"y")}catch{throw new Error("Invalid regular expression pattern.")}}setMergeCacheSize(i){this.mergeCacheSize===0&&i>0&&(this.mergeCache=new Map),this.mergeCacheSize=i,i===0&&(this.mergeCache=void 0)}clearMergeCache(){this.mergeCache?.clear()}*encodeNativeGenerator(i,e){let a=0,n=0;for(;;){let r=this.findNextSpecialToken(i,e,a),t=r?.[0],o=t??i.length,s=a===0&&o===i.length?i:i.slice(a,o);for(let[l]of s.matchAll(this.tokenSplitRegex)){let u=this.getBpeRankFromString(l);if(u!==void 0){n=1,yield[u];continue}let d=this.bytePairEncode(l);n=d.length,yield d}if(t!==void 0){let l=r[1],u=this.specialTokensEncoder.get(l);if(u===void 0)throw new Error(`Special token "${l}" is not in the special token encoder.`);yield[u],a=t+l.length,n=1}else break}return n}encodeNative(i,e){let a=0,n=[];for(;;){let r=this.findNextSpecialToken(i,e,a),t=r?.[0],o=t??i.length,s=a===0&&o===i.length?i:i.slice(a,o);for(let[l]of s.matchAll(this.tokenSplitRegex)){let u=this.getBpeRankFromString(l);if(u!==void 0){n.push(u);continue}let d=this.bytePairEncode(l);n.push(...d)}if(t!==void 0){let l=r[1],u=this.specialTokensEncoder.get(l);if(u===void 0)throw new Error(`Special token "${l}" is not in the special token encoder.`);n.push(u),a=t+l.length}else break}return n}countNative(i,e){let a=0,n=0;for(;;){let r=this.findNextSpecialToken(i,e,a),t=r?.[0],o=t??i.length,s=a===0&&o===i.length?i:i.slice(a,o);for(let[l]of s.matchAll(this.tokenSplitRegex)){if(this.getBpeRankFromString(l)!==void 0){n++;continue}let u=this.bytePairEncode(l);n+=u.length}if(t!==void 0){let l=r[1];if(this.specialTokensEncoder.get(l)===void 0)throw new Error(`Special token "${l}" is not in the special token encoder.`);n++,a=t+l.length}else break}return n}*decodeNativeGenerator(i){for(let e of i){let a=this.tryDecodeToken(e);a&&(yield a)}}decodeNative(i){let e="",a=te;for(let n of i){let r=this.tryDecodeToken(n);if(r===void 0)throw new Error(`Token ${n} is not in the byte pair encoder.`);if(typeof r=="string")a!==te&&(e+=H.decode(a,{stream:!0}),a=te),e+=r;else{let t=new Uint8Array(a.length+r.length);t.set(a),t.set(r,a.length),a=t}}return a!==te&&(e+=H.decode(a,{stream:!0})),e}async*decodeNativeAsyncIterable(i){for await(let e of i){let a=this.tryDecodeToken(e);a&&(yield a)}}getBpeRankFromString(i){return this.bytePairStringRankEncoder.get(i)}getBpeRankFromStringOrThrow(i){let e=this.getBpeRankFromString(i);if(e===void 0)throw new Error(`The byte-pair encoding does not contain a value for: ${i}`);return e}getBpeRankFromBytes(i){let e=Oe(i);if(e!==void 0)return this.getBpeRankFromString(e);let a=this.binarySearch(i);if(a!==-1)return this.bytePairNonUtfSortedEncoder[a][1]}getBpeRankFromBytesOrThrow(i){let e=this.getBpeRankFromBytes(i);if(e===void 0)throw new Error(`The byte-pair encoding does not contain a value for: ${i.toString()}`);return e}binarySearch(i){let e=0,a=this.bytePairNonUtfSortedEncoder.length-1;for(;e<=a;){let n=e+a>>>1,r=this.bytePairNonUtfSortedEncoder[n][0],t=0,o=Math.min(r.length,i.length);for(let s=0;s<o&&(t=r[s]-i[s],t===0);s++);if(t===0&&(t=r.length-i.length),t===0)return n;t<0?e=n+1:a=n-1}return-1}findNextSpecialToken(i,e,a){let n=a;for(;;){this.specialTokenPatternRegex.lastIndex=n;let r=this.specialTokenPatternRegex.exec(i);if(!r)return;let t=r[0];if(e?.has(t))return[r.index+n,t];n=r.index+n+1}}tryDecodeToken(i){let e=this.bytePairRankDecoder[i];if(typeof e=="string")return e;if(typeof e=="object"){let a=this.bytePairNonUtfRankDecoder.get(i);if(a)return a}return this.specialTokensDecoder.get(i)}addToMergeCache(i,e){if(this.mergeCache){if(this.mergeCache.size>=this.mergeCacheSize){let a=this.mergeCache.keys().next().value;this.mergeCache.delete(a)}this.mergeCache.set(i,e)}}bytePairEncode(i){if(i.length===1&&Le(i.codePointAt(0)))return[this.getBpeRankFromStringOrThrow(i)];if(this.mergeCache?.has(i)){let n=this.mergeCache.get(i);return this.mergeCache.delete(i),this.mergeCache.set(i,n),n}let e=this.textEncoder.encode(i),a=this.bytePairMerge(e);return this.addToMergeCache(i,a),a}bytePairMerge(i){let e=[],a=[],n=(t,o=e[t],s=e[t+2])=>{if(s===void 0)return Number.POSITIVE_INFINITY;let l=i.subarray(o,s);return this.getBpeRankFromBytes(l)??Number.POSITIVE_INFINITY};for(let t=0;t<=i.length;t++)e.push(t),t<i.length-1?a.push(n(t,t,t+2)):a.push(Number.POSITIVE_INFINITY);for(;e.length>1;){let t=Number.POSITIVE_INFINITY,o=-1;for(let s=0;s<a.length-1;s++){let l=a[s];l<t&&(t=l,o=s)}if(t===Number.POSITIVE_INFINITY||o===-1)break;e.splice(o+1,1),a.splice(o,1),a[o]=n(o),o>0&&(a[o-1]=n(o-1))}let r=[];for(let t=0;t<e.length-1;t++){let o=e[t],s=e[t+1],l=this.getBpeRankFromBytesOrThrow(i.subarray(o,s));r.push(l)}return r}};function xa(i,e){let a=0;if(i.role&&(a+=e(i.role)),i.content&&(a+=e(i.content)),i.name&&(a+=e(i.name)+1),i.function_call){let{name:n,arguments:r}=i.function_call;n&&(a+=e(n)),r&&(a+=e(r)),a+=3}return a+=3,i.role==="function"&&(a-=2),a}function He(i,e,a){if(!i.properties)return"";let n=[],r=new Set(i.required??[]),t=" ".repeat(e);for(let[o,s]of Object.entries(i.properties)){s.description&&e<2&&n.push(`${t}// ${s.description}`);let l=r.has(o),u=a(s,e);n.push(`${t}${o}${l?"":"?"}: ${u},`)}return n.join(`
|
|
50
|
+
"use strict";(()=>{var Ra=Object.defineProperty;var Pa=(i,e,a)=>e in i?Ra(i,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[e]=a;var m=(i,e,a)=>Pa(i,typeof e!="symbol"?e+"":e,a);function $(i,e,a,n){let r=n&&n>0?n:a.contextWindow,t=(i+e)/r,o=t>=.95?"full":t>=.8?"hot":t>=.5?"warm":"ok";return{conversationTokens:i,promptTokens:e,window:r,ratio:t,zone:o,longChat:i>=4e4}}function De(i,e){return i!=="auto"?i:e.zone==="hot"||e.zone==="full"?"aggressive":"balanced"}var za={coding:"the files and functions involved, the current state of the code (only the parts still changing, verbatim), and what is left to build",debugging:"the bug, what has been ruled out, the most likely cause, and the exact error message",writing:"the audience, tone, the current outline, and any passages I approved (verbatim)",editing:"the style rules we settled on and which parts are already done",analysis:"the dataset's shape, the findings so far with their numbers, and the next questions",research:"the question, the answers found so far with their sources, and what is still open"},z="Optional: the new chat only knows what the brief keeps, so later answers can differ. Check the brief before you rely on it.";function Ne(i){return["Write a handoff brief of this conversation that I can paste into a new chat to continue without the history.",`Cover: ${za[i]??"the goal, the decisions made, and the current state"}; plus open questions and my preferences.`,"Use terse bullets, under 250 words, and nothing else."].join(" ")}var q=i=>i.toLocaleString("en-US");function fe(i){let{profile:e,task:a,signals:n,promptTokens:r,usage:t,text:o}=i,s=[];if(a==="coding"&&n.pastedTokens>1500&&s.push({id:"paste-less-code",text:`About ${q(n.pastedTokens)} tokens of pasted code. Paste only the functions involved.`,saves:"input"}),a==="debugging"&&n.hasLogs&&n.pastedTokens>800&&s.push({id:"trim-logs",text:"Long log pasted. The first error and its stack are usually enough; Optimize collapses repeated lines and library frames.",saves:"input"}),a==="analysis"&&n.hasData&&n.pastedTokens>2e3&&s.push({id:"sample-data",text:"Large table pasted. The header plus ~20 sample rows and a description of the rest is usually enough; or attach the file instead.",saves:"input"}),n.pastedTokens>t.window*.4&&s.push({id:"split-material",text:`The pasted material is ${Math.round(n.pastedTokens/t.window*100)}% of ${e.label}'s context. Split it into parts or paste only what's needed.`,saves:"input"}),e.family==="anthropic"&&n.pastedTokens>300&&!/<[a-z][\w-]*>/i.test(o))for(let d of e.notes??[])s.push({id:"family-note",text:d,saves:"input"});t.zone==="hot"||t.zone==="full"?s.push({id:"handoff",text:`This chat fills about ${Math.round(t.ratio*100)}% of ${e.label}'s context. Older messages will be dropped or compacted soon. Hand off to a new chat. ${z}`,saves:"input"}):(t.longChat||t.zone==="warm")&&s.push({id:"handoff",text:`Every new message re-reads about ${q(t.conversationTokens)} tokens of history. A handoff brief and a new chat cut that. ${z}`,saves:"input"});let l=e.pricing?.longContext,u=t.conversationTokens+r;return l&&e.pricing&&u>=l.aboveTokens*.85&&s.push({id:"price-threshold",text:u>l.aboveTokens?`This message reads \u2248${q(u)} tokens, past ${q(l.aboveTokens)}, so ${e.label} bills all of it at $${l.inputPerMTok}/M instead of $${e.pricing.inputPerMTok}/M. Continuing from a handoff brief in a new chat brings it back under. ${z}`:`This chat is \u2248${q(u)} tokens; past ${q(l.aboveTokens)}, ${e.label} bills every message at $${l.inputPerMTok}/M instead of $${e.pricing.inputPerMTok}/M. Hand off to a new chat before then. ${z}`,saves:"input"}),s}var R="<|endoftext|>",I="<|fim_prefix|>",M="<|fim_middle|>",x="<|fim_suffix|>",B="<|im_start|>",F="<|im_end|>",j="<|im_sep|>",D="<|endofprompt|>",ve="<|startoftext|>",Y="<|start|>",X="<|end|>",Q="<|message|>",Z="<|channel|>",ee="<|return|>",ae="<|constrain|>",ie="<|call|>";var Le=i=>i<=127;function ye(i){if(i.length===0)return!1;let e=i.charCodeAt(i.length-1);return e>=55296&&e<=56319}function Ia(i){let e=0;for(;e<i.length;){let a=i[e],n=0,r=0;if(a<=127)n=1,r=a;else if((a&224)===192){if(n=2,r=a&31,a<=193)return!1}else if((a&240)===224)n=3,r=a&15;else if((a&248)===240){if(n=4,r=a&7,a>244)return!1}else return!1;if(e+n>i.length)return!1;for(let t=1;t<n;t++){let o=i[e+t];if(o===void 0||(o&192)!==128)return!1;r=r<<6|o&63}if(n===2&&r<128||n===3&&r<2048||n===4&&r<65536||r>=55296&&r<=57343||r>1114111)return!1;e+=n}return!0}var Ma=new TextDecoder("utf8",{fatal:!1});function Oe(i){if(Ia(i))return Ma.decode(i)}function Be(i,e){let a=Math.min(i.length,e.length);for(let n=0;n<a;n++)if(i[n]!==e[n])return i[n]-e[n];return i.length-e.length}function Fe(i){let e=0;return i.forEach(a=>{e=Math.max(e,a)}),e}function we(i){return i.replace(/[$()*+.?[\\\]^{|}]/g,"\\$&")}function Se(i){let e=[...i].map(we).join("|");return new RegExp(`(${e})`)}var te=new Uint8Array(0),H=new TextDecoder("utf8"),qe=class{constructor({bytePairRankDecoder:i,specialTokensEncoder:e,tokenSplitRegex:a,mergeCacheSize:n=1e5}){m(this,"mergeableBytePairRankCount");m(this,"bytePairRankDecoder");m(this,"bytePairNonUtfRankDecoder",new Map);m(this,"bytePairNonUtfSortedEncoder");m(this,"bytePairStringRankEncoder");m(this,"tokenSplitRegex");m(this,"specialTokensEncoder");m(this,"specialTokensDecoder");m(this,"specialTokenPatternRegex");m(this,"textEncoder",new TextEncoder);m(this,"mergeCache");m(this,"mergeCacheSize");this.bytePairRankDecoder=i,this.bytePairStringRankEncoder=new Map,this.mergeCacheSize=n,n>0&&(this.mergeCache=new Map),this.mergeableBytePairRankCount=Object.keys(i).length;let r=[];i.forEach((o,s)=>{if(typeof o=="string"){this.bytePairStringRankEncoder.set(o,s);return}let l=new Uint8Array(o);r.push([l,s]),this.bytePairNonUtfRankDecoder.set(s,l)}),this.bytePairNonUtfSortedEncoder=r.sort((o,s)=>Be(o[0],s[0])),this.specialTokensEncoder=e??new Map,this.specialTokensDecoder=e?new Map([...e].map(([o,s])=>[s,o])):new Map,this.tokenSplitRegex=a;let t=[...this.specialTokensEncoder.keys()].map(we).join("|");try{this.specialTokenPatternRegex=new RegExp(t,"y")}catch{throw new Error("Invalid regular expression pattern.")}}setMergeCacheSize(i){this.mergeCacheSize===0&&i>0&&(this.mergeCache=new Map),this.mergeCacheSize=i,i===0&&(this.mergeCache=void 0)}clearMergeCache(){this.mergeCache?.clear()}*encodeNativeGenerator(i,e){let a=0,n=0;for(;;){let r=this.findNextSpecialToken(i,e,a),t=r?.[0],o=t??i.length,s=a===0&&o===i.length?i:i.slice(a,o);for(let[l]of s.matchAll(this.tokenSplitRegex)){let u=this.getBpeRankFromString(l);if(u!==void 0){n=1,yield[u];continue}let d=this.bytePairEncode(l);n=d.length,yield d}if(t!==void 0){let l=r[1],u=this.specialTokensEncoder.get(l);if(u===void 0)throw new Error(`Special token "${l}" is not in the special token encoder.`);yield[u],a=t+l.length,n=1}else break}return n}encodeNative(i,e){let a=0,n=[];for(;;){let r=this.findNextSpecialToken(i,e,a),t=r?.[0],o=t??i.length,s=a===0&&o===i.length?i:i.slice(a,o);for(let[l]of s.matchAll(this.tokenSplitRegex)){let u=this.getBpeRankFromString(l);if(u!==void 0){n.push(u);continue}let d=this.bytePairEncode(l);n.push(...d)}if(t!==void 0){let l=r[1],u=this.specialTokensEncoder.get(l);if(u===void 0)throw new Error(`Special token "${l}" is not in the special token encoder.`);n.push(u),a=t+l.length}else break}return n}countNative(i,e){let a=0,n=0;for(;;){let r=this.findNextSpecialToken(i,e,a),t=r?.[0],o=t??i.length,s=a===0&&o===i.length?i:i.slice(a,o);for(let[l]of s.matchAll(this.tokenSplitRegex)){if(this.getBpeRankFromString(l)!==void 0){n++;continue}let u=this.bytePairEncode(l);n+=u.length}if(t!==void 0){let l=r[1];if(this.specialTokensEncoder.get(l)===void 0)throw new Error(`Special token "${l}" is not in the special token encoder.`);n++,a=t+l.length}else break}return n}*decodeNativeGenerator(i){for(let e of i){let a=this.tryDecodeToken(e);a&&(yield a)}}decodeNative(i){let e="",a=te;for(let n of i){let r=this.tryDecodeToken(n);if(r===void 0)throw new Error(`Token ${n} is not in the byte pair encoder.`);if(typeof r=="string")a!==te&&(e+=H.decode(a,{stream:!0}),a=te),e+=r;else{let t=new Uint8Array(a.length+r.length);t.set(a),t.set(r,a.length),a=t}}return a!==te&&(e+=H.decode(a,{stream:!0})),e}async*decodeNativeAsyncIterable(i){for await(let e of i){let a=this.tryDecodeToken(e);a&&(yield a)}}getBpeRankFromString(i){return this.bytePairStringRankEncoder.get(i)}getBpeRankFromStringOrThrow(i){let e=this.getBpeRankFromString(i);if(e===void 0)throw new Error(`The byte-pair encoding does not contain a value for: ${i}`);return e}getBpeRankFromBytes(i){let e=Oe(i);if(e!==void 0)return this.getBpeRankFromString(e);let a=this.binarySearch(i);if(a!==-1)return this.bytePairNonUtfSortedEncoder[a][1]}getBpeRankFromBytesOrThrow(i){let e=this.getBpeRankFromBytes(i);if(e===void 0)throw new Error(`The byte-pair encoding does not contain a value for: ${i.toString()}`);return e}binarySearch(i){let e=0,a=this.bytePairNonUtfSortedEncoder.length-1;for(;e<=a;){let n=e+a>>>1,r=this.bytePairNonUtfSortedEncoder[n][0],t=0,o=Math.min(r.length,i.length);for(let s=0;s<o&&(t=r[s]-i[s],t===0);s++);if(t===0&&(t=r.length-i.length),t===0)return n;t<0?e=n+1:a=n-1}return-1}findNextSpecialToken(i,e,a){let n=a;for(;;){this.specialTokenPatternRegex.lastIndex=n;let r=this.specialTokenPatternRegex.exec(i);if(!r)return;let t=r[0];if(e?.has(t))return[r.index+n,t];n=r.index+n+1}}tryDecodeToken(i){let e=this.bytePairRankDecoder[i];if(typeof e=="string")return e;if(typeof e=="object"){let a=this.bytePairNonUtfRankDecoder.get(i);if(a)return a}return this.specialTokensDecoder.get(i)}addToMergeCache(i,e){if(this.mergeCache){if(this.mergeCache.size>=this.mergeCacheSize){let a=this.mergeCache.keys().next().value;this.mergeCache.delete(a)}this.mergeCache.set(i,e)}}bytePairEncode(i){if(i.length===1&&Le(i.codePointAt(0)))return[this.getBpeRankFromStringOrThrow(i)];if(this.mergeCache?.has(i)){let n=this.mergeCache.get(i);return this.mergeCache.delete(i),this.mergeCache.set(i,n),n}let e=this.textEncoder.encode(i),a=this.bytePairMerge(e);return this.addToMergeCache(i,a),a}bytePairMerge(i){let e=[],a=[],n=(t,o=e[t],s=e[t+2])=>{if(s===void 0)return Number.POSITIVE_INFINITY;let l=i.subarray(o,s);return this.getBpeRankFromBytes(l)??Number.POSITIVE_INFINITY};for(let t=0;t<=i.length;t++)e.push(t),t<i.length-1?a.push(n(t,t,t+2)):a.push(Number.POSITIVE_INFINITY);for(;e.length>1;){let t=Number.POSITIVE_INFINITY,o=-1;for(let s=0;s<a.length-1;s++){let l=a[s];l<t&&(t=l,o=s)}if(t===Number.POSITIVE_INFINITY||o===-1)break;e.splice(o+1,1),a.splice(o,1),a[o]=n(o),o>0&&(a[o-1]=n(o-1))}let r=[];for(let t=0;t<e.length-1;t++){let o=e[t],s=e[t+1],l=this.getBpeRankFromBytesOrThrow(i.subarray(o,s));r.push(l)}return r}};function xa(i,e){let a=0;if(i.role&&(a+=e(i.role)),i.content&&(a+=e(i.content)),i.name&&(a+=e(i.name)+1),i.function_call){let{name:n,arguments:r}=i.function_call;n&&(a+=e(n)),r&&(a+=e(r)),a+=3}return a+=3,i.role==="function"&&(a-=2),a}function He(i,e,a){if(!i.properties)return"";let n=[],r=new Set(i.required??[]),t=" ".repeat(e);for(let[o,s]of Object.entries(i.properties)){s.description&&e<2&&n.push(`${t}// ${s.description}`);let l=r.has(o),u=a(s,e);n.push(`${t}${o}${l?"":"?"}: ${u},`)}return n.join(`
|
|
51
51
|
`)}function _e(i,e){switch(i.type){case"string":return i.enum?.map(a=>JSON.stringify(a)).join(" | ")??"string";case"integer":case"number":return i.enum?.map(a=>`${a}`).join(" | ")??"number";case"boolean":return"boolean";case"null":return"null";case"array":return i.items?`${_e(i.items,e)}[]`:"any[]";case"object":return`{
|
|
52
52
|
${He(i,e+2,_e)}
|
|
53
53
|
${" ".repeat(e)}}`;default:return"any"}}function ja(i){let e=["namespace functions {",""];for(let a of i){a.description&&e.push(`// ${a.description}`);let{parameters:n}=a,r=n?.properties;if(!n||!r||Object.keys(r).length===0)e.push(`type ${a.name} = () => any;`);else{e.push(`type ${a.name} = (_: {`);let t=He(n,0,_e);t.length>0&&e.push(t),e.push("}) => any;")}e.push("")}return e.push("} // namespace functions"),e.join(`
|
|
@@ -55,7 +55,7 @@ ${" ".repeat(e)}}`;default:return"any"}}function ja(i){let e=["namespace functio
|
|
|
55
55
|
`)?i:{...i,content:`${i.content}
|
|
56
56
|
`}}function Ue(i,e){let{messages:a,functions:n,function_call:r}=i,t=!!(n&&n.length>0),o=!1,s=0;for(let l of a){let u=Na(l,t,o);(u!==l&&l.role==="system"||l.role==="system"&&t&&!o)&&(o=!0),s+=xa(u,e)}return s+=3,t&&n&&(s+=Da(n,e),a.some(l=>l.role==="system")&&(s-=4)),r&&r!=="auto"&&(r==="none"?s+=1:typeof r=="object"&&r.name&&(s+=e(r.name)+4)),s}var Ve=["chat-latest","chatgpt-4o-latest","codex-mini-latest","computer-use-preview","computer-use-preview-2025-03-11","daybreak-blue-latest","daybreak-red-latest","gpt-3.5","gpt-3.5-0301","gpt-3.5-turbo","gpt-3.5-turbo-0125","gpt-3.5-turbo-0613","gpt-3.5-turbo-1106","gpt-3.5-turbo-16k-0613","gpt-3.5-turbo-instruct","gpt-4","gpt-4-0125-preview","gpt-4-0314","gpt-4-0613","gpt-4-1106-preview","gpt-4-1106-vision-preview","gpt-4-32k","gpt-4-turbo","gpt-4-turbo-2024-04-09","gpt-4-turbo-preview","gpt-4.1","gpt-4.1-2025-04-14","gpt-4.1-mini","gpt-4.1-mini-2025-04-14","gpt-4.1-nano","gpt-4.1-nano-2025-04-14","gpt-4.5-preview","gpt-4.5-preview-2025-02-27","gpt-4o","gpt-4o-2024-05-13","gpt-4o-2024-08-06","gpt-4o-2024-11-20","gpt-4o-audio-preview","gpt-4o-audio-preview-2024-10-01","gpt-4o-audio-preview-2024-12-17","gpt-4o-audio-preview-2025-06-03","gpt-4o-mini","gpt-4o-mini-2024-07-18","gpt-4o-mini-audio-preview","gpt-4o-mini-audio-preview-2024-12-17","gpt-4o-mini-search-preview","gpt-4o-mini-search-preview-2025-03-11","gpt-4o-search-preview","gpt-4o-search-preview-2025-03-11","gpt-5","gpt-5-2025-08-07","gpt-5-chat-latest","gpt-5-codex","gpt-5-mini","gpt-5-mini-2025-08-07","gpt-5-nano","gpt-5-nano-2025-08-07","gpt-5-pro","gpt-5-pro-2025-10-06","gpt-5.1","gpt-5.1-2025-11-13","gpt-5.1-chat-latest","gpt-5.1-codex","gpt-5.1-codex-max","gpt-5.1-codex-mini","gpt-5.2","gpt-5.2-2025-12-11","gpt-5.2-chat-latest","gpt-5.2-codex","gpt-5.2-pro","gpt-5.2-pro-2025-12-11","gpt-5.3-chat-latest","gpt-5.3-codex","gpt-5.4","gpt-5.4-2026-03-05","gpt-5.4-mini","gpt-5.4-mini-2026-03-17","gpt-5.4-nano","gpt-5.4-nano-2026-03-17","gpt-5.4-pro","gpt-5.4-pro-2026-03-05","gpt-5.5","gpt-5.5-2026-04-23","gpt-5.5-pro","gpt-5.5-pro-2026-04-23","gpt-5.6-cyber","gpt-5.6-luna","gpt-5.6-sol","gpt-5.6-terra","gpt-audio","gpt-audio-1.5","gpt-audio-2025-08-28","gpt-audio-mini","gpt-audio-mini-2025-10-06","gpt-audio-mini-2025-12-15","gpt-image-1","gpt-oss-120b","gpt-oss-20b","o1","o1-2024-12-17","o1-mini","o1-mini-2024-09-12","o1-preview","o1-preview-2024-09-12","o1-pro","o1-pro-2025-03-19","o3","o3-2025-04-16","o3-deep-research","o3-deep-research-2025-06-26","o3-mini","o3-mini-2025-01-31","o3-pro","o3-pro-2025-06-10","o4-mini","o4-mini-2025-04-16","o4-mini-deep-research","o4-mini-deep-research-2025-06-26"];var We=Object.defineProperty,Ke=(i,e)=>{let a={};for(var n in i)We(a,n,{get:i[n],enumerable:!0});return e||We(a,Symbol.toStringTag,{value:"Module"}),a};var Je=Ke({cl100k_base:()=>Ga,gpt2:()=>La,o200k_base:()=>qa,o200k_harmony:()=>Ha,p50k_base:()=>Oa,p50k_edit:()=>Fa,r50k_base:()=>Ba}),La=["gpt2","gpt-2"],Oa=["text-davinci-002","text-davinci-003","code-davinci-001","code-davinci-002","davinci-codex","code-cushman-001","code-cushman-002","cushman-codex"],Ba=["text-ada-001","text-babbage-001","text-curie-001","text-davinci-001","ada","babbage","curie","davinci","code-search-ada-code-001","code-search-ada-text-001","text-similarity-ada-001","text-search-ada-doc-001","text-search-ada-query-001","text-similarity-babbage-001","text-search-babbage-doc-001","text-search-babbage-query-001","code-search-babbage-code-001","code-search-babbage-text-001","text-similarity-curie-001","text-search-curie-doc-001","text-search-curie-query-001","text-similarity-davinci-001","text-search-davinci-doc-001","text-search-davinci-query-001"],Fa=["code-davinci-edit-001","text-davinci-edit-001"],Ga=["gpt-3.5","gpt-3.5-0301","gpt-3.5-turbo","gpt-3.5-turbo-0125","gpt-3.5-turbo-0613","gpt-3.5-turbo-1106","gpt-3.5-turbo-16k-0613","gpt-3.5-turbo-instruct","gpt-4","gpt-4-0125-preview","gpt-4-0314","gpt-4-0613","gpt-4-1106-preview","gpt-4-1106-vision-preview","gpt-4-32k","gpt-4-turbo","gpt-4-turbo-2024-04-09","gpt-4-turbo-preview","text-embedding-3-large","text-embedding-3-small","text-embedding-ada-002","babbage-002","davinci-002"],qa=[],Ha=["gpt-oss-20b","gpt-oss-120b"];var $e=Object.fromEntries(Object.entries(Je).flatMap(([i,e])=>e.map(a=>[a,i]))),Ua={messageSeparator:`
|
|
57
57
|
`,roleSeparator:`
|
|
58
|
-
`},Va={messageSeparator:"",roleSeparator:j},Ye=Object.fromEntries(Ve.flatMap(i=>i.startsWith("gpt-3.5")?[[i,Ua]]:[[i,Va]]));var U=/'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+/gu,Qe=String.raw`'(?:[sS]|[dD]|[mM]|[tT]|[lL][lL]|[vV][eE]|[rR][eE])`,Xe=String.raw`(?:${Qe})?`,Wa=String.raw`${Qe}|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s+$|\s*[\r\n]|\s+(?!\S)|\s`,Ze=new RegExp(Wa,"gu"),Ka=String.raw`[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]*[\p{Ll}\p{Lm}\p{Lo}\p{M}]+${Xe}|[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]+[\p{Ll}\p{Lm}\p{Lo}\p{M}]*${Xe}|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n/]*|\s*[\r\n]+|\s+(?!\S)|\s+`,se=new RegExp(Ka,"gu");function ea(i){return{tokenSplitRegex:Ze,bytePairRankDecoder:i,specialTokensEncoder:new Map([[R,100257],[I,100258],[M,100259],[x,100260],[B,100264],[F,100265],[j,100266],[D,100276]])}}var Ja=[[R,199999],[I,2e5],[M,200001],[x,200002],[B,200003],[F,200004],[j,200005],[D,200006]],$a=()=>new Map(Ja);function aa(i){return{tokenSplitRegex:se,bytePairRankDecoder:i,specialTokensEncoder:$a()}}var Ya=200013,Xa=201088,Qa=[[ve,199998],[R,199999],["<|reserved_200000|>",2e5],["<|reserved_200001|>",200001],[Z,200002],[ee,200003],["<|reserved_200004|>",200004],[Q,200005],[$,200006],[Y,200007],[X,200008],["<|reserved_200009|>",200009],["<|reserved_200010|>",200010],["<|reserved_200011|>",200011],[ae,200012]];function ia(i){let e=new Map(Qa);for(let a=Ya;a<Xa;a+=1)e.set(`<|reserved_${a}|>`,a);return e.set(D,200018),{tokenSplitRegex:se,bytePairRankDecoder:i,specialTokensEncoder:e,chatFormatter:"harmony"}}function na(i){return{expectedVocabularySize:50281,tokenSplitRegex:U,bytePairRankDecoder:i,specialTokensEncoder:new Map([[R,50256]])}}function ra(i){return{tokenSplitRegex:U,bytePairRankDecoder:i,specialTokensEncoder:new Map([[R,50256],[I,50281],[M,50282],[x,50283]])}}function ta(i){return{expectedVocabularySize:50257,tokenSplitRegex:U,bytePairRankDecoder:i,specialTokensEncoder:new Map([[R,50256]])}}function Ee(i,e){let a=e(i);switch(i.toLowerCase()){case"gpt2":case"r50k_base":return ta(a);case"p50k_base":return na(a);case"p50k_edit":return ra(a);case"cl100k_base":return ea(a);case"o200k_base":return aa(a);case"o200k_harmony":return ia(a);default:throw new Error(`Unknown encoding name: ${i}`)}}var P,sa=(P=class{constructor({bytePairRankDecoder:e,specialTokensEncoder:a,expectedVocabularySize:n,modelName:r,modelSpec:t,chatFormatter:o,...s}){m(this,"modelName");m(this,"modelSpec");m(this,"bytePairEncodingCoreProcessor");m(this,"specialTokensEncoder");m(this,"specialTokensSet");m(this,"allSpecialTokenRegex");m(this,"defaultSpecialTokenConfig");m(this,"chatFormatter");m(this,"countChatCompletionTokens");m(this,"vocabularySize");this.specialTokensEncoder=a,this.specialTokensSet=new Set(this.specialTokensEncoder.keys()),this.allSpecialTokenRegex=Se(this.specialTokensSet),this.bytePairEncodingCoreProcessor=new qe({bytePairRankDecoder:e,specialTokensEncoder:a,...s}),this.defaultSpecialTokenConfig=this.processSpecialTokens();let l=Math.max(e.length-1,Fe(a));if(this.vocabularySize=this.bytePairEncodingCoreProcessor.mergeableBytePairRankCount+a.size,n!==void 0){if(this.vocabularySize!==n)throw new Error("The number of mergeable tokens and special tokens must be equal to expectedVocabularySize.");if(l!==n-1)throw new Error(`The model encodings are invalid. The maximum token value must be equal to expectedVocabularySize - 1. Currently ${l}, expected ${n-1}`)}this.encode=this.encode.bind(this),this.decode=this.decode.bind(this),this.encodeGenerator=this.encodeGenerator.bind(this),this.decodeGenerator=this.decodeGenerator.bind(this),this.decodeAsyncGenerator=this.decodeAsyncGenerator.bind(this),this.decodeAsync=this.decodeAsync.bind(this),this.isWithinTokenLimit=this.isWithinTokenLimit.bind(this),this.encodeChat=this.encodeChat.bind(this),this.encodeChatGenerator=this.encodeChatGenerator.bind(this),this.countTokens=this.countTokens.bind(this),this.setMergeCacheSize=this.setMergeCacheSize.bind(this),this.clearMergeCache=this.clearMergeCache.bind(this),this.estimateCost=this.estimateCost.bind(this),t?.supported_features?.includes("function_calling")&&(this.countChatCompletionTokens=this.countChatCompletionTokensInternal.bind(this)),this.modelName=r,this.modelSpec=t,this.chatFormatter=o??"chatml"}*encodeHarmonyChatGenerator(e,a){let n=this.specialTokensEncoder.get($),r=this.specialTokensEncoder.get(X),t=this.specialTokensEncoder.get(Y),o=this.specialTokensEncoder.get(Z),s=this.specialTokensEncoder.get(ae),l=this.specialTokensEncoder.get(Q),u=this.specialTokensEncoder.get(ee);if(n===void 0||r===void 0||t===void 0||o===void 0||s===void 0||l===void 0||u===void 0)throw new Error("Harmony chat format requires dedicated special tokens.");let d=c=>c.length>0?this.encode(c):[],h=c=>{switch(c){case"<|return|>":return o;case"<|call|>":return s;default:return t}};for(let c of e){if(c.content===void 0)throw new Error("Content must be defined for all messages.");let f=c.name??c.role??"user";yield[n],yield d(f);let g=c.recipient&&(c.recipientPlacement==="role"||!c.channel),w=c.recipient&&!g;g&&(yield d(` to=${c.recipient}`)),c.channel&&(yield[l],yield d(c.channel),w&&(yield d(` to=${c.recipient}`))),c.constraint&&(yield[u],yield d(c.constraint)),yield[r],yield*this.encodeGenerator(c.content,a),yield[h(c.terminator)]}let k=a?.primeWithAssistantResponse??"assistant";k.length>0&&(yield[n],yield d(k))}static getEncodingApi(e,a){let n=Ee(e,a);return new P(n)}static getEncodingApiForModel(e,a,n){let r=$e[e]??"o200k_base",t=Ee(r,a);return new P({...t,modelName:e,modelSpec:n})}processSpecialTokens({allowedSpecial:e,disallowedSpecial:a}={}){let n;if(e==="all"||e?.has("all")){e=new Set(this.specialTokensSet);let r=e;if(a==="all")throw new Error('allowedSpecial and disallowedSpecial cannot both be set to "all".');typeof a=="object"?a.forEach(t=>r.delete(t)):a=new Set}if(!a||a==="all"||a.has("all")){a=new Set(this.specialTokensSet);let r=a;e?.size?(e.forEach(t=>r.delete(t)),a.forEach(t=>e.delete(t)),a.size>0&&(n=Se(a))):n=this.allSpecialTokenRegex}return{allowedSpecial:e,regexPattern:n}}encodeGenerator(e,a){let n=a?this.processSpecialTokens(a):this.defaultSpecialTokenConfig;if(n.regexPattern){let r=e.match(n.regexPattern);if(r!==null)throw new Error(`Disallowed special token found: ${r[0]}`)}return this.bytePairEncodingCoreProcessor.encodeNativeGenerator(e,n.allowedSpecial)}encode(e,a){let n=a?this.processSpecialTokens(a):this.defaultSpecialTokenConfig;if(n.regexPattern){let r=e.match(n.regexPattern);if(r!==null)throw new Error(`Disallowed special token found: ${r[0]}`)}return this.bytePairEncodingCoreProcessor.encodeNative(e,n.allowedSpecial)}*encodeChatGenerator(e,a=this.modelName,n){if(!a)throw new Error("Model name must be provided either during initialization or passed in to the method.");let r=Ye[a];if(!r)throw new Error(`Model '${a}' does not support chat.`);if(this.chatFormatter==="harmony"){yield*this.encodeHarmonyChatGenerator(e,n);return}let t=this.specialTokensEncoder.get(B),o=this.specialTokensEncoder.get(F);if(t===void 0||o===void 0)throw new Error(`Model '${a}' does not support chat.`);let s=new Set([j]),{messageSeparator:l,roleSeparator:u}=r,d=l.length>0?this.encode(l):[],h=u.length>0?this.encode(u,{allowedSpecial:s}):[],k=new Map;for(let{role:f="system",name:g=f,content:w}of e){if(w===void 0)throw new Error("Content must be defined for all messages.");yield[t];let C=k.get(g)??this.encode(g);k.set(g,C),yield C,h.length>0&&(yield h),yield*this.encodeGenerator(w,n),yield[o],yield d}let c=n?.primeWithAssistantResponse??"assistant";c.length>0&&(yield[t],yield*this.encodeGenerator(c,n)),h.length>0&&(yield h)}encodeChat(e,a=this.modelName,n){return[...this.encodeChatGenerator(e,a,n)].flat()}isWithinTokenLimit(e,a,n){let r=typeof e=="string"?this.encodeGenerator(e,n):this.encodeChatGenerator(e,void 0,n),t=0;for(let o of r)if(t+=o.length,t>a)return!1;return t}countTokens(e,a){if(typeof e=="string"){let t=a?this.processSpecialTokens(a):this.defaultSpecialTokenConfig;if(t.regexPattern){let o=e.match(t.regexPattern);if(o!==null)throw new Error(`Disallowed special token found: ${o[0]}`)}return this.bytePairEncodingCoreProcessor.countNative(e,t.allowedSpecial)}let n=this.encodeChatGenerator(e,void 0,a),r=0;for(let t of n)r+=t.length;return r}countStringTokens(e){return e?this.bytePairEncodingCoreProcessor.countNative(e):0}countChatCompletionTokensInternal(e){return Ue(e,a=>this.countStringTokens(a))}setMergeCacheSize(e){this.bytePairEncodingCoreProcessor.setMergeCacheSize(e)}clearMergeCache(){this.bytePairEncodingCoreProcessor.clearMergeCache()}decode(e){return this.bytePairEncodingCoreProcessor.decodeNative(e)}*decodeGenerator(e){let a=this.bytePairEncodingCoreProcessor.decodeNativeGenerator(e),n="";for(let r of a)n+=typeof r=="string"?r:H.decode(r,{stream:!0}),!(n.length===0||ye(n))&&(yield n,n="");n.length>0&&(yield n)}async*decodeAsyncGenerator(e){let a=this.bytePairEncodingCoreProcessor.decodeNativeAsyncIterable(e),n="";for await(let r of a)n+=typeof r=="string"?r:H.decode(r,{stream:!0}),!(n.length===0||ye(n))&&(yield n,n="");n.length>0&&(yield n)}async decodeAsync(e){let a=this.bytePairEncodingCoreProcessor.decodeNativeAsyncIterable(e),n="";for await(let r of a)n+=typeof r=="string"?r:H.decode(r,{stream:!0});return n}estimateCost(e,a=this.modelSpec){if(!a)throw new Error("Model spec must be provided either during initialization or passed in to the method.");if(!a.price_data)throw new Error(`No cost information available for model: ${a.name}`);let n=a.price_data,r={},t=e/1e6;return n.main&&(r.main={input:n.main.input&&n.main.input*t,output:n.main.output&&n.main.output*t,cached_input:n.main.cached_input&&n.main.cached_input*t,cached_output:n.main.cached_output&&n.main.cached_output*t}),n.batch&&(r.batch={input:n.batch.input&&n.batch.input*t,output:n.batch.output&&n.batch.output*t,cached_input:n.batch.cached_input&&n.batch.cached_input*t,cached_output:n.batch.cached_output&&n.batch.cached_output*t}),r}},m(P,"EndOfPrompt",D),m(P,"EndOfText",R),m(P,"FimMiddle",M),m(P,"FimPrefix",I),m(P,"FimSuffix",x),P);var oa=["!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~",[161],[162],[163],[164],[165],[166],[167],[168],[169],[170],[171],[172],[174],[175],[176],[177],[178],[179],[180],[181],[182],[183],[184],[185],[186],[187],[188],[189],[190],[191],[192],[193],[194],[195],[196],[197],[198],[199],[200],[201],[202],[203],[204],[205],[206],[207],[208],[209],[210],[211],[212],[213],[214],[215],[216],[217],[218],[219],[220],[221],[222],[223],[224],[225],[226],[227],[228],[229],[230],[231],[232],[233],[234],[235],[236],[237],[238],[239],[240],[241],[242],[243],[244],[245],[246],[247],[248],[249],[250],[251],[252],[253],[254],[255],"\0","","","","","","","\x07","\b"," ",`
|
|
58
|
+
`},Va={messageSeparator:"",roleSeparator:j},Ye=Object.fromEntries(Ve.flatMap(i=>i.startsWith("gpt-3.5")?[[i,Ua]]:[[i,Va]]));var U=/'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+/gu,Qe=String.raw`'(?:[sS]|[dD]|[mM]|[tT]|[lL][lL]|[vV][eE]|[rR][eE])`,Xe=String.raw`(?:${Qe})?`,Wa=String.raw`${Qe}|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s+$|\s*[\r\n]|\s+(?!\S)|\s`,Ze=new RegExp(Wa,"gu"),Ka=String.raw`[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]*[\p{Ll}\p{Lm}\p{Lo}\p{M}]+${Xe}|[^\r\n\p{L}\p{N}]?[\p{Lu}\p{Lt}\p{Lm}\p{Lo}\p{M}]+[\p{Ll}\p{Lm}\p{Lo}\p{M}]*${Xe}|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n/]*|\s*[\r\n]+|\s+(?!\S)|\s+`,se=new RegExp(Ka,"gu");function ea(i){return{tokenSplitRegex:Ze,bytePairRankDecoder:i,specialTokensEncoder:new Map([[R,100257],[I,100258],[M,100259],[x,100260],[B,100264],[F,100265],[j,100266],[D,100276]])}}var Ja=[[R,199999],[I,2e5],[M,200001],[x,200002],[B,200003],[F,200004],[j,200005],[D,200006]],$a=()=>new Map(Ja);function aa(i){return{tokenSplitRegex:se,bytePairRankDecoder:i,specialTokensEncoder:$a()}}var Ya=200013,Xa=201088,Qa=[[ve,199998],[R,199999],["<|reserved_200000|>",2e5],["<|reserved_200001|>",200001],[ee,200002],[ae,200003],["<|reserved_200004|>",200004],[Z,200005],[Y,200006],[X,200007],[Q,200008],["<|reserved_200009|>",200009],["<|reserved_200010|>",200010],["<|reserved_200011|>",200011],[ie,200012]];function ia(i){let e=new Map(Qa);for(let a=Ya;a<Xa;a+=1)e.set(`<|reserved_${a}|>`,a);return e.set(D,200018),{tokenSplitRegex:se,bytePairRankDecoder:i,specialTokensEncoder:e,chatFormatter:"harmony"}}function na(i){return{expectedVocabularySize:50281,tokenSplitRegex:U,bytePairRankDecoder:i,specialTokensEncoder:new Map([[R,50256]])}}function ra(i){return{tokenSplitRegex:U,bytePairRankDecoder:i,specialTokensEncoder:new Map([[R,50256],[I,50281],[M,50282],[x,50283]])}}function ta(i){return{expectedVocabularySize:50257,tokenSplitRegex:U,bytePairRankDecoder:i,specialTokensEncoder:new Map([[R,50256]])}}function Ee(i,e){let a=e(i);switch(i.toLowerCase()){case"gpt2":case"r50k_base":return ta(a);case"p50k_base":return na(a);case"p50k_edit":return ra(a);case"cl100k_base":return ea(a);case"o200k_base":return aa(a);case"o200k_harmony":return ia(a);default:throw new Error(`Unknown encoding name: ${i}`)}}var P,sa=(P=class{constructor({bytePairRankDecoder:e,specialTokensEncoder:a,expectedVocabularySize:n,modelName:r,modelSpec:t,chatFormatter:o,...s}){m(this,"modelName");m(this,"modelSpec");m(this,"bytePairEncodingCoreProcessor");m(this,"specialTokensEncoder");m(this,"specialTokensSet");m(this,"allSpecialTokenRegex");m(this,"defaultSpecialTokenConfig");m(this,"chatFormatter");m(this,"countChatCompletionTokens");m(this,"vocabularySize");this.specialTokensEncoder=a,this.specialTokensSet=new Set(this.specialTokensEncoder.keys()),this.allSpecialTokenRegex=Se(this.specialTokensSet),this.bytePairEncodingCoreProcessor=new qe({bytePairRankDecoder:e,specialTokensEncoder:a,...s}),this.defaultSpecialTokenConfig=this.processSpecialTokens();let l=Math.max(e.length-1,Fe(a));if(this.vocabularySize=this.bytePairEncodingCoreProcessor.mergeableBytePairRankCount+a.size,n!==void 0){if(this.vocabularySize!==n)throw new Error("The number of mergeable tokens and special tokens must be equal to expectedVocabularySize.");if(l!==n-1)throw new Error(`The model encodings are invalid. The maximum token value must be equal to expectedVocabularySize - 1. Currently ${l}, expected ${n-1}`)}this.encode=this.encode.bind(this),this.decode=this.decode.bind(this),this.encodeGenerator=this.encodeGenerator.bind(this),this.decodeGenerator=this.decodeGenerator.bind(this),this.decodeAsyncGenerator=this.decodeAsyncGenerator.bind(this),this.decodeAsync=this.decodeAsync.bind(this),this.isWithinTokenLimit=this.isWithinTokenLimit.bind(this),this.encodeChat=this.encodeChat.bind(this),this.encodeChatGenerator=this.encodeChatGenerator.bind(this),this.countTokens=this.countTokens.bind(this),this.setMergeCacheSize=this.setMergeCacheSize.bind(this),this.clearMergeCache=this.clearMergeCache.bind(this),this.estimateCost=this.estimateCost.bind(this),t?.supported_features?.includes("function_calling")&&(this.countChatCompletionTokens=this.countChatCompletionTokensInternal.bind(this)),this.modelName=r,this.modelSpec=t,this.chatFormatter=o??"chatml"}*encodeHarmonyChatGenerator(e,a){let n=this.specialTokensEncoder.get(Y),r=this.specialTokensEncoder.get(Q),t=this.specialTokensEncoder.get(X),o=this.specialTokensEncoder.get(ee),s=this.specialTokensEncoder.get(ie),l=this.specialTokensEncoder.get(Z),u=this.specialTokensEncoder.get(ae);if(n===void 0||r===void 0||t===void 0||o===void 0||s===void 0||l===void 0||u===void 0)throw new Error("Harmony chat format requires dedicated special tokens.");let d=c=>c.length>0?this.encode(c):[],h=c=>{switch(c){case"<|return|>":return o;case"<|call|>":return s;default:return t}};for(let c of e){if(c.content===void 0)throw new Error("Content must be defined for all messages.");let f=c.name??c.role??"user";yield[n],yield d(f);let g=c.recipient&&(c.recipientPlacement==="role"||!c.channel),w=c.recipient&&!g;g&&(yield d(` to=${c.recipient}`)),c.channel&&(yield[l],yield d(c.channel),w&&(yield d(` to=${c.recipient}`))),c.constraint&&(yield[u],yield d(c.constraint)),yield[r],yield*this.encodeGenerator(c.content,a),yield[h(c.terminator)]}let k=a?.primeWithAssistantResponse??"assistant";k.length>0&&(yield[n],yield d(k))}static getEncodingApi(e,a){let n=Ee(e,a);return new P(n)}static getEncodingApiForModel(e,a,n){let r=$e[e]??"o200k_base",t=Ee(r,a);return new P({...t,modelName:e,modelSpec:n})}processSpecialTokens({allowedSpecial:e,disallowedSpecial:a}={}){let n;if(e==="all"||e?.has("all")){e=new Set(this.specialTokensSet);let r=e;if(a==="all")throw new Error('allowedSpecial and disallowedSpecial cannot both be set to "all".');typeof a=="object"?a.forEach(t=>r.delete(t)):a=new Set}if(!a||a==="all"||a.has("all")){a=new Set(this.specialTokensSet);let r=a;e?.size?(e.forEach(t=>r.delete(t)),a.forEach(t=>e.delete(t)),a.size>0&&(n=Se(a))):n=this.allSpecialTokenRegex}return{allowedSpecial:e,regexPattern:n}}encodeGenerator(e,a){let n=a?this.processSpecialTokens(a):this.defaultSpecialTokenConfig;if(n.regexPattern){let r=e.match(n.regexPattern);if(r!==null)throw new Error(`Disallowed special token found: ${r[0]}`)}return this.bytePairEncodingCoreProcessor.encodeNativeGenerator(e,n.allowedSpecial)}encode(e,a){let n=a?this.processSpecialTokens(a):this.defaultSpecialTokenConfig;if(n.regexPattern){let r=e.match(n.regexPattern);if(r!==null)throw new Error(`Disallowed special token found: ${r[0]}`)}return this.bytePairEncodingCoreProcessor.encodeNative(e,n.allowedSpecial)}*encodeChatGenerator(e,a=this.modelName,n){if(!a)throw new Error("Model name must be provided either during initialization or passed in to the method.");let r=Ye[a];if(!r)throw new Error(`Model '${a}' does not support chat.`);if(this.chatFormatter==="harmony"){yield*this.encodeHarmonyChatGenerator(e,n);return}let t=this.specialTokensEncoder.get(B),o=this.specialTokensEncoder.get(F);if(t===void 0||o===void 0)throw new Error(`Model '${a}' does not support chat.`);let s=new Set([j]),{messageSeparator:l,roleSeparator:u}=r,d=l.length>0?this.encode(l):[],h=u.length>0?this.encode(u,{allowedSpecial:s}):[],k=new Map;for(let{role:f="system",name:g=f,content:w}of e){if(w===void 0)throw new Error("Content must be defined for all messages.");yield[t];let C=k.get(g)??this.encode(g);k.set(g,C),yield C,h.length>0&&(yield h),yield*this.encodeGenerator(w,n),yield[o],yield d}let c=n?.primeWithAssistantResponse??"assistant";c.length>0&&(yield[t],yield*this.encodeGenerator(c,n)),h.length>0&&(yield h)}encodeChat(e,a=this.modelName,n){return[...this.encodeChatGenerator(e,a,n)].flat()}isWithinTokenLimit(e,a,n){let r=typeof e=="string"?this.encodeGenerator(e,n):this.encodeChatGenerator(e,void 0,n),t=0;for(let o of r)if(t+=o.length,t>a)return!1;return t}countTokens(e,a){if(typeof e=="string"){let t=a?this.processSpecialTokens(a):this.defaultSpecialTokenConfig;if(t.regexPattern){let o=e.match(t.regexPattern);if(o!==null)throw new Error(`Disallowed special token found: ${o[0]}`)}return this.bytePairEncodingCoreProcessor.countNative(e,t.allowedSpecial)}let n=this.encodeChatGenerator(e,void 0,a),r=0;for(let t of n)r+=t.length;return r}countStringTokens(e){return e?this.bytePairEncodingCoreProcessor.countNative(e):0}countChatCompletionTokensInternal(e){return Ue(e,a=>this.countStringTokens(a))}setMergeCacheSize(e){this.bytePairEncodingCoreProcessor.setMergeCacheSize(e)}clearMergeCache(){this.bytePairEncodingCoreProcessor.clearMergeCache()}decode(e){return this.bytePairEncodingCoreProcessor.decodeNative(e)}*decodeGenerator(e){let a=this.bytePairEncodingCoreProcessor.decodeNativeGenerator(e),n="";for(let r of a)n+=typeof r=="string"?r:H.decode(r,{stream:!0}),!(n.length===0||ye(n))&&(yield n,n="");n.length>0&&(yield n)}async*decodeAsyncGenerator(e){let a=this.bytePairEncodingCoreProcessor.decodeNativeAsyncIterable(e),n="";for await(let r of a)n+=typeof r=="string"?r:H.decode(r,{stream:!0}),!(n.length===0||ye(n))&&(yield n,n="");n.length>0&&(yield n)}async decodeAsync(e){let a=this.bytePairEncodingCoreProcessor.decodeNativeAsyncIterable(e),n="";for await(let r of a)n+=typeof r=="string"?r:H.decode(r,{stream:!0});return n}estimateCost(e,a=this.modelSpec){if(!a)throw new Error("Model spec must be provided either during initialization or passed in to the method.");if(!a.price_data)throw new Error(`No cost information available for model: ${a.name}`);let n=a.price_data,r={},t=e/1e6;return n.main&&(r.main={input:n.main.input&&n.main.input*t,output:n.main.output&&n.main.output*t,cached_input:n.main.cached_input&&n.main.cached_input*t,cached_output:n.main.cached_output&&n.main.cached_output*t}),n.batch&&(r.batch={input:n.batch.input&&n.batch.input*t,output:n.batch.output&&n.batch.output*t,cached_input:n.batch.cached_input&&n.batch.cached_input*t,cached_output:n.batch.cached_output&&n.batch.cached_output*t}),r}},m(P,"EndOfPrompt",D),m(P,"EndOfText",R),m(P,"FimMiddle",M),m(P,"FimPrefix",I),m(P,"FimSuffix",x),P);var oa=["!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~",[161],[162],[163],[164],[165],[166],[167],[168],[169],[170],[171],[172],[174],[175],[176],[177],[178],[179],[180],[181],[182],[183],[184],[185],[186],[187],[188],[189],[190],[191],[192],[193],[194],[195],[196],[197],[198],[199],[200],[201],[202],[203],[204],[205],[206],[207],[208],[209],[210],[211],[212],[213],[214],[215],[216],[217],[218],[219],[220],[221],[222],[223],[224],[225],[226],[227],[228],[229],[230],[231],[232],[233],[234],[235],[236],[237],[238],[239],[240],[241],[242],[243],[244],[245],[246],[247],[248],[249],[250],[251],[252],[253],[254],[255],"\0","","","","","","","\x07","\b"," ",`
|
|
59
59
|
`,"\v","\f","\r","","","","","","","","","","","","","","\x1B","","","",""," ","\x7F",[128],[129],[130],[131],[132],[133],[134],[135],[136],[137],[138],[139],[140],[141],[142],[143],[144],[145],[146],[147],[148],[149],[150],[151],[152],[153],[154],[155],[156],[157],[158],[159],[160],[173]," "," ","in","er"," t"," a","en","on","re"," s","at","or","es"," ","an"," "," d","he"," c"," p","is","ar","it",`
|
|
60
60
|
|
|
61
61
|
`,"al",[224,164],"le","ou"," m"," f"," w"," b","as","ing"," the","ic","et"," o","ion","ed","el"," n","ro","ent",[32,208],"nd","st",[225,131],"\u0430"," l"," in",`;
|
|
@@ -3333,4 +3333,4 @@ ${" ".repeat(e)}}`;default:return"any"}}function ja(i){let e=["namespace functio
|
|
|
3333
3333
|
`),O=g[y].trim().endsWith(",")?",":"",ke=s(O?A.replace(/,\s*$/,""):A,`lines ${S+1}-${y+1}`);if(ke!==A&&ke!==A.replace(/,\s*$/,"")){w.push(T[1]+ke+O),S=y;continue}}}w.push(g[S])}let C=w.join(`
|
|
3334
3334
|
`),E=C.replace(/[ \t]+$/gm,"").replace(/\n{3,}/g,`
|
|
3335
3335
|
|
|
3336
|
-
`);return E!==C&&(h=!0),C=E,C});return n.length&&r.push(`removed indentation and line breaks from ${n.length} JSON block${n.length>1?"s":""} (same data)`),h&&r.push("removed trailing spaces and extra blank lines outside code"),o(k.join(""),n.length||h?void 0:"Nothing to compact: no pretty-printed JSON or extra whitespace found.")}var v=i=>i,G={"gpt-astra":v({id:"gpt-astra",label:"GPT-6 Astra",family:"openai",contextWindow:105e4,tokenizer:"heuristic",charsPerToken:4.2,reasoning:!0,pricing:{inputPerMTok:10,outputPerMTok:50}}),"gpt-reasoning":v({id:"gpt-reasoning",label:"GPT (thinking)",family:"openai",contextWindow:196e3,tokenizer:"o200k",charsPerToken:4.2,reasoning:!0,lighterAlternative:"the Instant / non-thinking model",pricing:{inputPerMTok:5,outputPerMTok:30,cachedInputPerMTok:.5}}),gpt:v({id:"gpt",label:"GPT",family:"openai",contextWindow:128e3,tokenizer:"o200k",charsPerToken:4.2,reasoning:!1,pricing:{inputPerMTok:2.5,outputPerMTok:15,cachedInputPerMTok:.25}}),"claude-fable":v({id:"claude-fable",label:"Claude Fable",family:"anthropic",contextWindow:1e6,tokenizer:"heuristic",charsPerToken:3.5,reasoning:!0,notes:["Claude reads XML-style tags well: wrap pasted material in <doc>\u2026</doc> instead of explaining it."],pricing:{inputPerMTok:10,outputPerMTok:50,cachedInputPerMTok:.25}}),"claude-opus":v({id:"claude-opus",label:"Claude Opus",family:"anthropic",contextWindow:2e5,tokenizer:"heuristic",charsPerToken:3.5,reasoning:!1,lighterAlternative:"Sonnet or Haiku",notes:["Claude reads XML-style tags well: wrap pasted material in <doc>\u2026</doc> instead of explaining it."],pricing:{inputPerMTok:4,outputPerMTok:20,cachedInputPerMTok:.2}}),"claude-sonnet":v({id:"claude-sonnet",label:"Claude Sonnet",family:"anthropic",contextWindow:2e5,tokenizer:"heuristic",charsPerToken:3.5,reasoning:!1,lighterAlternative:"Haiku",notes:["Claude reads XML-style tags well: wrap pasted material in <doc>\u2026</doc> instead of explaining it."],pricing:{inputPerMTok:2,outputPerMTok:10,cachedInputPerMTok:.2}}),"claude-haiku":v({id:"claude-haiku",label:"Claude Haiku",family:"anthropic",contextWindow:2e5,tokenizer:"heuristic",charsPerToken:3.5,reasoning:!1,pricing:{inputPerMTok:.1,outputPerMTok:.5,cachedInputPerMTok:.01}}),"gemini-pro":v({id:"gemini-pro",label:"Gemini Pro",family:"google",contextWindow:1e6,tokenizer:"heuristic",charsPerToken:4,reasoning:!0,lighterAlternative:"Flash",pricing:{inputPerMTok:2,outputPerMTok:12,cachedInputPerMTok:.2,longContext:{aboveTokens:2e5,inputPerMTok:4,outputPerMTok:18}}}),"gemini-flash":v({id:"gemini-flash",label:"Gemini Flash",family:"google",contextWindow:1e6,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:1.5,outputPerMTok:9,cachedInputPerMTok:.15}}),deepseek:v({id:"deepseek",label:"DeepSeek",family:"deepseek",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:.28,outputPerMTok:.42,cachedInputPerMTok:.028}}),"deepseek-reasoning":v({id:"deepseek-reasoning",label:"DeepSeek (thinking)",family:"deepseek",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!0,lighterAlternative:"the non-thinking mode",pricing:{inputPerMTok:.55,outputPerMTok:2.19,cachedInputPerMTok:.14}}),mistral:v({id:"mistral",label:"Mistral",family:"mistral",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:2,outputPerMTok:6}}),grok:v({id:"grok",label:"Grok",family:"xai",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:2,outputPerMTok:6}}),llama:v({id:"llama",label:"Llama",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.9,reasoning:!1,pricing:{inputPerMTok:.27,outputPerMTok:.85}}),qwen:v({id:"qwen",label:"Qwen",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:.4,outputPerMTok:1.2}}),kimi:v({id:"kimi",label:"Kimi",family:"other",contextWindow:256e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:.6,outputPerMTok:2.5,cachedInputPerMTok:.15}}),glm:v({id:"glm",label:"GLM",family:"other",contextWindow:2e5,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:.6,outputPerMTok:2.2,cachedInputPerMTok:.11}}),command:v({id:"command",label:"Cohere Command",family:"other",contextWindow:256e3,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:2.5,outputPerMTok:10}}),sonar:v({id:"sonar",label:"Perplexity Sonar",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:1,outputPerMTok:1}}),gemma:v({id:"gemma",label:"Gemma",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.9,reasoning:!1,pricing:{inputPerMTok:.1,outputPerMTok:.2}}),phi:v({id:"phi",label:"Phi",family:"other",contextWindow:16e3,tokenizer:"heuristic",charsPerToken:3.9,reasoning:!1,pricing:{inputPerMTok:.07,outputPerMTok:.14}}),generic:v({id:"generic",label:"Unknown model",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:2,outputPerMTok:10}})},_i=[[/\b(fable|mythos)\b/,"claude-fable"],[/\bastra\b|\bgpt[- ]?6\b/,"gpt-astra"],[/\bclaude\b.*\bopus\b|\bopus\b/,"claude-opus"],[/\bsonnet\b/,"claude-sonnet"],[/\bhaiku\b/,"claude-haiku"],[/\b(qwen|qwq)/,"qwen"],[/\b(glm|chatglm|zhipu)\b|\bglm-?\d/,"glm"],[/\b(kimi|moonshot)/,"kimi"],[/\bgemma/,"gemma"],[/\bgemini\b.*\bflash\b|\bflash\b/,"gemini-flash"],[/\bgemini\b.*\b(pro|ultra|deep think)\b|^\s*\d(\.\d)?\s*pro\b|\bdeep think\b/,"gemini-pro"],[/\bdeepseek\b.*\b(r1|reason|think|deepthink)|\bdeepthink\b/,"deepseek-reasoning"],[/\bdeepseek\b/,"deepseek"],[/\b(mistral|le chat|magistral|codestral)\b/,"mistral"],[/\bgrok\b/,"grok"],[/\bllama|codellama/,"llama"],[/\bcommand[- ]?(r|a)\b|\bcohere\b/,"command"],[/\bsonar\b|\bperplexity\b/,"sonar"],[/\bphi-?\d/,"phi"],[/\bo[1-9](-mini|-pro)?\b|\bgpt[- ]?\S*\s*(thinking|pro)\b|\bthinking\b/,"gpt-reasoning"],[/\b(gpt|chatgpt)\b|\bgpt-?\d/,"gpt"],[/\bgemini\b/,"gemini-pro"],[/\bclaude\b/,"claude-sonnet"]];var Ei={chatgpt:"gpt",claude:"claude-sonnet",gemini:"gemini-flash",deepseek:"deepseek",mistral:"mistral",grok:"grok",generic:"generic"},Ai=[];var zr={...G};function ie(i,e="generic"){let a=(i??"").toLowerCase().replace(/\s+/g," ").trim();if(a){for(let[n,r]of Ai)if(n.test(a))return G[r];if(e==="gemini"&&/\b(pro|deep think)\b/.test(a))return G["gemini-pro"];if(e==="gemini"&&/\bflash\b/.test(a))return G["gemini-flash"];if(e==="deepseek"&&/\b(deepthink|r1|think)/.test(a))return G["deepseek-reasoning"];for(let[n,r]of _i)if(n.test(a))return G[r]}return G[Ei[e]??"generic"]}var va="ai-toolbox.co ChatGPT limits guide",ne={"chatgpt-free":{id:"chatgpt-free",site:"chatgpt",label:"ChatGPT Free",meter:"messages",caps:[]},"chatgpt-go":{id:"chatgpt-go",site:"chatgpt",label:"ChatGPT Go",meter:"messages",caps:[]},"chatgpt-plus":{id:"chatgpt-plus",site:"chatgpt",label:"ChatGPT Plus",meter:"messages",caps:[{models:["gpt"],messages:160,window:"3h",source:va,asOf:"2026-10"},{models:["gpt-reasoning"],messages:3e3,window:"week",source:va,asOf:"2026-10"}]},"chatgpt-pro":{id:"chatgpt-pro",site:"chatgpt",label:"ChatGPT Pro",meter:"messages",caps:[],note:"Pro is close to unlimited for everyday models, but GPT-6 Astra Pro use is capped (number not published)."},"chatgpt-business":{id:"chatgpt-business",site:"chatgpt",label:"ChatGPT Business",meter:"messages",caps:[]},"claude-free":{id:"claude-free",site:"claude",label:"Claude Free",meter:"compute",caps:[]},"claude-pro":{id:"claude-pro",site:"claude",label:"Claude Pro",meter:"compute",caps:[],note:"5-hour session and weekly limits shared across models; Fable runs on usage credits."},"claude-max":{id:"claude-max",site:"claude",label:"Claude Max",meter:"compute",caps:[],note:"5x or 20x Pro's session usage, with a weekly limit across models and one for the top models."},"claude-team":{id:"claude-team",site:"claude",label:"Claude Team",meter:"compute",caps:[]},"gemini-free":{id:"gemini-free",site:"gemini",label:"Gemini (free)",meter:"messages",caps:[]},"gemini-pro":{id:"gemini-pro",site:"gemini",label:"Google AI Pro",meter:"messages",caps:[]},"gemini-ultra":{id:"gemini-ultra",site:"gemini",label:"Google AI Ultra",meter:"messages",caps:[]}};var pe=5*36e5,Ie=7*864e5,Ci=1e3,Ti=500,re=i=>Math.round(i).toLocaleString("en-US");function ge(i){let e=2166136261;for(let a=0;a<i.length;a++)e=Math.imul(e^i.charCodeAt(a),16777619)>>>0;return e.toString(36)}function ya(i){let e=/\b(Free|Pro|Max|Team|Enterprise)\s+plan\b/.exec(i);if(!e)return null;let a=e[1].toLowerCase();return ne[`claude-${a==="enterprise"?"team":a}`]??null}var Ri=["sun","mon","tue","wed","thu","fri","sat"];function Pi(i,e){let a=/\b(sun|mon|tue|wed|thu|fri|sat)\w*\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)?/i.exec(i);if(!a)return;let n=new Date(e),r=Number(a[2])%12;a[4]?.toLowerCase()==="pm"&&(r+=12),!a[4]&&Number(a[2])>=12&&(r=Number(a[2]));let t=(Ri.indexOf(a[1].slice(0,3).toLowerCase())-n.getDay()+7)%7,o=new Date(n.getFullYear(),n.getMonth(),n.getDate()+t,r,Number(a[3]??0)).getTime();return o<=e?o+Ie:o}function zi(i){let e=/resets?\s+in\s+(?:(\d+)\s*(?:hr|hour|h)s?)?\s*(?:(\d+)\s*(?:min|minute|m)s?)?/i.exec(i);if(!(!e||!e[1]&&!e[2]))return(Number(e[1]??0)*60+Number(e[2]??0))*6e4}function wa(i,e){let a=i.replace(/\s+/g," "),n=/current session(.{0,160}?)(\d{1,3})\s*%\s*used/i.exec(a),r=/weekly (?:limits?|usage)(.{0,260}?)(\d{1,3})\s*%\s*used/i.exec(a),t=!n&&/(\d{1,3})\s*%\s+of\s+your\s+(session|5-hour|weekly)\s+(?:usage\s+)?limit/i.exec(a);if(!n&&!r&&!t)return null;let o={at:e};if(n){o.sessionPct=Math.min(100,Number(n[2]));let s=zi(n[1]);s!==void 0&&(o.sessionResetsAt=e+s)}if(r){o.weekPct=Math.min(100,Number(r[2]));let s=/resets?\s+((?:sun|mon|tue|wed|thu|fri|sat)\w*\s+\d{1,2}(?::\d{2})?\s*(?:am|pm)?)/i.exec(r[1]);s&&(o.weekResetsText=s[1].trim(),o.weekResetsAt=Pi(s[1],e))}return t&&(/weekly/i.test(t[2])?o.weekPct=Math.min(100,Number(t[1])):o.sessionPct=Math.min(100,Number(t[1]))),o}var ze=i=>new Date(i).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});function xe(i,e){return{...i,sends:i.sends.filter(a=>e-a.at<Ie).slice(-5e3),readings:i.readings.filter(a=>e-a.at<Ie).slice(-50)}}function Sa(i,e){let a=[...i.readings].reverse().find(t=>t.sessionPct!==void 0),n=i.pctPer1k;if(a&&e.sessionPct!==void 0&&a.sessionPct!==void 0&&e.sessionPct>a.sessionPct&&e.at-a.at<pe){let t=i.sends.filter(o=>o.at>a.at&&o.at<=e.at).reduce((o,s)=>o+s.tokens,0);if(t>=5e3){let o=(e.sessionPct-a.sessionPct)/t*1e3;n=n===void 0?o:n*.5+o*.5}}let r=a&&a.sessionPct===e.sessionPct&&a.weekPct===e.weekPct&&e.at-a.at<10*6e4;return{...i,pctPer1k:n,readings:r?i.readings:[...i.readings,e]}}function _a(i){let{data:e,now:a,plan:n,current:r}=i,t=[...e.readings].reverse().find(p=>p.sessionPct!==void 0||p.weekPct!==void 0),o=[...e.readings].reverse().find(p=>p.weekPct!==void 0),s=[...e.readings].reverse().find(p=>p.sessionPct!==void 0),l=s&&(s.sessionResetsAt??s.at+pe)>a,u=l&&s.sessionResetsAt?s.sessionResetsAt-pe:a-pe,d=e.sends.filter(p=>p.at>=u),h=p=>p.reduce((y,A)=>y+A.tokens,0),k=h(d),c={plan:n,planSource:i.planSource,session:{messages:d.length,tokens:k,since:u},week:{messages:e.sends.length,tokens:h(e.sends)},topChats:[],insights:[]};if(l&&s?.sessionPct!==void 0){let p=h(e.sends.filter(A=>A.at>s.at)),y=s.sessionPct+(e.pctPer1k?p/1e3*e.pctPer1k:0);c.sessionPct=Math.min(100,Math.round(y)),c.sessionResetsAt=s.sessionResetsAt,c.meterAgeMin=Math.round((a-s.at)/6e4)}o?.weekPct!==void 0&&(o.weekResetsAt??1/0)>a&&(c.weekPct=o.weekPct,c.weekResetsAt=o.weekResetsAt,c.weekResetsText=o.weekResetsText);let f=new Map;for(let p of d){let y=f.get(p.chat)??{chat:p.chat,title:i.titles?.get(p.chat),tokens:0,messages:0,share:0};y.tokens+=p.tokens,y.messages++,f.set(p.chat,y)}c.topChats=[...f.values()].map(p=>({...p,share:k?p.tokens/k:0})).sort((p,y)=>y.tokens-p.tokens).slice(0,5);let g=Ti,w=(r?.tokens??0)+g,C=Ci+g;if(c.sessionPct!==void 0&&e.pctPer1k){let p=Math.max(0,100-c.sessionPct)/e.pctPer1k*1e3;c.left={here:Math.floor(p/w),fresh:Math.floor(p/C)}}let E=c.insights,S=n?n.label:"your plan";if(c.sessionPct!==void 0){let p=c.sessionResetsAt?`; it resets at ${ze(c.sessionResetsAt)}`:"";c.left&&r&&r.tokens>=1e4&&c.left.fresh>=c.left.here*2?E.push(`About ${re(c.left.here)} more messages fit in ${S}'s session at this chat's size, or about ${re(c.left.fresh)} in a new chat (${c.sessionPct}% used${p}). For a new topic, start a new chat. ${z}`):c.left?E.push(`About ${re(c.left.fresh)} more messages like your recent ones fit in this session (${c.sessionPct}% used${p}).`):E.push(`Session ${c.sessionPct}% used${p}.`);let y=s&&e.readings.find(A=>A.sessionPct!==void 0&&A.at>=u);if(y&&s&&y!==s&&c.sessionResetsAt&&c.sessionPct<100){let A=(c.sessionPct-(y.sessionPct??0))/Math.max(1,a-y.at),O=A>0?a+(100-c.sessionPct)/A:1/0;O<c.sessionResetsAt&&E.push(`At this pace the session runs out around ${ze(O)}, before it resets at ${ze(c.sessionResetsAt)}. Save the big asks for after the reset, or start new topics in new chats.`)}}let T=c.topChats[0];return T&&d.length>=4&&T.share>=.5&&f.size>1&&E.push(`${Math.round(T.share*100)}% of this session's usage came from one chat${T.title?` ("${T.title}")`:""}: each message there re-read about ${re(T.tokens/T.messages)} tokens.`),c.weekPct!==void 0&&c.weekResetsAt&&((c.weekResetsAt-a)/36e5<=36&&c.weekPct<=50?E.push(`${100-c.weekPct}% of ${S}'s weekly allowance is unused and resets ${c.weekResetsText??"soon"}. It doesn't carry over, so this is a good time for the big jobs you've been holding back.`):c.weekPct>=80&&E.push(`Week ${c.weekPct}% used${c.weekResetsText?`, resets ${c.weekResetsText}`:""}. New topics in new chats and one complete message per ask stretch what's left.`)),r&&r.tokens>=2e4&&!E.some(p=>p.includes("new chat"))&&E.push(`Every message in this chat re-reads about ${re(r.tokens)} tokens, ${Math.max(2,Math.round(w/C))}\xD7 a new chat. On ${S} that's what uses your allowance fastest.`),n?c.sessionPct===void 0&&n.site==="claude"&&E.push("Open Settings > Usage in Claude once and Token Lens reads your meter from it, to count how many messages you have left."):E.push("Tell Token Lens your plan once (Free, Pro, Max or Team) for advice that fits it."),c}var Ii=/^(?:ok(?:ay)?|k|thanks?(?: you)?(?: so much)?|thx|ty|great|perfect|nice|cool|awesome|got it|understood|sounds good|lgtm|yes|yep|sure|done|👍|🙏)[\s!.,🙂😊👍🙏]*$/i;function Ea(i){return Ii.test(i.trim())}var Me=i=>i.toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").trim();function Aa(i,e){let a=Me(i);return a.split(" ").length<8?!1:Me(e).includes(a)}function Ca(i){return i.split(/\n\s*\n/).map(e=>e.trim()).filter(e=>e.length>=1200).map(e=>ge(Me(e)))}function he(i){let e=typeof i.model=="string"?ie(i.model,i.site):i.model,a=i.pricing?{...e,pricing:i.pricing}:e,n=le(i.prompt),{tokens:r,exact:t}=_(i.prompt,a),o=J(i.conversationTokens??0,r,a,i.contextWindow),s=De(i.level??"auto",o),l=V(i.prompt,{profile:a,task:n.task,level:s}),u=fa(l.text,a),d=u.saved>0&&u.blocks.length?{...l,text:u.text,tokens:u.after,saved:l.originalTokens-u.after,rules:[...l.rules,"JSON whitespace (same data)"]}:l,h=fe({profile:a,task:n.task,signals:n.signals,promptTokens:r,usage:o,text:i.prompt}),k={pricing:a.pricing,promptUsd:N(r,a),sendUsd:N((i.conversationTokens??0)+r,a),saved:W(d.saved,a)},c=Object.entries(Re(i.prompt,d.text)).map(([g,[w,C]])=>`${C}/${w} ${g}s`).join(", "),f={text:d.text,tokens:d.tokens,changes:d.saved>0?d.rules.map(g=>`removed ${g}`):[],kept:c||"every instruction"};return{profile:a,task:n,promptTokens:r,exact:t,usage:o,level:s,optimized:d,tips:h,handoffPrompt:Ne(n.task),cost:k,best:f}}var ji=60,Di=20,Ni=12,Li=1800,Oi=25e3,Bi=15e3,Fi=80,Gi=3*6e4,K=i=>Math.round(i).toLocaleString("en-US"),Ta=i=>i.toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").trim(),be=class{constructor(e="claude-sonnet",a={}){m(this,"profile");m(this,"draftText","");m(this,"draftSince",0);m(this,"draftDone","");m(this,"lastDraftNotice",-1/0);m(this,"chatTold",new Map);m(this,"chatTokens",new Map);m(this,"chatEpoch",new Map);m(this,"chatText","");m(this,"chatId","");m(this,"chatTitle","");m(this,"titles",new Map);m(this,"pending",null);m(this,"pastes",new Map);m(this,"told",new Set);m(this,"data");m(this,"pickedPlan");m(this,"appPlan",null);m(this,"onData");m(this,"state");this.profile=ie(e),this.data=xe(a.data??{sends:[],readings:[]},Date.now()),this.pickedPlan=a.plan&&ne[a.plan]||null,this.onData=a.onData,this.state={model:this.profile.label,draft:null,chat:null,coach:null},this.refreshCoach(Date.now())}get currentDraft(){return this.draftText}get plan(){return this.pickedPlan??this.appPlan}setPlan(e,a=Date.now()){return this.pickedPlan=e&&ne[e]||null,this.refreshCoach(a),this.plan}draft(e,a){let n=(e??"").trim();if(n!==this.draftText)return e===""&&this.draftText.length>2&&this.chatId?this.pending={probe:Ta(this.draftText).slice(0,80),tokens:this.state.chat?.tokens??0,chat:this.chatId,at:a,text:this.draftText}:this.pending&&n===this.pending.text&&(this.pending=null),this.draftText=n,this.draftSince=a,this.state.draft=n?this.analyzeDraft(n):null,null;let r=this.state.draft;if(!r||a-this.draftSince<Li)return null;let t=ge(n);if(t===this.draftDone||a-this.lastDraftNotice<Oi)return null;let o=this.draftNotice(n,r);return o?(this.draftDone=t,this.lastDraftNotice=a,o):null}draftNotice(e,a){let n=this.state.chat?.tokens??0,r=this.plan?.label??"your plan";if(Aa(e,this.chatText))return{title:"You already asked this in this chat",body:`Its answer is above. Sending it again re-reads about ${K(n+a.tokens)} tokens of ${r}'s usage for the same question.`};if(Ea(e)&&n>=Bi)return{title:`"${e.slice(0,24)}" re-reads this whole chat`,body:`Sending it uses about ${K(n)} tokens of ${r}'s usage, as much as a long question. If there's nothing to ask, you can skip it, or add it to your next real message.`};let t=Ca(e);for(let s of t){let l=this.pastes.get(s)??new Set;if(l.add(this.chatId),this.pastes.set(s,l),l.size>=2&&!this.told.has(`paste:${s}`))return this.told.add(`paste:${s}`),{title:`You've pasted this text into ${l.size} chats`,body:"Put it in a Claude Project's knowledge or instructions once, and every chat in that Project has it without pasting it again."}}return a.tokens>=ji&&a.saved>=Di&&a.pct>=Ni?{title:`Draft: ${K(a.tokens)} \u2192 ${K(a.optimizedTokens)} tokens (${a.pct}% fewer)`,body:`Same request, ${a.savedUsd===null?"fewer tokens":`${Pe(a.savedUsd)} less per send at API prices`}. Token Lens can put the shorter version in the message box when you click.${a.tips[0]?` ${a.tips[0]}`:""}`}:a.tips.length?{title:"Token Lens tip for your draft",body:a.tips[0]}:null}chat(e,a,n=Date.now()){let{tokens:r}=_(a,this.profile),t=J(r,0,this.profile),o=N(r,this.profile),s=[],l=null;t.zone==="hot"||t.zone==="full"?(l=t.zone,s.push(`This chat fills about ${Math.round(t.ratio*100)}% of the context, so older messages will soon be dropped or compacted. ${z}`)):(t.zone==="warm"||t.longChat)&&(l=t.zone==="warm"?"warm":"long",s.push(`Every message you send re-reads about ${K(r)} tokens of this chat (${Pe(o)} each at API prices). Starting a new chat for a new topic avoids that.`)),this.state.chat={tokens:r,ratio:t.ratio,window:t.window,perMessageUsd:o,tips:s},r<(this.chatTokens.get(e)??0)*.5&&(this.chatTold.delete(e),this.chatEpoch.set(e,(this.chatEpoch.get(e)??0)+1)),this.chatTokens.set(e,r),this.chatText=a,this.chatId=ge(`${e}#${this.chatEpoch.get(e)??0}`),this.chatTitle=e&&!/^claude$/i.test(e)?e.slice(0,60):"",this.chatTitle&&this.titles.set(this.chatId,this.chatTitle);let u=this.observe(a,n),d=null;if(l){let h=this.chatTold.get(e)??new Set;this.chatTold.set(e,h),h.has(l)||(h.add(l),d={title:`This chat: ${K(r)} tokens (${Math.round(t.ratio*100)}% of context)`,body:s[0]})}return u??d}observe(e,a){let n=!1,r=ya(e);r&&(this.appPlan=r);let t=wa(e,a);t&&(this.data=Sa(this.data,t),n=!0);let o=this.pending;o&&a-o.at>Gi?this.pending=null:o&&o.probe&&Ta(e).includes(o.probe)&&(this.data.sends.push({at:o.at,tokens:o.tokens+_(o.text,this.profile).tokens,chat:o.chat}),this.pending=null,n=!0),n&&(this.data=xe(this.data,a),this.onData?.(this.data));let s=this.refreshCoach(a);if(s.sessionPct!==void 0&&s.sessionPct>=Fi){let u=`session:${Math.round(s.session.since/36e5)}`;if(!this.told.has(u))return this.told.add(u),{title:`${this.plan?.label??"Claude"} session ${s.sessionPct}% used`,body:s.insights[0]??"New topics in new chats stretch what's left."}}let l=s.insights.find(u=>u.includes("weekly allowance is unused"));if(l&&s.weekResetsAt){let u=`week:${Math.round(s.weekResetsAt/864e5)}`;if(!this.told.has(u))return this.told.add(u),{title:`${100-(s.weekPct??0)}% of your week is still unused`,body:l}}return null}refreshCoach(e=Date.now()){let a=_a({data:this.data,now:e,plan:this.plan,planSource:this.pickedPlan?"set":this.appPlan?"app":"unknown",current:this.chatId?{chat:this.chatId,title:this.chatTitle,tokens:this.state.chat?.tokens??0}:void 0,titles:this.titles});return this.state.coach=a,a}analyzeDraft(e){let a=he({prompt:e,model:this.profile,conversationTokens:this.state.chat?.tokens??0,level:"auto"}),n=a.optimized.saved;return{tokens:a.promptTokens,optimizedTokens:a.optimized.tokens,saved:n,pct:a.optimized.originalTokens?Math.round(n/a.optimized.originalTokens*100):0,savedUsd:a.cost.saved.usd,best:n>0?a.best.text:e,kept:a.best.kept,tips:a.tips.filter(r=>!["handoff","price-threshold","family-note"].includes(r.id)).map(r=>r.text)}}};var L=null,je="",qi={version:"0.2.48",start(i,e,a){let n;try{n=e?JSON.parse(e):void 0,(!n||!Array.isArray(n.sends)||!Array.isArray(n.readings))&&(n=void 0)}catch{n=void 0}L=new be(i||"claude-sonnet",{data:n,plan:a||void 0,onData:r=>je=JSON.stringify(r)})},draft(i,e){let a=L?.draft(i,e);return a?JSON.stringify(a):""},chat(i,e,a){let n=L?.chat(i,e,a);return n?JSON.stringify(n):""},state(i){return L?(L.refreshCoach(i),JSON.stringify(L.state)):"{}"},currentDraft(){return L?.currentDraft??""},setPlan(i){L?.setPlan(i||null)},takeData(){let i=je;return je="",i},optimize(i,e){let a=he({prompt:i,model:e,level:"auto"});return JSON.stringify({best:a.best.text,tokens:a.promptTokens,optimizedTokens:a.optimized.tokens,kept:a.best.kept})}};globalThis.TokenLensCore=qi;})();
|
|
3336
|
+
`);return E!==C&&(h=!0),C=E,C});return n.length&&r.push(`removed indentation and line breaks from ${n.length} JSON block${n.length>1?"s":""} (same data)`),h&&r.push("removed trailing spaces and extra blank lines outside code"),o(k.join(""),n.length||h?void 0:"Nothing to compact: no pretty-printed JSON or extra whitespace found.")}var v=i=>i,G={"gpt-astra":v({id:"gpt-astra",label:"GPT-6 Astra",family:"openai",contextWindow:105e4,tokenizer:"heuristic",charsPerToken:4.2,reasoning:!0,pricing:{inputPerMTok:10,outputPerMTok:50}}),"gpt-reasoning":v({id:"gpt-reasoning",label:"GPT (thinking)",family:"openai",contextWindow:196e3,tokenizer:"o200k",charsPerToken:4.2,reasoning:!0,lighterAlternative:"the Instant / non-thinking model",pricing:{inputPerMTok:5,outputPerMTok:30,cachedInputPerMTok:.5}}),gpt:v({id:"gpt",label:"GPT",family:"openai",contextWindow:128e3,tokenizer:"o200k",charsPerToken:4.2,reasoning:!1,pricing:{inputPerMTok:2.5,outputPerMTok:15,cachedInputPerMTok:.25}}),"claude-fable":v({id:"claude-fable",label:"Claude Fable",family:"anthropic",contextWindow:1e6,tokenizer:"heuristic",charsPerToken:3.5,reasoning:!0,notes:["Claude reads XML-style tags well: wrap pasted material in <doc>\u2026</doc> instead of explaining it."],pricing:{inputPerMTok:10,outputPerMTok:50,cachedInputPerMTok:.25}}),"claude-opus":v({id:"claude-opus",label:"Claude Opus",family:"anthropic",contextWindow:2e5,tokenizer:"heuristic",charsPerToken:3.5,reasoning:!1,lighterAlternative:"Sonnet or Haiku",notes:["Claude reads XML-style tags well: wrap pasted material in <doc>\u2026</doc> instead of explaining it."],pricing:{inputPerMTok:4,outputPerMTok:20,cachedInputPerMTok:.2}}),"claude-sonnet":v({id:"claude-sonnet",label:"Claude Sonnet",family:"anthropic",contextWindow:2e5,tokenizer:"heuristic",charsPerToken:3.5,reasoning:!1,lighterAlternative:"Haiku",notes:["Claude reads XML-style tags well: wrap pasted material in <doc>\u2026</doc> instead of explaining it."],pricing:{inputPerMTok:2,outputPerMTok:10,cachedInputPerMTok:.2}}),"claude-haiku":v({id:"claude-haiku",label:"Claude Haiku",family:"anthropic",contextWindow:2e5,tokenizer:"heuristic",charsPerToken:3.5,reasoning:!1,pricing:{inputPerMTok:.1,outputPerMTok:.5,cachedInputPerMTok:.01}}),"gemini-pro":v({id:"gemini-pro",label:"Gemini Pro",family:"google",contextWindow:1e6,tokenizer:"heuristic",charsPerToken:4,reasoning:!0,lighterAlternative:"Flash",pricing:{inputPerMTok:2,outputPerMTok:12,cachedInputPerMTok:.2,longContext:{aboveTokens:2e5,inputPerMTok:4,outputPerMTok:18}}}),"gemini-flash":v({id:"gemini-flash",label:"Gemini Flash",family:"google",contextWindow:1e6,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:1.5,outputPerMTok:9,cachedInputPerMTok:.15}}),deepseek:v({id:"deepseek",label:"DeepSeek",family:"deepseek",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:.28,outputPerMTok:.42,cachedInputPerMTok:.028}}),"deepseek-reasoning":v({id:"deepseek-reasoning",label:"DeepSeek (thinking)",family:"deepseek",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!0,lighterAlternative:"the non-thinking mode",pricing:{inputPerMTok:.55,outputPerMTok:2.19,cachedInputPerMTok:.14}}),mistral:v({id:"mistral",label:"Mistral",family:"mistral",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:2,outputPerMTok:6}}),grok:v({id:"grok",label:"Grok",family:"xai",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:2,outputPerMTok:6}}),llama:v({id:"llama",label:"Llama",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.9,reasoning:!1,pricing:{inputPerMTok:.27,outputPerMTok:.85}}),qwen:v({id:"qwen",label:"Qwen",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:.4,outputPerMTok:1.2}}),kimi:v({id:"kimi",label:"Kimi",family:"other",contextWindow:256e3,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:.6,outputPerMTok:2.5,cachedInputPerMTok:.15}}),glm:v({id:"glm",label:"GLM",family:"other",contextWindow:2e5,tokenizer:"heuristic",charsPerToken:3.8,reasoning:!1,pricing:{inputPerMTok:.6,outputPerMTok:2.2,cachedInputPerMTok:.11}}),command:v({id:"command",label:"Cohere Command",family:"other",contextWindow:256e3,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:2.5,outputPerMTok:10}}),sonar:v({id:"sonar",label:"Perplexity Sonar",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:1,outputPerMTok:1}}),gemma:v({id:"gemma",label:"Gemma",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:3.9,reasoning:!1,pricing:{inputPerMTok:.1,outputPerMTok:.2}}),phi:v({id:"phi",label:"Phi",family:"other",contextWindow:16e3,tokenizer:"heuristic",charsPerToken:3.9,reasoning:!1,pricing:{inputPerMTok:.07,outputPerMTok:.14}}),generic:v({id:"generic",label:"Unknown model",family:"other",contextWindow:128e3,tokenizer:"heuristic",charsPerToken:4,reasoning:!1,pricing:{inputPerMTok:2,outputPerMTok:10}})},_i=[[/\b(fable|mythos)\b/,"claude-fable"],[/\bastra\b|\bgpt[- ]?6\b/,"gpt-astra"],[/\bclaude\b.*\bopus\b|\bopus\b/,"claude-opus"],[/\bsonnet\b/,"claude-sonnet"],[/\bhaiku\b/,"claude-haiku"],[/\b(qwen|qwq)/,"qwen"],[/\b(glm|chatglm|zhipu)\b|\bglm-?\d/,"glm"],[/\b(kimi|moonshot)/,"kimi"],[/\bgemma/,"gemma"],[/\bgemini\b.*\bflash\b|\bflash\b/,"gemini-flash"],[/\bgemini\b.*\b(pro|ultra|deep think)\b|^\s*\d(\.\d)?\s*pro\b|\bdeep think\b/,"gemini-pro"],[/\bdeepseek\b.*\b(r1|reason|think|deepthink)|\bdeepthink\b/,"deepseek-reasoning"],[/\bdeepseek\b/,"deepseek"],[/\b(mistral|le chat|magistral|codestral)\b/,"mistral"],[/\bgrok\b/,"grok"],[/\bllama|codellama/,"llama"],[/\bcommand[- ]?(r|a)\b|\bcohere\b/,"command"],[/\bsonar\b|\bperplexity\b/,"sonar"],[/\bphi-?\d/,"phi"],[/\bo[1-9](-mini|-pro)?\b|\bgpt[- ]?\S*\s*(thinking|pro)\b|\bthinking\b/,"gpt-reasoning"],[/\b(gpt|chatgpt)\b|\bgpt-?\d/,"gpt"],[/\bgemini\b/,"gemini-pro"],[/\bclaude\b/,"claude-sonnet"]];var Ei={chatgpt:"gpt",claude:"claude-sonnet",gemini:"gemini-flash",deepseek:"deepseek",mistral:"mistral",grok:"grok",generic:"generic"},Ai=[];var zr={...G};function K(i,e="generic"){let a=(i??"").toLowerCase().replace(/\s+/g," ").trim();if(a){for(let[n,r]of Ai)if(n.test(a))return G[r];if(e==="gemini"&&/\b(pro|deep think)\b/.test(a))return G["gemini-pro"];if(e==="gemini"&&/\bflash\b/.test(a))return G["gemini-flash"];if(e==="deepseek"&&/\b(deepthink|r1|think)/.test(a))return G["deepseek-reasoning"];for(let[n,r]of _i)if(n.test(a))return G[r]}return G[Ei[e]??"generic"]}var va="ai-toolbox.co ChatGPT limits guide",ne={"chatgpt-free":{id:"chatgpt-free",site:"chatgpt",label:"ChatGPT Free",meter:"messages",caps:[]},"chatgpt-go":{id:"chatgpt-go",site:"chatgpt",label:"ChatGPT Go",meter:"messages",caps:[]},"chatgpt-plus":{id:"chatgpt-plus",site:"chatgpt",label:"ChatGPT Plus",meter:"messages",caps:[{models:["gpt"],messages:160,window:"3h",source:va,asOf:"2026-10"},{models:["gpt-reasoning"],messages:3e3,window:"week",source:va,asOf:"2026-10"}]},"chatgpt-pro":{id:"chatgpt-pro",site:"chatgpt",label:"ChatGPT Pro",meter:"messages",caps:[],note:"Pro is close to unlimited for everyday models, but GPT-6 Astra Pro use is capped (number not published)."},"chatgpt-business":{id:"chatgpt-business",site:"chatgpt",label:"ChatGPT Business",meter:"messages",caps:[]},"claude-free":{id:"claude-free",site:"claude",label:"Claude Free",meter:"compute",caps:[]},"claude-pro":{id:"claude-pro",site:"claude",label:"Claude Pro",meter:"compute",caps:[],note:"5-hour session and weekly limits shared across models; Fable runs on usage credits."},"claude-max":{id:"claude-max",site:"claude",label:"Claude Max",meter:"compute",caps:[],note:"5x or 20x Pro's session usage, with a weekly limit across models and one for the top models."},"claude-team":{id:"claude-team",site:"claude",label:"Claude Team",meter:"compute",caps:[]},"gemini-free":{id:"gemini-free",site:"gemini",label:"Gemini (free)",meter:"messages",caps:[]},"gemini-pro":{id:"gemini-pro",site:"gemini",label:"Google AI Pro",meter:"messages",caps:[]},"gemini-ultra":{id:"gemini-ultra",site:"gemini",label:"Google AI Ultra",meter:"messages",caps:[]}};var pe=5*36e5,Ie=7*864e5,Ci=1e3,Ti=500,re=i=>Math.round(i).toLocaleString("en-US");function ge(i){let e=2166136261;for(let a=0;a<i.length;a++)e=Math.imul(e^i.charCodeAt(a),16777619)>>>0;return e.toString(36)}function ya(i){let e=/\b(Free|Pro|Max|Team|Enterprise)\s+plan\b/.exec(i);if(!e)return null;let a=e[1].toLowerCase();return ne[`claude-${a==="enterprise"?"team":a}`]??null}var Ri=["sun","mon","tue","wed","thu","fri","sat"];function Pi(i,e){let a=/\b(sun|mon|tue|wed|thu|fri|sat)\w*\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)?/i.exec(i);if(!a)return;let n=new Date(e),r=Number(a[2])%12;a[4]?.toLowerCase()==="pm"&&(r+=12),!a[4]&&Number(a[2])>=12&&(r=Number(a[2]));let t=(Ri.indexOf(a[1].slice(0,3).toLowerCase())-n.getDay()+7)%7,o=new Date(n.getFullYear(),n.getMonth(),n.getDate()+t,r,Number(a[3]??0)).getTime();return o<=e?o+Ie:o}function zi(i){let e=/resets?\s+in\s+(?:(\d+)\s*(?:hr|hour|h)s?)?\s*(?:(\d+)\s*(?:min|minute|m)s?)?/i.exec(i);if(!(!e||!e[1]&&!e[2]))return(Number(e[1]??0)*60+Number(e[2]??0))*6e4}function wa(i,e){let a=i.replace(/\s+/g," "),n=/current session(.{0,160}?)(\d{1,3})\s*%\s*used/i.exec(a),r=/weekly (?:limits?|usage)(.{0,260}?)(\d{1,3})\s*%\s*used/i.exec(a),t=!n&&/(\d{1,3})\s*%\s+of\s+your\s+(session|5-hour|weekly)\s+(?:usage\s+)?limit/i.exec(a);if(!n&&!r&&!t)return null;let o={at:e};if(n){o.sessionPct=Math.min(100,Number(n[2]));let s=zi(n[1]);s!==void 0&&(o.sessionResetsAt=e+s)}if(r){o.weekPct=Math.min(100,Number(r[2]));let s=/resets?\s+((?:sun|mon|tue|wed|thu|fri|sat)\w*\s+\d{1,2}(?::\d{2})?\s*(?:am|pm)?)/i.exec(r[1]);s&&(o.weekResetsText=s[1].trim(),o.weekResetsAt=Pi(s[1],e))}return t&&(/weekly/i.test(t[2])?o.weekPct=Math.min(100,Number(t[1])):o.sessionPct=Math.min(100,Number(t[1]))),o}var ze=i=>new Date(i).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});function xe(i,e){return{...i,sends:i.sends.filter(a=>e-a.at<Ie).slice(-5e3),readings:i.readings.filter(a=>e-a.at<Ie).slice(-50)}}function Sa(i,e){let a=[...i.readings].reverse().find(t=>t.sessionPct!==void 0),n=i.pctPer1k;if(a&&e.sessionPct!==void 0&&a.sessionPct!==void 0&&e.sessionPct>a.sessionPct&&e.at-a.at<pe){let t=i.sends.filter(o=>o.at>a.at&&o.at<=e.at).reduce((o,s)=>o+s.tokens,0);if(t>=5e3){let o=(e.sessionPct-a.sessionPct)/t*1e3;n=n===void 0?o:n*.5+o*.5}}let r=a&&a.sessionPct===e.sessionPct&&a.weekPct===e.weekPct&&e.at-a.at<10*6e4;return{...i,pctPer1k:n,readings:r?i.readings:[...i.readings,e]}}function _a(i){let{data:e,now:a,plan:n,current:r}=i,t=[...e.readings].reverse().find(p=>p.sessionPct!==void 0||p.weekPct!==void 0),o=[...e.readings].reverse().find(p=>p.weekPct!==void 0),s=[...e.readings].reverse().find(p=>p.sessionPct!==void 0),l=s&&(s.sessionResetsAt??s.at+pe)>a,u=l&&s.sessionResetsAt?s.sessionResetsAt-pe:a-pe,d=e.sends.filter(p=>p.at>=u),h=p=>p.reduce((y,A)=>y+A.tokens,0),k=h(d),c={plan:n,planSource:i.planSource,session:{messages:d.length,tokens:k,since:u},week:{messages:e.sends.length,tokens:h(e.sends)},topChats:[],insights:[]};if(l&&s?.sessionPct!==void 0){let p=h(e.sends.filter(A=>A.at>s.at)),y=s.sessionPct+(e.pctPer1k?p/1e3*e.pctPer1k:0);c.sessionPct=Math.min(100,Math.round(y)),c.sessionResetsAt=s.sessionResetsAt,c.meterAgeMin=Math.round((a-s.at)/6e4)}o?.weekPct!==void 0&&(o.weekResetsAt??1/0)>a&&(c.weekPct=o.weekPct,c.weekResetsAt=o.weekResetsAt,c.weekResetsText=o.weekResetsText);let f=new Map;for(let p of d){let y=f.get(p.chat)??{chat:p.chat,title:i.titles?.get(p.chat),tokens:0,messages:0,share:0};y.tokens+=p.tokens,y.messages++,f.set(p.chat,y)}c.topChats=[...f.values()].map(p=>({...p,share:k?p.tokens/k:0})).sort((p,y)=>y.tokens-p.tokens).slice(0,5);let g=Ti,w=(r?.tokens??0)+g,C=Ci+g;if(c.sessionPct!==void 0&&e.pctPer1k){let p=Math.max(0,100-c.sessionPct)/e.pctPer1k*1e3;c.left={here:Math.floor(p/w),fresh:Math.floor(p/C)}}let E=c.insights,S=n?n.label:"your plan";if(c.sessionPct!==void 0){let p=c.sessionResetsAt?`; it resets at ${ze(c.sessionResetsAt)}`:"";c.left&&r&&r.tokens>=1e4&&c.left.fresh>=c.left.here*2?E.push(`About ${re(c.left.here)} more messages fit in ${S}'s session at this chat's size, or about ${re(c.left.fresh)} in a new chat (${c.sessionPct}% used${p}). For a new topic, start a new chat. ${z}`):c.left?E.push(`About ${re(c.left.fresh)} more messages like your recent ones fit in this session (${c.sessionPct}% used${p}).`):E.push(`Session ${c.sessionPct}% used${p}.`);let y=s&&e.readings.find(A=>A.sessionPct!==void 0&&A.at>=u);if(y&&s&&y!==s&&c.sessionResetsAt&&c.sessionPct<100){let A=(c.sessionPct-(y.sessionPct??0))/Math.max(1,a-y.at),O=A>0?a+(100-c.sessionPct)/A:1/0;O<c.sessionResetsAt&&E.push(`At this pace the session runs out around ${ze(O)}, before it resets at ${ze(c.sessionResetsAt)}. Save the big asks for after the reset, or start new topics in new chats.`)}}let T=c.topChats[0];return T&&d.length>=4&&T.share>=.5&&f.size>1&&E.push(`${Math.round(T.share*100)}% of this session's usage came from one chat${T.title?` ("${T.title}")`:""}: each message there re-read about ${re(T.tokens/T.messages)} tokens.`),c.weekPct!==void 0&&c.weekResetsAt&&((c.weekResetsAt-a)/36e5<=36&&c.weekPct<=50?E.push(`${100-c.weekPct}% of ${S}'s weekly allowance is unused and resets ${c.weekResetsText??"soon"}. It doesn't carry over, so this is a good time for the big jobs you've been holding back.`):c.weekPct>=80&&E.push(`Week ${c.weekPct}% used${c.weekResetsText?`, resets ${c.weekResetsText}`:""}. New topics in new chats and one complete message per ask stretch what's left.`)),r&&r.tokens>=2e4&&!E.some(p=>p.includes("new chat"))&&E.push(`Every message in this chat re-reads about ${re(r.tokens)} tokens, ${Math.max(2,Math.round(w/C))}\xD7 a new chat. On ${S} that's what uses your allowance fastest.`),n?c.sessionPct===void 0&&n.site==="claude"&&E.push("Open Settings > Usage in Claude once and Token Lens reads your meter from it, to count how many messages you have left."):E.push("Tell Token Lens your plan once (Free, Pro, Max or Team) for advice that fits it."),c}var Ii=/^(?:ok(?:ay)?|k|thanks?(?: you)?(?: so much)?|thx|ty|great|perfect|nice|cool|awesome|got it|understood|sounds good|lgtm|yes|yep|sure|done|👍|🙏)[\s!.,🙂😊👍🙏]*$/i;function Ea(i){return Ii.test(i.trim())}var Me=i=>i.toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").trim();function Aa(i,e){let a=Me(i);return a.split(" ").length<8?!1:Me(e).includes(a)}function Ca(i){return i.split(/\n\s*\n/).map(e=>e.trim()).filter(e=>e.length>=1200).map(e=>ge(Me(e)))}function he(i){let e=typeof i.model=="string"?K(i.model,i.site):i.model,a=i.pricing?{...e,pricing:i.pricing}:e,n=le(i.prompt),{tokens:r,exact:t}=_(i.prompt,a),o=$(i.conversationTokens??0,r,a,i.contextWindow),s=De(i.level??"auto",o),l=V(i.prompt,{profile:a,task:n.task,level:s}),u=fa(l.text,a),d=u.saved>0&&u.blocks.length?{...l,text:u.text,tokens:u.after,saved:l.originalTokens-u.after,rules:[...l.rules,"JSON whitespace (same data)"]}:l,h=fe({profile:a,task:n.task,signals:n.signals,promptTokens:r,usage:o,text:i.prompt}),k={pricing:a.pricing,promptUsd:N(r,a),sendUsd:N((i.conversationTokens??0)+r,a),saved:W(d.saved,a)},c=Object.entries(Re(i.prompt,d.text)).map(([g,[w,C]])=>`${C}/${w} ${g}s`).join(", "),f={text:d.text,tokens:d.tokens,changes:d.saved>0?d.rules.map(g=>`removed ${g}`):[],kept:c||"every instruction"};return{profile:a,task:n,promptTokens:r,exact:t,usage:o,level:s,optimized:d,tips:h,handoffPrompt:Ne(n.task),cost:k,best:f}}var ji=60,Di=20,Ni=12,Li=1800,Oi=25e3,Bi=15e3,Fi=80,Gi=3*6e4,J=i=>Math.round(i).toLocaleString("en-US"),Ta=i=>i.toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").trim(),be=class{constructor(e="claude-sonnet",a={}){m(this,"profile");m(this,"modelKnown",!1);m(this,"draftText","");m(this,"draftSince",0);m(this,"draftDone","");m(this,"lastDraftNotice",-1/0);m(this,"chatTold",new Map);m(this,"chatTokens",new Map);m(this,"chatEpoch",new Map);m(this,"chatText","");m(this,"chatId","");m(this,"chatTitle","");m(this,"titles",new Map);m(this,"pending",null);m(this,"pastes",new Map);m(this,"told",new Set);m(this,"data");m(this,"pickedPlan");m(this,"appPlan",null);m(this,"onData");m(this,"state");this.profile=K(e),this.data=xe(a.data??{sends:[],readings:[]},Date.now()),this.pickedPlan=a.plan&&ne[a.plan]||null,this.onData=a.onData,this.state={model:this.profile.label,draft:null,chat:null,coach:null},this.refreshCoach(Date.now())}get currentDraft(){return this.draftText}get plan(){return this.pickedPlan??this.appPlan}useModel(e){let a=K(e);a.id!=="generic"&&(this.profile=a,this.modelKnown=!0,this.state.model=this.profile.label)}setPlan(e,a=Date.now()){return this.pickedPlan=e&&ne[e]||null,this.refreshCoach(a),this.plan}draft(e,a){let n=(e??"").trim();if(n!==this.draftText)return e===""&&this.draftText.length>2&&this.chatId?this.pending={probe:Ta(this.draftText).slice(0,80),tokens:this.state.chat?.tokens??0,chat:this.chatId,at:a,text:this.draftText}:this.pending&&n===this.pending.text&&(this.pending=null),this.draftText=n,this.draftSince=a,this.state.draft=n?this.analyzeDraft(n):null,null;let r=this.state.draft;if(!r||a-this.draftSince<Li)return null;let t=ge(n);if(t===this.draftDone||a-this.lastDraftNotice<Oi)return null;let o=this.draftNotice(n,r);return o?(this.draftDone=t,this.lastDraftNotice=a,o):null}draftNotice(e,a){let n=this.state.chat?.tokens??0,r=this.plan?.label??"your plan";if(Aa(e,this.chatText))return{title:"You already asked this in this chat",body:`Its answer is above. Sending it again re-reads about ${J(n+a.tokens)} tokens of ${r}'s usage for the same question.`};if(Ea(e)&&n>=Bi)return{title:`"${e.slice(0,24)}" re-reads this whole chat`,body:`Sending it uses about ${J(n)} tokens of ${r}'s usage, as much as a long question. If there's nothing to ask, you can skip it, or add it to your next real message.`};let t=Ca(e);for(let s of t){let l=this.pastes.get(s)??new Set;if(l.add(this.chatId),this.pastes.set(s,l),l.size>=2&&!this.told.has(`paste:${s}`))return this.told.add(`paste:${s}`),{title:`You've pasted this text into ${l.size} chats`,body:"Put it in a Claude Project's knowledge or instructions once, and every chat in that Project has it without pasting it again."}}return a.tokens>=ji&&a.saved>=Di&&a.pct>=Ni?{title:`Draft: ${J(a.tokens)} \u2192 ${J(a.optimizedTokens)} tokens (${a.pct}% fewer)`,body:`Same request, ${a.savedUsd===null?"fewer tokens":`${Pe(a.savedUsd)} less per send at API prices`}. Token Lens can put the shorter version in the message box when you click.${a.tips[0]?` ${a.tips[0]}`:""}`}:a.tips.length?{title:"Token Lens tip for your draft",body:a.tips[0]}:null}chat(e,a,n=Date.now()){let{tokens:r}=_(a,this.profile),t=$(r,0,this.profile),o=N(r,this.profile),s=[],l=null;t.zone==="hot"||t.zone==="full"?(l=t.zone,s.push(`This chat fills about ${Math.round(t.ratio*100)}% of the context, so older messages will soon be dropped or compacted. ${z}`)):(t.zone==="warm"||t.longChat)&&(l=t.zone==="warm"?"warm":"long",s.push(`Every message you send re-reads about ${J(r)} tokens of this chat (${Pe(o)} each at API prices). Starting a new chat for a new topic avoids that.`)),this.state.chat={tokens:r,ratio:t.ratio,window:t.window,perMessageUsd:o,tips:s},r<(this.chatTokens.get(e)??0)*.5&&(this.chatTold.delete(e),this.chatEpoch.set(e,(this.chatEpoch.get(e)??0)+1)),this.chatTokens.set(e,r),this.chatText=a,this.chatId=ge(`${e}#${this.chatEpoch.get(e)??0}`),this.chatTitle=e&&!/^claude$/i.test(e)?e.slice(0,60):"",this.chatTitle&&this.titles.set(this.chatId,this.chatTitle);let u=this.observe(a,n),d=null;if(l){let h=this.chatTold.get(e)??new Set;this.chatTold.set(e,h),h.has(l)||(h.add(l),d={title:`This chat: ${J(r)} tokens (${Math.round(t.ratio*100)}% of context)`,body:s[0]})}return u??d}observe(e,a){let n=!1,r=ya(e);r&&(this.appPlan=r);let t=wa(e,a);t&&(this.data=Sa(this.data,t),n=!0);let o=this.pending;o&&a-o.at>Gi?this.pending=null:o&&o.probe&&Ta(e).includes(o.probe)&&(this.data.sends.push({at:o.at,tokens:o.tokens+_(o.text,this.profile).tokens,chat:o.chat}),this.pending=null,n=!0),n&&(this.data=xe(this.data,a),this.onData?.(this.data));let s=this.refreshCoach(a);if(s.sessionPct!==void 0&&s.sessionPct>=Fi){let u=`session:${Math.round(s.session.since/36e5)}`;if(!this.told.has(u))return this.told.add(u),{title:`${this.plan?.label??"Claude"} session ${s.sessionPct}% used`,body:s.insights[0]??"New topics in new chats stretch what's left."}}let l=s.insights.find(u=>u.includes("weekly allowance is unused"));if(l&&s.weekResetsAt){let u=`week:${Math.round(s.weekResetsAt/864e5)}`;if(!this.told.has(u))return this.told.add(u),{title:`${100-(s.weekPct??0)}% of your week is still unused`,body:l}}return null}refreshCoach(e=Date.now()){let a=_a({data:this.data,now:e,plan:this.plan,planSource:this.pickedPlan?"set":this.appPlan?"app":"unknown",current:this.chatId?{chat:this.chatId,title:this.chatTitle,tokens:this.state.chat?.tokens??0}:void 0,titles:this.titles});return this.state.coach=a,a}analyzeDraft(e){let a=he({prompt:e,model:this.profile,conversationTokens:this.state.chat?.tokens??0,level:"auto"}),n=a.optimized.saved;return{tokens:a.promptTokens,optimizedTokens:a.optimized.tokens,saved:n,pct:a.optimized.originalTokens?Math.round(n/a.optimized.originalTokens*100):0,savedUsd:a.cost.saved.usd,best:n>0?a.best.text:e,kept:a.best.kept,tips:a.tips.filter(r=>!["handoff","price-threshold","family-note"].includes(r.id)).map(r=>r.text)}}};var L=null,je="",qi={version:"0.2.50",start(i,e,a){let n;try{n=e?JSON.parse(e):void 0,(!n||!Array.isArray(n.sends)||!Array.isArray(n.readings))&&(n=void 0)}catch{n=void 0}L=new be(i||"claude-sonnet",{data:n,plan:a||void 0,onData:r=>je=JSON.stringify(r)})},draft(i,e){let a=L?.draft(i,e);return a?JSON.stringify(a):""},chat(i,e,a){let n=L?.chat(i,e,a);return n?JSON.stringify(n):""},state(i){return L?(L.refreshCoach(i),JSON.stringify(L.state)):"{}"},currentDraft(){return L?.currentDraft??""},setPlan(i){L?.setPlan(i||null)},takeData(){let i=je;return je="",i},optimize(i,e){let a=he({prompt:i,model:e,level:"auto"});return JSON.stringify({best:a.best.text,tokens:a.promptTokens,optimizedTokens:a.optimized.tokens,kept:a.best.kept})}};globalThis.TokenLensCore=qi;})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kunal_dutt/token-lens",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.50",
|
|
4
4
|
"description": "Count and cut the tokens your prompts, chats and agents use, adapted to the model and task. MCP server and self-hosted gateway. Collects no data.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|