@rstest/browser 0.11.6 → 0.11.7

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 (88) hide show
  1. package/dist/browser-container/container-static/css/index.43daaf6c93.css +1 -0
  2. package/dist/browser-container/container-static/js/260.3739fe815c.js +194 -0
  3. package/dist/browser-container/container-static/js/index.c0f87bfb3e.js +1 -0
  4. package/dist/browser-container/index.html +1 -1
  5. package/dist/browserRsbuild.d.ts +24 -4
  6. package/dist/browserV8Coverage.d.ts +15 -0
  7. package/dist/client/240~1.js +150 -0
  8. package/dist/{augmentExpect.d.ts → client/client/augmentExpect.d.ts} +1 -1
  9. package/dist/client/{browserRpc.d.ts → client/browserRpc.d.ts} +1 -1
  10. package/dist/client/{dispatchTransport.d.ts → client/dispatchTransport.d.ts} +8 -4
  11. package/dist/client/client/index.d.ts +2 -0
  12. package/dist/client/client/runIdentity.d.ts +12 -0
  13. package/dist/client/client/runner.d.ts +4 -0
  14. package/dist/client/client/snapshot.d.ts +27 -0
  15. package/dist/client/client/sourceMapSupport.d.ts +36 -0
  16. package/dist/{browser.js → client/index.js} +3 -102
  17. package/dist/client/protocol.d.ts +225 -0
  18. package/dist/client/rpcProtocol.d.ts +138 -0
  19. package/dist/client/runner.js +675 -0
  20. package/dist/client/sourceMap/sourceMapLoader.d.ts +25 -0
  21. package/dist/containerRpc.d.ts +27 -19
  22. package/dist/headedRunRegistry.d.ts +51 -0
  23. package/dist/headedScheduler.d.ts +10 -10
  24. package/dist/headlessScheduler.d.ts +5 -4
  25. package/dist/headlessTransport.d.ts +4 -2
  26. package/dist/hostPayloads.d.ts +1 -7
  27. package/dist/index.js +840 -330
  28. package/dist/protocol.d.ts +48 -8
  29. package/dist/providers/index.d.ts +21 -0
  30. package/dist/providers/playwright/v8Coverage.d.ts +2 -0
  31. package/dist/rpcProtocol.d.ts +1 -2
  32. package/dist/schedulerSeam.d.ts +5 -0
  33. package/dist/sourceMap/sourceMapLoader.d.ts +12 -1
  34. package/dist/watchRerunPlanner.d.ts +20 -9
  35. package/dist/watchSignals.d.ts +8 -1
  36. package/package.json +10 -10
  37. package/dist/33.js +0 -7
  38. package/dist/browser-container/container-static/css/index.0521ff95b1.css +0 -1
  39. package/dist/browser-container/container-static/js/683.4f821ce8f1.js +0 -194
  40. package/dist/browser-container/container-static/js/index.568aa7cb35.js +0 -1
  41. package/dist/browser.d.ts +0 -2
  42. package/src/augmentExpect.ts +0 -62
  43. package/src/browser.ts +0 -3
  44. package/src/browserExecutor.ts +0 -222
  45. package/src/browserRpcRegistry.ts +0 -57
  46. package/src/browserRsbuild.ts +0 -1927
  47. package/src/client/api.ts +0 -213
  48. package/src/client/browserRpc.ts +0 -86
  49. package/src/client/dispatchTransport.ts +0 -240
  50. package/src/client/entry.ts +0 -807
  51. package/src/client/locator.ts +0 -448
  52. package/src/client/snapshot.ts +0 -113
  53. package/src/client/sourceMapSupport.ts +0 -159
  54. package/src/concurrency.ts +0 -65
  55. package/src/configValidation.ts +0 -263
  56. package/src/containerRpc.ts +0 -206
  57. package/src/dispatchCapabilities.ts +0 -177
  58. package/src/dispatchRouter.ts +0 -82
  59. package/src/env.d.ts +0 -54
  60. package/src/headedScheduler.ts +0 -664
  61. package/src/headedSerialTaskQueue.ts +0 -23
  62. package/src/headlessScheduler.ts +0 -566
  63. package/src/headlessTransport.ts +0 -28
  64. package/src/hostController.ts +0 -1365
  65. package/src/hostPayloads.ts +0 -62
  66. package/src/index.ts +0 -51
  67. package/src/manifest.d.ts +0 -41
  68. package/src/protocol.ts +0 -225
  69. package/src/providers/index.ts +0 -126
  70. package/src/providers/playwright/compileLocator.ts +0 -130
  71. package/src/providers/playwright/dispatchBrowserRpc.ts +0 -372
  72. package/src/providers/playwright/expectUtils.ts +0 -57
  73. package/src/providers/playwright/implementation.ts +0 -35
  74. package/src/providers/playwright/index.ts +0 -1
  75. package/src/providers/playwright/runtime.ts +0 -159
  76. package/src/providers/playwright/textMatcher.ts +0 -10
  77. package/src/rpcProtocol.ts +0 -218
  78. package/src/runSession.ts +0 -110
  79. package/src/schedulerSeam.ts +0 -49
  80. package/src/sessionRegistry.ts +0 -89
  81. package/src/sourceMap/sourceMapLoader.ts +0 -96
  82. package/src/viewportPresets.ts +0 -69
  83. package/src/watchRerunPlanner.ts +0 -88
  84. package/src/watchRuntime.ts +0 -83
  85. package/src/watchSignals.ts +0 -93
  86. /package/dist/{rslib-runtime.js → 612~0.js} +0 -0
  87. /package/dist/client/{api.d.ts → client/api.d.ts} +0 -0
  88. /package/dist/client/{locator.d.ts → client/locator.d.ts} +0 -0
