@@ -1646,6 +1646,10 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server
16461646 Type : "number" ,
16471647 Description : "Issue number" ,
16481648 },
1649+ "base_ref" : {
1650+ Type : "string" ,
1651+ Description : "Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch" ,
1652+ },
16491653 },
16501654 Required : []string {"owner" , "repo" , "issue_number" },
16511655 },
@@ -1656,6 +1660,7 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server
16561660 Owner string `mapstructure:"owner"`
16571661 Repo string `mapstructure:"repo"`
16581662 IssueNumber int32 `mapstructure:"issue_number"`
1663+ BaseRef string `mapstructure:"base_ref"`
16591664 }
16601665 if err := mapstructure .Decode (args , & params ); err != nil {
16611666 return utils .NewToolResultError (err .Error ()), nil , nil
@@ -1724,10 +1729,10 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server
17241729 return utils .NewToolResultError ("copilot isn't available as an assignee for this issue. Please inform the user to visit https://docs.github.com/en/copilot/using-github-copilot/using-copilot-coding-agent-to-work-on-tasks/about-assigning-tasks-to-copilot for more information." ), nil , nil
17251730 }
17261731
1727- // Next let's get the GQL Node ID and current assignees for this issue because the only way to
1728- // assign copilot is to use replaceActorsForAssignable which requires the full list.
1732+ // Next, get the issue ID and repository ID
17291733 var getIssueQuery struct {
17301734 Repository struct {
1735+ ID githubv4.ID
17311736 Issue struct {
17321737 ID githubv4.ID
17331738 Assignees struct {
@@ -1749,30 +1754,54 @@ func AssignCopilotToIssue(t translations.TranslationHelperFunc) inventory.Server
17491754 return ghErrors .NewGitHubGraphQLErrorResponse (ctx , "failed to get issue ID" , err ), nil , nil
17501755 }
17511756
1752- // Finally, do the assignment. Just for reference, assigning copilot to an issue that it is already
1753- // assigned to seems to have no impact (which is a good thing).
1754- var assignCopilotMutation struct {
1755- ReplaceActorsForAssignable struct {
1756- Typename string `graphql:"__typename"` // Not required but we need a selector or GQL errors
1757- } `graphql:"replaceActorsForAssignable(input: $input)"`
1758- }
1759-
1757+ // Build the assignee IDs list including copilot
17601758 actorIDs := make ([]githubv4.ID , len (getIssueQuery .Repository .Issue .Assignees .Nodes )+ 1 )
17611759 for i , node := range getIssueQuery .Repository .Issue .Assignees .Nodes {
17621760 actorIDs [i ] = node .ID
17631761 }
17641762 actorIDs [len (getIssueQuery .Repository .Issue .Assignees .Nodes )] = copilotAssignee .ID
17651763
1764+ // Prepare agent assignment input
1765+ emptyString := githubv4 .String ("" )
1766+ agentAssignment := & AgentAssignmentInput {
1767+ CustomAgent : & emptyString ,
1768+ CustomInstructions : & emptyString ,
1769+ TargetRepositoryID : getIssueQuery .Repository .ID ,
1770+ }
1771+
1772+ // Add base ref if provided
1773+ if params .BaseRef != "" {
1774+ baseRef := githubv4 .String (params .BaseRef )
1775+ agentAssignment .BaseRef = & baseRef
1776+ }
1777+
1778+ // Execute the updateIssue mutation with the GraphQL-Features header
1779+ // This header is required for the agent assignment API which is not GA yet
1780+ var updateIssueMutation struct {
1781+ UpdateIssue struct {
1782+ Issue struct {
1783+ ID githubv4.ID
1784+ Number githubv4.Int
1785+ URL githubv4.String
1786+ }
1787+ } `graphql:"updateIssue(input: $input)"`
1788+ }
1789+
1790+ // Add the GraphQL-Features header for the agent assignment API
1791+ // The header will be read by the HTTP transport if it's configured to do so
1792+ ctxWithFeatures := withGraphQLFeatures (ctx , "issues_copilot_assignment_api_support" )
1793+
17661794 if err := client .Mutate (
1767- ctx ,
1768- & assignCopilotMutation ,
1769- ReplaceActorsForAssignableInput {
1770- AssignableID : getIssueQuery .Repository .Issue .ID ,
1771- ActorIDs : actorIDs ,
1795+ ctxWithFeatures ,
1796+ & updateIssueMutation ,
1797+ UpdateIssueInput {
1798+ ID : getIssueQuery .Repository .Issue .ID ,
1799+ AssigneeIDs : actorIDs ,
1800+ AgentAssignment : agentAssignment ,
17721801 },
17731802 nil ,
17741803 ); err != nil {
1775- return nil , nil , fmt .Errorf ("failed to replace actors for assignable : %w" , err )
1804+ return nil , nil , fmt .Errorf ("failed to update issue with agent assignment : %w" , err )
17761805 }
17771806
17781807 return utils .NewToolResultText ("successfully assigned copilot to issue" ), nil , nil
@@ -1784,6 +1813,21 @@ type ReplaceActorsForAssignableInput struct {
17841813 ActorIDs []githubv4.ID `json:"actorIds"`
17851814}
17861815
1816+ // AgentAssignmentInput represents the input for assigning an agent to an issue.
1817+ type AgentAssignmentInput struct {
1818+ BaseRef * githubv4.String `json:"baseRef,omitempty"`
1819+ CustomAgent * githubv4.String `json:"customAgent,omitempty"`
1820+ CustomInstructions * githubv4.String `json:"customInstructions,omitempty"`
1821+ TargetRepositoryID githubv4.ID `json:"targetRepositoryId"`
1822+ }
1823+
1824+ // UpdateIssueInput represents the input for updating an issue with agent assignment.
1825+ type UpdateIssueInput struct {
1826+ ID githubv4.ID `json:"id"`
1827+ AssigneeIDs []githubv4.ID `json:"assigneeIds"`
1828+ AgentAssignment * AgentAssignmentInput `json:"agentAssignment,omitempty"`
1829+ }
1830+
17871831// parseISOTimestamp parses an ISO 8601 timestamp string into a time.Time object.
17881832// Returns the parsed time or an error if parsing fails.
17891833// Example formats supported: "2023-01-15T14:30:00Z", "2023-01-15"
@@ -1869,3 +1913,19 @@ func AssignCodingAgentPrompt(t translations.TranslationHelperFunc) inventory.Ser
18691913 },
18701914 )
18711915}
1916+
1917+ // graphQLFeaturesKey is a context key for GraphQL feature flags
1918+ type graphQLFeaturesKey struct {}
1919+
1920+ // withGraphQLFeatures adds GraphQL feature flags to the context
1921+ func withGraphQLFeatures (ctx context.Context , features ... string ) context.Context {
1922+ return context .WithValue (ctx , graphQLFeaturesKey {}, features )
1923+ }
1924+
1925+ // GetGraphQLFeatures retrieves GraphQL feature flags from the context
1926+ func GetGraphQLFeatures (ctx context.Context ) []string {
1927+ if features , ok := ctx .Value (graphQLFeaturesKey {}).([]string ); ok {
1928+ return features
1929+ }
1930+ return nil
1931+ }
0 commit comments