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.
151 lines (150 loc) • 6.59 kB
JavaScript
;
/**
* Main client class for the RecallrAI SDK.
*
* This module provides the RecallrAI class, which is the primary interface for the SDK.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.RecallrAI = void 0;
const utils_1 = require("./utils");
const models_1 = require("./models");
const user_1 = require("./user");
const errors_1 = require("./errors");
/**
* Main client for interacting with the RecallrAI API.
*
* This class provides methods for creating and managing users, sessions, and memories.
*/
class RecallrAI {
/**
* Initialize the RecallrAI client.
*
* @param apiKey - Your RecallrAI API key. Must start with `rai_`.
* @param projectId - Your project ID.
* @param baseUrl - The base URL for the RecallrAI API. Defaults to `https://api.recallrai.com`.
* @param timeout - Request timeout in seconds. Defaults to `30`.
*/
constructor({ apiKey, projectId, baseUrl = "https://api.recallrai.com", timeout = 30, }) {
if (!apiKey.startsWith("rai_")) {
throw new Error("API key must start with 'rai_'");
}
this.http = new utils_1.HTTPClient(apiKey, projectId, baseUrl, timeout);
}
/**
* Create a new user.
*
* @param userId - Unique identifier for the user.
* @param metadata - Optional metadata to associate with the user.
* @param mergeConflictEnabled - Per-user merge conflict override.
* `true` = always raise merge conflicts for this user.
* `false` = never raise merge conflicts for this user.
* `undefined` (default) = inherit the project-level setting.
* @returns The created user object.
* @throws {UserAlreadyExistsError} If a user with the same ID already exists.
* @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 createUser(userId, metadata, mergeConflictEnabled) {
const payload = {
custom_user_id: userId,
metadata: metadata,
};
if (mergeConflictEnabled !== undefined) {
payload.merge_conflict_enabled = mergeConflictEnabled;
}
const response = await this.http.post("/api/v1/users", payload);
if (response.status === 409) {
const detail = response.data?.detail || `User with ID ${userId} already exists`;
throw new errors_1.UserAlreadyExistsError(detail, response.status);
}
else if (response.status !== 201) {
const detail = response.data?.detail || "Failed to create user";
throw new errors_1.RecallrAIError(detail, response.status);
}
const userData = this.parseUserResponse(response.data);
return new user_1.User(this.http, userData);
}
/**
* Get a user by ID.
*
* @param userId - Unique identifier of the user.
* @param options - Optional behavior flags.
* @param options.validate - Whether to validate user existence via API before creating the instance.
* Defaults to true. Set to false when userId is trusted.
* @returns A User object representing the user.
* @throws {UserNotFoundError} If the user 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 getUser(userId, { validate = true } = {}) {
if (!validate) {
return new user_1.User(this.http, {
userId,
metadata: models_1.UNAVAILABLE,
mergeConflictEnabled: models_1.UNAVAILABLE,
createdAt: models_1.UNAVAILABLE,
lastActiveAt: models_1.UNAVAILABLE,
});
}
const response = await this.http.get(`/api/v1/users/${userId}`);
if (response.status === 404) {
const detail = response.data?.detail || `User with ID ${userId} not found`;
throw new errors_1.UserNotFoundError(detail, response.status);
}
else if (response.status !== 200) {
const detail = response.data?.detail || "Failed to retrieve user";
throw new errors_1.RecallrAIError(detail, response.status);
}
const userData = this.parseUserResponse(response.data);
return new user_1.User(this.http, userData);
}
/**
* List users with pagination.
*
* @param offset - Number of records to skip. Defaults to 0.
* @param limit - Maximum number of records to return. Defaults to 10.
* @param metadataFilter - Optional metadata filter for users.
* @returns List of users with pagination info.
* @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 listUsers({ offset = 0, limit = 10, metadataFilter, } = {}) {
const params = {
offset,
limit,
};
if (metadataFilter) {
params.metadata_filter = JSON.stringify(metadataFilter);
}
const response = await this.http.get("/api/v1/users", params);
if (response.status !== 200) {
const detail = response.data?.detail || "Failed to list users";
throw new errors_1.RecallrAIError(detail, response.status);
}
return {
users: response.data.users.map((user) => new user_1.User(this.http, this.parseUserResponse(user))),
total: response.data.total,
hasMore: response.data.has_more,
};
}
parseUserResponse(data) {
const userData = data.user || data;
return {
userId: userData.custom_user_id,
metadata: userData.metadata,
mergeConflictEnabled: userData.merge_conflict_enabled,
createdAt: new Date(userData.created_at),
lastActiveAt: new Date(userData.last_active_at),
};
}
}
exports.RecallrAI = RecallrAI;