copilot-usage-studio 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +150 -0
- package/bin/copilot-usage-studio.mjs +10 -0
- package/data/github-copilot-pricing.json +227 -0
- package/dist/copilot-usage-studio/browser/chunk-C6VWIY5S.js +1 -0
- package/dist/copilot-usage-studio/browser/chunk-DLWQO3VR.js +1 -0
- package/dist/copilot-usage-studio/browser/chunk-F6TIG2GE.js +4 -0
- package/dist/copilot-usage-studio/browser/chunk-JIP7ONRZ.js +1 -0
- package/dist/copilot-usage-studio/browser/chunk-RNKEPBEU.js +1 -0
- package/dist/copilot-usage-studio/browser/chunk-Z3XIAKMM.js +1 -0
- package/dist/copilot-usage-studio/browser/index.html +13 -0
- package/dist/copilot-usage-studio/browser/main-C6XOJRSH.js +2 -0
- package/dist/copilot-usage-studio/browser/styles-GZOQ5QIH.css +1 -0
- package/dist/copilot-usage-studio/browser/usage-studio.svg +12 -0
- package/docs/local-deployment.md +202 -0
- package/docs/pricing.md +274 -0
- package/docs/scanner-api.md +109 -0
- package/lib/cli.mjs +173 -0
- package/lib/local-runtime.mjs +231 -0
- package/lib/scanner-api.mjs +12 -0
- package/package.json +86 -0
- package/scripts/pricing-utils.mjs +71 -0
- package/scripts/scan-vscode-sessions.mjs +1632 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{$a as _,Ba as W,Ca as x,Da as h,Eb as K,Fa as T,Fb as X,Ga as E,Gb as L,Ha as A,Hb as G,Ia as a,Ib as w,Ja as o,Ka as Q,Mb as S,Na as F,Nb as Y,O as U,Ob as j,P as D,Pa as O,Pb as Z,Qb as ee,Ra as u,Rb as te,Sb as ne,Ta as y,U as z,Ua as c,Va as f,Wa as k,Wb as ie,Xa as C,Ya as V,Z as B,Za as m,_a as b,cb as v,ka as s,lb as H,nb as J,sa as q}from"./chunk-F6TIG2GE.js";var re=(r,t)=>t.id,ae=(r,t)=>t.label,se=(r,t)=>t.title,ce=(r,t)=>t.model+t.pricingModel;function le(r,t){if(r&1){let e=F();a(0,"button",12),O("click",function(){U(e);let i=u();return D(i.openBaselinePicker())}),a(1,"strong"),c(2),o(),a(3,"em"),c(4),m(5,"number"),o()()}if(r&2){let e=t,n=u();s(2),f(e.title),s(2),C("",n.compactDate(e.startedAt)," \xB7 $",_(5,3,n.usageUsd(e),"1.2-4"))}}function pe(r,t){r&1&&(a(0,"em",15),c(1,"Same prompt as B"),o())}function de(r,t){if(r&1&&(a(0,"em",16),c(1),m(2,"number"),o()),r&2){let e=u().$implicit,n=u(2);s(),k("",b(2,1,n.promptRepeatCount(e))," matching prompts")}}function me(r,t){if(r&1){let e=F();a(0,"button",14),O("click",function(){let i=U(e).$implicit,l=u(2);return D(l.setCompareA(i.id))}),a(1,"strong"),c(2),o(),a(3,"span"),c(4),m(5,"number"),m(6,"number"),o(),x(7,pe,2,0,"em",15)(8,de,3,3,"em",16),o()}if(r&2){let e=t.$implicit,n=u(2);y("active",e.id===n.selectedAId())("same-prompt",n.isSamePromptAsOther(e,"baseline")),W("aria-selected",e.id===n.selectedAId()),s(2),f(e.title),s(2),V(" ",n.compactDate(e.startedAt)," \xB7 $",_(5,10,n.usageUsd(e),"1.2-4")," \xB7 ",b(6,13,n.runTokenTotal(e))," tokens "),s(3),h(n.isSamePromptAsOther(e,"baseline")?7:n.promptRepeatCount(e)>1?8:-1)}}function ue(r,t){r&1&&(a(0,"em"),c(1,"No matching runs"),o())}function ge(r,t){if(r&1&&(a(0,"div",7),T(1,me,9,15,"button",13,re,!1,ue,2,0,"em"),o()),r&2){let e=u();s(),E(e.baselineOptions().slice(0,8))}}function Ce(r,t){if(r&1){let e=F();a(0,"button",17),O("click",function(){U(e);let i=u();return D(i.openCandidatePicker())}),a(1,"strong"),c(2),o(),a(3,"em"),c(4),m(5,"number"),o()()}if(r&2){let e=t,n=u();s(2),f(e.title),s(2),C("",n.compactDate(e.startedAt)," \xB7 $",_(5,3,n.usageUsd(e),"1.2-4"))}}function _e(r,t){r&1&&(a(0,"em",15),c(1,"Same prompt as A"),o())}function xe(r,t){if(r&1&&(a(0,"em",16),c(1),m(2,"number"),o()),r&2){let e=u().$implicit,n=u(2);s(),k("",b(2,1,n.promptRepeatCount(e))," matching prompts")}}function he(r,t){if(r&1){let e=F();a(0,"button",14),O("click",function(){let i=U(e).$implicit,l=u(2);return D(l.setCompareB(i.id))}),a(1,"strong"),c(2),o(),a(3,"span"),c(4),m(5,"number"),m(6,"number"),o(),x(7,_e,2,0,"em",15)(8,xe,3,3,"em",16),o()}if(r&2){let e=t.$implicit,n=u(2);y("active",e.id===n.selectedBId())("same-prompt",n.isSamePromptAsOther(e,"candidate")),W("aria-selected",e.id===n.selectedBId()),s(2),f(e.title),s(2),V(" ",n.compactDate(e.startedAt)," \xB7 $",_(5,10,n.usageUsd(e),"1.2-4")," \xB7 ",b(6,13,n.runTokenTotal(e))," tokens "),s(3),h(n.isSamePromptAsOther(e,"candidate")?7:n.promptRepeatCount(e)>1?8:-1)}}function be(r,t){r&1&&(a(0,"em"),c(1,"No matching runs"),o())}function fe(r,t){if(r&1&&(a(0,"div",10),T(1,he,9,15,"button",13,re,!1,be,2,0,"em"),o()),r&2){let e=u();s(),E(e.candidateOptions().slice(0,8))}}function ve(r,t){r&1&&(a(0,"p",19),c(1,"These first prompts differ, so read this as run comparison rather than prompt A/B testing."),o())}function Pe(r,t){if(r&1&&(a(0,"strong"),c(1),m(2,"number"),o(),a(3,"em"),c(4),m(5,"number"),m(6,"number"),o()),r&2){let e=u().$implicit,n=u(2);y("saving",e.lowerIsBetter&&e.delta<0),s(),C(" ",e.delta<0?"-":"+","$",_(2,6,n.abs(e.delta),"1.2-4")," "),s(3),C("A $",_(5,9,e.a,"1.2-4")," / B $",_(6,12,e.b,"1.2-4"))}}function Me(r,t){if(r&1&&(c(0),m(1,"number")),r&2){let e=u(2).$implicit;C(" \xB7 ",e.percent>=0?"+":"","",_(1,2,e.percent,"1.0-0"),"% ")}}function Oe(r,t){if(r&1&&(a(0,"strong"),c(1),m(2,"number"),o(),a(3,"em"),c(4),m(5,"number"),m(6,"number"),x(7,Me,2,5),o()),r&2){let e=u().$implicit;y("saving",e.lowerIsBetter&&e.delta<0),s(),C(" ",e.delta>=0?"+":"","",b(2,7,e.delta)," "),s(3),C(" A ",b(5,9,e.a)," / B ",b(6,11,e.b)," "),s(3),h(e.percent!==null?7:-1)}}function ye(r,t){if(r&1&&(a(0,"div")(1,"span"),c(2),Q(3,"app-help-popover",29),o(),x(4,Pe,7,15)(5,Oe,8,13),o()),r&2){let e=t.$implicit;s(2),k(" ",e.label," "),s(),A("text",e.help)("label","Explain "+e.label),s(),h(e.format==="currency"?4:5)}}function ke(r,t){if(r&1&&(a(0,"article",24)(1,"div")(2,"span"),c(3),o(),a(4,"strong"),c(5),o()(),a(6,"p"),c(7),o()()),r&2){let e=t.$implicit;A("ngClass",e.tone),s(3),f(e.title),s(2),f(e.value),s(2),f(e.detail)}}function we(r,t){if(r&1&&(a(0,"em",30),c(1," fallback pricing "),Q(2,"app-help-popover",32),o()),r&2){let e=u().$implicit,n=u(2);s(2),A("text",n.pricingFallbackReason(e.model,e.pricingModel))}}function Se(r,t){if(r&1&&(a(0,"em"),c(1),o()),r&2){let e=u().$implicit,n=u(2);s(),k("write ",n.tokenDeltaLabel(e.cacheWriteDelta))}}function Be(r,t){if(r&1&&(a(0,"div",28)(1,"strong"),c(2),o(),a(3,"span"),c(4),x(5,we,3,1,"em",30),o(),a(6,"span"),c(7),m(8,"number"),m(9,"number"),o(),a(10,"span",31)(11,"strong"),c(12),m(13,"number"),o(),a(14,"em"),c(15),o(),x(16,Se,2,1,"em"),a(17,"em"),c(18),o()(),a(19,"span"),c(20),m(21,"number"),m(22,"number"),o(),a(23,"span"),c(24),m(25,"number"),o()()),r&2){let e=t.$implicit,n=u(2);s(2),f(e.model),s(2),k(" ",e.pricingModel," "),s(),h(e.usesFallbackPrice?5:-1),s(2),C("$",_(8,17,e.aCost,"1.4-6")," / $",_(9,20,e.bCost,"1.4-6")),s(5),C("",e.tokenDelta>=0?"+":"","",b(13,23,e.tokenDelta)),s(3),C(" normal ",n.tokenDeltaLabel(e.inputDelta)," \xB7 cached ",n.tokenDeltaLabel(e.cachedInputDelta)," "),s(),h(e.cacheWriteDelta?16:-1),s(2),k("out ",n.tokenDeltaLabel(e.outputDelta)),s(2),C("",b(21,25,e.aTurns)," / ",b(22,27,e.bTurns)),s(3),y("saving",e.costDelta<0),s(),C(" ",e.costDelta<0?"-":"+","$",_(25,29,n.abs(e.costDelta),"1.4-4")," ")}}function Ie(r,t){if(r&1&&(a(0,"div",18)(1,"div")(2,"span"),c(3),o(),a(4,"strong"),c(5),m(6,"number"),o(),a(7,"p"),c(8),o(),x(9,ve,2,0,"p",19),o(),a(10,"dl")(11,"div")(12,"dt"),c(13,"A"),o(),a(14,"dd"),c(15),m(16,"number"),o()(),a(17,"div")(18,"dt"),c(19,"B"),o(),a(20,"dd"),c(21),m(22,"number"),o()(),a(23,"div")(24,"dt"),c(25,"Tokens"),o(),a(26,"dd"),c(27),m(28,"number"),o()()()(),a(29,"div",20),T(30,ye,6,4,"div",null,ae),o(),a(32,"section",21)(33,"div",22)(34,"h3"),c(35,"What changed"),o()(),a(36,"div",23),T(37,ke,8,4,"article",24,se),o()(),a(39,"section",25)(40,"div",22)(41,"h3"),c(42,"Model movement"),o(),a(43,"p"),c(44,"Pricing row, token buckets, turns, and cost movement."),o()(),a(45,"div",26)(46,"div",27)(47,"span"),c(48,"Model"),o(),a(49,"span"),c(50,"Price row"),o(),a(51,"span"),c(52,"Cost A / B"),o(),a(53,"span"),c(54,"Token movement"),o(),a(55,"span"),c(56,"Model calls A / B"),o(),a(57,"span"),c(58,"Cost delta"),o()(),T(59,Be,26,32,"div",28,ce),o()()),r&2){let e=t,n=u();s(3),f(e.promptMatch?"Same-prompt read":"Manual comparison read"),s(),y("saving",e.costDelta<0),s(),C(" ",e.costDelta<0?"-":"+","$",_(6,11,n.abs(e.costDelta),"1.2-4")," "),s(3),f(e.summary),s(),h(e.promptMatch?-1:9),s(6),k("",_(16,14,n.usageUsd(e.a),"1.2-2")," USD"),s(6),k("",_(22,17,n.usageUsd(e.b),"1.2-2")," USD"),s(6),C("",e.totalTokenDelta>=0?"+":"","",b(28,20,e.totalTokenDelta)),s(3),E(e.metrics),s(7),E(e.drivers),s(22),E(e.modelRows)}}function Te(r,t){r&1&&(a(0,"p",11),c(1,"Pick two different sessions to compare cost and token deltas."),o())}var oe=class r{sessionsInput=B([]);compareAInput=B(null);compareBInput=B(null);baselineQuery=B("");candidateQuery=B("");baselinePickerOpen=B(!1);candidatePickerOpen=B(!1);compareAChange=new z;compareBChange=new z;set sessions(t){this.sessionsInput.set(t??[])}set compareA(t){this.compareAInput.set(t??null)}set compareB(t){this.compareBInput.set(t??null)}sessionOptions=v(()=>this.sessionsInput());selectedAId=v(()=>this.compareAInput()??this.sessionOptions()[0]?.id??null);selectedBId=v(()=>this.compareBInput()??this.sessionOptions()[1]?.id??null);selectedASession=v(()=>this.sessionOptions().find(t=>t.id===this.selectedAId())??null);selectedBSession=v(()=>this.sessionOptions().find(t=>t.id===this.selectedBId())??null);baselineOptions=v(()=>this.filteredSessionOptions(this.baselineQuery(),this.selectedAId()));candidateOptions=v(()=>this.filteredSessionOptions(this.candidateQuery(),this.selectedBId()));abs=Math.abs;pricingFallbackReason=K;promptGroups=v(()=>this.samePromptGroups(this.sessionOptions()));comparison=v(()=>{let t=this.sessionOptions().find(R=>R.id===this.selectedAId()),e=this.sessionOptions().find(R=>R.id===this.selectedBId());if(!t||!e||t.id===e.id)return null;let n=this.sessionComparisonAnalysis(t),i=this.sessionComparisonAnalysis(e),l=i.totalTokens-n.totalTokens,p=w(t),d=w(e),g=d-p,P=i.inputContextUsd-n.inputContextUsd,I=i.outputUsd-n.outputUsd,M=e.traceSummary.toolCalls-t.traceSummary.toolCalls,N=e.traceSummary.modelTurns-t.traceSummary.modelTurns;return{a:t,b:e,aAnalysis:n,bAnalysis:i,promptMatch:$(t.firstPrompt)===$(e.firstPrompt),costDelta:g,totalTokenDelta:l,percent:S(p,d),summary:this.comparisonSummary(g,l,P,I,M,N),metrics:[{label:"Usage",a:p,b:d,delta:g,percent:S(p,d),format:"currency",lowerIsBetter:!0,help:"GitHub source usage when VS Code logged it. Falls back to local token pricing when source usage is unavailable."},{label:"Normal input tokens",a:t.tokens.input,b:e.tokens.input,delta:e.tokens.input-t.tokens.input,percent:S(t.tokens.input,e.tokens.input),format:"number",lowerIsBetter:!0,help:"Prompt/context tokens priced at the normal input rate. Cached input is shown separately when present."},{label:"Cached input tokens",a:t.tokens.cachedInput,b:e.tokens.cachedInput,delta:e.tokens.cachedInput-t.tokens.cachedInput,percent:S(t.tokens.cachedInput,e.tokens.cachedInput),format:"number",lowerIsBetter:!0,help:"Prompt/context tokens VS Code reported as cachedTokens. These are priced with the cached-input rate, not merged into normal input."},{label:"Cache write tokens",a:t.tokens.cacheWrite,b:e.tokens.cacheWrite,delta:e.tokens.cacheWrite-t.tokens.cacheWrite,percent:S(t.tokens.cacheWrite,e.tokens.cacheWrite),format:"number",lowerIsBetter:!0,help:"Cache creation tokens when VS Code exposes a numeric cache-write field. These are priced separately from normal and cached input."},{label:"Output tokens",a:t.tokens.output,b:e.tokens.output,delta:e.tokens.output-t.tokens.output,percent:S(t.tokens.output,e.tokens.output),format:"number",lowerIsBetter:!1,help:"Generated response tokens. More output can be useful, but it still affects cost."},{label:"Model turns",a:t.traceSummary.modelTurns,b:e.traceSummary.modelTurns,delta:N,percent:S(t.traceSummary.modelTurns,e.traceSummary.modelTurns),format:"number",lowerIsBetter:!1,help:"Model request count. More turns often means more accumulated context gets resent."},{label:"Tool calls",a:t.traceSummary.toolCalls,b:e.traceSummary.toolCalls,delta:M,percent:S(t.traceSummary.toolCalls,e.traceSummary.toolCalls),format:"number",lowerIsBetter:!1,help:"Tool activity. Tool results can become later input context."}],drivers:this.comparisonDrivers(n,i,g,P,I,M,N),modelRows:this.compareModelRows(n.modelRows,i.modelRows)}});setCompareA(t){let e=this.selectedAId(),n=this.selectedBId();this.compareAInput.set(t),this.compareAChange.emit(t),t&&t===n&&e&&e!==t&&(this.compareBInput.set(e),this.compareBChange.emit(e)),this.baselineQuery.set(""),this.baselinePickerOpen.set(!1)}setCompareB(t){let e=this.selectedAId(),n=this.selectedBId();this.compareBInput.set(t),this.compareBChange.emit(t),t&&t===e&&n&&n!==t&&(this.compareAInput.set(n),this.compareAChange.emit(n)),this.candidateQuery.set(""),this.candidatePickerOpen.set(!1)}setBaselineQuery(t){this.baselineQuery.set(t),this.baselinePickerOpen.set(!0)}setCandidateQuery(t){this.candidateQuery.set(t),this.candidatePickerOpen.set(!0)}openBaselinePicker(){this.baselinePickerOpen.set(!0)}openCandidatePicker(){this.candidatePickerOpen.set(!0)}closePickerOnFocusOut(t,e){let n=e.relatedTarget;if(!(n instanceof Node&&e.currentTarget instanceof Node&&e.currentTarget.contains(n))){if(t==="baseline"){this.baselinePickerOpen.set(!1);return}this.candidatePickerOpen.set(!1)}}compactDate(t){return new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}).format(new Date(t))}runTokenTotal(t){return G(t)}usageUsd(t){return w(t)}promptRepeatCount(t){let e=$(t.firstPrompt);return e?this.promptGroups().find(n=>n.key===e)?.sessions.length??1:1}isSamePromptAsOther(t,e){let n=e==="baseline"?this.selectedBSession():this.selectedASession(),i=$(t.firstPrompt);return!!(n&&i&&i===$(n.firstPrompt))}tokenDeltaLabel(t){return`${t>=0?"+":""}${t.toLocaleString()}`}filteredSessionOptions(t,e){let n=t.trim().toLowerCase();if(!n)return this.sessionOptions();let i=this.sessionOptions().filter(p=>[p.title,p.firstPrompt,p.model,p.workspace].join(" ").toLowerCase().includes(n)),l=this.sessionOptions().find(p=>p.id===e);return l&&!i.some(p=>p.id===l.id)?[l,...i]:i}sessionComparisonAnalysis(t){let e=t.modelBreakdown.map(i=>X(i,w(t))),n=[...e].sort((i,l)=>l.totalUsd-i.totalUsd)[0]??null;return{session:t,modelRows:e,totalTokens:G(t),inputUsd:e.reduce((i,l)=>i+l.inputUsd,0),inputContextUsd:e.reduce((i,l)=>i+l.inputUsd+l.cachedInputUsd+l.cacheWriteUsd,0),outputUsd:e.reduce((i,l)=>i+l.outputUsd,0),cachedInputUsd:e.reduce((i,l)=>i+l.cachedInputUsd,0),cacheWriteUsd:e.reduce((i,l)=>i+l.cacheWriteUsd,0),topModel:n,modelNames:new Set(e.map(i=>i.model)),pricingRows:new Set(e.map(i=>i.pricingModel))}}samePromptGroups(t){let e=new Map;for(let n of t){let i=$(n.firstPrompt);i&&e.set(i,[...e.get(i)??[],n])}return[...e.entries()].filter(([,n])=>n.length>1).map(([n,i])=>{let l=[...i].sort((p,d)=>w(p)-w(d));return{key:n,sessions:[...i].sort((p,d)=>p.startedAt.localeCompare(d.startedAt)),costRangeUsd:w(l[l.length-1])-w(l[0])}}).sort((n,i)=>i.sessions.length-n.sessions.length||i.costRangeUsd-n.costRangeUsd)}comparisonSummary(t,e,n,i,l,p){let d=t>0?"more expensive":t<0?"cheaper":"about the same cost",g=e>0?"more":e<0?"fewer":"the same number of",P=Math.abs(n)>=Math.abs(i)?"input/context tokens":"generated output tokens",I=Math.abs(p)>=Math.abs(l)?`${Math.abs(p).toLocaleString()} ${p>=0?"more":"fewer"} model turns`:`${Math.abs(l).toLocaleString()} ${l>=0?"more":"fewer"} tool calls`;return t===0&&e===0?"These runs look equivalent on imported cost and token totals. Check logs if behavior differed qualitatively.":`Run B is ${d}, with ${Math.abs(e).toLocaleString()} ${g} imported tokens. The largest priced movement is ${P}; activity changed by ${I}.`}comparisonDrivers(t,e,n,i,l,p,d){let g=j(t.modelNames,e.modelNames)||j(t.pricingRows,e.pricingRows),P=t.topModel?.pricingModel!==e.topModel?.pricingModel;return[{title:"Cost movement",value:n>0?"Higher":n<0?"Lower":"Flat",tone:n>0?"high":n<0?"info":"medium",detail:n===0?"The imported estimate did not materially change between these two runs.":`Run B moved by ${n>0?"+":"-"}$${Math.abs(n).toFixed(4)}. Cheaper is only better if the run still did the job.`},{title:"Priced token driver",value:Math.abs(i)>=Math.abs(l)?"Input":"Output",tone:Math.abs(i)>=Math.abs(l)?"high":"medium",detail:Math.abs(i)>=Math.abs(l)?`Input/context cost moved by ${i>=0?"+":"-"}$${Math.abs(i).toFixed(4)} across normal input, cached input, and cache-write buckets. This is usually repo context, prior chat, or tool results.`:`Output cost moved by ${l>=0?"+":"-"}$${Math.abs(l).toFixed(4)}. The later run generated more or less text.`},{title:"Model pricing",value:g?"Changed":"Same",tone:g||P?"medium":"info",detail:g?`The model or pricing-row mix changed. A: ${[...t.pricingRows].join(", ")}. B: ${[...e.pricingRows].join(", ")}.`:`Both runs used the same imported pricing row mix: ${[...e.pricingRows].join(", ")}.`},{title:"Agent activity",value:`${d>=0?"+":""}${d} turns`,tone:d>3||p>10?"medium":"info",detail:`Run B has ${Math.abs(d)} ${d>=0?"more":"fewer"} model turns and ${Math.abs(p)} ${p>=0?"more":"fewer"} tool calls.`}]}compareModelRows(t,e){return[...new Set([...t,...e].map(i=>`${i.model}::${i.pricingModel}`))].map(i=>{let[l,p]=i.split("::"),d=t.find(M=>M.model===l&&M.pricingModel===p),g=e.find(M=>M.model===l&&M.pricingModel===p),P=d?L(d.tokens):0,I=g?L(g.tokens):0;return{model:l,pricingModel:p,usesFallbackPrice:Y(l,p),aCost:d?.totalUsd??0,bCost:g?.totalUsd??0,costDelta:(g?.totalUsd??0)-(d?.totalUsd??0),aTokens:P,bTokens:I,tokenDelta:I-P,inputDelta:(g?.tokens.input??0)-(d?.tokens.input??0),cachedInputDelta:(g?.tokens.cachedInput??0)-(d?.tokens.cachedInput??0),cacheWriteDelta:(g?.tokens.cacheWrite??0)-(d?.tokens.cacheWrite??0),outputDelta:(g?.tokens.output??0)-(d?.tokens.output??0),aTurns:d?.turns??0,bTurns:g?.turns??0}}).sort((i,l)=>Math.abs(l.costDelta)-Math.abs(i.costDelta))}static \u0275fac=function(e){return new(e||r)};static \u0275cmp=q({type:r,selectors:[["app-compare-page"]],inputs:{sessions:"sessions",compareA:"compareA",compareB:"compareB"},outputs:{compareAChange:"compareAChange",compareBChange:"compareBChange"},decls:24,vars:11,consts:[[1,"compare"],[1,"compare-header"],[1,"eyebrow"],[1,"selectors"],[1,"run-picker",3,"focusout"],["type","button","aria-label","Open baseline run picker",1,"selected-run"],["type","search","placeholder","Search baseline runs","aria-label","Search baseline runs",3,"ngModelChange","focus","ngModel"],["role","listbox","aria-label","Baseline run results",1,"selector-results"],["type","button","aria-label","Open candidate run picker",1,"selected-run"],["type","search","placeholder","Search candidate runs","aria-label","Search candidate runs",3,"ngModelChange","focus","ngModel"],["role","listbox","aria-label","Candidate run results",1,"selector-results"],[1,"empty"],["type","button","aria-label","Open baseline run picker",1,"selected-run",3,"click"],["type","button","role","option",3,"active","same-prompt"],["type","button","role","option",3,"click"],[1,"match-chip"],[1,"match-chip","muted-chip"],["type","button","aria-label","Open candidate run picker",1,"selected-run",3,"click"],[1,"compare-readout"],[1,"compare-caveat"],[1,"comparison-grid","advanced"],[1,"comparison-section","comparison-drivers"],[1,"section-heading"],[1,"driver-list"],[3,"ngClass"],[1,"comparison-section","comparison-models"],[1,"cost-table","compact-table"],[1,"cost-row","cost-row-heading"],[1,"cost-row"],[3,"text","label"],[1,"warning-text"],[1,"token-movement"],["label","Explain fallback pricing",3,"text"]],template:function(e,n){if(e&1&&(a(0,"section",0)(1,"div",1)(2,"div")(3,"p",2),c(4,"Evaluation"),o(),a(5,"h2"),c(6,"Compare runs"),o(),a(7,"p"),c(8,"Pick a baseline and a candidate run. The page explains what changed in cost, tokens, activity, and model mix."),o()(),a(9,"div",3)(10,"div",4),O("focusout",function(l){return n.closePickerOnFocusOut("baseline",l)}),a(11,"span"),c(12,"Baseline A"),o(),x(13,le,6,6,"button",5),a(14,"input",6),O("ngModelChange",function(l){return n.setBaselineQuery(l)})("focus",function(){return n.openBaselinePicker()}),o(),x(15,ge,4,1,"div",7),o(),a(16,"div",4),O("focusout",function(l){return n.closePickerOnFocusOut("candidate",l)}),a(17,"span"),c(18,"Candidate B"),o(),x(19,Ce,6,6,"button",8),a(20,"input",9),O("ngModelChange",function(l){return n.setCandidateQuery(l)})("focus",function(){return n.openCandidatePicker()}),o(),x(21,fe,4,1,"div",10),o()()(),x(22,Ie,61,22)(23,Te,2,0,"p",11),o()),e&2){let i,l,p;s(10),y("open",n.baselinePickerOpen()),s(3),h((i=n.selectedASession())?13:-1,i),s(),A("ngModel",n.baselineQuery()),s(),h(n.baselinePickerOpen()?15:-1),s(),y("open",n.candidatePickerOpen()),s(3),h((l=n.selectedBSession())?19:-1,l),s(),A("ngModel",n.candidateQuery()),s(),h(n.candidatePickerOpen()?21:-1),s(),h((p=n.comparison())?22:23,p)}},dependencies:[ie,ee,te,ne,Z,H,J],styles:["[_nghost-%COMP%]{display:block}.compare[_ngcontent-%COMP%]{display:grid;gap:10px;border:1px solid var(--line);border-radius:16px;padding:16px;background:linear-gradient(180deg,#6f5cff09,#0c9f8305),var(--surface);box-shadow:var(--shadow-soft, 0 16px 38px rgba(15, 23, 42, .1))}.compare-header[_ngcontent-%COMP%]{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}.compare[_ngcontent-%COMP%] h2[_ngcontent-%COMP%]{margin:4px 0 0;color:var(--text-strong);font-size:22px;font-weight:760;letter-spacing:0}.compare-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%]:not(.eyebrow){max-width:620px;margin:6px 0 0;color:var(--muted);font-size:12px;line-height:1.45}.eyebrow[_ngcontent-%COMP%]{margin:0;color:var(--accent-2);font-size:10px;font-weight:760;letter-spacing:.08em;text-transform:uppercase}.selectors[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(2,minmax(260px,360px));gap:12px;min-width:min(760px,62vw)}.run-picker[_ngcontent-%COMP%]{position:relative;display:grid;gap:6px;min-width:0}.run-picker[_ngcontent-%COMP%] > span[_ngcontent-%COMP%]{color:var(--muted);font-size:11px;font-weight:760}.selectors[_ngcontent-%COMP%] input[_ngcontent-%COMP%], .selected-run[_ngcontent-%COMP%]{width:100%;border:1px solid var(--line);border-radius:10px;padding:9px 11px;background:var(--control-bg, var(--surface-soft));color:var(--text);font:inherit;font-size:12px}.selected-run[_ngcontent-%COMP%]{display:grid;gap:3px;min-height:50px;text-align:left;cursor:pointer}.selected-run[_ngcontent-%COMP%]:hover, .run-picker.open[_ngcontent-%COMP%] .selected-run[_ngcontent-%COMP%]{border-color:#1fd1a573;box-shadow:0 0 0 3px #1fd1a514}.selected-run[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .selected-run[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.selected-run[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong);font-size:12px;font-weight:760}.selected-run[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{color:var(--muted);font-size:11px;font-style:normal}.selectors[_ngcontent-%COMP%] input[_ngcontent-%COMP%]{min-height:34px;border-color:#637d9438;background:color-mix(in srgb,var(--surface-soft) 78%,transparent)}.selectors[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder{color:var(--muted-2)}.selector-results[_ngcontent-%COMP%]{position:absolute;z-index:20;top:calc(100% + 6px);left:0;right:0;display:grid;gap:6px;max-height:min(320px,46vh);overflow:auto;border:1px solid var(--line);border-radius:11px;padding:6px;background:var(--surface);box-shadow:0 18px 42px #0f172a29}.selector-results[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{display:grid;gap:2px;width:100%;border:1px solid transparent;border-radius:9px;padding:8px 9px;background:transparent;color:var(--text);font:inherit;text-align:left;cursor:pointer}.selector-results[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:hover, .selector-results[_ngcontent-%COMP%] button.active[_ngcontent-%COMP%]{border-color:#1fd1a559;background:#1fd1a514}.selector-results[_ngcontent-%COMP%] button.same-prompt[_ngcontent-%COMP%]{border-color:#6f5cff61;background:linear-gradient(135deg,#6f5cff17,#1fd1a50e),transparent}.selector-results[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{overflow:hidden;color:var(--text-strong);font-size:12px;font-weight:760;text-overflow:ellipsis;white-space:nowrap}.selector-results[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .selector-results[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{overflow:hidden;color:var(--muted);font-size:11px;font-style:normal;text-overflow:ellipsis;white-space:nowrap}.match-chip[_ngcontent-%COMP%]{display:inline-flex;align-items:center;width:fit-content;max-width:100%;border:1px solid rgba(111,92,255,.28);border-radius:999px;padding:2px 7px;background:#6f5cff17;color:var(--text-strong)!important;font-size:10px!important;font-weight:760;line-height:1.2}.match-chip.muted-chip[_ngcontent-%COMP%]{border-color:var(--line);background:color-mix(in srgb,var(--surface-soft) 72%,transparent);color:var(--muted)!important}.compare-readout[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:stretch;border:1px solid rgba(12,159,131,.2);border-radius:13px;padding:12px;background:radial-gradient(circle at 100% 0%,rgba(111,92,255,.11),transparent 34%),linear-gradient(135deg,#0c9f8313,#6f5cff09),var(--surface)}.compare-readout[_ngcontent-%COMP%] > div[_ngcontent-%COMP%]{border-left:4px solid var(--accent-2);padding-left:12px}.compare-readout[_ngcontent-%COMP%] dl[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(3,minmax(86px,1fr));gap:8px;align-self:center;margin:0}.compare-readout[_ngcontent-%COMP%] dl[_ngcontent-%COMP%] div[_ngcontent-%COMP%]{display:grid;gap:4px;border:1px solid var(--line);border-radius:11px;padding:9px;background:var(--surface-soft)}.compare-readout[_ngcontent-%COMP%] dt[_ngcontent-%COMP%]{color:var(--muted-2);font-size:10px;font-weight:760;letter-spacing:.08em;text-transform:uppercase}.compare-readout[_ngcontent-%COMP%] dd[_ngcontent-%COMP%]{margin:0;color:var(--text-strong);font-size:14px;font-weight:760;white-space:nowrap}.compare-readout[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{display:block;margin-bottom:3px;color:var(--muted);font-size:11px;font-weight:760;letter-spacing:.08em;text-transform:uppercase}.compare-readout[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong);font-size:22px;font-weight:760}.compare-readout[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{max-width:920px;margin:5px 0 0;color:var(--muted);font-size:12px;line-height:1.45}.compare-caveat[_ngcontent-%COMP%]{color:var(--warning-text, #ffcf75)!important}.comparison-grid[_ngcontent-%COMP%]{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:7px}.comparison-grid[_ngcontent-%COMP%] > div[_ngcontent-%COMP%]{display:grid;gap:3px;border:1px solid var(--line);border-radius:10px;padding:8px 9px;background:var(--surface-soft)}.comparison-grid[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .comparison-grid[_ngcontent-%COMP%] em[_ngcontent-%COMP%], .cost-row[_ngcontent-%COMP%] span[_ngcontent-%COMP%], .cost-row[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{color:var(--muted);font-size:12px;font-style:normal}.comparison-grid[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong);font-size:15px;font-weight:760;letter-spacing:0}.comparison-section[_ngcontent-%COMP%]{display:grid;gap:8px}.section-heading[_ngcontent-%COMP%]{display:flex;align-items:end;justify-content:space-between;gap:14px}.section-heading[_ngcontent-%COMP%] h3[_ngcontent-%COMP%]{margin:0;color:var(--text-strong);font-size:15px;font-weight:760}.section-heading[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:0;color:var(--muted);font-size:12px}.driver-list[_ngcontent-%COMP%]{display:grid;gap:6px}.driver-list[_ngcontent-%COMP%] article[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(155px,.34fr) minmax(0,1fr);gap:10px;align-items:start;border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:10px;padding:8px 10px;background:color-mix(in srgb,var(--surface-soft) 58%,transparent)}.driver-list[_ngcontent-%COMP%] article.medium[_ngcontent-%COMP%]{border-left-color:var(--warning)}.driver-list[_ngcontent-%COMP%] article.high[_ngcontent-%COMP%]{border-left-color:var(--danger)}.driver-list[_ngcontent-%COMP%] article[_ngcontent-%COMP%] > div[_ngcontent-%COMP%]{display:grid;gap:2px;min-width:0}.driver-list[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{color:var(--muted-2);font-size:10px;font-weight:760;letter-spacing:.08em;text-transform:uppercase}.driver-list[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong);font-size:14px;font-weight:760;line-height:1.1;overflow-wrap:anywhere}.driver-list[_ngcontent-%COMP%] p[_ngcontent-%COMP%]{margin:0;color:var(--text);font-size:12px;line-height:1.35}.cost-table[_ngcontent-%COMP%]{display:grid;overflow:auto hidden;border:1px solid var(--line);border-radius:12px;background:var(--surface)}.cost-row[_ngcontent-%COMP%]{display:grid;grid-template-columns:minmax(140px,1.05fr) minmax(110px,.82fr) minmax(128px,.95fr) minmax(190px,1.25fr) minmax(96px,.7fr) minmax(74px,.5fr);gap:8px;align-items:start;min-width:760px;border-bottom:1px solid var(--line);padding:8px 9px}.cost-row[_ngcontent-%COMP%]:last-child{border-bottom:0}.cost-row-heading[_ngcontent-%COMP%]{background:var(--surface-soft);font-size:11px;font-weight:720;text-transform:uppercase}.cost-row[_ngcontent-%COMP%] strong[_ngcontent-%COMP%], .cost-row[_ngcontent-%COMP%] span[_ngcontent-%COMP%]{display:grid;gap:3px}.cost-row[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{color:var(--text-strong)}.cost-row[_ngcontent-%COMP%] .token-movement[_ngcontent-%COMP%]{gap:4px}.cost-row[_ngcontent-%COMP%] .token-movement[_ngcontent-%COMP%] strong[_ngcontent-%COMP%]{display:block;color:var(--text-strong);font-size:12px}.cost-row[_ngcontent-%COMP%] .token-movement[_ngcontent-%COMP%] em[_ngcontent-%COMP%]{line-height:1.35}.saving[_ngcontent-%COMP%]{color:var(--success-text, #35d07f)!important}.warning-text[_ngcontent-%COMP%]{color:var(--warning-text, #ffcf75)!important;font-weight:900}.empty[_ngcontent-%COMP%]{margin:0;color:var(--muted)}@media(max-width:900px){.compare-header[_ngcontent-%COMP%], .compare-readout[_ngcontent-%COMP%], .section-heading[_ngcontent-%COMP%]{display:grid}.comparison-grid[_ngcontent-%COMP%], .driver-list[_ngcontent-%COMP%] article[_ngcontent-%COMP%], .selectors[_ngcontent-%COMP%], .compare-readout[_ngcontent-%COMP%] dl[_ngcontent-%COMP%], .cost-row[_ngcontent-%COMP%]{grid-template-columns:1fr}.cost-row[_ngcontent-%COMP%], .selectors[_ngcontent-%COMP%]{min-width:0}}"]})};function $(r){return String(r??"").toLowerCase().replace(/[^\p{L}\p{N}#/@._-]+/gu," ").replace(/\s+/g," ").trim()}export{oe as ComparePageComponent};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en" data-beasties-container>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Copilot Usage Studio</title>
|
|
6
|
+
<base href="/">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
<link rel="icon" type="image/svg+xml" href="usage-studio.svg">
|
|
9
|
+
<style>*{box-sizing:border-box}html,body{margin:0;min-height:100%;font-family:Aptos,Segoe UI Variable,Segoe UI,Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,sans-serif;font-size:14px;line-height:1.45;background:#090d14;color:#d7dde7;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}</style><link rel="stylesheet" href="styles-GZOQ5QIH.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-GZOQ5QIH.css"></noscript></head>
|
|
10
|
+
<body>
|
|
11
|
+
<app-root></app-root>
|
|
12
|
+
<link rel="modulepreload" href="chunk-F6TIG2GE.js"><script src="main-C6XOJRSH.js" type="module"></script></body>
|
|
13
|
+
</html>
|