Skip to content

Commit dc7e789

Browse files
authored
Optimize context usage for getting an issue using the issue_read tool (#2022)
* minimize context usage using minimal types for get issue comments * preserver reactions field * add back author association
1 parent f04c137 commit dc7e789

File tree

3 files changed

+112
-12
lines changed

3 files changed

+112
-12
lines changed

pkg/github/issues.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -376,12 +376,9 @@ func GetIssue(ctx context.Context, client *github.Client, deps ToolDependencies,
376376
}
377377
}
378378

379-
r, err := json.Marshal(issue)
380-
if err != nil {
381-
return nil, fmt.Errorf("failed to marshal issue: %w", err)
382-
}
379+
minimalIssue := convertToMinimalIssue(issue)
383380

384-
return utils.NewToolResultText(string(r)), nil
381+
return MarshalledTextResult(minimalIssue), nil
385382
}
386383

387384
func GetIssueComments(ctx context.Context, client *github.Client, deps ToolDependencies, owner string, repo string, issueNumber int, pagination PaginationParams) (*mcp.CallToolResult, error) {

pkg/github/issues_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -345,15 +345,15 @@ func Test_GetIssue(t *testing.T) {
345345

346346
textContent := getTextResult(t, result)
347347

348-
var returnedIssue github.Issue
348+
var returnedIssue MinimalIssue
349349
err = json.Unmarshal([]byte(textContent.Text), &returnedIssue)
350350
require.NoError(t, err)
351-
assert.Equal(t, *tc.expectedIssue.Number, *returnedIssue.Number)
352-
assert.Equal(t, *tc.expectedIssue.Title, *returnedIssue.Title)
353-
assert.Equal(t, *tc.expectedIssue.Body, *returnedIssue.Body)
354-
assert.Equal(t, *tc.expectedIssue.State, *returnedIssue.State)
355-
assert.Equal(t, *tc.expectedIssue.HTMLURL, *returnedIssue.HTMLURL)
356-
assert.Equal(t, *tc.expectedIssue.User.Login, *returnedIssue.User.Login)
351+
assert.Equal(t, tc.expectedIssue.GetNumber(), returnedIssue.Number)
352+
assert.Equal(t, tc.expectedIssue.GetTitle(), returnedIssue.Title)
353+
assert.Equal(t, tc.expectedIssue.GetBody(), returnedIssue.Body)
354+
assert.Equal(t, tc.expectedIssue.GetState(), returnedIssue.State)
355+
assert.Equal(t, tc.expectedIssue.GetHTMLURL(), returnedIssue.HTMLURL)
356+
assert.Equal(t, tc.expectedIssue.GetUser().GetLogin(), returnedIssue.User.Login)
357357
})
358358
}
359359
}

pkg/github/minimal_types.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,43 @@ type MinimalProject struct {
136136
OwnerType string `json:"owner_type,omitempty"`
137137
}
138138

139+
// MinimalReactions is the trimmed output type for reaction summaries, dropping the API URL.
140+
type MinimalReactions struct {
141+
TotalCount int `json:"total_count"`
142+
PlusOne int `json:"+1"`
143+
MinusOne int `json:"-1"`
144+
Laugh int `json:"laugh"`
145+
Confused int `json:"confused"`
146+
Heart int `json:"heart"`
147+
Hooray int `json:"hooray"`
148+
Rocket int `json:"rocket"`
149+
Eyes int `json:"eyes"`
150+
}
151+
152+
// MinimalIssue is the trimmed output type for issue objects to reduce verbosity.
153+
type MinimalIssue struct {
154+
Number int `json:"number"`
155+
Title string `json:"title"`
156+
Body string `json:"body,omitempty"`
157+
State string `json:"state"`
158+
StateReason string `json:"state_reason,omitempty"`
159+
Draft bool `json:"draft,omitempty"`
160+
Locked bool `json:"locked,omitempty"`
161+
HTMLURL string `json:"html_url"`
162+
User *MinimalUser `json:"user,omitempty"`
163+
AuthorAssociation string `json:"author_association,omitempty"`
164+
Labels []string `json:"labels,omitempty"`
165+
Assignees []string `json:"assignees,omitempty"`
166+
Milestone string `json:"milestone,omitempty"`
167+
Comments int `json:"comments,omitempty"`
168+
Reactions *MinimalReactions `json:"reactions,omitempty"`
169+
CreatedAt string `json:"created_at,omitempty"`
170+
UpdatedAt string `json:"updated_at,omitempty"`
171+
ClosedAt string `json:"closed_at,omitempty"`
172+
ClosedBy string `json:"closed_by,omitempty"`
173+
IssueType string `json:"issue_type,omitempty"`
174+
}
175+
139176
// MinimalPullRequest is the trimmed output type for pull request objects to reduce verbosity.
140177
type MinimalPullRequest struct {
141178
Number int `json:"number"`
@@ -180,6 +217,72 @@ type MinimalPRBranchRepo struct {
180217

181218
// Helper functions
182219

220+
func convertToMinimalIssue(issue *github.Issue) MinimalIssue {
221+
m := MinimalIssue{
222+
Number: issue.GetNumber(),
223+
Title: issue.GetTitle(),
224+
Body: issue.GetBody(),
225+
State: issue.GetState(),
226+
StateReason: issue.GetStateReason(),
227+
Draft: issue.GetDraft(),
228+
Locked: issue.GetLocked(),
229+
HTMLURL: issue.GetHTMLURL(),
230+
User: convertToMinimalUser(issue.GetUser()),
231+
AuthorAssociation: issue.GetAuthorAssociation(),
232+
Comments: issue.GetComments(),
233+
}
234+
235+
if issue.CreatedAt != nil {
236+
m.CreatedAt = issue.CreatedAt.Format(time.RFC3339)
237+
}
238+
if issue.UpdatedAt != nil {
239+
m.UpdatedAt = issue.UpdatedAt.Format(time.RFC3339)
240+
}
241+
if issue.ClosedAt != nil {
242+
m.ClosedAt = issue.ClosedAt.Format(time.RFC3339)
243+
}
244+
245+
for _, label := range issue.Labels {
246+
if label != nil {
247+
m.Labels = append(m.Labels, label.GetName())
248+
}
249+
}
250+
251+
for _, assignee := range issue.Assignees {
252+
if assignee != nil {
253+
m.Assignees = append(m.Assignees, assignee.GetLogin())
254+
}
255+
}
256+
257+
if closedBy := issue.GetClosedBy(); closedBy != nil {
258+
m.ClosedBy = closedBy.GetLogin()
259+
}
260+
261+
if milestone := issue.GetMilestone(); milestone != nil {
262+
m.Milestone = milestone.GetTitle()
263+
}
264+
265+
if issueType := issue.GetType(); issueType != nil {
266+
m.IssueType = issueType.GetName()
267+
}
268+
269+
if r := issue.Reactions; r != nil {
270+
m.Reactions = &MinimalReactions{
271+
TotalCount: r.GetTotalCount(),
272+
PlusOne: r.GetPlusOne(),
273+
MinusOne: r.GetMinusOne(),
274+
Laugh: r.GetLaugh(),
275+
Confused: r.GetConfused(),
276+
Heart: r.GetHeart(),
277+
Hooray: r.GetHooray(),
278+
Rocket: r.GetRocket(),
279+
Eyes: r.GetEyes(),
280+
}
281+
}
282+
283+
return m
284+
}
285+
183286
func convertToMinimalPullRequest(pr *github.PullRequest) MinimalPullRequest {
184287
m := MinimalPullRequest{
185288
Number: pr.GetNumber(),

0 commit comments

Comments
 (0)