Skip to content

Commit

Permalink
updated vercel toolkit to include custom actions in tools
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-angelo committed Jan 9, 2025
1 parent 9f70e14 commit b5aac36
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 29 deletions.
51 changes: 51 additions & 0 deletions js/src/frameworks/vercel.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { beforeAll, describe, expect, it } from "@jest/globals";
import { z } from "zod";
import { getTestConfig } from "../../config/getTestConfig";
import { VercelAIToolSet } from "./vercel";
import type { CreateActionOptions } from "../sdk/actionRegistry";

Check warning on line 5 in js/src/frameworks/vercel.spec.ts

View workflow job for this annotation

GitHub Actions / lint-and-prettify

'CreateActionOptions' is defined but never used. Allowed unused vars must match /^_/u

describe("Apps class tests", () => {
let vercelAIToolSet: VercelAIToolSet;

beforeAll(() => {
vercelAIToolSet = new VercelAIToolSet({
apiKey: getTestConfig().COMPOSIO_API_KEY,
Expand All @@ -25,4 +28,52 @@ describe("Apps class tests", () => {
});
expect(Object.keys(tools).length).toBe(1);
});

describe("custom actions", () => {
let customAction: Awaited<ReturnType<typeof vercelAIToolSet.createAction>>;
let tools: Awaited<ReturnType<typeof vercelAIToolSet.getTools>>;

beforeAll(async () => {
const params = z.object({
owner: z.string().describe("The owner of the repository"),
repo: z.string().describe("The name of the repository without the `.git` extension."),
})


customAction = await vercelAIToolSet.createAction({
actionName: "starRepositoryCustomAction",
toolName: "github",
description: "Star A Github Repository For Given `Repo` And `Owner`",
inputParams: params,
callback: async (
inputParams,
) => ({ successful: true, data: inputParams })
})

tools = await vercelAIToolSet.getTools({
actions: ["starRepositoryCustomAction"],
});

});

it("check if custom actions are coming", async () => {
expect(Object.keys(tools).length).toBe(1);
expect(tools).toHaveProperty(customAction.name, tools[customAction.name]);
});

it("check if custom actions are executing", async () => {
const res = await vercelAIToolSet.executeAction({
action: customAction.name,
params: {
owner: "composioHQ",
repo: "composio"
},
})
expect(res.successful).toBe(true);
expect(res.data).toHaveProperty("owner", "composioHQ");
expect(res.data).toHaveProperty("repo", "composio");
});
})


});
28 changes: 13 additions & 15 deletions js/src/frameworks/vercel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { jsonSchema, tool } from "ai";
import { jsonSchema, tool, CoreTool } from "ai";
import { z } from "zod";
import { ComposioToolSet as BaseComposioToolSet } from "../sdk/base.toolset";
import { TELEMETRY_LOGGER } from "../sdk/utils/telemetry";
Expand Down Expand Up @@ -62,7 +62,7 @@ export class VercelAIToolSet extends BaseComposioToolSet {
useCase?: Optional<string>;
usecaseLimit?: Optional<number>;
filterByAvailableApps?: Optional<boolean>;
}): Promise<{ [key: string]: RawActionData }> {
}): Promise<{ [key: string]: CoreTool }> {
TELEMETRY_LOGGER.manualTelemetry(TELEMETRY_EVENTS.SDK_METHOD_INVOKED, {
method: "getTools",
file: this.fileName,
Expand All @@ -78,21 +78,19 @@ export class VercelAIToolSet extends BaseComposioToolSet {
actions,
} = ZExecuteToolCallParams.parse(filters);

const actionsList = await this.client.actions.list({
...(apps && { apps: apps?.join(",") }),
...(tags && { tags: tags?.join(",") }),
...(useCase && { useCase: useCase }),
...(actions && { actions: actions?.join(",") }),
...(usecaseLimit && { usecaseLimit: usecaseLimit }),
filterByAvailableApps: filterByAvailableApps ?? undefined,
});
const actionsList = await this.getToolsSchema({
apps,
actions,
tags,
useCase,
useCaseLimit: usecaseLimit,
filterByAvailableApps
})

const tools = {};
actionsList.items?.forEach((actionSchema) => {
// @ts-ignore
const tools: { [key: string]: CoreTool } = {};
actionsList.forEach((actionSchema) => {
tools[actionSchema.name!] = this.generateVercelTool(
// @ts-ignore
actionSchema as ActionData
actionSchema
);
});

Expand Down
28 changes: 22 additions & 6 deletions js/src/sdk/actionRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,25 @@ type RawExecuteRequestParam = {
};
};

export type CreateActionOptions = {

type ValidParameters = ZodObject<{ [key: string]: ZodString | ZodOptional<ZodString> }>
export type Parameters = ValidParameters | z.ZodObject<{}>

type inferParameters<PARAMETERS extends Parameters> =
PARAMETERS extends ValidParameters
? z.infer<PARAMETERS>
: z.infer<z.ZodObject<{}>>


export type CreateActionOptions<
P extends Parameters = z.ZodObject<{}>
> = {
actionName?: string;
toolName?: string;
description?: string;
inputParams: ZodObject<{ [key: string]: ZodString | ZodOptional<ZodString> }>;
inputParams?: P;
callback: (
inputParams: Record<string, string>,
inputParams: inferParameters<P>,
authCredentials: Record<string, string> | undefined,
executeRequest: (
data: RawExecuteRequestParam
Expand All @@ -50,15 +62,19 @@ export class ActionRegistry {
client: Composio;
customActions: Map<
string,
{ metadata: CreateActionOptions; schema: Record<string, unknown> }
{
metadata: CreateActionOptions;
schema: Record<string, unknown>
}
>;

constructor(client: Composio) {
this.client = client;
this.customActions = new Map();
}

async createAction(options: CreateActionOptions): Promise<RawActionData> {

async createAction<P extends Parameters = z.ZodObject<{}>>(options: CreateActionOptions<P>): Promise<RawActionData> {
const { callback } = options;
if (typeof callback !== "function") {
throw new Error("Callback must be a function");
Expand All @@ -67,7 +83,7 @@ export class ActionRegistry {
throw new Error("You must provide actionName for this action");
}
if (!options.inputParams) {
options.inputParams = z.object({});
options.inputParams = z.object({}) as P
}
const params = options.inputParams;
const actionName = options.actionName || callback.name || "";
Expand Down
16 changes: 8 additions & 8 deletions js/src/sdk/base.toolset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z, ZodObject } from "zod";

Check warning on line 1 in js/src/sdk/base.toolset.ts

View workflow job for this annotation

GitHub Actions / lint-and-prettify

'ZodObject' is defined but never used. Allowed unused vars must match /^_/u
import { Composio } from "../sdk";
import {
RawActionData,
Expand All @@ -10,7 +10,7 @@ import {
} from "../types/base_toolset";
import type { Optional, Sequence } from "../types/util";
import { getEnvVariable } from "../utils/shared";
import { ActionRegistry, CreateActionOptions } from "./actionRegistry";
import { ActionRegistry, CreateActionOptions, Parameters } from "./actionRegistry";
import { ActionExecutionResDto } from "./client/types.gen";
import { ActionExecuteResponse, Actions } from "./models/actions";
import { ActiveTriggers } from "./models/activeTriggers";
Expand Down Expand Up @@ -54,10 +54,10 @@ export class ComposioToolSet {
post: TPostProcessor[];
schema: TSchemaProcessor[];
} = {
pre: [fileInputProcessor],
post: [fileResponseProcessor],
schema: [fileSchemaProcessor],
};
pre: [fileInputProcessor],
post: [fileResponseProcessor],
schema: [fileSchemaProcessor],
};

private userDefinedProcessors: {
pre?: TPreProcessor;
Expand Down Expand Up @@ -172,8 +172,8 @@ export class ComposioToolSet {
});
}

async createAction(options: CreateActionOptions) {
return this.userActionRegistry.createAction(options);
async createAction<P extends Parameters = z.ZodObject<{}>>(options: CreateActionOptions<P>) {
return this.userActionRegistry.createAction<P>(options);
}

private isCustomAction(action: string) {
Expand Down

0 comments on commit b5aac36

Please sign in to comment.