ai-tool-set 0.1.0-alpha.3 → 0.1.0-alpha.4

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
@@ -58,58 +58,53 @@ const tools = {
58
58
  const toolSet = createToolSet({ tools });
59
59
  ```
60
60
 
61
- ### Use with `generateText` / `streamText`
61
+ ### Activate and Deactivate Tools
62
62
 
63
- The tool set exposes `tools` and `activeTools` as properties that can be used directly:
63
+ Use `.activate()` and `.deactivate()` to statically control which tools are available. Call `.inferTools()` to resolve `activeTools` and pass into `generateText()` or `streamText()`:
64
64
 
65
65
  ```typescript
66
66
  import { generateText } from 'ai';
67
67
 
68
- const { tools, activeTools } = toolSet;
69
-
70
- const result = await generateText({
71
- model,
72
- tools,
73
- activeTools,
74
- // Or spread tool set directly:
75
- // ...toolSet,
76
- prompt: 'Hello',
77
- });
78
- ```
79
-
80
- ### Activate and Deactivate Tools
81
-
82
- Use `.activate()` and `.deactivate()` to statically control which tools are available:
68
+ // Activate and deactivate tools
69
+ const toolSet = createToolSet({ tools })
70
+ .deactivate(['cancel_order'])
71
+ .activate(['list_orders']);
83
72
 
84
- ```typescript
85
- const { tools, activeTools } = toolSet.deactivate(['cancel_order']).activate(['list_orders']);
73
+ // Infer active tools
74
+ const { tools, activeTools } = toolSet.inferTools();
86
75
 
87
76
  const result = await generateText({
88
77
  model,
78
+ // Pass tools and activeTools:
89
79
  tools,
90
80
  activeTools,
81
+ // Or spread directly:
82
+ // ...toolSet.deactivate(['cancel_order']).activate(['list_orders']).inferTools(),
91
83
  prompt: 'Show me my orders',
92
84
  });
93
85
  ```
94
86
 
95
87
  ### Conditional Activation
96
88
 
97
- Use `.activateWhen()` and `.deactivateWhen()` to conditionally control tools based on messages and context. The predicate receives an `ActivationInput` with `messages` and `context`.
89
+ Use `.activateWhen()` and `.deactivateWhen()` to conditionally control tools based on messages and context. The predicate receives an input with `messages` and `context` (both can be `undefined` if not provided to `inferTools`) and should return a boolean (or undefined) to determine whether the tool should be activated/deactivated.
98
90
 
99
91
  ```typescript
100
- const toolSet = createToolSet({ tools }).activateWhen('cancel_order', ({ messages }) =>
101
- messages.some((m) =>
102
- m.parts.some(
103
- (p) =>
104
- p.type === 'tool-list_orders' &&
105
- p.state === 'output-available' &&
106
- p.output.orders?.some((order) => order.status !== 'fulfilled'),
92
+ // Conditional activation with a predicate that checks for unfulfilled orders in the messages
93
+ const toolSet = createToolSet({ tools })
94
+ .activateWhen('list_orders', ({ context }) => context?.isAuthenticated)
95
+ .activateWhen('cancel_order', ({ messages }) =>
96
+ messages?.some((m) =>
97
+ m.parts.some(
98
+ (p) =>
99
+ p.type === 'tool-list_orders' &&
100
+ p.state === 'output-available' &&
101
+ p.output.orders?.some((order) => order.status !== 'fulfilled'),
102
+ ),
107
103
  ),
108
- ),
109
- );
104
+ );
110
105
  ```
111
106
 
112
- Use `.inferTools()` to evaluate predicates with the current messages and context. It returns `{ tools, activeTools }` that can be spread directly into `generateText()`:
107
+ Call `.inferTools()` with messages and/or context to evaluate activation predicates and resolve `activeTools`:
113
108
 
114
109
  ```typescript
115
110
  const messages = [
@@ -136,8 +131,10 @@ const messages = [
136
131
  },
137
132
  ];
138
133
 
134
+ const context = { isAuthenticated: true };
135
+
139
136
  // cancel_order is now active because list_orders returned unfulfilled orders
140
- const { tools, activeTools } = toolSet.inferTools({ messages, context: {} });
137
+ const { tools, activeTools } = toolSet.inferTools({ messages, context });
141
138
 
142
139
  const result = await generateText({ model, tools, activeTools, messages });
143
140
  ```
@@ -145,26 +142,53 @@ const result = await generateText({ model, tools, activeTools, messages });
145
142
  You can also activate multiple tools at once:
146
143
 
147
144
  ```typescript
148
- const toolSet = createToolSet({ tools }).activateWhen({
149
- list_orders: ({ context }) => context.isAuthenticated,
150
- cancel_order: ({ messages }) => hasUnfulfilledOrders(messages),
151
- });
145
+ const toolSet = createToolSet({ tools })
146
+ .activateWhen({
147
+ list_orders: ({ context }) => context?.isAuthenticated,
148
+ cancel_order: ({ messages }) => hasUnfulfilledOrders(messages),
149
+ });
150
+ ```
151
+
152
+ ### Activation Defaults
153
+
154
+ `.activateWhen()` marks a tool as **inactive by default**. It only becomes active when the predicate returns `true`. If the predicate returns `undefined` or `false`, the tool stays inactive:
155
+
156
+ ```typescript
157
+ const toolSet = createToolSet({ tools })
158
+ // undefined when messages is not provided → tool stays inactive
159
+ // false when no orders found → tool stays inactive
160
+ // true when orders found → tool becomes active
161
+ .activateWhen('cancel_order', ({ messages }) => messages?.some((m) => hasOrders(m)));
162
+
163
+ toolSet.inferTools().activeTools; // cancel_order is inactive (predicate received undefined)
164
+ toolSet.inferTools({ messages: [] }).activeTools; // cancel_order is inactive (no orders)
165
+ ```
166
+
167
+ `.deactivateWhen()` marks a tool as **active by default**. It only becomes inactive when the predicate returns `true`. If the predicate returns `undefined` or `false`, the tool stays active:
168
+
169
+ ```typescript
170
+ const toolSet = createToolSet({ tools })
171
+ // undefined when messages is not provided → tool stays active
172
+ // false when few messages → tool stays active
173
+ // true when too many messages → tool becomes inactive
174
+ .deactivateWhen('search', ({ messages }) => messages && messages.length > 10);
175
+
176
+ toolSet.inferTools().activeTools; // search is active (predicate received undefined)
177
+ toolSet.inferTools({ messages: [] }).activeTools; // search is active (few messages)
152
178
  ```
153
179
 
154
180
  ### Last-Call Wins
155
181
 
156
- Each method appends to an internal list. For each tool, the **last entry** determines its state. This makes ordering explicit and predictable:
182
+ Each activation method appends to an internal list. For each tool, the **last entry** determines its state. This makes ordering explicit and predictable:
157
183
 
158
184
  ```typescript
159
185
  const toolSet = createToolSet({ tools })
160
- .activate(['cancel_order']) // cancel_order: activated
161
- .deactivate(['cancel_order']) // cancel_order: deactivated
162
- .activateWhen(
163
- 'cancel_order',
164
- (
165
- { messages }, // cancel_order: conditional activation
166
- ) => hasUnfulfilledOrders(messages),
167
- );
186
+ // cancel_order: activated
187
+ .activate(['cancel_order'])
188
+ // cancel_order: deactivated
189
+ .deactivate(['cancel_order'])
190
+ // cancel_order: deactivated with conditional activation
191
+ .activateWhen('cancel_order', ({ messages }) => hasUnfulfilledOrders(messages));
168
192
  ```
169
193
 
170
194
  ### Immutable vs Mutable
@@ -182,42 +206,36 @@ export async function POST(req: Request) {
182
206
  // myToolSet !== toolSet, original toolSet is unchanged for next request
183
207
  const myToolSet = toolSet.activate(['list_orders']);
184
208
 
185
- const { tools, activeTools } = myToolSet;
186
-
187
209
  const result = await generateText({
188
210
  model,
189
- tools,
190
- activeTools,
211
+ ...myToolSet.inferTools({ messages }),
191
212
  messages,
192
213
  });
193
214
  }
194
215
  ```
195
216
 
196
- Pass `mutable: true` to get a **mutable** tool set where each method mutates in-place and returns `this` for chaining. This is useful when the tool set is created per-request in a local scope:
217
+ Use `createToolSet({ mutable: true })` to get a **mutable** tool set where each method mutates in-place and returns `this` for chaining. This is useful when the tool set is created per-request in a local scope:
197
218
 
198
219
  ```typescript
199
220
  export async function POST(req: Request) {
200
221
  const { messages } = await req.json();
201
222
 
202
223
  // Local scope: created and mutated per request
203
- const toolSet = createToolSet({ tools, mutable: true }).deactivate(['list_order', 'cancel_order']);
204
-
205
- // Activate list_orders only for this request
206
- // myToolSet === toolSet, original toolSet is mutated for this request
207
- const myToolSet = toolSet.activate(['list_orders']);
208
-
209
- const { tools, activeTools } = myToolSet;
224
+ const toolSet = createToolSet({ tools, mutable: true })
225
+ .deactivate(['list_order', 'cancel_order'])
226
+ .activate(['list_orders']);
210
227
 
211
228
  const result = await generateText({
212
229
  model,
213
- tools,
214
- activeTools,
230
+ ...toolSet.inferTools({ messages }),
215
231
  messages,
216
232
  });
217
233
  }
218
234
  ```
219
235
 
220
- Use `.clone()` to convert between immutable and mutable, preserving all activation entries:
236
+ ### Cloning
237
+
238
+ Use `.clone({ mutable?: boolean })` to convert between immutable and mutable, preserving all activation entries:
221
239
 
222
240
  ```typescript
223
241
  // Convert an immutable toolset to mutable
@@ -227,6 +245,29 @@ const mutableToolSet = toolSet.clone({ mutable: true });
227
245
  const immutableToolSet = mutableToolSet.clone();
228
246
  ```
229
247
 
248
+ This is useful when you want to create a base tool set in the global scope and clone it per request to add request-specific activation:
249
+
250
+ ```typescript
251
+ // Global scope: base tool set
252
+ const baseToolSet = createToolSet({ tools }).deactivate(['list_order', 'cancel_order']);
253
+
254
+ export async function POST(req: Request) {
255
+ const { messages } = await req.json();
256
+
257
+ // Clone the base tool set into a mutable instance for this request
258
+ const toolSet = baseToolSet.clone({ mutable: true });
259
+
260
+ // Activate list_orders only for this request
261
+ toolSet.activate(['list_orders']);
262
+
263
+ const result = await generateText({
264
+ model,
265
+ ...toolSet.inferTools({ messages }),
266
+ messages,
267
+ });
268
+ }
269
+ ```
270
+
230
271
  ### Typed UI Tool Set
231
272
 
232
273
  Use `InferUIToolSet` to get fully typed UI messages from your tool set:
@@ -256,14 +297,16 @@ If you already have a custom `UIMessage` type, you can pass it as `MESSAGE` gene
256
297
  import { myTools } from './my-tools.js';
257
298
  import { MyUIMessage } from './my-ui-message.js';
258
299
 
259
- const toolSet = createToolSet<typeof myTools, MyUIMessage>({ tools: myTools }).activateWhen(
260
- 'cancel_order',
261
- ({ messages }) => hasUnfulfilledOrders(messages),
262
- );
263
- // ~~~~~~~~
264
- // Messages are now typed as MyUIMessage, so you get type safety and autocompletion in predicates!
300
+ const toolSet = createToolSet<typeof myTools, MyUIMessage>({ tools: myTools })
301
+ .activateWhen(
302
+ 'cancel_order',
303
+ ({ messages }) => hasUnfulfilledOrders(messages),
304
+ // ~~~~~~~~
305
+ // Messages are now typed as Array<MyUIMessage> | undefined
306
+ );
265
307
 
266
- const { tools, activeTools } = toolSet.inferTools({ messages, context: {} });
308
+
309
+ const { tools, activeTools } = toolSet.inferTools({ messages });
267
310
  ```
268
311
 
269
312
  ### Custom Context
@@ -276,16 +319,18 @@ import { MyUIMessage } from './my-ui-message.js';
276
319
 
277
320
  type MyContext = { userId: string; isAdmin: boolean };
278
321
 
279
- const toolSet = createToolSet<typeof myTools, MyUIMessage, MyContext>({ tools: myTools }).activateWhen(
280
- 'cancel_order',
281
- ({ context }) => context.isAdmin,
282
- );
283
- // ~~~~~~~~
284
- // Context is now typed as MyContext, so you get type safety and autocompletion
322
+ const toolSet = createToolSet<typeof myTools, MyUIMessage, MyContext>({ tools: myTools })
323
+ .activateWhen(
324
+ 'cancel_order',
325
+ ({ context }) => context?.isAdmin,
326
+ // ~~~~~~~
327
+ // Context is typed as MyContext | undefined
328
+ );
329
+
285
330
 
286
331
  const { tools, activeTools } = toolSet.inferTools({
287
332
  messages,
288
- context: { isAdmin: true },
333
+ context: { userId: '1', isAdmin: true },
289
334
  });
290
335
  ```
291
336
 
@@ -313,14 +358,6 @@ All tools as a standard AI SDK tool record, regardless of activation state.
313
358
  const { tools } = toolSet;
314
359
  ```
315
360
 
316
- #### `.activeTools`
317
-
318
- Resolved array of active tool names based on the current state.
319
-
320
- ```ts
321
- const { activeTools } = toolSet;
322
- ```
323
-
324
361
  #### `.activate(names)`
325
362
 
326
363
  Statically activate tools by name. Returns a new instance (immutable) or `this` (mutable).
@@ -339,35 +376,45 @@ toolSet.deactivate(['search']);
339
376
 
340
377
  #### `.activateWhen(name, predicate)` / `.activateWhen(predicates)`
341
378
 
342
- Conditionally activate tools. The predicate receives `{ messages, context }` and returns `true` to activate.
379
+ Conditionally activate tools. The predicate receives `{ messages, context }` and returns `true` to activate. Both `messages` and `context` can be `undefined` if not provided to `inferTools`. Returning `undefined` is treated as `false`.
343
380
 
344
381
  ```ts
345
- toolSet.activateWhen('cancel_order', ({ messages }) => hasOrders(messages));
382
+ toolSet.activateWhen('cancel_order', ({ messages }) => messages?.some((m) => hasOrders(m)));
346
383
 
347
384
  toolSet.activateWhen({
348
- cancel_order: ({ messages }) => hasOrders(messages),
349
- list_orders: ({ context }) => context.isAuthenticated,
385
+ cancel_order: ({ messages }) => messages?.some((m) => hasOrders(m)),
386
+ list_orders: ({ context }) => context?.isAuthenticated,
350
387
  });
351
388
  ```
352
389
 
353
390
  #### `.deactivateWhen(name, predicate)` / `.deactivateWhen(predicates)`
354
391
 
355
- Conditionally deactivate tools. The predicate receives `{ messages, context }` and returns `true` to deactivate.
392
+ Conditionally deactivate tools. The predicate receives `{ messages, context }` and returns `true` to deactivate. Both `messages` and `context` can be `undefined` if not provided to `inferTools`. Returning `undefined` is treated as `false` (tool stays active).
356
393
 
357
394
  ```ts
358
- toolSet.deactivateWhen('search', ({ messages }) => messages.length > 10);
395
+ toolSet.deactivateWhen('search', ({ messages }) => messages && messages.length > 10);
359
396
  ```
360
397
 
361
- #### `.inferTools(input)`
398
+ #### `.inferTools(input?)`
362
399
 
363
- Evaluate all predicates with the provided messages and context. Returns `{ tools, activeTools }` directly spreadable into `generateText()` or `streamText()`. This is a terminal operation: messages and context are consumed but not stored.
400
+ Evaluate all predicates and return `{ tools, activeTools }`, directly spreadable into `generateText()` or `streamText()`. The input is optional; all fields are optional. Predicates receive `undefined` for fields not provided.
364
401
 
365
- - `input`:
366
- - `messages`, the current conversation messages
367
- - `context`, arbitrary values passed to predicates
402
+ - `input` (optional):
403
+ - `messages` (optional), the current conversation messages
404
+ - `context` (optional), arbitrary values passed to predicates
368
405
 
369
406
  ```ts
370
- const { tools, activeTools } = toolSet.inferTools({ messages, context: {} });
407
+ // Static-only (no predicates)
408
+ const { tools, activeTools } = toolSet.inferTools();
409
+
410
+ // With messages
411
+ const { tools, activeTools } = toolSet.inferTools({ messages });
412
+
413
+ // With context
414
+ const { tools, activeTools } = toolSet.inferTools({ context: { isAdmin: true } });
415
+
416
+ // With both
417
+ const { tools, activeTools } = toolSet.inferTools({ messages, context });
371
418
 
372
419
  const result = await generateText({ model, tools, activeTools, messages });
373
420
  ```
@@ -385,13 +432,13 @@ const immutableClone = toolSet.clone();
385
432
 
386
433
  ### `ActivationInput`
387
434
 
388
- Input passed to activation predicates. Generic over `MESSAGE` and `CONTEXT`:
435
+ Input passed to activation predicates. Generic over `MESSAGE` and `CONTEXT`. Both `messages` and `context` are optional since they may not be provided to `inferTools`:
389
436
 
390
437
  ```ts
391
438
  import type { ActivationInput } from 'ai-tool-set';
392
439
 
393
440
  type MyInput = ActivationInput<MyUIMessage, { isAdmin: boolean }>;
394
- // { messages: Array<MyUIMessage>; context: { isAdmin: boolean } }
441
+ // { messages?: Array<MyUIMessage>; context?: { isAdmin: boolean } }
395
442
  ```
396
443
 
397
444
  ### `InferToolSet`
package/dist/index.d.mts CHANGED
@@ -26,14 +26,14 @@ type InactiveTools<T extends AnyToolSet> = T extends ImmutableToolSet<any, any,
26
26
  * Use `ActivationInput<MyMsg>` to get per-tool narrowing in callbacks.
27
27
  */
28
28
  type ActivationInput<MESSAGE extends MessageType = UIMessage, CONTEXT extends Record<string, unknown> = Record<string, unknown>> = {
29
- messages: Array<MESSAGE>;
30
- context: CONTEXT;
29
+ messages?: Array<MESSAGE>;
30
+ context?: CONTEXT;
31
31
  };
32
- /** Activation predicate — returns true if tool should be active. */
33
- type ActivationPredicate<MESSAGE extends MessageType = UIMessage, CONTEXT extends Record<string, unknown> = Record<string, unknown>> = (input: ActivationInput<MESSAGE, CONTEXT>) => boolean;
32
+ /** Activation predicate — returns true if tool should be active. Undefined is treated as false. */
33
+ type ActivationPredicate<MESSAGE extends MessageType = UIMessage, CONTEXT extends Record<string, unknown> = Record<string, unknown>> = (input: ActivationInput<MESSAGE, CONTEXT>) => boolean | undefined;
34
34
  type ActivationEntry = {
35
35
  toolName: string;
36
- resolve: (input: ActivationInput<any, any>) => boolean;
36
+ resolve: (input: ActivationInput<any, any>) => boolean | undefined;
37
37
  };
38
38
  /** Resolved tools and active tool names returned by `inferTools()`. */
39
39
  type ResolvedToolSet<TOOLS extends ToolRecord> = {
@@ -54,14 +54,12 @@ declare class ToolSetState<TOOLS extends ToolRecord, MESSAGE extends MessageType
54
54
  constructor(tools: TOOLS, entries: Array<ActivationEntry>);
55
55
  /** All tools as a standard AI SDK tool record. */
56
56
  get tools(): TOOLS;
57
- /** Resolved list of active tool names based on current entries (no predicates, default input). */
58
- get activeTools(): Array<keyof TOOLS & string>;
59
57
  activate(names: Array<string>): ToolSetState<TOOLS, MESSAGE, CONTEXT>;
60
58
  deactivate(names: Array<string>): ToolSetState<TOOLS, MESSAGE, CONTEXT>;
61
59
  activateWhen(nameOrPredicates: string | Partial<Record<string, ActivationPredicate<MESSAGE, CONTEXT>>>, predicate?: ActivationPredicate<MESSAGE, CONTEXT>): ToolSetState<TOOLS, MESSAGE, CONTEXT>;
62
60
  deactivateWhen(nameOrPredicates: string | Partial<Record<string, ActivationPredicate<MESSAGE, CONTEXT>>>, predicate?: ActivationPredicate<MESSAGE, CONTEXT>): ToolSetState<TOOLS, MESSAGE, CONTEXT>;
63
61
  /** Evaluate all predicates with the provided input and return resolved tools + activeTools. */
64
- inferTools(input: ActivationInput<MESSAGE, CONTEXT>): ResolvedToolSet<TOOLS>;
62
+ inferTools(input?: ActivationInput<MESSAGE, CONTEXT>): ResolvedToolSet<TOOLS>;
65
63
  }
66
64
  /**
67
65
  * An immutable tool set with chainable activation methods.
@@ -74,8 +72,6 @@ declare class ImmutableToolSet<TOOLS extends ToolRecord, MESSAGE extends Message
74
72
  #private;
75
73
  /** All tools as a standard AI SDK tool record. */
76
74
  readonly tools: TOOLS;
77
- /** Resolved list of active tool names based on current state. */
78
- readonly activeTools: Array<keyof TOOLS & string>;
79
75
  constructor(state: ToolSetState<TOOLS, MESSAGE, CONTEXT>);
80
76
  /** Statically activate tools by name. */
81
77
  activate<NAMES extends keyof TOOLS & string>(names: Array<NAMES>): ImmutableToolSet<TOOLS, MESSAGE, CONTEXT, ACTIVATED | NAMES, Exclude<DEACTIVATED, NAMES>>;
@@ -94,7 +90,7 @@ declare class ImmutableToolSet<TOOLS extends ToolRecord, MESSAGE extends Message
94
90
  deactivateWhen<NAME extends keyof TOOLS & string>(name: NAME, predicate: ActivationPredicate<MESSAGE, CONTEXT>): ImmutableToolSet<TOOLS, MESSAGE, CONTEXT, ACTIVATED | NAME, Exclude<DEACTIVATED, NAME>>;
95
91
  deactivateWhen<NAMES extends keyof TOOLS & string>(predicates: Partial<Record<NAMES, ActivationPredicate<MESSAGE, CONTEXT>>>): ImmutableToolSet<TOOLS, MESSAGE, CONTEXT, ACTIVATED | NAMES, Exclude<DEACTIVATED, NAMES>>;
96
92
  /** Evaluate all predicates with the provided input. Returns resolved `{ tools, activeTools }`. */
97
- inferTools(input: ActivationInput<MESSAGE, CONTEXT>): ResolvedToolSet<TOOLS>;
93
+ inferTools(input?: ActivationInput<MESSAGE, CONTEXT>): ResolvedToolSet<TOOLS>;
98
94
  /** Clone this toolset, optionally switching between immutable and mutable. */
99
95
  clone(options: {
100
96
  mutable: true;
@@ -113,8 +109,6 @@ declare class MutableToolSet<TOOLS extends ToolRecord, MESSAGE extends MessageTy
113
109
  #private;
114
110
  /** All tools as a standard AI SDK tool record. */
115
111
  readonly tools: TOOLS;
116
- /** Resolved list of active tool names based on current state. */
117
- activeTools: Array<keyof TOOLS & string>;
118
112
  constructor(state: ToolSetState<TOOLS, MESSAGE, CONTEXT>);
119
113
  /** Statically activate tools by name. */
120
114
  activate(names: Array<keyof TOOLS & string>): this;
@@ -131,7 +125,7 @@ declare class MutableToolSet<TOOLS extends ToolRecord, MESSAGE extends MessageTy
131
125
  deactivateWhen(name: keyof TOOLS & string, predicate: ActivationPredicate<MESSAGE, CONTEXT>): this;
132
126
  deactivateWhen(predicates: Partial<Record<keyof TOOLS & string, ActivationPredicate<MESSAGE, CONTEXT>>>): this;
133
127
  /** Evaluate all predicates with the provided input. Returns resolved `{ tools, activeTools }`. */
134
- inferTools(input: ActivationInput<MESSAGE, CONTEXT>): ResolvedToolSet<TOOLS>;
128
+ inferTools(input?: ActivationInput<MESSAGE, CONTEXT>): ResolvedToolSet<TOOLS>;
135
129
  /** Clone this toolset, optionally switching between immutable and mutable. */
136
130
  clone(options: {
137
131
  mutable: true;
package/dist/index.mjs CHANGED
@@ -27,13 +27,6 @@ var ToolSetState = class ToolSetState {
27
27
  get tools() {
28
28
  return this.#tools;
29
29
  }
30
- /** Resolved list of active tool names based on current entries (no predicates, default input). */
31
- get activeTools() {
32
- return this.inferTools({
33
- messages: [],
34
- context: {}
35
- }).activeTools;
36
- }
37
30
  activate(names) {
38
31
  const newEntries = names.map((name) => ({
39
32
  toolName: name,
@@ -63,7 +56,7 @@ var ToolSetState = class ToolSetState {
63
56
  const activeTools = Object.keys(this.#tools).filter((name) => {
64
57
  const lastEntry = this.#entries.findLast((e) => e.toolName === name);
65
58
  if (!lastEntry) return true;
66
- return lastEntry.resolve(input);
59
+ return lastEntry.resolve(input ?? {});
67
60
  });
68
61
  return {
69
62
  tools: this.#tools,
@@ -82,12 +75,9 @@ var ImmutableToolSet = class ImmutableToolSet {
82
75
  #state;
83
76
  /** All tools as a standard AI SDK tool record. */
84
77
  tools;
85
- /** Resolved list of active tool names based on current state. */
86
- activeTools;
87
78
  constructor(state) {
88
79
  this.#state = state;
89
80
  this.tools = state.tools;
90
- this.activeTools = state.activeTools;
91
81
  }
92
82
  /** Statically activate tools by name. */
93
83
  activate(names) {
@@ -121,33 +111,26 @@ var MutableToolSet = class MutableToolSet {
121
111
  #state;
122
112
  /** All tools as a standard AI SDK tool record. */
123
113
  tools;
124
- /** Resolved list of active tool names based on current state. */
125
- activeTools;
126
114
  constructor(state) {
127
115
  this.#state = state;
128
116
  this.tools = state.tools;
129
- this.activeTools = state.activeTools;
130
- }
131
- #apply(state) {
132
- this.#state = state;
133
- this.activeTools = state.activeTools;
134
117
  }
135
118
  /** Statically activate tools by name. */
136
119
  activate(names) {
137
- this.#apply(this.#state.activate(names));
120
+ this.#state = this.#state.activate(names);
138
121
  return this;
139
122
  }
140
123
  /** Statically deactivate tools by name. */
141
124
  deactivate(names) {
142
- this.#apply(this.#state.deactivate(names));
125
+ this.#state = this.#state.deactivate(names);
143
126
  return this;
144
127
  }
145
128
  activateWhen(nameOrPredicates, predicate) {
146
- this.#apply(this.#state.activateWhen(nameOrPredicates, predicate));
129
+ this.#state = this.#state.activateWhen(nameOrPredicates, predicate);
147
130
  return this;
148
131
  }
149
132
  deactivateWhen(nameOrPredicates, predicate) {
150
- this.#apply(this.#state.deactivateWhen(nameOrPredicates, predicate));
133
+ this.#state = this.#state.deactivateWhen(nameOrPredicates, predicate);
151
134
  return this;
152
135
  }
153
136
  /** Evaluate all predicates with the provided input. Returns resolved `{ tools, activeTools }`. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-tool-set",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.4",
4
4
  "description": "Tool set utilities for the Vercel AI SDK",
5
5
  "keywords": [],
6
6
  "license": "MIT",