exa-js 1.9.1 → 1.9.2
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.d.mts +1203 -2467
- package/dist/index.d.ts +1203 -2467
- package/dist/index.js +251 -168
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +251 -168
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,89 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import fetch2, { Headers } from "cross-fetch";
|
|
3
3
|
|
|
4
|
+
// package.json
|
|
5
|
+
var package_default = {
|
|
6
|
+
name: "exa-js",
|
|
7
|
+
version: "1.9.2",
|
|
8
|
+
description: "Exa SDK for Node.js and the browser",
|
|
9
|
+
publishConfig: {
|
|
10
|
+
access: "public"
|
|
11
|
+
},
|
|
12
|
+
files: [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
main: "./dist/index.js",
|
|
16
|
+
module: "./dist/index.mjs",
|
|
17
|
+
exports: {
|
|
18
|
+
".": {
|
|
19
|
+
types: "./dist/index.d.ts",
|
|
20
|
+
require: "./dist/index.js",
|
|
21
|
+
module: "./dist/index.mjs",
|
|
22
|
+
import: "./dist/index.mjs"
|
|
23
|
+
},
|
|
24
|
+
"./package.json": "./package.json"
|
|
25
|
+
},
|
|
26
|
+
types: "./dist/index.d.ts",
|
|
27
|
+
scripts: {
|
|
28
|
+
"build-fast": "tsup src/index.ts --format cjs,esm",
|
|
29
|
+
build: "tsup",
|
|
30
|
+
test: "vitest run",
|
|
31
|
+
typecheck: "tsc --noEmit",
|
|
32
|
+
"typecheck:src": "tsc --noEmit src/**/*.ts",
|
|
33
|
+
"typecheck:examples": "tsc --noEmit examples/**/*.ts",
|
|
34
|
+
"generate:types:websets": "openapi-typescript https://raw.githubusercontent.com/exa-labs/openapi-spec/refs/heads/master/exa-websets-spec.yaml --enum --root-types --alphabetize --root-types-no-schema-prefix --output ./src/websets/openapi.ts && npm run format:websets",
|
|
35
|
+
format: 'prettier --write "src/**/*.ts" "examples/**/*.ts"',
|
|
36
|
+
"format:websets": "prettier --write src/websets/openapi.ts",
|
|
37
|
+
"build:beta": "cross-env NPM_CONFIG_TAG=beta npm run build",
|
|
38
|
+
"version:beta": "npm version prerelease --preid=beta",
|
|
39
|
+
"version:stable": "npm version patch",
|
|
40
|
+
"publish:beta": "npm run version:beta && npm run build:beta && npm publish --tag beta",
|
|
41
|
+
"publish:stable": "npm run version:stable && npm run build && npm publish",
|
|
42
|
+
prepublishOnly: "npm run build"
|
|
43
|
+
},
|
|
44
|
+
license: "MIT",
|
|
45
|
+
devDependencies: {
|
|
46
|
+
"@types/node": "~22.14.0",
|
|
47
|
+
"cross-env": "~7.0.3",
|
|
48
|
+
"openapi-typescript": "~7.6.1",
|
|
49
|
+
prettier: "~3.5.3",
|
|
50
|
+
"ts-node": "~10.9.2",
|
|
51
|
+
tsup: "~8.4.0",
|
|
52
|
+
typescript: "~5.8.3",
|
|
53
|
+
vitest: "~3.1.1"
|
|
54
|
+
},
|
|
55
|
+
dependencies: {
|
|
56
|
+
"cross-fetch": "~4.1.0",
|
|
57
|
+
dotenv: "~16.4.7",
|
|
58
|
+
openai: "^5.0.1",
|
|
59
|
+
zod: "^3.22.0",
|
|
60
|
+
"zod-to-json-schema": "^3.20.0"
|
|
61
|
+
},
|
|
62
|
+
directories: {
|
|
63
|
+
test: "test"
|
|
64
|
+
},
|
|
65
|
+
repository: {
|
|
66
|
+
type: "git",
|
|
67
|
+
url: "git+https://github.com/exa-labs/exa-js.git"
|
|
68
|
+
},
|
|
69
|
+
keywords: [
|
|
70
|
+
"exa",
|
|
71
|
+
"metaphor",
|
|
72
|
+
"search",
|
|
73
|
+
"AI",
|
|
74
|
+
"LLMs",
|
|
75
|
+
"RAG",
|
|
76
|
+
"retrieval",
|
|
77
|
+
"augmented",
|
|
78
|
+
"generation"
|
|
79
|
+
],
|
|
80
|
+
author: "jeffzwang",
|
|
81
|
+
bugs: {
|
|
82
|
+
url: "https://github.com/exa-labs/exa-js/issues"
|
|
83
|
+
},
|
|
84
|
+
homepage: "https://github.com/exa-labs/exa-js#readme"
|
|
85
|
+
};
|
|
86
|
+
|
|
4
87
|
// src/errors.ts
|
|
5
88
|
var HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => {
|
|
6
89
|
HttpStatusCode2[HttpStatusCode2["BadRequest"] = 400] = "BadRequest";
|
|
@@ -30,6 +113,173 @@ var ExaError = class extends Error {
|
|
|
30
113
|
}
|
|
31
114
|
};
|
|
32
115
|
|
|
116
|
+
// src/zod-utils.ts
|
|
117
|
+
import { ZodType } from "zod";
|
|
118
|
+
import { zodToJsonSchema as convertZodToJsonSchema } from "zod-to-json-schema";
|
|
119
|
+
function isZodSchema(obj) {
|
|
120
|
+
return obj instanceof ZodType;
|
|
121
|
+
}
|
|
122
|
+
function zodToJsonSchema(schema) {
|
|
123
|
+
return convertZodToJsonSchema(schema, {
|
|
124
|
+
$refStrategy: "none"
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/research/base.ts
|
|
129
|
+
var ResearchBaseClient = class {
|
|
130
|
+
constructor(client) {
|
|
131
|
+
this.client = client;
|
|
132
|
+
}
|
|
133
|
+
async request(endpoint, method = "POST", data, params) {
|
|
134
|
+
return this.client.request(
|
|
135
|
+
`/research/v1${endpoint}`,
|
|
136
|
+
method,
|
|
137
|
+
data,
|
|
138
|
+
params
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
async rawRequest(endpoint, method = "POST", data, params) {
|
|
142
|
+
return this.client.rawRequest(
|
|
143
|
+
`/research/v1${endpoint}`,
|
|
144
|
+
method,
|
|
145
|
+
data,
|
|
146
|
+
params
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
buildPaginationParams(pagination) {
|
|
150
|
+
const params = {};
|
|
151
|
+
if (!pagination) return params;
|
|
152
|
+
if (pagination.cursor) params.cursor = pagination.cursor;
|
|
153
|
+
if (pagination.limit) params.limit = pagination.limit;
|
|
154
|
+
return params;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// src/research/client.ts
|
|
159
|
+
var ResearchClient = class extends ResearchBaseClient {
|
|
160
|
+
constructor(client) {
|
|
161
|
+
super(client);
|
|
162
|
+
}
|
|
163
|
+
async create(params) {
|
|
164
|
+
const { instructions, model, outputSchema } = params;
|
|
165
|
+
let schema = outputSchema;
|
|
166
|
+
if (schema && isZodSchema(schema)) {
|
|
167
|
+
schema = zodToJsonSchema(schema);
|
|
168
|
+
}
|
|
169
|
+
const payload = {
|
|
170
|
+
instructions,
|
|
171
|
+
model: model ?? "exa-research"
|
|
172
|
+
};
|
|
173
|
+
if (schema) {
|
|
174
|
+
payload.outputSchema = schema;
|
|
175
|
+
}
|
|
176
|
+
return this.request("", "POST", payload);
|
|
177
|
+
}
|
|
178
|
+
get(researchId, options) {
|
|
179
|
+
if (options?.stream) {
|
|
180
|
+
const promise = async () => {
|
|
181
|
+
const params = { stream: "true" };
|
|
182
|
+
if (options.events !== void 0) {
|
|
183
|
+
params.events = options.events.toString();
|
|
184
|
+
}
|
|
185
|
+
const resp = await this.rawRequest(
|
|
186
|
+
`/${researchId}`,
|
|
187
|
+
"GET",
|
|
188
|
+
void 0,
|
|
189
|
+
params
|
|
190
|
+
);
|
|
191
|
+
if (!resp.body) {
|
|
192
|
+
throw new Error("No response body for SSE stream");
|
|
193
|
+
}
|
|
194
|
+
const reader = resp.body.getReader();
|
|
195
|
+
const decoder = new TextDecoder();
|
|
196
|
+
let buffer = "";
|
|
197
|
+
function processPart(part) {
|
|
198
|
+
const lines = part.split("\n");
|
|
199
|
+
let data = lines.slice(1).join("\n");
|
|
200
|
+
if (data.startsWith("data:")) {
|
|
201
|
+
data = data.slice(5).trimStart();
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
return JSON.parse(data);
|
|
205
|
+
} catch (e) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function* streamEvents() {
|
|
210
|
+
while (true) {
|
|
211
|
+
const { done, value } = await reader.read();
|
|
212
|
+
if (done) break;
|
|
213
|
+
buffer += decoder.decode(value, { stream: true });
|
|
214
|
+
let parts = buffer.split("\n\n");
|
|
215
|
+
buffer = parts.pop() ?? "";
|
|
216
|
+
for (const part of parts) {
|
|
217
|
+
const processed = processPart(part);
|
|
218
|
+
if (processed) {
|
|
219
|
+
yield processed;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (buffer.trim()) {
|
|
224
|
+
const processed = processPart(buffer.trim());
|
|
225
|
+
if (processed) {
|
|
226
|
+
yield processed;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return streamEvents();
|
|
231
|
+
};
|
|
232
|
+
return promise();
|
|
233
|
+
} else {
|
|
234
|
+
const params = { stream: "false" };
|
|
235
|
+
if (options?.events !== void 0) {
|
|
236
|
+
params.events = options.events.toString();
|
|
237
|
+
}
|
|
238
|
+
return this.request(
|
|
239
|
+
`/${researchId}`,
|
|
240
|
+
"GET",
|
|
241
|
+
void 0,
|
|
242
|
+
params
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
async list(options) {
|
|
247
|
+
const params = this.buildPaginationParams(options);
|
|
248
|
+
return this.request("", "GET", void 0, params);
|
|
249
|
+
}
|
|
250
|
+
async pollUntilFinished(researchId, options) {
|
|
251
|
+
const pollInterval = options?.pollInterval ?? 1e3;
|
|
252
|
+
const timeoutMs = options?.timeoutMs ?? 10 * 60 * 1e3;
|
|
253
|
+
const maxConsecutiveFailures = 5;
|
|
254
|
+
const startTime = Date.now();
|
|
255
|
+
let consecutiveFailures = 0;
|
|
256
|
+
while (true) {
|
|
257
|
+
try {
|
|
258
|
+
const research = await this.get(researchId, {
|
|
259
|
+
events: options?.events
|
|
260
|
+
});
|
|
261
|
+
consecutiveFailures = 0;
|
|
262
|
+
if (research.status === "completed" || research.status === "failed" || research.status === "canceled") {
|
|
263
|
+
return research;
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
consecutiveFailures += 1;
|
|
267
|
+
if (consecutiveFailures >= maxConsecutiveFailures) {
|
|
268
|
+
throw new Error(
|
|
269
|
+
`Polling failed ${maxConsecutiveFailures} times in a row for research ${researchId}: ${err}`
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
`Polling timeout: Research ${researchId} did not complete within ${timeoutMs}ms`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
33
283
|
// src/websets/base.ts
|
|
34
284
|
var WebsetsBaseClient = class {
|
|
35
285
|
/**
|
|
@@ -1006,173 +1256,6 @@ var WebsetsClient = class extends WebsetsBaseClient {
|
|
|
1006
1256
|
}
|
|
1007
1257
|
};
|
|
1008
1258
|
|
|
1009
|
-
// src/zod-utils.ts
|
|
1010
|
-
import { ZodType } from "zod";
|
|
1011
|
-
import { zodToJsonSchema as convertZodToJsonSchema } from "zod-to-json-schema";
|
|
1012
|
-
function isZodSchema(obj) {
|
|
1013
|
-
return obj instanceof ZodType;
|
|
1014
|
-
}
|
|
1015
|
-
function zodToJsonSchema(schema) {
|
|
1016
|
-
return convertZodToJsonSchema(schema, {
|
|
1017
|
-
$refStrategy: "none"
|
|
1018
|
-
});
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
// src/research/base.ts
|
|
1022
|
-
var ResearchBaseClient = class {
|
|
1023
|
-
constructor(client) {
|
|
1024
|
-
this.client = client;
|
|
1025
|
-
}
|
|
1026
|
-
async request(endpoint, method = "POST", data, params) {
|
|
1027
|
-
return this.client.request(
|
|
1028
|
-
`/research/v1${endpoint}`,
|
|
1029
|
-
method,
|
|
1030
|
-
data,
|
|
1031
|
-
params
|
|
1032
|
-
);
|
|
1033
|
-
}
|
|
1034
|
-
async rawRequest(endpoint, method = "POST", data, params) {
|
|
1035
|
-
return this.client.rawRequest(
|
|
1036
|
-
`/research/v1${endpoint}`,
|
|
1037
|
-
method,
|
|
1038
|
-
data,
|
|
1039
|
-
params
|
|
1040
|
-
);
|
|
1041
|
-
}
|
|
1042
|
-
buildPaginationParams(pagination) {
|
|
1043
|
-
const params = {};
|
|
1044
|
-
if (!pagination) return params;
|
|
1045
|
-
if (pagination.cursor) params.cursor = pagination.cursor;
|
|
1046
|
-
if (pagination.limit) params.limit = pagination.limit;
|
|
1047
|
-
return params;
|
|
1048
|
-
}
|
|
1049
|
-
};
|
|
1050
|
-
|
|
1051
|
-
// src/research/client.ts
|
|
1052
|
-
var ResearchClient = class extends ResearchBaseClient {
|
|
1053
|
-
constructor(client) {
|
|
1054
|
-
super(client);
|
|
1055
|
-
}
|
|
1056
|
-
async create(params) {
|
|
1057
|
-
const { instructions, model, outputSchema } = params;
|
|
1058
|
-
let schema = outputSchema;
|
|
1059
|
-
if (schema && isZodSchema(schema)) {
|
|
1060
|
-
schema = zodToJsonSchema(schema);
|
|
1061
|
-
}
|
|
1062
|
-
const payload = {
|
|
1063
|
-
instructions,
|
|
1064
|
-
model: model ?? "exa-research"
|
|
1065
|
-
};
|
|
1066
|
-
if (schema) {
|
|
1067
|
-
payload.outputSchema = schema;
|
|
1068
|
-
}
|
|
1069
|
-
return this.request("", "POST", payload);
|
|
1070
|
-
}
|
|
1071
|
-
get(researchId, options) {
|
|
1072
|
-
if (options?.stream) {
|
|
1073
|
-
const promise = async () => {
|
|
1074
|
-
const params = { stream: "true" };
|
|
1075
|
-
if (options.events !== void 0) {
|
|
1076
|
-
params.events = options.events.toString();
|
|
1077
|
-
}
|
|
1078
|
-
const resp = await this.rawRequest(
|
|
1079
|
-
`/${researchId}`,
|
|
1080
|
-
"GET",
|
|
1081
|
-
void 0,
|
|
1082
|
-
params
|
|
1083
|
-
);
|
|
1084
|
-
if (!resp.body) {
|
|
1085
|
-
throw new Error("No response body for SSE stream");
|
|
1086
|
-
}
|
|
1087
|
-
const reader = resp.body.getReader();
|
|
1088
|
-
const decoder = new TextDecoder();
|
|
1089
|
-
let buffer = "";
|
|
1090
|
-
function processPart(part) {
|
|
1091
|
-
const lines = part.split("\n");
|
|
1092
|
-
let data = lines.slice(1).join("\n");
|
|
1093
|
-
if (data.startsWith("data:")) {
|
|
1094
|
-
data = data.slice(5).trimStart();
|
|
1095
|
-
}
|
|
1096
|
-
try {
|
|
1097
|
-
return JSON.parse(data);
|
|
1098
|
-
} catch (e) {
|
|
1099
|
-
return null;
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
async function* streamEvents() {
|
|
1103
|
-
while (true) {
|
|
1104
|
-
const { done, value } = await reader.read();
|
|
1105
|
-
if (done) break;
|
|
1106
|
-
buffer += decoder.decode(value, { stream: true });
|
|
1107
|
-
let parts = buffer.split("\n\n");
|
|
1108
|
-
buffer = parts.pop() ?? "";
|
|
1109
|
-
for (const part of parts) {
|
|
1110
|
-
const processed = processPart(part);
|
|
1111
|
-
if (processed) {
|
|
1112
|
-
yield processed;
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
if (buffer.trim()) {
|
|
1117
|
-
const processed = processPart(buffer.trim());
|
|
1118
|
-
if (processed) {
|
|
1119
|
-
yield processed;
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
return streamEvents();
|
|
1124
|
-
};
|
|
1125
|
-
return promise();
|
|
1126
|
-
} else {
|
|
1127
|
-
const params = { stream: "false" };
|
|
1128
|
-
if (options?.events !== void 0) {
|
|
1129
|
-
params.events = options.events.toString();
|
|
1130
|
-
}
|
|
1131
|
-
return this.request(
|
|
1132
|
-
`/${researchId}`,
|
|
1133
|
-
"GET",
|
|
1134
|
-
void 0,
|
|
1135
|
-
params
|
|
1136
|
-
);
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
async list(options) {
|
|
1140
|
-
const params = this.buildPaginationParams(options);
|
|
1141
|
-
return this.request("", "GET", void 0, params);
|
|
1142
|
-
}
|
|
1143
|
-
async pollUntilFinished(researchId, options) {
|
|
1144
|
-
const pollInterval = options?.pollInterval ?? 1e3;
|
|
1145
|
-
const timeoutMs = options?.timeoutMs ?? 10 * 60 * 1e3;
|
|
1146
|
-
const maxConsecutiveFailures = 5;
|
|
1147
|
-
const startTime = Date.now();
|
|
1148
|
-
let consecutiveFailures = 0;
|
|
1149
|
-
while (true) {
|
|
1150
|
-
try {
|
|
1151
|
-
const research = await this.get(researchId, {
|
|
1152
|
-
events: options?.events
|
|
1153
|
-
});
|
|
1154
|
-
consecutiveFailures = 0;
|
|
1155
|
-
if (research.status === "completed" || research.status === "failed" || research.status === "canceled") {
|
|
1156
|
-
return research;
|
|
1157
|
-
}
|
|
1158
|
-
} catch (err) {
|
|
1159
|
-
consecutiveFailures += 1;
|
|
1160
|
-
if (consecutiveFailures >= maxConsecutiveFailures) {
|
|
1161
|
-
throw new Error(
|
|
1162
|
-
`Polling failed ${maxConsecutiveFailures} times in a row for research ${researchId}: ${err}`
|
|
1163
|
-
);
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
if (Date.now() - startTime > timeoutMs) {
|
|
1167
|
-
throw new Error(
|
|
1168
|
-
`Polling timeout: Research ${researchId} did not complete within ${timeoutMs}ms`
|
|
1169
|
-
);
|
|
1170
|
-
}
|
|
1171
|
-
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
};
|
|
1175
|
-
|
|
1176
1259
|
// src/index.ts
|
|
1177
1260
|
var fetchImpl = typeof global !== "undefined" && global.fetch ? global.fetch : fetch2;
|
|
1178
1261
|
var HeadersImpl = typeof global !== "undefined" && global.Headers ? global.Headers : Headers;
|
|
@@ -1241,7 +1324,7 @@ var Exa2 = class {
|
|
|
1241
1324
|
this.headers = new HeadersImpl({
|
|
1242
1325
|
"x-api-key": apiKey,
|
|
1243
1326
|
"Content-Type": "application/json",
|
|
1244
|
-
"User-Agent":
|
|
1327
|
+
"User-Agent": `exa-node ${package_default.version}`
|
|
1245
1328
|
});
|
|
1246
1329
|
this.websets = new WebsetsClient(this);
|
|
1247
1330
|
this.research = new ResearchClient(this);
|