Skip to content

feat(PM-4199): Call tc-ai-api when a challenge is updated#82

Open
hentrymartin wants to merge 18 commits intodevelopfrom
pm-4199
Open

feat(PM-4199): Call tc-ai-api when a challenge is updated#82
hentrymartin wants to merge 18 commits intodevelopfrom
pm-4199

Conversation

@hentrymartin
Copy link
Collaborator

What's in this PR?

  • Call tc-ai-api when a challenge is updated so that the challenge context is generated and persisted in review schema.

Ticket link - https://topcoder.atlassian.net/browse/PM-4199

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",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ 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;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ 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 || {};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[⚠️ 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(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[💡 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.

@kkartunov kkartunov requested a review from Copilot March 19, 2026 08:19
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 updateChallenge when 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-run then start) using M2M auth.
  • Introduce TC_AI_API_URL configuration (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.

Comment on lines +3107 to +3118
// 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}`
)
);
}
Comment on lines +3111 to +3117
await challengeHelper
.triggerChallengeContextWorkflow(challengeId)
.catch((err) =>
logger.error(
`AI challenge-context trigger failed for challenge ${challengeId}: ${err.message}`
)
);
Comment on lines +3107 to +3113
// 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) =>
Comment on lines +528 to +542
/**
* 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;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants