From 7151e81fff353880d70cf4eaee0c62ac075b3c42 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Tue, 10 Mar 2026 19:34:29 -0700 Subject: [PATCH] fix(api-key-reminder) Add reminder on hosted keys that api key isnt needed (#3512) * Add reminder on hosted keys that api key isnt needed * Fix test case --------- Co-authored-by: Theodore Li --- apps/sim/lib/copilot/chat-payload.ts | 6 ++- .../sim/lib/copilot/tool-descriptions.test.ts | 43 +++++++++++++++++++ apps/sim/lib/copilot/tool-descriptions.ts | 25 +++++++++++ .../server/blocks/get-blocks-metadata-tool.ts | 15 +++++-- apps/sim/lib/copilot/vfs/serializers.ts | 3 +- 5 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 apps/sim/lib/copilot/tool-descriptions.test.ts create mode 100644 apps/sim/lib/copilot/tool-descriptions.ts diff --git a/apps/sim/lib/copilot/chat-payload.ts b/apps/sim/lib/copilot/chat-payload.ts index 1157ea6cea..1aca502bdf 100644 --- a/apps/sim/lib/copilot/chat-payload.ts +++ b/apps/sim/lib/copilot/chat-payload.ts @@ -1,5 +1,6 @@ import { createLogger } from '@sim/logger' import { processFileAttachments } from '@/lib/copilot/chat-context' +import { getCopilotToolDescription } from '@/lib/copilot/tool-descriptions' import { isHosted } from '@/lib/core/config/feature-flags' import { createMcpToolId } from '@/lib/mcp/utils' import { getWorkflowById } from '@/lib/workflows/utils' @@ -55,7 +56,10 @@ export async function buildIntegrationToolSchemas(): Promise { const strippedName = stripVersionSuffix(toolId) integrationTools.push({ name: strippedName, - description: toolConfig.description || toolConfig.name || strippedName, + description: getCopilotToolDescription(toolConfig, { + isHosted, + fallbackName: strippedName, + }), input_schema: userSchema as unknown as Record, defer_loading: true, ...(toolConfig.oauth?.required && { diff --git a/apps/sim/lib/copilot/tool-descriptions.test.ts b/apps/sim/lib/copilot/tool-descriptions.test.ts new file mode 100644 index 0000000000..132e504120 --- /dev/null +++ b/apps/sim/lib/copilot/tool-descriptions.test.ts @@ -0,0 +1,43 @@ +import { describe, expect, it } from 'vitest' +import { getCopilotToolDescription } from '@/lib/copilot/tool-descriptions' + +describe('getCopilotToolDescription', () => { + it.concurrent('returns the base description when hosted keys are not active', () => { + expect( + getCopilotToolDescription( + { + name: 'Brandfetch Search', + description: 'Search for brands by company name', + hosting: { apiKeyParam: 'apiKey' } as never, + }, + { isHosted: false } + ) + ).toBe('Search for brands by company name') + }) + + it.concurrent('appends the hosted API key note when the tool supports hosting', () => { + expect( + getCopilotToolDescription( + { + name: 'Brandfetch Search', + description: 'Search for brands by company name', + hosting: { apiKeyParam: 'apiKey' } as never, + }, + { isHosted: true } + ) + ).toBe('Search for brands by company name API key is hosted by Sim.') + }) + + it.concurrent('uses the fallback name when no description exists', () => { + expect( + getCopilotToolDescription( + { + name: '', + description: '', + hosting: { apiKeyParam: 'apiKey' } as never, + }, + { isHosted: true, fallbackName: 'brandfetch_search' } + ) + ).toBe('brandfetch_search API key is hosted by Sim.') + }) +}) diff --git a/apps/sim/lib/copilot/tool-descriptions.ts b/apps/sim/lib/copilot/tool-descriptions.ts new file mode 100644 index 0000000000..5441b6f0e3 --- /dev/null +++ b/apps/sim/lib/copilot/tool-descriptions.ts @@ -0,0 +1,25 @@ +import type { ToolConfig } from '@/tools/types' + +const HOSTED_API_KEY_NOTE = 'API key is hosted by Sim.' + +export function getCopilotToolDescription( + tool: Pick, + options?: { + isHosted?: boolean + fallbackName?: string + } +): string { + const baseDescription = tool.description || tool.name || options?.fallbackName || '' + + if (!options?.isHosted || !tool.hosting) { + return baseDescription + } + + if (baseDescription.includes(HOSTED_API_KEY_NOTE)) { + return baseDescription + } + + return baseDescription + ? `${baseDescription} ${HOSTED_API_KEY_NOTE}` + : HOSTED_API_KEY_NOTE +} diff --git a/apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts b/apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts index 4e6e7f6fe6..4d041ee6fd 100644 --- a/apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts +++ b/apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts @@ -1,9 +1,10 @@ import { existsSync, readFileSync } from 'fs' import { join } from 'path' import { createLogger } from '@sim/logger' +import { getCopilotToolDescription } from '@/lib/copilot/tool-descriptions' import type { BaseServerTool } from '@/lib/copilot/tools/server/base-tool' import { GetBlocksMetadataInput, GetBlocksMetadataResult } from '@/lib/copilot/tools/shared/schemas' -import { getAllowedIntegrationsFromEnv } from '@/lib/core/config/feature-flags' +import { getAllowedIntegrationsFromEnv, isHosted } from '@/lib/core/config/feature-flags' import { registry as blockRegistry } from '@/blocks/registry' import { AuthMode, type BlockConfig, isHiddenFromDisplay } from '@/blocks/types' import { getUserPermissionConfig } from '@/ee/access-control/utils/permission-check' @@ -161,7 +162,10 @@ export const getBlocksMetadataServerTool: BaseServerTool< return { id: toolId, name: tool.name || toolId, - description: tool.description || '', + description: getCopilotToolDescription(tool, { + isHosted, + fallbackName: toolId, + }), inputs: tool.params || {}, outputs: tool.outputs || {}, } @@ -246,7 +250,12 @@ export const getBlocksMetadataServerTool: BaseServerTool< operations[opId] = { toolId: resolvedToolId, toolName: toolCfg?.name || resolvedToolId, - description: toolCfg?.description || undefined, + description: toolCfg + ? getCopilotToolDescription(toolCfg, { + isHosted, + fallbackName: resolvedToolId, + }) + : undefined, inputs: { ...filteredToolParams, ...(operationInputs[opId] || {}) }, outputs: toolOutputs, inputSchema: operationParameters[opId] || [], diff --git a/apps/sim/lib/copilot/vfs/serializers.ts b/apps/sim/lib/copilot/vfs/serializers.ts index 529ebba50d..e438d1c57d 100644 --- a/apps/sim/lib/copilot/vfs/serializers.ts +++ b/apps/sim/lib/copilot/vfs/serializers.ts @@ -1,4 +1,5 @@ import { isHosted } from '@/lib/core/config/feature-flags' +import { getCopilotToolDescription } from '@/lib/copilot/tool-descriptions' import { isSubBlockHiddenByHostedKey } from '@/lib/workflows/subblocks/visibility' import type { BlockConfig, SubBlockConfig } from '@/blocks/types' import { PROVIDER_DEFINITIONS } from '@/providers/models' @@ -721,7 +722,7 @@ export function serializeIntegrationSchema(tool: ToolConfig): string { { id: tool.id, name: tool.name, - description: tool.description, + description: getCopilotToolDescription(tool, { isHosted }), version: tool.version, oauth: tool.oauth ? { required: tool.oauth.required, provider: tool.oauth.provider }