@@ -8,8 +8,10 @@ export declare const DISPATCH_RESPONSE_TYPE = '__rstest_dispatch_response__';
8
8
  export declare const DISPATCH_RPC_BRIDGE_NAME = '__rstest_dispatch_rpc__';
9
9
  export declare const DISPATCH_RPC_REQUEST_TYPE = 'dispatch-rpc-request';
10
10
  export declare const RSTEST_CONFIG_MESSAGE_TYPE = 'RSTEST_CONFIG';
11
+ export declare const NO_RPC_TIMEOUT = -1;
11
12
  export declare const DISPATCH_NAMESPACE_RUNNER = 'runner';
12
13
  export declare const DISPATCH_NAMESPACE_BROWSER = 'browser';
14
+ export declare const DISPATCH_NAMESPACE_FILE_CLEANUP = 'file-cleanup';
13
15
  export declare const DISPATCH_NAMESPACE_SNAPSHOT = 'snapshot';
14
16
  export declare const DISPATCH_METHOD_RPC = 'rpc';
15
17
  export type SerializedRuntimeConfig = BrowserRuntimeConfig;
@@ -31,6 +33,21 @@ export type BrowserProjectRuntime = {
31
33
  testPath: string;
32
34
  projectName: string;
33
35
  };
36
+ export type FileCleanupDispatchMethod = 'start' | 'end';
37
+ export type FileCleanupDispatchPayload = {
38
+ projectName: string;
39
+ result?: TestFileResult;
40
+ runId?: string;
41
+ testPath: string;
42
+ };
43
+ /**
44
+ * The committed test-file set plus its monotonic version. The version is what
45
+ * the container acks once every iframe for that set exists in the DOM, so both
46
+ * halves must travel together — a set without its version cannot be acked.
47
+ */ export type VersionedTestFileSet = {
48
+ files: TestFileInfo[];
49
+ version: number;
50
+ };
34
51
  /**
35
52
  * Execution mode for browser tests.
36
53
  * - 'run': Execute tests and report results (default)
@@ -66,8 +83,12 @@ export type BrowserHostConfig = {
66
83
  };
67
84
  testFile?: string;
68
85
  /**
69
- * Per-run identifier assigned by the container.
70
- * Used by browser RPC calls to prevent stale requests from previous reruns.
86
+ * The run identity this document executes under — the runner's SOLE identity
87
+ * source, adopted once at boot and stamped on every outbound message. Headed:
88
+ * the container confers its frame's current lease over the config handshake
89
+ * (so even an HMR full reload boots with the run the host is awaiting NOW).
90
+ * Headless: injected host-side as `${run.token}:${session.id}`. Never
91
+ * derivable from the URL.
71
92
  */ runId?: string;
