192 lines
7.4 KiB
TypeScript
192 lines
7.4 KiB
TypeScript
import { getOrcaClient } from "@_koii/task-manager/extensions";
|
|
import { namespaceWrapper, TASK_ID } from "@_koii/namespace-wrapper";
|
|
import "dotenv/config";
|
|
import { status, middleServerUrl } from "../utils/constant";
|
|
import dotenv from "dotenv";
|
|
import { checkAnthropicAPIKey, isValidAnthropicApiKey } from "../utils/anthropicCheck";
|
|
import { checkGitHub } from "../utils/githubCheck";
|
|
import { LogLevel } from "@_koii/namespace-wrapper/dist/types";
|
|
import { actionMessage } from "../utils/constant";
|
|
import { errorMessage } from "../utils/constant";
|
|
import { v4 as uuidv4 } from "uuid";
|
|
dotenv.config();
|
|
|
|
export async function task(roundNumber: number): Promise<void> {
|
|
/**
|
|
* Run your task and store the proofs to be submitted for auditing
|
|
* It is expected you will store the proofs in your container
|
|
* The submission of the proofs is done in the submission function
|
|
*/
|
|
// FORCE TO PAUSE 30 SECONDS
|
|
// No submission on Round 0 so no need to trigger fetch audit result before round 3
|
|
// Changed from 3 to 4 to have more time
|
|
if (roundNumber >= 4) {
|
|
const triggerFetchAuditResult = await fetch(`${middleServerUrl}/summarizer/worker/update-audit-result`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ taskId: TASK_ID, round: roundNumber - 4 }),
|
|
});
|
|
console.log(
|
|
`[TASK] Trigger fetch audit result for round ${roundNumber - 3}. Result is ${triggerFetchAuditResult.status}.`,
|
|
);
|
|
}
|
|
console.log(`[TASK] EXECUTE TASK FOR ROUND ${roundNumber}`);
|
|
try {
|
|
const orcaClient = await getOrcaClient();
|
|
// check if the env variable is valid
|
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
await namespaceWrapper.logMessage(
|
|
LogLevel.Error,
|
|
errorMessage.ANTHROPIC_API_KEY_INVALID,
|
|
actionMessage.ANTHROPIC_API_KEY_INVALID,
|
|
);
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.ANTHROPIC_API_KEY_INVALID);
|
|
return;
|
|
}
|
|
if (!isValidAnthropicApiKey(process.env.ANTHROPIC_API_KEY!)) {
|
|
await namespaceWrapper.logMessage(
|
|
LogLevel.Error,
|
|
errorMessage.ANTHROPIC_API_KEY_INVALID,
|
|
actionMessage.ANTHROPIC_API_KEY_INVALID,
|
|
);
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.ANTHROPIC_API_KEY_INVALID);
|
|
return;
|
|
}
|
|
const isAnthropicAPIKeyValid = await checkAnthropicAPIKey(process.env.ANTHROPIC_API_KEY!);
|
|
if (!isAnthropicAPIKeyValid) {
|
|
await namespaceWrapper.logMessage(
|
|
LogLevel.Error,
|
|
errorMessage.ANTHROPIC_API_KEY_NO_CREDIT,
|
|
actionMessage.ANTHROPIC_API_KEY_NO_CREDIT,
|
|
);
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.ANTHROPIC_API_KEY_NO_CREDIT);
|
|
return;
|
|
}
|
|
if (!process.env.GITHUB_USERNAME || !process.env.GITHUB_TOKEN) {
|
|
await namespaceWrapper.logMessage(
|
|
LogLevel.Error,
|
|
errorMessage.GITHUB_CHECK_FAILED,
|
|
actionMessage.GITHUB_CHECK_FAILED,
|
|
);
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.GITHUB_CHECK_FAILED);
|
|
return;
|
|
}
|
|
const isGitHubValid = await checkGitHub(process.env.GITHUB_USERNAME!, process.env.GITHUB_TOKEN!);
|
|
if (!isGitHubValid) {
|
|
await namespaceWrapper.logMessage(
|
|
LogLevel.Error,
|
|
errorMessage.GITHUB_CHECK_FAILED,
|
|
actionMessage.GITHUB_CHECK_FAILED,
|
|
);
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.GITHUB_CHECK_FAILED);
|
|
return;
|
|
}
|
|
if (!orcaClient) {
|
|
await namespaceWrapper.logMessage(LogLevel.Error, errorMessage.NO_ORCA_CLIENT, actionMessage.NO_ORCA_CLIENT);
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.NO_ORCA_CLIENT);
|
|
return;
|
|
}
|
|
|
|
const stakingKeypair = await namespaceWrapper.getSubmitterAccount();
|
|
if (!stakingKeypair) {
|
|
throw new Error("No staking keypair found");
|
|
}
|
|
const stakingKey = stakingKeypair.publicKey.toBase58();
|
|
const pubKey = await namespaceWrapper.getMainAccountPubkey();
|
|
if (!pubKey) {
|
|
throw new Error("No public key found");
|
|
}
|
|
|
|
/****************** All these issues need to be generate a markdown file ******************/
|
|
|
|
const signature = await namespaceWrapper.payloadSigning(
|
|
{
|
|
taskId: TASK_ID,
|
|
roundNumber: roundNumber,
|
|
action: "fetch-todo",
|
|
githubUsername: stakingKey,
|
|
stakingKey: stakingKey,
|
|
},
|
|
stakingKeypair.secretKey,
|
|
);
|
|
|
|
// const initializedDocumentSummarizeIssues = await getInitializedDocumentSummarizeIssues(existingIssues);
|
|
|
|
console.log(`[TASK] Making Request to Middle Server with taskId: ${TASK_ID} and round: ${roundNumber}`);
|
|
|
|
let requiredWorkResponse: Response = new Response();
|
|
let retryCount = 0;
|
|
const maxRetries = 36; // 6 minutes with 10 second intervals
|
|
const retryDelay = 10000; // 10 seconds in milliseconds
|
|
|
|
while (retryCount < maxRetries) {
|
|
requiredWorkResponse = await fetch(`${middleServerUrl}/summarizer/worker/fetch-todo`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ signature: signature, stakingKey: stakingKey }),
|
|
});
|
|
|
|
if (requiredWorkResponse.status === 200) {
|
|
break;
|
|
}
|
|
|
|
console.log(`[TASK] Server returned status ${requiredWorkResponse.status}, retrying in ${retryDelay/1000} seconds... (Attempt ${retryCount + 1}/${maxRetries})`);
|
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
retryCount++;
|
|
}
|
|
|
|
// check if the response is 200 after all retries
|
|
if (requiredWorkResponse.status !== 200) {
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.NO_ISSUES_PENDING_TO_BE_SUMMARIZED);
|
|
return;
|
|
}
|
|
const requiredWorkResponseData = await requiredWorkResponse.json();
|
|
console.log("[TASK] requiredWorkResponseData: ", requiredWorkResponseData);
|
|
const uuid = uuidv4();
|
|
|
|
// await namespaceWrapper.storeSet(`work-info`, JSON.stringify({
|
|
// ...requiredWorkResponseData.data,
|
|
// round: roundNumber
|
|
// }));
|
|
await namespaceWrapper.storeSet(`uuid-${roundNumber}`, uuid);
|
|
|
|
const podcallPayload = {
|
|
taskId: TASK_ID,
|
|
roundNumber,
|
|
uuid,
|
|
};
|
|
|
|
const podCallSignature = await namespaceWrapper.payloadSigning(podcallPayload, stakingKeypair.secretKey);
|
|
|
|
const jsonBody = {
|
|
task_id: TASK_ID,
|
|
round_number: roundNumber,
|
|
repo_url: `https://github.com/${requiredWorkResponseData.data.repo_owner}/${requiredWorkResponseData.data.repo_name}`,
|
|
podcall_signature: podCallSignature,
|
|
};
|
|
console.log("[TASK] jsonBody: ", jsonBody);
|
|
try {
|
|
const repoSummaryResponse = await orcaClient.podCall(`worker-task/${roundNumber}`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(jsonBody),
|
|
});
|
|
console.log("[TASK] repoSummaryResponse: ", repoSummaryResponse);
|
|
if (repoSummaryResponse.status !== 200) {
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.ISSUE_SUMMARIZATION_FAILED);
|
|
}
|
|
} catch (error) {
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.ISSUE_SUMMARIZATION_FAILED);
|
|
console.error("[TASK] EXECUTE TASK ERROR:", error);
|
|
}
|
|
} catch (error) {
|
|
await namespaceWrapper.storeSet(`result-${roundNumber}`, status.UNKNOWN_ERROR);
|
|
console.error("[TASK] EXECUTE TASK ERROR:", error);
|
|
}
|
|
} |