@riddledc/riddle-proof 0.8.84 → 0.8.85

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.
Files changed (67) hide show
  1. package/README.md +193 -0
  2. package/capabilities.json +17 -0
  3. package/dist/advanced/engine-harness.js +2 -2
  4. package/dist/advanced/index.js +4 -4
  5. package/dist/advanced/runner.js +2 -2
  6. package/dist/change-proof.cjs +22 -260
  7. package/dist/change-proof.d.cts +1 -1
  8. package/dist/change-proof.d.ts +1 -1
  9. package/dist/change-proof.js +2 -2
  10. package/dist/checked-meaning.cjs +67 -0
  11. package/dist/checked-meaning.d.cts +2 -0
  12. package/dist/checked-meaning.d.ts +2 -0
  13. package/dist/checked-meaning.js +41 -0
  14. package/dist/{chunk-QYZ3GKCP.js → chunk-AFARUBE4.js} +12 -11
  15. package/dist/chunk-J2SIQGQI.js +71 -0
  16. package/dist/{chunk-7OAETQU3.js → chunk-JZKLCY5G.js} +1 -1
  17. package/dist/chunk-KB7FYRBG.js +46 -0
  18. package/dist/chunk-NWLKJ2WI.js +31 -0
  19. package/dist/{chunk-LR4UYJDY.js → chunk-O2AO726C.js} +1 -1
  20. package/dist/chunk-ODLGSEP2.js +43 -0
  21. package/dist/chunk-OHDNCXRM.js +17 -0
  22. package/dist/cli/index.js +7 -7
  23. package/dist/cli.cjs +265 -1122
  24. package/dist/cli.d.cts +0 -1
  25. package/dist/cli.d.ts +0 -1
  26. package/dist/cli.js +7 -7
  27. package/dist/engine-harness.js +2 -2
  28. package/dist/grounded-evidence.cjs +95 -0
  29. package/dist/grounded-evidence.d.cts +2 -0
  30. package/dist/grounded-evidence.d.ts +2 -0
  31. package/dist/grounded-evidence.js +69 -0
  32. package/dist/index.cjs +314 -2042
  33. package/dist/index.d.cts +9 -3
  34. package/dist/index.d.ts +9 -3
  35. package/dist/index.js +126 -18
  36. package/dist/pr-comment.cjs +17 -107
  37. package/dist/pr-comment.d.cts +1 -1
  38. package/dist/pr-comment.d.ts +1 -1
  39. package/dist/pr-comment.js +3 -3
  40. package/dist/receipts.cjs +10 -255
  41. package/dist/receipts.d.cts +7 -115
  42. package/dist/receipts.d.ts +7 -115
  43. package/dist/receipts.js +1 -1
  44. package/dist/riddle-client.cjs +23 -695
  45. package/dist/riddle-client.d.cts +1 -188
  46. package/dist/riddle-client.d.ts +1 -188
  47. package/dist/riddle-client.js +5 -2
  48. package/dist/runner.js +2 -2
  49. package/dist/runtime/index.cjs +23 -695
  50. package/dist/runtime/index.d.cts +1 -5
  51. package/dist/runtime/index.d.ts +1 -5
  52. package/dist/runtime/index.js +5 -2
  53. package/dist/runtime/riddle-client.cjs +23 -695
  54. package/dist/runtime/riddle-client.d.cts +1 -5
  55. package/dist/runtime/riddle-client.d.ts +1 -5
  56. package/dist/runtime/riddle-client.js +5 -2
  57. package/dist/semantic-certificate.cjs +17 -1083
  58. package/dist/semantic-certificate.d.cts +2 -310
  59. package/dist/semantic-certificate.d.ts +2 -310
  60. package/dist/semantic-certificate.js +1 -1
  61. package/package.json +28 -5
  62. package/runtime/lib/riddle_core_call.mjs +3 -806
  63. package/dist/chunk-5IFZSUPF.js +0 -644
  64. package/dist/chunk-AQTCU6W5.js +0 -1086
  65. package/dist/chunk-MEVVL4TI.js +0 -258
  66. package/dist/{chunk-WLUMLHII.js → chunk-BID7CKMM.js} +9 -9
  67. package/dist/{chunk-YH7ADFY4.js → chunk-IVSP24XI.js} +3 -3
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,710 +15,39 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/riddle-client.ts
31
21
  var riddle_client_exports = {};
