@agimon-ai/po-style-system-tooling 0.2.14-alpha.20 → 0.2.14-alpha.22

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.
package/dist/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_stdio = require("./stdio-7W52L7gp.cjs");
2
+ const require_stdio = require("./stdio-CHZgcxF1.cjs");
3
3
  let node_fs = require("node:fs");
4
4
  let node_path = require("node:path");
5
5
  node_path = require_stdio.__toESM(node_path, 1);
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { A as resolveStyleSystemThemePath, B as STYLE_SYSTEM_TYPES, F as TailwindCSSClassesService, P as DEFAULT_STYLE_SYSTEM_CONFIG, a as STYLE_SYSTEM_CLI_NAME, i as createServer$1, o as STYLE_SYSTEM_VERSION, r as generateRestrictedClassesConfig, s as createContainer, t as StdioTransportHandler, w as getAppDesignSystemConfig, y as getBundlerServiceFromConfig, z as log } from "./stdio-Cs3GzGK4.mjs";
2
+ import { A as resolveStyleSystemThemePath, B as STYLE_SYSTEM_TYPES, F as TailwindCSSClassesService, P as DEFAULT_STYLE_SYSTEM_CONFIG, a as STYLE_SYSTEM_CLI_NAME, i as createServer$1, o as STYLE_SYSTEM_VERSION, r as generateRestrictedClassesConfig, s as createContainer, t as StdioTransportHandler, w as getAppDesignSystemConfig, y as getBundlerServiceFromConfig, z as log } from "./stdio-CooVeKmH.mjs";
3
3
  import { promises } from "node:fs";
4
4
  import path, { join } from "node:path";
5
5
  import { z } from "zod";
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_stdio = require("./stdio-7W52L7gp.cjs");
2
+ const require_stdio = require("./stdio-CHZgcxF1.cjs");
3
3
  let node_fs = require("node:fs");
4
4
  let node_path = require("node:path");
5
5
  node_path = require_stdio.__toESM(node_path, 1);
@@ -87,6 +87,100 @@ var StoryPreviewService = class {
87
87
  }
88
88
  };
89
89
  //#endregion
90
+ //#region src/utils/storyBrowser.ts
91
+ const BROWSER_IDLE_MS = 18e5;
92
+ /** Server-owned Chrome. Each capture borrows it until its context cleanup settles. */
93
+ function createStoryBrowser() {
94
+ let pending;
95
+ let closing;
96
+ let timer;
97
+ let active = 0;
98
+ let disposed = false;
99
+ let drained = Promise.resolve();
100
+ let resolveDrained;
101
+ const clearIdle = () => {
102
+ clearTimeout(timer);
103
+ timer = void 0;
104
+ };
105
+ const close = () => {
106
+ if (closing) return closing;
107
+ const generation = pending;
108
+ if (!generation) return Promise.resolve();
109
+ closing = generation.then((browser) => browser.close()).then(() => {
110
+ if (pending === generation) pending = void 0;
111
+ }).finally(() => {
112
+ closing = void 0;
113
+ });
114
+ return closing;
115
+ };
116
+ const idle = () => {
117
+ if (disposed || active !== 0 || !pending) return;
118
+ clearIdle();
119
+ const generation = pending;
120
+ timer = setTimeout(() => {
121
+ timer = void 0;
122
+ if (active !== 0 || pending !== generation) return;
123
+ close().catch((error) => {
124
+ require_stdio.log.error("[story-browser] Idle close failed:", error);
125
+ idle();
126
+ });
127
+ }, BROWSER_IDLE_MS);
128
+ timer.unref();
129
+ };
130
+ return {
131
+ async acquire() {
132
+ if (disposed) throw new Error("The story browser is shut down.");
133
+ clearIdle();
134
+ if (active++ === 0) drained = new Promise((resolve) => {
135
+ resolveDrained = resolve;
136
+ });
137
+ let released = false;
138
+ const release = () => {
139
+ if (released) return;
140
+ released = true;
141
+ if (--active === 0) {
142
+ resolveDrained?.();
143
+ idle();
144
+ }
145
+ };
146
+ try {
147
+ if (closing) await closing;
148
+ if (disposed) throw new Error("The story browser is shut down.");
149
+ if (!pending) {
150
+ const generation = require_stdio.launchBrowserWithFallback().then((browser) => {
151
+ browser.once("disconnected", () => {
152
+ if (pending === generation) {
153
+ pending = void 0;
154
+ clearIdle();
155
+ }
156
+ });
157
+ return browser;
158
+ }).catch((error) => {
159
+ if (pending === generation) pending = void 0;
160
+ throw error;
161
+ });
162
+ pending = generation;
163
+ }
164
+ const browser = await pending;
165
+ if (disposed) throw new Error("The story browser is shut down.");
166
+ return {
167
+ browser,
168
+ release
169
+ };
170
+ } catch (error) {
171
+ release();
172
+ throw error;
173
+ }
174
+ },
175
+ async dispose() {
176
+ disposed = true;
177
+ clearIdle();
178
+ await drained;
179
+ await close();
180
+ }
181
+ };
182
+ }
183
+ //#endregion
90
184
  //#region src/services/WarmStoryRenderer/WarmStoryRenderer.ts
