@botpress/zai 2.4.1 → 2.5.0

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/response.js CHANGED
@@ -29,19 +29,104 @@ export class Response {
29
29
  this._eventEmitter.emit("progress", usage);
30
30
  });
31
31
  }
32
- // Event emitter methods
32
+ /**
33
+ * Subscribes to events emitted during operation execution.
34
+ *
35
+ * @param type - Event type: 'progress', 'complete', or 'error'
36
+ * @param listener - Callback function to handle the event
37
+ * @returns This Response instance for chaining
38
+ *
39
+ * @example Track progress
40
+ * ```typescript
41
+ * response.on('progress', (usage) => {
42
+ * console.log(`${usage.requests.percentage * 100}% complete`)
43
+ * console.log(`Cost: $${usage.cost.total}`)
44
+ * })
45
+ * ```
46
+ *
47
+ * @example Handle completion
48
+ * ```typescript
49
+ * response.on('complete', (result) => {
50
+ * console.log('Operation completed:', result)
51
+ * })
52
+ * ```
53
+ *
54
+ * @example Handle errors
55
+ * ```typescript
56
+ * response.on('error', (error) => {
57
+ * console.error('Operation failed:', error)
58
+ * })
59
+ * ```
60
+ */
33
61
  on(type, listener) {
34
62
  this._eventEmitter.on(type, listener);
35
63
  return this;
36
64
  }
65
+ /**
66
+ * Unsubscribes from events.
67
+ *
68
+ * @param type - Event type to unsubscribe from
69
+ * @param listener - The exact listener function to remove
70
+ * @returns This Response instance for chaining
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const progressHandler = (usage) => console.log(usage.tokens.total)
75
+ * response.on('progress', progressHandler)
76
+ * // Later...
77
+ * response.off('progress', progressHandler)
78
+ * ```
79
+ */
37
80
  off(type, listener) {
38
81
  this._eventEmitter.off(type, listener);
39
82
  return this;
40
83
  }
84
+ /**
85
+ * Subscribes to an event for a single emission.
86
+ *
87
+ * The listener is automatically removed after being called once.
88
+ *
89
+ * @param type - Event type: 'progress', 'complete', or 'error'
90
+ * @param listener - Callback function to handle the event once
91
+ * @returns This Response instance for chaining
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * response.once('complete', (result) => {
96
+ * console.log('Finished:', result)
97
+ * })
98
+ * ```
99
+ */
41
100
  once(type, listener) {
42
101
  this._eventEmitter.once(type, listener);
43
102
  return this;
44
103
  }
