Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add resource completion for GitHub repository resources#1493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
omgitsads wants to merge7 commits intoomgitsads/go-sdk
base:omgitsads/go-sdk
Choose a base branch
Loading
fromomgitsads/go-sdk-completions

Conversation

@omgitsads
Copy link
Member

Add Completions for Repository Resources

Co-Authored-by: Ksenia Bobrova <almaleksia@github.com>
CopilotAI review requested due to automatic review settingsNovember 26, 2025 10:58
@omgitsadsomgitsads requested a review froma team as acode ownerNovember 26, 2025 10:58
Copilot finished reviewing on behalf ofomgitsadsNovember 26, 2025 11:02
Copy link
Contributor

CopilotAI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Pull request overview

This PR adds resource completion functionality for GitHub repository resources, enabling auto-completion for repository-related parameters like owner, repo, branch, SHA, tag, PR number, and file paths in the MCP server.

Key Changes:

  • Implements completion handlers for 7 repository resource arguments (owner, repo, branch, sha, tag, prNumber, path)
  • Adds routing logic to dispatch completion requests based on resource URI patterns
  • Includes comprehensive test coverage with 16 test cases covering various scenarios

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 15 comments.

FileDescription
pkg/github/server.goAddsGitHubCompletionsHandler to route completion requests for different resource types, removes redundant nil check for server options
pkg/github/repository_resource_completions.goImplements completion handlers for repository resources with GitHub API integration for suggestions
pkg/github/repository_resource_completions_test.goProvides test coverage for completion handlers including error cases, missing dependencies, and context handling

You can also share your feedback on Copilot code review for a chance to win a $100 gift card.Take the survey.

Comment on lines +265 to +292
// Get the tree for the ref (recursive)
tree, _, err := client.Git.GetTree(ctx, owner, repo, refVal, true)
if err != nil || tree == nil {
return nil, errors.New("failed to get file tree")
}

