@riddledc/riddle-proof 0.8.83 → 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.
- package/README.md +247 -29
- package/capabilities.json +17 -0
- package/dist/advanced/engine-harness.js +2 -2
- package/dist/advanced/index.d.cts +1 -1
- package/dist/advanced/index.d.ts +1 -1
- package/dist/advanced/index.js +4 -4
- package/dist/advanced/proof-run-engine.d.cts +1 -1
- package/dist/advanced/proof-run-engine.d.ts +1 -1
- package/dist/advanced/runner.js +2 -2
- package/dist/change-proof.cjs +22 -260
- package/dist/change-proof.d.cts +1 -1
- package/dist/change-proof.d.ts +1 -1
- package/dist/change-proof.js +2 -2
- package/dist/checked-meaning.cjs +67 -0
- package/dist/checked-meaning.d.cts +2 -0
- package/dist/checked-meaning.d.ts +2 -0
- package/dist/checked-meaning.js +41 -0
- package/dist/{chunk-QYZ3GKCP.js → chunk-AFARUBE4.js} +12 -11
- package/dist/chunk-J2SIQGQI.js +71 -0
- package/dist/{chunk-7OAETQU3.js → chunk-JZKLCY5G.js} +1 -1
- package/dist/chunk-KB7FYRBG.js +46 -0
- package/dist/chunk-NWLKJ2WI.js +31 -0
- package/dist/{chunk-LR4UYJDY.js → chunk-O2AO726C.js} +1 -1
- package/dist/chunk-ODLGSEP2.js +43 -0
- package/dist/chunk-OHDNCXRM.js +17 -0
- package/dist/cli/index.js +7 -7
- package/dist/cli.cjs +265 -1122
- package/dist/cli.d.cts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +7 -7
- package/dist/engine-harness.js +2 -2
- package/dist/grounded-evidence.cjs +95 -0
- package/dist/grounded-evidence.d.cts +2 -0
- package/dist/grounded-evidence.d.ts +2 -0
- package/dist/grounded-evidence.js +69 -0
- package/dist/index.cjs +318 -1539
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +136 -16
- package/dist/pr-comment.cjs +17 -107
- package/dist/pr-comment.d.cts +1 -1
- package/dist/pr-comment.d.ts +1 -1
- package/dist/pr-comment.js +3 -3
- package/dist/{proof-run-engine-MiKZt9oY.d.ts → proof-run-engine-BqRoA3Do.d.ts} +3 -3
- package/dist/{proof-run-engine-Baiv6l3A.d.cts → proof-run-engine-DpChFR5H.d.cts} +3 -3
- package/dist/proof-run-engine.d.cts +1 -1
- package/dist/proof-run-engine.d.ts +1 -1
- package/dist/receipts.cjs +10 -255
- package/dist/receipts.d.cts +7 -115
- package/dist/receipts.d.ts +7 -115
- package/dist/receipts.js +1 -1
- package/dist/riddle-client.cjs +23 -695
- package/dist/riddle-client.d.cts +1 -188
- package/dist/riddle-client.d.ts +1 -188
- package/dist/riddle-client.js +5 -2
- package/dist/runner.js +2 -2
- package/dist/runtime/index.cjs +23 -695
- package/dist/runtime/index.d.cts +1 -5
- package/dist/runtime/index.d.ts +1 -5
- package/dist/runtime/index.js +5 -2
- package/dist/runtime/riddle-client.cjs +23 -695
- package/dist/runtime/riddle-client.d.cts +1 -5
- package/dist/runtime/riddle-client.d.ts +1 -5
- package/dist/runtime/riddle-client.js +5 -2
- package/dist/semantic-certificate.cjs +23 -582
- package/dist/semantic-certificate.d.cts +2 -191
- package/dist/semantic-certificate.d.ts +2 -191
- package/dist/semantic-certificate.js +15 -3
- package/package.json +28 -5
- package/runtime/lib/riddle_core_call.mjs +3 -806
- package/dist/chunk-5IFZSUPF.js +0 -644
- package/dist/chunk-DB5ZHRUP.js +0 -585
- package/dist/chunk-MEVVL4TI.js +0 -258
- package/dist/{chunk-WLUMLHII.js → chunk-BID7CKMM.js} +9 -9
- package/dist/{chunk-YH7ADFY4.js → chunk-IVSP24XI.js} +3 -3
|
@@ -1,807 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import { createServer } from "node:net";
|
|
6
|
-
import { homedir } from "node:os";
|
|
7
|
-
import { join } from "node:path";
|
|
8
|
-
import { pathToFileURL } from "node:url";
|
|
9
|
-
|
|
10
|
-
const TOOL_DEFAULT_INCLUDE = ["screenshot", "console", "result", "data", "urls", "dataset", "sitemap", "visual_diff"];
|
|
11
|
-
const DEFAULT_BASE_URL = "https://api.riddledc.com";
|
|
12
|
-
const DEFAULT_API_KEY_FILE = "/tmp/riddle-api-key";
|
|
13
|
-
const require = createRequire(import.meta.url);
|
|
14
|
-
|
|
15
|
-
function readJson(path) {
|
|
16
|
-
try {
|
|
17
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
18
|
-
} catch {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function readOpenClawPluginConfig() {
|
|
24
|
-
const paths = [
|
|
25
|
-
process.env.OPENCLAW_CONFIG,
|
|
26
|
-
process.env.OPENCLAW_HOME ? join(process.env.OPENCLAW_HOME, "openclaw.json") : "",
|
|
27
|
-
join(homedir(), ".openclaw", "openclaw.json"),
|
|
28
|
-
"/root/.openclaw/openclaw.json",
|
|
29
|
-
].filter(Boolean);
|
|
30
|
-
|
|
31
|
-
for (const path of paths) {
|
|
32
|
-
const cfg = readJson(path);
|
|
33
|
-
const pluginCfg = cfg?.plugins?.entries?.["openclaw-riddledc"]?.config;
|
|
34
|
-
if (pluginCfg) return pluginCfg;
|
|
35
|
-
}
|
|
36
|
-
return {};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function buildConfig() {
|
|
40
|
-
const pluginCfg = readOpenClawPluginConfig();
|
|
41
|
-
return {
|
|
42
|
-
apiKey: process.env.RIDDLE_API_KEY || readApiKeyFile() || pluginCfg.apiKey,
|
|
43
|
-
baseUrl: process.env.RIDDLE_API_BASE_URL || pluginCfg.baseUrl || DEFAULT_BASE_URL,
|
|
44
|
-
workspace: process.env.OPENCLAW_WORKSPACE || process.cwd(),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function readApiKeyFile() {
|
|
49
|
-
const keyFile = process.env.RIDDLE_API_KEY_FILE || DEFAULT_API_KEY_FILE;
|
|
50
|
-
try {
|
|
51
|
-
const key = readFileSync(keyFile, "utf8").trim();
|
|
52
|
-
return key || "";
|
|
53
|
-
} catch {
|
|
54
|
-
return "";
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function requireConfig(config) {
|
|
59
|
-
const apiKey = config.apiKey || process.env.RIDDLE_API_KEY || readApiKeyFile();
|
|
60
|
-
const baseUrl = config.baseUrl || DEFAULT_BASE_URL;
|
|
61
|
-
if (!apiKey) {
|
|
62
|
-
throw new Error("Missing Riddle API key. Set RIDDLE_API_KEY or RIDDLE_API_KEY_FILE before running Riddle Proof direct browser evidence.");
|
|
63
|
-
}
|
|
64
|
-
assertAllowedBaseUrl(baseUrl);
|
|
65
|
-
return { apiKey, baseUrl, workspace: config.workspace || process.cwd() };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function assertAllowedBaseUrl(baseUrl) {
|
|
69
|
-
const url = new URL(baseUrl);
|
|
70
|
-
if (url.protocol !== "https:") throw new Error("Riddle baseUrl must be https: " + baseUrl);
|
|
71
|
-
if (url.hostname !== "api.riddledc.com") {
|
|
72
|
-
throw new Error("Refusing to use non-official Riddle host: " + url.hostname);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function detectMode(payload) {
|
|
77
|
-
if (payload.url) return "url";
|
|
78
|
-
if (payload.urls) return "urls";
|
|
79
|
-
if (payload.steps) return "steps";
|
|
80
|
-
if (payload.script) return "script";
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function abToBase64(ab) {
|
|
85
|
-
return Buffer.from(ab).toString("base64");
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function sleep(ms) {
|
|
89
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function truthy(value) {
|
|
93
|
-
return String(value || "").toLowerCase().match(/^(1|true|yes|y|on)$/);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function localRiddleScriptAllowed() {
|
|
97
|
-
const runner = String(process.env.RIDDLE_PROOF_BROWSER_RUNNER || "").toLowerCase();
|
|
98
|
-
if (runner === "hosted" || runner === "riddle") return false;
|
|
99
|
-
if (String(process.env.RIDDLE_PROOF_DISABLE_LOCAL_RIDDLE_SCRIPT || "").toLowerCase().match(/^(1|true|yes)$/)) return false;
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function localRiddleScriptPreferred() {
|
|
104
|
-
const runner = String(process.env.RIDDLE_PROOF_BROWSER_RUNNER || "").toLowerCase();
|
|
105
|
-
return runner === "local" || runner === "playwright" || runner === "local-playwright";
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function sanitizeArtifactName(input, fallback = "artifact") {
|
|
109
|
-
return String(input || fallback)
|
|
110
|
-
.trim()
|
|
111
|
-
.replace(/^\.\.?(\/|\\)/g, "")
|
|
112
|
-
.replace(/[/\\]/g, "-")
|
|
113
|
-
.replace(/\s+/g, "-")
|
|
114
|
-
.replace(/[^a-zA-Z0-9._-]/g, "-")
|
|
115
|
-
.replace(/-+/g, "-")
|
|
116
|
-
.replace(/^-|-$/g, "") || fallback;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function localArtifactRoot() {
|
|
120
|
-
const root = process.env.RIDDLE_PROOF_LOCAL_ARTIFACT_DIR || join(process.cwd(), "artifacts", "riddle-proof", "local-browser");
|
|
121
|
-
const id = `${new Date().toISOString().replace(/[:.]/g, "-")}-${Math.random().toString(36).slice(2, 8)}`;
|
|
122
|
-
const dir = join(root, id);
|
|
123
|
-
mkdirSync(dir, { recursive: true });
|
|
124
|
-
mkdirSync(join(dir, "screenshots"), { recursive: true });
|
|
125
|
-
return dir;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async function loadLocalPlaywright() {
|
|
129
|
-
const packagePaths = [
|
|
130
|
-
process.cwd(),
|
|
131
|
-
join(process.cwd(), "packages", "riddle-proof-runner-playwright"),
|
|
132
|
-
join(process.cwd(), "..", "riddle-proof-runner-playwright"),
|
|
133
|
-
process.env.RIDDLE_PROOF_PLAYWRIGHT_PACKAGE_DIR || "",
|
|
134
|
-
].filter(Boolean);
|
|
135
|
-
|
|
136
|
-
let resolved = "";
|
|
137
|
-
try {
|
|
138
|
-
resolved = require.resolve("playwright");
|
|
139
|
-
} catch {
|
|
140
|
-
for (const packagePath of packagePaths) {
|
|
141
|
-
try {
|
|
142
|
-
resolved = require.resolve("playwright", { paths: [packagePath] });
|
|
143
|
-
break;
|
|
144
|
-
} catch {
|
|
145
|
-
// Try next path.
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (!resolved) {
|
|
150
|
-
throw new Error("Playwright is required for local Riddle Proof browser evidence. Install playwright or set RIDDLE_PROOF_BROWSER_RUNNER=hosted with a Riddle API key.");
|
|
151
|
-
}
|
|
152
|
-
const mod = await import(pathToFileURL(resolved).href);
|
|
153
|
-
return mod.default || mod;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async function runLocalRiddleScript(payload, defaults = {}, blockedHostedReason = "") {
|
|
157
|
-
if (!payload.script || typeof payload.script !== "string") {
|
|
158
|
-
return { ok: false, error: blockedHostedReason || "Local Riddle Proof browser evidence requires a script payload." };
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const outputs = [];
|
|
162
|
-
const screenshots = [];
|
|
163
|
-
const consoleMessages = [];
|
|
164
|
-
const resultArtifacts = {};
|
|
165
|
-
const outputDir = localArtifactRoot();
|
|
166
|
-
const playwright = await loadLocalPlaywright();
|
|
167
|
-
const browserName = payload.browser || "chromium";
|
|
168
|
-
const browserType = playwright[browserName] || playwright.chromium;
|
|
169
|
-
const browser = await browserType.launch({ headless: payload.headful !== true });
|
|
170
|
-
const context = await browser.newContext({
|
|
171
|
-
viewport: payload.viewport || undefined,
|
|
172
|
-
});
|
|
173
|
-
const page = await context.newPage();
|
|
174
|
-
const timeoutMs = Number(payload.timeout_sec ?? payload.timeoutSec ?? 60) * 1000;
|
|
175
|
-
page.setDefaultTimeout(Math.min(timeoutMs, 120_000));
|
|
176
|
-
page.setDefaultNavigationTimeout(Math.min(timeoutMs, 120_000));
|
|
177
|
-
page.on("console", (message) => {
|
|
178
|
-
consoleMessages.push({ type: message.type(), text: message.text() });
|
|
179
|
-
});
|
|
180
|
-
page.on("pageerror", (error) => {
|
|
181
|
-
consoleMessages.push({ type: "pageerror", text: error?.message || String(error) });
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
const saveScreenshot = async (label = "screenshot", options = {}) => {
|
|
185
|
-
const name = sanitizeArtifactName(label, "screenshot").replace(/\.(png|jpg|jpeg)$/i, "") + ".png";
|
|
186
|
-
const path = join(outputDir, "screenshots", name);
|
|
187
|
-
const buffer = await page.screenshot({ fullPage: options?.fullPage === true });
|
|
188
|
-
writeFileSync(path, buffer);
|
|
189
|
-
const item = {
|
|
190
|
-
name,
|
|
191
|
-
url: pathToFileURL(path).href,
|
|
192
|
-
path,
|
|
193
|
-
size: buffer.byteLength,
|
|
194
|
-
};
|
|
195
|
-
outputs.push({ name, url: item.url, path, size_bytes: buffer.byteLength });
|
|
196
|
-
screenshots.push(item);
|
|
197
|
-
return { name, url: item.url, path };
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
const saveJson = async (name = "artifact", value = {}) => {
|
|
201
|
-
const fileName = sanitizeArtifactName(name, "artifact").replace(/\.json$/i, "") + ".json";
|
|
202
|
-
const path = join(outputDir, fileName);
|
|
203
|
-
writeFileSync(path, JSON.stringify(value, null, 2));
|
|
204
|
-
const item = { name: fileName, url: pathToFileURL(path).href, path };
|
|
205
|
-
outputs.push(item);
|
|
206
|
-
resultArtifacts[fileName] = value;
|
|
207
|
-
return item;
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
const previousEvidence = globalThis.__riddleProofEvidence;
|
|
211
|
-
globalThis.__riddleProofEvidence = undefined;
|
|
212
|
-
let scriptResult;
|
|
213
|
-
let proofEvidence;
|
|
214
|
-
try {
|
|
215
|
-
const runnerFactory = Object.getPrototypeOf(async function () {}).constructor;
|
|
216
|
-
const runScript = new runnerFactory("page", "saveScreenshot", "saveJson", "url", payload.script);
|
|
217
|
-
scriptResult = await Promise.race([
|
|
218
|
-
runScript(page, saveScreenshot, saveJson, payload.url || ""),
|
|
219
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error(`local riddle_script timed out after ${timeoutMs}ms`)), timeoutMs + 1000)),
|
|
220
|
-
]);
|
|
221
|
-
proofEvidence = globalThis.__riddleProofEvidence;
|
|
222
|
-
} catch (err) {
|
|
223
|
-
const failedProofEvidence = globalThis.__riddleProofEvidence;
|
|
224
|
-
return {
|
|
225
|
-
ok: false,
|
|
226
|
-
mode: "script",
|
|
227
|
-
runner: "local-playwright",
|
|
228
|
-
error: err instanceof Error ? err.message : String(err),
|
|
229
|
-
script_error: err instanceof Error ? err.stack || err.message : String(err),
|
|
230
|
-
outputs,
|
|
231
|
-
screenshots,
|
|
232
|
-
screenshot: screenshots[0],
|
|
233
|
-
console: consoleMessages,
|
|
234
|
-
result: failedProofEvidence ? { proofEvidence: failedProofEvidence } : undefined,
|
|
235
|
-
};
|
|
236
|
-
} finally {
|
|
237
|
-
try {
|
|
238
|
-
await context.close();
|
|
239
|
-
await browser.close();
|
|
240
|
-
} finally {
|
|
241
|
-
globalThis.__riddleProofEvidence = previousEvidence;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let result = typeof scriptResult === "object" && scriptResult !== null && !Array.isArray(scriptResult)
|
|
246
|
-
? scriptResult
|
|
247
|
-
: scriptResult !== undefined
|
|
248
|
-
? { value: scriptResult }
|
|
249
|
-
: {};
|
|
250
|
-
if (proofEvidence !== undefined && result.proofEvidence === undefined && result.proof_evidence === undefined) {
|
|
251
|
-
result = { ...result, proofEvidence };
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (!outputs.find((item) => item.name === "result.json")) {
|
|
255
|
-
await saveJson("result", result);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return {
|
|
259
|
-
ok: true,
|
|
260
|
-
mode: "script",
|
|
261
|
-
runner: "local-playwright",
|
|
262
|
-
local: true,
|
|
263
|
-
outputs,
|
|
264
|
-
screenshots,
|
|
265
|
-
screenshot: screenshots[0],
|
|
266
|
-
console: consoleMessages,
|
|
267
|
-
result,
|
|
268
|
-
resultArtifacts,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
function localServerPreviewAllowed() {
|
|
273
|
-
const runner = String(process.env.RIDDLE_PROOF_BROWSER_RUNNER || "").toLowerCase();
|
|
274
|
-
if (runner === "hosted" || runner === "riddle") return false;
|
|
275
|
-
if (truthy(process.env.RIDDLE_PROOF_DISABLE_LOCAL_SERVER_PREVIEW)) return false;
|
|
276
|
-
return true;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
async function isPortAvailable(port) {
|
|
280
|
-
return new Promise((resolve) => {
|
|
281
|
-
const server = createServer();
|
|
282
|
-
server.once("error", () => resolve(false));
|
|
283
|
-
server.once("listening", () => server.close(() => resolve(true)));
|
|
284
|
-
server.listen(port, "127.0.0.1");
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
async function availablePort(preferred) {
|
|
289
|
-
const start = numberValue(preferred, 3000);
|
|
290
|
-
for (let offset = 0; offset < 50; offset += 1) {
|
|
291
|
-
const port = start + offset;
|
|
292
|
-
if (await isPortAvailable(port)) return port;
|
|
293
|
-
}
|
|
294
|
-
throw new Error(`No available local preview port near ${start}`);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function appendLimited(lines, value, maxLength = 20_000) {
|
|
298
|
-
if (!value) return;
|
|
299
|
-
lines.push(String(value));
|
|
300
|
-
while (lines.join("").length > maxLength && lines.length > 1) lines.shift();
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
function localPreviewUrl(port, targetPath = "/") {
|
|
304
|
-
return new URL(targetPath || "/", `http://127.0.0.1:${port}/`).href;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
async function waitForReadiness(url, timeoutMs, child, stdoutLines, stderrLines) {
|
|
308
|
-
const start = Date.now();
|
|
309
|
-
let lastError = "";
|
|
310
|
-
while (Date.now() - start < timeoutMs) {
|
|
311
|
-
if (child.exitCode !== null) {
|
|
312
|
-
const tail = [stdoutLines.join(""), stderrLines.join("")].filter(Boolean).join("\n").slice(-2000);
|
|
313
|
-
throw new Error(`local server preview command exited before readiness (${child.exitCode}). ${tail}`.trim());
|
|
314
|
-
}
|
|
315
|
-
try {
|
|
316
|
-
const response = await fetch(url, { redirect: "manual" });
|
|
317
|
-
if (response.status < 500) return;
|
|
318
|
-
lastError = `HTTP ${response.status}`;
|
|
319
|
-
} catch (err) {
|
|
320
|
-
lastError = err instanceof Error ? err.message : String(err);
|
|
321
|
-
}
|
|
322
|
-
await sleep(500);
|
|
323
|
-
}
|
|
324
|
-
throw new Error(`local server preview was not ready at ${url} within ${timeoutMs}ms${lastError ? `: ${lastError}` : ""}`);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function terminateChild(child) {
|
|
328
|
-
if (!child || child.exitCode !== null) return;
|
|
329
|
-
try {
|
|
330
|
-
if (child.pid) process.kill(-child.pid, "SIGTERM");
|
|
331
|
-
} catch {
|
|
332
|
-
try {
|
|
333
|
-
child.kill("SIGTERM");
|
|
334
|
-
} catch {
|
|
335
|
-
// Best effort cleanup.
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
setTimeout(() => {
|
|
339
|
-
try {
|
|
340
|
-
if (child.exitCode === null && child.pid) process.kill(-child.pid, "SIGKILL");
|
|
341
|
-
} catch {
|
|
342
|
-
// Best effort cleanup.
|
|
343
|
-
}
|
|
344
|
-
}, 2000).unref?.();
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
async function runLocalServerPreview(rawArgs) {
|
|
348
|
-
if (!localServerPreviewAllowed()) {
|
|
349
|
-
return { ok: false, error: "Local Riddle Proof server preview is disabled." };
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const args = normalizeServerArgs(rawArgs);
|
|
353
|
-
const directory = String(args.directory || "").trim();
|
|
354
|
-
const command = String(args.command || "").trim();
|
|
355
|
-
if (!directory || !existsSync(directory)) {
|
|
356
|
-
return { ok: false, error: `Local Riddle Proof server preview directory does not exist: ${directory || "(missing)"}` };
|
|
357
|
-
}
|
|
358
|
-
if (!command) {
|
|
359
|
-
return { ok: false, error: "Local Riddle Proof server preview requires a command." };
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
const port = await availablePort(args.port);
|
|
363
|
-
const previewUrl = `http://127.0.0.1:${port}/`;
|
|
364
|
-
const targetUrl = localPreviewUrl(port, args.path || "/");
|
|
365
|
-
const readinessUrl = localPreviewUrl(port, args.readiness_path || args.path || "/");
|
|
366
|
-
const readinessTimeoutMs = numberValue(args.readiness_timeout ?? args.readinessTimeout, 120) * 1000;
|
|
367
|
-
const stdoutLines = [];
|
|
368
|
-
const stderrLines = [];
|
|
369
|
-
const env = {
|
|
370
|
-
...process.env,
|
|
371
|
-
...(args.env || {}),
|
|
372
|
-
PORT: String(port),
|
|
373
|
-
HOSTNAME: String((args.env || {}).HOSTNAME || "127.0.0.1"),
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
const child = spawn(command, {
|
|
377
|
-
cwd: directory,
|
|
378
|
-
env,
|
|
379
|
-
shell: true,
|
|
380
|
-
detached: true,
|
|
381
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
382
|
-
});
|
|
383
|
-
child.stdout?.on("data", (chunk) => appendLimited(stdoutLines, chunk.toString()));
|
|
384
|
-
child.stderr?.on("data", (chunk) => appendLimited(stderrLines, chunk.toString()));
|
|
385
|
-
|
|
386
|
-
try {
|
|
387
|
-
await waitForReadiness(readinessUrl, readinessTimeoutMs, child, stdoutLines, stderrLines);
|
|
388
|
-
const waitUntil = String(args.wait_until || args.waitUntil || "domcontentloaded");
|
|
389
|
-
const captureTimeoutSec = numberValue(args.timeout_sec ?? args.timeout, 300);
|
|
390
|
-
const scriptParts = [
|
|
391
|
-
`await page.goto(${JSON.stringify(targetUrl)}, { waitUntil: ${JSON.stringify(waitUntil)}, timeout: ${JSON.stringify(captureTimeoutSec * 1000)} });`,
|
|
392
|
-
];
|
|
393
|
-
if (args.wait_for_selector || args.waitForSelector) {
|
|
394
|
-
scriptParts.push(`await page.waitForSelector(${JSON.stringify(args.wait_for_selector || args.waitForSelector)}, { timeout: 30000 });`);
|
|
395
|
-
}
|
|
396
|
-
if (args.script && String(args.script).trim()) {
|
|
397
|
-
scriptParts.push(String(args.script).trim());
|
|
398
|
-
} else {
|
|
399
|
-
scriptParts.push("await saveScreenshot('after-proof');");
|
|
400
|
-
}
|
|
401
|
-
const capture = await runLocalRiddleScript({
|
|
402
|
-
...args,
|
|
403
|
-
url: targetUrl,
|
|
404
|
-
script: scriptParts.join("\n"),
|
|
405
|
-
timeout_sec: captureTimeoutSec,
|
|
406
|
-
});
|
|
407
|
-
return {
|
|
408
|
-
...capture,
|
|
409
|
-
local: true,
|
|
410
|
-
runner: "local-server-preview",
|
|
411
|
-
preview_url: previewUrl,
|
|
412
|
-
target_url: targetUrl,
|
|
413
|
-
readiness_url: readinessUrl,
|
|
414
|
-
port,
|
|
415
|
-
stdout: stdoutLines.join("").slice(-8000),
|
|
416
|
-
stderr: stderrLines.join("").slice(-8000),
|
|
417
|
-
};
|
|
418
|
-
} catch (err) {
|
|
419
|
-
return {
|
|
420
|
-
ok: false,
|
|
421
|
-
mode: "server_preview",
|
|
422
|
-
runner: "local-server-preview",
|
|
423
|
-
error: err instanceof Error ? err.message : String(err),
|
|
424
|
-
preview_url: previewUrl,
|
|
425
|
-
target_url: targetUrl,
|
|
426
|
-
readiness_url: readinessUrl,
|
|
427
|
-
port,
|
|
428
|
-
stdout: stdoutLines.join("").slice(-8000),
|
|
429
|
-
stderr: stderrLines.join("").slice(-8000),
|
|
430
|
-
};
|
|
431
|
-
} finally {
|
|
432
|
-
terminateChild(child);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
async function postRun(baseUrl, apiKey, payload) {
|
|
437
|
-
const response = await fetch(`${baseUrl.replace(/\/$/, "")}/v1/run`, {
|
|
438
|
-
method: "POST",
|
|
439
|
-
headers: {
|
|
440
|
-
Authorization: `Bearer ${apiKey}`,
|
|
441
|
-
"Content-Type": "application/json",
|
|
442
|
-
},
|
|
443
|
-
body: JSON.stringify(payload),
|
|
444
|
-
});
|
|
445
|
-
return {
|
|
446
|
-
contentType: response.headers.get("content-type"),
|
|
447
|
-
body: await response.arrayBuffer(),
|
|
448
|
-
headers: response.headers,
|
|
449
|
-
status: response.status,
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
async function pollJobStatus(config, jobId, maxWaitMs) {
|
|
454
|
-
const start = Date.now();
|
|
455
|
-
const pollIntervalMs = 2000;
|
|
456
|
-
|
|
457
|
-
while (Date.now() - start < maxWaitMs) {
|
|
458
|
-
const response = await fetch(`${config.baseUrl.replace(/\/$/, "")}/v1/jobs/${jobId}`, {
|
|
459
|
-
headers: { Authorization: `Bearer ${config.apiKey}` },
|
|
460
|
-
});
|
|
461
|
-
if (!response.ok) {
|
|
462
|
-
return { status: "poll_error", error: "HTTP " + response.status };
|
|
463
|
-
}
|
|
464
|
-
const data = await response.json();
|
|
465
|
-
if (["completed", "completed_timeout", "completed_error", "failed"].includes(data.status)) {
|
|
466
|
-
return data;
|
|
467
|
-
}
|
|
468
|
-
await sleep(pollIntervalMs);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
return { status: "poll_timeout", error: `Job ${jobId} did not complete within ${maxWaitMs}ms` };
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
async function fetchArtifactsAndBuild(config, jobId, include) {
|
|
475
|
-
const response = await fetch(
|
|
476
|
-
`${config.baseUrl.replace(/\/$/, "")}/v1/jobs/${jobId}/artifacts?include=${include.join(",")}`,
|
|
477
|
-
{ headers: { Authorization: `Bearer ${config.apiKey}` } }
|
|
478
|
-
);
|
|
479
|
-
if (!response.ok) {
|
|
480
|
-
return { error: "Artifacts fetch failed: HTTP " + response.status };
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
const data = await response.json();
|
|
484
|
-
const artifacts = data.artifacts || [];
|
|
485
|
-
const result = { outputs: artifacts };
|
|
486
|
-
if (data.status) result._artifactsStatus = data.status;
|
|
487
|
-
if (data.timeout) result._timeout = data.timeout;
|
|
488
|
-
if (data.error) result._error = data.error;
|
|
489
|
-
|
|
490
|
-
const screenshots = artifacts.filter((artifact) => artifact.name && /\.(png|jpg|jpeg)$/i.test(artifact.name));
|
|
491
|
-
if (screenshots.length > 0) {
|
|
492
|
-
result.screenshots = [];
|
|
493
|
-
for (const screenshot of screenshots) {
|
|
494
|
-
if (!screenshot.url) continue;
|
|
495
|
-
try {
|
|
496
|
-
const imageResponse = await fetch(screenshot.url);
|
|
497
|
-
if (imageResponse.ok) {
|
|
498
|
-
const buffer = await imageResponse.arrayBuffer();
|
|
499
|
-
result.screenshots.push({
|
|
500
|
-
name: screenshot.name,
|
|
501
|
-
data: `data:image/png;base64,${Buffer.from(buffer).toString("base64")}`,
|
|
502
|
-
size: buffer.byteLength,
|
|
503
|
-
url: screenshot.url,
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
} catch {
|
|
507
|
-
// Screenshot artifacts are optional diagnostics.
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
if (result.screenshots.length > 0) {
|
|
511
|
-
result.screenshot = result.screenshots[0];
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
const consoleArtifact = artifacts.find((artifact) => artifact.name === "console.json");
|
|
516
|
-
if (consoleArtifact?.url) {
|
|
517
|
-
try {
|
|
518
|
-
const consoleResponse = await fetch(consoleArtifact.url);
|
|
519
|
-
if (consoleResponse.ok) result.console = await consoleResponse.json();
|
|
520
|
-
} catch {
|
|
521
|
-
// Optional diagnostic.
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
const resultArtifact = artifacts.find((artifact) => artifact.name === "result.json");
|
|
526
|
-
if (resultArtifact?.url) {
|
|
527
|
-
try {
|
|
528
|
-
const resultResponse = await fetch(resultArtifact.url);
|
|
529
|
-
if (resultResponse.ok) result.result = await resultResponse.json();
|
|
530
|
-
} catch {
|
|
531
|
-
// Optional diagnostic.
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
const visualDiffArtifact = artifacts.find((artifact) => artifact.name === "visual-diff.json");
|
|
536
|
-
if (include.includes("visual_diff") && visualDiffArtifact?.url) {
|
|
537
|
-
try {
|
|
538
|
-
const visualDiffResponse = await fetch(visualDiffArtifact.url);
|
|
539
|
-
if (visualDiffResponse.ok) result.visual_diff = await visualDiffResponse.json();
|
|
540
|
-
} catch {
|
|
541
|
-
// Optional diagnostic.
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
const visualDiffImages = artifacts.filter((artifact) => /^visual-diff.*\.(png|jpg|jpeg)$/i.test(artifact.name || ""));
|
|
546
|
-
if (visualDiffImages.length > 0) {
|
|
547
|
-
result.visual_diff_images = visualDiffImages;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
if (include.includes("har")) {
|
|
551
|
-
const harArtifact = artifacts.find((artifact) => artifact.name === "network.har");
|
|
552
|
-
if (harArtifact?.url) {
|
|
553
|
-
try {
|
|
554
|
-
const harResponse = await fetch(harArtifact.url);
|
|
555
|
-
if (harResponse.ok) result.har = await harResponse.json();
|
|
556
|
-
} catch {
|
|
557
|
-
// Optional diagnostic.
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
return result;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
async function runWithDefaults(payload, defaults = {}) {
|
|
566
|
-
if (localRiddleScriptPreferred() && payload.script && localRiddleScriptAllowed()) {
|
|
567
|
-
try {
|
|
568
|
-
return await runLocalRiddleScript(payload, defaults);
|
|
569
|
-
} catch (err) {
|
|
570
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
let config;
|
|
575
|
-
try {
|
|
576
|
-
config = requireConfig(buildConfig());
|
|
577
|
-
} catch (err) {
|
|
578
|
-
if (payload.script && localRiddleScriptAllowed()) {
|
|
579
|
-
try {
|
|
580
|
-
return await runLocalRiddleScript(payload, defaults, err instanceof Error ? err.message : String(err));
|
|
581
|
-
} catch (localErr) {
|
|
582
|
-
return {
|
|
583
|
-
ok: false,
|
|
584
|
-
error: [
|
|
585
|
-
err instanceof Error ? err.message : String(err),
|
|
586
|
-
localErr instanceof Error ? localErr.message : String(localErr),
|
|
587
|
-
].filter(Boolean).join(" Local fallback also failed: "),
|
|
588
|
-
};
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
const mode = detectMode(payload);
|
|
595
|
-
const userInclude = Array.isArray(payload.include) ? payload.include : [];
|
|
596
|
-
const returnAsync = !!defaults.returnAsync;
|
|
597
|
-
const merged = { ...payload };
|
|
598
|
-
if (returnAsync) merged.sync = false;
|
|
599
|
-
merged.include = Array.from(new Set([...userInclude, ...(defaults.include || ["screenshot", "console"])]));
|
|
600
|
-
merged.inlineConsole = merged.inlineConsole ?? true;
|
|
601
|
-
merged.inlineResult = merged.inlineResult ?? true;
|
|
602
|
-
if (userInclude.includes("har")) merged.inlineHar = true;
|
|
603
|
-
|
|
604
|
-
const out = { ok: true, mode };
|
|
605
|
-
const { contentType, body, headers, status } = await postRun(config.baseUrl, config.apiKey, merged);
|
|
606
|
-
out.rawContentType = contentType || undefined;
|
|
607
|
-
|
|
608
|
-
if (status === 408) {
|
|
609
|
-
let jobId = "";
|
|
610
|
-
try {
|
|
611
|
-
jobId = JSON.parse(Buffer.from(body).toString("utf8")).job_id || "";
|
|
612
|
-
} catch {
|
|
613
|
-
// Fall through.
|
|
614
|
-
}
|
|
615
|
-
if (!jobId) {
|
|
616
|
-
return { ...out, ok: false, error: "Sync poll timed out but no job_id in 408 response" };
|
|
617
|
-
}
|
|
618
|
-
out.job_id = jobId;
|
|
619
|
-
if (returnAsync) {
|
|
620
|
-
out.status = "submitted";
|
|
621
|
-
return out;
|
|
622
|
-
}
|
|
623
|
-
return finishPolledRun(config, out, jobId, merged);
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
if (status >= 400) {
|
|
627
|
-
const text = Buffer.from(body).toString("utf8");
|
|
628
|
-
try {
|
|
629
|
-
return { ...out, ok: false, error: JSON.parse(text) };
|
|
630
|
-
} catch {
|
|
631
|
-
return { ...out, ok: false, error: `HTTP ${status}: ${text.slice(0, 500)}` };
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
if (contentType && contentType.includes("image/png")) {
|
|
636
|
-
out.rawPngBase64 = abToBase64(body);
|
|
637
|
-
out.job_id = headers.get("x-job-id") || undefined;
|
|
638
|
-
const duration = headers.get("x-duration-ms");
|
|
639
|
-
out.duration_ms = duration ? Number(duration) : undefined;
|
|
640
|
-
out.sync = true;
|
|
641
|
-
return out;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
const text = Buffer.from(body).toString("utf8");
|
|
645
|
-
const json = JSON.parse(text);
|
|
646
|
-
Object.assign(out, json);
|
|
647
|
-
out.job_id = json.job_id || json.jobId || out.job_id;
|
|
648
|
-
|
|
649
|
-
if (status === 202 && out.job_id && json.status_url) {
|
|
650
|
-
if (returnAsync) {
|
|
651
|
-
out.status = "submitted";
|
|
652
|
-
return out;
|
|
653
|
-
}
|
|
654
|
-
return finishPolledRun(config, out, out.job_id, merged);
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
if (json.status === "completed_timeout" || json.status === "completed_error") {
|
|
658
|
-
out.ok = false;
|
|
659
|
-
}
|
|
660
|
-
return out;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
async function finishPolledRun(config, out, jobId, payload) {
|
|
664
|
-
const scriptTimeoutMs = ((payload.timeout_sec ?? payload.timeoutSec ?? 60) * 1000);
|
|
665
|
-
const jobStatus = await pollJobStatus(config, jobId, scriptTimeoutMs + 30_000);
|
|
666
|
-
if (["poll_timeout", "poll_error", "failed"].includes(jobStatus.status)) {
|
|
667
|
-
out.ok = false;
|
|
668
|
-
out.status = jobStatus.status;
|
|
669
|
-
out.error = jobStatus.error || `Job ${jobStatus.status}`;
|
|
670
|
-
return out;
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
const artifacts = await fetchArtifactsAndBuild(config, jobId, payload.include || []);
|
|
674
|
-
Object.assign(out, artifacts);
|
|
675
|
-
out.job_id = jobId;
|
|
676
|
-
out.status = jobStatus.status;
|
|
677
|
-
out.duration_ms = jobStatus.duration_ms;
|
|
678
|
-
if (jobStatus.status !== "completed") {
|
|
679
|
-
out.ok = false;
|
|
680
|
-
if (jobStatus.timeout) out.timeout = jobStatus.timeout;
|
|
681
|
-
if (jobStatus.error) out.error = jobStatus.error;
|
|
682
|
-
}
|
|
683
|
-
return out;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
function numberValue(value, fallback) {
|
|
687
|
-
const n = Number(value);
|
|
688
|
-
return Number.isFinite(n) ? n : fallback;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
function normalizeServerArgs(args) {
|
|
692
|
-
return {
|
|
693
|
-
...args,
|
|
694
|
-
directory: args.directory ?? args.dir,
|
|
695
|
-
image: args.image ?? args.server_image,
|
|
696
|
-
command: args.command ?? args.server_command,
|
|
697
|
-
port: numberValue(args.port ?? args.server_port, 3000),
|
|
698
|
-
path: args.path ?? args.server_path,
|
|
699
|
-
};
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
function normalizeBuildArgs(args) {
|
|
703
|
-
return {
|
|
704
|
-
...args,
|
|
705
|
-
directory: args.directory ?? args.dir,
|
|
706
|
-
command: args.command ?? args.server_command,
|
|
707
|
-
port: numberValue(args.port ?? args.server_port, 3000),
|
|
708
|
-
path: args.path ?? args.server_path,
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
function normalizeJobId(args) {
|
|
713
|
-
return args.job_id ?? args.jobId ?? args.id;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
async function run(tool, args) {
|
|
717
|
-
if (tool === "riddle_preview") {
|
|
718
|
-
return {
|
|
719
|
-
ok: false,
|
|
720
|
-
error: "Direct Riddle Proof preview creation is not wired in this runtime bridge yet. Use remote/no-diff evidence or add generic preview support before enabling implementation previews.",
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
if (tool === "riddle_preview_delete") {
|
|
725
|
-
return { ok: false, error: "Direct Riddle Proof preview deletion is not wired in this runtime bridge yet." };
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
if (tool === "riddle_server_preview") {
|
|
729
|
-
return runLocalServerPreview(args);
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
if (tool === "riddle_server_preview_status") {
|
|
733
|
-
return { ok: false, error: "Direct Riddle Proof server preview status is not wired in this runtime bridge yet." };
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
if (tool === "riddle_build_preview") {
|
|
737
|
-
return { ok: false, error: "Direct Riddle Proof build preview is not wired in this runtime bridge yet." };
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
if (tool === "riddle_build_preview_status") {
|
|
741
|
-
return { ok: false, error: "Direct Riddle Proof build preview status is not wired in this runtime bridge yet." };
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
if (tool === "riddle_script") {
|
|
745
|
-
return runWithDefaults(args, {
|
|
746
|
-
include: TOOL_DEFAULT_INCLUDE,
|
|
747
|
-
returnAsync: !!args.async,
|
|
748
|
-
});
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
if (tool === "riddle_visual_diff") {
|
|
752
|
-
const {
|
|
753
|
-
async,
|
|
754
|
-
options,
|
|
755
|
-
stealth,
|
|
756
|
-
timeout_sec,
|
|
757
|
-
...visualDiffOptions
|
|
758
|
-
} = args;
|
|
759
|
-
const script = `return await visualDiff(${JSON.stringify(visualDiffOptions)});`;
|
|
760
|
-
return runWithDefaults({
|
|
761
|
-
url: args.url_before,
|
|
762
|
-
script,
|
|
763
|
-
options: { ...(options ?? {}), returnResult: true },
|
|
764
|
-
stealth,
|
|
765
|
-
timeout_sec: timeout_sec ?? 60,
|
|
766
|
-
async,
|
|
767
|
-
}, {
|
|
768
|
-
include: ["result", "console", "visual_diff"],
|
|
769
|
-
returnAsync: !!async,
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
if (tool === "riddle_run") {
|
|
774
|
-
return runWithDefaults(args.payload ?? args, {
|
|
775
|
-
include: ["screenshot", "console", "result"],
|
|
776
|
-
returnAsync: !!args.async,
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
throw new Error("Unsupported direct Riddle tool: " + tool);
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
async function main() {
|
|
784
|
-
const tool = process.argv[2];
|
|
785
|
-
const rawArgs = process.argv[3] || "{}";
|
|
786
|
-
if (!tool) throw new Error("Usage: riddle_core_call.mjs <tool> <json-args>");
|
|
787
|
-
const args = JSON.parse(rawArgs);
|
|
788
|
-
const result = await run(tool, args);
|
|
789
|
-
writeResult(result);
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
main().catch((err) => {
|
|
793
|
-
writeResult({
|
|
794
|
-
ok: false,
|
|
795
|
-
error: err instanceof Error ? err.message : String(err),
|
|
796
|
-
});
|
|
797
|
-
});
|
|
798
|
-
|
|
799
|
-
function writeResult(result) {
|
|
800
|
-
const encoded = JSON.stringify(result);
|
|
801
|
-
if (process.env.RIDDLE_PROOF_DIRECT_RESULT_FILE) {
|
|
802
|
-
writeFileSync(process.env.RIDDLE_PROOF_DIRECT_RESULT_FILE, encoded);
|
|
803
|
-
process.exit(0);
|
|
804
|
-
return;
|
|
805
|
-
}
|
|
806
|
-
console.log(encoded);
|
|
807
|
-
}
|
|
2
|
+
// Compatibility launcher. The network-capable implementation is owned by the
|
|
3
|
+
// hosted client package so the facade does not carry a second endpoint stack.
|
|
4
|
+
import "@riddledc/riddle-proof-riddle-client/runtime/riddle-core-call";
|