@ggui-ai/ui-gen 0.8.0 → 0.10.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/adapters/generation-dispatch.d.ts +18 -1
- package/dist/adapters/generation-dispatch.js +819 -1577
- package/dist/adapters/generation-dispatch.js.map +1 -1
- package/dist/adapters/index.js +28 -11
- package/dist/adapters/index.js.map +1 -1
- package/dist/advanced/index.d.ts +5 -3
- package/dist/advanced/index.js +838 -1579
- package/dist/advanced/index.js.map +1 -1
- package/dist/blueprint-validator.js +109 -3
- package/dist/blueprint-validator.js.map +1 -1
- package/dist/boilerplate.js +17 -4
- package/dist/boilerplate.js.map +1 -1
- package/dist/check/index.d.ts +1 -1
- package/dist/check/index.js +11 -1
- package/dist/check/index.js.map +1 -1
- package/dist/compose.js +5 -5
- package/dist/compose.js.map +1 -1
- package/dist/{create-ui-generator-GX7tvbyH.d.ts → create-ui-generator-CF0EL0Li.d.ts} +26 -1
- package/dist/{dispatch-Deo9qzrG.d.ts → dispatch-D75M-OfZ.d.ts} +1 -1
- package/dist/evaluation/axis-checks/index.d.ts +3 -3
- package/dist/evaluation/axis-checks/index.js +133 -1
- package/dist/evaluation/axis-checks/index.js.map +1 -1
- package/dist/evaluation/axis-checks/registry.d.ts +1 -1
- package/dist/evaluation/axis-checks/registry.js +133 -1
- package/dist/evaluation/axis-checks/registry.js.map +1 -1
- package/dist/evaluation/index.d.ts +46 -3
- package/dist/evaluation/index.js +410 -24
- package/dist/evaluation/index.js.map +1 -1
- package/dist/fragments/index.js +5 -5
- package/dist/fragments/index.js.map +1 -1
- package/dist/harness/check/runtime-render/index.d.ts +2 -2
- package/dist/harness/check/runtime-render/index.js +110 -3
- package/dist/harness/check/runtime-render/index.js.map +1 -1
- package/dist/harness/index.d.ts +5 -126
- package/dist/harness/index.js +292 -32
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/llm-trace-sink.d.ts +1 -1
- package/dist/harness/llm-trace-sink.js.map +1 -1
- package/dist/harness/prompts.js +17 -3
- package/dist/harness/prompts.js.map +1 -1
- package/dist/harness/result-types.d.ts +1 -1
- package/dist/harness/runtime.d.ts +17 -1
- package/dist/harness/runtime.js +23 -8
- package/dist/harness/runtime.js.map +1 -1
- package/dist/harness/types-public.d.ts +1 -1
- package/dist/harness/types-public.js +22 -9
- package/dist/harness/types-public.js.map +1 -1
- package/dist/harness/validator-trace-sink.d.ts +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +838 -1579
- package/dist/index.js.map +1 -1
- package/dist/llm-router-BEVtbAb9.d.ts +213 -0
- package/dist/patch.d.ts +1 -1
- package/dist/provider-adapter.d.ts +16 -6
- package/dist/provider-adapter.js.map +1 -1
- package/dist/providers/index.d.ts +54 -99
- package/dist/providers/index.js +13 -8
- package/dist/providers/index.js.map +1 -1
- package/dist/{render-check-CNZjHD5g.d.ts → render-check-BNYGVDJd.d.ts} +1 -1
- package/dist/{types-public-C36k1q6s.d.ts → types-public-DIpjC-OA.d.ts} +1 -1
- package/dist/validation/index.js +2 -2
- package/dist/validation/index.js.map +1 -1
- package/dist/workflows.d.ts +1 -1
- package/package.json +18 -18
- package/src/adapters/generation-dispatch.ts +28 -2
- package/src/adapters/openrouter/client.ts +2 -2
- package/src/adapters/openrouter/types.ts +10 -0
- package/src/boilerplate/generate.ts +10 -2
- package/src/boilerplate/json-schema-ts.ts +22 -2
- package/src/boilerplate/system-prompt.ts +4 -2
- package/src/compile.ts +1 -1
- package/src/contract-context.ts +10 -2
- package/src/create-ui-generator.ts +58 -11
- package/src/design-system-docs.ts +6 -4
- package/src/evaluation/axis-checks/checks/state-merge.ts +1 -1
- package/src/evaluation/axis-checks/checks/state-ui-affordance.ts +162 -0
- package/src/evaluation/axis-checks/checks/universal.ts +39 -0
- package/src/evaluation/axis-checks/registry.ts +2 -0
- package/src/evaluation/index.ts +11 -0
- package/src/evaluation/llm-evaluator.ts +26 -3
- package/src/evaluation/visual-evaluator.ts +49 -66
- package/src/fragments/realtime.ts +3 -3
- package/src/fragments/state.ts +2 -2
- package/src/harness/check/runtime-render/adapter.ts +18 -0
- package/src/harness/check/runtime-render/index.ts +8 -0
- package/src/harness/check/runtime-render/prepare-mockup.ts +14 -0
- package/src/harness/check/runtime-render/production-act-shim.ts +158 -0
- package/src/harness/check/runtime-render/render-check.ts +72 -1
- package/src/harness/coding/init-session.ts +4 -1
- package/src/harness/coding/run-eval-round.ts +67 -5
- package/src/harness/index.ts +1 -1
- package/src/harness/llm-router.ts +451 -27
- package/src/harness/llm-trace-sink.ts +2 -1
- package/src/harness/runtime.ts +15 -0
- package/src/index.ts +5 -5
- package/src/provider-adapter.ts +16 -6
- package/src/providers/bedrock.ts +89 -26
- package/src/providers/index.ts +16 -4
- package/src/tools/render-check.ts +19 -7
- package/src/validation/ui-compiler.ts +2 -2
package/dist/advanced/index.js
CHANGED
|
@@ -10,7 +10,10 @@ import path, { dirname, resolve, join, basename } from 'path';
|
|
|
10
10
|
import { createRequire } from 'module';
|
|
11
11
|
import { Linter } from 'eslint';
|
|
12
12
|
import { createHash } from 'crypto';
|
|
13
|
+
import 'fs/promises';
|
|
13
14
|
import { tmpdir } from 'os';
|
|
15
|
+
import { Readable } from 'stream';
|
|
16
|
+
import { pipeline } from 'stream/promises';
|
|
14
17
|
import { createBrotliDecompress, createUnzip } from 'zlib';
|
|
15
18
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
16
19
|
import { PlaywrightNotAvailableError, validateContractBehavior } from '@ggui-ai/ui-visual-tester';
|
|
@@ -1151,14 +1154,16 @@ var OpenRouterError;
|
|
|
1151
1154
|
var init_types = __esm({
|
|
1152
1155
|
"src/adapters/openrouter/types.ts"() {
|
|
1153
1156
|
OpenRouterError = class extends Error {
|
|
1154
|
-
constructor(message, status, code) {
|
|
1157
|
+
constructor(message, status, code, headers) {
|
|
1155
1158
|
super(message);
|
|
1156
1159
|
this.status = status;
|
|
1157
1160
|
this.code = code;
|
|
1161
|
+
this.headers = headers;
|
|
1158
1162
|
this.name = "OpenRouterError";
|
|
1159
1163
|
}
|
|
1160
1164
|
status;
|
|
1161
1165
|
code;
|
|
1166
|
+
headers;
|
|
1162
1167
|
get isTransient() {
|
|
1163
1168
|
return this.status === 408 || this.status === 429 || this.status === 502 || this.status === 503;
|
|
1164
1169
|
}
|
|
@@ -1203,7 +1208,7 @@ var init_client2 = __esm({
|
|
|
1203
1208
|
if (!response.ok) {
|
|
1204
1209
|
const errorBody = await response.json().catch(() => ({ error: { message: response.statusText } }));
|
|
1205
1210
|
const message = errorBody.error?.message ?? response.statusText;
|
|
1206
|
-
throw new OpenRouterError(message, response.status);
|
|
1211
|
+
throw new OpenRouterError(message, response.status, void 0, response.headers);
|
|
1207
1212
|
}
|
|
1208
1213
|
return response.json();
|
|
1209
1214
|
}
|
|
@@ -1221,7 +1226,7 @@ var init_client2 = __esm({
|
|
|
1221
1226
|
if (!response.ok) {
|
|
1222
1227
|
const errorBody = await response.json().catch(() => ({ error: { message: response.statusText } }));
|
|
1223
1228
|
const message = errorBody.error?.message ?? response.statusText;
|
|
1224
|
-
throw new OpenRouterError(message, response.status);
|
|
1229
|
+
throw new OpenRouterError(message, response.status, void 0, response.headers);
|
|
1225
1230
|
}
|
|
1226
1231
|
if (!response.body) {
|
|
1227
1232
|
throw new OpenRouterError("No response body for streaming request", 500);
|
|
@@ -1888,8 +1893,8 @@ var init_ui_compiler = __esm({
|
|
|
1888
1893
|
"@ggui-ai/design/*",
|
|
1889
1894
|
"@ggui-ai/wire",
|
|
1890
1895
|
"@ggui-ai/wire/*",
|
|
1891
|
-
"@ggui-ai/react",
|
|
1892
|
-
"@ggui-ai/react/*"
|
|
1896
|
+
"@ggui-ai/mcp-apps-react",
|
|
1897
|
+
"@ggui-ai/mcp-apps-react/*"
|
|
1893
1898
|
];
|
|
1894
1899
|
MAX_BUNDLE_SIZE = 2 * 1024 * 1024;
|
|
1895
1900
|
UiValidationError = class extends Error {
|
|
@@ -2074,6 +2079,15 @@ function jsonSchemaTypeToTs(schema) {
|
|
|
2074
2079
|
if (schema.enum?.length) {
|
|
2075
2080
|
return schema.enum.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
|
|
2076
2081
|
}
|
|
2082
|
+
if (Array.isArray(schema.type)) {
|
|
2083
|
+
const { nullable: _nullable, ...rest } = schema;
|
|
2084
|
+
const members = [...new Set(schema.type)].map(
|
|
2085
|
+
(member) => jsonSchemaTypeToTs({ ...rest, type: member })
|
|
2086
|
+
);
|
|
2087
|
+
const unique = [...new Set(members)];
|
|
2088
|
+
if (schema.nullable && !unique.includes("null")) unique.push("null");
|
|
2089
|
+
return unique.join(" | ");
|
|
2090
|
+
}
|
|
2077
2091
|
let result;
|
|
2078
2092
|
switch (schema.type) {
|
|
2079
2093
|
case "string":
|
|
@@ -2091,7 +2105,8 @@ function jsonSchemaTypeToTs(schema) {
|
|
|
2091
2105
|
case "array": {
|
|
2092
2106
|
if (schema.items) {
|
|
2093
2107
|
const itemType = jsonSchemaTypeToTs(schema.items);
|
|
2094
|
-
|
|
2108
|
+
const itemsDeclareObject = Array.isArray(schema.items.type) ? schema.items.type.includes("object") : schema.items.type === "object";
|
|
2109
|
+
result = itemsDeclareObject && schema.items.properties ? `Array<${itemType}>` : itemType.includes("|") ? `(${itemType})[]` : `${itemType}[]`;
|
|
2095
2110
|
} else {
|
|
2096
2111
|
result = "unknown[]";
|
|
2097
2112
|
}
|
|
@@ -4109,6 +4124,29 @@ function errorSummary(e) {
|
|
|
4109
4124
|
}
|
|
4110
4125
|
return `${e.constructor.name}${status}${code}: ${e.message.slice(0, 120)}${body}`;
|
|
4111
4126
|
}
|
|
4127
|
+
function isRateLimited(e) {
|
|
4128
|
+
if (!(e instanceof Error) || !("status" in e)) return false;
|
|
4129
|
+
return e.status === 429;
|
|
4130
|
+
}
|
|
4131
|
+
function extractStatus(e) {
|
|
4132
|
+
if (!(e instanceof Error) || !("status" in e)) return void 0;
|
|
4133
|
+
const status = e.status;
|
|
4134
|
+
return typeof status === "number" ? status : void 0;
|
|
4135
|
+
}
|
|
4136
|
+
function extractRetryAfterSec(e) {
|
|
4137
|
+
if (!(e instanceof Error) || !("headers" in e)) return void 0;
|
|
4138
|
+
const headers = e.headers;
|
|
4139
|
+
if (headers === null || typeof headers !== "object" || !("get" in headers) || typeof headers.get !== "function") {
|
|
4140
|
+
return void 0;
|
|
4141
|
+
}
|
|
4142
|
+
const raw = headers.get("retry-after");
|
|
4143
|
+
if (raw === null) return void 0;
|
|
4144
|
+
const parsed = Number(raw);
|
|
4145
|
+
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : void 0;
|
|
4146
|
+
}
|
|
4147
|
+
function sleep(ms) {
|
|
4148
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
4149
|
+
}
|
|
4112
4150
|
function interactionText(interaction) {
|
|
4113
4151
|
let text = "";
|
|
4114
4152
|
for (const step of interaction.steps ?? []) {
|
|
@@ -4130,25 +4168,41 @@ function functionCallSteps(interaction) {
|
|
|
4130
4168
|
function toUserInputStep(text) {
|
|
4131
4169
|
return { type: "user_input", content: [{ type: "text", text }] };
|
|
4132
4170
|
}
|
|
4133
|
-
function createAgent(
|
|
4171
|
+
function createAgent(providerOrConfig) {
|
|
4172
|
+
const provider = typeof providerOrConfig === "string" ? providerOrConfig : providerOrConfig.provider;
|
|
4173
|
+
const routeOverride = typeof providerOrConfig === "string" ? void 0 : providerOrConfig.routeOverride;
|
|
4174
|
+
const onRetry = typeof providerOrConfig === "string" ? void 0 : providerOrConfig.onRetry;
|
|
4134
4175
|
switch (provider) {
|
|
4135
4176
|
case "anthropic":
|
|
4136
|
-
return new AnthropicAgent();
|
|
4177
|
+
return new AnthropicAgent(routeOverride, onRetry);
|
|
4137
4178
|
case "openai":
|
|
4138
|
-
return new OpenAIAgent();
|
|
4179
|
+
return new OpenAIAgent(routeOverride, onRetry);
|
|
4139
4180
|
case "google":
|
|
4140
|
-
return new GoogleAgent();
|
|
4181
|
+
return new GoogleAgent(routeOverride, onRetry);
|
|
4141
4182
|
case "openrouter":
|
|
4142
|
-
return new OpenRouterAgent();
|
|
4183
|
+
return new OpenRouterAgent(routeOverride, onRetry);
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
function createVisionAgent(config) {
|
|
4187
|
+
switch (config.provider) {
|
|
4188
|
+
case "anthropic":
|
|
4189
|
+
return new AnthropicAgent(config.routeOverride, config.onRetry);
|
|
4190
|
+
case "google":
|
|
4191
|
+
return new GoogleAgent(config.routeOverride, config.onRetry);
|
|
4143
4192
|
}
|
|
4144
4193
|
}
|
|
4145
|
-
var LLMAgent, AnthropicAgent, OpenAIAgent, GoogleAgent, OpenRouterAgent;
|
|
4194
|
+
var MAX_RETRY_ATTEMPTS, RETRY_AFTER_CAP_SEC, DEFAULT_BACKOFF_BASE_MS, DEFAULT_BACKOFF_MAX_MS, MAX_TOTAL_RETRY_DELAY_MS, LLMAgent, AnthropicAgent, OpenAIAgent, GoogleAgent, OpenRouterAgent;
|
|
4146
4195
|
var init_llm_router = __esm({
|
|
4147
4196
|
"src/harness/llm-router.ts"() {
|
|
4148
4197
|
init_client();
|
|
4149
4198
|
init_provider_router();
|
|
4150
4199
|
init_tool_bridge();
|
|
4151
4200
|
init_llm_trace_sink();
|
|
4201
|
+
MAX_RETRY_ATTEMPTS = 2;
|
|
4202
|
+
RETRY_AFTER_CAP_SEC = 15;
|
|
4203
|
+
DEFAULT_BACKOFF_BASE_MS = 1e3;
|
|
4204
|
+
DEFAULT_BACKOFF_MAX_MS = 8e3;
|
|
4205
|
+
MAX_TOTAL_RETRY_DELAY_MS = 2e4;
|
|
4152
4206
|
LLMAgent = class {
|
|
4153
4207
|
client = null;
|
|
4154
4208
|
// ── Session state for server-side chaining ──────────────
|
|
@@ -4156,6 +4210,19 @@ var init_llm_router = __esm({
|
|
|
4156
4210
|
// Enables turn 2+ to skip re-sending system prompt + history.
|
|
4157
4211
|
// Call resetSession() between independent generation runs.
|
|
4158
4212
|
lastSessionId;
|
|
4213
|
+
/**
|
|
4214
|
+
* Explicit per-call routing override — see `AgentConfig.routeOverride`.
|
|
4215
|
+
* Absent when constructed via the bare `new XAgent()` form (every
|
|
4216
|
+
* existing call site), so `createClient()`/`resolveModel()` fall
|
|
4217
|
+
* back to `process.env` exactly as before.
|
|
4218
|
+
*/
|
|
4219
|
+
routeOverride;
|
|
4220
|
+
/** See `AgentConfig.onRetry` (#489). Absent is a no-op. */
|
|
4221
|
+
onRetry;
|
|
4222
|
+
constructor(routeOverride, onRetry) {
|
|
4223
|
+
this.routeOverride = routeOverride;
|
|
4224
|
+
this.onRetry = onRetry;
|
|
4225
|
+
}
|
|
4159
4226
|
async getClient() {
|
|
4160
4227
|
if (!this.client) {
|
|
4161
4228
|
this.client = await this.createClient();
|
|
@@ -4189,36 +4256,104 @@ var init_llm_router = __esm({
|
|
|
4189
4256
|
async sendToolResult(_results) {
|
|
4190
4257
|
}
|
|
4191
4258
|
/**
|
|
4192
|
-
* Execute an API call
|
|
4193
|
-
*
|
|
4259
|
+
* Execute an API call, retrying once or twice on HTTP 429
|
|
4260
|
+
* (rate-limited) before giving up (#489).
|
|
4261
|
+
*
|
|
4262
|
+
* Policy: on a 429, honor the provider's `Retry-After` header when
|
|
4263
|
+
* present (capped at `RETRY_AFTER_CAP_SEC` — a provider asking for a
|
|
4264
|
+
* longer wait is treated as "don't retry", not "wait longer": making
|
|
4265
|
+
* the caller sit through 15+ more seconds on a single failed call is
|
|
4266
|
+
* a bad experience regardless of what's driving the request);
|
|
4267
|
+
* otherwise fall back to exponential backoff with jitter, capped at
|
|
4268
|
+
* `DEFAULT_BACKOFF_MAX_MS` per attempt. Stops after
|
|
4269
|
+
* `MAX_RETRY_ATTEMPTS` retries OR once the cumulative delay would
|
|
4270
|
+
* exceed `MAX_TOTAL_RETRY_DELAY_MS`, whichever comes first. Any
|
|
4271
|
+
* non-429 error, or a 429 with no attempts left, is logged and
|
|
4272
|
+
* re-thrown immediately — unchanged from the pre-#489 behavior.
|
|
4273
|
+
*
|
|
4274
|
+
* **Budget scope (final-review correction):** `MAX_TOTAL_RETRY_DELAY_MS`
|
|
4275
|
+
* bounds a single `apiCall()` invocation, not a whole generation. A
|
|
4276
|
+
* generation issues many sequential `apiCall()` calls (coding turns,
|
|
4277
|
+
* tool-result round-trips, eval rounds); under sustained throttling
|
|
4278
|
+
* each one can independently add up to `MAX_TOTAL_RETRY_DELAY_MS`, so
|
|
4279
|
+
* a generation with k rate-limited calls can add up to roughly `k *
|
|
4280
|
+
* MAX_TOTAL_RETRY_DELAY_MS` to how long it holds its caller's
|
|
4281
|
+
* resources (e.g. the caller's concurrency slot) — not a flat 20s
|
|
4282
|
+
* ceiling. No shared per-generation budget is threaded here by
|
|
4283
|
+
* design (accepted ruling, not an oversight): the caller's own
|
|
4284
|
+
* queue/admission backstop is what bounds how long other
|
|
4285
|
+
* queued work waits, independent of any one generation's retry
|
|
4286
|
+
* total.
|
|
4194
4287
|
*/
|
|
4195
4288
|
async apiCall(fn) {
|
|
4196
4289
|
const start = Date.now();
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4290
|
+
let totalDelayMs = 0;
|
|
4291
|
+
for (let attempt = 0; ; attempt++) {
|
|
4292
|
+
try {
|
|
4293
|
+
return await fn();
|
|
4294
|
+
} catch (e) {
|
|
4295
|
+
const ms = Date.now() - start;
|
|
4296
|
+
if (attempt >= MAX_RETRY_ATTEMPTS || !isRateLimited(e)) {
|
|
4297
|
+
console.error(`[${this.provider}] API error after ${ms}ms: ${errorSummary(e)}`);
|
|
4298
|
+
throw e;
|
|
4299
|
+
}
|
|
4300
|
+
const retryAfterSec = extractRetryAfterSec(e);
|
|
4301
|
+
if (retryAfterSec !== void 0 && retryAfterSec > RETRY_AFTER_CAP_SEC) {
|
|
4302
|
+
console.error(
|
|
4303
|
+
`[${this.provider}] API error after ${ms}ms (retry-after ${retryAfterSec}s exceeds ${RETRY_AFTER_CAP_SEC}s cap, not retrying): ${errorSummary(e)}`
|
|
4304
|
+
);
|
|
4305
|
+
throw e;
|
|
4306
|
+
}
|
|
4307
|
+
const delayMs = retryAfterSec !== void 0 ? retryAfterSec * 1e3 : Math.min(DEFAULT_BACKOFF_BASE_MS * 2 ** attempt, DEFAULT_BACKOFF_MAX_MS) + Math.floor(Math.random() * 250);
|
|
4308
|
+
if (totalDelayMs + delayMs > MAX_TOTAL_RETRY_DELAY_MS) {
|
|
4309
|
+
console.error(
|
|
4310
|
+
`[${this.provider}] API error after ${ms}ms (retry budget exhausted, not retrying): ${errorSummary(e)}`
|
|
4311
|
+
);
|
|
4312
|
+
throw e;
|
|
4313
|
+
}
|
|
4314
|
+
totalDelayMs += delayMs;
|
|
4315
|
+
const info = {
|
|
4316
|
+
provider: this.provider,
|
|
4317
|
+
attempt: attempt + 1,
|
|
4318
|
+
maxAttempts: MAX_RETRY_ATTEMPTS,
|
|
4319
|
+
status: extractStatus(e),
|
|
4320
|
+
retryAfterSec,
|
|
4321
|
+
delayMs,
|
|
4322
|
+
message: errorSummary(e)
|
|
4323
|
+
};
|
|
4324
|
+
console.warn(
|
|
4325
|
+
`[${this.provider}] rate-limited (attempt ${info.attempt}/${info.maxAttempts}), retrying in ${delayMs}ms`
|
|
4326
|
+
);
|
|
4327
|
+
try {
|
|
4328
|
+
this.onRetry?.(info);
|
|
4329
|
+
} catch (observerError) {
|
|
4330
|
+
console.warn(
|
|
4331
|
+
`[${this.provider}] onRetry observer threw (ignored, retry proceeds): ${errorSummary(observerError)}`
|
|
4332
|
+
);
|
|
4333
|
+
}
|
|
4334
|
+
await sleep(delayMs);
|
|
4335
|
+
}
|
|
4203
4336
|
}
|
|
4204
4337
|
}
|
|
4205
4338
|
};
|
|
4206
4339
|
AnthropicAgent = class extends LLMAgent {
|
|
4207
4340
|
provider = "anthropic";
|
|
4208
4341
|
resolveModel(model) {
|
|
4209
|
-
|
|
4342
|
+
const useBedrock = this.routeOverride?.useBedrock ?? process.env.CLAUDE_CODE_USE_BEDROCK === "1";
|
|
4343
|
+
if (useBedrock) {
|
|
4210
4344
|
return getBedrockModelId(model);
|
|
4211
4345
|
}
|
|
4212
4346
|
return model.startsWith("anthropic/") ? model.slice("anthropic/".length) : model;
|
|
4213
4347
|
}
|
|
4214
4348
|
async createClient() {
|
|
4215
|
-
|
|
4349
|
+
const useBedrock = this.routeOverride?.useBedrock ?? process.env.CLAUDE_CODE_USE_BEDROCK === "1";
|
|
4350
|
+
if (useBedrock) {
|
|
4216
4351
|
const { AnthropicBedrock } = await import('@anthropic-ai/bedrock-sdk');
|
|
4217
4352
|
return new AnthropicBedrock({
|
|
4218
4353
|
awsRegion: process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? "us-east-1"
|
|
4219
4354
|
});
|
|
4220
4355
|
}
|
|
4221
|
-
return createAnthropicClient(process.env.ANTHROPIC_API_KEY);
|
|
4356
|
+
return createAnthropicClient(this.routeOverride?.apiKey ?? process.env.ANTHROPIC_API_KEY);
|
|
4222
4357
|
}
|
|
4223
4358
|
async callText(model, systemPrompt, userPrompt, maxTokens, temperature) {
|
|
4224
4359
|
const client = await this.getClient();
|
|
@@ -4290,6 +4425,73 @@ var init_llm_router = __esm({
|
|
|
4290
4425
|
throw e;
|
|
4291
4426
|
}
|
|
4292
4427
|
}
|
|
4428
|
+
async callVision(model, systemPrompt, userPrompt, image, maxTokens) {
|
|
4429
|
+
const client = await this.getClient();
|
|
4430
|
+
const traceId = newLlmTraceId();
|
|
4431
|
+
const startedAt = Date.now();
|
|
4432
|
+
const resolvedModel = this.resolveModel(model);
|
|
4433
|
+
const imageBlock = {
|
|
4434
|
+
type: "image",
|
|
4435
|
+
source: {
|
|
4436
|
+
type: "base64",
|
|
4437
|
+
media_type: image.mediaType,
|
|
4438
|
+
data: image.base64
|
|
4439
|
+
}
|
|
4440
|
+
};
|
|
4441
|
+
try {
|
|
4442
|
+
const response = await this.apiCall(
|
|
4443
|
+
() => client.messages.create({
|
|
4444
|
+
model: resolvedModel,
|
|
4445
|
+
max_tokens: maxTokens ?? 1500,
|
|
4446
|
+
system: systemPrompt,
|
|
4447
|
+
messages: [
|
|
4448
|
+
{
|
|
4449
|
+
role: "user",
|
|
4450
|
+
content: [imageBlock, { type: "text", text: userPrompt }]
|
|
4451
|
+
}
|
|
4452
|
+
]
|
|
4453
|
+
})
|
|
4454
|
+
);
|
|
4455
|
+
const text = response.content.filter((block) => block.type === "text").map((block) => block.text).join("");
|
|
4456
|
+
const endedAt = Date.now();
|
|
4457
|
+
emitLlmTraceEvent({
|
|
4458
|
+
id: traceId,
|
|
4459
|
+
at: startedAt,
|
|
4460
|
+
endedAt,
|
|
4461
|
+
durationMs: endedAt - startedAt,
|
|
4462
|
+
provider: "anthropic",
|
|
4463
|
+
model: resolvedModel,
|
|
4464
|
+
kind: "callVision",
|
|
4465
|
+
systemPrompt,
|
|
4466
|
+
userPrompt,
|
|
4467
|
+
result: {
|
|
4468
|
+
inputTokens: response.usage.input_tokens,
|
|
4469
|
+
outputTokens: response.usage.output_tokens,
|
|
4470
|
+
text
|
|
4471
|
+
}
|
|
4472
|
+
});
|
|
4473
|
+
return {
|
|
4474
|
+
text,
|
|
4475
|
+
inputTokens: response.usage.input_tokens,
|
|
4476
|
+
outputTokens: response.usage.output_tokens
|
|
4477
|
+
};
|
|
4478
|
+
} catch (e) {
|
|
4479
|
+
const endedAt = Date.now();
|
|
4480
|
+
emitLlmTraceEvent({
|
|
4481
|
+
id: traceId,
|
|
4482
|
+
at: startedAt,
|
|
4483
|
+
endedAt,
|
|
4484
|
+
durationMs: endedAt - startedAt,
|
|
4485
|
+
provider: "anthropic",
|
|
4486
|
+
model: resolvedModel,
|
|
4487
|
+
kind: "callVision",
|
|
4488
|
+
systemPrompt,
|
|
4489
|
+
userPrompt,
|
|
4490
|
+
error: { message: e instanceof Error ? e.message : String(e) }
|
|
4491
|
+
});
|
|
4492
|
+
throw e;
|
|
4493
|
+
}
|
|
4494
|
+
}
|
|
4293
4495
|
async callTools(model, systemPrompt, userPrompt, tools, toolChoice = "required", _scopedTools) {
|
|
4294
4496
|
const client = await this.getClient();
|
|
4295
4497
|
const traceId = newLlmTraceId();
|
|
@@ -4489,7 +4691,7 @@ var init_llm_router = __esm({
|
|
|
4489
4691
|
}
|
|
4490
4692
|
async createClient() {
|
|
4491
4693
|
const { default: OpenAISDK } = await import('openai');
|
|
4492
|
-
return new OpenAISDK({ apiKey: process.env.OPENAI_API_KEY });
|
|
4694
|
+
return new OpenAISDK({ apiKey: this.routeOverride?.apiKey ?? process.env.OPENAI_API_KEY });
|
|
4493
4695
|
}
|
|
4494
4696
|
async callText(model, systemPrompt, userPrompt, maxTokens, temperature) {
|
|
4495
4697
|
const client = await this.getClient();
|
|
@@ -4639,7 +4841,7 @@ var init_llm_router = __esm({
|
|
|
4639
4841
|
async createClient() {
|
|
4640
4842
|
const { GoogleGenAI: GoogleGenAISDK } = await import('@google/genai');
|
|
4641
4843
|
return new GoogleGenAISDK({
|
|
4642
|
-
apiKey: process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY,
|
|
4844
|
+
apiKey: this.routeOverride?.apiKey ?? (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY),
|
|
4643
4845
|
httpOptions: { timeout: 3e5 }
|
|
4644
4846
|
// 5 min — Pro models can be slow
|
|
4645
4847
|
});
|
|
@@ -4664,6 +4866,72 @@ var init_llm_router = __esm({
|
|
|
4664
4866
|
outputTokens: interaction.usage?.total_output_tokens ?? 0
|
|
4665
4867
|
};
|
|
4666
4868
|
}
|
|
4869
|
+
async callVision(model, systemPrompt, userPrompt, image, maxTokens) {
|
|
4870
|
+
const client = await this.getClient();
|
|
4871
|
+
const traceId = newLlmTraceId();
|
|
4872
|
+
const startedAt = Date.now();
|
|
4873
|
+
const resolvedModel = this.resolveModel(model);
|
|
4874
|
+
try {
|
|
4875
|
+
const response = await this.apiCall(
|
|
4876
|
+
() => client.models.generateContent({
|
|
4877
|
+
model: resolvedModel,
|
|
4878
|
+
contents: [
|
|
4879
|
+
{
|
|
4880
|
+
role: "user",
|
|
4881
|
+
parts: [
|
|
4882
|
+
{ inlineData: { mimeType: image.mediaType, data: image.base64 } },
|
|
4883
|
+
{ text: userPrompt }
|
|
4884
|
+
]
|
|
4885
|
+
}
|
|
4886
|
+
],
|
|
4887
|
+
config: {
|
|
4888
|
+
systemInstruction: systemPrompt,
|
|
4889
|
+
...maxTokens ? { maxOutputTokens: maxTokens } : {}
|
|
4890
|
+
}
|
|
4891
|
+
})
|
|
4892
|
+
);
|
|
4893
|
+
const text = response.candidates?.[0]?.content?.parts?.map((p) => p.text || "").join("") || "";
|
|
4894
|
+
const usage = response.usageMetadata;
|
|
4895
|
+
const result = {
|
|
4896
|
+
text,
|
|
4897
|
+
inputTokens: usage?.promptTokenCount ?? 0,
|
|
4898
|
+
outputTokens: usage?.candidatesTokenCount ?? 0
|
|
4899
|
+
};
|
|
4900
|
+
const endedAt = Date.now();
|
|
4901
|
+
emitLlmTraceEvent({
|
|
4902
|
+
id: traceId,
|
|
4903
|
+
at: startedAt,
|
|
4904
|
+
endedAt,
|
|
4905
|
+
durationMs: endedAt - startedAt,
|
|
4906
|
+
provider: "google",
|
|
4907
|
+
model: resolvedModel,
|
|
4908
|
+
kind: "callVision",
|
|
4909
|
+
systemPrompt,
|
|
4910
|
+
userPrompt,
|
|
4911
|
+
result: {
|
|
4912
|
+
inputTokens: result.inputTokens,
|
|
4913
|
+
outputTokens: result.outputTokens,
|
|
4914
|
+
text
|
|
4915
|
+
}
|
|
4916
|
+
});
|
|
4917
|
+
return result;
|
|
4918
|
+
} catch (e) {
|
|
4919
|
+
const endedAt = Date.now();
|
|
4920
|
+
emitLlmTraceEvent({
|
|
4921
|
+
id: traceId,
|
|
4922
|
+
at: startedAt,
|
|
4923
|
+
endedAt,
|
|
4924
|
+
durationMs: endedAt - startedAt,
|
|
4925
|
+
provider: "google",
|
|
4926
|
+
model: resolvedModel,
|
|
4927
|
+
kind: "callVision",
|
|
4928
|
+
systemPrompt,
|
|
4929
|
+
userPrompt,
|
|
4930
|
+
error: { message: e instanceof Error ? e.message : String(e) }
|
|
4931
|
+
});
|
|
4932
|
+
throw e;
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4667
4935
|
async callTools(model, systemPrompt, userPrompt, tools, _toolChoice = "required", scopedTools) {
|
|
4668
4936
|
const client = await this.getClient();
|
|
4669
4937
|
const interactionTools = tools.map((t) => ({
|
|
@@ -4866,7 +5134,7 @@ var init_llm_router = __esm({
|
|
|
4866
5134
|
async createClient() {
|
|
4867
5135
|
const { OpenRouterClient: OpenRouterClient2 } = await Promise.resolve().then(() => (init_client2(), client_exports));
|
|
4868
5136
|
return new OpenRouterClient2({
|
|
4869
|
-
apiKey: process.env.OPENROUTER_API_KEY
|
|
5137
|
+
apiKey: this.routeOverride?.apiKey ?? process.env.OPENROUTER_API_KEY
|
|
4870
5138
|
});
|
|
4871
5139
|
}
|
|
4872
5140
|
async callText(model, systemPrompt, userPrompt, maxTokens, temperature) {
|
|
@@ -6008,7 +6276,11 @@ async function runLLMEvaluation(context, config, preWarmedContext) {
|
|
|
6008
6276
|
designSystemSummary: context.designContext
|
|
6009
6277
|
});
|
|
6010
6278
|
const numberedSource = context.sourceCode.split("\n").map((line, i) => `${String(i + 1).padStart(4)} | ${line}`).join("\n");
|
|
6011
|
-
const agent = createAgent(
|
|
6279
|
+
const agent = createAgent({
|
|
6280
|
+
provider: routerProvider,
|
|
6281
|
+
routeOverride: config.routeOverride,
|
|
6282
|
+
onRetry: config.onRetry
|
|
6283
|
+
});
|
|
6012
6284
|
const evalStart = Date.now();
|
|
6013
6285
|
const totalCriteriaCount = TIER_1_CRITERIA.length + TIER_2_CRITERIA.length;
|
|
6014
6286
|
const results = await Promise.all([
|
|
@@ -6018,1399 +6290,107 @@ async function runLLMEvaluation(context, config, preWarmedContext) {
|
|
|
6018
6290
|
const allIssues = [];
|
|
6019
6291
|
const passCategories = [];
|
|
6020
6292
|
let totalIn = 0;
|
|
6021
|
-
let totalOut = 0;
|
|
6022
|
-
let cachedTokensEstimate = 0;
|
|
6023
|
-
for (const r of results) {
|
|
6024
|
-
allIssues.push(...r.issues);
|
|
6025
|
-
if (r.pass) {
|
|
6026
|
-
passCategories.push(r.criterion);
|
|
6027
|
-
}
|
|
6028
|
-
totalIn += r.tokens.in;
|
|
6029
|
-
totalOut += r.tokens.out;
|
|
6030
|
-
}
|
|
6031
|
-
const firstResult = results[0];
|
|
6032
|
-
if (firstResult && firstResult.tokens.in > 0) {
|
|
6033
|
-
cachedTokensEstimate = firstResult.tokens.in * (totalCriteriaCount - 1);
|
|
6034
|
-
}
|
|
6035
|
-
const wallMs = Date.now() - evalStart;
|
|
6036
|
-
for (const r of results) {
|
|
6037
|
-
const issueCount = r.issues.length;
|
|
6038
|
-
const status = r.pass ? "PASS" : r.tier === 1 ? "FAIL" : r.issues.some((i) => i.result === "fail") ? "FAIL" : "WARN";
|
|
6039
|
-
const issueLabel = issueCount > 0 ? ` (${issueCount} issue${issueCount > 1 ? "s" : ""})` : "";
|
|
6040
|
-
console.log(`[eval] ${r.criterion}: ${status}${issueLabel} ${(r.durationMs / 1e3).toFixed(1)}s`);
|
|
6041
|
-
}
|
|
6042
|
-
console.log(
|
|
6043
|
-
`[eval] total: ${(wallMs / 1e3).toFixed(1)}s wall (${totalCriteriaCount} parallel) | in=${totalIn} out=${totalOut} cached~=${cachedTokensEstimate} | issues=${allIssues.length} pass=${passCategories.length}`
|
|
6044
|
-
);
|
|
6045
|
-
return {
|
|
6046
|
-
issues: allIssues,
|
|
6047
|
-
pass: passCategories,
|
|
6048
|
-
inputTokens: totalIn,
|
|
6049
|
-
outputTokens: totalOut
|
|
6050
|
-
};
|
|
6051
|
-
}
|
|
6052
|
-
var TIER_1_CRITERIA, TIER_2_CRITERIA, TIER_1_CATEGORIES, TIER_2_CATEGORIES, VALID_CATEGORIES;
|
|
6053
|
-
var init_llm_evaluator = __esm({
|
|
6054
|
-
"src/evaluation/llm-evaluator.ts"() {
|
|
6055
|
-
init_llm_router();
|
|
6056
|
-
init_types_public();
|
|
6057
|
-
TIER_1_CRITERIA = ["functionality", "crash"];
|
|
6058
|
-
TIER_2_CRITERIA = ["interactivity", "accessibility", "layout", "loading", "visual"];
|
|
6059
|
-
TIER_1_CATEGORIES = /* @__PURE__ */ new Set(["functionality", "crash"]);
|
|
6060
|
-
TIER_2_CATEGORIES = /* @__PURE__ */ new Set([
|
|
6061
|
-
"interactivity",
|
|
6062
|
-
"accessibility",
|
|
6063
|
-
"layout",
|
|
6064
|
-
"loading",
|
|
6065
|
-
"visual"
|
|
6066
|
-
]);
|
|
6067
|
-
VALID_CATEGORIES = /* @__PURE__ */ new Set([
|
|
6068
|
-
...TIER_1_CATEGORIES,
|
|
6069
|
-
...TIER_2_CATEGORIES
|
|
6070
|
-
]);
|
|
6071
|
-
}
|
|
6072
|
-
});
|
|
6073
|
-
|
|
6074
|
-
// src/evaluation/cost-tracker.ts
|
|
6075
|
-
var cost_tracker_exports = {};
|
|
6076
|
-
__export(cost_tracker_exports, {
|
|
6077
|
-
CostTracker: () => CostTracker,
|
|
6078
|
-
pricePer1k: () => pricePer1k
|
|
6079
|
-
});
|
|
6080
|
-
function resolveRegistryId(model) {
|
|
6081
|
-
const keys = Object.keys(MODEL_REGISTRY);
|
|
6082
|
-
if (keys.includes(model)) return model;
|
|
6083
|
-
const bySuffix = keys.find((id) => id.endsWith(`/${model}`));
|
|
6084
|
-
if (bySuffix) return bySuffix;
|
|
6085
|
-
const undated = model.replace(/-\d{8}$/, "");
|
|
6086
|
-
return keys.find((id) => id.endsWith(`/${undated}`)) ?? null;
|
|
6087
|
-
}
|
|
6088
|
-
function pricePer1k(model) {
|
|
6089
|
-
const id = resolveRegistryId(model);
|
|
6090
|
-
if (id === null) return FALLBACK_PER_1K;
|
|
6091
|
-
const { costs } = MODEL_REGISTRY[id];
|
|
6092
|
-
return { input: costs.inputPer1M / 1e3, output: costs.outputPer1M / 1e3 };
|
|
6093
|
-
}
|
|
6094
|
-
var FALLBACK_PER_1K, CostTracker;
|
|
6095
|
-
var init_cost_tracker = __esm({
|
|
6096
|
-
"src/evaluation/cost-tracker.ts"() {
|
|
6097
|
-
FALLBACK_PER_1K = { input: 3e-3, output: 0.015 };
|
|
6098
|
-
CostTracker = class {
|
|
6099
|
-
constructor(maxBudget) {
|
|
6100
|
-
this.maxBudget = maxBudget;
|
|
6101
|
-
}
|
|
6102
|
-
maxBudget;
|
|
6103
|
-
totalCost = 0;
|
|
6104
|
-
record(model, inputTokens, outputTokens) {
|
|
6105
|
-
const prices = pricePer1k(model);
|
|
6106
|
-
const cost = inputTokens / 1e3 * prices.input + outputTokens / 1e3 * prices.output;
|
|
6107
|
-
this.totalCost += cost;
|
|
6108
|
-
return cost;
|
|
6109
|
-
}
|
|
6110
|
-
canContinue() {
|
|
6111
|
-
if (this.maxBudget === null) return true;
|
|
6112
|
-
return this.totalCost < this.maxBudget;
|
|
6113
|
-
}
|
|
6114
|
-
getTotal() {
|
|
6115
|
-
return this.totalCost;
|
|
6116
|
-
}
|
|
6117
|
-
getRemaining() {
|
|
6118
|
-
if (this.maxBudget === null) return null;
|
|
6119
|
-
return Math.max(0, this.maxBudget - this.totalCost);
|
|
6120
|
-
}
|
|
6121
|
-
};
|
|
6122
|
-
}
|
|
6123
|
-
});
|
|
6124
|
-
|
|
6125
|
-
// ../../node_modules/ms/index.js
|
|
6126
|
-
var require_ms = __commonJS({
|
|
6127
|
-
"../../node_modules/ms/index.js"(exports, module) {
|
|
6128
|
-
var s = 1e3;
|
|
6129
|
-
var m = s * 60;
|
|
6130
|
-
var h = m * 60;
|
|
6131
|
-
var d = h * 24;
|
|
6132
|
-
var w = d * 7;
|
|
6133
|
-
var y = d * 365.25;
|
|
6134
|
-
module.exports = function(val, options) {
|
|
6135
|
-
options = options || {};
|
|
6136
|
-
var type = typeof val;
|
|
6137
|
-
if (type === "string" && val.length > 0) {
|
|
6138
|
-
return parse(val);
|
|
6139
|
-
} else if (type === "number" && isFinite(val)) {
|
|
6140
|
-
return options.long ? fmtLong(val) : fmtShort(val);
|
|
6141
|
-
}
|
|
6142
|
-
throw new Error(
|
|
6143
|
-
"val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
|
|
6144
|
-
);
|
|
6145
|
-
};
|
|
6146
|
-
function parse(str) {
|
|
6147
|
-
str = String(str);
|
|
6148
|
-
if (str.length > 100) {
|
|
6149
|
-
return;
|
|
6150
|
-
}
|
|
6151
|
-
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
|
|
6152
|
-
str
|
|
6153
|
-
);
|
|
6154
|
-
if (!match) {
|
|
6155
|
-
return;
|
|
6156
|
-
}
|
|
6157
|
-
var n = parseFloat(match[1]);
|
|
6158
|
-
var type = (match[2] || "ms").toLowerCase();
|
|
6159
|
-
switch (type) {
|
|
6160
|
-
case "years":
|
|
6161
|
-
case "year":
|
|
6162
|
-
case "yrs":
|
|
6163
|
-
case "yr":
|
|
6164
|
-
case "y":
|
|
6165
|
-
return n * y;
|
|
6166
|
-
case "weeks":
|
|
6167
|
-
case "week":
|
|
6168
|
-
case "w":
|
|
6169
|
-
return n * w;
|
|
6170
|
-
case "days":
|
|
6171
|
-
case "day":
|
|
6172
|
-
case "d":
|
|
6173
|
-
return n * d;
|
|
6174
|
-
case "hours":
|
|
6175
|
-
case "hour":
|
|
6176
|
-
case "hrs":
|
|
6177
|
-
case "hr":
|
|
6178
|
-
case "h":
|
|
6179
|
-
return n * h;
|
|
6180
|
-
case "minutes":
|
|
6181
|
-
case "minute":
|
|
6182
|
-
case "mins":
|
|
6183
|
-
case "min":
|
|
6184
|
-
case "m":
|
|
6185
|
-
return n * m;
|
|
6186
|
-
case "seconds":
|
|
6187
|
-
case "second":
|
|
6188
|
-
case "secs":
|
|
6189
|
-
case "sec":
|
|
6190
|
-
case "s":
|
|
6191
|
-
return n * s;
|
|
6192
|
-
case "milliseconds":
|
|
6193
|
-
case "millisecond":
|
|
6194
|
-
case "msecs":
|
|
6195
|
-
case "msec":
|
|
6196
|
-
case "ms":
|
|
6197
|
-
return n;
|
|
6198
|
-
default:
|
|
6199
|
-
return void 0;
|
|
6200
|
-
}
|
|
6201
|
-
}
|
|
6202
|
-
function fmtShort(ms) {
|
|
6203
|
-
var msAbs = Math.abs(ms);
|
|
6204
|
-
if (msAbs >= d) {
|
|
6205
|
-
return Math.round(ms / d) + "d";
|
|
6206
|
-
}
|
|
6207
|
-
if (msAbs >= h) {
|
|
6208
|
-
return Math.round(ms / h) + "h";
|
|
6209
|
-
}
|
|
6210
|
-
if (msAbs >= m) {
|
|
6211
|
-
return Math.round(ms / m) + "m";
|
|
6212
|
-
}
|
|
6213
|
-
if (msAbs >= s) {
|
|
6214
|
-
return Math.round(ms / s) + "s";
|
|
6215
|
-
}
|
|
6216
|
-
return ms + "ms";
|
|
6217
|
-
}
|
|
6218
|
-
function fmtLong(ms) {
|
|
6219
|
-
var msAbs = Math.abs(ms);
|
|
6220
|
-
if (msAbs >= d) {
|
|
6221
|
-
return plural(ms, msAbs, d, "day");
|
|
6222
|
-
}
|
|
6223
|
-
if (msAbs >= h) {
|
|
6224
|
-
return plural(ms, msAbs, h, "hour");
|
|
6225
|
-
}
|
|
6226
|
-
if (msAbs >= m) {
|
|
6227
|
-
return plural(ms, msAbs, m, "minute");
|
|
6228
|
-
}
|
|
6229
|
-
if (msAbs >= s) {
|
|
6230
|
-
return plural(ms, msAbs, s, "second");
|
|
6231
|
-
}
|
|
6232
|
-
return ms + " ms";
|
|
6233
|
-
}
|
|
6234
|
-
function plural(ms, msAbs, n, name) {
|
|
6235
|
-
var isPlural = msAbs >= n * 1.5;
|
|
6236
|
-
return Math.round(ms / n) + " " + name + (isPlural ? "s" : "");
|
|
6237
|
-
}
|
|
6238
|
-
}
|
|
6239
|
-
});
|
|
6240
|
-
|
|
6241
|
-
// ../../node_modules/debug/src/common.js
|
|
6242
|
-
var require_common = __commonJS({
|
|
6243
|
-
"../../node_modules/debug/src/common.js"(exports, module) {
|
|
6244
|
-
function setup(env) {
|
|
6245
|
-
createDebug.debug = createDebug;
|
|
6246
|
-
createDebug.default = createDebug;
|
|
6247
|
-
createDebug.coerce = coerce;
|
|
6248
|
-
createDebug.disable = disable;
|
|
6249
|
-
createDebug.enable = enable;
|
|
6250
|
-
createDebug.enabled = enabled;
|
|
6251
|
-
createDebug.humanize = require_ms();
|
|
6252
|
-
createDebug.destroy = destroy;
|
|
6253
|
-
Object.keys(env).forEach((key) => {
|
|
6254
|
-
createDebug[key] = env[key];
|
|
6255
|
-
});
|
|
6256
|
-
createDebug.names = [];
|
|
6257
|
-
createDebug.skips = [];
|
|
6258
|
-
createDebug.formatters = {};
|
|
6259
|
-
function selectColor(namespace) {
|
|
6260
|
-
let hash = 0;
|
|
6261
|
-
for (let i = 0; i < namespace.length; i++) {
|
|
6262
|
-
hash = (hash << 5) - hash + namespace.charCodeAt(i);
|
|
6263
|
-
hash |= 0;
|
|
6264
|
-
}
|
|
6265
|
-
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
|
6266
|
-
}
|
|
6267
|
-
createDebug.selectColor = selectColor;
|
|
6268
|
-
function createDebug(namespace) {
|
|
6269
|
-
let prevTime;
|
|
6270
|
-
let enableOverride = null;
|
|
6271
|
-
let namespacesCache;
|
|
6272
|
-
let enabledCache;
|
|
6273
|
-
function debug(...args) {
|
|
6274
|
-
if (!debug.enabled) {
|
|
6275
|
-
return;
|
|
6276
|
-
}
|
|
6277
|
-
const self = debug;
|
|
6278
|
-
const curr = Number(/* @__PURE__ */ new Date());
|
|
6279
|
-
const ms = curr - (prevTime || curr);
|
|
6280
|
-
self.diff = ms;
|
|
6281
|
-
self.prev = prevTime;
|
|
6282
|
-
self.curr = curr;
|
|
6283
|
-
prevTime = curr;
|
|
6284
|
-
args[0] = createDebug.coerce(args[0]);
|
|
6285
|
-
if (typeof args[0] !== "string") {
|
|
6286
|
-
args.unshift("%O");
|
|
6287
|
-
}
|
|
6288
|
-
let index = 0;
|
|
6289
|
-
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
|
6290
|
-
if (match === "%%") {
|
|
6291
|
-
return "%";
|
|
6292
|
-
}
|
|
6293
|
-
index++;
|
|
6294
|
-
const formatter = createDebug.formatters[format];
|
|
6295
|
-
if (typeof formatter === "function") {
|
|
6296
|
-
const val = args[index];
|
|
6297
|
-
match = formatter.call(self, val);
|
|
6298
|
-
args.splice(index, 1);
|
|
6299
|
-
index--;
|
|
6300
|
-
}
|
|
6301
|
-
return match;
|
|
6302
|
-
});
|
|
6303
|
-
createDebug.formatArgs.call(self, args);
|
|
6304
|
-
const logFn = self.log || createDebug.log;
|
|
6305
|
-
logFn.apply(self, args);
|
|
6306
|
-
}
|
|
6307
|
-
debug.namespace = namespace;
|
|
6308
|
-
debug.useColors = createDebug.useColors();
|
|
6309
|
-
debug.color = createDebug.selectColor(namespace);
|
|
6310
|
-
debug.extend = extend;
|
|
6311
|
-
debug.destroy = createDebug.destroy;
|
|
6312
|
-
Object.defineProperty(debug, "enabled", {
|
|
6313
|
-
enumerable: true,
|
|
6314
|
-
configurable: false,
|
|
6315
|
-
get: () => {
|
|
6316
|
-
if (enableOverride !== null) {
|
|
6317
|
-
return enableOverride;
|
|
6318
|
-
}
|
|
6319
|
-
if (namespacesCache !== createDebug.namespaces) {
|
|
6320
|
-
namespacesCache = createDebug.namespaces;
|
|
6321
|
-
enabledCache = createDebug.enabled(namespace);
|
|
6322
|
-
}
|
|
6323
|
-
return enabledCache;
|
|
6324
|
-
},
|
|
6325
|
-
set: (v) => {
|
|
6326
|
-
enableOverride = v;
|
|
6327
|
-
}
|
|
6328
|
-
});
|
|
6329
|
-
if (typeof createDebug.init === "function") {
|
|
6330
|
-
createDebug.init(debug);
|
|
6331
|
-
}
|
|
6332
|
-
return debug;
|
|
6333
|
-
}
|
|
6334
|
-
function extend(namespace, delimiter) {
|
|
6335
|
-
const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
|
|
6336
|
-
newDebug.log = this.log;
|
|
6337
|
-
return newDebug;
|
|
6338
|
-
}
|
|
6339
|
-
function enable(namespaces) {
|
|
6340
|
-
createDebug.save(namespaces);
|
|
6341
|
-
createDebug.namespaces = namespaces;
|
|
6342
|
-
createDebug.names = [];
|
|
6343
|
-
createDebug.skips = [];
|
|
6344
|
-
const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(/\s+/g, ",").split(",").filter(Boolean);
|
|
6345
|
-
for (const ns of split) {
|
|
6346
|
-
if (ns[0] === "-") {
|
|
6347
|
-
createDebug.skips.push(ns.slice(1));
|
|
6348
|
-
} else {
|
|
6349
|
-
createDebug.names.push(ns);
|
|
6350
|
-
}
|
|
6351
|
-
}
|
|
6352
|
-
}
|
|
6353
|
-
function matchesTemplate(search, template) {
|
|
6354
|
-
let searchIndex = 0;
|
|
6355
|
-
let templateIndex = 0;
|
|
6356
|
-
let starIndex = -1;
|
|
6357
|
-
let matchIndex = 0;
|
|
6358
|
-
while (searchIndex < search.length) {
|
|
6359
|
-
if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === "*")) {
|
|
6360
|
-
if (template[templateIndex] === "*") {
|
|
6361
|
-
starIndex = templateIndex;
|
|
6362
|
-
matchIndex = searchIndex;
|
|
6363
|
-
templateIndex++;
|
|
6364
|
-
} else {
|
|
6365
|
-
searchIndex++;
|
|
6366
|
-
templateIndex++;
|
|
6367
|
-
}
|
|
6368
|
-
} else if (starIndex !== -1) {
|
|
6369
|
-
templateIndex = starIndex + 1;
|
|
6370
|
-
matchIndex++;
|
|
6371
|
-
searchIndex = matchIndex;
|
|
6372
|
-
} else {
|
|
6373
|
-
return false;
|
|
6374
|
-
}
|
|
6375
|
-
}
|
|
6376
|
-
while (templateIndex < template.length && template[templateIndex] === "*") {
|
|
6377
|
-
templateIndex++;
|
|
6378
|
-
}
|
|
6379
|
-
return templateIndex === template.length;
|
|
6380
|
-
}
|
|
6381
|
-
function disable() {
|
|
6382
|
-
const namespaces = [
|
|
6383
|
-
...createDebug.names,
|
|
6384
|
-
...createDebug.skips.map((namespace) => "-" + namespace)
|
|
6385
|
-
].join(",");
|
|
6386
|
-
createDebug.enable("");
|
|
6387
|
-
return namespaces;
|
|
6388
|
-
}
|
|
6389
|
-
function enabled(name) {
|
|
6390
|
-
for (const skip of createDebug.skips) {
|
|
6391
|
-
if (matchesTemplate(name, skip)) {
|
|
6392
|
-
return false;
|
|
6393
|
-
}
|
|
6394
|
-
}
|
|
6395
|
-
for (const ns of createDebug.names) {
|
|
6396
|
-
if (matchesTemplate(name, ns)) {
|
|
6397
|
-
return true;
|
|
6398
|
-
}
|
|
6399
|
-
}
|
|
6400
|
-
return false;
|
|
6401
|
-
}
|
|
6402
|
-
function coerce(val) {
|
|
6403
|
-
if (val instanceof Error) {
|
|
6404
|
-
return val.stack || val.message;
|
|
6405
|
-
}
|
|
6406
|
-
return val;
|
|
6407
|
-
}
|
|
6408
|
-
function destroy() {
|
|
6409
|
-
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
|
|
6410
|
-
}
|
|
6411
|
-
createDebug.enable(createDebug.load());
|
|
6412
|
-
return createDebug;
|
|
6413
|
-
}
|
|
6414
|
-
module.exports = setup;
|
|
6415
|
-
}
|
|
6416
|
-
});
|
|
6417
|
-
|
|
6418
|
-
// ../../node_modules/debug/src/browser.js
|
|
6419
|
-
var require_browser = __commonJS({
|
|
6420
|
-
"../../node_modules/debug/src/browser.js"(exports, module) {
|
|
6421
|
-
exports.formatArgs = formatArgs;
|
|
6422
|
-
exports.save = save;
|
|
6423
|
-
exports.load = load;
|
|
6424
|
-
exports.useColors = useColors;
|
|
6425
|
-
exports.storage = localstorage();
|
|
6426
|
-
exports.destroy = /* @__PURE__ */ (() => {
|
|
6427
|
-
let warned = false;
|
|
6428
|
-
return () => {
|
|
6429
|
-
if (!warned) {
|
|
6430
|
-
warned = true;
|
|
6431
|
-
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
|
|
6432
|
-
}
|
|
6433
|
-
};
|
|
6434
|
-
})();
|
|
6435
|
-
exports.colors = [
|
|
6436
|
-
"#0000CC",
|
|
6437
|
-
"#0000FF",
|
|
6438
|
-
"#0033CC",
|
|
6439
|
-
"#0033FF",
|
|
6440
|
-
"#0066CC",
|
|
6441
|
-
"#0066FF",
|
|
6442
|
-
"#0099CC",
|
|
6443
|
-
"#0099FF",
|
|
6444
|
-
"#00CC00",
|
|
6445
|
-
"#00CC33",
|
|
6446
|
-
"#00CC66",
|
|
6447
|
-
"#00CC99",
|
|
6448
|
-
"#00CCCC",
|
|
6449
|
-
"#00CCFF",
|
|
6450
|
-
"#3300CC",
|
|
6451
|
-
"#3300FF",
|
|
6452
|
-
"#3333CC",
|
|
6453
|
-
"#3333FF",
|
|
6454
|
-
"#3366CC",
|
|
6455
|
-
"#3366FF",
|
|
6456
|
-
"#3399CC",
|
|
6457
|
-
"#3399FF",
|
|
6458
|
-
"#33CC00",
|
|
6459
|
-
"#33CC33",
|
|
6460
|
-
"#33CC66",
|
|
6461
|
-
"#33CC99",
|
|
6462
|
-
"#33CCCC",
|
|
6463
|
-
"#33CCFF",
|
|
6464
|
-
"#6600CC",
|
|
6465
|
-
"#6600FF",
|
|
6466
|
-
"#6633CC",
|
|
6467
|
-
"#6633FF",
|
|
6468
|
-
"#66CC00",
|
|
6469
|
-
"#66CC33",
|
|
6470
|
-
"#9900CC",
|
|
6471
|
-
"#9900FF",
|
|
6472
|
-
"#9933CC",
|
|
6473
|
-
"#9933FF",
|
|
6474
|
-
"#99CC00",
|
|
6475
|
-
"#99CC33",
|
|
6476
|
-
"#CC0000",
|
|
6477
|
-
"#CC0033",
|
|
6478
|
-
"#CC0066",
|
|
6479
|
-
"#CC0099",
|
|
6480
|
-
"#CC00CC",
|
|
6481
|
-
"#CC00FF",
|
|
6482
|
-
"#CC3300",
|
|
6483
|
-
"#CC3333",
|
|
6484
|
-
"#CC3366",
|
|
6485
|
-
"#CC3399",
|
|
6486
|
-
"#CC33CC",
|
|
6487
|
-
"#CC33FF",
|
|
6488
|
-
"#CC6600",
|
|
6489
|
-
"#CC6633",
|
|
6490
|
-
"#CC9900",
|
|
6491
|
-
"#CC9933",
|
|
6492
|
-
"#CCCC00",
|
|
6493
|
-
"#CCCC33",
|
|
6494
|
-
"#FF0000",
|
|
6495
|
-
"#FF0033",
|
|
6496
|
-
"#FF0066",
|
|
6497
|
-
"#FF0099",
|
|
6498
|
-
"#FF00CC",
|
|
6499
|
-
"#FF00FF",
|
|
6500
|
-
"#FF3300",
|
|
6501
|
-
"#FF3333",
|
|
6502
|
-
"#FF3366",
|
|
6503
|
-
"#FF3399",
|
|
6504
|
-
"#FF33CC",
|
|
6505
|
-
"#FF33FF",
|
|
6506
|
-
"#FF6600",
|
|
6507
|
-
"#FF6633",
|
|
6508
|
-
"#FF9900",
|
|
6509
|
-
"#FF9933",
|
|
6510
|
-
"#FFCC00",
|
|
6511
|
-
"#FFCC33"
|
|
6512
|
-
];
|
|
6513
|
-
function useColors() {
|
|
6514
|
-
if (typeof window !== "undefined" && window.process && (window.process.type === "renderer" || window.process.__nwjs)) {
|
|
6515
|
-
return true;
|
|
6516
|
-
}
|
|
6517
|
-
if (typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
|
6518
|
-
return false;
|
|
6519
|
-
}
|
|
6520
|
-
let m;
|
|
6521
|
-
return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
|
|
6522
|
-
typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
|
|
6523
|
-
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
|
6524
|
-
typeof navigator !== "undefined" && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker
|
|
6525
|
-
typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
|
|
6526
|
-
}
|
|
6527
|
-
function formatArgs(args) {
|
|
6528
|
-
args[0] = (this.useColors ? "%c" : "") + this.namespace + (this.useColors ? " %c" : " ") + args[0] + (this.useColors ? "%c " : " ") + "+" + module.exports.humanize(this.diff);
|
|
6529
|
-
if (!this.useColors) {
|
|
6530
|
-
return;
|
|
6531
|
-
}
|
|
6532
|
-
const c = "color: " + this.color;
|
|
6533
|
-
args.splice(1, 0, c, "color: inherit");
|
|
6534
|
-
let index = 0;
|
|
6535
|
-
let lastC = 0;
|
|
6536
|
-
args[0].replace(/%[a-zA-Z%]/g, (match) => {
|
|
6537
|
-
if (match === "%%") {
|
|
6538
|
-
return;
|
|
6539
|
-
}
|
|
6540
|
-
index++;
|
|
6541
|
-
if (match === "%c") {
|
|
6542
|
-
lastC = index;
|
|
6543
|
-
}
|
|
6544
|
-
});
|
|
6545
|
-
args.splice(lastC, 0, c);
|
|
6546
|
-
}
|
|
6547
|
-
exports.log = console.debug || console.log || (() => {
|
|
6548
|
-
});
|
|
6549
|
-
function save(namespaces) {
|
|
6550
|
-
try {
|
|
6551
|
-
if (namespaces) {
|
|
6552
|
-
exports.storage.setItem("debug", namespaces);
|
|
6553
|
-
} else {
|
|
6554
|
-
exports.storage.removeItem("debug");
|
|
6555
|
-
}
|
|
6556
|
-
} catch (error) {
|
|
6557
|
-
}
|
|
6558
|
-
}
|
|
6559
|
-
function load() {
|
|
6560
|
-
let r;
|
|
6561
|
-
try {
|
|
6562
|
-
r = exports.storage.getItem("debug") || exports.storage.getItem("DEBUG");
|
|
6563
|
-
} catch (error) {
|
|
6564
|
-
}
|
|
6565
|
-
if (!r && typeof process !== "undefined" && "env" in process) {
|
|
6566
|
-
r = process.env.DEBUG;
|
|
6567
|
-
}
|
|
6568
|
-
return r;
|
|
6569
|
-
}
|
|
6570
|
-
function localstorage() {
|
|
6571
|
-
try {
|
|
6572
|
-
return localStorage;
|
|
6573
|
-
} catch (error) {
|
|
6574
|
-
}
|
|
6575
|
-
}
|
|
6576
|
-
module.exports = require_common()(exports);
|
|
6577
|
-
var { formatters } = module.exports;
|
|
6578
|
-
formatters.j = function(v) {
|
|
6579
|
-
try {
|
|
6580
|
-
return JSON.stringify(v);
|
|
6581
|
-
} catch (error) {
|
|
6582
|
-
return "[UnexpectedJSONParseError]: " + error.message;
|
|
6583
|
-
}
|
|
6584
|
-
};
|
|
6585
|
-
}
|
|
6586
|
-
});
|
|
6587
|
-
|
|
6588
|
-
// ../../node_modules/has-flag/index.js
|
|
6589
|
-
var require_has_flag = __commonJS({
|
|
6590
|
-
"../../node_modules/has-flag/index.js"(exports, module) {
|
|
6591
|
-
module.exports = (flag, argv = process.argv) => {
|
|
6592
|
-
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
6593
|
-
const position = argv.indexOf(prefix + flag);
|
|
6594
|
-
const terminatorPosition = argv.indexOf("--");
|
|
6595
|
-
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
6596
|
-
};
|
|
6597
|
-
}
|
|
6598
|
-
});
|
|
6599
|
-
|
|
6600
|
-
// ../../node_modules/supports-color/index.js
|
|
6601
|
-
var require_supports_color = __commonJS({
|
|
6602
|
-
"../../node_modules/supports-color/index.js"(exports, module) {
|
|
6603
|
-
var os = __require("os");
|
|
6604
|
-
var tty = __require("tty");
|
|
6605
|
-
var hasFlag = require_has_flag();
|
|
6606
|
-
var { env } = process;
|
|
6607
|
-
var forceColor;
|
|
6608
|
-
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
6609
|
-
forceColor = 0;
|
|
6610
|
-
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
6611
|
-
forceColor = 1;
|
|
6612
|
-
}
|
|
6613
|
-
if ("FORCE_COLOR" in env) {
|
|
6614
|
-
if (env.FORCE_COLOR === "true") {
|
|
6615
|
-
forceColor = 1;
|
|
6616
|
-
} else if (env.FORCE_COLOR === "false") {
|
|
6617
|
-
forceColor = 0;
|
|
6618
|
-
} else {
|
|
6619
|
-
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
|
|
6620
|
-
}
|
|
6621
|
-
}
|
|
6622
|
-
function translateLevel(level) {
|
|
6623
|
-
if (level === 0) {
|
|
6624
|
-
return false;
|
|
6625
|
-
}
|
|
6626
|
-
return {
|
|
6627
|
-
level,
|
|
6628
|
-
hasBasic: true,
|
|
6629
|
-
has256: level >= 2,
|
|
6630
|
-
has16m: level >= 3
|
|
6631
|
-
};
|
|
6632
|
-
}
|
|
6633
|
-
function supportsColor(haveStream, streamIsTTY) {
|
|
6634
|
-
if (forceColor === 0) {
|
|
6635
|
-
return 0;
|
|
6636
|
-
}
|
|
6637
|
-
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
6638
|
-
return 3;
|
|
6639
|
-
}
|
|
6640
|
-
if (hasFlag("color=256")) {
|
|
6641
|
-
return 2;
|
|
6642
|
-
}
|
|
6643
|
-
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
6644
|
-
return 0;
|
|
6645
|
-
}
|
|
6646
|
-
const min = forceColor || 0;
|
|
6647
|
-
if (env.TERM === "dumb") {
|
|
6648
|
-
return min;
|
|
6649
|
-
}
|
|
6650
|
-
if (process.platform === "win32") {
|
|
6651
|
-
const osRelease = os.release().split(".");
|
|
6652
|
-
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
6653
|
-
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
6654
|
-
}
|
|
6655
|
-
return 1;
|
|
6656
|
-
}
|
|
6657
|
-
if ("CI" in env) {
|
|
6658
|
-
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
6659
|
-
return 1;
|
|
6660
|
-
}
|
|
6661
|
-
return min;
|
|
6662
|
-
}
|
|
6663
|
-
if ("TEAMCITY_VERSION" in env) {
|
|
6664
|
-
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
6665
|
-
}
|
|
6666
|
-
if (env.COLORTERM === "truecolor") {
|
|
6667
|
-
return 3;
|
|
6668
|
-
}
|
|
6669
|
-
if ("TERM_PROGRAM" in env) {
|
|
6670
|
-
const version = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
6671
|
-
switch (env.TERM_PROGRAM) {
|
|
6672
|
-
case "iTerm.app":
|
|
6673
|
-
return version >= 3 ? 3 : 2;
|
|
6674
|
-
case "Apple_Terminal":
|
|
6675
|
-
return 2;
|
|
6676
|
-
}
|
|
6677
|
-
}
|
|
6678
|
-
if (/-256(color)?$/i.test(env.TERM)) {
|
|
6679
|
-
return 2;
|
|
6680
|
-
}
|
|
6681
|
-
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
6682
|
-
return 1;
|
|
6683
|
-
}
|
|
6684
|
-
if ("COLORTERM" in env) {
|
|
6685
|
-
return 1;
|
|
6686
|
-
}
|
|
6687
|
-
return min;
|
|
6688
|
-
}
|
|
6689
|
-
function getSupportLevel(stream) {
|
|
6690
|
-
const level = supportsColor(stream, stream && stream.isTTY);
|
|
6691
|
-
return translateLevel(level);
|
|
6692
|
-
}
|
|
6693
|
-
module.exports = {
|
|
6694
|
-
supportsColor: getSupportLevel,
|
|
6695
|
-
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
|
|
6696
|
-
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
|
|
6697
|
-
};
|
|
6698
|
-
}
|
|
6699
|
-
});
|
|
6700
|
-
|
|
6701
|
-
// ../../node_modules/debug/src/node.js
|
|
6702
|
-
var require_node = __commonJS({
|
|
6703
|
-
"../../node_modules/debug/src/node.js"(exports, module) {
|
|
6704
|
-
var tty = __require("tty");
|
|
6705
|
-
var util = __require("util");
|
|
6706
|
-
exports.init = init;
|
|
6707
|
-
exports.log = log;
|
|
6708
|
-
exports.formatArgs = formatArgs;
|
|
6709
|
-
exports.save = save;
|
|
6710
|
-
exports.load = load;
|
|
6711
|
-
exports.useColors = useColors;
|
|
6712
|
-
exports.destroy = util.deprecate(
|
|
6713
|
-
() => {
|
|
6714
|
-
},
|
|
6715
|
-
"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."
|
|
6716
|
-
);
|
|
6717
|
-
exports.colors = [6, 2, 3, 4, 5, 1];
|
|
6718
|
-
try {
|
|
6719
|
-
const supportsColor = require_supports_color();
|
|
6720
|
-
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
|
6721
|
-
exports.colors = [
|
|
6722
|
-
20,
|
|
6723
|
-
21,
|
|
6724
|
-
26,
|
|
6725
|
-
27,
|
|
6726
|
-
32,
|
|
6727
|
-
33,
|
|
6728
|
-
38,
|
|
6729
|
-
39,
|
|
6730
|
-
40,
|
|
6731
|
-
41,
|
|
6732
|
-
42,
|
|
6733
|
-
43,
|
|
6734
|
-
44,
|
|
6735
|
-
45,
|
|
6736
|
-
56,
|
|
6737
|
-
57,
|
|
6738
|
-
62,
|
|
6739
|
-
63,
|
|
6740
|
-
68,
|
|
6741
|
-
69,
|
|
6742
|
-
74,
|
|
6743
|
-
75,
|
|
6744
|
-
76,
|
|
6745
|
-
77,
|
|
6746
|
-
78,
|
|
6747
|
-
79,
|
|
6748
|
-
80,
|
|
6749
|
-
81,
|
|
6750
|
-
92,
|
|
6751
|
-
93,
|
|
6752
|
-
98,
|
|
6753
|
-
99,
|
|
6754
|
-
112,
|
|
6755
|
-
113,
|
|
6756
|
-
128,
|
|
6757
|
-
129,
|
|
6758
|
-
134,
|
|
6759
|
-
135,
|
|
6760
|
-
148,
|
|
6761
|
-
149,
|
|
6762
|
-
160,
|
|
6763
|
-
161,
|
|
6764
|
-
162,
|
|
6765
|
-
163,
|
|
6766
|
-
164,
|
|
6767
|
-
165,
|
|
6768
|
-
166,
|
|
6769
|
-
167,
|
|
6770
|
-
168,
|
|
6771
|
-
169,
|
|
6772
|
-
170,
|
|
6773
|
-
171,
|
|
6774
|
-
172,
|
|
6775
|
-
173,
|
|
6776
|
-
178,
|
|
6777
|
-
179,
|
|
6778
|
-
184,
|
|
6779
|
-
185,
|
|
6780
|
-
196,
|
|
6781
|
-
197,
|
|
6782
|
-
198,
|
|
6783
|
-
199,
|
|
6784
|
-
200,
|
|
6785
|
-
201,
|
|
6786
|
-
202,
|
|
6787
|
-
203,
|
|
6788
|
-
204,
|
|
6789
|
-
205,
|
|
6790
|
-
206,
|
|
6791
|
-
207,
|
|
6792
|
-
208,
|
|
6793
|
-
209,
|
|
6794
|
-
214,
|
|
6795
|
-
215,
|
|
6796
|
-
220,
|
|
6797
|
-
221
|
|
6798
|
-
];
|
|
6799
|
-
}
|
|
6800
|
-
} catch (error) {
|
|
6801
|
-
}
|
|
6802
|
-
exports.inspectOpts = Object.keys(process.env).filter((key) => {
|
|
6803
|
-
return /^debug_/i.test(key);
|
|
6804
|
-
}).reduce((obj, key) => {
|
|
6805
|
-
const prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, (_, k) => {
|
|
6806
|
-
return k.toUpperCase();
|
|
6807
|
-
});
|
|
6808
|
-
let val = process.env[key];
|
|
6809
|
-
if (/^(yes|on|true|enabled)$/i.test(val)) {
|
|
6810
|
-
val = true;
|
|
6811
|
-
} else if (/^(no|off|false|disabled)$/i.test(val)) {
|
|
6812
|
-
val = false;
|
|
6813
|
-
} else if (val === "null") {
|
|
6814
|
-
val = null;
|
|
6815
|
-
} else {
|
|
6816
|
-
val = Number(val);
|
|
6817
|
-
}
|
|
6818
|
-
obj[prop] = val;
|
|
6819
|
-
return obj;
|
|
6820
|
-
}, {});
|
|
6821
|
-
function useColors() {
|
|
6822
|
-
return "colors" in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd);
|
|
6823
|
-
}
|
|
6824
|
-
function formatArgs(args) {
|
|
6825
|
-
const { namespace: name, useColors: useColors2 } = this;
|
|
6826
|
-
if (useColors2) {
|
|
6827
|
-
const c = this.color;
|
|
6828
|
-
const colorCode = "\x1B[3" + (c < 8 ? c : "8;5;" + c);
|
|
6829
|
-
const prefix = ` ${colorCode};1m${name} \x1B[0m`;
|
|
6830
|
-
args[0] = prefix + args[0].split("\n").join("\n" + prefix);
|
|
6831
|
-
args.push(colorCode + "m+" + module.exports.humanize(this.diff) + "\x1B[0m");
|
|
6832
|
-
} else {
|
|
6833
|
-
args[0] = getDate() + name + " " + args[0];
|
|
6834
|
-
}
|
|
6835
|
-
}
|
|
6836
|
-
function getDate() {
|
|
6837
|
-
if (exports.inspectOpts.hideDate) {
|
|
6838
|
-
return "";
|
|
6839
|
-
}
|
|
6840
|
-
return (/* @__PURE__ */ new Date()).toISOString() + " ";
|
|
6841
|
-
}
|
|
6842
|
-
function log(...args) {
|
|
6843
|
-
return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + "\n");
|
|
6844
|
-
}
|
|
6845
|
-
function save(namespaces) {
|
|
6846
|
-
if (namespaces) {
|
|
6847
|
-
process.env.DEBUG = namespaces;
|
|
6848
|
-
} else {
|
|
6849
|
-
delete process.env.DEBUG;
|
|
6850
|
-
}
|
|
6851
|
-
}
|
|
6852
|
-
function load() {
|
|
6853
|
-
return process.env.DEBUG;
|
|
6854
|
-
}
|
|
6855
|
-
function init(debug) {
|
|
6856
|
-
debug.inspectOpts = {};
|
|
6857
|
-
const keys = Object.keys(exports.inspectOpts);
|
|
6858
|
-
for (let i = 0; i < keys.length; i++) {
|
|
6859
|
-
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
|
6860
|
-
}
|
|
6861
|
-
}
|
|
6862
|
-
module.exports = require_common()(exports);
|
|
6863
|
-
var { formatters } = module.exports;
|
|
6864
|
-
formatters.o = function(v) {
|
|
6865
|
-
this.inspectOpts.colors = this.useColors;
|
|
6866
|
-
return util.inspect(v, this.inspectOpts).split("\n").map((str) => str.trim()).join(" ");
|
|
6867
|
-
};
|
|
6868
|
-
formatters.O = function(v) {
|
|
6869
|
-
this.inspectOpts.colors = this.useColors;
|
|
6870
|
-
return util.inspect(v, this.inspectOpts);
|
|
6871
|
-
};
|
|
6872
|
-
}
|
|
6873
|
-
});
|
|
6874
|
-
|
|
6875
|
-
// ../../node_modules/debug/src/index.js
|
|
6876
|
-
var require_src = __commonJS({
|
|
6877
|
-
"../../node_modules/debug/src/index.js"(exports, module) {
|
|
6878
|
-
if (typeof process === "undefined" || process.type === "renderer" || process.browser === true || process.__nwjs) {
|
|
6879
|
-
module.exports = require_browser();
|
|
6880
|
-
} else {
|
|
6881
|
-
module.exports = require_node();
|
|
6882
|
-
}
|
|
6883
|
-
}
|
|
6884
|
-
});
|
|
6885
|
-
|
|
6886
|
-
// ../../node_modules/follow-redirects/debug.js
|
|
6887
|
-
var require_debug = __commonJS({
|
|
6888
|
-
"../../node_modules/follow-redirects/debug.js"(exports, module) {
|
|
6889
|
-
var debug;
|
|
6890
|
-
module.exports = function() {
|
|
6891
|
-
if (!debug) {
|
|
6892
|
-
try {
|
|
6893
|
-
debug = require_src()("follow-redirects");
|
|
6894
|
-
} catch (error) {
|
|
6895
|
-
}
|
|
6896
|
-
if (typeof debug !== "function") {
|
|
6897
|
-
debug = function() {
|
|
6898
|
-
};
|
|
6899
|
-
}
|
|
6900
|
-
}
|
|
6901
|
-
debug.apply(null, arguments);
|
|
6902
|
-
};
|
|
6903
|
-
}
|
|
6904
|
-
});
|
|
6905
|
-
|
|
6906
|
-
// ../../node_modules/follow-redirects/index.js
|
|
6907
|
-
var require_follow_redirects = __commonJS({
|
|
6908
|
-
"../../node_modules/follow-redirects/index.js"(exports, module) {
|
|
6909
|
-
var url = __require("url");
|
|
6910
|
-
var URL2 = url.URL;
|
|
6911
|
-
var http = __require("http");
|
|
6912
|
-
var https = __require("https");
|
|
6913
|
-
var Writable = __require("stream").Writable;
|
|
6914
|
-
var assert = __require("assert");
|
|
6915
|
-
var debug = require_debug();
|
|
6916
|
-
(function detectUnsupportedEnvironment() {
|
|
6917
|
-
var looksLikeNode = typeof process !== "undefined";
|
|
6918
|
-
var looksLikeBrowser = typeof window !== "undefined" && typeof document !== "undefined";
|
|
6919
|
-
var looksLikeV8 = isFunction(Error.captureStackTrace);
|
|
6920
|
-
if (!looksLikeNode && (looksLikeBrowser || !looksLikeV8)) {
|
|
6921
|
-
console.warn("The follow-redirects package should be excluded from browser builds.");
|
|
6922
|
-
}
|
|
6923
|
-
})();
|
|
6924
|
-
var useNativeURL = false;
|
|
6925
|
-
try {
|
|
6926
|
-
assert(new URL2(""));
|
|
6927
|
-
} catch (error) {
|
|
6928
|
-
useNativeURL = error.code === "ERR_INVALID_URL";
|
|
6929
|
-
}
|
|
6930
|
-
var sensitiveHeaders = [
|
|
6931
|
-
"Authorization",
|
|
6932
|
-
"Proxy-Authorization",
|
|
6933
|
-
"Cookie"
|
|
6934
|
-
];
|
|
6935
|
-
var preservedUrlFields = [
|
|
6936
|
-
"auth",
|
|
6937
|
-
"host",
|
|
6938
|
-
"hostname",
|
|
6939
|
-
"href",
|
|
6940
|
-
"path",
|
|
6941
|
-
"pathname",
|
|
6942
|
-
"port",
|
|
6943
|
-
"protocol",
|
|
6944
|
-
"query",
|
|
6945
|
-
"search",
|
|
6946
|
-
"hash"
|
|
6947
|
-
];
|
|
6948
|
-
var events = ["abort", "aborted", "connect", "error", "socket", "timeout"];
|
|
6949
|
-
var eventHandlers = /* @__PURE__ */ Object.create(null);
|
|
6950
|
-
events.forEach(function(event) {
|
|
6951
|
-
eventHandlers[event] = function(arg1, arg2, arg3) {
|
|
6952
|
-
this._redirectable.emit(event, arg1, arg2, arg3);
|
|
6953
|
-
};
|
|
6954
|
-
});
|
|
6955
|
-
var InvalidUrlError = createErrorType(
|
|
6956
|
-
"ERR_INVALID_URL",
|
|
6957
|
-
"Invalid URL",
|
|
6958
|
-
TypeError
|
|
6959
|
-
);
|
|
6960
|
-
var RedirectionError = createErrorType(
|
|
6961
|
-
"ERR_FR_REDIRECTION_FAILURE",
|
|
6962
|
-
"Redirected request failed"
|
|
6963
|
-
);
|
|
6964
|
-
var TooManyRedirectsError = createErrorType(
|
|
6965
|
-
"ERR_FR_TOO_MANY_REDIRECTS",
|
|
6966
|
-
"Maximum number of redirects exceeded",
|
|
6967
|
-
RedirectionError
|
|
6968
|
-
);
|
|
6969
|
-
var MaxBodyLengthExceededError = createErrorType(
|
|
6970
|
-
"ERR_FR_MAX_BODY_LENGTH_EXCEEDED",
|
|
6971
|
-
"Request body larger than maxBodyLength limit"
|
|
6972
|
-
);
|
|
6973
|
-
var WriteAfterEndError = createErrorType(
|
|
6974
|
-
"ERR_STREAM_WRITE_AFTER_END",
|
|
6975
|
-
"write after end"
|
|
6976
|
-
);
|
|
6977
|
-
var destroy = Writable.prototype.destroy || noop;
|
|
6978
|
-
function RedirectableRequest(options, responseCallback) {
|
|
6979
|
-
Writable.call(this);
|
|
6980
|
-
this._sanitizeOptions(options);
|
|
6981
|
-
this._options = options;
|
|
6982
|
-
this._ended = false;
|
|
6983
|
-
this._ending = false;
|
|
6984
|
-
this._redirectCount = 0;
|
|
6985
|
-
this._redirects = [];
|
|
6986
|
-
this._requestBodyLength = 0;
|
|
6987
|
-
this._requestBodyBuffers = [];
|
|
6988
|
-
if (responseCallback) {
|
|
6989
|
-
this.on("response", responseCallback);
|
|
6990
|
-
}
|
|
6991
|
-
var self = this;
|
|
6992
|
-
this._onNativeResponse = function(response) {
|
|
6993
|
-
try {
|
|
6994
|
-
self._processResponse(response);
|
|
6995
|
-
} catch (cause) {
|
|
6996
|
-
self.emit("error", cause instanceof RedirectionError ? cause : new RedirectionError({ cause }));
|
|
6997
|
-
}
|
|
6998
|
-
};
|
|
6999
|
-
this._headerFilter = new RegExp("^(?:" + sensitiveHeaders.concat(options.sensitiveHeaders).map(escapeRegex).join("|") + ")$", "i");
|
|
7000
|
-
this._performRequest();
|
|
7001
|
-
}
|
|
7002
|
-
RedirectableRequest.prototype = Object.create(Writable.prototype);
|
|
7003
|
-
RedirectableRequest.prototype.abort = function() {
|
|
7004
|
-
destroyRequest(this._currentRequest);
|
|
7005
|
-
this._currentRequest.abort();
|
|
7006
|
-
this.emit("abort");
|
|
7007
|
-
};
|
|
7008
|
-
RedirectableRequest.prototype.destroy = function(error) {
|
|
7009
|
-
destroyRequest(this._currentRequest, error);
|
|
7010
|
-
destroy.call(this, error);
|
|
7011
|
-
return this;
|
|
7012
|
-
};
|
|
7013
|
-
RedirectableRequest.prototype.write = function(data, encoding, callback) {
|
|
7014
|
-
if (this._ending) {
|
|
7015
|
-
throw new WriteAfterEndError();
|
|
7016
|
-
}
|
|
7017
|
-
if (!isString(data) && !isBuffer(data)) {
|
|
7018
|
-
throw new TypeError("data should be a string, Buffer or Uint8Array");
|
|
7019
|
-
}
|
|
7020
|
-
if (isFunction(encoding)) {
|
|
7021
|
-
callback = encoding;
|
|
7022
|
-
encoding = null;
|
|
7023
|
-
}
|
|
7024
|
-
if (data.length === 0) {
|
|
7025
|
-
if (callback) {
|
|
7026
|
-
callback();
|
|
7027
|
-
}
|
|
7028
|
-
return;
|
|
7029
|
-
}
|
|
7030
|
-
if (this._requestBodyLength + data.length <= this._options.maxBodyLength) {
|
|
7031
|
-
this._requestBodyLength += data.length;
|
|
7032
|
-
this._requestBodyBuffers.push({ data, encoding });
|
|
7033
|
-
this._currentRequest.write(data, encoding, callback);
|
|
7034
|
-
} else {
|
|
7035
|
-
this.emit("error", new MaxBodyLengthExceededError());
|
|
7036
|
-
this.abort();
|
|
7037
|
-
}
|
|
7038
|
-
};
|
|
7039
|
-
RedirectableRequest.prototype.end = function(data, encoding, callback) {
|
|
7040
|
-
if (isFunction(data)) {
|
|
7041
|
-
callback = data;
|
|
7042
|
-
data = encoding = null;
|
|
7043
|
-
} else if (isFunction(encoding)) {
|
|
7044
|
-
callback = encoding;
|
|
7045
|
-
encoding = null;
|
|
7046
|
-
}
|
|
7047
|
-
if (!data) {
|
|
7048
|
-
this._ended = this._ending = true;
|
|
7049
|
-
this._currentRequest.end(null, null, callback);
|
|
7050
|
-
} else {
|
|
7051
|
-
var self = this;
|
|
7052
|
-
var currentRequest = this._currentRequest;
|
|
7053
|
-
this.write(data, encoding, function() {
|
|
7054
|
-
self._ended = true;
|
|
7055
|
-
currentRequest.end(null, null, callback);
|
|
7056
|
-
});
|
|
7057
|
-
this._ending = true;
|
|
7058
|
-
}
|
|
7059
|
-
};
|
|
7060
|
-
RedirectableRequest.prototype.setHeader = function(name, value) {
|
|
7061
|
-
this._options.headers[name] = value;
|
|
7062
|
-
this._currentRequest.setHeader(name, value);
|
|
7063
|
-
};
|
|
7064
|
-
RedirectableRequest.prototype.removeHeader = function(name) {
|
|
7065
|
-
delete this._options.headers[name];
|
|
7066
|
-
this._currentRequest.removeHeader(name);
|
|
7067
|
-
};
|
|
7068
|
-
RedirectableRequest.prototype.setTimeout = function(msecs, callback) {
|
|
7069
|
-
var self = this;
|
|
7070
|
-
function destroyOnTimeout(socket) {
|
|
7071
|
-
socket.setTimeout(msecs);
|
|
7072
|
-
socket.removeListener("timeout", socket.destroy);
|
|
7073
|
-
socket.addListener("timeout", socket.destroy);
|
|
7074
|
-
}
|
|
7075
|
-
function startTimer(socket) {
|
|
7076
|
-
if (self._timeout) {
|
|
7077
|
-
clearTimeout(self._timeout);
|
|
7078
|
-
}
|
|
7079
|
-
self._timeout = setTimeout(function() {
|
|
7080
|
-
self.emit("timeout");
|
|
7081
|
-
clearTimer();
|
|
7082
|
-
}, msecs);
|
|
7083
|
-
destroyOnTimeout(socket);
|
|
7084
|
-
}
|
|
7085
|
-
function clearTimer() {
|
|
7086
|
-
if (self._timeout) {
|
|
7087
|
-
clearTimeout(self._timeout);
|
|
7088
|
-
self._timeout = null;
|
|
7089
|
-
}
|
|
7090
|
-
self.removeListener("abort", clearTimer);
|
|
7091
|
-
self.removeListener("error", clearTimer);
|
|
7092
|
-
self.removeListener("response", clearTimer);
|
|
7093
|
-
self.removeListener("close", clearTimer);
|
|
7094
|
-
if (callback) {
|
|
7095
|
-
self.removeListener("timeout", callback);
|
|
7096
|
-
}
|
|
7097
|
-
if (!self.socket) {
|
|
7098
|
-
self._currentRequest.removeListener("socket", startTimer);
|
|
7099
|
-
}
|
|
7100
|
-
}
|
|
7101
|
-
if (callback) {
|
|
7102
|
-
this.on("timeout", callback);
|
|
7103
|
-
}
|
|
7104
|
-
if (this.socket) {
|
|
7105
|
-
startTimer(this.socket);
|
|
7106
|
-
} else {
|
|
7107
|
-
this._currentRequest.once("socket", startTimer);
|
|
7108
|
-
}
|
|
7109
|
-
this.on("socket", destroyOnTimeout);
|
|
7110
|
-
this.on("abort", clearTimer);
|
|
7111
|
-
this.on("error", clearTimer);
|
|
7112
|
-
this.on("response", clearTimer);
|
|
7113
|
-
this.on("close", clearTimer);
|
|
7114
|
-
return this;
|
|
7115
|
-
};
|
|
7116
|
-
[
|
|
7117
|
-
"flushHeaders",
|
|
7118
|
-
"getHeader",
|
|
7119
|
-
"setNoDelay",
|
|
7120
|
-
"setSocketKeepAlive"
|
|
7121
|
-
].forEach(function(method) {
|
|
7122
|
-
RedirectableRequest.prototype[method] = function(a, b) {
|
|
7123
|
-
return this._currentRequest[method](a, b);
|
|
7124
|
-
};
|
|
7125
|
-
});
|
|
7126
|
-
["aborted", "connection", "socket"].forEach(function(property) {
|
|
7127
|
-
Object.defineProperty(RedirectableRequest.prototype, property, {
|
|
7128
|
-
get: function() {
|
|
7129
|
-
return this._currentRequest[property];
|
|
7130
|
-
}
|
|
7131
|
-
});
|
|
7132
|
-
});
|
|
7133
|
-
RedirectableRequest.prototype._sanitizeOptions = function(options) {
|
|
7134
|
-
if (!options.headers) {
|
|
7135
|
-
options.headers = {};
|
|
7136
|
-
}
|
|
7137
|
-
if (!isArray(options.sensitiveHeaders)) {
|
|
7138
|
-
options.sensitiveHeaders = [];
|
|
7139
|
-
}
|
|
7140
|
-
if (options.host) {
|
|
7141
|
-
if (!options.hostname) {
|
|
7142
|
-
options.hostname = options.host;
|
|
7143
|
-
}
|
|
7144
|
-
delete options.host;
|
|
7145
|
-
}
|
|
7146
|
-
if (!options.pathname && options.path) {
|
|
7147
|
-
var searchPos = options.path.indexOf("?");
|
|
7148
|
-
if (searchPos < 0) {
|
|
7149
|
-
options.pathname = options.path;
|
|
7150
|
-
} else {
|
|
7151
|
-
options.pathname = options.path.substring(0, searchPos);
|
|
7152
|
-
options.search = options.path.substring(searchPos);
|
|
7153
|
-
}
|
|
7154
|
-
}
|
|
7155
|
-
};
|
|
7156
|
-
RedirectableRequest.prototype._performRequest = function() {
|
|
7157
|
-
var protocol = this._options.protocol;
|
|
7158
|
-
var nativeProtocol = this._options.nativeProtocols[protocol];
|
|
7159
|
-
if (!nativeProtocol) {
|
|
7160
|
-
throw new TypeError("Unsupported protocol " + protocol);
|
|
7161
|
-
}
|
|
7162
|
-
if (this._options.agents) {
|
|
7163
|
-
var scheme = protocol.slice(0, -1);
|
|
7164
|
-
this._options.agent = this._options.agents[scheme];
|
|
7165
|
-
}
|
|
7166
|
-
var request = this._currentRequest = nativeProtocol.request(this._options, this._onNativeResponse);
|
|
7167
|
-
request._redirectable = this;
|
|
7168
|
-
for (var event of events) {
|
|
7169
|
-
request.on(event, eventHandlers[event]);
|
|
7170
|
-
}
|
|
7171
|
-
this._currentUrl = /^\//.test(this._options.path) ? url.format(this._options) : (
|
|
7172
|
-
// When making a request to a proxy, […]
|
|
7173
|
-
// a client MUST send the target URI in absolute-form […].
|
|
7174
|
-
this._options.path
|
|
7175
|
-
);
|
|
7176
|
-
if (this._isRedirect) {
|
|
7177
|
-
var i = 0;
|
|
7178
|
-
var self = this;
|
|
7179
|
-
var buffers = this._requestBodyBuffers;
|
|
7180
|
-
(function writeNext(error) {
|
|
7181
|
-
if (request === self._currentRequest) {
|
|
7182
|
-
if (error) {
|
|
7183
|
-
self.emit("error", error);
|
|
7184
|
-
} else if (i < buffers.length) {
|
|
7185
|
-
var buffer = buffers[i++];
|
|
7186
|
-
if (!request.finished) {
|
|
7187
|
-
request.write(buffer.data, buffer.encoding, writeNext);
|
|
7188
|
-
}
|
|
7189
|
-
} else if (self._ended) {
|
|
7190
|
-
request.end();
|
|
7191
|
-
}
|
|
7192
|
-
}
|
|
7193
|
-
})();
|
|
7194
|
-
}
|
|
7195
|
-
};
|
|
7196
|
-
RedirectableRequest.prototype._processResponse = function(response) {
|
|
7197
|
-
var statusCode = response.statusCode;
|
|
7198
|
-
if (this._options.trackRedirects) {
|
|
7199
|
-
this._redirects.push({
|
|
7200
|
-
url: this._currentUrl,
|
|
7201
|
-
headers: response.headers,
|
|
7202
|
-
statusCode
|
|
7203
|
-
});
|
|
7204
|
-
}
|
|
7205
|
-
var location = response.headers.location;
|
|
7206
|
-
if (!location || this._options.followRedirects === false || statusCode < 300 || statusCode >= 400) {
|
|
7207
|
-
response.responseUrl = this._currentUrl;
|
|
7208
|
-
response.redirects = this._redirects;
|
|
7209
|
-
this.emit("response", response);
|
|
7210
|
-
this._requestBodyBuffers = [];
|
|
7211
|
-
return;
|
|
7212
|
-
}
|
|
7213
|
-
destroyRequest(this._currentRequest);
|
|
7214
|
-
response.destroy();
|
|
7215
|
-
if (++this._redirectCount > this._options.maxRedirects) {
|
|
7216
|
-
throw new TooManyRedirectsError();
|
|
7217
|
-
}
|
|
7218
|
-
var requestHeaders;
|
|
7219
|
-
var beforeRedirect = this._options.beforeRedirect;
|
|
7220
|
-
if (beforeRedirect) {
|
|
7221
|
-
requestHeaders = Object.assign({
|
|
7222
|
-
// The Host header was set by nativeProtocol.request
|
|
7223
|
-
Host: response.req.getHeader("host")
|
|
7224
|
-
}, this._options.headers);
|
|
7225
|
-
}
|
|
7226
|
-
var method = this._options.method;
|
|
7227
|
-
if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" || // RFC7231§6.4.4: The 303 (See Other) status code indicates that
|
|
7228
|
-
// the server is redirecting the user agent to a different resource […]
|
|
7229
|
-
// A user agent can perform a retrieval request targeting that URI
|
|
7230
|
-
// (a GET or HEAD request if using HTTP) […]
|
|
7231
|
-
statusCode === 303 && !/^(?:GET|HEAD)$/.test(this._options.method)) {
|
|
7232
|
-
this._options.method = "GET";
|
|
7233
|
-
this._requestBodyBuffers = [];
|
|
7234
|
-
removeMatchingHeaders(/^content-/i, this._options.headers);
|
|
7235
|
-
}
|
|
7236
|
-
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
|
|
7237
|
-
var currentUrlParts = parseUrl(this._currentUrl);
|
|
7238
|
-
var currentHost = currentHostHeader || currentUrlParts.host;
|
|
7239
|
-
var currentUrl = /^\w+:/.test(location) ? this._currentUrl : url.format(Object.assign(currentUrlParts, { host: currentHost }));
|
|
7240
|
-
var redirectUrl = resolveUrl(location, currentUrl);
|
|
7241
|
-
debug("redirecting to", redirectUrl.href);
|
|
7242
|
-
this._isRedirect = true;
|
|
7243
|
-
spreadUrlObject(redirectUrl, this._options);
|
|
7244
|
-
if (redirectUrl.protocol !== currentUrlParts.protocol && redirectUrl.protocol !== "https:" || redirectUrl.host !== currentHost && !isSubdomain(redirectUrl.host, currentHost)) {
|
|
7245
|
-
removeMatchingHeaders(this._headerFilter, this._options.headers);
|
|
7246
|
-
}
|
|
7247
|
-
if (isFunction(beforeRedirect)) {
|
|
7248
|
-
var responseDetails = {
|
|
7249
|
-
headers: response.headers,
|
|
7250
|
-
statusCode
|
|
7251
|
-
};
|
|
7252
|
-
var requestDetails = {
|
|
7253
|
-
url: currentUrl,
|
|
7254
|
-
method,
|
|
7255
|
-
headers: requestHeaders
|
|
7256
|
-
};
|
|
7257
|
-
beforeRedirect(this._options, responseDetails, requestDetails);
|
|
7258
|
-
this._sanitizeOptions(this._options);
|
|
7259
|
-
}
|
|
7260
|
-
this._performRequest();
|
|
7261
|
-
};
|
|
7262
|
-
function wrap(protocols) {
|
|
7263
|
-
var exports2 = {
|
|
7264
|
-
maxRedirects: 21,
|
|
7265
|
-
maxBodyLength: 10 * 1024 * 1024
|
|
7266
|
-
};
|
|
7267
|
-
var nativeProtocols = {};
|
|
7268
|
-
Object.keys(protocols).forEach(function(scheme) {
|
|
7269
|
-
var protocol = scheme + ":";
|
|
7270
|
-
var nativeProtocol = nativeProtocols[protocol] = protocols[scheme];
|
|
7271
|
-
var wrappedProtocol = exports2[scheme] = Object.create(nativeProtocol);
|
|
7272
|
-
function request(input, options, callback) {
|
|
7273
|
-
if (isURL(input)) {
|
|
7274
|
-
input = spreadUrlObject(input);
|
|
7275
|
-
} else if (isString(input)) {
|
|
7276
|
-
input = spreadUrlObject(parseUrl(input));
|
|
7277
|
-
} else {
|
|
7278
|
-
callback = options;
|
|
7279
|
-
options = validateUrl(input);
|
|
7280
|
-
input = { protocol };
|
|
7281
|
-
}
|
|
7282
|
-
if (isFunction(options)) {
|
|
7283
|
-
callback = options;
|
|
7284
|
-
options = null;
|
|
7285
|
-
}
|
|
7286
|
-
options = Object.assign({
|
|
7287
|
-
maxRedirects: exports2.maxRedirects,
|
|
7288
|
-
maxBodyLength: exports2.maxBodyLength
|
|
7289
|
-
}, input, options);
|
|
7290
|
-
options.nativeProtocols = nativeProtocols;
|
|
7291
|
-
if (!isString(options.host) && !isString(options.hostname)) {
|
|
7292
|
-
options.hostname = "::1";
|
|
7293
|
-
}
|
|
7294
|
-
assert.equal(options.protocol, protocol, "protocol mismatch");
|
|
7295
|
-
debug("options", options);
|
|
7296
|
-
return new RedirectableRequest(options, callback);
|
|
7297
|
-
}
|
|
7298
|
-
function get(input, options, callback) {
|
|
7299
|
-
var wrappedRequest = wrappedProtocol.request(input, options, callback);
|
|
7300
|
-
wrappedRequest.end();
|
|
7301
|
-
return wrappedRequest;
|
|
7302
|
-
}
|
|
7303
|
-
Object.defineProperties(wrappedProtocol, {
|
|
7304
|
-
request: { value: request, configurable: true, enumerable: true, writable: true },
|
|
7305
|
-
get: { value: get, configurable: true, enumerable: true, writable: true }
|
|
7306
|
-
});
|
|
7307
|
-
});
|
|
7308
|
-
return exports2;
|
|
7309
|
-
}
|
|
7310
|
-
function noop() {
|
|
7311
|
-
}
|
|
7312
|
-
function parseUrl(input) {
|
|
7313
|
-
var parsed;
|
|
7314
|
-
if (useNativeURL) {
|
|
7315
|
-
parsed = new URL2(input);
|
|
7316
|
-
} else {
|
|
7317
|
-
parsed = validateUrl(url.parse(input));
|
|
7318
|
-
if (!isString(parsed.protocol)) {
|
|
7319
|
-
throw new InvalidUrlError({ input });
|
|
7320
|
-
}
|
|
7321
|
-
}
|
|
7322
|
-
return parsed;
|
|
7323
|
-
}
|
|
7324
|
-
function resolveUrl(relative, base) {
|
|
7325
|
-
return useNativeURL ? new URL2(relative, base) : parseUrl(url.resolve(base, relative));
|
|
7326
|
-
}
|
|
7327
|
-
function validateUrl(input) {
|
|
7328
|
-
if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) {
|
|
7329
|
-
throw new InvalidUrlError({ input: input.href || input });
|
|
7330
|
-
}
|
|
7331
|
-
if (/^\[/.test(input.host) && !/^\[[:0-9a-f]+\](:\d+)?$/i.test(input.host)) {
|
|
7332
|
-
throw new InvalidUrlError({ input: input.href || input });
|
|
7333
|
-
}
|
|
7334
|
-
return input;
|
|
6293
|
+
let totalOut = 0;
|
|
6294
|
+
let cachedTokensEstimate = 0;
|
|
6295
|
+
for (const r of results) {
|
|
6296
|
+
allIssues.push(...r.issues);
|
|
6297
|
+
if (r.pass) {
|
|
6298
|
+
passCategories.push(r.criterion);
|
|
7335
6299
|
}
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
6300
|
+
totalIn += r.tokens.in;
|
|
6301
|
+
totalOut += r.tokens.out;
|
|
6302
|
+
}
|
|
6303
|
+
const firstResult = results[0];
|
|
6304
|
+
if (firstResult && firstResult.tokens.in > 0) {
|
|
6305
|
+
cachedTokensEstimate = firstResult.tokens.in * (totalCriteriaCount - 1);
|
|
6306
|
+
}
|
|
6307
|
+
const wallMs = Date.now() - evalStart;
|
|
6308
|
+
for (const r of results) {
|
|
6309
|
+
const issueCount = r.issues.length;
|
|
6310
|
+
const status = r.pass ? "PASS" : r.tier === 1 ? "FAIL" : r.issues.some((i) => i.result === "fail") ? "FAIL" : "WARN";
|
|
6311
|
+
const issueLabel = issueCount > 0 ? ` (${issueCount} issue${issueCount > 1 ? "s" : ""})` : "";
|
|
6312
|
+
console.log(`[eval] ${r.criterion}: ${status}${issueLabel} ${(r.durationMs / 1e3).toFixed(1)}s`);
|
|
6313
|
+
}
|
|
6314
|
+
console.log(
|
|
6315
|
+
`[eval] total: ${(wallMs / 1e3).toFixed(1)}s wall (${totalCriteriaCount} parallel) | in=${totalIn} out=${totalOut} cached~=${cachedTokensEstimate} | issues=${allIssues.length} pass=${passCategories.length}`
|
|
6316
|
+
);
|
|
6317
|
+
return {
|
|
6318
|
+
issues: allIssues,
|
|
6319
|
+
pass: passCategories,
|
|
6320
|
+
inputTokens: totalIn,
|
|
6321
|
+
outputTokens: totalOut
|
|
6322
|
+
};
|
|
6323
|
+
}
|
|
6324
|
+
var TIER_1_CRITERIA, TIER_2_CRITERIA, TIER_1_CATEGORIES, TIER_2_CATEGORIES, VALID_CATEGORIES;
|
|
6325
|
+
var init_llm_evaluator = __esm({
|
|
6326
|
+
"src/evaluation/llm-evaluator.ts"() {
|
|
6327
|
+
init_llm_router();
|
|
6328
|
+
init_types_public();
|
|
6329
|
+
TIER_1_CRITERIA = ["functionality", "crash"];
|
|
6330
|
+
TIER_2_CRITERIA = ["interactivity", "accessibility", "layout", "loading", "visual"];
|
|
6331
|
+
TIER_1_CATEGORIES = /* @__PURE__ */ new Set(["functionality", "crash"]);
|
|
6332
|
+
TIER_2_CATEGORIES = /* @__PURE__ */ new Set([
|
|
6333
|
+
"interactivity",
|
|
6334
|
+
"accessibility",
|
|
6335
|
+
"layout",
|
|
6336
|
+
"loading",
|
|
6337
|
+
"visual"
|
|
6338
|
+
]);
|
|
6339
|
+
VALID_CATEGORIES = /* @__PURE__ */ new Set([
|
|
6340
|
+
...TIER_1_CATEGORIES,
|
|
6341
|
+
...TIER_2_CATEGORIES
|
|
6342
|
+
]);
|
|
6343
|
+
}
|
|
6344
|
+
});
|
|
6345
|
+
|
|
6346
|
+
// src/evaluation/cost-tracker.ts
|
|
6347
|
+
var cost_tracker_exports = {};
|
|
6348
|
+
__export(cost_tracker_exports, {
|
|
6349
|
+
CostTracker: () => CostTracker,
|
|
6350
|
+
pricePer1k: () => pricePer1k
|
|
6351
|
+
});
|
|
6352
|
+
function resolveRegistryId(model) {
|
|
6353
|
+
const keys = Object.keys(MODEL_REGISTRY);
|
|
6354
|
+
if (keys.includes(model)) return model;
|
|
6355
|
+
const bySuffix = keys.find((id) => id.endsWith(`/${model}`));
|
|
6356
|
+
if (bySuffix) return bySuffix;
|
|
6357
|
+
const undated = model.replace(/-\d{8}$/, "");
|
|
6358
|
+
return keys.find((id) => id.endsWith(`/${undated}`)) ?? null;
|
|
6359
|
+
}
|
|
6360
|
+
function pricePer1k(model) {
|
|
6361
|
+
const id = resolveRegistryId(model);
|
|
6362
|
+
if (id === null) return FALLBACK_PER_1K;
|
|
6363
|
+
const { costs } = MODEL_REGISTRY[id];
|
|
6364
|
+
return { input: costs.inputPer1M / 1e3, output: costs.outputPer1M / 1e3 };
|
|
6365
|
+
}
|
|
6366
|
+
var FALLBACK_PER_1K, CostTracker;
|
|
6367
|
+
var init_cost_tracker = __esm({
|
|
6368
|
+
"src/evaluation/cost-tracker.ts"() {
|
|
6369
|
+
FALLBACK_PER_1K = { input: 3e-3, output: 0.015 };
|
|
6370
|
+
CostTracker = class {
|
|
6371
|
+
constructor(maxBudget) {
|
|
6372
|
+
this.maxBudget = maxBudget;
|
|
7343
6373
|
}
|
|
7344
|
-
|
|
7345
|
-
|
|
6374
|
+
maxBudget;
|
|
6375
|
+
totalCost = 0;
|
|
6376
|
+
record(model, inputTokens, outputTokens) {
|
|
6377
|
+
const prices = pricePer1k(model);
|
|
6378
|
+
const cost = inputTokens / 1e3 * prices.input + outputTokens / 1e3 * prices.output;
|
|
6379
|
+
this.totalCost += cost;
|
|
6380
|
+
return cost;
|
|
7346
6381
|
}
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
function removeMatchingHeaders(regex, headers) {
|
|
7351
|
-
var lastValue;
|
|
7352
|
-
for (var header in headers) {
|
|
7353
|
-
if (regex.test(header)) {
|
|
7354
|
-
lastValue = headers[header];
|
|
7355
|
-
delete headers[header];
|
|
7356
|
-
}
|
|
6382
|
+
canContinue() {
|
|
6383
|
+
if (this.maxBudget === null) return true;
|
|
6384
|
+
return this.totalCost < this.maxBudget;
|
|
7357
6385
|
}
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
function createErrorType(code, message, baseClass) {
|
|
7361
|
-
function CustomError(properties) {
|
|
7362
|
-
if (isFunction(Error.captureStackTrace)) {
|
|
7363
|
-
Error.captureStackTrace(this, this.constructor);
|
|
7364
|
-
}
|
|
7365
|
-
Object.assign(this, properties || {});
|
|
7366
|
-
this.code = code;
|
|
7367
|
-
this.message = this.cause ? message + ": " + this.cause.message : message;
|
|
6386
|
+
getTotal() {
|
|
6387
|
+
return this.totalCost;
|
|
7368
6388
|
}
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
value: CustomError,
|
|
7373
|
-
enumerable: false
|
|
7374
|
-
},
|
|
7375
|
-
name: {
|
|
7376
|
-
value: "Error [" + code + "]",
|
|
7377
|
-
enumerable: false
|
|
7378
|
-
}
|
|
7379
|
-
});
|
|
7380
|
-
return CustomError;
|
|
7381
|
-
}
|
|
7382
|
-
function destroyRequest(request, error) {
|
|
7383
|
-
for (var event of events) {
|
|
7384
|
-
request.removeListener(event, eventHandlers[event]);
|
|
6389
|
+
getRemaining() {
|
|
6390
|
+
if (this.maxBudget === null) return null;
|
|
6391
|
+
return Math.max(0, this.maxBudget - this.totalCost);
|
|
7385
6392
|
}
|
|
7386
|
-
|
|
7387
|
-
request.destroy(error);
|
|
7388
|
-
}
|
|
7389
|
-
function isSubdomain(subdomain, domain) {
|
|
7390
|
-
assert(isString(subdomain) && isString(domain));
|
|
7391
|
-
var dot = subdomain.length - domain.length - 1;
|
|
7392
|
-
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
|
|
7393
|
-
}
|
|
7394
|
-
function isArray(value) {
|
|
7395
|
-
return value instanceof Array;
|
|
7396
|
-
}
|
|
7397
|
-
function isString(value) {
|
|
7398
|
-
return typeof value === "string" || value instanceof String;
|
|
7399
|
-
}
|
|
7400
|
-
function isFunction(value) {
|
|
7401
|
-
return typeof value === "function";
|
|
7402
|
-
}
|
|
7403
|
-
function isBuffer(value) {
|
|
7404
|
-
return typeof value === "object" && "length" in value;
|
|
7405
|
-
}
|
|
7406
|
-
function isURL(value) {
|
|
7407
|
-
return URL2 && value instanceof URL2;
|
|
7408
|
-
}
|
|
7409
|
-
function escapeRegex(regex) {
|
|
7410
|
-
return regex.replace(/[\]\\/()*+?.$]/g, "\\$&");
|
|
7411
|
-
}
|
|
7412
|
-
module.exports = wrap({ http, https });
|
|
7413
|
-
module.exports.wrap = wrap;
|
|
6393
|
+
};
|
|
7414
6394
|
}
|
|
7415
6395
|
});
|
|
7416
6396
|
|
|
@@ -8539,7 +7519,7 @@ var require_streamx = __commonJS({
|
|
|
8539
7519
|
}
|
|
8540
7520
|
}
|
|
8541
7521
|
};
|
|
8542
|
-
var
|
|
7522
|
+
var Readable2 = class _Readable extends Stream {
|
|
8543
7523
|
constructor(opts) {
|
|
8544
7524
|
super(opts);
|
|
8545
7525
|
this._duplexState |= OPENING | WRITE_DONE | READ_READ_AHEAD;
|
|
@@ -8556,7 +7536,7 @@ var require_streamx = __commonJS({
|
|
|
8556
7536
|
fn().then((src) => {
|
|
8557
7537
|
if (src === null) return out.end();
|
|
8558
7538
|
if (out.destroying) return;
|
|
8559
|
-
|
|
7539
|
+
pipeline2(src, out, noop);
|
|
8560
7540
|
}).catch((err) => out.destroy(err));
|
|
8561
7541
|
return out;
|
|
8562
7542
|
}
|
|
@@ -8750,7 +7730,7 @@ var require_streamx = __commonJS({
|
|
|
8750
7730
|
return this;
|
|
8751
7731
|
}
|
|
8752
7732
|
};
|
|
8753
|
-
var Duplex = class extends
|
|
7733
|
+
var Duplex = class extends Readable2 {
|
|
8754
7734
|
// and Writable
|
|
8755
7735
|
constructor(opts) {
|
|
8756
7736
|
super(opts);
|
|
@@ -8843,13 +7823,13 @@ var require_streamx = __commonJS({
|
|
|
8843
7823
|
}
|
|
8844
7824
|
function pipelinePromise(...streams) {
|
|
8845
7825
|
return new Promise((resolve3, reject) => {
|
|
8846
|
-
return
|
|
7826
|
+
return pipeline2(...streams, (err) => {
|
|
8847
7827
|
if (err) return reject(err);
|
|
8848
7828
|
resolve3();
|
|
8849
7829
|
});
|
|
8850
7830
|
});
|
|
8851
7831
|
}
|
|
8852
|
-
function
|
|
7832
|
+
function pipeline2(stream, ...streams) {
|
|
8853
7833
|
const all = Array.isArray(stream) ? [...stream, ...streams] : [stream, ...streams];
|
|
8854
7834
|
const done = all.length && typeof all[all.length - 1] === "function" ? all.pop() : null;
|
|
8855
7835
|
if (all.length < 2) throw StreamError.BAD_ARGUMENT("Pipeline requires at least 2 streams");
|
|
@@ -8947,7 +7927,7 @@ var require_streamx = __commonJS({
|
|
|
8947
7927
|
return s._writev !== Writable.prototype._writev && s._writev !== Duplex.prototype._writev;
|
|
8948
7928
|
}
|
|
8949
7929
|
module.exports = {
|
|
8950
|
-
pipeline,
|
|
7930
|
+
pipeline: pipeline2,
|
|
8951
7931
|
pipelinePromise,
|
|
8952
7932
|
isStream,
|
|
8953
7933
|
isStreamx,
|
|
@@ -8959,7 +7939,7 @@ var require_streamx = __commonJS({
|
|
|
8959
7939
|
getStreamError,
|
|
8960
7940
|
Stream,
|
|
8961
7941
|
Writable,
|
|
8962
|
-
Readable,
|
|
7942
|
+
Readable: Readable2,
|
|
8963
7943
|
Duplex,
|
|
8964
7944
|
Transform,
|
|
8965
7945
|
// Export PassThrough for compatibility with Node.js core's stream module
|
|
@@ -8968,9 +7948,9 @@ var require_streamx = __commonJS({
|
|
|
8968
7948
|
}
|
|
8969
7949
|
});
|
|
8970
7950
|
|
|
8971
|
-
// ../../node_modules/
|
|
7951
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/headers.js
|
|
8972
7952
|
var require_headers = __commonJS({
|
|
8973
|
-
"../../node_modules/
|
|
7953
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/headers.js"(exports) {
|
|
8974
7954
|
var b4a = require_b4a();
|
|
8975
7955
|
var ZEROS = "0000000000000000000";
|
|
8976
7956
|
var SEVENS = "7777777777777777777";
|
|
@@ -9228,10 +8208,10 @@ var require_headers = __commonJS({
|
|
|
9228
8208
|
}
|
|
9229
8209
|
});
|
|
9230
8210
|
|
|
9231
|
-
// ../../node_modules/
|
|
8211
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/extract.js
|
|
9232
8212
|
var require_extract = __commonJS({
|
|
9233
|
-
"../../node_modules/
|
|
9234
|
-
var { Writable, Readable, getStreamError } = require_streamx();
|
|
8213
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/extract.js"(exports, module) {
|
|
8214
|
+
var { Writable, Readable: Readable2, getStreamError } = require_streamx();
|
|
9235
8215
|
var FIFO = require_fast_fifo();
|
|
9236
8216
|
var b4a = require_b4a();
|
|
9237
8217
|
var headers = require_headers();
|
|
@@ -9278,7 +8258,7 @@ var require_extract = __commonJS({
|
|
|
9278
8258
|
return buf.subarray(this._offset, this._offset += size);
|
|
9279
8259
|
}
|
|
9280
8260
|
};
|
|
9281
|
-
var Source = class extends
|
|
8261
|
+
var Source = class extends Readable2 {
|
|
9282
8262
|
constructor(self, header, offset) {
|
|
9283
8263
|
super();
|
|
9284
8264
|
this.header = header;
|
|
@@ -9562,9 +8542,9 @@ var require_extract = __commonJS({
|
|
|
9562
8542
|
}
|
|
9563
8543
|
});
|
|
9564
8544
|
|
|
9565
|
-
// ../../node_modules/
|
|
8545
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/constants.js
|
|
9566
8546
|
var require_constants = __commonJS({
|
|
9567
|
-
"../../node_modules/
|
|
8547
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/constants.js"(exports, module) {
|
|
9568
8548
|
var constants = {
|
|
9569
8549
|
// just for envs without fs
|
|
9570
8550
|
S_IFMT: 61440,
|
|
@@ -9582,10 +8562,10 @@ var require_constants = __commonJS({
|
|
|
9582
8562
|
}
|
|
9583
8563
|
});
|
|
9584
8564
|
|
|
9585
|
-
// ../../node_modules/
|
|
8565
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/pack.js
|
|
9586
8566
|
var require_pack = __commonJS({
|
|
9587
|
-
"../../node_modules/
|
|
9588
|
-
var { Readable, Writable, getStreamError } = require_streamx();
|
|
8567
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/pack.js"(exports, module) {
|
|
8568
|
+
var { Readable: Readable2, Writable, getStreamError } = require_streamx();
|
|
9589
8569
|
var b4a = require_b4a();
|
|
9590
8570
|
var constants = require_constants();
|
|
9591
8571
|
var headers = require_headers();
|
|
@@ -9678,7 +8658,7 @@ var require_pack = __commonJS({
|
|
|
9678
8658
|
cb();
|
|
9679
8659
|
}
|
|
9680
8660
|
};
|
|
9681
|
-
var Pack = class extends
|
|
8661
|
+
var Pack = class extends Readable2 {
|
|
9682
8662
|
constructor(opts) {
|
|
9683
8663
|
super(opts);
|
|
9684
8664
|
this._drain = noop;
|
|
@@ -9816,9 +8796,9 @@ var require_pack = __commonJS({
|
|
|
9816
8796
|
}
|
|
9817
8797
|
});
|
|
9818
8798
|
|
|
9819
|
-
// ../../node_modules/
|
|
8799
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/index.js
|
|
9820
8800
|
var require_tar_stream = __commonJS({
|
|
9821
|
-
"../../node_modules/
|
|
8801
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/index.js"(exports) {
|
|
9822
8802
|
exports.extract = require_extract();
|
|
9823
8803
|
exports.pack = require_pack();
|
|
9824
8804
|
}
|
|
@@ -10056,9 +9036,9 @@ var require_pump = __commonJS({
|
|
|
10056
9036
|
}
|
|
10057
9037
|
});
|
|
10058
9038
|
|
|
10059
|
-
// ../../node_modules/tar-fs/index.js
|
|
9039
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-fs/index.js
|
|
10060
9040
|
var require_tar_fs = __commonJS({
|
|
10061
|
-
"../../node_modules/tar-fs/index.js"(exports) {
|
|
9041
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-fs/index.js"(exports) {
|
|
10062
9042
|
var tar = require_tar_stream();
|
|
10063
9043
|
var pump = require_pump();
|
|
10064
9044
|
var fs2 = __require("fs");
|
|
@@ -10384,10 +9364,9 @@ var require_tar_fs = __commonJS({
|
|
|
10384
9364
|
}
|
|
10385
9365
|
}
|
|
10386
9366
|
});
|
|
10387
|
-
var
|
|
9367
|
+
var import_tar_fs, setupLambdaEnvironment, isValidUrl, isRunningInAmazonLinux2023, downloadAndExtract;
|
|
10388
9368
|
var init_helper = __esm({
|
|
10389
|
-
"../../node_modules/@sparticuz/chromium/build/
|
|
10390
|
-
import_follow_redirects = __toESM(require_follow_redirects());
|
|
9369
|
+
"../../node_modules/@sparticuz/chromium/build/helper.js"() {
|
|
10391
9370
|
import_tar_fs = __toESM(require_tar_fs());
|
|
10392
9371
|
setupLambdaEnvironment = (baseLibPath) => {
|
|
10393
9372
|
process.env["FONTCONFIG_PATH"] ??= join(tmpdir(), "fonts");
|
|
@@ -10403,7 +9382,13 @@ var init_helper = __esm({
|
|
|
10403
9382
|
};
|
|
10404
9383
|
isValidUrl = (input) => {
|
|
10405
9384
|
try {
|
|
10406
|
-
|
|
9385
|
+
const url = new URL(input);
|
|
9386
|
+
if (url.protocol === "https:")
|
|
9387
|
+
return true;
|
|
9388
|
+
if (url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]")) {
|
|
9389
|
+
return true;
|
|
9390
|
+
}
|
|
9391
|
+
return false;
|
|
10407
9392
|
} catch {
|
|
10408
9393
|
return false;
|
|
10409
9394
|
}
|
|
@@ -10421,43 +9406,41 @@ var init_helper = __esm({
|
|
|
10421
9406
|
return false;
|
|
10422
9407
|
};
|
|
10423
9408
|
downloadAndExtract = async (url) => {
|
|
10424
|
-
const getOptions = new URL(url);
|
|
10425
|
-
getOptions.maxBodyLength = 60 * 1024 * 1024;
|
|
10426
9409
|
const destDir = join(tmpdir(), "chromium-pack");
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
9410
|
+
const response = await fetch(url, {
|
|
9411
|
+
redirect: "follow",
|
|
9412
|
+
signal: AbortSignal.timeout(3e5)
|
|
9413
|
+
});
|
|
9414
|
+
if (!response.ok) {
|
|
9415
|
+
throw new Error(`Unexpected status code: ${String(response.status)}.`);
|
|
9416
|
+
}
|
|
9417
|
+
if (!response.body) {
|
|
9418
|
+
throw new Error("Response body is empty.");
|
|
9419
|
+
}
|
|
9420
|
+
try {
|
|
9421
|
+
await pipeline(Readable.fromWeb(response.body), (0, import_tar_fs.extract)(destDir));
|
|
9422
|
+
} catch (error) {
|
|
9423
|
+
await new Promise((resolve3) => {
|
|
10430
9424
|
rm(destDir, { force: true, recursive: true }, () => {
|
|
10431
|
-
|
|
9425
|
+
resolve3();
|
|
10432
9426
|
});
|
|
10433
|
-
};
|
|
10434
|
-
extractObj.once("error", cleanupOnError);
|
|
10435
|
-
extractObj.once("finish", () => {
|
|
10436
|
-
resolve3(destDir);
|
|
10437
|
-
});
|
|
10438
|
-
const req = import_follow_redirects.default.https.get(url, (response) => {
|
|
10439
|
-
if (response.statusCode !== 200) {
|
|
10440
|
-
reject(new Error(`Unexpected status code: ${response.statusCode?.toFixed(0) ?? "UNK"}.`));
|
|
10441
|
-
return;
|
|
10442
|
-
}
|
|
10443
|
-
response.pipe(extractObj);
|
|
10444
|
-
response.once("error", cleanupOnError);
|
|
10445
9427
|
});
|
|
10446
|
-
|
|
10447
|
-
|
|
10448
|
-
|
|
10449
|
-
cleanupOnError(new Error("Request timeout"));
|
|
10450
|
-
});
|
|
10451
|
-
});
|
|
9428
|
+
throw error;
|
|
9429
|
+
}
|
|
9430
|
+
return destDir;
|
|
10452
9431
|
};
|
|
10453
9432
|
}
|
|
10454
9433
|
});
|
|
10455
|
-
var import_tar_fs2, inflate;
|
|
9434
|
+
var import_tar_fs2, ARCHIVE_EXTENSION_REGEX, TAR_EXTENSION_REGEX, BROTLI_EXTENSION_REGEX, GZIP_EXTENSION_REGEX, inflate;
|
|
10456
9435
|
var init_lambdafs = __esm({
|
|
10457
|
-
"../../node_modules/@sparticuz/chromium/build/
|
|
9436
|
+
"../../node_modules/@sparticuz/chromium/build/lambdafs.js"() {
|
|
10458
9437
|
import_tar_fs2 = __toESM(require_tar_fs());
|
|
9438
|
+
ARCHIVE_EXTENSION_REGEX = /\.(?:t(?:ar(?:\.(?:br|gz))?|br|gz)|br|gz)$/i;
|
|
9439
|
+
TAR_EXTENSION_REGEX = /\.t(?:ar(?:\.(?:br|gz))?|br|gz)$/i;
|
|
9440
|
+
BROTLI_EXTENSION_REGEX = /br$/i;
|
|
9441
|
+
GZIP_EXTENSION_REGEX = /gz$/i;
|
|
10459
9442
|
inflate = (filePath) => {
|
|
10460
|
-
const output = filePath.includes("swiftshader") ? tmpdir() : join(tmpdir(), basename(filePath).replace(
|
|
9443
|
+
const output = filePath.includes("swiftshader") ? tmpdir() : join(tmpdir(), basename(filePath).replace(ARCHIVE_EXTENSION_REGEX, ""));
|
|
10461
9444
|
return new Promise((resolve3, reject) => {
|
|
10462
9445
|
if (filePath.includes("swiftshader")) {
|
|
10463
9446
|
if (existsSync(`${output}/libGLESv2.so`)) {
|
|
@@ -10468,9 +9451,9 @@ var init_lambdafs = __esm({
|
|
|
10468
9451
|
resolve3(output);
|
|
10469
9452
|
return;
|
|
10470
9453
|
}
|
|
10471
|
-
const isBrotli =
|
|
10472
|
-
const isGzip =
|
|
10473
|
-
const isTar =
|
|
9454
|
+
const isBrotli = BROTLI_EXTENSION_REGEX.test(filePath);
|
|
9455
|
+
const isGzip = GZIP_EXTENSION_REGEX.test(filePath);
|
|
9456
|
+
const isTar = TAR_EXTENSION_REGEX.test(filePath);
|
|
10474
9457
|
const highWaterMark = 2 ** 22;
|
|
10475
9458
|
const source = createReadStream(filePath, { highWaterMark });
|
|
10476
9459
|
let target;
|
|
@@ -10502,24 +9485,28 @@ var init_lambdafs = __esm({
|
|
|
10502
9485
|
}
|
|
10503
9486
|
});
|
|
10504
9487
|
function getBinPath() {
|
|
10505
|
-
return join(dirname(fileURLToPath(import.meta.url)), "..", "
|
|
9488
|
+
return join(dirname(fileURLToPath(import.meta.url)), "..", "bin");
|
|
10506
9489
|
}
|
|
10507
|
-
var
|
|
10508
|
-
"../../node_modules/@sparticuz/chromium/build/
|
|
9490
|
+
var init_paths = __esm({
|
|
9491
|
+
"../../node_modules/@sparticuz/chromium/build/paths.js"() {
|
|
10509
9492
|
}
|
|
10510
9493
|
});
|
|
10511
9494
|
|
|
10512
|
-
// ../../node_modules/@sparticuz/chromium/build/
|
|
10513
|
-
var
|
|
10514
|
-
__export(
|
|
10515
|
-
default: () =>
|
|
9495
|
+
// ../../node_modules/@sparticuz/chromium/build/index.js
|
|
9496
|
+
var build_exports = {};
|
|
9497
|
+
__export(build_exports, {
|
|
9498
|
+
default: () => build_default,
|
|
9499
|
+
inflate: () => inflate,
|
|
9500
|
+
setupLambdaEnvironment: () => setupLambdaEnvironment
|
|
10516
9501
|
});
|
|
10517
|
-
var nodeMajorVersion, Chromium,
|
|
10518
|
-
var
|
|
10519
|
-
"../../node_modules/@sparticuz/chromium/build/
|
|
9502
|
+
var nodeMajorVersion, Chromium, build_default;
|
|
9503
|
+
var init_build = __esm({
|
|
9504
|
+
"../../node_modules/@sparticuz/chromium/build/index.js"() {
|
|
9505
|
+
init_helper();
|
|
9506
|
+
init_lambdafs();
|
|
9507
|
+
init_paths();
|
|
10520
9508
|
init_helper();
|
|
10521
9509
|
init_lambdafs();
|
|
10522
|
-
init_paths_esm();
|
|
10523
9510
|
nodeMajorVersion = Number.parseInt(process.versions.node.split(".")[0] ?? "");
|
|
10524
9511
|
if (isRunningInAmazonLinux2023(nodeMajorVersion)) {
|
|
10525
9512
|
setupLambdaEnvironment(join(tmpdir(), "al2023", "lib"));
|
|
@@ -10638,7 +9625,7 @@ var init_esm = __esm({
|
|
|
10638
9625
|
}
|
|
10639
9626
|
input ??= getBinPath();
|
|
10640
9627
|
if (!existsSync(input)) {
|
|
10641
|
-
throw new Error(`The input directory "${input}" does not exist.
|
|
9628
|
+
throw new Error(`The input directory "${input}" does not exist. If you are using a bundler (esbuild, webpack, etc.), you must externalize @sparticuz/chromium so it is not relocated. See: https://github.com/Sparticuz/chromium#bundler-configuration`);
|
|
10642
9629
|
}
|
|
10643
9630
|
const promises = [
|
|
10644
9631
|
inflate(join(input, "chromium.br")),
|
|
@@ -10652,7 +9639,7 @@ var init_esm = __esm({
|
|
|
10652
9639
|
return result.shift();
|
|
10653
9640
|
}
|
|
10654
9641
|
};
|
|
10655
|
-
|
|
9642
|
+
build_default = Chromium;
|
|
10656
9643
|
}
|
|
10657
9644
|
});
|
|
10658
9645
|
|
|
@@ -10661,6 +9648,7 @@ var visual_evaluator_exports = {};
|
|
|
10661
9648
|
__export(visual_evaluator_exports, {
|
|
10662
9649
|
buildRenderHTML: () => buildRenderHTML,
|
|
10663
9650
|
bundleForRendering: () => bundleForRendering,
|
|
9651
|
+
callMultimodalLLM: () => callMultimodalLLM,
|
|
10664
9652
|
runVisualEval: () => runVisualEval,
|
|
10665
9653
|
runVisualEvaluation: () => runVisualEvaluation
|
|
10666
9654
|
});
|
|
@@ -10759,7 +9747,7 @@ ${bundledCode}
|
|
|
10759
9747
|
async function captureScreenshot(html, viewport = { width: 1280, height: 800 }) {
|
|
10760
9748
|
try {
|
|
10761
9749
|
const puppeteer = await import('puppeteer-core');
|
|
10762
|
-
const chromium = await Promise.resolve().then(() => (
|
|
9750
|
+
const chromium = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
10763
9751
|
const launchOptions = {
|
|
10764
9752
|
args: chromium.default.args,
|
|
10765
9753
|
defaultViewport: viewport,
|
|
@@ -10769,7 +9757,9 @@ async function captureScreenshot(html, viewport = { width: 1280, height: 800 })
|
|
|
10769
9757
|
const browser = await puppeteer.default.launch(launchOptions);
|
|
10770
9758
|
try {
|
|
10771
9759
|
const page = await browser.newPage();
|
|
10772
|
-
await page.setContent(html, { waitUntil: "
|
|
9760
|
+
await page.setContent(html, { waitUntil: "load", timeout: 15e3 });
|
|
9761
|
+
await page.waitForNetworkIdle({ idleTime: 500, timeout: 15e3 }).catch(() => {
|
|
9762
|
+
});
|
|
10773
9763
|
await page.waitForSelector("#root > *", { timeout: 1e4 }).catch(() => {
|
|
10774
9764
|
});
|
|
10775
9765
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
@@ -10783,63 +9773,23 @@ async function captureScreenshot(html, viewport = { width: 1280, height: 800 })
|
|
|
10783
9773
|
return null;
|
|
10784
9774
|
}
|
|
10785
9775
|
}
|
|
10786
|
-
async function callMultimodalLLM(
|
|
9776
|
+
async function callMultimodalLLM(config, model, prompt, screenshot, originalPrompt) {
|
|
10787
9777
|
const userPrompt = `## Original Request
|
|
10788
9778
|
${originalPrompt}
|
|
10789
9779
|
|
|
10790
9780
|
Evaluate the screenshot of the generated component.`;
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
baseURL: "https://api.anthropic.com"
|
|
10796
|
-
});
|
|
10797
|
-
const response2 = await client2.messages.create({
|
|
10798
|
-
model: model.startsWith("anthropic/") ? model.slice(10) : model,
|
|
10799
|
-
max_tokens: 1500,
|
|
10800
|
-
system: prompt,
|
|
10801
|
-
messages: [{
|
|
10802
|
-
role: "user",
|
|
10803
|
-
content: [
|
|
10804
|
-
{
|
|
10805
|
-
type: "image",
|
|
10806
|
-
source: {
|
|
10807
|
-
type: "base64",
|
|
10808
|
-
media_type: "image/png",
|
|
10809
|
-
data: screenshot.toString("base64")
|
|
10810
|
-
}
|
|
10811
|
-
},
|
|
10812
|
-
{ type: "text", text: userPrompt }
|
|
10813
|
-
]
|
|
10814
|
-
}]
|
|
10815
|
-
});
|
|
10816
|
-
return {
|
|
10817
|
-
text: response2.content.filter((b) => b.type === "text").map((b) => b.text).join(""),
|
|
10818
|
-
inputTokens: response2.usage.input_tokens,
|
|
10819
|
-
outputTokens: response2.usage.output_tokens
|
|
10820
|
-
};
|
|
10821
|
-
}
|
|
10822
|
-
const { GoogleGenAI } = await import('@google/genai');
|
|
10823
|
-
const client = new GoogleGenAI({
|
|
10824
|
-
apiKey: process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY
|
|
10825
|
-
});
|
|
10826
|
-
const response = await client.models.generateContent({
|
|
10827
|
-
model: model.startsWith("google/") ? model.slice(7) : model,
|
|
10828
|
-
contents: [{
|
|
10829
|
-
role: "user",
|
|
10830
|
-
parts: [
|
|
10831
|
-
{ inlineData: { mimeType: "image/png", data: screenshot.toString("base64") } },
|
|
10832
|
-
{ text: userPrompt }
|
|
10833
|
-
]
|
|
10834
|
-
}],
|
|
10835
|
-
config: { systemInstruction: prompt }
|
|
9781
|
+
const agent = createVisionAgent({
|
|
9782
|
+
provider: config.provider === "claude" ? "anthropic" : config.provider,
|
|
9783
|
+
routeOverride: config.routeOverride,
|
|
9784
|
+
onRetry: config.onRetry
|
|
10836
9785
|
});
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
|
|
9786
|
+
return agent.callVision(
|
|
9787
|
+
model,
|
|
9788
|
+
prompt,
|
|
9789
|
+
userPrompt,
|
|
9790
|
+
{ mediaType: "image/png", base64: screenshot.toString("base64") },
|
|
9791
|
+
1500
|
|
9792
|
+
);
|
|
10843
9793
|
}
|
|
10844
9794
|
async function runVisualEvaluation(context, config) {
|
|
10845
9795
|
const startTime = Date.now();
|
|
@@ -10857,7 +9807,7 @@ async function runVisualEvaluation(context, config) {
|
|
|
10857
9807
|
console.log(`[visual-eval] screenshot: ${screenshot.length}B (${Date.now() - startTime}ms)`);
|
|
10858
9808
|
const model = config.model ?? getDefaultVisualModel(config.provider);
|
|
10859
9809
|
const response = await callMultimodalLLM(
|
|
10860
|
-
config
|
|
9810
|
+
config,
|
|
10861
9811
|
model,
|
|
10862
9812
|
VISUAL_EVAL_PROMPT,
|
|
10863
9813
|
screenshot,
|
|
@@ -10931,6 +9881,7 @@ async function runVisualEval(context, config) {
|
|
|
10931
9881
|
var VISUAL_EVAL_PROMPT;
|
|
10932
9882
|
var init_visual_evaluator = __esm({
|
|
10933
9883
|
"src/evaluation/visual-evaluator.ts"() {
|
|
9884
|
+
init_llm_router();
|
|
10934
9885
|
VISUAL_EVAL_PROMPT = `You are a visual quality evaluator for ggui \u2014 a platform where AI agents generate React UI components on demand.
|
|
10935
9886
|
|
|
10936
9887
|
## Context
|
|
@@ -11393,10 +10344,12 @@ These tokens adapt automatically to any theme (light, dark, branded). **ALWAYS u
|
|
|
11393
10344
|
- Borders/dividers \u2192 \`var(--ggui-color-outline)\` or \`var(--ggui-color-outlineVariant)\`
|
|
11394
10345
|
|
|
11395
10346
|
### State Colors
|
|
11396
|
-
|
|
11397
|
-
- var(--ggui-color-
|
|
11398
|
-
- var(--ggui-color-
|
|
11399
|
-
- var(--ggui-color-
|
|
10347
|
+
Semantic families ship as SCALES; the \`500\` stop is the role color (per-mode brightness), \`50\` the tint, \`800\` the on-tint text:
|
|
10348
|
+
- var(--ggui-color-success-500) \u2014 success states (tint bg: success-50, text on tint: success-800)
|
|
10349
|
+
- var(--ggui-color-warning-500) \u2014 warning states (warning-50 / warning-800)
|
|
10350
|
+
- var(--ggui-color-error-500) \u2014 error states, destructive actions (error-50 / error-800)
|
|
10351
|
+
- var(--ggui-color-info-500) \u2014 informational (info-50 / info-800)
|
|
10352
|
+
Prefer the primitives' \`tone="success|warning|error|info"\` prop over hand-written vars \u2014 it resolves to the same stops.
|
|
11400
10353
|
|
|
11401
10354
|
### IMPORTANT: Color Rules
|
|
11402
10355
|
- **NEVER** use hardcoded hex colors. ONLY use var(--ggui-color-*) tokens.
|
|
@@ -11696,16 +10649,19 @@ function generateSampleProps(spec) {
|
|
|
11696
10649
|
return props;
|
|
11697
10650
|
}
|
|
11698
10651
|
function synthesizeFromSchema(schema) {
|
|
11699
|
-
|
|
10652
|
+
const declared = Array.isArray(schema.type) ? schema.type.find((t) => t !== "null") : schema.type;
|
|
10653
|
+
switch (declared) {
|
|
11700
10654
|
case "string":
|
|
11701
10655
|
return "sample";
|
|
11702
10656
|
case "number":
|
|
10657
|
+
case "integer":
|
|
11703
10658
|
return 0;
|
|
11704
10659
|
case "boolean":
|
|
11705
10660
|
return false;
|
|
10661
|
+
case "null":
|
|
10662
|
+
return null;
|
|
11706
10663
|
case "array": {
|
|
11707
|
-
|
|
11708
|
-
if (itemSchema) return [synthesizeFromSchema(itemSchema) ?? null];
|
|
10664
|
+
if (schema.items) return [synthesizeFromSchema(schema.items) ?? null];
|
|
11709
10665
|
return [];
|
|
11710
10666
|
}
|
|
11711
10667
|
case "object": {
|
|
@@ -13171,11 +12127,11 @@ var stateFragments = {
|
|
|
13171
12127
|
axis: "state",
|
|
13172
12128
|
value: "merge",
|
|
13173
12129
|
cacheTier: "axisDelta",
|
|
13174
|
-
promptText: "## State: merge (live entity reconciliation)\n1. Seed `const [items, setItems] = useState(props.items ?? [])
|
|
12130
|
+
promptText: "## State: merge (live entity reconciliation)\n1. Seed `const [items, setItems] = useState(props.items ?? [])` AND re-seed on prop change: `useEffect(() => setItems(props.items ?? []), [props.items])` \u2014 a `ggui_amend` repaint must move the list.\n2. On stream updates: `setItems(prev => prev.map(it => it.id === event.id ? { ...it, ...event } : it))` \u2014 merge by id, do NOT append.\n3. Memoize derived views (grouping/sorting/filtering) with useMemo.\n4. Per-item actions pass `{ id, ... }` in the payload.\n5. Never push the stream payload into an append-only list unless realtime=append.",
|
|
13175
12131
|
boilerplateMarker: [
|
|
13176
12132
|
"",
|
|
13177
12133
|
" // \u2500\u2500 Live entity state (merge-by-id) \u2500\u2500",
|
|
13178
|
-
" // useState(props.items ?? []); merge stream events by item.id; never append.",
|
|
12134
|
+
" // useState(props.items ?? []); re-seed via useEffect on [props.items]; merge stream events by item.id; never append.",
|
|
13179
12135
|
""
|
|
13180
12136
|
].join("\n")
|
|
13181
12137
|
},
|
|
@@ -13293,13 +12249,13 @@ var realtimeFragments = {
|
|
|
13293
12249
|
axis: "realtime",
|
|
13294
12250
|
value: "merge",
|
|
13295
12251
|
cacheTier: "axisDelta",
|
|
13296
|
-
promptText: "## Realtime: merge\nStream events carry an id; merge into LOCAL STATE. Subscribing alone is not enough \u2014 the local list must update on each event for the DOM to re-render.\n\n```tsx\nconst stream = useStream<UpdateT>('streamName');\nconst [items, setItems] = useState(props.items);\nuseEffect(() => {\n if (!stream.latest) return;\n setItems((prev) => prev.map((it) => it.id === stream.latest!.id ? { ...it, ...stream.latest } : it));\n}, [stream.latest]);\n// Render `items.map(...)` \u2014 NOT props.items, NOT stream.all.\n```\n\nNever append \u2014 stream=merge means the entity already exists locally."
|
|
12252
|
+
promptText: "## Realtime: merge\nStream events carry an id; merge into LOCAL STATE. Subscribing alone is not enough \u2014 the local list must update on each event for the DOM to re-render.\n\n```tsx\nconst stream = useStream<UpdateT>('streamName');\nconst [items, setItems] = useState(props.items);\nuseEffect(() => setItems(props.items), [props.items]); // re-seed on ggui_amend repaint \u2014 props stay the source of truth\nuseEffect(() => {\n if (!stream.latest) return;\n setItems((prev) => prev.map((it) => it.id === stream.latest!.id ? { ...it, ...stream.latest } : it));\n}, [stream.latest]);\n// Render `items.map(...)` \u2014 NOT props.items, NOT stream.all.\n```\n\nNever append \u2014 stream=merge means the entity already exists locally."
|
|
13297
12253
|
},
|
|
13298
12254
|
append: {
|
|
13299
12255
|
axis: "realtime",
|
|
13300
12256
|
value: "append",
|
|
13301
12257
|
cacheTier: "axisDelta",
|
|
13302
|
-
promptText: "## Realtime: append\nStream events are new entities; APPEND to local state. Subscribing alone is not enough \u2014 the local list must update for the DOM to re-render.\n\n```tsx\nconst stream = useStream<EventT>('streamName');\nconst [items, setItems] = useState(props.items);\nuseEffect(() => {\n if (!stream.latest) return;\n setItems((prev) => [...prev, stream.latest!]);\n}, [stream.latest]);\n// Render `items.map(...)` \u2014 NOT props.items, NOT stream.all (which accumulates only post-mount).\n```\n\nUse head for newest-first, tail for chat-style. Cap list length if needed. Do not dedupe unless the contract guarantees at-most-once."
|
|
12258
|
+
promptText: "## Realtime: append\nStream events are new entities; APPEND to local state. Subscribing alone is not enough \u2014 the local list must update for the DOM to re-render.\n\n```tsx\nconst stream = useStream<EventT>('streamName');\nconst [items, setItems] = useState(props.items);\nuseEffect(() => setItems(props.items), [props.items]); // re-seed on ggui_amend repaint \u2014 props stay the source of truth\nuseEffect(() => {\n if (!stream.latest) return;\n setItems((prev) => [...prev, stream.latest!]);\n}, [stream.latest]);\n// Render `items.map(...)` \u2014 NOT props.items, NOT stream.all (which accumulates only post-mount).\n```\n\nUse head for newest-first, tail for chat-style. Cap list length if needed. Do not dedupe unless the contract guarantees at-most-once."
|
|
13303
12259
|
},
|
|
13304
12260
|
status: {
|
|
13305
12261
|
axis: "realtime",
|
|
@@ -13317,7 +12273,7 @@ var realtimeFragments = {
|
|
|
13317
12273
|
axis: "realtime",
|
|
13318
12274
|
value: "mixed",
|
|
13319
12275
|
cacheTier: "axisDelta",
|
|
13320
|
-
promptText: "## Realtime: mixed\nMultiple stream channels with DIFFERENT semantics. Each `streamKinds` entry in the contract maps to one of: merge, append, status, presence. Subscribe + sync to local state PER CHANNEL \u2014 subscribing alone never re-renders the DOM.\n\nExample (chat-interface \u2014 message=append, typing=presence):\n\n```tsx\nconst messages = useStream<MessageT>('message');\nconst typing = useStream<TypingT>('typing');\nconst [messageList, setMessageList] = useState(props.messages);\nconst [typingUsers, setTypingUsers] = useState<Set<string>>(new Set());\n\nuseEffect(() => {\n if (!messages.latest) return;\n setMessageList((prev) => [...prev, messages.latest!]);\n}, [messages.latest]);\n\nuseEffect(() => {\n if (!typing.latest) return;\n setTypingUsers((prev) => {\n const next = new Set(prev);\n if (typing.latest!.active) next.add(typing.latest!.sender);\n else next.delete(typing.latest!.sender);\n return next;\n });\n}, [typing.latest]);\n```\n\nDo NOT treat all events the same. Do NOT skip the local-state sync \u2014 `useStream` alone won't trigger DOM updates of your derived view.",
|
|
12276
|
+
promptText: "## Realtime: mixed\nMultiple stream channels with DIFFERENT semantics. Each `streamKinds` entry in the contract maps to one of: merge, append, status, presence. Subscribe + sync to local state PER CHANNEL \u2014 subscribing alone never re-renders the DOM.\n\nExample (chat-interface \u2014 message=append, typing=presence):\n\n```tsx\nconst messages = useStream<MessageT>('message');\nconst typing = useStream<TypingT>('typing');\nconst [messageList, setMessageList] = useState(props.messages);\nconst [typingUsers, setTypingUsers] = useState<Set<string>>(new Set());\n\nuseEffect(() => setMessageList(props.messages), [props.messages]); // re-seed on ggui_amend repaint\n\nuseEffect(() => {\n if (!messages.latest) return;\n setMessageList((prev) => [...prev, messages.latest!]);\n}, [messages.latest]);\n\nuseEffect(() => {\n if (!typing.latest) return;\n setTypingUsers((prev) => {\n const next = new Set(prev);\n if (typing.latest!.active) next.add(typing.latest!.sender);\n else next.delete(typing.latest!.sender);\n return next;\n });\n}, [typing.latest]);\n```\n\nDo NOT treat all events the same. Do NOT skip the local-state sync \u2014 `useStream` alone won't trigger DOM updates of your derived view.",
|
|
13321
12277
|
boilerplateMarker: [
|
|
13322
12278
|
"",
|
|
13323
12279
|
" // \u2500\u2500 Mixed stream handlers \u2500\u2500",
|
|
@@ -13628,13 +12584,14 @@ function generateBoilerplate(_userPrompt, contract, shellType, screen, composedS
|
|
|
13628
12584
|
const propsFields = [];
|
|
13629
12585
|
const propsProperties = contract?.propsSpec?.properties ?? {};
|
|
13630
12586
|
for (const [key, entry] of Object.entries(propsProperties)) {
|
|
13631
|
-
const required = entry.required
|
|
12587
|
+
const required = entry.required === true;
|
|
13632
12588
|
const nullable = entry.schema.nullable === true;
|
|
13633
12589
|
const tsType = jsonSchemaTypeToTs(entry.schema);
|
|
13634
12590
|
const fullType = nullable ? `${tsType} | null` : tsType;
|
|
13635
12591
|
const parts = [];
|
|
13636
12592
|
if (entry.description) parts.push(entry.description);
|
|
13637
12593
|
if (entry.default !== void 0) parts.push(`(default: ${JSON.stringify(entry.default)})`);
|
|
12594
|
+
if (!required) parts.push("(optional \u2014 the agent may omit it; guard or fall back)");
|
|
13638
12595
|
const desc = parts.length > 0 ? ` // ${parts.join(" ")}` : "";
|
|
13639
12596
|
propsFields.push(` ${key}${required ? "" : "?"}: ${fullType};${desc}`);
|
|
13640
12597
|
}
|
|
@@ -14191,13 +13148,15 @@ A \`DataContract\` declares everything a GguiSession exchanges with the outside
|
|
|
14191
13148
|
|
|
14192
13149
|
## Defensive coding for absent / late-arriving data
|
|
14193
13150
|
|
|
14194
|
-
Props arrive
|
|
13151
|
+
Props arrive at mount and may be partial on first render; later prop changes reach the SAME mounted component via \`ggui_amend\` (in-place repaint) on the live channel. Stream channels start empty and fill over time. Context slots start at their declared default (often \`null\`). **Never assume a field exists before you read it.**
|
|
14195
13152
|
|
|
13153
|
+
- **Optional contract props**: a \`Props\` field marked \`?\` in the boilerplate may be omitted by the agent ENTIRELY \u2014 the wire gate only enforces \`required: true\` entries, and the harness verifies your component with those props stripped. Guard them (\`?? default\`, \`?.\`, or an empty-state branch) from the FIRST render.
|
|
14196
13154
|
- **Array iteration**: always default to \`[]\` before \`.map\`/\`.filter\`/\`.length\`. Use \`(props.items ?? []).map(...)\` not \`props.items.map(...)\`. Same for stream.all, stream.latest, etc.
|
|
14197
13155
|
- **Object access**: optional-chain through nested fields. \`props.user?.name ?? 'Anonymous'\` not \`props.user.name\`.
|
|
14198
13156
|
- **Number ops**: default before arithmetic. \`(props.count ?? 0) + 1\` not \`props.count + 1\`.
|
|
14199
13157
|
- **Stream latest**: \`useStream\` returns \`{latest: T | null, all: T[], isComplete: boolean}\`. The default \`all\` is \`[]\` so it's safe to map; \`latest\` is null until the first frame arrives \u2014 guard before reading \`.foo\`.
|
|
14200
13158
|
- **Stream reconciliation**: when a stream event carries an \`action\` discriminant (e.g. \`create | move | edit | delete\`), the channel is a CRUD feed \u2014 your handler MUST branch on EVERY value: append on \`create\`, drop on \`delete\`, replace-by-id on \`move\` / \`edit\`. Merging only the "edit" case silently loses created and deleted items. Reconcile into the SAME state that seeds from \`props\` (e.g. \`useState(() => props.tasks ?? [])\`) so the seed data and the live feed render as one list \u2014 and handle an event whose id is not yet present (a \`create\` for an unknown item) by inserting it, not ignoring it.
|
|
13159
|
+
- **Props re-sync on repaint**: props the agent owns are the source of truth for display \u2014 prefer rendering DIRECTLY from \`props\` (controlled, no local copy). When local optimistic state genuinely needs a prop seed (a click bumps a count before the agent confirms), it MUST re-sync on prop change \u2014 \`useEffect(() => setCount(props.count ?? 0), [props.count])\` \u2014 or a \`ggui_amend\` repaint applies the new props while the display keeps the stale local value. BAD: \`const [count, setCount] = useState(props.count ?? 0)\` alone. GOOD: the same seed + the one-line re-sync effect.
|
|
14201
13160
|
- **Loading state**: while data is still absent, render \`<Skeleton>\` placeholders \u2014 never a blank screen. \`<Skeleton variant="text" />\` for a text line, \`variant="circle"\` for an avatar slot, default \`rect\` for a block.
|
|
14202
13161
|
- **Empty state**: when a list or results array is empty, render \`<EmptyState title="\u2026" description="\u2026" />\` \u2014 a region that renders nothing when empty looks broken to the user.
|
|
14203
13162
|
|
|
@@ -14325,7 +13284,7 @@ Every value change is mirrored to the host LLM's context automatically (debounce
|
|
|
14325
13284
|
|
|
14326
13285
|
**When NOT to use it.** Local UI state the contract did NOT declare \u2014 \`isDropdownOpen\`, hover flags, animation phase, ephemeral toggles. For those, use a plain \`useState\` directly. The runtime ignores undeclared state.
|
|
14327
13286
|
|
|
14328
|
-
**\`contextSpec\` direction is one-way: client \u2192 agent.** The agent uses \`propsSpec\` (via \`ggui_update\`) and \`streamSpec\` (via the live channel) to push state TO the client. Don't try to write to the agent via \`contextSpec\` \u2014 there is no return path.
|
|
13287
|
+
**\`contextSpec\` direction is one-way: client \u2192 agent.** The agent uses \`propsSpec\` (via \`ggui_amend\` for in-place repaints of this mount, or \`ggui_update\` when it mints a new history card) and \`streamSpec\` (via the live channel) to push state TO the client. Don't try to write to the agent via \`contextSpec\` \u2014 there is no return path.
|
|
14329
13288
|
|
|
14330
13289
|
**Schema mismatches drop silently.** If you set a value that doesn't match the slot's schema (e.g. a string into a \`{type: 'number'}\` slot), the runtime logs a dev \`console.warn\` and skips the post. Make sure your setter calls produce values that match the declared shape.
|
|
14331
13290
|
|
|
@@ -15432,6 +14391,31 @@ function runNoPhantomUseState(input) {
|
|
|
15432
14391
|
}
|
|
15433
14392
|
return issues;
|
|
15434
14393
|
}
|
|
14394
|
+
function runPropSeedNoResync(input) {
|
|
14395
|
+
if (input.compiledCode === null) return [];
|
|
14396
|
+
const src = input.sourceCode;
|
|
14397
|
+
const issues = [];
|
|
14398
|
+
const re = /const\s*\[\s*(\w+)\s*,\s*(\w+)\s*\]\s*=\s*useState(?:<[^>]*>)?\s*\(\s*props\??\.(\w+)/g;
|
|
14399
|
+
for (const m of src.matchAll(re)) {
|
|
14400
|
+
const [full, stateVar, setter, propName] = m;
|
|
14401
|
+
const idx = m.index ?? 0;
|
|
14402
|
+
const after = src.slice(idx + full.length);
|
|
14403
|
+
if (!new RegExp(`\\b${setter}\\s*\\(`).test(after)) continue;
|
|
14404
|
+
const resync = new RegExp(
|
|
14405
|
+
`\\[[^\\[\\]]*props\\??\\.${propName}\\b[^\\[\\]]*\\]`
|
|
14406
|
+
);
|
|
14407
|
+
if (resync.test(src)) continue;
|
|
14408
|
+
issues.push(
|
|
14409
|
+
mkIssue(
|
|
14410
|
+
"universal.prop_seed_no_resync",
|
|
14411
|
+
`useState(props.${propName}) seeds "${stateVar}" and mutates it, but no effect depends on [props.${propName}] \u2014 a ggui_amend repaint pushes new props that never reach this display (#480).`,
|
|
14412
|
+
`Add \`useEffect(() => ${setter}(props.${propName}), [props.${propName}]);\` so agent repaints re-seed the state, or derive the display directly from props.${propName}.`,
|
|
14413
|
+
"warn"
|
|
14414
|
+
)
|
|
14415
|
+
);
|
|
14416
|
+
}
|
|
14417
|
+
return issues;
|
|
14418
|
+
}
|
|
15435
14419
|
var UNIVERSAL_CHECKS = [
|
|
15436
14420
|
{
|
|
15437
14421
|
id: "universal.prop_coverage",
|
|
@@ -15450,6 +14434,12 @@ var UNIVERSAL_CHECKS = [
|
|
|
15450
14434
|
axis: "render",
|
|
15451
14435
|
values: ALL_RENDER_VALUES,
|
|
15452
14436
|
run: runNoPhantomUseState
|
|
14437
|
+
},
|
|
14438
|
+
{
|
|
14439
|
+
id: "universal.prop_seed_no_resync",
|
|
14440
|
+
axis: "render",
|
|
14441
|
+
values: ALL_RENDER_VALUES,
|
|
14442
|
+
run: runPropSeedNoResync
|
|
15453
14443
|
}
|
|
15454
14444
|
];
|
|
15455
14445
|
|
|
@@ -15469,7 +14459,7 @@ function runStateSeededFromProps(input) {
|
|
|
15469
14459
|
mkIssue(
|
|
15470
14460
|
"state.merge.seeded_from_props",
|
|
15471
14461
|
`Entity collection "${e.name}" is not seeded from props \u2014 no useState initializer reads props.${e.name}.`,
|
|
15472
|
-
`Add \`const [${e.name}, set${cap(e.name)}] = useState(props.${e.name});\` so stream/action updates
|
|
14462
|
+
`Add \`const [${e.name}, set${cap(e.name)}] = useState(props.${e.name});\` paired with \`useEffect(() => set${cap(e.name)}(props.${e.name}), [props.${e.name}]);\` so stream/action updates merge into live state AND agent repaints (ggui_amend) re-seed it (#480).`
|
|
15473
14463
|
)
|
|
15474
14464
|
);
|
|
15475
14465
|
}
|
|
@@ -15573,6 +14563,106 @@ var STATE_MERGE_CHECKS = [
|
|
|
15573
14563
|
}
|
|
15574
14564
|
];
|
|
15575
14565
|
|
|
14566
|
+
// src/evaluation/axis-checks/checks/state-ui-affordance.ts
|
|
14567
|
+
var STATE_ARIA_OR_ROLE = /aria-(checked|pressed|selected|expanded|current)\s*=|role\s*=/;
|
|
14568
|
+
var STATE_PRIMITIVE_IN_SUBTREE = /<(Checkbox|Toggle|Tabs|Accordion)[\s/>]/;
|
|
14569
|
+
var SEMANTIC_PRIMITIVES = /* @__PURE__ */ new Set(["Button", "Checkbox", "Toggle", "Link", "MenuItem"]);
|
|
14570
|
+
function collectSetters(src) {
|
|
14571
|
+
const setters = /* @__PURE__ */ new Set();
|
|
14572
|
+
for (const m of src.matchAll(/const\s*\[\s*\w+\s*,\s*(set\w+)\s*\]\s*=\s*useState/g)) {
|
|
14573
|
+
setters.add(m[1]);
|
|
14574
|
+
}
|
|
14575
|
+
return setters;
|
|
14576
|
+
}
|
|
14577
|
+
function collectHandlers(src, setters) {
|
|
14578
|
+
const handlers = /* @__PURE__ */ new Set();
|
|
14579
|
+
for (const m of src.matchAll(/const\s+(\w+)\s*=\s*(?:\([^)]*\)|\w+)\s*=>\s*\{?/g)) {
|
|
14580
|
+
const body = src.slice(m.index + m[0].length, m.index + m[0].length + 400);
|
|
14581
|
+
for (const s of setters) {
|
|
14582
|
+
if (body.includes(s)) {
|
|
14583
|
+
handlers.add(m[1]);
|
|
14584
|
+
break;
|
|
14585
|
+
}
|
|
14586
|
+
}
|
|
14587
|
+
}
|
|
14588
|
+
return handlers;
|
|
14589
|
+
}
|
|
14590
|
+
function attrBlock(src, start) {
|
|
14591
|
+
let depth = 0;
|
|
14592
|
+
for (let i = start; i < src.length; i++) {
|
|
14593
|
+
const c = src[i];
|
|
14594
|
+
if (c === "{") depth++;
|
|
14595
|
+
else if (c === "}") depth--;
|
|
14596
|
+
else if (c === ">" && depth === 0) return { block: src.slice(start, i), end: i };
|
|
14597
|
+
}
|
|
14598
|
+
return { block: src.slice(start, start + 900), end: start + 900 };
|
|
14599
|
+
}
|
|
14600
|
+
function onClickValue(block) {
|
|
14601
|
+
const m = block.match(/onClick\s*=\s*\{/);
|
|
14602
|
+
if (!m || m.index === void 0) return null;
|
|
14603
|
+
const open = m.index + m[0].length - 1;
|
|
14604
|
+
let depth = 0;
|
|
14605
|
+
for (let i = open; i < block.length; i++) {
|
|
14606
|
+
if (block[i] === "{") depth++;
|
|
14607
|
+
else if (block[i] === "}") {
|
|
14608
|
+
depth--;
|
|
14609
|
+
if (depth === 0) return block.slice(open + 1, i);
|
|
14610
|
+
}
|
|
14611
|
+
}
|
|
14612
|
+
return block.slice(open + 1);
|
|
14613
|
+
}
|
|
14614
|
+
function subtree(src, pos, tag) {
|
|
14615
|
+
const close = src.indexOf(`</${tag}>`, pos);
|
|
14616
|
+
return src.slice(pos, close === -1 ? pos + 700 : close);
|
|
14617
|
+
}
|
|
14618
|
+
function runStateAriaPresent(input) {
|
|
14619
|
+
if (input.compiledCode === null) return [];
|
|
14620
|
+
const src = input.sourceCode;
|
|
14621
|
+
const setters = collectSetters(src);
|
|
14622
|
+
const handlers = collectHandlers(src, setters);
|
|
14623
|
+
const issues = [];
|
|
14624
|
+
const flaggedLines = /* @__PURE__ */ new Set();
|
|
14625
|
+
const localComponents = /* @__PURE__ */ new Set();
|
|
14626
|
+
for (const m of src.matchAll(/(?:function\s+([A-Z]\w*)\s*\(|const\s+([A-Z]\w*)\s*=)/g)) {
|
|
14627
|
+
localComponents.add(m[1] ?? m[2]);
|
|
14628
|
+
}
|
|
14629
|
+
for (const m of src.matchAll(/<([A-Za-z][A-Za-z0-9]*)\b/g)) {
|
|
14630
|
+
const tag = m[1];
|
|
14631
|
+
if (m.index === void 0) continue;
|
|
14632
|
+
if (localComponents.has(tag)) continue;
|
|
14633
|
+
const { block, end } = attrBlock(src, m.index + m[0].length);
|
|
14634
|
+
const clickValue = onClickValue(block);
|
|
14635
|
+
if (clickValue === null) continue;
|
|
14636
|
+
const mutatesAffordance = [...setters].some((s) => clickValue.includes(s)) || [...handlers].some((h) => new RegExp(`\\b${h}\\b`).test(clickValue)) || // Extracted-subcomponent shape: the toggle handler arrives as an
|
|
14637
|
+
// `on[A-Z]…` callback prop and is invoked from onClick — inside a
|
|
14638
|
+
// ui-affordance component that IS the affordance mutation.
|
|
14639
|
+
/\bon[A-Z]\w*\b/.test(clickValue);
|
|
14640
|
+
if (!mutatesAffordance) continue;
|
|
14641
|
+
if (SEMANTIC_PRIMITIVES.has(tag)) continue;
|
|
14642
|
+
if (STATE_ARIA_OR_ROLE.test(block)) continue;
|
|
14643
|
+
if (STATE_PRIMITIVE_IN_SUBTREE.test(subtree(src, end, tag))) continue;
|
|
14644
|
+
const line = src.slice(0, m.index).split("\n").length;
|
|
14645
|
+
if (flaggedLines.has(line)) continue;
|
|
14646
|
+
flaggedLines.add(line);
|
|
14647
|
+
issues.push(
|
|
14648
|
+
mkIssue(
|
|
14649
|
+
"state.ui_affordance.state_aria_present",
|
|
14650
|
+
`Line ${line}: <${tag}> toggles the UI affordance from its onClick but exposes no state ARIA \u2014 its checked/selected/expanded state is invisible to assistive technology (styling is the only carrier).`,
|
|
14651
|
+
`Add the matching state attribute to the SAME element that carries the onClick: \`role="checkbox"\` + \`aria-checked={\u2026}\` for a toggle row, \`aria-pressed\` for a toggle button, \`aria-selected\` for a selection, \`aria-expanded\` for an open/close affordance \u2014 or replace the hand-rolled control with the state-carrying primitive (Checkbox / Toggle / Tabs / Accordion). \`as={Clickable}\` adds button + keyboard semantics but NOT state.`
|
|
14652
|
+
)
|
|
14653
|
+
);
|
|
14654
|
+
}
|
|
14655
|
+
return issues;
|
|
14656
|
+
}
|
|
14657
|
+
var STATE_UI_AFFORDANCE_CHECKS = [
|
|
14658
|
+
{
|
|
14659
|
+
id: "state.ui_affordance.state_aria_present",
|
|
14660
|
+
axis: "state",
|
|
14661
|
+
values: ["ui-affordance"],
|
|
14662
|
+
run: runStateAriaPresent
|
|
14663
|
+
}
|
|
14664
|
+
];
|
|
14665
|
+
|
|
15576
14666
|
// src/evaluation/axis-checks/checks/realtime.ts
|
|
15577
14667
|
var REALTIME_ACTIVE = ["merge", "append", "status", "presence", "mixed"];
|
|
15578
14668
|
function runStreamHandlerPerEvent(input) {
|
|
@@ -16262,6 +15352,7 @@ var EXTRA_CHECKS = [
|
|
|
16262
15352
|
var REGISTRY = [
|
|
16263
15353
|
...UNIVERSAL_CHECKS,
|
|
16264
15354
|
...STATE_MERGE_CHECKS,
|
|
15355
|
+
...STATE_UI_AFFORDANCE_CHECKS,
|
|
16265
15356
|
...REALTIME_CHECKS,
|
|
16266
15357
|
...WRITES_CHECKS,
|
|
16267
15358
|
...STATE_PAYLOAD_CHECKS,
|
|
@@ -16432,8 +15523,8 @@ ${cjsResult.code}
|
|
|
16432
15523
|
// src/harness/check/runtime-render/load-component.ts
|
|
16433
15524
|
async function loadComponent(input) {
|
|
16434
15525
|
const { sourceCode, moduleResolutions = {} } = input;
|
|
16435
|
-
const { createRequire:
|
|
16436
|
-
const require_ =
|
|
15526
|
+
const { createRequire: createRequire4 } = await import('module');
|
|
15527
|
+
const require_ = createRequire4(import.meta.url);
|
|
16437
15528
|
const sandboxRequire = (id) => {
|
|
16438
15529
|
if (id in moduleResolutions) return moduleResolutions[id];
|
|
16439
15530
|
if (id === "react/jsx-runtime" || id === "react/jsx-dev-runtime") {
|
|
@@ -16689,6 +15780,47 @@ function wrapDetection(kind, jsx, native, custom) {
|
|
|
16689
15780
|
function dedupe(arr) {
|
|
16690
15781
|
return Array.from(new Set(arr));
|
|
16691
15782
|
}
|
|
15783
|
+
var installed = false;
|
|
15784
|
+
function installProductionActShim() {
|
|
15785
|
+
if (installed) return;
|
|
15786
|
+
installed = true;
|
|
15787
|
+
const require_ = createRequire(import.meta.url);
|
|
15788
|
+
let reactCjs;
|
|
15789
|
+
try {
|
|
15790
|
+
reactCjs = require_("react");
|
|
15791
|
+
} catch {
|
|
15792
|
+
return;
|
|
15793
|
+
}
|
|
15794
|
+
if (typeof reactCjs.act === "function") {
|
|
15795
|
+
return;
|
|
15796
|
+
}
|
|
15797
|
+
try {
|
|
15798
|
+
const testUtils = require_("react-dom/test-utils");
|
|
15799
|
+
const reactDom = require_("react-dom");
|
|
15800
|
+
testUtils.act = createFlushSyncAct(reactDom.flushSync);
|
|
15801
|
+
} catch {
|
|
15802
|
+
}
|
|
15803
|
+
}
|
|
15804
|
+
function createFlushSyncAct(flushSync) {
|
|
15805
|
+
return (callback) => {
|
|
15806
|
+
let callbackResult;
|
|
15807
|
+
flushSync(() => {
|
|
15808
|
+
callbackResult = callback();
|
|
15809
|
+
});
|
|
15810
|
+
if (isThenable(callbackResult)) {
|
|
15811
|
+
const pending = callbackResult;
|
|
15812
|
+
return new Promise((resolve3, reject) => {
|
|
15813
|
+
pending.then(() => resolve3(), reject);
|
|
15814
|
+
});
|
|
15815
|
+
}
|
|
15816
|
+
return new Promise((resolve3) => {
|
|
15817
|
+
queueMicrotask(resolve3);
|
|
15818
|
+
});
|
|
15819
|
+
};
|
|
15820
|
+
}
|
|
15821
|
+
function isThenable(value) {
|
|
15822
|
+
return typeof value === "object" && value !== null && typeof value.then === "function";
|
|
15823
|
+
}
|
|
16692
15824
|
|
|
16693
15825
|
// src/internal/open-record.ts
|
|
16694
15826
|
function openRecord(o) {
|
|
@@ -16806,6 +15938,7 @@ async function runRenderCheck(input) {
|
|
|
16806
15938
|
const probe = createProbe();
|
|
16807
15939
|
const wireConfig = createProbeWireConfig(probe);
|
|
16808
15940
|
uninstallSpy = probe.installPostMessageSpy();
|
|
15941
|
+
installProductionActShim();
|
|
16809
15942
|
const { render, cleanup } = await import('@testing-library/react');
|
|
16810
15943
|
const userEventModule = await import('@testing-library/user-event');
|
|
16811
15944
|
const userEvent = userEventModule.default ?? userEventModule;
|
|
@@ -16961,6 +16094,50 @@ async function runRenderCheck(input) {
|
|
|
16961
16094
|
if (issue) issues.push(issue);
|
|
16962
16095
|
}
|
|
16963
16096
|
}
|
|
16097
|
+
const declaredProps = input.contract?.propsSpec?.properties;
|
|
16098
|
+
if (declaredProps) {
|
|
16099
|
+
const optionalFilled = Object.entries(declaredProps).filter(
|
|
16100
|
+
([name, entry]) => entry.required !== true && input.mockupProps[name] !== void 0
|
|
16101
|
+
).map(([name]) => name);
|
|
16102
|
+
if (optionalFilled.length > 0) {
|
|
16103
|
+
const requiredOnlyProps = { ...input.mockupProps };
|
|
16104
|
+
for (const name of optionalFilled) delete requiredOnlyProps[name];
|
|
16105
|
+
const omitBoundaryRef = {};
|
|
16106
|
+
class OmitErrorBoundary extends React.Component {
|
|
16107
|
+
state = { caught: false };
|
|
16108
|
+
static getDerivedStateFromError() {
|
|
16109
|
+
return { caught: true };
|
|
16110
|
+
}
|
|
16111
|
+
componentDidCatch(error) {
|
|
16112
|
+
omitBoundaryRef.error ??= error;
|
|
16113
|
+
}
|
|
16114
|
+
render() {
|
|
16115
|
+
if (this.state.caught) return null;
|
|
16116
|
+
return this.props.children;
|
|
16117
|
+
}
|
|
16118
|
+
}
|
|
16119
|
+
try {
|
|
16120
|
+
render(
|
|
16121
|
+
React.createElement(GguiWireProvider, {
|
|
16122
|
+
config: wireConfig,
|
|
16123
|
+
children: React.createElement(OmitErrorBoundary, {
|
|
16124
|
+
children: React.createElement(Component, requiredOnlyProps)
|
|
16125
|
+
})
|
|
16126
|
+
})
|
|
16127
|
+
);
|
|
16128
|
+
} catch (e) {
|
|
16129
|
+
omitBoundaryRef.error ??= e instanceof Error ? e : new Error(String(e));
|
|
16130
|
+
}
|
|
16131
|
+
if (omitBoundaryRef.error) {
|
|
16132
|
+
issues.push({
|
|
16133
|
+
check: "optional-props-omitted",
|
|
16134
|
+
outcome: "failed",
|
|
16135
|
+
subject: optionalFilled.join(", "),
|
|
16136
|
+
reason: `Render crashed when the optional prop(s) ${optionalFilled.map((n) => `'${n}'`).join(", ")} were omitted: ${omitBoundaryRef.error.message}. The contract marks them optional (no \`required: true\`), so a legitimate render may leave them out.`
|
|
16137
|
+
});
|
|
16138
|
+
}
|
|
16139
|
+
}
|
|
16140
|
+
}
|
|
16964
16141
|
} finally {
|
|
16965
16142
|
cleanup();
|
|
16966
16143
|
}
|
|
@@ -17128,8 +16305,8 @@ async function setupHappyDom() {
|
|
|
17128
16305
|
};
|
|
17129
16306
|
}
|
|
17130
16307
|
const { Window } = await import('happy-dom');
|
|
17131
|
-
const
|
|
17132
|
-
const windowAny = openRecord(
|
|
16308
|
+
const window = new Window({ url: "https://render-check.local" });
|
|
16309
|
+
const windowAny = openRecord(window);
|
|
17133
16310
|
const keys = [
|
|
17134
16311
|
"window",
|
|
17135
16312
|
"document",
|
|
@@ -17532,6 +16709,15 @@ function synthesizeFromSchema2(schema, hint, warnings, depth) {
|
|
|
17532
16709
|
if (schema.anyOf && schema.anyOf.length > 0) {
|
|
17533
16710
|
return synthesizeFromSchema2(schema.anyOf[0], hint, warnings, depth + 1);
|
|
17534
16711
|
}
|
|
16712
|
+
if (Array.isArray(schema.type)) {
|
|
16713
|
+
const primary = schema.type.find((t) => t !== "null") ?? "null";
|
|
16714
|
+
return synthesizeFromSchema2(
|
|
16715
|
+
{ ...schema, type: primary },
|
|
16716
|
+
hint,
|
|
16717
|
+
warnings,
|
|
16718
|
+
depth + 1
|
|
16719
|
+
);
|
|
16720
|
+
}
|
|
17535
16721
|
switch (schema.type) {
|
|
17536
16722
|
case "string": {
|
|
17537
16723
|
switch (schema.format) {
|
|
@@ -17702,6 +16888,16 @@ function toEvalIssue(issue) {
|
|
|
17702
16888
|
description: `Component crashed at runtime: ${issue.reason}`,
|
|
17703
16889
|
fix: classifyRenderCrashFix(issue.reason)
|
|
17704
16890
|
};
|
|
16891
|
+
case "optional-props-omitted":
|
|
16892
|
+
return {
|
|
16893
|
+
tier: 0,
|
|
16894
|
+
result,
|
|
16895
|
+
category: "crash",
|
|
16896
|
+
subcategory,
|
|
16897
|
+
severity: "critical",
|
|
16898
|
+
description: `Component crashed when optional props were omitted: ${issue.reason}`,
|
|
16899
|
+
fix: `Guard every optional prop before member access (props.${subject.split(",")[0]?.trim() ?? "x"}?.map(...), a default via destructuring, or an early empty-state return). Optional props (no \`required: true\` in the contract) may be absent at runtime even though the harness fills them.`
|
|
16900
|
+
};
|
|
17705
16901
|
case "action-wiring": {
|
|
17706
16902
|
const fix = issue.outcome === "unverified" ? `Source shows the action callback flowing into a non-native or custom-component prop. If wiring is intentional (e.g., Dropdown.onChange, drag-drop), this warn is informational \u2014 manual/browser verification is required to confirm. Otherwise wire to a native onClick={() => ${subject}(payload)} on <button> or design-system <Button>.` : `Wire ${subject}() to a native event prop. Common fix: <Button onClick={() => ${subject}(payload)}>Label</Button>. Source-AST analysis didn't find this wiring in your JSX.`;
|
|
17707
16903
|
return {
|
|
@@ -17748,6 +16944,7 @@ async function warmupRuntimeRenderProbe() {
|
|
|
17748
16944
|
missing += 1;
|
|
17749
16945
|
}
|
|
17750
16946
|
};
|
|
16947
|
+
installProductionActShim();
|
|
17751
16948
|
await Promise.all([
|
|
17752
16949
|
tryLoad("happy-dom"),
|
|
17753
16950
|
tryLoad("@testing-library/react"),
|
|
@@ -18824,6 +18021,14 @@ function mapProviderForEvaluator(provider) {
|
|
|
18824
18021
|
|
|
18825
18022
|
// src/harness/coding/run-eval-round.ts
|
|
18826
18023
|
var MAX_FEEDBACK_ISSUES = 3;
|
|
18024
|
+
function selectActionableFeedback(issues) {
|
|
18025
|
+
const pool = issues.filter((i) => i.result === "fail" || i.result === "warn");
|
|
18026
|
+
const reserved = pool.find((i) => i.tier === 0 && i.result === "fail");
|
|
18027
|
+
return [
|
|
18028
|
+
...reserved ? [reserved] : [],
|
|
18029
|
+
...pool.filter((i) => i !== reserved).sort((a, b) => (a.result === "fail" ? 0 : 1) - (b.result === "fail" ? 0 : 1))
|
|
18030
|
+
].slice(0, MAX_FEEDBACK_ISSUES);
|
|
18031
|
+
}
|
|
18827
18032
|
function fingerprintFail(issue) {
|
|
18828
18033
|
const cat = issue.category ?? "";
|
|
18829
18034
|
const sub = issue.subcategory ?? "";
|
|
@@ -18992,7 +18197,20 @@ async function runEvalRound(ctx, input) {
|
|
|
18992
18197
|
},
|
|
18993
18198
|
{
|
|
18994
18199
|
provider: mapProviderForEvaluator(evaluationAgent.provider),
|
|
18995
|
-
model: evaluationAgent.model
|
|
18200
|
+
model: evaluationAgent.model,
|
|
18201
|
+
// #484 — thread the coding-agent's routing override
|
|
18202
|
+
// through to the evaluator so its LLM call never falls
|
|
18203
|
+
// back to `process.env` either (the eval calls run
|
|
18204
|
+
// inside the same concurrent generation, so the race is
|
|
18205
|
+
// real here too, not just on the coding turn).
|
|
18206
|
+
routeOverride: evaluationAgent.routeOverride,
|
|
18207
|
+
// #489 — thread the same provider-429-retry observer.
|
|
18208
|
+
// Without this, a rate-limited retry inside the
|
|
18209
|
+
// evaluation agent's apiCall() happens (the base-class
|
|
18210
|
+
// retry loop is unconditional) but never reaches the
|
|
18211
|
+
// caller, silently missing the host application's
|
|
18212
|
+
// structured log.
|
|
18213
|
+
onRetry: evaluationAgent.onRetry
|
|
18996
18214
|
},
|
|
18997
18215
|
preWarmedContext
|
|
18998
18216
|
) : null,
|
|
@@ -19003,7 +18221,15 @@ async function runEvalRound(ctx, input) {
|
|
|
19003
18221
|
model: visualEvalAgent.model,
|
|
19004
18222
|
passThreshold: visualThreshold,
|
|
19005
18223
|
sampleProps: visualEvaluation?.sampleProps,
|
|
19006
|
-
viewport: visualEvaluation?.viewport
|
|
18224
|
+
viewport: visualEvaluation?.viewport,
|
|
18225
|
+
// #484/#489 — same threading as the LLM-eval leg above:
|
|
18226
|
+
// the visual eval's multimodal call runs inside the same
|
|
18227
|
+
// concurrent generation, so it needs the same routing
|
|
18228
|
+
// override (never fall back to `process.env`) and the
|
|
18229
|
+
// same provider-429-retry observer (retries reach the
|
|
18230
|
+
// host application's structured log).
|
|
18231
|
+
routeOverride: visualEvalAgent.routeOverride,
|
|
18232
|
+
onRetry: visualEvalAgent.onRetry
|
|
19007
18233
|
}
|
|
19008
18234
|
) : null
|
|
19009
18235
|
]);
|
|
@@ -19222,7 +18448,7 @@ async function runEvalRound(ctx, input) {
|
|
|
19222
18448
|
lastDiffFailed: false
|
|
19223
18449
|
};
|
|
19224
18450
|
}
|
|
19225
|
-
const allActionable = evalResult.issues
|
|
18451
|
+
const allActionable = selectActionableFeedback(evalResult.issues);
|
|
19226
18452
|
const issueLines = allActionable.map((issue) => {
|
|
19227
18453
|
const tag = issue.result === "fail" ? "FAIL" : "WARN";
|
|
19228
18454
|
return `[${tag}] ${issue.category}${issue.subcategory ? "/" + issue.subcategory : ""}: ${issue.description}
|
|
@@ -19237,7 +18463,16 @@ async function runEvalRound(ctx, input) {
|
|
|
19237
18463
|
evalResult,
|
|
19238
18464
|
evalRoundsUsed,
|
|
19239
18465
|
prevModeSubcats: updatedPrevModeSubcats,
|
|
19240
|
-
|
|
18466
|
+
// DELIVERED fails only (Exp 54 P1 addendum, proposal 2): the
|
|
18467
|
+
// stuck detector's premise is "the LLM saw these and did not
|
|
18468
|
+
// resolve them" — recording fails that the MAX_FEEDBACK_ISSUES
|
|
18469
|
+
// cap cut from the feedback turns truncation into a premature
|
|
18470
|
+
// stuck-exit (the model never saw the issue it is blamed for
|
|
18471
|
+
// not fixing). An undelivered fail recurring next round now
|
|
18472
|
+
// reads as NEW, gets delivered, and earns its fix round.
|
|
18473
|
+
prevFailFingerprints: new Set(
|
|
18474
|
+
allActionable.filter((i) => i.result === "fail").map(fingerprintFail)
|
|
18475
|
+
),
|
|
19241
18476
|
preWarmedContext,
|
|
19242
18477
|
evalTokens,
|
|
19243
18478
|
evalLlmMs,
|
|
@@ -19640,7 +18875,7 @@ async function initSession(input) {
|
|
|
19640
18875
|
await workspace.stage();
|
|
19641
18876
|
await workspace.commit("scaffold: boilerplate");
|
|
19642
18877
|
const systemPrompt = input.systemPromptOverride ?? harness.how.systemPrompt;
|
|
19643
|
-
const codingAgent = createAgent(agents.coding
|
|
18878
|
+
const codingAgent = createAgent(agents.coding);
|
|
19644
18879
|
await codingAgent.warmCache(
|
|
19645
18880
|
agents.coding.model,
|
|
19646
18881
|
systemPrompt,
|
|
@@ -19729,8 +18964,18 @@ async function dispatchGeneration(params) {
|
|
|
19729
18964
|
}
|
|
19730
18965
|
const routerProvider = mapProviderForLLMRouter(params.provider);
|
|
19731
18966
|
const resolvedModel = params.models?.coding ?? params.models?.default ?? params.model;
|
|
19732
|
-
const codingAgent = {
|
|
19733
|
-
|
|
18967
|
+
const codingAgent = {
|
|
18968
|
+
provider: routerProvider,
|
|
18969
|
+
model: resolvedModel,
|
|
18970
|
+
routeOverride: params.routeOverride,
|
|
18971
|
+
onRetry: params.onRetry
|
|
18972
|
+
};
|
|
18973
|
+
const evaluationAgent = params.models?.evaluation ? {
|
|
18974
|
+
provider: routerProvider,
|
|
18975
|
+
model: params.models.evaluation,
|
|
18976
|
+
routeOverride: params.routeOverride,
|
|
18977
|
+
onRetry: params.onRetry
|
|
18978
|
+
} : void 0;
|
|
19734
18979
|
const effectiveContract = params.contract;
|
|
19735
18980
|
const sessionParams = {
|
|
19736
18981
|
userPrompt: params.originalPrompt ?? params.userPrompt,
|
|
@@ -20090,11 +19335,15 @@ ${JSON.stringify(clientCapabilities, null, 2)}
|
|
|
20090
19335
|
const uiRequirements = [];
|
|
20091
19336
|
if (contract.propsSpec?.properties) {
|
|
20092
19337
|
for (const [name, entry] of Object.entries(contract.propsSpec.properties)) {
|
|
20093
|
-
const required = entry.required;
|
|
20094
|
-
if (required
|
|
19338
|
+
const required = entry.required === true;
|
|
19339
|
+
if (required) {
|
|
20095
19340
|
uiRequirements.push(
|
|
20096
19341
|
`- **Required prop \`${name}\`** must appear somewhere in rendered DOM (display the value, or use it to drive a label/aria/key).`
|
|
20097
19342
|
);
|
|
19343
|
+
} else {
|
|
19344
|
+
uiRequirements.push(
|
|
19345
|
+
`- **Optional prop \`${name}\`** may be ABSENT at runtime \u2014 the component must render without it (guard the access or apply its default) and must display it when it IS provided.`
|
|
19346
|
+
);
|
|
20098
19347
|
}
|
|
20099
19348
|
}
|
|
20100
19349
|
}
|
|
@@ -20177,7 +19426,9 @@ function createUiGenerator(options = {}) {
|
|
|
20177
19426
|
maxAttempts,
|
|
20178
19427
|
maxEvalRounds,
|
|
20179
19428
|
qualityConfig,
|
|
20180
|
-
gadgetCatalog
|
|
19429
|
+
gadgetCatalog,
|
|
19430
|
+
disableEnvMutation = false,
|
|
19431
|
+
onRetry
|
|
20181
19432
|
} = options;
|
|
20182
19433
|
const identity = resolveIdentity(options);
|
|
20183
19434
|
return {
|
|
@@ -20206,16 +19457,22 @@ function createUiGenerator(options = {}) {
|
|
|
20206
19457
|
});
|
|
20207
19458
|
}
|
|
20208
19459
|
const envBackup = {};
|
|
20209
|
-
|
|
20210
|
-
|
|
20211
|
-
|
|
20212
|
-
|
|
20213
|
-
|
|
20214
|
-
|
|
20215
|
-
|
|
20216
|
-
|
|
20217
|
-
|
|
19460
|
+
if (!disableEnvMutation) {
|
|
19461
|
+
for (const k of Object.keys(route.env)) envBackup[k] = process.env[k];
|
|
19462
|
+
const baseEnvForApply = {};
|
|
19463
|
+
for (const [k, v] of Object.entries(process.env)) {
|
|
19464
|
+
if (v !== void 0) baseEnvForApply[k] = v;
|
|
19465
|
+
}
|
|
19466
|
+
const routedEnv = applyRouteToEnv(baseEnvForApply, route);
|
|
19467
|
+
for (const [k, v] of Object.entries(routedEnv)) process.env[k] = v;
|
|
19468
|
+
for (const [k, v] of Object.entries(route.env)) {
|
|
19469
|
+
if (v === void 0) delete process.env[k];
|
|
19470
|
+
}
|
|
20218
19471
|
}
|
|
19472
|
+
const routeOverride = disableEnvMutation ? {
|
|
19473
|
+
apiKey: route.env["ANTHROPIC_API_KEY"] ?? route.env["OPENAI_API_KEY"] ?? route.env["GEMINI_API_KEY"] ?? route.env["OPENROUTER_API_KEY"],
|
|
19474
|
+
useBedrock: route.env["CLAUDE_CODE_USE_BEDROCK"] === "1"
|
|
19475
|
+
} : void 0;
|
|
20219
19476
|
try {
|
|
20220
19477
|
const tools = createGeneratorTools({
|
|
20221
19478
|
...input.contract ? { contract: input.contract } : {}
|
|
@@ -20248,7 +19505,9 @@ function createUiGenerator(options = {}) {
|
|
|
20248
19505
|
// `Type:` lines and the coding-agent typecheck overlay via
|
|
20249
19506
|
// `dispatchGeneration`.
|
|
20250
19507
|
...input.gadgetTypes !== void 0 ? { gadgetTypes: input.gadgetTypes } : {},
|
|
20251
|
-
enableRuntimeRender
|
|
19508
|
+
enableRuntimeRender,
|
|
19509
|
+
...routeOverride !== void 0 ? { routeOverride } : {},
|
|
19510
|
+
...onRetry !== void 0 ? { onRetry } : {}
|
|
20252
19511
|
});
|
|
20253
19512
|
const metadata = {
|
|
20254
19513
|
provider: input.llm.provider,
|