@ggui-ai/ui-gen 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter-Du7P_5Fx.d.ts +201 -0
- package/dist/adapters/generation-dispatch.d.ts +33 -12
- package/dist/adapters/generation-dispatch.js +549 -129
- package/dist/adapters/generation-dispatch.js.map +1 -1
- package/dist/adapters/index.js +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/advanced/index.d.ts +5 -3
- package/dist/advanced/index.js +601 -144
- package/dist/advanced/index.js.map +1 -1
- package/dist/blueprint-validator.js +178 -54
- package/dist/blueprint-validator.js.map +1 -1
- package/dist/boilerplate.js +1 -0
- package/dist/boilerplate.js.map +1 -1
- package/dist/check/index.d.ts +2 -1
- package/dist/check/index.js +47 -1
- package/dist/check/index.js.map +1 -1
- package/dist/{create-ui-generator-BEkzEtNz.d.ts → create-ui-generator-GIhzx08x.d.ts} +34 -10
- package/dist/{dispatch-DJNpQ7DI.d.ts → dispatch-BnAH56p4.d.ts} +1 -1
- package/dist/evaluation/axis-checks/index.d.ts +4 -3
- package/dist/evaluation/axis-checks/index.js +19 -4
- package/dist/evaluation/axis-checks/index.js.map +1 -1
- package/dist/evaluation/axis-checks/registry.d.ts +2 -1
- package/dist/evaluation/axis-checks/registry.js +19 -4
- package/dist/evaluation/axis-checks/registry.js.map +1 -1
- package/dist/evaluation/index.d.ts +4 -3
- package/dist/evaluation/index.js +21 -6
- package/dist/evaluation/index.js.map +1 -1
- package/dist/harness/check/runtime-render/index.d.ts +27 -8
- package/dist/harness/check/runtime-render/index.js +217 -54
- package/dist/harness/check/runtime-render/index.js.map +1 -1
- package/dist/harness/check/runtime-render/render-check-worker.d.ts +8 -1
- package/dist/harness/check/runtime-render/render-check-worker.js +72 -32
- package/dist/harness/check/runtime-render/render-check-worker.js.map +1 -1
- package/dist/harness/index.d.ts +2 -1
- package/dist/harness/index.js +3 -2
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/prompts.js.map +1 -1
- package/dist/harness/result-types.d.ts +2 -1
- package/dist/harness/runtime.d.ts +2 -1
- package/dist/harness/runtime.js +2 -1
- package/dist/harness/runtime.js.map +1 -1
- package/dist/harness/types-public.d.ts +18 -5
- package/dist/harness/types-public.js +1 -0
- package/dist/harness/types-public.js.map +1 -1
- package/dist/harness/validator-trace-sink.d.ts +2 -1
- package/dist/index.d.ts +38 -3
- package/dist/index.js +592 -144
- package/dist/index.js.map +1 -1
- package/dist/patch.d.ts +2 -1
- package/dist/policy.d.ts +7 -4
- package/dist/policy.js.map +1 -1
- package/dist/tools/get-primitives-ts.d.ts +1 -1
- package/dist/tools/get-primitives-ts.js +1 -1
- package/dist/tools/get-primitives-ts.js.map +1 -1
- package/dist/tools/render-check-worker.d.ts +7 -1
- package/dist/tools/render-check-worker.js +55 -23
- package/dist/tools/render-check-worker.js.map +1 -1
- package/dist/{types-public-mM_-1Yk3.d.ts → types-public-Bk6d1WLN.d.ts} +98 -9
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +1 -1
- package/dist/validation/index.js.map +1 -1
- package/dist/workflows.d.ts +2 -1
- package/package.json +12 -12
- package/src/adapters/generation-dispatch.ts +137 -96
- package/src/advanced/generator.ts +16 -1
- package/src/blueprint-validator.ts +21 -6
- package/src/boilerplate/hard-sections.ts +1 -0
- package/src/check/run-tier0.ts +80 -1
- package/src/coding-agent/tools.ts +6 -1
- package/src/create-ui-generator.ts +185 -95
- package/src/evaluation/axis-checks/checks/state-payload.ts +29 -4
- package/src/evaluation/types-public.ts +94 -8
- package/src/harness/check/runtime-render/adapter.ts +223 -58
- package/src/harness/check/runtime-render/index.ts +75 -2
- package/src/harness/check/runtime-render/render-check-host.ts +111 -26
- package/src/harness/check/runtime-render/render-check-worker.ts +83 -29
- package/src/harness/check/runtime-render/render-check.ts +173 -117
- package/src/harness/coding/generate-task-runner.ts +57 -4
- package/src/harness/coding/init-session.ts +13 -0
- package/src/harness/coding/run-eval-round.ts +238 -13
- package/src/harness/llm-router.ts +3 -3
- package/src/harness/policy.ts +11 -0
- package/src/harness/primitive-slice.ts +104 -0
- package/src/harness/types-public.ts +17 -5
- package/src/index.ts +4 -0
- package/src/policy.ts +7 -4
- package/src/tools/get-primitives-ts.ts +1 -1
- package/src/tools/render-check-worker.ts +74 -23
- package/src/validation/primitives.ts +1 -1
- package/dist/render-check-C0CqVceF.d.ts +0 -87
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { b as RenderCheckHostBounds } from '../../../adapter-Du7P_5Fx.js';
|
|
2
|
+
export { D as DEFAULT_RUNTIME_RENDER_CHECK, c as RENDER_CHECK_KINDS, d as RenderCheckHostOptions, a as RenderCheckIssue, e as RenderCheckKind, f as RenderCheckResult, R as RuntimeRenderProbeConfig, g as classifyRenderCrashFix, h as createRuntimeRenderCheck, i as isRecoverableRenderCrash, p as parseRuntimeSubcategory, r as runRenderCheck } from '../../../adapter-Du7P_5Fx.js';
|
|
2
3
|
import { WireConfig } from '@ggui-ai/wire';
|
|
3
4
|
import { JsonObject, DataContract } from '@ggui-ai/protocol';
|
|
4
|
-
import
|
|
5
|
+
import '../../types-public.js';
|
|
5
6
|
import '../../../styling-profile-CxfvV48g.js';
|
|
6
7
|
import '../../../axes-CzLEMDeB.js';
|
|
7
|
-
import '../../../types-public-
|
|
8
|
+
import '../../../types-public-Bk6d1WLN.js';
|
|
9
|
+
import '@ggui-ai/mcp-server-core';
|
|
8
10
|
import '../../../design-mode-DLufhrNp.js';
|
|
9
11
|
import '../../../types-BOvHNG7K.js';
|
|
10
12
|
import '../../../llm.js';
|
|
@@ -109,10 +111,6 @@ interface PrepareMockupInput {
|
|
|
109
111
|
*/
|
|
110
112
|
declare function prepareMockupProps(input: PrepareMockupInput): MockupPropsResult;
|
|
111
113
|
|
|
112
|
-
declare const DEFAULT_RUNTIME_RENDER_CHECK: RuntimeRenderCheck;
|
|
113
|
-
declare function isRecoverableRenderCrash(reason: string): boolean;
|
|
114
|
-
declare function classifyRenderCrashFix(reason: string): string;
|
|
115
|
-
|
|
116
114
|
/**
|
|
117
115
|
* Pre-warm the runtime-render probe's runtime dependencies so the first
|
|
118
116
|
* actual probe call hits a warm Node module cache.
|
|
@@ -139,5 +137,26 @@ declare function warmupRuntimeRenderProbe(): Promise<{
|
|
|
139
137
|
loaded: number;
|
|
140
138
|
missing: number;
|
|
141
139
|
}>;
|
|
140
|
+
/**
|
|
141
|
+
* Warm the PROCESS that runs every probe (ggui#1380): spawn one real check
|
|
142
|
+
* worker on a trivial component through the same host every probe uses.
|
|
143
|
+
* Afterwards the node binary, the worker's module tree and esbuild's
|
|
144
|
+
* service have all run once on this machine (OS page cache warm), and the
|
|
145
|
+
* result says whether that process can run a check at all — which
|
|
146
|
+
* `warmupRuntimeRenderProbe` (an import in THIS process) cannot tell.
|
|
147
|
+
*
|
|
148
|
+
* `bounds` are the subprocess bounds for the one run; a serving deployment
|
|
149
|
+
* passes the same bounds it will probe with. Never throws: a worker that
|
|
150
|
+
* cannot run is `{ ok: false, reason }`, so a boot sequence can log it and
|
|
151
|
+
* decide, instead of dying in a fire-and-forget.
|
|
152
|
+
*/
|
|
153
|
+
declare function warmupRuntimeRenderWorker(bounds?: Partial<RenderCheckHostBounds>): Promise<{
|
|
154
|
+
ok: true;
|
|
155
|
+
ms: number;
|
|
156
|
+
} | {
|
|
157
|
+
ok: false;
|
|
158
|
+
ms: number;
|
|
159
|
+
reason: string;
|
|
160
|
+
}>;
|
|
142
161
|
|
|
143
|
-
export {
|
|
162
|
+
export { type MockupPropsResult, type Probe, RenderCheckHostBounds, createProbe, createProbeWireConfig, prepareMockupProps, warmupRuntimeRenderProbe, warmupRuntimeRenderWorker };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'fs';
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
|
+
import { loadavg, availableParallelism } from 'os';
|
|
3
4
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
4
5
|
import { runSandboxed } from '@ggui-ai/sandbox';
|
|
5
6
|
import { listContractGadgets, HOOK_NAME_RE } from '@ggui-ai/protocol';
|
|
@@ -19,9 +20,25 @@ var __export = (target, all) => {
|
|
|
19
20
|
// src/harness/check/runtime-render/render-check-host.ts
|
|
20
21
|
var render_check_host_exports = {};
|
|
21
22
|
__export(render_check_host_exports, {
|
|
23
|
+
DEFAULT_RENDER_CHECK_HOST_BOUNDS: () => DEFAULT_RENDER_CHECK_HOST_BOUNDS,
|
|
22
24
|
mapSandboxResultToCheckResult: () => mapSandboxResultToCheckResult,
|
|
25
|
+
resolveRenderCheckHostBounds: () => resolveRenderCheckHostBounds,
|
|
26
|
+
resolveWorkerSpawn: () => resolveWorkerSpawn,
|
|
23
27
|
runRenderCheckViaWorker: () => runRenderCheckViaWorker
|
|
24
28
|
});
|
|
29
|
+
function resolveRenderCheckHostBounds(bounds = {}) {
|
|
30
|
+
const timeoutMs = bounds.timeoutMs ?? DEFAULT_RENDER_CHECK_HOST_BOUNDS.timeoutMs;
|
|
31
|
+
const heapMb = bounds.heapMb ?? DEFAULT_RENDER_CHECK_HOST_BOUNDS.heapMb;
|
|
32
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs < 2) {
|
|
33
|
+
throw new RangeError(`render-check: timeoutMs must be an integer \u2265 2, got ${timeoutMs}`);
|
|
34
|
+
}
|
|
35
|
+
if (!Number.isInteger(heapMb) || heapMb < 1) {
|
|
36
|
+
throw new RangeError(`render-check: heapMb must be a positive integer, got ${heapMb}`);
|
|
37
|
+
}
|
|
38
|
+
const requestedGrace = bounds.gracePeriodMs ?? DEFAULT_RENDER_CHECK_HOST_BOUNDS.gracePeriodMs;
|
|
39
|
+
const gracePeriodMs = Math.max(1, Math.min(requestedGrace, Math.floor(timeoutMs / 2)));
|
|
40
|
+
return { timeoutMs, heapMb, gracePeriodMs };
|
|
41
|
+
}
|
|
25
42
|
function resolveWorkerSpawn() {
|
|
26
43
|
const jsCandidates = [
|
|
27
44
|
// Sibling — when import.meta.url is already .../harness/check/runtime-render/.
|
|
@@ -70,12 +87,14 @@ function unverified(reason, t0) {
|
|
|
70
87
|
stats: { actionsChecked: 0, streamsChecked: 0, renderMs: Date.now() - t0 }
|
|
71
88
|
};
|
|
72
89
|
}
|
|
73
|
-
function mapSandboxResultToCheckResult(result, t0) {
|
|
90
|
+
function mapSandboxResultToCheckResult(result, t0, boundMs = DEFAULT_RENDER_CHECK_HOST_BOUNDS.timeoutMs) {
|
|
74
91
|
if (result.outcome === "timeout") {
|
|
75
|
-
return
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
92
|
+
return {
|
|
93
|
+
ok: false,
|
|
94
|
+
issues: [],
|
|
95
|
+
incomplete: { kind: "timeout", elapsedMs: result.durationMs, boundMs },
|
|
96
|
+
stats: { actionsChecked: 0, streamsChecked: 0, renderMs: Date.now() - t0 }
|
|
97
|
+
};
|
|
79
98
|
}
|
|
80
99
|
if (result.outcome === "overflow-stdout" || result.outcome === "overflow-stderr") {
|
|
81
100
|
return failed(
|
|
@@ -118,34 +137,46 @@ function mapSandboxResultToCheckResult(result, t0) {
|
|
|
118
137
|
);
|
|
119
138
|
}
|
|
120
139
|
}
|
|
121
|
-
async function runRenderCheckViaWorker(input) {
|
|
140
|
+
async function runRenderCheckViaWorker(input, options = {}) {
|
|
122
141
|
const t0 = Date.now();
|
|
142
|
+
const bounds = resolveRenderCheckHostBounds(options.bounds);
|
|
123
143
|
let spawn;
|
|
124
144
|
try {
|
|
125
145
|
spawn = resolveWorkerSpawn();
|
|
126
146
|
} catch (err) {
|
|
127
147
|
return unverified(err instanceof Error ? err.message : String(err), t0);
|
|
128
148
|
}
|
|
149
|
+
const loadAtStart = loadavg()[0] ?? 0;
|
|
129
150
|
const result = await runSandboxed({
|
|
130
151
|
command: spawn.command,
|
|
131
152
|
args: spawn.args,
|
|
132
|
-
timeoutMs:
|
|
153
|
+
timeoutMs: bounds.timeoutMs,
|
|
154
|
+
gracePeriodMs: bounds.gracePeriodMs,
|
|
133
155
|
maxStdoutBytes: CHECK_STDOUT_CAP,
|
|
134
|
-
nodeHeapMb:
|
|
156
|
+
nodeHeapMb: bounds.heapMb,
|
|
135
157
|
stdin: JSON.stringify(input),
|
|
136
158
|
// NODE_ENV steers React's production vs development build — keep
|
|
137
159
|
// parity with the caller; everything else stays on the sandbox's
|
|
138
160
|
// default allowlist.
|
|
139
161
|
env: { NODE_ENV: process.env.NODE_ENV ?? "production" }
|
|
140
162
|
});
|
|
141
|
-
|
|
163
|
+
const hostLoad = {
|
|
164
|
+
start: loadAtStart,
|
|
165
|
+
end: loadavg()[0] ?? 0,
|
|
166
|
+
cores: availableParallelism()
|
|
167
|
+
};
|
|
168
|
+
const mapped = mapSandboxResultToCheckResult(result, t0, bounds.timeoutMs);
|
|
169
|
+
return { ...mapped, stats: { ...mapped.stats, hostLoad } };
|
|
142
170
|
}
|
|
143
|
-
var
|
|
171
|
+
var DEFAULT_RENDER_CHECK_HOST_BOUNDS, CHECK_STDOUT_CAP, WORKER_BASENAME;
|
|
144
172
|
var init_render_check_host = __esm({
|
|
145
173
|
"src/harness/check/runtime-render/render-check-host.ts"() {
|
|
146
|
-
|
|
174
|
+
DEFAULT_RENDER_CHECK_HOST_BOUNDS = {
|
|
175
|
+
timeoutMs: 3e4,
|
|
176
|
+
heapMb: 512,
|
|
177
|
+
gracePeriodMs: 2e3
|
|
178
|
+
};
|
|
147
179
|
CHECK_STDOUT_CAP = 2 * 1024 * 1024;
|
|
148
|
-
CHECK_NODE_HEAP_MB = 512;
|
|
149
180
|
WORKER_BASENAME = "render-check-worker";
|
|
150
181
|
}
|
|
151
182
|
});
|
|
@@ -667,13 +698,22 @@ function editableSurface(el) {
|
|
|
667
698
|
function parentLink(node) {
|
|
668
699
|
return node;
|
|
669
700
|
}
|
|
670
|
-
|
|
701
|
+
var RENDER_CHECK_KINDS = [
|
|
702
|
+
"render-no-throw",
|
|
703
|
+
"prop-sensitivity",
|
|
704
|
+
"action-wiring",
|
|
705
|
+
"selection-identity",
|
|
706
|
+
"prop-coverage",
|
|
707
|
+
"optional-props-omitted",
|
|
708
|
+
"stream-rerender"
|
|
709
|
+
];
|
|
710
|
+
async function runRenderCheck(input, options = {}) {
|
|
671
711
|
const g = hostGlobals();
|
|
672
712
|
if ("window" in g && "document" in g) {
|
|
673
713
|
return runRenderCheckInProcess(input);
|
|
674
714
|
}
|
|
675
715
|
const { runRenderCheckViaWorker: runRenderCheckViaWorker2 } = await Promise.resolve().then(() => (init_render_check_host(), render_check_host_exports));
|
|
676
|
-
return runRenderCheckViaWorker2(input);
|
|
716
|
+
return runRenderCheckViaWorker2(input, options);
|
|
677
717
|
}
|
|
678
718
|
async function runRenderCheckInProcess(input) {
|
|
679
719
|
const t0 = Date.now();
|
|
@@ -687,7 +727,7 @@ async function runRenderCheckInProcess(input) {
|
|
|
687
727
|
const Wire = await import('@ggui-ai/wire');
|
|
688
728
|
const { GguiWireProvider } = Wire;
|
|
689
729
|
const moduleResolutions = {
|
|
690
|
-
|
|
730
|
+
react: React,
|
|
691
731
|
"react/jsx-runtime": ReactJsxRuntime,
|
|
692
732
|
"@ggui-ai/wire": Wire
|
|
693
733
|
};
|
|
@@ -803,14 +843,23 @@ async function runRenderCheckInProcess(input) {
|
|
|
803
843
|
)
|
|
804
844
|
);
|
|
805
845
|
const timeoutPromise = new Promise((_, reject) => {
|
|
806
|
-
setTimeout(
|
|
846
|
+
setTimeout(
|
|
847
|
+
() => reject(
|
|
848
|
+
new Error(
|
|
849
|
+
`[runtime-render] render exceeded ${RENDER_TIMEOUT_MS}ms \u2014 classified as runtime-hang`
|
|
850
|
+
)
|
|
851
|
+
),
|
|
852
|
+
RENDER_TIMEOUT_MS
|
|
853
|
+
).unref?.();
|
|
807
854
|
});
|
|
808
855
|
renderResult = await Promise.race([renderPromise, timeoutPromise]);
|
|
809
856
|
} catch (e) {
|
|
810
857
|
const msg = e instanceof Error ? e.message : String(e);
|
|
811
858
|
const errStack = e instanceof Error ? e.stack ?? "" : "";
|
|
812
859
|
const baseReason = loopSignature ? `Infinite render loop (${loopSignature}) \u2014 likely setState/dispatch inside useEffect with missing or unstable dependency` : /runtime-hang/.test(msg) ? `Render wall-clock exceeded ${RENDER_TIMEOUT_MS}ms \u2014 likely async effect loop or unresolved promise` : `Render threw: ${msg}`;
|
|
813
|
-
const userFrames = errStack.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("at ")).filter(
|
|
860
|
+
const userFrames = errStack.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("at ")).filter(
|
|
861
|
+
(l) => !/(node_modules|happy-dom|@testing-library|react-dom|node:internal|node:async)/.test(l)
|
|
862
|
+
).slice(0, 5);
|
|
814
863
|
const stackSource = boundaryRef.stack ?? capturedComponentStack ?? "";
|
|
815
864
|
const componentFrames = stackSource.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("at ")).slice(0, 4);
|
|
816
865
|
const stackBlock = userFrames.length ? `
|
|
@@ -1275,9 +1324,7 @@ function idLikeRequiredStringField(schema) {
|
|
|
1275
1324
|
const required = schema["required"];
|
|
1276
1325
|
if (properties === null || typeof properties !== "object") return null;
|
|
1277
1326
|
if (!Array.isArray(required)) return null;
|
|
1278
|
-
for (const [propName, propSchema] of Object.entries(
|
|
1279
|
-
properties
|
|
1280
|
-
)) {
|
|
1327
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
1281
1328
|
if (!/id$/i.test(propName)) continue;
|
|
1282
1329
|
if (!required.includes(propName)) continue;
|
|
1283
1330
|
const t = propSchema !== null && typeof propSchema === "object" ? propSchema["type"] : void 0;
|
|
@@ -1308,9 +1355,7 @@ async function checkSelectionIdentity(input) {
|
|
|
1308
1355
|
return void 0;
|
|
1309
1356
|
}
|
|
1310
1357
|
await flushPromises();
|
|
1311
|
-
const events = probe.getFireLog().slice(before).filter(
|
|
1312
|
-
(e) => e.kind === "action.fired" && e.name === actionName
|
|
1313
|
-
);
|
|
1358
|
+
const events = probe.getFireLog().slice(before).filter((e) => e.kind === "action.fired" && e.name === actionName);
|
|
1314
1359
|
return events.length > 0 ? events[events.length - 1].payload : void 0;
|
|
1315
1360
|
};
|
|
1316
1361
|
const first = await payloadFor(group[0]);
|
|
@@ -1371,7 +1416,10 @@ async function dispatchTrigger(el, kind, user) {
|
|
|
1371
1416
|
case "submit": {
|
|
1372
1417
|
const form = closestForm(el);
|
|
1373
1418
|
if (!form) return;
|
|
1374
|
-
const ev = new globalThis.Event("submit", {
|
|
1419
|
+
const ev = new globalThis.Event("submit", {
|
|
1420
|
+
bubbles: true,
|
|
1421
|
+
cancelable: true
|
|
1422
|
+
});
|
|
1375
1423
|
toEventDispatcher(form).dispatchEvent(ev);
|
|
1376
1424
|
return;
|
|
1377
1425
|
}
|
|
@@ -1708,37 +1756,112 @@ function synthesizeFromSchema(schema, hint, warnings, depth, ordinal) {
|
|
|
1708
1756
|
}
|
|
1709
1757
|
|
|
1710
1758
|
// src/harness/check/runtime-render/adapter.ts
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1759
|
+
init_render_check_host();
|
|
1760
|
+
function createSlotLimiter(maxConcurrent) {
|
|
1761
|
+
if (maxConcurrent === void 0) return (task) => task(0);
|
|
1762
|
+
if (!Number.isInteger(maxConcurrent) || maxConcurrent < 1) {
|
|
1763
|
+
throw new RangeError(
|
|
1764
|
+
`createRuntimeRenderCheck: maxConcurrent must be a positive integer, got ${maxConcurrent}`
|
|
1765
|
+
);
|
|
1766
|
+
}
|
|
1767
|
+
let active = 0;
|
|
1768
|
+
const waiting = [];
|
|
1769
|
+
const acquire = () => {
|
|
1770
|
+
if (active < maxConcurrent) {
|
|
1771
|
+
active += 1;
|
|
1772
|
+
return Promise.resolve(0);
|
|
1773
|
+
}
|
|
1774
|
+
const enqueuedAt = Date.now();
|
|
1775
|
+
return new Promise((resolve) => {
|
|
1776
|
+
waiting.push(() => {
|
|
1777
|
+
active += 1;
|
|
1778
|
+
resolve(Date.now() - enqueuedAt);
|
|
1728
1779
|
});
|
|
1729
|
-
}
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1780
|
+
});
|
|
1781
|
+
};
|
|
1782
|
+
const release = () => {
|
|
1783
|
+
active -= 1;
|
|
1784
|
+
const next = waiting.shift();
|
|
1785
|
+
if (next !== void 0) next();
|
|
1786
|
+
};
|
|
1787
|
+
return async (task) => {
|
|
1788
|
+
const waitedMs = await acquire();
|
|
1789
|
+
try {
|
|
1790
|
+
return await task(waitedMs);
|
|
1791
|
+
} finally {
|
|
1792
|
+
release();
|
|
1735
1793
|
}
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
function queuedField(queuedMs) {
|
|
1797
|
+
return queuedMs > 0 ? { queuedMs } : {};
|
|
1798
|
+
}
|
|
1799
|
+
function toRenderCheckOptions(config) {
|
|
1800
|
+
if (config.timeoutMs === void 0 && config.heapMb === void 0) return void 0;
|
|
1801
|
+
return {
|
|
1802
|
+
bounds: {
|
|
1803
|
+
...config.timeoutMs !== void 0 ? { timeoutMs: config.timeoutMs } : {},
|
|
1804
|
+
...config.heapMb !== void 0 ? { heapMb: config.heapMb } : {}
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
function createRuntimeRenderCheck(config = {}) {
|
|
1809
|
+
const limit = createSlotLimiter(config.maxConcurrent);
|
|
1810
|
+
const options = toRenderCheckOptions(config);
|
|
1811
|
+
if (options !== void 0) resolveRenderCheckHostBounds(options.bounds);
|
|
1812
|
+
return {
|
|
1813
|
+
id: "runtime-render",
|
|
1814
|
+
run: async (input) => {
|
|
1815
|
+
const { sourceCode, compiledCode, contract, fixtureProps } = input;
|
|
1816
|
+
if (compiledCode === null) {
|
|
1817
|
+
return { status: "not-applicable", issues: [], reason: "no compiled code" };
|
|
1818
|
+
}
|
|
1819
|
+
if (!contract) {
|
|
1820
|
+
return { status: "not-applicable", issues: [], reason: "no contract surface" };
|
|
1821
|
+
}
|
|
1822
|
+
const mockup = prepareMockupProps({ contract, fixtureProps });
|
|
1823
|
+
let queuedMs = 0;
|
|
1824
|
+
let t0 = Date.now();
|
|
1825
|
+
let result;
|
|
1826
|
+
try {
|
|
1827
|
+
result = await limit((waitedMs) => {
|
|
1828
|
+
queuedMs = waitedMs;
|
|
1829
|
+
t0 = Date.now();
|
|
1830
|
+
return runRenderCheck(
|
|
1831
|
+
{
|
|
1832
|
+
sourceCode,
|
|
1833
|
+
mockupProps: mockup.props,
|
|
1834
|
+
contract
|
|
1835
|
+
},
|
|
1836
|
+
options
|
|
1837
|
+
);
|
|
1838
|
+
});
|
|
1839
|
+
} catch (e) {
|
|
1840
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
1841
|
+
console.warn(`[runtime-render] probe skipped \u2014 infra failure: ${message}`);
|
|
1842
|
+
return { status: "infra-skipped", issues: [], reason: message, elapsedMs: Date.now() - t0, ...queuedField(queuedMs) };
|
|
1843
|
+
}
|
|
1844
|
+
const hostLoad = result.stats.hostLoad;
|
|
1845
|
+
const load = hostLoad !== void 0 ? { hostLoad } : {};
|
|
1846
|
+
if (result.incomplete !== void 0) {
|
|
1847
|
+
const { elapsedMs, boundMs } = result.incomplete;
|
|
1848
|
+
const loadNote = hostLoad !== void 0 ? `; host load ${hostLoad.start.toFixed(1)} \u2192 ${hostLoad.end.toFixed(1)} on ${hostLoad.cores} CPUs` : "";
|
|
1849
|
+
const reason = `render check did not finish within ${boundMs} ms (stopped at ${elapsedMs} ms)${loadNote}`;
|
|
1850
|
+
console.warn(`[runtime-render] probe timed out \u2014 ${reason}`);
|
|
1851
|
+
return { status: "timed-out", issues: [], reason, elapsedMs: Date.now() - t0, ...queuedField(queuedMs), ...load };
|
|
1852
|
+
}
|
|
1853
|
+
return {
|
|
1854
|
+
status: "ran",
|
|
1855
|
+
issues: result.issues.map(toEvalIssue).filter((x) => x !== null),
|
|
1856
|
+
elapsedMs: Date.now() - t0,
|
|
1857
|
+
...queuedField(queuedMs),
|
|
1858
|
+
renderMs: result.stats.renderMs,
|
|
1859
|
+
...load
|
|
1860
|
+
};
|
|
1861
|
+
}
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
var DEFAULT_RUNTIME_RENDER_CHECK = createRuntimeRenderCheck();
|
|
1742
1865
|
var CLASS_SPECIFIC_PATTERNS = [
|
|
1743
1866
|
/too many re-renders/i,
|
|
1744
1867
|
/maximum update depth/i,
|
|
@@ -1777,6 +1900,14 @@ function classifyRenderCrashFix(reason) {
|
|
|
1777
1900
|
}
|
|
1778
1901
|
return "Add null guards on optional props, handle empty arrays/strings, and verify all hook outputs before destructuring.";
|
|
1779
1902
|
}
|
|
1903
|
+
var RUNTIME_SUBCATEGORY_PREFIX = "runtime:";
|
|
1904
|
+
function parseRuntimeSubcategory(subcategory) {
|
|
1905
|
+
if (!subcategory.startsWith(RUNTIME_SUBCATEGORY_PREFIX)) return void 0;
|
|
1906
|
+
const rest = subcategory.slice(RUNTIME_SUBCATEGORY_PREFIX.length);
|
|
1907
|
+
const separator = rest.indexOf(":");
|
|
1908
|
+
const check = separator === -1 ? rest : rest.slice(0, separator);
|
|
1909
|
+
return RENDER_CHECK_KINDS.find((kind) => kind === check);
|
|
1910
|
+
}
|
|
1780
1911
|
function toEvalIssue(issue) {
|
|
1781
1912
|
if (issue.outcome === "verified" || issue.outcome === "skipped") return null;
|
|
1782
1913
|
const result = issue.outcome === "failed" ? "fail" : "warn";
|
|
@@ -1899,7 +2030,39 @@ async function warmupRuntimeRenderProbe() {
|
|
|
1899
2030
|
]);
|
|
1900
2031
|
return { ms: Date.now() - start, loaded, missing };
|
|
1901
2032
|
}
|
|
2033
|
+
var WARMUP_COMPONENT = "export default function Warmup() { return <div>warm</div>; }";
|
|
2034
|
+
async function warmupRuntimeRenderWorker(bounds) {
|
|
2035
|
+
const start = Date.now();
|
|
2036
|
+
try {
|
|
2037
|
+
const { runRenderCheckViaWorker: runRenderCheckViaWorker2 } = await Promise.resolve().then(() => (init_render_check_host(), render_check_host_exports));
|
|
2038
|
+
const result = await runRenderCheckViaWorker2(
|
|
2039
|
+
{ sourceCode: WARMUP_COMPONENT, mockupProps: {}, contract: {} },
|
|
2040
|
+
bounds !== void 0 ? { bounds } : {}
|
|
2041
|
+
);
|
|
2042
|
+
const ms = Date.now() - start;
|
|
2043
|
+
if (result.incomplete !== void 0) {
|
|
2044
|
+
return {
|
|
2045
|
+
ok: false,
|
|
2046
|
+
ms,
|
|
2047
|
+
reason: `the warm-up check did not finish within ${result.incomplete.boundMs} ms (stopped at ${result.incomplete.elapsedMs} ms)`
|
|
2048
|
+
};
|
|
2049
|
+
}
|
|
2050
|
+
const blocking = result.issues.find(
|
|
2051
|
+
(i) => i.outcome === "failed" || i.outcome === "unverified"
|
|
2052
|
+
);
|
|
2053
|
+
if (blocking !== void 0) {
|
|
2054
|
+
return { ok: false, ms, reason: `${blocking.check} ${blocking.outcome}: ${blocking.reason}` };
|
|
2055
|
+
}
|
|
2056
|
+
return { ok: true, ms };
|
|
2057
|
+
} catch (err) {
|
|
2058
|
+
return {
|
|
2059
|
+
ok: false,
|
|
2060
|
+
ms: Date.now() - start,
|
|
2061
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
1902
2065
|
|
|
1903
|
-
export { DEFAULT_RUNTIME_RENDER_CHECK, classifyRenderCrashFix, createProbe, createProbeWireConfig, isRecoverableRenderCrash, prepareMockupProps, runRenderCheck, warmupRuntimeRenderProbe };
|
|
2066
|
+
export { DEFAULT_RUNTIME_RENDER_CHECK, RENDER_CHECK_KINDS, classifyRenderCrashFix, createProbe, createProbeWireConfig, createRuntimeRenderCheck, isRecoverableRenderCrash, parseRuntimeSubcategory, prepareMockupProps, runRenderCheck, warmupRuntimeRenderProbe, warmupRuntimeRenderWorker };
|
|
1904
2067
|
//# sourceMappingURL=index.js.map
|
|
1905
2068
|
//# sourceMappingURL=index.js.map
|