@riddledc/openclaw-riddledc 0.9.2 → 0.9.4
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/CHECKSUMS.txt +7 -2
- package/README.md +10 -0
- package/dist/chunk-SNGACMAL.js +858 -0
- package/dist/core.cjs +897 -0
- package/dist/core.d.cts +57 -0
- package/dist/core.d.ts +57 -0
- package/dist/core.js +36 -0
- package/dist/index.cjs +318 -175
- package/dist/index.js +36 -101
- package/openclaw.plugin.json +1 -1
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
configFromOpenClawApi,
|
|
3
|
+
createStaticPreview,
|
|
4
|
+
deleteStaticPreview
|
|
5
|
+
} from "./chunk-SNGACMAL.js";
|
|
6
|
+
|
|
1
7
|
// src/index.ts
|
|
2
8
|
import { Type } from "@sinclair/typebox";
|
|
3
9
|
import { writeFile, mkdir, readFile, stat, rm } from "fs/promises";
|
|
@@ -126,6 +132,21 @@ async function fetchWithRetry(url, init, timeoutMs, label, opts = {}) {
|
|
|
126
132
|
function isAlreadyStartedResponse(status, body) {
|
|
127
133
|
return status === 409 && /already in status:\s*(queued|running|complete|completed)/i.test(body);
|
|
128
134
|
}
|
|
135
|
+
function previewTimeoutToolResult(jobId, timeoutMs, lastStatusData, extras = {}) {
|
|
136
|
+
const lastStatus = lastStatusData?.status ?? "unknown";
|
|
137
|
+
const result = {
|
|
138
|
+
ok: false,
|
|
139
|
+
job_id: jobId,
|
|
140
|
+
status: lastStatus,
|
|
141
|
+
outputs: lastStatusData?.outputs || [],
|
|
142
|
+
compute_seconds: lastStatusData?.compute_seconds,
|
|
143
|
+
egress_bytes: lastStatusData?.egress_bytes,
|
|
144
|
+
error: `Job did not complete within ${timeoutMs / 1e3}s; last status was ${lastStatus}`,
|
|
145
|
+
...extras
|
|
146
|
+
};
|
|
147
|
+
if (lastStatusData?.error) result.server_error = lastStatusData.error;
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
129
150
|
async function writeArtifact(workspace, subdir, filename, content) {
|
|
130
151
|
const dir = join(workspace, "riddle", subdir);
|
|
131
152
|
await mkdir(dir, { recursive: true });
|
|
@@ -860,85 +881,8 @@ function register(api) {
|
|
|
860
881
|
framework: Type.Optional(Type.String({ description: "Framework hint: 'spa' (default) or 'static'" }))
|
|
861
882
|
}),
|
|
862
883
|
async execute(_id, params) {
|
|
863
|
-
const
|
|
864
|
-
|
|
865
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: "Missing Riddle API key." }, null, 2) }] };
|
|
866
|
-
}
|
|
867
|
-
assertAllowedBaseUrl(baseUrl);
|
|
868
|
-
const dir = params.directory;
|
|
869
|
-
if (!dir || typeof dir !== "string") throw new Error("directory must be an absolute path");
|
|
870
|
-
try {
|
|
871
|
-
const st = await stat(dir);
|
|
872
|
-
if (!st.isDirectory()) throw new Error(`Not a directory: ${dir}`);
|
|
873
|
-
} catch (e) {
|
|
874
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: `Cannot access directory: ${e.message}` }, null, 2) }] };
|
|
875
|
-
}
|
|
876
|
-
const endpoint = baseUrl.replace(/\/$/, "");
|
|
877
|
-
let createRes;
|
|
878
|
-
try {
|
|
879
|
-
createRes = await fetchWithRetry(`${endpoint}/v1/preview`, {
|
|
880
|
-
method: "POST",
|
|
881
|
-
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
882
|
-
body: JSON.stringify({ framework: params.framework || "spa" })
|
|
883
|
-
}, PREVIEW_REQUEST_TIMEOUT_MS, "preview create");
|
|
884
|
-
} catch (e) {
|
|
885
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: `Create failed: ${describeError(e)}` }, null, 2) }] };
|
|
886
|
-
}
|
|
887
|
-
if (!createRes.ok) {
|
|
888
|
-
const err = await createRes.text();
|
|
889
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: `Create failed: HTTP ${createRes.status} ${err}` }, null, 2) }] };
|
|
890
|
-
}
|
|
891
|
-
const created = await createRes.json();
|
|
892
|
-
const tarball = `/tmp/riddle-preview-${created.id}.tar.gz`;
|
|
893
|
-
try {
|
|
894
|
-
await execFile("tar", ["czf", tarball, "-C", dir, "."], { timeout: 6e4 });
|
|
895
|
-
const tarData = await readFile(tarball);
|
|
896
|
-
let uploadRes;
|
|
897
|
-
try {
|
|
898
|
-
uploadRes = await fetchWithRetry(created.upload_url, {
|
|
899
|
-
method: "PUT",
|
|
900
|
-
headers: { "Content-Type": "application/gzip" },
|
|
901
|
-
body: tarData
|
|
902
|
-
}, PREVIEW_UPLOAD_TIMEOUT_MS, "preview upload");
|
|
903
|
-
} catch (e) {
|
|
904
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, id: created.id, error: `Upload failed: ${describeError(e)}` }, null, 2) }] };
|
|
905
|
-
}
|
|
906
|
-
if (!uploadRes.ok) {
|
|
907
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, id: created.id, error: `Upload failed: HTTP ${uploadRes.status}` }, null, 2) }] };
|
|
908
|
-
}
|
|
909
|
-
} finally {
|
|
910
|
-
try {
|
|
911
|
-
await rm(tarball, { force: true });
|
|
912
|
-
} catch {
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
let publishRes;
|
|
916
|
-
try {
|
|
917
|
-
publishRes = await fetchWithTimeout(`${endpoint}/v1/preview/${created.id}/publish`, {
|
|
918
|
-
method: "POST",
|
|
919
|
-
headers: { Authorization: `Bearer ${apiKey}` }
|
|
920
|
-
}, PREVIEW_REQUEST_TIMEOUT_MS, "preview publish");
|
|
921
|
-
} catch (e) {
|
|
922
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, id: created.id, error: `Publish failed: ${describeError(e)}` }, null, 2) }] };
|
|
923
|
-
}
|
|
924
|
-
if (!publishRes.ok) {
|
|
925
|
-
const err = await publishRes.text();
|
|
926
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, id: created.id, error: `Publish failed: HTTP ${publishRes.status} ${err}` }, null, 2) }] };
|
|
927
|
-
}
|
|
928
|
-
const published = await publishRes.json();
|
|
929
|
-
return {
|
|
930
|
-
content: [{
|
|
931
|
-
type: "text",
|
|
932
|
-
text: JSON.stringify({
|
|
933
|
-
ok: true,
|
|
934
|
-
id: published.id,
|
|
935
|
-
preview_url: published.preview_url,
|
|
936
|
-
file_count: published.file_count,
|
|
937
|
-
total_bytes: published.total_bytes,
|
|
938
|
-
expires_at: created.expires_at
|
|
939
|
-
}, null, 2)
|
|
940
|
-
}]
|
|
941
|
-
};
|
|
884
|
+
const result = await createStaticPreview(configFromOpenClawApi(api), params);
|
|
885
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
942
886
|
}
|
|
943
887
|
},
|
|
944
888
|
{ optional: true }
|
|
@@ -951,26 +895,8 @@ function register(api) {
|
|
|
951
895
|
id: Type.String({ description: "Preview ID (e.g. pv_a1b2c3d4)" })
|
|
952
896
|
}),
|
|
953
897
|
async execute(_id, params) {
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: "Missing Riddle API key." }, null, 2) }] };
|
|
957
|
-
}
|
|
958
|
-
assertAllowedBaseUrl(baseUrl);
|
|
959
|
-
let res;
|
|
960
|
-
try {
|
|
961
|
-
res = await fetchWithTimeout(`${baseUrl.replace(/\/$/, "")}/v1/preview/${params.id}`, {
|
|
962
|
-
method: "DELETE",
|
|
963
|
-
headers: { Authorization: `Bearer ${apiKey}` }
|
|
964
|
-
}, PREVIEW_REQUEST_TIMEOUT_MS, "preview delete");
|
|
965
|
-
} catch (e) {
|
|
966
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: `Delete failed: ${describeError(e)}` }, null, 2) }] };
|
|
967
|
-
}
|
|
968
|
-
if (!res.ok) {
|
|
969
|
-
const err = await res.text();
|
|
970
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: `Delete failed: HTTP ${res.status} ${err}` }, null, 2) }] };
|
|
971
|
-
}
|
|
972
|
-
const data = await res.json();
|
|
973
|
-
return { content: [{ type: "text", text: JSON.stringify({ ok: true, deleted: true, files_removed: data.files_removed }, null, 2) }] };
|
|
898
|
+
const result = await deleteStaticPreview(configFromOpenClawApi(api), params.id);
|
|
899
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
974
900
|
}
|
|
975
901
|
},
|
|
976
902
|
{ optional: true }
|
|
@@ -1117,6 +1043,7 @@ function register(api) {
|
|
|
1117
1043
|
const timeoutMs = ((params.timeout || 120) + 60) * 1e3;
|
|
1118
1044
|
const pollStart = Date.now();
|
|
1119
1045
|
const POLL_INTERVAL = 3e3;
|
|
1046
|
+
let lastStatusData = null;
|
|
1120
1047
|
while (Date.now() - pollStart < timeoutMs) {
|
|
1121
1048
|
let statusRes;
|
|
1122
1049
|
try {
|
|
@@ -1130,6 +1057,7 @@ function register(api) {
|
|
|
1130
1057
|
return { content: [{ type: "text", text: JSON.stringify({ ok: false, job_id: created.job_id, error: `Poll failed: HTTP ${statusRes.status}` }, null, 2) }] };
|
|
1131
1058
|
}
|
|
1132
1059
|
const statusData = await statusRes.json();
|
|
1060
|
+
lastStatusData = statusData;
|
|
1133
1061
|
if (statusData.status === "complete" || statusData.status === "completed" || statusData.status === "failed") {
|
|
1134
1062
|
const result = {
|
|
1135
1063
|
ok: statusData.status === "complete" || statusData.status === "completed",
|
|
@@ -1161,7 +1089,7 @@ function register(api) {
|
|
|
1161
1089
|
}
|
|
1162
1090
|
await new Promise((r) => setTimeout(r, POLL_INTERVAL));
|
|
1163
1091
|
}
|
|
1164
|
-
return { content: [{ type: "text", text: JSON.stringify(
|
|
1092
|
+
return { content: [{ type: "text", text: JSON.stringify(previewTimeoutToolResult(created.job_id, timeoutMs, lastStatusData), null, 2) }] };
|
|
1165
1093
|
}
|
|
1166
1094
|
},
|
|
1167
1095
|
{ optional: true }
|
|
@@ -1317,6 +1245,7 @@ function register(api) {
|
|
|
1317
1245
|
const timeoutMs = ((params.timeout || 180) + 120) * 1e3;
|
|
1318
1246
|
const pollStart = Date.now();
|
|
1319
1247
|
const POLL_INTERVAL = 3e3;
|
|
1248
|
+
let lastStatusData = null;
|
|
1320
1249
|
while (Date.now() - pollStart < timeoutMs) {
|
|
1321
1250
|
let statusRes;
|
|
1322
1251
|
try {
|
|
@@ -1330,6 +1259,7 @@ function register(api) {
|
|
|
1330
1259
|
return { content: [{ type: "text", text: JSON.stringify({ ok: false, job_id: created.job_id, error: `Poll failed: HTTP ${statusRes.status}` }, null, 2) }] };
|
|
1331
1260
|
}
|
|
1332
1261
|
const statusData = await statusRes.json();
|
|
1262
|
+
lastStatusData = statusData;
|
|
1333
1263
|
if (statusData.status === "complete" || statusData.status === "completed" || statusData.status === "failed") {
|
|
1334
1264
|
const result = {
|
|
1335
1265
|
ok: statusData.status === "complete" || statusData.status === "completed",
|
|
@@ -1365,7 +1295,12 @@ function register(api) {
|
|
|
1365
1295
|
}
|
|
1366
1296
|
await new Promise((r) => setTimeout(r, POLL_INTERVAL));
|
|
1367
1297
|
}
|
|
1368
|
-
return { content: [{ type: "text", text: JSON.stringify(
|
|
1298
|
+
return { content: [{ type: "text", text: JSON.stringify(previewTimeoutToolResult(created.job_id, timeoutMs, lastStatusData, {
|
|
1299
|
+
build_duration_ms: lastStatusData?.build_duration_ms,
|
|
1300
|
+
...lastStatusData?.build_log ? { build_log: lastStatusData.build_log } : {},
|
|
1301
|
+
...lastStatusData?.container_log ? { container_log: lastStatusData.container_log } : {},
|
|
1302
|
+
...lastStatusData?.audit ? { audit: lastStatusData.audit } : {}
|
|
1303
|
+
}), null, 2) }] };
|
|
1369
1304
|
}
|
|
1370
1305
|
},
|
|
1371
1306
|
{ optional: true }
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "openclaw-riddledc",
|
|
3
3
|
"name": "Riddle",
|
|
4
4
|
"description": "Riddle (riddledc.com) hosted browser API tools for OpenClaw agents.",
|
|
5
|
-
"version": "0.9.
|
|
5
|
+
"version": "0.9.4",
|
|
6
6
|
"notes": "0.8.0: Added riddle_build_preview for Dockerfile-based builds with image caching.",
|
|
7
7
|
"type": "plugin",
|
|
8
8
|
"bundledSkills": [],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riddledc/openclaw-riddledc",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "OpenClaw integration package for RiddleDC (no secrets).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "RiddleDC",
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
19
|
"import": "./dist/index.js",
|
|
20
20
|
"require": "./dist/index.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./core": {
|
|
23
|
+
"types": "./dist/core.d.ts",
|
|
24
|
+
"import": "./dist/core.js",
|
|
25
|
+
"require": "./dist/core.cjs"
|
|
21
26
|
}
|
|
22
27
|
},
|
|
23
28
|
"files": [
|
|
@@ -45,7 +50,7 @@
|
|
|
45
50
|
"typescript": "^5.4.5"
|
|
46
51
|
},
|
|
47
52
|
"scripts": {
|
|
48
|
-
"build": "npm run sync:openclaw-plugin-version && tsup src/index.ts --format cjs,esm --dts --out-dir dist",
|
|
53
|
+
"build": "npm run sync:openclaw-plugin-version && tsup src/index.ts src/core.ts --format cjs,esm --dts --out-dir dist",
|
|
49
54
|
"clean": "rm -rf dist",
|
|
50
55
|
"lint": "echo 'lint: (not configured)'",
|
|
51
56
|
"test": "echo 'test: (not configured)'",
|