modelrig 0.9.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/CHANGELOG.md +179 -0
- package/README.md +51 -27
- package/data/PROVENANCE.md +14 -0
- package/data/pricing-map.json +26 -0
- package/dist/adapters/attempt-meta-map.d.ts +8 -1
- package/dist/adapters/attempt-meta-map.d.ts.map +1 -1
- package/dist/adapters/attempt-meta-map.js +4 -0
- package/dist/adapters/build-adapters.js +2 -2
- package/dist/adapters/gemini.d.ts +28 -1
- package/dist/adapters/gemini.d.ts.map +1 -1
- package/dist/adapters/gemini.js +38 -9
- package/dist/adapters/grok.d.ts.map +1 -1
- package/dist/adapters/grok.js +53 -4
- package/dist/adapters/openai-compat.d.ts +8 -2
- package/dist/adapters/openai-compat.d.ts.map +1 -1
- package/dist/adapters/openai-compat.js +8 -1
- package/dist/adapters/openai-stream.d.ts +10 -2
- package/dist/adapters/openai-stream.d.ts.map +1 -1
- package/dist/adapters/openai-stream.js +5 -1
- package/dist/adapters/openai.d.ts +10 -1
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +57 -7
- package/dist/adapters/responses-api.d.ts +61 -0
- package/dist/adapters/responses-api.d.ts.map +1 -0
- package/dist/adapters/responses-api.js +124 -0
- package/dist/artifacts/artifact.d.ts +20 -0
- package/dist/artifacts/artifact.d.ts.map +1 -1
- package/dist/artifacts/artifact.js +207 -171
- package/dist/artifacts/index.d.ts +3 -1
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/index.js +8 -1
- package/dist/bakeoff/groundedness.d.ts +58 -0
- package/dist/bakeoff/groundedness.d.ts.map +1 -0
- package/dist/bakeoff/groundedness.js +165 -0
- package/dist/bakeoff/quality.d.ts +14 -1
- package/dist/bakeoff/quality.d.ts.map +1 -1
- package/dist/bakeoff/quality.js +10 -0
- package/dist/bakeoff/replay.d.ts.map +1 -1
- package/dist/bakeoff/replay.js +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +8 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -0
- package/dist/doctor-cli.d.ts +7 -0
- package/dist/doctor-cli.d.ts.map +1 -0
- package/dist/doctor-cli.js +67 -0
- package/dist/doctor-preflight.d.ts +52 -0
- package/dist/doctor-preflight.d.ts.map +1 -0
- package/dist/doctor-preflight.js +112 -0
- package/dist/feedback/grade.d.ts +8 -1
- package/dist/feedback/grade.d.ts.map +1 -1
- package/dist/feedback/grade.js +4 -0
- package/dist/gateway/http-protocol.d.ts +19 -0
- package/dist/gateway/http-protocol.d.ts.map +1 -1
- package/dist/gateway/serve-client.d.ts +99 -0
- package/dist/gateway/serve-client.d.ts.map +1 -0
- package/dist/gateway/serve-client.js +360 -0
- package/dist/index.d.ts +25 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -8
- package/dist/prompts/manifest.d.ts +128 -0
- package/dist/prompts/manifest.d.ts.map +1 -0
- package/dist/prompts/manifest.js +214 -0
- package/dist/prompts/prompt-fetch.d.ts +84 -0
- package/dist/prompts/prompt-fetch.d.ts.map +1 -0
- package/dist/prompts/prompt-fetch.js +120 -0
- package/dist/prompts/prompt-resolve.d.ts +76 -0
- package/dist/prompts/prompt-resolve.d.ts.map +1 -0
- package/dist/prompts/prompt-resolve.js +93 -0
- package/dist/prompts/slot-resolver.d.ts +91 -0
- package/dist/prompts/slot-resolver.d.ts.map +1 -0
- package/dist/prompts/slot-resolver.js +135 -0
- package/dist/prompts/tools-register.d.ts +60 -0
- package/dist/prompts/tools-register.d.ts.map +1 -0
- package/dist/prompts/tools-register.js +48 -0
- package/dist/prompts/version-hash.d.ts +29 -0
- package/dist/prompts/version-hash.d.ts.map +1 -0
- package/dist/prompts/version-hash.js +54 -0
- package/dist/prompts-export-cli.d.ts +21 -0
- package/dist/prompts-export-cli.d.ts.map +1 -0
- package/dist/prompts-export-cli.js +130 -0
- package/dist/registry/cache-policy.d.ts.map +1 -1
- package/dist/registry/cache-policy.js +22 -0
- package/dist/registry/pricing-shape.d.ts +38 -8
- package/dist/registry/pricing-shape.d.ts.map +1 -1
- package/dist/registry/pricing-shape.js +40 -12
- package/dist/registry/pricing.d.ts +6 -5
- package/dist/registry/pricing.d.ts.map +1 -1
- package/dist/registry/pricing.js +9 -5
- package/dist/routes/destination-loader.d.ts +16 -0
- package/dist/routes/destination-loader.d.ts.map +1 -0
- package/dist/routes/destination-loader.js +29 -0
- package/dist/routes/draft.d.ts +7 -0
- package/dist/routes/draft.d.ts.map +1 -1
- package/dist/routes/draft.js +12 -0
- package/dist/routes/loader.d.ts.map +1 -1
- package/dist/routes/loader.js +27 -54
- package/dist/routes/output-loader.d.ts +42 -0
- package/dist/routes/output-loader.d.ts.map +1 -0
- package/dist/routes/output-loader.js +112 -0
- package/dist/routes/prompt-loader.d.ts +49 -0
- package/dist/routes/prompt-loader.d.ts.map +1 -0
- package/dist/routes/prompt-loader.js +113 -0
- package/dist/routes/resolved-bundle.d.ts +19 -0
- package/dist/routes/resolved-bundle.d.ts.map +1 -1
- package/dist/routes/resolved-bundle.js +24 -0
- package/dist/routes/screen-loader.d.ts +1 -1
- package/dist/routes/screen-loader.d.ts.map +1 -1
- package/dist/routes/screen-loader.js +8 -1
- package/dist/run/accept.d.ts +3 -0
- package/dist/run/accept.d.ts.map +1 -1
- package/dist/run/accept.js +1 -0
- package/dist/run/cost.d.ts +31 -2
- package/dist/run/cost.d.ts.map +1 -1
- package/dist/run/cost.js +57 -2
- package/dist/run/destination.d.ts +39 -0
- package/dist/run/destination.d.ts.map +1 -0
- package/dist/run/destination.js +45 -0
- package/dist/run/dispatch.d.ts +25 -3
- package/dist/run/dispatch.d.ts.map +1 -1
- package/dist/run/dispatch.js +26 -4
- package/dist/run/raw-defaults.d.ts.map +1 -1
- package/dist/run/raw-defaults.js +6 -1
- package/dist/run/raw-finalize.d.ts +50 -0
- package/dist/run/raw-finalize.d.ts.map +1 -0
- package/dist/run/raw-finalize.js +266 -0
- package/dist/run/raw-knobs.d.ts +36 -0
- package/dist/run/raw-knobs.d.ts.map +1 -0
- package/dist/run/raw-knobs.js +99 -0
- package/dist/run/raw-request.d.ts +24 -0
- package/dist/run/raw-request.d.ts.map +1 -0
- package/dist/run/raw-request.js +69 -0
- package/dist/run/raw-schema.d.ts +76 -0
- package/dist/run/raw-schema.d.ts.map +1 -0
- package/dist/run/raw-schema.js +166 -0
- package/dist/run/raw-search-cost.d.ts +48 -0
- package/dist/run/raw-search-cost.d.ts.map +1 -0
- package/dist/run/raw-search-cost.js +78 -0
- package/dist/run/raw-support.d.ts +64 -6
- package/dist/run/raw-support.d.ts.map +1 -1
- package/dist/run/raw-support.js +84 -11
- package/dist/run/raw.d.ts +25 -26
- package/dist/run/raw.d.ts.map +1 -1
- package/dist/run/raw.js +30 -351
- package/dist/run/record-attempt.d.ts +8 -0
- package/dist/run/record-attempt.d.ts.map +1 -1
- package/dist/run/record-attempt.js +26 -12
- package/dist/run/repair-attempt.d.ts +68 -0
- package/dist/run/repair-attempt.d.ts.map +1 -0
- package/dist/run/repair-attempt.js +180 -0
- package/dist/run/resolve-destination.d.ts +49 -0
- package/dist/run/resolve-destination.d.ts.map +1 -0
- package/dist/run/resolve-destination.js +76 -0
- package/dist/run/routing-docs.d.ts.map +1 -1
- package/dist/run/routing-docs.js +9 -4
- package/dist/run/run.d.ts +30 -1
- package/dist/run/run.d.ts.map +1 -1
- package/dist/run/run.js +75 -148
- package/dist/run/telemetry-row.d.ts +92 -0
- package/dist/run/telemetry-row.d.ts.map +1 -0
- package/dist/run/telemetry-row.js +81 -0
- package/dist/run/validate.d.ts +12 -1
- package/dist/run/validate.d.ts.map +1 -1
- package/dist/run/validate.js +31 -0
- package/dist/run/web-search-pricing.d.ts +43 -0
- package/dist/run/web-search-pricing.d.ts.map +1 -0
- package/dist/run/web-search-pricing.js +56 -0
- package/dist/settings/grading-guide.d.ts +27 -1
- package/dist/settings/grading-guide.d.ts.map +1 -1
- package/dist/status.d.ts +6 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +4 -1
- package/dist/telemetry/artifact-store.d.ts.map +1 -1
- package/dist/telemetry/artifact-store.js +11 -0
- package/dist/telemetry/attempt-meta.d.ts +55 -1
- package/dist/telemetry/attempt-meta.d.ts.map +1 -1
- package/dist/telemetry/attempt-meta.js +24 -1
- package/dist/telemetry/exporter-setup.d.ts +2 -0
- package/dist/telemetry/exporter-setup.d.ts.map +1 -1
- package/dist/telemetry/exporter-setup.js +6 -1
- package/dist/telemetry/grade-mappers.d.ts +5 -2
- package/dist/telemetry/grade-mappers.d.ts.map +1 -1
- package/dist/telemetry/grade-mappers.js +8 -2
- package/dist/telemetry/grades-sql.d.ts +4 -1
- package/dist/telemetry/grades-sql.d.ts.map +1 -1
- package/dist/telemetry/grades-sql.js +26 -3
- package/dist/telemetry/ingest-protocol.d.ts +26 -2
- package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
- package/dist/telemetry/ingest-protocol.js +32 -29
- package/dist/telemetry/org-identity.d.ts +44 -0
- package/dist/telemetry/org-identity.d.ts.map +1 -0
- package/dist/telemetry/org-identity.js +98 -0
- package/dist/telemetry/route-registration.d.ts +48 -0
- package/dist/telemetry/route-registration.d.ts.map +1 -0
- package/dist/telemetry/route-registration.js +77 -0
- package/dist/telemetry/sinks.d.ts +10 -1
- package/dist/telemetry/sinks.d.ts.map +1 -1
- package/dist/telemetry/sinks.js +52 -6
- package/dist/telemetry/store-migrations.d.ts.map +1 -1
- package/dist/telemetry/store-migrations.js +13 -0
- package/dist/tenancy/api-key-format.d.ts +16 -1
- package/dist/tenancy/api-key-format.d.ts.map +1 -1
- package/dist/tenancy/api-key-format.js +17 -0
- package/dist/types/provider.d.ts +20 -3
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/provider.js +1 -0
- package/dist/types/route.d.ts +76 -0
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +30 -2
- package/dist/types/telemetry.d.ts.map +1 -1
- package/docs/agent-skill/SKILL.md +73 -5
- package/docs/instrumentation.md +81 -36
- package/docs/llms.txt +95 -16
- package/docs/managed-serving.md +150 -0
- package/docs/mcp-oracle.md +75 -2
- package/docs/migration-playbook.md +5 -4
- package/docs/quickstart.md +169 -83
- package/package.json +3 -2
- package/registry/registry.json +82 -0
- package/dist/feedback/feedback.d.ts +0 -35
- package/dist/feedback/feedback.d.ts.map +0 -1
- package/dist/feedback/feedback.js +0 -39
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/routes/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/routes/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAKV,WAAW,EAGZ,MAAM,gBAAgB,CAAC;AAaxB,OAAO,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AAE/H;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO;CAOxF;AA+BD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,IAAI,IAAI,SAAS,WAAW,EAAE,CAAC;CAChC;AA2aD;;;;;;;GAOG;AACH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAItF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAyB1F;AAED;;yBAEyB;AACzB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CA6CtE;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CA2C1D"}
|
package/dist/routes/loader.js
CHANGED
|
@@ -14,13 +14,17 @@ const node_fs_1 = require("node:fs");
|
|
|
14
14
|
const node_path_1 = require("node:path");
|
|
15
15
|
const yaml_1 = require("yaml");
|
|
16
16
|
const failures_1 = require("../types/failures");
|
|
17
|
+
const provider_1 = require("../types/provider");
|
|
17
18
|
const fingerprint_1 = require("../registry/fingerprint");
|
|
18
19
|
const cache_lint_1 = require("./cache-lint");
|
|
20
|
+
const destination_loader_1 = require("./destination-loader"); // U2 (D-2): validated `destination` field (carved out for the LOC cap)
|
|
19
21
|
const sampling_config_1 = require("./sampling-config");
|
|
20
22
|
const loader_warnings_1 = require("./loader-warnings");
|
|
21
23
|
const screen_loader_1 = require("./screen-loader");
|
|
24
|
+
const prompt_loader_1 = require("./prompt-loader"); // issue #5 (R1): `prompt.user` + the prompt block (moved out for the LOC cap)
|
|
22
25
|
const mask_loader_1 = require("./mask-loader");
|
|
23
26
|
const objective_loader_1 = require("./objective-loader");
|
|
27
|
+
const output_loader_1 = require("./output-loader"); // issue #1: `output: text` (prose) + the schema reader (moved out for the LOC cap)
|
|
24
28
|
// Re-exported so existing importers of "./loader" keep resolving these advisories
|
|
25
29
|
// (they live in ./loader-warnings to hold loader.ts under the 700-LOC cap).
|
|
26
30
|
var loader_warnings_2 = require("./loader-warnings");
|
|
@@ -43,13 +47,11 @@ class RouteConfigError extends Error {
|
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
exports.RouteConfigError = RouteConfigError;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"grok",
|
|
52
|
-
]);
|
|
50
|
+
// Provider allow-set for routable candidates and repair models (M-S1) — every
|
|
51
|
+
// known ProviderId, now INCLUDING the ModelRig-hosted aggregator hosts
|
|
52
|
+
// (fireworks/deepinfra/zai). Sourced from PROVIDER_IDS so it stays in lockstep
|
|
53
|
+
// with the union (compacted from an inline literal to hold the 700-LOC cap).
|
|
54
|
+
const PROVIDERS = new Set(provider_1.PROVIDER_IDS);
|
|
53
55
|
const REQUIREMENTS = new Set([
|
|
54
56
|
"schema_conformant",
|
|
55
57
|
"grounded",
|
|
@@ -314,31 +316,6 @@ function parseVariants(raw, routeCandidates, problems) {
|
|
|
314
316
|
}
|
|
315
317
|
return out;
|
|
316
318
|
}
|
|
317
|
-
function readSchema(schemaRaw, bundleDir, problems) {
|
|
318
|
-
if (schemaRaw === null || schemaRaw === undefined)
|
|
319
|
-
return null;
|
|
320
|
-
if (typeof schemaRaw !== "string" || schemaRaw === "") {
|
|
321
|
-
problems.push("schema must be a relative path or null");
|
|
322
|
-
return null;
|
|
323
|
-
}
|
|
324
|
-
const schemaPath = (0, node_path_1.resolve)(bundleDir, schemaRaw);
|
|
325
|
-
if (!(0, node_fs_1.existsSync)(schemaPath)) {
|
|
326
|
-
problems.push(`schema file not found: ${schemaRaw}`);
|
|
327
|
-
return null;
|
|
328
|
-
}
|
|
329
|
-
try {
|
|
330
|
-
const parsed = JSON.parse((0, node_fs_1.readFileSync)(schemaPath, "utf8"));
|
|
331
|
-
if (!isRecord(parsed)) {
|
|
332
|
-
problems.push(`schema file ${schemaRaw} must contain a JSON object`);
|
|
333
|
-
return null;
|
|
334
|
-
}
|
|
335
|
-
return parsed;
|
|
336
|
-
}
|
|
337
|
-
catch (err) {
|
|
338
|
-
problems.push(`schema file ${schemaRaw} is not valid JSON: ${err.message}`);
|
|
339
|
-
return null;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
319
|
function loadBundleFile(filePath) {
|
|
343
320
|
const problems = [];
|
|
344
321
|
let doc;
|
|
@@ -365,12 +342,14 @@ function loadBundleFile(filePath) {
|
|
|
365
342
|
const candidates = parseCandidates(doc.candidates, problems);
|
|
366
343
|
const require = parseStringList(doc.require, "require", REQUIREMENTS, problems);
|
|
367
344
|
const prefer = parseStringList(doc.prefer, "prefer", PREFERENCES, problems);
|
|
368
|
-
const outputSchema = readSchema(doc.schema, bundleDir, problems);
|
|
345
|
+
const outputSchema = (0, output_loader_1.readSchema)(doc.schema, bundleDir, problems);
|
|
369
346
|
const policy = parsePolicy(doc.policy, problems);
|
|
370
347
|
// Phase 3 (bundle v2, all additive): variants, repair, capture opt-in,
|
|
371
348
|
// grounding-inject query template.
|
|
372
349
|
const variants = parseVariants(doc.variants, candidates, problems);
|
|
373
350
|
const repair = parseRepair(doc.repair, "repair", candidates, problems);
|
|
351
|
+
// Issue #1: `output: text` (prose) — a load error when it contradicts schema:/require:/repair:.
|
|
352
|
+
const output = (0, output_loader_1.parseOutputBlock)(doc.output, { outputSchema, schemaDeclared: doc.schema !== undefined && doc.schema !== null, require, repair, variants }, problems);
|
|
374
353
|
const capture = doc.capture ?? false;
|
|
375
354
|
if (typeof capture !== "boolean") {
|
|
376
355
|
problems.push("capture must be a boolean");
|
|
@@ -408,26 +387,12 @@ function loadBundleFile(filePath) {
|
|
|
408
387
|
const mask = (0, mask_loader_1.parseMaskBlock)(doc.mask, bundleDir, problems);
|
|
409
388
|
const screen = (0, screen_loader_1.parseScreenBlock)(doc.screen, problems);
|
|
410
389
|
const classification = (0, screen_loader_1.parseClassificationAndPhiGate)(doc.classification, { mask, screen, require }, problems);
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
else {
|
|
418
|
-
const promptPath = (0, node_path_1.resolve)(bundleDir, doc.prompt.system);
|
|
419
|
-
if (!(0, node_fs_1.existsSync)(promptPath)) {
|
|
420
|
-
problems.push(`prompt.system file not found: ${doc.prompt.system}`);
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
systemTemplate = (0, node_fs_1.readFileSync)(promptPath, "utf8");
|
|
424
|
-
}
|
|
425
|
-
// Screening S2 (SC-0 B3): parse names + optional per-variable x-trust.
|
|
426
|
-
const parsed = (0, screen_loader_1.parseVariables)(doc.prompt.variables ?? [], problems);
|
|
427
|
-
variables = parsed.names;
|
|
428
|
-
variableTrust = parsed.trust;
|
|
429
|
-
}
|
|
430
|
-
(0, screen_loader_1.pushUndeclaredVariableProblems)(systemTemplate, groundingQuery, variables, problems);
|
|
390
|
+
const destination = (0, destination_loader_1.parseDestination)(doc.destination, problems); // Unified Route U2 (D-2)
|
|
391
|
+
// `prompt.system` / `prompt.user` (issue #5, R1) / `prompt.variables` (+ S2
|
|
392
|
+
// x-trust) — parsed in prompt-loader.ts; both templates are files relative to
|
|
393
|
+
// the bundle and share one declared-variable list.
|
|
394
|
+
const { systemTemplate, userTemplate, variables, variableTrust } = (0, prompt_loader_1.parsePromptBlock)(doc.prompt, bundleDir, problems);
|
|
395
|
+
(0, screen_loader_1.pushUndeclaredVariableProblems)(systemTemplate, groundingQuery, variables, problems, userTemplate);
|
|
431
396
|
if (problems.length > 0) {
|
|
432
397
|
throw new RouteConfigError("invalid route bundle", { file: filePath, problems });
|
|
433
398
|
}
|
|
@@ -462,14 +427,22 @@ function loadBundleFile(filePath) {
|
|
|
462
427
|
const xTrustWarning = (0, loader_warnings_1.untrustedShapedVariableWarning)(route, variables, variableTrust);
|
|
463
428
|
if (xTrustWarning !== null)
|
|
464
429
|
console.warn(`modelrig: ${xTrustWarning}`);
|
|
430
|
+
// Issue #5 (R1) advisory: a cached route with a Gemini candidate, a non-empty
|
|
431
|
+
// system template and no `prompt.user` — a handle would deliver the template
|
|
432
|
+
// as the user turn (never dropped); name the rule so the shape is deliberate.
|
|
433
|
+
const cachedPromptWarning = (0, prompt_loader_1.cachedRouteSystemOnlyWarning)(route, cache, candidates, systemTemplate, userTemplate);
|
|
434
|
+
if (cachedPromptWarning !== null)
|
|
435
|
+
console.warn(`modelrig: ${cachedPromptWarning}`);
|
|
465
436
|
return Object.freeze({
|
|
466
437
|
route: route,
|
|
467
438
|
version: version,
|
|
468
439
|
outputSchema: outputSchema === null ? null : Object.freeze(outputSchema),
|
|
440
|
+
...output, // outputKind/outputMinChars — present ONLY for `output: text` (json ⇒ nothing added)
|
|
469
441
|
candidates: Object.freeze(candidates),
|
|
470
442
|
require: Object.freeze(require),
|
|
471
443
|
prefer: Object.freeze(prefer),
|
|
472
444
|
systemTemplate,
|
|
445
|
+
...(userTemplate !== undefined ? { userTemplate } : {}), // issue #5 (R1): present ONLY when declared (absent ⇒ unchanged bundle_sha)
|
|
473
446
|
variables: Object.freeze(variables),
|
|
474
447
|
policy,
|
|
475
448
|
...(repair !== undefined ? { repair } : {}),
|
|
@@ -481,7 +454,7 @@ function loadBundleFile(filePath) {
|
|
|
481
454
|
...(variableTrust !== undefined ? { variableTrust } : {}),
|
|
482
455
|
...(mask !== undefined ? { mask } : {}),
|
|
483
456
|
...(screen !== undefined ? { screen } : {}),
|
|
484
|
-
...(classification !== undefined ? { classification } : {}),
|
|
457
|
+
...(classification !== undefined ? { classification } : {}), ...(destination !== undefined ? { destination } : {}),
|
|
485
458
|
// Network-effect instrumentation (spec WS6): computed once at load,
|
|
486
459
|
// stamped on every telemetry row for this route.
|
|
487
460
|
fingerprintCell: (0, fingerprint_1.fingerprintSchema)(outputSchema)?.cellKey ?? null,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route OUTPUT contract at load — the `schema:` file reader and the `output:`
|
|
3
|
+
* block (GitLab issue #1, incident 2026-10-11: a prose route had no way to say
|
|
4
|
+
* "my output is not JSON" and was rejected `content_invalid` on every call).
|
|
5
|
+
*
|
|
6
|
+
* Carved out of routes/loader.ts (which sits at the 700-LOC cap, dev-rule P1):
|
|
7
|
+
* `readSchema` is a PURE MOVE; `parseOutputBlock` is new.
|
|
8
|
+
*
|
|
9
|
+
* YAML forms accepted for `output:`:
|
|
10
|
+
* (absent) → json (the default; byte-identical)
|
|
11
|
+
* output: json → json (explicit; identical to absent)
|
|
12
|
+
* output: text → text (prose/markdown, returned verbatim)
|
|
13
|
+
* output: { kind: text, min_chars: N } → text with a declared length floor
|
|
14
|
+
* output: { kind: json } → json
|
|
15
|
+
*
|
|
16
|
+
* The parsed result OMITS `outputKind` for json so a JSON route's bundle (and
|
|
17
|
+
* its `bundle_sha`) is unchanged; only `text` is ever carried.
|
|
18
|
+
*/
|
|
19
|
+
import type { RepairPolicy, Requirement, RouteVariant } from "../types/route";
|
|
20
|
+
export declare const OUTPUT_KINDS: ReadonlySet<string>;
|
|
21
|
+
export declare const PROSE_DOCS_ANCHOR = "route-bundles.md#prose-and-markdown-output-output-text";
|
|
22
|
+
/** Resolve + parse the bundle's `schema:` file (null / absent ⇒ schema-less). */
|
|
23
|
+
export declare function readSchema(schemaRaw: unknown, bundleDir: string, problems: string[]): object | null;
|
|
24
|
+
export interface ParsedOutputBlock {
|
|
25
|
+
/** Present ONLY for `text` (json ⇒ omitted ⇒ byte-identical bundle). */
|
|
26
|
+
readonly outputKind?: "text";
|
|
27
|
+
readonly outputMinChars?: number;
|
|
28
|
+
}
|
|
29
|
+
/** What the loader already parsed that an `output: text` declaration must be
|
|
30
|
+
* consistent with — each conflict is a LOAD error that teaches, never a run-time
|
|
31
|
+
* surprise. */
|
|
32
|
+
export interface OutputBlockContext {
|
|
33
|
+
readonly outputSchema: object | null;
|
|
34
|
+
readonly schemaDeclared: boolean;
|
|
35
|
+
readonly require: readonly Requirement[];
|
|
36
|
+
readonly repair: RepairPolicy | undefined;
|
|
37
|
+
readonly variants: readonly RouteVariant[];
|
|
38
|
+
}
|
|
39
|
+
/** Parse the bundle's `output:` key. Pushes teaching problems; returns `{}` for
|
|
40
|
+
* json (absent / explicit) so the bundle spread adds nothing. */
|
|
41
|
+
export declare function parseOutputBlock(raw: unknown, ctx: OutputBlockContext, problems: string[]): ParsedOutputBlock;
|
|
42
|
+
//# sourceMappingURL=output-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-loader.d.ts","sourceRoot":"","sources":["../../src/routes/output-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAc,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE1F,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,MAAM,CAAyC,CAAC;AAGvF,eAAO,MAAM,iBAAiB,2DAA2D,CAAC;AAM1F,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAsBnG;AAED,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;eAEe;AACf,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;CAC5C;AAED;iEACiE;AACjE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAqD7G"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Route OUTPUT contract at load — the `schema:` file reader and the `output:`
|
|
4
|
+
* block (GitLab issue #1, incident 2026-10-11: a prose route had no way to say
|
|
5
|
+
* "my output is not JSON" and was rejected `content_invalid` on every call).
|
|
6
|
+
*
|
|
7
|
+
* Carved out of routes/loader.ts (which sits at the 700-LOC cap, dev-rule P1):
|
|
8
|
+
* `readSchema` is a PURE MOVE; `parseOutputBlock` is new.
|
|
9
|
+
*
|
|
10
|
+
* YAML forms accepted for `output:`:
|
|
11
|
+
* (absent) → json (the default; byte-identical)
|
|
12
|
+
* output: json → json (explicit; identical to absent)
|
|
13
|
+
* output: text → text (prose/markdown, returned verbatim)
|
|
14
|
+
* output: { kind: text, min_chars: N } → text with a declared length floor
|
|
15
|
+
* output: { kind: json } → json
|
|
16
|
+
*
|
|
17
|
+
* The parsed result OMITS `outputKind` for json so a JSON route's bundle (and
|
|
18
|
+
* its `bundle_sha`) is unchanged; only `text` is ever carried.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.PROSE_DOCS_ANCHOR = exports.OUTPUT_KINDS = void 0;
|
|
22
|
+
exports.readSchema = readSchema;
|
|
23
|
+
exports.parseOutputBlock = parseOutputBlock;
|
|
24
|
+
const node_fs_1 = require("node:fs");
|
|
25
|
+
const node_path_1 = require("node:path");
|
|
26
|
+
exports.OUTPUT_KINDS = new Set(["json", "text"]);
|
|
27
|
+
const OUTPUT_BLOCK_KEYS = new Set(["kind", "min_chars"]);
|
|
28
|
+
exports.PROSE_DOCS_ANCHOR = "route-bundles.md#prose-and-markdown-output-output-text";
|
|
29
|
+
function isRecord(v) {
|
|
30
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
31
|
+
}
|
|
32
|
+
/** Resolve + parse the bundle's `schema:` file (null / absent ⇒ schema-less). */
|
|
33
|
+
function readSchema(schemaRaw, bundleDir, problems) {
|
|
34
|
+
if (schemaRaw === null || schemaRaw === undefined)
|
|
35
|
+
return null;
|
|
36
|
+
if (typeof schemaRaw !== "string" || schemaRaw === "") {
|
|
37
|
+
problems.push("schema must be a relative path or null");
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const schemaPath = (0, node_path_1.resolve)(bundleDir, schemaRaw);
|
|
41
|
+
if (!(0, node_fs_1.existsSync)(schemaPath)) {
|
|
42
|
+
problems.push(`schema file not found: ${schemaRaw}`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const parsed = JSON.parse((0, node_fs_1.readFileSync)(schemaPath, "utf8"));
|
|
47
|
+
if (!isRecord(parsed)) {
|
|
48
|
+
problems.push(`schema file ${schemaRaw} must contain a JSON object`);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return parsed;
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
problems.push(`schema file ${schemaRaw} is not valid JSON: ${err.message}`);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Parse the bundle's `output:` key. Pushes teaching problems; returns `{}` for
|
|
59
|
+
* json (absent / explicit) so the bundle spread adds nothing. */
|
|
60
|
+
function parseOutputBlock(raw, ctx, problems) {
|
|
61
|
+
if (raw === undefined || raw === null)
|
|
62
|
+
return {};
|
|
63
|
+
let kind;
|
|
64
|
+
let minChars;
|
|
65
|
+
if (typeof raw === "string") {
|
|
66
|
+
kind = raw;
|
|
67
|
+
}
|
|
68
|
+
else if (isRecord(raw)) {
|
|
69
|
+
for (const key of Object.keys(raw)) {
|
|
70
|
+
if (!OUTPUT_BLOCK_KEYS.has(key)) {
|
|
71
|
+
problems.push(`output.${key} is not a known key — the block is {kind: json|text, min_chars?: integer >= 1}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
kind = raw.kind;
|
|
75
|
+
if (raw.min_chars !== undefined) {
|
|
76
|
+
if (typeof raw.min_chars !== "number" || !Number.isInteger(raw.min_chars) || raw.min_chars < 1) {
|
|
77
|
+
problems.push("output.min_chars must be an integer >= 1");
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
minChars = raw.min_chars;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
problems.push(`output must be "json", "text", or {kind, min_chars?} — got ${JSON.stringify(raw)}`);
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
88
|
+
if (typeof kind !== "string" || !exports.OUTPUT_KINDS.has(kind)) {
|
|
89
|
+
problems.push(`output "${String(kind)}" is not one of [json, text] — write \`output: text\` for a prose/markdown route, ` +
|
|
90
|
+
`or omit it for JSON (the default)`);
|
|
91
|
+
return {};
|
|
92
|
+
}
|
|
93
|
+
if (kind === "json") {
|
|
94
|
+
if (minChars !== undefined)
|
|
95
|
+
problems.push("output.min_chars applies to output: text only — a JSON route conforms to its schema instead");
|
|
96
|
+
return {};
|
|
97
|
+
}
|
|
98
|
+
// kind === "text": the prose contract must not contradict the JSON machinery.
|
|
99
|
+
if (ctx.schemaDeclared || ctx.outputSchema !== null) {
|
|
100
|
+
problems.push("output: text cannot be combined with schema: — a prose route has no JSON Schema to conform to. " +
|
|
101
|
+
"Remove `schema:` (or set it to null), or drop `output: text` to serve JSON");
|
|
102
|
+
}
|
|
103
|
+
if (ctx.require.includes("schema_conformant")) {
|
|
104
|
+
problems.push("output: text cannot require schema_conformant — there is no schema; remove it from `require`");
|
|
105
|
+
}
|
|
106
|
+
const repairDeclared = ctx.repair !== undefined || ctx.variants.some((v) => v.repair !== undefined);
|
|
107
|
+
if (repairDeclared) {
|
|
108
|
+
problems.push("repair: is the JSON repair rung and never runs on an output: text route — remove it (a prose " +
|
|
109
|
+
"response that fails min_chars is retried from the content_invalid budget instead)");
|
|
110
|
+
}
|
|
111
|
+
return { outputKind: "text", ...(minChars !== undefined ? { outputMinChars: minChars } : {}) };
|
|
112
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bundle's `prompt:` block at load — `prompt.system`, the per-call
|
|
3
|
+
* `prompt.user` (GitLab issue #5, R1), and `prompt.variables`.
|
|
4
|
+
*
|
|
5
|
+
* Carved out of routes/loader.ts (which sits at the 700-LOC cap, dev-rule P1):
|
|
6
|
+
* the `prompt.system` + `variables` handling is a PURE MOVE; `prompt.user` and
|
|
7
|
+
* the cache/system-only advisory are new.
|
|
8
|
+
*
|
|
9
|
+
* YAML forms accepted for `prompt:`:
|
|
10
|
+
* prompt: { system: <path>, variables: [...] } → today (byte-identical)
|
|
11
|
+
* prompt: { system: <path>, user: <path>, variables: [...] } → system + per-call user turn
|
|
12
|
+
* prompt: { user: <path>, variables: [...] } → user turn only (empty system)
|
|
13
|
+
*
|
|
14
|
+
* Both templates are files relative to the bundle (same rule as `schema:`);
|
|
15
|
+
* both render with the same variables, capability conditionals and `x-trust`
|
|
16
|
+
* removal. `prompt.user` must be a non-empty file — an empty user turn next to
|
|
17
|
+
* a cache handle would send the handle and nothing else, the exact trap R1
|
|
18
|
+
* closes.
|
|
19
|
+
*/
|
|
20
|
+
import type { CandidateSpec } from "../types/route";
|
|
21
|
+
export declare const CACHE_PROMPT_DOCS_ANCHOR = "caching-lifecycle.md#a-cache-handle-changes-where-the-template-is-delivered";
|
|
22
|
+
export interface ParsedPromptBlock {
|
|
23
|
+
readonly systemTemplate: string;
|
|
24
|
+
/** Present ONLY when `prompt.user` was declared (absent ⇒ byte-identical bundle). */
|
|
25
|
+
readonly userTemplate?: string;
|
|
26
|
+
readonly variables: readonly string[];
|
|
27
|
+
readonly variableTrust?: Record<string, "untrusted">;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse the bundle's `prompt:` block. `prompt.system` stays REQUIRED unless
|
|
31
|
+
* `prompt.user` is declared (a user-turn-only route has an empty system
|
|
32
|
+
* template — the shape a Gemini cache handle wants, since the cache already
|
|
33
|
+
* holds the system content). Returns `systemTemplate: ""` on any problem so the
|
|
34
|
+
* caller's later checks stay total; the collected problems fail the load.
|
|
35
|
+
*/
|
|
36
|
+
export declare function parsePromptBlock(raw: unknown, bundleDir: string, problems: string[]): ParsedPromptBlock;
|
|
37
|
+
/**
|
|
38
|
+
* Issue #5 (R1) advisory, P4 "errors teach": a route that opts into caching
|
|
39
|
+
* (`cache: auto`) AND has a Gemini candidate AND renders a non-empty system
|
|
40
|
+
* template with NO `prompt.user` is the shape that loses content the moment a
|
|
41
|
+
* customer passes a Gemini cache handle on `rig.run` — the handle forbids
|
|
42
|
+
* `systemInstruction`, so the rendered template is delivered as the user turn
|
|
43
|
+
* (never dropped), but the author almost certainly meant the cache to hold the
|
|
44
|
+
* prefix and `prompt.user` to hold the delta. Warn once at load naming the
|
|
45
|
+
* rule. Non-fatal: the route loads and serves as declared. Pure — unit-tested
|
|
46
|
+
* directly. Returns the warning line, or null.
|
|
47
|
+
*/
|
|
48
|
+
export declare function cachedRouteSystemOnlyWarning(route: string, cache: boolean, candidates: readonly CandidateSpec[], systemTemplate: string, userTemplate: string | undefined): string | null;
|
|
49
|
+
//# sourceMappingURL=prompt-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-loader.d.ts","sourceRoot":"","sources":["../../src/routes/prompt-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,eAAO,MAAM,wBAAwB,gFAAgF,CAAC;AAMtH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,qFAAqF;IACrF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACtD;AAkBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAiCvG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAYf"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The bundle's `prompt:` block at load — `prompt.system`, the per-call
|
|
4
|
+
* `prompt.user` (GitLab issue #5, R1), and `prompt.variables`.
|
|
5
|
+
*
|
|
6
|
+
* Carved out of routes/loader.ts (which sits at the 700-LOC cap, dev-rule P1):
|
|
7
|
+
* the `prompt.system` + `variables` handling is a PURE MOVE; `prompt.user` and
|
|
8
|
+
* the cache/system-only advisory are new.
|
|
9
|
+
*
|
|
10
|
+
* YAML forms accepted for `prompt:`:
|
|
11
|
+
* prompt: { system: <path>, variables: [...] } → today (byte-identical)
|
|
12
|
+
* prompt: { system: <path>, user: <path>, variables: [...] } → system + per-call user turn
|
|
13
|
+
* prompt: { user: <path>, variables: [...] } → user turn only (empty system)
|
|
14
|
+
*
|
|
15
|
+
* Both templates are files relative to the bundle (same rule as `schema:`);
|
|
16
|
+
* both render with the same variables, capability conditionals and `x-trust`
|
|
17
|
+
* removal. `prompt.user` must be a non-empty file — an empty user turn next to
|
|
18
|
+
* a cache handle would send the handle and nothing else, the exact trap R1
|
|
19
|
+
* closes.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.CACHE_PROMPT_DOCS_ANCHOR = void 0;
|
|
23
|
+
exports.parsePromptBlock = parsePromptBlock;
|
|
24
|
+
exports.cachedRouteSystemOnlyWarning = cachedRouteSystemOnlyWarning;
|
|
25
|
+
const node_fs_1 = require("node:fs");
|
|
26
|
+
const node_path_1 = require("node:path");
|
|
27
|
+
const screen_loader_1 = require("./screen-loader");
|
|
28
|
+
exports.CACHE_PROMPT_DOCS_ANCHOR = "caching-lifecycle.md#a-cache-handle-changes-where-the-template-is-delivered";
|
|
29
|
+
function isRecord(v) {
|
|
30
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
31
|
+
}
|
|
32
|
+
/** Read a template file named by `prompt.<key>` relative to the bundle. Pushes
|
|
33
|
+
* a teaching problem and returns null when the key is not a path or the file is
|
|
34
|
+
* missing. */
|
|
35
|
+
function readTemplateFile(raw, key, bundleDir, problems) {
|
|
36
|
+
if (typeof raw !== "string" || raw === "") {
|
|
37
|
+
problems.push(`prompt.${key} must be a relative path`);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const path = (0, node_path_1.resolve)(bundleDir, raw);
|
|
41
|
+
if (!(0, node_fs_1.existsSync)(path)) {
|
|
42
|
+
problems.push(`prompt.${key} file not found: ${raw}`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return (0, node_fs_1.readFileSync)(path, "utf8");
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse the bundle's `prompt:` block. `prompt.system` stays REQUIRED unless
|
|
49
|
+
* `prompt.user` is declared (a user-turn-only route has an empty system
|
|
50
|
+
* template — the shape a Gemini cache handle wants, since the cache already
|
|
51
|
+
* holds the system content). Returns `systemTemplate: ""` on any problem so the
|
|
52
|
+
* caller's later checks stay total; the collected problems fail the load.
|
|
53
|
+
*/
|
|
54
|
+
function parsePromptBlock(raw, bundleDir, problems) {
|
|
55
|
+
if (!isRecord(raw)) {
|
|
56
|
+
problems.push("prompt.system must be a relative path");
|
|
57
|
+
return { systemTemplate: "", variables: [] };
|
|
58
|
+
}
|
|
59
|
+
const userDeclared = raw.user !== undefined && raw.user !== null;
|
|
60
|
+
let systemTemplate = "";
|
|
61
|
+
if (raw.system !== undefined && raw.system !== null) {
|
|
62
|
+
systemTemplate = readTemplateFile(raw.system, "system", bundleDir, problems) ?? "";
|
|
63
|
+
}
|
|
64
|
+
else if (!userDeclared) {
|
|
65
|
+
problems.push("prompt.system must be a relative path");
|
|
66
|
+
}
|
|
67
|
+
let userTemplate;
|
|
68
|
+
if (userDeclared) {
|
|
69
|
+
const text = readTemplateFile(raw.user, "user", bundleDir, problems);
|
|
70
|
+
if (text !== null) {
|
|
71
|
+
if (text.trim() === "") {
|
|
72
|
+
problems.push(`prompt.user file is empty: ${String(raw.user)} — the user turn must carry content (with a cache handle ` +
|
|
73
|
+
`it is the ONLY per-call content the model sees; omit prompt.user to keep the fixed trigger)`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
userTemplate = text;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const parsed = (0, screen_loader_1.parseVariables)(raw.variables ?? [], problems);
|
|
81
|
+
return {
|
|
82
|
+
systemTemplate,
|
|
83
|
+
...(userTemplate !== undefined ? { userTemplate } : {}),
|
|
84
|
+
variables: parsed.names,
|
|
85
|
+
...(parsed.trust !== undefined ? { variableTrust: parsed.trust } : {}),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Issue #5 (R1) advisory, P4 "errors teach": a route that opts into caching
|
|
90
|
+
* (`cache: auto`) AND has a Gemini candidate AND renders a non-empty system
|
|
91
|
+
* template with NO `prompt.user` is the shape that loses content the moment a
|
|
92
|
+
* customer passes a Gemini cache handle on `rig.run` — the handle forbids
|
|
93
|
+
* `systemInstruction`, so the rendered template is delivered as the user turn
|
|
94
|
+
* (never dropped), but the author almost certainly meant the cache to hold the
|
|
95
|
+
* prefix and `prompt.user` to hold the delta. Warn once at load naming the
|
|
96
|
+
* rule. Non-fatal: the route loads and serves as declared. Pure — unit-tested
|
|
97
|
+
* directly. Returns the warning line, or null.
|
|
98
|
+
*/
|
|
99
|
+
function cachedRouteSystemOnlyWarning(route, cache, candidates, systemTemplate, userTemplate) {
|
|
100
|
+
if (!cache)
|
|
101
|
+
return null;
|
|
102
|
+
if (userTemplate !== undefined)
|
|
103
|
+
return null;
|
|
104
|
+
if (systemTemplate.trim() === "")
|
|
105
|
+
return null;
|
|
106
|
+
if (!candidates.some((c) => c.provider === "gemini"))
|
|
107
|
+
return null;
|
|
108
|
+
return (`route "${route}" declares cache: with a Gemini candidate, a non-empty prompt.system and no prompt.user. ` +
|
|
109
|
+
`A Gemini cache handle (rig.run(..., { cache: { key, provider: "gemini" } })) forbids systemInstruction, so ` +
|
|
110
|
+
`on a cached dispatch the rendered system template is delivered AS THE USER TURN (prompt_delivery: ` +
|
|
111
|
+
`"user+cache") — never dropped, but probably not what you meant. Put the shared prefix in the cache ` +
|
|
112
|
+
`resource and the per-call delta in a \`prompt.user\` template (see ${exports.CACHE_PROMPT_DOCS_ANCHOR}).`);
|
|
113
|
+
}
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
import type { LoadedRoutes } from "./loader";
|
|
28
28
|
import type { ScreenPolicy } from "../screen/types";
|
|
29
29
|
import type { ResolvedMaskPolicy } from "../mask/types";
|
|
30
|
+
import type { Manifest } from "../prompts/manifest";
|
|
30
31
|
import type { CandidateSpec, Preference, RepairPolicy, Requirement, RouteBundle, RoutePolicy, RouteVariant } from "../types/route";
|
|
31
32
|
/**
|
|
32
33
|
* The canonical, JSON-serialisable form of a resolved route bundle. Every field
|
|
@@ -39,11 +40,22 @@ export interface ResolvedRouteBundle {
|
|
|
39
40
|
readonly version: number;
|
|
40
41
|
/** Resolved, parsed JSON Schema (null = unstructured route). Inlined at sync. */
|
|
41
42
|
readonly outputSchema: object | null;
|
|
43
|
+
/** Issue #1 — `output: text`. Carried ONLY as `"text"` (a json route omits the
|
|
44
|
+
* key, so its `bundle_sha` is unchanged); the hosted/mirror lane rebuilds the
|
|
45
|
+
* same prose contract and never JSON-parses the response. `outputMinChars` is
|
|
46
|
+
* the declared floor, text routes only. Absent ⇒ json ⇒ byte-identical. */
|
|
47
|
+
readonly outputKind?: "text";
|
|
48
|
+
readonly outputMinChars?: number;
|
|
42
49
|
readonly candidates: readonly CandidateSpec[];
|
|
43
50
|
readonly require: readonly Requirement[];
|
|
44
51
|
readonly prefer: readonly Preference[];
|
|
45
52
|
/** Raw template text — the prompt FILE, inlined at sync. */
|
|
46
53
|
readonly systemTemplate: string;
|
|
54
|
+
/** Issue #5 (R1) — the per-call `prompt.user` template, inlined at sync and
|
|
55
|
+
* carried ONLY when declared (absent ⇒ the fixed trigger ⇒ unchanged
|
|
56
|
+
* `bundle_sha`), so the hosted/mirror lane renders the same user turn and a
|
|
57
|
+
* cache handle composes there too. */
|
|
58
|
+
readonly userTemplate?: string;
|
|
47
59
|
readonly variables: readonly string[];
|
|
48
60
|
readonly policy: RoutePolicy;
|
|
49
61
|
readonly repair?: RepairPolicy;
|
|
@@ -81,6 +93,13 @@ export interface ResolvedRouteBundle {
|
|
|
81
93
|
* always re-resolves on the mirror and needs no export refusal. Absent ⇒ no
|
|
82
94
|
* masking (byte-identical). */
|
|
83
95
|
readonly mask?: ResolvedMaskPolicy;
|
|
96
|
+
/** PSR-2 (spec §2.1/§3) — the served prompt's assembly manifest (structure-only).
|
|
97
|
+
* A promote writes the promoted `prompt_versions` row's `manifest` through into
|
|
98
|
+
* `routes.bundle` alongside the `systemTemplate`, and recomputes `bundle_sha`
|
|
99
|
+
* over this whole object — so the served projection carries the manifest the
|
|
100
|
+
* client-fill engine (PSR-2b) resolves against. Absent ⇒ no PSR manifest
|
|
101
|
+
* (byte-identical to a pre-PSR mirror). Additive & optional. */
|
|
102
|
+
readonly manifest?: Manifest;
|
|
84
103
|
}
|
|
85
104
|
/** Project an already-loaded (resolved) bundle to its serialisable form. Pure —
|
|
86
105
|
* no filesystem; the loader already followed every file reference. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolved-bundle.d.ts","sourceRoot":"","sources":["../../src/routes/resolved-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;iFAC6E;IAC7E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpD;;;;2BAIuB;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/D;;;;;;;;;;;mBAWe;IACf,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC;;;;;;;mCAO+B;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"resolved-bundle.d.ts","sourceRoot":"","sources":["../../src/routes/resolved-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;+EAG2E;IAC3E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;0CAGsC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;iFAC6E;IAC7E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACpD;;;;2BAIuB;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/D;;;;;;;;;;;mBAWe;IACf,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC;;;;;;;mCAO+B;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC;IACnC;;;;;oEAKgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC9B;AAED;sEACsE;AACtE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,CA8B3E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAe1D;AAiBD,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEvE;AAED;gFACgF;AAChF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAoE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAclE"}
|
|
@@ -43,10 +43,14 @@ function resolveRouteBundle(bundle) {
|
|
|
43
43
|
route: bundle.route,
|
|
44
44
|
version: bundle.version,
|
|
45
45
|
outputSchema: bundle.outputSchema,
|
|
46
|
+
// Issue #1: prose contract crosses the wire (text only; json adds no key).
|
|
47
|
+
...(bundle.outputKind === "text" ? { outputKind: "text" } : {}),
|
|
48
|
+
...(bundle.outputKind === "text" && bundle.outputMinChars !== undefined ? { outputMinChars: bundle.outputMinChars } : {}),
|
|
46
49
|
candidates: bundle.candidates,
|
|
47
50
|
require: bundle.require,
|
|
48
51
|
prefer: bundle.prefer,
|
|
49
52
|
systemTemplate: bundle.systemTemplate,
|
|
53
|
+
...(bundle.userTemplate !== undefined ? { userTemplate: bundle.userTemplate } : {}), // issue #5 (R1)
|
|
50
54
|
variables: bundle.variables,
|
|
51
55
|
policy: bundle.policy,
|
|
52
56
|
...(bundle.repair !== undefined ? { repair: bundle.repair } : {}),
|
|
@@ -60,6 +64,9 @@ function resolveRouteBundle(bundle) {
|
|
|
60
64
|
// silently inert on the hosted lane. Absent ⇒ omitted ⇒ byte-identical.
|
|
61
65
|
...(bundle.screen !== undefined ? { screenPolicy: bundle.screen.policy } : {}),
|
|
62
66
|
...(bundle.mask !== undefined ? { mask: bundle.mask } : {}),
|
|
67
|
+
// PSR-2: carry the served prompt's manifest so promote's write-through and the
|
|
68
|
+
// round-trip both preserve it. Absent ⇒ omitted ⇒ byte-identical.
|
|
69
|
+
...(bundle.manifest !== undefined ? { manifest: bundle.manifest } : {}),
|
|
63
70
|
};
|
|
64
71
|
}
|
|
65
72
|
/**
|
|
@@ -145,14 +152,28 @@ function bundleFromResolved(raw) {
|
|
|
145
152
|
throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" is missing \`policy\``);
|
|
146
153
|
}
|
|
147
154
|
const outputSchema = b.outputSchema ?? null;
|
|
155
|
+
// Issue #1: a mirrored `output: text` route rebuilds as text (never JSON-parsed
|
|
156
|
+
// on the hosted lane). Anything but the literal "text" ⇒ json (byte-identical);
|
|
157
|
+
// text + a schema is a corrupt mirror (the loader refuses that pair at author).
|
|
158
|
+
const outputKind = b.outputKind === "text" ? "text" : undefined;
|
|
159
|
+
if (outputKind === "text" && outputSchema !== null) {
|
|
160
|
+
throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" declares output: text AND a schema — remove one`);
|
|
161
|
+
}
|
|
162
|
+
const minChars = b.outputMinChars;
|
|
163
|
+
const outputMinChars = outputKind === "text" && typeof minChars === "number" && Number.isInteger(minChars) && minChars >= 1 ? minChars : undefined;
|
|
148
164
|
return Object.freeze({
|
|
149
165
|
route: b.route,
|
|
150
166
|
version: b.version,
|
|
151
167
|
outputSchema: outputSchema === null ? null : Object.freeze(outputSchema),
|
|
168
|
+
...(outputKind !== undefined ? { outputKind } : {}),
|
|
169
|
+
...(outputMinChars !== undefined ? { outputMinChars } : {}),
|
|
152
170
|
candidates: Object.freeze([...b.candidates]),
|
|
153
171
|
require: Object.freeze([...(b.require ?? [])]),
|
|
154
172
|
prefer: Object.freeze([...(b.prefer ?? [])]),
|
|
155
173
|
systemTemplate: b.systemTemplate,
|
|
174
|
+
// Issue #5 (R1): a mirrored `prompt.user` rebuilds as the user turn; anything
|
|
175
|
+
// but a non-empty string ⇒ absent ⇒ the fixed trigger (byte-identical).
|
|
176
|
+
...(typeof b.userTemplate === "string" && b.userTemplate !== "" ? { userTemplate: b.userTemplate } : {}),
|
|
156
177
|
variables: Object.freeze([...(b.variables ?? [])]),
|
|
157
178
|
policy: b.policy,
|
|
158
179
|
...(b.repair !== undefined ? { repair: b.repair } : {}),
|
|
@@ -171,6 +192,9 @@ function bundleFromResolved(raw) {
|
|
|
171
192
|
// Mask carries its FULLY-RESOLVED policy (entries inlined) — passed through,
|
|
172
193
|
// re-materialising byte-identically so `mask: block` is never inert.
|
|
173
194
|
...(b.mask !== undefined ? { mask: b.mask } : {}),
|
|
195
|
+
// PSR-2: the served prompt's structure-only manifest, passed through whole
|
|
196
|
+
// (no re-resolve — it carries no filesystem/closure state). Absent ⇒ omitted.
|
|
197
|
+
...(b.manifest !== undefined ? { manifest: b.manifest } : {}),
|
|
174
198
|
// Recomputed, never trusted from the wire — cannot drift from the schema.
|
|
175
199
|
fingerprintCell: (0, fingerprint_1.fingerprintSchema)(outputSchema)?.cellKey ?? null,
|
|
176
200
|
});
|
|
@@ -35,7 +35,7 @@ export declare function parseClassificationAndPhiGate(raw: unknown, ctx: {
|
|
|
35
35
|
/** Push a problem for every `{{var}}` referenced in the system template or the
|
|
36
36
|
* grounding query that was not declared in `prompt.variables`. Colocated with
|
|
37
37
|
* the variable parser it validates. */
|
|
38
|
-
export declare function pushUndeclaredVariableProblems(systemTemplate: string, groundingQuery: string | undefined, variables: readonly string[], problems: string[]): void;
|
|
38
|
+
export declare function pushUndeclaredVariableProblems(systemTemplate: string, groundingQuery: string | undefined, variables: readonly string[], problems: string[], userTemplate?: string): void;
|
|
39
39
|
/** Parse `prompt.variables` — each entry is a bare name (semi, stays in the
|
|
40
40
|
* system slot — the default) or `{name, "x-trust": "untrusted"}` (spotlighted out
|
|
41
41
|
* of the system slot, S2). Returns the declared names and, when any variable is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen-loader.d.ts","sourceRoot":"","sources":["../../src/routes/screen-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAG5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMlD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,oBAAoB,GAAG,SAAS,CAUnG;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE;IAAE,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAAC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE,EAClG,QAAQ,EAAE,MAAM,EAAE,GACjB,kBAAkB,GAAG,SAAS,CAYhC;AAED;;uCAEuC;AACvC,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"screen-loader.d.ts","sourceRoot":"","sources":["../../src/routes/screen-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAG5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMlD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,oBAAoB,GAAG,SAAS,CAUnG;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE;IAAE,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAAC,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE,EAClG,QAAQ,EAAE,MAAM,EAAE,GACjB,kBAAkB,GAAG,SAAS,CAYhC;AAED;;uCAEuC;AACvC,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,EAAE,MAAM,EAAE,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,IAAI,CAqBN;AAED;;;iFAGiF;AACjF,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,GACjB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;CAAE,CAwB5E;AAED;;iFAEiF;AACjF,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,QAAQ,EAAE,MAAM,EAAE,GACjB,QAAQ,GAAG,WAAW,GAAG,SAAS,CAQpC"}
|