add ai pages, cc usage
This commit is contained in:
parent
2f5b86111c
commit
7a9f907661
11 changed files with 1204 additions and 1 deletions
337
app/ai/claude/page.tsx
Normal file
337
app/ai/claude/page.tsx
Normal file
|
@ -0,0 +1,337 @@
|
|||
"use client"
|
||||
|
||||
import Header from '@/components/Header'
|
||||
import Footer from '@/components/Footer'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { SiClaude } from 'react-icons/si'
|
||||
import {
|
||||
Line,
|
||||
BarChart,
|
||||
Bar,
|
||||
PieChart,
|
||||
Pie,
|
||||
Cell,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
Legend,
|
||||
ResponsiveContainer,
|
||||
Area,
|
||||
AreaChart,
|
||||
ComposedChart,
|
||||
} from 'recharts'
|
||||
|
||||
interface ModelBreakdown {
|
||||
modelName: string
|
||||
inputTokens: number
|
||||
outputTokens: number
|
||||
cacheCreationTokens: number
|
||||
cacheReadTokens: number
|
||||
cost: number
|
||||
}
|
||||
|
||||
interface DailyData {
|
||||
date: string
|
||||
inputTokens: number
|
||||
outputTokens: number
|
||||
cacheCreationTokens: number
|
||||
cacheReadTokens: number
|
||||
totalTokens: number
|
||||
totalCost: number
|
||||
modelsUsed: string[]
|
||||
modelBreakdowns: ModelBreakdown[]
|
||||
}
|
||||
|
||||
interface CCData {
|
||||
daily: DailyData[]
|
||||
totals: {
|
||||
inputTokens: number
|
||||
outputTokens: number
|
||||
cacheCreationTokens: number
|
||||
cacheReadTokens: number
|
||||
totalCost: number
|
||||
totalTokens: number
|
||||
}
|
||||
}
|
||||
|
||||
const COLORS = ['#c15f3c', '#b1ada1', '#f4f3ee', '#c15f3c', '#b1ada1', '#f4f3ee']
|
||||
|
||||
export default function AI() {
|
||||
const [data, setData] = useState<CCData | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [selectedMetric, setSelectedMetric] = useState<'cost' | 'tokens'>('cost')
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/data/cc.json')
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error('Failed to fetch data')
|
||||
return res.json()
|
||||
})
|
||||
.then(data => {
|
||||
setData(data)
|
||||
setLoading(false)
|
||||
})
|
||||
.catch(err => {
|
||||
setError(err.message)
|
||||
setLoading(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<Header />
|
||||
<main className="flex-1 flex items-center justify-center">
|
||||
<div className="text-gray-300">Loading Claude metrics...</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (error || !data) {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<Header />
|
||||
<main className="flex-1 flex items-center justify-center">
|
||||
<div className="text-red-400">Error loading data: {error}</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const modelUsageData = data.daily.reduce((acc, day) => {
|
||||
day.modelBreakdowns.forEach(model => {
|
||||
const existing = acc.find(m => m.name === model.modelName)
|
||||
if (existing) {
|
||||
existing.value += model.cost
|
||||
} else {
|
||||
acc.push({ name: model.modelName, value: model.cost })
|
||||
}
|
||||
})
|
||||
return acc
|
||||
}, [] as { name: string; value: number }[])
|
||||
|
||||
const tokenTypeData = [
|
||||
{ name: 'Input', value: data.totals.inputTokens },
|
||||
{ name: 'Output', value: data.totals.outputTokens },
|
||||
{ name: 'Cache Creation', value: data.totals.cacheCreationTokens },
|
||||
{ name: 'Cache Read', value: data.totals.cacheReadTokens },
|
||||
]
|
||||
|
||||
const dailyTrendData = data.daily.map(day => ({
|
||||
date: new Date(day.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),
|
||||
cost: day.totalCost,
|
||||
tokens: day.totalTokens / 1000000,
|
||||
inputTokens: day.inputTokens / 1000,
|
||||
outputTokens: day.outputTokens / 1000,
|
||||
cacheTokens: (day.cacheCreationTokens + day.cacheReadTokens) / 1000000,
|
||||
}))
|
||||
|
||||
const formatCurrency = (value: number) => `$${value.toFixed(2)}`
|
||||
const formatTokens = (value: number) => `${value.toFixed(1)}M`
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<Header />
|
||||
<main className="w-full">
|
||||
<div className="my-12 text-center">
|
||||
<div className="flex justify-center mb-6">
|
||||
<SiClaude size={60} />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold mb-2 text-gray-100 glow">Claude Code Usage</h1>
|
||||
<p className="text-gray-400">How much I use Claude Code!</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 px-4">
|
||||
<div className="p-6 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h3 className="text-sm font-medium text-gray-400 mb-2">Total Cost</h3>
|
||||
<p className="text-3xl font-bold text-[#c15f3c]">${data.totals.totalCost.toFixed(2)}</p>
|
||||
</div>
|
||||
<div className="p-6 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h3 className="text-sm font-medium text-gray-400 mb-2">Total Tokens</h3>
|
||||
<p className="text-3xl font-bold text-[#c15f3c]">{(data.totals.totalTokens / 1000000).toFixed(1)}M</p>
|
||||
</div>
|
||||
<div className="p-6 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h3 className="text-sm font-medium text-gray-400 mb-2">Days Active</h3>
|
||||
<p className="text-3xl font-bold text-[#c15f3c]">{data.daily.length}</p>
|
||||
</div>
|
||||
<div className="p-6 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h3 className="text-sm font-medium text-gray-400 mb-2">Avg Daily Cost</h3>
|
||||
<p className="text-3xl font-bold text-[#c15f3c]">${(data.totals.totalCost / data.daily.length).toFixed(2)}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 p-4">
|
||||
<section className="p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">Daily Usage Trend</h2>
|
||||
<div className="flex gap-2 mb-4">
|
||||
<button
|
||||
onClick={() => setSelectedMetric('cost')}
|
||||
className={`px-3 py-1 rounded ${selectedMetric === 'cost' ? 'bg-[#c15f3c] text-white' : 'bg-gray-700 text-gray-300'}`}
|
||||
>
|
||||
Cost
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedMetric('tokens')}
|
||||
className={`px-3 py-1 rounded ${selectedMetric === 'tokens' ? 'bg-[#c15f3c] text-white' : 'bg-gray-700 text-gray-300'}`}
|
||||
>
|
||||
Tokens
|
||||
</button>
|
||||
</div>
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<AreaChart data={dailyTrendData}>
|
||||
<CartesianGrid strokeDasharray="3 3" stroke="#374151" />
|
||||
<XAxis dataKey="date" stroke="#9ca3af" />
|
||||
<YAxis
|
||||
stroke="#9ca3af"
|
||||
tickFormatter={selectedMetric === 'cost' ? formatCurrency : formatTokens}
|
||||
/>
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: '#1f2937', border: '1px solid #374151' }}
|
||||
formatter={(value: number) => selectedMetric === 'cost' ? formatCurrency(value) : formatTokens(value)}
|
||||
/>
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey={selectedMetric === 'cost' ? 'cost' : 'tokens'}
|
||||
stroke="#c15f3c"
|
||||
fill="#c15f3c"
|
||||
fillOpacity={0.3}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</section>
|
||||
|
||||
<section className="p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">Model Usage Distribution</h2>
|
||||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-4">
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={modelUsageData}
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
innerRadius={60}
|
||||
outerRadius={100}
|
||||
fill="#8884d8"
|
||||
paddingAngle={2}
|
||||
dataKey="value"
|
||||
>
|
||||
{modelUsageData.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: '#1f2937', border: '1px solid #374151', borderRadius: '8px' }}
|
||||
formatter={(value: number) => formatCurrency(value)}
|
||||
/>
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
<div className="flex flex-col justify-center space-y-3">
|
||||
{modelUsageData.map((model, index) => {
|
||||
const percentage = ((model.value / data.totals.totalCost) * 100).toFixed(1)
|
||||
return (
|
||||
<div key={index} className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className="w-3 h-3 rounded-full"
|
||||
style={{ backgroundColor: COLORS[index % COLORS.length] }}
|
||||
/>
|
||||
<span className="text-gray-300 font-medium text-xs">{model.name}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-gray-400 text-sm">{percentage}%</span>
|
||||
<span className="text-gray-200 font-semibold">${model.value.toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<div className="pt-3 mt-3 border-t border-gray-700">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-400">Total Models Used</span>
|
||||
<span className="text-gray-200 font-bold">{modelUsageData.length}</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center mt-2">
|
||||
<span className="text-gray-400">Most Used</span>
|
||||
<span className="text-gray-200 font-bold text-xs">
|
||||
{modelUsageData[0]?.name}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">Token Type Breakdown</h2>
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<BarChart data={tokenTypeData}>
|
||||
<CartesianGrid strokeDasharray="3 3" stroke="#374151" />
|
||||
<XAxis dataKey="name" stroke="#9ca3af" />
|
||||
<YAxis stroke="#9ca3af" tickFormatter={(value) => `${(value / 1000000).toFixed(0)}M`} />
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: '#1f2937', border: '1px solid #374151' }}
|
||||
formatter={(value: number) => `${(value / 1000000).toFixed(2)}M tokens`}
|
||||
/>
|
||||
<Bar dataKey="value" fill="#b1ada1" />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</section>
|
||||
|
||||
<section className="p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">Daily Token Composition</h2>
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<ComposedChart data={dailyTrendData}>
|
||||
<CartesianGrid strokeDasharray="3 3" stroke="#374151" />
|
||||
<XAxis dataKey="date" stroke="#9ca3af" />
|
||||
<YAxis stroke="#9ca3af" tickFormatter={(value) => `${value}K`} />
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: '#1f2937', border: '1px solid #374151' }}
|
||||
formatter={(value: number) => `${value.toFixed(1)}K tokens`}
|
||||
/>
|
||||
<Legend />
|
||||
<Bar dataKey="inputTokens" stackId="a" fill="#c15f3c" name="Input (K)" />
|
||||
<Bar dataKey="outputTokens" stackId="a" fill="#b1ada1" name="Output (K)" />
|
||||
<Line type="monotone" dataKey="cacheTokens" stroke="#f4f3ee" name="Cache (M)" strokeWidth={2} />
|
||||
</ComposedChart>
|
||||
</ResponsiveContainer>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div className="px-4 pb-4">
|
||||
<section className="p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">Recent Sessions</h2>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-left">
|
||||
<thead>
|
||||
<tr className="border-b border-gray-700">
|
||||
<th className="py-2 px-4 text-gray-400">Date</th>
|
||||
<th className="py-2 px-4 text-gray-400">Models Used</th>
|
||||
<th className="py-2 px-4 text-gray-400">Total Tokens</th>
|
||||
<th className="py-2 px-4 text-gray-400">Cost</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.daily.slice(-5).reverse().map((day, index) => (
|
||||
<tr key={index} className="border-b border-gray-800 hover:bg-gray-800/50">
|
||||
<td className="py-2 px-4 text-gray-300">{new Date(day.date).toLocaleDateString()}</td>
|
||||
<td className="py-2 px-4 text-gray-300">
|
||||
{day.modelsUsed.join(', ')}
|
||||
</td>
|
||||
<td className="py-2 px-4 text-gray-300">{(day.totalTokens / 1000000).toFixed(2)}M</td>
|
||||
<td className="py-2 px-4 text-[#c15f3c] font-semibold">${day.totalCost.toFixed(2)}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
73
app/ai/components/AIStack.tsx
Normal file
73
app/ai/components/AIStack.tsx
Normal file
|
@ -0,0 +1,73 @@
|
|||
import { Bot } from 'lucide-react'
|
||||
import Link from '@/components/objects/Link'
|
||||
import type { AITool } from '../types'
|
||||
|
||||
interface AIStackProps {
|
||||
tools: AITool[]
|
||||
}
|
||||
|
||||
export default function AIStack({ tools }: AIStackProps) {
|
||||
const getStatusColor = (status: string) => {
|
||||
switch(status) {
|
||||
case 'primary': return 'text-green-400 border-green-400 bg-green-400/10'
|
||||
case 'active': return 'text-blue-400 border-blue-400 bg-blue-400/10'
|
||||
case 'occasional': return 'text-yellow-400 border-yellow-400 bg-yellow-400/10'
|
||||
default: return 'text-gray-400 border-gray-400'
|
||||
}
|
||||
}
|
||||
|
||||
const getStatusLabel = (status: string) => {
|
||||
switch(status) {
|
||||
case 'primary': return 'Primary'
|
||||
case 'active': return 'Active Use'
|
||||
case 'occasional': return 'Occasional Use'
|
||||
default: return status
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h2 className="text-2xl font-semibold mb-6 text-gray-200 flex items-center gap-2">
|
||||
<Bot size={24} />
|
||||
My AI Stack
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{tools.map((tool, index) => (
|
||||
<div key={index} className="p-4 border border-gray-700 rounded-lg hover:border-gray-500 transition-all duration-300 flex flex-col">
|
||||
<div className="flex items-start justify-between mb-3 flex-1">
|
||||
<div className="flex items-center gap-3">
|
||||
{tool.icon && <tool.icon className="text-2xl text-gray-300" />}
|
||||
{tool.svg && (
|
||||
<div className="w-6 h-6 text-gray-300 fill-current">
|
||||
{tool.svg}
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-200">{tool.name}</h3>
|
||||
<p className="text-sm text-gray-400">{tool.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between mt-auto">
|
||||
<span className={`text-xs px-2 py-1 rounded-full border ${getStatusColor(tool.status)}`}>
|
||||
{getStatusLabel(tool.status)}
|
||||
</span>
|
||||
<span className="flex flex-row items-center gap-4">
|
||||
{tool.link && (
|
||||
<Link href={tool.link} className="text-blue-400 hover:text-blue-300 text-sm">
|
||||
View →
|
||||
</Link>
|
||||
)}
|
||||
{tool.usage && (
|
||||
<Link href={tool.usage} className="text-blue-400 hover:text-blue-300 text-sm">
|
||||
Usage →
|
||||
</Link>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
39
app/ai/components/FavoriteModels.tsx
Normal file
39
app/ai/components/FavoriteModels.tsx
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { Star } from 'lucide-react'
|
||||
import type { FavoriteModel } from '../types'
|
||||
|
||||
interface FavoriteModelsProps {
|
||||
models: FavoriteModel[]
|
||||
}
|
||||
|
||||
export default function FavoriteModels({ models }: FavoriteModelsProps) {
|
||||
return (
|
||||
<section className="p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h2 className="text-2xl font-semibold mb-6 text-gray-200 flex items-center gap-2">
|
||||
<Star size={24} />
|
||||
Favorite Models
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
{models.map((model, index) => (
|
||||
<div key={index} className="p-4 bg-gray-800/50 rounded-lg">
|
||||
<div className="flex justify-between items-start mb-2">
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-200">{model.name}</h3>
|
||||
<p className="text-sm text-gray-400">{model.provider}</p>
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<Star
|
||||
key={i}
|
||||
size={14}
|
||||
className={i < model.rating ? 'fill-yellow-400 text-yellow-400' : 'text-gray-600'}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-gray-300">{model.review}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
54
app/ai/components/ToolReviews.tsx
Normal file
54
app/ai/components/ToolReviews.tsx
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { MessageSquare, Star } from 'lucide-react'
|
||||
import type { AIReview } from '../types'
|
||||
|
||||
interface ToolReviewsProps {
|
||||
reviews: AIReview[]
|
||||
}
|
||||
|
||||
export default function ToolReviews({ reviews }: ToolReviewsProps) {
|
||||
return (
|
||||
<section className="p-8 border-2 border-gray-700 rounded-lg hover:border-gray-600 transition-colors duration-300">
|
||||
<h2 className="text-2xl font-semibold mb-6 text-gray-200 flex items-center gap-2">
|
||||
<MessageSquare size={24} />
|
||||
Tool Reviews
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
{reviews.map((review, index) => (
|
||||
<div key={index} className="p-4 bg-gray-800/50 rounded-lg">
|
||||
<div className="flex justify-between items-center mb-3">
|
||||
<h3 className="font-semibold text-gray-200">{review.tool}</h3>
|
||||
<div className="flex gap-1">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<Star
|
||||
key={i}
|
||||
size={14}
|
||||
className={i < review.rating ? 'fill-yellow-400 text-yellow-400' : 'text-gray-600'}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2 mb-2 text-sm">
|
||||
<div>
|
||||
<p className="text-green-400 font-medium mb-1">Pros:</p>
|
||||
<ul className="text-gray-300 space-y-1">
|
||||
{review.pros.map((pro, i) => (
|
||||
<li key={i} className="text-xs">• {pro}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-red-400 font-medium mb-1">Cons:</p>
|
||||
<ul className="text-gray-300 space-y-1">
|
||||
{review.cons.map((con, i) => (
|
||||
<li key={i} className="text-xs">• {con}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-blue-400 font-medium">{review.verdict}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
49
app/ai/components/TopPick.tsx
Normal file
49
app/ai/components/TopPick.tsx
Normal file
|
@ -0,0 +1,49 @@
|
|||
import { Trophy, ChevronRight } from 'lucide-react'
|
||||
import { SiClaude } from 'react-icons/si'
|
||||
import Link from '@/components/objects/Link'
|
||||
|
||||
export default function TopPick() {
|
||||
return (
|
||||
<div className="px-4 mb-4">
|
||||
<h2 className="text-4xl font-semibold mb-6 text-gray-200 flex items-center gap-2">
|
||||
<Trophy size={32} />
|
||||
Top Pick of 2025
|
||||
</h2>
|
||||
<div className="p-8 border-2 border-[#c15f3c] rounded-lg bg-orange-500/5">
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<SiClaude className="text-6xl text-[#c15f3c]" />
|
||||
<div>
|
||||
<h3 className="text-3xl font-bold text-gray-100">Claude</h3>
|
||||
<p className="text-gray-400">by Anthropic</p>
|
||||
<div className="flex items-center gap-2 mt-2">
|
||||
<Link href="/ai/claude" className="text-blue-400 hover:text-blue-300 flex items-center gap-1">
|
||||
View My Usage <ChevronRight size={16} />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<p className="text-gray-300">
|
||||
Claude has become my go-to AI assistant for coding, writing, and learning very quickly.
|
||||
I believe their Max 5x ($100/mo) is the best value for budget-conscious consumers like myself.
|
||||
</p>
|
||||
<div className='flex flex-col items-center gap-y-6 sm:flex-row sm:justify-between'>
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<span className="px-2 py-1 bg-gray-700 rounded text-xs text-gray-300">Claude Code</span>
|
||||
<span className="px-2 py-1 bg-gray-700 rounded text-xs text-gray-300">Best Tool Calling</span>
|
||||
<span className="px-2 py-1 bg-gray-700 rounded text-xs text-gray-300">High Value in Max Plan</span>
|
||||
<span className="px-2 py-1 bg-gray-700 rounded text-xs text-gray-300">Quite Fast Interface</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-end">
|
||||
<span className="px-3 py-1 bg-[#c15f3c]/20 text-[#c15f3c] rounded-full text-sm font-medium">
|
||||
Top Overall Pick
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
125
app/ai/data.tsx
Normal file
125
app/ai/data.tsx
Normal file
|
@ -0,0 +1,125 @@
|
|||
import {
|
||||
SiClaude,
|
||||
SiGithubcopilot,
|
||||
SiGooglegemini
|
||||
} from 'react-icons/si'
|
||||
import type { AITool, FavoriteModel, AIReview } from './types'
|
||||
|
||||
export const aiTools: AITool[] = [
|
||||
{
|
||||
name: "Claude Max 5x",
|
||||
icon: SiClaude,
|
||||
description: "My favorite model provider for general use and coding",
|
||||
status: "primary",
|
||||
usage: "/ai/claude",
|
||||
link: "https://claude.ai/"
|
||||
},
|
||||
{
|
||||
name: "GitHub Copilot Pro",
|
||||
icon: SiGithubcopilot,
|
||||
description: "Random edits when I don't want to start a Claude session",
|
||||
status: "active",
|
||||
link: "https://github.com/features/copilot"
|
||||
},
|
||||
{
|
||||
name: "Gemini Pro",
|
||||
icon: SiGooglegemini,
|
||||
description: "Chatting, asking questions, and image generation",
|
||||
status: "occasional",
|
||||
link: "https://gemini.google.com/"
|
||||
},
|
||||
{
|
||||
name: "v0 Free",
|
||||
svg: <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>v0</title><path d="M14.066 6.028v2.22h5.729q.075-.001.148.005l-5.853 5.752a2 2 0 0 1-.024-.309V8.247h-2.353v5.45c0 2.322 1.935 4.222 4.258 4.222h5.675v-2.22h-5.675q-.03 0-.059-.003l5.729-5.629q.006.082.006.166v5.465H24v-5.465a4.204 4.204 0 0 0-4.205-4.205zM0 8.245l8.28 9.266c.839.94 2.396.346 2.396-.914V8.245H8.19v5.44l-4.86-5.44Z"/></svg>,
|
||||
description: "Generating boilerplate UIs",
|
||||
status: "occasional",
|
||||
link: "https://v0.dev/"
|
||||
},
|
||||
{
|
||||
name: "Qwen",
|
||||
svg: (
|
||||
<svg viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg" className="size-8">
|
||||
<path d="M174.82 108.75L155.38 75L165.64 57.75C166.46 56.31 166.46 54.53 165.64 53.09L155.38 35.84C154.86 34.91 153.87 34.33 152.78 34.33H114.88L106.14 19.03C105.62 18.1 104.63 17.52 103.54 17.52H83.3C82.21 17.52 81.22 18.1 80.7 19.03L61.26 52.77H41.02C39.93 52.77 38.94 53.35 38.42 54.28L28.16 71.53C27.34 72.97 27.34 74.75 28.16 76.19L45.52 107.5L36.78 122.8C35.96 124.24 35.96 126.02 36.78 127.46L47.04 144.71C47.56 145.64 48.55 146.22 49.64 146.22H87.54L96.28 161.52C96.8 162.45 97.79 163.03 98.88 163.03H119.12C120.21 163.03 121.2 162.45 121.72 161.52L141.16 127.78H158.52C159.61 127.78 160.6 127.2 161.12 126.27L171.38 109.02C172.2 107.58 172.2 105.8 171.38 104.36L174.82 108.75Z" fill="url(#paint0_radial)"/>
|
||||
<path d="M119.12 163.03H98.88L87.54 144.71H49.64L61.26 126.39H80.7L38.42 55.29H61.26L83.3 19.03L93.56 37.35L83.3 55.29H161.58L151.32 72.54L170.76 106.28H151.32L141.16 88.34L101.18 163.03H119.12Z" fill="white"/>
|
||||
<path d="M127.86 79.83H76.14L101.18 122.11L127.86 79.83Z" fill="url(#paint1_radial)"/>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(100 100) rotate(90) scale(100)">
|
||||
<stop stopColor="#665CEE"/>
|
||||
<stop offset="1" stopColor="#332E91"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint1_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(100 100) rotate(90) scale(100)">
|
||||
<stop stopColor="#665CEE"/>
|
||||
<stop offset="1" stopColor="#332E91"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
),
|
||||
description: "My favorite open source LLM for chatting",
|
||||
status: "occasional",
|
||||
link: "https://chat.qwen.ai/"
|
||||
},
|
||||
]
|
||||
|
||||
export const favoriteModels: FavoriteModel[] = [
|
||||
{
|
||||
name: "Claude 4 Sonnet",
|
||||
provider: "Anthropic",
|
||||
review: "The perfect balance of capability, speed, and price. Perfect for development with React.",
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Claude 4.1 Opus",
|
||||
provider: "Anthropic",
|
||||
review: "Amazing planner, useful for Plan Mode in Claude Code. Useful in code generation too.",
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Qwen3-235B-A22B",
|
||||
provider: "Alibaba",
|
||||
review: "The OG thinking model. Amazing, funny, and smart for chats. Surprisingly good at coding too.",
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Gemini 2.5 Pro",
|
||||
provider: "Google",
|
||||
review: "Amazing for Deep Research and reasoning tasks. I hate it for coding.",
|
||||
rating: 4
|
||||
},
|
||||
{
|
||||
name: "gemma3 27B",
|
||||
provider: "Google",
|
||||
review: "My favorite for playing around with AI or creating a project. Easy to run locally and open weight!",
|
||||
rating: 4
|
||||
},
|
||||
]
|
||||
|
||||
export const aiReviews: AIReview[] = [
|
||||
{
|
||||
tool: "Claude Code",
|
||||
rating: 5,
|
||||
pros: ["Flagship models", "High usage limits", "Exceptional Claude integration"],
|
||||
cons: ["Can be slow", "High investment cost to get value"],
|
||||
verdict: "Best overall for Claude lovers"
|
||||
},
|
||||
{
|
||||
tool: "Cursor",
|
||||
rating: 4,
|
||||
pros: ["Works like magic", "Lots of model support", "Huge ecosystem and community"],
|
||||
cons: ["Expensive", "Hype around it is dying", "Unclear/manipulative pricing"],
|
||||
verdict: "Great all-rounder, slowly dying"
|
||||
},
|
||||
{
|
||||
tool: "Trae",
|
||||
rating: 4,
|
||||
pros: ["Good UI/UX", "Very budget-friendly", "Fantastic premium usage limits"],
|
||||
cons: ["No thinking", "Occasional parsing issues"],
|
||||
verdict: "Essential for productivity"
|
||||
},
|
||||
{
|
||||
tool: "GitHub Copilot",
|
||||
rating: 3,
|
||||
pros: ["Latest models", "Great autocomplete", "Budget-friendly subscription price"],
|
||||
cons: ["No thinking", "Low quality output", "Bad support for other IDEs"],
|
||||
verdict: "Good for casual use"
|
||||
},
|
||||
]
|
40
app/ai/page.tsx
Normal file
40
app/ai/page.tsx
Normal file
|
@ -0,0 +1,40 @@
|
|||
"use client"
|
||||
|
||||
import Header from '@/components/Header'
|
||||
import Footer from '@/components/Footer'
|
||||
import { Brain } from 'lucide-react'
|
||||
import TopPick from './components/TopPick'
|
||||
import AIStack from './components/AIStack'
|
||||
import FavoriteModels from './components/FavoriteModels'
|
||||
import ToolReviews from './components/ToolReviews'
|
||||
import { aiTools, favoriteModels, aiReviews } from './data'
|
||||
|
||||
export default function AI() {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<Header />
|
||||
<main className="w-full px-2 sm:px-6">
|
||||
<div className="my-12 text-center">
|
||||
<div className="flex justify-center mb-6">
|
||||
<Brain size={60} />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold mb-2 text-gray-100 glow">AI</h1>
|
||||
<p className="text-gray-400">My journey with using LLMs</p>
|
||||
</div>
|
||||
|
||||
<TopPick />
|
||||
|
||||
<div className="p-4">
|
||||
<AIStack tools={aiTools} />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 p-4">
|
||||
<FavoriteModels models={favoriteModels} />
|
||||
<ToolReviews reviews={aiReviews} />
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
24
app/ai/types.ts
Normal file
24
app/ai/types.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
export interface AITool {
|
||||
name: string;
|
||||
icon?: React.ElementType;
|
||||
svg?: React.ReactNode;
|
||||
description: string;
|
||||
status: 'primary' | 'active' | 'occasional' | string;
|
||||
link?: string;
|
||||
usage?: string;
|
||||
}
|
||||
|
||||
export interface FavoriteModel {
|
||||
name: string;
|
||||
provider: string;
|
||||
review: string;
|
||||
rating: number;
|
||||
}
|
||||
|
||||
export interface AIReview {
|
||||
tool: string;
|
||||
rating: number;
|
||||
pros: string[];
|
||||
cons: string[];
|
||||
verdict: string;
|
||||
}
|
|
@ -12,7 +12,8 @@ import {
|
|||
X,
|
||||
Menu,
|
||||
Globe,
|
||||
ChevronDown
|
||||
ChevronDown,
|
||||
Brain
|
||||
} from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
|
@ -145,6 +146,7 @@ export default function Header() {
|
|||
<ul className={`flex flex-col lg:flex-row space-y-2 lg:space-y-0 lg:space-x-4 absolute lg:static bg-gray-800 lg:bg-transparent w-full lg:w-auto left-0 lg:left-auto top-16 lg:top-auto p-4 lg:p-0 transition-all duration-300 ease-in-out ${isOpen ? 'flex' : 'hidden lg:flex'}`}>
|
||||
<NavItem href="/" icon={House}>Home</NavItem>
|
||||
<NavItem href="/about" icon={User}>About</NavItem>
|
||||
<NavItem href="/ai" icon={Brain}>AI</NavItem>
|
||||
<NavItem href="/contact" icon={Phone}>Contact</NavItem>
|
||||
<NavItem href="/domains" icon={LinkIcon}>Domains</NavItem>
|
||||
<NavItem href="/manifesto" icon={BookOpen}>Manifesto</NavItem>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"react-dom": "^19.1.1",
|
||||
"react-i18next": "^15.7.1",
|
||||
"react-icons": "^5.5.0",
|
||||
"recharts": "^3.1.2",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tw-animate-css": "^1.3.7"
|
||||
|
|
459
public/data/cc.json
Normal file
459
public/data/cc.json
Normal file
|
@ -0,0 +1,459 @@
|
|||
{
|
||||
"daily": [
|
||||
{
|
||||
"date": "2025-08-08",
|
||||
"inputTokens": 14919,
|
||||
"outputTokens": 23378,
|
||||
"cacheCreationTokens": 480031,
|
||||
"cacheReadTokens": 11034031,
|
||||
"totalTokens": 11552359,
|
||||
"totalCost": 6.777273749999996,
|
||||
"modelsUsed": [
|
||||
"claude-opus-4-1-20250805",
|
||||
"claude-sonnet-4-20250514"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 4837,
|
||||
"outputTokens": 20788,
|
||||
"cacheCreationTokens": 443453,
|
||||
"cacheReadTokens": 10661975,
|
||||
"cost": 5.18787225
|
||||
},
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 10082,
|
||||
"outputTokens": 2590,
|
||||
"cacheCreationTokens": 36578,
|
||||
"cacheReadTokens": 372056,
|
||||
"cost": 1.5894014999999997
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-09",
|
||||
"inputTokens": 3142,
|
||||
"outputTokens": 20594,
|
||||
"cacheCreationTokens": 513312,
|
||||
"cacheReadTokens": 13270007,
|
||||
"totalTokens": 13807055,
|
||||
"totalCost": 20.561232300000007,
|
||||
"modelsUsed": [
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 373,
|
||||
"outputTokens": 10485,
|
||||
"cacheCreationTokens": 294339,
|
||||
"cacheReadTokens": 7740261,
|
||||
"cost": 17.92121775
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 2769,
|
||||
"outputTokens": 10109,
|
||||
"cacheCreationTokens": 218973,
|
||||
"cacheReadTokens": 5529746,
|
||||
"cost": 2.640014549999999
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-10",
|
||||
"inputTokens": 2384,
|
||||
"outputTokens": 33087,
|
||||
"cacheCreationTokens": 752268,
|
||||
"cacheReadTokens": 12833548,
|
||||
"totalTokens": 13621287,
|
||||
"totalCost": 24.83825640000001,
|
||||
"modelsUsed": [
|
||||
"claude-opus-4-1-20250805",
|
||||
"claude-sonnet-4-20250514"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 983,
|
||||
"outputTokens": 24065,
|
||||
"cacheCreationTokens": 320876,
|
||||
"cacheReadTokens": 9495745,
|
||||
"cost": 22.079662499999998
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 1401,
|
||||
"outputTokens": 9022,
|
||||
"cacheCreationTokens": 431392,
|
||||
"cacheReadTokens": 3337803,
|
||||
"cost": 2.7585938999999993
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-11",
|
||||
"inputTokens": 1127,
|
||||
"outputTokens": 23663,
|
||||
"cacheCreationTokens": 746606,
|
||||
"cacheReadTokens": 10310633,
|
||||
"totalTokens": 11082029,
|
||||
"totalCost": 31.256441999999993,
|
||||
"modelsUsed": [
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 1127,
|
||||
"outputTokens": 23663,
|
||||
"cacheCreationTokens": 746606,
|
||||
"cacheReadTokens": 10310633,
|
||||
"cost": 31.256441999999993
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-12",
|
||||
"inputTokens": 17245,
|
||||
"outputTokens": 164864,
|
||||
"cacheCreationTokens": 2646250,
|
||||
"cacheReadTokens": 49767559,
|
||||
"totalTokens": 52595918,
|
||||
"totalCost": 85.49760780000005,
|
||||
"modelsUsed": [
|
||||
"claude-opus-4-1-20250805",
|
||||
"claude-sonnet-4-20250514"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 13710,
|
||||
"outputTokens": 77330,
|
||||
"cacheCreationTokens": 1413354,
|
||||
"cacheReadTokens": 26762148,
|
||||
"cost": 72.64900950000008
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 3535,
|
||||
"outputTokens": 87534,
|
||||
"cacheCreationTokens": 1232896,
|
||||
"cacheReadTokens": 23005411,
|
||||
"cost": 12.848598300000004
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-13",
|
||||
"inputTokens": 29365,
|
||||
"outputTokens": 23237,
|
||||
"cacheCreationTokens": 1034891,
|
||||
"cacheReadTokens": 7332169,
|
||||
"totalTokens": 8419662,
|
||||
"totalCost": 9.039594749999997,
|
||||
"modelsUsed": [
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 24909,
|
||||
"outputTokens": 18462,
|
||||
"cacheCreationTokens": 935307,
|
||||
"cacheReadTokens": 6758235,
|
||||
"cost": 5.886528749999999
|
||||
},
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 4456,
|
||||
"outputTokens": 4775,
|
||||
"cacheCreationTokens": 99584,
|
||||
"cacheReadTokens": 573934,
|
||||
"cost": 3.1530659999999995
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-14",
|
||||
"inputTokens": 4984,
|
||||
"outputTokens": 20654,
|
||||
"cacheCreationTokens": 676409,
|
||||
"cacheReadTokens": 8769252,
|
||||
"totalTokens": 9471299,
|
||||
"totalCost": 13.503454350000002,
|
||||
"modelsUsed": [
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 282,
|
||||
"outputTokens": 6364,
|
||||
"cacheCreationTokens": 260989,
|
||||
"cacheReadTokens": 3092770,
|
||||
"cost": 10.014228749999996
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 4702,
|
||||
"outputTokens": 14290,
|
||||
"cacheCreationTokens": 415420,
|
||||
"cacheReadTokens": 5676482,
|
||||
"cost": 3.489225600000001
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-15",
|
||||
"inputTokens": 6744,
|
||||
"outputTokens": 53509,
|
||||
"cacheCreationTokens": 1315474,
|
||||
"cacheReadTokens": 18699807,
|
||||
"totalTokens": 20075534,
|
||||
"totalCost": 37.771287000000015,
|
||||
"modelsUsed": [
|
||||
"claude-opus-4-1-20250805",
|
||||
"claude-sonnet-4-20250514"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 3739,
|
||||
"outputTokens": 36231,
|
||||
"cacheCreationTokens": 818888,
|
||||
"cacheReadTokens": 9919502,
|
||||
"cost": 33.00681300000001
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 3005,
|
||||
"outputTokens": 17278,
|
||||
"cacheCreationTokens": 496586,
|
||||
"cacheReadTokens": 8780305,
|
||||
"cost": 4.764474
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-16",
|
||||
"inputTokens": 67226,
|
||||
"outputTokens": 230912,
|
||||
"cacheCreationTokens": 4693459,
|
||||
"cacheReadTokens": 126251857,
|
||||
"totalTokens": 131243454,
|
||||
"totalCost": 67.51195695000014,
|
||||
"modelsUsed": [
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 66858,
|
||||
"outputTokens": 225159,
|
||||
"cacheCreationTokens": 4442992,
|
||||
"cacheReadTokens": 122698549,
|
||||
"cost": 57.048743700000024
|
||||
},
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 368,
|
||||
"outputTokens": 5753,
|
||||
"cacheCreationTokens": 250467,
|
||||
"cacheReadTokens": 3553308,
|
||||
"cost": 10.463213249999994
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-17",
|
||||
"inputTokens": 5258,
|
||||
"outputTokens": 107279,
|
||||
"cacheCreationTokens": 2065168,
|
||||
"cacheReadTokens": 40221095,
|
||||
"totalTokens": 42398800,
|
||||
"totalCost": 46.292036099999905,
|
||||
"modelsUsed": [
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 1306,
|
||||
"outputTokens": 37998,
|
||||
"cacheCreationTokens": 568961,
|
||||
"cacheReadTokens": 11688668,
|
||||
"cost": 31.07046074999999
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 3952,
|
||||
"outputTokens": 69281,
|
||||
"cacheCreationTokens": 1496207,
|
||||
"cacheReadTokens": 28532427,
|
||||
"cost": 15.221575350000005
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-18",
|
||||
"inputTokens": 26822,
|
||||
"outputTokens": 158126,
|
||||
"cacheCreationTokens": 4162794,
|
||||
"cacheReadTokens": 85133032,
|
||||
"totalTokens": 89480774,
|
||||
"totalCost": 98.36223149999994,
|
||||
"modelsUsed": [
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 1334,
|
||||
"outputTokens": 59577,
|
||||
"cacheCreationTokens": 1226868,
|
||||
"cacheReadTokens": 27304867,
|
||||
"cost": 68.4493605
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 25488,
|
||||
"outputTokens": 98549,
|
||||
"cacheCreationTokens": 2935926,
|
||||
"cacheReadTokens": 57828165,
|
||||
"cost": 29.912871000000024
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-19",
|
||||
"inputTokens": 25035,
|
||||
"outputTokens": 192422,
|
||||
"cacheCreationTokens": 2749046,
|
||||
"cacheReadTokens": 86412205,
|
||||
"totalTokens": 89378708,
|
||||
"totalCost": 120.90988019999996,
|
||||
"modelsUsed": [
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 6500,
|
||||
"outputTokens": 120014,
|
||||
"cacheCreationTokens": 1447294,
|
||||
"cacheReadTokens": 43939676,
|
||||
"cost": 102.14482650000001
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 18535,
|
||||
"outputTokens": 72408,
|
||||
"cacheCreationTokens": 1301752,
|
||||
"cacheReadTokens": 42472529,
|
||||
"cost": 18.76505370000004
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-20",
|
||||
"inputTokens": 1777,
|
||||
"outputTokens": 45019,
|
||||
"cacheCreationTokens": 1288952,
|
||||
"cacheReadTokens": 18847679,
|
||||
"totalTokens": 20183427,
|
||||
"totalCost": 46.130642700000024,
|
||||
"modelsUsed": [
|
||||
"claude-opus-4-1-20250805",
|
||||
"claude-sonnet-4-20250514"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 1472,
|
||||
"outputTokens": 29172,
|
||||
"cacheCreationTokens": 1017913,
|
||||
"cacheReadTokens": 14937895,
|
||||
"cost": 43.702691249999994
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 305,
|
||||
"outputTokens": 15847,
|
||||
"cacheCreationTokens": 271039,
|
||||
"cacheReadTokens": 3909784,
|
||||
"cost": 2.4279514499999997
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-21",
|
||||
"inputTokens": 81,
|
||||
"outputTokens": 3400,
|
||||
"cacheCreationTokens": 57191,
|
||||
"cacheReadTokens": 406935,
|
||||
"totalTokens": 467607,
|
||||
"totalCost": 1.0935505500000002,
|
||||
"modelsUsed": [
|
||||
"claude-sonnet-4-20250514",
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 37,
|
||||
"outputTokens": 826,
|
||||
"cacheCreationTokens": 29950,
|
||||
"cacheReadTokens": 172089,
|
||||
"cost": 0.882201
|
||||
},
|
||||
{
|
||||
"modelName": "claude-sonnet-4-20250514",
|
||||
"inputTokens": 44,
|
||||
"outputTokens": 2574,
|
||||
"cacheCreationTokens": 27241,
|
||||
"cacheReadTokens": 234846,
|
||||
"cost": 0.21134955
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"date": "2025-08-22",
|
||||
"inputTokens": 201,
|
||||
"outputTokens": 26357,
|
||||
"cacheCreationTokens": 182770,
|
||||
"cacheReadTokens": 1764101,
|
||||
"totalTokens": 1973429,
|
||||
"totalCost": 8.052878999999999,
|
||||
"modelsUsed": [
|
||||
"claude-opus-4-1-20250805"
|
||||
],
|
||||
"modelBreakdowns": [
|
||||
{
|
||||
"modelName": "claude-opus-4-1-20250805",
|
||||
"inputTokens": 201,
|
||||
"outputTokens": 26357,
|
||||
"cacheCreationTokens": 182770,
|
||||
"cacheReadTokens": 1764101,
|
||||
"cost": 8.052878999999999
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"totals": {
|
||||
"inputTokens": 206310,
|
||||
"outputTokens": 1126501,
|
||||
"cacheCreationTokens": 23364621,
|
||||
"cacheReadTokens": 491053910,
|
||||
"totalCost": 617.5983253500001,
|
||||
"totalTokens": 515751342
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue