@riddledc/riddle-proof 0.5.53 → 0.5.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/basic-gameplay.cjs +255 -0
- package/dist/basic-gameplay.d.cts +117 -0
- package/dist/basic-gameplay.d.ts +117 -0
- package/dist/basic-gameplay.js +14 -0
- package/dist/checkpoint.cjs +2 -2
- package/dist/checkpoint.js +1 -1
- package/dist/{chunk-KYGWIA7A.js → chunk-2FBF2UDZ.js} +8 -8
- package/dist/{chunk-T5RHGGQ2.js → chunk-33XO42CY.js} +2 -2
- package/dist/{chunk-53UPEUVU.js → chunk-3UHWI3FO.js} +1 -1
- package/dist/{chunk-PVUZZ2P6.js → chunk-MO24D3PY.js} +2 -1
- package/dist/{chunk-4ASMX4R6.js → chunk-RFJ5BQF6.js} +1 -0
- package/dist/chunk-RNGJX62B.js +227 -0
- package/dist/{chunk-QBOKV3ES.js → chunk-RXFKKYWA.js} +1 -1
- package/dist/chunk-UR6ADV4Y.js +163 -0
- package/dist/cli.cjs +217 -12
- package/dist/cli.js +67 -10
- package/dist/engine-harness.cjs +4 -2
- package/dist/engine-harness.js +5 -5
- package/dist/index.cjs +409 -5
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +49 -13
- package/dist/openclaw.cjs +1 -0
- package/dist/openclaw.js +3 -3
- package/dist/proof-run-core.cjs +1 -0
- package/dist/proof-run-core.js +1 -1
- package/dist/proof-run-engine.cjs +1 -0
- package/dist/proof-run-engine.d.cts +3 -3
- package/dist/proof-run-engine.d.ts +3 -3
- package/dist/proof-run-engine.js +1 -1
- package/dist/riddle-client.cjs +207 -0
- package/dist/riddle-client.d.cts +71 -0
- package/dist/riddle-client.d.ts +71 -0
- package/dist/riddle-client.js +26 -0
- package/dist/run-card.js +2 -2
- package/dist/runner.cjs +1 -0
- package/dist/runner.js +4 -4
- package/dist/state.cjs +1 -0
- package/dist/state.js +3 -3
- package/dist/types.d.cts +1 -0
- package/dist/types.d.ts +1 -0
- package/package.json +12 -2
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// src/basic-gameplay.ts
|
|
2
|
+
var RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION = "riddle-proof.basic-gameplay.v1";
|
|
3
|
+
var RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION = "riddle-proof.basic-gameplay.assessment.v1";
|
|
4
|
+
var BASIC_GAMEPLAY_CONTAINER_KEYS = [
|
|
5
|
+
"basic_gameplay",
|
|
6
|
+
"basicGameplay",
|
|
7
|
+
"basic_gameplay_evidence",
|
|
8
|
+
"basicGameplayEvidence",
|
|
9
|
+
"gameplay_proof",
|
|
10
|
+
"gameplayProof"
|
|
11
|
+
];
|
|
12
|
+
function assessBasicGameplayEvidence(evidence, options = {}) {
|
|
13
|
+
const run = extractBasicGameplayEvidence(evidence);
|
|
14
|
+
if (!run) {
|
|
15
|
+
return {
|
|
16
|
+
version: RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION,
|
|
17
|
+
evidence_present: false,
|
|
18
|
+
passed: false,
|
|
19
|
+
checked_routes: 0,
|
|
20
|
+
passing_routes: 0,
|
|
21
|
+
failing_routes: [],
|
|
22
|
+
failure_counts: {},
|
|
23
|
+
warning_counts: {},
|
|
24
|
+
route_results: []
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const routeResults = (run.results || []).map((route) => assessBasicGameplayRoute(route, options));
|
|
28
|
+
const failingRoutes = routeResults.filter((result) => !result.ok).map((result) => ({
|
|
29
|
+
name: result.name,
|
|
30
|
+
path: result.path,
|
|
31
|
+
failures: result.failures,
|
|
32
|
+
warnings: result.warnings
|
|
33
|
+
}));
|
|
34
|
+
return {
|
|
35
|
+
version: RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION,
|
|
36
|
+
evidence_present: true,
|
|
37
|
+
passed: failingRoutes.length === 0,
|
|
38
|
+
checked_routes: routeResults.length,
|
|
39
|
+
passing_routes: routeResults.filter((result) => result.ok).length,
|
|
40
|
+
failing_routes: failingRoutes,
|
|
41
|
+
failure_counts: countCodes(routeResults.flatMap((result) => result.failures)),
|
|
42
|
+
warning_counts: countCodes(routeResults.flatMap((result) => result.warnings)),
|
|
43
|
+
route_results: routeResults
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function assessBasicGameplayRoute(route, options = {}) {
|
|
47
|
+
const maxMobileOverflowPx = options.maxMobileOverflowPx ?? 4;
|
|
48
|
+
const minBodyTextLength = options.minBodyTextLength ?? 20;
|
|
49
|
+
const minVisibleLargeNodes = options.minVisibleLargeNodes ?? 3;
|
|
50
|
+
const minSurfaceLargeNodes = options.minSurfaceLargeNodes ?? 8;
|
|
51
|
+
const warnOnMissingResetPath = options.warnOnMissingResetPath ?? true;
|
|
52
|
+
const warnOnConsoleError = options.warnOnConsoleError ?? true;
|
|
53
|
+
const failOnConsoleError = options.failOnConsoleError ?? false;
|
|
54
|
+
const failures = [];
|
|
55
|
+
const warnings = [];
|
|
56
|
+
const initial = route.initial || {};
|
|
57
|
+
const timed = route.timed || {};
|
|
58
|
+
const afterAction = route.after_action || route.afterAction || {};
|
|
59
|
+
const mobile = route.mobile || {};
|
|
60
|
+
const timedChange = changed(initial, timed);
|
|
61
|
+
const actionChange = changed(timed, afterAction);
|
|
62
|
+
const surfaceVisible = numberValue(initial.visible_canvas_count) > 0 || numberValue(initial.enabled_clickable_count) > 0 || numberValue(initial.visible_large_node_count) >= minSurfaceLargeNodes;
|
|
63
|
+
const actionResults = listValue(route.action_results || route.actionResults);
|
|
64
|
+
const actionAttempted = actionResults.some((result) => result.ok === true && result.action !== "wait");
|
|
65
|
+
const actionFailed = actionResults.some((result) => result.ok === false && result.action !== "wait");
|
|
66
|
+
const stateChangeObserved = actionChange.changed || timedChange.changed;
|
|
67
|
+
const resetPathPresent = numberValue(initial.reset_control_count) > 0 || numberValue(timed.reset_control_count) > 0 || numberValue(afterAction.reset_control_count) > 0;
|
|
68
|
+
const responseStatus = firstNumber(route.http_status, route.response_status, route.status);
|
|
69
|
+
const pageErrorCount = numberValue(route.page_error_count);
|
|
70
|
+
const consoleErrorCount = numberValue(route.console_error_count);
|
|
71
|
+
const mobileOverflowPx = numberValue(mobile.overflow_px);
|
|
72
|
+
if (responseStatus !== null && responseStatus >= 400) failures.push("route_http_error");
|
|
73
|
+
if (pageErrorCount > 0) failures.push("fatal_page_error");
|
|
74
|
+
if (numberValue(initial.body_text_length) < minBodyTextLength && numberValue(initial.visible_large_node_count) < minVisibleLargeNodes) {
|
|
75
|
+
failures.push("route_blank_or_thin");
|
|
76
|
+
}
|
|
77
|
+
if (!surfaceVisible) failures.push("no_game_surface");
|
|
78
|
+
if (mobileOverflowPx > maxMobileOverflowPx) failures.push("mobile_horizontal_overflow");
|
|
79
|
+
if (!actionAttempted && !timedChange.changed) failures.push("primary_control_missing");
|
|
80
|
+
if (actionAttempted && !stateChangeObserved) failures.push("primary_control_inert");
|
|
81
|
+
if (failOnConsoleError && consoleErrorCount > 0) failures.push("fatal_page_error");
|
|
82
|
+
if (numberValue(initial.visible_canvas_count) > 0 && actionAttempted && !timedChange.canvas_changed && !actionChange.canvas_changed && !actionChange.screenshot_changed) {
|
|
83
|
+
warnings.push("canvas_inert");
|
|
84
|
+
}
|
|
85
|
+
if (actionFailed) warnings.push("some_actions_failed");
|
|
86
|
+
if (warnOnMissingResetPath && !resetPathPresent && route.requires_reset !== false && actionAttempted && stateChangeObserved) {
|
|
87
|
+
warnings.push("missing_reset_path");
|
|
88
|
+
}
|
|
89
|
+
if (warnOnConsoleError && consoleErrorCount > 0) warnings.push("critical_console_error");
|
|
90
|
+
return {
|
|
91
|
+
name: route.name,
|
|
92
|
+
path: route.path,
|
|
93
|
+
ok: failures.length === 0,
|
|
94
|
+
failures,
|
|
95
|
+
warnings,
|
|
96
|
+
signals: {
|
|
97
|
+
route_loaded: !failures.includes("route_http_error") && !failures.includes("route_blank_or_thin"),
|
|
98
|
+
surface_visible: surfaceVisible,
|
|
99
|
+
action_attempted: actionAttempted,
|
|
100
|
+
timed_progression_observed: timedChange.changed,
|
|
101
|
+
first_interaction_observed: actionChange.changed,
|
|
102
|
+
state_change_observed: stateChangeObserved,
|
|
103
|
+
mobile_overflow_absent: mobileOverflowPx <= maxMobileOverflowPx,
|
|
104
|
+
reset_path_present: resetPathPresent,
|
|
105
|
+
fatal_errors_absent: pageErrorCount === 0
|
|
106
|
+
},
|
|
107
|
+
diffs: {
|
|
108
|
+
timed: timedChange,
|
|
109
|
+
after_action: actionChange
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function extractBasicGameplayEvidence(...sources) {
|
|
114
|
+
const seen = /* @__PURE__ */ new Set();
|
|
115
|
+
for (const source of sources) {
|
|
116
|
+
const found = findBasicGameplayEvidence(source, seen);
|
|
117
|
+
if (found) return found;
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
function findBasicGameplayEvidence(value, seen, depth = 0) {
|
|
122
|
+
if (depth > 6 || value === null || value === void 0) return null;
|
|
123
|
+
if (typeof value === "string") {
|
|
124
|
+
const parsed = parseJson(value);
|
|
125
|
+
return parsed === null ? null : findBasicGameplayEvidence(parsed, seen, depth + 1);
|
|
126
|
+
}
|
|
127
|
+
if (Array.isArray(value)) {
|
|
128
|
+
if (seen.has(value)) return null;
|
|
129
|
+
seen.add(value);
|
|
130
|
+
if (value.some((item) => hasRouteShape(recordValue(item)))) {
|
|
131
|
+
return { results: value.filter((item) => hasRouteShape(recordValue(item))) };
|
|
132
|
+
}
|
|
133
|
+
for (const item of value) {
|
|
134
|
+
const found = findBasicGameplayEvidence(item, seen, depth + 1);
|
|
135
|
+
if (found) return found;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
const record = recordValue(value);
|
|
140
|
+
if (!record || seen.has(record)) return null;
|
|
141
|
+
seen.add(record);
|
|
142
|
+
if (record.version === RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION || Array.isArray(record.results)) {
|
|
143
|
+
return {
|
|
144
|
+
...record,
|
|
145
|
+
results: listValue(record.results).filter((item) => Boolean(recordValue(item)))
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
if (hasRouteShape(record)) {
|
|
149
|
+
return { results: [record] };
|
|
150
|
+
}
|
|
151
|
+
for (const key of BASIC_GAMEPLAY_CONTAINER_KEYS) {
|
|
152
|
+
if (Object.prototype.hasOwnProperty.call(record, key)) {
|
|
153
|
+
const nested = findBasicGameplayEvidence(record[key], seen, depth + 1);
|
|
154
|
+
if (nested) return nested;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
for (const item of Object.values(record)) {
|
|
158
|
+
const found = findBasicGameplayEvidence(item, seen, depth + 1);
|
|
159
|
+
if (found) return found;
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
function hasRouteShape(record) {
|
|
164
|
+
return Boolean(record && (record.initial || record.after_action || record.afterAction || record.action_results || record.actionResults) && (record.path || record.name));
|
|
165
|
+
}
|
|
166
|
+
function changed(before, after) {
|
|
167
|
+
const bodyTextChanged = Boolean(before.body_text_hash && after.body_text_hash && before.body_text_hash !== after.body_text_hash);
|
|
168
|
+
const screenshotChanged = Boolean(before.screenshot_hash && after.screenshot_hash && before.screenshot_hash !== after.screenshot_hash);
|
|
169
|
+
const beforeCanvasHashes = canvasHashes(before.canvases);
|
|
170
|
+
const afterCanvasHashes = canvasHashes(after.canvases);
|
|
171
|
+
const canvasChanged = Boolean(beforeCanvasHashes && afterCanvasHashes && beforeCanvasHashes !== afterCanvasHashes);
|
|
172
|
+
return {
|
|
173
|
+
body_text_changed: bodyTextChanged,
|
|
174
|
+
screenshot_changed: screenshotChanged,
|
|
175
|
+
canvas_changed: canvasChanged,
|
|
176
|
+
changed: bodyTextChanged || screenshotChanged || canvasChanged
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function canvasHashes(canvases) {
|
|
180
|
+
return (canvases || []).map((canvas) => canvas.hash).filter(Boolean).join("|");
|
|
181
|
+
}
|
|
182
|
+
function countCodes(codes) {
|
|
183
|
+
const counts = {};
|
|
184
|
+
for (const code of codes) counts[code] = (counts[code] || 0) + 1;
|
|
185
|
+
return counts;
|
|
186
|
+
}
|
|
187
|
+
function firstNumber(...values) {
|
|
188
|
+
for (const value of values) {
|
|
189
|
+
const number = numericValue(value);
|
|
190
|
+
if (number !== null) return number;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
function numberValue(value) {
|
|
195
|
+
return numericValue(value) ?? 0;
|
|
196
|
+
}
|
|
197
|
+
function numericValue(value) {
|
|
198
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
199
|
+
if (typeof value === "string" && value.trim()) {
|
|
200
|
+
const parsed = Number(value);
|
|
201
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
function recordValue(value) {
|
|
206
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
207
|
+
}
|
|
208
|
+
function listValue(value) {
|
|
209
|
+
return Array.isArray(value) ? value : [];
|
|
210
|
+
}
|
|
211
|
+
function parseJson(value) {
|
|
212
|
+
const trimmed = value.trim();
|
|
213
|
+
if (!trimmed || !/^[{[]/.test(trimmed)) return null;
|
|
214
|
+
try {
|
|
215
|
+
return JSON.parse(trimmed);
|
|
216
|
+
} catch {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export {
|
|
222
|
+
RIDDLE_PROOF_BASIC_GAMEPLAY_VERSION,
|
|
223
|
+
RIDDLE_PROOF_BASIC_GAMEPLAY_ASSESSMENT_VERSION,
|
|
224
|
+
assessBasicGameplayEvidence,
|
|
225
|
+
assessBasicGameplayRoute,
|
|
226
|
+
extractBasicGameplayEvidence
|
|
227
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// src/riddle-client.ts
|
|
2
|
+
import { execFileSync } from "child_process";
|
|
3
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from "fs";
|
|
4
|
+
import { tmpdir } from "os";
|
|
5
|
+
import path from "path";
|
|
6
|
+
var DEFAULT_RIDDLE_API_BASE_URL = "https://api.riddledc.com";
|
|
7
|
+
var DEFAULT_RIDDLE_API_KEY_FILE = "/tmp/riddle-api-key";
|
|
8
|
+
var RiddleApiError = class extends Error {
|
|
9
|
+
constructor(pathname, status, body) {
|
|
10
|
+
super(`Riddle API ${pathname} failed HTTP ${status}: ${body}`);
|
|
11
|
+
this.name = "RiddleApiError";
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.body = body;
|
|
14
|
+
this.path = pathname;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
function normalizeBaseUrl(value) {
|
|
18
|
+
return (value || DEFAULT_RIDDLE_API_BASE_URL).replace(/\/$/, "");
|
|
19
|
+
}
|
|
20
|
+
function fetchFor(config = {}) {
|
|
21
|
+
return config.fetchImpl || fetch;
|
|
22
|
+
}
|
|
23
|
+
function resolveRiddleApiKey(config = {}) {
|
|
24
|
+
if (config.apiKey?.trim()) return config.apiKey.trim();
|
|
25
|
+
if (process.env.RIDDLE_API_KEY?.trim()) return process.env.RIDDLE_API_KEY.trim();
|
|
26
|
+
const keyFile = config.apiKeyFile || process.env.RIDDLE_API_KEY_FILE || DEFAULT_RIDDLE_API_KEY_FILE;
|
|
27
|
+
if (existsSync(keyFile)) {
|
|
28
|
+
const key = readFileSync(keyFile, "utf8").trim();
|
|
29
|
+
if (key) return key;
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`Riddle API key missing. Set RIDDLE_API_KEY or write ${DEFAULT_RIDDLE_API_KEY_FILE}.`);
|
|
32
|
+
}
|
|
33
|
+
async function riddleRequestJson(config, pathname, init = {}) {
|
|
34
|
+
const response = await fetchFor(config)(`${normalizeBaseUrl(config.apiBaseUrl)}${pathname}`, {
|
|
35
|
+
...init,
|
|
36
|
+
headers: {
|
|
37
|
+
Authorization: `Bearer ${resolveRiddleApiKey(config)}`,
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
...init.headers || {}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
const text = await response.text();
|
|
43
|
+
let json = null;
|
|
44
|
+
try {
|
|
45
|
+
json = JSON.parse(text);
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
|
|
49
|
+
return json ?? text;
|
|
50
|
+
}
|
|
51
|
+
async function deployRiddleStaticPreview(config, directory, label) {
|
|
52
|
+
if (!directory?.trim()) throw new Error("directory is required");
|
|
53
|
+
if (!label?.trim()) throw new Error("label is required");
|
|
54
|
+
const created = await riddleRequestJson(config, "/v1/preview", {
|
|
55
|
+
method: "POST",
|
|
56
|
+
body: JSON.stringify({ framework: "spa", label })
|
|
57
|
+
});
|
|
58
|
+
const id = String(created.id || "");
|
|
59
|
+
const uploadUrl = String(created.upload_url || "");
|
|
60
|
+
if (!id || !uploadUrl) throw new Error("Riddle preview create response was missing id or upload_url.");
|
|
61
|
+
const scratch = mkdtempSync(path.join(tmpdir(), "riddle-preview-upload-"));
|
|
62
|
+
const tarball = path.join(scratch, `${id}.tar.gz`);
|
|
63
|
+
try {
|
|
64
|
+
execFileSync("tar", ["czf", tarball, "-C", directory, "."], { stdio: "pipe" });
|
|
65
|
+
const upload = await fetchFor(config)(uploadUrl, {
|
|
66
|
+
method: "PUT",
|
|
67
|
+
headers: { "Content-Type": "application/gzip" },
|
|
68
|
+
body: readFileSync(tarball)
|
|
69
|
+
});
|
|
70
|
+
if (!upload.ok) {
|
|
71
|
+
throw new RiddleApiError(uploadUrl, upload.status, await upload.text());
|
|
72
|
+
}
|
|
73
|
+
} finally {
|
|
74
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
75
|
+
}
|
|
76
|
+
const published = await riddleRequestJson(config, `/v1/preview/${id}/publish`, {
|
|
77
|
+
method: "POST"
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
ok: true,
|
|
81
|
+
id: String(published.id || id),
|
|
82
|
+
label,
|
|
83
|
+
preview_url: String(published.preview_url || ""),
|
|
84
|
+
file_count: typeof published.file_count === "number" ? published.file_count : void 0,
|
|
85
|
+
total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
|
|
86
|
+
expires_at: typeof created.expires_at === "string" ? created.expires_at : void 0,
|
|
87
|
+
raw: published
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function parseRiddleViewport(value) {
|
|
91
|
+
if (!value) return void 0;
|
|
92
|
+
const match = /^(\d+)x(\d+)$/.exec(value.trim());
|
|
93
|
+
if (!match) throw new Error("viewport must look like 1280x720");
|
|
94
|
+
return { width: Number(match[1]), height: Number(match[2]) };
|
|
95
|
+
}
|
|
96
|
+
async function runRiddleScript(config, input) {
|
|
97
|
+
if (!input.url?.trim()) throw new Error("url is required");
|
|
98
|
+
if (!input.script?.trim()) throw new Error("script is required");
|
|
99
|
+
const payload = {
|
|
100
|
+
url: input.url,
|
|
101
|
+
script: input.script,
|
|
102
|
+
sync: input.sync ?? false,
|
|
103
|
+
timeout_sec: input.timeoutSec || 120
|
|
104
|
+
};
|
|
105
|
+
if (input.viewport) payload.viewport = input.viewport;
|
|
106
|
+
if (input.include) payload.include = input.include;
|
|
107
|
+
if (input.options) payload.options = input.options;
|
|
108
|
+
return riddleRequestJson(config, "/v1/run", {
|
|
109
|
+
method: "POST",
|
|
110
|
+
body: JSON.stringify(payload)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function isTerminalRiddleJobStatus(status) {
|
|
114
|
+
return ["completed", "complete", "completed_error", "completed_timeout", "failed"].includes(String(status || ""));
|
|
115
|
+
}
|
|
116
|
+
async function pollRiddleJob(config, jobId, options = {}) {
|
|
117
|
+
if (!jobId?.trim()) throw new Error("jobId is required");
|
|
118
|
+
const attempts = options.attempts || (options.wait ? 60 : 1);
|
|
119
|
+
const intervalMs = options.intervalMs || 2e3;
|
|
120
|
+
let job = null;
|
|
121
|
+
for (let index = 0; index < attempts; index += 1) {
|
|
122
|
+
job = await riddleRequestJson(config, `/v1/jobs/${jobId}`);
|
|
123
|
+
if (isTerminalRiddleJobStatus(job.status)) break;
|
|
124
|
+
if (index + 1 < attempts) {
|
|
125
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const status = job?.status ? String(job.status) : null;
|
|
129
|
+
if (!isTerminalRiddleJobStatus(status)) {
|
|
130
|
+
return { ok: true, job_id: jobId, status, terminal: false, job };
|
|
131
|
+
}
|
|
132
|
+
const artifacts = await riddleRequestJson(config, `/v1/jobs/${jobId}/artifacts`);
|
|
133
|
+
return {
|
|
134
|
+
ok: status === "completed" || status === "complete",
|
|
135
|
+
job_id: jobId,
|
|
136
|
+
status,
|
|
137
|
+
terminal: true,
|
|
138
|
+
job,
|
|
139
|
+
artifacts
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function createRiddleApiClient(config = {}) {
|
|
143
|
+
return {
|
|
144
|
+
requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
|
|
145
|
+
deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
|
|
146
|
+
runScript: (input) => runRiddleScript(config, input),
|
|
147
|
+
pollJob: (jobId, options) => pollRiddleJob(config, jobId, options)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export {
|
|
152
|
+
DEFAULT_RIDDLE_API_BASE_URL,
|
|
153
|
+
DEFAULT_RIDDLE_API_KEY_FILE,
|
|
154
|
+
RiddleApiError,
|
|
155
|
+
resolveRiddleApiKey,
|
|
156
|
+
riddleRequestJson,
|
|
157
|
+
deployRiddleStaticPreview,
|
|
158
|
+
parseRiddleViewport,
|
|
159
|
+
runRiddleScript,
|
|
160
|
+
isTerminalRiddleJobStatus,
|
|
161
|
+
pollRiddleJob,
|
|
162
|
+
createRiddleApiClient
|
|
163
|
+
};
|