@riddledc/riddle-proof 0.7.24 → 0.7.26

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/README.md CHANGED
@@ -339,6 +339,16 @@ that performs the interaction. If proof is weak, keep the diagnostics history in
339
339
  the run state so the next agent can see the last route, tool status, artifact
340
340
  shape, and errors without rerunning blind.
341
341
 
342
+ ### Riddle Job Polling
343
+
344
+ `riddle-proof-loop riddle-poll <job-id> --wait` keeps stdout as JSON and writes
345
+ human progress lines to stderr while waiting. The JSON result includes
346
+ `poll.timed_out`, `poll.elapsed_ms`, `poll.queue_elapsed_ms`, and
347
+ `poll.running_without_submission` so delayed dispatch is distinguishable from a
348
+ terminal proof failure. If `--wait` exhausts its attempts before a terminal job
349
+ status, the command exits non-zero and the result explains the last observed
350
+ status and `submitted_at` state.
351
+
342
352
  ## OpenClaw Adapter Boundary
343
353
 
344
354
  `@riddledc/riddle-proof/openclaw` translates OpenClaw Riddle Proof tool params
@@ -196,21 +196,109 @@ async function runRiddleScript(config, input) {
196
196
  function isTerminalRiddleJobStatus(status) {
197
197
  return ["completed", "complete", "completed_error", "completed_timeout", "failed"].includes(String(status || ""));
198
198
  }
199
+ function stringField(record, key) {
200
+ const value = record?.[key];
201
+ return typeof value === "string" && value.trim() ? value.trim() : null;
202
+ }
203
+ function parseTimestampMs(value) {
204
+ if (!value) return null;
205
+ const parsed = Date.parse(value);
206
+ return Number.isFinite(parsed) ? parsed : null;
207
+ }
208
+ function buildPollSnapshot(jobId, job, input) {
209
+ const status = job?.status ? String(job.status) : null;
210
+ const terminal = isTerminalRiddleJobStatus(status);
211
+ const createdAt = stringField(job, "created_at");
212
+ const submittedAt = stringField(job, "submitted_at");
213
+ const completedAt = stringField(job, "completed_at");
214
+ const createdMs = parseTimestampMs(createdAt);
215
+ const submittedMs = parseTimestampMs(submittedAt);
216
+ let queueElapsedMs = null;
217
+ if (createdMs !== null && submittedMs !== null) {
218
+ queueElapsedMs = Math.max(0, submittedMs - createdMs);
219
+ } else if (createdMs !== null && !submittedAt && !terminal) {
220
+ queueElapsedMs = Math.max(0, input.observedAt - createdMs);
221
+ }
222
+ return {
223
+ job_id: jobId,
224
+ status,
225
+ terminal,
226
+ attempt: input.attempt,
227
+ attempts: input.attempts,
228
+ elapsed_ms: Math.max(0, input.observedAt - input.startedAt),
229
+ created_at: createdAt,
230
+ submitted_at: submittedAt,
231
+ completed_at: completedAt,
232
+ queue_elapsed_ms: queueElapsedMs,
233
+ running_without_submission: Boolean(status && !terminal && !submittedAt)
234
+ };
235
+ }
236
+ function pollMessage(snapshot, timedOut) {
237
+ if (!timedOut) return void 0;
238
+ const submitted = snapshot.submitted_at || "not submitted";
239
+ const queue = snapshot.queue_elapsed_ms !== null ? ` queue_elapsed_ms=${snapshot.queue_elapsed_ms}` : "";
240
+ return `Riddle job ${snapshot.job_id} did not reach a terminal status after ${snapshot.attempt} poll attempts; status=${snapshot.status || "unknown"} submitted_at=${submitted}.${queue}`;
241
+ }
199
242
  async function pollRiddleJob(config, jobId, options = {}) {
200
243
  if (!jobId?.trim()) throw new Error("jobId is required");
201
- const attempts = options.attempts || (options.wait ? 60 : 1);
202
- const intervalMs = options.intervalMs || 2e3;
244
+ const attempts = Math.max(1, Math.floor(options.attempts ?? (options.wait ? 300 : 1)));
245
+ const intervalMs = Math.max(0, Math.floor(options.intervalMs ?? 2e3));
246
+ const progressEveryMs = Math.max(0, Math.floor(options.progressEveryMs ?? 1e4));
247
+ const startedAt = Date.now();
203
248
  let job = null;
249
+ let lastSnapshot = null;
250
+ let lastProgressAt = 0;
251
+ let lastProgressKey = "";
204
252
  for (let index = 0; index < attempts; index += 1) {
205
253
  job = await riddleRequestJson(config, `/v1/jobs/${jobId}`);
206
- if (isTerminalRiddleJobStatus(job.status)) break;
254
+ const observedAt = Date.now();
255
+ lastSnapshot = buildPollSnapshot(jobId, job, {
256
+ attempt: index + 1,
257
+ attempts,
258
+ startedAt,
259
+ observedAt
260
+ });
261
+ const progressKey = [
262
+ lastSnapshot.status || "unknown",
263
+ lastSnapshot.terminal ? "terminal" : "nonterminal",
264
+ lastSnapshot.submitted_at ? "submitted" : "unsubmitted"
265
+ ].join(":");
266
+ if (options.onProgress) {
267
+ const shouldReport = index === 0 || lastSnapshot.terminal || progressKey !== lastProgressKey || observedAt - lastProgressAt >= progressEveryMs;
268
+ if (shouldReport) {
269
+ lastProgressAt = observedAt;
270
+ lastProgressKey = progressKey;
271
+ await options.onProgress(lastSnapshot);
272
+ }
273
+ }
274
+ if (lastSnapshot.terminal) break;
207
275
  if (index + 1 < attempts) {
208
276
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
209
277
  }
210
278
  }
211
279
  const status = job?.status ? String(job.status) : null;
280
+ const fallbackObservedAt = Date.now();
281
+ const snapshot = lastSnapshot || buildPollSnapshot(jobId, job, {
282
+ attempt: 0,
283
+ attempts,
284
+ startedAt,
285
+ observedAt: fallbackObservedAt
286
+ });
212
287
  if (!isTerminalRiddleJobStatus(status)) {
213
- return { ok: true, job_id: jobId, status, terminal: false, job };
288
+ const timedOut = Boolean(options.wait);
289
+ return {
290
+ ok: !timedOut,
291
+ job_id: jobId,
292
+ status,
293
+ terminal: false,
294
+ job,
295
+ poll: {
296
+ ...snapshot,
297
+ timed_out: timedOut,
298
+ interval_ms: intervalMs,
299
+ message: pollMessage(snapshot, timedOut)
300
+ }
301
+ };
214
302
  }
215
303
  const artifacts = await riddleRequestJson(config, `/v1/jobs/${jobId}/artifacts`);
216
304
  return {
@@ -219,7 +307,12 @@ async function pollRiddleJob(config, jobId, options = {}) {
219
307
  status,
220
308
  terminal: true,
221
309
  job,
222
- artifacts
310
+ artifacts,
311
+ poll: {
312
+ ...snapshot,
313
+ timed_out: false,
314
+ interval_ms: intervalMs
315
+ }
223
316
  };
224
317
  }
225
318
  function createRiddleApiClient(config = {}) {
package/dist/cli.cjs CHANGED
@@ -6743,21 +6743,109 @@ async function runRiddleScript(config, input) {
6743
6743
  function isTerminalRiddleJobStatus(status) {
6744
6744
  return ["completed", "complete", "completed_error", "completed_timeout", "failed"].includes(String(status || ""));
6745
6745
  }
6746
+ function stringField(record, key) {
6747
+ const value = record?.[key];
6748
+ return typeof value === "string" && value.trim() ? value.trim() : null;
6749
+ }
6750
+ function parseTimestampMs(value) {
6751
+ if (!value) return null;
6752
+ const parsed = Date.parse(value);
6753
+ return Number.isFinite(parsed) ? parsed : null;
6754
+ }
6755
+ function buildPollSnapshot(jobId, job, input) {
6756
+ const status = job?.status ? String(job.status) : null;
6757
+ const terminal = isTerminalRiddleJobStatus(status);
6758
+ const createdAt = stringField(job, "created_at");
6759
+ const submittedAt = stringField(job, "submitted_at");
6760
+ const completedAt = stringField(job, "completed_at");
6761
+ const createdMs = parseTimestampMs(createdAt);
6762
+ const submittedMs = parseTimestampMs(submittedAt);
6763
+ let queueElapsedMs = null;
6764
+ if (createdMs !== null && submittedMs !== null) {
6765
+ queueElapsedMs = Math.max(0, submittedMs - createdMs);
6766
+ } else if (createdMs !== null && !submittedAt && !terminal) {
6767
+ queueElapsedMs = Math.max(0, input.observedAt - createdMs);
6768
+ }
6769
+ return {
6770
+ job_id: jobId,
6771
+ status,
6772
+ terminal,
6773
+ attempt: input.attempt,
6774
+ attempts: input.attempts,
6775
+ elapsed_ms: Math.max(0, input.observedAt - input.startedAt),
6776
+ created_at: createdAt,
6777
+ submitted_at: submittedAt,
6778
+ completed_at: completedAt,
6779
+ queue_elapsed_ms: queueElapsedMs,
6780
+ running_without_submission: Boolean(status && !terminal && !submittedAt)
6781
+ };
6782
+ }
6783
+ function pollMessage(snapshot, timedOut) {
6784
+ if (!timedOut) return void 0;
6785
+ const submitted = snapshot.submitted_at || "not submitted";
6786
+ const queue = snapshot.queue_elapsed_ms !== null ? ` queue_elapsed_ms=${snapshot.queue_elapsed_ms}` : "";
6787
+ return `Riddle job ${snapshot.job_id} did not reach a terminal status after ${snapshot.attempt} poll attempts; status=${snapshot.status || "unknown"} submitted_at=${submitted}.${queue}`;
6788
+ }
6746
6789
  async function pollRiddleJob(config, jobId, options = {}) {
6747
6790
  if (!jobId?.trim()) throw new Error("jobId is required");
6748
- const attempts = options.attempts || (options.wait ? 60 : 1);
6749
- const intervalMs = options.intervalMs || 2e3;
6791
+ const attempts = Math.max(1, Math.floor(options.attempts ?? (options.wait ? 300 : 1)));
6792
+ const intervalMs = Math.max(0, Math.floor(options.intervalMs ?? 2e3));
6793
+ const progressEveryMs = Math.max(0, Math.floor(options.progressEveryMs ?? 1e4));
6794
+ const startedAt = Date.now();
6750
6795
  let job = null;
6796
+ let lastSnapshot = null;
6797
+ let lastProgressAt = 0;
6798
+ let lastProgressKey = "";
6751
6799
  for (let index = 0; index < attempts; index += 1) {
6752
6800
  job = await riddleRequestJson(config, `/v1/jobs/${jobId}`);
6753
- if (isTerminalRiddleJobStatus(job.status)) break;
6801
+ const observedAt = Date.now();
6802
+ lastSnapshot = buildPollSnapshot(jobId, job, {
6803
+ attempt: index + 1,
6804
+ attempts,
6805
+ startedAt,
6806
+ observedAt
6807
+ });
6808
+ const progressKey = [
6809
+ lastSnapshot.status || "unknown",
6810
+ lastSnapshot.terminal ? "terminal" : "nonterminal",
6811
+ lastSnapshot.submitted_at ? "submitted" : "unsubmitted"
6812
+ ].join(":");
6813
+ if (options.onProgress) {
6814
+ const shouldReport = index === 0 || lastSnapshot.terminal || progressKey !== lastProgressKey || observedAt - lastProgressAt >= progressEveryMs;
6815
+ if (shouldReport) {
6816
+ lastProgressAt = observedAt;
6817
+ lastProgressKey = progressKey;
6818
+ await options.onProgress(lastSnapshot);
6819
+ }
6820
+ }
6821
+ if (lastSnapshot.terminal) break;
6754
6822
  if (index + 1 < attempts) {
6755
6823
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
6756
6824
  }
6757
6825
  }
6758
6826
  const status = job?.status ? String(job.status) : null;
6827
+ const fallbackObservedAt = Date.now();
6828
+ const snapshot = lastSnapshot || buildPollSnapshot(jobId, job, {
6829
+ attempt: 0,
6830
+ attempts,
6831
+ startedAt,
6832
+ observedAt: fallbackObservedAt
6833
+ });
6759
6834
  if (!isTerminalRiddleJobStatus(status)) {
6760
- return { ok: true, job_id: jobId, status, terminal: false, job };
6835
+ const timedOut = Boolean(options.wait);
6836
+ return {
6837
+ ok: !timedOut,
6838
+ job_id: jobId,
6839
+ status,
6840
+ terminal: false,
6841
+ job,
6842
+ poll: {
6843
+ ...snapshot,
6844
+ timed_out: timedOut,
6845
+ interval_ms: intervalMs,
6846
+ message: pollMessage(snapshot, timedOut)
6847
+ }
6848
+ };
6761
6849
  }
6762
6850
  const artifacts = await riddleRequestJson(config, `/v1/jobs/${jobId}/artifacts`);
6763
6851
  return {
@@ -6766,7 +6854,12 @@ async function pollRiddleJob(config, jobId, options = {}) {
6766
6854
  status,
6767
6855
  terminal: true,
6768
6856
  job,
6769
- artifacts
6857
+ artifacts,
6858
+ poll: {
6859
+ ...snapshot,
6860
+ timed_out: false,
6861
+ interval_ms: intervalMs
6862
+ }
6770
6863
  };
6771
6864
  }
6772
6865
  function createRiddleApiClient(config = {}) {
@@ -8155,8 +8248,8 @@ function usage() {
8155
8248
  " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--output <dir>]",
8156
8249
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
8157
8250
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
8158
- " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720]",
8159
- " riddle-proof-loop riddle-poll <job-id> [--wait]",
8251
+ " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
8252
+ " riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
8160
8253
  " riddle-proof-loop doctor local [--codex-command <path>]",
8161
8254
  "",
8162
8255
  "The default CLI run mode is checkpoint-mode=yield unless --agent local is used.",
@@ -8172,7 +8265,14 @@ function parseArgs(argv) {
8172
8265
  positional.push(arg);
8173
8266
  continue;
8174
8267
  }
8175
- const key = arg.slice(2).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
8268
+ const raw = arg.slice(2);
8269
+ const equalIndex = raw.indexOf("=");
8270
+ const rawKey = equalIndex >= 0 ? raw.slice(0, equalIndex) : raw;
8271
+ const key = rawKey.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
8272
+ if (equalIndex >= 0) {
8273
+ options[key] = raw.slice(equalIndex + 1);
8274
+ continue;
8275
+ }
8176
8276
  const next = argv[index + 1];
8177
8277
  if (!next || next.startsWith("--")) {
8178
8278
  options[key] = true;
@@ -8187,9 +8287,39 @@ function optionString(options, key) {
8187
8287
  const value = options[key];
8188
8288
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
8189
8289
  }
8290
+ function optionBoolean(options, key) {
8291
+ const value = options[key];
8292
+ if (typeof value === "undefined") return void 0;
8293
+ if (typeof value === "boolean") return value;
8294
+ const normalized = value.trim().toLowerCase();
8295
+ if (["true", "1", "yes", "y"].includes(normalized)) return true;
8296
+ if (["false", "0", "no", "n"].includes(normalized)) return false;
8297
+ const flag = key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
8298
+ throw new Error(`--${flag} must be true or false.`);
8299
+ }
8190
8300
  function readStdin() {
8191
8301
  return (0, import_node_fs6.readFileSync)(0, "utf-8");
8192
8302
  }
8303
+ function formatPollDuration(ms) {
8304
+ if (typeof ms !== "number" || !Number.isFinite(ms)) return "n/a";
8305
+ const seconds = Math.max(0, Math.round(ms / 1e3));
8306
+ const minutes = Math.floor(seconds / 60);
8307
+ const remainder = seconds % 60;
8308
+ return minutes > 0 ? `${minutes}m${String(remainder).padStart(2, "0")}s` : `${seconds}s`;
8309
+ }
8310
+ function riddlePollProgressLine(snapshot) {
8311
+ const submittedAt = snapshot.submitted_at || "not-submitted";
8312
+ const queuePart = snapshot.running_without_submission ? ` queued_for=${formatPollDuration(snapshot.queue_elapsed_ms)}` : snapshot.queue_elapsed_ms !== null ? ` queue=${formatPollDuration(snapshot.queue_elapsed_ms)}` : "";
8313
+ const terminalPart = snapshot.terminal ? " terminal=true" : "";
8314
+ return [
8315
+ "[riddle-poll]",
8316
+ snapshot.job_id,
8317
+ `status=${snapshot.status || "unknown"}`,
8318
+ `attempt=${snapshot.attempt}/${snapshot.attempts}`,
8319
+ `elapsed=${formatPollDuration(snapshot.elapsed_ms)}`,
8320
+ `submitted_at=${submittedAt}${queuePart}${terminalPart}`
8321
+ ].join(" ");
8322
+ }
8193
8323
  function readJsonValue(value, label) {
8194
8324
  if (!value) throw new Error(`${label} is required.`);
8195
8325
  const raw = value === "-" ? readStdin() : (0, import_node_fs6.existsSync)(value) ? (0, import_node_fs6.readFileSync)(value, "utf-8") : value;
@@ -8612,6 +8742,7 @@ async function main() {
8612
8742
  script: (0, import_node_fs6.readFileSync)(scriptFile, "utf-8"),
8613
8743
  viewport: parseRiddleViewport(optionString(options, "viewport")),
8614
8744
  timeoutSec: optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0,
8745
+ strict: optionBoolean(options, "strict"),
8615
8746
  sync: options.sync === true ? true : void 0
8616
8747
  });
8617
8748
  process.stdout.write(`${JSON.stringify(result, null, 2)}
@@ -8621,10 +8752,16 @@ async function main() {
8621
8752
  if (command === "riddle-poll") {
8622
8753
  const jobId = positional[1];
8623
8754
  if (!jobId) throw new Error("riddle-poll requires <job-id>.");
8755
+ const wait = options.wait === true;
8624
8756
  const result = await createRiddleApiClient(riddleClientConfig(options)).pollJob(jobId, {
8625
- wait: options.wait === true,
8757
+ wait,
8626
8758
  attempts: optionString(options, "attempts") ? Number(optionString(options, "attempts")) : void 0,
8627
- intervalMs: optionString(options, "intervalMs") ? Number(optionString(options, "intervalMs")) : void 0
8759
+ intervalMs: optionString(options, "intervalMs") ? Number(optionString(options, "intervalMs")) : void 0,
8760
+ progressEveryMs: optionString(options, "progressEveryMs") ? Number(optionString(options, "progressEveryMs")) : void 0,
8761
+ onProgress: wait && options.quiet !== true ? (snapshot) => {
8762
+ process.stderr.write(`${riddlePollProgressLine(snapshot)}
8763
+ `);
8764
+ } : void 0
8628
8765
  });
8629
8766
  process.stdout.write(`${JSON.stringify(result, null, 2)}
8630
8767
  `);
package/dist/cli.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport
17
- } from "./chunk-5KOHSE4V.js";
17
+ } from "./chunk-7PSWK57T.js";
18
18
  import {
19
19
  createDisabledRiddleProofAgentAdapter,
20
20
  readRiddleProofRunStatus,
@@ -47,8 +47,8 @@ function usage() {
47
47
  " riddle-proof-loop run-profile --profile <file|json|-> --url <base-url> [--runner riddle] [--output <dir>]",
48
48
  " riddle-proof-loop riddle-preview-deploy <build-dir> <label>",
49
49
  " riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
50
- " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720]",
51
- " riddle-proof-loop riddle-poll <job-id> [--wait]",
50
+ " riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
51
+ " riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
52
52
  " riddle-proof-loop doctor local [--codex-command <path>]",
53
53
  "",
54
54
  "The default CLI run mode is checkpoint-mode=yield unless --agent local is used.",
@@ -64,7 +64,14 @@ function parseArgs(argv) {
64
64
  positional.push(arg);
65
65
  continue;
66
66
  }
67
- const key = arg.slice(2).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
67
+ const raw = arg.slice(2);
68
+ const equalIndex = raw.indexOf("=");
69
+ const rawKey = equalIndex >= 0 ? raw.slice(0, equalIndex) : raw;
70
+ const key = rawKey.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
71
+ if (equalIndex >= 0) {
72
+ options[key] = raw.slice(equalIndex + 1);
73
+ continue;
74
+ }
68
75
  const next = argv[index + 1];
69
76
  if (!next || next.startsWith("--")) {
70
77
  options[key] = true;
@@ -79,9 +86,39 @@ function optionString(options, key) {
79
86
  const value = options[key];
80
87
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
81
88
  }
89
+ function optionBoolean(options, key) {
90
+ const value = options[key];
91
+ if (typeof value === "undefined") return void 0;
92
+ if (typeof value === "boolean") return value;
93
+ const normalized = value.trim().toLowerCase();
94
+ if (["true", "1", "yes", "y"].includes(normalized)) return true;
95
+ if (["false", "0", "no", "n"].includes(normalized)) return false;
96
+ const flag = key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
97
+ throw new Error(`--${flag} must be true or false.`);
98
+ }
82
99
  function readStdin() {
83
100
  return readFileSync(0, "utf-8");
84
101
  }
102
+ function formatPollDuration(ms) {
103
+ if (typeof ms !== "number" || !Number.isFinite(ms)) return "n/a";
104
+ const seconds = Math.max(0, Math.round(ms / 1e3));
105
+ const minutes = Math.floor(seconds / 60);
106
+ const remainder = seconds % 60;
107
+ return minutes > 0 ? `${minutes}m${String(remainder).padStart(2, "0")}s` : `${seconds}s`;
108
+ }
109
+ function riddlePollProgressLine(snapshot) {
110
+ const submittedAt = snapshot.submitted_at || "not-submitted";
111
+ const queuePart = snapshot.running_without_submission ? ` queued_for=${formatPollDuration(snapshot.queue_elapsed_ms)}` : snapshot.queue_elapsed_ms !== null ? ` queue=${formatPollDuration(snapshot.queue_elapsed_ms)}` : "";
112
+ const terminalPart = snapshot.terminal ? " terminal=true" : "";
113
+ return [
114
+ "[riddle-poll]",
115
+ snapshot.job_id,
116
+ `status=${snapshot.status || "unknown"}`,
117
+ `attempt=${snapshot.attempt}/${snapshot.attempts}`,
118
+ `elapsed=${formatPollDuration(snapshot.elapsed_ms)}`,
119
+ `submitted_at=${submittedAt}${queuePart}${terminalPart}`
120
+ ].join(" ");
121
+ }
85
122
  function readJsonValue(value, label) {
86
123
  if (!value) throw new Error(`${label} is required.`);
87
124
  const raw = value === "-" ? readStdin() : existsSync(value) ? readFileSync(value, "utf-8") : value;
@@ -504,6 +541,7 @@ async function main() {
504
541
  script: readFileSync(scriptFile, "utf-8"),
505
542
  viewport: parseRiddleViewport(optionString(options, "viewport")),
506
543
  timeoutSec: optionString(options, "timeout") ? Number(optionString(options, "timeout")) : void 0,
544
+ strict: optionBoolean(options, "strict"),
507
545
  sync: options.sync === true ? true : void 0
508
546
  });
509
547
  process.stdout.write(`${JSON.stringify(result, null, 2)}
@@ -513,10 +551,16 @@ async function main() {
513
551
  if (command === "riddle-poll") {
514
552
  const jobId = positional[1];
515
553
  if (!jobId) throw new Error("riddle-poll requires <job-id>.");
554
+ const wait = options.wait === true;
516
555
  const result = await createRiddleApiClient(riddleClientConfig(options)).pollJob(jobId, {
517
- wait: options.wait === true,
556
+ wait,
518
557
  attempts: optionString(options, "attempts") ? Number(optionString(options, "attempts")) : void 0,
519
- intervalMs: optionString(options, "intervalMs") ? Number(optionString(options, "intervalMs")) : void 0
558
+ intervalMs: optionString(options, "intervalMs") ? Number(optionString(options, "intervalMs")) : void 0,
559
+ progressEveryMs: optionString(options, "progressEveryMs") ? Number(optionString(options, "progressEveryMs")) : void 0,
560
+ onProgress: wait && options.quiet !== true ? (snapshot) => {
561
+ process.stderr.write(`${riddlePollProgressLine(snapshot)}
562
+ `);
563
+ } : void 0
520
564
  });
521
565
  process.stdout.write(`${JSON.stringify(result, null, 2)}
522
566
  `);
package/dist/index.cjs CHANGED
@@ -10291,21 +10291,109 @@ async function runRiddleScript(config, input) {
10291
10291
  function isTerminalRiddleJobStatus(status) {
10292
10292
  return ["completed", "complete", "completed_error", "completed_timeout", "failed"].includes(String(status || ""));
10293
10293
  }
10294
+ function stringField(record, key) {
10295
+ const value = record?.[key];
10296
+ return typeof value === "string" && value.trim() ? value.trim() : null;
10297
+ }
10298
+ function parseTimestampMs(value) {
10299
+ if (!value) return null;
10300
+ const parsed = Date.parse(value);
10301
+ return Number.isFinite(parsed) ? parsed : null;
10302
+ }
10303
+ function buildPollSnapshot(jobId, job, input) {
10304
+ const status = job?.status ? String(job.status) : null;
10305
+ const terminal = isTerminalRiddleJobStatus(status);
10306
+ const createdAt = stringField(job, "created_at");
10307
+ const submittedAt = stringField(job, "submitted_at");
10308
+ const completedAt = stringField(job, "completed_at");
10309
+ const createdMs = parseTimestampMs(createdAt);
10310
+ const submittedMs = parseTimestampMs(submittedAt);
10311
+ let queueElapsedMs = null;
10312
+ if (createdMs !== null && submittedMs !== null) {
10313
+ queueElapsedMs = Math.max(0, submittedMs - createdMs);
10314
+ } else if (createdMs !== null && !submittedAt && !terminal) {
10315
+ queueElapsedMs = Math.max(0, input.observedAt - createdMs);
10316
+ }
10317
+ return {
10318
+ job_id: jobId,
10319
+ status,
10320
+ terminal,
10321
+ attempt: input.attempt,
10322
+ attempts: input.attempts,
10323
+ elapsed_ms: Math.max(0, input.observedAt - input.startedAt),
10324
+ created_at: createdAt,
10325
+ submitted_at: submittedAt,
10326
+ completed_at: completedAt,
10327
+ queue_elapsed_ms: queueElapsedMs,
10328
+ running_without_submission: Boolean(status && !terminal && !submittedAt)
10329
+ };
10330
+ }
10331
+ function pollMessage(snapshot, timedOut) {
10332
+ if (!timedOut) return void 0;
10333
+ const submitted = snapshot.submitted_at || "not submitted";
10334
+ const queue = snapshot.queue_elapsed_ms !== null ? ` queue_elapsed_ms=${snapshot.queue_elapsed_ms}` : "";
10335
+ return `Riddle job ${snapshot.job_id} did not reach a terminal status after ${snapshot.attempt} poll attempts; status=${snapshot.status || "unknown"} submitted_at=${submitted}.${queue}`;
10336
+ }
10294
10337
  async function pollRiddleJob(config, jobId, options = {}) {
10295
10338
  if (!jobId?.trim()) throw new Error("jobId is required");
10296
- const attempts = options.attempts || (options.wait ? 60 : 1);
10297
- const intervalMs = options.intervalMs || 2e3;
10339
+ const attempts = Math.max(1, Math.floor(options.attempts ?? (options.wait ? 300 : 1)));
10340
+ const intervalMs = Math.max(0, Math.floor(options.intervalMs ?? 2e3));
10341
+ const progressEveryMs = Math.max(0, Math.floor(options.progressEveryMs ?? 1e4));
10342
+ const startedAt = Date.now();
10298
10343
  let job = null;
10344
+ let lastSnapshot = null;
10345
+ let lastProgressAt = 0;
10346
+ let lastProgressKey = "";
10299
10347
  for (let index = 0; index < attempts; index += 1) {
10300
10348
  job = await riddleRequestJson(config, `/v1/jobs/${jobId}`);
10301
- if (isTerminalRiddleJobStatus(job.status)) break;
10349
+ const observedAt = Date.now();
10350
+ lastSnapshot = buildPollSnapshot(jobId, job, {
10351
+ attempt: index + 1,
10352
+ attempts,
10353
+ startedAt,
10354
+ observedAt
10355
+ });
10356
+ const progressKey = [
10357
+ lastSnapshot.status || "unknown",
10358
+ lastSnapshot.terminal ? "terminal" : "nonterminal",
10359
+ lastSnapshot.submitted_at ? "submitted" : "unsubmitted"
10360
+ ].join(":");
10361
+ if (options.onProgress) {
10362
+ const shouldReport = index === 0 || lastSnapshot.terminal || progressKey !== lastProgressKey || observedAt - lastProgressAt >= progressEveryMs;
10363
+ if (shouldReport) {
10364
+ lastProgressAt = observedAt;
10365
+ lastProgressKey = progressKey;
10366
+ await options.onProgress(lastSnapshot);
10367
+ }
10368
+ }
10369
+ if (lastSnapshot.terminal) break;
10302
10370
  if (index + 1 < attempts) {
10303
10371
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
10304
10372
  }
10305
10373
  }
10306
10374
  const status = job?.status ? String(job.status) : null;
10375
+ const fallbackObservedAt = Date.now();
10376
+ const snapshot = lastSnapshot || buildPollSnapshot(jobId, job, {
10377
+ attempt: 0,
10378
+ attempts,
10379
+ startedAt,
10380
+ observedAt: fallbackObservedAt
10381
+ });
10307
10382
  if (!isTerminalRiddleJobStatus(status)) {
10308
- return { ok: true, job_id: jobId, status, terminal: false, job };
10383
+ const timedOut = Boolean(options.wait);
10384
+ return {
10385
+ ok: !timedOut,
10386
+ job_id: jobId,
10387
+ status,
10388
+ terminal: false,
10389
+ job,
10390
+ poll: {
10391
+ ...snapshot,
10392
+ timed_out: timedOut,
10393
+ interval_ms: intervalMs,
10394
+ message: pollMessage(snapshot, timedOut)
10395
+ }
10396
+ };
10309
10397
  }
10310
10398
  const artifacts = await riddleRequestJson(config, `/v1/jobs/${jobId}/artifacts`);
10311
10399
  return {
@@ -10314,7 +10402,12 @@ async function pollRiddleJob(config, jobId, options = {}) {
10314
10402
  status,
10315
10403
  terminal: true,
10316
10404
  job,
10317
- artifacts
10405
+ artifacts,
10406
+ poll: {
10407
+ ...snapshot,
10408
+ timed_out: false,
10409
+ interval_ms: intervalMs
10410
+ }
10318
10411
  };
10319
10412
  }
10320
10413
  function createRiddleApiClient(config = {}) {
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, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, 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, RiddlePollJobResult, 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, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, 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, RiddleProofProfileResult, RiddleProofProfileRouteEvidence, 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, RiddlePollJobResult, 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, RiddleRunScriptInput, RiddleServerPreviewInput, RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview } from './riddle-client.js';
package/dist/index.js CHANGED
@@ -72,7 +72,7 @@ import {
72
72
  riddleRequestJson,
73
73
  runRiddleScript,
74
74
  runRiddleServerPreview
75
- } from "./chunk-5KOHSE4V.js";
75
+ } from "./chunk-7PSWK57T.js";
76
76
  import {
77
77
  DEFAULT_DIAGNOSTIC_ARRAY_LIMIT,
78
78
  DEFAULT_DIAGNOSTIC_HISTORY_LIMIT,
@@ -241,21 +241,109 @@ async function runRiddleScript(config, input) {
241
241
  function isTerminalRiddleJobStatus(status) {
242
242
  return ["completed", "complete", "completed_error", "completed_timeout", "failed"].includes(String(status || ""));
243
243
  }
244
+ function stringField(record, key) {
245
+ const value = record?.[key];
246
+ return typeof value === "string" && value.trim() ? value.trim() : null;
247
+ }
248
+ function parseTimestampMs(value) {
249
+ if (!value) return null;
250
+ const parsed = Date.parse(value);
251
+ return Number.isFinite(parsed) ? parsed : null;
252
+ }
253
+ function buildPollSnapshot(jobId, job, input) {
254
+ const status = job?.status ? String(job.status) : null;
255
+ const terminal = isTerminalRiddleJobStatus(status);
256
+ const createdAt = stringField(job, "created_at");
257
+ const submittedAt = stringField(job, "submitted_at");
258
+ const completedAt = stringField(job, "completed_at");
259
+ const createdMs = parseTimestampMs(createdAt);
260
+ const submittedMs = parseTimestampMs(submittedAt);
261
+ let queueElapsedMs = null;
262
+ if (createdMs !== null && submittedMs !== null) {
263
+ queueElapsedMs = Math.max(0, submittedMs - createdMs);
264
+ } else if (createdMs !== null && !submittedAt && !terminal) {
265
+ queueElapsedMs = Math.max(0, input.observedAt - createdMs);
266
+ }
267
+ return {
268
+ job_id: jobId,
269
+ status,
270
+ terminal,
271
+ attempt: input.attempt,
272
+ attempts: input.attempts,
273
+ elapsed_ms: Math.max(0, input.observedAt - input.startedAt),
274
+ created_at: createdAt,
275
+ submitted_at: submittedAt,
276
+ completed_at: completedAt,
277
+ queue_elapsed_ms: queueElapsedMs,
278
+ running_without_submission: Boolean(status && !terminal && !submittedAt)
279
+ };
280
+ }
281
+ function pollMessage(snapshot, timedOut) {
282
+ if (!timedOut) return void 0;
283
+ const submitted = snapshot.submitted_at || "not submitted";
284
+ const queue = snapshot.queue_elapsed_ms !== null ? ` queue_elapsed_ms=${snapshot.queue_elapsed_ms}` : "";
285
+ return `Riddle job ${snapshot.job_id} did not reach a terminal status after ${snapshot.attempt} poll attempts; status=${snapshot.status || "unknown"} submitted_at=${submitted}.${queue}`;
286
+ }
244
287
  async function pollRiddleJob(config, jobId, options = {}) {
245
288
  if (!jobId?.trim()) throw new Error("jobId is required");
246
- const attempts = options.attempts || (options.wait ? 60 : 1);
247
- const intervalMs = options.intervalMs || 2e3;
289
+ const attempts = Math.max(1, Math.floor(options.attempts ?? (options.wait ? 300 : 1)));
290
+ const intervalMs = Math.max(0, Math.floor(options.intervalMs ?? 2e3));
291
+ const progressEveryMs = Math.max(0, Math.floor(options.progressEveryMs ?? 1e4));
292
+ const startedAt = Date.now();
248
293
  let job = null;
294
+ let lastSnapshot = null;
295
+ let lastProgressAt = 0;
296
+ let lastProgressKey = "";
249
297
  for (let index = 0; index < attempts; index += 1) {
250
298
  job = await riddleRequestJson(config, `/v1/jobs/${jobId}`);
251
- if (isTerminalRiddleJobStatus(job.status)) break;
299
+ const observedAt = Date.now();
300
+ lastSnapshot = buildPollSnapshot(jobId, job, {
301
+ attempt: index + 1,
302
+ attempts,
303
+ startedAt,
304
+ observedAt
305
+ });
306
+ const progressKey = [
307
+ lastSnapshot.status || "unknown",
308
+ lastSnapshot.terminal ? "terminal" : "nonterminal",
309
+ lastSnapshot.submitted_at ? "submitted" : "unsubmitted"
310
+ ].join(":");
311
+ if (options.onProgress) {
312
+ const shouldReport = index === 0 || lastSnapshot.terminal || progressKey !== lastProgressKey || observedAt - lastProgressAt >= progressEveryMs;
313
+ if (shouldReport) {
314
+ lastProgressAt = observedAt;
315
+ lastProgressKey = progressKey;
316
+ await options.onProgress(lastSnapshot);
317
+ }
318
+ }
319
+ if (lastSnapshot.terminal) break;
252
320
  if (index + 1 < attempts) {
253
321
  await new Promise((resolve) => setTimeout(resolve, intervalMs));
254
322
  }
255
323
  }
256
324
  const status = job?.status ? String(job.status) : null;
325
+ const fallbackObservedAt = Date.now();
326
+ const snapshot = lastSnapshot || buildPollSnapshot(jobId, job, {
327
+ attempt: 0,
328
+ attempts,
329
+ startedAt,
330
+ observedAt: fallbackObservedAt
331
+ });
257
332
  if (!isTerminalRiddleJobStatus(status)) {
258
- return { ok: true, job_id: jobId, status, terminal: false, job };
333
+ const timedOut = Boolean(options.wait);
334
+ return {
335
+ ok: !timedOut,
336
+ job_id: jobId,
337
+ status,
338
+ terminal: false,
339
+ job,
340
+ poll: {
341
+ ...snapshot,
342
+ timed_out: timedOut,
343
+ interval_ms: intervalMs,
344
+ message: pollMessage(snapshot, timedOut)
345
+ }
346
+ };
259
347
  }
260
348
  const artifacts = await riddleRequestJson(config, `/v1/jobs/${jobId}/artifacts`);
261
349
  return {
@@ -264,7 +352,12 @@ async function pollRiddleJob(config, jobId, options = {}) {
264
352
  status,
265
353
  terminal: true,
266
354
  job,
267
- artifacts
355
+ artifacts,
356
+ poll: {
357
+ ...snapshot,
358
+ timed_out: false,
359
+ interval_ms: intervalMs
360
+ }
268
361
  };
269
362
  }
270
363
  function createRiddleApiClient(config = {}) {
@@ -7,6 +7,31 @@ interface RiddleClientConfig {
7
7
  apiBaseUrl?: string;
8
8
  fetchImpl?: RiddleFetch;
9
9
  }
10
+ interface RiddlePollProgressSnapshot {
11
+ job_id: string;
12
+ status: string | null;
13
+ terminal: boolean;
14
+ attempt: number;
15
+ attempts: number;
16
+ elapsed_ms: number;
17
+ created_at: string | null;
18
+ submitted_at: string | null;
19
+ completed_at: string | null;
20
+ queue_elapsed_ms: number | null;
21
+ running_without_submission: boolean;
22
+ }
23
+ interface RiddlePollSummary extends RiddlePollProgressSnapshot {
24
+ timed_out: boolean;
25
+ interval_ms: number;
26
+ message?: string;
27
+ }
28
+ interface RiddlePollJobOptions {
29
+ wait?: boolean;
30
+ attempts?: number;
31
+ intervalMs?: number;
32
+ progressEveryMs?: number;
33
+ onProgress?: (snapshot: RiddlePollProgressSnapshot) => void | Promise<void>;
34
+ }
10
35
  interface RiddlePreviewDeployResult {
11
36
  ok: true;
12
37
  id: string;
@@ -58,6 +83,7 @@ interface RiddlePollJobResult {
58
83
  terminal: boolean;
59
84
  job: Record<string, unknown> | null;
60
85
  artifacts?: Record<string, unknown> | null;
86
+ poll?: RiddlePollSummary;
61
87
  }
62
88
  interface RiddleServerPreviewResult {
63
89
  ok: boolean;
@@ -83,21 +109,13 @@ declare function parseRiddleViewport(value?: string): {
83
109
  declare function runRiddleServerPreview(config: RiddleClientConfig, input: RiddleServerPreviewInput): Promise<RiddleServerPreviewResult>;
84
110
  declare function runRiddleScript(config: RiddleClientConfig, input: RiddleRunScriptInput): Promise<Record<string, unknown>>;
85
111
  declare function isTerminalRiddleJobStatus(status: unknown): boolean;
86
- declare function pollRiddleJob(config: RiddleClientConfig, jobId: string, options?: {
87
- wait?: boolean;
88
- attempts?: number;
89
- intervalMs?: number;
90
- }): Promise<RiddlePollJobResult>;
112
+ declare function pollRiddleJob(config: RiddleClientConfig, jobId: string, options?: RiddlePollJobOptions): Promise<RiddlePollJobResult>;
91
113
  declare function createRiddleApiClient(config?: RiddleClientConfig): {
92
114
  requestJson: <T = unknown>(pathname: string, init?: RequestInit) => Promise<T>;
93
115
  deployStaticPreview: (directory: string, label: string) => Promise<RiddlePreviewDeployResult>;
94
116
  runScript: (input: RiddleRunScriptInput) => Promise<Record<string, unknown>>;
95
117
  runServerPreview: (input: RiddleServerPreviewInput) => Promise<RiddleServerPreviewResult>;
96
- pollJob: (jobId: string, options?: {
97
- wait?: boolean;
98
- attempts?: number;
99
- intervalMs?: number;
100
- }) => Promise<RiddlePollJobResult>;
118
+ pollJob: (jobId: string, options?: RiddlePollJobOptions) => Promise<RiddlePollJobResult>;
101
119
  };
102
120
 
103
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobResult, type RiddlePreviewDeployResult, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
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 };
@@ -7,6 +7,31 @@ interface RiddleClientConfig {
7
7
  apiBaseUrl?: string;
8
8
  fetchImpl?: RiddleFetch;
9
9
  }
10
+ interface RiddlePollProgressSnapshot {
11
+ job_id: string;
12
+ status: string | null;
13
+ terminal: boolean;
14
+ attempt: number;
15
+ attempts: number;
16
+ elapsed_ms: number;
17
+ created_at: string | null;
18
+ submitted_at: string | null;
19
+ completed_at: string | null;
20
+ queue_elapsed_ms: number | null;
21
+ running_without_submission: boolean;
22
+ }
23
+ interface RiddlePollSummary extends RiddlePollProgressSnapshot {
24
+ timed_out: boolean;
25
+ interval_ms: number;
26
+ message?: string;
27
+ }
28
+ interface RiddlePollJobOptions {
29
+ wait?: boolean;
30
+ attempts?: number;
31
+ intervalMs?: number;
32
+ progressEveryMs?: number;
33
+ onProgress?: (snapshot: RiddlePollProgressSnapshot) => void | Promise<void>;
34
+ }
10
35
  interface RiddlePreviewDeployResult {
11
36
  ok: true;
12
37
  id: string;
@@ -58,6 +83,7 @@ interface RiddlePollJobResult {
58
83
  terminal: boolean;
59
84
  job: Record<string, unknown> | null;
60
85
  artifacts?: Record<string, unknown> | null;
86
+ poll?: RiddlePollSummary;
61
87
  }
62
88
  interface RiddleServerPreviewResult {
63
89
  ok: boolean;
@@ -83,21 +109,13 @@ declare function parseRiddleViewport(value?: string): {
83
109
  declare function runRiddleServerPreview(config: RiddleClientConfig, input: RiddleServerPreviewInput): Promise<RiddleServerPreviewResult>;
84
110
  declare function runRiddleScript(config: RiddleClientConfig, input: RiddleRunScriptInput): Promise<Record<string, unknown>>;
85
111
  declare function isTerminalRiddleJobStatus(status: unknown): boolean;
86
- declare function pollRiddleJob(config: RiddleClientConfig, jobId: string, options?: {
87
- wait?: boolean;
88
- attempts?: number;
89
- intervalMs?: number;
90
- }): Promise<RiddlePollJobResult>;
112
+ declare function pollRiddleJob(config: RiddleClientConfig, jobId: string, options?: RiddlePollJobOptions): Promise<RiddlePollJobResult>;
91
113
  declare function createRiddleApiClient(config?: RiddleClientConfig): {
92
114
  requestJson: <T = unknown>(pathname: string, init?: RequestInit) => Promise<T>;
93
115
  deployStaticPreview: (directory: string, label: string) => Promise<RiddlePreviewDeployResult>;
94
116
  runScript: (input: RiddleRunScriptInput) => Promise<Record<string, unknown>>;
95
117
  runServerPreview: (input: RiddleServerPreviewInput) => Promise<RiddleServerPreviewResult>;
96
- pollJob: (jobId: string, options?: {
97
- wait?: boolean;
98
- attempts?: number;
99
- intervalMs?: number;
100
- }) => Promise<RiddlePollJobResult>;
118
+ pollJob: (jobId: string, options?: RiddlePollJobOptions) => Promise<RiddlePollJobResult>;
101
119
  };
102
120
 
103
- export { DEFAULT_RIDDLE_API_BASE_URL, DEFAULT_RIDDLE_API_KEY_FILE, RiddleApiError, type RiddleClientConfig, type RiddleFetch, type RiddlePollJobResult, type RiddlePreviewDeployResult, type RiddleRunScriptInput, type RiddleServerPreviewInput, type RiddleServerPreviewResult, createRiddleApiClient, deployRiddleStaticPreview, isTerminalRiddleJobStatus, parseRiddleViewport, pollRiddleJob, resolveRiddleApiKey, riddleRequestJson, runRiddleScript, runRiddleServerPreview };
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 };
@@ -11,7 +11,7 @@ import {
11
11
  riddleRequestJson,
12
12
  runRiddleScript,
13
13
  runRiddleServerPreview
14
- } from "./chunk-5KOHSE4V.js";
14
+ } from "./chunk-7PSWK57T.js";
15
15
  export {
16
16
  DEFAULT_RIDDLE_API_BASE_URL,
17
17
  DEFAULT_RIDDLE_API_KEY_FILE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riddledc/riddle-proof",
3
- "version": "0.7.24",
3
+ "version": "0.7.26",
4
4
  "description": "Reusable Riddle Proof contracts and helpers for evidence-backed agent changes.",
5
5
  "license": "MIT",
6
6
  "author": "RiddleDC",