// Collect immediate children of the prefix (files and directories, no duplicates)
dirs := map[string]struct{}{}
files := map[string]struct{}{}
prefixLen := len(prefix)
for _, entry := range tree.Entries {
if !strings.HasPrefix(entry.GetPath(), prefix) {
continue
}
rel := entry.GetPath()[prefixLen:]
if rel == "" {
continue
}
// Only immediate children
slashIdx := strings.Index(rel, "/")
if slashIdx >= 0 {
// Directory: only add the directory name (with trailing slash), prefixed with full path
dirName := prefix + rel[:slashIdx+1]
dirs[dirName] = struct{}{}
} else if entry.GetType() == "blob" {
// File: add as-is, prefixed with full path
fileName := prefix + rel
files[fileName] = struct{}{}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Fetching recursive tree could be inefficient for large repositories. Line 266 fetches the entire repository tree recursively (recursive: true), which can be very large for repositories with many files and deeply nested directories. This could cause performance issues or API rate limiting. Consider:

  1. Fetching only the specific directory level needed based on the path prefix
  2. Adding pagination or limiting the tree depth
  3. Implementing client-side caching if this is called frequently
Suggested change
// Get the tree for the ref (recursive)
tree,_,err:=client.Git.GetTree(ctx,owner,repo,refVal,true)
iferr!=nil||tree==nil {
returnnil,errors.New("failed to get file tree")
}
// Collect immediate children of the prefix (files and directories, no duplicates)
dirs:=map[string]struct{}{}
files:=map[string]struct{}{}
prefixLen:=len(prefix)
for_,entry:=range tree.Entries {
if!strings.HasPrefix(entry.GetPath(),prefix) {
continue
}
rel:=entry.GetPath()[prefixLen:]
ifrel=="" {
continue
}
// Only immediate children
slashIdx:=strings.Index(rel,"/")
ifslashIdx>=0 {
// Directory: only add the directory name (with trailing slash), prefixed with full path
dirName:=prefix+rel[:slashIdx+1]
dirs[dirName]=struct{}{}
}elseifentry.GetType()=="blob" {
// File: add as-is, prefixed with full path
fileName:=prefix+rel
files[fileName]=struct{}{}
// Get the contents of the directory at the prefix for the ref
contents,_,_,err:=client.Repositories.GetContents(ctx,owner,repo,prefix,&github.RepositoryContentGetOptions{Ref:refVal})
iferr!=nil {
returnnil,errors.New("failed to get directory contents")
}
// Collect immediate children of the prefix (files and directories, no duplicates)
dirs:=map[string]struct{}{}
files:=map[string]struct{}{}
for_,entry:=rangecontents {
ifentry.GetType()=="dir" {
// Directory: add with trailing slash
dirName:=entry.GetPath()
if!strings.HasSuffix(dirName,"/") {
dirName+="/"
}
dirs[dirName]=struct{}{}
}elseifentry.GetType()=="file" {
files[entry.GetPath()]=struct{}{}

Copilot uses AI. Check for mistakes.
Comment on lines 79 to 90
fmt.Printf("Found user: %v\n", err)
if err == nil && user.GetLogin() != "" {
values = append(values, user.GetLogin())
fmt.Println("Fetching organizations for user " + user.GetLogin())
}

orgs, _, err := client.Organizations.List(ctx, "", &github.ListOptions{PerPage: 100})
if err != nil {
return nil, err
}
for _, org := range orgs {
fmt.Println("Found organization: " + org.GetLogin())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Debug print statements should be removed from production code. These statements at lines 79, 82, and 90 are logging debugging information to stdout. Consider using the project's logging utilities (pkg/log) with proper log levels if this information needs to be captured.

Copilot uses AI. Check for mistakes.
if owner == "" || repo == "" {
return values, errors.New("owner or repo not specified")
}
branches, _, _ := client.Repositories.ListBranches(ctx, owner, repo, nil)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

API call error is silently ignored. The error fromListBranches should be checked and handled. If the call fails, it could result in returning an empty list without informing the user of the failure. Consider handling the error similar to other completion functions or at minimum checking if branches is nil before iterating.

Suggested change
branches,_,_:=client.Repositories.ListBranches(ctx,owner,repo,nil)
branches,_,err:=client.Repositories.ListBranches(ctx,owner,repo,nil)
iferr!=nil||branches==nil {
returnvalues,errors.New("failed to get branches")
}

Copilot uses AI. Check for mistakes.
if owner == "" || repo == "" {
return nil, errors.New("owner or repo not specified")
}
tags, _, _ := client.Repositories.ListTags(ctx, owner, repo, nil)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

API call error is silently ignored. The error fromListTags should be checked and handled. If the call fails, it could result in returning an empty list without informing the user of the failure. Consider handling the error similar to how it's done incompletePRNumber or at minimum checking if tags is nil before iterating.

Suggested change
tags,_,_:=client.Repositories.ListTags(ctx,owner,repo,nil)
tags,_,err:=client.Repositories.ListTags(ctx,owner,repo,nil)
iferr!=nil {
returnnil,err
}

Copilot uses AI. Check for mistakes.
Comment on lines +139 to +141
if err != nil || repos == nil {
return values, errors.New("failed to get repositories")
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Generic error message loses context. The error fromclient.Search.Repositories should be wrapped or propagated to provide more specific failure information to the caller. Consider returning the original error withfmt.Errorf("failed to get repositories: %w", err) instead of creating a new generic error.

Suggested change
iferr!=nil||repos==nil {
returnvalues,errors.New("failed to get repositories")
}
iferr!=nil {
returnvalues,fmt.Errorf("failed to get repositories: %w",err)
}
ifrepos==nil {
returnvalues,errors.New("failed to get repositories: response was nil")
}

Copilot uses AI. Check for mistakes.
Comment on lines 250 to 278
originalResolver := RepositoryResourceArgumentResolvers["owner"]
RepositoryResourceArgumentResolvers["owner"] = func(ctx context.Context, client *github.Client, resolved map[string]string, argValue string) ([]string, error) {
// Return 150 results
results := make([]string, 150)
for i := 0; i < 150; i++ {
results[i] = fmt.Sprintf("user%d", i)
}
return results, nil
}

request := &mcp.CompleteRequest{
Params: &mcp.CompleteParams{
Ref: &mcp.CompleteReference{
Type: "ref/resource",
},
Argument: mcp.CompleteParamsArgument{
Name: "owner",
Value: "test",
},
},
}

result, err := handler(t.Context(), request)
require.NoError(t, err)
assert.NotNil(t, result)
assert.LessOrEqual(t, len(result.Completion.Values), 100)

// Restore original resolver
RepositoryResourceArgumentResolvers["owner"] = originalResolver

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Tests mutate global variableRepositoryResourceArgumentResolvers. Lines 250-258, 290-296, and 333-337 directly modify the globalRepositoryResourceArgumentResolvers map, which can cause test failures when tests run in parallel or affect other tests. Consider either:

  1. MakingRepositoryResourceArgumentResolvers non-exported and providing a way to inject custom resolvers for testing
  2. Creating a copy of the map before modification and restoring after each test
  3. Using t.Parallel() carefully or avoiding parallel execution for these tests

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +68
if len(values) > 100 {
values = values[:100]
}

return &mcp.CompleteResult{
Completion: mcp.CompletionResultDetails{
Values: values,
Total: len(values),
HasMore: false,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

HasMore field is always false. Line 68 setsHasMore: false even when results are truncated to 100 items (line 60-62). If more than 100 results exist, HasMore should be set to true to indicate that additional results are available.

Copilot uses AI. Check for mistakes.
if owner == "" || repo == "" {
return values, errors.New("owner or repo not specified")
}
commits, _, _ := client.Repositories.ListCommits(ctx, owner, repo, nil)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

API call error is silently ignored. The error fromListCommits should be checked and handled. If the call fails, it could result in returning an empty list without informing the user of the failure. Consider handling the error similar to how it's done incompletePRNumber or at minimum checking if commits is nil before iterating.

Suggested change
commits,_,_:=client.Repositories.ListCommits(ctx,owner,repo,nil)
commits,_,err:=client.Repositories.ListCommits(ctx,owner,repo,nil)
iferr!=nil||commits==nil {
returnvalues,errors.New("failed to get commits")
}

Copilot uses AI. Check for mistakes.
if owner == "" || repo == "" {
return values, errors.New("owner or repo not specified")
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

[nitpick] Only returns open pull requests. The query on line 221 filters foris:open is:pr, which means closed PRs won't be included in completions. Consider whether this is the intended behavior or if closed/merged PRs should also be available for completion. If this is intentional, consider adding a comment explaining the rationale.

Suggested change
// Only open PRs are returned for completion, as closed/merged PRs are typically not relevant for selection in this context.

Copilot uses AI. Check for mistakes.
return values, errors.New("owner not specified")
}

query := fmt.Sprintf("org:%s", owner)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Search query may not work correctly for non-organization owners. Line 133 usesorg:%s in the search query, which will fail if the owner is a user rather than an organization. Consider usinguser:%s OR org:%s or checking the owner type first.

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

Copilot code reviewCopilotCopilot left review comments

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

2 participants

@omgitsads

[8]ページ先頭

©2009-2025 Movatter.jp