@riddledc/riddle-proof 0.7.90 → 0.7.92

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.
@@ -3097,6 +3097,10 @@ function textMatches(sample, check) {
3097
3097
  }
3098
3098
  return String(sample || "").includes(check.text || "");
3099
3099
  }
3100
+ function profileCheckAppliesToViewport(check, viewport) {
3101
+ if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
3102
+ return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
3103
+ }
3100
3104
  function setupActionType(action) {
3101
3105
  return String(action && action.type ? action.type : "").replace(/-/g, "_");
3102
3106
  }
@@ -3114,6 +3118,30 @@ function setupTextMatches(sample, action) {
3114
3118
  }
3115
3119
  return String(sample || "").includes(action.text || "");
3116
3120
  }
3121
+ async function waitForAnyVisibleSelector(context, selector, timeout) {
3122
+ const deadline = Date.now() + setupNumber(timeout, 15000);
3123
+ let lastReason = "selector_not_found";
3124
+ while (Date.now() <= deadline) {
3125
+ try {
3126
+ const locator = context.locator(selector);
3127
+ const count = await locator.count();
3128
+ if (!count) {
3129
+ lastReason = "selector_not_found";
3130
+ } else {
3131
+ lastReason = "no_visible_match";
3132
+ for (let index = 0; index < count; index += 1) {
3133
+ if (await locator.nth(index).isVisible().catch(() => false)) {
3134
+ return { ok: true, count, index };
3135
+ }
3136
+ }
3137
+ }
3138
+ } catch (error) {
3139
+ lastReason = String(error && error.message ? error.message : error).slice(0, 500);
3140
+ }
3141
+ await page.waitForTimeout(200);
3142
+ }
3143
+ throw new Error("No visible match for selector " + selector + ": " + lastReason);
3144
+ }
3117
3145
  function setupHasOwn(action, key) {
3118
3146
  return Boolean(action) && Object.keys(action).includes(key);
3119
3147
  }
@@ -3447,7 +3475,7 @@ async function executeSetupAction(action, ordinal, viewport) {
3447
3475
  if (type === "wait_for_selector") {
3448
3476
  const scope = await setupActionScope(action, timeout);
3449
3477
  if (!scope.ok) return setupScopeFailure(base, scope);
3450
- await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
3478
+ await waitForAnyVisibleSelector(scope.context, action.selector, timeout);
3451
3479
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
3452
3480
  }
3453
3481
  if (type === "drag") {
@@ -4463,7 +4491,7 @@ async function collectRouteInventory(check, viewport) {
4463
4491
  try {
4464
4492
  await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 90000 });
4465
4493
  if (profile.target.wait_for_selector) {
4466
- await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 }).catch(() => {});
4494
+ await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000).catch(() => {});
4467
4495
  }
4468
4496
  const index = await findInventoryLinkIndex(check, expectedRoute.path);
4469
4497
  if (index < 0) {
@@ -4522,7 +4550,7 @@ async function captureViewport(viewport) {
4522
4550
  }
4523
4551
  if (!navigationError && profile.target.wait_for_selector) {
4524
4552
  try {
4525
- await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 });
4553
+ await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000);
4526
4554
  } catch (error) {
4527
4555
  waitError = String(error && error.message ? error.message : error).slice(0, 1000);
4528
4556
  }
@@ -4626,6 +4654,7 @@ async function captureViewport(viewport) {
4626
4654
  const text_matches = {};
4627
4655
  const link_statuses = {};
4628
4656
  for (const check of profile.checks || []) {
4657
+ if (!profileCheckAppliesToViewport(check, viewport)) continue;
4629
4658
  if (
4630
4659
  (
4631
4660
  check.type === "selector_visible"
@@ -4661,7 +4690,7 @@ async function captureViewport(viewport) {
4661
4690
  pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
4662
4691
  }
4663
4692
  let routeInventory;
4664
- const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
4693
+ const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory" && profileCheckAppliesToViewport(check, viewport));
4665
4694
  const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
4666
4695
  if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
4667
4696
  try {
@@ -4766,7 +4795,7 @@ function buildProfileEvidence(currentViewports) {
4766
4795
  })),
4767
4796
  })),
4768
4797
  link_status: currentViewports
