vite-devtools-svelte 0.4.1 → 0.5.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.
Files changed (45) hide show
  1. package/README.md +2 -2
  2. package/dist/client/assets/{ApiPlayground-BMx5j-7t.js → ApiPlayground-B28mCUlr.js} +1 -1
  3. package/dist/client/assets/{Assets-BHhg5Smm.js → Assets-BVT22xZ3.js} +1 -1
  4. package/dist/client/assets/{Badge-CBVv8IFU.js → Badge-x4Lbd8pc.js} +1 -1
  5. package/dist/client/assets/{BuildAnalysis-BdVCnWpb.js → BuildAnalysis-BscZFEWI.js} +1 -1
  6. package/dist/client/assets/{CaptureNotice-BeXCVhO0.js → CaptureNotice-D0u6WNeR.js} +1 -1
  7. package/dist/client/assets/{Components-D_qDgEUt.js → Components-sw5zdu0k.js} +1 -1
  8. package/dist/client/assets/{DataTable-C6-tmcTQ.js → DataTable-CdM2Vyvn.js} +1 -1
  9. package/dist/client/assets/{ErrorDashboard-CfUhPzue.js → ErrorDashboard-BwGMVW_-.js} +1 -1
  10. package/dist/client/assets/{FpsMonitor-B_AuHgyu.js → FpsMonitor-C0FeLiag.js} +1 -1
  11. package/dist/client/assets/{Inspect-BOgmKm6W.js → Inspect-B-jb8MaB.js} +1 -1
  12. package/dist/client/assets/{Inspector-DGmAzhki.js → Inspector-C4wr2Zb4.js} +1 -1
  13. package/dist/client/assets/{LoadProfiler-5xhnDLjR.js → LoadProfiler-WeP1orWN.js} +1 -1
  14. package/dist/client/assets/{ModuleGraph-Cp7f0Nz0.js → ModuleGraph-BYer7OEL.js} +1 -1
  15. package/dist/client/assets/{OGPreview-CjBhXSgn.js → OGPreview-MRxnmCmb.js} +1 -1
  16. package/dist/client/assets/{Overview-Kbpkgsas.js → Overview-CDBKKylY.js} +1 -1
  17. package/dist/client/assets/Overview-Neh721Uf.css +1 -0
  18. package/dist/client/assets/ReactiveGraph-Bni33DP4.js +5 -0
  19. package/dist/client/assets/{RenderProfiler-CeF8_j3b.js → RenderProfiler-2rA8kCUf.js} +1 -1
  20. package/dist/client/assets/{Routes-DArWZtzC.js → Routes-BZ5XcmEt.js} +1 -1
  21. package/dist/client/assets/{SearchField-eocQu1eB.js → SearchField-D85HSGV_.js} +1 -1
  22. package/dist/client/assets/{Segmented-JGNuI5EZ.js → Segmented-BCcIUjA2.js} +1 -1
  23. package/dist/client/assets/{SplitView-B8lYXXEm.js → SplitView-DVk1HAf9.js} +1 -1
  24. package/dist/client/assets/{StateTimeline-HpyvgoK1.js → StateTimeline-DjTXe54T.js} +1 -1
  25. package/dist/client/assets/{TreeView-fty5aCC5.js → TreeView-e7dNH8HW.js} +1 -1
  26. package/dist/client/assets/{VirtualList-BvOBTnYJ.js → VirtualList-Ba0GhFn8.js} +1 -1
  27. package/dist/client/assets/{browser-agent-rpc-BXhoSh1z-D9g7mT9G.js → browser-agent-rpc-BXhoSh1z-UMmvacmP.js} +1 -1
  28. package/dist/client/assets/{capture.svelte-CUhwdJwX.js → capture.svelte-fve1ihQA.js} +1 -1
  29. package/dist/client/assets/{index-BzMw8R8l.js → index-CuoAAt-d.js} +3 -3
  30. package/dist/client/assets/{index-eZHqMk0z.css → index-u73uo_Ri.css} +1 -1
  31. package/dist/client/assets/{reactive-C2hv2QLH.js → reactive-BSjTkgqc.js} +1 -1
  32. package/dist/client/assets/reactive-selection.svelte-BmjgYyWR.js +1 -0
  33. package/dist/client/assets/{versions-Co596WUJ.css → versions-CMau2xlU.css} +1 -1
  34. package/dist/client/assets/{versions-CZjRj40E.js → versions-zyEGB_mz.js} +1 -1
  35. package/dist/client/index.html +2 -2
  36. package/dist/index.mjs +90 -91
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/mcp/issues.d.ts +10 -1
  39. package/dist/plugin.d.ts +22 -0
  40. package/dist/runtime.d.ts +2 -2
  41. package/dist/types.d.ts +26 -2
  42. package/package.json +4 -1
  43. package/dist/client/assets/Overview-B8hvIsIM.css +0 -1
  44. package/dist/client/assets/ReactiveGraph-w2TK82c8.js +0 -5
  45. package/dist/client/assets/reactive-selection.svelte-Dfd9zWsh.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["path","path","path","path","fs","fs","fs","classify","fs","fs","negativeIsBetter","fs","avg","round","path","crypto","fs","path$1","fs$1","dns","net","os","analyzeRoutes","routesDir","routes","scanDirectory","a","b","entries","dir","files","hasRouteFiles","entry","rootDir","routeFile","classifyFile","relativePath","routePath","buildRoutePath","params","extractParams","f","type","name","fullPath","part","inner","parts","matcherSplit","CACHE_TTL_MS","_cachedResult","_cachedRoot","_cachedAt","analyzeProject","now","root","result","_analyzeProjectUncached","pkgPath","pkg","deps","devDeps","getInstalledVersion","findRoutesDir","findStaticDir","pkgJsonPath","candidates","analyzeComponents","srcDir","svelteFiles","findSvelteFiles","imports","extractSvelteImports","file","getComponentName","i","filePath","importRegex","match","content","importPath","resolved","resolveImportPath","findProjectRoot","fromFile","libPath","RUNTIME_MODULE_ID","RESOLVED_RUNTIME_ID","WRAPPER_MODULE_ID","wrapperCode","runtimeCode","LIMITS","RUNTIME_REQUEST_TIMEOUT","lastSeq","nextSeq","LEGACY_EPOCH","HOT_EVENTS","MAX_CACHED_PULLS","SUMMARY_DEFAULTS","DROP_REASONS","validBaseline","v","clampInt","value","fallback","max","min","LEASE_TTL","tail","list","arr","head","Collector","keys","key","hooks","hot","listeners","client","d","event","listener","state","newest","epoch","evicted","wasActive","id","ttl","done","timer","idx","resolve","timeout","next","expiresAt","active","data","isDelta","incoming","c","ring","received","captured","drops","counts","reason","dropped","r","tooLarge","n","profiles","profilesTotal","graph","info","common","last","start","count","valueTooLarge","cursor","since","keep","e","changes","change","size","drop","bytes","requestId","pull","answered","legacy","nodes","rawEdges","policy","scope","total","own","truncated","ids","edgesOmitted","edges","rows","w","sample","error","profile","warning","req","maxNodes","maxEdges","topK","windowMs","empty","cached","existing","promise","payload","resolver","resolvers","pending","MIME_TYPES","analyzeAssets","staticDir","assets","scanDir","publicBase","base","stat","ext","parseExternalUrl","parsed","urlStr","hostname","isPrivateIP","lower","assertOutboundUrl","options","addresses","address","ip","isPrivateIPv6","p","v4","resolveWithinRoot","input","realRoot","candidate","real","HTTP_METHODS","analyzeApiEndpoints","endpoints","route","serverFile","methods","m","sendApiRequest","duration","parsedHeaders","init","res","body","headers","k","WEB_EXTENSIONS","analyzeBuild","chunks","dirs","walkDir","full","s","classify$1","buildModuleGraph","modules","idMap","moduleById","mod","allModules","relFile","node","importedBySets","importsSet","imp","impNode","by","cycles","visited","stack","pathBuf","dfs","cycleStart","cycle","cyclicIds","getOGPreview","preview","url","html","metaRegex","propRegex","contentRegex","attrs","propMatch","contentMatch","prop","titleMatch","descTag","t","findReactiveLine","lines","source","l","escaped","regex","DEVFRAME_ID","DEVFRAME_BASE","createRequire","clientAssets","fileURLToPath","z","createRpcFunctions","host","project","defineRpcFunction","collector","line","map","createSvelteDevframe","defineDevframe","scoped","ctx","fn","WILDCARD","LOOPBACK","formatHost","networkOrigins","proto","h","mountStandalone","instance","closed","httpServer","server","created","initDevframe","def","local","current","UNCHANGED_RENDER_THRESHOLD_MS","UNCHANGED_LOAD_THRESHOLD_MS","UNCHANGED_FPS_THRESHOLD","FPS_DROP_THRESHOLD","takeSnapshot","getters","classify","diff","threshold","lowerIsBetter","SESSION_ID_PATTERN","isSessionId","SessionStore","opts","record","rec","seen","out","had","onDisk","startMap","components","end","startRenderCount","startTotal","renderCountDelta","totalRenderTimeDelta","loadDurations","loadAvg","avg$1","loadP95","percentile","fpsValues","fpsAvg","fpsMin","fpsDrops","idA","idB","recA","recB","totalA","totalB","renderDiff","loadDiff","fpsDiff","raw","xs","x","sorted","DEFAULTS","listPerformanceIssues","thresholds","inputs","avg","round$1","outDegree","inDegree","fanout","compareSeverity","SEV_RANK","summarizeReactiveProblems","thresh","effects","orphanDeriveds","isolatedNodes","ind","outd","MCP_VALUE_CHARS","capValue","json","maxChars","sessionId","TEXT","buildMcpServer","McpServer","args","reactiveGraph","issues","round","topN","byRoute","ps","durations","samples","sinceMs","cutoff","includeMeta","all","limit","snap","getSummary","getScope","componentId","getDelta","delta","valueChars","maxValueChars","omitted","getInfo","label","persist","GENERATED_SERVER_SUFFIXES","TEMPLATE_APP_MARKER","INJECT_SCRIPT_URL","DEVTOOLS_MOUNT_PATH","INJECT_TAG","BODY_CLOSE","injectIntoSvelteKitInternal","code","markerIdx","bodyIdx","sveltekitTemplateInjector","env","suffix","isHosted","VITE_DEVTOOLS_PLUGIN","WARN_SINK","serverGeneration","collectModules","svelteDevtools","config","hostedByViteDevtools","mcpToken","sessions","getSessions","devframe","urls","u","launchEditor","target","middlewareModeMounts","resolvedConfig","devServer","generation","dispose","mcpServerFactory","addr","cmd","tokenHeader","mcpServer","mcpTransport","StreamableHTTPServerTransport","err","doomed","componentTracking","importer","createPluginFromDevframe","safeId","isServerLoad","isUniversalLoad","loadType","routesMatch","safeRoute","safeFile","safeType","transformed","profiledExport","logger","wrapped","msg","fileMatch","codeMatch","originalWarn"],"sources":["../src/analyzers/routes.ts","../src/analyzers/project.ts","../src/analyzers/components.ts","../src/runtime.ts","../src/collector.ts","../src/analyzers/assets.ts","../src/security.ts","../src/analyzers/api.ts","../src/analyzers/build.ts","../src/analyzers/module-graph.ts","../src/analyzers/og.ts","../src/analyzers/source.ts","../src/devframe.ts","../src/mount.ts","../src/mcp/sessions.ts","../src/mcp/issues.ts","../src/mcp/server.ts","../src/template-injector.ts","../src/plugin.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport type { RouteInfo, ParamInfo, RouteFile } from '../types.js'\n\nexport function analyzeRoutes(routesDir: string): RouteInfo[] {\n if (!fs.existsSync(routesDir)) return []\n\n const routes: RouteInfo[] = []\n scanDirectory(routesDir, routesDir, routes)\n return routes.sort((a, b) => a.path.localeCompare(b.path))\n}\n\nfunction scanDirectory(dir: string, rootDir: string, routes: RouteInfo[]): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n const files: RouteFile[] = []\n let hasRouteFiles = false\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n scanDirectory(path.join(dir, entry.name), rootDir, routes)\n continue\n }\n\n const routeFile = classifyFile(entry.name, path.join(dir, entry.name))\n if (routeFile) {\n files.push(routeFile)\n hasRouteFiles = true\n }\n }\n\n if (hasRouteFiles) {\n const relativePath = path.relative(rootDir, dir)\n const routePath = buildRoutePath(relativePath)\n const params = extractParams(relativePath)\n\n routes.push({\n id: relativePath || '/',\n path: routePath,\n pattern: routePath,\n segments: routePath.split('/').filter(Boolean),\n hasPage: files.some(f => f.type === 'page'),\n hasLayout: files.some(f => f.type === 'layout'),\n hasServerPage: files.some(f => f.type === 'page-load-server'),\n hasServerLayout: files.some(f => f.type === 'layout-load-server'),\n hasEndpoint: files.some(f => f.type === 'endpoint'),\n hasPageLoad: files.some(f => f.type === 'page-load'),\n hasLayoutLoad: files.some(f => f.type === 'layout-load'),\n params,\n files,\n })\n }\n}\n\nfunction classifyFile(name: string, fullPath: string): RouteFile | null {\n const map: Record<string, RouteFile['type']> = {\n '+page.svelte': 'page',\n '+layout.svelte': 'layout',\n '+page.server.ts': 'page-load-server',\n '+page.server.js': 'page-load-server',\n '+layout.server.ts': 'layout-load-server',\n '+layout.server.js': 'layout-load-server',\n '+page.ts': 'page-load',\n '+page.js': 'page-load',\n '+layout.ts': 'layout-load',\n '+layout.js': 'layout-load',\n '+server.ts': 'endpoint',\n '+server.js': 'endpoint',\n '+error.svelte': 'error',\n }\n\n const type = map[name]\n if (!type) return null\n return { type, path: fullPath }\n}\n\nfunction buildRoutePath(relativePath: string): string {\n if (!relativePath) return '/'\n\n const parts = relativePath.split(path.sep)\n const pathParts = parts.map(part => {\n // SvelteKit group syntax: (group) -> ignored in URL\n if (part.startsWith('(') && part.endsWith(')')) return null\n\n // Dynamic params: [param] -> :param\n if (part.startsWith('[') && part.endsWith(']')) {\n const inner = part.slice(1, -1)\n if (inner.startsWith('...')) return `*${inner.slice(3)}`\n if (inner.startsWith('[') && inner.endsWith(']')) return `:${inner.slice(1, -1)}?`\n return `:${inner}`\n }\n\n return part\n })\n\n return '/' + pathParts.filter(Boolean).join('/')\n}\n\nfunction extractParams(relativePath: string): ParamInfo[] {\n if (!relativePath) return []\n\n const params: ParamInfo[] = []\n const parts = relativePath.split(path.sep)\n\n for (const part of parts) {\n if (!part.startsWith('[') || !part.endsWith(']')) continue\n\n const inner = part.slice(1, -1)\n\n if (inner.startsWith('...')) {\n params.push({ name: inner.slice(3), optional: false, rest: true })\n } else if (inner.startsWith('[') && inner.endsWith(']')) {\n params.push({ name: inner.slice(1, -1), optional: true, rest: false })\n } else {\n const matcherSplit = inner.split('=')\n params.push({\n name: matcherSplit[0],\n optional: false,\n rest: false,\n matcher: matcherSplit[1],\n })\n }\n }\n\n return params\n}\n","import fs from 'fs'\nimport path from 'path'\nimport type { ProjectInfo } from '../types.js'\n\nconst CACHE_TTL_MS = 5000\nlet _cachedResult: ProjectInfo | null = null\nlet _cachedRoot: string | null = null\nlet _cachedAt = 0\n\nexport function analyzeProject(root: string): ProjectInfo {\n const now = Date.now()\n if (_cachedResult && _cachedRoot === root && now - _cachedAt < CACHE_TTL_MS) {\n return _cachedResult\n }\n const result = _analyzeProjectUncached(root)\n _cachedResult = result\n _cachedRoot = root\n _cachedAt = now\n return result\n}\n\nfunction _analyzeProjectUncached(root: string): ProjectInfo {\n const pkgPath = path.join(root, 'package.json')\n const pkg = fs.existsSync(pkgPath) ? JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) : {}\n\n const deps = pkg.dependencies || {}\n const devDeps = pkg.devDependencies || {}\n\n return {\n name: pkg.name || path.basename(root),\n version: pkg.version || '0.0.0',\n svelteVersion:\n getInstalledVersion(root, 'svelte') || deps.svelte || devDeps.svelte || 'unknown',\n sveltekitVersion:\n getInstalledVersion(root, '@sveltejs/kit') ||\n deps['@sveltejs/kit'] ||\n devDeps['@sveltejs/kit'] ||\n 'unknown',\n viteVersion: getInstalledVersion(root, 'vite') || deps.vite || devDeps.vite || 'unknown',\n dependencies: deps,\n devDependencies: devDeps,\n routesDir: findRoutesDir(root),\n staticDir: findStaticDir(root),\n }\n}\n\nfunction getInstalledVersion(root: string, pkg: string): string | null {\n try {\n const pkgJsonPath = path.join(root, 'node_modules', pkg, 'package.json')\n if (fs.existsSync(pkgJsonPath)) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'))\n return pkgJson.version\n }\n } catch {\n // ignore\n }\n return null\n}\n\nfunction findRoutesDir(root: string): string {\n const candidates = [path.join(root, 'src', 'routes'), path.join(root, 'src', 'pages')]\n for (const dir of candidates) {\n if (fs.existsSync(dir)) return dir\n }\n return path.join(root, 'src', 'routes')\n}\n\nfunction findStaticDir(root: string): string {\n const candidates = [path.join(root, 'static'), path.join(root, 'public')]\n for (const dir of candidates) {\n if (fs.existsSync(dir)) return dir\n }\n return path.join(root, 'static')\n}\n","import fs from 'fs'\nimport path from 'path'\nimport type { ComponentRelation } from '../types.js'\n\nexport function analyzeComponents(root: string): ComponentRelation[] {\n const srcDir = path.join(root, 'src')\n if (!fs.existsSync(srcDir)) return []\n\n const svelteFiles: string[] = []\n findSvelteFiles(srcDir, svelteFiles)\n\n return svelteFiles.map(file => {\n const content = fs.readFileSync(file, 'utf-8')\n const imports = extractSvelteImports(content, file)\n const name = getComponentName(file)\n\n return {\n file: path.relative(root, file),\n name,\n imports: imports.map(i => path.relative(root, i)),\n }\n })\n}\n\nfunction findSvelteFiles(dir: string, files: string[]): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === '.svelte-kit') continue\n findSvelteFiles(fullPath, files)\n } else if (entry.name.endsWith('.svelte')) {\n files.push(fullPath)\n }\n }\n}\n\nfunction extractSvelteImports(content: string, filePath: string): string[] {\n const imports: string[] = []\n const dir = path.dirname(filePath)\n\n // Match: import X from './Component.svelte'\n // Match: import X from '$lib/Component.svelte' (SvelteKit 2) or '#lib/…' (SvelteKit 3)\n const importRegex = /import\\s+[\\w{}\\s,*]+\\s+from\\s+['\"]([^'\"]+\\.svelte)['\"]/g\n let match: RegExpExecArray | null\n\n while ((match = importRegex.exec(content)) !== null) {\n const importPath = match[1]\n const resolved = resolveImportPath(importPath, dir, filePath)\n if (resolved) imports.push(resolved)\n }\n\n return imports\n}\n\nfunction resolveImportPath(importPath: string, dir: string, fromFile: string): string | null {\n // $lib alias (SvelteKit 2) or the `#lib/*` subpath import SvelteKit 3 uses\n // instead, both conventionally mapped to src/lib\n if (importPath.startsWith('$lib/') || importPath.startsWith('#lib/')) {\n const root = findProjectRoot(fromFile)\n if (root) {\n const libPath = path.join(root, 'src', 'lib', importPath.slice(5))\n if (fs.existsSync(libPath)) return libPath\n }\n return null\n }\n\n // Relative import\n if (importPath.startsWith('.')) {\n const resolved = path.resolve(dir, importPath)\n if (fs.existsSync(resolved)) return resolved\n }\n\n return null\n}\n\nfunction findProjectRoot(filePath: string): string | null {\n let dir = path.dirname(filePath)\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, 'package.json'))) return dir\n dir = path.dirname(dir)\n }\n return null\n}\n\nfunction getComponentName(filePath: string): string {\n return path.basename(filePath, '.svelte')\n}\n","// This code is injected into the user's app as a virtual module.\n// It tracks Svelte component mount/unmount and sends data to the Vite server via HMR.\nexport const RUNTIME_MODULE_ID = 'virtual:svelte-devtools-runtime'\nexport const RESOLVED_RUNTIME_ID = '\\0' + RUNTIME_MODULE_ID\n\n// Virtual module ID for the svelte/internal/client wrapper.\n// When user code imports 'svelte/internal/client', it is redirected to this module.\n// The wrapper re-exports everything and overrides key functions for devtools tracking.\nexport const WRAPPER_MODULE_ID = '\\0svelte-devtools:wrapped-client'\n\n/**\n * Wrapper code for svelte/internal/client.\n *\n * Re-exports everything from the real module, then overrides:\n * - push/pop: component lifecycle tracking\n * - tag/tag_proxy: named signal/proxy tracking (Svelte dev mode)\n * - state/derived/proxy: type markers consumed by tag/tag_proxy\n * - user_effect/user_pre_effect: effect tracking\n * - template_effect/deferred_template_effect: render count/time profiling\n * - each/if/key/await/component/boundary: block-callback owner attribution\n *\n * This single module replaces all post-compilation regex transforms\n * for reactive tracking, making the approach Svelte-compiler-output agnostic.\n */\nexport const wrapperCode = /* js */ `\nimport * as __svelte_original from 'svelte/internal/client';\nexport * from 'svelte/internal/client';\n\nfunction __dt() {\n return typeof window !== 'undefined' ? window.__SVELTE_DEVTOOLS__ : null;\n}\n\n// Component ID stack (parallel to runtime._stack but local to wrapper)\nconst __idStack = [];\nfunction __currentId() {\n return __idStack.length > 0 ? __idStack[__idStack.length - 1] : null;\n}\n\n// Tracks the most recently created signal for type determination in tag()\nconst __pendingSignal = { ref: null, type: null };\n\n// Component context -> devtools id (review B1b). A component created later\n// by a block update ({#each}/{#if} after mount) runs outside its parent's\n// push..pop, where the runtime's init stack is empty (the wrapper stack\n// below covers the wrapped block helpers; this covers the rest). Svelte (5.56.8,\n// internal/client) exports active_effect; every effect records the\n// component context it was created in (effect.ctx) and runs with that\n// context restored. The block effect that creates the child belongs to the\n// parent's template, so active_effect.ctx at push time IS the parent's\n// context. Each context is mapped to its id once the component mounted\n// (inside its own deferred effect, where active_effect.ctx is the\n// component's own context). Weak map: no leak, no Svelte state touched.\nconst __idByContext = new WeakMap();\nfunction __parentFromContext() {\n const effect = __svelte_original.active_effect;\n const ctx = effect ? effect.ctx : null;\n return ctx ? __idByContext.get(ctx) : undefined;\n}\n\n// --- Component Lifecycle ---\n//\n// Observer must not break the observed: every devtools side-effect below is\n// wrapped in try/catch so a bug or an out-of-shape runtime cannot tear down\n// the user's app. The original Svelte function is always called, and its\n// return value always returned, regardless of devtools failures.\n\nexport function push() {\n // Parent hint, read before this component's own id exists:\n // 1. the wrapper stack: the component whose init is running (children\n // rendered directly by a template, where active_effect still belongs to\n // an outer block), or the block owner re-pushed by __wrapBlockFn for a\n // later {#each}/{#if}/{#key} update (see Block Attribution below);\n // 2. else the context-derived owner, for re-creation paths the wrapper\n // does not wrap (snippet, svelte:element, ...).\n let parentHint = null;\n try { parentHint = __currentId(); } catch {}\n if (parentHint === null) {\n try { parentHint = __parentFromContext(); } catch {}\n }\n const result = __svelte_original.push.apply(null, arguments);\n try {\n const dt = __dt();\n if (dt) {\n const file = dt._pendingFile || 'Unknown';\n dt._pendingFile = null;\n dt._pendingParent = parentHint;\n const id = dt.register(file);\n __idStack.push(id);\n dt.startInit(id);\n try {\n __svelte_original.user_effect(() => {\n try {\n const own = __svelte_original.active_effect;\n if (own && own.ctx) __idByContext.set(own.ctx, id);\n } catch {}\n return () => { try { dt.unmount(id); } catch {} };\n });\n } catch {}\n }\n } catch {}\n return result;\n}\n\nexport function pop() {\n // Capture devtools errors but ALWAYS forward to the original pop so the\n // Svelte component stack stays balanced.\n try {\n const dt = __dt();\n if (dt && __idStack.length > 0) {\n const id = __idStack.pop();\n try { dt.endInit(id); } catch {}\n try { dt.registered(id); } catch {}\n }\n } catch {}\n return __svelte_original.pop.apply(null, arguments);\n}\n\n// --- Signal Creation (type markers) ---\n\nexport function state() {\n const signal = __svelte_original.state.apply(null, arguments);\n try {\n __pendingSignal.ref = signal;\n __pendingSignal.type = 'state';\n } catch {}\n return signal;\n}\n\nexport function derived() {\n const signal = __svelte_original.derived.apply(null, arguments);\n try {\n __pendingSignal.ref = signal;\n __pendingSignal.type = 'derived';\n } catch {}\n return signal;\n}\n\nexport function proxy() {\n const p = __svelte_original.proxy.apply(null, arguments);\n try {\n __pendingSignal.ref = p;\n __pendingSignal.type = 'proxy';\n } catch {}\n return p;\n}\n\n// --- Signal Tagging (Svelte dev mode) ---\n\nexport function tag(signal, name) {\n const result = __svelte_original.tag.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n const type = (__pendingSignal.ref === signal) ? __pendingSignal.type : 'state';\n if (type === 'derived') {\n dt.trackDerived(signal, name, cid);\n } else {\n dt.trackState(signal, name, cid);\n }\n }\n __pendingSignal.ref = null;\n __pendingSignal.type = null;\n } catch {}\n return result;\n}\n\nexport function tag_proxy(proxy, name) {\n const result = __svelte_original.tag_proxy.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt.trackProxy(proxy, name, cid);\n }\n __pendingSignal.ref = null;\n __pendingSignal.type = null;\n } catch {}\n return result;\n}\n\n// --- Effect Tracking ---\n\nexport function user_effect() {\n const result = __svelte_original.user_effect.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt._effectCounter = (dt._effectCounter || 0) + 1;\n // Track the effect OBJECT (not the callback). The Svelte runtime\n // populates result.deps with the signals this effect depends on,\n // which is what getReactiveGraph() reads to build edges.\n dt.trackEffect(result, 'effect_' + dt._effectCounter, cid);\n }\n } catch {}\n return result;\n}\n\nexport function user_pre_effect() {\n const result = __svelte_original.user_pre_effect.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __currentId();\n if (dt && cid !== null) {\n dt._effectCounter = (dt._effectCounter || 0) + 1;\n dt.trackEffect(result, 'effect_pre_' + dt._effectCounter, cid);\n }\n } catch {}\n return result;\n}\n\n// --- Render Profiling ---\n//\n// Svelte 5 has no virtual DOM: the compiler wraps every dynamic part of a\n// template in a template_effect (deferred_template_effect for <svelte:head>\n// <title>). A re-run of such an effect IS the component updating the DOM, so\n// these two functions are the measurement points for renders / render time.\n//\n// The first run of an effect is the mount-time paint, already covered by\n// initTime, so it is skipped (initialRun). One state change re-runs several\n// effects of the same component, so durations are pooled per microtask and\n// recorded once per flush: recordRender() +1, recordRenderTime() the sum.\n\nconst __pendingRenderDurations = new Map();\nlet __renderFlushScheduled = false;\n\nfunction __flushRenderDurations() {\n __renderFlushScheduled = false;\n const dt = __dt();\n for (const [cid, duration] of __pendingRenderDurations) {\n if (dt) {\n try { dt.recordRender(cid); } catch {}\n try { dt.recordRenderTime(cid, duration); } catch {}\n }\n }\n __pendingRenderDurations.clear();\n}\n\nfunction __recordRenderDuration(cid, duration) {\n __pendingRenderDurations.set(cid, (__pendingRenderDurations.get(cid) || 0) + duration);\n if (!__renderFlushScheduled) {\n __renderFlushScheduled = true;\n queueMicrotask(__flushRenderDurations);\n }\n}\n\n// Returns a (possibly new) args array whose first element times each re-run\n// of the effect closure. The owning component is whatever id is on top of\n// __idStack at effect-creation time. User exceptions propagate untouched;\n// only the args are built inside try so the original is called exactly once.\nfunction __wrapTemplateEffect(args) {\n const cid = __currentId();\n const fn = args[0];\n if (cid === null || typeof fn !== 'function') return args;\n const wrapped = Array.prototype.slice.call(args);\n let initialRun = true;\n wrapped[0] = function () {\n if (initialRun) {\n initialRun = false;\n return fn.apply(this, arguments);\n }\n const start = performance.now();\n try {\n return fn.apply(this, arguments);\n } finally {\n try { __recordRenderDuration(cid, performance.now() - start); } catch {}\n }\n };\n return wrapped;\n}\n\nexport function template_effect() {\n let args = arguments;\n try { args = __wrapTemplateEffect(arguments); } catch {}\n return __svelte_original.template_effect.apply(null, args);\n}\n\nexport function deferred_template_effect() {\n let args = arguments;\n try { args = __wrapTemplateEffect(arguments); } catch {}\n return __svelte_original.deferred_template_effect.apply(null, args);\n}\n\n// --- Block Attribution ---\n//\n// Svelte creates render effects synchronously at creation time. At mount this\n// happens during the component function (between push/pop), so __idStack has\n// the owner. But effects for {#each} items added later or re-created {#if}\n// branches are created during a batch flush, when the stack is empty — they\n// would never be attributed. Block helpers themselves ARE always called\n// during their owner's init (or inside an outer block's callback), so the\n// owner id is on the stack at block-creation time. __wrapBlock captures it\n// and re-pushes it around every function argument the block invokes later,\n// so effects created inside land on the innermost owner. Child components\n// push their own id on top, keeping nested attribution correct.\n\nfunction __wrapBlockFn(fn, cid) {\n return function () {\n let pushed = false;\n try { __idStack.push(cid); pushed = true; } catch {}\n try {\n return fn.apply(this, arguments);\n } finally {\n if (pushed) { try { __idStack.pop(); } catch {} }\n }\n };\n}\n\nfunction __wrapBlock(args) {\n const cid = __currentId();\n if (cid === null) return args;\n const wrapped = Array.prototype.slice.call(args);\n for (let i = 0; i < wrapped.length; i++) {\n if (typeof wrapped[i] === 'function') wrapped[i] = __wrapBlockFn(wrapped[i], cid);\n }\n return wrapped;\n}\n\nexport function each() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.each.apply(null, args);\n}\n\nexport function key() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.key.apply(null, args);\n}\n\nexport function component() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.component.apply(null, args);\n}\n\nexport function boundary() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.boundary.apply(null, args);\n}\n\n// 'if' and 'await' are reserved words, so they cannot be declared as\n// function names and are exported via aliases instead.\nfunction __if_block() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original['if'].apply(null, args);\n}\n\nfunction __await_block() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original['await'].apply(null, args);\n}\n\nexport { __if_block as if, __await_block as await };\n`\n\nexport const runtimeCode = /* js */ `\nif (typeof window !== 'undefined' && !window.__SVELTE_DEVTOOLS__) {\n const __NO_VALUE = Symbol('no value');\n // State timeline ring (§6.7 C): every read sees at most 500 entries and\n // __TIMELINE_BYTES (also the server's buffer budget). The raw array may\n // hold up to __TIMELINE_TRIM_AT (2 x the 500 cap) between bulk trims.\n const __TIMELINE_BYTES = 4 * 1024 * 1024;\n const __TIMELINE_TRIM_AT = 1000;\n // FNV-1a over UTF-16 code units: cheap change detection for large snapshots.\n const __hash = (str) => {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(36);\n };\n const __SVELTE_DT = {\n _nextId: 0,\n _instances: new Map(),\n _stack: [],\n _pendingParent: undefined,\n _pendingFile: null,\n _effectCounter: 0,\n _debounceTimer: null,\n _listeners: new Set(),\n\n // Phase 2: Profiling data\n _profiles: new Map(),\n _initStartTimes: new Map(),\n _profileDebounceTimer: null,\n\n // Phase 2: Reactive graph data\n _reactiveNodes: new Map(),\n _reactiveProxies: new Map(),\n\n // componentId -> Set<nodeId>. Lets unmount purge a component's reactive\n // nodes without scanning every node of the app (was O(components x nodes)).\n _nodesByComponent: new Map(),\n\n // Phase 3: State timeline\n _stateTimeline: [],\n _stateSnapshots: new Map(),\n _timelineDebounceTimer: null,\n // signal (or proxy marker) -> nodeId, set at track time and removed by\n // _forgetNode: a scoped graph resolves dependencies without scanning\n // every node (§6.7 D).\n _idBySignal: new WeakMap(),\n // Polling bookkeeping (§6.7 D): $state node ids in a dense array kept up\n // to date incrementally (_pollIndex: nodeId -> position; removal is\n // swap-with-last), a cursor carried across ticks, nodes found changed but\n // not yet serialized (_pollDirty), and per-node change hints\n // (nodeId -> { ref, wv, nextCheckAt }).\n _pollIds: [],\n _pollIndex: new Map(),\n _pollCursor: 0,\n _pollDirty: new Set(),\n // Full-sweep bookkeeping: how long the last complete pass over all $state\n // nodes took (ms), for disclosure (= the worst-case detection delay).\n _pollSweep: { startedAt: 0, lastMs: null, nodes: 0 },\n _pollMeta: new Map(),\n _deepCredit: 0,\n _lastSnapshotSize: new Map(),\n _timelineSeq: 0,\n _pushedSeq: 0,\n _timelineReset: false,\n _entryInfo: new WeakMap(),\n // Sum of _entryInfo.bytes over _stateTimeline (runtime byte budget).\n _timelineBytes: 0,\n // Disclosure since the last push (§6.7 C): unsent entries the ring removed\n // (by count / by bytes) and changes recorded only as a size summary.\n _timelineDropped: { 'runtime-count': 0, 'runtime-bytes': 0 },\n _valueTooLarge: 0,\n\n // Overview aggregate (§6.7 I/J), O(1) per event: registered nodes per\n // component and type (+ app totals), and per-component activity in a\n // ring of 60 one-second buckets (sampled changes, renders, render ms,\n // plus how long sampling ran in that second).\n _nodeCounts: new Map(),\n _nodeTotals: { state: 0, derived: 0, effect: 0 },\n _activity: [],\n _epoch: Math.random().toString(36).slice(2) + Date.now().toString(36),\n\n // --- Activity subscription (docs/devframe-migration.md §6.3) ---\n // Inactive until the server says a DevTools client (UI tab or MCP lease)\n // is watching: no state polling, FPS rAF loop, or periodic HMR sends.\n _active: false,\n _componentsCost: { ms: 0, bytes: 0 },\n _componentDeltas: false,\n _pendingAdded: new Set(),\n _pendingRemoved: new Set(),\n _lastFullAt: 0,\n _resync: false,\n _profilesCost: { ms: 0, bytes: 0 },\n // = collector LIMITS.renderProfiles (pinned by a unit test): the server\n // keeps only the newest entries, so sending more is wasted bytes.\n _profileCap: 5000,\n _sampling: null,\n _baselining: false,\n // Polled state nodes not observed yet (no seed value). Their first\n // observation is a seed, not a change: no timeline entry, no activity\n // count, no drops — the old value is unknown, not null (review B-1/B-2).\n _unseeded: new Set(),\n // pendingNodes last sent on a state-timeline message (null = none yet)\n _sentPendingNodes: null,\n _fpsGen: 0,\n\n register(file) {\n const id = this._nextId++;\n // Parent: the wrapper's context-derived hint (components created by a\n // later block update, review B1b) when it names a live instance, else\n // the synchronous init stack (children created during the parent's own\n // init, before the parent is mapped).\n const hint = this._pendingParent;\n this._pendingParent = undefined;\n const parentId =\n hint !== undefined && hint !== null && this._instances.has(hint)\n ? hint\n : this._stack.length > 0 ? this._stack[this._stack.length - 1] : null;\n const name = file.split('/').pop()?.replace('.svelte', '') || 'Unknown';\n // children is a Set so unmounting one row of a 5 000-row list is O(1).\n this._instances.set(id, { id, file, name, parentId, mounted: true, children: new Set() });\n if (parentId !== null) {\n const parent = this._instances.get(parentId);\n if (parent) parent.children.add(id);\n }\n this._stack.push(id);\n if (this._active) this._pendingAdded.add(id);\n this._scheduleUpdate();\n return id;\n },\n\n registered(id) {\n const idx = this._stack.indexOf(id);\n if (idx !== -1) this._stack.splice(idx, 1);\n },\n\n mount(id) {\n const instance = this._instances.get(id);\n if (instance && !instance.mounted) {\n instance.mounted = true;\n if (this._active) this._pendingAdded.add(id);\n this._scheduleUpdate();\n }\n },\n\n unmount(id) {\n const instance = this._instances.get(id);\n if (instance) {\n if (instance.parentId !== null) {\n const parent = this._instances.get(instance.parentId);\n if (parent) parent.children.delete(id);\n }\n this._removeChildren(id);\n this._cleanupComponent(id);\n }\n this._scheduleUpdate();\n this._scheduleProfileUpdate();\n },\n\n // Remounts get a fresh id, so entries keyed by a dead id would otherwise\n // survive forever — every per-component map must be purged here.\n _cleanupComponent(id) {\n // Delta bookkeeping: an id added and removed between two pushes was\n // never sent, so it cancels out.\n if (this._active && !this._pendingAdded.delete(id)) this._pendingRemoved.add(id);\n this._cleanupReactiveNodes(id);\n this._instances.delete(id);\n this._profiles.delete(id);\n this._initStartTimes.delete(id);\n },\n\n _cleanupReactiveNodes(componentId) {\n const nodeIds = this._nodesByComponent.get(componentId);\n if (!nodeIds) return;\n this._nodesByComponent.delete(componentId);\n for (const nodeId of nodeIds) this._forgetNode(nodeId);\n },\n\n _forgetNode(nodeId) {\n const entry = this._reactiveNodes.get(nodeId);\n if (entry) this._countNode(entry.meta.componentId, entry.meta.type, -1);\n const signal = entry && entry.signal.deref();\n if (signal && this._idBySignal.get(signal) === nodeId) this._idBySignal.delete(signal);\n this._pollRemove(nodeId);\n this._pollDirty.delete(nodeId);\n this._reactiveNodes.delete(nodeId);\n this._reactiveProxies.delete(nodeId);\n this._stateSnapshots.delete(nodeId);\n if (this._stateSnapshotStrs) this._stateSnapshotStrs.delete(nodeId);\n this._pollMeta.delete(nodeId);\n this._lastSnapshotSize.delete(nodeId);\n },\n\n _indexNode(nodeId, componentId) {\n let set = this._nodesByComponent.get(componentId);\n if (!set) {\n set = new Set();\n this._nodesByComponent.set(componentId, set);\n }\n set.add(nodeId);\n },\n\n _pollAdd(nodeId) {\n if (this._pollIndex.has(nodeId)) return;\n if (!this._stateSnapshots.has(nodeId)) this._unseeded.add(nodeId);\n this._pollIndex.set(nodeId, this._pollIds.length);\n this._pollIds.push(nodeId);\n },\n\n // O(1): the last id takes the removed slot. If that slot is behind the\n // cursor, the moved id is visited in the next sweep instead of this one\n // (still visited within a bounded number of ticks).\n // Before a track* call replaces/creates nodeId: move the count from the\n // previous registration (same name re-tracked) to the new one.\n _trackNodeCount(nodeId, componentId, type) {\n const prev = this._reactiveNodes.get(nodeId);\n if (prev) this._countNode(prev.meta.componentId, prev.meta.type, -1);\n this._countNode(componentId, type, 1);\n },\n\n _countNode(componentId, type, d) {\n const kind = type === 'derived' || type === 'effect' ? type : 'state';\n let c = this._nodeCounts.get(componentId);\n if (!c) {\n if (d < 0) return;\n c = { state: 0, derived: 0, effect: 0 };\n this._nodeCounts.set(componentId, c);\n }\n c[kind] += d;\n this._nodeTotals[kind] += d;\n if (c.state + c.derived + c.effect <= 0) this._nodeCounts.delete(componentId);\n },\n\n _bucket() {\n const sec = Math.floor(performance.now() / 1000);\n const slot = ((sec % 60) + 60) % 60;\n let b = this._activity[slot];\n if (!b || b.second !== sec) {\n b = { second: sec, sampledMs: 0, rows: new Map() };\n this._activity[slot] = b;\n }\n return b;\n },\n\n _activityRow(componentId) {\n const rows = this._bucket().rows;\n let r = rows.get(componentId);\n if (!r) {\n r = { changes: 0, renders: 0, renderMs: 0 };\n rows.set(componentId, r);\n }\n return r;\n },\n\n _pollRemove(nodeId) {\n const i = this._pollIndex.get(nodeId);\n if (i === undefined) return;\n this._unseeded.delete(nodeId);\n const ids = this._pollIds;\n const last = ids.pop();\n this._pollIndex.delete(nodeId);\n if (i < ids.length) {\n ids[i] = last;\n this._pollIndex.set(last, i);\n }\n },\n\n _removeChildren(parentId) {\n const parent = this._instances.get(parentId);\n if (!parent) return;\n for (const childId of [...parent.children]) {\n this._removeChildren(childId);\n this._cleanupComponent(childId);\n }\n },\n\n // Full-list pushes are throttled, not debounced: a pending timer is not\n // reset, so continuous churn still produces updates (a debounce would\n // starve), and the interval adapts to the last push's cost so a 10 000+\n // instance app can't spend its main thread serializing (review P3):\n // max(min, 20 x last send ms, 1 s when the last payload exceeded ~1 MB).\n _sendInterval(cost, min) {\n return Math.max(min, 20 * cost.ms, cost.bytes > 1000000 ? 1000 : 0);\n },\n\n _scheduleUpdate() {\n if (!this._active || this._debounceTimer) return;\n this._debounceTimer = setTimeout(() => {\n this._debounceTimer = null;\n this._sendUpdate();\n }, this._sendInterval(this._componentsCost, 100));\n },\n\n // components push (§6.5). Full form { epoch, components } replaces the\n // server's tree for this epoch: sent on activation, when the server does\n // not advertise componentDeltas, as a periodic checkpoint, or when the\n // delta would be larger than the tree. Otherwise the delta form\n // { epoch, added, removed } (removed ids first, ≤ 2 000 entries per\n // message, added in registration order = parents first).\n _sendUpdate(forceFull) {\n // Nobody watching: keep the registry, skip the O(N) payload. A full\n // snapshot is sent on activation (§6.3).\n if (!this._active) return;\n const t0 = performance.now();\n const CHUNK = 2000;\n const CHECKPOINT_MS = 30000;\n const pending = this._pendingAdded.size + this._pendingRemoved.size;\n const full =\n forceFull ||\n !this._componentDeltas ||\n t0 - this._lastFullAt >= CHECKPOINT_MS ||\n pending > this._instances.size;\n const toEntry = (instance) => ({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n });\n let bytes = 0;\n const msgs = [];\n if (full) {\n const components = [];\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push(toEntry(instance));\n bytes += instance.file.length + instance.name.length + 72;\n }\n }\n msgs.push({ epoch: this._epoch, reset: true, components });\n this._lastFullAt = t0;\n } else if (pending > 0) {\n const removed = [...this._pendingRemoved];\n const added = [];\n for (const id of this._pendingAdded) {\n const instance = this._instances.get(id);\n if (instance && instance.mounted) {\n added.push(toEntry(instance));\n bytes += instance.file.length + instance.name.length + 72;\n }\n }\n bytes += removed.length * 8;\n for (let r = 0; r < removed.length; r += CHUNK) {\n msgs.push({ epoch: this._epoch, added: [], removed: removed.slice(r, r + CHUNK) });\n }\n for (let a = 0; a < added.length; a += CHUNK) {\n msgs.push({ epoch: this._epoch, added: added.slice(a, a + CHUNK), removed: [] });\n }\n }\n this._pendingAdded.clear();\n this._pendingRemoved.clear();\n if (import.meta.hot) {\n for (const msg of msgs) import.meta.hot.send('svelte-devtools:components', msg);\n }\n this._componentsCost = { ms: performance.now() - t0, bytes };\n },\n\n getTree() {\n const components = [];\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n });\n }\n }\n return components;\n },\n\n // --- Phase 2: Render Profiling ---\n\n startInit(id) {\n this._initStartTimes.set(id, performance.now());\n },\n\n endInit(id) {\n const start = this._initStartTimes.get(id);\n if (start === undefined) return;\n const initTime = performance.now() - start;\n this._initStartTimes.delete(id);\n const instance = this._instances.get(id);\n if (!instance) return;\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime,\n renderCount: 0,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n });\n this._scheduleProfileUpdate();\n },\n\n recordRender(id) {\n const profile = this._profiles.get(id);\n if (!profile) {\n const instance = this._instances.get(id);\n if (!instance) return;\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime: 0,\n renderCount: 1,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n });\n } else {\n profile.renderCount++;\n profile.lastRenderAt = Date.now();\n }\n this._activityRow(id).renders++;\n this._scheduleProfileUpdate();\n },\n\n recordRenderTime(id, duration) {\n const profile = this._profiles.get(id);\n if (profile) {\n profile.totalRenderTime += duration;\n profile.lastRenderTime = duration;\n this._activityRow(id).renderMs += duration;\n }\n },\n\n // Profiles push (review P-1 Option A; contract in\n // docs/performance-status.md). Throttled like components, but the floor\n // grows with the payload: every push carries the whole retained map, so\n // a large app coalesces bursts instead of resending ~1 MB twice a second.\n // Hard cap 2 s (contract R6): a slow serialization must not stretch the\n // latency beyond it.\n _profileInterval() {\n const cost = this._profilesCost;\n return Math.min(\n 2000,\n Math.max(500, 20 * cost.ms, cost.bytes > 1000000 ? 2000 : cost.bytes > 250000 ? 1000 : 0),\n );\n },\n\n _scheduleProfileUpdate() {\n if (!this._active || this._profileDebounceTimer) return;\n this._profileDebounceTimer = setTimeout(() => {\n this._profileDebounceTimer = null;\n this._sendProfileUpdate();\n }, this._profileInterval());\n },\n\n // Also the forced path (activation / resync): a pending throttled push is\n // cancelled so the same state is not sent twice.\n _sendProfileUpdate() {\n if (this._profileDebounceTimer) {\n clearTimeout(this._profileDebounceTimer);\n this._profileDebounceTimer = null;\n }\n if (!this._active) return;\n const t0 = performance.now();\n const all = Array.from(this._profiles.values());\n // Exactly what the collector retains: its tail, in the same order.\n const profiles = all.length > this._profileCap ? all.slice(all.length - this._profileCap) : all;\n if (import.meta.hot) {\n // total = all retained profiles; the message carries the newest-mounted\n // tail (§6.7 J IA1 capture policy 'newest-mounted').\n import.meta.hot.send('svelte-devtools:profiles', { epoch: this._epoch, profiles, total: all.length });\n }\n // Payload size from a small sample (entries differ mainly by file path).\n const k = Math.min(8, profiles.length);\n let sampled = 0;\n for (let i = 0; i < k; i++) sampled += JSON.stringify(profiles[i]).length;\n const bytes = k > 0 ? Math.round((sampled / k) * profiles.length) : 0;\n this._profilesCost = { ms: performance.now() - t0, bytes };\n },\n\n getProfiles() {\n return Array.from(this._profiles.values());\n },\n\n resetProfiles() {\n this._profiles.clear();\n this._scheduleProfileUpdate();\n },\n\n // --- Phase 2: Reactive Graph Tracking ---\n\n trackState(signal, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._trackNodeCount(nodeId, componentId, 'state');\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(signal),\n meta: { id: nodeId, type: 'state', name, componentId, componentFile: instance ? instance.file : '' }\n });\n this._idBySignal.set(signal, nodeId);\n this._indexNode(nodeId, componentId);\n this._pollAdd(nodeId);\n },\n\n trackProxy(proxy, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._reactiveProxies.set(nodeId, new WeakRef(proxy));\n // The proxy itself stays weakly held (_reactiveProxies). The marker is\n // held strongly so the node is not GC-dropped while the component lives;\n // _cleanupComponent removes it on unmount.\n const marker = { v: '(proxy)', _isProxy: true };\n this._trackNodeCount(nodeId, componentId, 'state');\n this._reactiveNodes.set(nodeId, {\n signal: { deref: () => marker },\n meta: { id: nodeId, type: 'state', name, componentId, componentFile: instance ? instance.file : '' }\n });\n this._idBySignal.set(marker, nodeId);\n this._indexNode(nodeId, componentId);\n this._pollAdd(nodeId);\n },\n\n trackDerived(signal, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n this._trackNodeCount(nodeId, componentId, 'derived');\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(signal),\n meta: { id: nodeId, type: 'derived', name, componentId, componentFile: instance ? instance.file : '' }\n });\n this._idBySignal.set(signal, nodeId);\n this._indexNode(nodeId, componentId);\n },\n\n trackEffect(effect, name, componentId) {\n const instance = this._instances.get(componentId);\n const nodeId = componentId + ':' + name;\n const target = effect || { v: undefined, _isEffect: true };\n this._trackNodeCount(nodeId, componentId, 'effect');\n this._reactiveNodes.set(nodeId, {\n signal: new WeakRef(target),\n meta: { id: nodeId, type: 'effect', name, componentId, componentFile: instance ? instance.file : '' }\n });\n this._idBySignal.set(target, nodeId);\n this._indexNode(nodeId, componentId);\n return effect;\n },\n\n _graphNode(nodeId, entry, signal) {\n const node = { ...entry.meta };\n if (signal._isProxy) {\n const proxy = this._reactiveProxies.get(nodeId)?.deref();\n if (proxy) {\n try {\n node.value = Array.isArray(proxy) ? '[' + proxy.length + ']' : '{' + Object.keys(proxy).length + '}';\n } catch { node.value = '(proxy)'; }\n }\n } else if (node.type !== 'effect' && signal.v !== undefined && typeof signal.v !== 'symbol') {\n try {\n const v = signal.v;\n if (typeof v === 'number' || typeof v === 'string' || typeof v === 'boolean' || v === null) {\n node.value = v;\n } else {\n node.value = '(object)';\n }\n } catch { /* ignore */ }\n }\n return node;\n },\n\n // Reactive graph (§6.7 A/D). Caps are applied while building: past\n // maxNodes no node objects are created and only edges whose endpoints\n // are both included are emitted (the rest are counted in edgesOmitted).\n // - scoped (componentId): that component's nodes plus the tracked nodes\n // directly connected to them (via deps / reactions through untracked\n // intermediates). Dependencies are resolved through _idBySignal, so\n // the cost is O(scope + neighbours), not O(all nodes). The walk is\n // completed even past the cap, so total.nodes/edges are exact.\n // - global: nodes in registration order up to maxNodes ('global-head'),\n // with their incoming dependency edges. Nodes past the cap are not\n // dereferenced; total.nodes is the registered count (may include\n // nodes whose signal was already collected, nodesKind 'registered')\n // and total.edges is null when the walk stopped early (not guessed).\n getReactiveGraph(componentId, caps) {\n const scoped = componentId !== undefined && componentId !== null;\n const maxNodes = this._graphCap(caps && caps.maxNodes, 5000);\n const maxEdges = this._graphCap(caps && caps.maxEdges, 20000);\n const live = new Map();\n // Live signal of a tracked node, or null (forgets dead / unmounted nodes).\n const liveSignal = (nodeId) => {\n if (live.has(nodeId)) return live.get(nodeId);\n const entry = this._reactiveNodes.get(nodeId);\n let signal = entry ? entry.signal.deref() : null;\n if (entry && (!signal || !this._instances.has(entry.meta.componentId))) {\n this._forgetNode(nodeId);\n signal = null;\n }\n live.set(nodeId, signal || null);\n return signal || null;\n };\n const idOf = (dep) => {\n const id = this._idBySignal.get(dep);\n return id !== undefined && liveSignal(id) === dep ? id : null;\n };\n\n const included = new Set();\n const seen = new Set();\n const edges = [];\n const edgeSet = new Set();\n let edgesOmitted = 0;\n let truncated = false;\n const see = (id) => {\n seen.add(id);\n if (!included.has(id) && included.size < maxNodes) included.add(id);\n return included.has(id);\n };\n const addEdge = (from, to) => {\n const key = from + '>' + to;\n if (from === to || edgeSet.has(key)) return;\n edgeSet.add(key);\n const inFrom = see(from);\n const inTo = see(to);\n if (inFrom && inTo && edges.length < maxEdges) edges.push({ from, to });\n else edgesOmitted++;\n };\n // Walk a signal's neighbours (deps or reactions) through untracked\n // intermediates until tracked nodes are reached.\n const walk = (start, field, onHit) => {\n if (!start) return;\n const visited = new Set();\n const queue = [...start];\n // Index cursor instead of queue.shift(): shift is O(queue) per pop.\n for (let qi = 0; qi < queue.length; qi++) {\n const dep = queue[qi];\n if (!dep || visited.has(dep)) continue;\n visited.add(dep);\n const id = idOf(dep);\n if (id) onHit(id);\n else if (dep[field]) for (const d of dep[field]) queue.push(d);\n }\n };\n\n let totalNodes = 0;\n let totalEdges = null;\n if (scoped) {\n for (const nodeId of [...(this._nodesByComponent.get(componentId) || [])]) {\n const signal = liveSignal(nodeId);\n if (!signal) continue;\n see(nodeId);\n walk(signal.deps, 'deps', (depId) => addEdge(depId, nodeId));\n walk(signal.reactions, 'reactions', (rId) => addEdge(nodeId, rId));\n }\n totalNodes = seen.size;\n totalEdges = edgeSet.size;\n truncated = included.size < seen.size || edgesOmitted > 0;\n } else {\n let complete = true;\n for (const nodeId of [...this._reactiveNodes.keys()]) {\n if (included.size >= maxNodes && !included.has(nodeId)) {\n complete = false;\n break;\n }\n const signal = liveSignal(nodeId);\n if (!signal) continue;\n see(nodeId);\n walk(signal.deps, 'deps', (depId) => addEdge(depId, nodeId));\n }\n // registered count, minus nodes found dead while building\n totalNodes = this._reactiveNodes.size;\n totalEdges = complete ? edgeSet.size : null;\n truncated = !complete || edgesOmitted > 0;\n }\n\n const nodes = [];\n for (const nodeId of included) {\n const signal = liveSignal(nodeId);\n if (signal) nodes.push(this._graphNode(nodeId, this._reactiveNodes.get(nodeId), signal));\n }\n return {\n scope: scoped ? componentId : null,\n nodes,\n edges,\n total: { nodes: totalNodes, nodesKind: 'registered', edges: totalEdges },\n truncated,\n edgesOmitted,\n policy: scoped ? 'scoped' : 'global-head',\n };\n },\n\n _graphCap(value, max) {\n const n = Math.floor(Number(value));\n return Number.isFinite(n) && n >= 1 ? Math.min(n, max) : max;\n },\n\n // Request (§6.7 A + review M1): { requestId?, epoch?, componentId?,\n // maxNodes?, maxEdges? }. A request for another page load (epoch) is not\n // answered by this one; the reply echoes requestId and epoch. An old\n // server sends {} → global graph with the default caps (= its LIMITS).\n sendReactiveGraph(request) {\n const req = request || {};\n if (req.epoch !== undefined && req.epoch !== null && req.epoch !== this._epoch) return;\n const cid = typeof req.componentId === 'number' ? req.componentId : null;\n const graph = this.getReactiveGraph(cid, { maxNodes: req.maxNodes, maxEdges: req.maxEdges });\n graph.epoch = this._epoch;\n // freshness (review): when this answer was built; caches keep it\n graph.computedAt = Date.now();\n if (req.requestId !== undefined) graph.requestId = req.requestId;\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:reactive-graph', graph);\n }\n },\n\n // Overview aggregate (§6.7 I/J). Built from the activity buckets of the\n // window (whole seconds: the current partial second plus the previous\n // ones, ceil(windowMs / 1000) buckets) — cost O(components active in the\n // window), no graph, no node scan. Rows rank by sampled changes, then\n // renders, then render ms; rows + other = total (components and nodes).\n getReactiveSummary(opts) {\n const o = opts || {};\n const clampInt = (v, lo, hi, d) => {\n const n = Math.floor(Number(v));\n return Number.isFinite(n) ? Math.min(hi, Math.max(lo, n)) : d;\n };\n const topK = clampInt(o.topK, 1, 200, 50);\n const windowMs = clampInt(o.windowMs, 1000, 60000, 10000);\n const nowSec = Math.floor(performance.now() / 1000);\n const agg = new Map();\n let sampledMs = 0;\n for (let k = 0; k < Math.ceil(windowMs / 1000); k++) {\n const sec = nowSec - k;\n const b = this._activity[((sec % 60) + 60) % 60];\n if (!b || b.second !== sec) continue;\n sampledMs += b.sampledMs;\n for (const [cid, r] of b.rows) {\n if (!this._instances.has(cid)) continue;\n let a = agg.get(cid);\n if (!a) {\n a = { changes: 0, renders: 0, renderMs: 0 };\n agg.set(cid, a);\n }\n a.changes += r.changes;\n a.renders += r.renders;\n a.renderMs += r.renderMs;\n }\n }\n const ranked = [...agg].sort(\n (x, y) =>\n y[1].changes - x[1].changes || y[1].renders - x[1].renders || y[1].renderMs - x[1].renderMs || x[0] - y[0],\n );\n let rowNodes = 0;\n const rows = ranked.slice(0, topK).map(([cid, a]) => {\n const n = this._nodeCounts.get(cid) || { state: 0, derived: 0, effect: 0 };\n rowNodes += n.state + n.derived + n.effect;\n return {\n componentId: cid,\n file: this._instances.get(cid).file,\n nodes: { state: n.state, derived: n.derived, effect: n.effect },\n changes: a.changes,\n renders: a.renders,\n renderMs: Math.round(a.renderMs * 1000) / 1000,\n };\n });\n const t = this._nodeTotals;\n const until = Date.now();\n return {\n epoch: this._epoch,\n window: { ms: windowMs, since: until - windowMs, until, sampledActiveMs: Math.min(windowMs, sampledMs) },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: { total: this._instances.size, withActivity: agg.size },\n rows,\n other: { components: this._instances.size - rows.length, nodes: t.state + t.derived + t.effect - rowNodes },\n truncated: agg.size > topK,\n capabilities: { valueInspection: false, signalHistory: false, writeCause: false },\n // Seed coverage: changes of pending nodes are not observable yet.\n baseline: this._baselineInfo(),\n };\n },\n\n // Request { requestId?, epoch?, topK?, windowMs? } (same correlation as\n // the graph, review M1).\n sendReactiveSummary(request) {\n const req = request || {};\n if (req.epoch !== undefined && req.epoch !== null && req.epoch !== this._epoch) return;\n const summary = this.getReactiveSummary(req);\n if (req.requestId !== undefined) summary.requestId = req.requestId;\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:reactive-summary', summary);\n }\n },\n\n // --- Phase 3: State Timeline ---\n\n // Current value of a $state node: the signal value, or for tag_proxy\n // nodes (non-reassigned object/array state) the live proxy itself.\n // Returns a sentinel when the value can't be read.\n _readStateValue(nodeId, signal) {\n if (signal._isProxy) {\n const proxy = this._reactiveProxies.get(nodeId)?.deref();\n return proxy === undefined ? __NO_VALUE : proxy;\n }\n const v = signal.v;\n // Svelte's UNINITIALIZED marker is a symbol; functions aren't state data.\n return typeof v === 'symbol' || typeof v === 'function' ? __NO_VALUE : v;\n },\n\n // Runs every 200 ms in the user's app, so it must stay cheap regardless of\n // how much state the app holds (§6.7 D).\n // 1. Hint pass, time-sliced: at most HINT_NODES $state nodes per tick,\n // continuing from a cursor carried across ticks, so a full sweep over\n // n nodes takes ceil(n / HINT_NODES) ticks (_pollSweep.lastMs is the\n // measured sweep time = worst-case detection delay). Per node O(1):\n // primitives are compared directly and recorded at once; objects\n // whose reference or Svelte write version (wv) changed are added to\n // _pollDirty, which persists across ticks until serialized.\n // 2. Serialization work is limited to BUDGET_MS per tick (dirty nodes\n // carry over, nothing is dropped).\n // 3. In-place deep mutations (proxies don't bump an outer wv) are found by\n // time-based re-checks: each object is re-verified no earlier than\n // nextCheckAt = now + max(RECHECK_MS, 50 x its serialization cost),\n // paid from a DEEP_MS-per-tick credit, so the amortized cost is bounded\n // however many large states the app holds.\n // 4. Values serializing above MAX_SNAPSHOT_CHARS are kept as length+hash\n // (not the string) and appear in the timeline as a summary.\n // Writes between two visits of a node are observed as one change (the\n // timeline is a sample, policy 'sampled-200ms'; not counted as dropped).\n _pollStateValues(baseline) {\n const HINT_NODES = 4096;\n const BUDGET_MS = 2;\n const DEEP_MS = 0.5;\n const now = performance.now();\n if (!baseline) {\n this._deepCredit = Math.min(10 * DEEP_MS, (this._deepCredit || 0) + DEEP_MS);\n // this tick samples 200 ms of wall time (window.sampledActiveMs)\n const bucket = this._bucket();\n bucket.sampledMs = Math.min(1000, bucket.sampledMs + 200);\n }\n const ids = this._pollIds;\n const due = [];\n const limit = Math.min(HINT_NODES, ids.length);\n for (let visited = 0; visited < limit && ids.length > 0; visited++) {\n if (this._pollCursor >= ids.length) {\n this._pollCursor = 0;\n if (!baseline) {\n if (this._pollSweep.startedAt) this._pollSweep.lastMs = now - this._pollSweep.startedAt;\n this._pollSweep.startedAt = now;\n this._pollSweep.nodes = ids.length;\n }\n }\n if (!baseline && !this._pollSweep.startedAt) this._pollSweep.startedAt = now;\n const nodeId = ids[this._pollCursor];\n const entry = this._reactiveNodes.get(nodeId);\n if (!entry || entry.meta.type !== 'state') {\n // re-tracked as another type: drop from the poll list (slot reused)\n this._pollRemove(nodeId);\n continue;\n }\n if (!this._instances.has(entry.meta.componentId)) {\n this._forgetNode(nodeId); // swaps the last id into this slot\n continue;\n }\n this._pollCursor++;\n const signal = entry.signal.deref();\n const value = signal ? this._readStateValue(nodeId, signal) : __NO_VALUE;\n if (value === __NO_VALUE) {\n // nothing readable (collected, uninitialized, function): not pending\n this._unseeded.delete(nodeId);\n continue;\n }\n if (value === null || typeof value !== 'object') {\n const had = this._stateSnapshots.has(nodeId);\n const prev = this._stateSnapshots.get(nodeId);\n if (had && Object.is(prev, value)) continue;\n // Forget the object key so object -> primitive -> same object again\n // is still recorded as a change.\n if (this._stateSnapshotStrs) this._stateSnapshotStrs.delete(nodeId);\n this._pollDirty.delete(nodeId);\n if (!had) {\n // first observation: seed only\n this._stateSnapshots.set(nodeId, value);\n this._unseeded.delete(nodeId);\n continue;\n }\n this._recordChange(nodeId, entry, prev, value, typeof value === 'string' ? 2 * value.length : 64);\n continue;\n }\n let meta = this._pollMeta.get(nodeId);\n if (!meta) {\n meta = { ref: undefined, wv: undefined, nextCheckAt: 0 };\n this._pollMeta.set(nodeId, meta);\n }\n if (meta.ref !== value || meta.wv !== signal.wv) this._pollDirty.add(nodeId);\n else if (now >= meta.nextCheckAt) due.push(nodeId);\n }\n const start = performance.now();\n for (const nodeId of this._pollDirty) {\n if (performance.now() - start > BUDGET_MS) return;\n this._pollDirty.delete(nodeId);\n this._serializeNode(nodeId, false);\n }\n for (const nodeId of due) {\n if (this._deepCredit <= 0 || performance.now() - start > BUDGET_MS) return;\n this._serializeNode(nodeId, true);\n }\n },\n\n // Activation (late consumer): nodes registered while inactive have no\n // seed yet, so a write before their first visit could not be seen as a\n // change. The first slice is seeded at activation instead of 200 ms later:\n // ONE normal pass (<= HINT_NODES nodes, the per-tick serialization budget;\n // the rest follow on the usual ticks). Seeds record nothing; readiness is\n // disclosed in the summary as baseline { complete, pendingNodes }.\n _pollBaseline() {\n this._baselining = true;\n try {\n this._pollStateValues(true);\n } catch { /* never break activation */ } finally {\n this._baselining = false;\n }\n },\n\n _serializeNode(nodeId, deep) {\n const MAX_SNAPSHOT_CHARS = 32768;\n const RECHECK_MS = 1000;\n const entry = this._reactiveNodes.get(nodeId);\n const meta = this._pollMeta.get(nodeId);\n if (!entry || !meta) return;\n const signal = entry.signal.deref();\n if (!signal) return;\n const value = this._readStateValue(nodeId, signal);\n if (value === __NO_VALUE || value === null || typeof value !== 'object') return;\n try {\n const t0 = performance.now();\n const str = JSON.stringify(value);\n const cost = performance.now() - t0;\n if (deep) this._deepCredit -= cost;\n meta.ref = value;\n meta.wv = signal.wv;\n meta.nextCheckAt = t0 + Math.max(RECHECK_MS, 50 * cost);\n // Small values keep the string (exact compare); large ones only a\n // length+hash so a 5 MB array doesn't pin 5 MB per node.\n const key = str === undefined ? '' : str.length > MAX_SNAPSHOT_CHARS ? str.length + ':' + __hash(str) : str;\n if (!this._stateSnapshotStrs) this._stateSnapshotStrs = new Map();\n const hadKey = this._stateSnapshotStrs.has(nodeId);\n if (hadKey && this._stateSnapshotStrs.get(nodeId) === key) return;\n this._stateSnapshotStrs.set(nodeId, key);\n const tooLarge = str !== undefined && str.length > MAX_SNAPSHOT_CHARS;\n const snapshot =\n str === undefined\n ? null\n : tooLarge\n ? '(object: ' + str.length + ' chars, too large to snapshot)'\n : JSON.parse(str);\n const size = typeof snapshot === 'string' ? 64 : str.length;\n if (!this._stateSnapshots.has(nodeId)) {\n // first observation: seed only (no entry, no counters)\n this._stateSnapshots.set(nodeId, snapshot);\n this._lastSnapshotSize.set(nodeId, size);\n this._unseeded.delete(nodeId);\n return;\n }\n if (tooLarge) this._valueTooLarge++;\n const prev = this._stateSnapshots.get(nodeId);\n this._recordChange(nodeId, entry, prev, snapshot, size + (this._lastSnapshotSize.get(nodeId) || 0));\n this._lastSnapshotSize.set(nodeId, size);\n } catch {\n // non-serializable (cycles, BigInt): never observable, so not pending\n this._unseeded.delete(nodeId);\n }\n },\n\n _recordChange(nodeId, entry, oldValue, newValue, approxBytes) {\n const change = {\n id: nodeId,\n name: entry.meta.name,\n componentFile: entry.meta.componentFile,\n oldValue,\n newValue,\n timestamp: Date.now(),\n };\n const bytes = (approxBytes || 64) + 192;\n // seq stays runtime-internal: the server assigns its own seq (§6.4).\n this._entryInfo.set(change, { seq: ++this._timelineSeq, bytes });\n this._stateTimeline.push(change);\n this._timelineBytes += bytes;\n // sampled change count (§6.7 J IA2): independent of the ring\n this._activityRow(entry.meta.componentId).changes++;\n this._stateSnapshots.set(nodeId, newValue);\n // The ring (_trimTimeline) is applied in bulk, not with one splice per\n // change (a poll tick can record thousands): before every read (each\n // push — with a hot channel and an active consumer, at least every 200\n // changes — the full snapshot, getStateTimeline() and clear), and here\n // once more than __TIMELINE_TRIM_AT entries are held or the byte budget\n // is exceeded, which bounds memory when nothing reads or pushes.\n if (this._stateTimeline.length > __TIMELINE_TRIM_AT || this._timelineBytes > __TIMELINE_BYTES) {\n this._trimTimeline();\n }\n this._scheduleTimelineUpdate();\n },\n\n // Ring: at most 500 entries and __TIMELINE_BYTES (the newest entry is\n // always kept). Removed entries that were never pushed are disclosed\n // as dropped (§6.7 C); pushed ones are already on the server.\n _trimTimeline() {\n const all = this._stateTimeline;\n let cut = 0;\n let bytesLeft = this._timelineBytes;\n while (cut < all.length - 1 && (all.length - cut > 500 || bytesLeft > __TIMELINE_BYTES)) {\n const info = this._entryInfo.get(all[cut]);\n const reason = all.length - cut > 500 ? 'runtime-count' : 'runtime-bytes';\n if (info.seq > this._pushedSeq) this._timelineDropped[reason]++;\n bytesLeft -= info.bytes;\n cut++;\n }\n if (cut > 0) {\n all.splice(0, cut);\n this._timelineBytes = bytesLeft;\n }\n },\n\n // Push (§6.7 C): a throttle, not a debounce — a pending timer is never\n // re-armed, so unsent entries leave within 300 ms of the first one even\n // under continuous change — plus an immediate flush once 200 entries\n // (one message) are unsent, since one poll tick can record thousands.\n _scheduleTimelineUpdate() {\n if (!this._active || this._baselining) return;\n if (this._timelineSeq - this._pushedSeq >= 200) {\n this._flushTimeline();\n return;\n }\n if (this._timelineDebounceTimer) return;\n this._timelineDebounceTimer = setTimeout(() => {\n this._timelineDebounceTimer = null;\n this._flushTimeline();\n }, 300);\n },\n\n _flushTimeline() {\n if (this._timelineDebounceTimer) {\n clearTimeout(this._timelineDebounceTimer);\n this._timelineDebounceTimer = null;\n }\n if (!import.meta.hot) return;\n for (const msg of this._timelineDeltas()) {\n import.meta.hot.send('svelte-devtools:state-timeline', msg);\n }\n },\n\n // Disclosure counters since the previous push, attached to (and reset\n // by) the next message: dropped [{ reason, count }] and valueTooLarge.\n _takeTimelineDisclosure(msg) {\n msg.baseline = this._baselineInfo();\n this._sentPendingNodes = msg.baseline.pendingNodes;\n const dropped = [];\n for (const reason of ['runtime-count', 'runtime-bytes']) {\n const count = this._timelineDropped[reason];\n if (count > 0) dropped.push({ reason, count });\n this._timelineDropped[reason] = 0;\n }\n if (dropped.length) msg.dropped = dropped;\n if (this._valueTooLarge > 0) msg.valueTooLarge = this._valueTooLarge;\n this._valueTooLarge = 0;\n return msg;\n },\n\n // Seed coverage (review B-2), on every state-timeline message and the\n // summary: pendingNodes = polled $state nodes without a first sample;\n // their writes are not observable yet.\n _baselineInfo() {\n return { complete: this._unseeded.size === 0, pendingNodes: this._unseeded.size };\n },\n\n _hasTimelineDisclosure() {\n return (\n this._sentPendingNodes !== this._unseeded.size ||\n this._timelineDropped['runtime-count'] > 0 ||\n this._timelineDropped['runtime-bytes'] > 0 ||\n this._valueTooLarge > 0\n );\n },\n\n // Delta push (docs/devframe-migration.md §6.4): only entries recorded\n // since the previous push, ≤ 200 per message, tagged with a per-page-load\n // epoch; reset after clearStateTimeline(). A message with no changes is\n // still sent when there is something to disclose (all unsent dropped).\n _timelineDeltas() {\n this._trimTimeline();\n const all = this._stateTimeline;\n let start = all.length;\n while (start > 0 && this._entryInfo.get(all[start - 1]).seq > this._pushedSeq) start--;\n const pending = all.slice(start);\n const msgs = [];\n const first = this._timelineReset || this._hasTimelineDisclosure();\n for (let i = 0; i < pending.length || (first && i === 0); i += 200) {\n const msg = { epoch: this._epoch, changes: pending.slice(i, i + 200) };\n if (i === 0 && this._timelineReset) msg.reset = true;\n if (i === 0) this._takeTimelineDisclosure(msg);\n else msg.baseline = this._baselineInfo();\n msgs.push(msg);\n }\n this._timelineReset = false;\n this._pushedSeq = this._timelineSeq;\n return msgs;\n },\n\n // Full buffer (reset: true) — reply to request-state-timeline and the\n // activation snapshot. Newest entries first up to __TIMELINE_BYTES, the\n // server's own buffer budget, so nothing is sent that it would drop.\n _timelineFull() {\n this._trimTimeline();\n const all = this._stateTimeline;\n let start = all.length;\n let bytes = 0;\n while (start > 0) {\n const size = this._entryInfo.get(all[start - 1]).bytes;\n if (bytes + size > __TIMELINE_BYTES && start < all.length) break;\n bytes += size;\n start--;\n }\n this._timelineReset = false;\n this._pushedSeq = this._timelineSeq;\n return this._takeTimelineDisclosure({ epoch: this._epoch, changes: all.slice(start), reset: true });\n },\n\n getStateTimeline() {\n this._trimTimeline();\n return this._stateTimeline;\n },\n\n clearStateTimeline() {\n // Ring first: unsent entries past the cap are disclosed as dropped,\n // exactly as if they had been removed when recorded.\n this._trimTimeline();\n this._stateTimeline = [];\n this._timelineBytes = 0;\n this._pushedSeq = this._timelineSeq;\n this._timelineReset = true;\n this._scheduleTimelineUpdate();\n },\n\n // --- FPS Monitoring ---\n // Uses requestAnimationFrame to measure frame rate with minimal overhead.\n // Only stores timestamps - no allocations per frame beyond a single array push.\n _fpsFrameTimes: [],\n\n _fpsLoop(gen) {\n if (gen !== this._fpsGen) return;\n this._fpsFrameTimes.push(performance.now());\n requestAnimationFrame(() => this._fpsLoop(gen));\n },\n\n _isVisible() {\n return typeof document === 'undefined' || document.visibilityState !== 'hidden';\n },\n\n _setSubscription(data) {\n const wasActive = this._active;\n this._active = !!(data && data.active);\n this._componentDeltas = !!(data && data.componentDeltas);\n if (!this._active) {\n this._pendingAdded.clear();\n this._pendingRemoved.clear();\n }\n // resync: the server holds no full base for this epoch (§6.5, review\n // C1), or we reconnected to a possibly restarted server.\n const resync = this._resync || !!(data && data.resync);\n this._resync = false;\n if (this._active && !wasActive) this._pollBaseline();\n if (this._active && (!wasActive || resync)) {\n // Collector state may be stale or empty (first activation, resync, or a\n // reconnect to a possibly restarted server): resend everything once, in\n // the order components -> profiles -> timeline(reset: true); the\n // reset push marks the activation snapshot complete (D4).\n this._sendUpdate(true);\n this._sendProfileUpdate();\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:state-timeline', this._timelineFull());\n }\n }\n this._syncSampling();\n },\n\n // Sampling (state poll + FPS) runs only while active AND the app tab is\n // visible.\n _syncSampling() {\n const want = this._active && this._isVisible();\n if (want && !this._sampling) {\n this._fpsFrameTimes = [];\n const gen = ++this._fpsGen;\n this._sampling = {\n poll: setInterval(() => {\n this._pollStateValues();\n // seed progress changed: push it even without changes (B-2)\n if (this._sentPendingNodes !== this._unseeded.size) this._scheduleTimelineUpdate();\n }, 200),\n fps: setInterval(() => { this._sampleFps(); }, 500),\n };\n requestAnimationFrame(() => this._fpsLoop(gen));\n } else if (!want && this._sampling) {\n clearInterval(this._sampling.poll);\n clearInterval(this._sampling.fps);\n this._sampling = null;\n this._fpsGen++;\n this._fpsFrameTimes = [];\n }\n },\n\n _sampleFps() {\n const now = performance.now();\n // Remove frame timestamps older than 1 second\n const cutoff = now - 1000;\n let i = 0;\n while (i < this._fpsFrameTimes.length && this._fpsFrameTimes[i] < cutoff) i++;\n if (i > 0) this._fpsFrameTimes.splice(0, i);\n const fps = this._fpsFrameTimes.length;\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:fps', { timestamp: Date.now(), fps });\n }\n }\n };\n\n window.__SVELTE_DEVTOOLS__ = __SVELTE_DT;\n\n // State polling and FPS sampling start on the server's subscription\n // message (§6.3) and pause while the app tab is hidden.\n if (typeof document !== 'undefined' && document.addEventListener) {\n document.addEventListener('visibilitychange', () => __SVELTE_DT._syncSampling());\n }\n\n // Phase 3: Capture runtime errors\n window.addEventListener('error', (event) => {\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: event.message,\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n stack: event.error?.stack || '',\n timestamp: Date.now(),\n });\n }\n });\n window.addEventListener('unhandledrejection', (event) => {\n if (import.meta.hot) {\n const reason = event.reason;\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: reason?.message || String(reason),\n stack: reason?.stack || '',\n timestamp: Date.now(),\n });\n }\n });\n\n // Listen for reactive graph requests from server\n // Pull requests are answered regardless of the subscription state.\n if (import.meta.hot) {\n import.meta.hot.on('svelte-devtools:subscription', (data) => {\n __SVELTE_DT._setSubscription(data);\n });\n import.meta.hot.on('vite:ws:connect', () => {\n // The server may have restarted with an empty collector: the reply to\n // runtime-ready is treated as a fresh activation (full snapshot).\n __SVELTE_DT._resync = true;\n import.meta.hot.send('svelte-devtools:runtime-ready', {});\n });\n import.meta.hot.send('svelte-devtools:runtime-ready', {});\n import.meta.hot.on('svelte-devtools:request-reactive-graph', (data) => {\n __SVELTE_DT.sendReactiveGraph(data);\n });\n import.meta.hot.on('svelte-devtools:request-reactive-summary', (data) => {\n __SVELTE_DT.sendReactiveSummary(data);\n });\n import.meta.hot.on('svelte-devtools:request-state-timeline', () => {\n import.meta.hot.send('svelte-devtools:state-timeline', __SVELTE_DT._timelineFull());\n });\n import.meta.hot.on('svelte-devtools:clear-state-timeline', () => {\n __SVELTE_DT.clearStateTimeline();\n });\n }\n}\n`\n","import type {\n CaptureInfo,\n CaptureInfoMap,\n CompilerWarning,\n DropReason,\n ComponentInstance,\n FpsSample,\n LoadProfile,\n ReactiveGraph,\n ReactiveGraphRequest,\n ReactiveGraphResult,\n ReactiveGraphTotal,\n ReactiveSummary,\n ReactiveSummaryRequest,\n RenderProfile,\n RuntimeError,\n StateChange,\n StateTimelineDelta,\n StateTimelineEntry,\n DatasetVersions,\n TimelineBaseline,\n} from './types.js'\n\n// Defensive caps on runtime-supplied data: even though the runtime already\n// trims its own buffers, an out-of-spec or compromised runtime could hand us\n// unbounded payloads and inflate dev-server memory.\nexport const LIMITS = {\n liveComponents: 50000,\n renderProfiles: 5000,\n stateTimeline: 500,\n reactiveNodes: 5000,\n reactiveEdges: 20000,\n fpsSamples: 1200,\n runtimeErrors: 200,\n loadProfiles: 200,\n compilerWarnings: 500,\n} as const\n\n/** How long a pull request to the browser runtime may take before we answer from cache. */\nexport const RUNTIME_REQUEST_TIMEOUT = 1000\n\n/** A pull answered within this window is reused instead of asking the runtime again. */\nexport const PULL_FRESHNESS = 1000\n\n/** Byte budget (JSON length, measured once at ingest) for the server-side state timeline. */\nexport const STATE_TIMELINE_BYTES = 4 * 1024 * 1024\n\nexport type DatasetKey = keyof DatasetVersions\n\n// Timeline `seq` values come from one process-wide counter, seeded from the\n// clock: a cursor issued by an earlier collector in this process (inline or\n// config-file restart) is always below a newer collector's `timelineResetAt`,\n// and one from a previous process is too unless it issued more than 1 000\n// entries per millisecond of downtime (review D2).\nlet lastSeq = Date.now() * 1000\nconst nextSeq = () => ++lastSeq\n\n/** Epoch for runtimes that send payloads without an epoch. */\nconst LEGACY_EPOCH = '(legacy)'\n\n/** App page loads (tabs / reloads) whose component tree + profiles are kept, LRU. */\nexport const MAX_EPOCHS = 4\n\ninterface EpochState {\n /** Insertion order = registration order (parents first). */\n components: Map<number, ComponentInstance>\n /**\n * Ids of mounted instances not stored: beyond the cap, or whose parent\n * isn't stored (admitting them would show orphans). Ids only, so the total\n * and removals stay exact.\n */\n overflow: Set<number>\n /** A full components snapshot was applied, so deltas have a base. */\n hasBase: boolean\n profiles: RenderProfile[]\n /** Profiles the runtime holds before its tail cap (sent as `total`); `null` = unknown. */\n profilesTotal: number | null\n}\n\n/** Hot-channel event names shared with `runtime.ts` (stable contract, see docs/devframe-migration.md §6). */\nexport const HOT_EVENTS = {\n components: 'svelte-devtools:components',\n profiles: 'svelte-devtools:profiles',\n stateTimeline: 'svelte-devtools:state-timeline',\n fps: 'svelte-devtools:fps',\n runtimeError: 'svelte-devtools:runtime-error',\n reactiveGraph: 'svelte-devtools:reactive-graph',\n requestReactiveGraph: 'svelte-devtools:request-reactive-graph',\n /** server → runtime `{ requestId, epoch?, topK, windowMs }`; reply `reactiveSummary` (§6.7 I). */\n requestReactiveSummary: 'svelte-devtools:request-reactive-summary',\n reactiveSummary: 'svelte-devtools:reactive-summary',\n requestStateTimeline: 'svelte-devtools:request-state-timeline',\n clearStateTimeline: 'svelte-devtools:clear-state-timeline',\n /** runtime → server, once per page load: \"send me the current subscription state\". */\n runtimeReady: 'svelte-devtools:runtime-ready',\n /** server → runtime(s): `{ active: boolean }` — whether any consumer is watching. */\n subscription: 'svelte-devtools:subscription',\n} as const\n\n/** Keyed pull results kept for reuse / stale fallback (graph scopes, summaries), LRU. */\nconst MAX_CACHED_PULLS = 32\n\n/** Defaults and bounds for `get-reactive-summary` (§6.7 I). */\nexport const SUMMARY_DEFAULTS = {\n topK: 50,\n maxTopK: 200,\n windowMs: 10_000,\n minWindowMs: 1000,\n maxWindowMs: 60_000,\n} as const\n\nconst DROP_REASONS: readonly DropReason[] = [\n 'runtime-count',\n 'runtime-bytes',\n 'server-count',\n 'server-bytes',\n]\n\n/** An integer within [min, max], or `fallback` when absent / not a number. */\nfunction validBaseline(b: unknown): b is TimelineBaseline {\n const v = b as Partial<TimelineBaseline> | undefined\n return (\n !!v &&\n typeof v.complete === 'boolean' &&\n Number.isInteger(v.pendingNodes) &&\n (v.pendingNodes as number) >= 0\n )\n}\n\nfunction clampInt(value: unknown, min: number, max: number, fallback: number): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) return fallback\n return Math.min(max, Math.max(min, Math.trunc(value)))\n}\n\n/** A pull request waiting for the runtime's reply, matched by `requestId` (§6.7 A, M1). */\ninterface PendingPull {\n kind: 'graph' | 'summary'\n key: string\n epoch: string | null\n scope: number | null\n resolve: (value: ReactiveGraphResult | ReactiveSummary) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/** A consumer (DevTools UI tab, MCP agent) counts as watching until its lease expires. */\nexport const LEASE_TTL = 15_000\n\nexport interface HotClient {\n send(event: string, payload: unknown): void\n}\n\nexport interface HotChannel {\n send(event: string, payload: unknown): void\n on(event: string, listener: (payload: any, client: HotClient) => void): void\n off?(event: string, listener: (payload: any, client: HotClient) => void): void\n}\n\nexport interface CollectorHooks {\n onFpsSample?: (sample: FpsSample) => void\n onLoadProfile?: (profile: LoadProfile) => void\n}\n\nfunction tail<T>(arr: unknown, max: number): T[] {\n const list = Array.isArray(arr) ? (arr as T[]) : []\n return list.length > max ? list.slice(-max) : list\n}\n\nfunction head<T>(arr: unknown, max: number): T[] {\n const list = Array.isArray(arr) ? (arr as T[]) : []\n return list.length > max ? list.slice(0, max) : list\n}\n\n/**\n * Host-side store for everything the browser runtime and the instrumentation\n * transforms report. Independent of Vite and of devframe: the Vite plugin\n * feeds it, the devframe RPC layer and the MCP server read from it.\n */\nexport class Collector {\n // Component tree + render profiles are kept per app page load (`epoch`),\n // so several app tabs / a reload don't overwrite each other; the epoch that\n // pushed most recently is the one served (review D3, perf R-A8).\n private epochs = new Map<string, EpochState>()\n private servedEpoch: string | undefined\n private liveCache: ComponentInstance[] | undefined\n loadProfiles: LoadProfile[] = []\n reactiveGraph: ReactiveGraph = { nodes: [], edges: [] }\n compilerWarnings: CompilerWarning[] = []\n runtimeErrors: RuntimeError[] = []\n fpsSamples: FpsSample[] = []\n // Opaque change tokens drawn from the process-wide counter (like timeline\n // seqs): a restarted server's collector never reports a value a client saw\n // before, so \"unchanged version → skip refetch\" stays correct across\n // restarts (review B1).\n readonly versions: DatasetVersions = {\n components: nextSeq(),\n renderProfiles: nextSeq(),\n loadProfiles: nextSeq(),\n stateTimeline: nextSeq(),\n reactiveGraph: nextSeq(),\n errors: nextSeq(),\n fps: nextSeq(),\n }\n\n private bump(...keys: DatasetKey[]): void {\n for (const key of keys) this.versions[key] = nextSeq()\n }\n\n private timeline: StateTimelineEntry[] = []\n /** Parallel to `timeline`: JSON size and source epoch (app page load) of each entry. */\n private timelineSizes: number[] = []\n private timelineEpochs: string[] = []\n private timelineBytes = 0\n /** Newest seq issued by this collector (= the current cursor). */\n private timelineSeq = nextSeq()\n /** Cursor value at the last removal; older cursors must start over. */\n private timelineResetAt = this.timelineSeq\n /** Seq of the newest entry trimmed by the caps; cursors below it missed entries. */\n private timelineTrimmedAt = this.timelineSeq\n private lastPull = { stateTimeline: 0 }\n private inflight: { stateTimeline?: Promise<StateChange[]> } = {}\n\n // Keyed pulls (graph scopes, summaries; §6.7 A/I): each request carries a\n // requestId + the served epoch, and only the matching reply resolves it, so\n // one viewer never receives another viewer's scope (review G5, M1).\n private pulls = new Map<string, PendingPull>()\n private pullCache = new Map<\n string,\n { value: ReactiveGraphResult | ReactiveSummary; at: number }\n >()\n private pullInflight = new Map<string, Promise<ReactiveGraphResult | ReactiveSummary>>()\n private requestSeq = 0\n /** The most recent graph reply, for capture info. */\n private lastGraph: ReactiveGraphResult | undefined\n\n // Timeline losses per epoch, by reason; monotonic until the epoch is\n // evicted or the timeline is cleared (§6.7 B/C).\n private timelineDrops = new Map<string, Record<DropReason, number>>()\n /** Per epoch: whether the runtime has a first sample of every tracked $state yet. */\n private timelineBaseline = new Map<string, TimelineBaseline>()\n private timelineTooLarge = new Map<string, number>()\n // Items received since the last clear, for the ring datasets' totals.\n private received = { fps: 0, runtimeErrors: 0, loadProfiles: 0, compilerWarnings: 0 }\n\n private hot: HotChannel | undefined\n private detachHot: (() => void) | undefined\n private leases = new Map<string, number>()\n private snapshotWaiters: Array<() => void> = []\n private active = false\n private sweepTimer: ReturnType<typeof setTimeout> | undefined\n private stateTimelineResolvers: Array<(changes: StateChange[]) => void> = []\n\n constructor(private readonly hooks: CollectorHooks = {}) {}\n\n /**\n * Subscribe to the runtime's hot-channel events. Re-attaching (dev server\n * restart) detaches the previous channel first so listeners never pile up.\n */\n attach(hot: HotChannel): void {\n this.detach()\n this.hot = hot\n const listeners: Array<[string, (payload: any, client: HotClient) => void]> = [\n [\n HOT_EVENTS.runtimeReady,\n (_, client) => client?.send(HOT_EVENTS.subscription, this.subscription),\n ],\n [HOT_EVENTS.components, (d, client) => this.ingestComponents(d, client)],\n [HOT_EVENTS.profiles, d => this.ingestProfiles(d)],\n [HOT_EVENTS.stateTimeline, d => this.ingestStateTimeline(d)],\n [HOT_EVENTS.fps, d => this.ingestFps(d)],\n [HOT_EVENTS.runtimeError, d => this.ingestRuntimeError(d)],\n [HOT_EVENTS.reactiveGraph, d => this.ingestReactiveGraph(d)],\n [HOT_EVENTS.reactiveSummary, d => this.ingestReactiveSummary(d)],\n ]\n for (const [event, listener] of listeners) hot.on(event, listener)\n this.detachHot = () => {\n for (const [event, listener] of listeners) hot.off?.(event, listener)\n }\n }\n\n detach(): void {\n clearTimeout(this.sweepTimer)\n this.sweepTimer = undefined\n this.detachHot?.()\n this.detachHot = undefined\n this.hot = undefined\n // Answer pending pulls from cache instead of leaving them to time out.\n this.flushPulls('no-runtime')\n this.flushStateTimeline()\n }\n\n /** What the runtime is told: collect/poll only while somebody is watching. */\n get subscription(): { active: boolean; componentDeltas: true } {\n // `componentDeltas` advertises that the delta form of `components` is\n // accepted (§6.5), so a runtime never sends deltas to an older server.\n return { active: this.active, componentDeltas: true }\n }\n\n /** Epochs we asked for a full snapshot (delta without a base); answered once per epoch. */\n private resyncRequested = new Set<string>()\n\n /** Components of the served epoch, parents first, capped at {@link LIMITS.liveComponents}. */\n get liveComponents(): ComponentInstance[] {\n if (!this.liveCache) {\n const state = this.servedState()\n this.liveCache = state ? [...state.components.values()] : []\n }\n return this.liveCache\n }\n\n /**\n * The served epoch's components with that epoch, read together, so a\n * component id is never paired with another page load's epoch (several app\n * tabs keep separate trees; nothing is merged).\n */\n get liveSnapshot(): {\n epoch: string | null\n total: number\n components: ComponentInstance[]\n } {\n const state = this.servedState()\n return {\n epoch: state ? (this.servedEpoch ?? null) : null,\n total: this.liveComponentsTotal,\n components: this.liveComponents,\n }\n }\n\n /** Instances the served epoch has mounted, including those beyond the cap. */\n get liveComponentsTotal(): number {\n const state = this.servedState()\n return state ? state.components.size + state.overflow.size : 0\n }\n\n get renderProfiles(): RenderProfile[] {\n return this.servedState()?.profiles ?? []\n }\n\n /** The epoch currently served and how many app page loads are tracked. */\n get epochInfo(): { epoch: string | undefined; epochs: number } {\n return { epoch: this.servedEpoch ?? [...this.epochs.keys()].at(-1), epochs: this.epochs.size }\n }\n\n private servedState(): EpochState | undefined {\n if (this.servedEpoch !== undefined) return this.epochs.get(this.servedEpoch)\n // No page load has sent a component snapshot yet: show the most recent\n // pusher (its profiles; its tree is empty either way).\n let newest: EpochState | undefined\n for (const state of this.epochs.values()) newest = state\n return newest\n }\n\n /**\n * Get (creating, LRU-bounded) the state for `epoch` and mark it as the most\n * recent pusher. It becomes the served epoch only once it holds a full\n * component snapshot — an epoch known only from profiles/timeline would\n * otherwise show an empty tree (review B1).\n */\n private touchEpoch(epoch: string): EpochState {\n let state = this.epochs.get(epoch)\n if (state) this.epochs.delete(epoch)\n else\n state = {\n components: new Map(),\n overflow: new Set(),\n hasBase: false,\n profiles: [],\n profilesTotal: null,\n }\n this.epochs.set(epoch, state) // re-insert: Map order = recency\n while (this.epochs.size > MAX_EPOCHS) {\n const evicted = this.epochs.keys().next().value!\n this.epochs.delete(evicted)\n this.resyncRequested.delete(evicted)\n this.dropEpoch(evicted)\n this.timelineDrops.delete(evicted)\n this.timelineTooLarge.delete(evicted)\n this.timelineBaseline.delete(evicted)\n if (this.servedEpoch === evicted) this.serve(this.newestBasedEpoch())\n }\n if (state.hasBase) this.serve(epoch)\n return state\n }\n\n private newestBasedEpoch(): string | undefined {\n let newest: string | undefined\n for (const [epoch, state] of this.epochs) if (state.hasBase) newest = epoch\n return newest\n }\n\n private serve(epoch: string | undefined): void {\n if (this.servedEpoch === epoch) return\n // Switching from another tab's data changes what both datasets serve.\n if (this.servedEpoch !== undefined) this.bump('components', 'renderProfiles')\n this.servedEpoch = epoch\n this.liveCache = undefined\n }\n\n /**\n * Mark `id` as watching for `ttl` ms (renewed by heartbeats). The first\n * lease activates the runtime's polling/FPS sampling, the last expiry or\n * release pauses it.\n */\n lease(id: string, ttl = LEASE_TTL): boolean {\n const wasActive = this.active\n this.leases.set(id, Date.now() + ttl)\n this.updateSubscription()\n return !wasActive && this.active\n }\n\n /**\n * Resolve once the runtime has sent its activation snapshot (components,\n * profiles, then a `reset: true` timeline — the last part) or after\n * `timeout`, so a consumer that just activated the runtime doesn't read\n * the stale pre-activation state.\n */\n waitForSnapshot(timeout: number): Promise<void> {\n return new Promise(resolve => {\n const done = () => {\n clearTimeout(timer)\n const idx = this.snapshotWaiters.indexOf(done)\n if (idx !== -1) this.snapshotWaiters.splice(idx, 1)\n resolve()\n }\n const timer = setTimeout(done, timeout)\n this.snapshotWaiters.push(done)\n })\n }\n\n release(id: string): void {\n if (this.leases.delete(id)) this.updateSubscription()\n }\n\n private updateSubscription(): void {\n const now = Date.now()\n let next = Infinity\n for (const [id, expiresAt] of this.leases) {\n if (expiresAt <= now) this.leases.delete(id)\n else next = Math.min(next, expiresAt)\n }\n const active = this.leases.size > 0\n if (active !== this.active) {\n this.active = active\n this.hot?.send(HOT_EVENTS.subscription, this.subscription)\n }\n clearTimeout(this.sweepTimer)\n this.sweepTimer = undefined\n if (next !== Infinity) {\n this.sweepTimer = setTimeout(() => this.updateSubscription(), next - now + 1)\n this.sweepTimer.unref?.()\n }\n }\n\n /**\n * Full form `{ epoch?, reset?, components }` replaces the epoch's tree;\n * delta form `{ epoch, added, removed }` (ids) patches it (§6.5). A delta\n * for an epoch we hold no full snapshot of (new to us, or evicted) is not\n * applied — a partial tree would persist — and the sender is asked to\n * resync. Entries stay in registration order (parents first); an instance\n * is stored only while its parent is and the cap allows, otherwise only its\n * id is tracked, so the stored part is always a rooted, orphan-free tree.\n */\n ingestComponents(\n data: { components?: unknown; epoch?: unknown; added?: unknown; removed?: unknown } | undefined,\n client?: HotClient,\n ): void {\n const epoch = typeof data?.epoch === 'string' ? data.epoch : LEGACY_EPOCH\n const isDelta =\n !Array.isArray(data?.components) &&\n (Array.isArray(data?.added) || Array.isArray(data?.removed))\n if (isDelta && !this.epochs.get(epoch)?.hasBase) {\n if (!this.resyncRequested.has(epoch)) {\n this.resyncRequested.add(epoch)\n client?.send(HOT_EVENTS.subscription, { ...this.subscription, resync: true })\n }\n return\n }\n const state = this.touchEpoch(epoch)\n if (!isDelta) {\n this.resyncRequested.delete(epoch)\n state.hasBase = true\n this.serve(epoch)\n state.components = new Map()\n state.overflow = new Set()\n }\n if (isDelta && Array.isArray(data?.removed)) {\n for (const id of data.removed as unknown[]) {\n if (!state.components.delete(id as number)) state.overflow.delete(id as number)\n }\n }\n const incoming = isDelta ? data?.added : data?.components\n if (Array.isArray(incoming)) {\n for (const c of incoming as ComponentInstance[]) {\n const id = c?.id\n if (state.components.has(id)) {\n state.components.set(id, c)\n continue\n }\n const parentStored = c?.parentId == null || state.components.has(c.parentId)\n if (parentStored && state.components.size < LIMITS.liveComponents) {\n state.overflow.delete(id)\n state.components.set(id, c)\n } else {\n state.overflow.add(id)\n }\n }\n }\n this.liveCache = undefined\n this.bump('components')\n }\n\n ingestProfiles(data: { profiles?: unknown; epoch?: unknown; total?: unknown } | undefined): void {\n const epoch = typeof data?.epoch === 'string' ? data.epoch : LEGACY_EPOCH\n const state = this.touchEpoch(epoch)\n state.profiles = tail(data?.profiles, LIMITS.renderProfiles)\n state.profilesTotal =\n typeof data?.total === 'number' && Number.isFinite(data.total) ? data.total : null\n this.bump('renderProfiles')\n }\n\n /**\n * What the server holds versus what was reported, per dataset (§6.7 B).\n * `total: null` means unknown; nothing is estimated.\n */\n getCaptureInfo(): CaptureInfoMap {\n const state = this.servedState()\n const epoch = this.servedEpoch\n const ring = (captured: number, received: number): CaptureInfo => ({\n captured,\n total: received,\n truncated: received > captured,\n policy: 'tail',\n })\n const drops: Record<DropReason, number> = {\n 'runtime-count': 0,\n 'runtime-bytes': 0,\n 'server-count': 0,\n 'server-bytes': 0,\n }\n for (const counts of this.timelineDrops.values()) {\n for (const reason of DROP_REASONS) drops[reason] += counts[reason]\n }\n const dropped = DROP_REASONS.filter(r => drops[r] > 0).map(reason => ({\n reason,\n count: drops[reason],\n }))\n let tooLarge = 0\n for (const n of this.timelineTooLarge.values()) tooLarge += n\n const profiles = state?.profiles.length ?? 0\n const profilesTotal = state?.profilesTotal ?? null\n const graph = this.lastGraph\n const info: CaptureInfoMap = {\n liveComponents: {\n captured: state?.components.size ?? 0,\n total: this.liveComponentsTotal,\n truncated: (state?.overflow.size ?? 0) > 0,\n policy: 'roots-first',\n ...(epoch !== undefined && { epoch }),\n },\n renderProfiles: {\n captured: profiles,\n total: profilesTotal,\n truncated: profilesTotal !== null && profilesTotal > profiles,\n // The runtime keeps first-render order and sends the tail: the newest-mounted instances (review IA1).\n policy: 'newest-mounted',\n ...(epoch !== undefined && { epoch }),\n },\n stateTimeline: {\n captured: this.timeline.length,\n total: null,\n truncated: dropped.length > 0,\n policy: 'sampled-200ms',\n ...(dropped.length > 0 && { dropped }),\n ...(tooLarge > 0 && { valueTooLarge: tooLarge }),\n ...(epoch !== undefined &&\n this.timelineBaseline.has(epoch) && { baseline: this.timelineBaseline.get(epoch) }),\n },\n fpsSamples: ring(this.fpsSamples.length, this.received.fps),\n runtimeErrors: ring(this.runtimeErrors.length, this.received.runtimeErrors),\n loadProfiles: ring(this.loadProfiles.length, this.received.loadProfiles),\n compilerWarnings: ring(this.compilerWarnings.length, this.received.compilerWarnings),\n }\n if (graph) {\n const common = {\n truncated: graph.truncated,\n policy: graph.policy,\n ...(graph.epoch !== null && { epoch: graph.epoch }),\n }\n info.reactiveNodes = {\n captured: graph.nodes.length,\n total: graph.total?.nodes ?? null,\n ...common,\n }\n info.reactiveEdges = {\n captured: graph.edges.length,\n total: graph.total?.edges ?? null,\n ...common,\n }\n }\n return info\n }\n\n /** The server-side timeline (all tracked epochs, oldest first). */\n get stateTimeline(): StateTimelineEntry[] {\n return this.timeline\n }\n\n /**\n * Two payload shapes (docs/devframe-migration.md §6.4):\n * - delta: `{ epoch, changes, reset? }` — `changes` are new since the\n * previous push from that page load (`epoch`); `reset` replaces that\n * epoch's entries. Entries are kept per epoch, so several app tabs (or a\n * reload) interleave instead of wiping each other.\n * - legacy full snapshot: `{ changes }` — we append only the entries after\n * the newest one we already hold, so clients still get deltas.\n */\n ingestStateTimeline(\n data:\n | {\n changes?: unknown\n epoch?: unknown\n reset?: unknown\n dropped?: unknown\n valueTooLarge?: unknown\n baseline?: unknown\n }\n | undefined,\n ): void {\n const incoming = tail<StateChange>(data?.changes, LIMITS.stateTimeline)\n if (typeof data?.epoch === 'string') {\n this.touchEpoch(data.epoch)\n this.countRuntimeLosses(data.epoch, data.dropped, data.valueTooLarge)\n if (data.reset === true) this.dropEpoch(data.epoch)\n this.appendTimeline(incoming, data.epoch)\n if (validBaseline(data.baseline))\n this.timelineBaseline.set(data.epoch, {\n complete: data.baseline.complete,\n pendingNodes: data.baseline.pendingNodes,\n })\n } else {\n let last: StateTimelineEntry | undefined\n for (let i = this.timeline.length - 1; i >= 0 && !last; i--) {\n if (this.timelineEpochs[i] === LEGACY_EPOCH) last = this.timeline[i]\n }\n let start = -1\n if (last) {\n for (let i = incoming.length - 1; i >= 0; i--) {\n if (incoming[i].timestamp === last.timestamp && incoming[i].id === last.id) {\n start = i + 1\n break\n }\n }\n }\n if (start === -1) {\n this.dropEpoch(LEGACY_EPOCH)\n start = 0\n }\n this.appendTimeline(incoming.slice(start), LEGACY_EPOCH)\n }\n this.lastPull.stateTimeline = Date.now()\n this.flushStateTimeline()\n // The runtime's activation snapshot ends with a `reset: true` timeline\n // (after components and profiles), so that completes a snapshot (D4).\n if (data?.reset === true) this.resolveSnapshotWaiters()\n }\n\n /**\n * Add the runtime's own losses (unsent entries it evicted, §6.7 C) and\n * too-large values to the epoch's counters. Only runtime reasons are\n * accepted from the runtime; server reasons are counted here.\n */\n private countRuntimeLosses(epoch: string, dropped: unknown, valueTooLarge: unknown): void {\n if (Array.isArray(dropped)) {\n for (const d of dropped as Array<{ reason?: unknown; count?: unknown }>) {\n if (d?.reason !== 'runtime-count' && d?.reason !== 'runtime-bytes') continue\n const count = clampInt(d.count, 0, Number.MAX_SAFE_INTEGER, 0)\n if (count > 0) this.addDrop(epoch, d.reason, count)\n }\n }\n const tooLarge = clampInt(valueTooLarge, 0, Number.MAX_SAFE_INTEGER, 0)\n if (tooLarge > 0) {\n this.timelineTooLarge.set(epoch, (this.timelineTooLarge.get(epoch) ?? 0) + tooLarge)\n }\n }\n\n private addDrop(epoch: string, reason: DropReason, count: number): void {\n let counts = this.timelineDrops.get(epoch)\n if (!counts) {\n counts = { 'runtime-count': 0, 'runtime-bytes': 0, 'server-count': 0, 'server-bytes': 0 }\n this.timelineDrops.set(epoch, counts)\n }\n counts[reason] += count\n }\n\n /** Changes after `since` (a previous `cursor`), or the whole buffer when the cursor is stale. */\n getStateTimelineDelta(since?: number): StateTimelineDelta {\n const cursor = this.timelineSeq\n if (\n since === undefined ||\n since < this.timelineResetAt ||\n since < this.timelineTrimmedAt ||\n since > cursor\n ) {\n return { cursor, reset: true, changes: this.timeline }\n }\n let i = this.timeline.length\n while (i > 0 && this.timeline[i - 1].seq > since) i--\n return { cursor, reset: false, changes: this.timeline.slice(i) }\n }\n\n /** Invalidate every cursor issued so far (entries were removed, not just appended). */\n private markTimelineReset(): void {\n this.timelineResetAt = this.timelineSeq = nextSeq()\n this.bump('stateTimeline')\n }\n\n private dropEpoch(epoch: string): void {\n if (!this.timelineEpochs.includes(epoch)) return\n const keep = this.timelineEpochs.map(e => e !== epoch)\n this.timeline = this.timeline.filter((_, i) => keep[i])\n this.timelineSizes = this.timelineSizes.filter((_, i) => keep[i])\n this.timelineEpochs = this.timelineEpochs.filter((_, i) => keep[i])\n this.timelineBytes = this.timelineSizes.reduce((a, b) => a + b, 0)\n this.markTimelineReset()\n }\n\n private appendTimeline(changes: StateChange[], epoch: string): void {\n if (changes.length === 0) return\n for (const change of changes) {\n let size = 0\n try {\n size = JSON.stringify(change).length\n } catch {\n continue // not serializable: never reaches a client anyway\n }\n this.timeline.push({ ...change, seq: (this.timelineSeq = nextSeq()) })\n this.timelineSizes.push(size)\n this.timelineEpochs.push(epoch)\n this.timelineBytes += size\n }\n let drop = Math.max(0, this.timeline.length - LIMITS.stateTimeline)\n let bytes = this.timelineBytes\n for (let i = 0; i < drop; i++) {\n bytes -= this.timelineSizes[i]\n this.addDrop(this.timelineEpochs[i], 'server-count', 1)\n }\n // Keep at least the newest entry even if it alone exceeds the budget.\n while (bytes > STATE_TIMELINE_BYTES && drop < this.timeline.length - 1) {\n this.addDrop(this.timelineEpochs[drop], 'server-bytes', 1)\n bytes -= this.timelineSizes[drop++]\n }\n if (drop > 0) {\n this.timelineTrimmedAt = this.timeline[drop - 1].seq\n this.timeline = this.timeline.slice(drop)\n this.timelineSizes = this.timelineSizes.slice(drop)\n this.timelineEpochs = this.timelineEpochs.slice(drop)\n }\n this.timelineBytes = bytes\n this.bump('stateTimeline')\n }\n\n private resolveSnapshotWaiters(): void {\n // Copy: each waiter removes itself from the list while we iterate.\n for (const done of this.snapshotWaiters.slice()) done()\n }\n\n /**\n * A graph reply. With a `requestId` (§6.7 A) it resolves only that request,\n * and only if its epoch matches the one asked for; a reply nobody waits for\n * (another app tab, too late) is ignored. Without one (an older runtime) it\n * is a whole-app graph and answers every pending graph pull, scoped ones by\n * filtering here.\n */\n ingestReactiveGraph(data: Record<string, any> | undefined): void {\n const requestId = typeof data?.requestId === 'string' ? data.requestId : undefined\n if (requestId !== undefined) {\n const pull = this.pulls.get(requestId)\n if (!pull || pull.kind !== 'graph') return\n if (pull.epoch !== null && typeof data?.epoch === 'string' && data.epoch !== pull.epoch)\n return\n this.settle(requestId, this.normalizeGraph(data, pull.scope, pull.epoch))\n } else {\n let answered = false\n for (const [id, pull] of this.pulls) {\n if (pull.kind !== 'graph') continue\n answered = true\n this.settle(id, this.normalizeGraph(data, pull.scope, pull.epoch))\n }\n if (!answered) this.storeGraph(this.normalizeGraph(data, null, this.servedEpoch ?? null))\n }\n this.bump('reactiveGraph')\n }\n\n /**\n * Shape a runtime reply into a {@link ReactiveGraphResult}: apply the\n * collector caps (nodes, then only edges between kept nodes, then the edge\n * cap) and report what was left out. Totals come from the runtime; an older\n * runtime's are the counts it sent (`nodesKind: 'sent'`), or unknown when\n * the server had to scope its whole-app graph.\n */\n private normalizeGraph(\n data: Record<string, any> | undefined,\n scope: number | null,\n epoch: string | null,\n ): ReactiveGraphResult {\n const legacy = typeof data?.requestId !== 'string'\n let nodes = head<ReactiveGraph['nodes'][number]>(data?.nodes, Infinity)\n const rawEdges = head<ReactiveGraph['edges'][number]>(data?.edges, Infinity)\n let policy: ReactiveGraphResult['policy'] =\n data?.policy === 'scoped' || data?.policy === 'global-head'\n ? data.policy\n : scope === null\n ? 'global-head'\n : 'scoped'\n let total: ReactiveGraphTotal | null = null\n if (!legacy && data?.total && typeof data.total.nodes === 'number') {\n total = {\n nodes: data.total.nodes,\n nodesKind: 'registered',\n edges: typeof data.total.edges === 'number' ? data.total.edges : null,\n }\n }\n if (legacy && scope !== null) {\n // Older runtime: whole app. Keep the component's nodes and their direct neighbours.\n const own = new Set(nodes.filter(n => n?.componentId === scope).map(n => n.id))\n const keep = new Set(own)\n for (const e of rawEdges) {\n if (own.has(e?.from)) keep.add(e.to)\n if (own.has(e?.to)) keep.add(e.from)\n }\n nodes = nodes.filter(n => keep.has(n?.id))\n policy = 'server-filter'\n } else if (legacy) {\n total = { nodes: nodes.length, nodesKind: 'sent', edges: rawEdges.length }\n }\n let truncated = data?.truncated === true\n if (nodes.length > LIMITS.reactiveNodes) {\n nodes = nodes.slice(0, LIMITS.reactiveNodes)\n truncated = true\n }\n const ids = new Set(nodes.map(n => n?.id))\n let edgesOmitted = clampInt(data?.edgesOmitted, 0, Number.MAX_SAFE_INTEGER, 0)\n const edges: ReactiveGraph['edges'] = []\n for (const e of rawEdges) {\n if (!ids.has(e?.from) || !ids.has(e?.to)) {\n if (policy !== 'server-filter') edgesOmitted++\n } else if (edges.length < LIMITS.reactiveEdges) {\n edges.push(e)\n } else {\n edgesOmitted++\n truncated = true\n }\n }\n return {\n nodes,\n edges,\n scope,\n epoch: typeof data?.epoch === 'string' ? data.epoch : epoch,\n total,\n truncated,\n edgesOmitted,\n // When the app built this graph; null from a runtime that doesn't say.\n computedAt:\n typeof data?.computedAt === 'number' && Number.isFinite(data.computedAt)\n ? data.computedAt\n : null,\n policy,\n }\n }\n\n private storeGraph(result: ReactiveGraphResult): void {\n this.lastGraph = result\n if (result.scope === null) this.reactiveGraph = { nodes: result.nodes, edges: result.edges }\n }\n\n /** A summary reply (§6.7 I): resolves only the matching request. */\n ingestReactiveSummary(data: Record<string, any> | undefined): void {\n const requestId = typeof data?.requestId === 'string' ? data.requestId : undefined\n const pull = requestId === undefined ? undefined : this.pulls.get(requestId)\n if (!pull || pull.kind !== 'summary') return\n if (pull.epoch !== null && typeof data?.epoch === 'string' && data.epoch !== pull.epoch) return\n this.settle(requestId!, this.normalizeSummary(data, pull.epoch))\n }\n\n private normalizeSummary(\n data: Record<string, any> | undefined,\n epoch: string | null,\n ): ReactiveSummary {\n const count = (v: unknown) => clampInt(v, 0, Number.MAX_SAFE_INTEGER, 0)\n const rows = head<Record<string, any>>(data?.rows, SUMMARY_DEFAULTS.maxTopK).map(r => ({\n componentId: count(r?.componentId),\n file: typeof r?.file === 'string' ? r.file : '',\n nodes: {\n state: count(r?.nodes?.state),\n derived: count(r?.nodes?.derived),\n effect: count(r?.nodes?.effect),\n },\n changes: count(r?.changes),\n renders: count(r?.renders),\n renderMs: typeof r?.renderMs === 'number' && r.renderMs >= 0 ? r.renderMs : 0,\n }))\n const w = data?.window\n return {\n epoch: typeof data?.epoch === 'string' ? data.epoch : epoch,\n window: {\n ms: count(w?.ms),\n since: count(w?.since),\n until: count(w?.until),\n sampledActiveMs: count(w?.sampledActiveMs),\n },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: {\n total: typeof data?.components?.total === 'number' ? data.components.total : null,\n withActivity: count(data?.components?.withActivity),\n },\n rows,\n other:\n data?.other &&\n typeof data.other.components === 'number' &&\n typeof data.other.nodes === 'number'\n ? { components: data.other.components, nodes: data.other.nodes }\n : null,\n truncated: data?.truncated === true,\n // Only what the runtime says it implements; never assumed.\n capabilities: {\n valueInspection: data?.capabilities?.valueInspection === true,\n signalHistory: data?.capabilities?.signalHistory === true,\n writeCause: data?.capabilities?.writeCause === true,\n },\n ...(validBaseline(data?.baseline) && { baseline: { ...data!.baseline } }),\n }\n }\n\n ingestFps(sample: FpsSample): void {\n this.received.fps++\n this.fpsSamples.push(sample)\n if (this.fpsSamples.length > LIMITS.fpsSamples) {\n this.fpsSamples = this.fpsSamples.slice(-LIMITS.fpsSamples)\n }\n this.bump('fps')\n this.hooks.onFpsSample?.(sample)\n }\n\n ingestRuntimeError(error: RuntimeError): void {\n this.received.runtimeErrors++\n this.runtimeErrors.push(error)\n if (this.runtimeErrors.length > LIMITS.runtimeErrors) {\n this.runtimeErrors = this.runtimeErrors.slice(-LIMITS.runtimeErrors)\n }\n this.bump('errors')\n }\n\n recordLoadProfile(profile: LoadProfile): void {\n this.received.loadProfiles++\n this.loadProfiles.push(profile)\n if (this.loadProfiles.length > LIMITS.loadProfiles) {\n this.loadProfiles = this.loadProfiles.slice(-LIMITS.loadProfiles)\n }\n this.bump('loadProfiles')\n this.hooks.onLoadProfile?.(profile)\n }\n\n recordCompilerWarning(warning: CompilerWarning): void {\n this.received.compilerWarnings++\n this.compilerWarnings.push(warning)\n if (this.compilerWarnings.length > LIMITS.compilerWarnings) {\n this.compilerWarnings = this.compilerWarnings.slice(-LIMITS.compilerWarnings)\n }\n this.bump('errors')\n }\n\n clearLoadProfiles(): void {\n this.loadProfiles = []\n this.received.loadProfiles = 0\n this.bump('loadProfiles')\n }\n\n clearErrors(): void {\n this.compilerWarnings = []\n this.runtimeErrors = []\n this.received.compilerWarnings = 0\n this.received.runtimeErrors = 0\n this.bump('errors')\n }\n\n clearFps(): void {\n this.fpsSamples = []\n this.received.fps = 0\n this.bump('fps')\n }\n\n clearStateTimeline(): void {\n this.timeline = []\n this.timelineSizes = []\n this.timelineEpochs = []\n this.timelineBytes = 0\n this.timelineDrops.clear()\n this.timelineTooLarge.clear()\n this.markTimelineReset()\n this.hot?.send(HOT_EVENTS.clearStateTimeline, {})\n }\n\n /**\n * Ask the browser runtime for the graph of one component instance (or the\n * whole app), built by the runtime within the caps (§6.7 A). Falls back to\n * the last result for the same scope, marked `stale`.\n */\n requestReactiveGraph(req: ReactiveGraphRequest = {}): Promise<ReactiveGraphResult> {\n const scope =\n typeof req.componentId === 'number' &&\n Number.isInteger(req.componentId) &&\n req.componentId >= 0\n ? req.componentId\n : null\n const maxNodes = clampInt(req.maxNodes, 1, LIMITS.reactiveNodes, LIMITS.reactiveNodes)\n const maxEdges = clampInt(req.maxEdges, 1, LIMITS.reactiveEdges, LIMITS.reactiveEdges)\n const epoch = this.servedEpoch ?? null\n if (scope !== null && epoch === null) {\n // No page load has sent its tree: a component id means nothing yet, and\n // asking every tab would let any of them answer for it (review MUST-1).\n return Promise.resolve({\n nodes: [],\n edges: [],\n scope,\n epoch,\n total: null,\n truncated: false,\n edgesOmitted: 0,\n computedAt: null,\n policy: 'scoped',\n stale: true,\n staleReason: 'no-runtime',\n })\n }\n if (scope !== null && typeof req.epoch === 'string' && req.epoch !== epoch) {\n // The id belongs to an earlier page load; another instance may reuse it now.\n return Promise.resolve({\n nodes: [],\n edges: [],\n scope,\n epoch,\n total: null,\n truncated: false,\n edgesOmitted: 0,\n computedAt: null,\n policy: 'scoped',\n stale: true,\n staleReason: 'epoch-changed',\n })\n }\n const key = `graph|${epoch ?? ''}|${scope ?? '*'}|${maxNodes}|${maxEdges}`\n return this.keyedPull<ReactiveGraphResult>(\n 'graph',\n key,\n epoch,\n scope,\n HOT_EVENTS.requestReactiveGraph,\n { ...(scope !== null && { componentId: scope }), maxNodes, maxEdges },\n reason => ({\n nodes: [],\n edges: [],\n scope,\n epoch,\n total: null,\n truncated: false,\n edgesOmitted: 0,\n computedAt: null,\n policy: scope === null ? 'global-head' : 'scoped',\n stale: true,\n staleReason: reason,\n }),\n )\n }\n\n /** Ask the runtime for the overview aggregate (§6.7 I); never captures the graph. */\n requestReactiveSummary(req: ReactiveSummaryRequest = {}): Promise<ReactiveSummary> {\n const topK = clampInt(req.topK, 1, SUMMARY_DEFAULTS.maxTopK, SUMMARY_DEFAULTS.topK)\n const windowMs = clampInt(\n req.windowMs,\n SUMMARY_DEFAULTS.minWindowMs,\n SUMMARY_DEFAULTS.maxWindowMs,\n SUMMARY_DEFAULTS.windowMs,\n )\n const epoch = this.servedEpoch ?? null\n const key = `summary|${epoch ?? ''}|${topK}|${windowMs}`\n return this.keyedPull<ReactiveSummary>(\n 'summary',\n key,\n epoch,\n null,\n HOT_EVENTS.requestReactiveSummary,\n { topK, windowMs },\n reason => ({\n epoch,\n window: { ms: windowMs, since: 0, until: 0, sampledActiveMs: 0 },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: { total: null, withActivity: 0 },\n rows: [],\n other: null,\n truncated: false,\n capabilities: { valueInspection: false, signalHistory: false, writeCause: false },\n stale: true,\n staleReason: reason,\n }),\n )\n }\n\n /**\n * One pull per key at a time; a result younger than {@link PULL_FRESHNESS}\n * is reused. The request carries a requestId and the served epoch; only\n * the matching reply resolves it. On timeout (or without a runtime) the\n * last result for the same key is returned with `stale: true`.\n */\n private keyedPull<T extends ReactiveGraphResult | ReactiveSummary>(\n kind: PendingPull['kind'],\n key: string,\n epoch: string | null,\n scope: number | null,\n event: string,\n payload: Record<string, unknown>,\n empty: (reason: 'timeout' | 'no-runtime') => T,\n ): Promise<T> {\n const fallback = (reason: 'timeout' | 'no-runtime'): T => {\n const last = this.pullCache.get(key)\n return last ? ({ ...last.value, stale: true, staleReason: reason } as T) : empty(reason)\n }\n const cached = this.pullCache.get(key)\n if (!this.hot) return Promise.resolve(fallback('no-runtime'))\n if (cached && Date.now() - cached.at < PULL_FRESHNESS) return Promise.resolve(cached.value as T)\n const existing = this.pullInflight.get(key) as Promise<T> | undefined\n if (existing) return existing\n const hot = this.hot\n const requestId = `r${++this.requestSeq}`\n const promise = new Promise<T>(resolve => {\n const timer = setTimeout(() => {\n this.pulls.delete(requestId)\n resolve(fallback('timeout'))\n }, RUNTIME_REQUEST_TIMEOUT)\n this.pulls.set(requestId, {\n kind,\n key,\n epoch,\n scope,\n resolve: resolve as PendingPull['resolve'],\n timer,\n })\n hot.send(event, { requestId, ...(epoch !== null && { epoch }), ...payload })\n }).finally(() => {\n if (this.pullInflight.get(key) === promise) this.pullInflight.delete(key)\n })\n this.pullInflight.set(key, promise)\n return promise\n }\n\n /** Resolve a pending pull with a fresh result and cache it under its key. */\n private settle(requestId: string, value: ReactiveGraphResult | ReactiveSummary): void {\n const pull = this.pulls.get(requestId)\n if (!pull) return\n this.pulls.delete(requestId)\n clearTimeout(pull.timer)\n this.pullCache.delete(pull.key)\n this.pullCache.set(pull.key, { value, at: Date.now() })\n while (this.pullCache.size > MAX_CACHED_PULLS) {\n this.pullCache.delete(this.pullCache.keys().next().value!)\n }\n if (pull.kind === 'graph') this.storeGraph(value as ReactiveGraphResult)\n pull.resolve(value)\n }\n\n /** Answer every pending keyed pull from its cache (or empty), marked stale. */\n private flushPulls(reason: 'timeout' | 'no-runtime'): void {\n for (const [id, pull] of this.pulls) {\n this.pulls.delete(id)\n clearTimeout(pull.timer)\n const cached = this.pullCache.get(pull.key)\n if (cached) {\n pull.resolve({ ...cached.value, stale: true, staleReason: reason })\n } else if (pull.kind === 'graph') {\n pull.resolve({\n nodes: [],\n edges: [],\n scope: pull.scope,\n epoch: pull.epoch,\n total: null,\n truncated: false,\n edgesOmitted: 0,\n computedAt: null,\n policy: pull.scope === null ? 'global-head' : 'scoped',\n stale: true,\n staleReason: reason,\n })\n } else {\n pull.resolve({\n epoch: pull.epoch,\n window: { ms: 0, since: 0, until: 0, sampledActiveMs: 0 },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: { total: null, withActivity: 0 },\n rows: [],\n other: null,\n truncated: false,\n capabilities: { valueInspection: false, signalHistory: false, writeCause: false },\n stale: true,\n staleReason: reason,\n })\n }\n }\n }\n\n /** Ask the browser runtime for a fresh state timeline; falls back to the last one. */\n requestStateTimeline(): Promise<StateChange[]> {\n return this.pull(\n 'stateTimeline',\n HOT_EVENTS.requestStateTimeline,\n this.stateTimelineResolvers,\n () => this.stateTimeline,\n )\n }\n\n /**\n * Concurrent callers share one in-flight pull, and a result younger than\n * {@link PULL_FRESHNESS} is reused, so several polling clients never make\n * the user's app rebuild the same data more than once a second.\n */\n private pull<K extends 'stateTimeline', T>(\n key: K,\n event: string,\n resolvers: Array<(value: T) => void>,\n cached: () => T,\n ): Promise<T> {\n if (!this.hot || Date.now() - this.lastPull[key] < PULL_FRESHNESS) {\n return Promise.resolve(cached())\n }\n const existing = this.inflight[key] as Promise<T> | undefined\n if (existing) return existing\n const hot = this.hot\n const promise = new Promise<T>(resolve => {\n const resolver = (value: T) => {\n clearTimeout(timeout)\n resolve(value)\n }\n const timeout = setTimeout(() => {\n // Remove this resolver to prevent a leak, then answer from cache.\n const idx = resolvers.indexOf(resolver)\n if (idx !== -1) resolvers.splice(idx, 1)\n resolve(cached())\n }, RUNTIME_REQUEST_TIMEOUT)\n resolvers.push(resolver)\n hot.send(event, {})\n }).finally(() => {\n if (this.inflight[key] === promise) this.inflight[key] = undefined\n })\n this.inflight[key] = promise as never\n return promise\n }\n\n // Snapshot then reset before resolving so concurrent requests that push\n // during the resolve loop are not silently dropped.\n private flushStateTimeline(): void {\n const pending = this.stateTimelineResolvers\n this.stateTimelineResolvers = []\n for (const resolve of pending) resolve(this.stateTimeline)\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport type { AssetInfo } from '../types.js'\n\nexport const MIME_TYPES: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.eot': 'application/vnd.ms-fontobject',\n '.otf': 'font/otf',\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n '.json': 'application/json',\n '.xml': 'application/xml',\n '.pdf': 'application/pdf',\n '.txt': 'text/plain',\n '.css': 'text/css',\n '.js': 'text/javascript',\n '.html': 'text/html',\n}\n\n/**\n * List files in the static directory. `publicBase` is the dev server's\n * public base (Vite `base`); static files are served under it, so each asset\n * gets a previewable `url` without a dedicated file-serving endpoint.\n */\nexport function analyzeAssets(staticDir: string, publicBase = '/'): AssetInfo[] {\n if (!fs.existsSync(staticDir)) return []\n\n const assets: AssetInfo[] = []\n const base = publicBase.endsWith('/') ? publicBase : `${publicBase}/`\n scanDir(staticDir, staticDir, base, assets)\n return assets.sort((a, b) => a.relativePath.localeCompare(b.relativePath))\n}\n\nfunction scanDir(dir: string, rootDir: string, base: string, assets: AssetInfo[]): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n scanDir(fullPath, rootDir, base, assets)\n continue\n }\n\n // Skip hidden files\n if (entry.name.startsWith('.')) continue\n\n const stat = fs.statSync(fullPath)\n const ext = path.extname(entry.name).toLowerCase()\n\n const relativePath = path.relative(rootDir, fullPath)\n assets.push({\n name: entry.name,\n path: fullPath,\n relativePath,\n url: base + relativePath.split(path.sep).map(encodeURIComponent).join('/'),\n size: stat.size,\n type: MIME_TYPES[ext] || 'application/octet-stream',\n mtime: stat.mtimeMs,\n })\n }\n}\n","import dns from 'node:dns/promises'\nimport fs from 'node:fs'\nimport net from 'node:net'\nimport path from 'node:path'\n\n/**\n * Validate that a URL does not target private/internal network addresses (SSRF prevention).\n * Allows only http/https schemes and blocks private IP ranges.\n */\nexport function validateExternalUrl(urlStr: string): void {\n parseExternalUrl(urlStr)\n}\n\nfunction parseExternalUrl(urlStr: string): URL {\n let parsed: URL\n try {\n parsed = new URL(urlStr)\n } catch {\n throw new Error(`Invalid URL: ${urlStr}`)\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error(`Blocked URL scheme: ${parsed.protocol}`)\n }\n\n const hostname = parsed.hostname\n // Block IPv6 loopback\n if (hostname === '::1' || hostname === '[::1]') {\n throw new Error('Blocked: loopback address')\n }\n\n if (net.isIP(hostname)) {\n if (isPrivateIP(hostname)) {\n throw new Error(`Blocked: private IP address ${hostname}`)\n }\n } else {\n // For domain names, block common internal hostnames\n const lower = hostname.toLowerCase()\n if (lower === 'localhost' || lower.endsWith('.local') || lower.endsWith('.internal')) {\n throw new Error(`Blocked: internal hostname ${hostname}`)\n }\n }\n return parsed\n}\n\nexport interface OutboundUrlOptions {\n /**\n * Origins that may be fetched even though they are local — the dev\n * server's own resolved URLs, so the API playground can call the app.\n */\n allowedOrigins?: readonly string[]\n}\n\n/**\n * Like {@link validateExternalUrl}, but also resolves the hostname and\n * rejects names that point at private / loopback addresses (DNS-based SSRF).\n * Exact dev-server origins in `allowedOrigins` bypass the private checks.\n * Callers must also fetch with `redirect: 'manual'` so a public URL cannot\n * bounce the request to a private one.\n */\nexport async function assertOutboundUrl(\n urlStr: string,\n options: OutboundUrlOptions = {},\n): Promise<URL> {\n let parsed: URL\n try {\n parsed = new URL(urlStr)\n } catch {\n throw new Error(`Invalid URL: ${urlStr}`)\n }\n if (options.allowedOrigins?.includes(parsed.origin)) return parsed\n parseExternalUrl(urlStr)\n const hostname = parsed.hostname.replace(/^\\[|\\]$/g, '')\n if (net.isIP(hostname)) return parsed\n const addresses = await dns.lookup(hostname, { all: true }).catch(() => [])\n for (const { address } of addresses) {\n if (isPrivateIP(address)) throw new Error(`Blocked: ${hostname} resolves to private address`)\n }\n return parsed\n}\n\nexport function isPrivateIP(ip: string): boolean {\n if (ip.includes(':')) return isPrivateIPv6(ip)\n const parts = ip.split('.').map(Number)\n if (parts.length === 4) {\n // 127.0.0.0/8\n if (parts[0] === 127) return true\n // 10.0.0.0/8\n if (parts[0] === 10) return true\n // 172.16.0.0/12\n if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true\n // 192.168.0.0/16\n if (parts[0] === 192 && parts[1] === 168) return true\n // 169.254.0.0/16 (link-local)\n if (parts[0] === 169 && parts[1] === 254) return true\n // 0.0.0.0\n if (parts.every(p => p === 0)) return true\n }\n return false\n}\n\nfunction isPrivateIPv6(ip: string): boolean {\n const lower = ip.toLowerCase().replace(/^\\[|\\]$/g, '')\n // IPv4-mapped / -compatible (::ffff:127.0.0.1, ::127.0.0.1)\n const v4 = lower.match(/^::(?:ffff:)?(\\d+\\.\\d+\\.\\d+\\.\\d+)$/)\n if (v4) return isPrivateIP(v4[1])\n if (lower === '::' || lower === '::1') return true\n // fc00::/7 unique local, fe80::/10 link-local\n return /^f[cd][0-9a-f]{2}:/.test(lower) || /^fe[89ab][0-9a-f]:/.test(lower)\n}\n\n/**\n * Resolve a user-supplied file path strictly under `root`. Symlinks are\n * followed via realpathSync so that symlinks inside the project cannot be\n * used to escape the root sandbox. Throws if the real path is outside.\n */\nexport function resolveWithinRoot(root: string, input: string): string {\n if (typeof input !== 'string' || input.length === 0) {\n throw new Error('Invalid file path')\n }\n const realRoot = fs.realpathSync(root)\n const candidate = path.isAbsolute(input) ? input : path.resolve(root, input)\n let real: string\n try {\n real = fs.realpathSync(candidate)\n } catch {\n throw new Error('File not found')\n }\n if (real !== realRoot && !real.startsWith(realRoot + path.sep)) {\n throw new Error('Forbidden: path outside project root')\n }\n return real\n}\n","import fs from 'node:fs'\nimport { assertOutboundUrl } from '../security.js'\nimport type { OutboundUrlOptions } from '../security.js'\nimport type { ApiEndpoint, ApiResponse, RouteInfo } from '../types.js'\n\nconst HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']\n\n/** List `+server` endpoints and the HTTP methods they export. */\nexport function analyzeApiEndpoints(routes: RouteInfo[]): ApiEndpoint[] {\n const endpoints: ApiEndpoint[] = []\n for (const route of routes) {\n const serverFile = route.files.find(f => f.type === 'endpoint')\n if (!serverFile) continue\n let content = ''\n try {\n content = fs.readFileSync(serverFile.path, 'utf-8')\n } catch {\n /* file may not exist */\n }\n const methods = HTTP_METHODS.filter(\n m =>\n content.includes(`export const ${m}`) ||\n content.includes(`export async function ${m}`) ||\n content.includes(`export function ${m}`),\n )\n if (methods.length === 0) methods.push('GET')\n endpoints.push({ route: route.id, path: route.path, methods, file: serverFile.path })\n }\n return endpoints\n}\n\nexport interface ApiRequestInput {\n url: string\n method: string\n /** JSON-encoded header object (as typed by the user). */\n headers: string\n body: string\n}\n\n/**\n * Send a request to a public URL or the dev server itself (SSRF-guarded) and\n * report the response. Redirects are returned, never followed.\n */\nexport async function sendApiRequest(\n input: ApiRequestInput,\n options: OutboundUrlOptions = {},\n): Promise<ApiResponse> {\n const start = performance.now()\n const duration = () => Math.round((performance.now() - start) * 100) / 100\n try {\n await assertOutboundUrl(input.url, options)\n const parsedHeaders = input.headers ? JSON.parse(input.headers) : {}\n const init: RequestInit = { method: input.method, headers: parsedHeaders, redirect: 'manual' }\n if (input.body && input.method !== 'GET' && input.method !== 'HEAD') init.body = input.body\n const res = await fetch(input.url, init)\n const body = await res.text()\n const headers: Record<string, string> = {}\n res.headers.forEach((v, k) => {\n headers[k] = v\n })\n return { status: res.status, statusText: res.statusText, headers, body, duration: duration() }\n } catch (e) {\n return { status: 0, statusText: String(e), headers: {}, body: '', duration: duration() }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { BuildAnalysis, BuildChunk } from '../types.js'\n\nconst WEB_EXTENSIONS = new Set(['.js', '.css', '.html'])\n\n/** Scan common SvelteKit build output directories for emitted web assets. */\nexport function analyzeBuild(root: string): BuildAnalysis {\n const chunks: BuildChunk[] = []\n const dirs = [\n path.resolve(root, '.svelte-kit/output'),\n path.resolve(root, 'build/client'),\n path.resolve(root, 'build'),\n ]\n const walkDir = (d: string) => {\n for (const entry of fs.readdirSync(d, { withFileTypes: true })) {\n const full = path.join(d, entry.name)\n if (entry.isDirectory()) {\n walkDir(full)\n continue\n }\n if (!WEB_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) continue\n chunks.push({\n name: entry.name,\n file: path.relative(root, full),\n size: fs.statSync(full).size,\n modules: [],\n isEntry: entry.name.includes('index') || entry.name.includes('start'),\n })\n }\n }\n for (const dir of dirs) {\n try {\n walkDir(dir)\n } catch {\n /* directory doesn't exist or not readable */\n }\n }\n chunks.sort((a, b) => b.size - a.size)\n return { chunks, totalSize: chunks.reduce((s, c) => s + c.size, 0), timestamp: Date.now() }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { ModuleGraphData, ModuleNode } from '../types.js'\n\n/** Minimal shape of a Vite module-graph node that we read. */\nexport interface GraphModuleLike {\n file?: string | null\n importedModules: Iterable<{ file?: string | null }>\n}\n\nfunction classify(file: string): ModuleNode['type'] {\n const ext = path.extname(file).toLowerCase()\n if (ext === '.svelte') return 'svelte'\n if (ext === '.ts') return 'ts'\n if (ext === '.js') return 'js'\n if (ext === '.css') return 'css'\n return 'other'\n}\n\n/**\n * Build the project-local module graph (node_modules and files outside\n * `root` excluded) and detect import cycles.\n */\nexport function buildModuleGraph(root: string, allModules: GraphModuleLike[]): ModuleGraphData {\n const modules: ModuleNode[] = []\n const idMap = new Map<string, ModuleNode>()\n const moduleById = new Map<string, ModuleNode>()\n\n for (const mod of allModules) {\n if (!mod.file || mod.file.includes('node_modules')) continue\n const relFile = path.relative(root, mod.file)\n if (relFile.startsWith('..')) continue\n if (idMap.has(mod.file)) continue // deduplicate across environments\n let size: number | undefined\n try {\n size = fs.statSync(mod.file).size\n } catch {\n /* ignore */\n }\n const node: ModuleNode = {\n id: relFile,\n file: mod.file,\n type: classify(mod.file),\n importedBy: [],\n imports: [],\n size,\n }\n idMap.set(mod.file, node)\n moduleById.set(relFile, node)\n modules.push(node)\n }\n\n // Build edges using Sets for O(1) dedup\n const importedBySets = new Map<ModuleNode, Set<string>>()\n for (const mod of allModules) {\n if (!mod.file) continue\n const node = idMap.get(mod.file)\n if (!node) continue\n const importsSet = new Set(node.imports)\n for (const imp of mod.importedModules) {\n const impNode = imp.file ? idMap.get(imp.file) : undefined\n if (!impNode) continue\n if (!importsSet.has(impNode.id)) {\n importsSet.add(impNode.id)\n node.imports.push(impNode.id)\n }\n let by = importedBySets.get(impNode)\n if (!by) importedBySets.set(impNode, (by = new Set(impNode.importedBy)))\n if (!by.has(node.id)) {\n by.add(node.id)\n impNode.importedBy.push(node.id)\n }\n }\n }\n\n // Detect cycles (DFS), push/pop path buffer to avoid array copies\n const cycles: string[][] = []\n const visited = new Set<string>()\n const stack = new Set<string>()\n const pathBuf: string[] = []\n function dfs(id: string) {\n if (stack.has(id)) {\n const cycleStart = pathBuf.indexOf(id)\n if (cycleStart >= 0) {\n const cycle = pathBuf.slice(cycleStart).concat(id)\n if (cycle.length > 2) cycles.push(cycle) // skip self-references\n }\n return\n }\n if (visited.has(id)) return\n visited.add(id)\n stack.add(id)\n pathBuf.push(id)\n const node = moduleById.get(id)\n if (node) for (const imp of node.imports) dfs(imp)\n pathBuf.pop()\n stack.delete(id)\n }\n for (const m of modules) dfs(m.id)\n\n const cyclicIds = new Set(cycles.flat())\n for (const m of modules) if (cyclicIds.has(m.id)) m.isCyclic = true\n\n return { modules, cycles }\n}\n","import { assertOutboundUrl } from '../security.js'\nimport type { OutboundUrlOptions } from '../security.js'\nimport type { OGPreview } from '../types.js'\n\n/**\n * Fetch a public URL (or a page of the dev server itself) and report its Open\n * Graph tags + missing-tag issues. Redirects are not followed.\n */\nexport async function getOGPreview(\n url: string,\n options: OutboundUrlOptions = {},\n): Promise<OGPreview> {\n const preview: OGPreview = { url, title: '', description: '', image: '', tags: [], issues: [] }\n try {\n await assertOutboundUrl(url, options)\n const res = await fetch(url, { redirect: 'manual' })\n if (res.status >= 300 && res.status < 400) {\n preview.issues.push(\n `Redirects to ${res.headers.get('location') ?? '(no location)'} (not followed)`,\n )\n return preview\n }\n const html = await res.text()\n // Attribute-order independent; matches both <meta ...> and <meta ... />\n const metaRegex = /<meta\\s+([^>]*?)\\/?>/gi\n const propRegex = /(?:property|name)=[\"']([^\"']+)[\"']/\n const contentRegex = /content=[\"']([^\"']+)[\"']/\n let match\n while ((match = metaRegex.exec(html)) !== null) {\n const attrs = match[1]\n const propMatch = attrs.match(propRegex)\n const contentMatch = attrs.match(contentRegex)\n if (propMatch && contentMatch) {\n const prop = propMatch[1]\n const content = contentMatch[1]\n preview.tags.push({ property: prop, content })\n if (prop === 'og:title') preview.title = content\n else if (prop === 'og:description') preview.description = content\n else if (prop === 'og:image') preview.image = content\n }\n }\n if (!preview.title) {\n const titleMatch = html.match(/<title>([^<]+)<\\/title>/i)\n if (titleMatch) preview.title = titleMatch[1]\n }\n if (!preview.description) {\n const descTag = preview.tags.find(t => t.property === 'description')\n if (descTag) preview.description = descTag.content\n }\n if (!preview.title) preview.issues.push('Missing og:title or <title>')\n if (!preview.description) preview.issues.push('Missing og:description or meta description')\n if (!preview.image) preview.issues.push('Missing og:image')\n if (!preview.tags.some(t => t.property === 'og:url')) preview.issues.push('Missing og:url')\n if (!preview.tags.some(t => t.property === 'og:type')) preview.issues.push('Missing og:type')\n } catch (e) {\n preview.issues.push(`Failed to fetch: ${String(e)}`)\n }\n return preview\n}\n","/**\n * Find the 1-based line of a reactive declaration in a component source:\n * the first `$effect(` / `$effect.pre(` for effects, otherwise the\n * `let|const|var <name>` declaration. Returns 0 when not found.\n */\nexport function findReactiveLine(source: string, name: string, type: string): number {\n const lines = source.split('\\n')\n if (type === 'effect') {\n const idx = lines.findIndex(l => l.includes('$effect(') || l.includes('$effect.pre('))\n return idx + 1\n }\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n const regex = new RegExp(`(?:let|const|var)\\\\s+${escaped}\\\\b`)\n const idx = lines.findIndex(l => regex.test(l))\n return idx + 1\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { defineDevframe, defineRpcFunction } from 'devframe'\nimport type { DevframeDefinition } from 'devframe'\nimport { z } from 'zod'\nimport { analyzeRoutes } from './analyzers/routes.js'\nimport { analyzeAssets } from './analyzers/assets.js'\nimport { analyzeProject } from './analyzers/project.js'\nimport { analyzeComponents } from './analyzers/components.js'\nimport { analyzeApiEndpoints, sendApiRequest } from './analyzers/api.js'\nimport { analyzeBuild } from './analyzers/build.js'\nimport { buildModuleGraph } from './analyzers/module-graph.js'\nimport type { GraphModuleLike } from './analyzers/module-graph.js'\nimport { getOGPreview } from './analyzers/og.js'\nimport { findReactiveLine } from './analyzers/source.js'\nimport { resolveWithinRoot } from './security.js'\nimport type { Collector } from './collector.js'\nimport type {\n ApiResponse,\n CaptureInfoMap,\n InspectResult,\n OGPreview,\n ReactiveGraphResult,\n ReactiveSummary,\n StateTimelineDelta,\n LiveComponentsMeta,\n} from './types.js'\n\nexport const DEVFRAME_ID = 'svelte-devtools'\n/** Mount base for both hosts (standalone and Vite DevTools), so the SPA URL never changes. */\nexport const DEVFRAME_BASE = '/.svelte-devtools/'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('../package.json') as {\n name: string\n version: string\n description: string\n homepage: string\n}\nconst clientAssets = path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'client')\n\n/**\n * Everything the portable devframe needs from whatever hosts it. The Vite\n * plugin implements this over its dev server; tests implement it directly.\n * Getters are lazy because the host resolves config after construction.\n */\nexport interface SvelteDevtoolsHost {\n collector: Collector\n /** Absolute project root. */\n root: () => string\n /** Public base the dev server serves the app (and static files) under. */\n publicBase: () => string\n /** Every module the dev server currently knows about, across environments. */\n modules: () => GraphModuleLike[]\n /** Compile a project file through the dev server's pipeline (absent without a server). */\n transformRequest?: (file: string) => Promise<{\n code: string\n map?: { mappings?: string; sources?: string[] } | string | null\n } | null>\n /** Origins the dev server itself is reachable at (API playground / OG preview may call them). */\n serverOrigins: () => string[]\n /** Open `file[:line]` in the user's editor. */\n openInEditor: (target: string) => void\n}\n\nconst filePath = z.string().min(1).max(4096)\n\nexport function createRpcFunctions(host: SvelteDevtoolsHost) {\n const { collector } = host\n const project = () => analyzeProject(host.root())\n const routes = () => analyzeRoutes(project().routesDir)\n\n return [\n defineRpcFunction({\n name: 'get-project',\n type: 'query',\n jsonSerializable: true,\n handler: () => project(),\n }),\n defineRpcFunction({\n name: 'get-routes',\n type: 'query',\n jsonSerializable: true,\n handler: () => routes(),\n }),\n defineRpcFunction({\n name: 'get-assets',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeAssets(project().staticDir, host.publicBase()),\n }),\n defineRpcFunction({\n name: 'get-component-relations',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeComponents(host.root()),\n }),\n defineRpcFunction({\n name: 'get-svelte-files',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeComponents(host.root()).map(c => ({ file: c.file, name: c.name })),\n }),\n defineRpcFunction({\n name: 'get-live-components',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.liveComponents,\n }),\n defineRpcFunction({\n name: 'get-live-components-meta',\n type: 'query',\n jsonSerializable: true,\n handler: (): LiveComponentsMeta => ({\n total: collector.liveComponentsTotal,\n kept: collector.liveComponents.length,\n truncated: collector.liveComponentsTotal > collector.liveComponents.length,\n ...collector.epochInfo,\n }),\n }),\n defineRpcFunction({\n name: 'set-active',\n type: 'action',\n jsonSerializable: true,\n args: [z.object({ client: z.string().min(1).max(64), active: z.boolean() })],\n returns: z.void(),\n handler: ({ client, active }) => {\n if (active) collector.lease(`ui:${client}`)\n else collector.release(`ui:${client}`)\n },\n }),\n defineRpcFunction({\n name: 'open-in-editor',\n type: 'action',\n jsonSerializable: true,\n args: [z.object({ file: filePath, line: z.number().int().nonnegative().optional() })],\n returns: z.void(),\n handler: ({ file, line }) => {\n const resolved = resolveWithinRoot(host.root(), file)\n host.openInEditor(line ? `${resolved}:${line}` : resolved)\n },\n }),\n defineRpcFunction({\n name: 'open-reactive-in-editor',\n type: 'action',\n jsonSerializable: true,\n args: [z.object({ file: filePath, name: z.string().max(256), type: z.string().max(32) })],\n returns: z.void(),\n handler: ({ file, name, type }) => {\n const resolved = resolveWithinRoot(host.root(), file)\n let line = 0\n try {\n line = findReactiveLine(fs.readFileSync(resolved, 'utf-8'), name, type)\n } catch {\n /* file not readable */\n }\n host.openInEditor(line > 0 ? `${resolved}:${line}` : resolved)\n },\n }),\n defineRpcFunction({\n name: 'get-render-profiles',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.renderProfiles,\n }),\n defineRpcFunction({\n name: 'get-reactive-graph',\n type: 'query',\n jsonSerializable: true,\n // Omitted = whole app (older clients). Scoped requests are built by the\n // runtime within the caps (docs/devframe-migration.md §6.7 A).\n args: [\n z\n .object({\n componentId: z.number().int().nonnegative().optional(),\n epoch: z.string().max(200).optional(),\n maxNodes: z.number().int().positive().optional(),\n maxEdges: z.number().int().positive().optional(),\n })\n .optional(),\n ],\n returns: z.custom<ReactiveGraphResult>(),\n handler: req => collector.requestReactiveGraph(req ?? {}),\n }),\n defineRpcFunction({\n name: 'get-reactive-summary',\n type: 'query',\n jsonSerializable: true,\n // Overview aggregate from runtime counters; never captures the graph (§6.7 I).\n args: [\n z\n .object({\n topK: z.number().int().positive().optional(),\n windowMs: z.number().int().positive().optional(),\n })\n .optional(),\n ],\n returns: z.custom<ReactiveSummary>(),\n handler: req => collector.requestReactiveSummary(req ?? {}),\n }),\n defineRpcFunction({\n name: 'get-capture-info',\n type: 'query',\n jsonSerializable: true,\n handler: (): CaptureInfoMap => collector.getCaptureInfo(),\n }),\n defineRpcFunction({\n name: 'get-load-profiles',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.loadProfiles,\n }),\n defineRpcFunction({\n name: 'clear-load-profiles',\n type: 'action',\n jsonSerializable: true,\n handler: () => collector.clearLoadProfiles(),\n }),\n defineRpcFunction({\n name: 'get-state-timeline',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.requestStateTimeline(),\n }),\n defineRpcFunction({\n name: 'get-state-timeline-delta',\n type: 'query',\n jsonSerializable: true,\n args: [z.object({ since: z.number().int().nonnegative().optional() })],\n returns: z.custom<StateTimelineDelta>(),\n // Served from the buffer the runtime pushes into; never pulls the app.\n handler: ({ since }) => collector.getStateTimelineDelta(since),\n }),\n defineRpcFunction({\n name: 'get-versions',\n type: 'query',\n jsonSerializable: true,\n handler: () => ({ ...collector.versions }),\n }),\n defineRpcFunction({\n name: 'clear-state-timeline',\n type: 'action',\n jsonSerializable: true,\n handler: () => collector.clearStateTimeline(),\n }),\n defineRpcFunction({\n name: 'get-api-endpoints',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeApiEndpoints(routes()),\n }),\n defineRpcFunction({\n name: 'send-api-request',\n type: 'action',\n jsonSerializable: true,\n args: [\n z.object({\n url: z.string().max(8192),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),\n headers: z.string().max(65536),\n body: z.string().max(1_000_000),\n }),\n ],\n returns: z.custom<ApiResponse>(),\n handler: input => sendApiRequest(input, { allowedOrigins: host.serverOrigins() }),\n }),\n defineRpcFunction({\n name: 'get-compiler-warnings',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.compilerWarnings,\n }),\n defineRpcFunction({\n name: 'get-runtime-errors',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.runtimeErrors,\n }),\n defineRpcFunction({\n name: 'clear-errors',\n type: 'action',\n jsonSerializable: true,\n handler: () => collector.clearErrors(),\n }),\n defineRpcFunction({\n name: 'inspect-file',\n type: 'query',\n jsonSerializable: true,\n args: [z.object({ file: filePath })],\n returns: z.custom<InspectResult>(),\n handler: async ({ file }): Promise<InspectResult> => {\n const empty: InspectResult = { source: '', compiled: '', file }\n let resolved: string\n let source: string\n try {\n resolved = resolveWithinRoot(host.root(), file)\n source = fs.readFileSync(resolved, 'utf-8')\n } catch {\n return empty\n }\n if (!host.transformRequest) return { ...empty, source }\n try {\n const result = await host.transformRequest(resolved)\n const map = typeof result?.map === 'string' ? JSON.parse(result.map) : result?.map\n return {\n source,\n compiled: result?.code || '',\n file,\n mappings: map?.mappings,\n sources: map?.sources,\n }\n } catch {\n return { source, compiled: '// Transform failed', file }\n }\n },\n }),\n defineRpcFunction({\n name: 'get-module-graph',\n type: 'query',\n jsonSerializable: true,\n handler: () => buildModuleGraph(host.root(), host.modules()),\n }),\n defineRpcFunction({\n name: 'get-og-preview',\n type: 'action',\n jsonSerializable: true,\n args: [z.object({ url: z.string().max(8192) })],\n returns: z.custom<OGPreview>(),\n handler: ({ url }) => getOGPreview(url, { allowedOrigins: host.serverOrigins() }),\n }),\n defineRpcFunction({\n name: 'get-build-analysis',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeBuild(host.root()),\n }),\n defineRpcFunction({\n name: 'get-fps',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.fpsSamples,\n }),\n defineRpcFunction({\n name: 'clear-fps',\n type: 'action',\n jsonSerializable: true,\n handler: () => collector.clearFps(),\n }),\n ] as const\n}\n\n/**\n * The portable Svelte DevTools tool. Host-agnostic: the same definition is\n * mounted standalone (`initDevframe`) or inside Vite DevTools\n * (`createPluginFromDevframe`); the SPA in `dist/client` connects with\n * `connectDevframe()` either way.\n */\nexport function createSvelteDevframe(host: SvelteDevtoolsHost): DevframeDefinition {\n return defineDevframe({\n id: DEVFRAME_ID,\n name: 'Svelte',\n version: pkg.version,\n packageName: pkg.name,\n importMetaUrl: import.meta.url,\n homepage: pkg.homepage,\n description: pkg.description,\n icon: 'simple-icons:svelte',\n basePath: DEVFRAME_BASE,\n // Live data from an instrumented dev server only; a static export would be an empty shell.\n capabilities: { dev: true, build: false },\n dock: { category: 'framework' },\n clientAssets,\n setup(ctx) {\n const scoped = ctx.scope(DEVFRAME_ID)\n for (const fn of createRpcFunctions(host)) scoped.rpc.register(fn)\n },\n })\n}\n","import os from 'node:os'\nimport type { Server } from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport type { ViteDevServer } from 'vite'\nimport type { DevframeDefinition } from 'devframe'\nimport { initDevframe } from 'devframe/initiate'\nimport type { DevframeInstance } from 'devframe/initiate'\nimport { DEVFRAME_BASE } from './devframe.js'\n\nconst WILDCARD = new Set(['0.0.0.0', '::'])\nconst LOOPBACK = new Set(['127.0.0.1', '::1', 'localhost'])\n\nfunction formatHost(address: string): string {\n return address.includes(':') ? `[${address}]` : address\n}\n\n/**\n * Origins a browser may load the DevTools from when the dev server is\n * reachable beyond loopback (`server.host`). devframe accepts loopback\n * origins by default and rejects every other WS `Origin` unless listed.\n */\nexport function networkOrigins(address: AddressInfo, proto: string): string[] {\n if (LOOPBACK.has(address.address)) return []\n const hosts = WILDCARD.has(address.address)\n ? Object.values(os.networkInterfaces())\n .flat()\n .filter(i => i && !i.internal)\n .map(i => i!.address)\n : [address.address]\n return hosts.map(h => `${proto}://${formatHost(h)}:${address.port}`)\n}\n\n/**\n * Serve the devframe standalone on this dev server: SPA, discovery,\n * WebSocket RPC on Vite's own HTTP server at `<base>__ws`, auth gate.\n *\n * The instance is created per server and closed by *that* server's `close`\n * event, so a restart (which builds the new server before closing the old\n * one) can never tear down the new instance.\n */\nexport function mountStandalone(\n server: ViteDevServer,\n def: DevframeDefinition,\n): (() => Promise<void>) | undefined {\n let instance: DevframeInstance | undefined\n let closed = false\n const httpServer = server.httpServer\n\n server.middlewares.use((req, res, next) => {\n if (instance) return instance.nodeMiddleware(req, res, next)\n if (req.url?.startsWith(DEVFRAME_BASE)) {\n // Not listening yet (or already closed): don't let the app's SPA\n // fallback answer for the DevTools.\n res.statusCode = 503\n res.end('Svelte DevTools is starting')\n return\n }\n next()\n })\n\n if (!httpServer) {\n // Middleware mode: no server to share the upgrade with, so devframe\n // serves its SSE transport through the same middleware. There is no\n // `close` event either: the caller disposes via Vite's `closeServer` hook.\n const created = initDevframe(def, { base: DEVFRAME_BASE, ws: false, sse: true, mcp: false })\n instance = created\n return async () => {\n instance = undefined\n await created.close().catch(() => {})\n }\n }\n\n httpServer.once('listening', () => {\n const address = httpServer.address()\n if (closed || !address || typeof address === 'string') return\n const proto = server.config.server.https ? 'https' : 'http'\n const local = `${proto}://localhost:${address.port}`\n instance = initDevframe(def, {\n base: DEVFRAME_BASE,\n // Vite's https server is an HTTP/2 server with HTTP/1 fallback; it emits\n // the same `upgrade` events devframe listens for.\n server: httpServer as Server,\n mcp: false,\n // The auth banner's magic link is built from `origin`; point it at the\n // SPA so opening it authenticates (the app root has no devframe client).\n origin: `${local}${DEVFRAME_BASE}`,\n allowedOrigins: networkOrigins(address, proto),\n })\n server.config.logger.info(` ➜ Svelte DevTools: ${local}${DEVFRAME_BASE}`)\n })\n\n httpServer.once('close', () => {\n closed = true\n const current = instance\n instance = undefined\n current?.close().catch(() => {})\n })\n return undefined\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport type { RenderProfile, LoadProfile, FpsSample } from '../types.js'\n\nexport interface SessionSnapshot {\n /** componentId -> { renderCount, totalRenderTime } at snapshot moment */\n renderProfiles: Array<{\n componentId: number\n file: string\n name: string\n renderCount: number\n totalRenderTime: number\n }>\n loadProfilesCount: number\n fpsCount: number\n takenAt: number\n}\n\nexport interface SessionRecord {\n id: string\n label: string\n startedAt: number\n endedAt?: number\n persist: boolean\n startSnapshot: SessionSnapshot\n endSnapshot?: SessionSnapshot\n /** load profiles that arrived strictly between startedAt..endedAt */\n loadProfiles: LoadProfile[]\n /** fps samples that arrived strictly between startedAt..endedAt */\n fpsSamples: FpsSample[]\n}\n\nexport interface SessionDelta {\n durationMs: number\n components: Array<{\n componentId: number\n file: string\n name: string\n renderCountDelta: number\n totalRenderTimeDelta: number\n avgRenderTimeDelta: number\n }>\n loadProfiles: {\n count: number\n avgDuration: number\n p95Duration: number\n }\n fps: {\n samples: number\n avg: number\n min: number\n drops: number\n }\n}\n\nexport interface SessionDiff {\n a: { id: string; label: string }\n b: { id: string; label: string }\n render: {\n totalRenderTimeDeltaA: number\n totalRenderTimeDeltaB: number\n diff: number\n verdict: 'improved' | 'regressed' | 'unchanged'\n }\n load: {\n avgA: number\n avgB: number\n diff: number\n verdict: 'improved' | 'regressed' | 'unchanged'\n }\n fps: {\n avgA: number\n avgB: number\n diff: number\n verdict: 'improved' | 'regressed' | 'unchanged'\n }\n}\n\nexport interface MetricGetters {\n getRenderProfiles: () => RenderProfile[]\n getLoadProfiles: () => LoadProfile[]\n getFpsSamples: () => FpsSample[]\n}\n\nconst UNCHANGED_RENDER_THRESHOLD_MS = 1\nconst UNCHANGED_LOAD_THRESHOLD_MS = 5\nconst UNCHANGED_FPS_THRESHOLD = 1\nconst FPS_DROP_THRESHOLD = 30\n\nfunction takeSnapshot(getters: MetricGetters): SessionSnapshot {\n const renderProfiles = getters.getRenderProfiles().map(p => ({\n componentId: p.componentId,\n file: p.file,\n name: p.name,\n renderCount: p.renderCount,\n totalRenderTime: p.totalRenderTime,\n }))\n return {\n renderProfiles,\n loadProfilesCount: getters.getLoadProfiles().length,\n fpsCount: getters.getFpsSamples().length,\n takenAt: Date.now(),\n }\n}\n\nfunction classify(\n diff: number,\n threshold: number,\n lowerIsBetter: boolean,\n): 'improved' | 'regressed' | 'unchanged' {\n if (Math.abs(diff) < threshold) return 'unchanged'\n const negativeIsBetter = lowerIsBetter\n if (negativeIsBetter) return diff < 0 ? 'improved' : 'regressed'\n return diff > 0 ? 'improved' : 'regressed'\n}\n\n/**\n * The only id shape `start()` issues: `s_<Date.now() base36>_<6 hex>`. Ids\n * reach the store from MCP clients and become file names, so anything else\n * (path separators, `..`, absolute paths) is rejected before touching disk\n * (review C-7).\n */\nexport const SESSION_ID_PATTERN = /^s_[0-9a-z]{1,16}_[0-9a-f]{6}$/\n\nexport function isSessionId(id: unknown): id is string {\n return typeof id === 'string' && SESSION_ID_PATTERN.test(id)\n}\n\nexport interface SessionStoreOptions {\n persistDir: string\n getters: MetricGetters\n}\n\nexport class SessionStore {\n private sessions = new Map<string, SessionRecord>()\n private active: string | null = null\n private readonly persistDir: string\n private readonly getters: MetricGetters\n\n constructor(opts: SessionStoreOptions) {\n this.persistDir = path.resolve(opts.persistDir)\n this.getters = opts.getters\n }\n\n start(label: string, persist: boolean): SessionRecord {\n if (this.active) {\n throw new Error(\n `A session is already active: ${this.active}. Call end_session before starting a new one.`,\n )\n }\n const id = `s_${Date.now().toString(36)}_${crypto.randomBytes(3).toString('hex')}`\n const record: SessionRecord = {\n id,\n label,\n startedAt: Date.now(),\n persist,\n startSnapshot: takeSnapshot(this.getters),\n loadProfiles: [],\n fpsSamples: [],\n }\n this.sessions.set(id, record)\n this.active = id\n return record\n }\n\n /** Called by the plugin whenever a new load profile arrives. */\n recordLoadProfile(p: LoadProfile): void {\n if (!this.active) return\n const rec = this.sessions.get(this.active)\n if (rec) rec.loadProfiles.push(p)\n }\n\n /** Called by the plugin whenever a new fps sample arrives. */\n recordFpsSample(s: FpsSample): void {\n if (!this.active) return\n const rec = this.sessions.get(this.active)\n if (rec) rec.fpsSamples.push(s)\n }\n\n end(keep: 'memory' | 'disk' | 'discard'): SessionRecord {\n if (!this.active) throw new Error('No active session')\n const rec = this.sessions.get(this.active)\n if (!rec) throw new Error('Active session missing from store')\n rec.endedAt = Date.now()\n rec.endSnapshot = takeSnapshot(this.getters)\n this.active = null\n\n if (keep === 'discard') {\n this.sessions.delete(rec.id)\n } else if (keep === 'disk' || rec.persist) {\n this.persistToDisk(rec)\n }\n return rec\n }\n\n get(id: string): SessionRecord | undefined {\n if (!isSessionId(id)) return undefined\n const inMem = this.sessions.get(id)\n if (inMem) return inMem\n return this.loadFromDisk(id)\n }\n\n list(): Array<{\n id: string\n label: string\n startedAt: number\n endedAt?: number\n persisted: boolean\n active: boolean\n }> {\n const seen = new Set<string>()\n const out: Array<{\n id: string\n label: string\n startedAt: number\n endedAt?: number\n persisted: boolean\n active: boolean\n }> = []\n for (const rec of this.sessions.values()) {\n seen.add(rec.id)\n out.push({\n id: rec.id,\n label: rec.label,\n startedAt: rec.startedAt,\n endedAt: rec.endedAt,\n persisted: fs.existsSync(this.pathFor(rec.id)),\n active: this.active === rec.id,\n })\n }\n try {\n if (fs.existsSync(this.persistDir)) {\n for (const name of fs.readdirSync(this.persistDir)) {\n if (!name.endsWith('.json')) continue\n const id = name.slice(0, -5)\n if (!isSessionId(id) || seen.has(id)) continue\n try {\n const rec = JSON.parse(fs.readFileSync(this.pathFor(id), 'utf-8'))\n // A file whose content claims another id is not listed under it.\n if (rec?.id !== id) continue\n out.push({\n id: rec.id,\n label: rec.label,\n startedAt: rec.startedAt,\n endedAt: rec.endedAt,\n persisted: true,\n active: false,\n })\n } catch {\n /* skip unreadable session file */\n }\n }\n }\n } catch {\n /* persist dir not accessible */\n }\n return out.sort((a, b) => b.startedAt - a.startedAt)\n }\n\n delete(id: string): boolean {\n if (!isSessionId(id)) return false\n const had = this.sessions.delete(id)\n let onDisk = false\n try {\n const p = this.pathFor(id)\n if (fs.existsSync(p)) {\n fs.unlinkSync(p)\n onDisk = true\n }\n } catch {\n /* ignore */\n }\n if (this.active === id) this.active = null\n return had || onDisk\n }\n\n delta(id: string): SessionDelta {\n const rec = this.get(id)\n if (!rec) throw new Error(`Session not found: ${id}`)\n if (!rec.endSnapshot || rec.endedAt === undefined) {\n throw new Error(`Session ${id} has not been ended yet`)\n }\n const startMap = new Map(rec.startSnapshot.renderProfiles.map(p => [p.componentId, p]))\n const components = rec.endSnapshot.renderProfiles\n .map(end => {\n const start = startMap.get(end.componentId)\n const startRenderCount = start?.renderCount ?? 0\n const startTotal = start?.totalRenderTime ?? 0\n const renderCountDelta = end.renderCount - startRenderCount\n const totalRenderTimeDelta = end.totalRenderTime - startTotal\n return {\n componentId: end.componentId,\n file: end.file,\n name: end.name,\n renderCountDelta,\n totalRenderTimeDelta,\n avgRenderTimeDelta: renderCountDelta > 0 ? totalRenderTimeDelta / renderCountDelta : 0,\n }\n })\n .filter(c => c.renderCountDelta > 0)\n .sort((a, b) => b.totalRenderTimeDelta - a.totalRenderTimeDelta)\n\n const loadDurations = rec.loadProfiles.map(l => l.duration)\n const loadAvg = avg(loadDurations)\n const loadP95 = percentile(loadDurations, 95)\n\n const fpsValues = rec.fpsSamples.map(s => s.fps)\n const fpsAvg = avg(fpsValues)\n const fpsMin = fpsValues.length ? Math.min(...fpsValues) : 0\n const fpsDrops = fpsValues.filter(f => f < FPS_DROP_THRESHOLD).length\n\n return {\n durationMs: rec.endedAt - rec.startedAt,\n components,\n loadProfiles: { count: rec.loadProfiles.length, avgDuration: loadAvg, p95Duration: loadP95 },\n fps: { samples: fpsValues.length, avg: fpsAvg, min: fpsMin, drops: fpsDrops },\n }\n }\n\n compare(idA: string, idB: string): SessionDiff {\n const a = this.delta(idA)\n const b = this.delta(idB)\n const recA = this.get(idA)!\n const recB = this.get(idB)!\n const totalA = a.components.reduce((s, c) => s + c.totalRenderTimeDelta, 0)\n const totalB = b.components.reduce((s, c) => s + c.totalRenderTimeDelta, 0)\n const renderDiff = totalB - totalA\n const loadDiff = b.loadProfiles.avgDuration - a.loadProfiles.avgDuration\n const fpsDiff = b.fps.avg - a.fps.avg\n return {\n a: { id: recA.id, label: recA.label },\n b: { id: recB.id, label: recB.label },\n render: {\n totalRenderTimeDeltaA: totalA,\n totalRenderTimeDeltaB: totalB,\n diff: renderDiff,\n verdict: classify(renderDiff, UNCHANGED_RENDER_THRESHOLD_MS, true),\n },\n load: {\n avgA: a.loadProfiles.avgDuration,\n avgB: b.loadProfiles.avgDuration,\n diff: loadDiff,\n verdict: classify(loadDiff, UNCHANGED_LOAD_THRESHOLD_MS, true),\n },\n fps: {\n avgA: a.fps.avg,\n avgB: b.fps.avg,\n diff: fpsDiff,\n verdict: classify(fpsDiff, UNCHANGED_FPS_THRESHOLD, false),\n },\n }\n }\n\n /** The session's file, guaranteed to be a direct child of `persistDir`. */\n private pathFor(id: string): string {\n if (!isSessionId(id)) throw new Error('Invalid session id')\n const file = path.resolve(this.persistDir, `${id}.json`)\n if (path.dirname(file) !== this.persistDir) throw new Error('Invalid session id')\n return file\n }\n\n private persistToDisk(rec: SessionRecord): void {\n try {\n fs.mkdirSync(this.persistDir, { recursive: true })\n fs.writeFileSync(this.pathFor(rec.id), JSON.stringify(rec, null, 2), { mode: 0o600 })\n } catch {\n /* persist failure is non-fatal; the in-memory record stays available */\n }\n }\n\n private loadFromDisk(id: string): SessionRecord | undefined {\n try {\n const raw = fs.readFileSync(this.pathFor(id), 'utf-8')\n const rec = JSON.parse(raw)\n return rec?.id === id ? rec : undefined\n } catch {\n return undefined\n }\n }\n}\n\nfunction avg(xs: number[]): number {\n if (!xs.length) return 0\n return xs.reduce((s, x) => s + x, 0) / xs.length\n}\n\nfunction percentile(xs: number[], p: number): number {\n if (!xs.length) return 0\n const sorted = [...xs].sort((a, b) => a - b)\n const idx = Math.min(sorted.length - 1, Math.floor((p / 100) * sorted.length))\n return sorted[idx]\n}\n","import type { RenderProfile, ReactiveGraph, LoadProfile, FpsSample } from '../types.js'\n\nexport type IssueKind =\n | 'slow-component-render'\n | 'over-rendered-component'\n | 'slow-load'\n | 'fps-drop'\n | 'effect-overconnected'\n | 'derived-orphan'\n\nexport interface PerformanceIssue {\n id: string\n kind: IssueKind\n severity: 'low' | 'medium' | 'high'\n summary: string\n file?: string\n line?: number\n metric: Record<string, number>\n /** Tool that returns more detail for this issue. */\n suggestedTool: string\n}\n\nexport interface IssueThresholds {\n /** Per-render time (ms) above which a component render is considered slow. */\n avgRenderTimeMs?: number\n /** Render count above which a component is considered over-rendered. */\n renderCount?: number\n /** Load duration (ms) above which a SvelteKit load is slow. */\n loadDurationMs?: number\n /** FPS below which we record a drop. */\n fpsDropThreshold?: number\n /** Outgoing edge count from an effect above which it is over-connected. */\n effectMaxDeps?: number\n}\n\nconst DEFAULTS: Required<IssueThresholds> = {\n avgRenderTimeMs: 4,\n renderCount: 30,\n loadDurationMs: 200,\n fpsDropThreshold: 40,\n effectMaxDeps: 8,\n}\n\nexport interface IssueInputs {\n renderProfiles: RenderProfile[]\n reactiveGraph: ReactiveGraph\n loadProfiles: LoadProfile[]\n fpsSamples: FpsSample[]\n}\n\nexport function listPerformanceIssues(\n inputs: IssueInputs,\n thresholds: IssueThresholds = {},\n): PerformanceIssue[] {\n const t = { ...DEFAULTS, ...thresholds }\n const out: PerformanceIssue[] = []\n\n for (const p of inputs.renderProfiles) {\n const avg = p.renderCount > 0 ? p.totalRenderTime / p.renderCount : 0\n if (avg >= t.avgRenderTimeMs) {\n out.push({\n id: `slow-render:${p.file}:${p.componentId}`,\n kind: 'slow-component-render',\n severity:\n avg >= t.avgRenderTimeMs * 4 ? 'high' : avg >= t.avgRenderTimeMs * 2 ? 'medium' : 'low',\n summary: `${p.name} averages ${avg.toFixed(2)}ms per render (${p.renderCount} renders)`,\n file: p.file,\n metric: {\n avgRenderTimeMs: round(avg),\n renderCount: p.renderCount,\n totalRenderTimeMs: round(p.totalRenderTime),\n },\n suggestedTool: 'get_render_profile',\n })\n }\n if (p.renderCount >= t.renderCount) {\n out.push({\n id: `over-render:${p.file}:${p.componentId}`,\n kind: 'over-rendered-component',\n severity:\n p.renderCount >= t.renderCount * 8\n ? 'high'\n : p.renderCount >= t.renderCount * 3\n ? 'medium'\n : 'low',\n summary: `${p.name} rendered ${p.renderCount} times`,\n file: p.file,\n metric: { renderCount: p.renderCount, avgRenderTimeMs: round(avg) },\n suggestedTool: 'get_component_hotspots',\n })\n }\n }\n\n for (const l of inputs.loadProfiles) {\n if (l.duration >= t.loadDurationMs) {\n out.push({\n id: `slow-load:${l.route}:${l.timestamp}`,\n kind: 'slow-load',\n severity:\n l.duration >= t.loadDurationMs * 5\n ? 'high'\n : l.duration >= t.loadDurationMs * 2\n ? 'medium'\n : 'low',\n summary: `${l.type} load for ${l.route} took ${l.duration.toFixed(0)}ms`,\n file: l.file,\n metric: { durationMs: round(l.duration), dataSizeBytes: l.dataSize },\n suggestedTool: 'get_load_waterfall',\n })\n }\n }\n\n const fpsDrops = inputs.fpsSamples.filter(s => s.fps < t.fpsDropThreshold)\n if (fpsDrops.length > 0) {\n const min = Math.min(...fpsDrops.map(s => s.fps))\n out.push({\n id: `fps-drops:${inputs.fpsSamples[0]?.timestamp ?? 0}`,\n kind: 'fps-drop',\n severity: min < 15 ? 'high' : min < 30 ? 'medium' : 'low',\n summary: `${fpsDrops.length} FPS samples below ${t.fpsDropThreshold} (min ${min})`,\n metric: { dropCount: fpsDrops.length, minFps: min, threshold: t.fpsDropThreshold },\n suggestedTool: 'get_fps_drops',\n })\n }\n\n // Reactive graph: count outgoing edges per node\n const outDegree = new Map<string, number>()\n for (const e of inputs.reactiveGraph.edges) {\n outDegree.set(e.from, (outDegree.get(e.from) ?? 0) + 1)\n }\n const inDegree = new Map<string, number>()\n for (const e of inputs.reactiveGraph.edges) {\n inDegree.set(e.to, (inDegree.get(e.to) ?? 0) + 1)\n }\n for (const node of inputs.reactiveGraph.nodes) {\n if (node.type === 'effect') {\n const deps = inDegree.get(node.id) ?? 0\n if (deps >= t.effectMaxDeps) {\n out.push({\n id: `effect-deps:${node.id}`,\n kind: 'effect-overconnected',\n severity:\n deps >= t.effectMaxDeps * 3 ? 'high' : deps >= t.effectMaxDeps * 2 ? 'medium' : 'low',\n summary: `effect \"${node.name}\" depends on ${deps} reactive values`,\n file: node.componentFile,\n metric: { depCount: deps },\n suggestedTool: 'get_reactive_graph_problems',\n })\n }\n }\n if (node.type === 'derived') {\n const fanout = outDegree.get(node.id) ?? 0\n if (fanout === 0 && (inDegree.get(node.id) ?? 0) > 0) {\n out.push({\n id: `derived-orphan:${node.id}`,\n kind: 'derived-orphan',\n severity: 'low',\n summary: `derived \"${node.name}\" has dependencies but is unused`,\n file: node.componentFile,\n metric: { fanout },\n suggestedTool: 'get_reactive_graph_problems',\n })\n }\n }\n }\n\n return out.sort(compareSeverity)\n}\n\nconst SEV_RANK: Record<PerformanceIssue['severity'], number> = { high: 0, medium: 1, low: 2 }\n\nfunction compareSeverity(a: PerformanceIssue, b: PerformanceIssue): number {\n return SEV_RANK[a.severity] - SEV_RANK[b.severity]\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100\n}\n\nexport interface ReactiveProblems {\n effects: Array<{ id: string; name: string; file: string; depCount: number }>\n orphanDeriveds: Array<{ id: string; name: string; file: string }>\n isolatedNodes: Array<{ id: string; name: string; type: string; file: string }>\n}\n\nexport function summarizeReactiveProblems(\n graph: ReactiveGraph,\n t: IssueThresholds = {},\n): ReactiveProblems {\n const thresh = { ...DEFAULTS, ...t }\n const inDegree = new Map<string, number>()\n const outDegree = new Map<string, number>()\n for (const e of graph.edges) {\n inDegree.set(e.to, (inDegree.get(e.to) ?? 0) + 1)\n outDegree.set(e.from, (outDegree.get(e.from) ?? 0) + 1)\n }\n const effects: ReactiveProblems['effects'] = []\n const orphanDeriveds: ReactiveProblems['orphanDeriveds'] = []\n const isolatedNodes: ReactiveProblems['isolatedNodes'] = []\n for (const node of graph.nodes) {\n const ind = inDegree.get(node.id) ?? 0\n const outd = outDegree.get(node.id) ?? 0\n if (node.type === 'effect' && ind >= thresh.effectMaxDeps) {\n effects.push({ id: node.id, name: node.name, file: node.componentFile, depCount: ind })\n }\n if (node.type === 'derived' && outd === 0 && ind > 0) {\n orphanDeriveds.push({ id: node.id, name: node.name, file: node.componentFile })\n }\n if (ind === 0 && outd === 0) {\n isolatedNodes.push({\n id: node.id,\n name: node.name,\n type: node.type,\n file: node.componentFile,\n })\n }\n }\n return { effects, orphanDeriveds, isolatedNodes }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'\nimport { z } from 'zod'\nimport type {\n RenderProfile,\n ReactiveGraph,\n LoadProfile,\n FpsSample,\n ComponentInstance,\n ProjectInfo,\n RouteInfo,\n ComponentRelation,\n CaptureInfoMap,\n ReactiveGraphRequest,\n ReactiveGraphResult,\n ReactiveSummary,\n ReactiveSummaryRequest,\n StateTimelineDelta,\n} from '../types.js'\nimport { SessionStore, SESSION_ID_PATTERN } from './sessions.js'\nimport { listPerformanceIssues, summarizeReactiveProblems, type IssueThresholds } from './issues.js'\n\nexport interface McpDeps {\n getProject: () => ProjectInfo\n getRoutes: () => RouteInfo[]\n getLiveComponents: () => ComponentInstance[]\n /**\n * The served page load's components with its epoch, read together\n * (`get_live_components` with `includeMeta`).\n */\n getLiveSnapshot?: () => { epoch: string | null; total: number; components: ComponentInstance[] }\n getComponentRelations: () => ComponentRelation[]\n getRenderProfiles: () => RenderProfile[]\n /** Resolves with the current reactive graph after refreshing from the browser. */\n getReactiveGraph: () => Promise<ReactiveGraph>\n getLoadProfiles: () => LoadProfile[]\n getFpsSamples: () => FpsSample[]\n sessions: SessionStore\n // Bounded reactivity tools (docs/devframe-migration.md §6.7); registered only when provided.\n getReactiveSummary?: (req: ReactiveSummaryRequest) => Promise<ReactiveSummary>\n getReactiveScope?: (req: ReactiveGraphRequest) => Promise<ReactiveGraphResult>\n getStateTimelineDelta?: (since?: number) => StateTimelineDelta\n getCaptureInfo?: () => CaptureInfoMap\n}\n\n/** Most timeline entries one `get_state_timeline` call returns. */\nexport const MCP_TIMELINE_LIMIT = 500\n/** Default / largest JSON size of one old/new value in `get_state_timeline` output. */\nexport const MCP_VALUE_CHARS = { default: 2048, max: 32768 } as const\n\n/** A state value for MCP output: as is when small, otherwise a size summary. */\nfunction capValue(value: unknown, maxChars: number): unknown {\n let json: string | undefined\n try {\n json = JSON.stringify(value)\n } catch {\n return { omitted: 'not serializable' }\n }\n if (json === undefined || json.length <= maxChars) return value\n return {\n omitted: 'too large',\n chars: json.length,\n preview: json.slice(0, Math.min(200, maxChars)),\n }\n}\n\n/** Session ids as issued by `start_session`; anything else is rejected before the store. */\nconst sessionId = z.string().max(64).regex(SESSION_ID_PATTERN, 'not a session id')\n\nconst TEXT = (value: unknown) => ({\n content: [\n {\n type: 'text' as const,\n text: typeof value === 'string' ? value : JSON.stringify(value, null, 2),\n },\n ],\n})\n\nexport function buildMcpServer(deps: McpDeps): McpServer {\n const server = new McpServer({\n name: 'vite-devtools-svelte',\n version: '0.1.0',\n })\n\n // --- read tools: issue surface ---\n\n server.registerTool(\n 'list_performance_issues',\n {\n title: 'List performance issues',\n description:\n 'Cross-cuts render/reactive/load/fps metrics and returns ranked issues. The entry point for AI-driven performance audits. Each issue carries `suggestedTool` naming the detail tool to call next.',\n inputSchema: {\n avgRenderTimeMs: z.number().optional(),\n renderCount: z.number().optional(),\n loadDurationMs: z.number().optional(),\n fpsDropThreshold: z.number().optional(),\n effectMaxDeps: z.number().optional(),\n },\n },\n async args => {\n const thresholds: IssueThresholds = args\n const reactiveGraph = await deps.getReactiveGraph()\n const issues = listPerformanceIssues(\n {\n renderProfiles: deps.getRenderProfiles(),\n reactiveGraph,\n loadProfiles: deps.getLoadProfiles(),\n fpsSamples: deps.getFpsSamples(),\n },\n thresholds,\n )\n return TEXT({ count: issues.length, issues })\n },\n )\n\n server.registerTool(\n 'get_component_hotspots',\n {\n title: 'Component render hotspots',\n description: 'Top components by total render time, with render count and per-render average.',\n inputSchema: { topN: z.number().int().min(1).max(200).optional() },\n },\n async ({ topN = 20 }) => {\n const list = [...deps.getRenderProfiles()]\n .map(p => ({\n file: p.file,\n name: p.name,\n componentId: p.componentId,\n renderCount: p.renderCount,\n totalRenderTimeMs: round(p.totalRenderTime),\n avgRenderTimeMs: round(p.renderCount > 0 ? p.totalRenderTime / p.renderCount : 0),\n lastRenderTimeMs: round(p.lastRenderTime),\n lastRenderAt: p.lastRenderAt,\n }))\n .sort((a, b) => b.totalRenderTimeMs - a.totalRenderTimeMs)\n .slice(0, topN)\n return TEXT(list)\n },\n )\n\n server.registerTool(\n 'get_reactive_graph_problems',\n {\n title: 'Reactive graph problems',\n description:\n 'Classified reactive graph issues: over-connected effects, orphan deriveds, isolated nodes. Returns categories instead of the full graph.',\n inputSchema: { effectMaxDeps: z.number().int().min(1).optional() },\n },\n async ({ effectMaxDeps }) => {\n const graph = await deps.getReactiveGraph()\n return TEXT(summarizeReactiveProblems(graph, { effectMaxDeps }))\n },\n )\n\n server.registerTool(\n 'get_load_waterfall',\n {\n title: 'SvelteKit load waterfall',\n description:\n 'Load profiles grouped by route, with timing and data size. Optionally filtered by route.',\n inputSchema: { route: z.string().optional() },\n },\n async ({ route }) => {\n let profiles = deps.getLoadProfiles()\n if (route) profiles = profiles.filter(p => p.route === route)\n const byRoute = new Map<string, LoadProfile[]>()\n for (const p of profiles) {\n const arr = byRoute.get(p.route) ?? []\n arr.push(p)\n byRoute.set(p.route, arr)\n }\n const groups = [...byRoute.entries()].map(([r, ps]) => {\n const durations = ps.map(p => p.duration)\n return {\n route: r,\n file: ps[0]?.file,\n count: ps.length,\n avgDuration: round(avg(durations)),\n maxDuration: round(Math.max(...durations)),\n totalDataBytes: ps.reduce((s, p) => s + p.dataSize, 0),\n samples: ps,\n }\n })\n return TEXT(groups.sort((a, b) => b.avgDuration - a.avgDuration))\n },\n )\n\n server.registerTool(\n 'get_fps_drops',\n {\n title: 'FPS drops',\n description: 'Samples whose FPS fell below `threshold`. Returns timestamp + fps for each.',\n inputSchema: {\n threshold: z.number().min(1).max(120).optional(),\n sinceMs: z.number().optional(),\n },\n },\n async ({ threshold = 40, sinceMs }) => {\n let samples = deps.getFpsSamples()\n if (sinceMs !== undefined) {\n const cutoff = Date.now() - sinceMs\n samples = samples.filter(s => s.timestamp >= cutoff)\n }\n const drops = samples.filter(s => s.fps < threshold)\n return TEXT({\n threshold,\n sampleCount: samples.length,\n dropCount: drops.length,\n minFps: drops.length ? Math.min(...drops.map(s => s.fps)) : null,\n drops,\n })\n },\n )\n\n server.registerTool(\n 'get_render_profile',\n {\n title: 'Render profile for a specific file',\n description:\n 'Returns render profile entries matching the given component file (substring match).',\n inputSchema: { file: z.string() },\n },\n async ({ file }) => {\n const matches = deps\n .getRenderProfiles()\n .filter(p => p.file.includes(file))\n .map(p => ({\n ...p,\n totalRenderTimeMs: round(p.totalRenderTime),\n avgRenderTimeMs: round(p.renderCount > 0 ? p.totalRenderTime / p.renderCount : 0),\n }))\n return TEXT(matches)\n },\n )\n\n // --- context tools ---\n\n server.registerTool(\n 'get_project_info',\n {\n title: 'Project info',\n description: 'Package name/version, Svelte / SvelteKit / Vite versions, dependency lists.',\n inputSchema: {},\n },\n async () => TEXT(deps.getProject()),\n )\n\n server.registerTool(\n 'get_routes',\n {\n title: 'SvelteKit routes',\n description: 'Static analysis of the SvelteKit routes tree.',\n inputSchema: {},\n },\n async () => TEXT(deps.getRoutes()),\n )\n\n server.registerTool(\n 'get_live_components',\n {\n title: 'Currently mounted components',\n description:\n 'Component instances with file, parent, mounted status as currently mounted in the browser (an array, parents first). With `includeMeta: true` the answer is `{ epoch, total, captured, truncated, components }` instead, limited to `limit` (default 1000): component ids are only valid within that `epoch` (one page load), so pass both to get_reactive_scope.',\n inputSchema: {\n includeMeta: z.boolean().optional(),\n limit: z.number().int().min(1).max(50000).optional(),\n },\n },\n async ({ includeMeta, limit }) => {\n if (!includeMeta || !deps.getLiveSnapshot) {\n // Unchanged default: the bare array older clients expect (`limit` only when given).\n const all = deps.getLiveComponents()\n return TEXT(limit === undefined ? all : all.slice(0, limit))\n }\n const snap = deps.getLiveSnapshot()\n const max = limit ?? 1000\n return TEXT({\n epoch: snap.epoch,\n total: snap.total,\n captured: snap.components.length,\n truncated: snap.total > snap.components.length || snap.components.length > max,\n components: snap.components.slice(0, max),\n })\n },\n )\n\n server.registerTool(\n 'get_component_relations',\n {\n title: 'Component import graph',\n description: 'Static import relations between .svelte components.',\n inputSchema: {},\n },\n async () => TEXT(deps.getComponentRelations()),\n )\n\n // --- bounded reactivity tools (read only; every answer says what it covers) ---\n\n if (deps.getReactiveSummary) {\n const getSummary = deps.getReactiveSummary\n server.registerTool(\n 'get_reactive_summary',\n {\n title: 'Reactive overview (top components)',\n description:\n 'Busiest component instances from runtime counters over all instances, without capturing the graph. Counts are sampled state changes (at most one per state per 200 ms) and renders within the window, not rates. Only state created during component init is tracked. `rows` + `other` add up to the totals; null means unknown. Use get_reactive_scope with a componentId to look at one instance. The same request is answered from a cache for up to 1 s; `window.until` says when the answer was computed.',\n inputSchema: {\n topK: z.number().int().min(1).max(200).optional(),\n windowMs: z.number().int().min(1000).max(60000).optional(),\n },\n },\n async ({ topK, windowMs }) => TEXT(await getSummary({ topK, windowMs })),\n )\n }\n\n if (deps.getReactiveScope) {\n const getScope = deps.getReactiveScope\n server.registerTool(\n 'get_reactive_scope',\n {\n title: 'Reactive graph of one component',\n description:\n \"$state/$derived/$effect nodes of one component instance and their direct neighbours, built in the app within the caps. Edges mean 'can affect' (current dependencies), not a recorded cause. `componentId` requires the `epoch` it came from (get_live_components with includeMeta): after a reload the answer is empty with staleReason 'epoch-changed' instead of another instance. Omit componentId only for the whole-app graph (capped; see total/truncated). The same request may be answered from a cache for up to 1 s; `computedAt` says when the app built the graph (null when unknown or for an empty fallback). `stale: true` only marks a fallback after the app did not answer (an earlier answer with its own computedAt, or empty).\",\n inputSchema: {\n componentId: z.number().int().nonnegative().optional(),\n epoch: z.string().max(200).optional(),\n maxNodes: z.number().int().min(1).max(5000).optional(),\n maxEdges: z.number().int().min(1).max(20000).optional(),\n },\n },\n async ({ componentId, epoch, maxNodes, maxEdges }) => {\n if (componentId !== undefined && epoch === undefined)\n return {\n content: [\n {\n type: 'text' as const,\n text: 'componentId requires epoch (from get_live_components with includeMeta: true)',\n },\n ],\n isError: true,\n }\n return TEXT(await getScope({ componentId, epoch, maxNodes, maxEdges }))\n },\n )\n }\n\n if (deps.getStateTimelineDelta) {\n const getDelta = deps.getStateTimelineDelta\n server.registerTool(\n 'get_state_timeline',\n {\n title: 'State changes since a cursor',\n description:\n 'Sampled $state changes (200 ms) after `since` (the cursor from the previous call). Contains values of state in the running app. `reset: true` means the cursor was stale and this is the whole buffer. At most `limit` newest entries are returned; `omitted` counts older ones in the range that were left out. Values larger than `maxValueChars` (JSON) are replaced by a size summary. Timestamps are detection times, so order within about a second is not causal.',\n inputSchema: {\n since: z.number().int().nonnegative().optional(),\n limit: z.number().int().min(1).max(MCP_TIMELINE_LIMIT).optional(),\n maxValueChars: z.number().int().min(16).max(MCP_VALUE_CHARS.max).optional(),\n },\n },\n async ({ since, limit, maxValueChars }) => {\n const delta = getDelta(since)\n const max = limit ?? 100\n const valueChars = maxValueChars ?? MCP_VALUE_CHARS.default\n const omitted = Math.max(0, delta.changes.length - max)\n const changes = delta.changes.slice(omitted).map(c => ({\n ...c,\n oldValue: capValue(c.oldValue, valueChars),\n newValue: capValue(c.newValue, valueChars),\n }))\n return TEXT({ ...delta, changes, omitted, maxValueChars: valueChars })\n },\n )\n }\n\n if (deps.getCaptureInfo) {\n const getInfo = deps.getCaptureInfo\n server.registerTool(\n 'get_capture_info',\n {\n title: 'What the DevTools hold versus what the app reported',\n description:\n 'Per dataset: captured count, total (null = unknown), truncated, selection policy and dropped counts by reason. Read this before drawing conclusions from capped data.',\n inputSchema: {},\n },\n async () => TEXT(getInfo()),\n )\n }\n\n // --- session tools ---\n\n server.registerTool(\n 'start_session',\n {\n title: 'Start measurement session',\n description:\n 'Begin capturing metrics under a labelled session. Required before compare_sessions. Set `persist:true` to write to disk on end; otherwise the session lives in memory only.',\n inputSchema: {\n label: z.string(),\n persist: z.boolean().optional(),\n },\n },\n async ({ label, persist = false }) => {\n const rec = deps.sessions.start(label, persist)\n return TEXT({ id: rec.id, label: rec.label, startedAt: rec.startedAt, persist: rec.persist })\n },\n )\n\n server.registerTool(\n 'end_session',\n {\n title: 'End current measurement session',\n description:\n 'Closes the active session and returns its delta. `keep` decides disposal: \"memory\" keeps it for this dev-server lifetime, \"disk\" writes to .vite-devtools-svelte/sessions/, \"discard\" deletes it.',\n inputSchema: {\n keep: z.enum(['memory', 'disk', 'discard']).optional(),\n },\n },\n async ({ keep = 'memory' }) => {\n const rec = deps.sessions.end(keep)\n const delta = rec.endedAt ? deps.sessions.delta(rec.id) : null\n return TEXT({\n id: rec.id,\n label: rec.label,\n startedAt: rec.startedAt,\n endedAt: rec.endedAt,\n keep,\n delta,\n })\n },\n )\n\n server.registerTool(\n 'compare_sessions',\n {\n title: 'Compare two sessions',\n description:\n 'Diff render / load / fps metrics between two ended sessions. Each section carries `verdict`: improved | regressed | unchanged.',\n inputSchema: { a: sessionId, b: sessionId },\n },\n async ({ a, b }) => TEXT(deps.sessions.compare(a, b)),\n )\n\n server.registerTool(\n 'list_sessions',\n {\n title: 'List sessions',\n description: 'In-memory + on-disk sessions, most recent first.',\n inputSchema: {},\n },\n async () => TEXT(deps.sessions.list()),\n )\n\n server.registerTool(\n 'load_session',\n {\n title: 'Load a session by id',\n description: 'Returns the full session record (including delta if ended) by id.',\n inputSchema: { id: sessionId },\n },\n async ({ id }) => {\n const rec = deps.sessions.get(id)\n if (!rec) return TEXT({ error: `Session not found: ${id}` })\n const delta = rec.endedAt ? deps.sessions.delta(id) : null\n return TEXT({ ...rec, delta })\n },\n )\n\n server.registerTool(\n 'delete_session',\n {\n title: 'Delete a session',\n description: 'Removes a session from memory and disk.',\n inputSchema: { id: sessionId },\n },\n async ({ id }) => TEXT({ deleted: deps.sessions.delete(id) }),\n )\n\n return server\n}\n\nexport { StreamableHTTPServerTransport }\n\nfunction avg(xs: number[]): number {\n if (!xs.length) return 0\n return xs.reduce((s, x) => s + x, 0) / xs.length\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100\n}\n","/// <reference types=\"@vitejs/devtools-kit\" />\nimport { DEVTOOLS_MOUNT_PATH } from '@vitejs/devtools-kit/constants'\nimport type { Plugin } from 'vite'\n\n/**\n * SvelteKit dev bypasses Vite's `transformIndexHtml`, so `@vitejs/devtools`'s\n * `DevToolsInjection` never reaches the served HTML and the dock is invisible\n * on every SvelteKit page. Tracked upstream at\n * https://github.com/baseballyama/vite-devtools-repl/tree/main/sveltekit-transform-index-html-bypass\n *\n * As a stopgap, SvelteKit inlines `src/app.html` as a JS string literal inside\n * `.svelte-kit/generated/server/internal.js`:\n *\n * templates: {\n * app: ({ head, body, ... }) => \"<!doctype html>...<body>...</body>...\",\n * }\n *\n * That file is loaded through Vite's module pipeline (`vite.ssrLoadModule`),\n * so a regular `transform` hook can rewrite the literal to insert the dock's\n * inject script before `</body>`. The actual `<script>` runs in the browser\n * once the HTML is delivered, so no SSR safety guard on the inject module is\n * needed for this path.\n *\n * This is intentionally narrow — SvelteKit-specific path match plus a\n * structural assertion — and there's a test (`template-injector.test.ts`)\n * that fails if SvelteKit's generated shape changes, so a silent break shows\n * up in CI instead of as a missing dock in production.\n */\n\nexport const SVELTEKIT_INTERNAL_SUFFIX = '.svelte-kit/generated/server/internal.js'\n\n/**\n * SvelteKit 3 writes the same `templates: { app: … }` server module to\n * `generated/dev/server.js` while serving (and `generated/build/server.js`\n * for builds, which this dev-only plugin never sees).\n */\nexport const SVELTEKIT3_DEV_SERVER_SUFFIX = '.svelte-kit/generated/dev/server.js'\n\nconst GENERATED_SERVER_SUFFIXES = [SVELTEKIT_INTERNAL_SUFFIX, SVELTEKIT3_DEV_SERVER_SUFFIX]\n\n/** Marker that the `templates.app` literal in SvelteKit's generated server. */\nexport const TEMPLATE_APP_MARKER = 'templates: {'\n\n/**\n * The dock bootstrap the Vite DevTools hub serves itself (`@vitejs/devtools`\n * >= 0.7.6 injects the same `<mount>embedded.js` through `transformIndexHtml`;\n * the old `@vitejs/devtools/client/inject` module no longer exists). The hub's\n * middleware answers this URL before Vite's transform pipeline, and SvelteKit\n * HTML never goes through Vite's HTML processing, so a plain static `src` is\n * enough — and, unlike an inline loader, works under a strict `script-src 'self'`.\n */\nconst INJECT_SCRIPT_URL = `${DEVTOOLS_MOUNT_PATH}embedded.js`\n/** The tag, escaped because we're editing a JS string literal. */\nconst INJECT_TAG = `<script type=\\\\\"module\\\\\" src=\\\\\"${INJECT_SCRIPT_URL}\\\\\"></script>`\n\n/**\n * `</body>` as it appears inside SvelteKit's generated string literal.\n * SvelteKit emits `app.html` via `JSON.stringify`-style escaping, which leaves\n * `/` alone — only control characters and quotes are escaped. So the literal\n * substring we actually search for is plain `</body>`.\n */\nconst BODY_CLOSE = '</body>'\n\n/**\n * Transform `.svelte-kit/generated/server/internal.js` to add the\n * `@vitejs/devtools` inject script right before `</body>` inside the app\n * template literal. Exposed for unit testing.\n *\n * Returns the new source if a substitution was made, or `null` to signal\n * \"nothing to do\" (already injected, structural marker missing, etc.).\n */\nexport function injectIntoSvelteKitInternal(code: string): string | null {\n // Cheap structural sanity check — bail if SvelteKit changed how it generates\n // the template object. The companion test asserts this branch is reachable.\n if (!code.includes(TEMPLATE_APP_MARKER)) return null\n if (!code.includes(BODY_CLOSE)) return null\n\n // Idempotence: don't double-inject across HMR re-runs.\n if (code.includes(INJECT_SCRIPT_URL)) return null\n\n // Only patch the literal that follows the `templates: {` marker, so a\n // future `</body>` mentioned in unrelated source code won't be touched.\n const markerIdx = code.indexOf(TEMPLATE_APP_MARKER)\n const bodyIdx = code.indexOf(BODY_CLOSE, markerIdx)\n if (bodyIdx === -1) return null\n\n return code.slice(0, bodyIdx) + INJECT_TAG + code.slice(bodyIdx)\n}\n\n/**\n * Vite plugin: inject the Vite DevTools dock bootstrap into SvelteKit's\n * dev-only generated server template. Dev-only by construction.\n *\n * Only when the Vite DevTools hub is actually present: standalone has no\n * hub serving `/__devtools/embedded.js`, so the tag would fail to load.\n * `isHosted` is read in `transform` rather than `apply` because `apply` runs\n * while the plugin list is still being resolved; every `configResolved` hook\n * has finished before the server transforms its first module.\n */\nexport function sveltekitTemplateInjector(isHosted: () => boolean): Plugin {\n return {\n name: 'vite-devtools-svelte:sveltekit-template-injector',\n enforce: 'post',\n apply: (_userConfig, env) => env.command === 'serve' && !env.isSsrBuild,\n\n transform(code, id) {\n if (!GENERATED_SERVER_SUFFIXES.some(suffix => id.endsWith(suffix))) return\n if (!isHosted()) return\n const next = injectIntoSvelteKitInternal(code)\n if (next === null) return\n return { code: next, map: null }\n },\n }\n}\n","import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport { launchEditor } from 'devframe/utils/launch-editor'\nimport { analyzeRoutes } from './analyzers/routes.js'\nimport { analyzeProject } from './analyzers/project.js'\nimport { analyzeComponents } from './analyzers/components.js'\nimport type { GraphModuleLike } from './analyzers/module-graph.js'\nimport {\n RUNTIME_MODULE_ID,\n RESOLVED_RUNTIME_ID,\n runtimeCode,\n WRAPPER_MODULE_ID,\n wrapperCode,\n} from './runtime.js'\nimport { Collector } from './collector.js'\nimport { createSvelteDevframe, DEVFRAME_BASE } from './devframe.js'\nimport type { SvelteDevtoolsHost } from './devframe.js'\nimport { mountStandalone } from './mount.js'\nimport { SessionStore } from './mcp/sessions.js'\nimport { buildMcpServer, StreamableHTTPServerTransport } from './mcp/server.js'\nimport { sveltekitTemplateInjector } from './template-injector.js'\nimport type { LoadProfile } from './types.js'\n\nexport interface SvelteDevtoolsOptions {\n /**\n * Enable component tracking via code injection.\n * @default true\n */\n componentTracking?: boolean\n}\n\n/** Name of `@vitejs/devtools`' config plugin; its presence means the hub will call our `devtools.setup`. */\nconst VITE_DEVTOOLS_PLUGIN = 'vite:devtools'\nconst WARN_SINK = Symbol.for('vite-devtools-svelte:warn-sink')\n\n// Shared by every plugin instance in the process: a config-file restart\n// builds a *new* plugin instance for the new server, so only a process-wide\n// counter tells the old instance that a newer server exists.\nlet serverGeneration = 0\n\n/** Collect every module the dev server knows, across Vite 8 environments (legacy graph as fallback). */\nfunction collectModules(server: ViteDevServer): GraphModuleLike[] {\n const modules: GraphModuleLike[] = []\n for (const env of Object.values(server.environments ?? {})) {\n const graph = (env as { moduleGraph?: { idToModuleMap?: Map<string, GraphModuleLike> } })\n .moduleGraph\n if (graph?.idToModuleMap) modules.push(...graph.idToModuleMap.values())\n }\n if (modules.length === 0) {\n const legacy = (server as { moduleGraph?: { idToModuleMap?: Map<string, GraphModuleLike> } })\n .moduleGraph\n if (legacy?.idToModuleMap) modules.push(...legacy.idToModuleMap.values())\n }\n return modules\n}\n\nexport function svelteDevtools(options: SvelteDevtoolsOptions = {}): Plugin[] {\n const { componentTracking = true } = options\n\n let config: ResolvedConfig\n let server: ViteDevServer | undefined\n let root: string\n // When `@vitejs/devtools` is installed the hub mounts the devframe through\n // our `devtools` hook; otherwise we mount it ourselves. Never both: they\n // would claim the same base.\n let hostedByViteDevtools = false\n // Per-process token for the MCP endpoint (MCP clients are local processes,\n // not browser tabs, so they cannot use devframe's browser auth handshake).\n const mcpToken = crypto.randomUUID()\n\n // Session store for AI-driven measurement workflows. Built lazily after\n // `root` is resolved.\n let sessions: SessionStore | null = null\n function getSessions(): SessionStore {\n if (!sessions) {\n sessions = new SessionStore({\n persistDir: path.join(root, 'node_modules', '.vite-devtools-svelte', 'sessions'),\n getters: {\n getRenderProfiles: () => collector.renderProfiles,\n getLoadProfiles: () => collector.loadProfiles,\n getFpsSamples: () => collector.fpsSamples,\n },\n })\n }\n return sessions\n }\n\n const collector = new Collector({\n onFpsSample: sample => getSessions().recordFpsSample(sample),\n onLoadProfile: profile => getSessions().recordLoadProfile(profile),\n })\n\n const host: SvelteDevtoolsHost = {\n collector,\n root: () => root,\n publicBase: () => config?.base ?? '/',\n modules: () => (server ? collectModules(server) : []),\n transformRequest: file => (server ? server.transformRequest(file) : Promise.resolve(null)),\n serverOrigins: () => {\n const urls = server?.resolvedUrls\n if (!urls) return []\n return [...urls.local, ...urls.network].map(u => new URL(u).origin)\n },\n openInEditor: target => launchEditor(target),\n }\n const devframe = createSvelteDevframe(host)\n const middlewareModeMounts: Array<{ generation: number; dispose: () => Promise<void> }> = []\n\n const mainPlugin: Plugin = {\n name: 'vite-devtools-svelte',\n enforce: 'pre',\n apply: 'serve',\n\n // Surfaces the per-process MCP token for inter-plugin (and test)\n // consumption, so tests need no production-only flag.\n api: {\n getDevtoolsToken: () => mcpToken,\n },\n\n configResolved(resolvedConfig) {\n config = resolvedConfig\n root = config.root\n hostedByViteDevtools = config.plugins.some(p => p.name === VITE_DEVTOOLS_PLUGIN)\n },\n\n configureServer(devServer) {\n server = devServer\n const generation = ++serverGeneration\n collector.attach(devServer.hot)\n devServer.httpServer?.once('close', () => {\n if (server === devServer) {\n collector.detach()\n server = undefined\n }\n })\n\n if (!hostedByViteDevtools) {\n const dispose = mountStandalone(devServer, devframe)\n if (dispose) middlewareModeMounts.push({ generation, dispose })\n }\n\n const mcpServerFactory = () =>\n buildMcpServer({\n getProject: () => analyzeProject(root),\n getRoutes: () => analyzeRoutes(analyzeProject(root).routesDir),\n getLiveComponents: () => collector.liveComponents,\n getLiveSnapshot: () => collector.liveSnapshot,\n getComponentRelations: () => analyzeComponents(root),\n getRenderProfiles: () => collector.renderProfiles,\n getReactiveGraph: () => collector.requestReactiveGraph(),\n getLoadProfiles: () => collector.loadProfiles,\n getFpsSamples: () => collector.fpsSamples,\n sessions: getSessions(),\n getReactiveSummary: req => collector.requestReactiveSummary(req),\n getReactiveScope: req => collector.requestReactiveGraph(req),\n getStateTimelineDelta: since => collector.getStateTimelineDelta(since),\n getCaptureInfo: () => collector.getCaptureInfo(),\n })\n\n // Print a one-line `claude mcp add` snippet once the dev server is\n // actually listening — that's when we know the resolved port.\n devServer.httpServer?.once('listening', () => {\n try {\n const addr = devServer.httpServer?.address()\n if (!addr || typeof addr === 'string') return\n const proto = devServer.config.server?.https ? 'https' : 'http'\n // For wildcard / loopback bindings prefer the literal `localhost`\n // so the printed URL parses as-is. Brackets aren't enough for `::`\n // (wildcard) and `::1` is just a more verbose form of loopback.\n const loopbackOrWildcard =\n addr.address === '::' ||\n addr.address === '0.0.0.0' ||\n addr.address === '::1' ||\n addr.address === '127.0.0.1'\n const hostName = loopbackOrWildcard\n ? 'localhost'\n : addr.family === 'IPv6'\n ? `[${addr.address}]`\n : addr.address\n const url = `${proto}://${hostName}:${addr.port}/__svelte-devtools/mcp`\n const cmd = `claude mcp add --transport http svelte ${url} --header x-svelte-devtools-token:${mcpToken}`\n devServer.config.logger.info('')\n devServer.config.logger.info(` svelte-devtools MCP ready — register with Claude Code:`)\n devServer.config.logger.info(` ${cmd}`)\n devServer.config.logger.info('')\n } catch {\n /* logging is best-effort */\n }\n })\n\n // MCP endpoint: lets AI agents (Claude Code etc.) read metrics + run\n // measurement sessions over the Streamable HTTP transport. Same-origin\n // is *not* required because MCP clients are local processes that don't\n // run inside a browser tab; the token is the gate.\n devServer.middlewares.use('/__svelte-devtools/mcp', async (req, res) => {\n const tokenHeader = req.headers['x-svelte-devtools-token']\n const token = Array.isArray(tokenHeader) ? tokenHeader[0] : tokenHeader\n if (token !== mcpToken) {\n res.statusCode = 403\n res.end('Forbidden')\n return\n }\n // An agent talking to us is a consumer: keep the runtime sampling. If\n // this request woke the runtime up, give it a moment to send its\n // activation snapshot so the first answer isn't stale.\n if (collector.lease('mcp', 60_000)) await collector.waitForSnapshot(1000)\n // Build a fresh server+transport per request. Stateless mode in the\n // SDK still keeps per-instance bookkeeping that gets corrupted when\n // the same transport handles multiple requests.\n const mcpServer = mcpServerFactory()\n const mcpTransport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n })\n mcpTransport.onerror = err => {\n devServer.config.logger.error(\n `[svelte-devtools] MCP transport error: ${err.stack || err.message}`,\n )\n }\n try {\n await mcpServer.connect(mcpTransport)\n // The SDK consumes the request body itself; pre-reading would\n // leave the stream empty.\n await mcpTransport.handleRequest(req as any, res as any)\n } catch (e) {\n devServer.config.logger.error(\n `[svelte-devtools] MCP handler error: ${\n e instanceof Error ? e.stack || e.message : String(e)\n }`,\n )\n if (!res.headersSent) {\n res.statusCode = 500\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({ error: String(e) }))\n }\n } finally {\n await mcpTransport.close().catch(() => {})\n await mcpServer.close().catch(() => {})\n }\n })\n },\n\n // Middleware-mode mounts have no `httpServer` close event; dispose them\n // from Vite's public `closeServer` hook (>= 8.3), which runs after the\n // server is torn down but carries no server reference. On restart Vite has\n // already configured the replacement server, so every mount older than\n // the newest server generation belongs to the server being torn down —\n // whether that server used this plugin instance (inline config) or a\n // previous one (config file, re-evaluated per restart).\n async closeServer({ reason }) {\n const doomed = middlewareModeMounts.filter(\n m => reason === 'close' || m.generation < serverGeneration,\n )\n for (const m of doomed) middlewareModeMounts.splice(middlewareModeMounts.indexOf(m), 1)\n await Promise.all(doomed.map(m => m.dispose()))\n },\n\n // Virtual module resolution: runtime + svelte/internal/client wrapper.\n // dev only — never resolve our virtual modules during production build.\n resolveId(id, importer) {\n if (config?.command !== 'serve') return undefined\n if (id === RUNTIME_MODULE_ID) return RESOLVED_RUNTIME_ID\n if (\n componentTracking &&\n id === 'svelte/internal/client' &&\n importer &&\n !importer.includes('node_modules') &&\n !importer.startsWith('\\0')\n ) {\n return WRAPPER_MODULE_ID\n }\n return undefined\n },\n\n load(id) {\n if (config?.command !== 'serve') return undefined\n if (id === RESOLVED_RUNTIME_ID) return runtimeCode\n if (id === WRAPPER_MODULE_ID) return wrapperCode\n return undefined\n },\n\n // Inject the runtime into the user's app\n transformIndexHtml() {\n if (config.command !== 'serve') return []\n return [\n {\n tag: 'script',\n attrs: { type: 'module' },\n children: `import '${RUNTIME_MODULE_ID}'`,\n injectTo: 'head-prepend',\n },\n ]\n },\n\n // Vite DevTools integration: only invoked by `@vitejs/devtools`. The kit\n // is imported lazily so apps without Vite DevTools never load it.\n devtools: {\n capabilities: { dev: true, build: false },\n async setup(ctx) {\n const { createPluginFromDevframe } = await import('@vitejs/devtools-kit/node')\n const plugin = createPluginFromDevframe(devframe, { base: DEVFRAME_BASE })\n await plugin.devtools?.setup?.(ctx)\n },\n },\n }\n\n // Minimal component tracking transform plugin.\n // Only injects the file path before $.push() so the runtime wrapper knows\n // which component file is being initialized. All reactive tracking (state,\n // derived, proxy, effect) is handled by the svelte/internal/client wrapper.\n const trackingPlugin: Plugin = {\n name: 'vite-devtools-svelte:tracking',\n enforce: 'post',\n apply: 'serve',\n\n transform(code, id) {\n if (!componentTracking) return null\n if (!id.endsWith('.svelte')) return null\n if (id.includes('node_modules')) return null\n if (config?.command !== 'serve') return null\n if (!code.includes('$.push(')) return null\n\n const safeId = JSON.stringify(id)\n\n const importLine = `import '${RUNTIME_MODULE_ID}';\\n`\n\n const modified =\n importLine +\n code.replace(\n /(\\$\\.push\\([^)]+\\);?)/,\n `if (typeof window !== 'undefined' && window.__SVELTE_DEVTOOLS__) { window.__SVELTE_DEVTOOLS__._pendingFile = ${safeId}; }\\n$1`,\n )\n\n return { code: modified, map: null }\n },\n }\n\n // Load function profiling transform plugin\n const loadProfilePlugin: Plugin = {\n name: 'vite-devtools-svelte:load-profile',\n enforce: 'post',\n apply: 'serve',\n\n transform(code, id) {\n if (config?.command !== 'serve') return null\n // Only transform SvelteKit load files\n const isServerLoad = /\\+page\\.server\\.[tj]s$/.test(id) || /\\+layout\\.server\\.[tj]s$/.test(id)\n const isUniversalLoad = /\\+(page|layout)\\.[tj]s$/.test(id) && !id.includes('.server.')\n if (!isServerLoad && !isUniversalLoad) return null\n if (id.includes('node_modules')) return null\n // Must have an exported load function\n if (!code.includes('export') || !code.includes('load')) return null\n\n const loadType = isServerLoad ? 'server' : 'universal'\n // Determine route from file path\n const routesMatch = id.match(/routes(.*)\\/\\+/)\n const route = routesMatch ? routesMatch[1] || '/' : '/'\n const safeRoute = JSON.stringify(route)\n const safeFile = JSON.stringify(id)\n const safeType = JSON.stringify(loadType)\n\n // Replace the exported load function with a profiled version.\n // Supports both `export const load = ...` and `export (async) function load(...)` patterns.\n let transformed = code.replace(/export\\s+const\\s+load\\s*=\\s*/, `const __original_load = `)\n\n if (transformed === code) {\n // Try `export function load` / `export async function load` pattern\n transformed = code.replace(\n /export\\s+(async\\s+)?function\\s+load\\s*\\(/,\n `const __original_load = $1function __load_impl(`,\n )\n }\n\n if (transformed === code) return null // no match found\n\n const profiledExport = `\nexport const load = async (event) => {\n const __start = performance.now();\n const __result = await __original_load(event);\n const __duration = performance.now() - __start;\n const __dataSize = JSON.stringify(__result || {}).length;\n if (typeof globalThis.__svelte_devtools_record_load === 'function') {\n globalThis.__svelte_devtools_record_load(${safeRoute}, ${safeFile}, ${safeType}, __duration, __dataSize);\n }\n return __result;\n};\n`\n return { code: transformed + profiledExport, map: null }\n },\n }\n\n // Register load profiling hook on server\n const loadProfileServerPlugin: Plugin = {\n name: 'vite-devtools-svelte:load-profile-server',\n apply: 'serve',\n\n configureServer() {\n // Make the recording function available globally on the server\n ;(globalThis as Record<string, unknown>).__svelte_devtools_record_load = (\n route: string,\n file: string,\n type: string,\n duration: number,\n dataSize: number,\n ) => {\n const entry: LoadProfile = {\n route,\n file,\n type: type as 'server' | 'universal',\n duration: Math.round(duration * 100) / 100,\n dataSize,\n timestamp: Date.now(),\n }\n collector.recordLoadProfile(entry)\n }\n },\n }\n\n // Compiler warning capture plugin\n const warningCapturePlugin: Plugin = {\n name: 'vite-devtools-svelte:warning-capture',\n enforce: 'post',\n apply: 'serve',\n\n configResolved(resolvedConfig) {\n // Intercept Svelte compiler warnings from the logger. A user\n // `customLogger` survives restarts, so the wrapper is installed once and\n // forwards to whichever plugin instance configured it last.\n const logger = resolvedConfig.logger as typeof resolvedConfig.logger & {\n [WARN_SINK]?: (msg: string) => void\n }\n const wrapped = WARN_SINK in logger\n logger[WARN_SINK] = msg => {\n // Svelte compiler warnings usually contain file paths and codes\n if (!msg.includes('.svelte') || config?.command !== 'serve') return\n const fileMatch = msg.match(/(?:^|\\s)((?:\\/|\\.\\/|\\w:)[^\\s:]+\\.svelte)(?::(\\d+):(\\d+))?/)\n const codeMatch = msg.match(/\\(([a-z0-9_-]+)\\)/)\n collector.recordCompilerWarning({\n code: codeMatch?.[1] || 'unknown',\n // oxlint-disable-next-line no-control-regex -- intentional: strip ANSI escape sequences\n message: msg.replace(/\\x1b\\[[0-9;]*m/g, '').trim(),\n file: fileMatch?.[1] || '',\n line: fileMatch?.[2] ? parseInt(fileMatch[2]) : undefined,\n column: fileMatch?.[3] ? parseInt(fileMatch[3]) : undefined,\n })\n }\n if (wrapped) return\n const originalWarn = logger.warn\n logger.warn = (msg: string, options?: { timestamp?: boolean }) => {\n logger[WARN_SINK]?.(msg)\n originalWarn(msg, options)\n }\n },\n }\n\n return [\n mainPlugin,\n trackingPlugin,\n loadProfilePlugin,\n loadProfileServerPlugin,\n warningCapturePlugin,\n sveltekitTemplateInjector(() => hostedByViteDevtools),\n ]\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["path","path","path","path","fs","fs","fs","classify","fs","fs","negativeIsBetter","fs","avg","round","path","crypto","fs","path$1","fs$1","dns","net","os","analyzeRoutes","routesDir","routes","scanDirectory","a","b","entries","dir","files","hasRouteFiles","entry","rootDir","routeFile","classifyFile","relativePath","routePath","buildRoutePath","params","extractParams","f","type","name","fullPath","part","inner","parts","matcherSplit","CACHE_TTL_MS","_cachedResult","_cachedRoot","_cachedAt","analyzeProject","now","root","result","_analyzeProjectUncached","pkgPath","pkg","deps","devDeps","getInstalledVersion","findRoutesDir","findStaticDir","pkgJsonPath","candidates","analyzeComponents","srcDir","svelteFiles","findSvelteFiles","imports","extractSvelteImports","file","getComponentName","i","filePath","importRegex","match","content","importPath","resolved","resolveImportPath","findProjectRoot","fromFile","libPath","RUNTIME_MODULE_ID","RESOLVED_RUNTIME_ID","WRAPPER_MODULE_ID","wrapperCode","runtimeCode","LIMITS","RUNTIME_REQUEST_TIMEOUT","lastSeq","nextSeq","LEGACY_EPOCH","HOT_EVENTS","MAX_CACHED_PULLS","SUMMARY_DEFAULTS","DROP_REASONS","validBaseline","v","clampInt","value","fallback","max","min","LEASE_TTL","tail","list","arr","head","Collector","keys","key","hooks","hot","listeners","client","d","event","listener","state","newest","epoch","evicted","wasActive","id","ttl","done","timer","idx","resolve","timeout","next","expiresAt","active","data","isDelta","incoming","c","ring","received","captured","drops","counts","reason","dropped","r","tooLarge","n","profiles","profilesTotal","graph","info","common","last","start","count","valueTooLarge","cursor","since","keep","e","changes","change","size","drop","bytes","requestId","pull","answered","legacy","nodes","rawEdges","policy","scope","total","own","truncated","ids","edgesOmitted","edges","rows","w","sample","error","profile","warning","req","maxNodes","maxEdges","topK","windowMs","empty","cached","existing","promise","payload","resolver","resolvers","pending","MIME_TYPES","analyzeAssets","staticDir","assets","scanDir","publicBase","base","stat","ext","parseExternalUrl","parsed","urlStr","hostname","isPrivateIP","lower","assertOutboundUrl","options","addresses","address","ip","isPrivateIPv6","p","v4","resolveWithinRoot","input","realRoot","candidate","real","HTTP_METHODS","analyzeApiEndpoints","endpoints","route","serverFile","methods","m","sendApiRequest","duration","parsedHeaders","init","res","body","headers","k","WEB_EXTENSIONS","analyzeBuild","chunks","dirs","walkDir","full","s","classify$1","buildModuleGraph","modules","idMap","moduleById","mod","allModules","relFile","node","importedBySets","importsSet","imp","impNode","by","cycles","visited","stack","pathBuf","dfs","cycleStart","cycle","cyclicIds","getOGPreview","preview","url","html","metaRegex","propRegex","contentRegex","attrs","propMatch","contentMatch","prop","titleMatch","descTag","t","findReactiveLine","lines","source","l","escaped","regex","DEVFRAME_ID","DEVFRAME_BASE","createRequire","clientAssets","fileURLToPath","z","createRpcFunctions","host","project","defineRpcFunction","collector","line","map","createSvelteDevframe","defineDevframe","scoped","ctx","fn","WILDCARD","LOOPBACK","formatHost","networkOrigins","proto","h","mountStandalone","instance","closed","httpServer","server","created","initDevframe","def","local","current","UNCHANGED_RENDER_THRESHOLD_MS","UNCHANGED_LOAD_THRESHOLD_MS","UNCHANGED_FPS_THRESHOLD","FPS_DROP_THRESHOLD","takeSnapshot","getters","classify","diff","threshold","lowerIsBetter","SESSION_ID_PATTERN","isSessionId","SessionStore","opts","record","rec","seen","out","had","onDisk","startMap","components","end","startRenderCount","startTotal","renderCountDelta","totalRenderTimeDelta","loadDurations","loadAvg","avg$1","loadP95","percentile","fpsValues","fpsAvg","fpsMin","fpsDrops","idA","idB","recA","recB","totalA","totalB","renderDiff","loadDiff","fpsDiff","raw","xs","x","sorted","DEFAULTS","listPerformanceIssues","thresholds","inputs","avg","round$1","inDegree","compareSeverity","SEV_RANK","summarizeReactiveProblems","thresh","outDegree","effects","orphanDeriveds","isolatedNodes","ind","outd","MCP_VALUE_CHARS","capValue","json","maxChars","sessionId","TEXT","buildMcpServer","McpServer","args","reactiveGraph","issues","round","topN","byRoute","ps","durations","samples","sinceMs","cutoff","includeMeta","all","limit","snap","getSummary","getScope","componentId","getDelta","delta","valueChars","maxValueChars","omitted","getInfo","label","persist","GENERATED_SERVER_SUFFIXES","TEMPLATE_APP_MARKER","INJECT_SCRIPT_URL","DEVTOOLS_MOUNT_PATH","INJECT_TAG","BODY_CLOSE","injectIntoSvelteKitInternal","code","markerIdx","bodyIdx","sveltekitTemplateInjector","env","suffix","isHosted","VITE_DEVTOOLS_PLUGIN","WARN_SINK","serverGeneration","collectModules","injectComponentTracking","safeId","SVELTE_MODULE_RE","injectModuleTracking","dt","svelteDevtools","config","hostedByViteDevtools","mcpToken","sessions","getSessions","devframe","urls","u","launchEditor","target","middlewareModeMounts","resolvedConfig","devServer","generation","dispose","mcpServerFactory","addr","cmd","tokenHeader","mcpServer","mcpTransport","StreamableHTTPServerTransport","err","doomed","componentTracking","importer","createPluginFromDevframe","modified","isServerLoad","isUniversalLoad","loadType","routesMatch","safeRoute","safeFile","safeType","transformed","profiledExport","logger","wrapped","msg","fileMatch","codeMatch","originalWarn"],"sources":["../src/analyzers/routes.ts","../src/analyzers/project.ts","../src/analyzers/components.ts","../src/runtime.ts","../src/collector.ts","../src/analyzers/assets.ts","../src/security.ts","../src/analyzers/api.ts","../src/analyzers/build.ts","../src/analyzers/module-graph.ts","../src/analyzers/og.ts","../src/analyzers/source.ts","../src/devframe.ts","../src/mount.ts","../src/mcp/sessions.ts","../src/mcp/issues.ts","../src/mcp/server.ts","../src/template-injector.ts","../src/plugin.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport type { RouteInfo, ParamInfo, RouteFile } from '../types.js'\n\nexport function analyzeRoutes(routesDir: string): RouteInfo[] {\n if (!fs.existsSync(routesDir)) return []\n\n const routes: RouteInfo[] = []\n scanDirectory(routesDir, routesDir, routes)\n return routes.sort((a, b) => a.path.localeCompare(b.path))\n}\n\nfunction scanDirectory(dir: string, rootDir: string, routes: RouteInfo[]): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n const files: RouteFile[] = []\n let hasRouteFiles = false\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n scanDirectory(path.join(dir, entry.name), rootDir, routes)\n continue\n }\n\n const routeFile = classifyFile(entry.name, path.join(dir, entry.name))\n if (routeFile) {\n files.push(routeFile)\n hasRouteFiles = true\n }\n }\n\n if (hasRouteFiles) {\n const relativePath = path.relative(rootDir, dir)\n const routePath = buildRoutePath(relativePath)\n const params = extractParams(relativePath)\n\n routes.push({\n id: relativePath || '/',\n path: routePath,\n pattern: routePath,\n segments: routePath.split('/').filter(Boolean),\n hasPage: files.some(f => f.type === 'page'),\n hasLayout: files.some(f => f.type === 'layout'),\n hasServerPage: files.some(f => f.type === 'page-load-server'),\n hasServerLayout: files.some(f => f.type === 'layout-load-server'),\n hasEndpoint: files.some(f => f.type === 'endpoint'),\n hasPageLoad: files.some(f => f.type === 'page-load'),\n hasLayoutLoad: files.some(f => f.type === 'layout-load'),\n params,\n files,\n })\n }\n}\n\nfunction classifyFile(name: string, fullPath: string): RouteFile | null {\n const map: Record<string, RouteFile['type']> = {\n '+page.svelte': 'page',\n '+layout.svelte': 'layout',\n '+page.server.ts': 'page-load-server',\n '+page.server.js': 'page-load-server',\n '+layout.server.ts': 'layout-load-server',\n '+layout.server.js': 'layout-load-server',\n '+page.ts': 'page-load',\n '+page.js': 'page-load',\n '+layout.ts': 'layout-load',\n '+layout.js': 'layout-load',\n '+server.ts': 'endpoint',\n '+server.js': 'endpoint',\n '+error.svelte': 'error',\n }\n\n const type = map[name]\n if (!type) return null\n return { type, path: fullPath }\n}\n\nfunction buildRoutePath(relativePath: string): string {\n if (!relativePath) return '/'\n\n const parts = relativePath.split(path.sep)\n const pathParts = parts.map(part => {\n // SvelteKit group syntax: (group) -> ignored in URL\n if (part.startsWith('(') && part.endsWith(')')) return null\n\n // Dynamic params: [param] -> :param\n if (part.startsWith('[') && part.endsWith(']')) {\n const inner = part.slice(1, -1)\n if (inner.startsWith('...')) return `*${inner.slice(3)}`\n if (inner.startsWith('[') && inner.endsWith(']')) return `:${inner.slice(1, -1)}?`\n return `:${inner}`\n }\n\n return part\n })\n\n return '/' + pathParts.filter(Boolean).join('/')\n}\n\nfunction extractParams(relativePath: string): ParamInfo[] {\n if (!relativePath) return []\n\n const params: ParamInfo[] = []\n const parts = relativePath.split(path.sep)\n\n for (const part of parts) {\n if (!part.startsWith('[') || !part.endsWith(']')) continue\n\n const inner = part.slice(1, -1)\n\n if (inner.startsWith('...')) {\n params.push({ name: inner.slice(3), optional: false, rest: true })\n } else if (inner.startsWith('[') && inner.endsWith(']')) {\n params.push({ name: inner.slice(1, -1), optional: true, rest: false })\n } else {\n const matcherSplit = inner.split('=')\n params.push({\n name: matcherSplit[0],\n optional: false,\n rest: false,\n matcher: matcherSplit[1],\n })\n }\n }\n\n return params\n}\n","import fs from 'fs'\nimport path from 'path'\nimport type { ProjectInfo } from '../types.js'\n\nconst CACHE_TTL_MS = 5000\nlet _cachedResult: ProjectInfo | null = null\nlet _cachedRoot: string | null = null\nlet _cachedAt = 0\n\nexport function analyzeProject(root: string): ProjectInfo {\n const now = Date.now()\n if (_cachedResult && _cachedRoot === root && now - _cachedAt < CACHE_TTL_MS) {\n return _cachedResult\n }\n const result = _analyzeProjectUncached(root)\n _cachedResult = result\n _cachedRoot = root\n _cachedAt = now\n return result\n}\n\nfunction _analyzeProjectUncached(root: string): ProjectInfo {\n const pkgPath = path.join(root, 'package.json')\n const pkg = fs.existsSync(pkgPath) ? JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) : {}\n\n const deps = pkg.dependencies || {}\n const devDeps = pkg.devDependencies || {}\n\n return {\n name: pkg.name || path.basename(root),\n version: pkg.version || '0.0.0',\n svelteVersion:\n getInstalledVersion(root, 'svelte') || deps.svelte || devDeps.svelte || 'unknown',\n sveltekitVersion:\n getInstalledVersion(root, '@sveltejs/kit') ||\n deps['@sveltejs/kit'] ||\n devDeps['@sveltejs/kit'] ||\n 'unknown',\n viteVersion: getInstalledVersion(root, 'vite') || deps.vite || devDeps.vite || 'unknown',\n dependencies: deps,\n devDependencies: devDeps,\n routesDir: findRoutesDir(root),\n staticDir: findStaticDir(root),\n }\n}\n\nfunction getInstalledVersion(root: string, pkg: string): string | null {\n try {\n const pkgJsonPath = path.join(root, 'node_modules', pkg, 'package.json')\n if (fs.existsSync(pkgJsonPath)) {\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'))\n return pkgJson.version\n }\n } catch {\n // ignore\n }\n return null\n}\n\nfunction findRoutesDir(root: string): string {\n const candidates = [path.join(root, 'src', 'routes'), path.join(root, 'src', 'pages')]\n for (const dir of candidates) {\n if (fs.existsSync(dir)) return dir\n }\n return path.join(root, 'src', 'routes')\n}\n\nfunction findStaticDir(root: string): string {\n const candidates = [path.join(root, 'static'), path.join(root, 'public')]\n for (const dir of candidates) {\n if (fs.existsSync(dir)) return dir\n }\n return path.join(root, 'static')\n}\n","import fs from 'fs'\nimport path from 'path'\nimport type { ComponentRelation } from '../types.js'\n\nexport function analyzeComponents(root: string): ComponentRelation[] {\n const srcDir = path.join(root, 'src')\n if (!fs.existsSync(srcDir)) return []\n\n const svelteFiles: string[] = []\n findSvelteFiles(srcDir, svelteFiles)\n\n return svelteFiles.map(file => {\n const content = fs.readFileSync(file, 'utf-8')\n const imports = extractSvelteImports(content, file)\n const name = getComponentName(file)\n\n return {\n file: path.relative(root, file),\n name,\n imports: imports.map(i => path.relative(root, i)),\n }\n })\n}\n\nfunction findSvelteFiles(dir: string, files: string[]): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === '.svelte-kit') continue\n findSvelteFiles(fullPath, files)\n } else if (entry.name.endsWith('.svelte')) {\n files.push(fullPath)\n }\n }\n}\n\nfunction extractSvelteImports(content: string, filePath: string): string[] {\n const imports: string[] = []\n const dir = path.dirname(filePath)\n\n // Match: import X from './Component.svelte'\n // Match: import X from '$lib/Component.svelte' (SvelteKit 2) or '#lib/…' (SvelteKit 3)\n const importRegex = /import\\s+[\\w{}\\s,*]+\\s+from\\s+['\"]([^'\"]+\\.svelte)['\"]/g\n let match: RegExpExecArray | null\n\n while ((match = importRegex.exec(content)) !== null) {\n const importPath = match[1]\n const resolved = resolveImportPath(importPath, dir, filePath)\n if (resolved) imports.push(resolved)\n }\n\n return imports\n}\n\nfunction resolveImportPath(importPath: string, dir: string, fromFile: string): string | null {\n // $lib alias (SvelteKit 2) or the `#lib/*` subpath import SvelteKit 3 uses\n // instead, both conventionally mapped to src/lib\n if (importPath.startsWith('$lib/') || importPath.startsWith('#lib/')) {\n const root = findProjectRoot(fromFile)\n if (root) {\n const libPath = path.join(root, 'src', 'lib', importPath.slice(5))\n if (fs.existsSync(libPath)) return libPath\n }\n return null\n }\n\n // Relative import\n if (importPath.startsWith('.')) {\n const resolved = path.resolve(dir, importPath)\n if (fs.existsSync(resolved)) return resolved\n }\n\n return null\n}\n\nfunction findProjectRoot(filePath: string): string | null {\n let dir = path.dirname(filePath)\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, 'package.json'))) return dir\n dir = path.dirname(dir)\n }\n return null\n}\n\nfunction getComponentName(filePath: string): string {\n return path.basename(filePath, '.svelte')\n}\n","// This code is injected into the user's app as a virtual module.\n// It tracks Svelte component mount/unmount and sends data to the Vite server via HMR.\nexport const RUNTIME_MODULE_ID = 'virtual:svelte-devtools-runtime'\nexport const RESOLVED_RUNTIME_ID = '\\0' + RUNTIME_MODULE_ID\n\n// Virtual module ID for the svelte/internal/client wrapper.\n// When user code imports 'svelte/internal/client', it is redirected to this module.\n// The wrapper re-exports everything and overrides key functions for devtools tracking.\nexport const WRAPPER_MODULE_ID = '\\0svelte-devtools:wrapped-client'\n\n/**\n * Wrapper code for svelte/internal/client.\n *\n * Re-exports everything from the real module, then overrides:\n * - push/pop: component lifecycle tracking\n * - tag/tag_proxy: named signal/proxy tracking (Svelte dev mode)\n * - state/derived/proxy: type markers consumed by tag/tag_proxy\n * - user_effect/user_pre_effect: effect tracking\n * - template_effect/deferred_template_effect: render count/time profiling\n * - each/if/key/await/component/boundary: block-callback owner attribution\n *\n * This single module replaces all post-compilation regex transforms\n * for reactive tracking, making the approach Svelte-compiler-output agnostic.\n */\nexport const wrapperCode = /* js */ `\nimport * as __svelte_original from 'svelte/internal/client';\nexport * from 'svelte/internal/client';\n\nfunction __dt() {\n return typeof window !== 'undefined' ? window.__SVELTE_DEVTOOLS__ : null;\n}\n\n// Component ID stack (parallel to runtime._stack but local to wrapper)\nconst __idStack = [];\nfunction __currentId() {\n return __idStack.length > 0 ? __idStack[__idStack.length - 1] : null;\n}\n\n// Tracks the most recently created signal for type determination in tag()\nconst __pendingSignal = { ref: null, type: null };\n\n// Component context -> devtools id (review B1b). A component created later\n// by a block update ({#each}/{#if} after mount) runs outside its parent's\n// push..pop, where the runtime's init stack is empty (the wrapper stack\n// below covers the wrapped block helpers; this covers the rest). Svelte (5.56.8,\n// internal/client) exports active_effect; every effect records the\n// component context it was created in (effect.ctx) and runs with that\n// context restored. The block effect that creates the child belongs to the\n// parent's template, so active_effect.ctx at push time IS the parent's\n// context. Each context is mapped to its id once the component mounted\n// (inside its own deferred effect, where active_effect.ctx is the\n// component's own context). The map lives on the runtime (dt._idByContext)\n// so the reactive graph can name the component of any effect it reaches.\n// Weak map: no leak, no Svelte state touched.\nfunction __parentFromContext() {\n const dt = __dt();\n const effect = __svelte_original.active_effect;\n const ctx = effect ? effect.ctx : null;\n return dt && ctx && dt._idByContext ? dt._idByContext.get(ctx) : undefined;\n}\n\n// Owner of a signal/effect created right now: the component whose init (or\n// wrapped block callback) is running, else — outside init, e.g. an effect\n// created while another effect runs — the component of the active effect.\nfunction __owner() {\n const cid = __currentId();\n if (cid !== null) return cid;\n const fromContext = __parentFromContext();\n return fromContext === undefined ? null : fromContext;\n}\n\n// --- Component Lifecycle ---\n//\n// Observer must not break the observed: every devtools side-effect below is\n// wrapped in try/catch so a bug or an out-of-shape runtime cannot tear down\n// the user's app. The original Svelte function is always called, and its\n// return value always returned, regardless of devtools failures.\n\nexport function push() {\n // Parent hint, read before this component's own id exists:\n // 1. the wrapper stack: the component whose init is running (children\n // rendered directly by a template, where active_effect still belongs to\n // an outer block), or the block owner re-pushed by __wrapBlockFn for a\n // later {#each}/{#if}/{#key} update (see Block Attribution below);\n // 2. else the context-derived owner, for re-creation paths the wrapper\n // does not wrap (snippet, svelte:element, ...).\n let parentHint = null;\n try { parentHint = __currentId(); } catch {}\n if (parentHint === null) {\n try { parentHint = __parentFromContext(); } catch {}\n }\n const result = __svelte_original.push.apply(null, arguments);\n try {\n const dt = __dt();\n if (dt) {\n const file = dt._pendingFile || 'Unknown';\n dt._pendingFile = null;\n dt._pendingParent = parentHint;\n const id = dt.register(file);\n __idStack.push(id);\n dt.startInit(id);\n try {\n __svelte_original.user_effect(() => {\n try {\n const own = __svelte_original.active_effect;\n if (own && own.ctx) dt._idByContext.set(own.ctx, id);\n if (own) dt.setComponentEffect(id, own);\n } catch {}\n return () => { try { dt.unmount(id); } catch {} };\n });\n } catch {}\n }\n } catch {}\n return result;\n}\n\nexport function pop() {\n // Capture devtools errors but ALWAYS forward to the original pop so the\n // Svelte component stack stays balanced.\n try {\n const dt = __dt();\n if (dt && __idStack.length > 0) {\n const id = __idStack.pop();\n try { dt.endInit(id); } catch {}\n try { dt.registered(id); } catch {}\n }\n } catch {}\n return __svelte_original.pop.apply(null, arguments);\n}\n\n// --- Signal Creation (type markers) ---\n\nexport function state() {\n const signal = __svelte_original.state.apply(null, arguments);\n try {\n __pendingSignal.ref = signal;\n __pendingSignal.type = 'state';\n } catch {}\n return signal;\n}\n\nexport function derived() {\n const signal = __svelte_original.derived.apply(null, arguments);\n try {\n __pendingSignal.ref = signal;\n __pendingSignal.type = 'derived';\n } catch {}\n return signal;\n}\n\nexport function proxy() {\n const p = __svelte_original.proxy.apply(null, arguments);\n try {\n __pendingSignal.ref = p;\n __pendingSignal.type = 'proxy';\n } catch {}\n return p;\n}\n\n// --- Signal Tagging (Svelte dev mode) ---\n\nexport function tag(signal, name) {\n const result = __svelte_original.tag.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __owner();\n const type = (__pendingSignal.ref === signal) ? __pendingSignal.type : 'state';\n if (dt && cid !== null) {\n const owner = __svelte_original.active_effect;\n if (type === 'derived') {\n dt.trackDerived(signal, name, cid, owner);\n } else {\n dt.trackState(signal, name, cid, owner);\n }\n } else if (dt && dt._moduleFile) {\n // created while a .svelte.js/.ts module body runs (shared state)\n dt.trackModuleSignal(type === 'derived' ? 'derived' : 'state', signal, name);\n }\n __pendingSignal.ref = null;\n __pendingSignal.type = null;\n } catch {}\n return result;\n}\n\nexport function tag_proxy(proxy, name) {\n const result = __svelte_original.tag_proxy.apply(null, arguments);\n try {\n const dt = __dt();\n const cid = __owner();\n if (dt && cid !== null) {\n dt.trackProxy(proxy, name, cid, __svelte_original.active_effect);\n } else if (dt && dt._moduleFile) {\n dt.trackModuleSignal('proxy', proxy, name);\n }\n __pendingSignal.ref = null;\n __pendingSignal.type = null;\n } catch {}\n return result;\n}\n\n// --- Effect Tracking ---\n//\n// A top-level $effect in a component is deferred by Svelte until mount:\n// user_effect() returns undefined and the effect object is created later,\n// in pop(). So the node is registered now (named per component) and bound\n// to the real effect object on its first run, where active_effect IS the\n// effect; the Svelte runtime then keeps effect.deps current, which is what\n// getReactiveGraph() reads to build edges. The wrapped callback forwards\n// this, arguments and the return value (teardown) unchanged.\n\nfunction __trackUserEffect(original, kind, args) {\n let cid = null;\n let dt = null;\n let fn = null;\n try {\n dt = __dt();\n fn = args[0];\n if (dt && typeof fn === 'function') cid = __owner();\n } catch {}\n if (cid === null) return original.apply(null, args);\n let nodeId = null;\n let bound = false;\n const wrapped = Array.prototype.slice.call(args);\n wrapped[0] = function () {\n if (!bound) {\n bound = true;\n try { dt.bindEffect(nodeId, __svelte_original.active_effect); } catch {}\n }\n return fn.apply(this, arguments);\n };\n try { nodeId = dt.trackUserEffect(kind, cid, __svelte_original.active_effect); } catch {}\n const result = original.apply(null, wrapped);\n if (result && !bound) {\n bound = true;\n try { dt.bindEffect(nodeId, result); } catch {}\n }\n return result;\n}\n\nexport function user_effect() {\n return __trackUserEffect(__svelte_original.user_effect, 'effect', arguments);\n}\n\nexport function user_pre_effect() {\n return __trackUserEffect(__svelte_original.user_pre_effect, 'effect_pre', arguments);\n}\n\n// --- Render Profiling ---\n//\n// Svelte 5 has no virtual DOM: the compiler wraps every dynamic part of a\n// template in a template_effect (deferred_template_effect for <svelte:head>\n// <title>). A re-run of such an effect IS the component updating the DOM, so\n// these two functions are the measurement points for renders / render time.\n//\n// The first run of an effect is the mount-time paint, already covered by\n// initTime, so it is skipped (initialRun). One state change re-runs several\n// effects of the same component, so durations are pooled per microtask and\n// recorded once per flush: recordRender() +1, recordRenderTime() the sum.\n\nconst __pendingRenderDurations = new Map();\nlet __renderFlushScheduled = false;\n\nfunction __flushRenderDurations() {\n __renderFlushScheduled = false;\n const dt = __dt();\n for (const [cid, duration] of __pendingRenderDurations) {\n if (dt) {\n try { dt.recordRender(cid); } catch {}\n try { dt.recordRenderTime(cid, duration); } catch {}\n }\n }\n __pendingRenderDurations.clear();\n}\n\nfunction __recordRenderDuration(cid, duration) {\n __pendingRenderDurations.set(cid, (__pendingRenderDurations.get(cid) || 0) + duration);\n if (!__renderFlushScheduled) {\n __renderFlushScheduled = true;\n queueMicrotask(__flushRenderDurations);\n }\n}\n\n// Returns a (possibly new) args array whose first element times each re-run\n// of the effect closure. The owning component is whatever id is on top of\n// __idStack at effect-creation time. User exceptions propagate untouched;\n// only the args are built inside try so the original is called exactly once.\nfunction __wrapTemplateEffect(args) {\n const cid = __owner();\n const fn = args[0];\n if (cid === null || typeof fn !== 'function') return args;\n const wrapped = Array.prototype.slice.call(args);\n let initialRun = true;\n wrapped[0] = function () {\n if (initialRun) {\n initialRun = false;\n return fn.apply(this, arguments);\n }\n const start = performance.now();\n try {\n return fn.apply(this, arguments);\n } finally {\n try { __recordRenderDuration(cid, performance.now() - start); } catch {}\n }\n };\n return wrapped;\n}\n\nexport function template_effect() {\n let args = arguments;\n try { args = __wrapTemplateEffect(arguments); } catch {}\n return __svelte_original.template_effect.apply(null, args);\n}\n\nexport function deferred_template_effect() {\n let args = arguments;\n try { args = __wrapTemplateEffect(arguments); } catch {}\n return __svelte_original.deferred_template_effect.apply(null, args);\n}\n\n// --- Block Attribution ---\n//\n// Svelte creates render effects synchronously at creation time. At mount this\n// happens during the component function (between push/pop), so __idStack has\n// the owner. But effects for {#each} items added later or re-created {#if}\n// branches are created during a batch flush, when the stack is empty — they\n// would never be attributed. Block helpers themselves ARE always called\n// during their owner's init (or inside an outer block's callback), so the\n// owner id is on the stack at block-creation time. __wrapBlock captures it\n// and re-pushes it around every function argument the block invokes later,\n// so effects created inside land on the innermost owner. Child components\n// push their own id on top, keeping nested attribution correct.\n\n// A component whose init throws (caught by <svelte:boundary>, or by the\n// block's caller) never reaches pop(): its id would stay on both stacks and\n// every later signal/child would be attributed to it. On the way out — normal\n// or thrown — the stack is cut back to its depth on entry, and ids left\n// above it are dropped as aborted inits (registered, never mounted).\nfunction __wrapBlockFn(fn, cid) {\n return function () {\n let depth = -1;\n try { depth = __idStack.length; __idStack.push(cid); } catch {}\n try {\n return fn.apply(this, arguments);\n } finally {\n if (depth !== -1) {\n try {\n if (__idStack.length > depth + 1) {\n const dt = __dt();\n const aborted = __idStack.slice(depth + 1);\n for (let i = aborted.length - 1; i >= 0; i--) {\n try { if (dt) dt.abortInit(aborted[i]); } catch {}\n }\n }\n __idStack.length = depth;\n } catch {}\n }\n }\n };\n}\n\nfunction __wrapBlock(args) {\n const cid = __owner();\n if (cid === null) return args;\n const wrapped = Array.prototype.slice.call(args);\n for (let i = 0; i < wrapped.length; i++) {\n if (typeof wrapped[i] === 'function') wrapped[i] = __wrapBlockFn(wrapped[i], cid);\n }\n return wrapped;\n}\n\nexport function each() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.each.apply(null, args);\n}\n\nexport function key() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.key.apply(null, args);\n}\n\nexport function component() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.component.apply(null, args);\n}\n\nexport function boundary() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original.boundary.apply(null, args);\n}\n\n// 'if' and 'await' are reserved words, so they cannot be declared as\n// function names and are exported via aliases instead.\nfunction __if_block() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original['if'].apply(null, args);\n}\n\nfunction __await_block() {\n let args = arguments;\n try { args = __wrapBlock(arguments); } catch {}\n return __svelte_original['await'].apply(null, args);\n}\n\nexport { __if_block as if, __await_block as await };\n`\n\nexport const runtimeCode = /* js */ `\nif (typeof window !== 'undefined' && !window.__SVELTE_DEVTOOLS__) {\n const __NO_VALUE = Symbol('no value');\n // State timeline ring (§6.7 C): every read sees at most 500 entries and\n // __TIMELINE_BYTES (also the server's buffer budget). The raw array may\n // hold up to __TIMELINE_TRIM_AT (2 x the 500 cap) between bulk trims.\n const __TIMELINE_BYTES = 4 * 1024 * 1024;\n const __TIMELINE_TRIM_AT = 1000;\n // FNV-1a over UTF-16 code units: cheap change detection for large snapshots.\n const __hash = (str) => {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(36);\n };\n const __SVELTE_DT = {\n _nextId: 0,\n _instances: new Map(),\n _stack: [],\n _pendingParent: undefined,\n _pendingFile: null,\n _debounceTimer: null,\n _listeners: new Set(),\n\n // Phase 2: Profiling data\n _profiles: new Map(),\n _initStartTimes: new Map(),\n _profileDebounceTimer: null,\n\n // Phase 2: Reactive graph data\n _reactiveNodes: new Map(),\n _reactiveProxies: new Map(),\n\n // componentId -> Set<nodeId>. Lets unmount purge a component's reactive\n // nodes without scanning every node of the app (was O(components x nodes)).\n _nodesByComponent: new Map(),\n\n // Phase 3: State timeline\n _stateTimeline: [],\n _stateSnapshots: new Map(),\n _timelineDebounceTimer: null,\n // signal (or proxy marker) -> nodeId, set at track time and removed by\n // _forgetNode: a scoped graph resolves dependencies without scanning\n // every node (§6.7 D).\n _idBySignal: new WeakMap(),\n // proxy -> nodeId (tag_proxy nodes; the marker above is per node)\n _idByProxy: new WeakMap(),\n // Svelte component context -> component id (set by the wrapper on mount)\n _idByContext: new WeakMap(),\n // componentId -> (name -> last suffix) for names declared more than once\n // per instance ({@const} in {#each} items, several $state class instances)\n _nameSeq: new Map(),\n // Module scopes: signals created while a .svelte.js/.ts module body runs\n // (shared state such as \\`export const cart = $state(...)\\`) belong to a\n // scope per module file. Ids come from the component id counter (never\n // reused, non-negative) but scopes are not components: they are not in\n // _instances / the component tree, and live as long as the page.\n _modules: new Map(),\n _moduleByFile: new Map(),\n // $state node name -> (scope id -> Set<nodeId>): resolves a proxy's property source\n // (labelled '<name>.prop' by Svelte in dev) to the node of its proxy —\n // a tag_proxy node, or a state signal holding a proxy (reassigned object\n // state, class fields)\n _proxyNames: new Map(),\n // file of the module body running now (set by the module transform)\n _moduleFile: null,\n // componentId -> { effect, effect_pre } counters: effect names are\n // numbered per component, so instances of one file match\n _effectSeq: new Map(),\n // Every tracked node id (dense, swap-remove like _pollIds) for the\n // incremental liveness sweep, and its cursor.\n _sweepIds: [],\n _sweepIndex: new Map(),\n _sweepCursor: 0,\n // Polling bookkeeping (§6.7 D): $state node ids in a dense array kept up\n // to date incrementally (_pollIndex: nodeId -> position; removal is\n // swap-with-last), a cursor carried across ticks, nodes found changed but\n // not yet serialized (_pollDirty), and per-node change hints\n // (nodeId -> { ref, wv, nextCheckAt }).\n _pollIds: [],\n _pollIndex: new Map(),\n _pollCursor: 0,\n _pollDirty: new Set(),\n // Full-sweep bookkeeping: how long the last complete pass over all $state\n // nodes took (ms), for disclosure (= the worst-case detection delay).\n _pollSweep: { startedAt: 0, lastMs: null, nodes: 0 },\n _pollMeta: new Map(),\n _deepCredit: 0,\n _lastSnapshotSize: new Map(),\n _timelineSeq: 0,\n _pushedSeq: 0,\n _timelineReset: false,\n _entryInfo: new WeakMap(),\n // Sum of _entryInfo.bytes over _stateTimeline (runtime byte budget).\n _timelineBytes: 0,\n // Disclosure since the last push (§6.7 C): unsent entries the ring removed\n // (by count / by bytes) and changes recorded only as a size summary.\n _timelineDropped: { 'runtime-count': 0, 'runtime-bytes': 0 },\n _valueTooLarge: 0,\n\n // Overview aggregate (§6.7 I/J), O(1) per event: registered nodes per\n // component and type (+ app totals), and per-component activity in a\n // ring of 60 one-second buckets (sampled changes, renders, render ms,\n // plus how long sampling ran in that second).\n _nodeCounts: new Map(),\n _nodeTotals: { state: 0, derived: 0, effect: 0 },\n _activity: [],\n _epoch: Math.random().toString(36).slice(2) + Date.now().toString(36),\n\n // --- Activity subscription (docs/devframe-migration.md §6.3) ---\n // Inactive until the server says a DevTools client (UI tab or MCP lease)\n // is watching: no state polling, FPS rAF loop, or periodic HMR sends.\n _active: false,\n _componentsCost: { ms: 0, bytes: 0 },\n _componentDeltas: false,\n _pendingAdded: new Set(),\n _pendingRemoved: new Set(),\n _lastFullAt: 0,\n _resync: false,\n _profilesCost: { ms: 0, bytes: 0 },\n // = collector LIMITS.renderProfiles (pinned by a unit test): the server\n // keeps only the newest entries, so sending more is wasted bytes.\n _profileCap: 5000,\n _sampling: null,\n _baselining: false,\n // Polled state nodes not observed yet (no seed value). Their first\n // observation is a seed, not a change: no timeline entry, no activity\n // count, no drops — the old value is unknown, not null (review B-1/B-2).\n _unseeded: new Set(),\n // pendingNodes last sent on a state-timeline message (null = none yet)\n _sentPendingNodes: null,\n _fpsGen: 0,\n\n register(file) {\n const id = this._nextId++;\n // Parent: the wrapper's context-derived hint (components created by a\n // later block update, review B1b) when it names a live instance, else\n // the synchronous init stack (children created during the parent's own\n // init, before the parent is mapped).\n const hint = this._pendingParent;\n this._pendingParent = undefined;\n const parentId =\n hint !== undefined && hint !== null && this._instances.has(hint)\n ? hint\n : this._stack.length > 0 ? this._stack[this._stack.length - 1] : null;\n const name = file.split('/').pop()?.replace('.svelte', '') || 'Unknown';\n // children is a Set so unmounting one row of a 5 000-row list is O(1).\n this._instances.set(id, { id, file, name, parentId, mounted: true, children: new Set() });\n if (parentId !== null) {\n const parent = this._instances.get(parentId);\n if (parent) parent.children.add(id);\n }\n this._stack.push(id);\n if (this._active) this._pendingAdded.add(id);\n this._scheduleUpdate();\n return id;\n },\n\n registered(id) {\n const idx = this._stack.indexOf(id);\n if (idx !== -1) this._stack.splice(idx, 1);\n },\n\n mount(id) {\n const instance = this._instances.get(id);\n if (instance && !instance.mounted) {\n instance.mounted = true;\n if (this._active) this._pendingAdded.add(id);\n this._scheduleUpdate();\n }\n },\n\n unmount(id) {\n const instance = this._instances.get(id);\n if (instance) {\n if (instance.parentId !== null) {\n const parent = this._instances.get(instance.parentId);\n if (parent) parent.children.delete(id);\n }\n this._removeChildren(id);\n this._cleanupComponent(id);\n }\n this._scheduleUpdate();\n this._scheduleProfileUpdate();\n },\n\n // Remounts get a fresh id, so entries keyed by a dead id would otherwise\n // survive forever — every per-component map must be purged here.\n _cleanupComponent(id) {\n // Delta bookkeeping: an id added and removed between two pushes was\n // never sent, so it cancels out.\n if (this._active && !this._pendingAdded.delete(id)) this._pendingRemoved.add(id);\n this._cleanupReactiveNodes(id);\n this._effectSeq.delete(id);\n this._nameSeq.delete(id);\n this._instances.delete(id);\n this._profiles.delete(id);\n this._initStartTimes.delete(id);\n },\n\n _cleanupReactiveNodes(componentId) {\n const nodeIds = this._nodesByComponent.get(componentId);\n if (!nodeIds) return;\n this._nodesByComponent.delete(componentId);\n for (const nodeId of [...nodeIds]) this._forgetNode(nodeId);\n },\n\n _forgetNode(nodeId) {\n const entry = this._reactiveNodes.get(nodeId);\n if (entry) {\n this._countNode(entry.meta.componentId, entry.meta.type, -1);\n const set = this._nodesByComponent.get(entry.meta.componentId);\n if (set) set.delete(nodeId);\n }\n const signal = entry && entry.signal.deref();\n if (signal && this._idBySignal.get(signal) === nodeId) this._idBySignal.delete(signal);\n const proxy = this._reactiveProxies.get(nodeId)?.deref();\n if (proxy && this._idByProxy.get(proxy) === nodeId) this._idByProxy.delete(proxy);\n if (entry && entry.meta.type === 'state') {\n const named = this._proxyNames.get(entry.meta.name);\n const inScope = named && named.get(entry.meta.componentId);\n if (inScope) {\n inScope.delete(nodeId);\n if (inScope.size === 0) named.delete(entry.meta.componentId);\n if (named.size === 0) this._proxyNames.delete(entry.meta.name);\n }\n }\n this._pollRemove(nodeId);\n this._sweepRemove(nodeId);\n this._pollDirty.delete(nodeId);\n this._reactiveNodes.delete(nodeId);\n this._reactiveProxies.delete(nodeId);\n this._stateSnapshots.delete(nodeId);\n if (this._stateSnapshotStrs) this._stateSnapshotStrs.delete(nodeId);\n this._pollMeta.delete(nodeId);\n this._lastSnapshotSize.delete(nodeId);\n },\n\n // A component instance or a module scope that is still live.\n _scopeLive(id) {\n return this._instances.has(id) || this._modules.has(id);\n },\n\n _scopeFile(id) {\n const scope = this._instances.get(id) || this._modules.get(id);\n return scope ? scope.file : '';\n },\n\n _enterModule(file) {\n this._moduleFile = file;\n // a module body that throws (or awaits) never reaches _leaveModule\n queueMicrotask(() => {\n if (this._moduleFile === file) this._moduleFile = null;\n });\n },\n\n _leaveModule() {\n this._moduleFile = null;\n },\n\n trackModuleSignal(kind, target, name) {\n const file = this._moduleFile;\n let id = this._moduleByFile.get(file);\n if (id === undefined) {\n id = this._nextId++;\n const base = file.split('/').pop() || file;\n this._modules.set(id, { id, file, name: base, kind: 'module' });\n this._moduleByFile.set(file, id);\n }\n if (kind === 'proxy') this.trackProxy(target, name, id, null);\n else if (kind === 'derived') this.trackDerived(target, name, id, null);\n else this.trackState(target, name, id, null);\n },\n\n // A node is live while its signal is reachable, its component is mounted,\n // and the effect it was created in (an {#each} item, an effect run) has\n // not been destroyed. Svelte nulls effect.fn when it destroys an effect\n // (internal/client destroy_effect), which is checked instead of the\n // internal DESTROYED flag value. Returns the signal or null.\n _liveSignal(nodeId) {\n const entry = this._reactiveNodes.get(nodeId);\n if (!entry) return null;\n const signal = entry.signal.deref();\n if (signal && this._scopeLive(entry.meta.componentId) && this._ownerAlive(entry)) {\n if (!entry.effect) return signal;\n // a bound effect is destroyed when Svelte clears its callback\n if (signal.fn !== null) return signal;\n }\n this._forgetNode(nodeId);\n return null;\n },\n\n _ownerAlive(entry) {\n if (!entry.owner) return true;\n const owner = entry.owner.deref();\n return !!owner && owner.fn !== null;\n },\n\n _sweepAdd(nodeId) {\n if (this._sweepIndex.has(nodeId)) return;\n this._sweepIndex.set(nodeId, this._sweepIds.length);\n this._sweepIds.push(nodeId);\n },\n\n _sweepRemove(nodeId) {\n const i = this._sweepIndex.get(nodeId);\n if (i === undefined) return;\n const ids = this._sweepIds;\n const last = ids.pop();\n this._sweepIndex.delete(nodeId);\n if (i < ids.length) {\n ids[i] = last;\n this._sweepIndex.set(last, i);\n }\n },\n\n // Liveness of up to \\`max\\` nodes, continuing from a cursor (each poll\n // tick): nodes of destroyed {#each} items / effect runs leave the counts\n // and the graph without waiting for a graph request or GC.\n _sweepNodes(max) {\n const ids = this._sweepIds;\n for (let n = 0; n < max && ids.length > 0; n++) {\n if (this._sweepCursor >= ids.length) this._sweepCursor = 0;\n const nodeId = ids[this._sweepCursor];\n // a forgotten node's slot is refilled by the last id: re-check it\n if (this._liveSignal(nodeId)) this._sweepCursor++;\n }\n },\n\n // Unique node id for a signal: componentId:name, or componentId:name#k\n // when this instance already holds a live node of that name for another\n // signal. The same signal (re-tagged) keeps its id.\n _nodeIdFor(identity, byIdentity, componentId, name) {\n const known = byIdentity.get(identity);\n if (known !== undefined && this._reactiveNodes.has(known)) return known;\n const base = componentId + ':' + name;\n if (!this._reactiveNodes.has(base) || !this._liveSignal(base)) return base;\n let seq = this._nameSeq.get(componentId);\n if (!seq) {\n seq = new Map();\n this._nameSeq.set(componentId, seq);\n }\n let k = seq.get(name) || 1;\n let id;\n do {\n k++;\n id = base + '#' + k;\n } while (this._reactiveNodes.has(id) && this._liveSignal(id));\n seq.set(name, k);\n return id;\n },\n\n _registerNode(nodeId, componentId, type, name, signalRef, owner, extra) {\n this._trackNodeCount(nodeId, componentId, type);\n const entry = {\n signal: signalRef,\n owner: owner ? new WeakRef(owner) : null,\n meta: { id: nodeId, type, name, componentId, componentFile: this._scopeFile(componentId) },\n };\n if (extra) Object.assign(entry, extra);\n this._reactiveNodes.set(nodeId, entry);\n this._indexNode(nodeId, componentId);\n this._sweepAdd(nodeId);\n return entry;\n },\n\n _indexNode(nodeId, componentId) {\n let set = this._nodesByComponent.get(componentId);\n if (!set) {\n set = new Set();\n this._nodesByComponent.set(componentId, set);\n }\n set.add(nodeId);\n },\n\n _pollAdd(nodeId) {\n if (this._pollIndex.has(nodeId)) return;\n if (!this._stateSnapshots.has(nodeId)) this._unseeded.add(nodeId);\n this._pollIndex.set(nodeId, this._pollIds.length);\n this._pollIds.push(nodeId);\n },\n\n // O(1): the last id takes the removed slot. If that slot is behind the\n // cursor, the moved id is visited in the next sweep instead of this one\n // (still visited within a bounded number of ticks).\n // Before a track* call replaces/creates nodeId: move the count from the\n // previous registration (same name re-tracked) to the new one.\n _trackNodeCount(nodeId, componentId, type) {\n const prev = this._reactiveNodes.get(nodeId);\n if (prev) this._countNode(prev.meta.componentId, prev.meta.type, -1);\n this._countNode(componentId, type, 1);\n },\n\n _countNode(componentId, type, d) {\n const kind = type === 'derived' || type === 'effect' ? type : 'state';\n let c = this._nodeCounts.get(componentId);\n if (!c) {\n if (d < 0) return;\n c = { state: 0, derived: 0, effect: 0 };\n this._nodeCounts.set(componentId, c);\n }\n c[kind] += d;\n this._nodeTotals[kind] += d;\n if (c.state + c.derived + c.effect <= 0) this._nodeCounts.delete(componentId);\n },\n\n _bucket() {\n const sec = Math.floor(performance.now() / 1000);\n const slot = ((sec % 60) + 60) % 60;\n let b = this._activity[slot];\n if (!b || b.second !== sec) {\n b = { second: sec, sampledMs: 0, rows: new Map() };\n this._activity[slot] = b;\n }\n return b;\n },\n\n _activityRow(componentId) {\n const rows = this._bucket().rows;\n let r = rows.get(componentId);\n if (!r) {\n r = { changes: 0, renders: 0, renderMs: 0 };\n rows.set(componentId, r);\n }\n return r;\n },\n\n _pollRemove(nodeId) {\n const i = this._pollIndex.get(nodeId);\n if (i === undefined) return;\n this._unseeded.delete(nodeId);\n const ids = this._pollIds;\n const last = ids.pop();\n this._pollIndex.delete(nodeId);\n if (i < ids.length) {\n ids[i] = last;\n this._pollIndex.set(last, i);\n }\n },\n\n _removeChildren(parentId) {\n const parent = this._instances.get(parentId);\n if (!parent) return;\n for (const childId of [...parent.children]) {\n this._removeChildren(childId);\n this._cleanupComponent(childId);\n }\n },\n\n // Full-list pushes are throttled, not debounced: a pending timer is not\n // reset, so continuous churn still produces updates (a debounce would\n // starve), and the interval adapts to the last push's cost so a 10 000+\n // instance app can't spend its main thread serializing (review P3):\n // max(min, 20 x last send ms, 1 s when the last payload exceeded ~1 MB).\n _sendInterval(cost, min) {\n return Math.max(min, 20 * cost.ms, cost.bytes > 1000000 ? 1000 : 0);\n },\n\n _scheduleUpdate() {\n if (!this._active || this._debounceTimer) return;\n this._debounceTimer = setTimeout(() => {\n this._debounceTimer = null;\n this._sendUpdate();\n }, this._sendInterval(this._componentsCost, 100));\n },\n\n // components push (§6.5). Full form { epoch, components } replaces the\n // server's tree for this epoch: sent on activation, when the server does\n // not advertise componentDeltas, as a periodic checkpoint, or when the\n // delta would be larger than the tree. Otherwise the delta form\n // { epoch, added, removed } (removed ids first, ≤ 2 000 entries per\n // message, added in registration order = parents first).\n _sendUpdate(forceFull) {\n // Nobody watching: keep the registry, skip the O(N) payload. A full\n // snapshot is sent on activation (§6.3).\n if (!this._active) return;\n const t0 = performance.now();\n const CHUNK = 2000;\n const CHECKPOINT_MS = 30000;\n const pending = this._pendingAdded.size + this._pendingRemoved.size;\n const full =\n forceFull ||\n !this._componentDeltas ||\n t0 - this._lastFullAt >= CHECKPOINT_MS ||\n pending > this._instances.size;\n const toEntry = (instance) => ({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n });\n let bytes = 0;\n const msgs = [];\n if (full) {\n const components = [];\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push(toEntry(instance));\n bytes += instance.file.length + instance.name.length + 72;\n }\n }\n msgs.push({ epoch: this._epoch, reset: true, components });\n this._lastFullAt = t0;\n } else if (pending > 0) {\n const removed = [...this._pendingRemoved];\n const added = [];\n for (const id of this._pendingAdded) {\n const instance = this._instances.get(id);\n if (instance && instance.mounted) {\n added.push(toEntry(instance));\n bytes += instance.file.length + instance.name.length + 72;\n }\n }\n bytes += removed.length * 8;\n for (let r = 0; r < removed.length; r += CHUNK) {\n msgs.push({ epoch: this._epoch, added: [], removed: removed.slice(r, r + CHUNK) });\n }\n for (let a = 0; a < added.length; a += CHUNK) {\n msgs.push({ epoch: this._epoch, added: added.slice(a, a + CHUNK), removed: [] });\n }\n }\n this._pendingAdded.clear();\n this._pendingRemoved.clear();\n if (import.meta.hot) {\n for (const msg of msgs) import.meta.hot.send('svelte-devtools:components', msg);\n }\n this._componentsCost = { ms: performance.now() - t0, bytes };\n },\n\n getTree() {\n const components = [];\n for (const [, instance] of this._instances) {\n if (instance.mounted) {\n components.push({\n id: instance.id,\n file: instance.file,\n name: instance.name,\n parentId: instance.parentId,\n mounted: instance.mounted,\n });\n }\n }\n return components;\n },\n\n // --- Phase 2: Render Profiling ---\n\n startInit(id) {\n this._initStartTimes.set(id, performance.now());\n },\n\n endInit(id) {\n const start = this._initStartTimes.get(id);\n if (start === undefined) return;\n const initTime = performance.now() - start;\n this._initStartTimes.delete(id);\n const instance = this._instances.get(id);\n if (!instance) return;\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime,\n renderCount: 0,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n });\n this._scheduleProfileUpdate();\n },\n\n recordRender(id) {\n const profile = this._profiles.get(id);\n if (!profile) {\n const instance = this._instances.get(id);\n if (!instance) return;\n this._profiles.set(id, {\n componentId: id,\n file: instance.file,\n name: instance.name,\n initTime: 0,\n renderCount: 1,\n totalRenderTime: 0,\n lastRenderTime: 0,\n lastRenderAt: Date.now(),\n });\n } else {\n profile.renderCount++;\n profile.lastRenderAt = Date.now();\n }\n this._activityRow(id).renders++;\n this._scheduleProfileUpdate();\n },\n\n recordRenderTime(id, duration) {\n const profile = this._profiles.get(id);\n if (profile) {\n profile.totalRenderTime += duration;\n profile.lastRenderTime = duration;\n this._activityRow(id).renderMs += duration;\n }\n },\n\n // Profiles push (review P-1 Option A; contract in\n // docs/performance-status.md). Throttled like components, but the floor\n // grows with the payload: every push carries the whole retained map, so\n // a large app coalesces bursts instead of resending ~1 MB twice a second.\n // Hard cap 2 s (contract R6): a slow serialization must not stretch the\n // latency beyond it.\n _profileInterval() {\n const cost = this._profilesCost;\n return Math.min(\n 2000,\n Math.max(500, 20 * cost.ms, cost.bytes > 1000000 ? 2000 : cost.bytes > 250000 ? 1000 : 0),\n );\n },\n\n _scheduleProfileUpdate() {\n if (!this._active || this._profileDebounceTimer) return;\n this._profileDebounceTimer = setTimeout(() => {\n this._profileDebounceTimer = null;\n this._sendProfileUpdate();\n }, this._profileInterval());\n },\n\n // Also the forced path (activation / resync): a pending throttled push is\n // cancelled so the same state is not sent twice.\n _sendProfileUpdate() {\n if (this._profileDebounceTimer) {\n clearTimeout(this._profileDebounceTimer);\n this._profileDebounceTimer = null;\n }\n if (!this._active) return;\n const t0 = performance.now();\n const all = Array.from(this._profiles.values());\n // Exactly what the collector retains: its tail, in the same order.\n const profiles = all.length > this._profileCap ? all.slice(all.length - this._profileCap) : all;\n if (import.meta.hot) {\n // total = all retained profiles; the message carries the newest-mounted\n // tail (§6.7 J IA1 capture policy 'newest-mounted').\n import.meta.hot.send('svelte-devtools:profiles', { epoch: this._epoch, profiles, total: all.length });\n }\n // Payload size from a small sample (entries differ mainly by file path).\n const k = Math.min(8, profiles.length);\n let sampled = 0;\n for (let i = 0; i < k; i++) sampled += JSON.stringify(profiles[i]).length;\n const bytes = k > 0 ? Math.round((sampled / k) * profiles.length) : 0;\n this._profilesCost = { ms: performance.now() - t0, bytes };\n },\n\n getProfiles() {\n return Array.from(this._profiles.values());\n },\n\n resetProfiles() {\n this._profiles.clear();\n this._scheduleProfileUpdate();\n },\n\n // --- Phase 2: Reactive Graph Tracking ---\n\n // \\`owner\\` (optional): the effect active when the signal was created; the\n // node dies with it (an {#each} item's {@const}, a class instance created\n // in an effect run).\n trackState(signal, name, componentId, owner) {\n const nodeId = this._nodeIdFor(signal, this._idBySignal, componentId, name);\n this._registerNode(nodeId, componentId, 'state', name, new WeakRef(signal), owner);\n this._idBySignal.set(signal, nodeId);\n this._nameProxyRoot(nodeId, name, componentId);\n this._pollAdd(nodeId);\n },\n\n trackProxy(proxy, name, componentId, owner) {\n const nodeId = this._nodeIdFor(proxy, this._idByProxy, componentId, name);\n this._reactiveProxies.set(nodeId, new WeakRef(proxy));\n // The proxy itself stays weakly held (_reactiveProxies). The marker is\n // held strongly so the node is not GC-dropped while the component lives;\n // _cleanupComponent removes it on unmount.\n const marker = { v: '(proxy)', _isProxy: true };\n this._registerNode(nodeId, componentId, 'state', name, { deref: () => marker }, owner);\n this._idBySignal.set(marker, nodeId);\n this._idByProxy.set(proxy, nodeId);\n this._nameProxyRoot(nodeId, name, componentId);\n this._pollAdd(nodeId);\n },\n\n trackDerived(signal, name, componentId, owner) {\n const nodeId = this._nodeIdFor(signal, this._idBySignal, componentId, name);\n this._registerNode(nodeId, componentId, 'derived', name, new WeakRef(signal), owner);\n this._idBySignal.set(signal, nodeId);\n },\n\n // A user effect object (already created). Kept for callers that have one.\n trackEffect(effect, name, componentId) {\n const nodeId = componentId + ':' + name;\n const target = effect || { v: undefined, _isEffect: true };\n this._registerNode(nodeId, componentId, 'effect', name, effect ? new WeakRef(target) : { deref: () => target });\n this._idBySignal.set(target, nodeId);\n return effect;\n },\n\n // $effect / $effect.pre being created now (the wrapper). The effect object\n // may not exist yet (deferred to mount): the node holds a placeholder\n // until bindEffect() is called on the effect's first run. kind: 'effect'\n // | 'effect_pre'; names are effect_1, effect_pre_1, ... per component.\n trackUserEffect(kind, componentId, owner) {\n let seq = this._effectSeq.get(componentId);\n if (!seq) {\n seq = { effect: 0, effect_pre: 0 };\n this._effectSeq.set(componentId, seq);\n }\n const name = kind + '_' + ++seq[kind];\n const nodeId = componentId + ':' + name;\n const placeholder = { v: undefined, _isEffect: true };\n this._registerNode(nodeId, componentId, 'effect', name, { deref: () => placeholder }, owner);\n return nodeId;\n },\n\n bindEffect(nodeId, effect) {\n const entry = nodeId !== null && this._reactiveNodes.get(nodeId);\n if (!entry || !effect || typeof effect !== 'object') return;\n entry.signal = new WeakRef(effect);\n entry.effect = true;\n this._idBySignal.set(effect, nodeId);\n },\n\n // The component's mount hook effect (the wrapper's, created at pop): its\n // parent is the effect the component's markup effects were created in.\n setComponentEffect(id, effect) {\n const instance = this._instances.get(id);\n if (instance) instance.hook = new WeakRef(effect);\n },\n\n // Markup effects of a component: the effects of its template\n // (template_effect, {#if}/{#each}/... blocks, <svelte:head>), i.e. the\n // effects under the hook's parent created in the component's context\n // (effect.ctx), without descending into other components or the\n // tracked $effect nodes. Svelte links child effects via first/next.\n _markupEffects(id) {\n const instance = this._instances.get(id);\n const hook = instance && instance.hook && instance.hook.deref();\n if (!hook || !hook.ctx || !hook.parent) return [];\n const ctx = hook.ctx;\n const out = [];\n const stack = [];\n for (let e = hook.parent.first; e; e = e.next) stack.push(e);\n while (stack.length) {\n const e = stack.pop();\n if (e === hook || e.ctx !== ctx) continue;\n if (e.deps && !this._idBySignal.has(e)) out.push(e);\n for (let c = e.first; c; c = c.next) stack.push(c);\n }\n return out;\n },\n\n // The tracked node a proxy's property source belongs to. Svelte (dev)\n // labels a proxy's sources after the proxy's path ('todos[0].text',\n // 'cart.items.length', 'todos version'); the root name is a $state node\n // name. Many live nodes may share the name (one per instance), so the\n // candidates are looked up per scope: the reader's component, then its\n // ancestors (props flow down), then module scopes, then all — each\n // narrowed by the source's value at that path (identity for objects).\n // Cost O(label + ancestry depth) for the common cases. null when\n // unresolved.\n _sourceOwner(source, readerCid, liveSignal) {\n const label = source.label;\n if (typeof label !== 'string' || this._proxyNames.size === 0) return null;\n let named = null;\n let rest = '';\n for (let i = label.length; i > 0; i--) {\n const ch = i === label.length ? '' : label[i];\n if (ch !== '' && ch !== '.' && ch !== '[' && ch !== ' ') continue;\n named = this._proxyNames.get(label.slice(0, i));\n if (named) {\n rest = label.slice(i);\n break;\n }\n }\n if (!named) return null;\n let path;\n // live candidates whose value at the source's path is the source's\n // value; without a property path (' version'), all live candidates\n const fits = (ids) => {\n const live = [...ids].filter((id) => liveSignal(id));\n if (live.length === 0) return live;\n if (path === undefined) path = this._labelPath(rest);\n if (!path) return live;\n const v = source.v;\n return live.filter((id) => {\n const at = this._valueAt(this._rootValue(id), path);\n return at !== __NO_VALUE && (Object.is(at, v) || (typeof v === 'symbol' && at === undefined));\n });\n };\n const scopes = [];\n for (let cid = readerCid; cid !== null && cid !== undefined; ) {\n scopes.push(cid);\n const instance = this._instances.get(cid);\n cid = instance ? instance.parentId : null;\n }\n for (const cid of named.keys()) if (this._modules.has(cid)) scopes.push(cid);\n for (const cid of scopes) {\n const ids = named.get(cid);\n const found = ids ? fits(ids) : [];\n if (found.length > 0) return found[0];\n }\n // not in the reader's ancestry or a module: any matching node, else the\n // nearest live one by name\n const all = [];\n for (const ids of named.values()) for (const id of ids) all.push(id);\n const found = fits(all);\n if (found.length > 0) return found[0];\n for (const cid of scopes) for (const id of named.get(cid) || []) if (liveSignal(id)) return id;\n return all.find((id) => liveSignal(id)) || null;\n },\n\n // '.items[0].text' -> ['items', '0', 'text']; null for ' version' and\n // anything else that is not a property path.\n _labelPath(rest) {\n const path = [];\n const re = /\\\\.([A-Za-z_$][\\\\w$]*)|\\\\[(\\\\d+)\\\\]|\\\\['((?:[^'\\\\\\\\]|\\\\\\\\.)*)'\\\\]/y;\n let m;\n while (re.lastIndex < rest.length && (m = re.exec(rest))) path.push(m[1] ?? m[2] ?? m[3]);\n return re.lastIndex === rest.length || rest.length === 0 ? path : null;\n },\n\n // Own-property walk (getOwnPropertyDescriptor does not create sources on\n // a Svelte proxy, unlike reading a missing property).\n _valueAt(obj, path) {\n let v = obj;\n for (const key of path) {\n if (v === null || (typeof v !== 'object' && typeof v !== 'function')) return __NO_VALUE;\n let d;\n try { d = Object.getOwnPropertyDescriptor(v, key); } catch { return __NO_VALUE; }\n if (!d) return __NO_VALUE;\n v = 'value' in d ? d.value : __NO_VALUE;\n if (v === __NO_VALUE) return v;\n }\n return v;\n },\n\n _nameProxyRoot(nodeId, name, componentId) {\n let named = this._proxyNames.get(name);\n if (!named) {\n named = new Map();\n this._proxyNames.set(name, named);\n }\n let inScope = named.get(componentId);\n if (!inScope) {\n inScope = new Set();\n named.set(componentId, inScope);\n }\n inScope.add(nodeId);\n },\n\n // The proxy a $state node holds now (tag_proxy: the proxy itself; a\n // state signal: its current value), or undefined.\n _rootValue(nodeId) {\n const proxy = this._reactiveProxies.get(nodeId);\n if (proxy) return proxy.deref();\n const signal = this._reactiveNodes.get(nodeId)?.signal.deref();\n return signal ? signal.v : undefined;\n },\n\n // A component whose init threw (the wrapper unwinds its stack): it never\n // mounted and never will, so it leaves the tree and the init stack.\n abortInit(id) {\n const idx = this._stack.indexOf(id);\n if (idx !== -1) this._stack.splice(idx, 1);\n const instance = this._instances.get(id);\n if (!instance) return;\n if (instance.parentId !== null) {\n const parent = this._instances.get(instance.parentId);\n if (parent) parent.children.delete(id);\n }\n this._removeChildren(id);\n this._cleanupComponent(id);\n this._scheduleUpdate();\n },\n\n _graphNode(nodeId, entry, signal) {\n const node = { ...entry.meta };\n if (signal._isProxy) {\n const proxy = this._reactiveProxies.get(nodeId)?.deref();\n if (proxy) {\n try {\n node.value = Array.isArray(proxy) ? '[' + proxy.length + ']' : '{' + Object.keys(proxy).length + '}';\n } catch { node.value = '(proxy)'; }\n }\n } else if (node.type === 'derived' && typeof signal.v === 'symbol') {\n // Svelte computes a derived lazily: until something reads it, v is\n // the UNINITIALIZED marker (a symbol)\n node.unevaluated = true;\n } else if (node.type !== 'effect' && signal.v !== undefined && typeof signal.v !== 'symbol') {\n try {\n const v = signal.v;\n if (typeof v === 'number' || typeof v === 'string' || typeof v === 'boolean' || v === null) {\n node.value = v;\n } else {\n node.value = '(object)';\n }\n } catch { /* ignore */ }\n }\n return node;\n },\n\n // Reactive graph (§6.7 A/D). Caps are applied while building: past\n // maxNodes no node objects are created and only edges whose endpoints\n // are both included are emitted (the rest are counted in edgesOmitted).\n // - scoped (componentId): that component's nodes plus the tracked nodes\n // directly connected to them (via deps / reactions through untracked\n // intermediates). Dependencies are resolved through _idBySignal, so\n // the cost is O(scope + neighbours), not O(all nodes). The walk is\n // completed even past the cap, so total.nodes/edges are exact.\n // - global: nodes in registration order up to maxNodes ('global-head'),\n // with their incoming dependency edges. Nodes past the cap are not\n // dereferenced; total.nodes is the registered count (may include\n // nodes whose signal was already collected, nodesKind 'registered')\n // and total.edges is null when the walk stopped early (not guessed).\n // Template consumers: the compiler turns every dynamic part of the markup\n // ({expr}, attributes, {#if}/{#each}/{#key}/{#await} conditions,\n // <svelte:head>) into effects that are not tracked one by one. A read\n // from such an effect is reported as an edge to the synthetic node\n // '<componentId>:(template)' (type 'template') of the component the\n // effect belongs to (effect.ctx), so a value only the markup reads is\n // not shown without readers.\n getReactiveGraph(componentId, caps) {\n const scoped = componentId !== undefined && componentId !== null;\n const maxNodes = this._graphCap(caps && caps.maxNodes, 5000);\n const maxEdges = this._graphCap(caps && caps.maxEdges, 20000);\n const live = new Map();\n // Live signal of a tracked node, or null (forgets dead / unmounted nodes).\n const liveSignal = (nodeId) => {\n if (live.has(nodeId)) return live.get(nodeId);\n const signal = this._liveSignal(nodeId);\n live.set(nodeId, signal);\n return signal;\n };\n const idOf = (dep) => {\n const id = this._idBySignal.get(dep);\n return id !== undefined && liveSignal(id) === dep ? id : null;\n };\n // Synthetic template nodes reached in this build: id -> componentId.\n const templates = new Map();\n // Template node of an untracked effect (no reactions: not a derived),\n // or null when its component is unknown / unmounted.\n const templateOf = (effect) => {\n if (!effect || 'reactions' in effect || !effect.ctx) return null;\n const cid = this._idByContext.get(effect.ctx);\n if (cid === undefined || !this._instances.has(cid)) return null;\n const id = cid + ':(template)';\n templates.set(id, cid);\n return id;\n };\n\n const included = new Set();\n const seen = new Set();\n const edges = [];\n const edgeSet = new Set();\n let edgesOmitted = 0;\n let truncated = false;\n const see = (id) => {\n seen.add(id);\n if (!included.has(id) && included.size < maxNodes) included.add(id);\n return included.has(id);\n };\n const addEdge = (from, to) => {\n const key = from + '>' + to;\n if (from === to || edgeSet.has(key)) return;\n edgeSet.add(key);\n const inFrom = see(from);\n const inTo = see(to);\n if (inFrom && inTo && edges.length < maxEdges) edges.push({ from, to });\n else edgesOmitted++;\n };\n // Walk a signal's neighbours (deps or reactions) through untracked\n // intermediates until tracked nodes are reached. onTemplate (reactions\n // only) receives the template node of each untracked effect reached.\n // On the deps side an untracked leaf source (a proxy's property) is\n // resolved to its proxy's node (readerCid: the reading component).\n // nodeId -> dependencies on signals devtools does not track (created\n // in node_modules, e.g. SvelteKit's page state, or outside any\n // component/module body): reported so such a node is not \"isolated\"\n const untracked = new Map();\n const walk = (start, field, onHit, onTemplate, readerCid, onUntracked) => {\n if (!start) return;\n const visited = new Set();\n const queue = [...start];\n // Index cursor instead of queue.shift(): shift is O(queue) per pop.\n for (let qi = 0; qi < queue.length; qi++) {\n const dep = queue[qi];\n if (!dep || visited.has(dep)) continue;\n visited.add(dep);\n const id = idOf(dep);\n if (id) {\n if (onHit) onHit(id);\n } else if (dep[field]) {\n for (const d of dep[field]) queue.push(d);\n } else if (onTemplate) {\n const t = templateOf(dep);\n if (t) onTemplate(t);\n } else if (field === 'deps' && onHit && !('fn' in dep)) {\n const owner = this._sourceOwner(dep, readerCid, liveSignal);\n if (owner) onHit(owner);\n else if (onUntracked) onUntracked();\n }\n }\n };\n const nodeCid = (nodeId) => this._reactiveNodes.get(nodeId).meta.componentId;\n const countUntracked = (nodeId) => () => untracked.set(nodeId, (untracked.get(nodeId) || 0) + 1);\n // Reads of a component's markup effects: edges into its template node\n // (filter: keep only edges from these node ids, for neighbours).\n const markupEdges = (cid, filter) => {\n const effects = this._markupEffects(cid);\n if (effects.length === 0) return;\n const t = cid + ':(template)';\n for (const effect of effects) {\n walk(effect.deps, 'deps', (id) => {\n if (filter && !filter(id)) return;\n templates.set(t, cid);\n addEdge(id, t);\n }, null, cid);\n }\n };\n\n let totalNodes = 0;\n let totalEdges = null;\n if (scoped) {\n for (const nodeId of [...(this._nodesByComponent.get(componentId) || [])]) {\n const signal = liveSignal(nodeId);\n if (!signal) continue;\n see(nodeId);\n walk(signal.deps, 'deps', (depId) => addEdge(depId, nodeId), null, componentId, countUntracked(nodeId));\n const toReader = (rId) => addEdge(nodeId, rId);\n walk(signal.reactions, 'reactions', toReader, toReader);\n }\n if (this._instances.has(componentId)) markupEdges(componentId, null);\n // Readers in direct children (props): a proxy has no reactions list\n // of its own, so its readers are found from their dependencies.\n const own = (id) => nodeCid(id) === componentId;\n const instance = this._instances.get(componentId);\n for (const child of instance ? instance.children : []) {\n for (const nodeId of [...(this._nodesByComponent.get(child) || [])]) {\n const signal = liveSignal(nodeId);\n if (signal) walk(signal.deps, 'deps', (depId) => own(depId) && addEdge(depId, nodeId), null, child);\n }\n markupEdges(child, own);\n }\n totalNodes = seen.size;\n totalEdges = edgeSet.size;\n truncated = included.size < seen.size || edgesOmitted > 0;\n } else {\n let complete = true;\n for (const nodeId of [...this._reactiveNodes.keys()]) {\n if (included.size >= maxNodes && !included.has(nodeId)) {\n complete = false;\n break;\n }\n const signal = liveSignal(nodeId);\n if (!signal) continue;\n see(nodeId);\n walk(signal.deps, 'deps', (depId) => addEdge(depId, nodeId), null, nodeCid(nodeId), countUntracked(nodeId));\n // tracked readers are found from their own deps; only template\n // readers need the reactions side\n walk(signal.reactions, 'reactions', null, (t) => addEdge(nodeId, t));\n }\n if (complete) for (const cid of this._instances.keys()) markupEdges(cid, null);\n // registered count (+ template nodes reached), minus nodes found\n // dead while building\n totalNodes = this._reactiveNodes.size + templates.size;\n totalEdges = complete ? edgeSet.size : null;\n truncated = !complete || edgesOmitted > 0;\n }\n\n const nodes = [];\n for (const nodeId of included) {\n const cid = templates.get(nodeId);\n if (cid !== undefined) {\n const instance = this._instances.get(cid);\n nodes.push({ id: nodeId, type: 'template', name: '(template)', componentId: cid, componentFile: instance ? instance.file : '' });\n continue;\n }\n const signal = liveSignal(nodeId);\n if (!signal) continue;\n const node = this._graphNode(nodeId, this._reactiveNodes.get(nodeId), signal);\n if (untracked.has(nodeId)) node.untrackedDeps = untracked.get(nodeId);\n nodes.push(node);\n }\n return {\n scope: scoped ? componentId : null,\n nodes,\n edges,\n total: { nodes: totalNodes, nodesKind: 'registered', edges: totalEdges },\n truncated,\n edgesOmitted,\n policy: scoped ? 'scoped' : 'global-head',\n };\n },\n\n _graphCap(value, max) {\n const n = Math.floor(Number(value));\n return Number.isFinite(n) && n >= 1 ? Math.min(n, max) : max;\n },\n\n // Request (§6.7 A + review M1): { requestId?, epoch?, componentId?,\n // maxNodes?, maxEdges? }. A request for another page load (epoch) is not\n // answered by this one; the reply echoes requestId and epoch. An old\n // server sends {} → global graph with the default caps (= its LIMITS).\n sendReactiveGraph(request) {\n const req = request || {};\n if (req.epoch !== undefined && req.epoch !== null && req.epoch !== this._epoch) return;\n const cid = typeof req.componentId === 'number' ? req.componentId : null;\n const graph = this.getReactiveGraph(cid, { maxNodes: req.maxNodes, maxEdges: req.maxEdges });\n graph.epoch = this._epoch;\n // freshness (review): when this answer was built; caches keep it\n graph.computedAt = Date.now();\n if (req.requestId !== undefined) graph.requestId = req.requestId;\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:reactive-graph', graph);\n }\n },\n\n // Overview aggregate (§6.7 I/J). Built from the activity buckets of the\n // window (whole seconds: the current partial second plus the previous\n // ones, ceil(windowMs / 1000) buckets) — cost O(components active in the\n // window), no graph, no node scan. Rows rank by sampled changes, then\n // renders, then render ms; rows + other = total (components and nodes).\n getReactiveSummary(opts) {\n const o = opts || {};\n const clampInt = (v, lo, hi, d) => {\n const n = Math.floor(Number(v));\n return Number.isFinite(n) ? Math.min(hi, Math.max(lo, n)) : d;\n };\n const topK = clampInt(o.topK, 1, 200, 50);\n const windowMs = clampInt(o.windowMs, 1000, 60000, 10000);\n const nowSec = Math.floor(performance.now() / 1000);\n const agg = new Map();\n let sampledMs = 0;\n for (let k = 0; k < Math.ceil(windowMs / 1000); k++) {\n const sec = nowSec - k;\n const b = this._activity[((sec % 60) + 60) % 60];\n if (!b || b.second !== sec) continue;\n sampledMs += b.sampledMs;\n for (const [cid, r] of b.rows) {\n if (!this._scopeLive(cid)) continue;\n let a = agg.get(cid);\n if (!a) {\n a = { changes: 0, renders: 0, renderMs: 0 };\n agg.set(cid, a);\n }\n a.changes += r.changes;\n a.renders += r.renders;\n a.renderMs += r.renderMs;\n }\n }\n const ranked = [...agg].sort(\n (x, y) =>\n y[1].changes - x[1].changes || y[1].renders - x[1].renders || y[1].renderMs - x[1].renderMs || x[0] - y[0],\n );\n let rowNodes = 0;\n const rows = ranked.slice(0, topK).map(([cid, a]) => {\n const n = this._nodeCounts.get(cid) || { state: 0, derived: 0, effect: 0 };\n rowNodes += n.state + n.derived + n.effect;\n const row = {\n componentId: cid,\n file: this._scopeFile(cid),\n nodes: { state: n.state, derived: n.derived, effect: n.effect },\n changes: a.changes,\n renders: a.renders,\n renderMs: Math.round(a.renderMs * 1000) / 1000,\n };\n // module scope (shared .svelte.js state), not a component instance\n if (this._modules.has(cid)) row.kind = 'module';\n return row;\n });\n const t = this._nodeTotals;\n // module scopes count as rows like components (rows + other = total)\n const scopes = this._instances.size + this._modules.size;\n const until = Date.now();\n return {\n epoch: this._epoch,\n window: { ms: windowMs, since: until - windowMs, until, sampledActiveMs: Math.min(windowMs, sampledMs) },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: { total: scopes, withActivity: agg.size },\n rows,\n other: { components: scopes - rows.length, nodes: t.state + t.derived + t.effect - rowNodes },\n truncated: agg.size > topK,\n capabilities: { valueInspection: false, signalHistory: false, writeCause: false },\n // Seed coverage: changes of pending nodes are not observable yet.\n baseline: this._baselineInfo(),\n };\n },\n\n // Request { requestId?, epoch?, topK?, windowMs? } (same correlation as\n // the graph, review M1).\n sendReactiveSummary(request) {\n const req = request || {};\n if (req.epoch !== undefined && req.epoch !== null && req.epoch !== this._epoch) return;\n const summary = this.getReactiveSummary(req);\n if (req.requestId !== undefined) summary.requestId = req.requestId;\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:reactive-summary', summary);\n }\n },\n\n // --- Phase 3: State Timeline ---\n\n // Current value of a $state node: the signal value, or for tag_proxy\n // nodes (non-reassigned object/array state) the live proxy itself.\n // Returns a sentinel when the value can't be read.\n _readStateValue(nodeId, signal) {\n if (signal._isProxy) {\n const proxy = this._reactiveProxies.get(nodeId)?.deref();\n return proxy === undefined ? __NO_VALUE : proxy;\n }\n const v = signal.v;\n // Svelte's UNINITIALIZED marker is a symbol; functions aren't state data.\n return typeof v === 'symbol' || typeof v === 'function' ? __NO_VALUE : v;\n },\n\n // Runs every 200 ms in the user's app, so it must stay cheap regardless of\n // how much state the app holds (§6.7 D).\n // 1. Hint pass, time-sliced: at most HINT_NODES $state nodes per tick,\n // continuing from a cursor carried across ticks, so a full sweep over\n // n nodes takes ceil(n / HINT_NODES) ticks (_pollSweep.lastMs is the\n // measured sweep time = worst-case detection delay). Per node O(1):\n // primitives are compared directly and recorded at once; objects\n // whose reference or Svelte write version (wv) changed are added to\n // _pollDirty, which persists across ticks until serialized.\n // 2. Serialization work is limited to BUDGET_MS per tick (dirty nodes\n // carry over, nothing is dropped).\n // 3. In-place deep mutations (proxies don't bump an outer wv) are found by\n // time-based re-checks: each object is re-verified no earlier than\n // nextCheckAt = now + max(RECHECK_MS, 50 x its serialization cost),\n // paid from a DEEP_MS-per-tick credit, so the amortized cost is bounded\n // however many large states the app holds.\n // 4. Values serializing above MAX_SNAPSHOT_CHARS are kept as length+hash\n // (not the string) and appear in the timeline as a summary.\n // Writes between two visits of a node are observed as one change (the\n // timeline is a sample, policy 'sampled-200ms'; not counted as dropped).\n _pollStateValues(baseline) {\n const HINT_NODES = 4096;\n const SWEEP_NODES = 2048;\n const BUDGET_MS = 2;\n const DEEP_MS = 0.5;\n const now = performance.now();\n if (!baseline) {\n // nodes of destroyed {#each} items / effect runs leave the counts\n this._sweepNodes(SWEEP_NODES);\n this._deepCredit = Math.min(10 * DEEP_MS, (this._deepCredit || 0) + DEEP_MS);\n // this tick samples 200 ms of wall time (window.sampledActiveMs)\n const bucket = this._bucket();\n bucket.sampledMs = Math.min(1000, bucket.sampledMs + 200);\n }\n const ids = this._pollIds;\n const due = [];\n const limit = Math.min(HINT_NODES, ids.length);\n for (let visited = 0; visited < limit && ids.length > 0; visited++) {\n if (this._pollCursor >= ids.length) {\n this._pollCursor = 0;\n if (!baseline) {\n if (this._pollSweep.startedAt) this._pollSweep.lastMs = now - this._pollSweep.startedAt;\n this._pollSweep.startedAt = now;\n this._pollSweep.nodes = ids.length;\n }\n }\n if (!baseline && !this._pollSweep.startedAt) this._pollSweep.startedAt = now;\n const nodeId = ids[this._pollCursor];\n const entry = this._reactiveNodes.get(nodeId);\n if (!entry || entry.meta.type !== 'state') {\n // re-tracked as another type: drop from the poll list (slot reused)\n this._pollRemove(nodeId);\n continue;\n }\n if (!this._scopeLive(entry.meta.componentId)) {\n this._forgetNode(nodeId); // swaps the last id into this slot\n continue;\n }\n this._pollCursor++;\n const signal = entry.signal.deref();\n const value = signal ? this._readStateValue(nodeId, signal) : __NO_VALUE;\n if (value === __NO_VALUE) {\n // nothing readable (collected, uninitialized, function): not pending\n this._unseeded.delete(nodeId);\n continue;\n }\n if (value === null || typeof value !== 'object') {\n const had = this._stateSnapshots.has(nodeId);\n const prev = this._stateSnapshots.get(nodeId);\n if (had && Object.is(prev, value)) continue;\n // Forget the object key so object -> primitive -> same object again\n // is still recorded as a change.\n if (this._stateSnapshotStrs) this._stateSnapshotStrs.delete(nodeId);\n this._pollDirty.delete(nodeId);\n if (!had) {\n // first observation: seed only\n this._stateSnapshots.set(nodeId, value);\n this._unseeded.delete(nodeId);\n continue;\n }\n this._recordChange(nodeId, entry, prev, value, typeof value === 'string' ? 2 * value.length : 64);\n continue;\n }\n let meta = this._pollMeta.get(nodeId);\n if (!meta) {\n meta = { ref: undefined, wv: undefined, nextCheckAt: 0 };\n this._pollMeta.set(nodeId, meta);\n }\n if (meta.ref !== value || meta.wv !== signal.wv) this._pollDirty.add(nodeId);\n else if (now >= meta.nextCheckAt) due.push(nodeId);\n }\n const start = performance.now();\n for (const nodeId of this._pollDirty) {\n if (performance.now() - start > BUDGET_MS) return;\n this._pollDirty.delete(nodeId);\n this._serializeNode(nodeId, false);\n }\n for (const nodeId of due) {\n if (this._deepCredit <= 0 || performance.now() - start > BUDGET_MS) return;\n this._serializeNode(nodeId, true);\n }\n },\n\n // Activation (late consumer): nodes registered while inactive have no\n // seed yet, so a write before their first visit could not be seen as a\n // change. The first slice is seeded at activation instead of 200 ms later:\n // ONE normal pass (<= HINT_NODES nodes, the per-tick serialization budget;\n // the rest follow on the usual ticks). Seeds record nothing; readiness is\n // disclosed in the summary as baseline { complete, pendingNodes }.\n _pollBaseline() {\n this._baselining = true;\n try {\n this._pollStateValues(true);\n } catch { /* never break activation */ } finally {\n this._baselining = false;\n }\n },\n\n _serializeNode(nodeId, deep) {\n const MAX_SNAPSHOT_CHARS = 32768;\n const RECHECK_MS = 1000;\n const entry = this._reactiveNodes.get(nodeId);\n const meta = this._pollMeta.get(nodeId);\n if (!entry || !meta) return;\n const signal = entry.signal.deref();\n if (!signal) return;\n const value = this._readStateValue(nodeId, signal);\n if (value === __NO_VALUE || value === null || typeof value !== 'object') return;\n try {\n const t0 = performance.now();\n const str = JSON.stringify(value);\n const cost = performance.now() - t0;\n if (deep) this._deepCredit -= cost;\n meta.ref = value;\n meta.wv = signal.wv;\n meta.nextCheckAt = t0 + Math.max(RECHECK_MS, 50 * cost);\n // Small values keep the string (exact compare); large ones only a\n // length+hash so a 5 MB array doesn't pin 5 MB per node.\n const key = str === undefined ? '' : str.length > MAX_SNAPSHOT_CHARS ? str.length + ':' + __hash(str) : str;\n if (!this._stateSnapshotStrs) this._stateSnapshotStrs = new Map();\n const hadKey = this._stateSnapshotStrs.has(nodeId);\n if (hadKey && this._stateSnapshotStrs.get(nodeId) === key) return;\n this._stateSnapshotStrs.set(nodeId, key);\n const tooLarge = str !== undefined && str.length > MAX_SNAPSHOT_CHARS;\n const snapshot =\n str === undefined\n ? null\n : tooLarge\n ? '(object: ' + str.length + ' chars, too large to snapshot)'\n : JSON.parse(str);\n const size = typeof snapshot === 'string' ? 64 : str.length;\n if (!this._stateSnapshots.has(nodeId)) {\n // first observation: seed only (no entry, no counters)\n this._stateSnapshots.set(nodeId, snapshot);\n this._lastSnapshotSize.set(nodeId, size);\n this._unseeded.delete(nodeId);\n return;\n }\n if (tooLarge) this._valueTooLarge++;\n const prev = this._stateSnapshots.get(nodeId);\n this._recordChange(nodeId, entry, prev, snapshot, size + (this._lastSnapshotSize.get(nodeId) || 0));\n this._lastSnapshotSize.set(nodeId, size);\n } catch {\n // non-serializable (cycles, BigInt): never observable, so not pending\n this._unseeded.delete(nodeId);\n }\n },\n\n _recordChange(nodeId, entry, oldValue, newValue, approxBytes) {\n const change = {\n id: nodeId,\n name: entry.meta.name,\n componentFile: entry.meta.componentFile,\n oldValue,\n newValue,\n timestamp: Date.now(),\n };\n const bytes = (approxBytes || 64) + 192;\n // seq stays runtime-internal: the server assigns its own seq (§6.4).\n this._entryInfo.set(change, { seq: ++this._timelineSeq, bytes });\n this._stateTimeline.push(change);\n this._timelineBytes += bytes;\n // sampled change count (§6.7 J IA2): independent of the ring\n this._activityRow(entry.meta.componentId).changes++;\n this._stateSnapshots.set(nodeId, newValue);\n // The ring (_trimTimeline) is applied in bulk, not with one splice per\n // change (a poll tick can record thousands): before every read (each\n // push — with a hot channel and an active consumer, at least every 200\n // changes — the full snapshot, getStateTimeline() and clear), and here\n // once more than __TIMELINE_TRIM_AT entries are held or the byte budget\n // is exceeded, which bounds memory when nothing reads or pushes.\n if (this._stateTimeline.length > __TIMELINE_TRIM_AT || this._timelineBytes > __TIMELINE_BYTES) {\n this._trimTimeline();\n }\n this._scheduleTimelineUpdate();\n },\n\n // Ring: at most 500 entries and __TIMELINE_BYTES (the newest entry is\n // always kept). Removed entries that were never pushed are disclosed\n // as dropped (§6.7 C); pushed ones are already on the server.\n _trimTimeline() {\n const all = this._stateTimeline;\n let cut = 0;\n let bytesLeft = this._timelineBytes;\n while (cut < all.length - 1 && (all.length - cut > 500 || bytesLeft > __TIMELINE_BYTES)) {\n const info = this._entryInfo.get(all[cut]);\n const reason = all.length - cut > 500 ? 'runtime-count' : 'runtime-bytes';\n if (info.seq > this._pushedSeq) this._timelineDropped[reason]++;\n bytesLeft -= info.bytes;\n cut++;\n }\n if (cut > 0) {\n all.splice(0, cut);\n this._timelineBytes = bytesLeft;\n }\n },\n\n // Push (§6.7 C): a throttle, not a debounce — a pending timer is never\n // re-armed, so unsent entries leave within 300 ms of the first one even\n // under continuous change — plus an immediate flush once 200 entries\n // (one message) are unsent, since one poll tick can record thousands.\n _scheduleTimelineUpdate() {\n if (!this._active || this._baselining) return;\n if (this._timelineSeq - this._pushedSeq >= 200) {\n this._flushTimeline();\n return;\n }\n if (this._timelineDebounceTimer) return;\n this._timelineDebounceTimer = setTimeout(() => {\n this._timelineDebounceTimer = null;\n this._flushTimeline();\n }, 300);\n },\n\n _flushTimeline() {\n if (this._timelineDebounceTimer) {\n clearTimeout(this._timelineDebounceTimer);\n this._timelineDebounceTimer = null;\n }\n if (!import.meta.hot) return;\n for (const msg of this._timelineDeltas()) {\n import.meta.hot.send('svelte-devtools:state-timeline', msg);\n }\n },\n\n // Disclosure counters since the previous push, attached to (and reset\n // by) the next message: dropped [{ reason, count }] and valueTooLarge.\n _takeTimelineDisclosure(msg) {\n msg.baseline = this._baselineInfo();\n this._sentPendingNodes = msg.baseline.pendingNodes;\n const dropped = [];\n for (const reason of ['runtime-count', 'runtime-bytes']) {\n const count = this._timelineDropped[reason];\n if (count > 0) dropped.push({ reason, count });\n this._timelineDropped[reason] = 0;\n }\n if (dropped.length) msg.dropped = dropped;\n if (this._valueTooLarge > 0) msg.valueTooLarge = this._valueTooLarge;\n this._valueTooLarge = 0;\n return msg;\n },\n\n // Seed coverage (review B-2), on every state-timeline message and the\n // summary: pendingNodes = polled $state nodes without a first sample;\n // their writes are not observable yet.\n _baselineInfo() {\n return { complete: this._unseeded.size === 0, pendingNodes: this._unseeded.size };\n },\n\n _hasTimelineDisclosure() {\n return (\n this._sentPendingNodes !== this._unseeded.size ||\n this._timelineDropped['runtime-count'] > 0 ||\n this._timelineDropped['runtime-bytes'] > 0 ||\n this._valueTooLarge > 0\n );\n },\n\n // Delta push (docs/devframe-migration.md §6.4): only entries recorded\n // since the previous push, ≤ 200 per message, tagged with a per-page-load\n // epoch; reset after clearStateTimeline(). A message with no changes is\n // still sent when there is something to disclose (all unsent dropped).\n _timelineDeltas() {\n this._trimTimeline();\n const all = this._stateTimeline;\n let start = all.length;\n while (start > 0 && this._entryInfo.get(all[start - 1]).seq > this._pushedSeq) start--;\n const pending = all.slice(start);\n const msgs = [];\n const first = this._timelineReset || this._hasTimelineDisclosure();\n for (let i = 0; i < pending.length || (first && i === 0); i += 200) {\n const msg = { epoch: this._epoch, changes: pending.slice(i, i + 200) };\n if (i === 0 && this._timelineReset) msg.reset = true;\n if (i === 0) this._takeTimelineDisclosure(msg);\n else msg.baseline = this._baselineInfo();\n msgs.push(msg);\n }\n this._timelineReset = false;\n this._pushedSeq = this._timelineSeq;\n return msgs;\n },\n\n // Full buffer (reset: true) — reply to request-state-timeline and the\n // activation snapshot. Newest entries first up to __TIMELINE_BYTES, the\n // server's own buffer budget, so nothing is sent that it would drop.\n _timelineFull() {\n this._trimTimeline();\n const all = this._stateTimeline;\n let start = all.length;\n let bytes = 0;\n while (start > 0) {\n const size = this._entryInfo.get(all[start - 1]).bytes;\n if (bytes + size > __TIMELINE_BYTES && start < all.length) break;\n bytes += size;\n start--;\n }\n this._timelineReset = false;\n this._pushedSeq = this._timelineSeq;\n return this._takeTimelineDisclosure({ epoch: this._epoch, changes: all.slice(start), reset: true });\n },\n\n getStateTimeline() {\n this._trimTimeline();\n return this._stateTimeline;\n },\n\n clearStateTimeline() {\n // Ring first: unsent entries past the cap are disclosed as dropped,\n // exactly as if they had been removed when recorded.\n this._trimTimeline();\n this._stateTimeline = [];\n this._timelineBytes = 0;\n this._pushedSeq = this._timelineSeq;\n this._timelineReset = true;\n this._scheduleTimelineUpdate();\n },\n\n // --- FPS Monitoring ---\n // Uses requestAnimationFrame to measure frame rate with minimal overhead.\n // Only stores timestamps - no allocations per frame beyond a single array push.\n _fpsFrameTimes: [],\n\n _fpsLoop(gen) {\n if (gen !== this._fpsGen) return;\n this._fpsFrameTimes.push(performance.now());\n requestAnimationFrame(() => this._fpsLoop(gen));\n },\n\n _isVisible() {\n return typeof document === 'undefined' || document.visibilityState !== 'hidden';\n },\n\n _setSubscription(data) {\n const wasActive = this._active;\n this._active = !!(data && data.active);\n this._componentDeltas = !!(data && data.componentDeltas);\n if (!this._active) {\n this._pendingAdded.clear();\n this._pendingRemoved.clear();\n }\n // resync: the server holds no full base for this epoch (§6.5, review\n // C1), or we reconnected to a possibly restarted server.\n const resync = this._resync || !!(data && data.resync);\n this._resync = false;\n if (this._active && !wasActive) this._pollBaseline();\n if (this._active && (!wasActive || resync)) {\n // Collector state may be stale or empty (first activation, resync, or a\n // reconnect to a possibly restarted server): resend everything once, in\n // the order components -> profiles -> timeline(reset: true); the\n // reset push marks the activation snapshot complete (D4).\n this._sendUpdate(true);\n this._sendProfileUpdate();\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:state-timeline', this._timelineFull());\n }\n }\n this._syncSampling();\n },\n\n // Sampling (state poll + FPS) runs only while active AND the app tab is\n // visible.\n _syncSampling() {\n const want = this._active && this._isVisible();\n if (want && !this._sampling) {\n this._fpsFrameTimes = [];\n const gen = ++this._fpsGen;\n this._sampling = {\n poll: setInterval(() => {\n this._pollStateValues();\n // seed progress changed: push it even without changes (B-2)\n if (this._sentPendingNodes !== this._unseeded.size) this._scheduleTimelineUpdate();\n }, 200),\n fps: setInterval(() => { this._sampleFps(); }, 500),\n };\n requestAnimationFrame(() => this._fpsLoop(gen));\n } else if (!want && this._sampling) {\n clearInterval(this._sampling.poll);\n clearInterval(this._sampling.fps);\n this._sampling = null;\n this._fpsGen++;\n this._fpsFrameTimes = [];\n }\n },\n\n _sampleFps() {\n const now = performance.now();\n // Remove frame timestamps older than 1 second\n const cutoff = now - 1000;\n let i = 0;\n while (i < this._fpsFrameTimes.length && this._fpsFrameTimes[i] < cutoff) i++;\n if (i > 0) this._fpsFrameTimes.splice(0, i);\n const fps = this._fpsFrameTimes.length;\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:fps', { timestamp: Date.now(), fps });\n }\n }\n };\n\n window.__SVELTE_DEVTOOLS__ = __SVELTE_DT;\n\n // State polling and FPS sampling start on the server's subscription\n // message (§6.3) and pause while the app tab is hidden.\n if (typeof document !== 'undefined' && document.addEventListener) {\n document.addEventListener('visibilitychange', () => __SVELTE_DT._syncSampling());\n }\n\n // Phase 3: Capture runtime errors\n window.addEventListener('error', (event) => {\n if (import.meta.hot) {\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: event.message,\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n stack: event.error?.stack || '',\n timestamp: Date.now(),\n });\n }\n });\n window.addEventListener('unhandledrejection', (event) => {\n if (import.meta.hot) {\n const reason = event.reason;\n import.meta.hot.send('svelte-devtools:runtime-error', {\n message: reason?.message || String(reason),\n stack: reason?.stack || '',\n timestamp: Date.now(),\n });\n }\n });\n\n // Listen for reactive graph requests from server\n // Pull requests are answered regardless of the subscription state.\n if (import.meta.hot) {\n import.meta.hot.on('svelte-devtools:subscription', (data) => {\n __SVELTE_DT._setSubscription(data);\n });\n import.meta.hot.on('vite:ws:connect', () => {\n // The server may have restarted with an empty collector: the reply to\n // runtime-ready is treated as a fresh activation (full snapshot).\n __SVELTE_DT._resync = true;\n import.meta.hot.send('svelte-devtools:runtime-ready', {});\n });\n import.meta.hot.send('svelte-devtools:runtime-ready', {});\n import.meta.hot.on('svelte-devtools:request-reactive-graph', (data) => {\n __SVELTE_DT.sendReactiveGraph(data);\n });\n import.meta.hot.on('svelte-devtools:request-reactive-summary', (data) => {\n __SVELTE_DT.sendReactiveSummary(data);\n });\n import.meta.hot.on('svelte-devtools:request-state-timeline', () => {\n import.meta.hot.send('svelte-devtools:state-timeline', __SVELTE_DT._timelineFull());\n });\n import.meta.hot.on('svelte-devtools:clear-state-timeline', () => {\n __SVELTE_DT.clearStateTimeline();\n });\n }\n}\n`\n","import type {\n CaptureInfo,\n CaptureInfoMap,\n CompilerWarning,\n DropReason,\n ComponentInstance,\n FpsSample,\n LoadProfile,\n ReactiveGraph,\n ReactiveGraphRequest,\n ReactiveGraphResult,\n ReactiveGraphTotal,\n ReactiveSummary,\n ReactiveSummaryRequest,\n RenderProfile,\n RuntimeError,\n StateChange,\n StateTimelineDelta,\n StateTimelineEntry,\n DatasetVersions,\n TimelineBaseline,\n} from './types.js'\n\n// Defensive caps on runtime-supplied data: even though the runtime already\n// trims its own buffers, an out-of-spec or compromised runtime could hand us\n// unbounded payloads and inflate dev-server memory.\nexport const LIMITS = {\n liveComponents: 50000,\n renderProfiles: 5000,\n stateTimeline: 500,\n reactiveNodes: 5000,\n reactiveEdges: 20000,\n fpsSamples: 1200,\n runtimeErrors: 200,\n loadProfiles: 200,\n compilerWarnings: 500,\n} as const\n\n/** How long a pull request to the browser runtime may take before we answer from cache. */\nexport const RUNTIME_REQUEST_TIMEOUT = 1000\n\n/** A pull answered within this window is reused instead of asking the runtime again. */\nexport const PULL_FRESHNESS = 1000\n\n/** Byte budget (JSON length, measured once at ingest) for the server-side state timeline. */\nexport const STATE_TIMELINE_BYTES = 4 * 1024 * 1024\n\nexport type DatasetKey = keyof DatasetVersions\n\n// Timeline `seq` values come from one process-wide counter, seeded from the\n// clock: a cursor issued by an earlier collector in this process (inline or\n// config-file restart) is always below a newer collector's `timelineResetAt`,\n// and one from a previous process is too unless it issued more than 1 000\n// entries per millisecond of downtime (review D2).\nlet lastSeq = Date.now() * 1000\nconst nextSeq = () => ++lastSeq\n\n/** Epoch for runtimes that send payloads without an epoch. */\nconst LEGACY_EPOCH = '(legacy)'\n\n/** App page loads (tabs / reloads) whose component tree + profiles are kept, LRU. */\nexport const MAX_EPOCHS = 4\n\ninterface EpochState {\n /** Insertion order = registration order (parents first). */\n components: Map<number, ComponentInstance>\n /**\n * Ids of mounted instances not stored: beyond the cap, or whose parent\n * isn't stored (admitting them would show orphans). Ids only, so the total\n * and removals stay exact.\n */\n overflow: Set<number>\n /** A full components snapshot was applied, so deltas have a base. */\n hasBase: boolean\n profiles: RenderProfile[]\n /** Profiles the runtime holds before its tail cap (sent as `total`); `null` = unknown. */\n profilesTotal: number | null\n}\n\n/** Hot-channel event names shared with `runtime.ts` (stable contract, see docs/devframe-migration.md §6). */\nexport const HOT_EVENTS = {\n components: 'svelte-devtools:components',\n profiles: 'svelte-devtools:profiles',\n stateTimeline: 'svelte-devtools:state-timeline',\n fps: 'svelte-devtools:fps',\n runtimeError: 'svelte-devtools:runtime-error',\n reactiveGraph: 'svelte-devtools:reactive-graph',\n requestReactiveGraph: 'svelte-devtools:request-reactive-graph',\n /** server → runtime `{ requestId, epoch?, topK, windowMs }`; reply `reactiveSummary` (§6.7 I). */\n requestReactiveSummary: 'svelte-devtools:request-reactive-summary',\n reactiveSummary: 'svelte-devtools:reactive-summary',\n requestStateTimeline: 'svelte-devtools:request-state-timeline',\n clearStateTimeline: 'svelte-devtools:clear-state-timeline',\n /** runtime → server, once per page load: \"send me the current subscription state\". */\n runtimeReady: 'svelte-devtools:runtime-ready',\n /** server → runtime(s): `{ active: boolean }` — whether any consumer is watching. */\n subscription: 'svelte-devtools:subscription',\n} as const\n\n/** Keyed pull results kept for reuse / stale fallback (graph scopes, summaries), LRU. */\nconst MAX_CACHED_PULLS = 32\n\n/** Defaults and bounds for `get-reactive-summary` (§6.7 I). */\nexport const SUMMARY_DEFAULTS = {\n topK: 50,\n maxTopK: 200,\n windowMs: 10_000,\n minWindowMs: 1000,\n maxWindowMs: 60_000,\n} as const\n\nconst DROP_REASONS: readonly DropReason[] = [\n 'runtime-count',\n 'runtime-bytes',\n 'server-count',\n 'server-bytes',\n]\n\n/** An integer within [min, max], or `fallback` when absent / not a number. */\nfunction validBaseline(b: unknown): b is TimelineBaseline {\n const v = b as Partial<TimelineBaseline> | undefined\n return (\n !!v &&\n typeof v.complete === 'boolean' &&\n Number.isInteger(v.pendingNodes) &&\n (v.pendingNodes as number) >= 0\n )\n}\n\nfunction clampInt(value: unknown, min: number, max: number, fallback: number): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) return fallback\n return Math.min(max, Math.max(min, Math.trunc(value)))\n}\n\n/** A pull request waiting for the runtime's reply, matched by `requestId` (§6.7 A, M1). */\ninterface PendingPull {\n kind: 'graph' | 'summary'\n key: string\n epoch: string | null\n scope: number | null\n resolve: (value: ReactiveGraphResult | ReactiveSummary) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/** A consumer (DevTools UI tab, MCP agent) counts as watching until its lease expires. */\nexport const LEASE_TTL = 15_000\n\nexport interface HotClient {\n send(event: string, payload: unknown): void\n}\n\nexport interface HotChannel {\n send(event: string, payload: unknown): void\n on(event: string, listener: (payload: any, client: HotClient) => void): void\n off?(event: string, listener: (payload: any, client: HotClient) => void): void\n}\n\nexport interface CollectorHooks {\n onFpsSample?: (sample: FpsSample) => void\n onLoadProfile?: (profile: LoadProfile) => void\n}\n\nfunction tail<T>(arr: unknown, max: number): T[] {\n const list = Array.isArray(arr) ? (arr as T[]) : []\n return list.length > max ? list.slice(-max) : list\n}\n\nfunction head<T>(arr: unknown, max: number): T[] {\n const list = Array.isArray(arr) ? (arr as T[]) : []\n return list.length > max ? list.slice(0, max) : list\n}\n\n/**\n * Host-side store for everything the browser runtime and the instrumentation\n * transforms report. Independent of Vite and of devframe: the Vite plugin\n * feeds it, the devframe RPC layer and the MCP server read from it.\n */\nexport class Collector {\n // Component tree + render profiles are kept per app page load (`epoch`),\n // so several app tabs / a reload don't overwrite each other; the epoch that\n // pushed most recently is the one served (review D3, perf R-A8).\n private epochs = new Map<string, EpochState>()\n private servedEpoch: string | undefined\n private liveCache: ComponentInstance[] | undefined\n loadProfiles: LoadProfile[] = []\n reactiveGraph: ReactiveGraph = { nodes: [], edges: [] }\n compilerWarnings: CompilerWarning[] = []\n runtimeErrors: RuntimeError[] = []\n fpsSamples: FpsSample[] = []\n // Opaque change tokens drawn from the process-wide counter (like timeline\n // seqs): a restarted server's collector never reports a value a client saw\n // before, so \"unchanged version → skip refetch\" stays correct across\n // restarts (review B1).\n readonly versions: DatasetVersions = {\n components: nextSeq(),\n renderProfiles: nextSeq(),\n loadProfiles: nextSeq(),\n stateTimeline: nextSeq(),\n reactiveGraph: nextSeq(),\n errors: nextSeq(),\n fps: nextSeq(),\n }\n\n private bump(...keys: DatasetKey[]): void {\n for (const key of keys) this.versions[key] = nextSeq()\n }\n\n private timeline: StateTimelineEntry[] = []\n /** Parallel to `timeline`: JSON size and source epoch (app page load) of each entry. */\n private timelineSizes: number[] = []\n private timelineEpochs: string[] = []\n private timelineBytes = 0\n /** Newest seq issued by this collector (= the current cursor). */\n private timelineSeq = nextSeq()\n /** Cursor value at the last removal; older cursors must start over. */\n private timelineResetAt = this.timelineSeq\n /** Seq of the newest entry trimmed by the caps; cursors below it missed entries. */\n private timelineTrimmedAt = this.timelineSeq\n private lastPull = { stateTimeline: 0 }\n private inflight: { stateTimeline?: Promise<StateChange[]> } = {}\n\n // Keyed pulls (graph scopes, summaries; §6.7 A/I): each request carries a\n // requestId + the served epoch, and only the matching reply resolves it, so\n // one viewer never receives another viewer's scope (review G5, M1).\n private pulls = new Map<string, PendingPull>()\n private pullCache = new Map<\n string,\n { value: ReactiveGraphResult | ReactiveSummary; at: number }\n >()\n private pullInflight = new Map<string, Promise<ReactiveGraphResult | ReactiveSummary>>()\n private requestSeq = 0\n /** The most recent graph reply, for capture info. */\n private lastGraph: ReactiveGraphResult | undefined\n\n // Timeline losses per epoch, by reason; monotonic until the epoch is\n // evicted or the timeline is cleared (§6.7 B/C).\n private timelineDrops = new Map<string, Record<DropReason, number>>()\n /** Per epoch: whether the runtime has a first sample of every tracked $state yet. */\n private timelineBaseline = new Map<string, TimelineBaseline>()\n private timelineTooLarge = new Map<string, number>()\n // Items received since the last clear, for the ring datasets' totals.\n private received = { fps: 0, runtimeErrors: 0, loadProfiles: 0, compilerWarnings: 0 }\n\n private hot: HotChannel | undefined\n private detachHot: (() => void) | undefined\n private leases = new Map<string, number>()\n private snapshotWaiters: Array<() => void> = []\n private active = false\n private sweepTimer: ReturnType<typeof setTimeout> | undefined\n private stateTimelineResolvers: Array<(changes: StateChange[]) => void> = []\n\n constructor(private readonly hooks: CollectorHooks = {}) {}\n\n /**\n * Subscribe to the runtime's hot-channel events. Re-attaching (dev server\n * restart) detaches the previous channel first so listeners never pile up.\n */\n attach(hot: HotChannel): void {\n this.detach()\n this.hot = hot\n const listeners: Array<[string, (payload: any, client: HotClient) => void]> = [\n [\n HOT_EVENTS.runtimeReady,\n (_, client) => client?.send(HOT_EVENTS.subscription, this.subscription),\n ],\n [HOT_EVENTS.components, (d, client) => this.ingestComponents(d, client)],\n [HOT_EVENTS.profiles, d => this.ingestProfiles(d)],\n [HOT_EVENTS.stateTimeline, d => this.ingestStateTimeline(d)],\n [HOT_EVENTS.fps, d => this.ingestFps(d)],\n [HOT_EVENTS.runtimeError, d => this.ingestRuntimeError(d)],\n [HOT_EVENTS.reactiveGraph, d => this.ingestReactiveGraph(d)],\n [HOT_EVENTS.reactiveSummary, d => this.ingestReactiveSummary(d)],\n ]\n for (const [event, listener] of listeners) hot.on(event, listener)\n this.detachHot = () => {\n for (const [event, listener] of listeners) hot.off?.(event, listener)\n }\n }\n\n detach(): void {\n clearTimeout(this.sweepTimer)\n this.sweepTimer = undefined\n this.detachHot?.()\n this.detachHot = undefined\n this.hot = undefined\n // Answer pending pulls from cache instead of leaving them to time out.\n this.flushPulls('no-runtime')\n this.flushStateTimeline()\n }\n\n /** What the runtime is told: collect/poll only while somebody is watching. */\n get subscription(): { active: boolean; componentDeltas: true } {\n // `componentDeltas` advertises that the delta form of `components` is\n // accepted (§6.5), so a runtime never sends deltas to an older server.\n return { active: this.active, componentDeltas: true }\n }\n\n /** Epochs we asked for a full snapshot (delta without a base); answered once per epoch. */\n private resyncRequested = new Set<string>()\n\n /** Components of the served epoch, parents first, capped at {@link LIMITS.liveComponents}. */\n get liveComponents(): ComponentInstance[] {\n if (!this.liveCache) {\n const state = this.servedState()\n this.liveCache = state ? [...state.components.values()] : []\n }\n return this.liveCache\n }\n\n /**\n * The served epoch's components with that epoch, read together, so a\n * component id is never paired with another page load's epoch (several app\n * tabs keep separate trees; nothing is merged).\n */\n get liveSnapshot(): {\n epoch: string | null\n total: number\n components: ComponentInstance[]\n } {\n const state = this.servedState()\n return {\n epoch: state ? (this.servedEpoch ?? null) : null,\n total: this.liveComponentsTotal,\n components: this.liveComponents,\n }\n }\n\n /** Instances the served epoch has mounted, including those beyond the cap. */\n get liveComponentsTotal(): number {\n const state = this.servedState()\n return state ? state.components.size + state.overflow.size : 0\n }\n\n get renderProfiles(): RenderProfile[] {\n return this.servedState()?.profiles ?? []\n }\n\n /** The epoch currently served and how many app page loads are tracked. */\n get epochInfo(): { epoch: string | undefined; epochs: number } {\n return { epoch: this.servedEpoch ?? [...this.epochs.keys()].at(-1), epochs: this.epochs.size }\n }\n\n private servedState(): EpochState | undefined {\n if (this.servedEpoch !== undefined) return this.epochs.get(this.servedEpoch)\n // No page load has sent a component snapshot yet: show the most recent\n // pusher (its profiles; its tree is empty either way).\n let newest: EpochState | undefined\n for (const state of this.epochs.values()) newest = state\n return newest\n }\n\n /**\n * Get (creating, LRU-bounded) the state for `epoch` and mark it as the most\n * recent pusher. It becomes the served epoch only once it holds a full\n * component snapshot — an epoch known only from profiles/timeline would\n * otherwise show an empty tree (review B1).\n */\n private touchEpoch(epoch: string): EpochState {\n let state = this.epochs.get(epoch)\n if (state) this.epochs.delete(epoch)\n else\n state = {\n components: new Map(),\n overflow: new Set(),\n hasBase: false,\n profiles: [],\n profilesTotal: null,\n }\n this.epochs.set(epoch, state) // re-insert: Map order = recency\n while (this.epochs.size > MAX_EPOCHS) {\n const evicted = this.epochs.keys().next().value!\n this.epochs.delete(evicted)\n this.resyncRequested.delete(evicted)\n this.dropEpoch(evicted)\n this.timelineDrops.delete(evicted)\n this.timelineTooLarge.delete(evicted)\n this.timelineBaseline.delete(evicted)\n if (this.servedEpoch === evicted) this.serve(this.newestBasedEpoch())\n }\n if (state.hasBase) this.serve(epoch)\n return state\n }\n\n private newestBasedEpoch(): string | undefined {\n let newest: string | undefined\n for (const [epoch, state] of this.epochs) if (state.hasBase) newest = epoch\n return newest\n }\n\n private serve(epoch: string | undefined): void {\n if (this.servedEpoch === epoch) return\n // Switching from another tab's data changes what both datasets serve.\n if (this.servedEpoch !== undefined) this.bump('components', 'renderProfiles')\n this.servedEpoch = epoch\n this.liveCache = undefined\n }\n\n /**\n * Mark `id` as watching for `ttl` ms (renewed by heartbeats). The first\n * lease activates the runtime's polling/FPS sampling, the last expiry or\n * release pauses it.\n */\n lease(id: string, ttl = LEASE_TTL): boolean {\n const wasActive = this.active\n this.leases.set(id, Date.now() + ttl)\n this.updateSubscription()\n return !wasActive && this.active\n }\n\n /**\n * Resolve once the runtime has sent its activation snapshot (components,\n * profiles, then a `reset: true` timeline — the last part) or after\n * `timeout`, so a consumer that just activated the runtime doesn't read\n * the stale pre-activation state.\n */\n waitForSnapshot(timeout: number): Promise<void> {\n return new Promise(resolve => {\n const done = () => {\n clearTimeout(timer)\n const idx = this.snapshotWaiters.indexOf(done)\n if (idx !== -1) this.snapshotWaiters.splice(idx, 1)\n resolve()\n }\n const timer = setTimeout(done, timeout)\n this.snapshotWaiters.push(done)\n })\n }\n\n release(id: string): void {\n if (this.leases.delete(id)) this.updateSubscription()\n }\n\n private updateSubscription(): void {\n const now = Date.now()\n let next = Infinity\n for (const [id, expiresAt] of this.leases) {\n if (expiresAt <= now) this.leases.delete(id)\n else next = Math.min(next, expiresAt)\n }\n const active = this.leases.size > 0\n if (active !== this.active) {\n this.active = active\n this.hot?.send(HOT_EVENTS.subscription, this.subscription)\n }\n clearTimeout(this.sweepTimer)\n this.sweepTimer = undefined\n if (next !== Infinity) {\n this.sweepTimer = setTimeout(() => this.updateSubscription(), next - now + 1)\n this.sweepTimer.unref?.()\n }\n }\n\n /**\n * Full form `{ epoch?, reset?, components }` replaces the epoch's tree;\n * delta form `{ epoch, added, removed }` (ids) patches it (§6.5). A delta\n * for an epoch we hold no full snapshot of (new to us, or evicted) is not\n * applied — a partial tree would persist — and the sender is asked to\n * resync. Entries stay in registration order (parents first); an instance\n * is stored only while its parent is and the cap allows, otherwise only its\n * id is tracked, so the stored part is always a rooted, orphan-free tree.\n */\n ingestComponents(\n data: { components?: unknown; epoch?: unknown; added?: unknown; removed?: unknown } | undefined,\n client?: HotClient,\n ): void {\n const epoch = typeof data?.epoch === 'string' ? data.epoch : LEGACY_EPOCH\n const isDelta =\n !Array.isArray(data?.components) &&\n (Array.isArray(data?.added) || Array.isArray(data?.removed))\n if (isDelta && !this.epochs.get(epoch)?.hasBase) {\n if (!this.resyncRequested.has(epoch)) {\n this.resyncRequested.add(epoch)\n client?.send(HOT_EVENTS.subscription, { ...this.subscription, resync: true })\n }\n return\n }\n const state = this.touchEpoch(epoch)\n if (!isDelta) {\n this.resyncRequested.delete(epoch)\n state.hasBase = true\n this.serve(epoch)\n state.components = new Map()\n state.overflow = new Set()\n }\n if (isDelta && Array.isArray(data?.removed)) {\n for (const id of data.removed as unknown[]) {\n if (!state.components.delete(id as number)) state.overflow.delete(id as number)\n }\n }\n const incoming = isDelta ? data?.added : data?.components\n if (Array.isArray(incoming)) {\n for (const c of incoming as ComponentInstance[]) {\n const id = c?.id\n if (state.components.has(id)) {\n state.components.set(id, c)\n continue\n }\n const parentStored = c?.parentId == null || state.components.has(c.parentId)\n if (parentStored && state.components.size < LIMITS.liveComponents) {\n state.overflow.delete(id)\n state.components.set(id, c)\n } else {\n state.overflow.add(id)\n }\n }\n }\n this.liveCache = undefined\n this.bump('components')\n }\n\n ingestProfiles(data: { profiles?: unknown; epoch?: unknown; total?: unknown } | undefined): void {\n const epoch = typeof data?.epoch === 'string' ? data.epoch : LEGACY_EPOCH\n const state = this.touchEpoch(epoch)\n state.profiles = tail(data?.profiles, LIMITS.renderProfiles)\n state.profilesTotal =\n typeof data?.total === 'number' && Number.isFinite(data.total) ? data.total : null\n this.bump('renderProfiles')\n }\n\n /**\n * What the server holds versus what was reported, per dataset (§6.7 B).\n * `total: null` means unknown; nothing is estimated.\n */\n getCaptureInfo(): CaptureInfoMap {\n const state = this.servedState()\n const epoch = this.servedEpoch\n const ring = (captured: number, received: number): CaptureInfo => ({\n captured,\n total: received,\n truncated: received > captured,\n policy: 'tail',\n })\n const drops: Record<DropReason, number> = {\n 'runtime-count': 0,\n 'runtime-bytes': 0,\n 'server-count': 0,\n 'server-bytes': 0,\n }\n for (const counts of this.timelineDrops.values()) {\n for (const reason of DROP_REASONS) drops[reason] += counts[reason]\n }\n const dropped = DROP_REASONS.filter(r => drops[r] > 0).map(reason => ({\n reason,\n count: drops[reason],\n }))\n let tooLarge = 0\n for (const n of this.timelineTooLarge.values()) tooLarge += n\n const profiles = state?.profiles.length ?? 0\n const profilesTotal = state?.profilesTotal ?? null\n const graph = this.lastGraph\n const info: CaptureInfoMap = {\n liveComponents: {\n captured: state?.components.size ?? 0,\n total: this.liveComponentsTotal,\n truncated: (state?.overflow.size ?? 0) > 0,\n policy: 'roots-first',\n ...(epoch !== undefined && { epoch }),\n },\n renderProfiles: {\n captured: profiles,\n total: profilesTotal,\n truncated: profilesTotal !== null && profilesTotal > profiles,\n // The runtime keeps first-render order and sends the tail: the newest-mounted instances (review IA1).\n policy: 'newest-mounted',\n ...(epoch !== undefined && { epoch }),\n },\n stateTimeline: {\n captured: this.timeline.length,\n total: null,\n truncated: dropped.length > 0,\n policy: 'sampled-200ms',\n ...(dropped.length > 0 && { dropped }),\n ...(tooLarge > 0 && { valueTooLarge: tooLarge }),\n ...(epoch !== undefined &&\n this.timelineBaseline.has(epoch) && { baseline: this.timelineBaseline.get(epoch) }),\n },\n fpsSamples: ring(this.fpsSamples.length, this.received.fps),\n runtimeErrors: ring(this.runtimeErrors.length, this.received.runtimeErrors),\n loadProfiles: ring(this.loadProfiles.length, this.received.loadProfiles),\n compilerWarnings: ring(this.compilerWarnings.length, this.received.compilerWarnings),\n }\n if (graph) {\n const common = {\n truncated: graph.truncated,\n policy: graph.policy,\n ...(graph.epoch !== null && { epoch: graph.epoch }),\n }\n info.reactiveNodes = {\n captured: graph.nodes.length,\n total: graph.total?.nodes ?? null,\n ...common,\n }\n info.reactiveEdges = {\n captured: graph.edges.length,\n total: graph.total?.edges ?? null,\n ...common,\n }\n }\n return info\n }\n\n /** The server-side timeline (all tracked epochs, oldest first). */\n get stateTimeline(): StateTimelineEntry[] {\n return this.timeline\n }\n\n /**\n * Two payload shapes (docs/devframe-migration.md §6.4):\n * - delta: `{ epoch, changes, reset? }` — `changes` are new since the\n * previous push from that page load (`epoch`); `reset` replaces that\n * epoch's entries. Entries are kept per epoch, so several app tabs (or a\n * reload) interleave instead of wiping each other.\n * - legacy full snapshot: `{ changes }` — we append only the entries after\n * the newest one we already hold, so clients still get deltas.\n */\n ingestStateTimeline(\n data:\n | {\n changes?: unknown\n epoch?: unknown\n reset?: unknown\n dropped?: unknown\n valueTooLarge?: unknown\n baseline?: unknown\n }\n | undefined,\n ): void {\n const incoming = tail<StateChange>(data?.changes, LIMITS.stateTimeline)\n if (typeof data?.epoch === 'string') {\n this.touchEpoch(data.epoch)\n this.countRuntimeLosses(data.epoch, data.dropped, data.valueTooLarge)\n if (data.reset === true) this.dropEpoch(data.epoch)\n this.appendTimeline(incoming, data.epoch)\n if (validBaseline(data.baseline))\n this.timelineBaseline.set(data.epoch, {\n complete: data.baseline.complete,\n pendingNodes: data.baseline.pendingNodes,\n })\n } else {\n let last: StateTimelineEntry | undefined\n for (let i = this.timeline.length - 1; i >= 0 && !last; i--) {\n if (this.timelineEpochs[i] === LEGACY_EPOCH) last = this.timeline[i]\n }\n let start = -1\n if (last) {\n for (let i = incoming.length - 1; i >= 0; i--) {\n if (incoming[i].timestamp === last.timestamp && incoming[i].id === last.id) {\n start = i + 1\n break\n }\n }\n }\n if (start === -1) {\n this.dropEpoch(LEGACY_EPOCH)\n start = 0\n }\n this.appendTimeline(incoming.slice(start), LEGACY_EPOCH)\n }\n this.lastPull.stateTimeline = Date.now()\n this.flushStateTimeline()\n // The runtime's activation snapshot ends with a `reset: true` timeline\n // (after components and profiles), so that completes a snapshot (D4).\n if (data?.reset === true) this.resolveSnapshotWaiters()\n }\n\n /**\n * Add the runtime's own losses (unsent entries it evicted, §6.7 C) and\n * too-large values to the epoch's counters. Only runtime reasons are\n * accepted from the runtime; server reasons are counted here.\n */\n private countRuntimeLosses(epoch: string, dropped: unknown, valueTooLarge: unknown): void {\n if (Array.isArray(dropped)) {\n for (const d of dropped as Array<{ reason?: unknown; count?: unknown }>) {\n if (d?.reason !== 'runtime-count' && d?.reason !== 'runtime-bytes') continue\n const count = clampInt(d.count, 0, Number.MAX_SAFE_INTEGER, 0)\n if (count > 0) this.addDrop(epoch, d.reason, count)\n }\n }\n const tooLarge = clampInt(valueTooLarge, 0, Number.MAX_SAFE_INTEGER, 0)\n if (tooLarge > 0) {\n this.timelineTooLarge.set(epoch, (this.timelineTooLarge.get(epoch) ?? 0) + tooLarge)\n }\n }\n\n private addDrop(epoch: string, reason: DropReason, count: number): void {\n let counts = this.timelineDrops.get(epoch)\n if (!counts) {\n counts = { 'runtime-count': 0, 'runtime-bytes': 0, 'server-count': 0, 'server-bytes': 0 }\n this.timelineDrops.set(epoch, counts)\n }\n counts[reason] += count\n }\n\n /** Changes after `since` (a previous `cursor`), or the whole buffer when the cursor is stale. */\n getStateTimelineDelta(since?: number): StateTimelineDelta {\n const cursor = this.timelineSeq\n if (\n since === undefined ||\n since < this.timelineResetAt ||\n since < this.timelineTrimmedAt ||\n since > cursor\n ) {\n return { cursor, reset: true, changes: this.timeline }\n }\n let i = this.timeline.length\n while (i > 0 && this.timeline[i - 1].seq > since) i--\n return { cursor, reset: false, changes: this.timeline.slice(i) }\n }\n\n /** Invalidate every cursor issued so far (entries were removed, not just appended). */\n private markTimelineReset(): void {\n this.timelineResetAt = this.timelineSeq = nextSeq()\n this.bump('stateTimeline')\n }\n\n private dropEpoch(epoch: string): void {\n if (!this.timelineEpochs.includes(epoch)) return\n const keep = this.timelineEpochs.map(e => e !== epoch)\n this.timeline = this.timeline.filter((_, i) => keep[i])\n this.timelineSizes = this.timelineSizes.filter((_, i) => keep[i])\n this.timelineEpochs = this.timelineEpochs.filter((_, i) => keep[i])\n this.timelineBytes = this.timelineSizes.reduce((a, b) => a + b, 0)\n this.markTimelineReset()\n }\n\n private appendTimeline(changes: StateChange[], epoch: string): void {\n if (changes.length === 0) return\n for (const change of changes) {\n let size = 0\n try {\n size = JSON.stringify(change).length\n } catch {\n continue // not serializable: never reaches a client anyway\n }\n this.timeline.push({ ...change, seq: (this.timelineSeq = nextSeq()) })\n this.timelineSizes.push(size)\n this.timelineEpochs.push(epoch)\n this.timelineBytes += size\n }\n let drop = Math.max(0, this.timeline.length - LIMITS.stateTimeline)\n let bytes = this.timelineBytes\n for (let i = 0; i < drop; i++) {\n bytes -= this.timelineSizes[i]\n this.addDrop(this.timelineEpochs[i], 'server-count', 1)\n }\n // Keep at least the newest entry even if it alone exceeds the budget.\n while (bytes > STATE_TIMELINE_BYTES && drop < this.timeline.length - 1) {\n this.addDrop(this.timelineEpochs[drop], 'server-bytes', 1)\n bytes -= this.timelineSizes[drop++]\n }\n if (drop > 0) {\n this.timelineTrimmedAt = this.timeline[drop - 1].seq\n this.timeline = this.timeline.slice(drop)\n this.timelineSizes = this.timelineSizes.slice(drop)\n this.timelineEpochs = this.timelineEpochs.slice(drop)\n }\n this.timelineBytes = bytes\n this.bump('stateTimeline')\n }\n\n private resolveSnapshotWaiters(): void {\n // Copy: each waiter removes itself from the list while we iterate.\n for (const done of this.snapshotWaiters.slice()) done()\n }\n\n /**\n * A graph reply. With a `requestId` (§6.7 A) it resolves only that request,\n * and only if its epoch matches the one asked for; a reply nobody waits for\n * (another app tab, too late) is ignored. Without one (an older runtime) it\n * is a whole-app graph and answers every pending graph pull, scoped ones by\n * filtering here.\n */\n ingestReactiveGraph(data: Record<string, any> | undefined): void {\n const requestId = typeof data?.requestId === 'string' ? data.requestId : undefined\n if (requestId !== undefined) {\n const pull = this.pulls.get(requestId)\n if (!pull || pull.kind !== 'graph') return\n if (pull.epoch !== null && typeof data?.epoch === 'string' && data.epoch !== pull.epoch)\n return\n this.settle(requestId, this.normalizeGraph(data, pull.scope, pull.epoch))\n } else {\n let answered = false\n for (const [id, pull] of this.pulls) {\n if (pull.kind !== 'graph') continue\n answered = true\n this.settle(id, this.normalizeGraph(data, pull.scope, pull.epoch))\n }\n if (!answered) this.storeGraph(this.normalizeGraph(data, null, this.servedEpoch ?? null))\n }\n this.bump('reactiveGraph')\n }\n\n /**\n * Shape a runtime reply into a {@link ReactiveGraphResult}: apply the\n * collector caps (nodes, then only edges between kept nodes, then the edge\n * cap) and report what was left out. Totals come from the runtime; an older\n * runtime's are the counts it sent (`nodesKind: 'sent'`), or unknown when\n * the server had to scope its whole-app graph.\n */\n private normalizeGraph(\n data: Record<string, any> | undefined,\n scope: number | null,\n epoch: string | null,\n ): ReactiveGraphResult {\n const legacy = typeof data?.requestId !== 'string'\n let nodes = head<ReactiveGraph['nodes'][number]>(data?.nodes, Infinity)\n const rawEdges = head<ReactiveGraph['edges'][number]>(data?.edges, Infinity)\n let policy: ReactiveGraphResult['policy'] =\n data?.policy === 'scoped' || data?.policy === 'global-head'\n ? data.policy\n : scope === null\n ? 'global-head'\n : 'scoped'\n let total: ReactiveGraphTotal | null = null\n if (!legacy && data?.total && typeof data.total.nodes === 'number') {\n total = {\n nodes: data.total.nodes,\n nodesKind: 'registered',\n edges: typeof data.total.edges === 'number' ? data.total.edges : null,\n }\n }\n if (legacy && scope !== null) {\n // Older runtime: whole app. Keep the component's nodes and their direct neighbours.\n const own = new Set(nodes.filter(n => n?.componentId === scope).map(n => n.id))\n const keep = new Set(own)\n for (const e of rawEdges) {\n if (own.has(e?.from)) keep.add(e.to)\n if (own.has(e?.to)) keep.add(e.from)\n }\n nodes = nodes.filter(n => keep.has(n?.id))\n policy = 'server-filter'\n } else if (legacy) {\n total = { nodes: nodes.length, nodesKind: 'sent', edges: rawEdges.length }\n }\n let truncated = data?.truncated === true\n if (nodes.length > LIMITS.reactiveNodes) {\n nodes = nodes.slice(0, LIMITS.reactiveNodes)\n truncated = true\n }\n const ids = new Set(nodes.map(n => n?.id))\n let edgesOmitted = clampInt(data?.edgesOmitted, 0, Number.MAX_SAFE_INTEGER, 0)\n const edges: ReactiveGraph['edges'] = []\n for (const e of rawEdges) {\n if (!ids.has(e?.from) || !ids.has(e?.to)) {\n if (policy !== 'server-filter') edgesOmitted++\n } else if (edges.length < LIMITS.reactiveEdges) {\n edges.push(e)\n } else {\n edgesOmitted++\n truncated = true\n }\n }\n return {\n nodes,\n edges,\n scope,\n epoch: typeof data?.epoch === 'string' ? data.epoch : epoch,\n total,\n truncated,\n edgesOmitted,\n // When the app built this graph; null from a runtime that doesn't say.\n computedAt:\n typeof data?.computedAt === 'number' && Number.isFinite(data.computedAt)\n ? data.computedAt\n : null,\n policy,\n }\n }\n\n private storeGraph(result: ReactiveGraphResult): void {\n this.lastGraph = result\n if (result.scope === null) this.reactiveGraph = { nodes: result.nodes, edges: result.edges }\n }\n\n /** A summary reply (§6.7 I): resolves only the matching request. */\n ingestReactiveSummary(data: Record<string, any> | undefined): void {\n const requestId = typeof data?.requestId === 'string' ? data.requestId : undefined\n const pull = requestId === undefined ? undefined : this.pulls.get(requestId)\n if (!pull || pull.kind !== 'summary') return\n if (pull.epoch !== null && typeof data?.epoch === 'string' && data.epoch !== pull.epoch) return\n this.settle(requestId!, this.normalizeSummary(data, pull.epoch))\n }\n\n private normalizeSummary(\n data: Record<string, any> | undefined,\n epoch: string | null,\n ): ReactiveSummary {\n const count = (v: unknown) => clampInt(v, 0, Number.MAX_SAFE_INTEGER, 0)\n const rows = head<Record<string, any>>(data?.rows, SUMMARY_DEFAULTS.maxTopK).map(r => ({\n componentId: count(r?.componentId),\n file: typeof r?.file === 'string' ? r.file : '',\n nodes: {\n state: count(r?.nodes?.state),\n derived: count(r?.nodes?.derived),\n effect: count(r?.nodes?.effect),\n },\n changes: count(r?.changes),\n renders: count(r?.renders),\n renderMs: typeof r?.renderMs === 'number' && r.renderMs >= 0 ? r.renderMs : 0,\n ...(r?.kind === 'module' && { kind: 'module' as const }),\n }))\n const w = data?.window\n return {\n epoch: typeof data?.epoch === 'string' ? data.epoch : epoch,\n window: {\n ms: count(w?.ms),\n since: count(w?.since),\n until: count(w?.until),\n sampledActiveMs: count(w?.sampledActiveMs),\n },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: {\n total: typeof data?.components?.total === 'number' ? data.components.total : null,\n withActivity: count(data?.components?.withActivity),\n },\n rows,\n other:\n data?.other &&\n typeof data.other.components === 'number' &&\n typeof data.other.nodes === 'number'\n ? { components: data.other.components, nodes: data.other.nodes }\n : null,\n truncated: data?.truncated === true,\n // Only what the runtime says it implements; never assumed.\n capabilities: {\n valueInspection: data?.capabilities?.valueInspection === true,\n signalHistory: data?.capabilities?.signalHistory === true,\n writeCause: data?.capabilities?.writeCause === true,\n },\n ...(validBaseline(data?.baseline) && { baseline: { ...data!.baseline } }),\n }\n }\n\n ingestFps(sample: FpsSample): void {\n this.received.fps++\n this.fpsSamples.push(sample)\n if (this.fpsSamples.length > LIMITS.fpsSamples) {\n this.fpsSamples = this.fpsSamples.slice(-LIMITS.fpsSamples)\n }\n this.bump('fps')\n this.hooks.onFpsSample?.(sample)\n }\n\n ingestRuntimeError(error: RuntimeError): void {\n this.received.runtimeErrors++\n this.runtimeErrors.push(error)\n if (this.runtimeErrors.length > LIMITS.runtimeErrors) {\n this.runtimeErrors = this.runtimeErrors.slice(-LIMITS.runtimeErrors)\n }\n this.bump('errors')\n }\n\n recordLoadProfile(profile: LoadProfile): void {\n this.received.loadProfiles++\n this.loadProfiles.push(profile)\n if (this.loadProfiles.length > LIMITS.loadProfiles) {\n this.loadProfiles = this.loadProfiles.slice(-LIMITS.loadProfiles)\n }\n this.bump('loadProfiles')\n this.hooks.onLoadProfile?.(profile)\n }\n\n recordCompilerWarning(warning: CompilerWarning): void {\n this.received.compilerWarnings++\n this.compilerWarnings.push(warning)\n if (this.compilerWarnings.length > LIMITS.compilerWarnings) {\n this.compilerWarnings = this.compilerWarnings.slice(-LIMITS.compilerWarnings)\n }\n this.bump('errors')\n }\n\n clearLoadProfiles(): void {\n this.loadProfiles = []\n this.received.loadProfiles = 0\n this.bump('loadProfiles')\n }\n\n clearErrors(): void {\n this.compilerWarnings = []\n this.runtimeErrors = []\n this.received.compilerWarnings = 0\n this.received.runtimeErrors = 0\n this.bump('errors')\n }\n\n clearFps(): void {\n this.fpsSamples = []\n this.received.fps = 0\n this.bump('fps')\n }\n\n clearStateTimeline(): void {\n this.timeline = []\n this.timelineSizes = []\n this.timelineEpochs = []\n this.timelineBytes = 0\n this.timelineDrops.clear()\n this.timelineTooLarge.clear()\n this.markTimelineReset()\n this.hot?.send(HOT_EVENTS.clearStateTimeline, {})\n }\n\n /**\n * Ask the browser runtime for the graph of one component instance (or the\n * whole app), built by the runtime within the caps (§6.7 A). Falls back to\n * the last result for the same scope, marked `stale`.\n */\n requestReactiveGraph(req: ReactiveGraphRequest = {}): Promise<ReactiveGraphResult> {\n const scope =\n typeof req.componentId === 'number' &&\n Number.isInteger(req.componentId) &&\n req.componentId >= 0\n ? req.componentId\n : null\n const maxNodes = clampInt(req.maxNodes, 1, LIMITS.reactiveNodes, LIMITS.reactiveNodes)\n const maxEdges = clampInt(req.maxEdges, 1, LIMITS.reactiveEdges, LIMITS.reactiveEdges)\n const epoch = this.servedEpoch ?? null\n if (scope !== null && epoch === null) {\n // No page load has sent its tree: a component id means nothing yet, and\n // asking every tab would let any of them answer for it (review MUST-1).\n return Promise.resolve({\n nodes: [],\n edges: [],\n scope,\n epoch,\n total: null,\n truncated: false,\n edgesOmitted: 0,\n computedAt: null,\n policy: 'scoped',\n stale: true,\n staleReason: 'no-runtime',\n })\n }\n if (scope !== null && typeof req.epoch === 'string' && req.epoch !== epoch) {\n // The id belongs to an earlier page load; another instance may reuse it now.\n return Promise.resolve({\n nodes: [],\n edges: [],\n scope,\n epoch,\n total: null,\n truncated: false,\n edgesOmitted: 0,\n computedAt: null,\n policy: 'scoped',\n stale: true,\n staleReason: 'epoch-changed',\n })\n }\n const key = `graph|${epoch ?? ''}|${scope ?? '*'}|${maxNodes}|${maxEdges}`\n return this.keyedPull<ReactiveGraphResult>(\n 'graph',\n key,\n epoch,\n scope,\n HOT_EVENTS.requestReactiveGraph,\n { ...(scope !== null && { componentId: scope }), maxNodes, maxEdges },\n reason => ({\n nodes: [],\n edges: [],\n scope,\n epoch,\n total: null,\n truncated: false,\n edgesOmitted: 0,\n computedAt: null,\n policy: scope === null ? 'global-head' : 'scoped',\n stale: true,\n staleReason: reason,\n }),\n )\n }\n\n /** Ask the runtime for the overview aggregate (§6.7 I); never captures the graph. */\n requestReactiveSummary(req: ReactiveSummaryRequest = {}): Promise<ReactiveSummary> {\n const topK = clampInt(req.topK, 1, SUMMARY_DEFAULTS.maxTopK, SUMMARY_DEFAULTS.topK)\n const windowMs = clampInt(\n req.windowMs,\n SUMMARY_DEFAULTS.minWindowMs,\n SUMMARY_DEFAULTS.maxWindowMs,\n SUMMARY_DEFAULTS.windowMs,\n )\n const epoch = this.servedEpoch ?? null\n const key = `summary|${epoch ?? ''}|${topK}|${windowMs}`\n return this.keyedPull<ReactiveSummary>(\n 'summary',\n key,\n epoch,\n null,\n HOT_EVENTS.requestReactiveSummary,\n { topK, windowMs },\n reason => ({\n epoch,\n window: { ms: windowMs, since: 0, until: 0, sampledActiveMs: 0 },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: { total: null, withActivity: 0 },\n rows: [],\n other: null,\n truncated: false,\n capabilities: { valueInspection: false, signalHistory: false, writeCause: false },\n stale: true,\n staleReason: reason,\n }),\n )\n }\n\n /**\n * One pull per key at a time; a result younger than {@link PULL_FRESHNESS}\n * is reused. The request carries a requestId and the served epoch; only\n * the matching reply resolves it. On timeout (or without a runtime) the\n * last result for the same key is returned with `stale: true`.\n */\n private keyedPull<T extends ReactiveGraphResult | ReactiveSummary>(\n kind: PendingPull['kind'],\n key: string,\n epoch: string | null,\n scope: number | null,\n event: string,\n payload: Record<string, unknown>,\n empty: (reason: 'timeout' | 'no-runtime') => T,\n ): Promise<T> {\n const fallback = (reason: 'timeout' | 'no-runtime'): T => {\n const last = this.pullCache.get(key)\n return last ? ({ ...last.value, stale: true, staleReason: reason } as T) : empty(reason)\n }\n const cached = this.pullCache.get(key)\n if (!this.hot) return Promise.resolve(fallback('no-runtime'))\n if (cached && Date.now() - cached.at < PULL_FRESHNESS) return Promise.resolve(cached.value as T)\n const existing = this.pullInflight.get(key) as Promise<T> | undefined\n if (existing) return existing\n const hot = this.hot\n const requestId = `r${++this.requestSeq}`\n const promise = new Promise<T>(resolve => {\n const timer = setTimeout(() => {\n this.pulls.delete(requestId)\n resolve(fallback('timeout'))\n }, RUNTIME_REQUEST_TIMEOUT)\n this.pulls.set(requestId, {\n kind,\n key,\n epoch,\n scope,\n resolve: resolve as PendingPull['resolve'],\n timer,\n })\n hot.send(event, { requestId, ...(epoch !== null && { epoch }), ...payload })\n }).finally(() => {\n if (this.pullInflight.get(key) === promise) this.pullInflight.delete(key)\n })\n this.pullInflight.set(key, promise)\n return promise\n }\n\n /** Resolve a pending pull with a fresh result and cache it under its key. */\n private settle(requestId: string, value: ReactiveGraphResult | ReactiveSummary): void {\n const pull = this.pulls.get(requestId)\n if (!pull) return\n this.pulls.delete(requestId)\n clearTimeout(pull.timer)\n this.pullCache.delete(pull.key)\n this.pullCache.set(pull.key, { value, at: Date.now() })\n while (this.pullCache.size > MAX_CACHED_PULLS) {\n this.pullCache.delete(this.pullCache.keys().next().value!)\n }\n if (pull.kind === 'graph') this.storeGraph(value as ReactiveGraphResult)\n pull.resolve(value)\n }\n\n /** Answer every pending keyed pull from its cache (or empty), marked stale. */\n private flushPulls(reason: 'timeout' | 'no-runtime'): void {\n for (const [id, pull] of this.pulls) {\n this.pulls.delete(id)\n clearTimeout(pull.timer)\n const cached = this.pullCache.get(pull.key)\n if (cached) {\n pull.resolve({ ...cached.value, stale: true, staleReason: reason })\n } else if (pull.kind === 'graph') {\n pull.resolve({\n nodes: [],\n edges: [],\n scope: pull.scope,\n epoch: pull.epoch,\n total: null,\n truncated: false,\n edgesOmitted: 0,\n computedAt: null,\n policy: pull.scope === null ? 'global-head' : 'scoped',\n stale: true,\n staleReason: reason,\n })\n } else {\n pull.resolve({\n epoch: pull.epoch,\n window: { ms: 0, since: 0, until: 0, sampledActiveMs: 0 },\n policy: 'sampled-200ms',\n coverage: 'component-init',\n components: { total: null, withActivity: 0 },\n rows: [],\n other: null,\n truncated: false,\n capabilities: { valueInspection: false, signalHistory: false, writeCause: false },\n stale: true,\n staleReason: reason,\n })\n }\n }\n }\n\n /** Ask the browser runtime for a fresh state timeline; falls back to the last one. */\n requestStateTimeline(): Promise<StateChange[]> {\n return this.pull(\n 'stateTimeline',\n HOT_EVENTS.requestStateTimeline,\n this.stateTimelineResolvers,\n () => this.stateTimeline,\n )\n }\n\n /**\n * Concurrent callers share one in-flight pull, and a result younger than\n * {@link PULL_FRESHNESS} is reused, so several polling clients never make\n * the user's app rebuild the same data more than once a second.\n */\n private pull<K extends 'stateTimeline', T>(\n key: K,\n event: string,\n resolvers: Array<(value: T) => void>,\n cached: () => T,\n ): Promise<T> {\n if (!this.hot || Date.now() - this.lastPull[key] < PULL_FRESHNESS) {\n return Promise.resolve(cached())\n }\n const existing = this.inflight[key] as Promise<T> | undefined\n if (existing) return existing\n const hot = this.hot\n const promise = new Promise<T>(resolve => {\n const resolver = (value: T) => {\n clearTimeout(timeout)\n resolve(value)\n }\n const timeout = setTimeout(() => {\n // Remove this resolver to prevent a leak, then answer from cache.\n const idx = resolvers.indexOf(resolver)\n if (idx !== -1) resolvers.splice(idx, 1)\n resolve(cached())\n }, RUNTIME_REQUEST_TIMEOUT)\n resolvers.push(resolver)\n hot.send(event, {})\n }).finally(() => {\n if (this.inflight[key] === promise) this.inflight[key] = undefined\n })\n this.inflight[key] = promise as never\n return promise\n }\n\n // Snapshot then reset before resolving so concurrent requests that push\n // during the resolve loop are not silently dropped.\n private flushStateTimeline(): void {\n const pending = this.stateTimelineResolvers\n this.stateTimelineResolvers = []\n for (const resolve of pending) resolve(this.stateTimeline)\n }\n}\n","import fs from 'fs'\nimport path from 'path'\nimport type { AssetInfo } from '../types.js'\n\nexport const MIME_TYPES: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.eot': 'application/vnd.ms-fontobject',\n '.otf': 'font/otf',\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n '.json': 'application/json',\n '.xml': 'application/xml',\n '.pdf': 'application/pdf',\n '.txt': 'text/plain',\n '.css': 'text/css',\n '.js': 'text/javascript',\n '.html': 'text/html',\n}\n\n/**\n * List files in the static directory. `publicBase` is the dev server's\n * public base (Vite `base`); static files are served under it, so each asset\n * gets a previewable `url` without a dedicated file-serving endpoint.\n */\nexport function analyzeAssets(staticDir: string, publicBase = '/'): AssetInfo[] {\n if (!fs.existsSync(staticDir)) return []\n\n const assets: AssetInfo[] = []\n const base = publicBase.endsWith('/') ? publicBase : `${publicBase}/`\n scanDir(staticDir, staticDir, base, assets)\n return assets.sort((a, b) => a.relativePath.localeCompare(b.relativePath))\n}\n\nfunction scanDir(dir: string, rootDir: string, base: string, assets: AssetInfo[]): void {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n scanDir(fullPath, rootDir, base, assets)\n continue\n }\n\n // Skip hidden files\n if (entry.name.startsWith('.')) continue\n\n const stat = fs.statSync(fullPath)\n const ext = path.extname(entry.name).toLowerCase()\n\n const relativePath = path.relative(rootDir, fullPath)\n assets.push({\n name: entry.name,\n path: fullPath,\n relativePath,\n url: base + relativePath.split(path.sep).map(encodeURIComponent).join('/'),\n size: stat.size,\n type: MIME_TYPES[ext] || 'application/octet-stream',\n mtime: stat.mtimeMs,\n })\n }\n}\n","import dns from 'node:dns/promises'\nimport fs from 'node:fs'\nimport net from 'node:net'\nimport path from 'node:path'\n\n/**\n * Validate that a URL does not target private/internal network addresses (SSRF prevention).\n * Allows only http/https schemes and blocks private IP ranges.\n */\nexport function validateExternalUrl(urlStr: string): void {\n parseExternalUrl(urlStr)\n}\n\nfunction parseExternalUrl(urlStr: string): URL {\n let parsed: URL\n try {\n parsed = new URL(urlStr)\n } catch {\n throw new Error(`Invalid URL: ${urlStr}`)\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error(`Blocked URL scheme: ${parsed.protocol}`)\n }\n\n const hostname = parsed.hostname\n // Block IPv6 loopback\n if (hostname === '::1' || hostname === '[::1]') {\n throw new Error('Blocked: loopback address')\n }\n\n if (net.isIP(hostname)) {\n if (isPrivateIP(hostname)) {\n throw new Error(`Blocked: private IP address ${hostname}`)\n }\n } else {\n // For domain names, block common internal hostnames\n const lower = hostname.toLowerCase()\n if (lower === 'localhost' || lower.endsWith('.local') || lower.endsWith('.internal')) {\n throw new Error(`Blocked: internal hostname ${hostname}`)\n }\n }\n return parsed\n}\n\nexport interface OutboundUrlOptions {\n /**\n * Origins that may be fetched even though they are local — the dev\n * server's own resolved URLs, so the API playground can call the app.\n */\n allowedOrigins?: readonly string[]\n}\n\n/**\n * Like {@link validateExternalUrl}, but also resolves the hostname and\n * rejects names that point at private / loopback addresses (DNS-based SSRF).\n * Exact dev-server origins in `allowedOrigins` bypass the private checks.\n * Callers must also fetch with `redirect: 'manual'` so a public URL cannot\n * bounce the request to a private one.\n */\nexport async function assertOutboundUrl(\n urlStr: string,\n options: OutboundUrlOptions = {},\n): Promise<URL> {\n let parsed: URL\n try {\n parsed = new URL(urlStr)\n } catch {\n throw new Error(`Invalid URL: ${urlStr}`)\n }\n if (options.allowedOrigins?.includes(parsed.origin)) return parsed\n parseExternalUrl(urlStr)\n const hostname = parsed.hostname.replace(/^\\[|\\]$/g, '')\n if (net.isIP(hostname)) return parsed\n const addresses = await dns.lookup(hostname, { all: true }).catch(() => [])\n for (const { address } of addresses) {\n if (isPrivateIP(address)) throw new Error(`Blocked: ${hostname} resolves to private address`)\n }\n return parsed\n}\n\nexport function isPrivateIP(ip: string): boolean {\n if (ip.includes(':')) return isPrivateIPv6(ip)\n const parts = ip.split('.').map(Number)\n if (parts.length === 4) {\n // 127.0.0.0/8\n if (parts[0] === 127) return true\n // 10.0.0.0/8\n if (parts[0] === 10) return true\n // 172.16.0.0/12\n if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true\n // 192.168.0.0/16\n if (parts[0] === 192 && parts[1] === 168) return true\n // 169.254.0.0/16 (link-local)\n if (parts[0] === 169 && parts[1] === 254) return true\n // 0.0.0.0\n if (parts.every(p => p === 0)) return true\n }\n return false\n}\n\nfunction isPrivateIPv6(ip: string): boolean {\n const lower = ip.toLowerCase().replace(/^\\[|\\]$/g, '')\n // IPv4-mapped / -compatible (::ffff:127.0.0.1, ::127.0.0.1)\n const v4 = lower.match(/^::(?:ffff:)?(\\d+\\.\\d+\\.\\d+\\.\\d+)$/)\n if (v4) return isPrivateIP(v4[1])\n if (lower === '::' || lower === '::1') return true\n // fc00::/7 unique local, fe80::/10 link-local\n return /^f[cd][0-9a-f]{2}:/.test(lower) || /^fe[89ab][0-9a-f]:/.test(lower)\n}\n\n/**\n * Resolve a user-supplied file path strictly under `root`. Symlinks are\n * followed via realpathSync so that symlinks inside the project cannot be\n * used to escape the root sandbox. Throws if the real path is outside.\n */\nexport function resolveWithinRoot(root: string, input: string): string {\n if (typeof input !== 'string' || input.length === 0) {\n throw new Error('Invalid file path')\n }\n const realRoot = fs.realpathSync(root)\n const candidate = path.isAbsolute(input) ? input : path.resolve(root, input)\n let real: string\n try {\n real = fs.realpathSync(candidate)\n } catch {\n throw new Error('File not found')\n }\n if (real !== realRoot && !real.startsWith(realRoot + path.sep)) {\n throw new Error('Forbidden: path outside project root')\n }\n return real\n}\n","import fs from 'node:fs'\nimport { assertOutboundUrl } from '../security.js'\nimport type { OutboundUrlOptions } from '../security.js'\nimport type { ApiEndpoint, ApiResponse, RouteInfo } from '../types.js'\n\nconst HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']\n\n/** List `+server` endpoints and the HTTP methods they export. */\nexport function analyzeApiEndpoints(routes: RouteInfo[]): ApiEndpoint[] {\n const endpoints: ApiEndpoint[] = []\n for (const route of routes) {\n const serverFile = route.files.find(f => f.type === 'endpoint')\n if (!serverFile) continue\n let content = ''\n try {\n content = fs.readFileSync(serverFile.path, 'utf-8')\n } catch {\n /* file may not exist */\n }\n const methods = HTTP_METHODS.filter(\n m =>\n content.includes(`export const ${m}`) ||\n content.includes(`export async function ${m}`) ||\n content.includes(`export function ${m}`),\n )\n if (methods.length === 0) methods.push('GET')\n endpoints.push({ route: route.id, path: route.path, methods, file: serverFile.path })\n }\n return endpoints\n}\n\nexport interface ApiRequestInput {\n url: string\n method: string\n /** JSON-encoded header object (as typed by the user). */\n headers: string\n body: string\n}\n\n/**\n * Send a request to a public URL or the dev server itself (SSRF-guarded) and\n * report the response. Redirects are returned, never followed.\n */\nexport async function sendApiRequest(\n input: ApiRequestInput,\n options: OutboundUrlOptions = {},\n): Promise<ApiResponse> {\n const start = performance.now()\n const duration = () => Math.round((performance.now() - start) * 100) / 100\n try {\n await assertOutboundUrl(input.url, options)\n const parsedHeaders = input.headers ? JSON.parse(input.headers) : {}\n const init: RequestInit = { method: input.method, headers: parsedHeaders, redirect: 'manual' }\n if (input.body && input.method !== 'GET' && input.method !== 'HEAD') init.body = input.body\n const res = await fetch(input.url, init)\n const body = await res.text()\n const headers: Record<string, string> = {}\n res.headers.forEach((v, k) => {\n headers[k] = v\n })\n return { status: res.status, statusText: res.statusText, headers, body, duration: duration() }\n } catch (e) {\n return { status: 0, statusText: String(e), headers: {}, body: '', duration: duration() }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { BuildAnalysis, BuildChunk } from '../types.js'\n\nconst WEB_EXTENSIONS = new Set(['.js', '.css', '.html'])\n\n/** Scan common SvelteKit build output directories for emitted web assets. */\nexport function analyzeBuild(root: string): BuildAnalysis {\n const chunks: BuildChunk[] = []\n const dirs = [\n path.resolve(root, '.svelte-kit/output'),\n path.resolve(root, 'build/client'),\n path.resolve(root, 'build'),\n ]\n const walkDir = (d: string) => {\n for (const entry of fs.readdirSync(d, { withFileTypes: true })) {\n const full = path.join(d, entry.name)\n if (entry.isDirectory()) {\n walkDir(full)\n continue\n }\n if (!WEB_EXTENSIONS.has(path.extname(entry.name).toLowerCase())) continue\n chunks.push({\n name: entry.name,\n file: path.relative(root, full),\n size: fs.statSync(full).size,\n modules: [],\n isEntry: entry.name.includes('index') || entry.name.includes('start'),\n })\n }\n }\n for (const dir of dirs) {\n try {\n walkDir(dir)\n } catch {\n /* directory doesn't exist or not readable */\n }\n }\n chunks.sort((a, b) => b.size - a.size)\n return { chunks, totalSize: chunks.reduce((s, c) => s + c.size, 0), timestamp: Date.now() }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { ModuleGraphData, ModuleNode } from '../types.js'\n\n/** Minimal shape of a Vite module-graph node that we read. */\nexport interface GraphModuleLike {\n file?: string | null\n importedModules: Iterable<{ file?: string | null }>\n}\n\nfunction classify(file: string): ModuleNode['type'] {\n const ext = path.extname(file).toLowerCase()\n if (ext === '.svelte') return 'svelte'\n if (ext === '.ts') return 'ts'\n if (ext === '.js') return 'js'\n if (ext === '.css') return 'css'\n return 'other'\n}\n\n/**\n * Build the project-local module graph (node_modules and files outside\n * `root` excluded) and detect import cycles.\n */\nexport function buildModuleGraph(root: string, allModules: GraphModuleLike[]): ModuleGraphData {\n const modules: ModuleNode[] = []\n const idMap = new Map<string, ModuleNode>()\n const moduleById = new Map<string, ModuleNode>()\n\n for (const mod of allModules) {\n if (!mod.file || mod.file.includes('node_modules')) continue\n const relFile = path.relative(root, mod.file)\n if (relFile.startsWith('..')) continue\n if (idMap.has(mod.file)) continue // deduplicate across environments\n let size: number | undefined\n try {\n size = fs.statSync(mod.file).size\n } catch {\n /* ignore */\n }\n const node: ModuleNode = {\n id: relFile,\n file: mod.file,\n type: classify(mod.file),\n importedBy: [],\n imports: [],\n size,\n }\n idMap.set(mod.file, node)\n moduleById.set(relFile, node)\n modules.push(node)\n }\n\n // Build edges using Sets for O(1) dedup\n const importedBySets = new Map<ModuleNode, Set<string>>()\n for (const mod of allModules) {\n if (!mod.file) continue\n const node = idMap.get(mod.file)\n if (!node) continue\n const importsSet = new Set(node.imports)\n for (const imp of mod.importedModules) {\n const impNode = imp.file ? idMap.get(imp.file) : undefined\n if (!impNode) continue\n if (!importsSet.has(impNode.id)) {\n importsSet.add(impNode.id)\n node.imports.push(impNode.id)\n }\n let by = importedBySets.get(impNode)\n if (!by) importedBySets.set(impNode, (by = new Set(impNode.importedBy)))\n if (!by.has(node.id)) {\n by.add(node.id)\n impNode.importedBy.push(node.id)\n }\n }\n }\n\n // Detect cycles (DFS), push/pop path buffer to avoid array copies\n const cycles: string[][] = []\n const visited = new Set<string>()\n const stack = new Set<string>()\n const pathBuf: string[] = []\n function dfs(id: string) {\n if (stack.has(id)) {\n const cycleStart = pathBuf.indexOf(id)\n if (cycleStart >= 0) {\n const cycle = pathBuf.slice(cycleStart).concat(id)\n if (cycle.length > 2) cycles.push(cycle) // skip self-references\n }\n return\n }\n if (visited.has(id)) return\n visited.add(id)\n stack.add(id)\n pathBuf.push(id)\n const node = moduleById.get(id)\n if (node) for (const imp of node.imports) dfs(imp)\n pathBuf.pop()\n stack.delete(id)\n }\n for (const m of modules) dfs(m.id)\n\n const cyclicIds = new Set(cycles.flat())\n for (const m of modules) if (cyclicIds.has(m.id)) m.isCyclic = true\n\n return { modules, cycles }\n}\n","import { assertOutboundUrl } from '../security.js'\nimport type { OutboundUrlOptions } from '../security.js'\nimport type { OGPreview } from '../types.js'\n\n/**\n * Fetch a public URL (or a page of the dev server itself) and report its Open\n * Graph tags + missing-tag issues. Redirects are not followed.\n */\nexport async function getOGPreview(\n url: string,\n options: OutboundUrlOptions = {},\n): Promise<OGPreview> {\n const preview: OGPreview = { url, title: '', description: '', image: '', tags: [], issues: [] }\n try {\n await assertOutboundUrl(url, options)\n const res = await fetch(url, { redirect: 'manual' })\n if (res.status >= 300 && res.status < 400) {\n preview.issues.push(\n `Redirects to ${res.headers.get('location') ?? '(no location)'} (not followed)`,\n )\n return preview\n }\n const html = await res.text()\n // Attribute-order independent; matches both <meta ...> and <meta ... />\n const metaRegex = /<meta\\s+([^>]*?)\\/?>/gi\n const propRegex = /(?:property|name)=[\"']([^\"']+)[\"']/\n const contentRegex = /content=[\"']([^\"']+)[\"']/\n let match\n while ((match = metaRegex.exec(html)) !== null) {\n const attrs = match[1]\n const propMatch = attrs.match(propRegex)\n const contentMatch = attrs.match(contentRegex)\n if (propMatch && contentMatch) {\n const prop = propMatch[1]\n const content = contentMatch[1]\n preview.tags.push({ property: prop, content })\n if (prop === 'og:title') preview.title = content\n else if (prop === 'og:description') preview.description = content\n else if (prop === 'og:image') preview.image = content\n }\n }\n if (!preview.title) {\n const titleMatch = html.match(/<title>([^<]+)<\\/title>/i)\n if (titleMatch) preview.title = titleMatch[1]\n }\n if (!preview.description) {\n const descTag = preview.tags.find(t => t.property === 'description')\n if (descTag) preview.description = descTag.content\n }\n if (!preview.title) preview.issues.push('Missing og:title or <title>')\n if (!preview.description) preview.issues.push('Missing og:description or meta description')\n if (!preview.image) preview.issues.push('Missing og:image')\n if (!preview.tags.some(t => t.property === 'og:url')) preview.issues.push('Missing og:url')\n if (!preview.tags.some(t => t.property === 'og:type')) preview.issues.push('Missing og:type')\n } catch (e) {\n preview.issues.push(`Failed to fetch: ${String(e)}`)\n }\n return preview\n}\n","/**\n * Find the 1-based line of a reactive declaration in a component source:\n * the first `$effect(` / `$effect.pre(` for effects, otherwise the\n * `let|const|var <name>` declaration. Returns 0 when not found.\n */\nexport function findReactiveLine(source: string, name: string, type: string): number {\n const lines = source.split('\\n')\n if (type === 'effect') {\n const idx = lines.findIndex(l => l.includes('$effect(') || l.includes('$effect.pre('))\n return idx + 1\n }\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n const regex = new RegExp(`(?:let|const|var)\\\\s+${escaped}\\\\b`)\n const idx = lines.findIndex(l => regex.test(l))\n return idx + 1\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { defineDevframe, defineRpcFunction } from 'devframe'\nimport type { DevframeDefinition } from 'devframe'\nimport { z } from 'zod'\nimport { analyzeRoutes } from './analyzers/routes.js'\nimport { analyzeAssets } from './analyzers/assets.js'\nimport { analyzeProject } from './analyzers/project.js'\nimport { analyzeComponents } from './analyzers/components.js'\nimport { analyzeApiEndpoints, sendApiRequest } from './analyzers/api.js'\nimport { analyzeBuild } from './analyzers/build.js'\nimport { buildModuleGraph } from './analyzers/module-graph.js'\nimport type { GraphModuleLike } from './analyzers/module-graph.js'\nimport { getOGPreview } from './analyzers/og.js'\nimport { findReactiveLine } from './analyzers/source.js'\nimport { resolveWithinRoot } from './security.js'\nimport type { Collector } from './collector.js'\nimport type {\n ApiResponse,\n CaptureInfoMap,\n InspectResult,\n OGPreview,\n ReactiveGraphResult,\n ReactiveSummary,\n StateTimelineDelta,\n LiveComponentsMeta,\n} from './types.js'\n\nexport const DEVFRAME_ID = 'svelte-devtools'\n/** Mount base for both hosts (standalone and Vite DevTools), so the SPA URL never changes. */\nexport const DEVFRAME_BASE = '/.svelte-devtools/'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('../package.json') as {\n name: string\n version: string\n description: string\n homepage: string\n}\nconst clientAssets = path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'client')\n\n/**\n * Everything the portable devframe needs from whatever hosts it. The Vite\n * plugin implements this over its dev server; tests implement it directly.\n * Getters are lazy because the host resolves config after construction.\n */\nexport interface SvelteDevtoolsHost {\n collector: Collector\n /** Absolute project root. */\n root: () => string\n /** Public base the dev server serves the app (and static files) under. */\n publicBase: () => string\n /** Every module the dev server currently knows about, across environments. */\n modules: () => GraphModuleLike[]\n /** Compile a project file through the dev server's pipeline (absent without a server). */\n transformRequest?: (file: string) => Promise<{\n code: string\n map?: { mappings?: string; sources?: string[] } | string | null\n } | null>\n /** Origins the dev server itself is reachable at (API playground / OG preview may call them). */\n serverOrigins: () => string[]\n /** Open `file[:line]` in the user's editor. */\n openInEditor: (target: string) => void\n}\n\nconst filePath = z.string().min(1).max(4096)\n\nexport function createRpcFunctions(host: SvelteDevtoolsHost) {\n const { collector } = host\n const project = () => analyzeProject(host.root())\n const routes = () => analyzeRoutes(project().routesDir)\n\n return [\n defineRpcFunction({\n name: 'get-project',\n type: 'query',\n jsonSerializable: true,\n handler: () => project(),\n }),\n defineRpcFunction({\n name: 'get-routes',\n type: 'query',\n jsonSerializable: true,\n handler: () => routes(),\n }),\n defineRpcFunction({\n name: 'get-assets',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeAssets(project().staticDir, host.publicBase()),\n }),\n defineRpcFunction({\n name: 'get-component-relations',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeComponents(host.root()),\n }),\n defineRpcFunction({\n name: 'get-svelte-files',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeComponents(host.root()).map(c => ({ file: c.file, name: c.name })),\n }),\n defineRpcFunction({\n name: 'get-live-components',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.liveComponents,\n }),\n defineRpcFunction({\n name: 'get-live-components-meta',\n type: 'query',\n jsonSerializable: true,\n handler: (): LiveComponentsMeta => ({\n total: collector.liveComponentsTotal,\n kept: collector.liveComponents.length,\n truncated: collector.liveComponentsTotal > collector.liveComponents.length,\n ...collector.epochInfo,\n }),\n }),\n defineRpcFunction({\n name: 'set-active',\n type: 'action',\n jsonSerializable: true,\n args: [z.object({ client: z.string().min(1).max(64), active: z.boolean() })],\n returns: z.void(),\n handler: ({ client, active }) => {\n if (active) collector.lease(`ui:${client}`)\n else collector.release(`ui:${client}`)\n },\n }),\n defineRpcFunction({\n name: 'open-in-editor',\n type: 'action',\n jsonSerializable: true,\n args: [z.object({ file: filePath, line: z.number().int().nonnegative().optional() })],\n returns: z.void(),\n handler: ({ file, line }) => {\n const resolved = resolveWithinRoot(host.root(), file)\n host.openInEditor(line ? `${resolved}:${line}` : resolved)\n },\n }),\n defineRpcFunction({\n name: 'open-reactive-in-editor',\n type: 'action',\n jsonSerializable: true,\n args: [z.object({ file: filePath, name: z.string().max(256), type: z.string().max(32) })],\n returns: z.void(),\n handler: ({ file, name, type }) => {\n const resolved = resolveWithinRoot(host.root(), file)\n let line = 0\n try {\n line = findReactiveLine(fs.readFileSync(resolved, 'utf-8'), name, type)\n } catch {\n /* file not readable */\n }\n host.openInEditor(line > 0 ? `${resolved}:${line}` : resolved)\n },\n }),\n defineRpcFunction({\n name: 'get-render-profiles',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.renderProfiles,\n }),\n defineRpcFunction({\n name: 'get-reactive-graph',\n type: 'query',\n jsonSerializable: true,\n // Omitted = whole app (older clients). Scoped requests are built by the\n // runtime within the caps (docs/devframe-migration.md §6.7 A).\n args: [\n z\n .object({\n componentId: z.number().int().nonnegative().optional(),\n epoch: z.string().max(200).optional(),\n maxNodes: z.number().int().positive().optional(),\n maxEdges: z.number().int().positive().optional(),\n })\n .optional(),\n ],\n returns: z.custom<ReactiveGraphResult>(),\n handler: req => collector.requestReactiveGraph(req ?? {}),\n }),\n defineRpcFunction({\n name: 'get-reactive-summary',\n type: 'query',\n jsonSerializable: true,\n // Overview aggregate from runtime counters; never captures the graph (§6.7 I).\n args: [\n z\n .object({\n topK: z.number().int().positive().optional(),\n windowMs: z.number().int().positive().optional(),\n })\n .optional(),\n ],\n returns: z.custom<ReactiveSummary>(),\n handler: req => collector.requestReactiveSummary(req ?? {}),\n }),\n defineRpcFunction({\n name: 'get-capture-info',\n type: 'query',\n jsonSerializable: true,\n handler: (): CaptureInfoMap => collector.getCaptureInfo(),\n }),\n defineRpcFunction({\n name: 'get-load-profiles',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.loadProfiles,\n }),\n defineRpcFunction({\n name: 'clear-load-profiles',\n type: 'action',\n jsonSerializable: true,\n handler: () => collector.clearLoadProfiles(),\n }),\n defineRpcFunction({\n name: 'get-state-timeline',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.requestStateTimeline(),\n }),\n defineRpcFunction({\n name: 'get-state-timeline-delta',\n type: 'query',\n jsonSerializable: true,\n args: [z.object({ since: z.number().int().nonnegative().optional() })],\n returns: z.custom<StateTimelineDelta>(),\n // Served from the buffer the runtime pushes into; never pulls the app.\n handler: ({ since }) => collector.getStateTimelineDelta(since),\n }),\n defineRpcFunction({\n name: 'get-versions',\n type: 'query',\n jsonSerializable: true,\n handler: () => ({ ...collector.versions }),\n }),\n defineRpcFunction({\n name: 'clear-state-timeline',\n type: 'action',\n jsonSerializable: true,\n handler: () => collector.clearStateTimeline(),\n }),\n defineRpcFunction({\n name: 'get-api-endpoints',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeApiEndpoints(routes()),\n }),\n defineRpcFunction({\n name: 'send-api-request',\n type: 'action',\n jsonSerializable: true,\n args: [\n z.object({\n url: z.string().max(8192),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']),\n headers: z.string().max(65536),\n body: z.string().max(1_000_000),\n }),\n ],\n returns: z.custom<ApiResponse>(),\n handler: input => sendApiRequest(input, { allowedOrigins: host.serverOrigins() }),\n }),\n defineRpcFunction({\n name: 'get-compiler-warnings',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.compilerWarnings,\n }),\n defineRpcFunction({\n name: 'get-runtime-errors',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.runtimeErrors,\n }),\n defineRpcFunction({\n name: 'clear-errors',\n type: 'action',\n jsonSerializable: true,\n handler: () => collector.clearErrors(),\n }),\n defineRpcFunction({\n name: 'inspect-file',\n type: 'query',\n jsonSerializable: true,\n args: [z.object({ file: filePath })],\n returns: z.custom<InspectResult>(),\n handler: async ({ file }): Promise<InspectResult> => {\n const empty: InspectResult = { source: '', compiled: '', file }\n let resolved: string\n let source: string\n try {\n resolved = resolveWithinRoot(host.root(), file)\n source = fs.readFileSync(resolved, 'utf-8')\n } catch {\n return empty\n }\n if (!host.transformRequest) return { ...empty, source }\n try {\n const result = await host.transformRequest(resolved)\n const map = typeof result?.map === 'string' ? JSON.parse(result.map) : result?.map\n return {\n source,\n compiled: result?.code || '',\n file,\n mappings: map?.mappings,\n sources: map?.sources,\n }\n } catch {\n return { source, compiled: '// Transform failed', file }\n }\n },\n }),\n defineRpcFunction({\n name: 'get-module-graph',\n type: 'query',\n jsonSerializable: true,\n handler: () => buildModuleGraph(host.root(), host.modules()),\n }),\n defineRpcFunction({\n name: 'get-og-preview',\n type: 'action',\n jsonSerializable: true,\n args: [z.object({ url: z.string().max(8192) })],\n returns: z.custom<OGPreview>(),\n handler: ({ url }) => getOGPreview(url, { allowedOrigins: host.serverOrigins() }),\n }),\n defineRpcFunction({\n name: 'get-build-analysis',\n type: 'query',\n jsonSerializable: true,\n handler: () => analyzeBuild(host.root()),\n }),\n defineRpcFunction({\n name: 'get-fps',\n type: 'query',\n jsonSerializable: true,\n handler: () => collector.fpsSamples,\n }),\n defineRpcFunction({\n name: 'clear-fps',\n type: 'action',\n jsonSerializable: true,\n handler: () => collector.clearFps(),\n }),\n ] as const\n}\n\n/**\n * The portable Svelte DevTools tool. Host-agnostic: the same definition is\n * mounted standalone (`initDevframe`) or inside Vite DevTools\n * (`createPluginFromDevframe`); the SPA in `dist/client` connects with\n * `connectDevframe()` either way.\n */\nexport function createSvelteDevframe(host: SvelteDevtoolsHost): DevframeDefinition {\n return defineDevframe({\n id: DEVFRAME_ID,\n name: 'Svelte',\n version: pkg.version,\n packageName: pkg.name,\n importMetaUrl: import.meta.url,\n homepage: pkg.homepage,\n description: pkg.description,\n icon: 'simple-icons:svelte',\n basePath: DEVFRAME_BASE,\n // Live data from an instrumented dev server only; a static export would be an empty shell.\n capabilities: { dev: true, build: false },\n dock: { category: 'framework' },\n clientAssets,\n setup(ctx) {\n const scoped = ctx.scope(DEVFRAME_ID)\n for (const fn of createRpcFunctions(host)) scoped.rpc.register(fn)\n },\n })\n}\n","import os from 'node:os'\nimport type { Server } from 'node:http'\nimport type { AddressInfo } from 'node:net'\nimport type { ViteDevServer } from 'vite'\nimport type { DevframeDefinition } from 'devframe'\nimport { initDevframe } from 'devframe/initiate'\nimport type { DevframeInstance } from 'devframe/initiate'\nimport { DEVFRAME_BASE } from './devframe.js'\n\nconst WILDCARD = new Set(['0.0.0.0', '::'])\nconst LOOPBACK = new Set(['127.0.0.1', '::1', 'localhost'])\n\nfunction formatHost(address: string): string {\n return address.includes(':') ? `[${address}]` : address\n}\n\n/**\n * Origins a browser may load the DevTools from when the dev server is\n * reachable beyond loopback (`server.host`). devframe accepts loopback\n * origins by default and rejects every other WS `Origin` unless listed.\n */\nexport function networkOrigins(address: AddressInfo, proto: string): string[] {\n if (LOOPBACK.has(address.address)) return []\n const hosts = WILDCARD.has(address.address)\n ? Object.values(os.networkInterfaces())\n .flat()\n .filter(i => i && !i.internal)\n .map(i => i!.address)\n : [address.address]\n return hosts.map(h => `${proto}://${formatHost(h)}:${address.port}`)\n}\n\n/**\n * Serve the devframe standalone on this dev server: SPA, discovery,\n * WebSocket RPC on Vite's own HTTP server at `<base>__ws`, auth gate.\n *\n * The instance is created per server and closed by *that* server's `close`\n * event, so a restart (which builds the new server before closing the old\n * one) can never tear down the new instance.\n */\nexport function mountStandalone(\n server: ViteDevServer,\n def: DevframeDefinition,\n): (() => Promise<void>) | undefined {\n let instance: DevframeInstance | undefined\n let closed = false\n const httpServer = server.httpServer\n\n server.middlewares.use((req, res, next) => {\n if (instance) return instance.nodeMiddleware(req, res, next)\n if (req.url?.startsWith(DEVFRAME_BASE)) {\n // Not listening yet (or already closed): don't let the app's SPA\n // fallback answer for the DevTools.\n res.statusCode = 503\n res.end('Svelte DevTools is starting')\n return\n }\n next()\n })\n\n if (!httpServer) {\n // Middleware mode: no server to share the upgrade with, so devframe\n // serves its SSE transport through the same middleware. There is no\n // `close` event either: the caller disposes via Vite's `closeServer` hook.\n const created = initDevframe(def, { base: DEVFRAME_BASE, ws: false, sse: true, mcp: false })\n instance = created\n return async () => {\n instance = undefined\n await created.close().catch(() => {})\n }\n }\n\n httpServer.once('listening', () => {\n const address = httpServer.address()\n if (closed || !address || typeof address === 'string') return\n const proto = server.config.server.https ? 'https' : 'http'\n const local = `${proto}://localhost:${address.port}`\n instance = initDevframe(def, {\n base: DEVFRAME_BASE,\n // Vite's https server is an HTTP/2 server with HTTP/1 fallback; it emits\n // the same `upgrade` events devframe listens for.\n server: httpServer as Server,\n mcp: false,\n // The auth banner's magic link is built from `origin`; point it at the\n // SPA so opening it authenticates (the app root has no devframe client).\n origin: `${local}${DEVFRAME_BASE}`,\n allowedOrigins: networkOrigins(address, proto),\n })\n server.config.logger.info(` ➜ Svelte DevTools: ${local}${DEVFRAME_BASE}`)\n })\n\n httpServer.once('close', () => {\n closed = true\n const current = instance\n instance = undefined\n current?.close().catch(() => {})\n })\n return undefined\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport type { RenderProfile, LoadProfile, FpsSample } from '../types.js'\n\nexport interface SessionSnapshot {\n /** componentId -> { renderCount, totalRenderTime } at snapshot moment */\n renderProfiles: Array<{\n componentId: number\n file: string\n name: string\n renderCount: number\n totalRenderTime: number\n }>\n loadProfilesCount: number\n fpsCount: number\n takenAt: number\n}\n\nexport interface SessionRecord {\n id: string\n label: string\n startedAt: number\n endedAt?: number\n persist: boolean\n startSnapshot: SessionSnapshot\n endSnapshot?: SessionSnapshot\n /** load profiles that arrived strictly between startedAt..endedAt */\n loadProfiles: LoadProfile[]\n /** fps samples that arrived strictly between startedAt..endedAt */\n fpsSamples: FpsSample[]\n}\n\nexport interface SessionDelta {\n durationMs: number\n components: Array<{\n componentId: number\n file: string\n name: string\n renderCountDelta: number\n totalRenderTimeDelta: number\n avgRenderTimeDelta: number\n }>\n loadProfiles: {\n count: number\n avgDuration: number\n p95Duration: number\n }\n fps: {\n samples: number\n avg: number\n min: number\n drops: number\n }\n}\n\nexport interface SessionDiff {\n a: { id: string; label: string }\n b: { id: string; label: string }\n render: {\n totalRenderTimeDeltaA: number\n totalRenderTimeDeltaB: number\n diff: number\n verdict: 'improved' | 'regressed' | 'unchanged'\n }\n load: {\n avgA: number\n avgB: number\n diff: number\n verdict: 'improved' | 'regressed' | 'unchanged'\n }\n fps: {\n avgA: number\n avgB: number\n diff: number\n verdict: 'improved' | 'regressed' | 'unchanged'\n }\n}\n\nexport interface MetricGetters {\n getRenderProfiles: () => RenderProfile[]\n getLoadProfiles: () => LoadProfile[]\n getFpsSamples: () => FpsSample[]\n}\n\nconst UNCHANGED_RENDER_THRESHOLD_MS = 1\nconst UNCHANGED_LOAD_THRESHOLD_MS = 5\nconst UNCHANGED_FPS_THRESHOLD = 1\nconst FPS_DROP_THRESHOLD = 30\n\nfunction takeSnapshot(getters: MetricGetters): SessionSnapshot {\n const renderProfiles = getters.getRenderProfiles().map(p => ({\n componentId: p.componentId,\n file: p.file,\n name: p.name,\n renderCount: p.renderCount,\n totalRenderTime: p.totalRenderTime,\n }))\n return {\n renderProfiles,\n loadProfilesCount: getters.getLoadProfiles().length,\n fpsCount: getters.getFpsSamples().length,\n takenAt: Date.now(),\n }\n}\n\nfunction classify(\n diff: number,\n threshold: number,\n lowerIsBetter: boolean,\n): 'improved' | 'regressed' | 'unchanged' {\n if (Math.abs(diff) < threshold) return 'unchanged'\n const negativeIsBetter = lowerIsBetter\n if (negativeIsBetter) return diff < 0 ? 'improved' : 'regressed'\n return diff > 0 ? 'improved' : 'regressed'\n}\n\n/**\n * The only id shape `start()` issues: `s_<Date.now() base36>_<6 hex>`. Ids\n * reach the store from MCP clients and become file names, so anything else\n * (path separators, `..`, absolute paths) is rejected before touching disk\n * (review C-7).\n */\nexport const SESSION_ID_PATTERN = /^s_[0-9a-z]{1,16}_[0-9a-f]{6}$/\n\nexport function isSessionId(id: unknown): id is string {\n return typeof id === 'string' && SESSION_ID_PATTERN.test(id)\n}\n\nexport interface SessionStoreOptions {\n persistDir: string\n getters: MetricGetters\n}\n\nexport class SessionStore {\n private sessions = new Map<string, SessionRecord>()\n private active: string | null = null\n private readonly persistDir: string\n private readonly getters: MetricGetters\n\n constructor(opts: SessionStoreOptions) {\n this.persistDir = path.resolve(opts.persistDir)\n this.getters = opts.getters\n }\n\n start(label: string, persist: boolean): SessionRecord {\n if (this.active) {\n throw new Error(\n `A session is already active: ${this.active}. Call end_session before starting a new one.`,\n )\n }\n const id = `s_${Date.now().toString(36)}_${crypto.randomBytes(3).toString('hex')}`\n const record: SessionRecord = {\n id,\n label,\n startedAt: Date.now(),\n persist,\n startSnapshot: takeSnapshot(this.getters),\n loadProfiles: [],\n fpsSamples: [],\n }\n this.sessions.set(id, record)\n this.active = id\n return record\n }\n\n /** Called by the plugin whenever a new load profile arrives. */\n recordLoadProfile(p: LoadProfile): void {\n if (!this.active) return\n const rec = this.sessions.get(this.active)\n if (rec) rec.loadProfiles.push(p)\n }\n\n /** Called by the plugin whenever a new fps sample arrives. */\n recordFpsSample(s: FpsSample): void {\n if (!this.active) return\n const rec = this.sessions.get(this.active)\n if (rec) rec.fpsSamples.push(s)\n }\n\n end(keep: 'memory' | 'disk' | 'discard'): SessionRecord {\n if (!this.active) throw new Error('No active session')\n const rec = this.sessions.get(this.active)\n if (!rec) throw new Error('Active session missing from store')\n rec.endedAt = Date.now()\n rec.endSnapshot = takeSnapshot(this.getters)\n this.active = null\n\n if (keep === 'discard') {\n this.sessions.delete(rec.id)\n } else if (keep === 'disk' || rec.persist) {\n this.persistToDisk(rec)\n }\n return rec\n }\n\n get(id: string): SessionRecord | undefined {\n if (!isSessionId(id)) return undefined\n const inMem = this.sessions.get(id)\n if (inMem) return inMem\n return this.loadFromDisk(id)\n }\n\n list(): Array<{\n id: string\n label: string\n startedAt: number\n endedAt?: number\n persisted: boolean\n active: boolean\n }> {\n const seen = new Set<string>()\n const out: Array<{\n id: string\n label: string\n startedAt: number\n endedAt?: number\n persisted: boolean\n active: boolean\n }> = []\n for (const rec of this.sessions.values()) {\n seen.add(rec.id)\n out.push({\n id: rec.id,\n label: rec.label,\n startedAt: rec.startedAt,\n endedAt: rec.endedAt,\n persisted: fs.existsSync(this.pathFor(rec.id)),\n active: this.active === rec.id,\n })\n }\n try {\n if (fs.existsSync(this.persistDir)) {\n for (const name of fs.readdirSync(this.persistDir)) {\n if (!name.endsWith('.json')) continue\n const id = name.slice(0, -5)\n if (!isSessionId(id) || seen.has(id)) continue\n try {\n const rec = JSON.parse(fs.readFileSync(this.pathFor(id), 'utf-8'))\n // A file whose content claims another id is not listed under it.\n if (rec?.id !== id) continue\n out.push({\n id: rec.id,\n label: rec.label,\n startedAt: rec.startedAt,\n endedAt: rec.endedAt,\n persisted: true,\n active: false,\n })\n } catch {\n /* skip unreadable session file */\n }\n }\n }\n } catch {\n /* persist dir not accessible */\n }\n return out.sort((a, b) => b.startedAt - a.startedAt)\n }\n\n delete(id: string): boolean {\n if (!isSessionId(id)) return false\n const had = this.sessions.delete(id)\n let onDisk = false\n try {\n const p = this.pathFor(id)\n if (fs.existsSync(p)) {\n fs.unlinkSync(p)\n onDisk = true\n }\n } catch {\n /* ignore */\n }\n if (this.active === id) this.active = null\n return had || onDisk\n }\n\n delta(id: string): SessionDelta {\n const rec = this.get(id)\n if (!rec) throw new Error(`Session not found: ${id}`)\n if (!rec.endSnapshot || rec.endedAt === undefined) {\n throw new Error(`Session ${id} has not been ended yet`)\n }\n const startMap = new Map(rec.startSnapshot.renderProfiles.map(p => [p.componentId, p]))\n const components = rec.endSnapshot.renderProfiles\n .map(end => {\n const start = startMap.get(end.componentId)\n const startRenderCount = start?.renderCount ?? 0\n const startTotal = start?.totalRenderTime ?? 0\n const renderCountDelta = end.renderCount - startRenderCount\n const totalRenderTimeDelta = end.totalRenderTime - startTotal\n return {\n componentId: end.componentId,\n file: end.file,\n name: end.name,\n renderCountDelta,\n totalRenderTimeDelta,\n avgRenderTimeDelta: renderCountDelta > 0 ? totalRenderTimeDelta / renderCountDelta : 0,\n }\n })\n .filter(c => c.renderCountDelta > 0)\n .sort((a, b) => b.totalRenderTimeDelta - a.totalRenderTimeDelta)\n\n const loadDurations = rec.loadProfiles.map(l => l.duration)\n const loadAvg = avg(loadDurations)\n const loadP95 = percentile(loadDurations, 95)\n\n const fpsValues = rec.fpsSamples.map(s => s.fps)\n const fpsAvg = avg(fpsValues)\n const fpsMin = fpsValues.length ? Math.min(...fpsValues) : 0\n const fpsDrops = fpsValues.filter(f => f < FPS_DROP_THRESHOLD).length\n\n return {\n durationMs: rec.endedAt - rec.startedAt,\n components,\n loadProfiles: { count: rec.loadProfiles.length, avgDuration: loadAvg, p95Duration: loadP95 },\n fps: { samples: fpsValues.length, avg: fpsAvg, min: fpsMin, drops: fpsDrops },\n }\n }\n\n compare(idA: string, idB: string): SessionDiff {\n const a = this.delta(idA)\n const b = this.delta(idB)\n const recA = this.get(idA)!\n const recB = this.get(idB)!\n const totalA = a.components.reduce((s, c) => s + c.totalRenderTimeDelta, 0)\n const totalB = b.components.reduce((s, c) => s + c.totalRenderTimeDelta, 0)\n const renderDiff = totalB - totalA\n const loadDiff = b.loadProfiles.avgDuration - a.loadProfiles.avgDuration\n const fpsDiff = b.fps.avg - a.fps.avg\n return {\n a: { id: recA.id, label: recA.label },\n b: { id: recB.id, label: recB.label },\n render: {\n totalRenderTimeDeltaA: totalA,\n totalRenderTimeDeltaB: totalB,\n diff: renderDiff,\n verdict: classify(renderDiff, UNCHANGED_RENDER_THRESHOLD_MS, true),\n },\n load: {\n avgA: a.loadProfiles.avgDuration,\n avgB: b.loadProfiles.avgDuration,\n diff: loadDiff,\n verdict: classify(loadDiff, UNCHANGED_LOAD_THRESHOLD_MS, true),\n },\n fps: {\n avgA: a.fps.avg,\n avgB: b.fps.avg,\n diff: fpsDiff,\n verdict: classify(fpsDiff, UNCHANGED_FPS_THRESHOLD, false),\n },\n }\n }\n\n /** The session's file, guaranteed to be a direct child of `persistDir`. */\n private pathFor(id: string): string {\n if (!isSessionId(id)) throw new Error('Invalid session id')\n const file = path.resolve(this.persistDir, `${id}.json`)\n if (path.dirname(file) !== this.persistDir) throw new Error('Invalid session id')\n return file\n }\n\n private persistToDisk(rec: SessionRecord): void {\n try {\n fs.mkdirSync(this.persistDir, { recursive: true })\n fs.writeFileSync(this.pathFor(rec.id), JSON.stringify(rec, null, 2), { mode: 0o600 })\n } catch {\n /* persist failure is non-fatal; the in-memory record stays available */\n }\n }\n\n private loadFromDisk(id: string): SessionRecord | undefined {\n try {\n const raw = fs.readFileSync(this.pathFor(id), 'utf-8')\n const rec = JSON.parse(raw)\n return rec?.id === id ? rec : undefined\n } catch {\n return undefined\n }\n }\n}\n\nfunction avg(xs: number[]): number {\n if (!xs.length) return 0\n return xs.reduce((s, x) => s + x, 0) / xs.length\n}\n\nfunction percentile(xs: number[], p: number): number {\n if (!xs.length) return 0\n const sorted = [...xs].sort((a, b) => a - b)\n const idx = Math.min(sorted.length - 1, Math.floor((p / 100) * sorted.length))\n return sorted[idx]\n}\n","import type { RenderProfile, ReactiveGraph, LoadProfile, FpsSample } from '../types.js'\n\nexport type IssueKind =\n | 'slow-component-render'\n | 'over-rendered-component'\n | 'slow-load'\n | 'fps-drop'\n | 'effect-overconnected'\n\nexport interface PerformanceIssue {\n id: string\n kind: IssueKind\n severity: 'low' | 'medium' | 'high'\n summary: string\n file?: string\n line?: number\n metric: Record<string, number>\n /** Tool that returns more detail for this issue. */\n suggestedTool: string\n}\n\nexport interface IssueThresholds {\n /** Per-render time (ms) above which a component render is considered slow. */\n avgRenderTimeMs?: number\n /** Render count above which a component is considered over-rendered. */\n renderCount?: number\n /** Load duration (ms) above which a SvelteKit load is slow. */\n loadDurationMs?: number\n /** FPS below which we record a drop. */\n fpsDropThreshold?: number\n /** Outgoing edge count from an effect above which it is over-connected. */\n effectMaxDeps?: number\n}\n\nconst DEFAULTS: Required<IssueThresholds> = {\n avgRenderTimeMs: 4,\n renderCount: 30,\n loadDurationMs: 200,\n fpsDropThreshold: 40,\n effectMaxDeps: 8,\n}\n\nexport interface IssueInputs {\n renderProfiles: RenderProfile[]\n reactiveGraph: ReactiveGraph\n loadProfiles: LoadProfile[]\n fpsSamples: FpsSample[]\n}\n\nexport function listPerformanceIssues(\n inputs: IssueInputs,\n thresholds: IssueThresholds = {},\n): PerformanceIssue[] {\n const t = { ...DEFAULTS, ...thresholds }\n const out: PerformanceIssue[] = []\n\n for (const p of inputs.renderProfiles) {\n const avg = p.renderCount > 0 ? p.totalRenderTime / p.renderCount : 0\n if (avg >= t.avgRenderTimeMs) {\n out.push({\n id: `slow-render:${p.file}:${p.componentId}`,\n kind: 'slow-component-render',\n severity:\n avg >= t.avgRenderTimeMs * 4 ? 'high' : avg >= t.avgRenderTimeMs * 2 ? 'medium' : 'low',\n summary: `${p.name} averages ${avg.toFixed(2)}ms per render (${p.renderCount} renders)`,\n file: p.file,\n metric: {\n avgRenderTimeMs: round(avg),\n renderCount: p.renderCount,\n totalRenderTimeMs: round(p.totalRenderTime),\n },\n suggestedTool: 'get_render_profile',\n })\n }\n if (p.renderCount >= t.renderCount) {\n out.push({\n id: `over-render:${p.file}:${p.componentId}`,\n kind: 'over-rendered-component',\n severity:\n p.renderCount >= t.renderCount * 8\n ? 'high'\n : p.renderCount >= t.renderCount * 3\n ? 'medium'\n : 'low',\n summary: `${p.name} rendered ${p.renderCount} times`,\n file: p.file,\n metric: { renderCount: p.renderCount, avgRenderTimeMs: round(avg) },\n suggestedTool: 'get_component_hotspots',\n })\n }\n }\n\n for (const l of inputs.loadProfiles) {\n if (l.duration >= t.loadDurationMs) {\n out.push({\n id: `slow-load:${l.route}:${l.timestamp}`,\n kind: 'slow-load',\n severity:\n l.duration >= t.loadDurationMs * 5\n ? 'high'\n : l.duration >= t.loadDurationMs * 2\n ? 'medium'\n : 'low',\n summary: `${l.type} load for ${l.route} took ${l.duration.toFixed(0)}ms`,\n file: l.file,\n metric: { durationMs: round(l.duration), dataSizeBytes: l.dataSize },\n suggestedTool: 'get_load_waterfall',\n })\n }\n }\n\n const fpsDrops = inputs.fpsSamples.filter(s => s.fps < t.fpsDropThreshold)\n if (fpsDrops.length > 0) {\n const min = Math.min(...fpsDrops.map(s => s.fps))\n out.push({\n id: `fps-drops:${inputs.fpsSamples[0]?.timestamp ?? 0}`,\n kind: 'fps-drop',\n severity: min < 15 ? 'high' : min < 30 ? 'medium' : 'low',\n summary: `${fpsDrops.length} FPS samples below ${t.fpsDropThreshold} (min ${min})`,\n metric: { dropCount: fpsDrops.length, minFps: min, threshold: t.fpsDropThreshold },\n suggestedTool: 'get_fps_drops',\n })\n }\n\n // Reactive graph: count incoming (dependency) edges per node\n const inDegree = new Map<string, number>()\n for (const e of inputs.reactiveGraph.edges) {\n inDegree.set(e.to, (inDegree.get(e.to) ?? 0) + 1)\n }\n for (const node of inputs.reactiveGraph.nodes) {\n if (node.type === 'effect') {\n const deps = inDegree.get(node.id) ?? 0\n if (deps >= t.effectMaxDeps) {\n out.push({\n id: `effect-deps:${node.id}`,\n kind: 'effect-overconnected',\n severity:\n deps >= t.effectMaxDeps * 3 ? 'high' : deps >= t.effectMaxDeps * 2 ? 'medium' : 'low',\n summary: `effect \"${node.name}\" depends on ${deps} reactive values`,\n file: node.componentFile,\n metric: { depCount: deps },\n suggestedTool: 'get_reactive_graph_problems',\n })\n }\n }\n }\n\n return out.sort(compareSeverity)\n}\n\nconst SEV_RANK: Record<PerformanceIssue['severity'], number> = { high: 0, medium: 1, low: 2 }\n\nfunction compareSeverity(a: PerformanceIssue, b: PerformanceIssue): number {\n return SEV_RANK[a.severity] - SEV_RANK[b.severity]\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100\n}\n\nexport interface ReactiveProblems {\n effects: Array<{ id: string; name: string; file: string; depCount: number }>\n /**\n * `$derived` values nothing has read so far (never evaluated). A derived\n * read only imperatively (event handler, plain function) is evaluated and\n * is not listed: having no effect/markup reader is not \"unused\".\n */\n orphanDeriveds: Array<{ id: string; name: string; file: string }>\n /**\n * Nodes without any dependency or tracked reader (markup reads included).\n * A node depending only on untracked signals (`untrackedDeps`) is not listed.\n */\n isolatedNodes: Array<{ id: string; name: string; type: string; file: string }>\n}\n\nexport function summarizeReactiveProblems(\n graph: ReactiveGraph,\n t: IssueThresholds = {},\n): ReactiveProblems {\n const thresh = { ...DEFAULTS, ...t }\n const inDegree = new Map<string, number>()\n const outDegree = new Map<string, number>()\n for (const e of graph.edges) {\n inDegree.set(e.to, (inDegree.get(e.to) ?? 0) + 1)\n outDegree.set(e.from, (outDegree.get(e.from) ?? 0) + 1)\n }\n const effects: ReactiveProblems['effects'] = []\n const orphanDeriveds: ReactiveProblems['orphanDeriveds'] = []\n const isolatedNodes: ReactiveProblems['isolatedNodes'] = []\n for (const node of graph.nodes) {\n const ind = inDegree.get(node.id) ?? 0\n const outd = outDegree.get(node.id) ?? 0\n if (node.type === 'effect' && ind >= thresh.effectMaxDeps) {\n effects.push({ id: node.id, name: node.name, file: node.componentFile, depCount: ind })\n }\n if (node.type === 'template') continue\n if (node.type === 'derived' && node.unevaluated) {\n orphanDeriveds.push({ id: node.id, name: node.name, file: node.componentFile })\n } else if (ind === 0 && outd === 0 && !node.untrackedDeps) {\n isolatedNodes.push({\n id: node.id,\n name: node.name,\n type: node.type,\n file: node.componentFile,\n })\n }\n }\n return { effects, orphanDeriveds, isolatedNodes }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'\nimport { z } from 'zod'\nimport type {\n RenderProfile,\n ReactiveGraph,\n LoadProfile,\n FpsSample,\n ComponentInstance,\n ProjectInfo,\n RouteInfo,\n ComponentRelation,\n CaptureInfoMap,\n ReactiveGraphRequest,\n ReactiveGraphResult,\n ReactiveSummary,\n ReactiveSummaryRequest,\n StateTimelineDelta,\n} from '../types.js'\nimport { SessionStore, SESSION_ID_PATTERN } from './sessions.js'\nimport { listPerformanceIssues, summarizeReactiveProblems, type IssueThresholds } from './issues.js'\n\nexport interface McpDeps {\n getProject: () => ProjectInfo\n getRoutes: () => RouteInfo[]\n getLiveComponents: () => ComponentInstance[]\n /**\n * The served page load's components with its epoch, read together\n * (`get_live_components` with `includeMeta`).\n */\n getLiveSnapshot?: () => { epoch: string | null; total: number; components: ComponentInstance[] }\n getComponentRelations: () => ComponentRelation[]\n getRenderProfiles: () => RenderProfile[]\n /** Resolves with the current reactive graph after refreshing from the browser. */\n getReactiveGraph: () => Promise<ReactiveGraph>\n getLoadProfiles: () => LoadProfile[]\n getFpsSamples: () => FpsSample[]\n sessions: SessionStore\n // Bounded reactivity tools (docs/devframe-migration.md §6.7); registered only when provided.\n getReactiveSummary?: (req: ReactiveSummaryRequest) => Promise<ReactiveSummary>\n getReactiveScope?: (req: ReactiveGraphRequest) => Promise<ReactiveGraphResult>\n getStateTimelineDelta?: (since?: number) => StateTimelineDelta\n getCaptureInfo?: () => CaptureInfoMap\n}\n\n/** Most timeline entries one `get_state_timeline` call returns. */\nexport const MCP_TIMELINE_LIMIT = 500\n/** Default / largest JSON size of one old/new value in `get_state_timeline` output. */\nexport const MCP_VALUE_CHARS = { default: 2048, max: 32768 } as const\n\n/** A state value for MCP output: as is when small, otherwise a size summary. */\nfunction capValue(value: unknown, maxChars: number): unknown {\n let json: string | undefined\n try {\n json = JSON.stringify(value)\n } catch {\n return { omitted: 'not serializable' }\n }\n if (json === undefined || json.length <= maxChars) return value\n return {\n omitted: 'too large',\n chars: json.length,\n preview: json.slice(0, Math.min(200, maxChars)),\n }\n}\n\n/** Session ids as issued by `start_session`; anything else is rejected before the store. */\nconst sessionId = z.string().max(64).regex(SESSION_ID_PATTERN, 'not a session id')\n\nconst TEXT = (value: unknown) => ({\n content: [\n {\n type: 'text' as const,\n text: typeof value === 'string' ? value : JSON.stringify(value, null, 2),\n },\n ],\n})\n\nexport function buildMcpServer(deps: McpDeps): McpServer {\n const server = new McpServer({\n name: 'vite-devtools-svelte',\n version: '0.1.0',\n })\n\n // --- read tools: issue surface ---\n\n server.registerTool(\n 'list_performance_issues',\n {\n title: 'List performance issues',\n description:\n 'Cross-cuts render/reactive/load/fps metrics and returns ranked issues. The entry point for AI-driven performance audits. Each issue carries `suggestedTool` naming the detail tool to call next.',\n inputSchema: {\n avgRenderTimeMs: z.number().optional(),\n renderCount: z.number().optional(),\n loadDurationMs: z.number().optional(),\n fpsDropThreshold: z.number().optional(),\n effectMaxDeps: z.number().optional(),\n },\n },\n async args => {\n const thresholds: IssueThresholds = args\n const reactiveGraph = await deps.getReactiveGraph()\n const issues = listPerformanceIssues(\n {\n renderProfiles: deps.getRenderProfiles(),\n reactiveGraph,\n loadProfiles: deps.getLoadProfiles(),\n fpsSamples: deps.getFpsSamples(),\n },\n thresholds,\n )\n return TEXT({ count: issues.length, issues })\n },\n )\n\n server.registerTool(\n 'get_component_hotspots',\n {\n title: 'Component render hotspots',\n description: 'Top components by total render time, with render count and per-render average.',\n inputSchema: { topN: z.number().int().min(1).max(200).optional() },\n },\n async ({ topN = 20 }) => {\n const list = [...deps.getRenderProfiles()]\n .map(p => ({\n file: p.file,\n name: p.name,\n componentId: p.componentId,\n renderCount: p.renderCount,\n totalRenderTimeMs: round(p.totalRenderTime),\n avgRenderTimeMs: round(p.renderCount > 0 ? p.totalRenderTime / p.renderCount : 0),\n lastRenderTimeMs: round(p.lastRenderTime),\n lastRenderAt: p.lastRenderAt,\n }))\n .sort((a, b) => b.totalRenderTimeMs - a.totalRenderTimeMs)\n .slice(0, topN)\n return TEXT(list)\n },\n )\n\n server.registerTool(\n 'get_reactive_graph_problems',\n {\n title: 'Reactive graph problems',\n description:\n 'Classified reactive graph issues: over-connected effects, orphan deriveds (declared but never evaluated so far — may still be read later, e.g. in a branch not shown yet), isolated nodes (no tracked dependency or reader; reads from the markup count as readers). Returns categories instead of the full graph.',\n inputSchema: { effectMaxDeps: z.number().int().min(1).optional() },\n },\n async ({ effectMaxDeps }) => {\n const graph = await deps.getReactiveGraph()\n return TEXT(summarizeReactiveProblems(graph, { effectMaxDeps }))\n },\n )\n\n server.registerTool(\n 'get_load_waterfall',\n {\n title: 'SvelteKit load waterfall',\n description:\n 'Load profiles grouped by route, with timing and data size. Optionally filtered by route.',\n inputSchema: { route: z.string().optional() },\n },\n async ({ route }) => {\n let profiles = deps.getLoadProfiles()\n if (route) profiles = profiles.filter(p => p.route === route)\n const byRoute = new Map<string, LoadProfile[]>()\n for (const p of profiles) {\n const arr = byRoute.get(p.route) ?? []\n arr.push(p)\n byRoute.set(p.route, arr)\n }\n const groups = [...byRoute.entries()].map(([r, ps]) => {\n const durations = ps.map(p => p.duration)\n return {\n route: r,\n file: ps[0]?.file,\n count: ps.length,\n avgDuration: round(avg(durations)),\n maxDuration: round(Math.max(...durations)),\n totalDataBytes: ps.reduce((s, p) => s + p.dataSize, 0),\n samples: ps,\n }\n })\n return TEXT(groups.sort((a, b) => b.avgDuration - a.avgDuration))\n },\n )\n\n server.registerTool(\n 'get_fps_drops',\n {\n title: 'FPS drops',\n description: 'Samples whose FPS fell below `threshold`. Returns timestamp + fps for each.',\n inputSchema: {\n threshold: z.number().min(1).max(120).optional(),\n sinceMs: z.number().optional(),\n },\n },\n async ({ threshold = 40, sinceMs }) => {\n let samples = deps.getFpsSamples()\n if (sinceMs !== undefined) {\n const cutoff = Date.now() - sinceMs\n samples = samples.filter(s => s.timestamp >= cutoff)\n }\n const drops = samples.filter(s => s.fps < threshold)\n return TEXT({\n threshold,\n sampleCount: samples.length,\n dropCount: drops.length,\n minFps: drops.length ? Math.min(...drops.map(s => s.fps)) : null,\n drops,\n })\n },\n )\n\n server.registerTool(\n 'get_render_profile',\n {\n title: 'Render profile for a specific file',\n description:\n 'Returns render profile entries matching the given component file (substring match).',\n inputSchema: { file: z.string() },\n },\n async ({ file }) => {\n const matches = deps\n .getRenderProfiles()\n .filter(p => p.file.includes(file))\n .map(p => ({\n ...p,\n totalRenderTimeMs: round(p.totalRenderTime),\n avgRenderTimeMs: round(p.renderCount > 0 ? p.totalRenderTime / p.renderCount : 0),\n }))\n return TEXT(matches)\n },\n )\n\n // --- context tools ---\n\n server.registerTool(\n 'get_project_info',\n {\n title: 'Project info',\n description: 'Package name/version, Svelte / SvelteKit / Vite versions, dependency lists.',\n inputSchema: {},\n },\n async () => TEXT(deps.getProject()),\n )\n\n server.registerTool(\n 'get_routes',\n {\n title: 'SvelteKit routes',\n description: 'Static analysis of the SvelteKit routes tree.',\n inputSchema: {},\n },\n async () => TEXT(deps.getRoutes()),\n )\n\n server.registerTool(\n 'get_live_components',\n {\n title: 'Currently mounted components',\n description:\n 'Component instances with file, parent, mounted status as currently mounted in the browser (an array, parents first). With `includeMeta: true` the answer is `{ epoch, total, captured, truncated, components }` instead, limited to `limit` (default 1000): component ids are only valid within that `epoch` (one page load), so pass both to get_reactive_scope.',\n inputSchema: {\n includeMeta: z.boolean().optional(),\n limit: z.number().int().min(1).max(50000).optional(),\n },\n },\n async ({ includeMeta, limit }) => {\n if (!includeMeta || !deps.getLiveSnapshot) {\n // Unchanged default: the bare array older clients expect (`limit` only when given).\n const all = deps.getLiveComponents()\n return TEXT(limit === undefined ? all : all.slice(0, limit))\n }\n const snap = deps.getLiveSnapshot()\n const max = limit ?? 1000\n return TEXT({\n epoch: snap.epoch,\n total: snap.total,\n captured: snap.components.length,\n truncated: snap.total > snap.components.length || snap.components.length > max,\n components: snap.components.slice(0, max),\n })\n },\n )\n\n server.registerTool(\n 'get_component_relations',\n {\n title: 'Component import graph',\n description: 'Static import relations between .svelte components.',\n inputSchema: {},\n },\n async () => TEXT(deps.getComponentRelations()),\n )\n\n // --- bounded reactivity tools (read only; every answer says what it covers) ---\n\n if (deps.getReactiveSummary) {\n const getSummary = deps.getReactiveSummary\n server.registerTool(\n 'get_reactive_summary',\n {\n title: 'Reactive overview (top components)',\n description:\n 'Busiest component instances from runtime counters over all instances, without capturing the graph. Counts are sampled state changes (at most one per state per 200 ms) and renders within the window, not rates. Tracked: state created during component init and shared state of .svelte.js/.ts modules (rows with kind \"module\"; their componentId is a module scope id, usable with get_reactive_scope). `rows` + `other` add up to the totals; null means unknown. Use get_reactive_scope with a componentId to look at one instance. The same request is answered from a cache for up to 1 s; `window.until` says when the answer was computed.',\n inputSchema: {\n topK: z.number().int().min(1).max(200).optional(),\n windowMs: z.number().int().min(1000).max(60000).optional(),\n },\n },\n async ({ topK, windowMs }) => TEXT(await getSummary({ topK, windowMs })),\n )\n }\n\n if (deps.getReactiveScope) {\n const getScope = deps.getReactiveScope\n server.registerTool(\n 'get_reactive_scope',\n {\n title: 'Reactive graph of one component',\n description:\n \"$state/$derived/$effect nodes of one component instance and their direct neighbours, built in the app within the caps. Edges mean 'can affect' (current dependencies), not a recorded cause. `componentId` requires the `epoch` it came from (get_live_components with includeMeta): after a reload the answer is empty with staleReason 'epoch-changed' instead of another instance. Omit componentId only for the whole-app graph (capped; see total/truncated). The same request may be answered from a cache for up to 1 s; `computedAt` says when the app built the graph (null when unknown or for an empty fallback). `stale: true` only marks a fallback after the app did not answer (an earlier answer with its own computedAt, or empty).\",\n inputSchema: {\n componentId: z.number().int().nonnegative().optional(),\n epoch: z.string().max(200).optional(),\n maxNodes: z.number().int().min(1).max(5000).optional(),\n maxEdges: z.number().int().min(1).max(20000).optional(),\n },\n },\n async ({ componentId, epoch, maxNodes, maxEdges }) => {\n if (componentId !== undefined && epoch === undefined)\n return {\n content: [\n {\n type: 'text' as const,\n text: 'componentId requires epoch (from get_live_components with includeMeta: true)',\n },\n ],\n isError: true,\n }\n return TEXT(await getScope({ componentId, epoch, maxNodes, maxEdges }))\n },\n )\n }\n\n if (deps.getStateTimelineDelta) {\n const getDelta = deps.getStateTimelineDelta\n server.registerTool(\n 'get_state_timeline',\n {\n title: 'State changes since a cursor',\n description:\n 'Sampled $state changes (200 ms) after `since` (the cursor from the previous call). Contains values of state in the running app. `reset: true` means the cursor was stale and this is the whole buffer. At most `limit` newest entries are returned; `omitted` counts older ones in the range that were left out. Values larger than `maxValueChars` (JSON) are replaced by a size summary. Timestamps are detection times, so order within about a second is not causal.',\n inputSchema: {\n since: z.number().int().nonnegative().optional(),\n limit: z.number().int().min(1).max(MCP_TIMELINE_LIMIT).optional(),\n maxValueChars: z.number().int().min(16).max(MCP_VALUE_CHARS.max).optional(),\n },\n },\n async ({ since, limit, maxValueChars }) => {\n const delta = getDelta(since)\n const max = limit ?? 100\n const valueChars = maxValueChars ?? MCP_VALUE_CHARS.default\n const omitted = Math.max(0, delta.changes.length - max)\n const changes = delta.changes.slice(omitted).map(c => ({\n ...c,\n oldValue: capValue(c.oldValue, valueChars),\n newValue: capValue(c.newValue, valueChars),\n }))\n return TEXT({ ...delta, changes, omitted, maxValueChars: valueChars })\n },\n )\n }\n\n if (deps.getCaptureInfo) {\n const getInfo = deps.getCaptureInfo\n server.registerTool(\n 'get_capture_info',\n {\n title: 'What the DevTools hold versus what the app reported',\n description:\n 'Per dataset: captured count, total (null = unknown), truncated, selection policy and dropped counts by reason. Read this before drawing conclusions from capped data.',\n inputSchema: {},\n },\n async () => TEXT(getInfo()),\n )\n }\n\n // --- session tools ---\n\n server.registerTool(\n 'start_session',\n {\n title: 'Start measurement session',\n description:\n 'Begin capturing metrics under a labelled session. Required before compare_sessions. Set `persist:true` to write to disk on end; otherwise the session lives in memory only.',\n inputSchema: {\n label: z.string(),\n persist: z.boolean().optional(),\n },\n },\n async ({ label, persist = false }) => {\n const rec = deps.sessions.start(label, persist)\n return TEXT({ id: rec.id, label: rec.label, startedAt: rec.startedAt, persist: rec.persist })\n },\n )\n\n server.registerTool(\n 'end_session',\n {\n title: 'End current measurement session',\n description:\n 'Closes the active session and returns its delta. `keep` decides disposal: \"memory\" keeps it for this dev-server lifetime, \"disk\" writes to .vite-devtools-svelte/sessions/, \"discard\" deletes it.',\n inputSchema: {\n keep: z.enum(['memory', 'disk', 'discard']).optional(),\n },\n },\n async ({ keep = 'memory' }) => {\n const rec = deps.sessions.end(keep)\n const delta = rec.endedAt ? deps.sessions.delta(rec.id) : null\n return TEXT({\n id: rec.id,\n label: rec.label,\n startedAt: rec.startedAt,\n endedAt: rec.endedAt,\n keep,\n delta,\n })\n },\n )\n\n server.registerTool(\n 'compare_sessions',\n {\n title: 'Compare two sessions',\n description:\n 'Diff render / load / fps metrics between two ended sessions. Each section carries `verdict`: improved | regressed | unchanged.',\n inputSchema: { a: sessionId, b: sessionId },\n },\n async ({ a, b }) => TEXT(deps.sessions.compare(a, b)),\n )\n\n server.registerTool(\n 'list_sessions',\n {\n title: 'List sessions',\n description: 'In-memory + on-disk sessions, most recent first.',\n inputSchema: {},\n },\n async () => TEXT(deps.sessions.list()),\n )\n\n server.registerTool(\n 'load_session',\n {\n title: 'Load a session by id',\n description: 'Returns the full session record (including delta if ended) by id.',\n inputSchema: { id: sessionId },\n },\n async ({ id }) => {\n const rec = deps.sessions.get(id)\n if (!rec) return TEXT({ error: `Session not found: ${id}` })\n const delta = rec.endedAt ? deps.sessions.delta(id) : null\n return TEXT({ ...rec, delta })\n },\n )\n\n server.registerTool(\n 'delete_session',\n {\n title: 'Delete a session',\n description: 'Removes a session from memory and disk.',\n inputSchema: { id: sessionId },\n },\n async ({ id }) => TEXT({ deleted: deps.sessions.delete(id) }),\n )\n\n return server\n}\n\nexport { StreamableHTTPServerTransport }\n\nfunction avg(xs: number[]): number {\n if (!xs.length) return 0\n return xs.reduce((s, x) => s + x, 0) / xs.length\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100\n}\n","/// <reference types=\"@vitejs/devtools-kit\" />\nimport { DEVTOOLS_MOUNT_PATH } from '@vitejs/devtools-kit/constants'\nimport type { Plugin } from 'vite'\n\n/**\n * SvelteKit dev bypasses Vite's `transformIndexHtml`, so `@vitejs/devtools`'s\n * `DevToolsInjection` never reaches the served HTML and the dock is invisible\n * on every SvelteKit page. Tracked upstream at\n * https://github.com/baseballyama/vite-devtools-repl/tree/main/sveltekit-transform-index-html-bypass\n *\n * As a stopgap, SvelteKit inlines `src/app.html` as a JS string literal inside\n * `.svelte-kit/generated/server/internal.js`:\n *\n * templates: {\n * app: ({ head, body, ... }) => \"<!doctype html>...<body>...</body>...\",\n * }\n *\n * That file is loaded through Vite's module pipeline (`vite.ssrLoadModule`),\n * so a regular `transform` hook can rewrite the literal to insert the dock's\n * inject script before `</body>`. The actual `<script>` runs in the browser\n * once the HTML is delivered, so no SSR safety guard on the inject module is\n * needed for this path.\n *\n * This is intentionally narrow — SvelteKit-specific path match plus a\n * structural assertion — and there's a test (`template-injector.test.ts`)\n * that fails if SvelteKit's generated shape changes, so a silent break shows\n * up in CI instead of as a missing dock in production.\n */\n\nexport const SVELTEKIT_INTERNAL_SUFFIX = '.svelte-kit/generated/server/internal.js'\n\n/**\n * SvelteKit 3 writes the same `templates: { app: … }` server module to\n * `generated/dev/server.js` while serving (and `generated/build/server.js`\n * for builds, which this dev-only plugin never sees).\n */\nexport const SVELTEKIT3_DEV_SERVER_SUFFIX = '.svelte-kit/generated/dev/server.js'\n\nconst GENERATED_SERVER_SUFFIXES = [SVELTEKIT_INTERNAL_SUFFIX, SVELTEKIT3_DEV_SERVER_SUFFIX]\n\n/** Marker that the `templates.app` literal in SvelteKit's generated server. */\nexport const TEMPLATE_APP_MARKER = 'templates: {'\n\n/**\n * The dock bootstrap the Vite DevTools hub serves itself (`@vitejs/devtools`\n * >= 0.7.6 injects the same `<mount>embedded.js` through `transformIndexHtml`;\n * the old `@vitejs/devtools/client/inject` module no longer exists). The hub's\n * middleware answers this URL before Vite's transform pipeline, and SvelteKit\n * HTML never goes through Vite's HTML processing, so a plain static `src` is\n * enough — and, unlike an inline loader, works under a strict `script-src 'self'`.\n */\nconst INJECT_SCRIPT_URL = `${DEVTOOLS_MOUNT_PATH}embedded.js`\n/** The tag, escaped because we're editing a JS string literal. */\nconst INJECT_TAG = `<script type=\\\\\"module\\\\\" src=\\\\\"${INJECT_SCRIPT_URL}\\\\\"></script>`\n\n/**\n * `</body>` as it appears inside SvelteKit's generated string literal.\n * SvelteKit emits `app.html` via `JSON.stringify`-style escaping, which leaves\n * `/` alone — only control characters and quotes are escaped. So the literal\n * substring we actually search for is plain `</body>`.\n */\nconst BODY_CLOSE = '</body>'\n\n/**\n * Transform `.svelte-kit/generated/server/internal.js` to add the\n * `@vitejs/devtools` inject script right before `</body>` inside the app\n * template literal. Exposed for unit testing.\n *\n * Returns the new source if a substitution was made, or `null` to signal\n * \"nothing to do\" (already injected, structural marker missing, etc.).\n */\nexport function injectIntoSvelteKitInternal(code: string): string | null {\n // Cheap structural sanity check — bail if SvelteKit changed how it generates\n // the template object. The companion test asserts this branch is reachable.\n if (!code.includes(TEMPLATE_APP_MARKER)) return null\n if (!code.includes(BODY_CLOSE)) return null\n\n // Idempotence: don't double-inject across HMR re-runs.\n if (code.includes(INJECT_SCRIPT_URL)) return null\n\n // Only patch the literal that follows the `templates: {` marker, so a\n // future `</body>` mentioned in unrelated source code won't be touched.\n const markerIdx = code.indexOf(TEMPLATE_APP_MARKER)\n const bodyIdx = code.indexOf(BODY_CLOSE, markerIdx)\n if (bodyIdx === -1) return null\n\n return code.slice(0, bodyIdx) + INJECT_TAG + code.slice(bodyIdx)\n}\n\n/**\n * Vite plugin: inject the Vite DevTools dock bootstrap into SvelteKit's\n * dev-only generated server template. Dev-only by construction.\n *\n * Only when the Vite DevTools hub is actually present: standalone has no\n * hub serving `/__devtools/embedded.js`, so the tag would fail to load.\n * `isHosted` is read in `transform` rather than `apply` because `apply` runs\n * while the plugin list is still being resolved; every `configResolved` hook\n * has finished before the server transforms its first module.\n */\nexport function sveltekitTemplateInjector(isHosted: () => boolean): Plugin {\n return {\n name: 'vite-devtools-svelte:sveltekit-template-injector',\n enforce: 'post',\n apply: (_userConfig, env) => env.command === 'serve' && !env.isSsrBuild,\n\n transform(code, id) {\n if (!GENERATED_SERVER_SUFFIXES.some(suffix => id.endsWith(suffix))) return\n if (!isHosted()) return\n const next = injectIntoSvelteKitInternal(code)\n if (next === null) return\n return { code: next, map: null }\n },\n }\n}\n","import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport { launchEditor } from 'devframe/utils/launch-editor'\nimport { analyzeRoutes } from './analyzers/routes.js'\nimport { analyzeProject } from './analyzers/project.js'\nimport { analyzeComponents } from './analyzers/components.js'\nimport type { GraphModuleLike } from './analyzers/module-graph.js'\nimport {\n RUNTIME_MODULE_ID,\n RESOLVED_RUNTIME_ID,\n runtimeCode,\n WRAPPER_MODULE_ID,\n wrapperCode,\n} from './runtime.js'\nimport { Collector } from './collector.js'\nimport { createSvelteDevframe, DEVFRAME_BASE } from './devframe.js'\nimport type { SvelteDevtoolsHost } from './devframe.js'\nimport { mountStandalone } from './mount.js'\nimport { SessionStore } from './mcp/sessions.js'\nimport { buildMcpServer, StreamableHTTPServerTransport } from './mcp/server.js'\nimport { sveltekitTemplateInjector } from './template-injector.js'\nimport type { LoadProfile } from './types.js'\n\nexport interface SvelteDevtoolsOptions {\n /**\n * Enable component tracking via code injection.\n * @default true\n */\n componentTracking?: boolean\n}\n\n/** Name of `@vitejs/devtools`' config plugin; its presence means the hub will call our `devtools.setup`. */\nconst VITE_DEVTOOLS_PLUGIN = 'vite:devtools'\nconst WARN_SINK = Symbol.for('vite-devtools-svelte:warn-sink')\n\n// Shared by every plugin instance in the process: a config-file restart\n// builds a *new* plugin instance for the new server, so only a process-wide\n// counter tells the old instance that a newer server exists.\nlet serverGeneration = 0\n\n/** Collect every module the dev server knows, across Vite 8 environments (legacy graph as fallback). */\nfunction collectModules(server: ViteDevServer): GraphModuleLike[] {\n const modules: GraphModuleLike[] = []\n for (const env of Object.values(server.environments ?? {})) {\n const graph = (env as { moduleGraph?: { idToModuleMap?: Map<string, GraphModuleLike> } })\n .moduleGraph\n if (graph?.idToModuleMap) modules.push(...graph.idToModuleMap.values())\n }\n if (modules.length === 0) {\n const legacy = (server as { moduleGraph?: { idToModuleMap?: Map<string, GraphModuleLike> } })\n .moduleGraph\n if (legacy?.idToModuleMap) modules.push(...legacy.idToModuleMap.values())\n }\n return modules\n}\n\n/**\n * Component-tracking transform for one compiled client `.svelte` module:\n * imports the runtime and names the file for the wrapper's next `push()`.\n * `null` when the module has no component (`$.push(`) to track.\n *\n * Nothing is inserted as a new line, so every original line keeps its\n * number (`map: null` = mappings unchanged; stack traces and the\n * compiler's sourcemap stay aligned).\n */\nexport function injectComponentTracking(code: string, id: string): string | null {\n if (!code.includes('$.push(')) return null\n const safeId = JSON.stringify(id)\n return (\n `import '${RUNTIME_MODULE_ID}';` +\n code.replace(\n /(\\$\\.push\\([^)]+\\);?)/,\n `if (typeof window !== 'undefined' && window.__SVELTE_DEVTOOLS__) { window.__SVELTE_DEVTOOLS__._pendingFile = ${safeId}; } $1`,\n )\n )\n}\n\n/** A Svelte module (`.svelte.js` / `.svelte.ts`, runes outside components). */\nexport const SVELTE_MODULE_RE = /\\.svelte\\.[cm]?[jt]s$/\n\n/**\n * Module-scope transform for one client Svelte module: signals created while\n * its body runs (shared state, `export const cart = $state(...)`) are tracked\n * under a scope named after the file. The body is bracketed by enter/leave\n * calls; nothing is inserted as a new line. The bracket is plain JS, so it\n * works before or after vite-plugin-svelte compiles the module (with\n * `svelteDevtools()` listed before `sveltekit()`, a `.svelte.ts` module is\n * compiled after this transform). `null` for a server-compiled module.\n */\nexport function injectModuleTracking(code: string, id: string): string | null {\n if (code.includes('svelte/internal/server')) return null\n const safeId = JSON.stringify(id)\n const dt = `(typeof window !== 'undefined' && window.__SVELTE_DEVTOOLS__)`\n return (\n `import '${RUNTIME_MODULE_ID}';if (${dt}) { window.__SVELTE_DEVTOOLS__._enterModule(${safeId}); }` +\n code +\n `\\n;if (${dt}) { window.__SVELTE_DEVTOOLS__._leaveModule(); }\\n`\n )\n}\n\nexport function svelteDevtools(options: SvelteDevtoolsOptions = {}): Plugin[] {\n const { componentTracking = true } = options\n\n let config: ResolvedConfig\n let server: ViteDevServer | undefined\n let root: string\n // When `@vitejs/devtools` is installed the hub mounts the devframe through\n // our `devtools` hook; otherwise we mount it ourselves. Never both: they\n // would claim the same base.\n let hostedByViteDevtools = false\n // Per-process token for the MCP endpoint (MCP clients are local processes,\n // not browser tabs, so they cannot use devframe's browser auth handshake).\n const mcpToken = crypto.randomUUID()\n\n // Session store for AI-driven measurement workflows. Built lazily after\n // `root` is resolved.\n let sessions: SessionStore | null = null\n function getSessions(): SessionStore {\n if (!sessions) {\n sessions = new SessionStore({\n persistDir: path.join(root, 'node_modules', '.vite-devtools-svelte', 'sessions'),\n getters: {\n getRenderProfiles: () => collector.renderProfiles,\n getLoadProfiles: () => collector.loadProfiles,\n getFpsSamples: () => collector.fpsSamples,\n },\n })\n }\n return sessions\n }\n\n const collector = new Collector({\n onFpsSample: sample => getSessions().recordFpsSample(sample),\n onLoadProfile: profile => getSessions().recordLoadProfile(profile),\n })\n\n const host: SvelteDevtoolsHost = {\n collector,\n root: () => root,\n publicBase: () => config?.base ?? '/',\n modules: () => (server ? collectModules(server) : []),\n transformRequest: file => (server ? server.transformRequest(file) : Promise.resolve(null)),\n serverOrigins: () => {\n const urls = server?.resolvedUrls\n if (!urls) return []\n return [...urls.local, ...urls.network].map(u => new URL(u).origin)\n },\n openInEditor: target => launchEditor(target),\n }\n const devframe = createSvelteDevframe(host)\n const middlewareModeMounts: Array<{ generation: number; dispose: () => Promise<void> }> = []\n\n const mainPlugin: Plugin = {\n name: 'vite-devtools-svelte',\n enforce: 'pre',\n apply: 'serve',\n\n // Surfaces the per-process MCP token for inter-plugin (and test)\n // consumption, so tests need no production-only flag.\n api: {\n getDevtoolsToken: () => mcpToken,\n },\n\n configResolved(resolvedConfig) {\n config = resolvedConfig\n root = config.root\n hostedByViteDevtools = config.plugins.some(p => p.name === VITE_DEVTOOLS_PLUGIN)\n },\n\n configureServer(devServer) {\n server = devServer\n const generation = ++serverGeneration\n collector.attach(devServer.hot)\n devServer.httpServer?.once('close', () => {\n if (server === devServer) {\n collector.detach()\n server = undefined\n }\n })\n\n if (!hostedByViteDevtools) {\n const dispose = mountStandalone(devServer, devframe)\n if (dispose) middlewareModeMounts.push({ generation, dispose })\n }\n\n const mcpServerFactory = () =>\n buildMcpServer({\n getProject: () => analyzeProject(root),\n getRoutes: () => analyzeRoutes(analyzeProject(root).routesDir),\n getLiveComponents: () => collector.liveComponents,\n getLiveSnapshot: () => collector.liveSnapshot,\n getComponentRelations: () => analyzeComponents(root),\n getRenderProfiles: () => collector.renderProfiles,\n getReactiveGraph: () => collector.requestReactiveGraph(),\n getLoadProfiles: () => collector.loadProfiles,\n getFpsSamples: () => collector.fpsSamples,\n sessions: getSessions(),\n getReactiveSummary: req => collector.requestReactiveSummary(req),\n getReactiveScope: req => collector.requestReactiveGraph(req),\n getStateTimelineDelta: since => collector.getStateTimelineDelta(since),\n getCaptureInfo: () => collector.getCaptureInfo(),\n })\n\n // Print a one-line `claude mcp add` snippet once the dev server is\n // actually listening — that's when we know the resolved port.\n devServer.httpServer?.once('listening', () => {\n try {\n const addr = devServer.httpServer?.address()\n if (!addr || typeof addr === 'string') return\n const proto = devServer.config.server?.https ? 'https' : 'http'\n // For wildcard / loopback bindings prefer the literal `localhost`\n // so the printed URL parses as-is. Brackets aren't enough for `::`\n // (wildcard) and `::1` is just a more verbose form of loopback.\n const loopbackOrWildcard =\n addr.address === '::' ||\n addr.address === '0.0.0.0' ||\n addr.address === '::1' ||\n addr.address === '127.0.0.1'\n const hostName = loopbackOrWildcard\n ? 'localhost'\n : addr.family === 'IPv6'\n ? `[${addr.address}]`\n : addr.address\n const url = `${proto}://${hostName}:${addr.port}/__svelte-devtools/mcp`\n const cmd = `claude mcp add --transport http svelte ${url} --header x-svelte-devtools-token:${mcpToken}`\n devServer.config.logger.info('')\n devServer.config.logger.info(` svelte-devtools MCP ready — register with Claude Code:`)\n devServer.config.logger.info(` ${cmd}`)\n devServer.config.logger.info('')\n } catch {\n /* logging is best-effort */\n }\n })\n\n // MCP endpoint: lets AI agents (Claude Code etc.) read metrics + run\n // measurement sessions over the Streamable HTTP transport. Same-origin\n // is *not* required because MCP clients are local processes that don't\n // run inside a browser tab; the token is the gate.\n devServer.middlewares.use('/__svelte-devtools/mcp', async (req, res) => {\n const tokenHeader = req.headers['x-svelte-devtools-token']\n const token = Array.isArray(tokenHeader) ? tokenHeader[0] : tokenHeader\n if (token !== mcpToken) {\n res.statusCode = 403\n res.end('Forbidden')\n return\n }\n // An agent talking to us is a consumer: keep the runtime sampling. If\n // this request woke the runtime up, give it a moment to send its\n // activation snapshot so the first answer isn't stale.\n if (collector.lease('mcp', 60_000)) await collector.waitForSnapshot(1000)\n // Build a fresh server+transport per request. Stateless mode in the\n // SDK still keeps per-instance bookkeeping that gets corrupted when\n // the same transport handles multiple requests.\n const mcpServer = mcpServerFactory()\n const mcpTransport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableJsonResponse: true,\n })\n mcpTransport.onerror = err => {\n devServer.config.logger.error(\n `[svelte-devtools] MCP transport error: ${err.stack || err.message}`,\n )\n }\n try {\n await mcpServer.connect(mcpTransport)\n // The SDK consumes the request body itself; pre-reading would\n // leave the stream empty.\n await mcpTransport.handleRequest(req as any, res as any)\n } catch (e) {\n devServer.config.logger.error(\n `[svelte-devtools] MCP handler error: ${\n e instanceof Error ? e.stack || e.message : String(e)\n }`,\n )\n if (!res.headersSent) {\n res.statusCode = 500\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({ error: String(e) }))\n }\n } finally {\n await mcpTransport.close().catch(() => {})\n await mcpServer.close().catch(() => {})\n }\n })\n },\n\n // Middleware-mode mounts have no `httpServer` close event; dispose them\n // from Vite's public `closeServer` hook (>= 8.3), which runs after the\n // server is torn down but carries no server reference. On restart Vite has\n // already configured the replacement server, so every mount older than\n // the newest server generation belongs to the server being torn down —\n // whether that server used this plugin instance (inline config) or a\n // previous one (config file, re-evaluated per restart).\n async closeServer({ reason }) {\n const doomed = middlewareModeMounts.filter(\n m => reason === 'close' || m.generation < serverGeneration,\n )\n for (const m of doomed) middlewareModeMounts.splice(middlewareModeMounts.indexOf(m), 1)\n await Promise.all(doomed.map(m => m.dispose()))\n },\n\n // Virtual module resolution: runtime + svelte/internal/client wrapper.\n // dev only — never resolve our virtual modules during production build.\n resolveId(id, importer) {\n if (config?.command !== 'serve') return undefined\n if (id === RUNTIME_MODULE_ID) return RESOLVED_RUNTIME_ID\n if (\n componentTracking &&\n id === 'svelte/internal/client' &&\n importer &&\n !importer.includes('node_modules') &&\n !importer.startsWith('\\0')\n ) {\n return WRAPPER_MODULE_ID\n }\n return undefined\n },\n\n load(id) {\n if (config?.command !== 'serve') return undefined\n if (id === RESOLVED_RUNTIME_ID) return runtimeCode\n if (id === WRAPPER_MODULE_ID) return wrapperCode\n return undefined\n },\n\n // Inject the runtime into the user's app\n // 'pre': the tag is injected before Vite's own HTML processing, which\n // rewrites the inline module's bare `virtual:` import to a URL the browser\n // can load (as a normal-order hook, the browser requested\n // 'virtual:svelte-devtools-runtime' itself and failed with a CORS error).\n transformIndexHtml: {\n order: 'pre',\n handler() {\n if (config.command !== 'serve') return []\n return [\n {\n tag: 'script',\n attrs: { type: 'module' },\n children: `import '${RUNTIME_MODULE_ID}'`,\n injectTo: 'head-prepend',\n },\n ]\n },\n },\n\n // Vite DevTools integration: only invoked by `@vitejs/devtools`. The kit\n // is imported lazily so apps without Vite DevTools never load it.\n devtools: {\n capabilities: { dev: true, build: false },\n async setup(ctx) {\n const { createPluginFromDevframe } = await import('@vitejs/devtools-kit/node')\n const plugin = createPluginFromDevframe(devframe, { base: DEVFRAME_BASE })\n await plugin.devtools?.setup?.(ctx)\n },\n },\n }\n\n // Minimal component tracking transform plugin.\n // Only injects the file path before $.push() so the runtime wrapper knows\n // which component file is being initialized. All reactive tracking (state,\n // derived, proxy, effect) is handled by the svelte/internal/client wrapper.\n const trackingPlugin: Plugin = {\n name: 'vite-devtools-svelte:tracking',\n enforce: 'post',\n apply: 'serve',\n\n transform(code, id, options) {\n if (!componentTracking) return null\n if (id.includes('node_modules')) return null\n if (config?.command !== 'serve') return null\n const file = id.split('?')[0]\n const modified = file.endsWith('.svelte')\n ? injectComponentTracking(code, id)\n : SVELTE_MODULE_RE.test(file) && !options?.ssr\n ? injectModuleTracking(code, file)\n : null\n return modified === null ? null : { code: modified, map: null }\n },\n }\n\n // Load function profiling transform plugin\n const loadProfilePlugin: Plugin = {\n name: 'vite-devtools-svelte:load-profile',\n enforce: 'post',\n apply: 'serve',\n\n transform(code, id) {\n if (config?.command !== 'serve') return null\n // Only transform SvelteKit load files\n const isServerLoad = /\\+page\\.server\\.[tj]s$/.test(id) || /\\+layout\\.server\\.[tj]s$/.test(id)\n const isUniversalLoad = /\\+(page|layout)\\.[tj]s$/.test(id) && !id.includes('.server.')\n if (!isServerLoad && !isUniversalLoad) return null\n if (id.includes('node_modules')) return null\n // Must have an exported load function\n if (!code.includes('export') || !code.includes('load')) return null\n\n const loadType = isServerLoad ? 'server' : 'universal'\n // Determine route from file path\n const routesMatch = id.match(/routes(.*)\\/\\+/)\n const route = routesMatch ? routesMatch[1] || '/' : '/'\n const safeRoute = JSON.stringify(route)\n const safeFile = JSON.stringify(id)\n const safeType = JSON.stringify(loadType)\n\n // Replace the exported load function with a profiled version.\n // Supports both `export const load = ...` and `export (async) function load(...)` patterns.\n let transformed = code.replace(/export\\s+const\\s+load\\s*=\\s*/, `const __original_load = `)\n\n if (transformed === code) {\n // Try `export function load` / `export async function load` pattern\n transformed = code.replace(\n /export\\s+(async\\s+)?function\\s+load\\s*\\(/,\n `const __original_load = $1function __load_impl(`,\n )\n }\n\n if (transformed === code) return null // no match found\n\n const profiledExport = `\nexport const load = async (event) => {\n const __start = performance.now();\n const __result = await __original_load(event);\n const __duration = performance.now() - __start;\n const __dataSize = JSON.stringify(__result || {}).length;\n if (typeof globalThis.__svelte_devtools_record_load === 'function') {\n globalThis.__svelte_devtools_record_load(${safeRoute}, ${safeFile}, ${safeType}, __duration, __dataSize);\n }\n return __result;\n};\n`\n return { code: transformed + profiledExport, map: null }\n },\n }\n\n // Register load profiling hook on server\n const loadProfileServerPlugin: Plugin = {\n name: 'vite-devtools-svelte:load-profile-server',\n apply: 'serve',\n\n configureServer() {\n // Make the recording function available globally on the server\n ;(globalThis as Record<string, unknown>).__svelte_devtools_record_load = (\n route: string,\n file: string,\n type: string,\n duration: number,\n dataSize: number,\n ) => {\n const entry: LoadProfile = {\n route,\n file,\n type: type as 'server' | 'universal',\n duration: Math.round(duration * 100) / 100,\n dataSize,\n timestamp: Date.now(),\n }\n collector.recordLoadProfile(entry)\n }\n },\n }\n\n // Compiler warning capture plugin\n const warningCapturePlugin: Plugin = {\n name: 'vite-devtools-svelte:warning-capture',\n enforce: 'post',\n apply: 'serve',\n\n configResolved(resolvedConfig) {\n // Intercept Svelte compiler warnings from the logger. A user\n // `customLogger` survives restarts, so the wrapper is installed once and\n // forwards to whichever plugin instance configured it last.\n const logger = resolvedConfig.logger as typeof resolvedConfig.logger & {\n [WARN_SINK]?: (msg: string) => void\n }\n const wrapped = WARN_SINK in logger\n logger[WARN_SINK] = msg => {\n // Svelte compiler warnings usually contain file paths and codes\n if (!msg.includes('.svelte') || config?.command !== 'serve') return\n const fileMatch = msg.match(/(?:^|\\s)((?:\\/|\\.\\/|\\w:)[^\\s:]+\\.svelte)(?::(\\d+):(\\d+))?/)\n const codeMatch = msg.match(/\\(([a-z0-9_-]+)\\)/)\n collector.recordCompilerWarning({\n code: codeMatch?.[1] || 'unknown',\n // oxlint-disable-next-line no-control-regex -- intentional: strip ANSI escape sequences\n message: msg.replace(/\\x1b\\[[0-9;]*m/g, '').trim(),\n file: fileMatch?.[1] || '',\n line: fileMatch?.[2] ? parseInt(fileMatch[2]) : undefined,\n column: fileMatch?.[3] ? parseInt(fileMatch[3]) : undefined,\n })\n }\n if (wrapped) return\n const originalWarn = logger.warn\n logger.warn = (msg: string, options?: { timestamp?: boolean }) => {\n logger[WARN_SINK]?.(msg)\n originalWarn(msg, options)\n }\n },\n }\n\n return [\n mainPlugin,\n trackingPlugin,\n loadProfilePlugin,\n loadProfileServerPlugin,\n warningCapturePlugin,\n sveltekitTemplateInjector(() => hostedByViteDevtools),\n ]\n}\n"],"mappings":"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"}