72
93
  /**
73
94
  * Base URL for runner (iframe) pages. Container origin; used as a fallback
@@ -87,10 +108,21 @@ export type BrowserHostConfig = {
87
108
  /**
88
109
  * Debug mode. When true, enables verbose logging in browser.
89
110
  */ debug?: boolean;
90
- /**
91
- * Timeout for RPC operations in milliseconds (e.g., snapshot file operations).
92
- * Derived from testTimeout config.
93
- */ rpcTimeout?: number;
111
+ /** Timeout for RPC operations in milliseconds; negative values disable it. */ rpcTimeout?: number;
112
+ };
113
+ export declare const RSTEST_BROWSER_CACHE_CLEANERS_KEY = '@rstest/browser/cache-cleaners';
114
+ /**
115
+ * The wrapper every runner document posts over `postMessage` / the headless
116
+ * bridge. Identity rides BESIDE the payload, never inside it: `message`
117
+ * payloads reach core reporting (`RunnerEventSink`, `BlobReporter`) as-is, so a
118
+ * transport identity spread into them would leak a nondeterministic UUID into
119
+ * reporter output. `runId` is the identity the document was granted at boot
120
+ * (headed: the container's config handshake; headless: the injected inline
121
+ * options) — never re-derived from the URL or the frame. Absent only for a
122
+ * document that was never granted one; the headed host drops such messages.
123
+ */ export type RunnerEnvelope = {
124
+ runId?: string;
125
+ message: BrowserClientMessage;
94
126
  };
