assistan-ts
Version:
A typesafe and code-first library to define and run OpenAI assistants
129 lines • 5.64 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.AssistantVisibleError = exports.toolbox = exports.filter = exports.join = exports.defaultOptions = void 0;
const definition_1 = require("./definition");
const value_1 = require("@sinclair/typebox/value");
const formats_1 = require("./lib/formats");
const typebox_1 = require("./lib/typebox");
(0, formats_1.registerTypeboxFormats)();
exports.defaultOptions = {
jsonParser: defaultJsonParser,
validator: defaultValidator,
formatValidationError: defaultValidateFormatter,
formatToolError: defaultErrorFormatter,
validateArguments: true,
formatOutput: defaultOutputFormatter,
};
// TODO: how to handle options and tool conflicts?
const join = (...toolboxes) => {
var _a;
const toolDefs = Object.assign({}, ...toolboxes.map((it) => it.toolDefs));
const toolsFn = Object.assign({}, ...toolboxes.map((it) => it.toolsFn));
return (0, exports.toolbox)(toolDefs, toolsFn, (_a = toolboxes[0]) === null || _a === void 0 ? void 0 : _a.options);
};
exports.join = join;
const filter = (tb, filter) => {
const toolDefs = Object.fromEntries(Object.entries(tb.toolDefs).filter(([key, tool]) => filter(key, tool)));
const toolsFn = Object.fromEntries(Object.entries(tb.toolsFn).filter(([key, tool]) => filter(key, tool)));
return (0, exports.toolbox)(toolDefs, toolsFn, tb.options);
};
exports.filter = filter;
const toolbox = (toolDefs, toolsFn, options = exports.defaultOptions) => {
const opts = Object.assign(Object.assign({}, exports.defaultOptions), options);
const { jsonParser, validator, formatOutput, formatToolError } = opts;
return {
toolDefs,
toolsFn,
options: opts,
payload: (0, definition_1.functionsToPayload)(toolDefs),
handleAction: (action) => __awaiter(void 0, void 0, void 0, function* () {
const toolDef = toolDefs === null || toolDefs === void 0 ? void 0 : toolDefs[action.function.name];
const ctx = { action, options: opts, toolDef };
try {
if (!toolDef)
throw new AssistantVisibleError(`Tool key not found: ${action.function.name}. Please select from ${Object.keys(toolDefs).toString()}`);
let output;
if (!(toolDef === null || toolDef === void 0 ? void 0 : toolDef.parameters) || (0, typebox_1.isNullType)(toolDef.parameters)) {
output = yield toolsFn[action.function.name](undefined);
}
else {
const args = jsonParser(action.function.arguments, ctx);
validator(args, ctx);
output = yield toolsFn[action.function.name](args);
}
return {
tool_call_id: action.id,
output: formatOutput(output, ctx),
};
}
catch (e) {
return {
tool_call_id: action.id,
output: formatToolError(e, ctx),
};
}
}),
};
};
exports.toolbox = toolbox;
function defaultJsonParser(args, ctx) {
try {
return JSON.parse(args);
}
catch (e) {
throw new AssistantVisibleError(`Invalid JSON: ${args}`);
}
}
function defaultValidator(args, ctx) {
if (ctx.options.validateArguments && ctx.toolDef) {
// const validate = ajv.compile(ctx.toolDef.parameters);
const errors = [...value_1.Value.Errors(ctx.toolDef.parameters, args)];
const valid = errors.length === 0;
if (valid === false) {
throw new AssistantVisibleError(ctx.options.formatValidationError(errors !== null && errors !== void 0 ? errors : [], ctx));
}
}
}
function defaultValidateFormatter(errors) {
return errors.map((it) => `arguments${it.path} ${it.message}`).join("\n");
}
function defaultOutputFormatter(output) {
switch (typeof output) {
case "string":
return output;
case "number":
case "boolean":
return output + "";
case "object":
return JSON.stringify(output);
}
}
function defaultErrorFormatter(error, ctx) {
if (error instanceof AssistantVisibleError) {
return `Error calling ${ctx.action.function.name}: ${error.message}`;
}
throw error;
}
/**
* Throw this if you want your assistant to receive the error message
*/
class AssistantVisibleError extends Error {
constructor(message) {
super(message); // Pass the message to the parent class Error
// This line makes stack traces work correctly, do not remove it!
Object.setPrototypeOf(this, AssistantVisibleError.prototype);
// Set the name of the error class as CustomError.
this.name = "AssistantVisibleError";
}
}
exports.AssistantVisibleError = AssistantVisibleError;
//# sourceMappingURL=toolbox.js.map