|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
15 |
| -from typing import Any |
16 |
| - |
17 | 15 | from adk_answering_agent.settings import BOT_RESPONSE_LABEL
|
18 | 16 | from adk_answering_agent.settings import IS_INTERACTIVE
|
19 | 17 | from adk_answering_agent.settings import OWNER
|
20 | 18 | from adk_answering_agent.settings import REPO
|
21 | 19 | from adk_answering_agent.settings import VERTEXAI_DATASTORE_ID
|
22 |
| -from adk_answering_agent.utils import error_response |
23 |
| -from adk_answering_agent.utils import run_graphql_query |
| 20 | +from adk_answering_agent.tools import add_comment_to_discussion |
| 21 | +from adk_answering_agent.tools import add_label_to_discussion |
| 22 | +from adk_answering_agent.tools import convert_gcs_links_to_https |
| 23 | +from adk_answering_agent.tools import get_discussion_and_comments |
24 | 24 | from google.adk.agents.llm_agent import Agent
|
25 | 25 | from google.adk.tools.vertex_ai_search_tool import VertexAiSearchTool
|
26 |
| -import requests |
27 | 26 |
|
28 | 27 | if IS_INTERACTIVE:
|
29 | 28 | APPROVAL_INSTRUCTION = (
|
|
35 | 34 | " comment."
|
36 | 35 | )
|
37 | 36 |
|
38 |
| - |
39 |
| -def get_discussion_and_comments(discussion_number: int) -> dict[str, Any]: |
40 |
| - """Fetches a discussion and its comments using the GitHub GraphQL API. |
41 |
| -
|
42 |
| - Args: |
43 |
| - discussion_number: The number of the GitHub discussion. |
44 |
| -
|
45 |
| - Returns: |
46 |
| - A dictionary with the request status and the discussion details. |
47 |
| - """ |
48 |
| - print(f"Attempting to get discussion #{discussion_number} and its comments") |
49 |
| - query = """ |
50 |
| - query($owner: String!, $repo: String!, $discussionNumber: Int!) { |
51 |
| - repository(owner: $owner, name: $repo) { |
52 |
| - discussion(number: $discussionNumber) { |
53 |
| - id |
54 |
| - title |
55 |
| - body |
56 |
| - createdAt |
57 |
| - closed |
58 |
| - author { |
59 |
| - login |
60 |
| - } |
61 |
| - # For each discussion, fetch the latest 20 labels. |
62 |
| - labels(last: 20) { |
63 |
| - nodes { |
64 |
| - id |
65 |
| - name |
66 |
| - } |
67 |
| - } |
68 |
| - # For each discussion, fetch the latest 100 comments. |
69 |
| - comments(last: 100) { |
70 |
| - nodes { |
71 |
| - id |
72 |
| - body |
73 |
| - createdAt |
74 |
| - author { |
75 |
| - login |
76 |
| - } |
77 |
| - # For each discussion, fetch the latest 50 replies |
78 |
| - replies(last: 50) { |
79 |
| - nodes { |
80 |
| - id |
81 |
| - body |
82 |
| - createdAt |
83 |
| - author { |
84 |
| - login |
85 |
| - } |
86 |
| - } |
87 |
| - } |
88 |
| - } |
89 |
| - } |
90 |
| - } |
91 |
| - } |
92 |
| - } |
93 |
| - """ |
94 |
| - variables = { |
95 |
| - "owner": OWNER, |
96 |
| - "repo": REPO, |
97 |
| - "discussionNumber": discussion_number, |
98 |
| - } |
99 |
| - try: |
100 |
| - response = run_graphql_query(query, variables) |
101 |
| - if "errors" in response: |
102 |
| - return error_response(str(response["errors"])) |
103 |
| - discussion_data = ( |
104 |
| - response.get("data", {}).get("repository", {}).get("discussion") |
105 |
| - ) |
106 |
| - if not discussion_data: |
107 |
| - return error_response(f"Discussion #{discussion_number} not found.") |
108 |
| - return {"status": "success", "discussion": discussion_data} |
109 |
| - except requests.exceptions.RequestException as e: |
110 |
| - return error_response(str(e)) |
111 |
| - |
112 |
| - |
113 |
| -def add_comment_to_discussion( |
114 |
| - discussion_id: str, comment_body: str |
115 |
| -) -> dict[str, Any]: |
116 |
| - """Adds a comment to a specific discussion. |
117 |
| -
|
118 |
| - Args: |
119 |
| - discussion_id: The GraphQL node ID of the discussion. |
120 |
| - comment_body: The content of the comment in Markdown. |
121 |
| -
|
122 |
| - Returns: |
123 |
| - The status of the request and the new comment's details. |
124 |
| - """ |
125 |
| - print(f"Adding comment to discussion {discussion_id}") |
126 |
| - query = """ |
127 |
| - mutation($discussionId: ID!, $body: String!) { |
128 |
| - addDiscussionComment(input: {discussionId: $discussionId, body: $body}) { |
129 |
| - comment { |
130 |
| - id |
131 |
| - body |
132 |
| - createdAt |
133 |
| - author { |
134 |
| - login |
135 |
| - } |
136 |
| - } |
137 |
| - } |
138 |
| - } |
139 |
| - """ |
140 |
| - variables = {"discussionId": discussion_id, "body": comment_body} |
141 |
| - try: |
142 |
| - response = run_graphql_query(query, variables) |
143 |
| - if "errors" in response: |
144 |
| - return error_response(str(response["errors"])) |
145 |
| - new_comment = ( |
146 |
| - response.get("data", {}).get("addDiscussionComment", {}).get("comment") |
147 |
| - ) |
148 |
| - return {"status": "success", "comment": new_comment} |
149 |
| - except requests.exceptions.RequestException as e: |
150 |
| - return error_response(str(e)) |
151 |
| - |
152 |
| - |
153 |
| -def get_label_id(label_name: str) -> str | None: |
154 |
| - """Helper function to find the GraphQL node ID for a given label name.""" |
155 |
| - print(f"Finding ID for label '{label_name}'...") |
156 |
| - query = """ |
157 |
| - query($owner: String!, $repo: String!, $labelName: String!) { |
158 |
| - repository(owner: $owner, name: $repo) { |
159 |
| - label(name: $labelName) { |
160 |
| - id |
161 |
| - } |
162 |
| - } |
163 |
| - } |
164 |
| - """ |
165 |
| - variables = {"owner": OWNER, "repo": REPO, "labelName": label_name} |
166 |
| - |
167 |
| - try: |
168 |
| - response = run_graphql_query(query, variables) |
169 |
| - if "errors" in response: |
170 |
| - print( |
171 |
| - f"[Warning] Error from GitHub API response for label '{label_name}':" |
172 |
| - f" {response['errors']}" |
173 |
| - ) |
174 |
| - return None |
175 |
| - label_info = response["data"].get("repository", {}).get("label") |
176 |
| - if label_info: |
177 |
| - return label_info.get("id") |
178 |
| - print(f"[Warning] Label information for '{label_name}' not found.") |
179 |
| - return None |
180 |
| - except requests.exceptions.RequestException as e: |
181 |
| - print(f"[Warning] Error from GitHub API: {e}") |
182 |
| - return None |
183 |
| - |
184 |
| - |
185 |
| -def add_label_to_discussion( |
186 |
| - discussion_id: str, label_name: str |
187 |
| -) -> dict[str, Any]: |
188 |
| - """Adds a label to a specific discussion. |
189 |
| -
|
190 |
| - Args: |
191 |
| - discussion_id: The GraphQL node ID of the discussion. |
192 |
| - label_name: The name of the label to add (e.g., "bug"). |
193 |
| -
|
194 |
| - Returns: |
195 |
| - The status of the request and the label details. |
196 |
| - """ |
197 |
| - print( |
198 |
| - f"Attempting to add label '{label_name}' to discussion {discussion_id}..." |
199 |
| - ) |
200 |
| - # First, get the GraphQL ID of the label by its name |
201 |
| - label_id = get_label_id(label_name) |
202 |
| - if not label_id: |
203 |
| - return error_response(f"Label '{label_name}' not found.") |
204 |
| - |
205 |
| - # Then, perform the mutation to add the label to the discussion |
206 |
| - mutation = """ |
207 |
| - mutation AddLabel($discussionId: ID!, $labelId: ID!) { |
208 |
| - addLabelsToLabelable(input: {labelableId: $discussionId, labelIds: [$labelId]}) { |
209 |
| - clientMutationId |
210 |
| - } |
211 |
| - } |
212 |
| - """ |
213 |
| - variables = {"discussionId": discussion_id, "labelId": label_id} |
214 |
| - try: |
215 |
| - response = run_graphql_query(mutation, variables) |
216 |
| - if "errors" in response: |
217 |
| - return error_response(str(response["errors"])) |
218 |
| - return {"status": "success", "label_id": label_id, "label_name": label_name} |
219 |
| - except requests.exceptions.RequestException as e: |
220 |
| - return error_response(str(e)) |
221 |
| - |
222 |
| - |
223 | 37 | root_agent = Agent(
|
224 | 38 | model="gemini-2.5-pro",
|
225 | 39 | name="adk_answering_agent",
|
@@ -249,28 +63,20 @@ def add_label_to_discussion(
|
249 | 63 | information that is not in the document store. Do not invent citations which are not in the document store.
|
250 | 64 | * **Be Objective**: your answer should be based on the facts you found in the document store, do not be misled by user's assumptions or user's understanding of ADK.
|
251 | 65 | * If you can't find the answer or information in the document store, **do not** respond.
|
252 |
| - * Include a bolded note (e.g. "Response from ADK Answering Agent") in your comment |
253 |
| - to indicate this comment was added by an ADK Answering Agent. |
254 |
| - * Have an empty line between the note and the rest of your response. |
255 | 66 | * Inlclude a short summary of your response in the comment as a TLDR, e.g. "**TLDR**: <your summary>".
|
256 | 67 | * Have a divider line between the TLDR and your detail response.
|
257 | 68 | * Do not respond to any other discussion except the one specified by the user.
|
258 | 69 | * Please include your justification for your decision in your output
|
259 | 70 | to the user who is telling with you.
|
260 | 71 | * If you uses citation from the document store, please provide a footnote
|
261 |
| - referencing the source document format it as: "[1] URL of the document". |
262 |
| - * Replace the "gs://prefix/" part, e.g. "gs://adk-qa-bucket/", to be "https://github.com/google/" |
263 |
| - * Add "blob/main/" after the repo name, e.g. "adk-python", "adk-docs", for example: |
264 |
| - * If the original URL is "gs://adk-qa-bucket/adk-python/src/google/adk/version.py", |
265 |
| - then the citation URL is "https://github.com/google/adk-python/blob/main/src/google/adk/version.py", |
266 |
| - * If the original URL is "gs://adk-qa-bucket/adk-docs/docs/index.md", |
267 |
| - then the citation URL is "https://github.com/google/adk-docs/blob/main/docs/index.md" |
268 |
| - * If the file is a html file, replace the ".html" to be ".md" |
| 72 | + referencing the source document format it as: "[1] publicly accessible HTTPS URL of the document". |
| 73 | + * You can use the `convert_gcs_links_to_https` tool to convert GCS links to HTTPS links. |
269 | 74 | """,
|
270 | 75 | tools=[
|
271 | 76 | VertexAiSearchTool(data_store_id=VERTEXAI_DATASTORE_ID),
|
272 | 77 | get_discussion_and_comments,
|
273 | 78 | add_comment_to_discussion,
|
274 | 79 | add_label_to_discussion,
|
| 80 | + convert_gcs_links_to_https, |
275 | 81 | ],
|
276 | 82 | )
|
0 commit comments