32
22
  __export(riddle_client_exports, {
33
- DEFAULT_RIDDLE_API_BASE_URL: () => DEFAULT_RIDDLE_API_BASE_URL,
34
- DEFAULT_RIDDLE_API_KEY_FILE: () => DEFAULT_RIDDLE_API_KEY_FILE,
35
- RIDDLE_UNSUBMITTED_WAKE_HINT: () => RIDDLE_UNSUBMITTED_WAKE_HINT,
36
- RiddleApiError: () => RiddleApiError,
37
- collectRiddlePreviewDeployWarnings: () => collectRiddlePreviewDeployWarnings,
38
- createRiddleApiClient: () => createRiddleApiClient,
39
- deployRiddlePreview: () => deployRiddlePreview,
40
- deployRiddleStaticPreview: () => deployRiddleStaticPreview,
41
- detectRiddlePreviewSource: () => detectRiddlePreviewSource,
42
- getRiddleBalance: () => getRiddleBalance,
43
- isTerminalRiddleJobStatus: () => isTerminalRiddleJobStatus,
44
- parseRiddleViewport: () => parseRiddleViewport,
45
- pollRiddleJob: () => pollRiddleJob,
46
- resolveRiddleApiKey: () => resolveRiddleApiKey,
47
- resolveRiddleApiKeySource: () => resolveRiddleApiKeySource,
48
- riddleRequestJson: () => riddleRequestJson,
49
- runRiddleScript: () => runRiddleScript,
50
- runRiddleServerPreview: () => runRiddleServerPreview
23
+ DEFAULT_RIDDLE_API_BASE_URL: () => import_client.DEFAULT_RIDDLE_API_BASE_URL,
24
+ DEFAULT_RIDDLE_API_KEY_FILE: () => import_client.DEFAULT_RIDDLE_API_KEY_FILE,
25
+ RIDDLE_BALANCE_ENDPOINT_PATH: () => import_client.RIDDLE_BALANCE_ENDPOINT_PATH,
26
+ RIDDLE_UNSUBMITTED_WAKE_HINT: () => import_client.RIDDLE_UNSUBMITTED_WAKE_HINT,
27
+ RiddleApiError: () => import_client.RiddleApiError,
28
+ collectRiddlePreviewDeployWarnings: () => import_client.collectRiddlePreviewDeployWarnings,
29
+ createRiddleApiClient: () => import_client.createRiddleApiClient,
30
+ deployRiddlePreview: () => import_client.deployRiddlePreview,
31
+ deployRiddleStaticPreview: () => import_client.deployRiddleStaticPreview,
32
+ detectRiddlePreviewSource: () => import_client.detectRiddlePreviewSource,
33
+ getRiddleBalance: () => import_client.getRiddleBalance,
34
+ getRiddleJobArtifacts: () => import_client.getRiddleJobArtifacts,
35
+ isTerminalRiddleJobStatus: () => import_client.isTerminalRiddleJobStatus,
36
+ parseRiddleViewport: () => import_client.parseRiddleViewport,
37
+ pollRiddleJob: () => import_client.pollRiddleJob,
38
+ resolveRiddleApiKey: () => import_client.resolveRiddleApiKey,
39
+ resolveRiddleApiKeySource: () => import_client.resolveRiddleApiKeySource,
40
+ riddleRequestJson: () => import_client.riddleRequestJson,
41
+ runRiddleScript: () => import_client.runRiddleScript,
42
+ runRiddleServerPreview: () => import_client.runRiddleServerPreview
51
43
  });
52
44
  module.exports = __toCommonJS(riddle_client_exports);
