exa-js 1.7.0 → 1.7.1

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 CHANGED
@@ -8,71 +8,91 @@ features associated with Metaphor's rename to Exa. New site is https://exa.ai
8
8
  https://www.npmjs.com/package/exa-js
9
9
 
10
10
  ## Installation
11
+
11
12
  ```
12
13
  npm install exa-js
13
14
  ```
14
15
 
15
- ## Initialization
16
+ ## Initialization
17
+
16
18
  ```js
17
- import Exa from "exa-js"
19
+ import Exa from "exa-js";
18
20
 
19
- const exa = new Exa(process.env.EXA_API_KEY)
21
+ const exa = new Exa(process.env.EXA_API_KEY);
20
22
  ```
21
23
 
22
24
  ### Common commands
23
25
 
24
26
  ```js
25
-
26
27
  // Basic search
27
28
  const basicResults = await exa.search("This is a Exa query:");
28
29
 
29
30
  // Search with date filters
30
31
  const dateFilteredResults = await exa.search("This is a Exa query:", {
31
32
  startPublishedDate: "2019-01-01",
32
- endPublishedDate: "2019-01-31"
33
+ endPublishedDate: "2019-01-31",
33
34
  });
34
35
 
35
36
  // Search with domain filters
36
37
  const domainFilteredResults = await exa.search("This is a Exa query:", {
37
- includeDomains: ["www.cnn.com", "www.nytimes.com"]
38
+ includeDomains: ["www.cnn.com", "www.nytimes.com"],
38
39
  });
39
40
 
40
41
  // Search and get text contents
41
- const searchAndTextResults = await exa.searchAndContents("This is a Exa query:", { text: true });
42
+ const searchAndTextResults = await exa.searchAndContents(
43
+ "This is a Exa query:",
44
+ { text: true }
45
+ );
42
46
 
43
47
  // Search and get contents with contents options
44
- const searchAndCustomContentsResults = await exa.searchAndContents("This is a Exa query:", {
45
- text: { maxCharacters: 3000 }
46
- });
48
+ const searchAndCustomContentsResults = await exa.searchAndContents(
49
+ "This is a Exa query:",
50
+ {
51
+ text: { maxCharacters: 3000 },
52
+ }
53
+ );
47
54
 
48
55
  // Find similar documents
49
56
  const similarResults = await exa.findSimilar("https://example.com");
50
57
 
51
58
  // Find similar excluding source domain
52
- const similarExcludingSourceResults = await exa.findSimilar("https://example.com", { excludeSourceDomain: true });
59
+ const similarExcludingSourceResults = await exa.findSimilar(
60
+ "https://example.com",
61
+ { excludeSourceDomain: true }
62
+ );
53
63
 
54
64
  // Find similar with contents
55
- const similarWithContentsResults = await exa.findSimilarAndContents("https://example.com", { text: true });
65
+ const similarWithContentsResults = await exa.findSimilarAndContents(
66
+ "https://example.com",
67
+ { text: true }
68
+ );
56
69
 
57
70
  // Get text contents
58
71
  const textContentsResults = await exa.getContents(["urls"], { text: true });
59
72
 
60
73
  // Get contents with contents options
61
74
  const customContentsResults = await exa.getContents(["urls"], {
62
- text: { includeHtmlTags: true, maxCharacters: 3000 }
75
+ text: { includeHtmlTags: true, maxCharacters: 3000 },
63
76
  });
64
77
 
65
78
  // Get an answer to a question
66
- const answerResult = await exa.answer("What is the population of New York City?");
67
-
68
- // Get answer with citation contents and use the exa-pro model, which passes 2 extra queries to exa to increase coverage of the search space.
69
- const answerWithTextResults = await exa.answer("What is the population of New York City?", {
70
- text: true,
71
- model: "exa-pro"
72
- });
79
+ const answerResult = await exa.answer(
80
+ "What is the population of New York City?"
81
+ );
82
+
83
+ // Get answer with citation contents and use the exa-pro model, which passes 2 extra queries to exa to increase coverage of the search space.
84
+ const answerWithTextResults = await exa.answer(
85
+ "What is the population of New York City?",
86
+ {
87
+ text: true,
88
+ model: "exa-pro",
89
+ }
90
+ );
73
91
 
74
92
  // Get an answer with streaming
75
- for await (const chunk of exa.streamAnswer("What is the population of New York City?")) {
93
+ for await (const chunk of exa.streamAnswer(
94
+ "What is the population of New York City?"
95
+ )) {
76
96
  if (chunk.content) {
77
97
  process.stdout.write(chunk.content);
78
98
  }
@@ -80,45 +100,72 @@ for await (const chunk of exa.streamAnswer("What is the population of New York C
80
100
  console.log("\nCitations:", chunk.citations);
81
101
  }
82
102
  }
103
+
104
+ // Get an answer with output schema
105
+ const answerResult = await exa.answer(
106
+ "What is the population of New York City?",
107
+ {
108
+ outputSchema: {
109
+ type: "object",
110
+ required: ["answer"],
111
+ additionalProperties: false,
112
+ properties: {
113
+ answer: {
114
+ type: "number",
115
+ },
116
+ },
117
+ },
118
+ }
119
+ );
83
120
  ```
