@@ -3,7 +3,7 @@ import { config } from '../index.mjs'
3
3
4
4
const getPatchUrl = async ( ) => {
5
5
const patchUrl = location . origin + location . pathname + '.patch'
6
- const response = await fetch ( patchUrl , { method : 'HEAD' } )
6
+ const response = await fetch ( patchUrl , { method : 'HEAD' } ) . catch ( ( ) => ( { } ) )
7
7
if ( response . ok ) return patchUrl
8
8
return ''
9
9
}
@@ -16,13 +16,118 @@ const getPatchData = async (patchUrl) => {
16
16
return patchData
17
17
}
18
18
19
+ const isPull = ( ) => {
20
+ return location . href . match ( / \/ p u l l \/ \d + $ / )
21
+ }
22
+
23
+ const isIssue = ( ) => {
24
+ return location . href . match ( / \/ i s s u e s \/ \d + $ / )
25
+ }
26
+
27
+ function parseGitHubIssueData ( ) {
28
+ // Function to parse a single comment
29
+ function parseComment ( commentElement ) {
30
+ // Parse the date
31
+ const dateElement = commentElement . querySelector ( 'relative-time' )
32
+ const date = dateElement . getAttribute ( 'datetime' )
33
+
34
+ // Parse the author
35
+ const authorElement =
36
+ commentElement . querySelector ( '.author' ) || commentElement . querySelector ( '.author-name' )
37
+ const author = authorElement . textContent . trim ( )
38
+
39
+ // Parse the body
40
+ const bodyElement = commentElement . querySelector ( '.comment-body' )
41
+ const body = bodyElement . textContent . trim ( )
42
+
43
+ return { date, author, body }
44
+ }
45
+
46
+ // Function to parse all messages on the page
47
+ function parseAllMessages ( ) {
48
+ // Find all comment containers
49
+ const commentElements = document . querySelectorAll ( '.timeline-comment-group' )
50
+ const messages = Array . from ( commentElements ) . map ( parseComment )
51
+
52
+ // The initial post is not a ".timeline-comment-group", so we need to handle it separately
53
+ const initialPostElement = document . querySelector ( '.js-comment-container' )
54
+ const initialPost = parseComment ( initialPostElement )
55
+
56
+ // Combine the initial post with the rest of the comments
57
+ return [ initialPost , ...messages ]
58
+ }
59
+
60
+ // Function to get the content of the comment input box
61
+ function getCommentInputContent ( ) {
62
+ const commentInput = document . querySelector ( '.js-new-comment-form textarea' )
63
+ return commentInput ? commentInput . value : ''
64
+ }
65
+
66
+ // Get the issue title
67
+ const title = document . querySelector ( '.js-issue-title' ) . textContent . trim ( )
68
+
69
+ // Get all messages
70
+ const messages = parseAllMessages ( )
71
+
72
+ // Get the content of the new comment box
73
+ const commentBoxContent = getCommentInputContent ( )
74
+
75
+ // Return an object with both results
76
+ return {
77
+ title : title ,
78
+ messages : messages ,
79
+ commentBoxContent : commentBoxContent ,
80
+ }
81
+ }
82
+
83
+ function createChatGPtSummaryPrompt ( issueData , isIssue = true ) {
84
+ // Destructure the issueData object into messages and commentBoxContent
85
+ const { title, messages, commentBoxContent } = issueData
86
+
87
+ // Start crafting the prompt
88
+ let prompt = ''
89
+
90
+ if ( isIssue ) {
91
+ prompt =
92
+ 'Please summarize the following GitHub issue thread.\nWhat is the main issue and key points discussed in this thread?\n\n'
93
+ } else {
94
+ prompt =
95
+ 'Please summarize the following GitHub pull request thread.\nWhat is the main issue this pull request is trying to solve?\n\n'
96
+ }
97
+
98
+ prompt += '---\n\n'
99
+
100
+ prompt += `Title:\n${ title } \n\n`
101
+
102
+ // Add each message to the prompt
103
+ messages . forEach ( ( message , index ) => {
104
+ prompt += `Message ${ index + 1 } by ${ message . author } on ${ message . date } :\n${ message . body } \n\n`
105
+ } )
106
+
107
+ // If there's content in the comment box, add it as a draft message
108
+ if ( commentBoxContent ) {
109
+ prompt += '---\n\n'
110
+ prompt += `Draft message in comment box:\n${ commentBoxContent } \n\n`
111
+ }
112
+
113
+ // Add a request for summary at the end of the prompt
114
+ // prompt += 'What is the main issue and key points discussed in this thread?'
115
+
116
+ return prompt
117
+ }
118
+
19
119
export default {
20
120
init : async ( hostname , userConfig , getInput , mountComponent ) => {
21
121
try {
22
122
let oldUrl = location . href
23
123
const checkUrlChange = async ( ) => {
24
124
if ( location . href !== oldUrl ) {
25
125
oldUrl = location . href
126
+ if ( isPull ( ) || isIssue ( ) ) {
127
+ mountComponent ( config . github , userConfig )
128
+ return
129
+ }
130
+
26
131
const patchUrl = await getPatchUrl ( )
27
132
if ( patchUrl ) {
28
133
mountComponent ( config . github , userConfig )
@@ -33,9 +138,16 @@ export default {
33
138
} catch ( e ) {
34
139
/* empty */
35
140
}
141
+ return ( await getPatchUrl ( ) ) || isPull ( ) || isIssue ( )
36
142
} ,
37
143
inputQuery : async ( ) => {
38
144
try {
145
+ if ( isPull ( ) || isIssue ( ) ) {
146
+ const issueData = parseGitHubIssueData ( )
147
+ const summaryPrompt = createChatGPtSummaryPrompt ( issueData , isIssue ( ) )
148
+
149
+ return await cropText ( summaryPrompt )
150
+ }
39
151
const patchUrl = await getPatchUrl ( )
40
152
const patchData = await getPatchData ( patchUrl )
41
153
if ( ! patchData ) return
0 commit comments