Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/sim/lib/knowledge/mcp/tool-arguments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ export function repairToolCallMessage(message: Record<string, unknown>) {
}

/**
* 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
Expand Down
34 changes: 33 additions & 1 deletion apps/sim/lib/sim-search/live/providers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>).'
)
Expand Down Expand Up @@ -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
Expand Down
15 changes: 9 additions & 6 deletions apps/sim/lib/sim-search/live/slack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,15 @@ function searchableChannels(data: Record<string, unknown>, 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()
}

/**
Expand Down Expand Up @@ -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}.` : '',
])
}
Expand Down
Loading