recallrai
Version:
Official Node.js SDK for RecallrAI - Revolutionary contextual memory system that enables AI assistants to form meaningful connections between conversations, just like human memory.
171 lines (170 loc) • 8.13 kB
JavaScript
"use strict";
/**
* Merge conflict management functionality for the RecallrAI SDK.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.MergeConflict = void 0;
const models_1 = require("./models");
const errors_1 = require("./errors");
/**
* Represents a merge conflict in the RecallrAI system.
*
* This class provides methods for inspecting and resolving merge conflicts
* that occur when new memories conflict with existing ones.
*/
class MergeConflict {
/**
* Initialize a merge conflict.
*
* @param httpClient - HTTP client for API communication.
* @param userId - User ID who owns this conflict.
* @param conflictData - Merge conflict data model.
*/
constructor(httpClient, userId, conflictData) {
this.http = httpClient;
this.userId = userId;
this.conflictData = conflictData;
this.conflictId = conflictData.id;
this.status = conflictData.status;
this.proposedMemoryContent = conflictData.proposedMemoryContent;
this.newMemories = conflictData.newMemories;
this.conflictingMemories = conflictData.conflictingMemories;
this.clarifyingQuestions = conflictData.clarifyingQuestions;
this.createdAt = conflictData.createdAt;
this.resolvedAt = conflictData.resolvedAt;
this.resolutionData = conflictData.resolutionData;
}
/**
* Resolve this merge conflict by providing answers to clarifying questions.
*
* @param answers - List of answers to the clarifying questions.
* @throws {UserNotFoundError} If the user is not found.
* @throws {MergeConflictNotFoundError} If the merge conflict is not found.
* @throws {MergeConflictAlreadyResolvedError} If the conflict is already resolved.
* @throws {MergeConflictInvalidQuestionsError} If the provided questions don't match the original questions.
* @throws {MergeConflictMissingAnswersError} If not all required questions have been answered.
* @throws {MergeConflictInvalidAnswerError} If an answer is not a valid option for its question.
* @throws {ValidationError} If the answers are invalid.
* @throws {AuthenticationError} If the API key or project ID is invalid.
* @throws {InternalServerError} If the server encounters an error.
* @throws {NetworkError} If there are network issues.
* @throws {TimeoutError} If the request times out.
* @throws {RecallrAIError} For other API-related errors.
*/
async resolve(answers) {
if (this.status === models_1.MergeConflictStatus.RESOLVED || this.status === models_1.MergeConflictStatus.FAILED) {
throw new errors_1.MergeConflictAlreadyResolvedError(`Merge conflict ${this.conflictId} is already resolved`, 400);
}
const answerData = {
answers: {
question_answers: answers.map((answer) => ({
question: answer.question,
answer: answer.answer,
message: answer.message,
})),
},
};
const response = await this.http.post(`/api/v1/users/${this.userId}/merge-conflicts/${this.conflictId}/resolve`, answerData);
if (response.status === 404) {
const detail = response.data?.detail || "";
if (detail.includes(`User ${this.userId} not found`)) {
throw new errors_1.UserNotFoundError(detail, response.status);
}
else {
throw new errors_1.MergeConflictNotFoundError(detail, response.status);
}
}
else if (response.status === 400) {
const detail = response.data?.detail || "";
if (detail.includes("already resolved")) {
throw new errors_1.MergeConflictAlreadyResolvedError(detail, response.status);
}
else if (detail.includes("Invalid questions provided")) {
throw new errors_1.MergeConflictInvalidQuestionsError(detail, response.status);
}
else if (detail.includes("Missing answers for the following questions")) {
throw new errors_1.MergeConflictMissingAnswersError(detail, response.status);
}
else if (detail.includes("Invalid answer") && detail.includes("for question")) {
throw new errors_1.MergeConflictInvalidAnswerError(detail, response.status);
}
else {
throw new errors_1.RecallrAIError(detail, response.status);
}
}
else if (response.status !== 200) {
throw new errors_1.RecallrAIError(response.data?.detail || "Unknown error", response.status);
}
const updatedData = this.parseMergeConflictResponse(response.data);
this.conflictData = updatedData;
this.status = updatedData.status;
this.resolvedAt = updatedData.resolvedAt;
this.resolutionData = updatedData.resolutionData;
}
/**
* Refresh this merge conflict's data from the API.
*
* @throws {UserNotFoundError} If the user is not found.
* @throws {MergeConflictNotFoundError} If the merge conflict is not found.
* @throws {AuthenticationError} If the API key or project ID is invalid.
* @throws {InternalServerError} If the server encounters an error.
* @throws {NetworkError} If there are network issues.
* @throws {TimeoutError} If the request times out.
* @throws {RecallrAIError} For other API-related errors.
*/
async refresh() {
const response = await this.http.get(`/api/v1/users/${this.userId}/merge-conflicts/${this.conflictId}`);
if (response.status === 404) {
const detail = response.data?.detail || "";
if (detail.includes(`User ${this.userId} not found`)) {
throw new errors_1.UserNotFoundError(detail, response.status);
}
else {
throw new errors_1.MergeConflictNotFoundError(detail, response.status);
}
}
else if (response.status !== 200) {
throw new errors_1.RecallrAIError(response.data?.detail || "Unknown error", response.status);
}
const updatedData = this.parseMergeConflictResponse(response.data);
this.conflictData = updatedData;
this.status = updatedData.status;
this.resolvedAt = updatedData.resolvedAt;
this.resolutionData = updatedData.resolutionData;
}
parseMergeConflictResponse(data) {
const conflictData = data.conflict || data;
return {
id: conflictData.id,
projectUserSessionId: conflictData.project_user_session_id,
proposedMemoryContent: conflictData.proposed_memory_content,
newMemories: conflictData.new_memories?.map((mem) => ({
memoryId: mem.memory_id,
content: mem.content,
eventDateStart: new Date(mem.event_date_start),
eventDateEnd: new Date(mem.event_date_end),
createdAt: new Date(mem.created_at),
})),
conflictingMemories: conflictData.conflicting_memories.map((mem) => ({
memoryId: mem.memory_id,
content: mem.content,
reason: mem.reason,
eventDateStart: new Date(mem.event_date_start),
eventDateEnd: new Date(mem.event_date_end),
createdAt: new Date(mem.created_at),
})),
clarifyingQuestions: conflictData.clarifying_questions.map((q) => ({
question: q.question,
options: q.options,
})),
status: conflictData.status,
resolutionData: conflictData.resolution_data,
createdAt: new Date(conflictData.created_at),
resolvedAt: conflictData.resolved_at ? new Date(conflictData.resolved_at) : undefined,
};
}
toString() {
return `MergeConflict(id='${this.conflictId}', status='${this.status}', user_id='${this.userId}')`;
}
}
exports.MergeConflict = MergeConflict;