vite-devtools-svelte 0.6.0 → 0.6.1

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 (110) hide show
  1. package/dist/analyzers/html.d.ts +24 -0
  2. package/dist/analyzers/og.d.ts +2 -5
  3. package/dist/analyzers/project.d.ts +1 -0
  4. package/dist/analyzers/routes.d.ts +6 -0
  5. package/dist/analyzers/script.d.ts +26 -0
  6. package/dist/analyzers/source.d.ts +8 -3
  7. package/dist/analyzers/text.d.ts +6 -0
  8. package/dist/client/assets/ApiPlayground-r3PMCbhw.js +3 -0
  9. package/dist/client/assets/Assets-F6ySiRNw.js +1 -0
  10. package/dist/client/assets/BuildAnalysis-Ci5Or0e4.js +1 -0
  11. package/dist/client/assets/CaptureNotice-DNYJjRjY.js +1 -0
  12. package/dist/client/assets/{Components-Co50xTrv.css → Components-DcHDCSmh.css} +1 -1
  13. package/dist/client/assets/Components-DzrFq-Jl.js +2 -0
  14. package/dist/client/assets/DataTable-C8wIHfdk.js +1 -0
  15. package/dist/client/assets/ErrorDashboard-DvBrkCGu.js +1 -0
  16. package/dist/client/assets/FpsMonitor-Bot5x4nP.js +1 -0
  17. package/dist/client/assets/FpsMonitor-D0MLqumc.css +1 -0
  18. package/dist/client/assets/Inspect-TF2sVdn4.js +4 -0
  19. package/dist/client/assets/Inspector-pD5_jg0-.js +1 -0
  20. package/dist/client/assets/LiveControls-BDWnVlkm.js +1 -0
  21. package/dist/client/assets/LoadProfiler-9jiBcPzy.css +1 -0
  22. package/dist/client/assets/LoadProfiler-RcwiKanZ.js +1 -0
  23. package/dist/client/assets/ModuleGraph-BscNTo-U.js +1 -0
  24. package/dist/client/assets/OGPreview-Ca39RUrW.js +1 -0
  25. package/dist/client/assets/Overview-CNCVS-EJ.js +1 -0
  26. package/dist/client/assets/Panel-BoUvB1nh.js +1 -0
  27. package/dist/client/assets/ReactiveGraph-BInCBdAu.css +1 -0
  28. package/dist/client/assets/ReactiveGraph-BmQbARuQ.js +17 -0
  29. package/dist/client/assets/RefreshButton-QYzgSJG9.js +1 -0
  30. package/dist/client/assets/RenderProfiler-Brp8i8K4.js +1 -0
  31. package/dist/client/assets/RenderProfiler-C0XQZUzw.css +1 -0
  32. package/dist/client/assets/ResourceEmpty-BBhK6GZB.js +1 -0
  33. package/dist/client/assets/Routes-BS5YDx3C.js +1 -0
  34. package/dist/client/assets/SearchField-C1RVVJht.js +1 -0
  35. package/dist/client/assets/Segmented-CK2euuus.js +1 -0
  36. package/dist/client/assets/SplitView-D7jY4n9A.js +1 -0
  37. package/dist/client/assets/StatList-Cd2sByRK.js +1 -0
  38. package/dist/client/assets/StatList-CwVfs0x8.css +1 -0
  39. package/dist/client/assets/StateTimeline-CaYBN88_.js +1 -0
  40. package/dist/client/assets/TreeView-T5wWFSLQ.js +1 -0
  41. package/dist/client/assets/VirtualList-CLxNqdaN.js +1 -0
  42. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-DrvKG05N.js +1 -0
  43. package/dist/client/assets/capture.svelte-CetYVdiG.js +1 -0
  44. package/dist/client/assets/{collections-uqk9p1aQ.js → collections-BtFss6Lo.js} +1 -1
  45. package/dist/client/assets/index-BBFupqc_.js +3 -0
  46. package/dist/client/assets/index-C_6yCKMs.css +1 -0
  47. package/dist/client/assets/kind-options-BLIV2wQY.js +1 -0
  48. package/dist/client/assets/nanoid-Cya-tyvy.js +1 -0
  49. package/dist/client/assets/reactive-BQ_s2f5H.js +1 -0
  50. package/dist/client/assets/reactive-selection.svelte-DI6qEBmx.js +1 -0
  51. package/dist/client/assets/resource-f-V9vBwK.css +1 -0
  52. package/dist/client/assets/resource.svelte-GBY8qvgR.js +5 -0
  53. package/dist/client/assets/versions-Dmo1-Hsc.js +1 -0
  54. package/dist/client/index.html +5 -2
  55. package/dist/index.mjs +1739 -1529
  56. package/dist/index.mjs.map +1 -1
  57. package/dist/mcp/http.d.ts +24 -0
  58. package/dist/mcp/server.d.ts +6 -12
  59. package/dist/mcp/sessions.d.ts +20 -17
  60. package/dist/mcp/stats.d.ts +13 -0
  61. package/dist/plugin.d.ts +0 -6
  62. package/dist/runtime/transform.d.ts +2 -2
  63. package/dist/server/collector.d.ts +54 -109
  64. package/dist/server/compiler-warnings.d.ts +13 -0
  65. package/dist/server/devframe.d.ts +9 -9
  66. package/dist/server/load-profile.d.ts +12 -0
  67. package/dist/server/mount.d.ts +2 -0
  68. package/dist/server/payload.d.ts +11 -0
  69. package/dist/server/reactive.d.ts +30 -0
  70. package/dist/server/ring.d.ts +11 -0
  71. package/dist/server/security.d.ts +3 -1
  72. package/dist/server/state-timeline.d.ts +72 -0
  73. package/package.json +1 -1
  74. package/dist/client/assets/ApiPlayground-qRDX0tRk.js +0 -3
  75. package/dist/client/assets/Assets-yTFLB7w2.js +0 -1
  76. package/dist/client/assets/BuildAnalysis-C6yO6EJN.js +0 -1
  77. package/dist/client/assets/CaptureNotice-DykEK0Kp.js +0 -1
  78. package/dist/client/assets/Components-BTG8jKec.js +0 -2
  79. package/dist/client/assets/DataTable-C5C0HrMd.js +0 -1
  80. package/dist/client/assets/ErrorDashboard-DHdptxQP.js +0 -1
  81. package/dist/client/assets/FpsMonitor-BmS11Tn7.css +0 -1
  82. package/dist/client/assets/FpsMonitor-G1xRBjK3.js +0 -1
  83. package/dist/client/assets/Inspect-Ba_b5o73.js +0 -4
  84. package/dist/client/assets/Inspector-mTvtYmwt.js +0 -1
  85. package/dist/client/assets/LiveControls-nrc1-cBk.js +0 -1
  86. package/dist/client/assets/LoadProfiler-cg28l5zW.css +0 -1
  87. package/dist/client/assets/LoadProfiler-eYXaLPba.js +0 -1
  88. package/dist/client/assets/ModuleGraph-Dp-bJUnD.js +0 -1
  89. package/dist/client/assets/OGPreview-BzZ_MAg7.js +0 -1
  90. package/dist/client/assets/Overview-Cbi5ayT1.js +0 -1
  91. package/dist/client/assets/Panel-CKQaY_Qq.js +0 -1
  92. package/dist/client/assets/ReactiveGraph-Bq_aP4uo.css +0 -1
  93. package/dist/client/assets/ReactiveGraph-CQpsrwa7.js +0 -19
  94. package/dist/client/assets/RenderProfiler-CCG8KJ2a.js +0 -1
  95. package/dist/client/assets/RenderProfiler-CS1FAvX6.css +0 -1
  96. package/dist/client/assets/Routes-Dg3ZrLhJ.js +0 -1
  97. package/dist/client/assets/SearchField-B5EQ5IIf.js +0 -1
  98. package/dist/client/assets/Segmented-Dz1OdcPr.js +0 -1
  99. package/dist/client/assets/SplitView-CxRUXpY5.js +0 -1
  100. package/dist/client/assets/StateTimeline-CLt2yN8k.js +0 -1
  101. package/dist/client/assets/TreeView-BYOJBzxO.js +0 -1
  102. package/dist/client/assets/VirtualList-Bfn8is0p.js +0 -1
  103. package/dist/client/assets/browser-agent-rpc-BXhoSh1z-CuoUGU_3.js +0 -1
  104. package/dist/client/assets/capture.svelte-BLIttZ2Z.js +0 -1
  105. package/dist/client/assets/format-BEILGi1v.js +0 -1
  106. package/dist/client/assets/index-BmEfdt6W.css +0 -1
  107. package/dist/client/assets/index-Cf5oAFpK.js +0 -7
  108. package/dist/client/assets/reactive-DuxZv-g7.js +0 -1
  109. package/dist/client/assets/reactive-selection.svelte-iv05jhlt.js +0 -1
  110. package/dist/client/assets/versions-Bd19hz8p.js +0 -1
