From 6edab1b651d37c334d1ea5fdd372d5813664163d Mon Sep 17 00:00:00 2001 From: Justin Blumencranz <96924014+j15z@users.noreply.github.com> Date: Fri, 24 Jul 2026 19:13:24 -0700 Subject: [PATCH] test(copilot): catch a tool silently dropping its query from the chip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "has an intentional display title for every visible catalog tool" assertion only checks that a title exists. A bare fallback label satisfies it exactly as well as the useful one, so a tool that DID show its query can lose that behavior with the suite still green — a coarse check contented by a degraded state. Adds a subset ratchet: any catalog tool that takes a `query` must show it, unless it is in a documented allowlist. The set may shrink, never grow, so removing a tool or teaching one to show its query needs no update here. Baselines the three tools that ignore their query today rather than changing their chips — making the rule true everywhere is a UX change and does not belong in a test-hardening commit. Verified by removing an entry from the allowlist: the assertion fails with the offending tool named. --- .../lib/copilot/tools/tool-display.test.ts | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/apps/sim/lib/copilot/tools/tool-display.test.ts b/apps/sim/lib/copilot/tools/tool-display.test.ts index da571a7cd01..156cfa546a4 100644 --- a/apps/sim/lib/copilot/tools/tool-display.test.ts +++ b/apps/sim/lib/copilot/tools/tool-display.test.ts @@ -84,6 +84,45 @@ describe('getToolDisplayTitle natural-language coverage', () => { ) }) + /** + * Tools that take a `query` but whose chip does not show it. This set may + * SHRINK, never grow — the assertion below is a subset check, so removing a + * tool or teaching one to show its query needs no update here. + * + * The point is to catch a specific silent regression: a tool that DID show + * its query losing that behavior. The neighbouring "has an intentional + * display title" test cannot catch it, because a bare fallback label like + * "Searching docs" satisfies it just as well as the useful one — a coarse + * check contented by a degraded state. + */ + const TITLES_IGNORING_QUERY = new Set([ + 'search_documentation', + 'search_library_docs', + // Has an argument-aware case, but reads toolTitle/title and never falls + // back to query. + 'search_online', + ]) + + it('no tool silently stops showing its query in the chip', () => { + const hiddenToolNames = getHiddenToolNames() + const regressions = Object.entries(TOOL_CATALOG) + .filter(([name, entry]) => !hiddenToolNames.has(name) && !entry.internal) + .filter(([, entry]) => { + const properties = (entry.parameters as { properties?: Record }) + ?.properties + return properties !== undefined && 'query' in properties + }) + .filter(([name]) => { + const withoutArgs = getToolDisplayTitle(name) + const withQuery = getToolDisplayTitle(name, { query: 'a distinctive query' }) + return withoutArgs === withQuery + }) + .map(([name]) => name) + .filter((name) => !TITLES_IGNORING_QUERY.has(name)) + + expect(regressions).toEqual([]) + }) + it('has an intentional display title for every visible catalog tool', () => { const hiddenToolNames = getHiddenToolNames() const fallbackToolNames = Object.keys(TOOL_CATALOG).filter(