Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export default function Home() {
<span className="relative inline-flex h-2 w-2 rounded-full bg-emerald-500" />
</span>
<span className="text-xs font-medium tracking-wide text-white/50">
Now supporting Claude Code traces
Now supporting Claude Code & Tesslate Studio
</span>
</div>
</BlurFade>
Expand Down Expand Up @@ -527,9 +527,7 @@ export default function Home() {
Agent Wrapped — open source, privacy-first
</span>
<div className="flex items-center gap-6 text-xs text-white/15">
<span>Currently supports Claude Code</span>
<span className="text-white/8">|</span>
<span>More agents coming soon</span>
<span>Supports Claude Code & Tesslate Studio</span>
<span className="text-white/8">|</span>
<Link
href="/privacy"
Expand Down
11 changes: 6 additions & 5 deletions src/app/upload/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,20 @@ export default function UploadPage() {

const totalSize = files.reduce((sum, f) => sum + f.size, 0)
trackFileUploaded({
agent_type: "claude_code",
agent_type: "auto_detect",
file_count: files.length,
total_size_bytes: totalSize,
})

try {
setStatus("parsing")
trackParsingStarted({ agent_type: "claude_code" })
trackParsingStarted({ agent_type: "auto_detect" })
const parseStart = performance.now()
const traceData = await parseFiles(files)
const agentType = traceData.source === "tesslate-studio" ? "tesslate_studio" : "claude_code"
setTraceData(traceData)
trackParsingCompleted({
agent_type: "claude_code",
agent_type: agentType,
duration_ms: Math.round(performance.now() - parseStart),
})

Expand All @@ -57,7 +58,7 @@ export default function UploadPage() {

setAnalysisResult(result)
trackAnalysisCompleted({
agent_type: "claude_code",
agent_type: agentType,
session_count: result.rawStats.totalSessions,
message_count: result.rawStats.totalMessages,
})
Expand All @@ -66,7 +67,7 @@ export default function UploadPage() {
} catch (err) {
const message = err instanceof Error ? err.message : "Failed to process files"
setError(message)
trackParsingFailed({ agent_type: "claude_code", error_type: message })
trackParsingFailed({ agent_type: "auto_detect", error_type: message })
trackError({
error_type: "parsing_error",
error_message: message,
Expand Down
9 changes: 8 additions & 1 deletion src/app/wrapped/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,14 @@ function DashboardContent() {
<main className="min-h-screen bg-[#0a0a0a] px-4 py-6 md:px-8 lg:px-12">
<div className="mx-auto max-w-7xl">
<div className="mb-8 flex items-center justify-between">
<h1 className="text-2xl font-bold text-white">Dashboard</h1>
<div className="flex items-center gap-3">
<h1 className="text-2xl font-bold text-white">Dashboard</h1>
{state.traceData?.source && (
<span className="rounded-full border border-white/[0.08] bg-white/[0.03] px-2.5 py-0.5 text-xs font-medium text-white/40">
{state.traceData.source === "tesslate-studio" ? "Tesslate Studio" : "Claude Code"}
</span>
)}
</div>

{/* Desktop nav — hidden on small screens */}
<div className="hidden md:flex items-center gap-3">
Expand Down
44 changes: 40 additions & 4 deletions src/components/upload/file-dropzone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function FileDropzone({ onFilesSelected }: FileDropzoneProps) {
const traceFiles = filterTraceFiles(allFiles)

if (traceFiles.length === 0) {
setErrors(["No trace files (.jsonl) found. Make sure you're uploading your .claude/ directory or individual .jsonl files."])
setErrors(["No trace files found. Upload your .claude/ directory (.jsonl files) or Tesslate Studio export (.json files)."])
setIsScanning(false)
return
}
Expand Down Expand Up @@ -246,7 +246,7 @@ export function FileDropzone({ onFilesSelected }: FileDropzoneProps) {

<div>
<p className="text-lg font-medium text-white/90">
{isDragOver ? "Drop it here" : "Drop a folder or .jsonl files here"}
{isDragOver ? "Drop it here" : "Drop a folder, .jsonl, or .json files here"}
</p>
<p className="mt-1 text-sm text-white/50">
or use the buttons below to browse
Expand Down Expand Up @@ -277,7 +277,7 @@ export function FileDropzone({ onFilesSelected }: FileDropzoneProps) {
</div>

<p className="text-xs text-white/30">
We&apos;ll find all .jsonl trace files automatically
We&apos;ll find all trace files automatically
</p>
</>
)}
Expand Down Expand Up @@ -323,7 +323,7 @@ export function FileDropzone({ onFilesSelected }: FileDropzoneProps) {
Where are my trace files?
</p>
<p className="mb-4 text-[13px] leading-relaxed text-white/30">
Claude Code stores traces in a hidden <code className="rounded bg-white/[0.06] px-1.5 py-0.5 font-mono text-white/50">.claude/</code> folder in your home directory.
Claude Code traces are in your <code className="rounded bg-white/[0.06] px-1.5 py-0.5 font-mono text-white/50">.claude/</code> folder. Tesslate Studio traces can be exported as JSON.
</p>

<div className="space-y-1">
Expand Down Expand Up @@ -449,6 +449,42 @@ export function FileDropzone({ onFilesSelected }: FileDropzoneProps) {
</ul>
</div>
</details>

{/* Tesslate Studio */}
<details className="group rounded-lg border border-white/[0.04] bg-white/[0.01]">
<summary className="flex cursor-pointer items-center justify-between px-4 py-3 text-sm font-medium text-white/50 transition-colors hover:text-white/70">
<span className="flex items-center gap-2">
<svg className="h-4 w-4 text-white/30" viewBox="0 0 161.9 126.66" fill="currentColor">
<path d="m13.45,46.48h54.06c10.21,0,16.68-10.94,11.77-19.89l-9.19-16.75c-2.36-4.3-6.87-6.97-11.77-6.97H22.41c-4.95,0-9.5,2.73-11.84,7.09L1.61,26.71c-4.79,8.95,1.69,19.77,11.84,19.77Z" />
<path d="m61.05,119.93l26.95-46.86c5.09-8.85-1.17-19.91-11.37-20.12l-19.11-.38c-4.9-.1-9.47,2.48-11.91,6.73l-17.89,31.12c-2.47,4.29-2.37,9.6.25,13.8l10.05,16.13c5.37,8.61,17.98,8.39,23.04-.41Z" />
<path d="m148.46,0h-54.06c-10.21,0-16.68,10.94-11.77,19.89l9.19,16.75c2.36,4.3,6.87,6.97,11.77,6.97h35.9c4.95,0,9.5-2.73,11.84-7.09l8.97-16.75C165.08,10.82,158.6,0,148.46,0Z" />
</svg>
Tesslate Studio
</span>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="transition-transform group-open:rotate-180">
<path d="m6 9 6 6 6-6" />
</svg>
</summary>
<div className="px-4 pb-4">
<ul className="space-y-2 text-[13px] text-white/30">
<li className="flex gap-2">
<span className="shrink-0 text-white/20">1.</span>
<span>
Export your trace data from Tesslate Studio as a JSON file
</span>
</li>
<li className="flex gap-2">
<span className="shrink-0 text-white/20">2.</span>
<span>
Drop the <code className="rounded bg-white/[0.06] px-1.5 py-0.5 font-mono text-white/50">.json</code> export file(s) into the box above
</span>
</li>
</ul>
<p className="mt-3 text-[11px] text-white/20">
Supports both single-project and full account exports.
</p>
</div>
</details>
</div>
</div>

Expand Down
7 changes: 6 additions & 1 deletion src/lib/analyzers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,12 @@ export const STOPWORDS = new Set([
"some", "any", "other", "new",
])

export const FILE_TOOL_NAMES = ["Read", "Edit", "Write", "Glob", "Grep"]
export const FILE_TOOL_NAMES = [
// Claude Code tools
"Read", "Edit", "Write", "Glob", "Grep",
// Tesslate Studio tools
"read_file", "write_file", "edit_file",
]

export const EXTENSION_TO_LANGUAGE: Record<string, string> = {
".ts": "TypeScript", ".tsx": "TypeScript", ".js": "JavaScript", ".jsx": "JavaScript",
Expand Down
6 changes: 6 additions & 0 deletions src/lib/analyzers/cost-estimate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ const PRICING: Record<string, { input: number; output: number }> = {
"claude-3-5-haiku-20241022": { input: 0.8, output: 4.0 },
"claude-3-haiku": { input: 0.25, output: 1.25 },
"claude-3-haiku-20240307": { input: 0.25, output: 1.25 },
// Dot-variant aliases (Tesslate Studio uses dots in model versions)
"claude-opus-4.6": { input: 5.0, output: 25.0 },
"claude-opus-4.5": { input: 5.0, output: 25.0 },
"claude-sonnet-4.6": { input: 3.0, output: 15.0 },
"claude-sonnet-4.5": { input: 3.0, output: 15.0 },
"claude-haiku-4.5": { input: 1.0, output: 5.0 },
// Fallback for unknown models
_default: { input: 3.0, output: 15.0 },
}
Expand Down
Loading
Loading