From e66ea3c1fe6870e7d4630c738c611c5c96b0dbd8 Mon Sep 17 00:00:00 2001 From: Apoorv Taneja Date: Thu, 21 Nov 2024 01:38:06 +0530 Subject: [PATCH 1/6] add proxy support for executing custom actions --- js/src/frameworks/langchain.spec.ts | 83 ++++++--- js/src/sdk/actionRegistry.spec.ts | 239 ++++++++++++++------------ js/src/sdk/base.toolset.ts | 15 +- js/src/sdk/client/schemas.gen.ts | 257 ++++++++++++++++++++-------- js/src/sdk/client/services.gen.ts | 34 +++- js/src/sdk/client/types.gen.ts | 212 ++++++++++++++++++----- js/src/sdk/index.ts | 5 +- js/src/sdk/models/Entity.ts | 2 +- js/src/sdk/models/actions.ts | 23 ++- 9 files changed, 611 insertions(+), 259 deletions(-) diff --git a/js/src/frameworks/langchain.spec.ts b/js/src/frameworks/langchain.spec.ts index ef25cd91fa..e0cb004a97 100644 --- a/js/src/frameworks/langchain.spec.ts +++ b/js/src/frameworks/langchain.spec.ts @@ -1,42 +1,75 @@ import { describe, it, expect, beforeAll } from "@jest/globals"; -import { CloudflareToolSet } from "./cloudflare"; -import { get } from "http"; +import { z } from "zod"; import { getTestConfig } from "../../config/getTestConfig"; import { LangchainToolSet } from "./langchain"; - describe("Apps class tests", () => { - - let langchainToolSet: LangchainToolSet; - beforeAll(() => { - langchainToolSet = new LangchainToolSet({ - apiKey: getTestConfig().COMPOSIO_API_KEY, - baseUrl: getTestConfig().BACKEND_HERMES_URL - }); + let langchainToolSet: LangchainToolSet; + beforeAll(() => { + langchainToolSet = new LangchainToolSet({ + apiKey: getTestConfig().COMPOSIO_API_KEY, + baseUrl: getTestConfig().BACKEND_HERMES_URL, }); + }); - it("getools",async() => { - const tools = await langchainToolSet.getTools({ - apps: ['github'] - }); + it("getools", async () => { + const tools = await langchainToolSet.getTools({ + apps: ["github"], + }); - expect(tools).toBeInstanceOf(Array); + expect(tools).toBeInstanceOf(Array); + }); + it("check if tools are coming", async () => { + const tools = await langchainToolSet.getTools({ + actions: ["GITHUB_GITHUB_API_ROOT"], }); - it("check if tools are coming", async () => { - const tools = await langchainToolSet.getTools({ - actions: ['GITHUB_GITHUB_API_ROOT'] - }); + expect(tools.length).toBe(1); + }); - expect(tools.length).toBe(1); + it("check if getTools, actions are coming", async () => { + const tools = await langchainToolSet.getTools({ + actions: ["GITHUB_GITHUB_API_ROOT"], }); - it("check if getTools, actions are coming", async () => { - const tools = await langchainToolSet.getTools({ - actions: ['GITHUB_GITHUB_API_ROOT'] - }); + expect(tools.length).toBe(1); + }); - expect(tools.length).toBe(1) + it("Should create custom action to star a repository", async () => { + const action = await langchainToolSet.createAction({ + actionName: "starRepositoryPlxityCustom2", + toolName: "github", + description: "This action stars a repository", + inputParams: z.object({ + owner: z.string(), + repo: z.string(), + }), + callback: async (inputParams, authCredentials) => { + try { + const res = await langchainToolSet.executeRequest({ + connectedAccountId: "45993fa0-c769-4297-887b-94b5170da306", + endpoint: `/user/starred/${inputParams.owner}/${inputParams.repo}`, + method: "PUT", + parameters: [], + }); + return res; + } catch (e) { + console.error(e); + return {}; + } + }, }); + + const actionOuput = await langchainToolSet.executeAction( + "starRepositoryPlxityCustom2", + { + owner: "plxity", + repo: "achievementsof.life", + }, + "default" + ); + + expect(actionOuput).toHaveProperty("successfull", true); + }); }); diff --git a/js/src/sdk/actionRegistry.spec.ts b/js/src/sdk/actionRegistry.spec.ts index d8361df3aa..d91a1ddb15 100644 --- a/js/src/sdk/actionRegistry.spec.ts +++ b/js/src/sdk/actionRegistry.spec.ts @@ -5,131 +5,150 @@ import { Composio } from "."; import { getTestConfig } from "../../config/getTestConfig"; describe("ActionRegistry", () => { - let actionRegistry: ActionRegistry; - let client: Composio; - const testConfig = getTestConfig(); - - beforeAll(() => { - client = new Composio(testConfig.COMPOSIO_API_KEY!,testConfig.BACKEND_HERMES_URL!); + let actionRegistry: ActionRegistry; + let client: Composio; + const testConfig = getTestConfig(); + + beforeAll(() => { + client = new Composio( + testConfig.COMPOSIO_API_KEY!, + testConfig.BACKEND_HERMES_URL! + ); + }); + + beforeEach(() => { + actionRegistry = new ActionRegistry(client); + }); + + it("should create an action with valid parameters", async () => { + const params = z.object({ + param1: z.string(), + param2: z.string().optional(), }); - beforeEach(() => { - actionRegistry = new ActionRegistry(client); + const callback = async (params: Record) => { + return { success: true }; + }; + + const options = { + actionName: "testAction", + toolName: "testTool", + description: "This is a test action", + inputParams: params, + callback, + }; + + const action = await actionRegistry.createAction(options); + + expect(action.parameters.title).toBe("testAction"); + expect(action.parameters.type).toBe("object"); + expect(action.parameters.description).toBe("This is a test action"); + expect(action.parameters.required).toEqual(["param1"]); + expect(action.parameters.properties).toHaveProperty("param1"); + expect(action.parameters.properties).toHaveProperty("param2"); + }); + + it("should throw an error if callback is not a function", async () => { + const params = z.object({ + param1: z.string(), }); - it("should create an action with valid parameters", async () => { - const params = z.object({ - param1: z.string(), - param2: z.string().optional(), - }); - - const callback = async (params: Record) => { - return { success: true }; - }; - - const options = { - actionName: "testAction", - toolName: "testTool", - description: "This is a test action", - inputParams: params, - callback, - }; - - const action = await actionRegistry.createAction(options); - - expect(action.parameters.title).toBe("testAction"); - expect(action.parameters.type).toBe("object"); - expect(action.parameters.description).toBe("This is a test action"); - expect(action.parameters.required).toEqual(["param1"]); - expect(action.parameters.properties).toHaveProperty("param1"); - expect(action.parameters.properties).toHaveProperty("param2"); + const options = { + actionName: "testAction1", + toolName: "testTool", + description: "This is a test action", + params, + callback: "notAFunction", + }; + + await expect(actionRegistry.createAction(options as any)).rejects.toThrow( + "Callback must be a function" + ); + }); + + it("should throw an error if callback is an anonymous function and noActionName is specified", async () => { + const params = z.object({ + param1: z.string(), }); - it("should throw an error if callback is not a function", async () => { - const params = z.object({ - param1: z.string(), - }); - - const options = { - actionName: "testAction1", - toolName: "testTool", - description: "This is a test action", - params, - callback: "notAFunction", - }; - - await expect(actionRegistry.createAction(options as any)).rejects.toThrow("Callback must be a function"); + const options = { + toolName: "testTool", + description: "This is a test action", + inputParams: params, + callback: async function () { + return { success: true }; + }, + }; + + await expect(actionRegistry.createAction(options)).rejects.toThrow( + "You must provide actionName for this action" + ); + }); + + it("should execute an action with valid parameters", async () => { + const params = z.object({ + param1: z.string(), }); - it("should throw an error if callback is an anonymous function and noActionName is specified", async () => { - const params = z.object({ - param1: z.string(), - }); - - const options = { - toolName: "testTool", - description: "This is a test action", - inputParams: params, - callback: async function () { return { success: true }; }, - }; - - await expect(actionRegistry.createAction(options)).rejects.toThrow("You must provide actionName for this action"); + const callback = async (params: Record) => { + return { success: true }; + }; + + const options = { + actionName: "testAction2", + description: "This is a test action", + inputParams: params, + callback, + }; + + await actionRegistry.createAction(options); + + const result = await actionRegistry.executeAction( + "testAction2", + { param1: "value1" }, + {} + ); + + expect(result).toEqual({ success: true }); + }); + + it("should throw an error if action does not exist", async () => { + await expect( + actionRegistry.executeAction("nonExistentAction", {}, {}) + ).rejects.toThrow("Action with name nonExistentAction does not exist"); + }); + + it("should get actions by names", async () => { + const params = z.object({ + param1: z.string(), }); - it("should execute an action with valid parameters", async () => { - const params = z.object({ - param1: z.string(), - }); - - const callback = async (params: Record) => { - return { success: true }; - }; + const callback = async (params: Record) => { + return { success: true }; + }; - const options = { - actionName: "testAction2", - description: "This is a test action", - inputParams: params, - callback, - }; + const options = { + actionName: "testAction", + toolName: "testTool", + description: "This is a test action", + inputParams: params, + callback, + }; - await actionRegistry.createAction(options); + await actionRegistry.createAction(options); - const result = await actionRegistry.executeAction("testAction2", { param1: "value1" }, {}); - - expect(result).toEqual({ success: true }); + const actions = await actionRegistry.getActions({ + actions: ["testAction"], }); + expect(actions.length).toBe(1); + expect(actions[0].parameters.properties).toHaveProperty("param1"); + }); - it("should throw an error if action does not exist", async () => { - await expect(actionRegistry.executeAction("nonExistentAction", {}, {})).rejects.toThrow("Action with name nonExistentAction does not exist"); + it("should return an empty array if no actions match the names", async () => { + const actions = await actionRegistry.getActions({ + actions: ["nonExistentAction"], }); - it("should get actions by names", async () => { - const params = z.object({ - param1: z.string(), - }); - - const callback = async (params: Record) => { - return { success: true }; - }; - - const options = { - actionName: "testAction", - toolName: "testTool", - description: "This is a test action", - inputParams: params, - callback, - }; - - await actionRegistry.createAction(options); - - const actions = await actionRegistry.getActions({actions: ["testAction"]}); - expect(actions.length).toBe(1); - expect(actions[0].parameters.properties).toHaveProperty("param1"); - }); - - it("should return an empty array if no actions match the names", async () => { - const actions = await actionRegistry.getActions({actions: ["nonExistentAction"]}); - - expect(actions.length).toBe(0); - }); + expect(actions.length).toBe(0); + }); }); diff --git a/js/src/sdk/base.toolset.ts b/js/src/sdk/base.toolset.ts index adb091dd7c..4215ce5097 100644 --- a/js/src/sdk/base.toolset.ts +++ b/js/src/sdk/base.toolset.ts @@ -7,12 +7,14 @@ import { getEnvVariable } from "../utils/shared"; import { WorkspaceConfig } from "../env/config"; import { Workspace } from "../env"; import logger from "../utils/logger"; +import { CEG } from '../sdk/utils/error'; import { ExecuteActionResDTO } from "./client/types.gen"; import { saveFile } from "./utils/fileUtils"; import { convertReqParams, converReqParamForActionExecution } from "./utils"; import { ActionRegistry, CreateActionOptions } from "./actionRegistry"; import { getUserDataJson } from "./utils/config"; - +import apiClient from '../sdk/client/client'; +import { ActionProxyRequestConfigDTO } from './client'; type GetListActionsResponse = any; @@ -279,4 +281,15 @@ export class ComposioToolSet { logger.warn("execute_action is deprecated, use executeAction instead"); return this.executeAction(action, params, entityId); } + + async executeRequest(data: ActionProxyRequestConfigDTO){ + try { + const { data: res } = await apiClient.actionsV2.executeActionProxyV2({ + body: data as unknown as ActionProxyRequestConfigDTO + }); + return res!; + } catch (error) { + throw CEG.handleError(error); + } + } } \ No newline at end of file diff --git a/js/src/sdk/client/schemas.gen.ts b/js/src/sdk/client/schemas.gen.ts index e456b7d8bc..259d465d49 100644 --- a/js/src/sdk/client/schemas.gen.ts +++ b/js/src/sdk/client/schemas.gen.ts @@ -5,7 +5,7 @@ export const $MemberInfoResDTO = { id: { type: 'string' }, - clientId: { + projectId: { type: 'string' }, email: { @@ -57,7 +57,7 @@ export const $MemberInfoResDTO = { } }, type: 'object', - required: ['id', 'clientId', 'email', 'name', 'role', 'createdAt', 'updatedAt'], + required: ['id', 'projectId', 'email', 'name', 'role', 'createdAt', 'updatedAt'], description: 'Member information' } as const; @@ -172,10 +172,14 @@ export const $IdentifyClientResDTO = { email: { type: 'string', description: 'The email associated with the client' + }, + orgId: { + type: 'string', + description: 'The organization ID associated with the client' } }, type: 'object', - required: ['clientId', 'apiKey', 'email'] + required: ['clientId', 'apiKey', 'email', 'orgId'] } as const; export const $UserGitUserInfo = { @@ -320,14 +324,14 @@ export const $ClientDTO = { } }, type: 'object', - required: ['autoId', 'id', 'name', 'email', 'createdAt', 'updatedAt', 'triggersEnabled', 'plan'] + required: ['autoId', 'id', 'name', 'email', 'createdAt', 'updatedAt', 'triggersEnabled', 'plan'], + description: 'Client information' } as const; export const $ClientInfoResDTO = { properties: { client: { - '$ref': '#/components/schemas/ClientDTO', - description: 'Client information' + '$ref': '#/components/schemas/ClientDTO' }, apiKey: { type: 'string', @@ -338,6 +342,46 @@ export const $ClientInfoResDTO = { required: ['client', 'apiKey'] } as const; +export const $ProjectReqDTO = { + properties: { + name: { + type: 'string', + description: 'The name of the project' + } + }, + type: 'object', + required: ['name'] +} as const; + +export const $ProjectResDTO = { + properties: { + id: { + type: 'string', + description: 'The ID of the project' + }, + name: { + type: 'string', + description: 'The name of the project' + } + }, + type: 'object', + required: ['id', 'name'] +} as const; + +export const $ProjectListResDTO = { + properties: { + items: { + items: { + type: 'object' + }, + type: 'array', + description: 'The list of projects' + } + }, + type: 'object', + required: ['items'] +} as const; + export const $InviteMemberReqDTO = { properties: { email: { @@ -707,7 +751,7 @@ export const $AppQueryDTO = { }, includeLocal: { type: 'string', - description: 'Whether to include local tools or not' + description: "Enter 'true' or 'false'" } }, type: 'object' @@ -1189,66 +1233,6 @@ export const $GetConnectionsResult = { required: ['connections', 'pageInfo'] } as const; -export const $ToolsExecuteReqDto = { - properties: { - actionName: { - type: 'string' - }, - runInSandbox: { - type: 'boolean' - }, - input: { - type: 'object' - }, - nlaInput: { - type: 'string' - }, - authorizationData: { - type: 'object' - }, - appSchema: { - type: 'object' - } - }, - type: 'object', - required: ['actionName', 'runInSandbox', 'input'] -} as const; - -export const $DirectExecuteReqDto = { - properties: { - endpoint: { - type: 'string' - }, - base_url: { - type: 'string' - }, - headers: { - type: 'object' - }, - queryParams: { - type: 'object' - } - }, - type: 'object', - required: ['endpoint', 'base_url', 'headers', 'queryParams'] -} as const; - -export const $ActionExecutionResDto = { - properties: { - data: { - type: 'object' - }, - error: { - type: 'string' - }, - successfull: { - type: 'string' - } - }, - type: 'object', - required: ['data'] -} as const; - export const $ConnectionParams = { properties: { integrationId: { @@ -1508,13 +1492,17 @@ export const $GetConnectionInfoResponseDTO = { export const $Parameter = { properties: { name: { - type: 'string' + type: 'string', + description: "The name of the parameter. For example, 'x-api-key', 'Content-Type', etc.," }, in: { - type: 'string' + enum: ['query', 'header'], + type: 'string', + description: "The location of the parameter. Can be 'query' or 'header'." }, value: { - type: 'string' + type: 'string', + description: "The value of the parameter. For example, '1234567890', 'application/json', etc.," } }, type: 'object', @@ -1643,6 +1631,75 @@ export const $InitiateConnectionResponse = { required: ['connectionStatus', 'connectedAccountId'] } as const; +export const $ToolsExecuteReqDto = { + properties: { + actionName: { + type: 'string' + }, + runInSandbox: { + type: 'boolean' + }, + input: { + type: 'object' + }, + nlaInput: { + type: 'string' + }, + authorizationData: { + type: 'object' + }, + appSchema: { + type: 'object' + }, + customDescription: { + type: 'string' + }, + systemPrompt: { + type: 'string' + } + }, + type: 'object', + required: ['actionName', 'runInSandbox', 'input'] +} as const; + +export const $DirectExecuteReqDto = { + properties: { + endpoint: { + type: 'string' + }, + base_url: { + type: 'string' + }, + headers: { + type: 'object' + }, + queryParams: { + type: 'object' + }, + body: { + type: 'object' + } + }, + type: 'object', + required: ['endpoint', 'base_url', 'headers', 'queryParams'] +} as const; + +export const $ActionExecutionResDto = { + properties: { + data: { + type: 'object' + }, + error: { + type: 'string' + }, + successfull: { + type: 'string' + } + }, + type: 'object', + required: ['data'] +} as const; + export const $CustomAuthDTO = { properties: { base_url: { @@ -1662,6 +1719,51 @@ export const $CustomAuthDTO = { required: ['parameters'] } as const; +export const $ActionProxyRequestMethodDTO = { + properties: { + type: { + enum: ['formData', 'urlEncoded', 'raw', 'binary', 'graphql', 'none'], + type: 'string', + description: "The type of request body to use for the action. Defaults to 'none'." + }, + data: { + type: 'string', + description: 'The data to be sent to the endpoint. This will override the body set in the connected account.' + } + }, + type: 'object' +} as const; + +export const $ActionProxyRequestConfigDTO = { + properties: { + connectedAccountId: { + type: 'string', + description: 'The connected account uuid to use for the action.' + }, + endpoint: { + type: 'string', + description: 'The endpoint to call for the action. If the given url is relative, it will be resolved relative to the base_url set in the connected account info.' + }, + method: { + enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], + type: 'string', + description: 'The HTTP method to use for the action.' + }, + parameters: { + items: { + '$ref': '#/components/schemas/Parameter' + }, + type: 'array' + }, + body: { + type: 'object', + description: 'The body to be sent to the endpoint. This can either be a JSON field or a string.' + } + }, + type: 'object', + required: ['connectedAccountId', 'endpoint', 'method', 'parameters'] +} as const; + export const $SessionInfoDTO = { properties: { sessionId: { @@ -1692,14 +1794,19 @@ export const $ActionExecutionReqDTO = { type: 'object' }, sessionInfo: { - '$ref': '#/components/schemas/SessionInfoDTO', - type: 'object' + '$ref': '#/components/schemas/SessionInfoDTO' }, authConfig: { '$ref': '#/components/schemas/CustomAuthDTO' }, text: { type: 'string' + }, + customDescription: { + type: 'string' + }, + systemPrompt: { + type: 'string' } }, type: 'object' @@ -1709,6 +1816,12 @@ export const $ActionGetNLAInputsReqDTO = { properties: { text: { type: 'string' + }, + customDescription: { + type: 'string' + }, + systemPrompt: { + type: 'string' } }, type: 'object', diff --git a/js/src/sdk/client/services.gen.ts b/js/src/sdk/client/services.gen.ts index d9029ae9e3..5695b296e8 100644 --- a/js/src/sdk/client/services.gen.ts +++ b/js/src/sdk/client/services.gen.ts @@ -1,7 +1,7 @@ // This file is auto-generated by @hey-api/openapi-ts import { createClient, createConfig, type Options } from '@hey-api/client-axios'; -import type { IdentifyClientData, IdentifyClientError, IdentifyClientResponse, GetUserInfoError, GetUserInfoResponse, GenerateApiKeyData, GenerateApiKeyError, GenerateApiKeyResponse, ListApiKeysError, ListApiKeysResponse, DeleteApiKeyData, DeleteApiKeyError, DeleteApiKeyResponse, GetAppsData, GetAppsError, GetAppsResponse, GetOpenApiSpecsError, GetOpenApiSpecsResponse, DeleteOpenApiSpecToolData, DeleteOpenApiSpecToolError, DeleteOpenApiSpecToolResponse, AppControllerSendEmailToClientData, AppControllerSendEmailToClientError, AppControllerSendEmailToClientResponse, GetOpenApiSpecStatusData, GetOpenApiSpecStatusError, GetOpenApiSpecStatusResponse, GetAppData, GetAppError, GetAppResponse, CreateConnectorData, CreateConnectorError, CreateConnectorResponse, ListAllConnectorsError, ListAllConnectorsResponse, GetConnectorInfoData, GetConnectorInfoError, GetConnectorInfoResponse, ModifyConnectorData, ModifyConnectorError, ModifyConnectorResponse, DeleteConnectorData, DeleteConnectorError, DeleteConnectorResponse, GetConnectionsData, GetConnectionsError, GetConnectionsResponse, InitiateConnectionData, InitiateConnectionError, InitiateConnectionResponse2, UpdateConnectionDataData, UpdateConnectionDataError, UpdateConnectionDataResponse, GetConnectionData, GetConnectionError, GetConnectionResponse, DeleteConnectionData, DeleteConnectionError, DeleteConnectionResponse, GetConnectionInfoData, GetConnectionInfoError, GetConnectionInfoResponse, DisableConnectionData, DisableConnectionError, DisableConnectionResponse, EnableConnectionData, EnableConnectionError, EnableConnectionResponse, ListTriggersData, ListTriggersError, ListTriggersResponse, EnableTriggerData, EnableTriggerError, EnableTriggerResponse, GetActiveTriggersData, GetActiveTriggersError, GetActiveTriggersResponse, SwitchTriggerInstanceStatusData, SwitchTriggerInstanceStatusError, SwitchTriggerInstanceStatusResponse, DisableTriggerData, DisableTriggerError, DisableTriggerResponse, DeleteTriggerData, DeleteTriggerError, DeleteTriggerResponse, SetCallbackUrlData, SetCallbackUrlError, SetCallbackUrlResponse, GetWebhookUrlError, GetWebhookUrlResponse, GetTriggerLogsData, GetTriggerLogsError, GetTriggerLogsResponse, GetTriggerInfoV2Data, GetTriggerInfoV2Error, GetTriggerInfoV2Response, GetSentryDnsError, GetSentryDnsResponse, ClearCacheData, ClearCacheError, ClearCacheResponse, GenerateCliSessionError, GenerateCliSessionResponse, GetCliCodeData, GetCliCodeError, GetCliCodeResponse, VerifyCliCodeData, VerifyCliCodeError, VerifyCliCodeResponse, GetLogsData, GetLogsError, GetLogsResponse, PostLogsData, PostLogsError, PostLogsResponse, ListActionsV2Data, ListActionsV2Error, ListActionsV2Response, ListActionsMinimalV2Data, ListActionsMinimalV2Error, ListActionsMinimalV2Response, ExecuteActionV2Data, ExecuteActionV2Error, ExecuteActionV2Response, GetActionInputsV2Data, GetActionInputsV2Error, GetActionInputsV2Response, GetActionV2Data, GetActionV2Error, GetActionV2Response, ExecuteActionProxyV2Data, ExecuteActionProxyV2Error, ExecuteActionProxyV2Response, GetAnalyticsData, GetAnalyticsError, GetAnalyticsResponse, GetTopEntitiesData, GetTopEntitiesError, GetTopEntitiesResponse, UpdateWebhookData, UpdateWebhookError, UpdateWebhookResponse } from './types.gen'; +import type { IdentifyClientData, IdentifyClientError, IdentifyClientResponse, GetUserInfoError, GetUserInfoResponse, AddProjectData, AddProjectError, AddProjectResponse, DeleteProjectData, DeleteProjectError, DeleteProjectResponse, GetProjectsError, GetProjectsResponse, GenerateApiKeyData, GenerateApiKeyError, GenerateApiKeyResponse, ListApiKeysError, ListApiKeysResponse, DeleteApiKeyData, DeleteApiKeyError, DeleteApiKeyResponse, GetAppsData, GetAppsError, GetAppsResponse, GetOpenApiSpecsError, GetOpenApiSpecsResponse, DeleteOpenApiSpecToolData, DeleteOpenApiSpecToolError, DeleteOpenApiSpecToolResponse, AppControllerSendEmailToClientData, AppControllerSendEmailToClientError, AppControllerSendEmailToClientResponse, GetOpenApiSpecStatusData, GetOpenApiSpecStatusError, GetOpenApiSpecStatusResponse, GetAppData, GetAppError, GetAppResponse, CreateConnectorData, CreateConnectorError, CreateConnectorResponse, ListAllConnectorsError, ListAllConnectorsResponse, GetConnectorInfoData, GetConnectorInfoError, GetConnectorInfoResponse, ModifyConnectorData, ModifyConnectorError, ModifyConnectorResponse, DeleteConnectorData, DeleteConnectorError, DeleteConnectorResponse, GetConnectionsData, GetConnectionsError, GetConnectionsResponse, InitiateConnectionData, InitiateConnectionError, InitiateConnectionResponse2, UpdateConnectionDataData, UpdateConnectionDataError, UpdateConnectionDataResponse, GetConnectionData, GetConnectionError, GetConnectionResponse, DeleteConnectionData, DeleteConnectionError, DeleteConnectionResponse, GetConnectionInfoData, GetConnectionInfoError, GetConnectionInfoResponse, DisableConnectionData, DisableConnectionError, DisableConnectionResponse, EnableConnectionData, EnableConnectionError, EnableConnectionResponse, ListTriggersData, ListTriggersError, ListTriggersResponse, EnableTriggerData, EnableTriggerError, EnableTriggerResponse, GetActiveTriggersData, GetActiveTriggersError, GetActiveTriggersResponse, SwitchTriggerInstanceStatusData, SwitchTriggerInstanceStatusError, SwitchTriggerInstanceStatusResponse, DisableTriggerData, DisableTriggerError, DisableTriggerResponse, DeleteTriggerData, DeleteTriggerError, DeleteTriggerResponse, SetCallbackUrlData, SetCallbackUrlError, SetCallbackUrlResponse, GetWebhookUrlError, GetWebhookUrlResponse, GetTriggerLogsData, GetTriggerLogsError, GetTriggerLogsResponse, GetTriggerInfoV2Data, GetTriggerInfoV2Error, GetTriggerInfoV2Response, GetSentryDnsError, GetSentryDnsResponse, ClearCacheData, ClearCacheError, ClearCacheResponse, GenerateCliSessionError, GenerateCliSessionResponse, GetCliCodeData, GetCliCodeError, GetCliCodeResponse, VerifyCliCodeData, VerifyCliCodeError, VerifyCliCodeResponse, GetLogsData, GetLogsError, GetLogsResponse, PostLogsData, PostLogsError, PostLogsResponse, ListActionsV2Data, ListActionsV2Error, ListActionsV2Response, ListActionsMinimalV2Data, ListActionsMinimalV2Error, ListActionsMinimalV2Response, ExecuteActionV2Data, ExecuteActionV2Error, ExecuteActionV2Response, GetActionInputsV2Data, GetActionInputsV2Error, GetActionInputsV2Response, GetActionV2Data, GetActionV2Error, GetActionV2Response, ExecuteActionProxyV2Data, ExecuteActionProxyV2Error, ExecuteActionProxyV2Response, GetAnalyticsData, GetAnalyticsError, GetAnalyticsResponse, GetTopEntitiesData, GetTopEntitiesError, GetTopEntitiesResponse, UpdateWebhookData, UpdateWebhookError, UpdateWebhookResponse } from './types.gen'; export const client = createClient(createConfig()); @@ -27,6 +27,36 @@ export class AuthService { }); } + /** + * Add project + */ + public static addProject(options?: Options) { + return (options?.client ?? client).post({ + ...options, + url: '/api/v1/client/auth/project/add' + }); + } + + /** + * Delete project + */ + public static deleteProject(options: Options) { + return (options?.client ?? client).delete({ + ...options, + url: '/api/v1/client/auth/project/delete/{projectId}' + }); + } + + /** + * Get projects + */ + public static getProjects(options?: Options) { + return (options?.client ?? client).get({ + ...options, + url: '/api/v1/client/auth/projects' + }); + } + } export class ApiKeysService { @@ -530,7 +560,7 @@ export class ActionsService { * Execute action proxy * Execute an action with direct auth. */ - public static executeActionProxyV2(options: Options) { + public static executeActionProxyV2(options?: Options) { return (options?.client ?? client).post({ ...options, url: '/api/v2/actions/proxy' diff --git a/js/src/sdk/client/types.gen.ts b/js/src/sdk/client/types.gen.ts index 9e869568ad..8185e9e618 100644 --- a/js/src/sdk/client/types.gen.ts +++ b/js/src/sdk/client/types.gen.ts @@ -5,7 +5,7 @@ */ export type MemberInfoResDTO = { id: string; - clientId: string; + projectId: string; email: string; name: string; role: string; @@ -86,6 +86,10 @@ export type IdentifyClientResDTO = { * The email associated with the client */ email: string; + /** + * The organization ID associated with the client + */ + orgId: string; }; /** @@ -126,6 +130,9 @@ export type DeleteRowAPIDTO = { count: number; }; +/** + * Client information + */ export type ClientDTO = { /** * Auto-generated ID of the client @@ -182,9 +189,6 @@ export type ClientDTO = { }; export type ClientInfoResDTO = { - /** - * Client information - */ client: ClientDTO; /** * API key of the client @@ -192,6 +196,33 @@ export type ClientInfoResDTO = { apiKey: string; }; +export type ProjectReqDTO = { + /** + * The name of the project + */ + name: string; +}; + +export type ProjectResDTO = { + /** + * The ID of the project + */ + id: string; + /** + * The name of the project + */ + name: string; +}; + +export type ProjectListResDTO = { + /** + * The list of projects + */ + items: Array<{ + [key: string]: unknown; + }>; +}; + export type InviteMemberReqDTO = { /** * The email of the member @@ -818,40 +849,6 @@ export type GetConnectionsResult = { pageInfo: PageInfo; }; -export type ToolsExecuteReqDto = { - actionName: string; - runInSandbox: boolean; - input: { - [key: string]: unknown; - }; - nlaInput?: string; - authorizationData?: { - [key: string]: unknown; - }; - appSchema?: { - [key: string]: unknown; - }; -}; - -export type DirectExecuteReqDto = { - endpoint: string; - base_url: string; - headers: { - [key: string]: unknown; - }; - queryParams: { - [key: string]: unknown; - }; -}; - -export type ActionExecutionResDto = { - data: { - [key: string]: unknown; - }; - error?: string; - successfull?: string; -}; - export type ConnectionParams = { integrationId: string; connectionParams?: { @@ -951,11 +948,25 @@ export type GetConnectionInfoResponseDTO = { }; export type Parameter = { + /** + * The name of the parameter. For example, 'x-api-key', 'Content-Type', etc., + */ name: string; - in: string; + /** + * The location of the parameter. Can be 'query' or 'header'. + */ + in: 'query' | 'header'; + /** + * The value of the parameter. For example, '1234567890', 'application/json', etc., + */ value: string; }; +/** + * The location of the parameter. Can be 'query' or 'header'. + */ +export type in = 'query' | 'header'; + export type Data = { field1: string; field2: string; @@ -999,6 +1010,45 @@ export type InitiateConnectionResponse = { redirectUrl?: string; }; +export type ToolsExecuteReqDto = { + actionName: string; + runInSandbox: boolean; + input: { + [key: string]: unknown; + }; + nlaInput?: string; + authorizationData?: { + [key: string]: unknown; + }; + appSchema?: { + [key: string]: unknown; + }; + customDescription?: string; + systemPrompt?: string; +}; + +export type DirectExecuteReqDto = { + endpoint: string; + base_url: string; + headers: { + [key: string]: unknown; + }; + queryParams: { + [key: string]: unknown; + }; + body?: { + [key: string]: unknown; + }; +}; + +export type ActionExecutionResDto = { + data: { + [key: string]: unknown; + }; + error?: string; + successfull?: string; +}; + export type CustomAuthDTO = { base_url?: string; parameters: Array; @@ -1007,6 +1057,49 @@ export type CustomAuthDTO = { }; }; +export type ActionProxyRequestMethodDTO = { + /** + * The type of request body to use for the action. Defaults to 'none'. + */ + type?: 'formData' | 'urlEncoded' | 'raw' | 'binary' | 'graphql' | 'none'; + /** + * The data to be sent to the endpoint. This will override the body set in the connected account. + */ + data?: string; +}; + +/** + * The type of request body to use for the action. Defaults to 'none'. + */ +export type type = 'formData' | 'urlEncoded' | 'raw' | 'binary' | 'graphql' | 'none'; + +export type ActionProxyRequestConfigDTO = { + /** + * The connected account uuid to use for the action. + */ + connectedAccountId: string; + /** + * The endpoint to call for the action. If the given url is relative, it will be resolved relative to the base_url set in the connected account info. + */ + endpoint: string; + /** + * The HTTP method to use for the action. + */ + method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; + parameters: Array; + /** + * The body to be sent to the endpoint. This can either be a JSON field or a string. + */ + body?: { + [key: string]: unknown; + }; +}; + +/** + * The HTTP method to use for the action. + */ +export type method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; + export type SessionInfoDTO = { sessionId?: string; metadata?: { @@ -1025,10 +1118,14 @@ export type ActionExecutionReqDTO = { sessionInfo?: SessionInfoDTO; authConfig?: CustomAuthDTO; text?: string; + customDescription?: string; + systemPrompt?: string; }; export type ActionGetNLAInputsReqDTO = { text: string; + customDescription?: string; + systemPrompt?: string; }; export type ProxyExecutionReqDTO = { @@ -1898,7 +1995,7 @@ export type GetLogsDTO = { /** * Type of the log */ -export type type = 'error' | 'info' | 'debug'; +export type type2 = 'error' | 'info' | 'debug'; /** * Time interval for which data needs to be fetched @@ -2174,6 +2271,31 @@ export type GetUserInfoResponse = ClientInfoResDTO; export type GetUserInfoError = unknown; +export type AddProjectData = { + /** + * ProjectReqDTO + */ + body?: ProjectReqDTO; +}; + +export type AddProjectResponse = unknown; + +export type AddProjectError = unknown; + +export type DeleteProjectData = { + path: { + projectId: string; + }; +}; + +export type DeleteProjectResponse = unknown; + +export type DeleteProjectError = unknown; + +export type GetProjectsResponse = ProjectListResDTO; + +export type GetProjectsError = unknown; + export type GenerateApiKeyData = { /** * GenerateAPIKeyReqDTO @@ -2599,7 +2721,7 @@ export type ListActionsV2Data = { showEnabledOnly?: boolean; tags?: string; useCase?: string; - useCaseLimit?: number; + usecaseLimit?: number; }; }; @@ -2667,10 +2789,10 @@ export type GetActionV2Response = ActionDetails; export type GetActionV2Error = unknown; export type ExecuteActionProxyV2Data = { - query: { - connectedAccountId: string; - endpoint: string; - }; + /** + * ActionProxyRequestConfigDTO + */ + body?: ActionProxyRequestConfigDTO; }; export type ExecuteActionProxyV2Response = ActionExecutionResDto; diff --git a/js/src/sdk/index.ts b/js/src/sdk/index.ts index 1a8dd43a30..c1e3a9a574 100644 --- a/js/src/sdk/index.ts +++ b/js/src/sdk/index.ts @@ -14,7 +14,10 @@ import { isNewerVersion } from './utils/other'; import { getClientBaseConfig } from './utils/config'; import chalk from 'chalk'; import { CEG, ERROR } from './utils/error'; +import { ActionProxyRequestConfigDTO } from './client'; +import apiClient from '../sdk/client/client'; import { GetConnectorInfoResDTO } from './client'; + export class Composio { /** * The Composio class serves as the main entry point for interacting with the Composio SDK. @@ -94,7 +97,6 @@ export class Composio { return new Entity(this.backendClient, id); } - async getExpectedParamsForUser( params: { app?: string; integrationId?: string; entityId?: string; authScheme?: "OAUTH2" | "OAUTH1" | "API_KEY" | "BASIC" | "BEARER_TOKEN" | "BASIC_WITH_JWT" } = {}, ): Promise<{ expectedInputFields: GetConnectorInfoResDTO["expectedInputFields"], integrationId: string, authScheme: "OAUTH2" | "OAUTH1" | "API_KEY" | "BASIC" | "BEARER_TOKEN" | "BASIC_WITH_JWT" }> { @@ -202,4 +204,3 @@ export class Composio { } } } - diff --git a/js/src/sdk/models/Entity.ts b/js/src/sdk/models/Entity.ts index 79cacf114b..eec7b3869d 100644 --- a/js/src/sdk/models/Entity.ts +++ b/js/src/sdk/models/Entity.ts @@ -299,4 +299,4 @@ export class Entity { throw CEG.handleError(error); } } -} +} \ No newline at end of file diff --git a/js/src/sdk/models/actions.ts b/js/src/sdk/models/actions.ts index 9eb777d637..ec8872230e 100644 --- a/js/src/sdk/models/actions.ts +++ b/js/src/sdk/models/actions.ts @@ -1,4 +1,4 @@ -import { ActionExecutionReqDTO, ActionExecutionResDto, ActionsListResponseDTO, ExecuteActionResDTO, ExecuteActionV2Data } from "../client"; +import { ActionExecutionReqDTO, ActionProxyRequestConfigDTO, ActionsListResponseDTO } from "../client"; import apiClient from "../client/client"; import { CEG } from "../utils/error"; import { BackendClient } from "./backendClient"; @@ -238,4 +238,25 @@ export class Actions { throw CEG.handleError(error); } } + + /** + * Executes a action using Composio Proxy + * + * This method allows you to trigger the execution of an action by providing its name and the necessary input parameters. The request includes the connected account ID to identify the app connection to use for the action, and the input parameters required by the action. The response provides details about the execution status and the response data returned by the action. + * + * @param {ExecuteActionData} data The data for the request. + * @returns {Promise} A promise that resolves to the execution status and response data. + * @throws {ApiError} If the request fails. + */ + + async executeRequest(data: ActionProxyRequestConfigDTO){ + try { + const { data: res } = await apiClient.actionsV2.executeActionProxyV2({ + body: data as unknown as ActionProxyRequestConfigDTO + }); + return res!; + } catch (error) { + throw CEG.handleError(error); + } + } } \ No newline at end of file From e94e0dd1d1a95847649ffbde0a106c34669d45d4 Mon Sep 17 00:00:00 2001 From: Apoorv Taneja Date: Thu, 21 Nov 2024 01:39:12 +0530 Subject: [PATCH 2/6] removed unchanged file --- js/src/sdk/models/Entity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/sdk/models/Entity.ts b/js/src/sdk/models/Entity.ts index eec7b3869d..79cacf114b 100644 --- a/js/src/sdk/models/Entity.ts +++ b/js/src/sdk/models/Entity.ts @@ -299,4 +299,4 @@ export class Entity { throw CEG.handleError(error); } } -} \ No newline at end of file +} From 6417fd43680ecd77db091b28c798fc5427b9eb34 Mon Sep 17 00:00:00 2001 From: Apoorv Taneja Date: Thu, 21 Nov 2024 01:44:24 +0530 Subject: [PATCH 3/6] fixed typegen --- js/src/sdk/client/types.gen.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/sdk/client/types.gen.ts b/js/src/sdk/client/types.gen.ts index 8185e9e618..c25602754a 100644 --- a/js/src/sdk/client/types.gen.ts +++ b/js/src/sdk/client/types.gen.ts @@ -955,7 +955,7 @@ export type Parameter = { /** * The location of the parameter. Can be 'query' or 'header'. */ - in: 'query' | 'header'; + in: ParameterLocation; /** * The value of the parameter. For example, '1234567890', 'application/json', etc., */ @@ -965,7 +965,7 @@ export type Parameter = { /** * The location of the parameter. Can be 'query' or 'header'. */ -export type in = 'query' | 'header'; +export type ParameterLocation = 'query' | 'header'; export type Data = { field1: string; From 3c11cabd70fab1dc32825aa28fc4675341cc5c0d Mon Sep 17 00:00:00 2001 From: Apoorv Taneja Date: Fri, 22 Nov 2024 15:42:34 +0530 Subject: [PATCH 4/6] updated v --- js/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/package.json b/js/package.json index 4e5aefeb15..2a696fea07 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "composio-core", - "version": "0.2.9-8", + "version": "0.2.9-9", "description": "", "main": "lib/src/index.js", "scripts": { From da17494848964c3b77035b5f11c23001bd7cd149 Mon Sep 17 00:00:00 2001 From: Apoorv Taneja Date: Fri, 22 Nov 2024 22:24:08 +0530 Subject: [PATCH 5/6] updated proxy feature --- js/src/sdk/actionRegistry.ts | 95 +++++++++++++++++++++++++++--------- js/src/sdk/base.toolset.ts | 16 ++---- 2 files changed, 75 insertions(+), 36 deletions(-) diff --git a/js/src/sdk/actionRegistry.ts b/js/src/sdk/actionRegistry.ts index 2be388f84a..f1bc8538d2 100644 --- a/js/src/sdk/actionRegistry.ts +++ b/js/src/sdk/actionRegistry.ts @@ -1,13 +1,28 @@ -import { z, ZodType, ZodObject, ZodString, AnyZodObject, ZodOptional } from "zod"; +import { + z, + ZodType, + ZodObject, + ZodString, + AnyZodObject, + ZodOptional, +} from "zod"; import { zodToJsonSchema, JsonSchema7Type } from "zod-to-json-schema"; +import { ActionProxyRequestConfigDTO } from "./client"; import { Composio } from "."; +import apiClient from "../sdk/client/client"; +import { CEG } from "../sdk/utils/error"; +type ExecuteRequest = Omit; export interface CreateActionOptions { actionName?: string; toolName?: string; description?: string; inputParams: ZodObject<{ [key: string]: ZodString | ZodOptional }>; - callback: (inputParams: Record, authCredentials: Record | undefined) => Promise>; + callback: ( + inputParams: Record, + authCredentials: Record | undefined, + executeRequest: (data: ExecuteRequest) => Promise + ) => Promise>; } interface ParamsSchema { @@ -26,14 +41,16 @@ interface ExecuteMetadata { export class ActionRegistry { client: Composio; - customActions: Map; + customActions: Map; constructor(client: Composio) { this.client = client; this.customActions = new Map(); } - async createAction(options: CreateActionOptions): Promise> { + async createAction( + options: CreateActionOptions + ): Promise> { const { callback } = options; if (typeof callback !== "function") { throw new Error("Callback must be a function"); @@ -45,18 +62,15 @@ export class ActionRegistry { options.inputParams = z.object({}); } const params = options.inputParams; - const actionName = options.actionName || callback.name || ''; - const paramsSchema: ParamsSchema = await zodToJsonSchema( - params, - { - name: "input", - } - ) as ParamsSchema; + const actionName = options.actionName || callback.name || ""; + const paramsSchema: ParamsSchema = (await zodToJsonSchema(params, { + name: "input", + })) as ParamsSchema; const _params = paramsSchema.definitions.input.properties; const composioSchema = { name: actionName, description: options.description, - parameters: { + parameters: { title: actionName, type: "object", description: options.description, @@ -67,16 +81,20 @@ export class ActionRegistry { type: "object", title: "Response for " + actionName, properties: [], - } + }, }; - this.customActions.set(options.actionName?.toLocaleLowerCase() || '', { + this.customActions.set(options.actionName?.toLocaleLowerCase() || "", { metadata: options, - schema: composioSchema - }); + schema: composioSchema, + }); return composioSchema; } - async getActions({actions}: {actions: Array}): Promise> { + async getActions({ + actions, + }: { + actions: Array; + }): Promise> { const actionsArr: Array = []; for (const name of actions) { const lowerCaseName = name.toLowerCase(); @@ -92,7 +110,11 @@ export class ActionRegistry { return Array.from(this.customActions.values()).map((action: any) => action); } - async executeAction(name: string, inputParams: Record, metadata: ExecuteMetadata): Promise { + async executeAction( + name: string, + inputParams: Record, + metadata: ExecuteMetadata + ): Promise { const lowerCaseName = name.toLocaleLowerCase(); if (!this.customActions.has(lowerCaseName)) { throw new Error(`Action with name ${name} does not exist`); @@ -107,20 +129,45 @@ export class ActionRegistry { let authCredentials = {}; if (toolName) { const entity = await this.client.getEntity(metadata.entityId); - const connection = await entity.getConnection(toolName, metadata.connectionId); - if(!connection) { - throw new Error(`Connection with app name ${toolName} and entityId ${metadata.entityId} not found`); + const connection = await entity.getConnection( + toolName, + metadata.connectionId + ); + if (!connection) { + throw new Error( + `Connection with app name ${toolName} and entityId ${metadata.entityId} not found` + ); } authCredentials = { headers: connection.connectionParams?.headers, queryParams: connection.connectionParams?.queryParams, - baseUrl: connection.connectionParams?.baseUrl || connection.connectionParams?.base_url, - } + baseUrl: + connection.connectionParams?.baseUrl || + connection.connectionParams?.base_url, + }; } if (typeof callback !== "function") { throw new Error("Callback must be a function"); } - return await callback(inputParams, authCredentials); + const executeRequest = async (data: ExecuteRequest) => { + try { + const { data: res } = await apiClient.actionsV2.executeActionProxyV2({ + body: { + ...data, + connectedAccountId: metadata?.connectionId + } as ActionProxyRequestConfigDTO, + }); + return res!; + } catch (error) { + throw CEG.handleError(error); + } + }; + + return await callback( + inputParams, + authCredentials, + (data: ExecuteRequest) => executeRequest(data) + ); } } diff --git a/js/src/sdk/base.toolset.ts b/js/src/sdk/base.toolset.ts index 4215ce5097..d7490f588e 100644 --- a/js/src/sdk/base.toolset.ts +++ b/js/src/sdk/base.toolset.ts @@ -215,12 +215,14 @@ export class ComposioToolSet { action: string, params: Record, entityId: string = "default", - nlaText: string = "" + nlaText: string = "", + connectedAccountId?: string, ): Promise> { // Custom actions are always executed in the host/local environment for JS SDK if(await this.isCustomAction(action)) { return this.customActionRegistry.executeAction(action, params, { - entityId: entityId + entityId: entityId, + connectionId: connectedAccountId }); } if(this.workspaceEnv && this.workspaceEnv !== ExecEnv.HOST) { @@ -282,14 +284,4 @@ export class ComposioToolSet { return this.executeAction(action, params, entityId); } - async executeRequest(data: ActionProxyRequestConfigDTO){ - try { - const { data: res } = await apiClient.actionsV2.executeActionProxyV2({ - body: data as unknown as ActionProxyRequestConfigDTO - }); - return res!; - } catch (error) { - throw CEG.handleError(error); - } - } } \ No newline at end of file From 294be4274a2cfd4ca437e307ee5b4c48fa16cd1e Mon Sep 17 00:00:00 2001 From: Apoorv Taneja Date: Fri, 22 Nov 2024 22:36:20 +0530 Subject: [PATCH 6/6] updated test --- js/src/frameworks/langchain.spec.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/js/src/frameworks/langchain.spec.ts b/js/src/frameworks/langchain.spec.ts index e0cb004a97..97eec1a7b7 100644 --- a/js/src/frameworks/langchain.spec.ts +++ b/js/src/frameworks/langchain.spec.ts @@ -38,20 +38,19 @@ describe("Apps class tests", () => { it("Should create custom action to star a repository", async () => { const action = await langchainToolSet.createAction({ - actionName: "starRepositoryPlxityCustom2", + actionName: "starRepositoryPlxityCustom12345", toolName: "github", description: "This action stars a repository", inputParams: z.object({ owner: z.string(), repo: z.string(), }), - callback: async (inputParams, authCredentials) => { + callback: async (inputParams, authCredentials, executeRequest) => { try { - const res = await langchainToolSet.executeRequest({ - connectedAccountId: "45993fa0-c769-4297-887b-94b5170da306", - endpoint: `/user/starred/${inputParams.owner}/${inputParams.repo}`, - method: "PUT", - parameters: [], + const res = await executeRequest({ + endpoint: `/user/starred/${inputParams.owner}/${inputParams.repo}`, + method: "PUT", + parameters: [], }); return res; } catch (e) { @@ -62,12 +61,14 @@ describe("Apps class tests", () => { }); const actionOuput = await langchainToolSet.executeAction( - "starRepositoryPlxityCustom2", + "starRepositoryPlxityCustom12345", { owner: "plxity", repo: "achievementsof.life", }, - "default" + "default", + "", + "db3c8d95-73e9-474e-8ae8-edfbdaab98b1" ); expect(actionOuput).toHaveProperty("successfull", true);