import type { ConsoleClient } from '../../../../support/api/console-client' import type { DifyWorld } from '../../../support/world' import type { PreseededResource } from './common' import { asRecord, asString, failFixturePrerequisite, matchesNameOrLabel } from './common' export const splitToolDisplayName = (resourceName: string) => { const [providerName, toolName] = resourceName.split('/').map((item) => item.trim()) if (!providerName || !toolName) { return { ok: false as const, reason: `Preseeded tool "${resourceName}" must use "Provider / Tool" format.`, } } return { ok: true as const, providerName, toolName, } } export const splitToolResourceId = (resourceId: string) => { const parts = resourceId .split('/') .map((item) => item.trim()) .filter(Boolean) const toolName = parts.at(-1) const providerName = parts.slice(0, -1).join('/') return { providerName, toolName: toolName ?? '', } } export const findToolEntry = ( items: unknown[], { providerDisplayName, providerName, toolDisplayName, toolName, }: { providerDisplayName: string providerName: string toolDisplayName: string toolName: string }, ) => items.find((item) => { const record = asRecord(item) const providerValues = [record.provider_id, record.provider, record.plugin_id, record.name].map( asString, ) const toolValues = [record.tool_name, record.name].map(asString) return ( providerValues.some((value) => value === providerName || value === providerDisplayName) && toolValues.some((value) => value === toolName || value === toolDisplayName) ) }) export const hasToolEntry = ( items: unknown[], tool: { providerDisplayName: string providerName: string toolDisplayName: string toolName: string }, ) => Boolean(findToolEntry(items, tool)) export const hasUnauthorizedToolCredentialState = (item: unknown) => { const record = asRecord(item) return asString(record.credential_type) === 'unauthorized' } export async function requirePreseededTool( world: DifyWorld, client: ConsoleClient, resourceName: string, ): Promise { const parsed = splitToolDisplayName(resourceName) if (!parsed.ok) return failFixturePrerequisite(world, parsed.reason) const providers = await client.workspaces.current.tools.builtin.get() const provider = providers.find((item) => matchesNameOrLabel(parsed.providerName, item.name, item.label), ) const tool = provider?.tools?.find((item) => matchesNameOrLabel(parsed.toolName, item.name, item.label), ) if (!provider || !tool) return failFixturePrerequisite(world, `Preseeded tool "${resourceName}" was not found.`) return { id: `${provider.name}/${tool.name}`, kind: 'tool', name: resourceName, } }