feat(PM-4199): Call tc-ai-api when a challenge is updated#82
feat(PM-4199): Call tc-ai-api when a challenge is updated#82hentrymartin wants to merge 18 commits intodevelopfrom
Conversation
| MEMBERS_API_URL: process.env.MEMBERS_API_URL || "https://api.topcoder-dev.com/v6/members", | ||
| REVIEW_SUMMATIONS_API_URL: process.env.REVIEW_SUMMATIONS_API_URL || "https://api.topcoder-dev.com/v6/reviewSummations", | ||
| REVIEWS_API_URL: process.env.REVIEWS_API_URL || "https://api.topcoder-dev.com", | ||
| TC_AI_API_URL: process.env.TC_AI_API_URL || "https://api.topcoder-dev.com", |
There was a problem hiding this comment.
[correctness]
The default URL for TC_AI_API_URL is set to https://api.topcoder-dev.com, which is the same as the default for REVIEWS_API_URL. Ensure this is intentional and that the correct endpoint is being used for the AI API.
| * @returns {Promise<void>} | ||
| */ | ||
| async triggerChallengeContextWorkflow(challengeId) { | ||
| if (!challengeId) return; |
There was a problem hiding this comment.
[correctness]
The triggerChallengeContextWorkflow function does not handle the case where getM2MToken fails to retrieve a token. Consider adding error handling for this scenario to ensure the function behaves predictably if the token retrieval fails.
| headers.Authorization = `Bearer ${token}`; | ||
|
|
||
| const createRunRes = await axios.post(createRunUrl, {}, { headers, timeout }); | ||
| const data = createRunRes.data || {}; |
There was a problem hiding this comment.
[correctness]
The createRunRes.data object is accessed without checking if createRunRes is defined or if the request was successful. Consider checking the response status or ensuring createRunRes is defined before accessing its properties to prevent potential runtime errors.
| { headers, timeout } | ||
| ); | ||
| } catch (err) { | ||
| logger.error( |
There was a problem hiding this comment.
[💡 readability]
The error logging in the catch block uses _.get(err, "message", err), which may not provide useful information if err is not an object. Consider using err.toString() or JSON.stringify(err) for more informative logging.
There was a problem hiding this comment.
Pull request overview
Adds an integration to trigger the tc-ai-api “challenge-context” workflow when a challenge with AI review configuration is updated/activated, so AI context can be generated and persisted for review.
Changes:
- Invoke an AI challenge-context workflow trigger during
updateChallengewhen AI reviewers are configured and the challenge is activated or not in DRAFT. - Add helper utilities to detect AI review configuration and call tc-ai-api (
create-runthenstart) using M2M auth. - Introduce
TC_AI_API_URLconfiguration (plus dev env documentation) and add a CircleCI context entry.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/services/ChallengeService.js |
Triggers AI workflow during challenge updates based on status + AI reviewers. |
src/common/challenge-helper.js |
Adds AI-review detection helper and tc-ai-api workflow trigger implementation. |
docs/dev.env |
Documents optional TC_AI_API_URL override for local/dev. |
config/default.js |
Adds TC_AI_API_URL config wiring. |
.circleci/config.yml |
Adds a CircleCI context entry for PM-4199. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| // Trigger AI challenge-context workflow when challenge has AI Review Config and either | ||
| // is being activated (PATCH/PUT with status ACTIVE) or is updated while not in DRAFT. | ||
| if (challengeHelper.hasAIReviewConfig(updatedChallenge)) { | ||
| if (isStatusChangingToActive || challenge.status !== ChallengeStatusEnum.DRAFT) { | ||
| await challengeHelper | ||
| .triggerChallengeContextWorkflow(challengeId) | ||
| .catch((err) => | ||
| logger.error( | ||
| `AI challenge-context trigger failed for challenge ${challengeId}: ${err.message}` | ||
| ) | ||
| ); | ||
| } |
| await challengeHelper | ||
| .triggerChallengeContextWorkflow(challengeId) | ||
| .catch((err) => | ||
| logger.error( | ||
| `AI challenge-context trigger failed for challenge ${challengeId}: ${err.message}` | ||
| ) | ||
| ); |
| // Trigger AI challenge-context workflow when challenge has AI Review Config and either | ||
| // is being activated (PATCH/PUT with status ACTIVE) or is updated while not in DRAFT. | ||
| if (challengeHelper.hasAIReviewConfig(updatedChallenge)) { | ||
| if (isStatusChangingToActive || challenge.status !== ChallengeStatusEnum.DRAFT) { | ||
| await challengeHelper | ||
| .triggerChallengeContextWorkflow(challengeId) | ||
| .catch((err) => |
| /** | ||
| * Triggers the TC AI API challenge-context workflow for the given challenge (fire-and-forget). | ||
| * Creates a run via create-run, then starts it with the returned runId so the server finds the run. | ||
| * @param {string} challengeId challenge UUID | ||
| * @returns {Promise<void>} | ||
| */ | ||
| async triggerChallengeContextWorkflow(challengeId) { | ||
| if (!challengeId) return; | ||
| const baseUrl = _.trimEnd(config.TC_AI_API_URL || "https://api.topcoder-dev.com", "/"); | ||
| const workflowPath = "/v6/ai/workflows/challenge-context"; | ||
| const createRunUrl = `${baseUrl}${workflowPath}/create-run`; | ||
| const startUrl = `${baseUrl}${workflowPath}/start`; | ||
| const headers = { "Content-Type": "application/json" }; | ||
| const timeout = 10000; | ||
|
|
What's in this PR?
Ticket link - https://topcoder.atlassian.net/browse/PM-4199