PRIX / lib /src /bot.js
yamxxx1's picture
Upload 117 files
a2fe16e verified
Raw
History Blame
5.9 kB
"use strict";
// Node 20 includes native fetch support
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Bot = void 0;
// AI Client for Groq with Failover Support
// Fallback shims for Probot runtime
/* eslint-disable no-console */
const chatgpt_1 = require("chatgpt");
const p_retry_1 = __importDefault(require("p-retry"));
const options_1 = require("./options");
const limits_1 = require("./limits");
const logInfo = console.log;
const logWarning = console.warn;
const logError = console.error;
/* eslint-enable no-console */
const setFailed = (msg) => {
console.error(msg);
process.exit(1);
};
class Bot {
api = null;
options;
aiOptions;
currentModel;
fallbackModels;
constructor(options, aiOptions) {
this.options = options;
this.aiOptions = aiOptions;
this.currentModel = aiOptions.model;
// Setup fallback chain based on tier
if (options_1.Options.HEAVY_MODELS.includes(this.currentModel)) {
this.fallbackModels = [...options_1.Options.HEAVY_MODELS];
}
else {
this.fallbackModels = [...options_1.Options.LIGHT_MODELS];
}
// Remove current model from fallbacks to avoid immediate repeat
this.fallbackModels = this.fallbackModels.filter(m => m !== this.currentModel);
this.initClient();
}
initClient() {
const apiKey = process.env.GROQ_API_KEY || process.env.AI_API_KEY;
if (apiKey) {
const currentDate = new Date().toISOString().split('T')[0];
const limits = new limits_1.TokenLimits(this.currentModel);
const systemMessage = `${this.options.systemMessage}
Knowledge cutoff: ${limits.knowledgeCutOff}
Current date: ${currentDate}
IMPORTANT: Entire response must be in ISO code: ${this.options.language}
`;
this.api = new chatgpt_1.ChatGPTAPI({
apiBaseUrl: this.options.apiBaseUrl,
systemMessage,
apiKey,
apiOrg: process.env.AI_API_ORG || undefined,
debug: this.options.debug,
maxModelTokens: limits.maxTokens,
maxResponseTokens: limits.responseTokens,
completionParams: {
temperature: this.options.modelTemperature,
model: this.currentModel
}
});
logInfo(`Initialized AI client with model: ${this.currentModel}`);
}
else {
throw new Error("Missing 'GROQ_API_KEY' or 'AI_API_KEY'");
}
}
chat = async (message, ids) => {
let res = ['', {}];
try {
res = await this.chat_(message, ids);
return res;
}
catch (e) {
if (e instanceof chatgpt_1.ChatGPTError) {
logWarning(`AI communication error: ${e.message}`);
}
return res;
}
};
chat_ = async (message, ids) => {
const start = Date.now();
if (!message)
return ['', {}];
let response;
if (this.api != null) {
const opts = {
timeoutMs: this.options.timeoutMS
};
if (ids.parentMessageId) {
opts.parentMessageId = ids.parentMessageId;
}
try {
response = await (0, p_retry_1.default)(async (attemptState) => {
try {
const result = await this.api.sendMessage(message, opts);
return result;
}
catch (e) {
if (e?.status === 429 && this.fallbackModels.length > 0) {
const nextModel = this.fallbackModels.shift();
if (nextModel) {
logWarning(`Rate limit (429) hit for ${this.currentModel}. Switching to fallback: ${nextModel}`);
this.currentModel = nextModel;
this.initClient();
}
}
throw e;
}
}, {
retries: this.options.retries,
onFailedAttempt: (err) => {
logInfo(`Attempt ${err.attemptNumber} failed. ${err.retriesLeft} retries left.`);
const errorResponse = err.response || err.status;
if (errorResponse === 429 && this.fallbackModels.length > 0) {
const nextModel = this.fallbackModels.shift();
if (nextModel) {
logWarning(`Proactive switch to fallback model: ${nextModel} due to 429`);
this.currentModel = nextModel;
this.initClient();
}
}
}
});
}
catch (e) {
if (e instanceof chatgpt_1.ChatGPTError) {
logInfo(`AI Error: ${e.message} (Last model used: ${this.currentModel})`);
}
}
const end = Date.now();
logInfo(`AI response time: ${end - start} ms`);
}
else {
setFailed('AI client is not initialized');
}
let responseText = '';
if (response != null) {
responseText = response.text;
}
const newIds = {
parentMessageId: response?.id,
conversationId: response?.conversationId
};
return [responseText, newIds];
};
}
exports.Bot = Bot;
//# sourceMappingURL=bot.js.map