104
+ /**
105
+ * Binds an external AbortSignal to this operation.
106
+ *
107
+ * When the signal is aborted, the operation will be cancelled automatically.
108
+ * Useful for integrating with UI cancel buttons or request timeouts.
109
+ *
110
+ * @param signal - AbortSignal to bind
111
+ * @returns This Response instance for chaining
112
+ *
113
+ * @example With AbortController
114
+ * ```typescript
115
+ * const controller = new AbortController()
116
+ * const response = zai.extract(data, schema).bindSignal(controller.signal)
117
+ *
118
+ * // Cancel from elsewhere
119
+ * cancelButton.onclick = () => controller.abort()
120
+ * ```
121
+ *
122
+ * @example With timeout
123
+ * ```typescript
124
+ * const controller = new AbortController()
125
+ * setTimeout(() => controller.abort('Timeout'), 10000)
126
+ *
127
+ * const response = zai.answer(docs, question).bindSignal(controller.signal)
128
+ * ```
129
+ */
45
130
  bindSignal(signal) {
46
131
  if (signal.aborted) {
47
132
  this.abort(signal.reason);
@@ -54,9 +139,48 @@ export class Response {
54
139
  void this.once("error", () => signal.removeEventListener("abort", signalAbort));
55
140
  return this;
56
141
  }
142
+ /**
143
+ * Aborts the operation in progress.
144
+ *
145
+ * The operation will be cancelled and throw an abort error.
146
+ * Any partial results will not be returned.
147
+ *
148
+ * @param reason - Optional reason for aborting (string or Error)
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const response = zai.extract(largeDocument, schema)
153
+ *
154
+ * // Abort after 5 seconds
155
+ * setTimeout(() => response.abort('Operation timeout'), 5000)
156
+ *
157
+ * try {
158
+ * await response
159
+ * } catch (error) {
160
+ * console.log('Aborted:', error)
161
+ * }
162
+ * ```
163
+ */
57
164
  abort(reason) {
58
165
  this._context.controller.abort(reason);
59
166
  }
167
+ /**
168
+ * Promise interface - allows awaiting the Response.
169
+ *
170
+ * When awaited, returns the simplified value (S).
171
+ * Use `.result()` for full output with usage statistics.
172
+ *
173
+ * @param onfulfilled - Success handler
174
+ * @param onrejected - Error handler
175
+ * @returns Promise resolving to simplified value
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * // Simplified value
180
+ * const isPositive = await zai.check(review, 'Is positive?')
181
+ * console.log(isPositive) // true
182
+ * ```
183
+ */
60
184
  // oxlint-disable-next-line no-thenable
61
185
  then(onfulfilled, onrejected) {
62
186
  return this._promise.then(
@@ -72,9 +196,50 @@ export class Response {
72
196
  }
73
197
  );
74
198
  }
199
+ /**
200
+ * Promise interface - handles errors.
201
+ *
202
+ * @param onrejected - Error handler
203
+ * @returns Promise resolving to simplified value or error result
204
+ */
75
205
  catch(onrejected) {
76
206
  return this._promise.catch(onrejected);
77
207
  }
208
+ /**
209
+ * Gets the full result with detailed usage statistics and timing.
210
+ *
211
+ * Unlike awaiting the Response directly (which returns simplified value),
212
+ * this method provides:
213
+ * - `output`: Full operation result (not simplified)
214
+ * - `usage`: Detailed token usage, cost, and request statistics
215
+ * - `elapsed`: Operation duration in milliseconds
216
+ *
217
+ * @returns Promise resolving to full result object
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * const { output, usage, elapsed } = await zai.check(text, condition).result()
222
+ *
223
+ * console.log(output.value) // true/false
224
+ * console.log(output.explanation) // "The text expresses..."
225
+ * console.log(usage.tokens.total) // 245
226
+ * console.log(usage.cost.total) // 0.0012
227
+ * console.log(elapsed) // 1523 (ms)
228
+ * ```
229
+ *
230
+ * @example Usage statistics breakdown
231
+ * ```typescript
232
+ * const { usage } = await response.result()
233
+ *
234
+ * console.log('Requests:', usage.requests.requests)
235
+ * console.log('Cached:', usage.requests.cached)
236
+ * console.log('Input tokens:', usage.tokens.input)
237
+ * console.log('Output tokens:', usage.tokens.output)
238
+ * console.log('Input cost:', usage.cost.input)
239
+ * console.log('Output cost:', usage.cost.output)
240
+ * console.log('Total cost:', usage.cost.total)
241
+ * ```
242
+ */
78
243
  async result() {
79
244
  const output = await this._promise;
80
245
  const usage = this._context.usage;
package/dist/zai.js CHANGED
@@ -47,6 +47,27 @@ export class Zai {
47
47
  namespace;
48
48
  adapter;
49
49
  activeLearning;
50
+ /**
51
+ * Creates a new Zai instance with the specified configuration.
52
+ *
53
+ * @param config - Configuration object containing client, model, and learning settings
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * import { Client } from '@botpress/client'
58
+ * import { Zai } from '@botpress/zai'
59
+ *
60
+ * const client = new Client({ token: 'your-token' })
61
+ * const zai = new Zai({
62
+ * client,
63
+ * modelId: 'best',
64
+ * namespace: 'my-app',
65
+ * userId: 'user-123'
66
+ * })
67
+ * ```
68
+ *
69
+ * @throws {Error} If the configuration is invalid (e.g., invalid modelId format)
70
+ */
50
71
  constructor(config) {
51
72
  this._originalConfig = config;
52
73
  const parsed = _ZaiConfig.parse(config);
@@ -89,12 +110,97 @@ export class Zai {
89
110
  }
90
111
  return `${this.namespace}/${this.activeLearning.taskId}`.replace(/\/+/g, "/");
91
112
  }
113
+ /**
114
+ * Creates a new Zai instance with merged configuration options.
115
+ *
116
+ * This method allows you to create variations of your Zai instance with different
117
+ * settings without modifying the original. Useful for switching models, namespaces,
118
+ * or other configuration on a per-operation basis.
119
+ *
120
+ * @param options - Partial configuration to override the current settings
121
+ * @returns A new Zai instance with the merged configuration
122
+ *
123
+ * @example Switch to a faster model
124
+ * ```typescript
125
+ * const zai = new Zai({ client })
126
+ *
127
+ * // Use fast model for simple operations
128
+ * const fastZai = zai.with({ modelId: 'fast' })
129
+ * await fastZai.check(text, 'Is this spam?')
130
+ *
131
+ * // Use best model for complex operations
132
+ * const bestZai = zai.with({ modelId: 'best' })
133
+ * await bestZai.extract(document, complexSchema)
134
+ * ```
135
+ *
136
+ * @example Change namespace
137
+ * ```typescript
138
+ * const customerZai = zai.with({ namespace: 'customer-support' })
139
+ * const salesZai = zai.with({ namespace: 'sales' })
140
+ * ```
141
+ *
142
+ * @example Use specific model
143
+ * ```typescript
144
+ * const gpt4 = zai.with({ modelId: 'openai:gpt-4' })
145
+ * const claude = zai.with({ modelId: 'anthropic:claude-3-5-sonnet-20241022' })
146
+ * ```
147
+ */
92
148
  with(options) {
93
149
  return new Zai({
94
150
  ...this._originalConfig,
95
151
  ...options
96
152
  });
97
153
  }
154
+ /**
155
+ * Creates a new Zai instance with active learning enabled for a specific task.
156
+ *
157
+ * Active learning stores successful operation results and uses them as examples for
158
+ * future operations, improving accuracy and consistency over time. Each task ID
159
+ * maintains its own set of learned examples.
160
+ *
161
+ * @param taskId - Unique identifier for the learning task (alphanumeric, hyphens, underscores, slashes)
162
+ * @returns A new Zai instance with active learning enabled for the specified task
163
+ *
164
+ * @example Sentiment analysis with learning
165
+ * ```typescript
166
+ * const zai = new Zai({
167
+ * client,
168
+ * activeLearning: {
169
+ * enable: false,
170
+ * tableName: 'AppLearningTable',
171
+ * taskId: 'default'
172
+ * }
173
+ * })
174
+ *
175
+ * // Enable learning for sentiment analysis
176
+ * const sentimentZai = zai.learn('sentiment-analysis')
177
+ * const result = await sentimentZai.check(review, 'Is this review positive?')
178
+ *
179
+ * // Each successful call is stored and used to improve future calls
180
+ * ```
181
+ *
182
+ * @example Different tasks for different purposes
183
+ * ```typescript
184
+ * // Extract user info with learning
185
+ * const userExtractor = zai.learn('user-extraction')
186
+ * await userExtractor.extract(text, userSchema)
187
+ *
188
+ * // Extract product info with separate learning
189
+ * const productExtractor = zai.learn('product-extraction')
190
+ * await productExtractor.extract(text, productSchema)
191
+ *
192
+ * // Each task learns independently
193
+ * ```
194
+ *
195
+ * @example Combining with other configuration
196
+ * ```typescript
197
+ * // Use fast model + learning
198
+ * const fastLearner = zai.with({ modelId: 'fast' }).learn('quick-checks')
199
+ * await fastLearner.check(email, 'Is this spam?')
200
+ * ```
201
+ *
202
+ * @see {@link ZaiConfig.activeLearning} for configuration options
203
+ */
98
204
  learn(taskId) {
99
205
  return new Zai({
100
206
  ...this._originalConfig,