mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-12 19:55:19 +02:00
Address PR round 2: use query param, remove inferToolkitSlug, consolidate types
- Rename deprecated `search` param to `query` per Composio docs - Remove inferToolkitSlug fallback; make toolkit required in ZSearchResultTool - Replace inline Awaited<ReturnType<...>> with concrete Toolkit type in handler - Move ZToolkitMeta/ZToolkitItem/ZListToolkitsResponse to shared/composio.ts - Reference shared schemas in ipc.ts and core/types.ts (single source of truth) - Remove unused ZTool import from client.ts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5284b10cd4
commit
6c44131794
5 changed files with 41 additions and 63 deletions
|
|
@ -4,7 +4,7 @@ import * as composioClient from '@x/core/dist/composio/client.js';
|
|||
import { composioAccountsRepo } from '@x/core/dist/composio/repo.js';
|
||||
import { invalidateCopilotInstructionsCache } from '@x/core/dist/application/assistant/instructions.js';
|
||||
import { CURATED_TOOLKIT_SLUGS } from '@x/shared/dist/composio.js';
|
||||
import type { LocalConnectedAccount } from '@x/core/dist/composio/types.js';
|
||||
import type { LocalConnectedAccount, Toolkit } from '@x/core/dist/composio/types.js';
|
||||
import { triggerSync as triggerGmailSync } from '@x/core/dist/knowledge/sync_gmail.js';
|
||||
import { triggerSync as triggerCalendarSync } from '@x/core/dist/knowledge/sync_calendar.js';
|
||||
|
||||
|
|
@ -312,8 +312,7 @@ export async function useComposioForGoogleCalendar(): Promise<{ enabled: boolean
|
|||
*/
|
||||
export async function listToolkits() {
|
||||
// Paginate through all API pages to collect every curated toolkit
|
||||
type ToolkitItem = Awaited<ReturnType<typeof composioClient.listToolkits>>['items'][number];
|
||||
const allItems: ToolkitItem[] = [];
|
||||
const allItems: Toolkit[] = [];
|
||||
let cursor: string | null = null;
|
||||
const maxPages = 10; // safety limit
|
||||
for (let page = 0; page < maxPages; page++) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import {
|
|||
ZExecuteActionResponse,
|
||||
ZListResponse,
|
||||
ZSearchResultTool,
|
||||
ZTool,
|
||||
ZToolkit,
|
||||
type NormalizedToolResult,
|
||||
} from "./types.js";
|
||||
|
|
@ -284,21 +283,6 @@ export async function deleteConnectedAccount(connectedAccountId: string): Promis
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Infer toolkit slug from a tool slug when the API omits the toolkit object.
|
||||
* Convention: TOOLKIT_ACTION (e.g., GITHUB_CREATE_ISSUE → github).
|
||||
*
|
||||
* This fallback exists because the Composio /tools search endpoint occasionally
|
||||
* returns results without the `toolkit` field — observed with certain search
|
||||
* queries and when the tool is from a less-common integration. The inference is
|
||||
* a best-effort heuristic: lowercase the first segment before the first underscore.
|
||||
*/
|
||||
function inferToolkitSlug(toolSlug: string): string {
|
||||
const lower = toolSlug.toLowerCase();
|
||||
const parts = lower.split('_');
|
||||
return parts[0] ?? lower;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for tools across all toolkits (or optionally filtered by specific toolkit slugs).
|
||||
* Returns tools with full input_parameters so the agent knows what params to pass.
|
||||
|
|
@ -311,7 +295,7 @@ export async function searchTools(
|
|||
toolkitSlugs?: string[],
|
||||
): Promise<{ items: NormalizedToolResult[] }> {
|
||||
const params: Record<string, string> = {
|
||||
search: searchQuery,
|
||||
query: searchQuery,
|
||||
limit: '50',
|
||||
};
|
||||
if (toolkitSlugs && toolkitSlugs.length === 1) {
|
||||
|
|
@ -324,9 +308,7 @@ export async function searchTools(
|
|||
slug: item.slug,
|
||||
name: item.name,
|
||||
description: item.description,
|
||||
toolkitSlug: item.toolkit?.slug
|
||||
|| inferToolkitSlug(item.slug)
|
||||
|| (toolkitSlugs?.length === 1 ? toolkitSlugs[0] : ''),
|
||||
toolkitSlug: item.toolkit.slug,
|
||||
inputParameters: {
|
||||
type: 'object' as const,
|
||||
properties: item.input_parameters?.properties ?? {},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { z } from "zod";
|
||||
import { ZToolkitMeta as ZSharedToolkitMeta, ZToolkitItem } from "@x/shared/dist/composio.js";
|
||||
|
||||
// Re-export the shared toolkit schemas so existing imports continue to work
|
||||
export const ZToolkitMeta = ZSharedToolkitMeta;
|
||||
|
||||
/**
|
||||
* Composio authentication schemes
|
||||
|
|
@ -29,28 +33,9 @@ export const ZConnectedAccountStatus = z.enum([
|
|||
]);
|
||||
|
||||
/**
|
||||
* Toolkit metadata
|
||||
* Toolkit schema — same shape as ZToolkitItem from shared, re-exported for convenience.
|
||||
*/
|
||||
export const ZToolkitMeta = z.object({
|
||||
description: z.string(),
|
||||
logo: z.string(),
|
||||
tools_count: z.number(),
|
||||
triggers_count: z.number(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Toolkit schema
|
||||
*/
|
||||
export const ZToolkit = z.object({
|
||||
slug: z.string(),
|
||||
name: z.string(),
|
||||
meta: ZToolkitMeta,
|
||||
no_auth: z.boolean().optional(),
|
||||
// Use z.string() instead of ZAuthScheme to be resilient against
|
||||
// new auth types added by the Composio API over time.
|
||||
auth_schemes: z.array(z.string()).optional(),
|
||||
composio_managed_auth_schemes: z.array(z.string()).optional(),
|
||||
});
|
||||
export const ZToolkit = ZToolkitItem;
|
||||
|
||||
/**
|
||||
* Tool schema
|
||||
|
|
@ -246,7 +231,7 @@ export const ZSearchResultTool = z.object({
|
|||
slug: z.string(),
|
||||
name: z.string(),
|
||||
logo: z.string(),
|
||||
}).optional(),
|
||||
}),
|
||||
input_parameters: z.object({
|
||||
type: z.literal('object').optional().default('object'),
|
||||
properties: z.record(z.string(), z.unknown()).optional().default({}),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,31 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* Zod schemas for Composio IPC responses.
|
||||
* Defined here in shared so both ipc.ts and core/composio/types.ts can reference them.
|
||||
*/
|
||||
export const ZToolkitMeta = z.object({
|
||||
description: z.string(),
|
||||
logo: z.string(),
|
||||
tools_count: z.number(),
|
||||
triggers_count: z.number(),
|
||||
});
|
||||
|
||||
export const ZToolkitItem = z.object({
|
||||
slug: z.string(),
|
||||
name: z.string(),
|
||||
meta: ZToolkitMeta,
|
||||
no_auth: z.boolean().optional(),
|
||||
auth_schemes: z.array(z.string()).optional(),
|
||||
composio_managed_auth_schemes: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
export const ZListToolkitsResponse = z.object({
|
||||
items: z.array(ZToolkitItem),
|
||||
nextCursor: z.string().nullable(),
|
||||
totalItems: z.number(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Curated Composio toolkits available to Rowboat users.
|
||||
* Single source of truth for slugs, display names, and categories.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { AgentScheduleState } from './agent-schedule-state.js';
|
|||
import { ServiceEvent } from './service-events.js';
|
||||
import { UserMessageContent } from './message.js';
|
||||
import { RowboatApiConfig } from './rowboat-account.js';
|
||||
import { ZListToolkitsResponse } from './composio.js';
|
||||
|
||||
// ============================================================================
|
||||
// Runtime Validation Schemas (Single Source of Truth)
|
||||
|
|
@ -398,26 +399,9 @@ const ipcSchemas = {
|
|||
res: z.null(),
|
||||
},
|
||||
// Composio Tools Library channels
|
||||
// Response schema mirrors core/composio/types.ts ZToolkit (kept inline to avoid cross-package import)
|
||||
'composio:list-toolkits': {
|
||||
req: z.object({}),
|
||||
res: z.object({
|
||||
items: z.array(z.object({
|
||||
slug: z.string(),
|
||||
name: z.string(),
|
||||
meta: z.object({
|
||||
description: z.string(),
|
||||
logo: z.string(),
|
||||
tools_count: z.number(),
|
||||
triggers_count: z.number(),
|
||||
}),
|
||||
no_auth: z.boolean().optional(),
|
||||
auth_schemes: z.array(z.string()).optional(),
|
||||
composio_managed_auth_schemes: z.array(z.string()).optional(),
|
||||
})),
|
||||
nextCursor: z.string().nullable(),
|
||||
totalItems: z.number(),
|
||||
}),
|
||||
res: ZListToolkitsResponse,
|
||||
},
|
||||
// Agent schedule channels
|
||||
'agent-schedule:getConfig': {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue