From d2b0ddd3d336560d4772fe9d03039286c8f6dbca Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 28 Sep 2026 22:29:04 -0700 Subject: [PATCH 1/7] improvement(search): accept several same-kind native queries per account and cap oversized read limits --- .../contracts/mothership-assistant-tools.test.ts | 4 ++-- .../lib/api/contracts/mothership-assistant-tools.ts | 13 +++++++------ .../generated/sim-assistant-tools.generated.ts | 13 +++++++------ .../sim/lib/mothership/generated/tool-catalog-v1.ts | 1 - .../sim/lib/mothership/generated/tool-schemas-v1.ts | 1 - .../tools/server/knowledge/workspace-search.test.ts | 8 +++++--- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts index 87e8da2e513..2f584dbc153 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts @@ -57,13 +57,13 @@ describe('Assistant execution contracts', () => { expect(accepts([trip, { ...trip, accountId: 'other' }])).toBe(true) }) - it('takes one GitHub or GitLab query per account and kind', () => { + it('runs several same-kind GitHub queries on one account but refuses kind fan-out overlap', () => { const accepts = (nativeQueries: Record[]) => searchWorkspaceInputSchema.safeParse({ query: 'launch', nativeQueries }).success const github = { provider: 'github', accountId: 'account', query: 'repo:org/repo launch' } const kinds = ['issues', 'commits', 'code', 'repositories'].map((kind) => ({ ...github, kind })) expect(accepts(kinds)).toBe(true) - expect(accepts([kinds[0]!, { ...kinds[0]!, query: 'repo:org/repo deploy' }])).toBe(false) + expect(accepts([kinds[0]!, { ...kinds[0]!, query: 'repo:org/repo deploy' }])).toBe(true) expect(accepts([kinds[0]!, github])).toBe(false) expect( searchWorkspaceInputSchema.safeParse({ nativeQueries: [{ provider: 'github', query: '' }] }) diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts index 70289cee3b0..e34a5d662dd 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts @@ -102,10 +102,10 @@ export const nativeSearchQueriesSchema = z addIssue('Duplicate native query.') else if ( hasSearchKinds(query.provider) && - earlier.some((previous) => !previous.kind || !query.kind || previous.kind === query.kind) + earlier.some((previous) => !previous.kind || !query.kind) ) addIssue( - 'Send one query per account and kind for GitHub, GitLab, or HubSpot. Use provider-supported operators for alternatives, or send another call.' + 'A GitHub, GitLab, or HubSpot query without a kind already searches every kind; give each query on this account a kind.' ) else if (busiestAccountLoad(earlier) >= MAX_NATIVE_QUERIES_PER_ACCOUNT) addIssue( @@ -246,11 +246,12 @@ export const readDocumentInputSchema = z.object({ .min(1) .max(4000) .describe('Canonical document ID returned by search or selected document context.'), + /** A larger request is capped rather than refused: the server returns at most 8 chunks anyway. */ limit: z - .number() - .int() - .min(1) - .max(8) + .preprocess( + (limit) => (typeof limit === 'number' && limit > 8 ? 8 : limit), + z.number().int().min(1).max(8) + ) .default(3) .describe( 'Maximum number of chunks, from 1 to 8 (default 3); the server may return fewer to fit its text budget. Follow next for more context.' diff --git a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts index a41b1ea417a..a43438a7839 100644 --- a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts +++ b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts @@ -119,10 +119,10 @@ export const nativeSearchQueriesSchema = z addIssue('Duplicate native query.') else if ( hasSearchKinds(query.provider) && - earlier.some((previous) => !previous.kind || !query.kind || previous.kind === query.kind) + earlier.some((previous) => !previous.kind || !query.kind) ) addIssue( - 'Send one query per account and kind for GitHub, GitLab, or HubSpot. Use provider-supported operators for alternatives, or send another call.' + 'A GitHub, GitLab, or HubSpot query without a kind already searches every kind; give each query on this account a kind.' ) else if (busiestAccountLoad(earlier) >= MAX_NATIVE_QUERIES_PER_ACCOUNT) addIssue( @@ -263,11 +263,12 @@ export const readDocumentInputSchema = z.object({ .min(1) .max(4000) .describe('Canonical document ID returned by search or selected document context.'), + /** A larger request is capped rather than refused: the server returns at most 8 chunks anyway. */ limit: z - .number() - .int() - .min(1) - .max(8) + .preprocess( + (limit) => (typeof limit === 'number' && limit > 8 ? 8 : limit), + z.number().int().min(1).max(8) + ) .default(3) .describe( 'Maximum number of chunks, from 1 to 8 (default 3); the server may return fewer to fit its text budget. Follow next for more context.' diff --git a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts index 2d05e9fb9b5..3d8173c57d4 100644 --- a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts @@ -5196,7 +5196,6 @@ export const ReadDocument: ToolCatalogEntry = { description: 'Canonical document ID returned by search or selected document context.', }, limit: { - default: 3, description: 'Maximum number of chunks, from 1 to 8 (default 3); the server may return fewer to fit its text budget. Follow next for more context.', type: 'integer', diff --git a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts index 1ec5eafcda1..6cf6dc99a7a 100644 --- a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts @@ -5184,7 +5184,6 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { description: 'Canonical document ID returned by search or selected document context.', }, limit: { - default: 3, description: 'Maximum number of chunks, from 1 to 8 (default 3); the server may return fewer to fit its text budget. Follow next for more context.', type: 'integer', diff --git a/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts b/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts index 2a44b3e3608..284d5a87083 100644 --- a/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts +++ b/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts @@ -376,7 +376,7 @@ describe('Assistant retrieval tools', () => { expect(mocks.search).not.toHaveBeenCalled() expect(mocks.read).not.toHaveBeenCalled() }) - it('reads a selected document through the shared use case and rejects unbounded pages', async () => { + it('reads a selected document through the shared use case and caps oversized pages', async () => { expect( await readDocumentServerTool.execute({ documentId: 'doc', startChunkIndex: 20 }, context) ).toMatchObject({ success: true }) @@ -392,7 +392,9 @@ describe('Assistant retrieval tools', () => { ) expect( await readDocumentServerTool.execute({ documentId: 'doc', limit: 9 }, context) - ).toMatchObject({ success: false }) - expect(mocks.read).toHaveBeenCalledOnce() + ).toMatchObject({ success: true }) + expect(mocks.read).toHaveBeenLastCalledWith( + expect.objectContaining({ input: expect.objectContaining({ limit: 8 }) }) + ) }) }) From 4fc84bb9b4c1e9de1d1e11acda42030ce1945e96 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 28 Sep 2026 23:06:00 -0700 Subject: [PATCH 2/7] fix(search): describe same-kind native queries and test the read cap on the contract --- .../lib/api/contracts/mothership-assistant-tools.test.ts | 7 +++++++ apps/sim/lib/api/contracts/mothership-assistant-tools.ts | 7 ++++--- .../mothership/generated/sim-assistant-tools.generated.ts | 7 ++++--- apps/sim/lib/mothership/generated/tool-catalog-v1.ts | 2 +- apps/sim/lib/mothership/generated/tool-schemas-v1.ts | 2 +- .../tools/server/knowledge/workspace-search.test.ts | 3 --- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts index 2f584dbc153..36562737858 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest' import { z } from 'zod' import { assistantToolContracts, + readDocumentInputSchema, searchWorkspaceInputSchema, } from '@/lib/api/contracts/mothership-assistant-tools' import { TOOL_CATALOG } from '@/lib/mothership/generated/tool-catalog-v1' @@ -57,6 +58,12 @@ describe('Assistant execution contracts', () => { expect(accepts([trip, { ...trip, accountId: 'other' }])).toBe(true) }) + it('caps an oversized read_document limit at the eight chunks the server returns', () => { + expect(readDocumentInputSchema.parse({ documentId: 'doc', limit: 20 }).limit).toBe(8) + expect(readDocumentInputSchema.parse({ documentId: 'doc' }).limit).toBe(3) + expect(readDocumentInputSchema.safeParse({ documentId: 'doc', limit: 0 }).success).toBe(false) + }) + it('runs several same-kind GitHub queries on one account but refuses kind fan-out overlap', () => { const accepts = (nativeQueries: Record[]) => searchWorkspaceInputSchema.safeParse({ query: 'launch', nativeQueries }).success diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts index e34a5d662dd..c8a978c4ac1 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts @@ -16,8 +16,9 @@ export const NOTION_SEARCH_TERMS_REQUIRED = export const MAX_NATIVE_QUERIES_PER_ACCOUNT = 4 /** - * Providers whose kind selects a distinct search collection. One query per kind bounds fanout - * while retaining independently searchable collections within the per-account request limit. + * Providers whose kind selects a distinct search collection. A query without a kind fans out + * across every collection, so it cannot share an account with kinded queries; the per-account + * request limit bounds the rest. */ const PROVIDER_KIND_SCHEMAS = { github: z.enum(['issues', 'code', 'repositories', 'commits']), @@ -187,7 +188,7 @@ export const searchWorkspaceInputSchema = workspaceSearchFiltersSchema nativeQueries: nativeSearchQueriesSchema .optional() .describe( - `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; GitHub, GitLab, and HubSpot take one per kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` + `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; GitHub, GitLab, and HubSpot queries on one account each need a kind, and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` ), query: z .string() diff --git a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts index a43438a7839..c08988cff9d 100644 --- a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts +++ b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts @@ -33,8 +33,9 @@ export const NOTION_SEARCH_TERMS_REQUIRED = export const MAX_NATIVE_QUERIES_PER_ACCOUNT = 4 /** - * Providers whose kind selects a distinct search collection. One query per kind bounds fanout - * while retaining independently searchable collections within the per-account request limit. + * Providers whose kind selects a distinct search collection. A query without a kind fans out + * across every collection, so it cannot share an account with kinded queries; the per-account + * request limit bounds the rest. */ const PROVIDER_KIND_SCHEMAS = { github: z.enum(['issues', 'code', 'repositories', 'commits']), @@ -204,7 +205,7 @@ export const searchWorkspaceInputSchema = workspaceSearchFiltersSchema nativeQueries: nativeSearchQueriesSchema .optional() .describe( - `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; GitHub, GitLab, and HubSpot take one per kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` + `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; GitHub, GitLab, and HubSpot queries on one account each need a kind, and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` ), query: z .string() diff --git a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts index 3d8173c57d4..46f7fb14107 100644 --- a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts @@ -6095,7 +6095,7 @@ export const SearchWorkspace: ToolCatalogEntry = { }, nativeQueries: { description: - "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; GitHub, GitLab, and HubSpot take one per kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", + "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; GitHub, GitLab, and HubSpot queries on one account each need a kind, and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", minItems: 1, maxItems: 9, type: 'array', diff --git a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts index 6cf6dc99a7a..e8735649e02 100644 --- a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts @@ -6043,7 +6043,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, nativeQueries: { description: - "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; GitHub, GitLab, and HubSpot take one per kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", + "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; GitHub, GitLab, and HubSpot queries on one account each need a kind, and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", minItems: 1, maxItems: 9, type: 'array', diff --git a/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts b/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts index 284d5a87083..02f838a1424 100644 --- a/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts +++ b/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts @@ -393,8 +393,5 @@ describe('Assistant retrieval tools', () => { expect( await readDocumentServerTool.execute({ documentId: 'doc', limit: 9 }, context) ).toMatchObject({ success: true }) - expect(mocks.read).toHaveBeenLastCalledWith( - expect.objectContaining({ input: expect.objectContaining({ limit: 8 }) }) - ) }) }) From 30368b5f37f7650957fc9000fc618466e0c092da Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 28 Sep 2026 23:28:53 -0700 Subject: [PATCH 3/7] fix(search): test the read cap through tool output and describe kindless native queries --- .../mothership-assistant-tools.test.ts | 7 ------- .../contracts/mothership-assistant-tools.ts | 2 +- .../generated/sim-assistant-tools.generated.ts | 2 +- .../mothership/generated/tool-catalog-v1.ts | 2 +- .../mothership/generated/tool-schemas-v1.ts | 2 +- .../server/knowledge/workspace-search.test.ts | 18 +++++++++++++++--- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts index 36562737858..2f584dbc153 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts @@ -2,7 +2,6 @@ import { describe, expect, it } from 'vitest' import { z } from 'zod' import { assistantToolContracts, - readDocumentInputSchema, searchWorkspaceInputSchema, } from '@/lib/api/contracts/mothership-assistant-tools' import { TOOL_CATALOG } from '@/lib/mothership/generated/tool-catalog-v1' @@ -58,12 +57,6 @@ describe('Assistant execution contracts', () => { expect(accepts([trip, { ...trip, accountId: 'other' }])).toBe(true) }) - it('caps an oversized read_document limit at the eight chunks the server returns', () => { - expect(readDocumentInputSchema.parse({ documentId: 'doc', limit: 20 }).limit).toBe(8) - expect(readDocumentInputSchema.parse({ documentId: 'doc' }).limit).toBe(3) - expect(readDocumentInputSchema.safeParse({ documentId: 'doc', limit: 0 }).success).toBe(false) - }) - it('runs several same-kind GitHub queries on one account but refuses kind fan-out overlap', () => { const accepts = (nativeQueries: Record[]) => searchWorkspaceInputSchema.safeParse({ query: 'launch', nativeQueries }).success diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts index c8a978c4ac1..13c864d614f 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts @@ -188,7 +188,7 @@ export const searchWorkspaceInputSchema = workspaceSearchFiltersSchema nativeQueries: nativeSearchQueriesSchema .optional() .describe( - `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; GitHub, GitLab, and HubSpot queries on one account each need a kind, and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` + `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; for GitHub, GitLab, and HubSpot, one query without a kind searches every kind, while multiple queries on one account each need a kind and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` ), query: z .string() diff --git a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts index c08988cff9d..6a449fcd294 100644 --- a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts +++ b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts @@ -205,7 +205,7 @@ export const searchWorkspaceInputSchema = workspaceSearchFiltersSchema nativeQueries: nativeSearchQueriesSchema .optional() .describe( - `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; GitHub, GitLab, and HubSpot queries on one account each need a kind, and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` + `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; for GitHub, GitLab, and HubSpot, one query without a kind searches every kind, while multiple queries on one account each need a kind and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` ), query: z .string() diff --git a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts index 46f7fb14107..ceea0931162 100644 --- a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts @@ -6095,7 +6095,7 @@ export const SearchWorkspace: ToolCatalogEntry = { }, nativeQueries: { description: - "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; GitHub, GitLab, and HubSpot queries on one account each need a kind, and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", + "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; for GitHub, GitLab, and HubSpot, one query without a kind searches every kind, while multiple queries on one account each need a kind and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", minItems: 1, maxItems: 9, type: 'array', diff --git a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts index e8735649e02..2edae94e1ed 100644 --- a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts @@ -6043,7 +6043,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, nativeQueries: { description: - "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; GitHub, GitLab, and HubSpot queries on one account each need a kind, and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", + "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; for GitHub, GitLab, and HubSpot, one query without a kind searches every kind, while multiple queries on one account each need a kind and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", minItems: 1, maxItems: 9, type: 'array', diff --git a/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts b/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts index 02f838a1424..00e482484c4 100644 --- a/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts +++ b/apps/sim/lib/mothership/tools/server/knowledge/workspace-search.test.ts @@ -390,8 +390,20 @@ describe('Assistant retrieval tools', () => { }), }) ) - expect( - await readDocumentServerTool.execute({ documentId: 'doc', limit: 9 }, context) - ).toMatchObject({ success: true }) + mocks.read.mockImplementationOnce(async ({ input }: { input: { limit: number } }) => ({ + knowledgeBaseId: 'index', + documentId: 'doc', + documentName: 'Title', + sourceUrl: 'https://source.test/doc', + chunks: Array.from({ length: input.limit }, (_, chunkIndex) => ({ + content: 'body', + chunkIndex, + })), + hasMore: true, + next: null, + })) + const capped = await readDocumentServerTool.execute({ documentId: 'doc', limit: 9 }, context) + expect(capped).toMatchObject({ success: true }) + expect((capped as { data: { chunks: unknown[] } }).data.chunks).toHaveLength(8) }) }) From b60617fc134208ae35fbb2dad56f1fe6f8d19a31 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 28 Sep 2026 23:50:43 -0700 Subject: [PATCH 4/7] fix(search): state what a kindless GitHub, GitLab, or HubSpot query covers --- apps/sim/lib/api/contracts/mothership-assistant-tools.ts | 2 +- .../lib/mothership/generated/sim-assistant-tools.generated.ts | 2 +- apps/sim/lib/mothership/generated/tool-catalog-v1.ts | 2 +- apps/sim/lib/mothership/generated/tool-schemas-v1.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts index 13c864d614f..98c6db0fa09 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts @@ -188,7 +188,7 @@ export const searchWorkspaceInputSchema = workspaceSearchFiltersSchema nativeQueries: nativeSearchQueriesSchema .optional() .describe( - `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; for GitHub, GitLab, and HubSpot, one query without a kind searches every kind, while multiple queries on one account each need a kind and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` + `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues and code, GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` ), query: z .string() diff --git a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts index 6a449fcd294..2014c4c0e61 100644 --- a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts +++ b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts @@ -205,7 +205,7 @@ export const searchWorkspaceInputSchema = workspaceSearchFiltersSchema nativeQueries: nativeSearchQueriesSchema .optional() .describe( - `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; for GitHub, GitLab, and HubSpot, one query without a kind searches every kind, while multiple queries on one account each need a kind and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` + `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues and code, GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` ), query: z .string() diff --git a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts index ceea0931162..9d978a137b7 100644 --- a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts @@ -6095,7 +6095,7 @@ export const SearchWorkspace: ToolCatalogEntry = { }, nativeQueries: { description: - "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; for GitHub, GitLab, and HubSpot, one query without a kind searches every kind, while multiple queries on one account each need a kind and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", + "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues and code, GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", minItems: 1, maxItems: 9, type: 'array', diff --git a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts index 2edae94e1ed..7c60a0df5cc 100644 --- a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts @@ -6043,7 +6043,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, nativeQueries: { description: - "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; for GitHub, GitLab, and HubSpot, one query without a kind searches every kind, while multiple queries on one account each need a kind and may repeat a kind. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", + "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues and code, GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", minItems: 1, maxItems: 9, type: 'array', From 02ec1b8c9e4d223a12f0d3ae9ee2820714a1391b Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 29 Sep 2026 00:17:27 -0700 Subject: [PATCH 5/7] fix(search): kindless queries fan out across default collections --- apps/sim/lib/api/contracts/mothership-assistant-tools.ts | 4 ++-- .../lib/mothership/generated/sim-assistant-tools.generated.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts index 98c6db0fa09..8a24c5ae549 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts @@ -17,8 +17,8 @@ export const MAX_NATIVE_QUERIES_PER_ACCOUNT = 4 /** * Providers whose kind selects a distinct search collection. A query without a kind fans out - * across every collection, so it cannot share an account with kinded queries; the per-account - * request limit bounds the rest. + * across its provider's default collections, so it cannot share an account with kinded queries; + * the per-account request limit bounds the rest. */ const PROVIDER_KIND_SCHEMAS = { github: z.enum(['issues', 'code', 'repositories', 'commits']), diff --git a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts index 2014c4c0e61..26a9cb229d0 100644 --- a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts +++ b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts @@ -34,8 +34,8 @@ export const MAX_NATIVE_QUERIES_PER_ACCOUNT = 4 /** * Providers whose kind selects a distinct search collection. A query without a kind fans out - * across every collection, so it cannot share an account with kinded queries; the per-account - * request limit bounds the rest. + * across its provider's default collections, so it cannot share an account with kinded queries; + * the per-account request limit bounds the rest. */ const PROVIDER_KIND_SCHEMAS = { github: z.enum(['issues', 'code', 'repositories', 'commits']), From f7221071e0d1d80dbe3f5880ad2865da6f81aeb8 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 29 Sep 2026 00:45:20 -0700 Subject: [PATCH 6/7] fix(search): kindless GitHub queries search code only without date bounds or boolean operators --- apps/sim/lib/api/contracts/mothership-assistant-tools.ts | 2 +- .../lib/mothership/generated/sim-assistant-tools.generated.ts | 2 +- apps/sim/lib/mothership/generated/tool-catalog-v1.ts | 2 +- apps/sim/lib/mothership/generated/tool-schemas-v1.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts index 8a24c5ae549..109948291a6 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.ts @@ -188,7 +188,7 @@ export const searchWorkspaceInputSchema = workspaceSearchFiltersSchema nativeQueries: nativeSearchQueriesSchema .optional() .describe( - `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues and code, GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` + `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues (plus code when the query has no date bound or boolean operators, as its status message says), GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` ), query: z .string() diff --git a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts index 26a9cb229d0..e9f86f3e8a2 100644 --- a/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts +++ b/apps/sim/lib/mothership/generated/sim-assistant-tools.generated.ts @@ -205,7 +205,7 @@ export const searchWorkspaceInputSchema = workspaceSearchFiltersSchema nativeQueries: nativeSearchQueriesSchema .optional() .describe( - `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues and code, GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` + `Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to ${MAX_NATIVE_QUERIES_PER_ACCOUNT} per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues (plus code when the query has no date bound or boolean operators, as its status message says), GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.` ), query: z .string() diff --git a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts index 9d978a137b7..35b58f4b7d5 100644 --- a/apps/sim/lib/mothership/generated/tool-catalog-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-catalog-v1.ts @@ -6095,7 +6095,7 @@ export const SearchWorkspace: ToolCatalogEntry = { }, nativeQueries: { description: - "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues and code, GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", + "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues (plus code when the query has no date bound or boolean operators, as its status message says), GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", minItems: 1, maxItems: 9, type: 'array', diff --git a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts index 7c60a0df5cc..51b94ea62ce 100644 --- a/apps/sim/lib/mothership/generated/tool-schemas-v1.ts +++ b/apps/sim/lib/mothership/generated/tool-schemas-v1.ts @@ -6043,7 +6043,7 @@ export const TOOL_RUNTIME_SCHEMAS: Record = { }, nativeQueries: { description: - "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues and code, GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", + "Live search only: queries in a provider's own language (Drive q, Gmail operators, JQL, CQL, GitHub qualifiers, Slack RTS, plain Linear/Fireflies/HubSpot terms, Granola natural-language questions, Notion keywords or AI questions when available). Blank queries require a date bound or sortBy newest/oldest; Notion always requires search terms. Up to 4 per account run separately and merge; one GitHub, GitLab, or HubSpot query without a kind searches GitHub issues (plus code when the query has no date bound or boolean operators, as its status message says), GitLab issues, merge requests, and code, or every HubSpot CRM kind; other collections, and multiple queries on one account, each need a kind, which may repeat. HubSpot kinds are contacts, companies, deals, and tickets; ownership filters are unsupported. Write queries from the returned live guidance and account IDs; each account status names the queryIndex its cursor belongs to. Omit for simple cross-provider terms.", minItems: 1, maxItems: 9, type: 'array', From b62b2dc6928d228f121a67b2078060f0192f135d Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 29 Sep 2026 01:15:57 -0700 Subject: [PATCH 7/7] test(search): keep only the refusal the contract still enforces --- apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts b/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts index 2f584dbc153..aef3a59c2af 100644 --- a/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts +++ b/apps/sim/lib/api/contracts/mothership-assistant-tools.test.ts @@ -57,13 +57,12 @@ describe('Assistant execution contracts', () => { expect(accepts([trip, { ...trip, accountId: 'other' }])).toBe(true) }) - it('runs several same-kind GitHub queries on one account but refuses kind fan-out overlap', () => { + it('refuses a kindless GitHub query alongside kinded queries on one account', () => { const accepts = (nativeQueries: Record[]) => searchWorkspaceInputSchema.safeParse({ query: 'launch', nativeQueries }).success const github = { provider: 'github', accountId: 'account', query: 'repo:org/repo launch' } const kinds = ['issues', 'commits', 'code', 'repositories'].map((kind) => ({ ...github, kind })) expect(accepts(kinds)).toBe(true) - expect(accepts([kinds[0]!, { ...kinds[0]!, query: 'repo:org/repo deploy' }])).toBe(true) expect(accepts([kinds[0]!, github])).toBe(false) expect( searchWorkspaceInputSchema.safeParse({ nativeQueries: [{ provider: 'github', query: '' }] })