@agimon-ai/po-style-system-tooling 0.2.14-alpha.2 → 0.2.14-alpha.21
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/LICENSE +149 -21
- package/README.md +1 -2
- package/dist/cli.cjs +9 -41
- package/dist/cli.mjs +10 -42
- package/dist/index.cjs +229 -7
- package/dist/index.d.cts +361 -257
- package/dist/index.d.mts +360 -256
- package/dist/index.mjs +224 -2
- package/dist/{stdio-CT9XjOJQ.cjs → stdio-CSwuqV9E.cjs} +427 -660
- package/dist/{stdio-Dgaj2-_8.mjs → stdio-DBEflKj3.mjs} +415 -658
- package/package.json +22 -14
- package/skills/style-system/SKILL.md +43 -21
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as STYLE_SYSTEM_TYPES, C as
|
|
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-DBEflKj3.mjs";
|
|
2
2
|
import { promises } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -85,4 +85,226 @@ var StoryPreviewService = class {
|
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
87
|
//#endregion
|
|
88
|
-
|
|
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
|
|
182
|
+
//#region src/services/WarmStoryRenderer/WarmStoryRenderer.ts
|
|
183
|
+
/** The style-system tools a warm host exposes, by tool name. */
|
|
184
|
+
const WARM_RENDERER_TOOLS = {
|
|
185
|
+
get_component_visual: STYLE_SYSTEM_TYPES.GetComponentVisualTool,
|
|
186
|
+
get_css_classes: STYLE_SYSTEM_TYPES.GetCSSClassesTool,
|
|
187
|
+
list_themes: STYLE_SYSTEM_TYPES.ListThemesTool,
|
|
188
|
+
list_shared_components: STYLE_SYSTEM_TYPES.ListSharedComponentsTool,
|
|
189
|
+
list_app_components: STYLE_SYSTEM_TYPES.ListAppComponentsTool
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* Keeps one browser and one Vite dev server warm across renders, so a render after the first
|
|
193
|
+
* skips the browser launch and the static build. Rendered screenshots come back as base64.
|
|
194
|
+
*/
|
|
195
|
+
function createWarmStoryRenderer(options = {}) {
|
|
196
|
+
const workspaceRoot = options.workspaceRoot ? path.resolve(options.workspaceRoot) : void 0;
|
|
197
|
+
let browser;
|
|
198
|
+
const sharedBrowser = () => {
|
|
199
|
+
browser ??= launchBrowserWithFallback().catch((error) => {
|
|
200
|
+
browser = void 0;
|
|
201
|
+
throw error;
|
|
202
|
+
});
|
|
203
|
+
return browser;
|
|
204
|
+
};
|
|
205
|
+
let activeBundler;
|
|
206
|
+
const bundlers = /* @__PURE__ */ new Map();
|
|
207
|
+
const container = createContainer({
|
|
208
|
+
...options,
|
|
209
|
+
workspaceRoot,
|
|
210
|
+
sharedBrowser: options.sharedBrowser ?? sharedBrowser,
|
|
211
|
+
bundlerFactory: () => {
|
|
212
|
+
if (!activeBundler) throw new Error("The story bundler has not been initialized.");
|
|
213
|
+
return activeBundler;
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
const configLoader = container.get(STYLE_SYSTEM_TYPES.StyleSystemConfigLoader);
|
|
217
|
+
const createBundler = (config) => config.bundler ? getBundlerService(config.bundler, workspaceRoot) : createDefaultBundlerService(workspaceRoot);
|
|
218
|
+
let queue = Promise.resolve();
|
|
219
|
+
let disposed = false;
|
|
220
|
+
let captures = 0;
|
|
221
|
+
const ensureDevServer = async (appPath) => {
|
|
222
|
+
const resolved = path.resolve(workspaceRoot ?? ".", appPath);
|
|
223
|
+
const { config } = await configLoader.resolveProject(resolved);
|
|
224
|
+
const key = config.bundler ?? "vite-react";
|
|
225
|
+
let pending = bundlers.get(key);
|
|
226
|
+
if (!pending) {
|
|
227
|
+
pending = workspaceRoot ? getBundlerServiceFromConfig({
|
|
228
|
+
workspaceRoot,
|
|
229
|
+
configLoader,
|
|
230
|
+
defaultFactory: () => createBundler(config)
|
|
231
|
+
}) : Promise.resolve(createBundler(config));
|
|
232
|
+
bundlers.set(key, pending);
|
|
233
|
+
pending.catch(() => bundlers.delete(key));
|
|
234
|
+
}
|
|
235
|
+
const bundler = await pending;
|
|
236
|
+
if (activeBundler && activeBundler !== bundler && activeBundler.isServerRunning()) await activeBundler.cleanup();
|
|
237
|
+
activeBundler = bundler;
|
|
238
|
+
const recycle = bundler.getBundlerId() === "vite" && captures >= 100;
|
|
239
|
+
if (bundler.isServerRunning() && bundler.getCurrentAppPath() === resolved && !recycle) return;
|
|
240
|
+
if (bundler.isServerRunning()) await bundler.cleanup();
|
|
241
|
+
captures = 0;
|
|
242
|
+
await bundler.startDevServer(resolved);
|
|
243
|
+
};
|
|
244
|
+
const reset = async () => {
|
|
245
|
+
const open = browser;
|
|
246
|
+
browser = void 0;
|
|
247
|
+
captures = 0;
|
|
248
|
+
await Promise.allSettled([open?.then((instance) => instance.close()), ...[...bundlers.values()].map((pending) => pending.then((bundler) => bundler.cleanup()))]);
|
|
249
|
+
};
|
|
250
|
+
const run = async (tool, input) => {
|
|
251
|
+
if (disposed) throw new Error("The story renderer is shut down.");
|
|
252
|
+
if (workspaceRoot && typeof input.appPath === "string") {
|
|
253
|
+
const [root, appPath] = await Promise.all([promises.realpath(workspaceRoot), promises.realpath(path.resolve(workspaceRoot, input.appPath))]);
|
|
254
|
+
if (!isContained(root, appPath)) throw new Error("appPath must remain inside the configured workspace root.");
|
|
255
|
+
input = {
|
|
256
|
+
...input,
|
|
257
|
+
appPath
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const visualAppPath = tool === "get_component_visual" && typeof input.appPath === "string" ? input.appPath : void 0;
|
|
261
|
+
const execute = async () => {
|
|
262
|
+
if (visualAppPath) {
|
|
263
|
+
await ensureDevServer(visualAppPath);
|
|
264
|
+
captures++;
|
|
265
|
+
}
|
|
266
|
+
const result = await container.get(WARM_RENDERER_TOOLS[tool]).execute(input);
|
|
267
|
+
return {
|
|
268
|
+
result,
|
|
269
|
+
text: result.content.flatMap((item) => item.type === "text" && item.text ? [item.text] : []).join("\n\n")
|
|
270
|
+
};
|
|
271
|
+
};
|
|
272
|
+
let { result, text } = await execute();
|
|
273
|
+
if (visualAppPath && result.isError && text.includes("Failed to render component")) {
|
|
274
|
+
await reset();
|
|
275
|
+
({result, text} = await execute());
|
|
276
|
+
}
|
|
277
|
+
const images = [];
|
|
278
|
+
if (tool === "get_component_visual" && !result.isError) {
|
|
279
|
+
const imagePath = /"imagePath":\s*"([^"]+)"/u.exec(text)?.[1];
|
|
280
|
+
if (imagePath) images.push({
|
|
281
|
+
data: (await promises.readFile(imagePath)).toString("base64"),
|
|
282
|
+
mimeType: "image/png"
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
text,
|
|
287
|
+
images,
|
|
288
|
+
isError: result.isError === true
|
|
289
|
+
};
|
|
290
|
+
};
|
|
291
|
+
return {
|
|
292
|
+
call(tool, input) {
|
|
293
|
+
const next = queue.then(() => run(tool, input));
|
|
294
|
+
queue = next.catch(() => void 0);
|
|
295
|
+
return next;
|
|
296
|
+
},
|
|
297
|
+
restart() {
|
|
298
|
+
const next = queue.then(reset);
|
|
299
|
+
queue = next.catch(() => void 0);
|
|
300
|
+
return next;
|
|
301
|
+
},
|
|
302
|
+
async dispose() {
|
|
303
|
+
disposed = true;
|
|
304
|
+
await queue;
|
|
305
|
+
await reset();
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
//#endregion
|
|
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 };
|