betach
Version:
Node.js Character.AI Unofficial API
110 lines (99 loc) • 2.58 kB
JavaScript
/**
* @file Chat.js
* @description Chat class for Character AI
* @exports Chat
* @class Chat
*/
export default class Chat {
/**
* Chat constructor
* @param {Client} client
* @param {Object} input
*/
constructor(client, input) {
this.client = client;
this.externalId = input.external_id;
const ai = input.participants.find((participant) => participant.is_human === false);
this.aiId = ai.user.username;
}
/**
* Chat history
* @returns {Promise<Object>} history
*/
async fetchHistory() {
const url = `${this.client.getBase()}/chat/history/msgs/user/?history_external_id=${this.externalId}`;
const body = await fetch(url,
{
method: "GET",
headers: this.client.getHeaders()
}
);
const res = await body.json();
return res;
}
/**
* Send message
* @param {string} message
* @param {boolean} singleReply
* @returns {Promise<Object>} response
*/
async sendAndAwaitResponse({message, singleReply}) {
const payload = {
history_external_id: this.externalId,
character_external_id: this.client.getCharacter(),
text: message,
tgt: this.aiId,
ranking_method: "random",
faux_chat: false,
staging: false,
model_server_address: null,
override_prefix: null,
override_rank: null,
rank_candidates: null,
filter_candidates: null,
prefix_limit: null,
prefix_token_limit: null,
livetune_coeff: null,
stream_params: null,
enable_tti: true,
initial_timeout: null,
insert_beginning: null,
translate_candidates: null,
stream_every_n_steps: 16,
chunks_to_pad: 8,
};
const url = `${this.client.getBase()}/chat/streaming/`;
const body = await fetch(url,
{
method: "POST",
headers: this.client.getHeaders(),
body: JSON.stringify(payload)
}
);
const replies = [];
const res = await body.text();
for (const line of res.split("\n")) {
if (line.startsWith("{")) {
replies.push(JSON.parse(line));
continue;
}
const start = line.indexOf(" {");
if (start < 0) {
continue;
}
replies.push(JSON.parse(line.slice(start - 1)));
}
if (!singleReply) {
return replies;
}
// Returns what's seen in the chat window of the CharacterAI website
else {
try {
return replies.pop().replies.shift().text;
}
catch (e) {
return "Error: no response from CharacterAI";
}
}
}
}