-
Notifications
You must be signed in to change notification settings - Fork 167
Closed
Labels
Description
Overview
The _wrapTools function in wrapAISDK is incompatible with class-based tools because it uses the spread operator ({ ...tool }), which loses prototype methods and breaks the this context.
// Current implementation in _wrapTools
wrappedTools[key] = { ...tool }; // Loses prototype methods
if ("execute" in wrappedTools[key]) {
wrappedTools[key].execute = traceable(
wrappedTools[key].execute.bind(wrappedTools[key]), // Rebinds to plain object
// ...
);
}Problems:
- Spread operator creates a shallow copy with only own properties, losing prototype methods
- Rebinding execute to the spread object breaks this context for class instances
Reproducible Example
class MyTool {
async execute(params: any) {
return this.helperMethod(); // `this.helperMethod` is undefined after wrapping
}
helperMethod() {
return "result";
}
}
const { streamText } = wrapAISDK(ai);
await streamText({
tools: { myTool: new MyTool() } // Breaks
});Suggested Fix
Create a non-mutating copy that preserves class instances while wrapping execute with tracing functionality.
function _wrapTools(tools, toolConfig) {
const wrappedTools = {};
if (tools) {
for (const [key, tool] of Object.entries(tools)) {
// Create new object with same prototype chain and own properties
wrappedTools[key] = Object.assign(
Object.create(Object.getPrototypeOf(tool)),
tool
);