4769
- .filter((viewport) => viewport.link_statuses)
4798
+ .filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
4770
4799
  .map((viewport) => ({
4771
4800
  viewport: viewport.name,
4772
4801
  selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
@@ -48,12 +48,13 @@ async function riddleRequestJson(config, pathname, init = {}) {
48
48
  if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
49
49
  return json ?? text;
50
50
  }
51
- async function deployRiddleStaticPreview(config, directory, label) {
51
+ async function deployRiddlePreview(config, directory, label, framework = "static") {
52
52
  if (!directory?.trim()) throw new Error("directory is required");
53
53
  if (!label?.trim()) throw new Error("label is required");
54
+ if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
54
55
  const created = await riddleRequestJson(config, "/v1/preview", {
55
56
  method: "POST",
56
- body: JSON.stringify({ framework: "static", label })
57
+ body: JSON.stringify({ framework, label })
57
58
  });
58
59
  const id = String(created.id || "");
59
60
  const uploadUrl = String(created.upload_url || "");
@@ -80,6 +81,7 @@ async function deployRiddleStaticPreview(config, directory, label) {
80
81
  ok: true,
81
82
  id: String(published.id || id),
82
83
  label,
84
+ framework,
83
85
  preview_url: String(published.preview_url || ""),
84
86
  file_count: typeof published.file_count === "number" ? published.file_count : void 0,
85
87
  total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
@@ -87,6 +89,9 @@ async function deployRiddleStaticPreview(config, directory, label) {
87
89
  raw: published
88
90
  };
89
91
  }
92
+ async function deployRiddleStaticPreview(config, directory, label) {
93
+ return deployRiddlePreview(config, directory, label, "static");
94
+ }
90
95
  function createTarball(directory, label, exclude = []) {
91
96
  const scratch = mkdtempSync(path.join(tmpdir(), "riddle-upload-"));
92
97
  const tarball = path.join(scratch, `${label}.tar.gz`);
@@ -318,6 +323,7 @@ async function pollRiddleJob(config, jobId, options = {}) {
318
323
  function createRiddleApiClient(config = {}) {
319
324
  return {
320
325
  requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
326
+ deployPreview: (directory, label, framework = "static") => deployRiddlePreview(config, directory, label, framework),
321
327
  deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
322
328
  runScript: (input) => runRiddleScript(config, input),
323
329
  runServerPreview: (input) => runRiddleServerPreview(config, input),
@@ -331,6 +337,7 @@ export {
331
337
  RiddleApiError,
332
338
  resolveRiddleApiKey,
333
339
  riddleRequestJson,
340
+ deployRiddlePreview,
334
341
  deployRiddleStaticPreview,
335
342
  parseRiddleViewport,
336
343
  runRiddleServerPreview,
package/dist/cli.cjs CHANGED
@@ -6609,12 +6609,13 @@ async function riddleRequestJson(config, pathname, init = {}) {
6609
6609
  if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
6610
6610
  return json ?? text;
6611
6611
  }
6612
- async function deployRiddleStaticPreview(config, directory, label) {
6612
+ async function deployRiddlePreview(config, directory, label, framework = "static") {
6613
6613
  if (!directory?.trim()) throw new Error("directory is required");
6614
6614
  if (!label?.trim()) throw new Error("label is required");
6615
+ if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
6615
6616
  const created = await riddleRequestJson(config, "/v1/preview", {
6616
6617
  method: "POST",
6617
- body: JSON.stringify({ framework: "static", label })
6618
+ body: JSON.stringify({ framework, label })
6618
6619
  });
6619
6620
  const id = String(created.id || "");
6620
6621
  const uploadUrl = String(created.upload_url || "");
@@ -6641,6 +6642,7 @@ async function deployRiddleStaticPreview(config, directory, label) {
6641
6642
  ok: true,
6642
6643
  id: String(published.id || id),
6643
6644
  label,
6645
+ framework,
6644
6646
  preview_url: String(published.preview_url || ""),
6645
6647
  file_count: typeof published.file_count === "number" ? published.file_count : void 0,
6646
6648
  total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
@@ -6648,6 +6650,9 @@ async function deployRiddleStaticPreview(config, directory, label) {
6648
6650
  raw: published
6649
6651
  };
6650
6652
  }
6653
+ async function deployRiddleStaticPreview(config, directory, label) {
6654
+ return deployRiddlePreview(config, directory, label, "static");
6655
+ }
6651
6656
  function createTarball(directory, label, exclude = []) {
6652
6657
  const scratch = (0, import_node_fs5.mkdtempSync)(import_node_path5.default.join((0, import_node_os2.tmpdir)(), "riddle-upload-"));
6653
6658
  const tarball = import_node_path5.default.join(scratch, `${label}.tar.gz`);
@@ -6879,6 +6884,7 @@ async function pollRiddleJob(config, jobId, options = {}) {
6879
6884
  function createRiddleApiClient(config = {}) {
6880
6885
  return {
6881
6886
  requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
6887
+ deployPreview: (directory, label, framework = "static") => deployRiddlePreview(config, directory, label, framework),
6882
6888
  deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
6883
6889
  runScript: (input) => runRiddleScript(config, input),
6884
6890
  runServerPreview: (input) => runRiddleServerPreview(config, input),
@@ -9968,6 +9974,10 @@ function textMatches(sample, check) {
9968
9974
  }
9969
9975
  return String(sample || "").includes(check.text || "");
9970
9976
  }
9977
+ function profileCheckAppliesToViewport(check, viewport) {
9978
+ if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
9979
+ return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
9980
+ }
9971
9981
  function setupActionType(action) {
9972
9982
  return String(action && action.type ? action.type : "").replace(/-/g, "_");
9973
9983
  }
@@ -9985,6 +9995,30 @@ function setupTextMatches(sample, action) {
9985
9995
  }
9986
9996
  return String(sample || "").includes(action.text || "");
9987
9997
  }
9998
+ async function waitForAnyVisibleSelector(context, selector, timeout) {
9999
+ const deadline = Date.now() + setupNumber(timeout, 15000);
10000
+ let lastReason = "selector_not_found";
10001
+ while (Date.now() <= deadline) {
10002
+ try {
10003
+ const locator = context.locator(selector);
10004
+ const count = await locator.count();
10005
+ if (!count) {
10006
+ lastReason = "selector_not_found";
10007
+ } else {
10008
+ lastReason = "no_visible_match";
10009
+ for (let index = 0; index < count; index += 1) {
10010
+ if (await locator.nth(index).isVisible().catch(() => false)) {
10011
+ return { ok: true, count, index };
10012
+ }
10013
+ }
10014
+ }
10015
+ } catch (error) {
10016
+ lastReason = String(error && error.message ? error.message : error).slice(0, 500);
10017
+ }
10018
+ await page.waitForTimeout(200);
10019
+ }
10020
+ throw new Error("No visible match for selector " + selector + ": " + lastReason);
10021
+ }
9988
10022
  function setupHasOwn(action, key) {
9989
10023
  return Boolean(action) && Object.keys(action).includes(key);
9990
10024
  }
@@ -10318,7 +10352,7 @@ async function executeSetupAction(action, ordinal, viewport) {
10318
10352
  if (type === "wait_for_selector") {
10319
10353
  const scope = await setupActionScope(action, timeout);
10320
10354
  if (!scope.ok) return setupScopeFailure(base, scope);
10321
- await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
10355
+ await waitForAnyVisibleSelector(scope.context, action.selector, timeout);
10322
10356
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
10323
10357
  }
10324
10358
  if (type === "drag") {
@@ -11334,7 +11368,7 @@ async function collectRouteInventory(check, viewport) {
11334
11368
  try {
11335
11369
  await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 90000 });
11336
11370
  if (profile.target.wait_for_selector) {
11337
- await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 }).catch(() => {});
11371
+ await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000).catch(() => {});
11338
11372
  }
11339
11373
  const index = await findInventoryLinkIndex(check, expectedRoute.path);
11340
11374
  if (index < 0) {
@@ -11393,7 +11427,7 @@ async function captureViewport(viewport) {
11393
11427
  }
11394
11428
  if (!navigationError && profile.target.wait_for_selector) {
11395
11429
  try {
11396
- await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 });
11430
+ await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000);
11397
11431
  } catch (error) {
11398
11432
  waitError = String(error && error.message ? error.message : error).slice(0, 1000);
11399
11433
  }
@@ -11497,6 +11531,7 @@ async function captureViewport(viewport) {
11497
11531
  const text_matches = {};
11498
11532
  const link_statuses = {};
11499
11533
  for (const check of profile.checks || []) {
11534
+ if (!profileCheckAppliesToViewport(check, viewport)) continue;
11500
11535
  if (
11501
11536
  (
11502
11537
  check.type === "selector_visible"
@@ -11532,7 +11567,7 @@ async function captureViewport(viewport) {
11532
11567
  pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
11533
11568
  }
11534
11569
  let routeInventory;
11535
- const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
11570
+ const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory" && profileCheckAppliesToViewport(check, viewport));
11536
11571
  const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
11537
11572
  if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
11538
11573
  try {
@@ -11637,7 +11672,7 @@ function buildProfileEvidence(currentViewports) {
11637
11672
  })),
11638
11673
  })),
11639
11674
  link_status: currentViewports
11640
- .filter((viewport) => viewport.link_statuses)
11675
+ .filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
11641
11676
  .map((viewport) => ({
11642
11677
  viewport: viewport.name,
11643
11678
  selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
@@ -11792,7 +11827,7 @@ function usage() {
11792
11827
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
11793
11828
  " riddle-proof-loop status --state-path <path>",
11794
11829
  " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--quiet]",
11795
- " riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
11830
+ " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
11796
11831
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
11797
11832
  " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
11798
11833
  " riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
@@ -11856,6 +11891,11 @@ function optionNumber(options, ...keys) {
11856
11891
  function profileOutputDirOption(options) {
11857
11892
  return optionString(options, "output") ?? optionString(options, "outputDir");
11858
11893
  }
11894
+ function previewFrameworkOption(options) {
11895
+ const framework = optionString(options, "framework") ?? "static";
11896
+ if (framework === "spa" || framework === "static") return framework;
11897
+ throw new Error("--framework must be spa or static.");
11898
+ }
11859
11899
  function readStdin() {
11860
11900
  return (0, import_node_fs6.readFileSync)(0, "utf-8");
11861
11901
  }
@@ -12568,7 +12608,7 @@ async function main() {
12568
12608
  if (command === "riddle-preview-deploy") {
12569
12609
  const buildDir = positional[1];
12570
12610
  const label = positional[2];
12571
- const result = await createRiddleApiClient(riddleClientConfig(options)).deployStaticPreview(buildDir, label);
12611
+ const result = await createRiddleApiClient(riddleClientConfig(options)).deployPreview(buildDir, label, previewFrameworkOption(options));
12572
12612
  process.stdout.write(`${JSON.stringify(result, null, 2)}
12573
12613
  `);
12574
12614
  return;
package/dist/cli.js CHANGED
@@ -10,11 +10,11 @@ import {
10
10
  profileStatusExitCode,
11
11
  resolveRiddleProofProfileTargetUrl,
12
12
  resolveRiddleProofProfileTimeoutSec
13
- } from "./chunk-4FMBHM4E.js";
13
+ } from "./chunk-2SGLFPFX.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport
17
- } from "./chunk-6RQGBHJ5.js";
17
+ } from "./chunk-OI57LO6Y.js";
18
18
  import {
19
19
  createDisabledRiddleProofAgentAdapter,
20
20
  readRiddleProofRunStatus,
@@ -45,7 +45,7 @@ function usage() {
45
45
  " riddle-proof-loop respond --state-path <path> --decision <decision> --summary <text> [--payload-json <file|json|->]",
46
46
  " riddle-proof-loop status --state-path <path>",
47
47
  " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--strict true|false] [--poll-attempts n] [--output <dir>|--output-dir <dir>] [--quiet]",
48
- " riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
48
+ " riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
49
49
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
50
50
  " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
51
51
  " riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
@@ -109,6 +109,11 @@ function optionNumber(options, ...keys) {
109
109
  function profileOutputDirOption(options) {
110
110
  return optionString(options, "output") ?? optionString(options, "outputDir");
111
111
  }
112
+ function previewFrameworkOption(options) {
113
+ const framework = optionString(options, "framework") ?? "static";
114
+ if (framework === "spa" || framework === "static") return framework;
115
+ throw new Error("--framework must be spa or static.");
116
+ }
112
117
  function readStdin() {
113
118
  return readFileSync(0, "utf-8");
114
119
  }
@@ -821,7 +826,7 @@ async function main() {
821
826
  if (command === "riddle-preview-deploy") {
822
827
  const buildDir = positional[1];
823
828
  const label = positional[2];
824
- const result = await createRiddleApiClient(riddleClientConfig(options)).deployStaticPreview(buildDir, label);
829
+ const result = await createRiddleApiClient(riddleClientConfig(options)).deployPreview(buildDir, label, previewFrameworkOption(options));
825
830
  process.stdout.write(`${JSON.stringify(result, null, 2)}
826
831
  `);
827
832
  return;
package/dist/index.cjs CHANGED
@@ -2968,6 +2968,7 @@ __export(index_exports, {
2968
2968
  createRunResult: () => createRunResult,
2969
2969
  createRunState: () => createRunState,
2970
2970
  createRunStatusSnapshot: () => createRunStatusSnapshot,
2971
+ deployRiddlePreview: () => deployRiddlePreview,
2971
2972
  deployRiddleStaticPreview: () => deployRiddleStaticPreview,
2972
2973
  extractBasicGameplayEvidence: () => extractBasicGameplayEvidence,
2973
2974
  extractPlayabilityEvidence: () => extractPlayabilityEvidence,
@@ -11825,6 +11826,10 @@ function textMatches(sample, check) {
11825
11826
  }
11826
11827
  return String(sample || "").includes(check.text || "");
11827
11828
  }
11829
+ function profileCheckAppliesToViewport(check, viewport) {
11830
+ if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
11831
+ return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
11832
+ }
11828
11833
  function setupActionType(action) {
11829
11834
  return String(action && action.type ? action.type : "").replace(/-/g, "_");
11830
11835
  }
@@ -11842,6 +11847,30 @@ function setupTextMatches(sample, action) {
11842
11847
  }
11843
11848
  return String(sample || "").includes(action.text || "");
11844
11849
  }
11850
+ async function waitForAnyVisibleSelector(context, selector, timeout) {
11851
+ const deadline = Date.now() + setupNumber(timeout, 15000);
11852
+ let lastReason = "selector_not_found";
11853
+ while (Date.now() <= deadline) {
11854
+ try {
11855
+ const locator = context.locator(selector);
11856
+ const count = await locator.count();
11857
+ if (!count) {
11858
+ lastReason = "selector_not_found";
11859
+ } else {
11860
+ lastReason = "no_visible_match";
11861
+ for (let index = 0; index < count; index += 1) {
11862
+ if (await locator.nth(index).isVisible().catch(() => false)) {
11863
+ return { ok: true, count, index };
11864
+ }
11865
+ }
11866
+ }
11867
+ } catch (error) {
11868
+ lastReason = String(error && error.message ? error.message : error).slice(0, 500);
11869
+ }
11870
+ await page.waitForTimeout(200);
11871
+ }
11872
+ throw new Error("No visible match for selector " + selector + ": " + lastReason);
11873
+ }
11845
11874
  function setupHasOwn(action, key) {
11846
11875
  return Boolean(action) && Object.keys(action).includes(key);
11847
11876
  }
@@ -12175,7 +12204,7 @@ async function executeSetupAction(action, ordinal, viewport) {
12175
12204
  if (type === "wait_for_selector") {
12176
12205
  const scope = await setupActionScope(action, timeout);
12177
12206
  if (!scope.ok) return setupScopeFailure(base, scope);
12178
- await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
12207
+ await waitForAnyVisibleSelector(scope.context, action.selector, timeout);
12179
12208
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
12180
12209
  }
12181
12210
  if (type === "drag") {
@@ -13191,7 +13220,7 @@ async function collectRouteInventory(check, viewport) {
13191
13220
  try {
13192
13221
  await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 90000 });
13193
13222
  if (profile.target.wait_for_selector) {
13194
- await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 }).catch(() => {});
13223
+ await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000).catch(() => {});
13195
13224
  }
13196
13225
  const index = await findInventoryLinkIndex(check, expectedRoute.path);
13197
13226
  if (index < 0) {
@@ -13250,7 +13279,7 @@ async function captureViewport(viewport) {
13250
13279
  }
13251
13280
  if (!navigationError && profile.target.wait_for_selector) {
13252
13281
  try {
13253
- await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 });
13282
+ await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000);
13254
13283
  } catch (error) {
13255
13284
  waitError = String(error && error.message ? error.message : error).slice(0, 1000);
13256
13285
  }
@@ -13354,6 +13383,7 @@ async function captureViewport(viewport) {
13354
13383
  const text_matches = {};
13355
13384
  const link_statuses = {};
13356
13385
  for (const check of profile.checks || []) {
13386
+ if (!profileCheckAppliesToViewport(check, viewport)) continue;
13357
13387
  if (
13358
13388
  (
13359
13389
  check.type === "selector_visible"
@@ -13389,7 +13419,7 @@ async function captureViewport(viewport) {
13389
13419
  pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
13390
13420
  }
13391
13421
  let routeInventory;
13392
- const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
13422
+ const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory" && profileCheckAppliesToViewport(check, viewport));
13393
13423
  const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
13394
13424
  if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
13395
13425
  try {
@@ -13494,7 +13524,7 @@ function buildProfileEvidence(currentViewports) {
13494
13524
  })),
13495
13525
  })),
13496
13526
  link_status: currentViewports
13497
- .filter((viewport) => viewport.link_statuses)
13527
+ .filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
13498
13528
  .map((viewport) => ({
13499
13529
  viewport: viewport.name,
13500
13530
  selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
@@ -13689,12 +13719,13 @@ async function riddleRequestJson(config, pathname, init = {}) {
13689
13719
  if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
13690
13720
  return json ?? text;
13691
13721
  }
13692
- async function deployRiddleStaticPreview(config, directory, label) {
13722
+ async function deployRiddlePreview(config, directory, label, framework = "static") {
13693
13723
  if (!directory?.trim()) throw new Error("directory is required");
13694
13724
  if (!label?.trim()) throw new Error("label is required");
13725
+ if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
13695
13726
  const created = await riddleRequestJson(config, "/v1/preview", {
13696
13727
  method: "POST",
13697
- body: JSON.stringify({ framework: "static", label })
13728
+ body: JSON.stringify({ framework, label })
13698
13729
  });
13699
13730
  const id = String(created.id || "");
13700
13731
  const uploadUrl = String(created.upload_url || "");
@@ -13721,6 +13752,7 @@ async function deployRiddleStaticPreview(config, directory, label) {
13721
13752
  ok: true,
13722
13753
  id: String(published.id || id),
13723
13754
  label,
13755
+ framework,
13724
13756
  preview_url: String(published.preview_url || ""),
13725
13757
  file_count: typeof published.file_count === "number" ? published.file_count : void 0,
13726
13758
  total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
@@ -13728,6 +13760,9 @@ async function deployRiddleStaticPreview(config, directory, label) {
13728
13760
  raw: published
13729
13761
  };
13730
13762
  }
13763
+ async function deployRiddleStaticPreview(config, directory, label) {
13764
+ return deployRiddlePreview(config, directory, label, "static");
13765
+ }
13731
13766
  function createTarball(directory, label, exclude = []) {
13732
13767
  const scratch = (0, import_node_fs5.mkdtempSync)(import_node_path5.default.join((0, import_node_os2.tmpdir)(), "riddle-upload-"));
13733
13768
  const tarball = import_node_path5.default.join(scratch, `${label}.tar.gz`);
@@ -13959,6 +13994,7 @@ async function pollRiddleJob(config, jobId, options = {}) {
13959
13994
  function createRiddleApiClient(config = {}) {
13960
13995
  return {
13961
13996
  requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
13997
+ deployPreview: (directory, label, framework = "static") => deployRiddlePreview(config, directory, label, framework),
13962
13998
  deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
13963
13999
  runScript: (input) => runRiddleScript(config, input),
13964
14000
  runServerPreview: (input) => runRiddleServerPreview(config, input),
@@ -14036,6 +14072,7 @@ function createRiddleApiClient(config = {}) {
14036
14072
  createRunResult,
14037
14073
  createRunState,
14038
14074
  createRunStatusSnapshot,
14075
+ deployRiddlePreview,
14039
14076
  deployRiddleStaticPreview,
14040
14077
  extractBasicGameplayEvidence,
14041
14078
  extractPlayabilityEvidence,
package/dist/index.d.cts CHANGED
@@ -11,4 +11,4 @@ export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_V
11
11
  export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.cjs';
12
12
  export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayBoundsOffender, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayResponsiveViewportEvidence, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.cjs';
13
13
  export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.cjs';
14
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
14
+ export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.cjs';
package/dist/index.d.ts CHANGED
@@ -11,4 +11,4 @@ export { BuildVisualProofSessionInput, RIDDLE_PROOF_VISUAL_SESSION_FINGERPRINT_V
11
11
  export { AssessPlayabilityOptions, RIDDLE_PROOF_PLAYABILITY_ASSESSMENT_VERSION, RIDDLE_PROOF_PLAYABILITY_VERSION, RiddleProofPlayabilityAssessment, RiddleProofPlayabilityEvidence, assessPlayabilityEvidence, extractPlayabilityEvidence, isRiddleProofPlayabilityMode } from './playability.js';
12
12
  export { AssessBasicGameplayOptions, AttachBasicGameplayArtifactOptions, BASIC_GAMEPLAY_ACTION_TYPES, BASIC_GAMEPLAY_PROGRESS_CHECK_TYPES, BasicGameplayActionResult, BasicGameplayActionType, BasicGameplayArtifactResolution, BasicGameplayAssessmentSummary, BasicGameplayBoundsOffender, BasicGameplayCanvasState, BasicGameplayCatchRecord, BasicGameplayChangeSummary, BasicGameplayFailureCode, BasicGameplayFixReference, BasicGameplayMetric, BasicGameplayMobileEvidence, BasicGameplayProgressCheckType, BasicGameplayProgressionCheck, BasicGameplayProofArtifact, BasicGameplayResponsiveViewportEvidence, BasicGameplayRouteReference, BasicGameplaySnapshot, BasicGameplaySuiteFailure, BasicGameplayWarningCode, CreateBasicGameplayCatchSummaryInput, RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_CATCH_VERSION, RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION, RiddleProofBasicGameplayAssessment, RiddleProofBasicGameplayCatchSummary, RiddleProofBasicGameplayEvidence, RiddleProofBasicGameplayRouteAssessment, RiddleProofBasicGameplayRouteEvidence, assessBasicGameplayEvidence, assessBasicGameplayProgressionCheck, assessBasicGameplayProgressionChecks, assessBasicGameplayRoute, attachBasicGameplayArtifactScreenshotHashes, augmentBasicGameplayAssessmentWithProgressionChecks, compactBasicGameplayText, createBasicGameplayCatchRecords, createBasicGameplayCatchSummary, extractBasicGameplayEvidence, resolveBasicGameplayProgressionCheckWithArtifactScreenshots, sanitizeBasicGameplayJsonString } from './basic-gameplay.js';
13
13
  export { NormalizeRiddleProofProfileOptions, RIDDLE_PROOF_PROFILE_CHECK_TYPES, RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION, RIDDLE_PROOF_PROFILE_RESULT_VERSION, RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES, RIDDLE_PROOF_PROFILE_STATUSES, RIDDLE_PROOF_PROFILE_VERSION, RiddleProofProfile, RiddleProofProfileArtifactRef, RiddleProofProfileBaselinePolicy, RiddleProofProfileBoundsOffender, RiddleProofProfileCheck, RiddleProofProfileCheckResult, RiddleProofProfileCheckType, RiddleProofProfileEvidence, RiddleProofProfileFailureAction, RiddleProofProfileNetworkMock, RiddleProofProfileNetworkMockResponse, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, RiddleProofProfileRouteInventoryRoute, RiddleProofProfileRunner, RiddleProofProfileSetupAction, RiddleProofProfileSetupActionType, RiddleProofProfileStatus, RiddleProofProfileTarget, RiddleProofProfileViewport, RiddleProofProfileViewportEvidence, assessRiddleProofProfileEvidence, buildRiddleProofProfileScript, collectRiddleProfileArtifactRefs, createRiddleProofProfileConfigurationError, createRiddleProofProfileEnvironmentBlockedResult, createRiddleProofProfileInsufficientResult, extractRiddleProofProfileResult, normalizeRiddleProofProfile, profileStatusExitCode, resolveRiddleProofProfileRouteUrl, resolveRiddleProofProfileTargetUrl, resolveRiddleProofProfileTimeoutSec, slugifyRiddleProofProfileName, summarizeRiddleProofProfileResult } from './profile.js';
14
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
14
+ export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, RiddleClientConfig, RiddleFetch, RiddlePollJobOptions, RiddlePollJobResult, RiddlePollProgressSnapshot, RiddlePollSummary, RiddlePreviewDeployResult, RiddlePreviewFramework, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
package/dist/index.js CHANGED
@@ -58,12 +58,13 @@ import {
58
58
  resolveRiddleProofProfileTimeoutSec,
59
59
  slugifyRiddleProofProfileName,
60
60
  summarizeRiddleProofProfileResult
61
- } from "./chunk-4FMBHM4E.js";
61
+ } from "./chunk-2SGLFPFX.js";
62
62
  import {
63
63
  DEFAULT_RIDDLE_API_BASE_URL,
64
64
  DEFAULT_RIDDLE_API_KEY_FILE,
65
65
  RiddleApiError,
66
66
  createRiddleApiClient,
67
+ deployRiddlePreview,
67
68
  deployRiddleStaticPreview,
68
69
  isTerminalRiddleJobStatus,
69
70
  parseRiddleViewport,
@@ -72,7 +73,7 @@ import {
72
73
  riddleRequestJson,
73
74
  runRiddleScript,
74
75
  runRiddleServerPreview
75
- } from "./chunk-6RQGBHJ5.js";
76
+ } from "./chunk-OI57LO6Y.js";
76
77
  import {
77
78
  DEFAULT_DIAGNOSTIC_ARRAY_LIMIT,
78
79
  DEFAULT_DIAGNOSTIC_HISTORY_LIMIT,
@@ -207,6 +208,7 @@ export {
207
208
  createRunResult,
208
209
  createRunState,
209
210
  createRunStatusSnapshot,
211
+ deployRiddlePreview,
210
212
  deployRiddleStaticPreview,
211
213
  extractBasicGameplayEvidence,
212
214
  extractPlayabilityEvidence,
package/dist/profile.cjs CHANGED
@@ -3140,6 +3140,10 @@ function textMatches(sample, check) {
3140
3140
  }
3141
3141
  return String(sample || "").includes(check.text || "");
3142
3142
  }
3143
+ function profileCheckAppliesToViewport(check, viewport) {
3144
+ if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
3145
+ return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
3146
+ }
3143
3147
  function setupActionType(action) {
3144
3148
  return String(action && action.type ? action.type : "").replace(/-/g, "_");
3145
3149
  }
@@ -3157,6 +3161,30 @@ function setupTextMatches(sample, action) {
3157
3161
  }
3158
3162
  return String(sample || "").includes(action.text || "");
3159
3163
  }
3164
+ async function waitForAnyVisibleSelector(context, selector, timeout) {
3165
+ const deadline = Date.now() + setupNumber(timeout, 15000);
3166
+ let lastReason = "selector_not_found";
3167
+ while (Date.now() <= deadline) {
3168
+ try {
3169
+ const locator = context.locator(selector);
3170
+ const count = await locator.count();
3171
+ if (!count) {
3172
+ lastReason = "selector_not_found";
3173
+ } else {
3174
+ lastReason = "no_visible_match";
3175
+ for (let index = 0; index < count; index += 1) {
3176
+ if (await locator.nth(index).isVisible().catch(() => false)) {
3177
+ return { ok: true, count, index };
3178
+ }
3179
+ }
3180
+ }
3181
+ } catch (error) {
3182
+ lastReason = String(error && error.message ? error.message : error).slice(0, 500);
3183
+ }
3184
+ await page.waitForTimeout(200);
3185
+ }
3186
+ throw new Error("No visible match for selector " + selector + ": " + lastReason);
3187
+ }
3160
3188
  function setupHasOwn(action, key) {
3161
3189
  return Boolean(action) && Object.keys(action).includes(key);
3162
3190
  }
@@ -3490,7 +3518,7 @@ async function executeSetupAction(action, ordinal, viewport) {
3490
3518
  if (type === "wait_for_selector") {
3491
3519
  const scope = await setupActionScope(action, timeout);
3492
3520
  if (!scope.ok) return setupScopeFailure(base, scope);
3493
- await scope.context.waitForSelector(action.selector, { state: "visible", timeout });
3521
+ await waitForAnyVisibleSelector(scope.context, action.selector, timeout);
3494
3522
  return { ...base, ...setupScopeEvidence(scope), ok: true, timeout_ms: timeout };
3495
3523
  }
3496
3524
  if (type === "drag") {
@@ -4506,7 +4534,7 @@ async function collectRouteInventory(check, viewport) {
4506
4534
  try {
4507
4535
  await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 90000 });
4508
4536
  if (profile.target.wait_for_selector) {
4509
- await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 }).catch(() => {});
4537
+ await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000).catch(() => {});
4510
4538
  }
4511
4539
  const index = await findInventoryLinkIndex(check, expectedRoute.path);
4512
4540
  if (index < 0) {
@@ -4565,7 +4593,7 @@ async function captureViewport(viewport) {
4565
4593
  }
4566
4594
  if (!navigationError && profile.target.wait_for_selector) {
4567
4595
  try {
4568
- await page.waitForSelector(profile.target.wait_for_selector, { state: "visible", timeout: 15000 });
4596
+ await waitForAnyVisibleSelector(page, profile.target.wait_for_selector, 15000);
4569
4597
  } catch (error) {
4570
4598
  waitError = String(error && error.message ? error.message : error).slice(0, 1000);
4571
4599
  }
@@ -4669,6 +4697,7 @@ async function captureViewport(viewport) {
4669
4697
  const text_matches = {};
4670
4698
  const link_statuses = {};
4671
4699
  for (const check of profile.checks || []) {
4700
+ if (!profileCheckAppliesToViewport(check, viewport)) continue;
4672
4701
  if (
4673
4702
  (
4674
4703
  check.type === "selector_visible"
@@ -4704,7 +4733,7 @@ async function captureViewport(viewport) {
4704
4733
  pageErrors.push({ message: "saveScreenshot failed: " + String(error && error.message ? error.message : error).slice(0, 500) });
4705
4734
  }
4706
4735
  let routeInventory;
4707
- const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory");
4736
+ const routeInventoryCheck = (profile.checks || []).find((check) => check.type === "route_inventory" && profileCheckAppliesToViewport(check, viewport));
4708
4737
  const firstViewportName = (profile.target.viewports || [])[0] && (profile.target.viewports || [])[0].name;
4709
4738
  if (routeInventoryCheck && (routeInventoryCheck.run_all_viewports || !firstViewportName || viewport.name === firstViewportName)) {
4710
4739
  try {
@@ -4809,7 +4838,7 @@ function buildProfileEvidence(currentViewports) {
4809
4838
  })),
4810
4839
  })),
4811
4840
  link_status: currentViewports
4812
- .filter((viewport) => viewport.link_statuses)
4841
+ .filter((viewport) => viewport.link_statuses && Object.keys(viewport.link_statuses).length)
4813
4842
  .map((viewport) => ({
4814
4843
  viewport: viewport.name,
4815
4844
  selectors: Object.entries(viewport.link_statuses || {}).map(([selector, statusSet]) => ({
package/dist/profile.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  resolveRiddleProofProfileTimeoutSec,
20
20
  slugifyRiddleProofProfileName,
21
21
  summarizeRiddleProofProfileResult
22
- } from "./chunk-4FMBHM4E.js";
22
+ } from "./chunk-2SGLFPFX.js";
23
23
  export {
24
24
  RIDDLE_PROOF_PROFILE_CHECK_TYPES,
25
25
  RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
@@ -34,6 +34,7 @@ __export(riddle_client_exports, {
34
34
  DEFAULT_RIDDLE_API_KEY_FILE: () => DEFAULT_RIDDLE_API_KEY_FILE,
35
35
  RiddleApiError: () => RiddleApiError,
36
36
  createRiddleApiClient: () => createRiddleApiClient,
37
+ deployRiddlePreview: () => deployRiddlePreview,
37
38
  deployRiddleStaticPreview: () => deployRiddleStaticPreview,
38
39
  isTerminalRiddleJobStatus: () => isTerminalRiddleJobStatus,
39
40
  parseRiddleViewport: () => parseRiddleViewport,
@@ -93,12 +94,13 @@ async function riddleRequestJson(config, pathname, init = {}) {
93
94
  if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
94
95
  return json ?? text;
95
96
  }
96
- async function deployRiddleStaticPreview(config, directory, label) {
97
+ async function deployRiddlePreview(config, directory, label, framework = "static") {
97
98
  if (!directory?.trim()) throw new Error("directory is required");
98
99
  if (!label?.trim()) throw new Error("label is required");
100
+ if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
99
101
  const created = await riddleRequestJson(config, "/v1/preview", {
100
102
  method: "POST",
101
- body: JSON.stringify({ framework: "static", label })
103
+ body: JSON.stringify({ framework, label })
102
104
  });
103
105
  const id = String(created.id || "");
104
106
  const uploadUrl = String(created.upload_url || "");
@@ -125,6 +127,7 @@ async function deployRiddleStaticPreview(config, directory, label) {
125
127
  ok: true,
126
128
  id: String(published.id || id),
127
129
  label,
130
+ framework,
128
131
  preview_url: String(published.preview_url || ""),
129
132
  file_count: typeof published.file_count === "number" ? published.file_count : void 0,
130
133
  total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
@@ -132,6 +135,9 @@ async function deployRiddleStaticPreview(config, directory, label) {
132
135
  raw: published
133
136
  };
134
137
  }
138
+ async function deployRiddleStaticPreview(config, directory, label) {
139
+ return deployRiddlePreview(config, directory, label, "static");
140
+ }
135
141
  function createTarball(directory, label, exclude = []) {
136
142
  const scratch = (0, import_node_fs.mkdtempSync)(import_node_path.default.join((0, import_node_os.tmpdir)(), "riddle-upload-"));
137
143
  const tarball = import_node_path.default.join(scratch, `${label}.tar.gz`);
@@ -363,6 +369,7 @@ async function pollRiddleJob(config, jobId, options = {}) {
363
369
  function createRiddleApiClient(config = {}) {
364
370
  return {
365
371
  requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
372
+ deployPreview: (directory, label, framework = "static") => deployRiddlePreview(config, directory, label, framework),
366
373
  deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
367
374
  runScript: (input) => runRiddleScript(config, input),
368
375
  runServerPreview: (input) => runRiddleServerPreview(config, input),
@@ -375,6 +382,7 @@ function createRiddleApiClient(config = {}) {
375
382
  DEFAULT_RIDDLE_API_KEY_FILE,
376
383
  RiddleApiError,
377
384
  createRiddleApiClient,
385
+ deployRiddlePreview,
378
386
  deployRiddleStaticPreview,
379
387
  isTerminalRiddleJobStatus,
380
388
  parseRiddleViewport,
@@ -32,10 +32,12 @@ interface RiddlePollJobOptions {
32
32
  progressEveryMs?: number;
33
33
  onProgress?: (snapshot: RiddlePollProgressSnapshot) => void | Promise<void>;
34
34
  }
35
+ type RiddlePreviewFramework = "spa" | "static";
35
36
  interface RiddlePreviewDeployResult {
36
37
  ok: true;
37
38
  id: string;
38
39
  label: string;
40
+ framework: RiddlePreviewFramework;
39
41
  preview_url: string;
40
42
  file_count?: number;
41
43
  total_bytes?: number;
@@ -101,6 +103,7 @@ declare class RiddleApiError extends Error {
101
103
  }
102
104
  declare function resolveRiddleApiKey(config?: RiddleClientConfig): string;
103
105
  declare function riddleRequestJson<T = unknown>(config: RiddleClientConfig, pathname: string, init?: RequestInit): Promise<T>;
106
+ declare function deployRiddlePreview(config: RiddleClientConfig, directory: string, label: string, framework?: RiddlePreviewFramework): Promise<RiddlePreviewDeployResult>;
104
107
  declare function deployRiddleStaticPreview(config: RiddleClientConfig, directory: string, label: string): Promise<RiddlePreviewDeployResult>;
105
108
  declare function parseRiddleViewport(value?: string): {
106
109
  width: number;
@@ -112,10 +115,11 @@ declare function isTerminalRiddleJobStatus(status: unknown): boolean;
112
115
  declare function pollRiddleJob(config: RiddleClientConfig, jobId: string, options?: RiddlePollJobOptions): Promise<RiddlePollJobResult>;
113
116
  declare function createRiddleApiClient(config?: RiddleClientConfig): {
114
117
  requestJson: <T = unknown>(pathname: string, init?: RequestInit) => Promise<T>;
118
+ deployPreview: (directory: string, label: string, framework?: RiddlePreviewFramework) => Promise<RiddlePreviewDeployResult>;
115
119
  deployStaticPreview: (directory: string, label: string) => Promise<RiddlePreviewDeployResult>;
116
120
  runScript: (input: RiddleRunScriptInput) => Promise<Record<string, unknown>>;
117
121
  runServerPreview: (input: RiddleServerPreviewInput) => Promise<RiddleServerPreviewResult>;
118
122
  pollJob: (jobId: string, options?: RiddlePollJobOptions) => Promise<RiddlePollJobResult>;
119
123
  };
120
124
 
121
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
125
+ export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddlePreviewFramework, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
@@ -32,10 +32,12 @@ interface RiddlePollJobOptions {
32
32
  progressEveryMs?: number;
33
33
  onProgress?: (snapshot: RiddlePollProgressSnapshot) => void | Promise<void>;
34
34
  }
35
+ type RiddlePreviewFramework = "spa" | "static";
35
36
  interface RiddlePreviewDeployResult {
36
37
  ok: true;
37
38
  id: string;
38
39
  label: string;
40
+ framework: RiddlePreviewFramework;
39
41
  preview_url: string;
40
42
  file_count?: number;
41
43
  total_bytes?: number;
@@ -101,6 +103,7 @@ declare class RiddleApiError extends Error {
101
103
  }
102
104
  declare function resolveRiddleApiKey(config?: RiddleClientConfig): string;
103
105
  declare function riddleRequestJson<T = unknown>(config: RiddleClientConfig, pathname: string, init?: RequestInit): Promise<T>;
106
+ declare function deployRiddlePreview(config: RiddleClientConfig, directory: string, label: string, framework?: RiddlePreviewFramework): Promise<RiddlePreviewDeployResult>;
104
107
  declare function deployRiddleStaticPreview(config: RiddleClientConfig, directory: string, label: string): Promise<RiddlePreviewDeployResult>;
105
108
  declare function parseRiddleViewport(value?: string): {
106
109
  width: number;
@@ -112,10 +115,11 @@ declare function isTerminalRiddleJobStatus(status: unknown): boolean;
112
115
  declare function pollRiddleJob(config: RiddleClientConfig, jobId: string, options?: RiddlePollJobOptions): Promise<RiddlePollJobResult>;
113
116
  declare function createRiddleApiClient(config?: RiddleClientConfig): {
114
117
  requestJson: <T = unknown>(pathname: string, init?: RequestInit) => Promise<T>;
118
+ deployPreview: (directory: string, label: string, framework?: RiddlePreviewFramework) => Promise<RiddlePreviewDeployResult>;
115
119
  deployStaticPreview: (directory: string, label: string) => Promise<RiddlePreviewDeployResult>;
116
120
  runScript: (input: RiddleRunScriptInput) => Promise<Record<string, unknown>>;
117
121
  runServerPreview: (input: RiddleServerPreviewInput) => Promise<RiddleServerPreviewResult>;
118
122
  pollJob: (jobId: string, options?: RiddlePollJobOptions) => Promise<RiddlePollJobResult>;
119
123
  };
120
124
 
121
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
125
+ export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobOptions, type RiddlePollJobResult, type RiddlePollProgressSnapshot, type RiddlePollSummary, type RiddlePreviewDeployResult, type RiddlePreviewFramework, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddlePreview, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
@@ -3,6 +3,7 @@ import {
3
3
  DEFAULT_RIDDLE_API_KEY_FILE,
4
4
  RiddleApiError,
5
5
  createRiddleApiClient,
6
+ deployRiddlePreview,
6
7
  deployRiddleStaticPreview,
7
8
  isTerminalRiddleJobStatus,
8
9
  parseRiddleViewport,
@@ -11,12 +12,13 @@ import {
11
12
  riddleRequestJson,
12
13
  runRiddleScript,
13
14
  runRiddleServerPreview
14
- } from "./chunk-6RQGBHJ5.js";
15
+ } from "./chunk-OI57LO6Y.js";
15
16
  export {
16
17
  DEFAULT_RIDDLE_API_BASE_URL,
17
18
  DEFAULT_RIDDLE_API_KEY_FILE,
18
19
  RiddleApiError,
19
20
  createRiddleApiClient,
21
+ deployRiddlePreview,
20
22
  deployRiddleStaticPreview,
21
23
  isTerminalRiddleJobStatus,
22
24
  parseRiddleViewport,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.90",
3
+ "version": "0.7.92",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",