53
- var import_node_child_process = require("child_process");
54
- var import_node_fs = require("fs");
55
- var import_node_os = require("os");
56
- var import_node_path = __toESM(require("path"), 1);
57
-
58
- // src/receipts.ts
59
- var RIDDLE_PREVIEW_RECEIPT_VERSION = "riddle.preview-receipt.v1";
60
- function isRecord(value) {
61
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
62
- }
63
- function requiredString(record, key, context) {
64
- const value = record[key];
65
- if (typeof value !== "string" || !value.trim()) {
66
- throw new Error(`${context}.${key} must be a non-empty string.`);
67
- }
68
- return value.trim();
69
- }
70
- function normalizedSourceIdentity(value) {
71
- if (!isRecord(value)) return {};
72
- return {
73
- git_revision: typeof value.git_revision === "string" && value.git_revision.trim() ? value.git_revision.trim() : void 0,
74
- repository: typeof value.repository === "string" && value.repository.trim() ? value.repository.trim() : void 0,
75
- dirty: typeof value.dirty === "boolean" ? value.dirty : void 0,
76
- label: typeof value.label === "string" && value.label.trim() ? value.label.trim() : void 0
77
- };
78
- }
79
- function parseRiddlePreviewReceipt(value) {
80
- if (!isRecord(value)) throw new Error("Preview receipt must be an object.");
81
- if (value.version !== RIDDLE_PREVIEW_RECEIPT_VERSION) {
82
- throw new Error(`Unsupported Preview receipt version ${String(value.version || "missing")}.`);
83
- }
84
- if (!isRecord(value.source)) throw new Error("Preview receipt source must be an object.");
85
- const expiresAt = requiredString(value, "expires_at", "preview receipt");
86
- const publishedAt = requiredString(value, "published_at", "preview receipt");
87
- const contentDigest = requiredString(value, "content_digest", "preview receipt");
88
- if (!contentDigest.startsWith("sha256:") || contentDigest.length <= "sha256:".length) {
89
- throw new Error("preview receipt.content_digest must be a sha256 digest.");
90
- }
91
- if (!Number.isFinite(Date.parse(expiresAt)) || !Number.isFinite(Date.parse(publishedAt))) {
92
- throw new Error("Preview receipt timestamps must be valid ISO date strings.");
93
- }
94
- return {
95
- version: RIDDLE_PREVIEW_RECEIPT_VERSION,
96
- preview_id: requiredString(value, "preview_id", "preview receipt"),
97
- url: requiredString(value, "url", "preview receipt"),
98
- expires_at: expiresAt,
99
- content_digest: contentDigest,
100
- source: normalizedSourceIdentity(value.source),
101
- published_at: publishedAt
102
- };
103
- }
104
-
105
- // src/riddle-client.ts
106
- var DEFAULT_RIDDLE_API_BASE_URL = "https://api.riddledc.com";
107
- var DEFAULT_RIDDLE_API_KEY_FILE = "/tmp/riddle-api-key";
108
- var RIDDLE_UNSUBMITTED_WAKE_HINT = "hosted worker may still be waking or waiting for a lease";
109
- var RiddleApiError = class extends Error {
110
- constructor(pathname, status, body) {
111
- super(`Riddle API ${pathname} failed HTTP ${status}: ${body}`);
112
- this.name = "RiddleApiError";
113
- this.status = status;
114
- this.body = body;
115
- this.path = pathname;
116
- }
117
- };
118
- var PREVIEW_PUBLISH_RECOVERY_STATUSES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
119
- var PREVIEW_PUBLISH_RECOVERY_ATTEMPTS = 30;
120
- var PREVIEW_PUBLISH_RECOVERY_INTERVAL_MS = 2e3;
121
- function normalizeBaseUrl(value) {
122
- return (value || DEFAULT_RIDDLE_API_BASE_URL).replace(/\/$/, "");
123
- }
124
- function fetchFor(config = {}) {
125
- return config.fetchImpl || fetch;
126
- }
127
- function resolveRiddleApiKeyWithSource(config = {}) {
128
- if (config.apiKey?.trim()) return { apiKey: config.apiKey.trim(), source: "option" };
129
- if (process.env.RIDDLE_API_KEY?.trim()) return { apiKey: process.env.RIDDLE_API_KEY.trim(), source: "env" };
130
- const keyFile = config.apiKeyFile || process.env.RIDDLE_API_KEY_FILE || DEFAULT_RIDDLE_API_KEY_FILE;
131
- if ((0, import_node_fs.existsSync)(keyFile)) {
132
- const key = (0, import_node_fs.readFileSync)(keyFile, "utf8").trim();
133
- if (key) return { apiKey: key, source: "file", file: keyFile };
134
- }
135
- throw new Error(`Riddle API key missing. Set RIDDLE_API_KEY or write ${DEFAULT_RIDDLE_API_KEY_FILE}.`);
136
- }
137
- function resolveRiddleApiKeySource(config = {}) {
138
- const { apiKey: _apiKey, ...source } = resolveRiddleApiKeyWithSource(config);
139
- return source;
140
- }
141
- function resolveRiddleApiKey(config = {}) {
142
- return resolveRiddleApiKeyWithSource(config).apiKey;
143
- }
144
- async function riddleRequestJson(config, pathname, init = {}) {
145
- const response = await fetchFor(config)(`${normalizeBaseUrl(config.apiBaseUrl)}${pathname}`, {
146
- ...init,
147
- headers: {
148
- Authorization: `Bearer ${resolveRiddleApiKey(config)}`,
149
- "Content-Type": "application/json",
150
- ...init.headers || {}
151
- }
152
- });
153
- const text = await response.text();
154
- let json = null;
155
- try {
156
- json = JSON.parse(text);
157
- } catch {
158
- }
159
- if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
160
- return json ?? text;
161
- }
162
- async function getRiddleBalance(config = {}) {
163
- return riddleRequestJson(config, "/v1/balance", { method: "GET" });
164
- }
165
- function previewDeployResultFromRecord(input) {
166
- const { record, id, label, framework, expiresAt, publishRecovered, publishError } = input;
167
- const receipt = record.receipt && typeof record.receipt === "object" ? parseRiddlePreviewReceipt(record.receipt) : void 0;
168
- return {
169
- ok: true,
170
- id: String(record.id || record.preview_id || id),
171
- label,
172
- framework,
173
- preview_url: String(record.preview_url || ""),
174
- file_count: typeof record.file_count === "number" ? record.file_count : void 0,
175
- total_bytes: typeof record.total_bytes === "number" ? record.total_bytes : void 0,
176
- expires_at: receipt?.expires_at || expiresAt,
177
- receipt,
178
- publish_recovered: publishRecovered || void 0,
179
- publish_error: publishError,
180
- warnings: input.warnings?.length ? input.warnings : void 0,
181
- raw: record
182
- };
183
- }
184
- function gitOutput(directory, args) {
185
- try {
186
- return (0, import_node_child_process.execFileSync)("git", ["-C", directory, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
187
- } catch {
188
- return "";
189
- }
190
- }
191
- function detectRiddlePreviewSource(directory) {
192
- const gitRevision = gitOutput(directory, ["rev-parse", "HEAD"]);
193
- if (!gitRevision) return {};
194
- const repository = gitOutput(directory, ["config", "--get", "remote.origin.url"]);
195
- const status = gitOutput(directory, ["status", "--porcelain", "--untracked-files=normal"]);
196
- return {
197
- git_revision: gitRevision,
198
- repository: repository || void 0,
199
- dirty: Boolean(status)
200
- };
201
- }
202
- function canRecoverPreviewPublish(error) {
203
- return error instanceof RiddleApiError && PREVIEW_PUBLISH_RECOVERY_STATUSES.has(error.status);
204
- }
205
- function summarizePreviewDirectory(directory) {
206
- const stack = [directory];
207
- let fileCount = 0;
208
- let totalBytes = 0;
209
- while (stack.length) {
210
- const current = stack.pop();
211
- for (const entry of (0, import_node_fs.readdirSync)(current, { withFileTypes: true })) {
212
- const fullPath = import_node_path.default.join(current, entry.name);
213
- if (entry.isDirectory()) {
214
- stack.push(fullPath);
215
- continue;
216
- }
217
- if (!entry.isFile()) continue;
218
- const stat = (0, import_node_fs.statSync)(fullPath);
219
- fileCount += 1;
220
- totalBytes += stat.size;
221
- }
222
- }
223
- return { file_count: fileCount, total_bytes: totalBytes };
224
- }
225
- function previewProgressEmitter(config, base) {
226
- return async (snapshot) => {
227
- if (!config.onPreviewProgress) return;
228
- await config.onPreviewProgress({
229
- label: base.label,
230
- framework: base.framework,
231
- directory: base.directory,
232
- elapsed_ms: Math.max(0, Date.now() - base.startedAt),
233
- warnings: base.warnings?.length ? base.warnings : void 0,
234
- ...snapshot
235
- });
236
- };
237
- }
238
- async function waitForPublishedPreview(config, input) {
239
- await input.emitProgress?.({
240
- stage: "publish_recovering",
241
- id: input.id,
242
- file_count: input.localSummary?.file_count,
243
- total_bytes: input.localSummary?.total_bytes,
244
- publish_error: input.publishError.message,
245
- message: `publish returned ${input.publishError.status}; polling preview status`
246
- });
247
- for (let attempt = 1; attempt <= PREVIEW_PUBLISH_RECOVERY_ATTEMPTS; attempt += 1) {
248
- const status = await riddleRequestJson(config, `/v1/preview/${input.id}`);
249
- await input.emitProgress?.({
250
- stage: "checking_status",
251
- id: input.id,
252
- attempt,
253
- attempts: PREVIEW_PUBLISH_RECOVERY_ATTEMPTS,
254
- status: typeof status.status === "string" ? status.status : null,
255
- preview_url: typeof status.preview_url === "string" ? status.preview_url : void 0,
256
- file_count: typeof status.file_count === "number" ? status.file_count : input.localSummary?.file_count,
257
- total_bytes: typeof status.total_bytes === "number" ? status.total_bytes : input.localSummary?.total_bytes
258
- });
259
- if (String(status.status || "") === "ready" && String(status.preview_url || "").trim()) {
260
- await input.emitProgress?.({
261
- stage: "ready",
262
- id: input.id,
263
- preview_url: String(status.preview_url),
264
- file_count: typeof status.file_count === "number" ? status.file_count : input.localSummary?.file_count,
265
- total_bytes: typeof status.total_bytes === "number" ? status.total_bytes : input.localSummary?.total_bytes
266
- });
267
- return previewDeployResultFromRecord({
268
- record: status,
269
- id: input.id,
270
- label: input.label,
271
- framework: input.framework,
272
- expiresAt: input.expiresAt,
273
- publishRecovered: true,
274
- publishError: input.publishError.message,
275
- warnings: input.warnings
276
- });
277
- }
278
- if (attempt < PREVIEW_PUBLISH_RECOVERY_ATTEMPTS) {
279
- await new Promise((resolve) => setTimeout(resolve, PREVIEW_PUBLISH_RECOVERY_INTERVAL_MS));
280
- }
281
- }
282
- throw input.publishError;
283
- }
284
- async function deployRiddlePreview(config, directory, label, framework = "static", options = {}) {
285
- if (!directory?.trim()) throw new Error("directory is required");
286
- if (!label?.trim()) throw new Error("label is required");
287
- if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
288
- const startedAt = Date.now();
289
- const warnings = collectRiddlePreviewDeployWarnings(directory, framework);
290
- const source = options.source || detectRiddlePreviewSource(directory);
291
- const emitProgress = previewProgressEmitter(config, { label, framework, directory, startedAt, warnings });
292
- await emitProgress({ stage: "validating", message: "checking preview input directory" });
293
- const localSummary = summarizePreviewDirectory(directory);
294
- await emitProgress({
295
- stage: "creating",
296
- file_count: localSummary.file_count,
297
- total_bytes: localSummary.total_bytes,
298
- message: "creating preview upload target"
299
- });
300
- const created = await riddleRequestJson(config, "/v1/preview", {
301
- method: "POST",
302
- body: JSON.stringify({ framework, label, source })
303
- });
304
- const id = String(created.id || "");
305
- const uploadUrl = String(created.upload_url || "");
306
- if (!id || !uploadUrl) throw new Error("Riddle preview create response was missing id or upload_url.");
307
- await emitProgress({
308
- stage: "created",
309
- id,
310
- file_count: localSummary.file_count,
311
- total_bytes: localSummary.total_bytes,
312
- message: "preview upload target created"
313
- });
314
- const scratch = (0, import_node_fs.mkdtempSync)(import_node_path.default.join((0, import_node_os.tmpdir)(), "riddle-preview-upload-"));
315
- const tarball = import_node_path.default.join(scratch, `${id}.tar.gz`);
316
- let tarballBytes = 0;
317
- try {
318
- await emitProgress({
319
- stage: "archiving",
320
- id,
321
- file_count: localSummary.file_count,
322
- total_bytes: localSummary.total_bytes,
323
- message: "creating preview archive"
324
- });
325
- (0, import_node_child_process.execFileSync)("tar", ["czf", tarball, "-C", directory, "."], { stdio: "pipe" });
326
- tarballBytes = (0, import_node_fs.statSync)(tarball).size;
327
- await emitProgress({
328
- stage: "archived",
329
- id,
330
- file_count: localSummary.file_count,
331
- total_bytes: localSummary.total_bytes,
332
- tarball_bytes: tarballBytes,
333
- message: "preview archive created"
334
- });
335
- await emitProgress({
336
- stage: "uploading",
337
- id,
338
- file_count: localSummary.file_count,
339
- total_bytes: localSummary.total_bytes,
340
- tarball_bytes: tarballBytes,
341
- message: "uploading preview archive"
342
- });
343
- const upload = await fetchFor(config)(uploadUrl, {
344
- method: "PUT",
345
- headers: { "Content-Type": "application/gzip" },
346
- body: (0, import_node_fs.readFileSync)(tarball)
347
- });
348
- if (!upload.ok) {
349
- throw new RiddleApiError(uploadUrl, upload.status, await upload.text());
350
- }
351
- await emitProgress({
352
- stage: "uploaded",
353
- id,
354
- file_count: localSummary.file_count,
355
- total_bytes: localSummary.total_bytes,
356
- tarball_bytes: tarballBytes,
357
- message: "preview archive uploaded"
358
- });
359
- } finally {
360
- (0, import_node_fs.rmSync)(scratch, { recursive: true, force: true });
361
- }
362
- const expiresAt = typeof created.expires_at === "string" ? created.expires_at : void 0;
363
- try {
364
- await emitProgress({
365
- stage: "publishing",
366
- id,
367
- file_count: localSummary.file_count,
368
- total_bytes: localSummary.total_bytes,
369
- tarball_bytes: tarballBytes || void 0,
370
- message: "publishing preview"
371
- });
372
- const published = await riddleRequestJson(config, `/v1/preview/${id}/publish`, {
373
- method: "POST"
374
- });
375
- await emitProgress({
376
- stage: "ready",
377
- id,
378
- preview_url: String(published.preview_url || ""),
379
- file_count: typeof published.file_count === "number" ? published.file_count : localSummary.file_count,
380
- total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : localSummary.total_bytes
381
- });
382
- return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt, warnings });
383
- } catch (error) {
384
- if (!canRecoverPreviewPublish(error)) throw error;
385
- return waitForPublishedPreview(config, {
386
- id,
387
- label,
388
- framework,
389
- expiresAt,
390
- publishError: error,
391
- warnings,
392
- localSummary,
393
- emitProgress
394
- });
395
- }
396
- }
397
- function latestMatchingMtimeMs(directory, predicate) {
398
- let latest = 0;
399
- const stack = [directory];
400
- let visited = 0;
401
- while (stack.length) {
402
- const current = stack.pop();
403
- for (const entry of (0, import_node_fs.readdirSync)(current, { withFileTypes: true })) {
404
- const fullPath = import_node_path.default.join(current, entry.name);
405
- if (entry.isDirectory()) {
406
- stack.push(fullPath);
407
- continue;
408
- }
409
- if (!entry.isFile() || !predicate(fullPath)) continue;
410
- const stat = (0, import_node_fs.statSync)(fullPath);
411
- latest = Math.max(latest, stat.mtimeMs);
412
- visited += 1;
413
- if (visited >= 1e4) return latest;
414
- }
415
- }
416
- return latest;
417
- }
418
- function collectRiddlePreviewDeployWarnings(directory, framework = "static") {
419
- try {
420
- if (framework !== "static") return [];
421
- const resolvedDirectory = import_node_path.default.resolve(directory);
422
- if (import_node_path.default.basename(resolvedDirectory) !== "out") return [];
423
- const repoRoot = import_node_path.default.dirname(resolvedDirectory);
424
- const nextAppDir = import_node_path.default.join(repoRoot, ".next", "server", "app");
425
- if (!(0, import_node_fs.existsSync)(nextAppDir)) return [];
426
- const nextRenderedMtimeMs = latestMatchingMtimeMs(nextAppDir, (filePath) => /\.(?:html|rsc)$/i.test(filePath));
427
- if (!nextRenderedMtimeMs) return [];
428
- const outRenderedMtimeMs = (0, import_node_fs.existsSync)(resolvedDirectory) ? latestMatchingMtimeMs(resolvedDirectory, (filePath) => /\.(?:html|txt|rsc)$/i.test(filePath)) : 0;
429
- if (!outRenderedMtimeMs) {
430
- return [
431
- "Riddle Preview static deploy target is an out/ directory with newer Next render output in .next/server/app, but no rendered HTML/RSC files were found in out/. Run the project static bundle/export step before deploying."
432
- ];
433
- }
434
- if (nextRenderedMtimeMs > outRenderedMtimeMs + 1e3) {
435
- return [
436
- "Riddle Preview static deploy target out/ appears older than the Next render output in .next/server/app. Run the project static bundle/export step, such as npm run build:static-deploy or next export, before deploying to avoid a stale Preview."
437
- ];
438
- }
439
- return [];
440
- } catch {
441
- return [];
442
- }
443
- }
444
- async function deployRiddleStaticPreview(config, directory, label, options = {}) {
445
- return deployRiddlePreview(config, directory, label, "static", options);
446
- }
447
- function createTarball(directory, label, exclude = []) {
448
- const scratch = (0, import_node_fs.mkdtempSync)(import_node_path.default.join((0, import_node_os.tmpdir)(), "riddle-upload-"));
449
- const tarball = import_node_path.default.join(scratch, `${label}.tar.gz`);
450
- const excludeArgs = exclude.flatMap((item) => ["--exclude", item]);
451
- try {
452
- (0, import_node_child_process.execFileSync)("tar", ["czf", tarball, ...excludeArgs, "-C", directory, "."], { stdio: "pipe" });
453
- return { scratch, tarball };
454
- } catch (error) {
455
- (0, import_node_fs.rmSync)(scratch, { recursive: true, force: true });
456
- throw error;
457
- }
458
- }
459
- function parseRiddleViewport(value) {
460
- if (!value) return void 0;
461
- const match = /^(\d+)x(\d+)$/.exec(value.trim());
462
- if (!match) throw new Error("viewport must look like 1280x720");
463
- return { width: Number(match[1]), height: Number(match[2]) };
464
- }
465
- function scriptErrorFrom(job) {
466
- const nested = job?.proof_of_execution && typeof job.proof_of_execution === "object" && !Array.isArray(job.proof_of_execution) ? job.proof_of_execution : null;
467
- return typeof job?.script_error === "string" && job.script_error.trim() ? job.script_error : typeof nested?.script_error === "string" && nested.script_error.trim() ? nested.script_error : null;
468
- }
469
- async function runRiddleServerPreview(config, input) {
470
- if (!input.directory?.trim()) throw new Error("directory is required");
471
- if (!input.script?.trim()) throw new Error("script is required");
472
- const port = input.port || 3e3;
473
- const routePath = input.path || "/";
474
- const timeoutSec = input.timeoutSec || 180;
475
- const created = await riddleRequestJson(config, "/v1/server-preview", {
476
- method: "POST",
477
- body: JSON.stringify({
478
- image: input.image || "node:22-slim",
479
- command: input.command || "node scripts/riddleSpaPreviewServer.mjs build 3000",
480
- port,
481
- path: routePath,
482
- readiness_path: input.readinessPath || routePath,
483
- readiness_timeout: input.readinessTimeoutSec || 90,
484
- wait_until: input.waitUntil || "domcontentloaded",
485
- wait_for_selector: input.waitForSelector || "body",
486
- navigation_timeout: input.navigationTimeoutSec || 60,
487
- viewport: input.viewport,
488
- timeout: timeoutSec,
489
- script: input.script
490
- })
491
- });
492
- const jobId = String(created.job_id || "");
493
- const uploadUrl = String(created.upload_url || "");
494
- if (!jobId || !uploadUrl) {
495
- throw new Error(`Riddle server preview create response was missing job_id or upload_url.`);
496
- }
497
- const { scratch, tarball } = createTarball(input.directory, jobId, [
498
- ".git",
499
- "node_modules",
500
- "test-results",
501
- ...input.exclude || []
502
- ]);
503
- try {
504
- const upload = await fetchFor(config)(uploadUrl, {
505
- method: "PUT",
506
- headers: { "Content-Type": "application/gzip" },
507
- body: (0, import_node_fs.readFileSync)(tarball)
508
- });
509
- if (!upload.ok) throw new RiddleApiError(uploadUrl, upload.status, await upload.text());
510
- } finally {
511
- (0, import_node_fs.rmSync)(scratch, { recursive: true, force: true });
512
- }
513
- await riddleRequestJson(config, `/v1/server-preview/${jobId}/start`, {
514
- method: "POST"
515
- });
516
- let job = null;
517
- const attempts = input.pollAttempts || Math.ceil((timeoutSec + 90) / 2);
518
- const intervalMs = input.pollIntervalMs || 2e3;
519
- for (let index = 0; index < attempts; index += 1) {
520
- job = await riddleRequestJson(config, `/v1/server-preview/${jobId}`);
521
- if (isTerminalRiddleJobStatus(job.status)) break;
522
- if (index + 1 < attempts) await new Promise((resolve) => setTimeout(resolve, intervalMs));
523
- }
524
- const status = job?.status ? String(job.status) : null;
525
- const scriptError = scriptErrorFrom(job);
526
- return {
527
- ok: (status === "completed" || status === "complete") && !scriptError,
528
- job_id: jobId,
529
- status,
530
- terminal: isTerminalRiddleJobStatus(status),
531
- script_error: scriptError,
532
- job
533
- };
534
- }
535
- async function runRiddleScript(config, input) {
536
- if (!input.url?.trim()) throw new Error("url is required");
537
- if (!input.script?.trim()) throw new Error("script is required");
538
- const payload = {
539
- url: input.url,
540
- script: input.script,
541
- sync: input.sync ?? false,
542
- timeout_sec: input.timeoutSec || 120
543
- };
544
- if (input.viewport) payload.viewport = input.viewport;
545
- if (input.include) payload.include = input.include;
546
- if (typeof input.strict === "boolean") payload.strict = input.strict;
547
- if (input.options) payload.options = input.options;
548
- return riddleRequestJson(config, "/v1/run", {
549
- method: "POST",
550
- body: JSON.stringify(payload)
551
- });
552
- }
553
- function isTerminalRiddleJobStatus(status) {
554
- return ["completed", "complete", "completed_error", "completed_timeout", "failed"].includes(String(status || ""));
555
- }
556
- function stringField(record, key) {
557
- const value = record?.[key];
558
- return typeof value === "string" && value.trim() ? value.trim() : null;
559
- }
560
- function parseTimestampMs(value) {
561
- if (!value) return null;
562
- const parsed = Date.parse(value);
563
- return Number.isFinite(parsed) ? parsed : null;
564
- }
565
- function buildPollSnapshot(jobId, job, input) {
566
- const status = job?.status ? String(job.status) : null;
567
- const phase = job?.phase ? String(job.phase) : null;
568
- const terminal = isTerminalRiddleJobStatus(status);
569
- const createdAt = stringField(job, "created_at");
570
- const submittedAt = stringField(job, "submitted_at");
571
- const completedAt = stringField(job, "completed_at");
572
- const createdMs = parseTimestampMs(createdAt);
573
- const submittedMs = parseTimestampMs(submittedAt);
574
- const rawExecution = job?.execution && typeof job.execution === "object" && !Array.isArray(job.execution) ? job.execution : null;
575
- const enqueuedAt = rawExecution ? stringField(rawExecution, "enqueued_at") : null;
576
- const enqueuedMs = parseTimestampMs(enqueuedAt);
577
- const queueStartedMs = enqueuedMs ?? createdMs;
578
- const claimedAt = rawExecution ? stringField(rawExecution, "claimed_at") : null;
579
- const claimedMs = parseTimestampMs(claimedAt);
580
- let queueElapsedMs = null;
581
- if (queueStartedMs !== null && claimedMs !== null) {
582
- queueElapsedMs = Math.max(0, claimedMs - queueStartedMs);
583
- } else if (queueStartedMs !== null && submittedMs !== null) {
584
- queueElapsedMs = Math.max(0, submittedMs - queueStartedMs);
585
- } else if (queueStartedMs !== null && !submittedAt && !terminal) {
586
- queueElapsedMs = Math.max(0, input.observedAt - queueStartedMs);
587
- }
588
- return {
589
- job_id: jobId,
590
- status,
591
- phase,
592
- terminal,
593
- attempt: input.attempt,
594
- attempts: input.attempts,
595
- elapsed_ms: Math.max(0, input.observedAt - input.startedAt),
596
- created_at: createdAt,
597
- submitted_at: submittedAt,
598
- completed_at: completedAt,
599
- queue_elapsed_ms: queueElapsedMs,
600
- pre_submission_elapsed_ms: Math.max(0, Math.floor(input.preSubmissionElapsedMs ?? 0)),
601
- running_without_submission: Boolean(status && !terminal && !submittedAt),
602
- active_execution: Boolean(status === "running" && phase && phase !== "queued"),
603
- execution: rawExecution ? rawExecution : void 0
604
- };
605
- }
606
- function pollMessage(snapshot, timedOut) {
607
- if (!timedOut) return void 0;
608
- const submitted = snapshot.submitted_at || "not submitted";
609
- const wakeHint = snapshot.running_without_submission && !snapshot.created_at && !snapshot.submitted_at ? ` ${RIDDLE_UNSUBMITTED_WAKE_HINT}.` : "";
610
- const queue = snapshot.queue_elapsed_ms !== null ? ` queue_elapsed_ms=${snapshot.queue_elapsed_ms}` : "";
611
- const preSubmit = snapshot.pre_submission_elapsed_ms > 0 ? ` pre_submission_elapsed_ms=${snapshot.pre_submission_elapsed_ms}` : "";
612
- return `Riddle job ${snapshot.job_id} did not reach a terminal status after ${snapshot.attempt} poll attempts; status=${snapshot.status || "unknown"} phase=${snapshot.phase || "unknown"} submitted_at=${submitted}.${wakeHint}${queue}${preSubmit}`;
613
- }
614
- async function pollRiddleJob(config, jobId, options = {}) {
615
- if (!jobId?.trim()) throw new Error("jobId is required");
616
- const attempts = Math.max(1, Math.floor(options.attempts ?? (options.wait ? 300 : 1)));
617
- const intervalMs = Math.max(0, Math.floor(options.intervalMs ?? 2e3));
618
- const progressEveryMs = Math.max(0, Math.floor(options.progressEveryMs ?? 1e4));
619
- const unsubmittedTimeoutMs = Math.max(0, Math.floor(options.unsubmittedTimeoutMs ?? 0));
620
- const startedAt = Date.now();
621
- let job = null;
622
- let lastSnapshot = null;
623
- let lastProgressAt = 0;
624
- let lastProgressKey = "";
625
- let preSubmissionElapsedMs = 0;
626
- let unsubmittedTimedOut = false;
627
- for (let index = 0; index < attempts; index += 1) {
628
- job = await riddleRequestJson(config, `/v1/jobs/${jobId}`);
629
- const observedAt = Date.now();
630
- const nextSnapshot = buildPollSnapshot(jobId, job, {
631
- attempt: index + 1,
632
- attempts,
633
- startedAt,
634
- observedAt,
635
- preSubmissionElapsedMs
636
- });
637
- if (nextSnapshot.running_without_submission) {
638
- preSubmissionElapsedMs = Math.max(preSubmissionElapsedMs, nextSnapshot.elapsed_ms);
639
- }
640
- lastSnapshot = {
641
- ...nextSnapshot,
642
- pre_submission_elapsed_ms: preSubmissionElapsedMs
643
- };
644
- const progressKey = [
645
- lastSnapshot.status || "unknown",
646
- lastSnapshot.phase || "unknown",
647
- lastSnapshot.terminal ? "terminal" : "nonterminal",
648
- lastSnapshot.submitted_at ? "submitted" : "unsubmitted"
649
- ].join(":");
650
- if (options.onProgress) {
651
- const shouldReport = index === 0 || lastSnapshot.terminal || progressKey !== lastProgressKey || observedAt - lastProgressAt >= progressEveryMs;
652
- if (shouldReport) {
653
- lastProgressAt = observedAt;
654
- lastProgressKey = progressKey;
655
- await options.onProgress(lastSnapshot);
656
- }
657
- }
658
- unsubmittedTimedOut = Boolean(
659
- options.wait && unsubmittedTimeoutMs > 0 && lastSnapshot.running_without_submission && !lastSnapshot.created_at && !lastSnapshot.submitted_at && preSubmissionElapsedMs >= unsubmittedTimeoutMs
660
- );
661
- if (lastSnapshot.terminal) break;
662
- if (unsubmittedTimedOut) break;
663
- if (index + 1 < attempts) {
664
- await new Promise((resolve) => setTimeout(resolve, intervalMs));
665
- }
666
- }
667
- const status = job?.status ? String(job.status) : null;
668
- const fallbackObservedAt = Date.now();
669
- const snapshot = lastSnapshot || buildPollSnapshot(jobId, job, {
670
- attempt: 0,
671
- attempts,
672
- startedAt,
673
- observedAt: fallbackObservedAt
674
- });
675
- if (!isTerminalRiddleJobStatus(status)) {
676
- const timedOut = Boolean(options.wait);
677
- return {
678
- ok: !timedOut,
679
- job_id: jobId,
680
- status,
681
- terminal: false,
682
- job,
683
- poll: {
684
- ...snapshot,
685
- timed_out: timedOut,
686
- interval_ms: intervalMs,
687
- unsubmitted_timeout: unsubmittedTimedOut || void 0,
688
- unsubmitted_timeout_ms: unsubmittedTimedOut ? unsubmittedTimeoutMs : void 0,
689
- message: pollMessage(snapshot, timedOut)
690
- }
691
- };
692
- }
693
- const artifacts = await riddleRequestJson(config, `/v1/jobs/${jobId}/artifacts`);
694
- return {
695
- ok: status === "completed" || status === "complete",
696
- job_id: jobId,
697
- status,
698
- terminal: true,
699
- job,
700
- artifacts,
701
- poll: {
702
- ...snapshot,
703
- timed_out: false,
704
- interval_ms: intervalMs
705
- }
706
- };
707
- }
708
- function createRiddleApiClient(config = {}) {
709
- return {
710
- apiKeySource: () => resolveRiddleApiKeySource(config),
711
- requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
712
- getBalance: () => getRiddleBalance(config),
713
- deployPreview: (directory, label, framework = "static", options) => deployRiddlePreview(config, directory, label, framework, options),
714
- deployStaticPreview: (directory, label, options) => deployRiddleStaticPreview(config, directory, label, options),
715
- runScript: (input) => runRiddleScript(config, input),
716
- runServerPreview: (input) => runRiddleServerPreview(config, input),
717
- pollJob: (jobId, options) => pollRiddleJob(config, jobId, options)
718
- };
719
- }
45
+ var import_client = require("@riddledc/riddle-proof-riddle-client/client");
720
46
  // Annotate the CommonJS export names for ESM import in node:
721
47
  0 && (module.exports = {
722
48
  DEFAULT_RIDDLE_API_BASE_URL,
723
49
  DEFAULT_RIDDLE_API_KEY_FILE,
50
+ RIDDLE_BALANCE_ENDPOINT_PATH,
724
51
  RIDDLE_UNSUBMITTED_WAKE_HINT,
725
52
  RiddleApiError,
726
53
  collectRiddlePreviewDeployWarnings,
@@ -729,6 +56,7 @@ function createRiddleApiClient(config = {}) {
729
56
  deployRiddleStaticPreview,
730
57
  detectRiddlePreviewSource,
731
58
  getRiddleBalance,
59
+ getRiddleJobArtifacts,
732
60
  isTerminalRiddleJobStatus,
733
61
  parseRiddleViewport,
734
62
  pollRiddleJob,