assistan-ts
Version:
A typesafe and code-first library to define and run OpenAI assistants
124 lines (116 loc) • 3.4 kB
text/typescript
import { FunctionTool, toolsToPayload } from "./definition";
import { LinkedDefinition } from "./link";
import {
RunOptions,
ToolsRequiredResponse,
waitForComplete,
waitForRequiredAction,
} from "./run";
import {
ToolBox,
ToolOptions,
ToolsDefsToToolbox,
toolbox as initToolBox,
} from "./toolbox";
import { Run, RunCreateParams, OpenAI } from "./types/openai";
export type Assistant<T extends Record<string, FunctionTool>> = {
/** A definition that has been "linked" to OpenAI */
definition: LinkedDefinition<T>;
/** The toolbox that was created from the definition + tool functions */
toolbox: ToolBox<T>;
/** Run related functions */
run: {
/** Create a new run */
create: (params: {
threadId: string;
body?: Omit<RunCreateParams, "assistant_id">;
options?: OpenAI.RequestOptions;
}) => Promise<SetupRunResponse>;
/** Load an existing run */
load: (run: Run) => SetupRunResponse;
};
};
type SetupRunResponse = {
run: OpenAI.Beta.Threads.Runs.Run;
toolsRequired: (
opts?: RunOptions & { timeout?: number }
) => Promise<ToolsRequiredResponse>;
complete: (
opts?: RunOptions & { timeout?: number }
) => Promise<OpenAI.Beta.Threads.Runs.Run>;
};
type Props<T extends Record<string, FunctionTool>> = {
/** A definition that has been "linked" to OpenAI */
definition: LinkedDefinition<T>;
/** Functions matching the tool definitions */
tools: ToolsDefsToToolbox<T>;
/** Options to pass to the toolbox */
toolOptions?: Partial<ToolOptions>;
/** Override the toolbox before creating a run
* @param base The toolbox that was created from the definition
*/
toolBoxOverride?: (base: ToolBox<T>) => ToolBox<any>;
};
export const assistant = <T extends Record<string, FunctionTool>>({
definition,
tools,
toolOptions,
toolBoxOverride: overrideToolbox,
}: Props<T>): Assistant<T> => {
const toolbox = initToolBox(definition.functionTools!, tools, toolOptions);
const setupRun = (
run: Run,
overriddenToolbox?: ToolBox<any>
): SetupRunResponse => ({
run,
toolsRequired: async (opts) =>
waitForRequiredAction(
run,
{
toolbox: overriddenToolbox ?? toolbox,
openai: definition.openai,
...opts,
},
opts?.timeout
),
complete: async (opts) =>
waitForComplete(
run,
{
toolbox: overriddenToolbox ?? toolbox,
openai: definition.openai,
...opts,
},
opts?.timeout
),
});
return {
definition,
toolbox: toolbox,
run: {
create: async (params) => {
const { threadId, body, options } = params;
const overriddenToolbox = overrideToolbox?.(toolbox);
const run = await definition.openai.beta.threads.runs.create(
threadId,
{
assistant_id: definition.id,
...(body ?? {}),
tools: overriddenToolbox
? toolsToPayload({
functionTools: overriddenToolbox.toolDefs,
retrieval: definition.retrieval,
codeInterpreter: definition.codeInterpreter,
})
: undefined,
},
options
);
return setupRun(run, overriddenToolbox);
},
load: (run: Run) => {
return setupRun(run);
},
},
};
};