Tools
Composio
Composio adapter for xsAI.
This code is untested, feel free to test it yourself and provide feedback.
npm i composio-core zod @xsai/shared-chat @xsai/tool
import type { Tool } from '@xsai/shared-chat'
import type { RawActionData } from 'composio-core'
import { ComposioToolSet } from 'composio-core'
import { z } from 'zod'
type Optional<T> = null | T
const ZExecuteToolCallParams = z.object({
actions: z.array(z.string()).optional(),
apps: z.array(z.string()).optional(),
connectedAccountId: z.string().optional(),
entityId: z.string().optional(),
filterByAvailableApps: z.boolean().optional().default(false),
params: z.record(z.any()).optional(),
tags: z.array(z.string()).optional(),
useCase: z.string().optional(),
useCaseLimit: z.number().optional(),
})
export class XSAIToolSet extends ComposioToolSet {
fileName: string = 'js/src/frameworks/xsai.ts'
constructor(
config: {
allowTracing?: boolean
apiKey?: Optional<string>
baseUrl?: Optional<string>
connectedAccountIds?: Record<string, string>
entityId?: string
} = {},
) {
super({
allowTracing: config.allowTracing || false,
apiKey: config.apiKey ?? null,
baseUrl: config.baseUrl ?? null,
connectedAccountIds: config.connectedAccountIds,
entityId: config.entityId ?? 'default',
runtime: null,
})
}
async executeToolCall(
tool: { arguments: unknown, name: string },
entityId: Optional<string> = null,
): Promise<string> {
const toolSchema = await this.getToolsSchema({ actions: [tool.name] })
const appName = toolSchema[0]?.appName?.toLowerCase()
const connectedAccountId = appName && this.connectedAccountIds?.[appName]
return JSON.stringify(
await this.executeAction({
action: tool.name,
connectedAccountId,
entityId: entityId ?? this.entityId,
params:
typeof tool.arguments === 'string'
? JSON.parse(tool.arguments) as Record<string, unknown>
: tool.arguments as Record<string, unknown>,
}),
)
}
async getTools(
filters: {
actions?: Array<string>
apps?: Array<string>
filterByAvailableApps?: Optional<boolean>
integrationId?: Optional<string>
tags?: Optional<Array<string>>
useCase?: Optional<string>
useCaseLimit?: Optional<number>
},
entityId: Optional<string> = null,
): Promise<Tool[]> {
const {
actions,
apps,
filterByAvailableApps,
tags,
useCase,
useCaseLimit,
} = ZExecuteToolCallParams.parse(filters)
const actionsList = await this.getToolsSchema(
{
actions,
apps,
filterByAvailableApps,
tags,
useCase,
useCaseLimit,
},
entityId,
filters.integrationId,
)
return actionsList.map(actionSchema => this.generateTool(
actionSchema,
entityId,
))
}
private generateTool(
schema: RawActionData,
entityId: Optional<string> = null,
) {
return {
execute: async params => this.executeToolCall(
{
arguments: JSON.stringify(params),
name: schema.name,
},
entityId ?? this.entityId,
),
function: {
description: schema.description,
name: schema.name,
parameters: schema.parameters,
strict: true,
},
type: 'function',
} satisfies Tool
}
}
Examples
import { generateText } from '@xsai/generate-text'
import { env } from 'node:process'
import { XSAIToolSet } from './utils/xsai-tool-set'
const toolset = new XSAIToolSet()
const tools = await toolset.getTools({ apps: ['github'] })
const result = await generateText({
apiKey: env.OPENAI_API_KEY!,
baseURL: 'https://api.openai.com/v1/',
maxSteps: 5,
model: 'gpt-4o-mini',
messages: [{
role: 'user',
content: 'Star the repository "moeru-ai/xsai"',
}],
tools,
toolChoice: 'required',
temperature: 0,
})
console.log(result.steps)
console.log(result.text)
Edit on GitHub
Last updated on