diff --git a/apps/sim/lib/knowledge/mcp/tool-arguments.ts b/apps/sim/lib/knowledge/mcp/tool-arguments.ts index 80ee4ee4d2e..384cafcf20a 100644 --- a/apps/sim/lib/knowledge/mcp/tool-arguments.ts +++ b/apps/sim/lib/knowledge/mcp/tool-arguments.ts @@ -88,8 +88,8 @@ export function repairToolCallMessage(message: Record) { } /** - * Unrecognized field names logged per schema issue, each cut short. The schema caps native queries - * at nine, so a rejection's log line stays bounded. + * Unrecognized field names logged per schema issue, each cut short. The route's request body cap + * bounds how many issues one rejection can carry. */ const MAX_LOGGED_KEYS = 5 const MAX_LOGGED_KEY_CHARACTERS = 64 diff --git a/apps/sim/lib/sim-search/live/providers.test.ts b/apps/sim/lib/sim-search/live/providers.test.ts index 065636be387..50c69722f2a 100644 --- a/apps/sim/lib/sim-search/live/providers.test.ts +++ b/apps/sim/lib/sim-search/live/providers.test.ts @@ -448,7 +448,7 @@ describe('Slack channels', () => { filters: { startDate: '2026-10-30T00:00:00Z' }, native: { provider: 'slack', query: '', modifiers: 'in:#announcements' }, }) - expect(result.message).toContain('No channel named #announcements is visible to this account.') + expect(result.message).toContain('No channel named #announcements can be searched here.') expect(result.message).toContain( 'Channels with similar names: #company-announcements (in:<#C7>).' ) @@ -485,6 +485,38 @@ describe('Slack channels', () => { expect(result.message).not.toContain('#announcements') }) + it('looks up no channel when the query is already scoped to a channel ID', async () => { + const api = client() + api.json.mockResolvedValue(rts([])) + const result = await searchSlack(api, { + ...input, + scopes, + native: { provider: 'slack', query: 'launch in:<#C1>', modifiers: 'in:#announcements' }, + }) + expect(api.json).toHaveBeenCalledTimes(1) + expect(result.message).not.toContain('#announcements') + }) + + it.each([ + ['in:#launch-team.', 'launch-team'], + ['in:#équipe_ventes,', 'équipe_ventes'], + ['in:#हिंदी-टीम', 'हिंदी-टीम'], + ])('looks up the whole channel name in %s', async (modifiers, name) => { + const api = client() + api.json.mockResolvedValue(rts([])) + await searchSlack(api, { + ...input, + query: '', + scopes, + filters: { startDate: '2026-10-30T00:00:00Z' }, + native: { provider: 'slack', query: '', modifiers }, + }) + expect(api.json.mock.calls[1]?.[1]?.body).toMatchObject({ + query: name, + content_types: ['channels'], + }) + }) + it('keeps the empty search when the channel lookup fails', async () => { const api = client() api.json diff --git a/apps/sim/lib/sim-search/live/slack.ts b/apps/sim/lib/sim-search/live/slack.ts index abb77bc2e42..d01a35f5b8b 100644 --- a/apps/sim/lib/sim-search/live/slack.ts +++ b/apps/sim/lib/sim-search/live/slack.ts @@ -65,12 +65,15 @@ function searchableChannels(data: Record, input: NativeSearchIn const channelLabel = ({ id, name, archived }: SlackChannel) => `#${name} (in:<#${id}>${archived ? ', archived' : ''})` -/** The channel name an `in:#name` filter in the query or modifiers names, if any. */ +/** + * The channel name an `in:#name` filter in the query or modifiers names, without a trailing period. + * A query that also carries an `in:<#ID>` scope gets no lookup: a source limited to selected + * channels adds one to each search it runs per channel and drops the notes of the empty ones. + */ function filteredChannelName(input: NativeSearchInput): string | undefined { - return [nativeText(input), input.native?.modifiers] - .join(' ') - .match(/(?:^|\s)in:#([\w.-]+)/i)?.[1] - ?.toLowerCase() + const text = [nativeText(input), input.native?.modifiers].join(' ') + if (text.includes('in:<#')) return undefined + return text.match(/(?:^|\s)in:#([\p{L}\p{M}\p{N}_.-]*[\p{L}\p{M}\p{N}_-])/iu)?.[1]?.toLowerCase() } /** @@ -108,7 +111,7 @@ async function channelFilterNote( const complete = !string(object(data.response_metadata).next_cursor) const similar = channels.slice(0, MAX_LISTED_CHANNELS).map(channelLabel).join(', ') return joinMessages([ - complete ? `No channel named #${name} is visible to this account.` : '', + complete ? `No channel named #${name} can be searched here.` : '', similar ? `Channels with similar names: ${similar}.` : '', ]) }