notte-sdk 0.0.19 → 0.0.21
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 +1268 -48
- package/dist/index.d.ts +1268 -48
- package/dist/index.js +273 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +262 -4
- package/dist/index.mjs.map +1 -1
- package/dist/proxy/core.js +19 -0
- package/dist/proxy/core.js.map +1 -1
- package/dist/proxy/core.mjs +19 -0
- package/dist/proxy/core.mjs.map +1 -1
- package/dist/proxy/next.js +19 -0
- package/dist/proxy/next.js.map +1 -1
- package/dist/proxy/next.mjs +19 -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.21" : "dev";
|
|
10
10
|
var SDK_PACKAGE_NAME = true ? "notte-sdk" : "notte-sdk";
|
|
11
11
|
|
|
12
12
|
// src/version-check.ts
|
|
@@ -1043,6 +1043,11 @@ var listAgents = (options) => (options?.client ?? client).get({
|
|
|
1043
1043
|
url: "/agents",
|
|
1044
1044
|
...options
|
|
1045
1045
|
});
|
|
1046
|
+
var functionRuntimeHealth = (options) => (options?.client ?? client).get({
|
|
1047
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1048
|
+
url: "/functions/health",
|
|
1049
|
+
...options
|
|
1050
|
+
});
|
|
1046
1051
|
var listFunctions = (options) => (options?.client ?? client).get({
|
|
1047
1052
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1048
1053
|
url: "/functions",
|
|
@@ -1068,6 +1073,15 @@ var functionDownloadUrl = (options) => (options.client ?? client).get({
|
|
|
1068
1073
|
url: "/functions/{function_id}",
|
|
1069
1074
|
...options
|
|
1070
1075
|
});
|
|
1076
|
+
var functionMetadataUpdate = (options) => (options.client ?? client).patch({
|
|
1077
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1078
|
+
url: "/functions/{function_id}",
|
|
1079
|
+
...options,
|
|
1080
|
+
headers: {
|
|
1081
|
+
"Content-Type": "application/json",
|
|
1082
|
+
...options.headers
|
|
1083
|
+
}
|
|
1084
|
+
});
|
|
1071
1085
|
var functionUpdate = (options) => (options.client ?? client).post({
|
|
1072
1086
|
...formDataBodySerializer,
|
|
1073
1087
|
security: [{ scheme: "bearer", type: "http" }],
|
|
@@ -1083,6 +1097,15 @@ var functionFork = (options) => (options.client ?? client).post({
|
|
|
1083
1097
|
url: "/functions/{function_id}/fork",
|
|
1084
1098
|
...options
|
|
1085
1099
|
});
|
|
1100
|
+
var functionRollback = (options) => (options.client ?? client).post({
|
|
1101
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1102
|
+
url: "/functions/{function_id}/rollback",
|
|
1103
|
+
...options,
|
|
1104
|
+
headers: {
|
|
1105
|
+
"Content-Type": "application/json",
|
|
1106
|
+
...options.headers
|
|
1107
|
+
}
|
|
1108
|
+
});
|
|
1086
1109
|
var functionScheduleDelete = (options) => (options.client ?? client).delete({
|
|
1087
1110
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1088
1111
|
url: "/functions/{function_id}/schedule",
|
|
@@ -1333,6 +1356,42 @@ var mailboxUpdate = (options) => (options.client ?? client).patch({
|
|
|
1333
1356
|
...options.headers
|
|
1334
1357
|
}
|
|
1335
1358
|
});
|
|
1359
|
+
var managedAuthConnectLinkCreate = (options) => (options.client ?? client).post({
|
|
1360
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1361
|
+
url: "/managed-auth/connect-links",
|
|
1362
|
+
...options,
|
|
1363
|
+
headers: {
|
|
1364
|
+
"Content-Type": "application/json",
|
|
1365
|
+
...options.headers
|
|
1366
|
+
}
|
|
1367
|
+
});
|
|
1368
|
+
var connectLinkContext = (options) => (options.client ?? client).post({ url: "/managed-auth/connect-links/context", ...options });
|
|
1369
|
+
var connectLinkMailboxes = (options) => (options.client ?? client).post({ url: "/managed-auth/connect-links/mailboxes", ...options });
|
|
1370
|
+
var connectLinkMailboxConnect = (options) => (options.client ?? client).post({
|
|
1371
|
+
url: "/managed-auth/connect-links/mailboxes/connect",
|
|
1372
|
+
...options,
|
|
1373
|
+
headers: {
|
|
1374
|
+
"Content-Type": "application/json",
|
|
1375
|
+
...options.headers
|
|
1376
|
+
}
|
|
1377
|
+
});
|
|
1378
|
+
var connectLinkMailboxSync = (options) => (options.client ?? client).post({
|
|
1379
|
+
url: "/managed-auth/connect-links/mailboxes/sync",
|
|
1380
|
+
...options,
|
|
1381
|
+
headers: {
|
|
1382
|
+
"Content-Type": "application/json",
|
|
1383
|
+
...options.headers
|
|
1384
|
+
}
|
|
1385
|
+
});
|
|
1386
|
+
var connectLinkSubmit = (options) => (options.client ?? client).post({
|
|
1387
|
+
url: "/managed-auth/connect-links/submit",
|
|
1388
|
+
...options,
|
|
1389
|
+
headers: {
|
|
1390
|
+
"Content-Type": "application/json",
|
|
1391
|
+
...options.headers
|
|
1392
|
+
}
|
|
1393
|
+
});
|
|
1394
|
+
var connectLinkStatus = (options) => (options.client ?? client).get({ url: "/managed-auth/connect-links/status", ...options });
|
|
1336
1395
|
var improvePrompt = (options) => (options.client ?? client).post({
|
|
1337
1396
|
url: "/prompts/improve",
|
|
1338
1397
|
...options,
|
|
@@ -1546,14 +1605,24 @@ var Session = class {
|
|
|
1546
1605
|
this.isActive = false;
|
|
1547
1606
|
this.response = null;
|
|
1548
1607
|
this.client = client2;
|
|
1549
|
-
const { open_viewer = false, ...sessionOptions } = options;
|
|
1608
|
+
const { open_viewer = false, headless, ...sessionOptions } = options;
|
|
1550
1609
|
this.options = sessionOptions;
|
|
1551
1610
|
this.openViewer = open_viewer;
|
|
1611
|
+
this.legacyHeadless = headless;
|
|
1552
1612
|
}
|
|
1553
1613
|
/**
|
|
1554
1614
|
* Start the session - creates a new session on the server
|
|
1555
1615
|
*/
|
|
1556
1616
|
async start() {
|
|
1617
|
+
if (this.legacyHeadless === false) {
|
|
1618
|
+
throw new Error(
|
|
1619
|
+
"Remote `headless: false` is no longer supported. `headless: true` sessions still include session replays and access to the live viewer."
|
|
1620
|
+
);
|
|
1621
|
+
}
|
|
1622
|
+
if (this.legacyHeadless === true) {
|
|
1623
|
+
console.warn("`headless: true` is deprecated and ignored; remote sessions always use the supported browser launch mode.");
|
|
1624
|
+
this.legacyHeadless = void 0;
|
|
1625
|
+
}
|
|
1557
1626
|
if (this.isActive) {
|
|
1558
1627
|
throw new Error("Session is already active");
|
|
1559
1628
|
}
|
|
@@ -1581,7 +1650,7 @@ var Session = class {
|
|
|
1581
1650
|
/**
|
|
1582
1651
|
* Stop the session - terminates the session on the server
|
|
1583
1652
|
*/
|
|
1584
|
-
async stop() {
|
|
1653
|
+
async stop(closeReason = "manual") {
|
|
1585
1654
|
if (!this.isActive || !this.sessionId) {
|
|
1586
1655
|
return;
|
|
1587
1656
|
}
|
|
@@ -1589,6 +1658,9 @@ var Session = class {
|
|
|
1589
1658
|
client: this.client.getClient(),
|
|
1590
1659
|
path: {
|
|
1591
1660
|
session_id: this.sessionId
|
|
1661
|
+
},
|
|
1662
|
+
query: {
|
|
1663
|
+
close_reason: closeReason
|
|
1592
1664
|
}
|
|
1593
1665
|
});
|
|
1594
1666
|
if (response?.error) {
|
|
@@ -1807,10 +1879,21 @@ var Session = class {
|
|
|
1807
1879
|
*/
|
|
1808
1880
|
async use(callback) {
|
|
1809
1881
|
await this.start();
|
|
1882
|
+
let callbackFailed = false;
|
|
1810
1883
|
try {
|
|
1811
1884
|
return await callback(this);
|
|
1885
|
+
} catch (error) {
|
|
1886
|
+
callbackFailed = true;
|
|
1887
|
+
throw error;
|
|
1812
1888
|
} finally {
|
|
1813
|
-
|
|
1889
|
+
try {
|
|
1890
|
+
await this.stop(callbackFailed ? "error" : "manual");
|
|
1891
|
+
} catch (stopError) {
|
|
1892
|
+
if (!callbackFailed) {
|
|
1893
|
+
throw stopError;
|
|
1894
|
+
}
|
|
1895
|
+
console.error("[Session] Failed to stop session after callback error:", stopError);
|
|
1896
|
+
}
|
|
1814
1897
|
}
|
|
1815
1898
|
}
|
|
1816
1899
|
/**
|
|
@@ -2742,6 +2825,59 @@ var NottePersona = class {
|
|
|
2742
2825
|
};
|
|
2743
2826
|
|
|
2744
2827
|
// src/functions.ts
|
|
2828
|
+
import { writeFile } from "fs/promises";
|
|
2829
|
+
|
|
2830
|
+
// src/encryption.ts
|
|
2831
|
+
import { createDecipheriv, createHmac, pbkdf2Sync, timingSafeEqual } from "crypto";
|
|
2832
|
+
var SALT_LENGTH = 16;
|
|
2833
|
+
var PBKDF2_ITERATIONS = 1e5;
|
|
2834
|
+
var PBKDF2_KEY_LENGTH = 32;
|
|
2835
|
+
var FERNET_VERSION = 128;
|
|
2836
|
+
var FERNET_IV_LENGTH = 16;
|
|
2837
|
+
var FERNET_HMAC_LENGTH = 32;
|
|
2838
|
+
var FERNET_HEADER_LENGTH = 1 + 8 + FERNET_IV_LENGTH;
|
|
2839
|
+
var Encryption = class {
|
|
2840
|
+
constructor(rootKey) {
|
|
2841
|
+
if (!rootKey) {
|
|
2842
|
+
throw new Error("Root key cannot be empty");
|
|
2843
|
+
}
|
|
2844
|
+
this.rootKey = rootKey;
|
|
2845
|
+
}
|
|
2846
|
+
decrypt(token) {
|
|
2847
|
+
const combined = Buffer.from(token, "base64url");
|
|
2848
|
+
if (combined.length <= SALT_LENGTH) {
|
|
2849
|
+
throw new Error("Invalid encrypted token: too short to contain a salt");
|
|
2850
|
+
}
|
|
2851
|
+
const salt = combined.subarray(0, SALT_LENGTH);
|
|
2852
|
+
const fernetToken = combined.subarray(SALT_LENGTH).toString("utf8");
|
|
2853
|
+
const key = pbkdf2Sync(this.rootKey, salt, PBKDF2_ITERATIONS, PBKDF2_KEY_LENGTH, "sha256");
|
|
2854
|
+
return decryptFernet(fernetToken, key);
|
|
2855
|
+
}
|
|
2856
|
+
};
|
|
2857
|
+
function decryptFernet(token, key) {
|
|
2858
|
+
const signingKey = key.subarray(0, 16);
|
|
2859
|
+
const encryptionKey = key.subarray(16);
|
|
2860
|
+
const data = Buffer.from(token, "base64url");
|
|
2861
|
+
if (data.length < FERNET_HEADER_LENGTH + FERNET_HMAC_LENGTH) {
|
|
2862
|
+
throw new Error("Invalid Fernet token: too short");
|
|
2863
|
+
}
|
|
2864
|
+
if (data[0] !== FERNET_VERSION) {
|
|
2865
|
+
throw new Error(`Invalid Fernet token: unsupported version 0x${data[0].toString(16)}`);
|
|
2866
|
+
}
|
|
2867
|
+
const signed = data.subarray(0, data.length - FERNET_HMAC_LENGTH);
|
|
2868
|
+
const signature = data.subarray(data.length - FERNET_HMAC_LENGTH);
|
|
2869
|
+
const expected = createHmac("sha256", signingKey).update(signed).digest();
|
|
2870
|
+
if (!timingSafeEqual(signature, expected)) {
|
|
2871
|
+
throw new Error("Invalid Fernet token: signature verification failed");
|
|
2872
|
+
}
|
|
2873
|
+
const iv = signed.subarray(9, FERNET_HEADER_LENGTH);
|
|
2874
|
+
const ciphertext = signed.subarray(FERNET_HEADER_LENGTH);
|
|
2875
|
+
const decipher = createDecipheriv("aes-128-cbc", encryptionKey, iv);
|
|
2876
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2879
|
+
// src/functions.ts
|
|
2880
|
+
var DOWNLOAD_TIMEOUT_MS = 3e4;
|
|
2745
2881
|
var NotteFunction = class {
|
|
2746
2882
|
constructor(client2, options) {
|
|
2747
2883
|
this.client = client2;
|
|
@@ -2771,6 +2907,48 @@ var NotteFunction = class {
|
|
|
2771
2907
|
throw new Error(`Failed to get function run metadata: ${error instanceof Error ? error.message : String(error)}`);
|
|
2772
2908
|
}
|
|
2773
2909
|
}
|
|
2910
|
+
/**
|
|
2911
|
+
* List the runs of this function.
|
|
2912
|
+
*
|
|
2913
|
+
* `only_active` is sent as `false` unless the caller says otherwise, and that
|
|
2914
|
+
* is deliberate rather than redundant. `GET /functions/{function_id}/runs`
|
|
2915
|
+
* now defaults it to `false` server-side as well, but it used to default to
|
|
2916
|
+
* `true`: the request model was a bare subclass of the session one, where
|
|
2917
|
+
* "only active" reads sensibly as "list my running sessions" and, for "list
|
|
2918
|
+
* this function's runs", was a trap. Hitting the endpoint with no query
|
|
2919
|
+
* parameters returned only the runs executing right now - an empty list for
|
|
2920
|
+
* any function that had finished. That cost us a bug in the anything-api
|
|
2921
|
+
* console, where a function with 15 recorded runs displayed "Nothing has run
|
|
2922
|
+
* this endpoint yet".
|
|
2923
|
+
*
|
|
2924
|
+
* Sending it explicitly pins this method to the documented behaviour against
|
|
2925
|
+
* whichever API version it is talking to, including deployments that predate
|
|
2926
|
+
* the server-side change. Callers who want only in-flight runs pass
|
|
2927
|
+
* `only_active: true`.
|
|
2928
|
+
*/
|
|
2929
|
+
async runs(options = {}) {
|
|
2930
|
+
try {
|
|
2931
|
+
const response = await listFunctionRunsByFunctionId({
|
|
2932
|
+
client: this.client.getClient(),
|
|
2933
|
+
path: {
|
|
2934
|
+
function_id: this.functionId
|
|
2935
|
+
},
|
|
2936
|
+
query: {
|
|
2937
|
+
...options,
|
|
2938
|
+
only_active: options.only_active ?? false
|
|
2939
|
+
}
|
|
2940
|
+
});
|
|
2941
|
+
if (response?.error) {
|
|
2942
|
+
throw new Error(`Failed to list function runs: ${formatError(response.error)}`);
|
|
2943
|
+
}
|
|
2944
|
+
return response.data;
|
|
2945
|
+
} catch (error) {
|
|
2946
|
+
if (error instanceof Error && error.message.startsWith("Failed to list function runs:")) {
|
|
2947
|
+
throw error;
|
|
2948
|
+
}
|
|
2949
|
+
throw new Error(`Failed to list function runs: ${error instanceof Error ? error.message : String(error)}`);
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2774
2952
|
/**
|
|
2775
2953
|
* Start a function run
|
|
2776
2954
|
*/
|
|
@@ -2807,6 +2985,72 @@ var NotteFunction = class {
|
|
|
2807
2985
|
throw new Error(`Failed to run function: ${error instanceof Error ? error.message : String(error)}`);
|
|
2808
2986
|
}
|
|
2809
2987
|
}
|
|
2988
|
+
/**
|
|
2989
|
+
* Get the download URL of the function code, decrypting it when the API
|
|
2990
|
+
* returns an encrypted one (Notte managed functions).
|
|
2991
|
+
*/
|
|
2992
|
+
async getUrl(options = {}) {
|
|
2993
|
+
let response;
|
|
2994
|
+
try {
|
|
2995
|
+
response = await functionDownloadUrl({
|
|
2996
|
+
client: this.client.getClient(),
|
|
2997
|
+
path: {
|
|
2998
|
+
function_id: this.functionId
|
|
2999
|
+
},
|
|
3000
|
+
query: options.version ? { version: options.version } : {}
|
|
3001
|
+
});
|
|
3002
|
+
} catch (error) {
|
|
3003
|
+
throw new Error(`Failed to get function download url: ${error instanceof Error ? error.message : String(error)}`);
|
|
3004
|
+
}
|
|
3005
|
+
if (response?.error) {
|
|
3006
|
+
throw new Error(`Failed to get function download url: ${formatError(response.error)}`);
|
|
3007
|
+
}
|
|
3008
|
+
const url = response.data.url;
|
|
3009
|
+
if (isHttpUrl(url)) {
|
|
3010
|
+
return url;
|
|
3011
|
+
}
|
|
3012
|
+
const decryptionKey = options.decryption_key ?? this.decryptionKey;
|
|
3013
|
+
if (!decryptionKey) {
|
|
3014
|
+
throw new Error(
|
|
3015
|
+
"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>' })."
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3018
|
+
let decrypted;
|
|
3019
|
+
try {
|
|
3020
|
+
decrypted = new Encryption(decryptionKey).decrypt(url);
|
|
3021
|
+
} catch (error) {
|
|
3022
|
+
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.`);
|
|
3023
|
+
}
|
|
3024
|
+
if (!isHttpUrl(decrypted)) {
|
|
3025
|
+
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.");
|
|
3026
|
+
}
|
|
3027
|
+
return decrypted;
|
|
3028
|
+
}
|
|
3029
|
+
/**
|
|
3030
|
+
* Download the function code as a python file. Returns the code, and writes
|
|
3031
|
+
* it to `path` when one is provided.
|
|
3032
|
+
*/
|
|
3033
|
+
async download(options = {}) {
|
|
3034
|
+
const { path } = options;
|
|
3035
|
+
if (path !== void 0 && !path.endsWith(".py")) {
|
|
3036
|
+
throw new Error(`Code file path must end with .py, got '${path}'`);
|
|
3037
|
+
}
|
|
3038
|
+
const url = await this.getUrl(options);
|
|
3039
|
+
let response;
|
|
3040
|
+
try {
|
|
3041
|
+
response = await fetch(url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) });
|
|
3042
|
+
} catch (error) {
|
|
3043
|
+
throw new Error(`Failed to download function code: ${error instanceof Error ? error.message : String(error)}`);
|
|
3044
|
+
}
|
|
3045
|
+
if (!response.ok) {
|
|
3046
|
+
throw new Error(`Failed to download function code: ${response.status} ${response.statusText}`);
|
|
3047
|
+
}
|
|
3048
|
+
const code = await response.text();
|
|
3049
|
+
if (path !== void 0) {
|
|
3050
|
+
await writeFile(path, code, "utf8");
|
|
3051
|
+
}
|
|
3052
|
+
return code;
|
|
3053
|
+
}
|
|
2810
3054
|
/**
|
|
2811
3055
|
* Get the function ID
|
|
2812
3056
|
*/
|
|
@@ -2814,6 +3058,9 @@ var NotteFunction = class {
|
|
|
2814
3058
|
return this.functionId;
|
|
2815
3059
|
}
|
|
2816
3060
|
};
|
|
3061
|
+
function isHttpUrl(value) {
|
|
3062
|
+
return value.startsWith("https://") || value.startsWith("http://");
|
|
3063
|
+
}
|
|
2817
3064
|
|
|
2818
3065
|
// src/client.ts
|
|
2819
3066
|
import { z as z3 } from "zod";
|
|
@@ -2986,6 +3233,7 @@ var createClient2 = (config) => {
|
|
|
2986
3233
|
};
|
|
2987
3234
|
export {
|
|
2988
3235
|
Agent,
|
|
3236
|
+
Encryption,
|
|
2989
3237
|
NotteClient,
|
|
2990
3238
|
NotteFunction,
|
|
2991
3239
|
NottePersona,
|
|
@@ -2997,6 +3245,12 @@ export {
|
|
|
2997
3245
|
agentStop,
|
|
2998
3246
|
anythingStart,
|
|
2999
3247
|
client,
|
|
3248
|
+
connectLinkContext,
|
|
3249
|
+
connectLinkMailboxConnect,
|
|
3250
|
+
connectLinkMailboxSync,
|
|
3251
|
+
connectLinkMailboxes,
|
|
3252
|
+
connectLinkStatus,
|
|
3253
|
+
connectLinkSubmit,
|
|
3000
3254
|
createClient2 as createClient,
|
|
3001
3255
|
NotteClient as default,
|
|
3002
3256
|
deleteSecret,
|
|
@@ -3010,10 +3264,13 @@ export {
|
|
|
3010
3264
|
functionDelete,
|
|
3011
3265
|
functionDownloadUrl,
|
|
3012
3266
|
functionFork,
|
|
3267
|
+
functionMetadataUpdate,
|
|
3268
|
+
functionRollback,
|
|
3013
3269
|
functionRunGetMetadata,
|
|
3014
3270
|
functionRunStart,
|
|
3015
3271
|
functionRunStop,
|
|
3016
3272
|
functionRunUpdateMetadata,
|
|
3273
|
+
functionRuntimeHealth,
|
|
3017
3274
|
functionScheduleDelete,
|
|
3018
3275
|
functionScheduleSet,
|
|
3019
3276
|
functionUpdate,
|
|
@@ -3037,6 +3294,7 @@ export {
|
|
|
3037
3294
|
mailboxList,
|
|
3038
3295
|
mailboxSync,
|
|
3039
3296
|
mailboxUpdate,
|
|
3297
|
+
managedAuthConnectLinkCreate,
|
|
3040
3298
|
nudgePrompt,
|
|
3041
3299
|
pageExecute,
|
|
3042
3300
|
pageObserve,
|