@draftor/tools
Version:
A simple TypeScript/Javascript functions to openai tool call format
150 lines (149 loc) • 5.88 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tools = void 0;
const doctrine = require("doctrine");
class Tools {
constructor(funcs) {
this.queue = [];
this.isProcessing = false;
this.funcs = funcs;
}
extractFirstJsDocComment(func) {
const jsDocRegex = /\/\*\*([\s\S]*?)\*\//;
const match = jsDocRegex.exec(func.toString());
return match ? match[0] : null;
}
transformDoctrineToOpenAITool(doctrineOutput, func) {
const { description, tags } = doctrineOutput;
const params = {
type: 'object',
properties: {},
};
let returnType = 'void';
let returnDescription = '';
tags.forEach((tag) => {
var _a, _b;
if (tag.title === 'param') {
const param = tag === null || tag === void 0 ? void 0 : tag.name;
const type = ((_a = tag === null || tag === void 0 ? void 0 : tag.type) === null || _a === void 0 ? void 0 : _a.name) || 'any';
const desc = (tag === null || tag === void 0 ? void 0 : tag.description) || '';
console.log(typeof desc);
params.properties[param] = {
type,
description: desc,
};
}
if (tag.title === 'returns') {
returnType = ((_b = tag.type) === null || _b === void 0 ? void 0 : _b.name) || 'any';
returnDescription = tag.description || '';
}
});
const funcDesc = {
name: func.name,
description: (description === null || description === void 0 ? void 0 : description.trim()) || 'Description unavailable.',
parameters: params,
};
const tool = {
type: 'function',
function: funcDesc,
};
return tool;
//
}
toOpenAI(type) {
var _a;
if (this.funcs && ((_a = this.funcs) === null || _a === void 0 ? void 0 : _a.length) !== 0) {
// reducer
const processedFunctions = this.funcs.reduce((acc, func) => {
const comment = this.extractFirstJsDocComment(func);
const doc = doctrine.parse(comment || '', { unwrap: true });
const transformed = this.transformDoctrineToOpenAITool(doc, func);
acc.push(transformed);
return acc;
}, []);
return type == 'string' ? JSON.stringify(processedFunctions) : processedFunctions;
}
return '';
}
/**
* Processes the queue of function calls
* @returns Array of results from executed functions
*/
processQueue() {
return __awaiter(this, void 0, void 0, function* () {
this.isProcessing = true;
const results = [];
while (this.queue.length > 0) {
const { toolCall, args } = this.queue.shift();
try {
const result = this.exec(toolCall, args);
results.push(result);
}
catch (error) {
console.error('Error executing function:', error);
results.push(null);
}
}
this.isProcessing = false;
return results;
});
}
/**
* Adds function calls to queue and processes them
* @param toolCalls Array of tool calls or function names
* @param args Optional arguments for each call
*/
executeAll(toolCalls, args) {
return __awaiter(this, void 0, void 0, function* () {
// Add calls to queue
toolCalls.forEach((call, index) => {
this.queue.push({
toolCall: call,
args: args === null || args === void 0 ? void 0 : args[index]
});
});
// Process queue if not already processing
if (!this.isProcessing) {
return this.processQueue();
}
return [];
});
}
exec(toolCall, args) {
var _a, _b;
if (typeof toolCall !== 'string') {
const { function: func } = toolCall;
const { name, arguments: args } = func;
try {
const callArgs = JSON.parse(args);
const callFunc = (_a = this.funcs) === null || _a === void 0 ? void 0 : _a.filter((e) => e.name == name)[0];
const x = Object.keys(callArgs).map(e => callArgs[e]);
return callFunc(...x);
}
catch (e) {
console.log(e);
}
}
else {
try {
const callFunc = (_b = this.funcs) === null || _b === void 0 ? void 0 : _b.filter((e) => e.name == toolCall)[0];
const y = args !== null && args !== void 0 ? args : {};
const x = Object.keys(y).map((key) => y[key]);
return callFunc(...x);
}
catch (e) {
console.log(e);
}
}
}
}
exports.Tools = Tools;