You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.8 KiB
145 lines
3.8 KiB
// deno-lint-ignore-file no-explicit-any
|
|
|
|
import Client from "./Client.ts";
|
|
|
|
interface MessageHistory {
|
|
messages: {
|
|
id: number;
|
|
text: string;
|
|
src__name: string;
|
|
src__user__username: string;
|
|
src__user__id: number;
|
|
tgt__user__id: number;
|
|
src__is_human: boolean;
|
|
src__character__avatar_file_name: string | null;
|
|
is_alternative: boolean;
|
|
image_rel_path: string;
|
|
image_prompt_text: string;
|
|
image_description_type: string;
|
|
responsible_user__username: string | null;
|
|
deleted: boolean | null; // This is probably a boolean???
|
|
src_char: {
|
|
participant: { name: string };
|
|
avatar_file_name: string | null;
|
|
};
|
|
}[];
|
|
|
|
has_more: boolean;
|
|
next_page: number;
|
|
}
|
|
|
|
interface Reply {
|
|
replies: {
|
|
text: string;
|
|
id: number;
|
|
}[];
|
|
src_char: {
|
|
participant: { name: string };
|
|
avatar_file_name: string;
|
|
};
|
|
is_final_chunk: boolean;
|
|
last_user_msg_id: number;
|
|
}
|
|
|
|
export default class Chat {
|
|
#client: Client;
|
|
|
|
public characterId: string;
|
|
public characterInternalId?: string;
|
|
public historyId: string;
|
|
|
|
constructor(client: Client, id: string, history: any) {
|
|
this.#client = client;
|
|
|
|
this.characterId = id;
|
|
this.historyId = history.external_id;
|
|
// this.characterInternalId = history.participants.find(
|
|
// (participant: any) => participant.is_human === false
|
|
// ).user.username;
|
|
}
|
|
|
|
/**
|
|
* Fetches message history
|
|
* @returns Message history
|
|
*/
|
|
public async fetchMessageHistory(): Promise<MessageHistory> {
|
|
const url = new URL("https://beta.character.ai/chat/history/msgs/user/");
|
|
url.searchParams.set("history_external_id", this.historyId);
|
|
|
|
const res = await this.#client.fetch(url, {
|
|
headers: {
|
|
Authorization: `Token ${this.#client.token}`,
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
const messageHistory = await res.json();
|
|
|
|
return messageHistory;
|
|
}
|
|
|
|
/**
|
|
* Sends a message to the character
|
|
* @param message The message you want to send
|
|
* @returns Object with replies
|
|
*/
|
|
public async sendMessage(message: string): Promise<Reply> {
|
|
if (!this.characterInternalId)
|
|
this.characterInternalId = (
|
|
await this.#client.fetchCharacterInfo(this.characterId)
|
|
).participant__user__username;
|
|
|
|
const payload = {
|
|
history_external_id: this.historyId,
|
|
character_external_id: this.characterId,
|
|
text: message,
|
|
tgt: this.characterInternalId,
|
|
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,
|
|
is_proactive: false,
|
|
};
|
|
|
|
const res = await this.#client.fetch(
|
|
"https://beta.character.ai/chat/streaming/",
|
|
{
|
|
body: JSON.stringify(payload),
|
|
method: "POST",
|
|
headers: {
|
|
Authorization: `Token ${this.#client.token}`,
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json",
|
|
},
|
|
}
|
|
);
|
|
const reader = res.body?.getReader();
|
|
|
|
if (!reader) throw new Error("How."); // Let's hope no one ever sees this
|
|
|
|
let reply = "";
|
|
|
|
while (true) {
|
|
const { value, done } = await reader.read();
|
|
if (done) break;
|
|
reply = new TextDecoder("utf-8").decode(value);
|
|
}
|
|
|
|
return JSON.parse(reply);
|
|
}
|
|
}
|