91
185
  /** The style-system tools a warm host exposes, by tool name. */
92
186
  const WARM_RENDERER_TOOLS = {
@@ -115,7 +209,7 @@ function createWarmStoryRenderer(options = {}) {
115
209
  const container = require_stdio.createContainer({
116
210
  ...options,
117
211
  workspaceRoot,
118
- sharedBrowser,
212
+ sharedBrowser: options.sharedBrowser ?? sharedBrowser,
119
213
  bundlerFactory: () => {
120
214
  if (!activeBundler) throw new Error("The story bundler has not been initialized.");
121
215
  return activeBundler;
@@ -125,6 +219,7 @@ function createWarmStoryRenderer(options = {}) {
125
219
  const createBundler = (config) => config.bundler ? require_stdio.getBundlerService(config.bundler, workspaceRoot) : require_stdio.createDefaultBundlerService(workspaceRoot);
126
220
  let queue = Promise.resolve();
127
221
  let disposed = false;
222
+ let captures = 0;
128
223
  const ensureDevServer = async (appPath) => {
129
224
  const resolved = node_path.default.resolve(workspaceRoot ?? ".", appPath);
130
225
  const { config } = await configLoader.resolveProject(resolved);
@@ -142,13 +237,16 @@ function createWarmStoryRenderer(options = {}) {
142
237
  const bundler = await pending;
143
238
  if (activeBundler && activeBundler !== bundler && activeBundler.isServerRunning()) await activeBundler.cleanup();
144
239
  activeBundler = bundler;
145
- if (bundler.isServerRunning() && bundler.getCurrentAppPath() === resolved) return;
240
+ const recycle = bundler.getBundlerId() === "vite" && captures >= 100;
241
+ if (bundler.isServerRunning() && bundler.getCurrentAppPath() === resolved && !recycle) return;
146
242
  if (bundler.isServerRunning()) await bundler.cleanup();
243
+ captures = 0;
147
244
  await bundler.startDevServer(resolved);
148
245
  };
149
246
  const reset = async () => {
150
247
  const open = browser;
151
248
  browser = void 0;
249
+ captures = 0;
152
250
  await Promise.allSettled([open?.then((instance) => instance.close()), ...[...bundlers.values()].map((pending) => pending.then((bundler) => bundler.cleanup()))]);
153
251
  };
154
252
  const run = async (tool, input) => {
@@ -163,7 +261,10 @@ function createWarmStoryRenderer(options = {}) {
163
261
  }
164
262
  const visualAppPath = tool === "get_component_visual" && typeof input.appPath === "string" ? input.appPath : void 0;
165
263
  const execute = async () => {
166
- if (visualAppPath) await ensureDevServer(visualAppPath);
264
+ if (visualAppPath) {
265
+ await ensureDevServer(visualAppPath);
266
+ captures++;
267
+ }
167
268
  const result = await container.get(WARM_RENDERER_TOOLS[tool]).execute(input);
168
269
  return {
169
270
  result,
@@ -278,6 +379,7 @@ exports.WARM_RENDERER_TOOLS = WARM_RENDERER_TOOLS;
278
379
  exports.createContainer = require_stdio.createContainer;
279
380
  exports.createDefaultBundlerService = require_stdio.createDefaultBundlerService;
280
381
  exports.createServer = require_stdio.createServer;
382
+ exports.createStoryBrowser = createStoryBrowser;
281
383
  exports.createStyleSystemModule = require_stdio.createStyleSystemModule;
282
384
  exports.createWarmStoryRenderer = createWarmStoryRenderer;
283
385
  exports.extractCustomTokenNames = require_stdio.extractCustomTokenNames;
package/dist/index.d.cts CHANGED
@@ -148,6 +148,35 @@ export declare function hasStyleSystemProjectConfig(appPath: string): Promise<bo
148
148
  /** Workspace-wide tags that identify shared/design system components. */
149
149
  export declare function getSharedComponentTags(): Promise<string[]>;
150
150
  //#endregion
151
+ //#region src/utils/screenshot.d.ts
152
+ interface BrowserLease {
153
+ browser: Browser;
154
+ release(): void;
155
+ }
156
+ interface ScreenshotOptions {
157
+ /** A borrowed browser; release runs only after this render's context cleanup settles. */
158
+ sharedBrowser?: () => Promise<Browser | BrowserLease>;
159
+ url: string;
160
+ output: string;
161
+ width?: number;
162
+ height?: number;
163
+ fullPage?: boolean;
164
+ browser?: 'chromium' | 'firefox' | 'webkit';
165
+ waitTime?: number;
166
+ darkMode?: boolean;
167
+ mobile?: boolean;
168
+ generateThumbnail?: boolean;
169
+ thumbnailWidth?: number;
170
+ thumbnailQuality?: number;
171
+ base64?: boolean;
172
+ }
173
+ /**
174
+ * Attempts to launch a browser, trying multiple configurations in order of preference.
175
+ * @returns Launched browser instance
176
+ * @throws Error if no browser can be launched
177
+ */
178
+ export declare function launchBrowserWithFallback(): Promise<Browser>;
179
+ //#endregion
151
180
  //#region src/services/BundlerService/types.d.ts
152
181
  /**
153
182
  * BundlerService Types
@@ -623,7 +652,7 @@ interface StyleSystemModuleOptions {
623
652
  bundlerFactory?: (config: DesignSystemConfig) => BaseBundlerService;
624
653
  temporaryDirectory?: string;
625
654
  /** A browser a long-lived host keeps warm across renders; one-shot CLI runs leave it unset. */
626
- sharedBrowser?: () => Promise<Browser>;
655
+ sharedBrowser?: ScreenshotOptions['sharedBrowser'];
627
656
  }
628
657
  export declare function createStyleSystemModule(optionsInput?: StyleSystemModuleOptions): ContainerModule;
629
658
  //#endregion
@@ -926,7 +955,7 @@ export declare class ComponentRendererService {
926
955
  bundlerFactory?: BundlerFactory;
927
956
  workspaceRoot?: string;
928
957
  temporaryDirectory?: string;
929
- sharedBrowser?: () => Promise<Browser>;
958
+ sharedBrowser?: ScreenshotOptions['sharedBrowser'];
930
959
  });
931
960
  /**
932
961
  * Get the bundler service instance.
@@ -2057,13 +2086,12 @@ export declare class StdioTransportHandler {
2057
2086
  stop(): Promise<void>;
2058
2087
  }
2059
2088
  //#endregion
2060
- //#region src/utils/screenshot.d.ts
2061
- /**
2062
- * Attempts to launch a browser, trying multiple configurations in order of preference.
2063
- * @returns Launched browser instance
2064
- * @throws Error if no browser can be launched
2065
- */
2066
- export declare function launchBrowserWithFallback(): Promise<Browser>;
2089
+ //#region src/utils/storyBrowser.d.ts
2090
+ /** Server-owned Chrome. Each capture borrows it until its context cleanup settles. */
2091
+ export declare function createStoryBrowser(): {
2092
+ acquire(): Promise<BrowserLease>;
2093
+ dispose(): Promise<void>;
2094
+ };
2067
2095
  //#endregion
2068
2096
  //#region src/services/WarmStoryRenderer/WarmStoryRenderer.d.ts
2069
2097
  /** The style-system tools a warm host exposes, by tool name. */
@@ -2086,7 +2114,7 @@ interface WarmRendererResult {
2086
2114
  interface WarmStoryRenderer {
2087
2115
  /** Runs one tool. Calls are serialized: the dev server serves one app at a time. */
2088
2116
  call(tool: WarmRendererToolName, input: Record<string, unknown>): Promise<WarmRendererResult>;
2089
- /** Closes the browser and dev servers; the next render starts fresh ones. */
2117
+ /** Closes owned resources; a borrowed server browser remains running. */
2090
2118
  restart(): Promise<void>;
2091
2119
  dispose(): Promise<void>;
2092
2120
  }
@@ -2097,6 +2125,7 @@ interface WarmStoryRenderer {
2097
2125
  export declare function createWarmStoryRenderer(options?: {
2098
2126
  workspaceRoot?: string;
2099
2127
  temporaryDirectory?: string;
2128
+ sharedBrowser?: ScreenshotOptions['sharedBrowser'];
2100
2129
  }): WarmStoryRenderer;
2101
2130
  //#endregion
2102
2131
  export type { CSSClassCategory, CSSClassValue, CSSClassesResult, DesignSystemConfig, OxlintRestrictedClassPattern, OxlintRestrictedClassesConfig, ResolvedDesignSystemConfig, StoryPreviewIdentity, StoryPreviewInput, StoryPreviewResult, StoryPreviewServiceOptions, StyleSystemConfig, StyleSystemModuleOptions, Tool, ToolDefinition, WarmRendererResult, WarmRendererToolName, WarmStoryRenderer };
package/dist/index.d.mts CHANGED
@@ -148,6 +148,35 @@ export declare function hasStyleSystemProjectConfig(appPath: string): Promise<bo
148
148
  /** Workspace-wide tags that identify shared/design system components. */
149
149
  export declare function getSharedComponentTags(): Promise<string[]>;
150
150
  //#endregion
151
+ //#region src/utils/screenshot.d.ts
152
+ interface BrowserLease {
153
+ browser: Browser;
154
+ release(): void;
155
+ }
156
+ interface ScreenshotOptions {
157
+ /** A borrowed browser; release runs only after this render's context cleanup settles. */
158
+ sharedBrowser?: () => Promise<Browser | BrowserLease>;
159
+ url: string;
160
+ output: string;
161
+ width?: number;
162
+ height?: number;
163
+ fullPage?: boolean;
164
+ browser?: 'chromium' | 'firefox' | 'webkit';
165
+ waitTime?: number;
166
+ darkMode?: boolean;
167
+ mobile?: boolean;
168
+ generateThumbnail?: boolean;
169
+ thumbnailWidth?: number;
170
+ thumbnailQuality?: number;
171
+ base64?: boolean;
172
+ }
173
+ /**
174
+ * Attempts to launch a browser, trying multiple configurations in order of preference.
175
+ * @returns Launched browser instance
176
+ * @throws Error if no browser can be launched
177
+ */
178
+ export declare function launchBrowserWithFallback(): Promise<Browser>;
179
+ //#endregion
151
180
  //#region src/services/BundlerService/types.d.ts
152
181
  /**
153
182
  * BundlerService Types
@@ -623,7 +652,7 @@ interface StyleSystemModuleOptions {
623
652
  bundlerFactory?: (config: DesignSystemConfig) => BaseBundlerService;
624
653
  temporaryDirectory?: string;
625
654
  /** A browser a long-lived host keeps warm across renders; one-shot CLI runs leave it unset. */
626
- sharedBrowser?: () => Promise<Browser>;
655
+ sharedBrowser?: ScreenshotOptions['sharedBrowser'];
627
656
  }
628
657
  export declare function createStyleSystemModule(optionsInput?: StyleSystemModuleOptions): ContainerModule;
629
658
  //#endregion
@@ -926,7 +955,7 @@ export declare class ComponentRendererService {
926
955
  bundlerFactory?: BundlerFactory;
927
956
  workspaceRoot?: string;
928
957
  temporaryDirectory?: string;
929
- sharedBrowser?: () => Promise<Browser>;
958
+ sharedBrowser?: ScreenshotOptions['sharedBrowser'];
930
959
  });
931
960
  /**
932
961
  * Get the bundler service instance.
@@ -2057,13 +2086,12 @@ export declare class StdioTransportHandler {
2057
2086
  stop(): Promise<void>;
2058
2087
  }
2059
2088
  //#endregion
2060
- //#region src/utils/screenshot.d.ts
2061
- /**
2062
- * Attempts to launch a browser, trying multiple configurations in order of preference.
2063
- * @returns Launched browser instance
2064
- * @throws Error if no browser can be launched
2065
- */
2066
- export declare function launchBrowserWithFallback(): Promise<Browser>;
2089
+ //#region src/utils/storyBrowser.d.ts
2090
+ /** Server-owned Chrome. Each capture borrows it until its context cleanup settles. */
2091
+ export declare function createStoryBrowser(): {
2092
+ acquire(): Promise<BrowserLease>;
2093
+ dispose(): Promise<void>;
2094
+ };
2067
2095
  //#endregion
2068
2096
  //#region src/services/WarmStoryRenderer/WarmStoryRenderer.d.ts
2069
2097
  /** The style-system tools a warm host exposes, by tool name. */
@@ -2086,7 +2114,7 @@ interface WarmRendererResult {
2086
2114
  interface WarmStoryRenderer {
2087
2115
  /** Runs one tool. Calls are serialized: the dev server serves one app at a time. */
2088
2116
  call(tool: WarmRendererToolName, input: Record<string, unknown>): Promise<WarmRendererResult>;
2089
- /** Closes the browser and dev servers; the next render starts fresh ones. */
2117
+ /** Closes owned resources; a borrowed server browser remains running. */
2090
2118
  restart(): Promise<void>;
2091
2119
  dispose(): Promise<void>;
2092
2120
  }
@@ -2097,6 +2125,7 @@ interface WarmStoryRenderer {
2097
2125
  export declare function createWarmStoryRenderer(options?: {
2098
2126
  workspaceRoot?: string;
2099
2127
  temporaryDirectory?: string;
2128
+ sharedBrowser?: ScreenshotOptions['sharedBrowser'];
2100
2129
  }): WarmStoryRenderer;
2101
2130
  //#endregion
2102
2131
  export type { CSSClassCategory, CSSClassValue, CSSClassesResult, DesignSystemConfig, OxlintRestrictedClassPattern, OxlintRestrictedClassesConfig, ResolvedDesignSystemConfig, StoryPreviewIdentity, StoryPreviewInput, StoryPreviewResult, StoryPreviewServiceOptions, StyleSystemConfig, StyleSystemModuleOptions, Tool, ToolDefinition, WarmRendererResult, WarmRendererToolName, WarmStoryRenderer };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as resolveStyleSystemThemePath, B as STYLE_SYSTEM_TYPES, C as launchBrowserWithFallback, D as resetStyleSystemConfigCache, E as hasStyleSystemProjectConfig, F as TailwindCSSClassesService, I as BaseCSSClassesService, L as TemplatesManagerService, M as StoriesIndexService, N as CSSClassesServiceFactory, O as resolveAppDesignSystemConfig, P as DEFAULT_STYLE_SYSTEM_CONFIG, R as isContained, S as BaseBundlerService, T as getSharedComponentTags, _ as createDefaultBundlerService, b as ViteReactNativeBundlerService, c as createStyleSystemModule, d as GetComponentVisualTool, f as GetCSSClassesTool, g as ThemeService, h as ComponentRendererService, i as createServer, j as MAX_STYLE_SYSTEM_VIEWPORT_DIMENSION, k as StyleSystemConfigLoader, l as ListAppComponentsTool, m as GetUiComponentService, n as extractCustomTokenNames, p as ListThemesTool, r as generateRestrictedClassesConfig, s as createContainer, t as StdioTransportHandler, u as ListSharedComponentsTool, v as getBundlerService, w as getAppDesignSystemConfig, x as ViteReactBundlerService, y as getBundlerServiceFromConfig } from "./stdio-Cs3GzGK4.mjs";
1
+ import { A as resolveStyleSystemThemePath, B as STYLE_SYSTEM_TYPES, C as launchBrowserWithFallback, D as resetStyleSystemConfigCache, E as hasStyleSystemProjectConfig, F as TailwindCSSClassesService, I as BaseCSSClassesService, L as TemplatesManagerService, M as StoriesIndexService, N as CSSClassesServiceFactory, O as resolveAppDesignSystemConfig, P as DEFAULT_STYLE_SYSTEM_CONFIG, R as isContained, S as BaseBundlerService, T as getSharedComponentTags, _ as createDefaultBundlerService, b as ViteReactNativeBundlerService, c as createStyleSystemModule, d as GetComponentVisualTool, f as GetCSSClassesTool, g as ThemeService, h as ComponentRendererService, i as createServer, j as MAX_STYLE_SYSTEM_VIEWPORT_DIMENSION, k as StyleSystemConfigLoader, l as ListAppComponentsTool, m as GetUiComponentService, n as extractCustomTokenNames, p as ListThemesTool, r as generateRestrictedClassesConfig, s as createContainer, t as StdioTransportHandler, u as ListSharedComponentsTool, v as getBundlerService, w as getAppDesignSystemConfig, x as ViteReactBundlerService, y as getBundlerServiceFromConfig, z as log } from "./stdio-CooVeKmH.mjs";
2
2
  import { promises } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { createHash, randomUUID } from "node:crypto";
@@ -85,6 +85,100 @@ var StoryPreviewService = class {
85
85
  }
86
86
  };
87
87
  //#endregion
88
+ //#region src/utils/storyBrowser.ts
89
+ const BROWSER_IDLE_MS = 18e5;
90
+ /** Server-owned Chrome. Each capture borrows it until its context cleanup settles. */
91
+ function createStoryBrowser() {
92
+ let pending;
93
+ let closing;
94
+ let timer;
95
+ let active = 0;
96
+ let disposed = false;
97
+ let drained = Promise.resolve();
98
+ let resolveDrained;
99
+ const clearIdle = () => {
100
+ clearTimeout(timer);
101
+ timer = void 0;
102
+ };
103
+ const close = () => {
104
+ if (closing) return closing;
105
+ const generation = pending;
106
+ if (!generation) return Promise.resolve();
107
+ closing = generation.then((browser) => browser.close()).then(() => {
108
+ if (pending === generation) pending = void 0;
109
+ }).finally(() => {
110
+ closing = void 0;
111
+ });
112
+ return closing;
113
+ };
114
+ const idle = () => {
115
+ if (disposed || active !== 0 || !pending) return;
116
+ clearIdle();
117
+ const generation = pending;
118
+ timer = setTimeout(() => {
119
+ timer = void 0;
120
+ if (active !== 0 || pending !== generation) return;
121
+ close().catch((error) => {
122
+ log.error("[story-browser] Idle close failed:", error);
123
+ idle();
124
+ });
125
+ }, BROWSER_IDLE_MS);
126
+ timer.unref();
127
+ };
128
+ return {
129
+ async acquire() {
130
+ if (disposed) throw new Error("The story browser is shut down.");
131
+ clearIdle();
132
+ if (active++ === 0) drained = new Promise((resolve) => {
133
+ resolveDrained = resolve;
134
+ });
135
+ let released = false;
136
+ const release = () => {
137
+ if (released) return;
138
+ released = true;
139
+ if (--active === 0) {
140
+ resolveDrained?.();
141
+ idle();
142
+ }
143
+ };
144
+ try {
145
+ if (closing) await closing;
146
+ if (disposed) throw new Error("The story browser is shut down.");
147
+ if (!pending) {
148
+ const generation = launchBrowserWithFallback().then((browser) => {
149
+ browser.once("disconnected", () => {
150
+ if (pending === generation) {
151
+ pending = void 0;
152
+ clearIdle();
153
+ }
154
+ });
155
+ return browser;
156
+ }).catch((error) => {
157
+ if (pending === generation) pending = void 0;
158
+ throw error;
159
+ });
160
+ pending = generation;
161
+ }
162
+ const browser = await pending;
163
+ if (disposed) throw new Error("The story browser is shut down.");
164
+ return {
165
+ browser,
166
+ release
167
+ };
168
+ } catch (error) {
169
+ release();
170
+ throw error;
171
+ }
172
+ },
173
+ async dispose() {
174
+ disposed = true;
175
+ clearIdle();
176
+ await drained;
177
+ await close();
178
+ }
179
+ };
180
+ }
181
+ //#endregion
88
182
  //#region src/services/WarmStoryRenderer/WarmStoryRenderer.ts
89
183
  /** The style-system tools a warm host exposes, by tool name. */
90
184
  const WARM_RENDERER_TOOLS = {
@@ -113,7 +207,7 @@ function createWarmStoryRenderer(options = {}) {
113
207
  const container = createContainer({
114
208
  ...options,
115
209
  workspaceRoot,
116
- sharedBrowser,
210
+ sharedBrowser: options.sharedBrowser ?? sharedBrowser,
117
211
  bundlerFactory: () => {
118
212
  if (!activeBundler) throw new Error("The story bundler has not been initialized.");
119
213
  return activeBundler;
@@ -123,6 +217,7 @@ function createWarmStoryRenderer(options = {}) {
123
217
  const createBundler = (config) => config.bundler ? getBundlerService(config.bundler, workspaceRoot) : createDefaultBundlerService(workspaceRoot);
124
218
  let queue = Promise.resolve();
125
219
  let disposed = false;
220
+ let captures = 0;
126
221
  const ensureDevServer = async (appPath) => {
127
222
  const resolved = path.resolve(workspaceRoot ?? ".", appPath);
128
223
  const { config } = await configLoader.resolveProject(resolved);
@@ -140,13 +235,16 @@ function createWarmStoryRenderer(options = {}) {
140
235
  const bundler = await pending;
141
236
  if (activeBundler && activeBundler !== bundler && activeBundler.isServerRunning()) await activeBundler.cleanup();
142
237
  activeBundler = bundler;
143
- if (bundler.isServerRunning() && bundler.getCurrentAppPath() === resolved) return;
238
+ const recycle = bundler.getBundlerId() === "vite" && captures >= 100;
239
+ if (bundler.isServerRunning() && bundler.getCurrentAppPath() === resolved && !recycle) return;
144
240
  if (bundler.isServerRunning()) await bundler.cleanup();
241
+ captures = 0;
145
242
  await bundler.startDevServer(resolved);
146
243
  };
147
244
  const reset = async () => {
148
245
  const open = browser;
149
246
  browser = void 0;
247
+ captures = 0;
150
248
  await Promise.allSettled([open?.then((instance) => instance.close()), ...[...bundlers.values()].map((pending) => pending.then((bundler) => bundler.cleanup()))]);
151
249
  };
152
250
  const run = async (tool, input) => {
@@ -161,7 +259,10 @@ function createWarmStoryRenderer(options = {}) {
161
259
  }
162
260
  const visualAppPath = tool === "get_component_visual" && typeof input.appPath === "string" ? input.appPath : void 0;
163
261
  const execute = async () => {
164
- if (visualAppPath) await ensureDevServer(visualAppPath);
262
+ if (visualAppPath) {
263
+ await ensureDevServer(visualAppPath);
264
+ captures++;
265
+ }
165
266
  const result = await container.get(WARM_RENDERER_TOOLS[tool]).execute(input);
166
267
  return {
167
268
  result,
@@ -206,4 +307,4 @@ function createWarmStoryRenderer(options = {}) {
206
307
  };
207
308
  }
208
309
  //#endregion
209
- export { BaseBundlerService, BaseCSSClassesService, CSSClassesServiceFactory, ComponentRendererService, DEFAULT_STYLE_SYSTEM_CONFIG, GetCSSClassesTool, GetComponentVisualTool, GetUiComponentService, ListAppComponentsTool, ListSharedComponentsTool, ListThemesTool, MAX_STYLE_SYSTEM_VIEWPORT_DIMENSION, STYLE_SYSTEM_TYPES, StdioTransportHandler, StoriesIndexService, StoryPreviewService, StyleSystemConfigLoader, TailwindCSSClassesService, ThemeService, ViteReactBundlerService, ViteReactNativeBundlerService, WARM_RENDERER_TOOLS, createContainer, createDefaultBundlerService, createServer, createStyleSystemModule, createWarmStoryRenderer, extractCustomTokenNames, generateRestrictedClassesConfig, getAppDesignSystemConfig, getBundlerService, getBundlerServiceFromConfig, getSharedComponentTags, hasStyleSystemProjectConfig, launchBrowserWithFallback, resetStyleSystemConfigCache, resolveAppDesignSystemConfig, resolveStyleSystemThemePath };
310
+ export { BaseBundlerService, BaseCSSClassesService, CSSClassesServiceFactory, ComponentRendererService, DEFAULT_STYLE_SYSTEM_CONFIG, GetCSSClassesTool, GetComponentVisualTool, GetUiComponentService, ListAppComponentsTool, ListSharedComponentsTool, ListThemesTool, MAX_STYLE_SYSTEM_VIEWPORT_DIMENSION, STYLE_SYSTEM_TYPES, StdioTransportHandler, StoriesIndexService, StoryPreviewService, StyleSystemConfigLoader, TailwindCSSClassesService, ThemeService, ViteReactBundlerService, ViteReactNativeBundlerService, WARM_RENDERER_TOOLS, createContainer, createDefaultBundlerService, createServer, createStoryBrowser, createStyleSystemModule, createWarmStoryRenderer, extractCustomTokenNames, generateRestrictedClassesConfig, getAppDesignSystemConfig, getBundlerService, getBundlerServiceFromConfig, getSharedComponentTags, hasStyleSystemProjectConfig, launchBrowserWithFallback, resetStyleSystemConfigCache, resolveAppDesignSystemConfig, resolveStyleSystemThemePath };
@@ -1665,9 +1665,15 @@ async function takeScreenshot(options) {
1665
1665
  const { url, output, width = 1280, height = 800, fullPage = false, browser: browserName = "chromium", waitTime = 1e3, darkMode = false, mobile = false, generateThumbnail = false, thumbnailWidth = 400, thumbnailQuality = 80, base64 = false, sharedBrowser } = options;
1666
1666
  let browser = null;
1667
1667
  let context = null;
1668
+ let release;
1668
1669
  try {
1669
- if (sharedBrowser) browser = await sharedBrowser();
1670
- else if (browserName === "chromium") browser = await launchBrowserWithFallback();
1670
+ if (sharedBrowser) {
1671
+ const borrowed = await sharedBrowser();
1672
+ if ("browser" in borrowed) {
1673
+ browser = borrowed.browser;
1674
+ release = () => borrowed.release();
1675
+ } else browser = borrowed;
1676
+ } else if (browserName === "chromium") browser = await launchBrowserWithFallback();
1671
1677
  else {
1672
1678
  const browserType = browsers[browserName];
1673
1679
  if (!browserType) throw new Error(`Unsupported browser: ${browserName}`);
@@ -1735,8 +1741,12 @@ async function takeScreenshot(options) {
1735
1741
  if (base64) result.base64 = screenshotBuffer.toString("base64");
1736
1742
  return result;
1737
1743
  } finally {
1738
- if (sharedBrowser) await context?.close();
1739
- else if (browser) await browser.close();
1744
+ try {
1745
+ if (sharedBrowser) await context?.close();
1746
+ else if (browser) await browser.close();
1747
+ } finally {
1748
+ release?.();
1749
+ }
1740
1750
  }
1741
1751
  }
1742
1752
  //#endregion
@@ -4748,7 +4758,7 @@ function createContainer(options) {
4748
4758
  }
4749
4759
  //#endregion
4750
4760
  //#region package.json
4751
- var version = "0.2.14-alpha.20";
4761
+ var version = "0.2.14-alpha.22";
4752
4762
  //#endregion
4753
4763
  //#region src/metadata.ts
4754
4764
  const STYLE_SYSTEM_CLI_NAME = "style-system";
@@ -1640,9 +1640,15 @@ async function takeScreenshot(options) {
1640
1640
  const { url, output, width = 1280, height = 800, fullPage = false, browser: browserName = "chromium", waitTime = 1e3, darkMode = false, mobile = false, generateThumbnail = false, thumbnailWidth = 400, thumbnailQuality = 80, base64 = false, sharedBrowser } = options;
1641
1641
  let browser = null;
1642
1642
  let context = null;
1643
+ let release;
1643
1644
  try {
1644
- if (sharedBrowser) browser = await sharedBrowser();
1645
- else if (browserName === "chromium") browser = await launchBrowserWithFallback();
1645
+ if (sharedBrowser) {
1646
+ const borrowed = await sharedBrowser();
1647
+ if ("browser" in borrowed) {
1648
+ browser = borrowed.browser;
1649
+ release = () => borrowed.release();
1650
+ } else browser = borrowed;
1651
+ } else if (browserName === "chromium") browser = await launchBrowserWithFallback();
1646
1652
  else {
1647
1653
  const browserType = browsers[browserName];
1648
1654
  if (!browserType) throw new Error(`Unsupported browser: ${browserName}`);
@@ -1710,8 +1716,12 @@ async function takeScreenshot(options) {
1710
1716
  if (base64) result.base64 = screenshotBuffer.toString("base64");
1711
1717
  return result;
1712
1718
  } finally {
1713
- if (sharedBrowser) await context?.close();
1714
- else if (browser) await browser.close();
1719
+ try {
1720
+ if (sharedBrowser) await context?.close();
1721
+ else if (browser) await browser.close();
1722
+ } finally {
1723
+ release?.();
1724
+ }
1715
1725
  }
1716
1726
  }
1717
1727
  //#endregion
@@ -4723,7 +4733,7 @@ function createContainer(options) {
4723
4733
  }
4724
4734
  //#endregion
4725
4735
  //#region package.json
4726
- var version = "0.2.14-alpha.20";
4736
+ var version = "0.2.14-alpha.22";
4727
4737
  //#endregion
4728
4738
  //#region src/metadata.ts
4729
4739
  const STYLE_SYSTEM_CLI_NAME = "style-system";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/po-style-system-tooling",
3
- "version": "0.2.14-alpha.20",
3
+ "version": "0.2.14-alpha.22",
4
4
  "description": "MCP server for exploring themes, Tailwind CSS classes, and UI components from Storybook with standalone component rendering capabilities",
5
5
  "keywords": [
6
6
  "design-system",