From 1c9c1607b8353bd6f2f4e679c6ab5031c05fd397 Mon Sep 17 00:00:00 2001 From: tommaso-moro Date: Mon, 27 Jul 2026 10:25:37 +0100 Subject: [PATCH 1/2] Promote fields parameter beyond Insiders Keep fields_param as an independently controlled feature flag while removing it from the Insiders expansion. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/insiders-features.md | 90 -------------------------------- pkg/github/feature_flags.go | 1 - pkg/github/feature_flags_test.go | 4 +- 3 files changed, 2 insertions(+), 93 deletions(-) diff --git a/docs/insiders-features.md b/docs/insiders-features.md index f85870ef20..10df187a91 100644 --- a/docs/insiders-features.md +++ b/docs/insiders-features.md @@ -133,96 +133,6 @@ The list below is generated from the Go source. It covers tool **inventory and s - 'blocked_by' - the subject issue is blocked by the related issue. - 'blocking' - the subject issue blocks the related issue. (string, required) -### `fields_param` - -- **get_file_contents** - Get file or directory contents - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each entry when the path is a directory. If omitted, all fields are returned. Ignored when the path is a single file. Use this to reduce response size when listing directories and you only need specific fields, e.g. just 'name' and 'type'. (string[], optional) - - `owner`: Repository owner (username or organization) (string, required) - - `path`: Path to file/directory (string, optional) - - `ref`: Accepts optional git refs such as `refs/tags/{tag}`, `refs/heads/{branch}` or `refs/pull/{pr_number}/head` (string, optional) - - `repo`: Repository name (string, required) - - `sha`: Accepts optional commit SHA. If specified, it will be used instead of ref (string, optional) - -- **list_commits** - List commits - - **Required OAuth Scopes**: `repo` - - `author`: Author username or email address to filter commits by (string, optional) - - `fields`: Subset of fields to return for each commit. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields, e.g. just 'sha' and 'html_url'. (string[], optional) - - `owner`: Repository owner (string, required) - - `page`: Page number for pagination (min 1) (number, optional) - - `path`: Only commits containing this file path will be returned (string, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `repo`: Repository name (string, required) - - `sha`: Commit SHA, branch or tag name to list commits of. If not provided, uses the default branch of the repository. If a commit SHA is provided, will list commits up to that SHA. (string, optional) - - `since`: Only commits after this date will be returned (ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DD) (string, optional) - - `until`: Only commits before this date will be returned (ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DD) (string, optional) - -- **list_issues** - List issues - - **Required OAuth Scopes**: `repo` - - `after`: Cursor for pagination. Use the cursor from the previous response. (string, optional) - - `direction`: Order direction. If provided, the 'orderBy' also needs to be provided. (string, optional) - - `field_filters`: Filter by custom issue field values. Each entry takes a field_name and a value; the server looks up the field and coerces the value to its type (single-select option name, text, number, or YYYY-MM-DD date). (object[], optional) - - `fields`: Subset of fields to return for each issue. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' and 'field_values' in particular drops the largest per-result data. (string[], optional) - - `labels`: Filter by labels (string[], optional) - - `orderBy`: Order issues by field. If provided, the 'direction' also needs to be provided. (string, optional) - - `owner`: Repository owner (string, required) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `repo`: Repository name (string, required) - - `since`: Filter by date (ISO 8601 timestamp) (string, optional) - - `state`: Filter by state, by default both open and closed issues are returned when not provided (string, optional) - -- **list_pull_requests** - List pull requests - - **Required OAuth Scopes**: `repo` - - `base`: Filter by base branch (string, optional) - - `direction`: Sort direction (string, optional) - - `fields`: Subset of fields to return for each pull request. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-result data. (string[], optional) - - `head`: Filter by head user/org and branch (string, optional) - - `owner`: Repository owner (string, required) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `repo`: Repository name (string, required) - - `sort`: Sort by (string, optional) - - `state`: Filter by state (string, optional) - -- **list_releases** - List releases - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each release. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-release data. (string[], optional) - - `owner`: Repository owner (string, required) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `repo`: Repository name (string, required) - -- **search_code** - Search code - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each code search result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'repository' and 'text_matches' in particular drops the largest per-result data. (string[], optional) - - `order`: Sort order for results (string, optional) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `query`: Search query (GitHub code search REST). Implicit AND between terms; supports `OR`, `NOT`, and `"quoted phrase"` for exact match. Qualifiers: `repo:owner/repo`, `org:`, `user:`, `language:`, `path:dir` (prefix match), `filename:exact.ext`, `extension:`, `in:file`, `in:path`, `size:`, `is:archived`, `is:fork`. Max 256 chars. Examples: `WithContext language:go org:github`; `"package main" repo:o/r`; `func extension:go path:cmd repo:o/r`; `NOT TODO language:go repo:o/r`. (string, required) - - `sort`: Sort field ('indexed' only) (string, optional) - -- **search_issues** - Search issues - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each issue result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data. (string[], optional) - - `order`: Sort order (string, optional) - - `owner`: Optional repository owner. If provided with repo, only issues for this repository are listed. (string, optional) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `query`: Search query using GitHub issues search syntax (string, required) - - `repo`: Optional repository name. If provided with owner, only issues for this repository are listed. (string, optional) - - `sort`: Sort field by number of matches of categories, defaults to best match (string, optional) - -- **search_pull_requests** - Search pull requests - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each pull request result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data. (string[], optional) - - `order`: Sort order (string, optional) - - `owner`: Optional repository owner. If provided with repo, only pull requests for this repository are listed. (string, optional) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `query`: Search query using GitHub pull request search syntax (string, required) - - `repo`: Optional repository name. If provided with owner, only pull requests for this repository are listed. (string, optional) - - `sort`: Sort field by number of matches of categories, defaults to best match (string, optional) - --- diff --git a/pkg/github/feature_flags.go b/pkg/github/feature_flags.go index b0652c3346..5c427eb601 100644 --- a/pkg/github/feature_flags.go +++ b/pkg/github/feature_flags.go @@ -60,7 +60,6 @@ var InsidersFeatureFlags = []string{ FeatureFlagCSVOutput, FeatureFlagFileBlame, FeatureFlagIssueDependencies, - FeatureFlagFieldsParam, } // FeatureFlags defines runtime feature toggles that adjust tool behavior. diff --git a/pkg/github/feature_flags_test.go b/pkg/github/feature_flags_test.go index 30f2b56122..fb648e744f 100644 --- a/pkg/github/feature_flags_test.go +++ b/pkg/github/feature_flags_test.go @@ -177,10 +177,10 @@ func TestResolveFeatureFlags(t *testing.T) { expectedFlags: InsidersFeatureFlags, }, { - name: "insiders mode enables fields param", + name: "insiders mode does not enable fields param", enabledFeatures: nil, insidersMode: true, - expectedFlags: []string{FeatureFlagFieldsParam}, + unexpectedFlags: []string{FeatureFlagFieldsParam}, }, { name: "insiders mode does not auto-enable ifc labels", From 227d29bec81821e1a8596ca4a065fa3864af39de Mon Sep 17 00:00:00 2001 From: tommaso-moro Date: Wed, 29 Jul 2026 12:03:56 +0100 Subject: [PATCH 2/2] Make fields parameter available by default Remove the fields_param feature flag and legacy tool variants so selected read tools always advertise and honor fields. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c43cc70-27b5-47b4-bbd1-99d20f42d61b --- README.md | 8 + docs/feature-flags.md | 90 ---------- .../__toolsnaps__/get_file_contents.snap | 18 ++ .../get_file_contents_ff_fields_param.snap | 57 ------- pkg/github/__toolsnaps__/list_commits.snap | 14 ++ .../list_commits_ff_fields_param.snap | 71 -------- pkg/github/__toolsnaps__/list_issues.snap | 19 +++ .../list_issues_ff_fields_param.snap | 112 ------------- .../__toolsnaps__/list_pull_requests.snap | 34 ++++ .../list_pull_requests_ff_fields_param.snap | 106 ------------ pkg/github/__toolsnaps__/list_releases.snap | 18 ++ .../list_releases_ff_fields_param.snap | 55 ------ pkg/github/__toolsnaps__/search_code.snap | 14 ++ .../search_code_ff_fields_param.snap | 58 ------- pkg/github/__toolsnaps__/search_issues.snap | 33 ++++ .../search_issues_ff_fields_param.snap | 98 ----------- .../__toolsnaps__/search_pull_requests.snap | 31 ++++ .../search_pull_requests_ff_fields_param.snap | 96 ----------- pkg/github/feature_flags.go | 9 - pkg/github/feature_flags_test.go | 16 -- pkg/github/fields_filtering_test.go | 74 -------- pkg/github/fields_param_gating_test.go | 84 ---------- pkg/github/issues.go | 101 +++-------- pkg/github/issues_test.go | 12 +- pkg/github/pullrequests.go | 101 ++--------- pkg/github/pullrequests_test.go | 12 +- pkg/github/repositories.go | 158 ++++-------------- pkg/github/repositories_test.go | 32 +--- pkg/github/search.go | 53 ++---- pkg/github/search_test.go | 20 +-- pkg/github/tools.go | 8 - 31 files changed, 274 insertions(+), 1338 deletions(-) delete mode 100644 pkg/github/__toolsnaps__/get_file_contents_ff_fields_param.snap delete mode 100644 pkg/github/__toolsnaps__/list_commits_ff_fields_param.snap delete mode 100644 pkg/github/__toolsnaps__/list_issues_ff_fields_param.snap delete mode 100644 pkg/github/__toolsnaps__/list_pull_requests_ff_fields_param.snap delete mode 100644 pkg/github/__toolsnaps__/list_releases_ff_fields_param.snap delete mode 100644 pkg/github/__toolsnaps__/search_code_ff_fields_param.snap delete mode 100644 pkg/github/__toolsnaps__/search_issues_ff_fields_param.snap delete mode 100644 pkg/github/__toolsnaps__/search_pull_requests_ff_fields_param.snap delete mode 100644 pkg/github/fields_param_gating_test.go diff --git a/README.md b/README.md index 1a06c0697d..61021f2950 100644 --- a/README.md +++ b/README.md @@ -960,6 +960,7 @@ The following sets of tools are available: - `after`: Cursor for pagination. Use the cursor from the previous response. (string, optional) - `direction`: Order direction. If provided, the 'orderBy' also needs to be provided. (string, optional) - `field_filters`: Filter by custom issue field values. Each entry takes a field_name and a value; the server looks up the field and coerces the value to its type (single-select option name, text, number, or YYYY-MM-DD date). (object[], optional) + - `fields`: Subset of fields to return for each issue. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' and 'field_values' in particular drops the largest per-result data. (string[], optional) - `labels`: Filter by labels (string[], optional) - `orderBy`: Order issues by field. If provided, the 'direction' also needs to be provided. (string, optional) - `owner`: Repository owner (string, required) @@ -970,6 +971,7 @@ The following sets of tools are available: - **search_issues** - Search issues - **Required OAuth Scopes**: `repo` + - `fields`: Subset of fields to return for each issue result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data. (string[], optional) - `order`: Sort order (string, optional) - `owner`: Optional repository owner. If provided with repo, only issues for this repository are listed. (string, optional) - `page`: Page number for pagination (min 1) (number, optional) @@ -1178,6 +1180,7 @@ The following sets of tools are available: - **Required OAuth Scopes**: `repo` - `base`: Filter by base branch (string, optional) - `direction`: Sort direction (string, optional) + - `fields`: Subset of fields to return for each pull request. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-result data. (string[], optional) - `head`: Filter by head user/org and branch (string, optional) - `owner`: Repository owner (string, required) - `page`: Page number for pagination (min 1) (number, optional) @@ -1229,6 +1232,7 @@ The following sets of tools are available: - **search_pull_requests** - Search pull requests - **Required OAuth Scopes**: `repo` + - `fields`: Subset of fields to return for each pull request result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data. (string[], optional) - `order`: Sort order (string, optional) - `owner`: Optional repository owner. If provided with repo, only pull requests for this repository are listed. (string, optional) - `page`: Page number for pagination (min 1) (number, optional) @@ -1313,6 +1317,7 @@ The following sets of tools are available: - **get_file_contents** - Get file or directory contents - **Required OAuth Scopes**: `repo` + - `fields`: Subset of fields to return for each entry when the path is a directory. If omitted, all fields are returned. Ignored when the path is a single file. Use this to reduce response size when listing directories and you only need specific fields, e.g. just 'name' and 'type'. (string[], optional) - `owner`: Repository owner (username or organization) (string, required) - `path`: Path to file/directory (string, optional) - `ref`: Accepts optional git refs such as `refs/tags/{tag}`, `refs/heads/{branch}` or `refs/pull/{pr_number}/head` (string, optional) @@ -1346,6 +1351,7 @@ The following sets of tools are available: - **list_commits** - List commits - **Required OAuth Scopes**: `repo` - `author`: Author username or email address to filter commits by (string, optional) + - `fields`: Subset of fields to return for each commit. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields, e.g. just 'sha' and 'html_url'. (string[], optional) - `owner`: Repository owner (string, required) - `page`: Page number for pagination (min 1) (number, optional) - `path`: Only commits containing this file path will be returned (string, optional) @@ -1357,6 +1363,7 @@ The following sets of tools are available: - **list_releases** - List releases - **Required OAuth Scopes**: `repo` + - `fields`: Subset of fields to return for each release. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-release data. (string[], optional) - `owner`: Repository owner (string, required) - `page`: Page number for pagination (min 1) (number, optional) - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) @@ -1387,6 +1394,7 @@ The following sets of tools are available: - **search_code** - Search code - **Required OAuth Scopes**: `repo` + - `fields`: Subset of fields to return for each code search result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'repository' and 'text_matches' in particular drops the largest per-result data. (string[], optional) - `order`: Sort order for results (string, optional) - `page`: Page number for pagination (min 1) (number, optional) - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) diff --git a/docs/feature-flags.md b/docs/feature-flags.md index c83e0c74be..32891af62e 100644 --- a/docs/feature-flags.md +++ b/docs/feature-flags.md @@ -338,94 +338,4 @@ runtime behavior (such as output formatting) won't appear here. - 'blocked_by' - the subject issue is blocked by the related issue. - 'blocking' - the subject issue blocks the related issue. (string, required) -### `fields_param` - -- **get_file_contents** - Get file or directory contents - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each entry when the path is a directory. If omitted, all fields are returned. Ignored when the path is a single file. Use this to reduce response size when listing directories and you only need specific fields, e.g. just 'name' and 'type'. (string[], optional) - - `owner`: Repository owner (username or organization) (string, required) - - `path`: Path to file/directory (string, optional) - - `ref`: Accepts optional git refs such as `refs/tags/{tag}`, `refs/heads/{branch}` or `refs/pull/{pr_number}/head` (string, optional) - - `repo`: Repository name (string, required) - - `sha`: Accepts optional commit SHA. If specified, it will be used instead of ref (string, optional) - -- **list_commits** - List commits - - **Required OAuth Scopes**: `repo` - - `author`: Author username or email address to filter commits by (string, optional) - - `fields`: Subset of fields to return for each commit. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields, e.g. just 'sha' and 'html_url'. (string[], optional) - - `owner`: Repository owner (string, required) - - `page`: Page number for pagination (min 1) (number, optional) - - `path`: Only commits containing this file path will be returned (string, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `repo`: Repository name (string, required) - - `sha`: Commit SHA, branch or tag name to list commits of. If not provided, uses the default branch of the repository. If a commit SHA is provided, will list commits up to that SHA. (string, optional) - - `since`: Only commits after this date will be returned (ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DD) (string, optional) - - `until`: Only commits before this date will be returned (ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DD) (string, optional) - -- **list_issues** - List issues - - **Required OAuth Scopes**: `repo` - - `after`: Cursor for pagination. Use the cursor from the previous response. (string, optional) - - `direction`: Order direction. If provided, the 'orderBy' also needs to be provided. (string, optional) - - `field_filters`: Filter by custom issue field values. Each entry takes a field_name and a value; the server looks up the field and coerces the value to its type (single-select option name, text, number, or YYYY-MM-DD date). (object[], optional) - - `fields`: Subset of fields to return for each issue. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' and 'field_values' in particular drops the largest per-result data. (string[], optional) - - `labels`: Filter by labels (string[], optional) - - `orderBy`: Order issues by field. If provided, the 'direction' also needs to be provided. (string, optional) - - `owner`: Repository owner (string, required) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `repo`: Repository name (string, required) - - `since`: Filter by date (ISO 8601 timestamp) (string, optional) - - `state`: Filter by state, by default both open and closed issues are returned when not provided (string, optional) - -- **list_pull_requests** - List pull requests - - **Required OAuth Scopes**: `repo` - - `base`: Filter by base branch (string, optional) - - `direction`: Sort direction (string, optional) - - `fields`: Subset of fields to return for each pull request. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-result data. (string[], optional) - - `head`: Filter by head user/org and branch (string, optional) - - `owner`: Repository owner (string, required) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `repo`: Repository name (string, required) - - `sort`: Sort by (string, optional) - - `state`: Filter by state (string, optional) - -- **list_releases** - List releases - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each release. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-release data. (string[], optional) - - `owner`: Repository owner (string, required) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `repo`: Repository name (string, required) - -- **search_code** - Search code - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each code search result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'repository' and 'text_matches' in particular drops the largest per-result data. (string[], optional) - - `order`: Sort order for results (string, optional) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `query`: Search query (GitHub code search REST). Implicit AND between terms; supports `OR`, `NOT`, and `"quoted phrase"` for exact match. Qualifiers: `repo:owner/repo`, `org:`, `user:`, `language:`, `path:dir` (prefix match), `filename:exact.ext`, `extension:`, `in:file`, `in:path`, `size:`, `is:archived`, `is:fork`. Max 256 chars. Examples: `WithContext language:go org:github`; `"package main" repo:o/r`; `func extension:go path:cmd repo:o/r`; `NOT TODO language:go repo:o/r`. (string, required) - - `sort`: Sort field ('indexed' only) (string, optional) - -- **search_issues** - Search issues - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each issue result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data. (string[], optional) - - `order`: Sort order (string, optional) - - `owner`: Optional repository owner. If provided with repo, only issues for this repository are listed. (string, optional) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `query`: Search query using GitHub issues search syntax (string, required) - - `repo`: Optional repository name. If provided with owner, only issues for this repository are listed. (string, optional) - - `sort`: Sort field by number of matches of categories, defaults to best match (string, optional) - -- **search_pull_requests** - Search pull requests - - **Required OAuth Scopes**: `repo` - - `fields`: Subset of fields to return for each pull request result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data. (string[], optional) - - `order`: Sort order (string, optional) - - `owner`: Optional repository owner. If provided with repo, only pull requests for this repository are listed. (string, optional) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `query`: Search query using GitHub pull request search syntax (string, required) - - `repo`: Optional repository name. If provided with owner, only pull requests for this repository are listed. (string, optional) - - `sort`: Sort field by number of matches of categories, defaults to best match (string, optional) - diff --git a/pkg/github/__toolsnaps__/get_file_contents.snap b/pkg/github/__toolsnaps__/get_file_contents.snap index ea317f6f14..dec933c94d 100644 --- a/pkg/github/__toolsnaps__/get_file_contents.snap +++ b/pkg/github/__toolsnaps__/get_file_contents.snap @@ -7,6 +7,24 @@ "description": "Get the contents of a file or directory from a GitHub repository", "inputSchema": { "properties": { + "fields": { + "description": "Subset of fields to return for each entry when the path is a directory. If omitted, all fields are returned. Ignored when the path is a single file. Use this to reduce response size when listing directories and you only need specific fields, e.g. just 'name' and 'type'.", + "items": { + "enum": [ + "type", + "name", + "path", + "size", + "sha", + "url", + "git_url", + "html_url", + "download_url" + ], + "type": "string" + }, + "type": "array" + }, "owner": { "description": "Repository owner (username or organization)", "type": "string" diff --git a/pkg/github/__toolsnaps__/get_file_contents_ff_fields_param.snap b/pkg/github/__toolsnaps__/get_file_contents_ff_fields_param.snap deleted file mode 100644 index dec933c94d..0000000000 --- a/pkg/github/__toolsnaps__/get_file_contents_ff_fields_param.snap +++ /dev/null @@ -1,57 +0,0 @@ -{ - "annotations": { - "idempotentHint": false, - "readOnlyHint": true, - "title": "Get file or directory contents" - }, - "description": "Get the contents of a file or directory from a GitHub repository", - "inputSchema": { - "properties": { - "fields": { - "description": "Subset of fields to return for each entry when the path is a directory. If omitted, all fields are returned. Ignored when the path is a single file. Use this to reduce response size when listing directories and you only need specific fields, e.g. just 'name' and 'type'.", - "items": { - "enum": [ - "type", - "name", - "path", - "size", - "sha", - "url", - "git_url", - "html_url", - "download_url" - ], - "type": "string" - }, - "type": "array" - }, - "owner": { - "description": "Repository owner (username or organization)", - "type": "string" - }, - "path": { - "default": "/", - "description": "Path to file/directory", - "type": "string" - }, - "ref": { - "description": "Accepts optional git refs such as `refs/tags/{tag}`, `refs/heads/{branch}` or `refs/pull/{pr_number}/head`", - "type": "string" - }, - "repo": { - "description": "Repository name", - "type": "string" - }, - "sha": { - "description": "Accepts optional commit SHA. If specified, it will be used instead of ref", - "type": "string" - } - }, - "required": [ - "owner", - "repo" - ], - "type": "object" - }, - "name": "get_file_contents" -} \ No newline at end of file diff --git a/pkg/github/__toolsnaps__/list_commits.snap b/pkg/github/__toolsnaps__/list_commits.snap index 00cce882f1..bc4ffd1753 100644 --- a/pkg/github/__toolsnaps__/list_commits.snap +++ b/pkg/github/__toolsnaps__/list_commits.snap @@ -11,6 +11,20 @@ "description": "Author username or email address to filter commits by", "type": "string" }, + "fields": { + "description": "Subset of fields to return for each commit. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields, e.g. just 'sha' and 'html_url'.", + "items": { + "enum": [ + "sha", + "html_url", + "commit", + "author", + "committer" + ], + "type": "string" + }, + "type": "array" + }, "owner": { "description": "Repository owner", "type": "string" diff --git a/pkg/github/__toolsnaps__/list_commits_ff_fields_param.snap b/pkg/github/__toolsnaps__/list_commits_ff_fields_param.snap deleted file mode 100644 index bc4ffd1753..0000000000 --- a/pkg/github/__toolsnaps__/list_commits_ff_fields_param.snap +++ /dev/null @@ -1,71 +0,0 @@ -{ - "annotations": { - "idempotentHint": false, - "readOnlyHint": true, - "title": "List commits" - }, - "description": "Get list of commits of a branch in a GitHub repository. Returns at least 30 results per page by default, but can return more if specified using the perPage parameter (up to 100).", - "inputSchema": { - "properties": { - "author": { - "description": "Author username or email address to filter commits by", - "type": "string" - }, - "fields": { - "description": "Subset of fields to return for each commit. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields, e.g. just 'sha' and 'html_url'.", - "items": { - "enum": [ - "sha", - "html_url", - "commit", - "author", - "committer" - ], - "type": "string" - }, - "type": "array" - }, - "owner": { - "description": "Repository owner", - "type": "string" - }, - "page": { - "description": "Page number for pagination (min 1)", - "minimum": 1, - "type": "number" - }, - "path": { - "description": "Only commits containing this file path will be returned", - "type": "string" - }, - "perPage": { - "description": "Results per page for pagination (min 1, max 100)", - "maximum": 100, - "minimum": 1, - "type": "number" - }, - "repo": { - "description": "Repository name", - "type": "string" - }, - "sha": { - "description": "Commit SHA, branch or tag name to list commits of. If not provided, uses the default branch of the repository. If a commit SHA is provided, will list commits up to that SHA.", - "type": "string" - }, - "since": { - "description": "Only commits after this date will be returned (ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DD)", - "type": "string" - }, - "until": { - "description": "Only commits before this date will be returned (ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DD)", - "type": "string" - } - }, - "required": [ - "owner", - "repo" - ], - "type": "object" - }, - "name": "list_commits" -} \ No newline at end of file diff --git a/pkg/github/__toolsnaps__/list_issues.snap b/pkg/github/__toolsnaps__/list_issues.snap index 5c68c01497..1055fe9947 100644 --- a/pkg/github/__toolsnaps__/list_issues.snap +++ b/pkg/github/__toolsnaps__/list_issues.snap @@ -40,6 +40,25 @@ }, "type": "array" }, + "fields": { + "description": "Subset of fields to return for each issue. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' and 'field_values' in particular drops the largest per-result data.", + "items": { + "enum": [ + "number", + "title", + "body", + "state", + "user", + "labels", + "comments", + "created_at", + "updated_at", + "field_values" + ], + "type": "string" + }, + "type": "array" + }, "labels": { "description": "Filter by labels", "items": { diff --git a/pkg/github/__toolsnaps__/list_issues_ff_fields_param.snap b/pkg/github/__toolsnaps__/list_issues_ff_fields_param.snap deleted file mode 100644 index 1055fe9947..0000000000 --- a/pkg/github/__toolsnaps__/list_issues_ff_fields_param.snap +++ /dev/null @@ -1,112 +0,0 @@ -{ - "annotations": { - "idempotentHint": false, - "readOnlyHint": true, - "title": "List issues" - }, - "description": "List issues in a GitHub repository. For pagination, use the 'endCursor' from the previous response's 'pageInfo' in the 'after' parameter.", - "inputSchema": { - "properties": { - "after": { - "description": "Cursor for pagination. Use the cursor from the previous response.", - "type": "string" - }, - "direction": { - "description": "Order direction. If provided, the 'orderBy' also needs to be provided.", - "enum": [ - "ASC", - "DESC" - ], - "type": "string" - }, - "field_filters": { - "description": "Filter by custom issue field values. Each entry takes a field_name and a value; the server looks up the field and coerces the value to its type (single-select option name, text, number, or YYYY-MM-DD date).", - "items": { - "properties": { - "field_name": { - "description": "Name of the custom field (e.g. \"Priority\"). Case-insensitive.", - "type": "string" - }, - "value": { - "description": "Value to filter on. For single-select fields, the option name (e.g. \"P1\"). For dates, YYYY-MM-DD. For numbers, the numeric value as a string. For text, the text value.", - "type": "string" - } - }, - "required": [ - "field_name", - "value" - ], - "type": "object" - }, - "type": "array" - }, - "fields": { - "description": "Subset of fields to return for each issue. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' and 'field_values' in particular drops the largest per-result data.", - "items": { - "enum": [ - "number", - "title", - "body", - "state", - "user", - "labels", - "comments", - "created_at", - "updated_at", - "field_values" - ], - "type": "string" - }, - "type": "array" - }, - "labels": { - "description": "Filter by labels", - "items": { - "type": "string" - }, - "type": "array" - }, - "orderBy": { - "description": "Order issues by field. If provided, the 'direction' also needs to be provided.", - "enum": [ - "CREATED_AT", - "UPDATED_AT", - "COMMENTS" - ], - "type": "string" - }, - "owner": { - "description": "Repository owner", - "type": "string" - }, - "perPage": { - "description": "Results per page for pagination (min 1, max 100)", - "maximum": 100, - "minimum": 1, - "type": "number" - }, - "repo": { - "description": "Repository name", - "type": "string" - }, - "since": { - "description": "Filter by date (ISO 8601 timestamp)", - "type": "string" - }, - "state": { - "description": "Filter by state, by default both open and closed issues are returned when not provided", - "enum": [ - "OPEN", - "CLOSED" - ], - "type": "string" - } - }, - "required": [ - "owner", - "repo" - ], - "type": "object" - }, - "name": "list_issues" -} \ No newline at end of file diff --git a/pkg/github/__toolsnaps__/list_pull_requests.snap b/pkg/github/__toolsnaps__/list_pull_requests.snap index a94b6eaee1..d37986d529 100644 --- a/pkg/github/__toolsnaps__/list_pull_requests.snap +++ b/pkg/github/__toolsnaps__/list_pull_requests.snap @@ -19,6 +19,40 @@ ], "type": "string" }, + "fields": { + "description": "Subset of fields to return for each pull request. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-result data.", + "items": { + "enum": [ + "number", + "title", + "body", + "state", + "draft", + "merged", + "mergeable_state", + "html_url", + "user", + "labels", + "assignees", + "requested_reviewers", + "merged_by", + "head", + "base", + "additions", + "deletions", + "changed_files", + "commits", + "comments", + "created_at", + "updated_at", + "closed_at", + "merged_at", + "milestone" + ], + "type": "string" + }, + "type": "array" + }, "head": { "description": "Filter by head user/org and branch", "type": "string" diff --git a/pkg/github/__toolsnaps__/list_pull_requests_ff_fields_param.snap b/pkg/github/__toolsnaps__/list_pull_requests_ff_fields_param.snap deleted file mode 100644 index d37986d529..0000000000 --- a/pkg/github/__toolsnaps__/list_pull_requests_ff_fields_param.snap +++ /dev/null @@ -1,106 +0,0 @@ -{ - "annotations": { - "idempotentHint": false, - "readOnlyHint": true, - "title": "List pull requests" - }, - "description": "List pull requests in a GitHub repository. If the user specifies an author, then DO NOT use this tool and use the search_pull_requests tool instead.", - "inputSchema": { - "properties": { - "base": { - "description": "Filter by base branch", - "type": "string" - }, - "direction": { - "description": "Sort direction", - "enum": [ - "asc", - "desc" - ], - "type": "string" - }, - "fields": { - "description": "Subset of fields to return for each pull request. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-result data.", - "items": { - "enum": [ - "number", - "title", - "body", - "state", - "draft", - "merged", - "mergeable_state", - "html_url", - "user", - "labels", - "assignees", - "requested_reviewers", - "merged_by", - "head", - "base", - "additions", - "deletions", - "changed_files", - "commits", - "comments", - "created_at", - "updated_at", - "closed_at", - "merged_at", - "milestone" - ], - "type": "string" - }, - "type": "array" - }, - "head": { - "description": "Filter by head user/org and branch", - "type": "string" - }, - "owner": { - "description": "Repository owner", - "type": "string" - }, - "page": { - "description": "Page number for pagination (min 1)", - "minimum": 1, - "type": "number" - }, - "perPage": { - "description": "Results per page for pagination (min 1, max 100)", - "maximum": 100, - "minimum": 1, - "type": "number" - }, - "repo": { - "description": "Repository name", - "type": "string" - }, - "sort": { - "description": "Sort by", - "enum": [ - "created", - "updated", - "popularity", - "long-running" - ], - "type": "string" - }, - "state": { - "description": "Filter by state", - "enum": [ - "open", - "closed", - "all" - ], - "type": "string" - } - }, - "required": [ - "owner", - "repo" - ], - "type": "object" - }, - "name": "list_pull_requests" -} \ No newline at end of file diff --git a/pkg/github/__toolsnaps__/list_releases.snap b/pkg/github/__toolsnaps__/list_releases.snap index d905f32087..4eeef279e9 100644 --- a/pkg/github/__toolsnaps__/list_releases.snap +++ b/pkg/github/__toolsnaps__/list_releases.snap @@ -7,6 +7,24 @@ "description": "List releases in a GitHub repository", "inputSchema": { "properties": { + "fields": { + "description": "Subset of fields to return for each release. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-release data.", + "items": { + "enum": [ + "id", + "tag_name", + "name", + "body", + "html_url", + "published_at", + "prerelease", + "draft", + "author" + ], + "type": "string" + }, + "type": "array" + }, "owner": { "description": "Repository owner", "type": "string" diff --git a/pkg/github/__toolsnaps__/list_releases_ff_fields_param.snap b/pkg/github/__toolsnaps__/list_releases_ff_fields_param.snap deleted file mode 100644 index 4eeef279e9..0000000000 --- a/pkg/github/__toolsnaps__/list_releases_ff_fields_param.snap +++ /dev/null @@ -1,55 +0,0 @@ -{ - "annotations": { - "idempotentHint": false, - "readOnlyHint": true, - "title": "List releases" - }, - "description": "List releases in a GitHub repository", - "inputSchema": { - "properties": { - "fields": { - "description": "Subset of fields to return for each release. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-release data.", - "items": { - "enum": [ - "id", - "tag_name", - "name", - "body", - "html_url", - "published_at", - "prerelease", - "draft", - "author" - ], - "type": "string" - }, - "type": "array" - }, - "owner": { - "description": "Repository owner", - "type": "string" - }, - "page": { - "description": "Page number for pagination (min 1)", - "minimum": 1, - "type": "number" - }, - "perPage": { - "description": "Results per page for pagination (min 1, max 100)", - "maximum": 100, - "minimum": 1, - "type": "number" - }, - "repo": { - "description": "Repository name", - "type": "string" - } - }, - "required": [ - "owner", - "repo" - ], - "type": "object" - }, - "name": "list_releases" -} \ No newline at end of file diff --git a/pkg/github/__toolsnaps__/search_code.snap b/pkg/github/__toolsnaps__/search_code.snap index 313c2f4c5f..00d4686712 100644 --- a/pkg/github/__toolsnaps__/search_code.snap +++ b/pkg/github/__toolsnaps__/search_code.snap @@ -7,6 +7,20 @@ "description": "Fast and precise code search across ALL GitHub repositories using GitHub's native search engine. Best for finding exact symbols, functions, classes, or specific code patterns.", "inputSchema": { "properties": { + "fields": { + "description": "Subset of fields to return for each code search result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'repository' and 'text_matches' in particular drops the largest per-result data.", + "items": { + "enum": [ + "name", + "path", + "sha", + "repository", + "text_matches" + ], + "type": "string" + }, + "type": "array" + }, "order": { "description": "Sort order for results", "enum": [ diff --git a/pkg/github/__toolsnaps__/search_code_ff_fields_param.snap b/pkg/github/__toolsnaps__/search_code_ff_fields_param.snap deleted file mode 100644 index 00d4686712..0000000000 --- a/pkg/github/__toolsnaps__/search_code_ff_fields_param.snap +++ /dev/null @@ -1,58 +0,0 @@ -{ - "annotations": { - "idempotentHint": false, - "readOnlyHint": true, - "title": "Search code" - }, - "description": "Fast and precise code search across ALL GitHub repositories using GitHub's native search engine. Best for finding exact symbols, functions, classes, or specific code patterns.", - "inputSchema": { - "properties": { - "fields": { - "description": "Subset of fields to return for each code search result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'repository' and 'text_matches' in particular drops the largest per-result data.", - "items": { - "enum": [ - "name", - "path", - "sha", - "repository", - "text_matches" - ], - "type": "string" - }, - "type": "array" - }, - "order": { - "description": "Sort order for results", - "enum": [ - "asc", - "desc" - ], - "type": "string" - }, - "page": { - "description": "Page number for pagination (min 1)", - "minimum": 1, - "type": "number" - }, - "perPage": { - "description": "Results per page for pagination (min 1, max 100)", - "maximum": 100, - "minimum": 1, - "type": "number" - }, - "query": { - "description": "Search query (GitHub code search REST). Implicit AND between terms; supports `OR`, `NOT`, and `\"quoted phrase\"` for exact match. Qualifiers: `repo:owner/repo`, `org:`, `user:`, `language:`, `path:dir` (prefix match), `filename:exact.ext`, `extension:`, `in:file`, `in:path`, `size:`, `is:archived`, `is:fork`. Max 256 chars. Examples: `WithContext language:go org:github`; `\"package main\" repo:o/r`; `func extension:go path:cmd repo:o/r`; `NOT TODO language:go repo:o/r`.", - "type": "string" - }, - "sort": { - "description": "Sort field ('indexed' only)", - "type": "string" - } - }, - "required": [ - "query" - ], - "type": "object" - }, - "name": "search_code" -} \ No newline at end of file diff --git a/pkg/github/__toolsnaps__/search_issues.snap b/pkg/github/__toolsnaps__/search_issues.snap index a2ec55b911..f705f14725 100644 --- a/pkg/github/__toolsnaps__/search_issues.snap +++ b/pkg/github/__toolsnaps__/search_issues.snap @@ -7,6 +7,39 @@ "description": "Search for issues in GitHub repositories using issues search syntax already scoped to is:issue", "inputSchema": { "properties": { + "fields": { + "description": "Subset of fields to return for each issue result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data.", + "items": { + "enum": [ + "number", + "title", + "body", + "state", + "state_reason", + "draft", + "locked", + "html_url", + "user", + "author_association", + "labels", + "assignee", + "assignees", + "milestone", + "comments", + "reactions", + "created_at", + "updated_at", + "closed_at", + "closed_by", + "type", + "repository_url", + "pull_request", + "field_values" + ], + "type": "string" + }, + "type": "array" + }, "order": { "description": "Sort order", "enum": [ diff --git a/pkg/github/__toolsnaps__/search_issues_ff_fields_param.snap b/pkg/github/__toolsnaps__/search_issues_ff_fields_param.snap deleted file mode 100644 index f705f14725..0000000000 --- a/pkg/github/__toolsnaps__/search_issues_ff_fields_param.snap +++ /dev/null @@ -1,98 +0,0 @@ -{ - "annotations": { - "idempotentHint": false, - "readOnlyHint": true, - "title": "Search issues" - }, - "description": "Search for issues in GitHub repositories using issues search syntax already scoped to is:issue", - "inputSchema": { - "properties": { - "fields": { - "description": "Subset of fields to return for each issue result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data.", - "items": { - "enum": [ - "number", - "title", - "body", - "state", - "state_reason", - "draft", - "locked", - "html_url", - "user", - "author_association", - "labels", - "assignee", - "assignees", - "milestone", - "comments", - "reactions", - "created_at", - "updated_at", - "closed_at", - "closed_by", - "type", - "repository_url", - "pull_request", - "field_values" - ], - "type": "string" - }, - "type": "array" - }, - "order": { - "description": "Sort order", - "enum": [ - "asc", - "desc" - ], - "type": "string" - }, - "owner": { - "description": "Optional repository owner. If provided with repo, only issues for this repository are listed.", - "type": "string" - }, - "page": { - "description": "Page number for pagination (min 1)", - "minimum": 1, - "type": "number" - }, - "perPage": { - "description": "Results per page for pagination (min 1, max 100)", - "maximum": 100, - "minimum": 1, - "type": "number" - }, - "query": { - "description": "Search query using GitHub issues search syntax", - "type": "string" - }, - "repo": { - "description": "Optional repository name. If provided with owner, only issues for this repository are listed.", - "type": "string" - }, - "sort": { - "description": "Sort field by number of matches of categories, defaults to best match", - "enum": [ - "comments", - "reactions", - "reactions-+1", - "reactions--1", - "reactions-smile", - "reactions-thinking_face", - "reactions-heart", - "reactions-tada", - "interactions", - "created", - "updated" - ], - "type": "string" - } - }, - "required": [ - "query" - ], - "type": "object" - }, - "name": "search_issues" -} \ No newline at end of file diff --git a/pkg/github/__toolsnaps__/search_pull_requests.snap b/pkg/github/__toolsnaps__/search_pull_requests.snap index 2e33af03b3..847168b471 100644 --- a/pkg/github/__toolsnaps__/search_pull_requests.snap +++ b/pkg/github/__toolsnaps__/search_pull_requests.snap @@ -7,6 +7,37 @@ "description": "Search for pull requests in GitHub repositories using issues search syntax already scoped to is:pr", "inputSchema": { "properties": { + "fields": { + "description": "Subset of fields to return for each pull request result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data.", + "items": { + "enum": [ + "number", + "title", + "body", + "state", + "state_reason", + "draft", + "locked", + "html_url", + "user", + "author_association", + "labels", + "assignee", + "assignees", + "milestone", + "comments", + "reactions", + "created_at", + "updated_at", + "closed_at", + "closed_by", + "pull_request", + "repository_url" + ], + "type": "string" + }, + "type": "array" + }, "order": { "description": "Sort order", "enum": [ diff --git a/pkg/github/__toolsnaps__/search_pull_requests_ff_fields_param.snap b/pkg/github/__toolsnaps__/search_pull_requests_ff_fields_param.snap deleted file mode 100644 index 847168b471..0000000000 --- a/pkg/github/__toolsnaps__/search_pull_requests_ff_fields_param.snap +++ /dev/null @@ -1,96 +0,0 @@ -{ - "annotations": { - "idempotentHint": false, - "readOnlyHint": true, - "title": "Search pull requests" - }, - "description": "Search for pull requests in GitHub repositories using issues search syntax already scoped to is:pr", - "inputSchema": { - "properties": { - "fields": { - "description": "Subset of fields to return for each pull request result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data.", - "items": { - "enum": [ - "number", - "title", - "body", - "state", - "state_reason", - "draft", - "locked", - "html_url", - "user", - "author_association", - "labels", - "assignee", - "assignees", - "milestone", - "comments", - "reactions", - "created_at", - "updated_at", - "closed_at", - "closed_by", - "pull_request", - "repository_url" - ], - "type": "string" - }, - "type": "array" - }, - "order": { - "description": "Sort order", - "enum": [ - "asc", - "desc" - ], - "type": "string" - }, - "owner": { - "description": "Optional repository owner. If provided with repo, only pull requests for this repository are listed.", - "type": "string" - }, - "page": { - "description": "Page number for pagination (min 1)", - "minimum": 1, - "type": "number" - }, - "perPage": { - "description": "Results per page for pagination (min 1, max 100)", - "maximum": 100, - "minimum": 1, - "type": "number" - }, - "query": { - "description": "Search query using GitHub pull request search syntax", - "type": "string" - }, - "repo": { - "description": "Optional repository name. If provided with owner, only pull requests for this repository are listed.", - "type": "string" - }, - "sort": { - "description": "Sort field by number of matches of categories, defaults to best match", - "enum": [ - "comments", - "reactions", - "reactions-+1", - "reactions--1", - "reactions-smile", - "reactions-thinking_face", - "reactions-heart", - "reactions-tada", - "interactions", - "created", - "updated" - ], - "type": "string" - } - }, - "required": [ - "query" - ], - "type": "object" - }, - "name": "search_pull_requests" -} \ No newline at end of file diff --git a/pkg/github/feature_flags.go b/pkg/github/feature_flags.go index 5c427eb601..abf5de1e95 100644 --- a/pkg/github/feature_flags.go +++ b/pkg/github/feature_flags.go @@ -27,14 +27,6 @@ const FeatureFlagFileBlame = "file_blame" // unless explicitly opted in. const FeatureFlagIssueDependencies = "issue_dependencies" -// FeatureFlagFieldsParam is the feature flag name for the optional `fields` -// parameter on selected read tools (for example search_code and -// get_file_contents). When enabled, those tools advertise `fields` and filter -// each result to the requested subset, reducing response size. It is gated so -// the feature can be rolled out gradually and disabled as a kill switch without -// a redeploy. -const FeatureFlagFieldsParam = "fields_param" - // AllowedFeatureFlags is the allowlist of feature flags that can be enabled // by users via --features CLI flag or X-MCP-Features HTTP header. // Only flags in this list are accepted; unknown flags are silently ignored. @@ -48,7 +40,6 @@ var AllowedFeatureFlags = []string{ FeatureFlagPullRequestsGranular, FeatureFlagFileBlame, FeatureFlagIssueDependencies, - FeatureFlagFieldsParam, } // InsidersFeatureFlags is the list of feature flags that insiders mode enables. diff --git a/pkg/github/feature_flags_test.go b/pkg/github/feature_flags_test.go index fb648e744f..0b73ddeb3b 100644 --- a/pkg/github/feature_flags_test.go +++ b/pkg/github/feature_flags_test.go @@ -160,28 +160,12 @@ func TestResolveFeatureFlags(t *testing.T) { enabledFeatures: []string{MCPAppsDisableFormDeferralFeatureFlag}, expectedFlags: []string{MCPAppsDisableFormDeferralFeatureFlag}, }, - { - name: "fields param is not enabled by default", - enabledFeatures: nil, - unexpectedFlags: []string{FeatureFlagFieldsParam}, - }, - { - name: "fields param can be directly enabled", - enabledFeatures: []string{FeatureFlagFieldsParam}, - expectedFlags: []string{FeatureFlagFieldsParam}, - }, { name: "insiders mode enables insiders flags", enabledFeatures: nil, insidersMode: true, expectedFlags: InsidersFeatureFlags, }, - { - name: "insiders mode does not enable fields param", - enabledFeatures: nil, - insidersMode: true, - unexpectedFlags: []string{FeatureFlagFieldsParam}, - }, { name: "insiders mode does not auto-enable ifc labels", enabledFeatures: nil, diff --git a/pkg/github/fields_filtering_test.go b/pkg/github/fields_filtering_test.go index f421fe1ebb..c9dc5de0ee 100644 --- a/pkg/github/fields_filtering_test.go +++ b/pkg/github/fields_filtering_test.go @@ -7,11 +7,9 @@ import ( "testing" "github.com/github/github-mcp-server/internal/githubv4mock" - "github.com/github/github-mcp-server/internal/toolsnaps" "github.com/github/github-mcp-server/pkg/inventory" "github.com/github/github-mcp-server/pkg/translations" "github.com/google/go-github/v89/github" - "github.com/google/jsonschema-go/jsonschema" "github.com/shurcooL/githubv4" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -19,18 +17,6 @@ import ( // --- list_commits --------------------------------------------------------- -func Test_LegacyListCommits_Definition(t *testing.T) { - serverTool := LegacyListCommits(translations.NullTranslationHelper) - tool := serverTool.Tool - require.NoError(t, toolsnaps.Test(tool.Name, tool)) - require.Equal(t, []string{FeatureFlagFieldsParam}, serverTool.FeatureFlagDisable) - - assert.Equal(t, "list_commits", tool.Name) - schema, ok := tool.InputSchema.(*jsonschema.Schema) - require.True(t, ok, "InputSchema should be *jsonschema.Schema") - assert.NotContains(t, schema.Properties, "fields") -} - func mockListCommits() []*github.RepositoryCommit { return []*github.RepositoryCommit{ { @@ -88,18 +74,6 @@ func Test_ListCommits_FieldsTelemetry(t *testing.T) { // --- list_releases -------------------------------------------------------- -func Test_LegacyListReleases_Definition(t *testing.T) { - serverTool := LegacyListReleases(translations.NullTranslationHelper) - tool := serverTool.Tool - require.NoError(t, toolsnaps.Test(tool.Name, tool)) - require.Equal(t, []string{FeatureFlagFieldsParam}, serverTool.FeatureFlagDisable) - - assert.Equal(t, "list_releases", tool.Name) - schema, ok := tool.InputSchema.(*jsonschema.Schema) - require.True(t, ok, "InputSchema should be *jsonschema.Schema") - assert.NotContains(t, schema.Properties, "fields") -} - func mockListReleases() []*github.RepositoryRelease { return []*github.RepositoryRelease{ { @@ -153,18 +127,6 @@ func Test_ListReleases_FieldsTelemetry(t *testing.T) { // --- list_pull_requests --------------------------------------------------- -func Test_LegacyListPullRequests_Definition(t *testing.T) { - serverTool := LegacyListPullRequests(translations.NullTranslationHelper) - tool := serverTool.Tool - require.NoError(t, toolsnaps.Test(tool.Name, tool)) - require.Equal(t, []string{FeatureFlagFieldsParam}, serverTool.FeatureFlagDisable) - - assert.Equal(t, "list_pull_requests", tool.Name) - schema, ok := tool.InputSchema.(*jsonschema.Schema) - require.True(t, ok, "InputSchema should be *jsonschema.Schema") - assert.NotContains(t, schema.Properties, "fields") -} - func mockListPullRequests() []*github.PullRequest { return []*github.PullRequest{ { @@ -219,18 +181,6 @@ func Test_ListPullRequests_FieldsTelemetry(t *testing.T) { // --- search_pull_requests ------------------------------------------------- -func Test_LegacySearchPullRequests_Definition(t *testing.T) { - serverTool := LegacySearchPullRequests(translations.NullTranslationHelper) - tool := serverTool.Tool - require.NoError(t, toolsnaps.Test(tool.Name, tool)) - require.Equal(t, []string{FeatureFlagFieldsParam}, serverTool.FeatureFlagDisable) - - assert.Equal(t, "search_pull_requests", tool.Name) - schema, ok := tool.InputSchema.(*jsonschema.Schema) - require.True(t, ok, "InputSchema should be *jsonschema.Schema") - assert.NotContains(t, schema.Properties, "fields") -} - // mockIssueSearchResult returns a single-item issues search result. It is used // for both search_pull_requests and search_issues since both hit the REST // issues search endpoint. Issues intentionally omit NodeID so search_issues @@ -285,18 +235,6 @@ func Test_SearchPullRequests_FieldsTelemetry(t *testing.T) { // --- search_issues -------------------------------------------------------- -func Test_LegacySearchIssues_Definition(t *testing.T) { - serverTool := LegacySearchIssues(translations.NullTranslationHelper) - tool := serverTool.Tool - require.NoError(t, toolsnaps.Test(tool.Name, tool)) - require.Equal(t, []string{FeatureFlagFieldsParam}, serverTool.FeatureFlagDisable) - - assert.Equal(t, "search_issues", tool.Name) - schema, ok := tool.InputSchema.(*jsonschema.Schema) - require.True(t, ok, "InputSchema should be *jsonschema.Schema") - assert.NotContains(t, schema.Properties, "fields") -} - func Test_SearchIssues_FieldFiltering(t *testing.T) { serverTool := SearchIssues(translations.NullTranslationHelper) client := mustNewGHClient(t, MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ @@ -330,18 +268,6 @@ func Test_SearchIssues_FieldsTelemetry(t *testing.T) { // --- list_issues (GraphQL) ------------------------------------------------ -func Test_LegacyListIssues_Definition(t *testing.T) { - serverTool := LegacyListIssues(translations.NullTranslationHelper) - tool := serverTool.Tool - require.NoError(t, toolsnaps.Test(tool.Name, tool)) - require.Equal(t, []string{FeatureFlagFieldsParam}, serverTool.FeatureFlagDisable) - - assert.Equal(t, "list_issues", tool.Name) - schema, ok := tool.InputSchema.(*jsonschema.Schema) - require.True(t, ok, "InputSchema should be *jsonschema.Schema") - assert.NotContains(t, schema.Properties, "fields") -} - // listIssuesFieldsQuery and listIssuesFieldsVars mirror the exact GraphQL query // and variables list_issues issues for owner/repo with default parameters (no // labels, no since). They must stay in sync with the query built in diff --git a/pkg/github/fields_param_gating_test.go b/pkg/github/fields_param_gating_test.go deleted file mode 100644 index 1e61d4eb81..0000000000 --- a/pkg/github/fields_param_gating_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package github - -import ( - "context" - "testing" - - "github.com/github/github-mcp-server/pkg/translations" - "github.com/google/jsonschema-go/jsonschema" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// Test_FieldsParamVariants_MutuallyExclusive guards the dual-variant -// registration for the fields_param feature flag. The flag-enabled tools and -// their Legacy* counterparts share a tool name, so exactly one of each pair must -// survive inventory filtering for any flag state. If both ever leaked, a client -// could be offered two tools with the same name. This asserts that each gated -// tool is present exactly once, advertising the `fields` parameter only when -// fields_param is enabled. -func Test_FieldsParamVariants_MutuallyExclusive(t *testing.T) { - gatedTools := []string{ - "search_code", - "get_file_contents", - "list_issues", - "list_releases", - "list_pull_requests", - "search_issues", - "search_pull_requests", - "list_commits", - } - - for _, tc := range []struct { - name string - flagEnabled bool - expectFields bool - featureChecks func(context.Context, string) (bool, error) - }{ - { - name: "flag off registers the legacy variant without fields", - flagEnabled: false, - expectFields: false, - featureChecks: featureCheckerFor(), // fields_param disabled - }, - { - name: "flag on registers the fields variant with fields", - flagEnabled: true, - expectFields: true, - featureChecks: featureCheckerFor(FeatureFlagFieldsParam), - }, - } { - t.Run(tc.name, func(t *testing.T) { - inv, err := NewInventory(translations.NullTranslationHelper). - WithToolsets([]string{"all"}). - WithFeatureChecker(tc.featureChecks). - Build() - require.NoError(t, err) - - available := inv.AvailableTools(context.Background()) - - counts := make(map[string]int, len(available)) - for _, tool := range available { - counts[tool.Tool.Name]++ - } - - // Each gated tool must be present exactly once (never both variants) - // and advertise `fields` only when the flag is enabled. - for _, name := range gatedTools { - require.Equalf(t, 1, counts[name], "expected exactly one %q for flagEnabled=%v; dual variants must be mutually exclusive", name, tc.flagEnabled) - - tool := requireToolByName(t, available, name) - schema, ok := tool.Tool.InputSchema.(*jsonschema.Schema) - require.Truef(t, ok, "%q InputSchema should be *jsonschema.Schema", name) - - if tc.expectFields { - assert.Containsf(t, schema.Properties, "fields", "%q should advertise fields when flag is on", name) - assert.Equalf(t, FeatureFlagFieldsParam, tool.FeatureFlagEnable, "%q should be the flag-enabled variant", name) - } else { - assert.NotContainsf(t, schema.Properties, "fields", "%q must not advertise fields when flag is off", name) - assert.Containsf(t, tool.FeatureFlagDisable, FeatureFlagFieldsParam, "%q should be the legacy (flag-disabled) variant", name) - } - } - }) - } -} diff --git a/pkg/github/issues.go b/pkg/github/issues.go index 0f12804a59..c224f605a7 100644 --- a/pkg/github/issues.go +++ b/pkg/github/issues.go @@ -1595,34 +1595,8 @@ func ReprioritizeSubIssue(ctx context.Context, client *github.Client, owner stri return utils.NewToolResultText(string(r)), nil } -// SearchIssues creates a tool to search for issues. It is the -// FeatureFlagFieldsParam-enabled variant: it advertises the optional `fields` -// parameter and filters each result to the requested subset. Both this and -// LegacySearchIssues register under the tool name "search_issues"; exactly one is -// active for any given request thanks to mutually exclusive FeatureFlagEnable / -// FeatureFlagDisable annotations. +// SearchIssues creates a tool to search for issues. func SearchIssues(t translations.TranslationHelperFunc) inventory.ServerTool { - st := searchIssuesTool(t, true) - st.FeatureFlagEnable = FeatureFlagFieldsParam - return st -} - -// LegacySearchIssues is the FeatureFlagFieldsParam-disabled variant of -// search_issues. It exposes the original schema (no `fields` parameter) and never -// filters results, so it acts as the kill switch when the flag is off. It owns -// the canonical search_issues.snap; the flag-enabled variant owns -// search_issues_ff_.snap. Delete this function when the flag is removed. -func LegacySearchIssues(t translations.TranslationHelperFunc) inventory.ServerTool { - st := searchIssuesTool(t, false) - st.FeatureFlagDisable = []string{FeatureFlagFieldsParam} - return st -} - -// searchIssuesTool builds the search_issues tool. When includeFields is true the -// tool advertises the optional `fields` parameter, filters each result to the -// requested subset, and emits fields telemetry. When false it is the original -// tool with no fields parameter and no filtering. -func searchIssuesTool(t translations.TranslationHelperFunc, includeFields bool) inventory.ServerTool { schema := &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ @@ -1663,12 +1637,10 @@ func searchIssuesTool(t translations.TranslationHelperFunc, includeFields bool) }, Required: []string{"query"}, } - if includeFields { - schema.Properties["fields"] = fieldsSchemaProperty( - "Subset of fields to return for each issue result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data.", - searchIssuesItemFieldEnum, - ) - } + schema.Properties["fields"] = fieldsSchemaProperty( + "Subset of fields to return for each issue result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data.", + searchIssuesItemFieldEnum, + ) WithPagination(schema) return NewTool( @@ -1685,13 +1657,11 @@ func searchIssuesTool(t translations.TranslationHelperFunc, includeFields bool) []scopes.Scope{scopes.Repo}, func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { options := []searchOption{ifcSearchPostProcessOption(ctx, deps)} - if includeFields { - fields, err := OptionalStringArrayParam(args, "fields") - if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil - } - options = append(options, withFieldsFiltering(deps, "search_issues", fields)) + fields, err := OptionalStringArrayParam(args, "fields") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil } + options = append(options, withFieldsFiltering(deps, "search_issues", fields)) result, err := searchIssuesHandler(ctx, deps, args, options...) return result, nil, err }) @@ -2652,34 +2622,8 @@ func UpdateIssue(ctx context.Context, client *github.Client, gqlClient *githubv4 return utils.NewToolResultText(string(r)), nil } -// ListIssues creates a tool to list issues in a GitHub repository. It is the -// FeatureFlagFieldsParam-enabled variant: it advertises the optional `fields` -// parameter and filters each issue to the requested subset. Both this and -// LegacyListIssues register under the tool name "list_issues"; exactly one is -// active for any given request thanks to mutually exclusive FeatureFlagEnable / -// FeatureFlagDisable annotations. +// ListIssues creates a tool to list issues in a GitHub repository. func ListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { - st := listIssuesTool(t, true) - st.FeatureFlagEnable = FeatureFlagFieldsParam - return st -} - -// LegacyListIssues is the FeatureFlagFieldsParam-disabled variant of list_issues. -// It exposes the original schema (no `fields` parameter) and never filters -// results, so it acts as the kill switch when the flag is off. It owns the -// canonical list_issues.snap; the flag-enabled variant owns -// list_issues_ff_.snap. Delete this function when the flag is removed. -func LegacyListIssues(t translations.TranslationHelperFunc) inventory.ServerTool { - st := listIssuesTool(t, false) - st.FeatureFlagDisable = []string{FeatureFlagFieldsParam} - return st -} - -// listIssuesTool builds the list_issues tool. When includeFields is true the -// tool advertises the optional `fields` parameter, filters each issue to the -// requested subset, and emits fields telemetry. When false it is the original -// tool with no fields parameter and no filtering. -func listIssuesTool(t translations.TranslationHelperFunc, includeFields bool) inventory.ServerTool { schema := &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ @@ -2738,12 +2682,10 @@ func listIssuesTool(t translations.TranslationHelperFunc, includeFields bool) in }, Required: []string{"owner", "repo"}, } - if includeFields { - schema.Properties["fields"] = fieldsSchemaProperty( - "Subset of fields to return for each issue. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' and 'field_values' in particular drops the largest per-result data.", - listIssuesItemFieldEnum, - ) - } + schema.Properties["fields"] = fieldsSchemaProperty( + "Subset of fields to return for each issue. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' and 'field_values' in particular drops the largest per-result data.", + listIssuesItemFieldEnum, + ) WithCursorPagination(schema) st := NewTool( @@ -2768,12 +2710,9 @@ func listIssuesTool(t translations.TranslationHelperFunc, includeFields bool) in return utils.NewToolResultError(err.Error()), nil, nil } - var fields []string - if includeFields { - fields, err = OptionalStringArrayParam(args, "fields") - if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil - } + fields, err := OptionalStringArrayParam(args, "fields") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil } // Set optional parameters if provided @@ -2947,7 +2886,7 @@ func listIssuesTool(t translations.TranslationHelperFunc, includeFields bool) in filtered := false var payload any = resp - if includeFields && len(fields) > 0 { + if len(fields) > 0 { filteredIssues, err := filterEachField(resp.Issues, fields) if err != nil { return utils.NewToolResultErrorFromErr("failed to filter issues", err), nil, nil @@ -2965,9 +2904,7 @@ func listIssuesTool(t translations.TranslationHelperFunc, includeFields bool) in return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil } - if includeFields { - recordFieldsUsageFor(ctx, deps, "list_issues", resp, filtered, len(r)) - } + recordFieldsUsageFor(ctx, deps, "list_issues", resp, filtered, len(r)) result := utils.NewToolResultText(string(r)) result = attachStaticIFCLabel(ctx, deps, result, ifc.LabelListIssues(isPrivate)) diff --git a/pkg/github/issues_test.go b/pkg/github/issues_test.go index c3ea692464..2fceda8a58 100644 --- a/pkg/github/issues_test.go +++ b/pkg/github/issues_test.go @@ -812,11 +812,7 @@ func Test_SearchIssues(t *testing.T) { // Verify tool definition once serverTool := SearchIssues(translations.NullTranslationHelper) tool := serverTool.Tool - // SearchIssues is the FeatureFlagFieldsParam-enabled variant; it owns the - // _ff_ snapshot. The canonical search_issues.snap is owned by - // LegacySearchIssues (see Test_LegacySearchIssues_Definition). - require.NoError(t, toolsnaps.Test(tool.Name+"_ff_"+FeatureFlagFieldsParam, tool)) - require.Equal(t, FeatureFlagFieldsParam, serverTool.FeatureFlagEnable) + require.NoError(t, toolsnaps.Test(tool.Name, tool)) assert.Equal(t, "search_issues", tool.Name) assert.NotEmpty(t, tool.Description) @@ -1897,11 +1893,7 @@ func Test_ListIssues(t *testing.T) { // Verify tool definition serverTool := ListIssues(translations.NullTranslationHelper) tool := serverTool.Tool - // ListIssues is the FeatureFlagFieldsParam-enabled variant; it owns the - // _ff_ snapshot. The canonical list_issues.snap is owned by - // LegacyListIssues (see Test_LegacyListIssues_Definition). - require.NoError(t, toolsnaps.Test(tool.Name+"_ff_"+FeatureFlagFieldsParam, tool)) - require.Equal(t, FeatureFlagFieldsParam, serverTool.FeatureFlagEnable) + require.NoError(t, toolsnaps.Test(tool.Name, tool)) assert.Equal(t, "list_issues", tool.Name) assert.NotEmpty(t, tool.Description) diff --git a/pkg/github/pullrequests.go b/pkg/github/pullrequests.go index daf3b97331..eea4c29cd6 100644 --- a/pkg/github/pullrequests.go +++ b/pkg/github/pullrequests.go @@ -1322,34 +1322,7 @@ func AddReplyToPullRequestComment(t translations.TranslationHelperFunc) inventor } // ListPullRequests creates a tool to list pull requests in a GitHub repository. -// It is the FeatureFlagFieldsParam-enabled variant: it advertises the optional -// `fields` parameter and filters each pull request to the requested subset. Both -// this and LegacyListPullRequests register under the tool name -// "list_pull_requests"; exactly one is active for any given request thanks to -// mutually exclusive FeatureFlagEnable / FeatureFlagDisable annotations. func ListPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool { - st := listPullRequestsTool(t, true) - st.FeatureFlagEnable = FeatureFlagFieldsParam - return st -} - -// LegacyListPullRequests is the FeatureFlagFieldsParam-disabled variant of -// list_pull_requests. It exposes the original schema (no `fields` parameter) and -// never filters results, so it acts as the kill switch when the flag is off. It -// owns the canonical list_pull_requests.snap; the flag-enabled variant owns -// list_pull_requests_ff_.snap. Delete this function when the flag is -// removed. -func LegacyListPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool { - st := listPullRequestsTool(t, false) - st.FeatureFlagDisable = []string{FeatureFlagFieldsParam} - return st -} - -// listPullRequestsTool builds the list_pull_requests tool. When includeFields is -// true the tool advertises the optional `fields` parameter, filters each pull -// request to the requested subset, and emits fields telemetry. When false it is -// the original tool with no fields parameter and no filtering. -func listPullRequestsTool(t translations.TranslationHelperFunc, includeFields bool) inventory.ServerTool { schema := &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ @@ -1387,12 +1360,10 @@ func listPullRequestsTool(t translations.TranslationHelperFunc, includeFields bo }, Required: []string{"owner", "repo"}, } - if includeFields { - schema.Properties["fields"] = fieldsSchemaProperty( - "Subset of fields to return for each pull request. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-result data.", - listPullRequestsItemFieldEnum, - ) - } + schema.Properties["fields"] = fieldsSchemaProperty( + "Subset of fields to return for each pull request. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-result data.", + listPullRequestsItemFieldEnum, + ) WithPagination(schema) return NewTool( @@ -1436,12 +1407,9 @@ func listPullRequestsTool(t translations.TranslationHelperFunc, includeFields bo if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } - var fields []string - if includeFields { - fields, err = OptionalStringArrayParam(args, "fields") - if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil - } + fields, err := OptionalStringArrayParam(args, "fields") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { @@ -1504,7 +1472,7 @@ func listPullRequestsTool(t translations.TranslationHelperFunc, includeFields bo filtered := false var payload any = minimalPRs - if includeFields && len(fields) > 0 { + if len(fields) > 0 { filteredPRs, err := filterEachField(minimalPRs, fields) if err != nil { return utils.NewToolResultErrorFromErr("failed to filter pull requests", err), nil, nil @@ -1518,9 +1486,7 @@ func listPullRequestsTool(t translations.TranslationHelperFunc, includeFields bo return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil } - if includeFields { - recordFieldsUsageFor(ctx, deps, "list_pull_requests", minimalPRs, filtered, len(r)) - } + recordFieldsUsageFor(ctx, deps, "list_pull_requests", minimalPRs, filtered, len(r)) result := utils.NewToolResultText(string(r)) // Pull request titles/bodies are user-authored (untrusted); @@ -1639,35 +1605,8 @@ func MergePullRequest(t translations.TranslationHelperFunc) inventory.ServerTool }) } -// SearchPullRequests creates a tool to search for pull requests. It is the -// FeatureFlagFieldsParam-enabled variant: it advertises the optional `fields` -// parameter and filters each result to the requested subset. Both this and -// LegacySearchPullRequests register under the tool name "search_pull_requests"; -// exactly one is active for any given request thanks to mutually exclusive -// FeatureFlagEnable / FeatureFlagDisable annotations. +// SearchPullRequests creates a tool to search for pull requests. func SearchPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool { - st := searchPullRequestsTool(t, true) - st.FeatureFlagEnable = FeatureFlagFieldsParam - return st -} - -// LegacySearchPullRequests is the FeatureFlagFieldsParam-disabled variant of -// search_pull_requests. It exposes the original schema (no `fields` parameter) -// and never filters results, so it acts as the kill switch when the flag is off. -// It owns the canonical search_pull_requests.snap; the flag-enabled variant owns -// search_pull_requests_ff_.snap. Delete this function when the flag is -// removed. -func LegacySearchPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool { - st := searchPullRequestsTool(t, false) - st.FeatureFlagDisable = []string{FeatureFlagFieldsParam} - return st -} - -// searchPullRequestsTool builds the search_pull_requests tool. When -// includeFields is true the tool advertises the optional `fields` parameter, -// filters each result to the requested subset, and emits fields telemetry. When -// false it is the original tool with no fields parameter and no filtering. -func searchPullRequestsTool(t translations.TranslationHelperFunc, includeFields bool) inventory.ServerTool { schema := &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ @@ -1708,12 +1647,10 @@ func searchPullRequestsTool(t translations.TranslationHelperFunc, includeFields }, Required: []string{"query"}, } - if includeFields { - schema.Properties["fields"] = fieldsSchemaProperty( - "Subset of fields to return for each pull request result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data.", - searchPullRequestsItemFieldEnum, - ) - } + schema.Properties["fields"] = fieldsSchemaProperty( + "Subset of fields to return for each pull request result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body', 'reactions', and 'labels' in particular drops the largest per-result data.", + searchPullRequestsItemFieldEnum, + ) WithPagination(schema) return NewTool( @@ -1730,13 +1667,11 @@ func searchPullRequestsTool(t translations.TranslationHelperFunc, includeFields []scopes.Scope{scopes.Repo}, func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { options := []searchOption{ifcSearchPostProcessOption(ctx, deps)} - if includeFields { - fields, err := OptionalStringArrayParam(args, "fields") - if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil - } - options = append(options, withFieldsFiltering(deps, "search_pull_requests", fields)) + fields, err := OptionalStringArrayParam(args, "fields") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil } + options = append(options, withFieldsFiltering(deps, "search_pull_requests", fields)) result, err := searchHandler(ctx, deps.GetClient, args, "pr", "failed to search pull requests", options...) return result, nil, err }) diff --git a/pkg/github/pullrequests_test.go b/pkg/github/pullrequests_test.go index ace47c666b..5fe1229dba 100644 --- a/pkg/github/pullrequests_test.go +++ b/pkg/github/pullrequests_test.go @@ -615,11 +615,7 @@ func Test_ListPullRequests(t *testing.T) { // Verify tool definition once serverTool := ListPullRequests(translations.NullTranslationHelper) tool := serverTool.Tool - // ListPullRequests is the FeatureFlagFieldsParam-enabled variant; it owns - // the _ff_ snapshot. The canonical list_pull_requests.snap is owned by - // LegacyListPullRequests (see Test_LegacyListPullRequests_Definition). - require.NoError(t, toolsnaps.Test(tool.Name+"_ff_"+FeatureFlagFieldsParam, tool)) - require.Equal(t, FeatureFlagFieldsParam, serverTool.FeatureFlagEnable) + require.NoError(t, toolsnaps.Test(tool.Name, tool)) assert.Equal(t, "list_pull_requests", tool.Name) assert.NotEmpty(t, tool.Description) @@ -866,11 +862,7 @@ func Test_MergePullRequest(t *testing.T) { func Test_SearchPullRequests(t *testing.T) { serverTool := SearchPullRequests(translations.NullTranslationHelper) tool := serverTool.Tool - // SearchPullRequests is the FeatureFlagFieldsParam-enabled variant; it owns - // the _ff_ snapshot. The canonical search_pull_requests.snap is owned - // by LegacySearchPullRequests (see Test_LegacySearchPullRequests_Definition). - require.NoError(t, toolsnaps.Test(tool.Name+"_ff_"+FeatureFlagFieldsParam, tool)) - require.Equal(t, FeatureFlagFieldsParam, serverTool.FeatureFlagEnable) + require.NoError(t, toolsnaps.Test(tool.Name, tool)) assert.Equal(t, "search_pull_requests", tool.Name) assert.NotEmpty(t, tool.Description) diff --git a/pkg/github/repositories.go b/pkg/github/repositories.go index aa236cd53a..be7b76edda 100644 --- a/pkg/github/repositories.go +++ b/pkg/github/repositories.go @@ -133,33 +133,8 @@ func GetCommit(t translations.TranslationHelperFunc) inventory.ServerTool { } // ListCommits creates a tool to get the list of commits of a branch in a GitHub -// repository. It is the FeatureFlagFieldsParam-enabled variant: it advertises -// the optional `fields` parameter and filters each commit to the requested -// subset. Both this and LegacyListCommits register under the tool name -// "list_commits"; exactly one is active for any given request thanks to mutually -// exclusive FeatureFlagEnable / FeatureFlagDisable annotations. +// repository. func ListCommits(t translations.TranslationHelperFunc) inventory.ServerTool { - st := listCommitsTool(t, true) - st.FeatureFlagEnable = FeatureFlagFieldsParam - return st -} - -// LegacyListCommits is the FeatureFlagFieldsParam-disabled variant of -// list_commits. It exposes the original schema (no `fields` parameter) and never -// filters results, so it acts as the kill switch when the flag is off. It owns -// the canonical list_commits.snap; the flag-enabled variant owns -// list_commits_ff_.snap. Delete this function when the flag is removed. -func LegacyListCommits(t translations.TranslationHelperFunc) inventory.ServerTool { - st := listCommitsTool(t, false) - st.FeatureFlagDisable = []string{FeatureFlagFieldsParam} - return st -} - -// listCommitsTool builds the list_commits tool. When includeFields is true the -// tool advertises the optional `fields` parameter, filters each commit to the -// requested subset, and emits fields telemetry. When false it is the original -// tool with no fields parameter and no filtering. -func listCommitsTool(t translations.TranslationHelperFunc, includeFields bool) inventory.ServerTool { schema := &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ @@ -194,12 +169,10 @@ func listCommitsTool(t translations.TranslationHelperFunc, includeFields bool) i }, Required: []string{"owner", "repo"}, } - if includeFields { - schema.Properties["fields"] = fieldsSchemaProperty( - "Subset of fields to return for each commit. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields, e.g. just 'sha' and 'html_url'.", - listCommitsItemFieldEnum, - ) - } + schema.Properties["fields"] = fieldsSchemaProperty( + "Subset of fields to return for each commit. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields, e.g. just 'sha' and 'html_url'.", + listCommitsItemFieldEnum, + ) WithPagination(schema) return NewTool( @@ -235,12 +208,9 @@ func listCommitsTool(t translations.TranslationHelperFunc, includeFields bool) i if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } - var fields []string - if includeFields { - fields, err = OptionalStringArrayParam(args, "fields") - if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil - } + fields, err := OptionalStringArrayParam(args, "fields") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil } sinceStr, err := OptionalParam[string](args, "since") if err != nil { @@ -313,7 +283,7 @@ func listCommitsTool(t translations.TranslationHelperFunc, includeFields bool) i filtered := false var payload any = minimalCommits - if includeFields && len(fields) > 0 { + if len(fields) > 0 { filteredCommits, err := filterEachField(minimalCommits, fields) if err != nil { return utils.NewToolResultErrorFromErr("failed to filter commits", err), nil, nil @@ -327,9 +297,7 @@ func listCommitsTool(t translations.TranslationHelperFunc, includeFields bool) i return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - if includeFields { - recordFieldsUsageFor(ctx, deps, "list_commits", minimalCommits, filtered, len(r)) - } + recordFieldsUsageFor(ctx, deps, "list_commits", minimalCommits, filtered, len(r)) result := utils.NewToolResultText(string(r)) // Commit content is reachable from the repo's history; integrity @@ -751,34 +719,8 @@ func FetchRepoIsPrivate(ctx context.Context, client *github.Client, owner, repo } // GetFileContents creates a tool to get the contents of a file or directory from -// a GitHub repository. It is the FeatureFlagFieldsParam-enabled variant: it -// advertises the optional `fields` parameter and filters directory listings to -// the requested subset. Both this and LegacyGetFileContents register under the -// tool name "get_file_contents"; exactly one is active for any given request -// thanks to mutually exclusive FeatureFlagEnable / FeatureFlagDisable annotations. +// a GitHub repository. func GetFileContents(t translations.TranslationHelperFunc) inventory.ServerTool { - st := getFileContentsTool(t, true) - st.FeatureFlagEnable = FeatureFlagFieldsParam - return st -} - -// LegacyGetFileContents is the FeatureFlagFieldsParam-disabled variant of -// get_file_contents. It exposes the original schema (no `fields` parameter) and -// never filters directory listings, so it acts as the kill switch when the flag -// is off. It owns the canonical get_file_contents.snap; the flag-enabled variant -// owns get_file_contents_ff_.snap. Delete this function when the flag is -// removed. -func LegacyGetFileContents(t translations.TranslationHelperFunc) inventory.ServerTool { - st := getFileContentsTool(t, false) - st.FeatureFlagDisable = []string{FeatureFlagFieldsParam} - return st -} - -// getFileContentsTool builds the get_file_contents tool. When includeFields is -// true the tool advertises the optional `fields` parameter, filters directory -// listings to the requested subset, and emits fields telemetry. When false it is -// the original tool with no fields parameter and no filtering. -func getFileContentsTool(t translations.TranslationHelperFunc, includeFields bool) inventory.ServerTool { schema := &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ @@ -806,12 +748,10 @@ func getFileContentsTool(t translations.TranslationHelperFunc, includeFields boo }, Required: []string{"owner", "repo"}, } - if includeFields { - schema.Properties["fields"] = fieldsSchemaProperty( - "Subset of fields to return for each entry when the path is a directory. If omitted, all fields are returned. Ignored when the path is a single file. Use this to reduce response size when listing directories and you only need specific fields, e.g. just 'name' and 'type'.", - fileContentFieldEnum, - ) - } + schema.Properties["fields"] = fieldsSchemaProperty( + "Subset of fields to return for each entry when the path is a directory. If omitted, all fields are returned. Ignored when the path is a single file. Use this to reduce response size when listing directories and you only need specific fields, e.g. just 'name' and 'type'.", + fileContentFieldEnum, + ) return NewTool( ToolsetMetadataRepos, @@ -852,12 +792,9 @@ func getFileContentsTool(t translations.TranslationHelperFunc, includeFields boo return utils.NewToolResultError(err.Error()), nil, nil } - var fields []string - if includeFields { - fields, err = OptionalStringArrayParam(args, "fields") - if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil - } + fields, err := OptionalStringArrayParam(args, "fields") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil } client, err := deps.GetClient(ctx) @@ -985,7 +922,7 @@ func getFileContentsTool(t translations.TranslationHelperFunc, includeFields boo // file content or file SHA is nil which means it's a directory filtered := false var payload any = dirContent - if includeFields && len(fields) > 0 { + if len(fields) > 0 { filteredEntries, err := filterEachField(dirContent, fields) if err != nil { return utils.NewToolResultErrorFromErr("failed to filter directory contents", err), nil, nil @@ -997,9 +934,7 @@ func getFileContentsTool(t translations.TranslationHelperFunc, includeFields boo if err != nil { return utils.NewToolResultError("failed to marshal response"), nil, nil } - if includeFields { - recordDirContentsFieldsUsage(ctx, deps, dirContent, filtered, len(r)) - } + recordDirContentsFieldsUsage(ctx, deps, dirContent, filtered, len(r)) return attachIFC(utils.NewToolResultText(string(r))), nil, nil } @@ -1850,34 +1785,8 @@ func GetTag(t translations.TranslationHelperFunc) inventory.ServerTool { ) } -// ListReleases creates a tool to list releases in a GitHub repository. It is the -// FeatureFlagFieldsParam-enabled variant: it advertises the optional `fields` -// parameter and filters each release to the requested subset. Both this and -// LegacyListReleases register under the tool name "list_releases"; exactly one is -// active for any given request thanks to mutually exclusive FeatureFlagEnable / -// FeatureFlagDisable annotations. +// ListReleases creates a tool to list releases in a GitHub repository. func ListReleases(t translations.TranslationHelperFunc) inventory.ServerTool { - st := listReleasesTool(t, true) - st.FeatureFlagEnable = FeatureFlagFieldsParam - return st -} - -// LegacyListReleases is the FeatureFlagFieldsParam-disabled variant of -// list_releases. It exposes the original schema (no `fields` parameter) and never -// filters results, so it acts as the kill switch when the flag is off. It owns -// the canonical list_releases.snap; the flag-enabled variant owns -// list_releases_ff_.snap. Delete this function when the flag is removed. -func LegacyListReleases(t translations.TranslationHelperFunc) inventory.ServerTool { - st := listReleasesTool(t, false) - st.FeatureFlagDisable = []string{FeatureFlagFieldsParam} - return st -} - -// listReleasesTool builds the list_releases tool. When includeFields is true the -// tool advertises the optional `fields` parameter, filters each release to the -// requested subset, and emits fields telemetry. When false it is the original -// tool with no fields parameter and no filtering. -func listReleasesTool(t translations.TranslationHelperFunc, includeFields bool) inventory.ServerTool { schema := &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ @@ -1892,12 +1801,10 @@ func listReleasesTool(t translations.TranslationHelperFunc, includeFields bool) }, Required: []string{"owner", "repo"}, } - if includeFields { - schema.Properties["fields"] = fieldsSchemaProperty( - "Subset of fields to return for each release. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-release data.", - listReleasesItemFieldEnum, - ) - } + schema.Properties["fields"] = fieldsSchemaProperty( + "Subset of fields to return for each release. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'body' in particular drops the largest per-release data.", + listReleasesItemFieldEnum, + ) WithPagination(schema) return NewTool( @@ -1921,12 +1828,9 @@ func listReleasesTool(t translations.TranslationHelperFunc, includeFields bool) if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } - var fields []string - if includeFields { - fields, err = OptionalStringArrayParam(args, "fields") - if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil - } + fields, err := OptionalStringArrayParam(args, "fields") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { @@ -1966,7 +1870,7 @@ func listReleasesTool(t translations.TranslationHelperFunc, includeFields bool) filtered := false var payload any = minimalReleases - if includeFields && len(fields) > 0 { + if len(fields) > 0 { filteredReleases, err := filterEachField(minimalReleases, fields) if err != nil { return utils.NewToolResultErrorFromErr("failed to filter releases", err), nil, nil @@ -1980,9 +1884,7 @@ func listReleasesTool(t translations.TranslationHelperFunc, includeFields bool) return nil, nil, fmt.Errorf("failed to marshal response: %w", err) } - if includeFields { - recordFieldsUsageFor(ctx, deps, "list_releases", minimalReleases, filtered, len(r)) - } + recordFieldsUsageFor(ctx, deps, "list_releases", minimalReleases, filtered, len(r)) result := utils.NewToolResultText(string(r)) // Releases are published by collaborators with push access, so diff --git a/pkg/github/repositories_test.go b/pkg/github/repositories_test.go index fcc5fa0634..332b212a17 100644 --- a/pkg/github/repositories_test.go +++ b/pkg/github/repositories_test.go @@ -27,11 +27,7 @@ func Test_GetFileContents(t *testing.T) { // Verify tool definition once serverTool := GetFileContents(translations.NullTranslationHelper) tool := serverTool.Tool - // GetFileContents is the FeatureFlagFieldsParam-enabled variant; it owns the - // _ff_ snapshot. The canonical get_file_contents.snap is owned by - // LegacyGetFileContents (see Test_LegacyGetFileContents_Definition). - require.NoError(t, toolsnaps.Test(tool.Name+"_ff_"+FeatureFlagFieldsParam, tool)) - require.Equal(t, FeatureFlagFieldsParam, serverTool.FeatureFlagEnable) + require.NoError(t, toolsnaps.Test(tool.Name, tool)) schema, ok := tool.InputSchema.(*jsonschema.Schema) require.True(t, ok, "InputSchema should be *jsonschema.Schema") @@ -548,20 +544,6 @@ func Test_GetFileContents_DirectoryFieldFiltering(t *testing.T) { assert.NotContains(t, textContent.Text, "download_url") } -func Test_LegacyGetFileContents_Definition(t *testing.T) { - serverTool := LegacyGetFileContents(translations.NullTranslationHelper) - tool := serverTool.Tool - // LegacyGetFileContents is the FeatureFlagFieldsParam-disabled variant and - // owns the canonical get_file_contents.snap (no `fields`). - require.NoError(t, toolsnaps.Test(tool.Name, tool)) - require.Equal(t, []string{FeatureFlagFieldsParam}, serverTool.FeatureFlagDisable) - - assert.Equal(t, "get_file_contents", tool.Name) - schema, ok := tool.InputSchema.(*jsonschema.Schema) - require.True(t, ok, "InputSchema should be *jsonschema.Schema") - assert.NotContains(t, schema.Properties, "fields") -} - func Test_GetFileContents_DirectoryFieldsTelemetry(t *testing.T) { mockDirContent := []*github.RepositoryContent{ { @@ -1402,11 +1384,7 @@ func Test_ListCommits(t *testing.T) { // Verify tool definition once serverTool := ListCommits(translations.NullTranslationHelper) tool := serverTool.Tool - // ListCommits is the FeatureFlagFieldsParam-enabled variant; it owns the - // _ff_ snapshot. The canonical list_commits.snap is owned by - // LegacyListCommits (see Test_LegacyListCommits_Definition). - require.NoError(t, toolsnaps.Test(tool.Name+"_ff_"+FeatureFlagFieldsParam, tool)) - require.Equal(t, FeatureFlagFieldsParam, serverTool.FeatureFlagEnable) + require.NoError(t, toolsnaps.Test(tool.Name, tool)) schema, ok := tool.InputSchema.(*jsonschema.Schema) require.True(t, ok, "InputSchema should be *jsonschema.Schema") @@ -3644,11 +3622,7 @@ func Test_GetTag(t *testing.T) { func Test_ListReleases(t *testing.T) { serverTool := ListReleases(translations.NullTranslationHelper) tool := serverTool.Tool - // ListReleases is the FeatureFlagFieldsParam-enabled variant; it owns the - // _ff_ snapshot. The canonical list_releases.snap is owned by - // LegacyListReleases (see Test_LegacyListReleases_Definition). - require.NoError(t, toolsnaps.Test(tool.Name+"_ff_"+FeatureFlagFieldsParam, tool)) - require.Equal(t, FeatureFlagFieldsParam, serverTool.FeatureFlagEnable) + require.NoError(t, toolsnaps.Test(tool.Name, tool)) schema, ok := tool.InputSchema.(*jsonschema.Schema) require.True(t, ok, "InputSchema should be *jsonschema.Schema") diff --git a/pkg/github/search.go b/pkg/github/search.go index 28439e9fb7..3160209318 100644 --- a/pkg/github/search.go +++ b/pkg/github/search.go @@ -191,34 +191,8 @@ func attachSearchRepositoriesIFCLabel(ctx context.Context, deps ToolDependencies setIFCLabel(callResult, ifc.LabelSearchIssues(visibilities)) } -// SearchCode creates a tool to search for code across GitHub repositories. It is -// the FeatureFlagFieldsParam-enabled variant: it advertises the optional -// `fields` parameter and filters each result to the requested subset. Both this -// and LegacySearchCode register under the tool name "search_code"; exactly one -// is active for any given request thanks to mutually exclusive -// FeatureFlagEnable / FeatureFlagDisable annotations. +// SearchCode creates a tool to search for code across GitHub repositories. func SearchCode(t translations.TranslationHelperFunc) inventory.ServerTool { - st := searchCodeTool(t, true) - st.FeatureFlagEnable = FeatureFlagFieldsParam - return st -} - -// LegacySearchCode is the FeatureFlagFieldsParam-disabled variant of -// search_code. It exposes the original schema (no `fields` parameter) and never -// filters results, so it acts as the kill switch when the flag is off. It owns -// the canonical search_code.snap; the flag-enabled variant owns -// search_code_ff_.snap. Delete this function when the flag is removed. -func LegacySearchCode(t translations.TranslationHelperFunc) inventory.ServerTool { - st := searchCodeTool(t, false) - st.FeatureFlagDisable = []string{FeatureFlagFieldsParam} - return st -} - -// searchCodeTool builds the search_code tool. When includeFields is true the -// tool advertises the optional `fields` parameter, filters each result to the -// requested subset, and emits fields telemetry. When false it is the original -// tool with no fields parameter and no filtering. -func searchCodeTool(t translations.TranslationHelperFunc, includeFields bool) inventory.ServerTool { schema := &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ @@ -238,12 +212,10 @@ func searchCodeTool(t translations.TranslationHelperFunc, includeFields bool) in }, Required: []string{"query"}, } - if includeFields { - schema.Properties["fields"] = fieldsSchemaProperty( - "Subset of fields to return for each code search result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'repository' and 'text_matches' in particular drops the largest per-result data.", - codeSearchItemFieldEnum, - ) - } + schema.Properties["fields"] = fieldsSchemaProperty( + "Subset of fields to return for each code search result. If omitted, all fields are returned. Use this to reduce response size when you only need specific fields; omitting 'repository' and 'text_matches' in particular drops the largest per-result data.", + codeSearchItemFieldEnum, + ) WithPagination(schema) return NewTool( @@ -271,12 +243,9 @@ func searchCodeTool(t translations.TranslationHelperFunc, includeFields bool) in if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } - var fields []string - if includeFields { - fields, err = OptionalStringArrayParam(args, "fields") - if err != nil { - return utils.NewToolResultError(err.Error()), nil, nil - } + fields, err := OptionalStringArrayParam(args, "fields") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil } pagination, err := OptionalPaginationParams(args) if err != nil { @@ -338,7 +307,7 @@ func searchCodeTool(t translations.TranslationHelperFunc, includeFields bool) in filtered := false var payload any = minimalResult - if includeFields && len(fields) > 0 { + if len(fields) > 0 { filteredItems, err := filterEachField(minimalItems, fields) if err != nil { return utils.NewToolResultErrorFromErr("failed to filter code search results", err), nil, nil @@ -356,9 +325,7 @@ func searchCodeTool(t translations.TranslationHelperFunc, includeFields bool) in return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil } - if includeFields { - recordSearchCodeFieldsUsage(ctx, deps, minimalResult, filtered, len(r)) - } + recordSearchCodeFieldsUsage(ctx, deps, minimalResult, filtered, len(r)) callResult := utils.NewToolResultText(string(r)) // Code search spans repositories; the IFC label is the conservative diff --git a/pkg/github/search_test.go b/pkg/github/search_test.go index e5e673e74f..52e70b639c 100644 --- a/pkg/github/search_test.go +++ b/pkg/github/search_test.go @@ -342,11 +342,7 @@ func Test_SearchCode(t *testing.T) { // Verify tool definition once serverTool := SearchCode(translations.NullTranslationHelper) tool := serverTool.Tool - // SearchCode is the FeatureFlagFieldsParam-enabled variant; it owns the - // _ff_ snapshot. The canonical search_code.snap is owned by - // LegacySearchCode (see Test_LegacySearchCode_Definition). - require.NoError(t, toolsnaps.Test(tool.Name+"_ff_"+FeatureFlagFieldsParam, tool)) - require.Equal(t, FeatureFlagFieldsParam, serverTool.FeatureFlagEnable) + require.NoError(t, toolsnaps.Test(tool.Name, tool)) assert.Equal(t, "search_code", tool.Name) assert.NotEmpty(t, tool.Description) @@ -571,20 +567,6 @@ func Test_SearchCode_FieldFiltering(t *testing.T) { assert.NotContains(t, textContent.Text, "text_matches") } -func Test_LegacySearchCode_Definition(t *testing.T) { - serverTool := LegacySearchCode(translations.NullTranslationHelper) - tool := serverTool.Tool - // LegacySearchCode is the FeatureFlagFieldsParam-disabled variant and owns - // the canonical search_code.snap (no `fields`). - require.NoError(t, toolsnaps.Test(tool.Name, tool)) - require.Equal(t, []string{FeatureFlagFieldsParam}, serverTool.FeatureFlagDisable) - - assert.Equal(t, "search_code", tool.Name) - schema, ok := tool.InputSchema.(*jsonschema.Schema) - require.True(t, ok, "InputSchema should be *jsonschema.Schema") - assert.NotContains(t, schema.Properties, "fields") -} - func Test_SearchCode_FieldsTelemetry(t *testing.T) { mockSearchResult := &github.CodeSearchResult{ Total: github.Ptr(1), diff --git a/pkg/github/tools.go b/pkg/github/tools.go index 2cfcd3e89b..7bae64d2e8 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -192,11 +192,8 @@ func AllTools(t translations.TranslationHelperFunc) []inventory.ServerTool { // Repository tools SearchRepositories(t), GetFileContents(t), - LegacyGetFileContents(t), ListCommits(t), - LegacyListCommits(t), SearchCode(t), - LegacySearchCode(t), SearchCommits(t), GetCommit(t), GetFileBlame(t), @@ -204,7 +201,6 @@ func AllTools(t translations.TranslationHelperFunc) []inventory.ServerTool { ListTags(t), GetTag(t), ListReleases(t), - LegacyListReleases(t), GetLatestRelease(t), GetReleaseByTag(t), CreateOrUpdateFile(t), @@ -224,9 +220,7 @@ func AllTools(t translations.TranslationHelperFunc) []inventory.ServerTool { // Issue tools IssueRead(t), SearchIssues(t), - LegacySearchIssues(t), ListIssues(t), - LegacyListIssues(t), ListIssueTypes(t), ListIssueFields(t), IssueWrite(t), @@ -244,9 +238,7 @@ func AllTools(t translations.TranslationHelperFunc) []inventory.ServerTool { // Pull request tools PullRequestRead(t), ListPullRequests(t), - LegacyListPullRequests(t), SearchPullRequests(t), - LegacySearchPullRequests(t), MergePullRequest(t), UpdatePullRequestBranch(t), CreatePullRequest(t),