@@ -0,0 +1,24 @@
1
+ import { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { Logger } from 'vite';
4
+ import { Collector } from '../server/collector.js';
5
+ /** Dev-server path of the MCP endpoint. */
6
+ export declare const MCP_PATH = "/__svelte-devtools/mcp";
7
+ /**
8
+ * Whether the request's `x-svelte-devtools-token` header is exactly `token`.
9
+ * Constant-time for equal lengths (the length itself is not secret: every
10
+ * token is a UUID). A repeated header (string array) is never accepted.
11
+ */
12
+ export declare function isValidMcpToken(header: string | string[] | undefined, token: string): boolean;
13
+ /**
14
+ * Connect middleware for the MCP endpoint: lets AI agents (Claude Code etc.)
15
+ * read metrics and run measurement sessions over the Streamable HTTP
16
+ * transport. Same-origin is *not* required because MCP clients are local
17
+ * processes that don't run inside a browser tab; the token is the gate.
18
+ */
19
+ export declare function createMcpMiddleware(opts: {
20
+ token: string;
21
+ collector: Collector;
22
+ logger: Logger;
23
+ createServer: () => McpServer;
24
+ }): (req: IncomingMessage, res: ServerResponse) => void;
@@ -1,16 +1,11 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
2
  import { RenderProfile, ReactiveGraph, LoadProfile, FpsSample, ComponentInstance, ProjectInfo, RouteInfo, ComponentRelation, CaptureInfoMap, ReactiveGraphRequest, ReactiveGraphResult, ReactiveSummary, ReactiveSummaryRequest, StateTimelineDelta } from '../types.js';
4
3
  import { SessionStore } from './sessions.js';
5
4
  export interface McpDeps {
6
5
  getProject: () => ProjectInfo;
7
6
  getRoutes: () => RouteInfo[];
8
- getLiveComponents: () => ComponentInstance[];
9
- /**
10
- * The served page load's components with its epoch, read together
11
- * (`get_live_components` with `includeMeta`).
12
- */
13
- getLiveSnapshot?: () => {
7
+ /** The served page load's components with its epoch, read together. */
8
+ getLiveSnapshot: () => {
14
9
  epoch: string | null;
15
10
  total: number;
16
11
  components: ComponentInstance[];
@@ -22,12 +17,11 @@ export interface McpDeps {
22
17
  getLoadProfiles: () => LoadProfile[];
23
18
  getFpsSamples: () => FpsSample[];
24
19
  sessions: SessionStore;
25
- getReactiveSummary?: (req: ReactiveSummaryRequest) => Promise<ReactiveSummary>;
26
- getReactiveScope?: (req: ReactiveGraphRequest) => Promise<ReactiveGraphResult>;
27
- getStateTimelineDelta?: (since?: number) => StateTimelineDelta;
28
- getCaptureInfo?: () => CaptureInfoMap;
20
+ getReactiveSummary: (req: ReactiveSummaryRequest) => Promise<ReactiveSummary>;
21
+ getReactiveScope: (req: ReactiveGraphRequest) => Promise<ReactiveGraphResult>;
22
+ getStateTimelineDelta: (since?: number) => StateTimelineDelta;
23
+ getCaptureInfo: () => CaptureInfoMap;
29
24
  }
30
25
  /** Most timeline entries one `get_state_timeline` call returns. */
31
26
  export declare const MCP_TIMELINE_LIMIT = 500;
32
27
  export declare function buildMcpServer(deps: McpDeps): McpServer;
33
- export { StreamableHTTPServerTransport };
@@ -47,6 +47,7 @@ export interface SessionDelta {
47
47
  drops: number;
48
48
  };
49
49
  }
50
+ type Verdict = 'improved' | 'regressed' | 'unchanged';
50
51
  export interface SessionDiff {
51
52
  a: {
52
53
  id: string;
@@ -60,33 +61,40 @@ export interface SessionDiff {
60
61
  totalRenderTimeDeltaA: number;
61
62
  totalRenderTimeDeltaB: number;
62
63
  diff: number;
63
- verdict: 'improved' | 'regressed' | 'unchanged';
64
+ verdict: Verdict;
64
65
  };
65
66
  load: {
66
67
  avgA: number;
67
68
  avgB: number;
68
69
  diff: number;
69
- verdict: 'improved' | 'regressed' | 'unchanged';
70
+ verdict: Verdict;
70
71
  };
71
72
  fps: {
72
73
  avgA: number;
73
74
  avgB: number;
74
75
  diff: number;
75
- verdict: 'improved' | 'regressed' | 'unchanged';
76
+ verdict: Verdict;
76
77
  };
77
78
  }
79
+ interface SessionSummary {
80
+ id: string;
81
+ label: string;
82
+ startedAt: number;
83
+ endedAt?: number;
84
+ persisted: boolean;
85
+ active: boolean;
86
+ }
78
87
  export interface MetricGetters {
79
88
  getRenderProfiles: () => RenderProfile[];
80
89
  getLoadProfiles: () => LoadProfile[];
81
90
  getFpsSamples: () => FpsSample[];
82
91
  }
83
92
  /**
84
- * The only id shape `start()` issues: `s_<Date.now() base36>_<6 hex>`. Ids
85
- * reach the store from MCP clients and become file names, so anything else
86
- * (path separators, `..`, absolute paths) is rejected before touching disk
87
- * (review C-7).
93
+ * Whether `id` has the only shape `start()` issues: `s_<Date.now() base36>_<6
94
+ * hex>`. Ids reach the store from MCP clients and become file names, so
95
+ * anything else (path separators, `..`, absolute paths) is rejected before
96
+ * touching disk (review C-7).
88
97
  */
89
- export declare const SESSION_ID_PATTERN: RegExp;
90
98
  export declare function isSessionId(id: unknown): id is string;
91
99
  export interface SessionStoreOptions {
92
100
  persistDir: string;
@@ -99,28 +107,23 @@ export declare class SessionStore {
99
107
  private readonly getters;
100
108
  constructor(opts: SessionStoreOptions);
101
109
  start(label: string, persist: boolean): SessionRecord;
110
+ private get activeRecord();
102
111
  /** Called by the plugin whenever a new load profile arrives. */
103
112
  recordLoadProfile(p: LoadProfile): void;
104
113
  /** Called by the plugin whenever a new fps sample arrives. */
105
114
  recordFpsSample(s: FpsSample): void;
106
115
  end(keep: 'memory' | 'disk' | 'discard'): SessionRecord;
107
116
  get(id: string): SessionRecord | undefined;
108
- list(): Array<{
109
- id: string;
110
- label: string;
111
- startedAt: number;
112
- endedAt?: number;
113
- persisted: boolean;
114
- active: boolean;
115
- }>;
117
+ list(): SessionSummary[];
116
118
  delete(id: string): boolean;
117
- delta(id: string): SessionDelta;
118
119
  /**
119
120
  * The delta of a record in hand. `end('discard')` removes the record from
120
121
  * the store, so end_session must not look it up again by id (it used to,
121
122
  * and failed with "Session not found" for every discarded session).
122
123
  */
123
124
  deltaOf(rec: SessionRecord): SessionDelta;
125
+ delta(id: string): SessionDelta;
126
+ private found;
124
127
  compare(idA: string, idB: string): SessionDiff;
125
128
  /** The session's file, guaranteed to be a direct child of `persistDir`. */
126
129
  private pathFor;
@@ -0,0 +1,13 @@
1
+ /** Arithmetic mean, 0 for no values. */
2
+ export declare function avg(xs: number[]): number;
3
+ /** Smallest value, `fallback` for no values (reduce, not `Math.min(...)`: long lists overflow the stack). */
4
+ export declare function min<T>(xs: number[], fallback: T): number | T;
5
+ /** Largest value, `fallback` for no values. */
6
+ export declare function max<T>(xs: number[], fallback: T): number | T;
7
+ /** Rounded to 2 decimals. */
8
+ export declare function round(n: number): number;
9
+ /** Average render time of a profile, 0 when it never rendered. */
10
+ export declare function avgRenderTime(p: {
11
+ renderCount: number;
12
+ totalRenderTime: number;
13
+ }): number;
package/dist/plugin.d.ts CHANGED
@@ -20,10 +20,4 @@ export interface SvelteDevtoolsOptions {
20
20
  */
21
21
  clientAuth?: boolean;
22
22
  }
23
- /**
24
- * Whether the request's `x-svelte-devtools-token` header is exactly `token`.
25
- * Constant-time for equal lengths (the length itself is not secret: every
26
- * token is a UUID). A repeated header (string array) is never accepted.
27
- */
28
- export declare function isValidMcpToken(header: string | string[] | undefined, token: string): boolean;
29
23
  export declare function svelteDevtools(options?: SvelteDevtoolsOptions): Plugin[];
@@ -8,8 +8,8 @@
8
8
  * compiler's sourcemap stay aligned).
9
9
  */
10
10
  export declare function injectComponentTracking(code: string, id: string): string | null;
11
- /** A Svelte module (`.svelte.js` / `.svelte.ts`, runes outside components). */
12
- export declare const SVELTE_MODULE_RE: RegExp;
11
+ /** A Svelte module (`.svelte.js` / `.svelte.ts`, runes outside components); `file` has no query. */
12
+ export declare function isSvelteModule(file: string): boolean;
13
13
  /**
14
14
  * Module-scope transform for one client Svelte module: signals created while
15
15
  * its body runs (shared state, `export const cart = $state(...)`) are tracked
@@ -1,4 +1,7 @@
1
- import { CaptureInfoMap, CompilerWarning, ComponentInstance, FpsSample, LoadProfile, ReactiveGraph, ReactiveGraphRequest, ReactiveGraphResult, ReactiveSummary, ReactiveSummaryRequest, RenderProfile, RuntimeError, StateChange, StateTimelineDelta, StateTimelineEntry, DatasetVersions } from '../types.js';
1
+ import { CaptureInfoMap, CompilerWarning, ComponentInstance, FpsSample, LoadProfile, ReactiveGraphRequest, ReactiveGraphResult, ReactiveSummary, ReactiveSummaryRequest, RenderProfile, RuntimeError, StateChange, StateTimelineDelta, StateTimelineEntry, DatasetVersions } from '../types.js';
2
+ import { Payload } from './payload.js';
3
+ import { TimelinePush } from './state-timeline.js';
4
+ export { STATE_TIMELINE_BYTES } from './state-timeline.js';
2
5
  export declare const LIMITS: {
3
6
  readonly liveComponents: 50000;
4
7
  readonly renderProfiles: 5000;
@@ -14,9 +17,8 @@ export declare const LIMITS: {
14
17
  export declare const RUNTIME_REQUEST_TIMEOUT = 1000;
15
18
  /** A pull answered within this window is reused instead of asking the runtime again. */
16
19
  export declare const PULL_FRESHNESS = 1000;
17
- /** Byte budget (JSON length, measured once at ingest) for the server-side state timeline. */
18
- export declare const STATE_TIMELINE_BYTES: number;
19
- export type DatasetKey = keyof DatasetVersions;
20
+ /** A consumer (DevTools UI tab, MCP agent) counts as watching until its lease expires. */
21
+ export declare const LEASE_TTL = 15000;
20
22
  /** App page loads (tabs / reloads) whose component tree + profiles are kept, LRU. */
21
23
  export declare const MAX_EPOCHS = 4;
22
24
  /** Hot-channel event names shared with `runtime.ts` (stable contract, see docs/devframe-migration.md §6). */
@@ -38,10 +40,6 @@ export declare const HOT_EVENTS: {
38
40
  /** server → runtime(s): `{ active: boolean }` — whether any consumer is watching. */
39
41
  readonly subscription: "svelte-devtools:subscription";
40
42
  };
41
- /** A hot-channel payload: an untrusted JSON object from the app's runtime. */
42
- type Payload = Record<string, unknown>;
43
- /** A consumer (DevTools UI tab, MCP agent) counts as watching until its lease expires. */
44
- export declare const LEASE_TTL = 15000;
45
43
  export interface HotClient {
46
44
  send(event: string, payload: unknown): void;
47
45
  }
@@ -63,46 +61,32 @@ export declare class Collector {
63
61
  private epochs;
64
62
  private servedEpoch;
65
63
  private liveCache;
66
- loadProfiles: LoadProfile[];
67
- reactiveGraph: ReactiveGraph;
68
- compilerWarnings: CompilerWarning[];
69
- runtimeErrors: RuntimeError[];
70
- fpsSamples: FpsSample[];
64
+ /** Epochs we asked for a full snapshot (delta without a base); answered once per epoch. */
65
+ private resyncRequested;
66
+ private readonly fps;
67
+ private readonly errors;
68
+ private readonly loads;
69
+ private readonly warnings;
70
+ private readonly timeline;
71
71
  readonly versions: DatasetVersions;
72
- private bump;
73
- private timeline;
74
- /** Parallel to `timeline`: JSON size and source epoch (app page load) of each entry. */
75
- private timelineSizes;
76
- private timelineEpochs;
77
- private timelineBytes;
78
- /** Newest seq issued by this collector (= the current cursor). */
79
- private timelineSeq;
80
- /** Cursor value at the last removal; older cursors must start over. */
81
- private timelineResetAt;
82
- /** Seq of the newest entry trimmed by the caps; cursors below it missed entries. */
83
- private timelineTrimmedAt;
84
- private lastPull;
85
- private inflight;
86
72
  private pulls;
87
73
  private pullCache;
88
74
  private pullInflight;
89
75
  private requestSeq;
90
76
  /** The most recent graph reply, for capture info. */
91
77
  private lastGraph;
92
- private timelineDrops;
93
- /** Per epoch: whether the runtime has a first sample of every tracked $state yet. */
94
- private timelineBaseline;
95
- private timelineTooLarge;
96
- private received;
78
+ private lastTimelinePull;
79
+ private timelineInflight;
80
+ private timelineResolvers;
97
81
  private hot;
98
82
  private detachHot;
99
83
  private leases;
100
84
  private snapshotWaiters;
101
85
  private active;
102
86
  private sweepTimer;
103
- private stateTimelineResolvers;
104
87
  private readonly hooks;
105
88
  constructor(hooks?: CollectorHooks);
89
+ private bump;
106
90
  /**
107
91
  * Subscribe to the runtime's hot-channel events. Re-attaching (dev server
108
92
  * restart) detaches the previous channel first so listeners never pile up.
@@ -114,8 +98,12 @@ export declare class Collector {
114
98
  active: boolean;
115
99
  componentDeltas: true;
116
100
  };
117
- /** Epochs we asked for a full snapshot (delta without a base); answered once per epoch. */
118
- private resyncRequested;
101
+ get fpsSamples(): FpsSample[];
102
+ get runtimeErrors(): RuntimeError[];
103
+ get loadProfiles(): LoadProfile[];
104
+ get compilerWarnings(): CompilerWarning[];
105
+ /** The server-side timeline (all tracked epochs, oldest first). */
106
+ get stateTimeline(): StateTimelineEntry[];
119
107
  /** Components of the served epoch, parents first, capped at {@link LIMITS.liveComponents}. */
120
108
  get liveComponents(): ComponentInstance[];
121
109
  /**
@@ -149,9 +137,10 @@ export declare class Collector {
149
137
  /**
150
138
  * Mark `id` as watching for `ttl` ms (renewed by heartbeats). The first
151
139
  * lease activates the runtime's polling/FPS sampling, the last expiry or
152
- * release pauses it.
140
+ * release pauses it. Returns whether this call activated it.
153
141
  */
154
142
  lease(id: string, ttl?: number): boolean;
143
+ release(id: string): void;
155
144
  /**
156
145
  * Resolve once the runtime has sent its activation snapshot (components,
157
146
  * profiles, then a `reset: true` timeline — the last part) or after
@@ -159,7 +148,6 @@ export declare class Collector {
159
148
  * the stale pre-activation state.
160
149
  */
161
150
  waitForSnapshot(timeout: number): Promise<void>;
162
- release(id: string): void;
163
151
  private updateSubscription;
164
152
  /**
165
153
  * Full form `{ epoch?, reset?, components }` replaces the epoch's tree;
@@ -169,56 +157,30 @@ export declare class Collector {
169
157
  * resync. Entries stay in registration order (parents first); an instance
170
158
  * is stored only while its parent is and the cap allows, otherwise only its
171
159
  * id is tracked, so the stored part is always a rooted, orphan-free tree.
160
+ * Entries that are not objects with a numeric `id` are ignored.
161
+ */
162
+ ingestComponents(data: Payload | undefined, client?: HotClient): void;
163
+ ingestProfiles(data?: Payload): void;
164
+ ingestStateTimeline(data: TimelinePush | undefined): void;
165
+ ingestFps(sample: FpsSample): void;
166
+ ingestRuntimeError(error: RuntimeError): void;
167
+ recordLoadProfile(profile: LoadProfile): void;
168
+ /**
169
+ * A warning identical to one held is not recorded again: a component is
170
+ * compiled once per environment (client and SSR), each time warning anew.
172
171
  */
173
- ingestComponents(data: {
174
- components?: unknown;
175
- epoch?: unknown;
176
- added?: unknown;
177
- removed?: unknown;
178
- } | undefined, client?: HotClient): void;
179
- ingestProfiles(data?: {
180
- profiles?: unknown;
181
- epoch?: unknown;
182
- total?: unknown;
183
- }): void;
172
+ recordCompilerWarning(warning: CompilerWarning): void;
173
+ clearLoadProfiles(): void;
174
+ clearErrors(): void;
175
+ clearFps(): void;
176
+ clearStateTimeline(): void;
177
+ /** Changes after `since` (a previous `cursor`), or the whole buffer when the cursor is stale. */
178
+ getStateTimelineDelta(since?: number): StateTimelineDelta;
184
179
  /**
185
180
  * What the server holds versus what was reported, per dataset (§6.7 B).
186
181
  * `total: null` means unknown; nothing is estimated.
187
182
  */
188
183
  getCaptureInfo(): CaptureInfoMap;
189
- /** The server-side timeline (all tracked epochs, oldest first). */
190
- get stateTimeline(): StateTimelineEntry[];
191
- /**
192
- * Two payload shapes (docs/devframe-migration.md §6.4):
193
- * - delta: `{ epoch, changes, reset? }` — `changes` are new since the
194
- * previous push from that page load (`epoch`); `reset` replaces that
195
- * epoch's entries. Entries are kept per epoch, so several app tabs (or a
196
- * reload) interleave instead of wiping each other.
197
- * - legacy full snapshot: `{ changes }` — we append only the entries after
198
- * the newest one we already hold, so clients still get deltas.
199
- */
200
- ingestStateTimeline(data: {
201
- changes?: unknown;
202
- epoch?: unknown;
203
- reset?: unknown;
204
- dropped?: unknown;
205
- valueTooLarge?: unknown;
206
- baseline?: unknown;
207
- } | undefined): void;
208
- /**
209
- * Add the runtime's own losses (unsent entries it evicted, §6.7 C) and
210
- * too-large values to the epoch's counters. Only runtime reasons are
211
- * accepted from the runtime; server reasons are counted here.
212
- */
213
- private countRuntimeLosses;
214
- private addDrop;
215
- /** Changes after `since` (a previous `cursor`), or the whole buffer when the cursor is stale. */
216
- getStateTimelineDelta(since?: number): StateTimelineDelta;
217
- /** Invalidate every cursor issued so far (entries were removed, not just appended). */
218
- private markTimelineReset;
219
- private dropEpoch;
220
- private appendTimeline;
221
- private resolveSnapshotWaiters;
222
184
  /**
223
185
  * A graph reply. With a `requestId` (§6.7 A) it resolves only that request,
224
186
  * and only if its epoch matches the one asked for; a reply nobody waits for
@@ -227,26 +189,10 @@ export declare class Collector {
227
189
  * filtering here.
228
190
  */
229
191
  ingestReactiveGraph(data: Payload | undefined): void;
230
- /**
231
- * Shape a runtime reply into a {@link ReactiveGraphResult}: apply the
232
- * collector caps (nodes, then only edges between kept nodes, then the edge
233
- * cap) and report what was left out. Totals come from the runtime; an older
234
- * runtime's are the counts it sent (`nodesKind: 'sent'`), or unknown when
235
- * the server had to scope its whole-app graph.
236
- */
237
- private normalizeGraph;
238
- private storeGraph;
239
192
  /** A summary reply (§6.7 I): resolves only the matching request. */
240
193
  ingestReactiveSummary(data: Payload | undefined): void;
241
- private normalizeSummary;
242
- ingestFps(sample: FpsSample): void;
243
- ingestRuntimeError(error: RuntimeError): void;
244
- recordLoadProfile(profile: LoadProfile): void;
245
- recordCompilerWarning(warning: CompilerWarning): void;
246
- clearLoadProfiles(): void;
247
- clearErrors(): void;
248
- clearFps(): void;
249
- clearStateTimeline(): void;
194
+ /** The pending pull `requestId` names, if the reply is of its kind and from its epoch. */
195
+ private matchingPull;
250
196
  /**
251
197
  * Ask the browser runtime for the graph of one component instance (or the
252
198
  * whole app), built by the runtime within the caps (§6.7 A). Falls back to
@@ -262,18 +208,17 @@ export declare class Collector {
262
208
  * last result for the same key is returned with `stale: true`.
263
209
  */
264
210
  private keyedPull;
265
- /** Resolve a pending pull with a fresh result and cache it under its key. */
211
+ /**
212
+ * Resolve a pending pull: with a fresh result (cached under its key), or
213
+ * with its fallback when the runtime did not answer.
214
+ */
266
215
  private settle;
267
- /** Answer every pending keyed pull from its cache (or empty), marked stale. */
268
- private flushPulls;
269
- /** Ask the browser runtime for a fresh state timeline; falls back to the last one. */
270
- requestStateTimeline(): Promise<StateChange[]>;
271
216
  /**
272
- * Concurrent callers share one in-flight pull, and a result younger than
273
- * {@link PULL_FRESHNESS} is reused, so several polling clients never make
274
- * the user's app rebuild the same data more than once a second.
217
+ * Ask the browser runtime for a fresh state timeline; falls back to the
218
+ * last one. Concurrent callers share one in-flight pull, and a result
219
+ * younger than {@link PULL_FRESHNESS} is reused, so several polling clients
220
+ * never make the user's app rebuild the same data more than once a second.
275
221
  */
276
- private pull;
222
+ requestStateTimeline(): Promise<StateChange[]>;
277
223
  private flushStateTimeline;
278
224
  }
279
- export {};
@@ -0,0 +1,13 @@
1
+ import { Plugin } from 'vite';
2
+ import { CompilerWarning } from '../types.js';
3
+ /**
4
+ * Report every Svelte compiler warning of the app to `record`, as the
5
+ * compiler's structured warning (vite-plugin-svelte prints dev warnings with
6
+ * `console.log`, past Vite's logger). The user's `onwarn` (or the default
7
+ * handler) still runs, so console output is unchanged. Dependencies'
8
+ * warnings are skipped, as vite-plugin-svelte does in dev.
9
+ *
10
+ * Must run after vite-plugin-svelte's own `configResolved`, which creates
11
+ * the options (a restart creates new ones, so wrappers never stack).
12
+ */
13
+ export declare function captureCompilerWarnings(plugins: readonly Plugin[], record: (warning: CompilerWarning) => void): void;
@@ -32,10 +32,10 @@ export interface SvelteDevtoolsHost {
32
32
  /** Open `file[:line]` in the user's editor. */
33
33
  openInEditor: (target: string) => void;
34
34
  }
35
- export declare function createRpcFunctions(host: SvelteDevtoolsHost): readonly [import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-project", "query", [], import('../types.js').ProjectInfo, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-routes", "query", [], import('../types.js').RouteInfo[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-assets", "query", [], import('../types.js').AssetInfo[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-component-relations", "query", [], import('../types.js').ComponentRelation[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-svelte-files", "query", [], {
35
+ export declare function createRpcFunctions(host: SvelteDevtoolsHost): readonly [import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-project", "query" | "action", [], import('../types.js').ProjectInfo, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-routes", "query" | "action", [], import('../types.js').RouteInfo[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-assets", "query" | "action", [], import('../types.js').AssetInfo[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-component-relations", "query" | "action", [], import('../types.js').ComponentRelation[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-svelte-files", "query" | "action", [], {
36
36
  file: string;
37
37
  name: string;
38
- }[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-live-components", "query", [], import('../types.js').ComponentInstance[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-live-components-meta", "query", [], LiveComponentsMeta, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"set-active", "action", readonly [z.ZodObject<{
38
+ }[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-live-components", "query" | "action", [], import('../types.js').ComponentInstance[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-live-components-meta", "query" | "action", [], LiveComponentsMeta, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"set-active", "action", readonly [z.ZodObject<{
39
39
  client: z.ZodString;
40
40
  active: z.ZodBoolean;
41
41
  }, z.core.$strip>], z.ZodVoid, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"open-in-editor", "action", readonly [z.ZodObject<{
@@ -45,7 +45,7 @@ export declare function createRpcFunctions(host: SvelteDevtoolsHost): readonly [
45
45
  file: z.ZodString;
46
46
  name: z.ZodString;
47
47
  type: z.ZodString;
48
- }, z.core.$strip>], z.ZodVoid, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-render-profiles", "query", [], import('../types.js').RenderProfile[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"get-reactive-graph", "query", readonly [z.ZodOptional<z.ZodObject<{
48
+ }, z.core.$strip>], z.ZodVoid, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-render-profiles", "query" | "action", [], import('../types.js').RenderProfile[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"get-reactive-graph", "query", readonly [z.ZodOptional<z.ZodObject<{
49
49
  componentId: z.ZodOptional<z.ZodNumber>;
50
50
  epoch: z.ZodOptional<z.ZodString>;
51
51
  maxNodes: z.ZodOptional<z.ZodNumber>;
@@ -53,9 +53,9 @@ export declare function createRpcFunctions(host: SvelteDevtoolsHost): readonly [
53
53
  }, z.core.$strip>>], z.ZodCustom<ReactiveGraphResult, ReactiveGraphResult>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"get-reactive-summary", "query", readonly [z.ZodOptional<z.ZodObject<{
54
54
  topK: z.ZodOptional<z.ZodNumber>;
55
55
  windowMs: z.ZodOptional<z.ZodNumber>;
56
- }, z.core.$strip>>], z.ZodCustom<ReactiveSummary, ReactiveSummary>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-capture-info", "query", [], Partial<Record<import('../types.js').CaptureKey, import('../types.js').CaptureInfo>>, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-load-profiles", "query", [], import('../types.js').LoadProfile[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"clear-load-profiles", "action", [], void, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-state-timeline", "query", [], Promise<import('../types.js').StateChange[]>, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"get-state-timeline-delta", "query", readonly [z.ZodObject<{
56
+ }, z.core.$strip>>], z.ZodCustom<ReactiveSummary, ReactiveSummary>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-capture-info", "query" | "action", [], Partial<Record<import('../types.js').CaptureKey, import('../types.js').CaptureInfo>>, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-load-profiles", "query" | "action", [], import('../types.js').LoadProfile[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"clear-load-profiles", "query" | "action", [], void, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-state-timeline", "query" | "action", [], Promise<import('../types.js').StateChange[]>, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"get-state-timeline-delta", "query", readonly [z.ZodObject<{
57
57
  since: z.ZodOptional<z.ZodNumber>;
58
- }, z.core.$strip>], z.ZodCustom<StateTimelineDelta, StateTimelineDelta>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-versions", "query", [], {
58
+ }, z.core.$strip>], z.ZodCustom<StateTimelineDelta, StateTimelineDelta>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-versions", "query" | "action", [], {
59
59
  components: number;
60
60
  renderProfiles: number;
61
61
  loadProfiles: number;
@@ -63,7 +63,7 @@ export declare function createRpcFunctions(host: SvelteDevtoolsHost): readonly [
63
63
  reactiveGraph: number;
64
64
  errors: number;
65
65
  fps: number;
66
- }, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"clear-state-timeline", "action", [], void, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-api-endpoints", "query", [], import('../types.js').ApiEndpoint[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"send-api-request", "action", readonly [z.ZodObject<{
66
+ }, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"clear-state-timeline", "query" | "action", [], void, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-api-endpoints", "query" | "action", [], import('../types.js').ApiEndpoint[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"send-api-request", "action", readonly [z.ZodObject<{
67
67
  url: z.ZodString;
68
68
  method: z.ZodEnum<{
69
69
  GET: "GET";
@@ -76,11 +76,11 @@ export declare function createRpcFunctions(host: SvelteDevtoolsHost): readonly [
76
76
  }>;
77
77
  headers: z.ZodString;
78
78
  body: z.ZodString;
79
- }, z.core.$strip>], z.ZodCustom<ApiResponse, ApiResponse>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-compiler-warnings", "query", [], import('../types.js').CompilerWarning[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-runtime-errors", "query", [], import('../types.js').RuntimeError[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"clear-errors", "action", [], void, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"inspect-file", "query", readonly [z.ZodObject<{
79
+ }, z.core.$strip>], z.ZodCustom<ApiResponse, ApiResponse>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-compiler-warnings", "query" | "action", [], import('../types.js').CompilerWarning[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-runtime-errors", "query" | "action", [], import('../types.js').RuntimeError[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"clear-errors", "query" | "action", [], void, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"inspect-file", "query", readonly [z.ZodObject<{
80
80
  file: z.ZodString;
81
- }, z.core.$strip>], z.ZodCustom<InspectResult, InspectResult>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-module-graph", "query", [], import('../types.js').ModuleGraphData, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"get-og-preview", "action", readonly [z.ZodObject<{
81
+ }, z.core.$strip>], z.ZodCustom<InspectResult, InspectResult>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-module-graph", "query" | "action", [], import('../types.js').ModuleGraphData, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithSchemas<"get-og-preview", "action", readonly [z.ZodObject<{
82
82
  url: z.ZodString;
83
- }, z.core.$strip>], z.ZodCustom<OGPreview, OGPreview>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-build-analysis", "query", [], import('../types.js').BuildAnalysis, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-fps", "query", [], import('../types.js').FpsSample[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"clear-fps", "action", [], void, undefined, undefined, import('devframe').DevframeNodeContext>];
83
+ }, z.core.$strip>], z.ZodCustom<OGPreview, OGPreview>, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-build-analysis", "query" | "action", [], import('../types.js').BuildAnalysis, undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"get-fps", "query" | "action", [], import('../types.js').FpsSample[], undefined, undefined, import('devframe').DevframeNodeContext>, import('devframe/rpc').RpcFunctionDefinitionWithoutSchemas<"clear-fps", "query" | "action", [], void, undefined, undefined, import('devframe').DevframeNodeContext>];
84
84
  /**
85
85
  * The portable Svelte DevTools tool. Host-agnostic: the same definition is
86
86
  * mounted standalone (`initDevframe`) or inside Vite DevTools
@@ -0,0 +1,12 @@
1
+ /** Server-side hook the profiled `load` wrappers report to (set by the plugin on the dev server). */
2
+ export declare const LOAD_RECORDER = "__svelte_devtools_record_load";
3
+ /**
4
+ * Wrap the exported `load` of a SvelteKit load file (`+page.ts`,
5
+ * `+layout.server.js`, …) so each call reports its duration and data size,
6
+ * or `null` when `id` is not a load file or declares no exported `load`.
7
+ *
8
+ * Only the `export` keyword is removed (the local binding stays, so the
9
+ * module's own references keep the original) and a profiled wrapper is
10
+ * exported as `load` instead; line numbers are unchanged.
11
+ */
12
+ export declare function profileLoad(code: string, id: string, root: string): string | null;
@@ -1,5 +1,7 @@
1
1
  import { DevframeDefinition } from 'devframe';
2
2
  import { ViteDevServer } from 'vite';
3
+ /** `address` as a URL host: `localhost` for loopback / wildcard bindings, IPv6 bracketed. */
4
+ export declare function urlHost(address: string): string;
3
5
  /**
4
6
  * Serve the devframe standalone on this dev server: SPA, discovery,
5
7
  * WebSocket RPC on Vite's own HTTP server at `<base>__ws`, auth gate.
@@ -0,0 +1,11 @@
1
+ /** A hot-channel payload: an untrusted JSON object from the app's runtime. */
2
+ export type Payload = Record<string, unknown>;
3
+ export declare function asPayload(value: unknown): Payload | undefined;
4
+ /** An integer within [min, max], or `fallback` when absent / not a number. */
5
+ export declare function clampInt(value: unknown, min: number, max: number, fallback: number): number;
6
+ /** A non-negative safe integer, 0 when absent / not a number. */
7
+ export declare function nonNegInt(value: unknown): number;
8
+ /** A finite number, or `null` when absent / not one. */
9
+ export declare function finiteOrNull(value: unknown): number | null;
10
+ /** The array's elements (none when it is not an array). */
11
+ export declare function arrayOf<T>(value: unknown): T[];
@@ -0,0 +1,30 @@
1
+ import { ReactiveGraphResult, ReactiveSummary } from '../types.js';
2
+ import { Payload } from './payload.js';
3
+ /** Most nodes / edges one graph answer holds. */
4
+ export declare const GRAPH_LIMITS: {
5
+ readonly nodes: 5000;
6
+ readonly edges: 20000;
7
+ };
8
+ /** Defaults and bounds for `get-reactive-summary` (§6.7 I). */
9
+ export declare const SUMMARY_DEFAULTS: {
10
+ readonly topK: 50;
11
+ readonly maxTopK: 200;
12
+ readonly windowMs: 10000;
13
+ readonly minWindowMs: 1000;
14
+ readonly maxWindowMs: 60000;
15
+ };
16
+ export type StaleReason = NonNullable<ReactiveGraphResult['staleReason']>;
17
+ /** An empty graph answer, marked stale for `reason`. */
18
+ export declare function emptyGraph(scope: number | null, epoch: string | null, reason: StaleReason): ReactiveGraphResult;
19
+ /** An empty summary answer, marked stale for `reason`. */
20
+ export declare function emptySummary(epoch: string | null, windowMs: number, reason: 'timeout' | 'no-runtime'): ReactiveSummary;
21
+ /**
22
+ * Shape a runtime reply into a {@link ReactiveGraphResult}: apply the caps
23
+ * (nodes, then only edges between kept nodes, then the edge cap) and report
24
+ * what was left out. Totals come from the runtime; an older runtime's (no
25
+ * `requestId`) are the counts it sent (`nodesKind: 'sent'`), or unknown when
26
+ * the server had to scope its whole-app graph.
27
+ */
28
+ export declare function normalizeGraph(data: Payload | undefined, scope: number | null, epoch: string | null): ReactiveGraphResult;
29
+ /** Shape a runtime summary reply (§6.7 I); every field is validated, nothing assumed. */
30
+ export declare function normalizeSummary(data: Payload | undefined, epoch: string | null): ReactiveSummary;
@@ -0,0 +1,11 @@
1
+ import { CaptureInfo } from '../types.js';
2
+ /** A tail-capped dataset that counts what it received since the last clear. */
3
+ export declare class Ring<T> {
4
+ items: T[];
5
+ received: number;
6
+ private readonly max;
7
+ constructor(max: number);
8
+ push(item: T): void;
9
+ clear(): void;
10
+ get info(): CaptureInfo;
11
+ }
@@ -2,7 +2,7 @@
2
2
  * Validate that a URL does not target private/internal network addresses (SSRF prevention).
3
3
  * Allows only http/https schemes and blocks private IP ranges.
4
4
  */
5
- export declare function validateExternalUrl(urlStr: string): void;
5
+ export declare function validateExternalUrl(urlStr: string): URL;
6
6
  export interface OutboundUrlOptions {
7
7
  /**
8
8
  * Origins that may be fetched even though they are local — the dev
@@ -27,6 +27,8 @@ export declare function assertOutboundUrl(urlStr: string, options?: OutboundUrlO
27
27
  * malformed value is never let through.
28
28
  */
29
29
  export declare function isPrivateIP(ip: string): boolean;
30
+ /** Whether `file` lies inside `dir` (`..foo/x` does; `dir` itself, `../x` and other drives do not). */
31
+ export declare function isInside(dir: string, file: string): boolean;
30
32
  /**
31
33
  * Resolve a user-supplied file path strictly under `root`. Symlinks are
32
34
  * followed via realpathSync so that symlinks inside the project cannot be