84
121
 
85
122
  ### `exa.search(query: string, options?: SearchOptions): Promise<SearchResponse>`
123
+
86
124
  Performs a search on the Exa system with the given parameters.
87
125
 
88
126
  ```javascript
89
- const response = await exa.search('funny article about tech culture', {
127
+ const response = await exa.search("funny article about tech culture", {
90
128
  numResults: 5,
91
- includeDomains: ['nytimes.com', 'wsj.com'],
92
- startPublishedDate: '2023-06-12'
129
+ includeDomains: ["nytimes.com", "wsj.com"],
130
+ startPublishedDate: "2023-06-12",
93
131
  });
94
132
  ```
95
133
 
96
134
  ### `exa.findSimilar(url: string, options?: FindSimilarOptions): Promise<SearchResponse>`
135
+
97
136
  Finds content similar to the specified URL.
98
137
 
99
138
  ```javascript
100
- const response = await exa.findSimilar('https://waitbutwhy.com/2014/05/fermi-paradox.html', {
101
- numResults: 10
102
- });
139
+ const response = await exa.findSimilar(
140
+ "https://waitbutwhy.com/2014/05/fermi-paradox.html",
141
+ {
142
+ numResults: 10,
143
+ }
144
+ );
103
145
  ```
104
146
 
105
147
  ### `exa.getContents(urls: string[] | Result[]): Promise<GetContentsResponse>`
148
+
106
149
  Retrieves the contents of the specified documents.
107
150
 
108
151
  ```javascript
109
- const response = await exa.getContents(['https://blog.samaltman.com/how-to-be-successful']);
152
+ const response = await exa.getContents([
153
+ "https://blog.samaltman.com/how-to-be-successful",
154
+ ]);
110
155
  ```
111
156
 
112
157
  ### `exa.answer(query: string, options?: AnswerOptions): Promise<AnswerResponse>`
158
+
113
159
  Generates an answer to a query using search results as context.
114
160
 
115
161
  ```javascript
116
- const response = await exa.answer('What is the population of New York City?', {
117
- text: true
162
+ const response = await exa.answer("What is the population of New York City?", {
163
+ text: true,
118
164
  });
119
165
  ```
120
166
 
121
167
  ### `exa.streamAnswer(query: string, options?: { text?: boolean }): AsyncGenerator<AnswerStreamChunk>`
168
+
122
169
  Streams an answer as it's being generated, yielding chunks of text and citations. This is useful for providing real-time updates in chat interfaces or displaying partial results as they become available.
123
170
 
124
171
  ```javascript
@@ -132,13 +179,17 @@ for await (const chunk of exa.streamAnswer("What is quantum computing?")) {
132
179
  }
133
180
  }
134
181
 
135
- for await (const chunk of exa.streamAnswer("What is quantum computing?", { text: true })) {
182
+ for await (const chunk of exa.streamAnswer("What is quantum computing?", {
183
+ text: true,
184
+ })) {
136
185
  }
137
186
  ```
138
187
 
139
188
  Each chunk contains:
189
+
140
190
  - `content`: A string containing the next piece of generated text
141
191
  - `citations`: An array of citation objects containing source information
142
192
 
143
193
  # Contributing
194
+
144
195
  Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.