95
127
  export type BrowserClientMessage = {
96
128
  type: 'ready';
@@ -140,8 +172,9 @@ export type BrowserClientMessage = {
140
172
  /**
141
173
  * {@link BrowserClientMessage} types that are forwarded to the `runner`
142
174
  * namespace (by message `type`) rather than handled at the transport layer.
143
- * `Extract` keeps this a checked subset of the message union renaming a
144
- * message type drops it here, surfacing as a missing handler downstream.
175
+ * `Extract` keeps this a checked subset of the message union. `ready` and
176
+ * `complete` are deliberately absent: they still arrive, but their only job
177
+ * is done at the dispatch gate and the router ignores them silently.
145
178
  */ type RunnerMessageMethod = Extract<BrowserClientMessage['type'], 'file-start' | 'case-result' | 'file-complete' | 'log' | 'fatal'>;
146
179
  /**
147
180
  * Single source of truth for every method handled by the `runner` dispatch
@@ -158,6 +191,13 @@ export type BrowserClientMessage = {
158
191
  // Optional so headed/container paths can adopt the same envelope even when
159
192
  // run-token isolation is only enforced in headless scheduling today.
160
193
  runToken?: number;
194
+ /**
195
+ * Headed run identity, stamped by the runner's dispatch transport from the
196
+ * identity its document adopted at boot. The headed host accepts a request
197
+ * iff this names a live run; headless keeps using the host-injected
198
+ * `runToken` instead (`runToken` is the CYCLE generation, `runId` is the
199
+ * RUN identity — they are not interchangeable).
200
+ */ runId?: string;
161
201
  namespace: string;
162
202
  method: string;
163
203
  args?: unknown;
@@ -48,6 +48,24 @@ import type { BrowserRpcRequest } from '../rpcProtocol.js';
48
48
  close: () => Promise<void>;
49
49
  [Symbol.asyncDispose]: () => Promise<void>;
50
50
  };
51
+ export type BrowserV8CoverageEntry = {
52
+ url: string;
53
+ scriptId: string;
54
+ source?: string;
55
+ functions: {
56
+ functionName: string;
57
+ isBlockCoverage: boolean;
58
+ ranges: {
59
+ startOffset: number;
60
+ endOffset: number;
61
+ count: number;
62
+ }[];
63
+ }[];
64
+ };
65
+ export type BrowserV8CoverageCollector = {
66
+ start: (page: BrowserProviderPage) => Promise<void>;
67
+ take: (page: BrowserProviderPage) => Promise<BrowserV8CoverageEntry[]>;
68
+ };
51
69
  /** Minimal browser context API surface required by hostController. */ export type BrowserProviderContext = {
52
70
  newPage: () => Promise<BrowserProviderPage>;
53
71
  on: (event: 'page', listener: (page: BrowserProviderPage) => void) => void;
@@ -88,6 +106,9 @@ import type { BrowserRpcRequest } from '../rpcProtocol.js';
88
106
  */ export type BrowserProviderImplementation = {
89
107
  name: BrowserProvider;
90
108
  launchRuntime: (input: LaunchBrowserInput) => Promise<BrowserProviderRuntime>;
109
+ createV8CoverageCollector?: (input: {
110
+ browserName: LaunchBrowserInput['browserName'];
111
+ }) => BrowserV8CoverageCollector | null;
91
112
  dispatchRpc: (input: DispatchBrowserRpcInput) => Promise<unknown>;
92
113
  };
93
114
  export declare function getBrowserProviderImplementation(provider: BrowserProvider): BrowserProviderImplementation;
@@ -0,0 +1,2 @@
1
+ import type { BrowserV8CoverageCollector } from '../index.js';
2
+ export declare const createPlaywrightV8CoverageCollector: () => BrowserV8CoverageCollector;
@@ -84,7 +84,6 @@ export type BrowserLocatorIR = {
84
84
  export type BrowserRpcRequest = {
85
85
  id: string;
86
86
  /** Absolute test file path for locating runner iframe */ testPath: string;
87
- /** Run identifier generated by container for stale-request protection. */ runId: string;
88
87
  kind: 'locator' | 'expect' | 'config';
89
88
  locator: BrowserLocatorIR;
90
89
  method: string;
@@ -93,7 +92,7 @@ export type BrowserRpcRequest = {
93
92
  * Negation for expect matchers (equivalent to Playwright expect(...).not).
94
93
  * Only meaningful for kind === 'expect'.
95
94
  */ isNot?: boolean;
96
- /** Optional timeout override (ms). Falls back to browser rpcTimeout. */ timeout?: number;
95
+ /** Optional assertion timeout override (ms). Falls back to the host-provided assertion timeout. */ timeout?: number;
97
96
  };
98
97
  export declare const validateBrowserRpcRequest: (payload: unknown) => BrowserRpcRequest;
99
98
  /**
@@ -17,6 +17,10 @@ import type { BrowserProviderPage } from './providers/index.js';
17
17
  /** Execute the scope the last trigger resolved, as one cycle outcome. */ runCycle: (testPaths: string[]) => Promise<ExecutorCycleOutcome>;
18
18
  /** Explicit path-scoped rerun request (a CLI shortcut's browser fanout). */ requestRerun: (testPaths?: string[]) => Promise<void>;
19
19
  };
20
+ export type BrowserV8CoverageRuntime = {
21
+ start: (page: BrowserProviderPage) => Promise<void>;
22
+ take: (page: BrowserProviderPage, projectRoot: string, projectName?: string) => Promise<unknown | null>;
23
+ };
20
24
  /**
21
25
  * What a run branch produces. Results and errors accumulate in the sinks the
22
26
  * controller owns, so a scheduler reports only what it alone knows: how long
@@ -24,6 +28,7 @@ import type { BrowserProviderPage } from './providers/index.js';
24
28
  * that does not outlive the run.
25
29
  */ export type SchedulerRunResult = {
26
30
  testTime: number;
31
+ rawCoverage?: unknown[];
27
32
  watchSession?: BrowserWatchSession;
28
33
  close?: () => Promise<void>;
29
34
  };
@@ -1,9 +1,20 @@
1
- import type { DecodedSourceMapXInput, EncodedSourceMapXInput } from '@jridgewell/trace-mapping';
1
+ import { type DecodedSourceMapXInput, type EncodedSourceMapXInput } from '@jridgewell/trace-mapping';
2
2
  export type SourceMapPayload = EncodedSourceMapXInput | DecodedSourceMapXInput;
3
+ export type LoadedSourceMap = {
4
+ sourceMap: SourceMapPayload;
5
+ sourceMapUrl: string;
6
+ };
3
7
  type Fetcher = typeof fetch;
4
8
  export declare const normalizeJavaScriptUrl: (value: string, options?: {
5
9
  origin?: string;
6
10
  }) => string | null;
11
+ export declare const resolveInlineSourceMap: (code: string, sourceMapUrl?: string) => SourceMapPayload | null;
12
+ export declare const loadSourceMapForSource: ({ jsUrl, signal, source, fetcher }: {
13
+ jsUrl: string;
14
+ signal?: AbortSignal;
15
+ source: string;
16
+ fetcher?: Fetcher;
17
+ }) => Promise<LoadedSourceMap | null>;
7
18
  export declare const loadSourceMapWithCache: ({ jsUrl, cache, force, origin, fetcher }: {
8
19
  jsUrl: string;
9
20
  cache: Map<string, SourceMapPayload | null>;
@@ -1,9 +1,4 @@
1
1
  import type { TestFileInfo } from './protocol.js';
2
- /**
3
- * Paths the previous cycle ran that the current file set no longer contains.
4
- * Core prunes its own state from this, so a file deleted mid-session stops
5
- * being reported instead of lingering as a passing result.
6
- */ export declare const collectDeletedTestPaths: (previous: TestFileInfo[], current: TestFileInfo[]) => string[];
7
2
  type WatchPlannerProjectEntry = {
8
3
  project: {
9
4
  name: string;
@@ -15,12 +10,28 @@ type WatchRerunPlannerInput = {
15
10
  previousTestFiles: TestFileInfo[];
16
11
  affectedTestFiles: string[];
17
12
  };
18
- type WatchRerunPlan = {
13
+ type WatchFileSetUpdate = {
19
14
  currentTestFiles: TestFileInfo[];
20
- filesChanged: boolean;
21
- normalizedAffectedTestFiles: string[];
22
- affectedTestFiles: TestFileInfo[];
15
+ deletedTestPaths: string[];
16
+ };
17
+ type WatchRerunDecision = {
18
+ kind: 'rerun';
19
+ testPaths: string[];
20
+ message: string;
21
+ } | {
22
+ kind: 'empty';
23
+ message: string;
24
+ } | {
25
+ kind: 'idle';
26
+ message: string;
27
+ };
28
+ type WatchRerunPlan = {
29
+ fileSetUpdate?: WatchFileSetUpdate;
30
+ decision: WatchRerunDecision;
23
31
  };
24
32
  export declare const collectWatchTestFiles: (projectEntries: WatchPlannerProjectEntry[]) => TestFileInfo[];
25
33
  export declare const planWatchRerun: ({ projectEntries, previousTestFiles, affectedTestFiles }: WatchRerunPlannerInput) => WatchRerunPlan;
34
+ export declare const commitWatchFileSetUpdate: (update: WatchFileSetUpdate | undefined, watchState: {
35
+ lastTestFiles: TestFileInfo[];
36
+ }, pruneDeletedTestPaths: (testPaths: string[]) => void) => void;
26
37
  export { };
@@ -17,6 +17,13 @@ export declare const createWatchSignals: (onInvalidate: ExecutorInvalidationCall
17
17
  * between and read it. The headed rerun's per-file test-name pattern is the
18
18
  * one such state; core's cycle options cannot carry it, so the only thing
19
19
  * that makes it the property of one cycle is claiming it here.
20
- */ claimScope?: () => void): Promise<void>;
20
+ *
21
+ * Returns a handle to the cycle THIS signal started (still not awaited
22
+ * here — see above). A caller with state to restore must await the
23
+ * returned `cycle` rather than `awaitSignalledCycle`: the shared slot
24
+ * can be overwritten by a concurrent trigger between signal and wait.
25
+ */ claimScope?: () => void): Promise<{
26
+ cycle: Promise<void>;
27
+ }>;
21
28
  awaitSignalledCycle(): Promise<void>;
22
29
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rstest/browser",
3
- "version": "0.11.6",
3
+ "version": "0.11.7",
4
4
  "description": "Browser mode support for Rstest testing framework.",
5
5
  "keywords": [
6
6
  "rstest",
@@ -21,8 +21,8 @@
21
21
  "type": "module",
22
22
  "exports": {
23
23
  ".": {
24
- "types": "./dist/browser.d.ts",
25
- "default": "./dist/browser.js"
24
+ "types": "./dist/client/client/index.d.ts",
25
+ "default": "./dist/client/index.js"
26
26
  },
27
27
  "./internal": {
28
28
  "types": "./dist/index.d.ts",
@@ -32,10 +32,10 @@
32
32
  "default": "./package.json"
33
33
  }
34
34
  },
35
- "main": "./dist/browser.js",
35
+ "main": "./dist/client/index.js",
36
+ "types": "./dist/client/client/index.d.ts",
36
37
  "files": [
37
38
  "dist",
38
- "src",
39
39
  "NOTICE",
40
40
  "LICENSE-APACHE-2.0"
41
41
  ],
@@ -45,24 +45,24 @@
45
45
  "open-editor": "^6.0.0",
46
46
  "pathe": "^2.0.3",
47
47
  "sirv": "^3.0.2",
48
- "ws": "^8.21.1"
48
+ "ws": "^8.21.3"
49
49
  },
50
50
  "devDependencies": {
51
- "@rslib/core": "1.0.0-beta.1",
51
+ "@rslib/core": "1.0.0-beta.2",
52
52
  "@types/convert-source-map": "^2.0.3",
53
53
  "@types/picomatch": "^4.0.3",
54
54
  "@types/ws": "^8.18.1",
55
55
  "@vitest/snapshot": "^4.1.10",
56
- "birpc": "^4.0.0",
56
+ "birpc": "^4.1.0",
57
57
  "picomatch": "^4.0.5",
58
58
  "playwright": "^1.62.1",
59
59
  "@rstest/browser-ui": "0.0.0",
60
60
  "@rstest/tsconfig": "0.0.1",
61
- "@rstest/core": "0.11.6"
61
+ "@rstest/core": "0.11.7"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "playwright": "^1.49.1",
65
- "@rstest/core": "0.11.6"
65
+ "@rstest/core": "0.11.7"
66
66
  },
67
67
  "peerDependenciesMeta": {
68
68
  "playwright": {
package/dist/33.js DELETED
@@ -1,7 +0,0 @@
1
- const DISPATCH_MESSAGE_TYPE = '__rstest_dispatch__';
2
- const DISPATCH_RESPONSE_TYPE = '__rstest_dispatch_response__';
3
- const DISPATCH_RPC_BRIDGE_NAME = '__rstest_dispatch_rpc__';
4
- const DISPATCH_RPC_REQUEST_TYPE = 'dispatch-rpc-request';
5
- const DISPATCH_NAMESPACE_BROWSER = 'browser';
6
- const DISPATCH_NAMESPACE_SNAPSHOT = 'snapshot';
7
- export { DISPATCH_MESSAGE_TYPE, DISPATCH_NAMESPACE_BROWSER, DISPATCH_NAMESPACE_SNAPSHOT, DISPATCH_RESPONSE_TYPE, DISPATCH_RPC_BRIDGE_NAME, DISPATCH_RPC_REQUEST_TYPE };
@@ -1 +0,0 @@
1
- @import "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap";@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-zinc-950:#09090b;--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-light:300;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--tracking-widest:.1em;--radius-md:.375rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}@supports (color:lab(0% 0 0)){:root,:host{--color-zinc-950:lab(2.51107% .242703 -.886115)}}}@layer base,components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.bottom-0{bottom:0}.left-0{left:0}.z-10{z-index:10}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:0}.mt-3{margin-top:calc(var(--spacing) * 3)}.ml-1{margin-left:var(--spacing)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.h-2{height:calc(var(--spacing) * 2)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-\[1px\]{height:1px}.h-\[48px\]{height:48px}.h-full{height:100%}.h-screen{height:100vh}.min-h-0{min-height:0}.w-2{width:calc(var(--spacing) * 2)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-\[16px\]{width:16px}.w-\[120px\]{width:120px}.w-\[280px\]{width:280px}.w-full{width:100%}.max-w-\[400px\]{max-width:400px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.resize{resize:both}.grid-cols-\[auto_minmax\(0\,1fr\)_auto\]{grid-template-columns:auto minmax(0,1fr) auto}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.bg-black\/\[0\.02\]{background-color:#00000005}@supports (color:color-mix(in lab, red, red)){.bg-black\/\[0\.02\]{background-color:color-mix(in oklab, var(--color-black) 2%, transparent)}}.bg-transparent{background-color:#0000}.bg-zinc-950{background-color:var(--color-zinc-950)}.p-0{padding:0}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0{padding-block:0}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.leading-none{--tw-leading:1;line-height:1}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-light{--tw-font-weight:var(--font-weight-light);font-weight:var(--font-weight-light)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-\(--accents-3\){color:var(--accents-3)}.text-\(--accents-4\){color:var(--accents-4)}.text-\(--accents-5\){color:var(--accents-5)}.text-\(--accents-6\){color:var(--accents-6)}.text-\(--accents-7\){color:var(--accents-7)}.text-\(--muted-foreground\){color:var(--muted-foreground)}.text-\(--warning\){color:var(--warning)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal, ) var(--tw-slashed-zero, ) var(--tw-numeric-figure, ) var(--tw-numeric-spacing, ) var(--tw-numeric-fraction, )}.opacity-0{opacity:0}.opacity-40{opacity:.4}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-\[cubic-bezier\(0\.4\,0\,0\.2\,1\)\]{--tw-ease:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1)}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:bg-\(--accents-1\):hover{background-color:var(--accents-1)}.hover\:text-\(--accents-6\):hover{color:var(--accents-6)}}}.ant-typography.font-mono{font-family:var(--font-mono)}:root{--font-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--background:#fff;--foreground:#000;--ds-gray-100:#fafafa;--ds-gray-200:#eaeaea;--ds-gray-300:#999;--ds-gray-400:#888;--ds-gray-500:#666;--ds-gray-600:#444;--ds-gray-700:#333;--ds-gray-800:#111;--ds-gray-900:#000;--ds-gray-1000:#000;--ds-red-100:#fff0f0;--ds-red-200:#ffebeb;--ds-red-300:#ffe6e6;--ds-red-700:#e5484d;--ds-red-800:#da2f35;--ds-red-900:#cb2a2f;--ds-green-100:#effbef;--ds-green-200:#ebfaeb;--ds-green-300:#daf6da;--ds-green-700:#45a557;--ds-green-800:#398e4a;--ds-green-900:#297a3a;--ds-amber-100:#fff6e6;--ds-amber-200:#fff4d6;--ds-amber-300:#fef0cd;--ds-amber-700:#ffb224;--ds-amber-800:#ff990a;--ds-amber-900:#a35200;--ds-blue-700:#0070f3;--accents-1:var(--ds-gray-100);--accents-2:var(--ds-gray-200);--accents-3:var(--ds-gray-300);--accents-4:var(--ds-gray-400);--accents-5:var(--ds-gray-500);--accents-6:var(--ds-gray-600);--accents-7:var(--ds-gray-700);--accents-8:var(--ds-gray-800);--border:var(--accents-2);--muted:var(--accents-1);--muted-foreground:var(--accents-5);--primary:var(--foreground);--success:var(--ds-green-700);--error:var(--ds-red-800);--warning:var(--ds-amber-700);--lightningcss-light:initial;--lightningcss-dark: ;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light}[data-theme=dark]{--background:#000;--foreground:#fff;--ds-gray-100:#111;--ds-gray-200:#333;--ds-gray-300:#444;--ds-gray-400:#666;--ds-gray-500:#888;--ds-gray-600:#999;--ds-gray-700:#eaeaea;--ds-gray-800:#fafafa;--ds-gray-900:#fff;--ds-gray-1000:#fff;--ds-red-100:#2a1314;--ds-red-200:#3c1618;--ds-red-300:#561a1e;--ds-red-700:#e5484d;--ds-red-800:#d93036;--ds-red-900:#ff6166;--ds-green-100:#0b2212;--ds-green-200:#0f2e18;--ds-green-300:#12361b;--ds-green-700:#45a557;--ds-green-800:#398e4a;--ds-green-900:#62c073;--ds-amber-100:#291800;--ds-amber-200:#331b00;--ds-amber-300:#4d2a00;--ds-amber-700:#ffb224;--ds-amber-800:#ff990a;--ds-amber-900:#f2a20d;--ds-blue-700:#0070f3;--accents-1:var(--ds-gray-100);--accents-2:var(--ds-gray-200);--accents-3:var(--ds-gray-300);--accents-4:var(--ds-gray-400);--accents-5:var(--ds-gray-500);--accents-6:var(--ds-gray-600);--accents-7:var(--ds-gray-700);--accents-8:var(--ds-gray-800);--border:var(--accents-2);--muted:var(--accents-1);--muted-foreground:var(--accents-5);--primary:var(--foreground);--success:var(--ds-green-700);--error:var(--ds-red-800);--warning:var(--ds-amber-700);--lightningcss-light: ;--lightningcss-dark:initial;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}*{box-sizing:border-box}body{background:var(--background);min-height:100vh;color:var(--foreground);margin:0;font-family:Inter,system-ui,-apple-system,sans-serif;overflow:hidden}.ant-input-affix-wrapper:focus,.ant-input-affix-wrapper-focused{border-color:var(--foreground);box-shadow:0 0 0 1px var(--foreground)}.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected{transition:none}@keyframes status-flash{0%{filter:brightness()}5%{filter:brightness(2.5)}15%{filter:brightness(1.8)}40%{filter:brightness(1.3)}to{filter:brightness()}}.status-icon-flash{animation:1.5s ease-out status-flash}@keyframes progress-segment-flash{0%{filter:brightness();box-shadow:none}10%{filter:brightness(2.5);box-shadow:0 0 8px 1px}to{filter:brightness();box-shadow:none}}.progress-flash-active{animation:1s cubic-bezier(.4,0,.2,1) progress-segment-flash}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}