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/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var SDK_VERSION = true ? "1.9.4" : "dev";
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, query = void 0, requestOptions = {}) => {
1837
- const response = await sessionDebugInfo({ client: client2, throwOnError: true, signal: requestOptions.signal, headers: { ...requestOptions.headers }, path: { "session_id": sessionId }, query });
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 functionRunGetMetadata({
4676
- client: this.client.getClient(),
4677
- throwOnError: true,
4678
- path: { function_id: functionId, run_id: functionRunId }
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,