notte-sdk 1.9.4 → 1.9.6
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 +3 -1
- package/dist/index.d.mts +324 -42
- package/dist/index.d.ts +324 -42
- package/dist/index.js +280 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +276 -54
- package/dist/index.mjs.map +1 -1
- package/dist/proxy/core.js +4 -0
- package/dist/proxy/core.js.map +1 -1
- package/dist/proxy/core.mjs +4 -0
- package/dist/proxy/core.mjs.map +1 -1
- package/dist/proxy/next.js +4 -0
- package/dist/proxy/next.js.map +1 -1
- package/dist/proxy/next.mjs +4 -0
- package/dist/proxy/next.mjs.map +1 -1
- package/package.json +13 -6
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var SDK_VERSION = true ? "1.9.
|
|
2
|
+
var SDK_VERSION = true ? "1.9.6" : "dev";
|
|
3
3
|
var SDK_PACKAGE_NAME = true ? "notte-sdk" : "notte-sdk";
|
|
4
4
|
|
|
5
5
|
// src/version-check.ts
|
|
@@ -1196,6 +1196,20 @@ var functionRunUpdateMetadata = (options) => (options.client ?? client).patch({
|
|
|
1196
1196
|
...options.headers
|
|
1197
1197
|
}
|
|
1198
1198
|
});
|
|
1199
|
+
var prepareRunPayloadUpload = (options) => (options.client ?? client).post({
|
|
1200
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1201
|
+
url: "/functions/{function_id}/runs/{run_id}/payloads/{field}/upload",
|
|
1202
|
+
...options,
|
|
1203
|
+
headers: {
|
|
1204
|
+
"Content-Type": "application/json",
|
|
1205
|
+
...options.headers
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
var downloadRunPayload = (options) => (options.client ?? client).get({
|
|
1209
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1210
|
+
url: "/functions/{function_id}/runs/{run_id}/payloads/{field}",
|
|
1211
|
+
...options
|
|
1212
|
+
});
|
|
1199
1213
|
var listFunctionRunsByFunctionId = (options) => (options.client ?? client).get({
|
|
1200
1214
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1201
1215
|
url: "/functions/{function_id}/runs",
|
|
@@ -1473,6 +1487,7 @@ var connectLinkSubmit = (options) => (options.client ?? client).post({
|
|
|
1473
1487
|
});
|
|
1474
1488
|
var connectLinkStatus = (options) => (options.client ?? client).get({ url: "/managed-auth/connect-links/status", ...options });
|
|
1475
1489
|
var improvePrompt = (options) => (options.client ?? client).post({
|
|
1490
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1476
1491
|
url: "/prompts/improve",
|
|
1477
1492
|
...options,
|
|
1478
1493
|
headers: {
|
|
@@ -1481,6 +1496,7 @@ var improvePrompt = (options) => (options.client ?? client).post({
|
|
|
1481
1496
|
}
|
|
1482
1497
|
});
|
|
1483
1498
|
var nudgePrompt = (options) => (options.client ?? client).post({
|
|
1499
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1484
1500
|
url: "/prompts/nudge",
|
|
1485
1501
|
...options,
|
|
1486
1502
|
headers: {
|
|
@@ -1833,8 +1849,8 @@ function createResources(client2, getApiKey) {
|
|
|
1833
1849
|
return response.data;
|
|
1834
1850
|
},
|
|
1835
1851
|
/** sessionDebugInfo: /sessions/{session_id}/debug. Returns the API response body. */
|
|
1836
|
-
debugInfo: async (sessionId,
|
|
1837
|
-
const response = await sessionDebugInfo({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }
|
|
1852
|
+
debugInfo: async (sessionId, requestOptions = {}) => {
|
|
1853
|
+
const response = await sessionDebugInfo({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId } });
|
|
1838
1854
|
return response.data;
|
|
1839
1855
|
},
|
|
1840
1856
|
/** deleteSessionFile: /sessions/{session_id}/files/{file_id}. Returns the API response body. */
|
|
@@ -1883,8 +1899,8 @@ function createResources(client2, getApiKey) {
|
|
|
1883
1899
|
return response.data;
|
|
1884
1900
|
},
|
|
1885
1901
|
/** sessionOffset: /sessions/{session_id}/offset. Returns the API response body. */
|
|
1886
|
-
offset: async (sessionId, requestOptions = {}) => {
|
|
1887
|
-
const response = await sessionOffset({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId } });
|
|
1902
|
+
offset: async (sessionId, query = void 0, requestOptions = {}) => {
|
|
1903
|
+
const response = await sessionOffset({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, query });
|
|
1888
1904
|
return response.data;
|
|
1889
1905
|
},
|
|
1890
1906
|
/** pageScreenshot: /sessions/{session_id}/page/screenshot. Returns the API response body. */
|
|
@@ -1976,6 +1992,11 @@ function createResources(client2, getApiKey) {
|
|
|
1976
1992
|
const response = await functionScheduleDelete({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "function_id": functionId } });
|
|
1977
1993
|
return response.data;
|
|
1978
1994
|
},
|
|
1995
|
+
/** downloadRunPayload: /functions/{function_id}/runs/{run_id}/payloads/{field}. Returns the API response body. */
|
|
1996
|
+
downloadRunPayload: async (functionId, runId, field, requestOptions = {}) => {
|
|
1997
|
+
const response = await downloadRunPayload({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "function_id": functionId, "run_id": runId, "field": field } });
|
|
1998
|
+
return response.data;
|
|
1999
|
+
},
|
|
1979
2000
|
/** functionDownloadUrl: /functions/{function_id}. Returns the API response body. */
|
|
1980
2001
|
downloadUrl: async (functionId, query = void 0, requestOptions = {}) => {
|
|
1981
2002
|
const response = await functionDownloadUrl({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "function_id": functionId }, query });
|
|
@@ -2001,14 +2022,19 @@ function createResources(client2, getApiKey) {
|
|
|
2001
2022
|
const response = await functionMetadataUpdate({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "function_id": functionId }, body });
|
|
2002
2023
|
return response.data;
|
|
2003
2024
|
},
|
|
2025
|
+
/** prepareRunPayloadUpload: /functions/{function_id}/runs/{run_id}/payloads/{field}/upload. Returns the API response body. */
|
|
2026
|
+
prepareRunPayloadUpload: async (functionId, runId, field, body, requestOptions = {}) => {
|
|
2027
|
+
const response = await prepareRunPayloadUpload({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "function_id": functionId, "run_id": runId, "field": field }, body });
|
|
2028
|
+
return response.data;
|
|
2029
|
+
},
|
|
2004
2030
|
/** functionRollback: /functions/{function_id}/rollback. Returns the API response body. */
|
|
2005
2031
|
rollback: async (functionId, body, query = void 0, requestOptions = {}) => {
|
|
2006
2032
|
const response = await functionRollback({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "function_id": functionId }, body, query });
|
|
2007
2033
|
return response.data;
|
|
2008
2034
|
},
|
|
2009
2035
|
/** functionRunGetMetadata: /functions/{function_id}/runs/{run_id}. Returns the API response body. */
|
|
2010
|
-
runGetMetadata: async (functionId, runId, requestOptions = {}) => {
|
|
2011
|
-
const response = await functionRunGetMetadata({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "function_id": functionId, "run_id": runId } });
|
|
2036
|
+
runGetMetadata: async (functionId, runId, requestOptions = {}, query = void 0) => {
|
|
2037
|
+
const response = await functionRunGetMetadata({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "function_id": functionId, "run_id": runId }, query });
|
|
2012
2038
|
return response.data;
|
|
2013
2039
|
},
|
|
2014
2040
|
/** functionRunStart: /functions/{function_id}/runs/start. Returns the API response body. */
|
|
@@ -2232,6 +2258,12 @@ async function executeWithCaptcha(action, budgetSeconds, request) {
|
|
|
2232
2258
|
if (status.state === "cancelled" && status.cancel_reason === "navigation" && original) {
|
|
2233
2259
|
return { ...original, captcha: status };
|
|
2234
2260
|
}
|
|
2261
|
+
if (status.state === "cancelled" && status.cancel_reason === "navigation" && action.type === "wait" && result.action_executed === false) {
|
|
2262
|
+
params = { captcha_timeout_seconds: remaining() };
|
|
2263
|
+
requestAction = action;
|
|
2264
|
+
await pause();
|
|
2265
|
+
continue;
|
|
2266
|
+
}
|
|
2235
2267
|
if (status.state === "failed" || status.state === "cancelled") {
|
|
2236
2268
|
return failure(status.message || `CAPTCHA ${status.state}`, `captcha_${status.state}`);
|
|
2237
2269
|
}
|
|
@@ -2557,6 +2589,126 @@ function isNotFound(error) {
|
|
|
2557
2589
|
return typeof error === "object" && error !== null && error.code === "ENOENT";
|
|
2558
2590
|
}
|
|
2559
2591
|
|
|
2592
|
+
// src/utils.ts
|
|
2593
|
+
import { spawn } from "child_process";
|
|
2594
|
+
function formatError(error) {
|
|
2595
|
+
if (typeof error === "object" && error !== null) {
|
|
2596
|
+
if ("message" in error && typeof error.message === "string") {
|
|
2597
|
+
return error.message;
|
|
2598
|
+
}
|
|
2599
|
+
try {
|
|
2600
|
+
return JSON.stringify(error, null, 2);
|
|
2601
|
+
} catch {
|
|
2602
|
+
return String(error);
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
if (error instanceof Error) {
|
|
2606
|
+
return error.message;
|
|
2607
|
+
}
|
|
2608
|
+
return String(error);
|
|
2609
|
+
}
|
|
2610
|
+
function openBrowser(url) {
|
|
2611
|
+
const platform = process.platform;
|
|
2612
|
+
let command;
|
|
2613
|
+
let args;
|
|
2614
|
+
if (platform === "darwin") {
|
|
2615
|
+
command = "open";
|
|
2616
|
+
args = [url];
|
|
2617
|
+
} else if (platform === "win32") {
|
|
2618
|
+
command = "rundll32";
|
|
2619
|
+
args = ["url.dll,FileProtocolHandler", url];
|
|
2620
|
+
} else {
|
|
2621
|
+
command = "xdg-open";
|
|
2622
|
+
args = [url];
|
|
2623
|
+
}
|
|
2624
|
+
const child = spawn(command, args, {
|
|
2625
|
+
detached: true,
|
|
2626
|
+
stdio: "ignore"
|
|
2627
|
+
});
|
|
2628
|
+
child.on("error", () => {
|
|
2629
|
+
});
|
|
2630
|
+
child.unref();
|
|
2631
|
+
}
|
|
2632
|
+
var SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
2633
|
+
"items",
|
|
2634
|
+
"additionalItems",
|
|
2635
|
+
"additionalProperties",
|
|
2636
|
+
"contains",
|
|
2637
|
+
"propertyNames",
|
|
2638
|
+
"not",
|
|
2639
|
+
"if",
|
|
2640
|
+
"then",
|
|
2641
|
+
"else",
|
|
2642
|
+
"unevaluatedItems",
|
|
2643
|
+
"unevaluatedProperties"
|
|
2644
|
+
]);
|
|
2645
|
+
var SCHEMA_ARRAY_KEYWORDS = /* @__PURE__ */ new Set(["anyOf", "oneOf", "allOf", "prefixItems"]);
|
|
2646
|
+
var TYPE_SCOPED_KEYWORDS = /* @__PURE__ */ new Set([
|
|
2647
|
+
"items",
|
|
2648
|
+
"prefixItems",
|
|
2649
|
+
"additionalItems",
|
|
2650
|
+
"contains",
|
|
2651
|
+
"unevaluatedItems",
|
|
2652
|
+
"properties",
|
|
2653
|
+
"patternProperties",
|
|
2654
|
+
"required",
|
|
2655
|
+
"additionalProperties",
|
|
2656
|
+
"propertyNames",
|
|
2657
|
+
"unevaluatedProperties",
|
|
2658
|
+
"format"
|
|
2659
|
+
]);
|
|
2660
|
+
var SCHEMA_MAP_KEYWORDS = /* @__PURE__ */ new Set(["properties", "patternProperties", "$defs", "definitions", "dependentSchemas"]);
|
|
2661
|
+
function normalizeJsonSchema(schema) {
|
|
2662
|
+
if (schema === null || typeof schema !== "object" || Array.isArray(schema)) return schema;
|
|
2663
|
+
const out = {};
|
|
2664
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
2665
|
+
if (SCHEMA_KEYWORDS.has(key) || key === "items" && Array.isArray(value)) {
|
|
2666
|
+
out[key] = Array.isArray(value) ? value.map(normalizeJsonSchema) : normalizeJsonSchema(value);
|
|
2667
|
+
} else if (SCHEMA_ARRAY_KEYWORDS.has(key) && Array.isArray(value)) {
|
|
2668
|
+
out[key] = value.map(normalizeJsonSchema);
|
|
2669
|
+
} else if (SCHEMA_MAP_KEYWORDS.has(key) && value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
2670
|
+
out[key] = Object.fromEntries(
|
|
2671
|
+
Object.entries(value).map(([name, sub]) => [name, normalizeJsonSchema(sub)])
|
|
2672
|
+
);
|
|
2673
|
+
} else {
|
|
2674
|
+
out[key] = value;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
if (Array.isArray(out.type)) {
|
|
2678
|
+
const { type, anyOf: existing, ...rest } = out;
|
|
2679
|
+
const types = type;
|
|
2680
|
+
const parent = {};
|
|
2681
|
+
const scoped = {};
|
|
2682
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
2683
|
+
(TYPE_SCOPED_KEYWORDS.has(key) ? scoped : parent)[key] = value;
|
|
2684
|
+
}
|
|
2685
|
+
const typed = (t) => t === "null" ? { type: t } : { type: t, ...scoped };
|
|
2686
|
+
let branches;
|
|
2687
|
+
if (Array.isArray(existing)) {
|
|
2688
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2689
|
+
branches = [];
|
|
2690
|
+
const push = (b) => {
|
|
2691
|
+
const key = JSON.stringify(b);
|
|
2692
|
+
if (!seen.has(key)) {
|
|
2693
|
+
seen.add(key);
|
|
2694
|
+
branches.push(b);
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
for (const branch of existing) {
|
|
2698
|
+
if (typeof branch.type === "string") {
|
|
2699
|
+
if (types.includes(branch.type)) push(branch.type === "null" ? branch : { ...scoped, ...branch });
|
|
2700
|
+
} else {
|
|
2701
|
+
for (const t of types) push({ ...typed(t), ...branch });
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
} else {
|
|
2705
|
+
branches = types.map(typed);
|
|
2706
|
+
}
|
|
2707
|
+
return { ...parent, anyOf: branches };
|
|
2708
|
+
}
|
|
2709
|
+
return out;
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2560
2712
|
// src/scrape.ts
|
|
2561
2713
|
function isZodSchema(value) {
|
|
2562
2714
|
return typeof value === "object" && value !== null && typeof value.parse === "function";
|
|
@@ -2572,7 +2724,7 @@ async function buildScrapeBody(options) {
|
|
|
2572
2724
|
body.response_format = json_schema;
|
|
2573
2725
|
} else {
|
|
2574
2726
|
const { z: z2 } = await import("zod");
|
|
2575
|
-
body.response_format = z2.toJSONSchema(response_format);
|
|
2727
|
+
body.response_format = normalizeJsonSchema(z2.toJSONSchema(response_format));
|
|
2576
2728
|
}
|
|
2577
2729
|
} else if (response_format) {
|
|
2578
2730
|
body.response_format = response_format;
|
|
@@ -2609,47 +2761,6 @@ function processScrapeResponse(scrapeResponse, options) {
|
|
|
2609
2761
|
return scrapeResponse.markdown;
|
|
2610
2762
|
}
|
|
2611
2763
|
|
|
2612
|
-
// src/utils.ts
|
|
2613
|
-
import { spawn } from "child_process";
|
|
2614
|
-
function formatError(error) {
|
|
2615
|
-
if (typeof error === "object" && error !== null) {
|
|
2616
|
-
if ("message" in error && typeof error.message === "string") {
|
|
2617
|
-
return error.message;
|
|
2618
|
-
}
|
|
2619
|
-
try {
|
|
2620
|
-
return JSON.stringify(error, null, 2);
|
|
2621
|
-
} catch {
|
|
2622
|
-
return String(error);
|
|
2623
|
-
}
|
|
2624
|
-
}
|
|
2625
|
-
if (error instanceof Error) {
|
|
2626
|
-
return error.message;
|
|
2627
|
-
}
|
|
2628
|
-
return String(error);
|
|
2629
|
-
}
|
|
2630
|
-
function openBrowser(url) {
|
|
2631
|
-
const platform = process.platform;
|
|
2632
|
-
let command;
|
|
2633
|
-
let args;
|
|
2634
|
-
if (platform === "darwin") {
|
|
2635
|
-
command = "open";
|
|
2636
|
-
args = [url];
|
|
2637
|
-
} else if (platform === "win32") {
|
|
2638
|
-
command = "rundll32";
|
|
2639
|
-
args = ["url.dll,FileProtocolHandler", url];
|
|
2640
|
-
} else {
|
|
2641
|
-
command = "xdg-open";
|
|
2642
|
-
args = [url];
|
|
2643
|
-
}
|
|
2644
|
-
const child = spawn(command, args, {
|
|
2645
|
-
detached: true,
|
|
2646
|
-
stdio: "ignore"
|
|
2647
|
-
});
|
|
2648
|
-
child.on("error", () => {
|
|
2649
|
-
});
|
|
2650
|
-
child.unref();
|
|
2651
|
-
}
|
|
2652
|
-
|
|
2653
2764
|
// src/session.ts
|
|
2654
2765
|
var SESSION_START_TRIES = 3;
|
|
2655
2766
|
var CLUSTER_OVERLOAD_RETRY_DELAY_MS = 3e4;
|
|
@@ -3399,7 +3510,7 @@ function prepareAgentRequest(data) {
|
|
|
3399
3510
|
const apiData = { ...data };
|
|
3400
3511
|
const rf = data.response_format;
|
|
3401
3512
|
if (rf && typeof rf.parse === "function" && typeof rf.safeParse === "function") {
|
|
3402
|
-
apiData.response_format = z.toJSONSchema(rf);
|
|
3513
|
+
apiData.response_format = normalizeJsonSchema(z.toJSONSchema(rf));
|
|
3403
3514
|
return { apiData, zodSchema: rf };
|
|
3404
3515
|
}
|
|
3405
3516
|
return { apiData, zodSchema: null };
|
|
@@ -4445,6 +4556,90 @@ function decryptFernet(token, key) {
|
|
|
4445
4556
|
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
4446
4557
|
}
|
|
4447
4558
|
|
|
4559
|
+
// src/run-payloads.ts
|
|
4560
|
+
import { createHash } from "crypto";
|
|
4561
|
+
var INLINE_FIELD_BYTES = 1024 * 1024;
|
|
4562
|
+
var MAX_PAYLOAD_BYTES = 256 * 1024 * 1024;
|
|
4563
|
+
async function offloadRunPayloads(client2, path, fields) {
|
|
4564
|
+
const data = { ...fields };
|
|
4565
|
+
const references = {};
|
|
4566
|
+
if (data.result != null && typeof data.result !== "string") data.result = JSON.stringify(data.result);
|
|
4567
|
+
for (const field of ["result", "logs", "variables"]) {
|
|
4568
|
+
if (data[field] == null) continue;
|
|
4569
|
+
const payload = Buffer.from(JSON.stringify(data[field]), "utf8");
|
|
4570
|
+
if (payload.length > MAX_PAYLOAD_BYTES) throw new Error(`Function run ${field} exceeds the payload limit`);
|
|
4571
|
+
if (payload.length <= INLINE_FIELD_BYTES) continue;
|
|
4572
|
+
const checksum = createHash("sha256").update(payload).digest("base64");
|
|
4573
|
+
const prepared = await client2.post({
|
|
4574
|
+
url: "/functions/{function_id}/runs/{run_id}/payloads/{field}/upload",
|
|
4575
|
+
path: { ...path, field },
|
|
4576
|
+
body: { size_bytes: payload.length, sha256: checksum },
|
|
4577
|
+
headers: { "Content-Type": "application/json" },
|
|
4578
|
+
throwOnError: true
|
|
4579
|
+
});
|
|
4580
|
+
const upload = prepared.data;
|
|
4581
|
+
if (upload.reference.size_bytes !== payload.length || upload.reference.sha256 !== checksum) {
|
|
4582
|
+
throw new Error("Run payload upload reference does not match the local payload");
|
|
4583
|
+
}
|
|
4584
|
+
if (new URL(upload.url).protocol !== "https:") throw new Error("Invalid run payload URL");
|
|
4585
|
+
const response = await fetch(upload.url, {
|
|
4586
|
+
method: "PUT",
|
|
4587
|
+
body: payload,
|
|
4588
|
+
headers: upload.headers,
|
|
4589
|
+
redirect: "error",
|
|
4590
|
+
signal: AbortSignal.timeout(3e5)
|
|
4591
|
+
});
|
|
4592
|
+
await response.body?.cancel();
|
|
4593
|
+
if (!response.ok) throw new Error(`Run payload upload failed (${response.status})`);
|
|
4594
|
+
references[field] = upload.reference;
|
|
4595
|
+
if (field === "result" && typeof data.result === "string") data.result_preview = data.result.slice(0, 16e3);
|
|
4596
|
+
delete data[field];
|
|
4597
|
+
}
|
|
4598
|
+
if (Object.keys(references).length) data.payloads = references;
|
|
4599
|
+
return data;
|
|
4600
|
+
}
|
|
4601
|
+
async function resolveRunPayloads(input) {
|
|
4602
|
+
const run = { ...input };
|
|
4603
|
+
for (const [field, reference] of Object.entries(run.payloads ?? {})) {
|
|
4604
|
+
if (!["result", "logs", "variables"].includes(field)) throw new Error("Unknown run payload field");
|
|
4605
|
+
if (!Number.isSafeInteger(reference.size_bytes) || reference.size_bytes <= 0 || reference.size_bytes > 256 * 1024 * 1024) {
|
|
4606
|
+
throw new Error("Invalid run payload size");
|
|
4607
|
+
}
|
|
4608
|
+
const url = run.payload_urls?.[field];
|
|
4609
|
+
if (!url || new URL(url).protocol !== "https:") throw new Error("Invalid run payload URL");
|
|
4610
|
+
const response = await fetch(url, { redirect: "error", signal: AbortSignal.timeout(3e5) });
|
|
4611
|
+
if (!response.ok || !response.body) throw new Error(`Run payload download failed (${response.status})`);
|
|
4612
|
+
const reader = response.body.getReader();
|
|
4613
|
+
const chunks = [];
|
|
4614
|
+
const hash = createHash("sha256");
|
|
4615
|
+
let size = 0;
|
|
4616
|
+
try {
|
|
4617
|
+
while (true) {
|
|
4618
|
+
const { done, value: value2 } = await reader.read();
|
|
4619
|
+
if (done) break;
|
|
4620
|
+
size += value2.length;
|
|
4621
|
+
if (size > reference.size_bytes) throw new Error("Run payload exceeds its declared size");
|
|
4622
|
+
hash.update(value2);
|
|
4623
|
+
chunks.push(value2);
|
|
4624
|
+
}
|
|
4625
|
+
} finally {
|
|
4626
|
+
await reader.cancel();
|
|
4627
|
+
reader.releaseLock();
|
|
4628
|
+
}
|
|
4629
|
+
if (size !== reference.size_bytes || hash.digest("base64") !== reference.sha256) {
|
|
4630
|
+
throw new Error("Run payload failed size/checksum verification");
|
|
4631
|
+
}
|
|
4632
|
+
const value = JSON.parse(Buffer.concat(chunks, size).toString("utf8"));
|
|
4633
|
+
if (field === "result" && value !== null && typeof value !== "string") throw new Error("Invalid stored result");
|
|
4634
|
+
if (field === "logs" && (!Array.isArray(value) || !value.every((line) => typeof line === "string"))) throw new Error("Invalid stored logs");
|
|
4635
|
+
if (field === "variables" && value !== null && (typeof value !== "object" || Array.isArray(value))) throw new Error("Invalid stored variables");
|
|
4636
|
+
Object.assign(run, { [field]: value });
|
|
4637
|
+
}
|
|
4638
|
+
delete run.payloads;
|
|
4639
|
+
delete run.payload_urls;
|
|
4640
|
+
return run;
|
|
4641
|
+
}
|
|
4642
|
+
|
|
4448
4643
|
// src/functions.ts
|
|
4449
4644
|
var DOWNLOAD_TIMEOUT_MS = 3e4;
|
|
4450
4645
|
var FUNCTION_RUN_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -4672,10 +4867,35 @@ var NotteFunction = class {
|
|
|
4672
4867
|
*/
|
|
4673
4868
|
async getRun(functionRunId) {
|
|
4674
4869
|
const functionId = await this.ensureInitialized();
|
|
4675
|
-
const response = await
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4870
|
+
const response = await this.client.getClient().get({
|
|
4871
|
+
url: "/functions/{function_id}/runs/{run_id}",
|
|
4872
|
+
path: { function_id: functionId, run_id: functionRunId },
|
|
4873
|
+
query: { payload_mode: "references" },
|
|
4874
|
+
throwOnError: true
|
|
4875
|
+
});
|
|
4876
|
+
return resolveRunPayloads(response.data);
|
|
4877
|
+
}
|
|
4878
|
+
/**
|
|
4879
|
+
* Update a run, uploading fields above 1 MiB directly to private storage.
|
|
4880
|
+
*
|
|
4881
|
+
* @param functionRunId - ID of a run belonging to this function.
|
|
4882
|
+
* @param fields - Status and fields to update. Omitted fields remain unchanged.
|
|
4883
|
+
* @returns Confirmation of the persisted update.
|
|
4884
|
+
* @throws Error if a field exceeds 256 MiB or an upload fails; the update is not finalized.
|
|
4885
|
+
* @example
|
|
4886
|
+
* await fn.updateRun(runId, { status: 'closed', result: { records } });
|
|
4887
|
+
*/
|
|
4888
|
+
async updateRun(functionRunId, fields) {
|
|
4889
|
+
const functionId = await this.ensureInitialized();
|
|
4890
|
+
const client2 = this.client.getClient();
|
|
4891
|
+
const path = { function_id: functionId, run_id: functionRunId };
|
|
4892
|
+
const body = await offloadRunPayloads(client2, path, fields);
|
|
4893
|
+
const response = await client2.patch({
|
|
4894
|
+
url: "/functions/{function_id}/runs/{run_id}",
|
|
4895
|
+
path,
|
|
4896
|
+
body,
|
|
4897
|
+
headers: { "Content-Type": "application/json" },
|
|
4898
|
+
throwOnError: true
|
|
4679
4899
|
});
|
|
4680
4900
|
return response.data;
|
|
4681
4901
|
}
|
|
@@ -6078,6 +6298,7 @@ export {
|
|
|
6078
6298
|
deleteSecret,
|
|
6079
6299
|
deleteSessionFile,
|
|
6080
6300
|
disconnectPaymentWallet,
|
|
6301
|
+
downloadRunPayload,
|
|
6081
6302
|
downloadSessionFile,
|
|
6082
6303
|
functionCreate,
|
|
6083
6304
|
functionDelete,
|
|
@@ -6134,6 +6355,7 @@ export {
|
|
|
6134
6355
|
personaSmsList,
|
|
6135
6356
|
personaUpdate,
|
|
6136
6357
|
prepareAgentRequest,
|
|
6358
|
+
prepareRunPayloadUpload,
|
|
6137
6359
|
processScrapeResponse,
|
|
6138
6360
|
profileCookiesGet,
|
|
6139
6361
|
profileCookiesSet,
|