notte-sdk 0.0.18 → 0.0.20
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 +28 -0
- package/dist/index.d.mts +1035 -46
- package/dist/index.d.ts +1035 -46
- package/dist/index.js +228 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +219 -4
- package/dist/index.mjs.map +1 -1
- package/dist/proxy/core.js +9 -0
- package/dist/proxy/core.js.map +1 -1
- package/dist/proxy/core.mjs +9 -0
- package/dist/proxy/core.mjs.map +1 -1
- package/dist/proxy/next.js +9 -0
- package/dist/proxy/next.js.map +1 -1
- package/dist/proxy/next.mjs +9 -0
- package/dist/proxy/next.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
// src/version.ts
|
|
9
|
-
var SDK_VERSION = true ? "0.0.
|
|
9
|
+
var SDK_VERSION = true ? "0.0.20" : "dev";
|
|
10
10
|
var SDK_PACKAGE_NAME = true ? "notte-sdk" : "notte-sdk";
|
|
11
11
|
|
|
12
12
|
// src/version-check.ts
|
|
@@ -1068,6 +1068,15 @@ var functionDownloadUrl = (options) => (options.client ?? client).get({
|
|
|
1068
1068
|
url: "/functions/{function_id}",
|
|
1069
1069
|
...options
|
|
1070
1070
|
});
|
|
1071
|
+
var functionMetadataUpdate = (options) => (options.client ?? client).patch({
|
|
1072
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1073
|
+
url: "/functions/{function_id}",
|
|
1074
|
+
...options,
|
|
1075
|
+
headers: {
|
|
1076
|
+
"Content-Type": "application/json",
|
|
1077
|
+
...options.headers
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1071
1080
|
var functionUpdate = (options) => (options.client ?? client).post({
|
|
1072
1081
|
...formDataBodySerializer,
|
|
1073
1082
|
security: [{ scheme: "bearer", type: "http" }],
|
|
@@ -1267,6 +1276,15 @@ var personaGet = (options) => (options.client ?? client).get({
|
|
|
1267
1276
|
url: "/personas/{persona_id}",
|
|
1268
1277
|
...options
|
|
1269
1278
|
});
|
|
1279
|
+
var personaUpdate = (options) => (options.client ?? client).patch({
|
|
1280
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1281
|
+
url: "/personas/{persona_id}",
|
|
1282
|
+
...options,
|
|
1283
|
+
headers: {
|
|
1284
|
+
"Content-Type": "application/json",
|
|
1285
|
+
...options.headers
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1270
1288
|
var personaEmailsList = (options) => (options.client ?? client).get({
|
|
1271
1289
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1272
1290
|
url: "/personas/{persona_id}/emails",
|
|
@@ -1282,6 +1300,48 @@ var personaSmsList = (options) => (options.client ?? client).get({
|
|
|
1282
1300
|
url: "/personas/{persona_id}/sms",
|
|
1283
1301
|
...options
|
|
1284
1302
|
});
|
|
1303
|
+
var mailboxConnectToken = (options) => (options.client ?? client).post({
|
|
1304
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1305
|
+
url: "/mailboxes/connect-token",
|
|
1306
|
+
...options,
|
|
1307
|
+
headers: {
|
|
1308
|
+
"Content-Type": "application/json",
|
|
1309
|
+
...options.headers
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1312
|
+
var mailboxSync = (options) => (options?.client ?? client).post({
|
|
1313
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1314
|
+
url: "/mailboxes/sync",
|
|
1315
|
+
...options,
|
|
1316
|
+
headers: {
|
|
1317
|
+
"Content-Type": "application/json",
|
|
1318
|
+
...options?.headers
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
var mailboxList = (options) => (options?.client ?? client).get({
|
|
1322
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1323
|
+
url: "/mailboxes",
|
|
1324
|
+
...options
|
|
1325
|
+
});
|
|
1326
|
+
var mailboxDelete = (options) => (options.client ?? client).delete({
|
|
1327
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1328
|
+
url: "/mailboxes/{mailbox_id}",
|
|
1329
|
+
...options
|
|
1330
|
+
});
|
|
1331
|
+
var mailboxGet = (options) => (options.client ?? client).get({
|
|
1332
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1333
|
+
url: "/mailboxes/{mailbox_id}",
|
|
1334
|
+
...options
|
|
1335
|
+
});
|
|
1336
|
+
var mailboxUpdate = (options) => (options.client ?? client).patch({
|
|
1337
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1338
|
+
url: "/mailboxes/{mailbox_id}",
|
|
1339
|
+
...options,
|
|
1340
|
+
headers: {
|
|
1341
|
+
"Content-Type": "application/json",
|
|
1342
|
+
...options.headers
|
|
1343
|
+
}
|
|
1344
|
+
});
|
|
1285
1345
|
var improvePrompt = (options) => (options.client ?? client).post({
|
|
1286
1346
|
url: "/prompts/improve",
|
|
1287
1347
|
...options,
|
|
@@ -1495,14 +1555,24 @@ var Session = class {
|
|
|
1495
1555
|
this.isActive = false;
|
|
1496
1556
|
this.response = null;
|
|
1497
1557
|
this.client = client2;
|
|
1498
|
-
const { open_viewer = false, ...sessionOptions } = options;
|
|
1558
|
+
const { open_viewer = false, headless, ...sessionOptions } = options;
|
|
1499
1559
|
this.options = sessionOptions;
|
|
1500
1560
|
this.openViewer = open_viewer;
|
|
1561
|
+
this.legacyHeadless = headless;
|
|
1501
1562
|
}
|
|
1502
1563
|
/**
|
|
1503
1564
|
* Start the session - creates a new session on the server
|
|
1504
1565
|
*/
|
|
1505
1566
|
async start() {
|
|
1567
|
+
if (this.legacyHeadless === false) {
|
|
1568
|
+
throw new Error(
|
|
1569
|
+
"Remote `headless: false` is no longer supported. `headless: true` sessions still include session replays and access to the live viewer."
|
|
1570
|
+
);
|
|
1571
|
+
}
|
|
1572
|
+
if (this.legacyHeadless === true) {
|
|
1573
|
+
console.warn("`headless: true` is deprecated and ignored; remote sessions always use the supported browser launch mode.");
|
|
1574
|
+
this.legacyHeadless = void 0;
|
|
1575
|
+
}
|
|
1506
1576
|
if (this.isActive) {
|
|
1507
1577
|
throw new Error("Session is already active");
|
|
1508
1578
|
}
|
|
@@ -1530,7 +1600,7 @@ var Session = class {
|
|
|
1530
1600
|
/**
|
|
1531
1601
|
* Stop the session - terminates the session on the server
|
|
1532
1602
|
*/
|
|
1533
|
-
async stop() {
|
|
1603
|
+
async stop(closeReason = "manual") {
|
|
1534
1604
|
if (!this.isActive || !this.sessionId) {
|
|
1535
1605
|
return;
|
|
1536
1606
|
}
|
|
@@ -1538,6 +1608,9 @@ var Session = class {
|
|
|
1538
1608
|
client: this.client.getClient(),
|
|
1539
1609
|
path: {
|
|
1540
1610
|
session_id: this.sessionId
|
|
1611
|
+
},
|
|
1612
|
+
query: {
|
|
1613
|
+
close_reason: closeReason
|
|
1541
1614
|
}
|
|
1542
1615
|
});
|
|
1543
1616
|
if (response?.error) {
|
|
@@ -1756,10 +1829,21 @@ var Session = class {
|
|
|
1756
1829
|
*/
|
|
1757
1830
|
async use(callback) {
|
|
1758
1831
|
await this.start();
|
|
1832
|
+
let callbackFailed = false;
|
|
1759
1833
|
try {
|
|
1760
1834
|
return await callback(this);
|
|
1835
|
+
} catch (error) {
|
|
1836
|
+
callbackFailed = true;
|
|
1837
|
+
throw error;
|
|
1761
1838
|
} finally {
|
|
1762
|
-
|
|
1839
|
+
try {
|
|
1840
|
+
await this.stop(callbackFailed ? "error" : "manual");
|
|
1841
|
+
} catch (stopError) {
|
|
1842
|
+
if (!callbackFailed) {
|
|
1843
|
+
throw stopError;
|
|
1844
|
+
}
|
|
1845
|
+
console.error("[Session] Failed to stop session after callback error:", stopError);
|
|
1846
|
+
}
|
|
1763
1847
|
}
|
|
1764
1848
|
}
|
|
1765
1849
|
/**
|
|
@@ -2691,6 +2775,59 @@ var NottePersona = class {
|
|
|
2691
2775
|
};
|
|
2692
2776
|
|
|
2693
2777
|
// src/functions.ts
|
|
2778
|
+
import { writeFile } from "fs/promises";
|
|
2779
|
+
|
|
2780
|
+
// src/encryption.ts
|
|
2781
|
+
import { createDecipheriv, createHmac, pbkdf2Sync, timingSafeEqual } from "crypto";
|
|
2782
|
+
var SALT_LENGTH = 16;
|
|
2783
|
+
var PBKDF2_ITERATIONS = 1e5;
|
|
2784
|
+
var PBKDF2_KEY_LENGTH = 32;
|
|
2785
|
+
var FERNET_VERSION = 128;
|
|
2786
|
+
var FERNET_IV_LENGTH = 16;
|
|
2787
|
+
var FERNET_HMAC_LENGTH = 32;
|
|
2788
|
+
var FERNET_HEADER_LENGTH = 1 + 8 + FERNET_IV_LENGTH;
|
|
2789
|
+
var Encryption = class {
|
|
2790
|
+
constructor(rootKey) {
|
|
2791
|
+
if (!rootKey) {
|
|
2792
|
+
throw new Error("Root key cannot be empty");
|
|
2793
|
+
}
|
|
2794
|
+
this.rootKey = rootKey;
|
|
2795
|
+
}
|
|
2796
|
+
decrypt(token) {
|
|
2797
|
+
const combined = Buffer.from(token, "base64url");
|
|
2798
|
+
if (combined.length <= SALT_LENGTH) {
|
|
2799
|
+
throw new Error("Invalid encrypted token: too short to contain a salt");
|
|
2800
|
+
}
|
|
2801
|
+
const salt = combined.subarray(0, SALT_LENGTH);
|
|
2802
|
+
const fernetToken = combined.subarray(SALT_LENGTH).toString("utf8");
|
|
2803
|
+
const key = pbkdf2Sync(this.rootKey, salt, PBKDF2_ITERATIONS, PBKDF2_KEY_LENGTH, "sha256");
|
|
2804
|
+
return decryptFernet(fernetToken, key);
|
|
2805
|
+
}
|
|
2806
|
+
};
|
|
2807
|
+
function decryptFernet(token, key) {
|
|
2808
|
+
const signingKey = key.subarray(0, 16);
|
|
2809
|
+
const encryptionKey = key.subarray(16);
|
|
2810
|
+
const data = Buffer.from(token, "base64url");
|
|
2811
|
+
if (data.length < FERNET_HEADER_LENGTH + FERNET_HMAC_LENGTH) {
|
|
2812
|
+
throw new Error("Invalid Fernet token: too short");
|
|
2813
|
+
}
|
|
2814
|
+
if (data[0] !== FERNET_VERSION) {
|
|
2815
|
+
throw new Error(`Invalid Fernet token: unsupported version 0x${data[0].toString(16)}`);
|
|
2816
|
+
}
|
|
2817
|
+
const signed = data.subarray(0, data.length - FERNET_HMAC_LENGTH);
|
|
2818
|
+
const signature = data.subarray(data.length - FERNET_HMAC_LENGTH);
|
|
2819
|
+
const expected = createHmac("sha256", signingKey).update(signed).digest();
|
|
2820
|
+
if (!timingSafeEqual(signature, expected)) {
|
|
2821
|
+
throw new Error("Invalid Fernet token: signature verification failed");
|
|
2822
|
+
}
|
|
2823
|
+
const iv = signed.subarray(9, FERNET_HEADER_LENGTH);
|
|
2824
|
+
const ciphertext = signed.subarray(FERNET_HEADER_LENGTH);
|
|
2825
|
+
const decipher = createDecipheriv("aes-128-cbc", encryptionKey, iv);
|
|
2826
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
// src/functions.ts
|
|
2830
|
+
var DOWNLOAD_TIMEOUT_MS = 3e4;
|
|
2694
2831
|
var NotteFunction = class {
|
|
2695
2832
|
constructor(client2, options) {
|
|
2696
2833
|
this.client = client2;
|
|
@@ -2756,6 +2893,72 @@ var NotteFunction = class {
|
|
|
2756
2893
|
throw new Error(`Failed to run function: ${error instanceof Error ? error.message : String(error)}`);
|
|
2757
2894
|
}
|
|
2758
2895
|
}
|
|
2896
|
+
/**
|
|
2897
|
+
* Get the download URL of the function code, decrypting it when the API
|
|
2898
|
+
* returns an encrypted one (Notte managed functions).
|
|
2899
|
+
*/
|
|
2900
|
+
async getUrl(options = {}) {
|
|
2901
|
+
let response;
|
|
2902
|
+
try {
|
|
2903
|
+
response = await functionDownloadUrl({
|
|
2904
|
+
client: this.client.getClient(),
|
|
2905
|
+
path: {
|
|
2906
|
+
function_id: this.functionId
|
|
2907
|
+
},
|
|
2908
|
+
query: options.version ? { version: options.version } : {}
|
|
2909
|
+
});
|
|
2910
|
+
} catch (error) {
|
|
2911
|
+
throw new Error(`Failed to get function download url: ${error instanceof Error ? error.message : String(error)}`);
|
|
2912
|
+
}
|
|
2913
|
+
if (response?.error) {
|
|
2914
|
+
throw new Error(`Failed to get function download url: ${formatError(response.error)}`);
|
|
2915
|
+
}
|
|
2916
|
+
const url = response.data.url;
|
|
2917
|
+
if (isHttpUrl(url)) {
|
|
2918
|
+
return url;
|
|
2919
|
+
}
|
|
2920
|
+
const decryptionKey = options.decryption_key ?? this.decryptionKey;
|
|
2921
|
+
if (!decryptionKey) {
|
|
2922
|
+
throw new Error(
|
|
2923
|
+
"Decryption key is required to decrypt the function download url. Set it when creating the function, i.e. client.NotteFunction({ function_id: '<your-function-id>', decryption_key: '<your-key>' })."
|
|
2924
|
+
);
|
|
2925
|
+
}
|
|
2926
|
+
let decrypted;
|
|
2927
|
+
try {
|
|
2928
|
+
decrypted = new Encryption(decryptionKey).decrypt(url);
|
|
2929
|
+
} catch (error) {
|
|
2930
|
+
throw new Error(`Failed to decrypt the function download url: ${error instanceof Error ? error.message : String(error)}. Contact support@notte.cc if you need help.`);
|
|
2931
|
+
}
|
|
2932
|
+
if (!isHttpUrl(decrypted)) {
|
|
2933
|
+
throw new Error("Failed to decrypt the function download url: the decrypted value is not a URL. Contact support@notte.cc if you need help.");
|
|
2934
|
+
}
|
|
2935
|
+
return decrypted;
|
|
2936
|
+
}
|
|
2937
|
+
/**
|
|
2938
|
+
* Download the function code as a python file. Returns the code, and writes
|
|
2939
|
+
* it to `path` when one is provided.
|
|
2940
|
+
*/
|
|
2941
|
+
async download(options = {}) {
|
|
2942
|
+
const { path } = options;
|
|
2943
|
+
if (path !== void 0 && !path.endsWith(".py")) {
|
|
2944
|
+
throw new Error(`Code file path must end with .py, got '${path}'`);
|
|
2945
|
+
}
|
|
2946
|
+
const url = await this.getUrl(options);
|
|
2947
|
+
let response;
|
|
2948
|
+
try {
|
|
2949
|
+
response = await fetch(url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) });
|
|
2950
|
+
} catch (error) {
|
|
2951
|
+
throw new Error(`Failed to download function code: ${error instanceof Error ? error.message : String(error)}`);
|
|
2952
|
+
}
|
|
2953
|
+
if (!response.ok) {
|
|
2954
|
+
throw new Error(`Failed to download function code: ${response.status} ${response.statusText}`);
|
|
2955
|
+
}
|
|
2956
|
+
const code = await response.text();
|
|
2957
|
+
if (path !== void 0) {
|
|
2958
|
+
await writeFile(path, code, "utf8");
|
|
2959
|
+
}
|
|
2960
|
+
return code;
|
|
2961
|
+
}
|
|
2759
2962
|
/**
|
|
2760
2963
|
* Get the function ID
|
|
2761
2964
|
*/
|
|
@@ -2763,6 +2966,9 @@ var NotteFunction = class {
|
|
|
2763
2966
|
return this.functionId;
|
|
2764
2967
|
}
|
|
2765
2968
|
};
|
|
2969
|
+
function isHttpUrl(value) {
|
|
2970
|
+
return value.startsWith("https://") || value.startsWith("http://");
|
|
2971
|
+
}
|
|
2766
2972
|
|
|
2767
2973
|
// src/client.ts
|
|
2768
2974
|
import { z as z3 } from "zod";
|
|
@@ -2935,6 +3141,7 @@ var createClient2 = (config) => {
|
|
|
2935
3141
|
};
|
|
2936
3142
|
export {
|
|
2937
3143
|
Agent,
|
|
3144
|
+
Encryption,
|
|
2938
3145
|
NotteClient,
|
|
2939
3146
|
NotteFunction,
|
|
2940
3147
|
NottePersona,
|
|
@@ -2959,6 +3166,7 @@ export {
|
|
|
2959
3166
|
functionDelete,
|
|
2960
3167
|
functionDownloadUrl,
|
|
2961
3168
|
functionFork,
|
|
3169
|
+
functionMetadataUpdate,
|
|
2962
3170
|
functionRunGetMetadata,
|
|
2963
3171
|
functionRunStart,
|
|
2964
3172
|
functionRunStop,
|
|
@@ -2980,6 +3188,12 @@ export {
|
|
|
2980
3188
|
listSecrets,
|
|
2981
3189
|
listSessions,
|
|
2982
3190
|
listVaults,
|
|
3191
|
+
mailboxConnectToken,
|
|
3192
|
+
mailboxDelete,
|
|
3193
|
+
mailboxGet,
|
|
3194
|
+
mailboxList,
|
|
3195
|
+
mailboxSync,
|
|
3196
|
+
mailboxUpdate,
|
|
2983
3197
|
nudgePrompt,
|
|
2984
3198
|
pageExecute,
|
|
2985
3199
|
pageObserve,
|
|
@@ -2990,6 +3204,7 @@ export {
|
|
|
2990
3204
|
personaEmailsList,
|
|
2991
3205
|
personaGet,
|
|
2992
3206
|
personaSmsList,
|
|
3207
|
+
personaUpdate,
|
|
2993
3208
|
profileCookiesGet,
|
|
2994
3209
|
profileCookiesSet,
|
|
2995
3210
|
profileCreate,
|