package/dist/index.d.mts CHANGED
@@ -1644,23 +1644,25 @@ type SearchResponse<T extends ContentsOptions> = {
1644
1644
  * @property {boolean} [text] - Whether to include text in the source results. Default false.
1645
1645
  * @property {"exa" | "exa-pro"} [model] - The model to use for generating the answer. Default "exa".
1646
1646
  * @property {string} [systemPrompt] - A system prompt to guide the LLM's behavior when generating the answer.
1647
+ * @property {Object} [outputSchema] - A JSON Schema specification for the structure you expect the output to take
1647
1648
  */
1648
1649
  type AnswerOptions = {
1649
1650
  stream?: boolean;
1650
1651
  text?: boolean;
1651
1652
  model?: "exa" | "exa-pro";
1652
1653
  systemPrompt?: string;
1654
+ outputSchema?: Record<string, unknown>;
1653
1655
  };
1654
1656
  /**
1655
1657
  * Represents an answer response object from the /answer endpoint.
1656
1658
  * @typedef {Object} AnswerResponse
1657
- * @property {string} answer - The generated answer text.
1659
+ * @property {string | Object} answer - The generated answer text (or an object matching `outputSchema`, if provided)
1658
1660
  * @property {SearchResult<{}>[]} citations - The sources used to generate the answer.
1659
1661
  * @property {CostDollars} [costDollars] - The cost breakdown for this request.
1660
1662
  * @property {string} [requestId] - Optional request ID for the answer.
1661
1663
  */
1662
1664
  type AnswerResponse = {
1663
- answer: string;
1665
+ answer: string | Record<string, unknown>;
1664
1666
  citations: SearchResult<{}>[];
1665
1667
  requestId?: string;
1666
1668
  costDollars?: CostDollars;
@@ -1828,6 +1830,7 @@ declare class Exa {
1828
1830
  text?: boolean;
1829
1831
  model?: "exa" | "exa-pro";
1830
1832
  systemPrompt?: string;
1833
+ outputSchema?: Record<string, unknown>;
1831
1834
  }): AsyncGenerator<AnswerStreamChunk>;
1832
1835
  private processChunk;
1833
1836
  /**
package/dist/index.d.ts CHANGED
@@ -1644,23 +1644,25 @@ type SearchResponse<T extends ContentsOptions> = {
1644
1644
  * @property {boolean} [text] - Whether to include text in the source results. Default false.
1645
1645
  * @property {"exa" | "exa-pro"} [model] - The model to use for generating the answer. Default "exa".
1646
1646
  * @property {string} [systemPrompt] - A system prompt to guide the LLM's behavior when generating the answer.
1647
+ * @property {Object} [outputSchema] - A JSON Schema specification for the structure you expect the output to take
1647
1648
  */
1648
1649
  type AnswerOptions = {
1649
1650
  stream?: boolean;
1650
1651
  text?: boolean;
1651
1652
  model?: "exa" | "exa-pro";
1652
1653
  systemPrompt?: string;
1654
+ outputSchema?: Record<string, unknown>;
1653
1655
  };
1654
1656
  /**
1655
1657
  * Represents an answer response object from the /answer endpoint.
1656
1658
  * @typedef {Object} AnswerResponse
1657
- * @property {string} answer - The generated answer text.
1659
+ * @property {string | Object} answer - The generated answer text (or an object matching `outputSchema`, if provided)
1658
1660
  * @property {SearchResult<{}>[]} citations - The sources used to generate the answer.
1659
1661
  * @property {CostDollars} [costDollars] - The cost breakdown for this request.
1660
1662
  * @property {string} [requestId] - Optional request ID for the answer.
1661
1663
  */
1662
1664
  type AnswerResponse = {
1663
- answer: string;
1665
+ answer: string | Record<string, unknown>;
1664
1666
  citations: SearchResult<{}>[];
1665
1667
  requestId?: string;
1666
1668
  costDollars?: CostDollars;
@@ -1828,6 +1830,7 @@ declare class Exa {
1828
1830
  text?: boolean;
1829
1831
  model?: "exa" | "exa-pro";
1830
1832
  systemPrompt?: string;
1833
+ outputSchema?: Record<string, unknown>;
1831
1834
  }): AsyncGenerator<AnswerStreamChunk>;
1832
1835
  private processChunk;
1833
1836
  /**
package/dist/index.js CHANGED
@@ -915,7 +915,8 @@ var Exa2 = class {
915
915
  stream: false,
916
916
  text: options?.text ?? false,
917
917
  model: options?.model ?? "exa",
918
- systemPrompt: options?.systemPrompt
918
+ systemPrompt: options?.systemPrompt,
919
+ outputSchema: options?.outputSchema
919
920
  };
920
921
  return await this.request("/answer", "POST", requestBody);
921
922
  }
@@ -944,7 +945,8 @@ var Exa2 = class {
944
945
  text: options?.text ?? false,
945
946
  stream: true,
946
947
  model: options?.model ?? "exa",
947
- systemPrompt: options?.systemPrompt
948
+ systemPrompt: options?.systemPrompt,
949
+ outputSchema: options?.outputSchema
948
950
  };
949
951
  const response = await fetchImpl(this.baseURL + "/answer", {
950
952
  method: "POST",