From c75669fc10555857324ff620f6b085eb24ea0f34 Mon Sep 17 00:00:00 2001 From: Garrett Delfosse Date: Mon, 24 Aug 2026 13:26:24 +0000 Subject: [PATCH 1/3] docs(docs/ai-coder/agents): document the chat search: full-text filter --- docs/ai-coder/agents/chat-search-syntax.md | 68 +++++++++++++++++----- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/docs/ai-coder/agents/chat-search-syntax.md b/docs/ai-coder/agents/chat-search-syntax.md index 4551c2fd2531c..0559ce2cf8d27 100644 --- a/docs/ai-coder/agents/chat-search-syntax.md +++ b/docs/ai-coder/agents/chat-search-syntax.md @@ -2,22 +2,53 @@ The chat list endpoint accepts a `q` query parameter for filtering conversations. All filters use `key:value` syntax. Bare search terms -are rejected; use `title:` for title filtering. +are rejected; use `title:` for title filtering or `search:` for +full-text search. ## Filters -| Key | Values | Description | -|--------------|-------------------------------------|----------------------------------------------------------------------------------------------------| -| `title` | substring | Case-insensitive substring match. Quote multi-word values. | -| `archived` | `true`, `false` | Filter by archived state. Default: `false`. | -| `has_unread` | `true`, `false` | Conversations with unread assistant messages. | -| `pr_status` | `draft`, `open`, `merged`, `closed` | Linked pull request state. Comma-separated for OR. | -| `diff_url` | URL | Match by associated diff URL. Quote values containing colons. | -| `pr` | positive integer | Exact PR number match. | -| `repo` | substring | Case-insensitive substring match against git remote origin or URL. Quote values containing colons. | -| `pr_title` | substring | Case-insensitive PR title substring match. Quote multi-word values. | - -Multiple filters in one query combine with AND logic. +| Key | Values | Description | +|--------------|-------------------------------------|-----------------------------------------------------------------------------------------------------------| +| `title` | substring | Case-insensitive substring match. Quote multi-word values. | +| `archived` | `true`, `false` | Filter by archived state. Default: `false`. | +| `has_unread` | `true`, `false` | Conversations with unread assistant messages. | +| `pr_status` | `draft`, `open`, `merged`, `closed` | Linked pull request state. Comma-separated for OR. | +| `diff_url` | URL | Match by associated diff URL. Quote values containing colons. | +| `pr` | positive integer | Exact PR number match. | +| `repo` | substring | Case-insensitive substring match against git remote origin or URL. Quote values containing colons. | +| `pr_title` | substring | Case-insensitive PR title substring match. Quote multi-word values. | +| `search` | text | Full-text search across chat titles, PR titles, PR numbers, and message content. Quote multi-word values. | + +Multiple filters in one query combine with AND logic. `search:` cannot +be combined with `title:`, `pr_title:`, or `pr:`. + +## Full-text search + +`search:` uses token-based PostgreSQL full-text search with the +`english` text search configuration: + +- Matching is case-insensitive. Every word in the value must match + (AND semantics). Quoted phrases, `OR`, and `-` negation follow + [`websearch_to_tsquery`](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES) + semantics. +- English word stems match, so `refactor` matches `refactoring`. There + is no fuzzy, semantic, or partial-word (prefix) matching. +- Common English stopwords (such as `the`, `or`, `and`) are dropped + during tokenization. A value that tokenizes to no searchable words, + including stopword-only or punctuation-only values, returns an empty + list. An empty `search:` value returns HTTP 400. +- A value that is a whole number also matches chats by exact PR number. +- Results list matching conversations only; there are no match snippets + or highlights. +- Results use the standard chat list ordering (pinned conversations + first, then most recently updated) and pagination (default page size + 50). +- Message content is indexed by a background job and becomes searchable + shortly after it is written, usually within 10 minutes. Chat titles + and PR titles are searchable immediately. + +The `title:`, `pr_title:`, and `repo:` filters are unaffected: they use +case-insensitive `ILIKE` substring matching, not full-text search. ## Examples @@ -48,6 +79,15 @@ Multiple filters in one query combine with AND logic. # Conversations with a specific PR title ?q=pr_title:"fix auth bug" + +# Full-text search across titles, PR titles, and messages +?q=search:deploy + +# Multi-word full-text search (all words must match) +?q=search:"kubernetes restart" + +# Combine full-text search with other filters +?q=search:refactor+pr_status:open ``` ## Notes @@ -56,4 +96,4 @@ Multiple filters in one query combine with AND logic. - `pr_status:draft` means the PR is open **and** marked as a draft. `pr_status:open` means the PR is open and not a draft. - Conversations without a linked diff status are excluded when `pr_status`, `pr`, `repo`, or `pr_title` is set. The `repo:` filter also matches chats tracking a branch with no PR. -- Unrecognized keys or bare terms return HTTP 400 with a validation error. +- Unrecognized keys, bare terms, or combining `search:` with `title:`, `pr_title:`, or `pr:` return HTTP 400 with a validation error. From e8824befb2dbd067b85df5421471bfb8cf1e1cd4 Mon Sep 17 00:00:00 2001 From: Garrett Delfosse Date: Mon, 24 Aug 2026 17:32:19 +0000 Subject: [PATCH 2/3] docs(docs/ai-coder/agents): scope search stemming to message content --- docs/ai-coder/agents/chat-search-syntax.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/ai-coder/agents/chat-search-syntax.md b/docs/ai-coder/agents/chat-search-syntax.md index 0559ce2cf8d27..2b1933a85c046 100644 --- a/docs/ai-coder/agents/chat-search-syntax.md +++ b/docs/ai-coder/agents/chat-search-syntax.md @@ -24,19 +24,20 @@ be combined with `title:`, `pr_title:`, or `pr:`. ## Full-text search -`search:` uses token-based PostgreSQL full-text search with the -`english` text search configuration: +`search:` uses token-based PostgreSQL full-text search: - Matching is case-insensitive. Every word in the value must match (AND semantics). Quoted phrases, `OR`, and `-` negation follow [`websearch_to_tsquery`](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES) semantics. -- English word stems match, so `refactor` matches `refactoring`. There - is no fuzzy, semantic, or partial-word (prefix) matching. -- Common English stopwords (such as `the`, `or`, `and`) are dropped - during tokenization. A value that tokenizes to no searchable words, - including stopword-only or punctuation-only values, returns an empty - list. An empty `search:` value returns HTTP 400. +- Chat titles and PR titles match whole words without stemming. +- Message content matches English word stems, so `refactor` matches a + message containing `refactoring`, and ignores common English + stopwords (such as `the`, `or`, `and`). +- There is no fuzzy, semantic, or partial-word (prefix) matching. +- A value that tokenizes to no searchable words, such as punctuation + only, returns an empty list. An empty `search:` value returns HTTP + 400. - A value that is a whole number also matches chats by exact PR number. - Results list matching conversations only; there are no match snippets or highlights. From 6cd722fa7736d60ecf0a2f705c4d51c4c0a207a7 Mon Sep 17 00:00:00 2001 From: Garrett Delfosse Date: Tue, 25 Aug 2026 12:35:24 +0000 Subject: [PATCH 3/3] docs(docs/ai-coder/agents): tighten the chat full-text search section --- docs/ai-coder/agents/chat-search-syntax.md | 41 ++++++++-------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/docs/ai-coder/agents/chat-search-syntax.md b/docs/ai-coder/agents/chat-search-syntax.md index 2b1933a85c046..bd4f046b4897c 100644 --- a/docs/ai-coder/agents/chat-search-syntax.md +++ b/docs/ai-coder/agents/chat-search-syntax.md @@ -26,30 +26,22 @@ be combined with `title:`, `pr_title:`, or `pr:`. `search:` uses token-based PostgreSQL full-text search: -- Matching is case-insensitive. Every word in the value must match - (AND semantics). Quoted phrases, `OR`, and `-` negation follow +- Case-insensitive whole-word matching with AND semantics. Quoted + phrases, `OR`, and `-` negation follow [`websearch_to_tsquery`](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES) - semantics. -- Chat titles and PR titles match whole words without stemming. -- Message content matches English word stems, so `refactor` matches a - message containing `refactoring`, and ignores common English - stopwords (such as `the`, `or`, `and`). -- There is no fuzzy, semantic, or partial-word (prefix) matching. -- A value that tokenizes to no searchable words, such as punctuation - only, returns an empty list. An empty `search:` value returns HTTP - 400. -- A value that is a whole number also matches chats by exact PR number. -- Results list matching conversations only; there are no match snippets - or highlights. -- Results use the standard chat list ordering (pinned conversations - first, then most recently updated) and pagination (default page size - 50). -- Message content is indexed by a background job and becomes searchable - shortly after it is written, usually within 10 minutes. Chat titles - and PR titles are searchable immediately. - -The `title:`, `pr_title:`, and `repo:` filters are unaffected: they use -case-insensitive `ILIKE` substring matching, not full-text search. + rules. +- Message content matches English word stems (`refactor` matches + `refactoring`) and ignores English stopwords. Titles and PR titles + do not stem. +- No fuzzy, semantic, or prefix matching. +- Whole-number values also match exact PR numbers. +- A value with no searchable words (punctuation only) returns an empty + list; an empty value returns HTTP 400. +- Results use the standard chat list ordering (pinned first, then most + recently updated) and pagination, without match snippets. +- Message content becomes searchable shortly after it is written + (background indexing, usually within 10 minutes). Titles and PR + titles are searchable immediately. ## Examples @@ -82,9 +74,6 @@ case-insensitive `ILIKE` substring matching, not full-text search. ?q=pr_title:"fix auth bug" # Full-text search across titles, PR titles, and messages -?q=search:deploy - -# Multi-word full-text search (all words must match) ?q=search:"kubernetes restart" # Combine full-text search with other filters