Merge branch 'dev'
17
package-lock.json
generated
@ -16,6 +16,7 @@
|
||||
"csrf-csrf": "^2.2.3",
|
||||
"exifreader": "^4.12.0",
|
||||
"express": "^4.18.2",
|
||||
"gpt3-tokenizer": "^1.1.5",
|
||||
"ipaddr.js": "^2.0.1",
|
||||
"jimp": "^0.22.7",
|
||||
"json5": "^2.2.3",
|
||||
@ -490,6 +491,11 @@
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
||||
},
|
||||
"node_modules/array-keyed-map": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/array-keyed-map/-/array-keyed-map-2.1.3.tgz",
|
||||
"integrity": "sha512-JIUwuFakO+jHjxyp4YgSiKXSZeC0U+R1jR94bXWBcVlFRBycqXlb+kH9JHxBGcxnVuSqx5bnn0Qz9xtSeKOjiA=="
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
@ -1117,6 +1123,17 @@
|
||||
"process": "^0.11.10"
|
||||
}
|
||||
},
|
||||
"node_modules/gpt3-tokenizer": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/gpt3-tokenizer/-/gpt3-tokenizer-1.1.5.tgz",
|
||||
"integrity": "sha512-O9iCL8MqGR0Oe9wTh0YftzIbysypNQmS5a5JG3cB3M4LMYjlAVvNnf8LUzVY9MrI7tj+YLY356uHtO2lLX2HpA==",
|
||||
"dependencies": {
|
||||
"array-keyed-map": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
|
@ -8,6 +8,7 @@
|
||||
"csrf-csrf": "^2.2.3",
|
||||
"exifreader": "^4.12.0",
|
||||
"express": "^4.18.2",
|
||||
"gpt3-tokenizer": "^1.1.5",
|
||||
"ipaddr.js": "^2.0.1",
|
||||
"jimp": "^0.22.7",
|
||||
"json5": "^2.2.3",
|
||||
|
223
poe-client.js
@ -29,9 +29,178 @@ const parent_path = path.resolve(__dirname);
|
||||
const queries_path = path.join(parent_path, "poe_graphql");
|
||||
let queries = {};
|
||||
|
||||
const cached_bots = {};
|
||||
|
||||
const logger = console;
|
||||
|
||||
const user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0";
|
||||
const user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36";
|
||||
|
||||
function extractFormKey(html) {
|
||||
const scriptRegex = /<script>if\(.+\)throw new Error;(.+)<\/script>/;
|
||||
const scriptText = html.match(scriptRegex)[1];
|
||||
const keyRegex = /var .="([0-9a-f]+)",/;
|
||||
const keyText = scriptText.match(keyRegex)[1];
|
||||
const cipherRegex = /.\[(\d+)\]=.\[(\d+)\]/g;
|
||||
const cipherPairs = Array.from(scriptText.matchAll(cipherRegex));
|
||||
|
||||
const formKeyList = new Array(cipherPairs.length).fill("");
|
||||
for (const pair of cipherPairs) {
|
||||
const [formKeyIndex, keyIndex] = pair.slice(1).map(Number);
|
||||
formKeyList[formKeyIndex] = keyText[keyIndex];
|
||||
}
|
||||
const formKey = formKeyList.join("");
|
||||
|
||||
return formKey;
|
||||
}
|
||||
|
||||
|
||||
function md5() {
|
||||
function a(e, t) {
|
||||
var r = (65535 & e) + (65535 & t);
|
||||
return (e >> 16) + (t >> 16) + (r >> 16) << 16 | 65535 & r
|
||||
}
|
||||
function s(e, t, r, n, i, s) {
|
||||
var o;
|
||||
return a((o = a(a(t, e), a(n, s))) << i | o >>> 32 - i, r)
|
||||
}
|
||||
function o(e, t, r, n, i, a, o) {
|
||||
return s(t & r | ~t & n, e, t, i, a, o)
|
||||
}
|
||||
function l(e, t, r, n, i, a, o) {
|
||||
return s(t & n | r & ~n, e, t, i, a, o)
|
||||
}
|
||||
function u(e, t, r, n, i, a, o) {
|
||||
return s(t ^ r ^ n, e, t, i, a, o)
|
||||
}
|
||||
function c(e, t, r, n, i, a, o) {
|
||||
return s(r ^ (t | ~n), e, t, i, a, o)
|
||||
}
|
||||
function d(e, t) {
|
||||
e[t >> 5] |= 128 << t % 32,
|
||||
e[(t + 64 >>> 9 << 4) + 14] = t;
|
||||
var r, n, i, s, d, f = 1732584193, h = -271733879, p = -1732584194, _ = 271733878;
|
||||
for (r = 0; r < e.length; r += 16)
|
||||
n = f,
|
||||
i = h,
|
||||
s = p,
|
||||
d = _,
|
||||
f = o(f, h, p, _, e[r], 7, -680876936),
|
||||
_ = o(_, f, h, p, e[r + 1], 12, -389564586),
|
||||
p = o(p, _, f, h, e[r + 2], 17, 606105819),
|
||||
h = o(h, p, _, f, e[r + 3], 22, -1044525330),
|
||||
f = o(f, h, p, _, e[r + 4], 7, -176418897),
|
||||
_ = o(_, f, h, p, e[r + 5], 12, 1200080426),
|
||||
p = o(p, _, f, h, e[r + 6], 17, -1473231341),
|
||||
h = o(h, p, _, f, e[r + 7], 22, -45705983),
|
||||
f = o(f, h, p, _, e[r + 8], 7, 1770035416),
|
||||
_ = o(_, f, h, p, e[r + 9], 12, -1958414417),
|
||||
p = o(p, _, f, h, e[r + 10], 17, -42063),
|
||||
h = o(h, p, _, f, e[r + 11], 22, -1990404162),
|
||||
f = o(f, h, p, _, e[r + 12], 7, 1804603682),
|
||||
_ = o(_, f, h, p, e[r + 13], 12, -40341101),
|
||||
p = o(p, _, f, h, e[r + 14], 17, -1502002290),
|
||||
h = o(h, p, _, f, e[r + 15], 22, 1236535329),
|
||||
f = l(f, h, p, _, e[r + 1], 5, -165796510),
|
||||
_ = l(_, f, h, p, e[r + 6], 9, -1069501632),
|
||||
p = l(p, _, f, h, e[r + 11], 14, 643717713),
|
||||
h = l(h, p, _, f, e[r], 20, -373897302),
|
||||
f = l(f, h, p, _, e[r + 5], 5, -701558691),
|
||||
_ = l(_, f, h, p, e[r + 10], 9, 38016083),
|
||||
p = l(p, _, f, h, e[r + 15], 14, -660478335),
|
||||
h = l(h, p, _, f, e[r + 4], 20, -405537848),
|
||||
f = l(f, h, p, _, e[r + 9], 5, 568446438),
|
||||
_ = l(_, f, h, p, e[r + 14], 9, -1019803690),
|
||||
p = l(p, _, f, h, e[r + 3], 14, -187363961),
|
||||
h = l(h, p, _, f, e[r + 8], 20, 1163531501),
|
||||
f = l(f, h, p, _, e[r + 13], 5, -1444681467),
|
||||
_ = l(_, f, h, p, e[r + 2], 9, -51403784),
|
||||
p = l(p, _, f, h, e[r + 7], 14, 1735328473),
|
||||
h = l(h, p, _, f, e[r + 12], 20, -1926607734),
|
||||
f = u(f, h, p, _, e[r + 5], 4, -378558),
|
||||
_ = u(_, f, h, p, e[r + 8], 11, -2022574463),
|
||||
p = u(p, _, f, h, e[r + 11], 16, 1839030562),
|
||||
h = u(h, p, _, f, e[r + 14], 23, -35309556),
|
||||
f = u(f, h, p, _, e[r + 1], 4, -1530992060),
|
||||
_ = u(_, f, h, p, e[r + 4], 11, 1272893353),
|
||||
p = u(p, _, f, h, e[r + 7], 16, -155497632),
|
||||
h = u(h, p, _, f, e[r + 10], 23, -1094730640),
|
||||
f = u(f, h, p, _, e[r + 13], 4, 681279174),
|
||||
_ = u(_, f, h, p, e[r], 11, -358537222),
|
||||
p = u(p, _, f, h, e[r + 3], 16, -722521979),
|
||||
h = u(h, p, _, f, e[r + 6], 23, 76029189),
|
||||
f = u(f, h, p, _, e[r + 9], 4, -640364487),
|
||||
_ = u(_, f, h, p, e[r + 12], 11, -421815835),
|
||||
p = u(p, _, f, h, e[r + 15], 16, 530742520),
|
||||
h = u(h, p, _, f, e[r + 2], 23, -995338651),
|
||||
f = c(f, h, p, _, e[r], 6, -198630844),
|
||||
_ = c(_, f, h, p, e[r + 7], 10, 1126891415),
|
||||
p = c(p, _, f, h, e[r + 14], 15, -1416354905),
|
||||
h = c(h, p, _, f, e[r + 5], 21, -57434055),
|
||||
f = c(f, h, p, _, e[r + 12], 6, 1700485571),
|
||||
_ = c(_, f, h, p, e[r + 3], 10, -1894986606),
|
||||
p = c(p, _, f, h, e[r + 10], 15, -1051523),
|
||||
h = c(h, p, _, f, e[r + 1], 21, -2054922799),
|
||||
f = c(f, h, p, _, e[r + 8], 6, 1873313359),
|
||||
_ = c(_, f, h, p, e[r + 15], 10, -30611744),
|
||||
p = c(p, _, f, h, e[r + 6], 15, -1560198380),
|
||||
h = c(h, p, _, f, e[r + 13], 21, 1309151649),
|
||||
f = c(f, h, p, _, e[r + 4], 6, -145523070),
|
||||
_ = c(_, f, h, p, e[r + 11], 10, -1120210379),
|
||||
p = c(p, _, f, h, e[r + 2], 15, 718787259),
|
||||
h = c(h, p, _, f, e[r + 9], 21, -343485551),
|
||||
f = a(f, n),
|
||||
h = a(h, i),
|
||||
p = a(p, s),
|
||||
_ = a(_, d);
|
||||
return [f, h, p, _]
|
||||
}
|
||||
function f(e) {
|
||||
var t, r = "", n = 32 * e.length;
|
||||
for (t = 0; t < n; t += 8)
|
||||
r += String.fromCharCode(e[t >> 5] >>> t % 32 & 255);
|
||||
return r
|
||||
}
|
||||
function h(e) {
|
||||
var t, r = [];
|
||||
for (t = 0,
|
||||
r[(e.length >> 2) - 1] = void 0; t < r.length; t += 1)
|
||||
r[t] = 0;
|
||||
var n = 8 * e.length;
|
||||
for (t = 0; t < n; t += 8)
|
||||
r[t >> 5] |= (255 & e.charCodeAt(t / 8)) << t % 32;
|
||||
return r
|
||||
}
|
||||
function p(e) {
|
||||
var t, r, n = "0123456789abcdef", i = "";
|
||||
for (r = 0; r < e.length; r += 1)
|
||||
i += n.charAt((t = e.charCodeAt(r)) >>> 4 & 15) + n.charAt(15 & t);
|
||||
return i
|
||||
}
|
||||
function _(e) {
|
||||
return unescape(encodeURIComponent(e))
|
||||
}
|
||||
function v(e) {
|
||||
var t;
|
||||
return f(d(h(t = _(e)), 8 * t.length))
|
||||
}
|
||||
function g(e, t) {
|
||||
return function (e, t) {
|
||||
var r, n, i = h(e), a = [], s = [];
|
||||
for (a[15] = s[15] = void 0,
|
||||
i.length > 16 && (i = d(i, 8 * e.length)),
|
||||
r = 0; r < 16; r += 1)
|
||||
a[r] = 909522486 ^ i[r],
|
||||
s[r] = 1549556828 ^ i[r];
|
||||
return n = d(a.concat(h(t)), 512 + 8 * t.length),
|
||||
f(d(s.concat(n), 640))
|
||||
}(_(e), _(t))
|
||||
}
|
||||
function m(e, t, r) {
|
||||
return t ? r ? g(t, e) : p(g(t, e)) : r ? v(e) : p(v(e))
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
function load_queries() {
|
||||
const files = fs.readdirSync(queries_path);
|
||||
@ -46,9 +215,9 @@ function load_queries() {
|
||||
}
|
||||
}
|
||||
|
||||
function generate_payload(query_name, variables) {
|
||||
function generate_payload(query, variables) {
|
||||
return {
|
||||
query: queries[query_name],
|
||||
query: queries[query],
|
||||
variables: variables,
|
||||
}
|
||||
}
|
||||
@ -85,9 +254,11 @@ class Client {
|
||||
ws = null;
|
||||
ws_connected = false;
|
||||
auto_reconnect = false;
|
||||
use_cached_bots = false;
|
||||
|
||||
constructor(auto_reconnect = false) {
|
||||
constructor(auto_reconnect = false, use_cached_bots = false) {
|
||||
this.auto_reconnect = auto_reconnect;
|
||||
this.use_cached_bots = use_cached_bots;
|
||||
}
|
||||
|
||||
async init(token, proxy = null) {
|
||||
@ -111,18 +282,18 @@ class Client {
|
||||
"Origin": "https://poe.com",
|
||||
"Cookie": cookies,
|
||||
};
|
||||
this.ws_domain = `tch${Math.floor(Math.random() * 1e6)}`;
|
||||
this.session.defaults.headers.common = this.headers;
|
||||
this.next_data = await this.get_next_data();
|
||||
this.channel = await this.get_channel_data();
|
||||
await this.connect_ws();
|
||||
this.bots = await this.get_bots();
|
||||
this.bot_names = this.get_bot_names();
|
||||
this.ws_domain = `tch${Math.floor(Math.random() * 1e6)}`;
|
||||
this.gql_headers = {
|
||||
"poe-formkey": this.formkey,
|
||||
"poe-tchannel": this.channel["channel"],
|
||||
...this.headers,
|
||||
};
|
||||
await this.connect_ws();
|
||||
await this.subscribe();
|
||||
}
|
||||
|
||||
@ -134,7 +305,7 @@ class Client {
|
||||
const jsonText = jsonRegex.exec(r.data)[1];
|
||||
const nextData = JSON.parse(jsonText);
|
||||
|
||||
this.formkey = nextData.props.formkey;
|
||||
this.formkey = extractFormKey(r.data);
|
||||
this.viewer = nextData.props.pageProps.payload.viewer;
|
||||
|
||||
return nextData;
|
||||
@ -150,9 +321,16 @@ class Client {
|
||||
const bots = {};
|
||||
for (const bot of botList.filter(x => x.deletionState == 'not_deleted')) {
|
||||
const url = `https://poe.com/_next/data/${this.next_data.buildId}/${bot.displayName}.json`;
|
||||
logger.info(`Downloading ${url}`);
|
||||
let r;
|
||||
|
||||
const r = await request_with_retries(() => this.session.get(url));
|
||||
if (this.use_cached_bots && cached_bots[url]) {
|
||||
r = cached_bots[url];
|
||||
}
|
||||
else {
|
||||
logger.info(`Downloading ${url}`);
|
||||
r = await request_with_retries(() => this.session.get(url));
|
||||
cached_bots[url] = r;
|
||||
}
|
||||
|
||||
const chatData = r.data.pageProps.payload.chatOfBotDisplayName;
|
||||
bots[chatData.defaultBotObject.nickname] = chatData;
|
||||
@ -175,7 +353,6 @@ class Client {
|
||||
const r = await request_with_retries(() => this.session.get(this.settings_url));
|
||||
const data = r.data;
|
||||
|
||||
this.formkey = data.formkey;
|
||||
return data.tchannelData;
|
||||
}
|
||||
|
||||
@ -187,9 +364,14 @@ class Client {
|
||||
return `wss://${this.ws_domain}.tch.${channel.baseHost}/up/${channel.boxName}/updates${query}`;
|
||||
}
|
||||
|
||||
async send_query(queryName, variables) {
|
||||
async send_query(queryName, variables, queryDisplayName) {
|
||||
for (let i = 0; i < 20; i++) {
|
||||
const payload = generate_payload(queryName, variables);
|
||||
if (queryDisplayName) payload['queryName'] = queryDisplayName;
|
||||
const scramblePayload = JSON.stringify(payload);
|
||||
const _headers = this.gql_headers;
|
||||
_headers['poe-tag-id'] = md5()(scramblePayload + this.formkey + "WpuLMiXEKKE98j56k");
|
||||
_headers['poe-formkey'] = this.formkey;
|
||||
const r = await request_with_retries(() => this.session.post(this.gql_url, payload, { headers: this.gql_headers }));
|
||||
if (!r.data.data) {
|
||||
logger.warn(`${queryName} returned an error: ${data.errors[0].message} | Retrying (${i + 1}/20)`);
|
||||
@ -214,9 +396,14 @@ class Client {
|
||||
{
|
||||
"subscriptionName": "viewerStateUpdated",
|
||||
"query": queries["ViewerStateUpdatedSubscription"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"subscriptionName": "viewerMessageLimitUpdated",
|
||||
"query": queries["ViewerMessageLimitUpdatedSubscription"]
|
||||
},
|
||||
]
|
||||
});
|
||||
},
|
||||
'subscriptionsMutation');
|
||||
}
|
||||
|
||||
ws_run_thread() {
|
||||
@ -283,12 +470,16 @@ class Client {
|
||||
for (const message_str of data["messages"]) {
|
||||
const message_data = JSON.parse(message_str);
|
||||
|
||||
if (message_data["message_type"] != "subscriptionUpdate"){
|
||||
if (message_data["message_type"] != "subscriptionUpdate") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const message = message_data["payload"]["data"]["messageAdded"]
|
||||
|
||||
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
|
||||
const copiedDict = Object.assign({}, this.active_messages);
|
||||
for (const [key, value] of Object.entries(copiedDict)) {
|
||||
//add the message to the appropriate queue
|
||||
@ -296,7 +487,7 @@ class Client {
|
||||
this.message_queues[key].push(message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//indicate that the response id is tied to the human message id
|
||||
else if (key !== "pending" && value === null && message["state"] !== "complete") {
|
||||
this.active_messages[key] = message["messageId"];
|
||||
|
@ -1,10 +1,11 @@
|
||||
subscription messageAdded (
|
||||
subscription subscriptions_messageAdded_Subscription(
|
||||
$chatId: BigInt!
|
||||
) {
|
||||
messageAdded(chatId: $chatId) {
|
||||
id
|
||||
messageId
|
||||
creationTime
|
||||
clientNonce
|
||||
state
|
||||
...ChatMessage_message
|
||||
...chatHelpers_isBotMessage
|
||||
@ -21,7 +22,7 @@ fragment ChatMessageDropdownMenu_message on Message {
|
||||
messageId
|
||||
vote
|
||||
text
|
||||
linkifiedText
|
||||
author
|
||||
...chatHelpers_isBotMessage
|
||||
}
|
||||
|
||||
@ -45,6 +46,7 @@ fragment ChatMessageSuggestedReplies_SuggestedReplyButton_message on Message {
|
||||
|
||||
fragment ChatMessageSuggestedReplies_message on Message {
|
||||
suggestedReplies
|
||||
author
|
||||
...ChatMessageSuggestedReplies_SuggestedReplyButton_message
|
||||
}
|
||||
|
||||
@ -55,6 +57,7 @@ fragment ChatMessage_message on Message {
|
||||
author
|
||||
linkifiedText
|
||||
state
|
||||
contentType
|
||||
...ChatMessageSuggestedReplies_message
|
||||
...ChatMessageFeedbackButtons_message
|
||||
...ChatMessageOverflowButton_message
|
||||
@ -63,6 +66,12 @@ fragment ChatMessage_message on Message {
|
||||
...chatHelpers_isChatBreak
|
||||
...chatHelpers_useTimeoutLevel
|
||||
...MarkdownLinkInner_message
|
||||
...IdAnnotation_node
|
||||
}
|
||||
|
||||
fragment IdAnnotation_node on Node {
|
||||
__isNode: __typename
|
||||
id
|
||||
}
|
||||
|
||||
fragment MarkdownLinkInner_message on Message {
|
||||
@ -97,4 +106,10 @@ fragment chatHelpers_useTimeoutLevel on Message {
|
||||
state
|
||||
text
|
||||
messageId
|
||||
author
|
||||
chat {
|
||||
chatId
|
||||
defaultBotNickname
|
||||
id
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
subscription MessageDeletedSubscription($chatId: BigInt!) {
|
||||
messageDeleted(chatId: $chatId) {
|
||||
id
|
||||
messageId
|
||||
}
|
||||
subscription subscriptions_messageDeleted_Subscription(
|
||||
$chatId: BigInt!
|
||||
) {
|
||||
messageDeleted(chatId: $chatId) {
|
||||
id
|
||||
messageId
|
||||
}
|
||||
}
|
||||
|
@ -6,4 +6,4 @@ mutation subscriptionsMutation(
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
81
poe_graphql/ViewerMessageLimitUpdatedSubscription.graphql
Normal file
@ -0,0 +1,81 @@
|
||||
subscription subscriptions_viewerMessageLimitUpdated_Subscription {
|
||||
viewerMessageLimitUpdated {
|
||||
...SettingsSubscriptionSection_viewer
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
fragment SettingsSubscriptionPaywallModal_viewer on Viewer {
|
||||
...WebSubscriptionPaywall_viewer
|
||||
}
|
||||
|
||||
fragment SettingsSubscriptionSectionNonSubscriberView_viewer on Viewer {
|
||||
...SettingsSubscriptionPaywallModal_viewer
|
||||
}
|
||||
|
||||
fragment SettingsSubscriptionSectionSubscriberView_viewer on Viewer {
|
||||
subscription {
|
||||
isActive
|
||||
expiresTime
|
||||
purchaseType
|
||||
isAnnualSubscription
|
||||
willCancelAtPeriodEnd
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
fragment SettingsSubscriptionSection_viewer on Viewer {
|
||||
availableBots {
|
||||
displayName
|
||||
messageLimit {
|
||||
canSend
|
||||
numMessagesRemaining
|
||||
resetTime
|
||||
dailyBalance
|
||||
dailyLimit
|
||||
monthlyBalance
|
||||
monthlyLimit
|
||||
monthlyBalanceRefreshTime
|
||||
shouldShowRemainingMessageCount
|
||||
}
|
||||
id
|
||||
}
|
||||
subscription {
|
||||
isActive
|
||||
id
|
||||
}
|
||||
isEligibleForWebSubscriptions
|
||||
...SettingsSubscriptionSectionNonSubscriberView_viewer
|
||||
...SettingsSubscriptionSectionSubscriberView_viewer
|
||||
...WebSubscriptionSuccessMessage_viewer
|
||||
}
|
||||
|
||||
fragment SubscriptionMessageLimitExplanation_viewer on Viewer {
|
||||
availableBots {
|
||||
displayName
|
||||
messageLimit {
|
||||
monthlyLimit
|
||||
}
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
fragment WebSubscriptionPaywall_viewer on Viewer {
|
||||
...SubscriptionMessageLimitExplanation_viewer
|
||||
webSubscriptionPriceInfo {
|
||||
monthlyPrice
|
||||
yearlyPrice
|
||||
yearlyPricePerMonth
|
||||
yearlyPercentageSavings
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
fragment WebSubscriptionSuccessMessage_viewer on Viewer {
|
||||
subscription {
|
||||
isActive
|
||||
expiresTime
|
||||
willCancelAtPeriodEnd
|
||||
id
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
subscription viewerStateUpdated {
|
||||
subscription subscriptions_viewerStateUpdated_Subscription {
|
||||
viewerStateUpdated {
|
||||
id
|
||||
...ChatPageBotSwitcher_viewer
|
||||
@ -11,9 +11,19 @@ fragment BotHeader_bot on Bot {
|
||||
dailyLimit
|
||||
}
|
||||
...BotImage_bot
|
||||
...BotLink_bot
|
||||
...IdAnnotation_node
|
||||
...botHelpers_useViewerCanAccessPrivateBot
|
||||
...botHelpers_useDeletion_bot
|
||||
}
|
||||
|
||||
fragment BotImage_bot on Bot {
|
||||
displayName
|
||||
...botHelpers_useDeletion_bot
|
||||
...BotImage_useProfileImage_bot
|
||||
}
|
||||
|
||||
fragment BotImage_useProfileImage_bot on Bot {
|
||||
image {
|
||||
__typename
|
||||
... on LocalBotImage {
|
||||
@ -23,7 +33,7 @@ fragment BotImage_bot on Bot {
|
||||
url
|
||||
}
|
||||
}
|
||||
displayName
|
||||
...botHelpers_useDeletion_bot
|
||||
}
|
||||
|
||||
fragment BotLink_bot on Bot {
|
||||
@ -33,11 +43,21 @@ fragment BotLink_bot on Bot {
|
||||
fragment ChatPageBotSwitcher_viewer on Viewer {
|
||||
availableBots {
|
||||
id
|
||||
messageLimit {
|
||||
dailyLimit
|
||||
}
|
||||
...BotLink_bot
|
||||
handle
|
||||
...BotHeader_bot
|
||||
}
|
||||
allowUserCreatedBots: booleanGate(gateName: "enable_user_created_bots")
|
||||
}
|
||||
|
||||
fragment IdAnnotation_node on Node {
|
||||
__isNode: __typename
|
||||
id
|
||||
}
|
||||
|
||||
fragment botHelpers_useDeletion_bot on Bot {
|
||||
deletionState
|
||||
}
|
||||
|
||||
fragment botHelpers_useViewerCanAccessPrivateBot on Bot {
|
||||
isPrivateBot
|
||||
viewerIsCreator
|
||||
}
|
||||
|
7955
public/css/all.css
Normal file
19
public/css/solid.css
Normal file
@ -0,0 +1,19 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2023 Fonticons, Inc.
|
||||
*/
|
||||
:root, :host {
|
||||
--fa-style-family-classic: 'Font Awesome 6 Free';
|
||||
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
||||
|
||||
.fas,
|
||||
.fa-solid {
|
||||
font-weight: 900; }
|
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 0C60.7 0 32 28.7 32 64V448c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64H96zM208 288h64c44.2 0 80 35.8 80 80c0 8.8-7.2 16-16 16H144c-8.8 0-16-7.2-16-16c0-44.2 35.8-80 80-80zm-32-96a64 64 0 1 1 128 0 64 64 0 1 1 -128 0zM512 80c0-8.8-7.2-16-16-16s-16 7.2-16 16v64c0 8.8 7.2 16 16 16s16-7.2 16-16V80zM496 192c-8.8 0-16 7.2-16 16v64c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm16 144c0-8.8-7.2-16-16-16s-16 7.2-16 16v64c0 8.8 7.2 16 16 16s16-7.2 16-16V336z"/></svg>
|
Before Width: | Height: | Size: 740 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M0 96C0 43 43 0 96 0H384h32c17.7 0 32 14.3 32 32V352c0 17.7-14.3 32-32 32v64c17.7 0 32 14.3 32 32s-14.3 32-32 32H384 96c-53 0-96-43-96-96V96zM64 416c0 17.7 14.3 32 32 32H352V384H96c-17.7 0-32 14.3-32 32zM247.4 283.8c-3.7 3.7-6.2 4.2-7.4 4.2s-3.7-.5-7.4-4.2c-3.8-3.7-8-10-11.8-18.9c-6.2-14.5-10.8-34.3-12.2-56.9h63c-1.5 22.6-6 42.4-12.2 56.9c-3.8 8.9-8 15.2-11.8 18.9zm42.7-9.9c7.3-18.3 12-41.1 13.4-65.9h31.1c-4.7 27.9-21.4 51.7-44.5 65.9zm0-163.8c23.2 14.2 39.9 38 44.5 65.9H303.5c-1.4-24.7-6.1-47.5-13.4-65.9zM368 192a128 128 0 1 0 -256 0 128 128 0 1 0 256 0zM145.3 208h31.1c1.4 24.7 6.1 47.5 13.4 65.9c-23.2-14.2-39.9-38-44.5-65.9zm31.1-32H145.3c4.7-27.9 21.4-51.7 44.5-65.9c-7.3 18.3-12 41.1-13.4 65.9zm56.1-75.8c3.7-3.7 6.2-4.2 7.4-4.2s3.7 .5 7.4 4.2c3.8 3.7 8 10 11.8 18.9c6.2 14.5 10.8 34.3 12.2 56.9h-63c1.5-22.6 6-42.4 12.2-56.9c3.8-8.9 8-15.2 11.8-18.9z"/></svg>
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 0C43 0 0 43 0 96V416c0 53 43 96 96 96H384h32c17.7 0 32-14.3 32-32s-14.3-32-32-32V384c17.7 0 32-14.3 32-32V32c0-17.7-14.3-32-32-32H384 96zm0 384H352v64H96c-17.7 0-32-14.3-32-32s14.3-32 32-32zm32-240c0-8.8 7.2-16 16-16H336c8.8 0 16 7.2 16 16s-7.2 16-16 16H144c-8.8 0-16-7.2-16-16zm16 48H336c8.8 0 16 7.2 16 16s-7.2 16-16 16H144c-8.8 0-16-7.2-16-16s7.2-16 16-16z"/></svg>
|
Before Width: | Height: | Size: 611 B |
Before Width: | Height: | Size: 1.7 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M0 48V487.7C0 501.1 10.9 512 24.3 512c5 0 9.9-1.5 14-4.4L192 400 345.7 507.6c4.1 2.9 9 4.4 14 4.4c13.4 0 24.3-10.9 24.3-24.3V48c0-26.5-21.5-48-48-48H48C21.5 0 0 21.5 0 48z"/></svg>
|
Before Width: | Height: | Size: 419 B |
Before Width: | Height: | Size: 1.1 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>
|
Before Width: | Height: | Size: 428 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"/></svg>
|
Before Width: | Height: | Size: 416 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M233.4 105.4c12.5-12.5 32.8-12.5 45.3 0l192 192c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L256 173.3 86.6 342.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l192-192z"/></svg>
|
Before Width: | Height: | Size: 416 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M256 0a256 256 0 1 0 0 512A256 256 0 1 0 256 0zM135 241c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l87 87 87-87c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9L273 345c-9.4 9.4-24.6 9.4-33.9 0L135 241z"/></svg>
|
Before Width: | Height: | Size: 438 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM377 271c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-87-87-87 87c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9L239 167c9.4-9.4 24.6-9.4 33.9 0L377 271z"/></svg>
|
Before Width: | Height: | Size: 442 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z"/></svg>
|
Before Width: | Height: | Size: 712 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M144 480C64.5 480 0 415.5 0 336c0-62.8 40.2-116.2 96.2-135.9c-.1-2.7-.2-5.4-.2-8.1c0-88.4 71.6-160 160-160c59.3 0 111 32.2 138.7 80.2C409.9 102 428.3 96 448 96c53 0 96 43 96 96c0 12.2-2.3 23.8-6.4 34.6C596 238.4 640 290.1 640 352c0 70.7-57.3 128-128 128H144zm79-217c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l39-39V392c0 13.3 10.7 24 24 24s24-10.7 24-24V257.9l39 39c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-80-80c-9.4-9.4-24.6-9.4-33.9 0l-80 80z"/></svg>
|
Before Width: | Height: | Size: 691 B |
Before Width: | Height: | Size: 724 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M256 448c141.4 0 256-93.1 256-208S397.4 32 256 32S0 125.1 0 240c0 45.1 17.7 86.8 47.7 120.9c-1.9 24.5-11.4 46.3-21.4 62.9c-5.5 9.2-11.1 16.6-15.2 21.6c-2.1 2.5-3.7 4.4-4.9 5.7c-.6 .6-1 1.1-1.3 1.4l-.3 .3 0 0 0 0 0 0 0 0c-4.6 4.6-5.9 11.4-3.4 17.4c2.5 6 8.3 9.9 14.8 9.9c28.7 0 57.6-8.9 81.6-19.3c22.9-10 42.4-21.9 54.3-30.6c31.8 11.5 67 17.9 104.1 17.9zM128 208a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm128 0a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm96 32a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/></svg>
|
Before Width: | Height: | Size: 727 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M256 448c141.4 0 256-93.1 256-208S397.4 32 256 32S0 125.1 0 240c0 45.1 17.7 86.8 47.7 120.9c-1.9 24.5-11.4 46.3-21.4 62.9c-5.5 9.2-11.1 16.6-15.2 21.6c-2.1 2.5-3.7 4.4-4.9 5.7c-.6 .6-1 1.1-1.3 1.4l-.3 .3 0 0 0 0 0 0 0 0c-4.6 4.6-5.9 11.4-3.4 17.4c2.5 6 8.3 9.9 14.8 9.9c28.7 0 57.6-8.9 81.6-19.3c22.9-10 42.4-21.9 54.3-30.6c31.8 11.5 67 17.9 104.1 17.9zM224 160c0-8.8 7.2-16 16-16h32c8.8 0 16 7.2 16 16v48h48c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H288v48c0 8.8-7.2 16-16 16H240c-8.8 0-16-7.2-16-16V272H176c-8.8 0-16-7.2-16-16V224c0-8.8 7.2-16 16-16h48V160z"/></svg>
|
Before Width: | Height: | Size: 806 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M272 0H396.1c12.7 0 24.9 5.1 33.9 14.1l67.9 67.9c9 9 14.1 21.2 14.1 33.9V336c0 26.5-21.5 48-48 48H272c-26.5 0-48-21.5-48-48V48c0-26.5 21.5-48 48-48zM48 128H192v64H64V448H256V416h64v48c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V176c0-26.5 21.5-48 48-48z"/></svg>
|
Before Width: | Height: | Size: 503 B |
Before Width: | Height: | Size: 4.3 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M273.8 45.8l73.7 28L271.2 103 194.8 73.7l73.7-28c1.7-.7 3.6-.7 5.3 0zM128.1 87.1V192.6c-1.2 .4-2.4 .8-3.6 1.2L34.1 228.1c-20.5 7.8-34 27.4-34 49.3V389.5c0 20.9 12.4 39.8 31.5 48.3L122 477.5c13.5 5.9 28.9 5.9 42.4 0l106.8-46.9L378 477.5c13.5 5.9 28.9 5.9 42.4 0l90.4-39.7c19.1-8.4 31.5-27.3 31.5-48.3V277.4c0-21.9-13.5-41.5-34-49.3l-90.4-34.3c-1.2-.5-2.4-.9-3.6-1.2V87.1c0-21.9-13.5-41.5-34-49.3L289.9 3.5c-12-4.6-25.3-4.6-37.4 0L162.1 37.8c-20.5 7.8-34 27.4-34 49.3zM369.1 198.2l-77.5 29.4v-84l77.5-29.7v84.3zM145.8 236.1l73.7 28-76.4 29.3L66.8 264.1l73.7-28c1.7-.7 3.6-.7 5.3 0zm17.7 192.4V333.9l77.5-29.7v90.2l-77.5 34.1zm233-192.4c1.7-.7 3.6-.7 5.3 0l73.7 28-76.4 29.3-76.4-29.3 73.7-28zm96.1 160.3l-73 32.1V333.9l77.5-29.7v85.3c0 3-1.8 5.7-4.5 6.9z"/></svg>
|
Before Width: | Height: | Size: 1000 B |
Before Width: | Height: | Size: 4.3 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M252.3 11.7c-15.6-15.6-40.9-15.6-56.6 0l-184 184c-15.6 15.6-15.6 40.9 0 56.6l184 184c15.6 15.6 40.9 15.6 56.6 0l184-184c15.6-15.6 15.6-40.9 0-56.6l-184-184zM248 224c0 13.3-10.7 24-24 24s-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24zM96 248c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24zm128 80c13.3 0 24 10.7 24 24s-10.7 24-24 24s-24-10.7-24-24s10.7-24 24-24zm128-80c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24zM224 72c13.3 0 24 10.7 24 24s-10.7 24-24 24s-24-10.7-24-24s10.7-24 24-24zm96 392c0 26.5 21.5 48 48 48H592c26.5 0 48-21.5 48-48V240c0-26.5-21.5-48-48-48H472.5c13.4 26.9 8.8 60.5-13.6 82.9L320 413.8V464zm160-88c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z"/></svg>
|
Before Width: | Height: | Size: 970 B |
Before Width: | Height: | Size: 884 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm177.6 62.1C192.8 334.5 218.8 352 256 352s63.2-17.5 78.4-33.9c9-9.7 24.2-10.4 33.9-1.4s10.4 24.2 1.4 33.9c-22 23.8-60 49.4-113.6 49.4s-91.7-25.5-113.6-49.4c-9-9.7-8.4-24.9 1.4-33.9s24.9-8.4 33.9 1.4zM144.4 208a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm192-32a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>
|
Before Width: | Height: | Size: 632 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M64 0C28.7 0 0 28.7 0 64V448c0 35.3 28.7 64 64 64H320c35.3 0 64-28.7 64-64V160H256c-17.7 0-32-14.3-32-32V0H64zM256 0V128H384L256 0zM216 408c0 13.3-10.7 24-24 24s-24-10.7-24-24V305.9l-31 31c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l72-72c9.4-9.4 24.6-9.4 33.9 0l72 72c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-31-31V408z"/></svg>
|
Before Width: | Height: | Size: 567 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M0 64C0 28.7 28.7 0 64 0H224V128c0 17.7 14.3 32 32 32H384V288H216c-13.3 0-24 10.7-24 24s10.7 24 24 24H384V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64zM384 336V288H494.1l-39-39c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l80 80c9.4 9.4 9.4 24.6 0 33.9l-80 80c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l39-39H384zm0-208H256V0L384 128z"/></svg>
|
Before Width: | Height: | Size: 584 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M64 0C28.7 0 0 28.7 0 64V448c0 35.3 28.7 64 64 64H320c35.3 0 64-28.7 64-64V160H256c-17.7 0-32-14.3-32-32V0H64zM256 0V128H384L256 0zM64 256a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm152 32c5.3 0 10.2 2.6 13.2 6.9l88 128c3.4 4.9 3.7 11.3 1 16.5s-8.2 8.6-14.2 8.6H216 176 128 80c-5.8 0-11.1-3.1-13.9-8.1s-2.8-11.2 .2-16.1l48-80c2.9-4.8 8.1-7.8 13.7-7.8s10.8 2.9 13.7 7.8l12.8 21.4 48.3-70.2c3-4.3 7.9-6.9 13.2-6.9z"/></svg>
|
Before Width: | Height: | Size: 653 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M254 52.8C249.3 40.3 237.3 32 224 32s-25.3 8.3-30 20.8L57.8 416H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32h-1.8l18-48H303.8l18 48H320c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H390.2L254 52.8zM279.8 304H168.2L224 155.1 279.8 304z"/></svg>
|
Before Width: | Height: | Size: 544 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M481.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-30.9 28.1c-7.7 7.1-11.4 17.5-10.9 27.9c.1 2.9 .2 5.8 .2 8.8s-.1 5.9-.2 8.8c-.5 10.5 3.1 20.9 10.9 27.9l30.9 28.1c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-39.7-12.6c-10-3.2-20.8-1.1-29.7 4.6c-4.9 3.1-9.9 6.1-15.1 8.7c-9.3 4.8-16.5 13.2-18.8 23.4l-8.9 40.7c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-8.9-40.7c-2.2-10.2-9.5-18.6-18.8-23.4c-5.2-2.7-10.2-5.6-15.1-8.7c-8.8-5.7-19.7-7.8-29.7-4.6L69.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l30.9-28.1c7.7-7.1 11.4-17.5 10.9-27.9c-.1-2.9-.2-5.8-.2-8.8s.1-5.9 .2-8.8c.5-10.5-3.1-20.9-10.9-27.9L8.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l39.7 12.6c10 3.2 20.8 1.1 29.7-4.6c4.9-3.1 9.9-6.1 15.1-8.7c9.3-4.8 16.5-13.2 18.8-23.4l8.9-40.7c2-9.1 9-16.3 18.2-17.8C213.3 1.2 227.5 0 242 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l8.9 40.7c2.2 10.2 9.4 18.6 18.8 23.4c5.2 2.7 10.2 5.6 15.1 8.7c8.8 5.7 19.7 7.7 29.7 4.6l39.7-12.6c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM242 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/></svg>
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M528 160V416c0 8.8-7.2 16-16 16H320c0-44.2-35.8-80-80-80H176c-44.2 0-80 35.8-80 80H64c-8.8 0-16-7.2-16-16V160H528zM64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H512c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64zM272 256a64 64 0 1 0 -128 0 64 64 0 1 0 128 0zm104-48c-13.3 0-24 10.7-24 24s10.7 24 24 24h80c13.3 0 24-10.7 24-24s-10.7-24-24-24H376zm0 96c-13.3 0-24 10.7-24 24s10.7 24 24 24h80c13.3 0 24-10.7 24-24s-10.7-24-24-24H376z"/></svg>
|
Before Width: | Height: | Size: 684 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M0 96C0 60.7 28.7 32 64 32H448c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM323.8 202.5c-4.5-6.6-11.9-10.5-19.8-10.5s-15.4 3.9-19.8 10.5l-87 127.6L170.7 297c-4.6-5.7-11.5-9-18.7-9s-14.2 3.3-18.7 9l-64 80c-5.8 7.2-6.9 17.1-2.9 25.4s12.4 13.6 21.6 13.6h96 32H424c8.9 0 17.1-4.9 21.2-12.8s3.6-17.4-1.4-24.7l-120-176zM112 192a48 48 0 1 0 0-96 48 48 0 1 0 0 96z"/></svg>
|
Before Width: | Height: | Size: 634 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M177.5 414c-8.8 3.8-19 2-26-4.6l-144-136C2.7 268.9 0 262.6 0 256s2.7-12.9 7.5-17.4l144-136c7-6.6 17.2-8.4 26-4.6s14.5 12.5 14.5 22l0 72 288 0c17.7 0 32 14.3 32 32l0 64c0 17.7-14.3 32-32 32l-288 0 0 72c0 9.6-5.7 18.2-14.5 22z"/></svg>
|
Before Width: | Height: | Size: 472 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M64 144a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zM64 464a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm48-208a48 48 0 1 0 -96 0 48 48 0 1 0 96 0z"/></svg>
|
Before Width: | Height: | Size: 637 B |
@ -1,60 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block; shape-rendering: auto;" width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
|
||||
<g transform="translate(80,50)">
|
||||
<g transform="rotate(0)">
|
||||
<circle cx="0" cy="0" r="6" fill="#dedede" fill-opacity="1">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.875s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.875s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(71.21320343559643,71.21320343559643)">
|
||||
<g transform="rotate(45)">
|
||||
<circle cx="0" cy="0" r="6" fill="#dedede" fill-opacity="0.875">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.75s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.75s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(50,80)">
|
||||
<g transform="rotate(90)">
|
||||
<circle cx="0" cy="0" r="6" fill="#dedede" fill-opacity="0.75">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.625s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.625s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(28.786796564403577,71.21320343559643)">
|
||||
<g transform="rotate(135)">
|
||||
<circle cx="0" cy="0" r="6" fill="#dedede" fill-opacity="0.625">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.5s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.5s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(20,50.00000000000001)">
|
||||
<g transform="rotate(180)">
|
||||
<circle cx="0" cy="0" r="6" fill="#dedede" fill-opacity="0.5">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.375s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.375s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(28.78679656440357,28.786796564403577)">
|
||||
<g transform="rotate(225)">
|
||||
<circle cx="0" cy="0" r="6" fill="#dedede" fill-opacity="0.375">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.25s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.25s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(49.99999999999999,20)">
|
||||
<g transform="rotate(270)">
|
||||
<circle cx="0" cy="0" r="6" fill="#dedede" fill-opacity="0.25">
|
||||
<animateTransform attributeName="transform" type="scale" begin="-0.125s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="-0.125s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g><g transform="translate(71.21320343559643,28.78679656440357)">
|
||||
<g transform="rotate(315)">
|
||||
<circle cx="0" cy="0" r="6" fill="#dedede" fill-opacity="0.125">
|
||||
<animateTransform attributeName="transform" type="scale" begin="0s" values="1.5 1.5;1 1" keyTimes="0;1" dur="1s" repeatCount="indefinite"></animateTransform>
|
||||
<animate attributeName="fill-opacity" keyTimes="0;1" dur="1s" repeatCount="indefinite" values="1;0" begin="0s"></animate>
|
||||
</circle>
|
||||
</g>
|
||||
</g>
|
||||
<!-- [ldio] generated by https://loading.io/ --></svg>
|
Before Width: | Height: | Size: 3.9 KiB |
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block; shape-rendering: auto;" width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
|
||||
<circle cx="50" cy="50" fill="none" stroke="#dedede" stroke-width="10" r="35" stroke-dasharray="164.93361431346415 56.97787143782138">
|
||||
<animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" dur="1s" values="0 50 50;360 50 50" keyTimes="0;1"></animateTransform>
|
||||
</circle>
|
||||
<!-- [ldio] generated by https://loading.io/ --></svg>
|
Before Width: | Height: | Size: 639 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M352 144c0-44.2 35.8-80 80-80s80 35.8 80 80v48c0 17.7 14.3 32 32 32s32-14.3 32-32V144C576 64.5 511.5 0 432 0S288 64.5 288 144v48H64c-35.3 0-64 28.7-64 64V448c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V256c0-35.3-28.7-64-64-64H352V144z"/></svg>
|
Before Width: | Height: | Size: 485 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M144 144v48H304V144c0-44.2-35.8-80-80-80s-80 35.8-80 80zM80 192V144C80 64.5 144.5 0 224 0s144 64.5 144 144v48h16c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V256c0-35.3 28.7-64 64-64H80z"/></svg>
|
Before Width: | Height: | Size: 460 B |
Before Width: | Height: | Size: 861 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M416 256c0 17.7-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z"/></svg>
|
Before Width: | Height: | Size: 348 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M45.6 32C20.4 32 0 52.4 0 77.6V434.4C0 459.6 20.4 480 45.6 480c5.1 0 10-.8 14.7-2.4C74.6 472.8 177.6 440 320 440s245.4 32.8 259.6 37.6c4.7 1.6 9.7 2.4 14.7 2.4c25.2 0 45.6-20.4 45.6-45.6V77.6C640 52.4 619.6 32 594.4 32c-5 0-10 .8-14.7 2.4C565.4 39.2 462.4 72 320 72S74.6 39.2 60.4 34.4C55.6 32.8 50.7 32 45.6 32zM96 160a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm272 0c7.9 0 15.4 3.9 19.8 10.5L512.3 353c5.4 8 5.6 18.4 .4 26.5s-14.7 12.3-24.2 10.7C442.7 382.4 385.2 376 320 376c-65.6 0-123.4 6.5-169.3 14.4c-9.8 1.7-19.7-2.9-24.7-11.5s-4.3-19.4 1.9-27.2L197.3 265c4.6-5.7 11.4-9 18.7-9s14.2 3.3 18.7 9l26.4 33.1 87-127.6c4.5-6.6 11.9-10.5 19.8-10.5z"/></svg>
|
Before Width: | Height: | Size: 890 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M410.3 231l11.3-11.3-33.9-33.9-62.1-62.1L291.7 89.8l-11.3 11.3-22.6 22.6L58.6 322.9c-10.4 10.4-18 23.3-22.2 37.4L1 480.7c-2.5 8.4-.2 17.5 6.1 23.7s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L387.7 253.7 410.3 231zM160 399.4l-9.1 22.7c-4 3.1-8.5 5.4-13.3 6.9L59.4 452l23-78.1c1.4-4.9 3.8-9.4 6.9-13.3l22.7-9.1v32c0 8.8 7.2 16 16 16h32zM362.7 18.7L348.3 33.2 325.7 55.8 314.3 67.1l33.9 33.9 62.1 62.1 33.9 33.9 11.3-11.3 22.6-22.6 14.5-14.5c25-25 25-65.5 0-90.5L453.3 18.7c-25-25-65.5-25-90.5 0zm-47.4 168l-144 144c-6.2 6.2-16.4 6.2-22.6 0s-6.2-16.4 0-22.6l144-144c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z"/></svg>
|
Before Width: | Height: | Size: 863 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 0C78.3 0 64 14.3 64 32v96h64V32c0-17.7-14.3-32-32-32zM288 0c-17.7 0-32 14.3-32 32v96h64V32c0-17.7-14.3-32-32-32zM32 160c-17.7 0-32 14.3-32 32s14.3 32 32 32v32c0 77.4 55 142 128 156.8V480c0 17.7 14.3 32 32 32s32-14.3 32-32V412.8c12.3-2.5 24.1-6.4 35.1-11.5c-2.1-10.8-3.1-21.9-3.1-33.3c0-80.3 53.8-148 127.3-169.2c.5-2.2 .7-4.5 .7-6.8c0-17.7-14.3-32-32-32H32zM432 512a144 144 0 1 0 0-288 144 144 0 1 0 0 288zm0-96a24 24 0 1 1 0 48 24 24 0 1 1 0-48zm0-144c8.8 0 16 7.2 16 16v80c0 8.8-7.2 16-16 16s-16-7.2-16-16V288c0-8.8 7.2-16 16-16z"/></svg>
|
Before Width: | Height: | Size: 783 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 0C78.3 0 64 14.3 64 32v96h64V32c0-17.7-14.3-32-32-32zM288 0c-17.7 0-32 14.3-32 32v96h64V32c0-17.7-14.3-32-32-32zM32 160c-17.7 0-32 14.3-32 32s14.3 32 32 32v32c0 77.4 55 142 128 156.8V480c0 17.7 14.3 32 32 32s32-14.3 32-32V412.8C297 398 352 333.4 352 256V224c17.7 0 32-14.3 32-32s-14.3-32-32-32H32z"/></svg>
|
Before Width: | Height: | Size: 549 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M240 80c0-17.7-14.3-32-32-32s-32 14.3-32 32V224H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H176V432c0 17.7 14.3 32 32 32s32-14.3 32-32V288H384c17.7 0 32-14.3 32-32s-14.3-32-32-32H240V80z"/></svg>
|
Before Width: | Height: | Size: 429 B |
Before Width: | Height: | Size: 4.8 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M0 224c0 17.7 14.3 32 32 32s32-14.3 32-32c0-53 43-96 96-96H320v32c0 12.9 7.8 24.6 19.8 29.6s25.7 2.2 34.9-6.9l64-64c12.5-12.5 12.5-32.8 0-45.3l-64-64c-9.2-9.2-22.9-11.9-34.9-6.9S320 19.1 320 32V64H160C71.6 64 0 135.6 0 224zm512 64c0-17.7-14.3-32-32-32s-32 14.3-32 32c0 53-43 96-96 96H192V352c0-12.9-7.8-24.6-19.8-29.6s-25.7-2.2-34.9 6.9l-64 64c-12.5 12.5-12.5 32.8 0 45.3l64 64c9.2 9.2 22.9 11.9 34.9 6.9s19.8-16.6 19.8-29.6V448H352c88.4 0 160-71.6 160-160z"/></svg>
|
Before Width: | Height: | Size: 705 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M256 192l-39.5-39.5c4.9-12.6 7.5-26.2 7.5-40.5C224 50.1 173.9 0 112 0S0 50.1 0 112s50.1 112 112 112c14.3 0 27.9-2.7 40.5-7.5L192 256l-39.5 39.5c-12.6-4.9-26.2-7.5-40.5-7.5C50.1 288 0 338.1 0 400s50.1 112 112 112s112-50.1 112-112c0-14.3-2.7-27.9-7.5-40.5L499.2 76.8c7.1-7.1 7.1-18.5 0-25.6c-28.3-28.3-74.1-28.3-102.4 0L256 192zm22.6 150.6L396.8 460.8c28.3 28.3 74.1 28.3 102.4 0c7.1-7.1 7.1-18.5 0-25.6L342.6 278.6l-64 64zM64 112a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm48 240a48 48 0 1 1 0 96 48 48 0 1 1 0-96z"/></svg>
|
Before Width: | Height: | Size: 754 B |
Before Width: | Height: | Size: 5.0 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M0 416c0-17.7 14.3-32 32-32l54.7 0c12.3-28.3 40.5-48 73.3-48s61 19.7 73.3 48L480 384c17.7 0 32 14.3 32 32s-14.3 32-32 32l-246.7 0c-12.3 28.3-40.5 48-73.3 48s-61-19.7-73.3-48L32 448c-17.7 0-32-14.3-32-32zm192 0a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zM384 256a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm-32-80c32.8 0 61 19.7 73.3 48l54.7 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-54.7 0c-12.3 28.3-40.5 48-73.3 48s-61-19.7-73.3-48L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l246.7 0c12.3-28.3 40.5-48 73.3-48zM192 64a32 32 0 1 0 0 64 32 32 0 1 0 0-64zm73.3 0L480 64c17.7 0 32 14.3 32 32s-14.3 32-32 32l-214.7 0c-12.3 28.3-40.5 48-73.3 48s-61-19.7-73.3-48L32 128C14.3 128 0 113.7 0 96S14.3 64 32 64l86.7 0C131 35.7 159.2 16 192 16s61 19.7 73.3 48z"/></svg>
|
Before Width: | Height: | Size: 977 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M304 48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zm0 416c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM48 304c26.5 0 48-21.5 48-48s-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48zm464-48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM142.9 437c18.7-18.7 18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zm0-294.2c18.7-18.7 18.7-49.1 0-67.9S93.7 56.2 75 75s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zM369.1 437c18.7 18.7 49.1 18.7 67.9 0s18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9z"/></svg>
|
Before Width: | Height: | Size: 805 B |
Before Width: | Height: | Size: 497 B |
Before Width: | Height: | Size: 520 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M135.2 17.7C140.6 6.8 151.7 0 163.8 0H284.2c12.1 0 23.2 6.8 28.6 17.7L320 32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32h96l7.2-14.3zM32 128H416V448c0 35.3-28.7 64-64 64H96c-35.3 0-64-28.7-64-64V128zm96 64c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16z"/></svg>
|
Before Width: | Height: | Size: 735 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 128a128 128 0 1 1 256 0A128 128 0 1 1 96 128zM0 482.3C0 383.8 79.8 304 178.3 304h91.4C368.2 304 448 383.8 448 482.3c0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3zM625 177L497 305c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L591 143c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"/></svg>
|
Before Width: | Height: | Size: 569 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 128a128 128 0 1 1 256 0A128 128 0 1 1 96 128zM0 482.3C0 383.8 79.8 304 178.3 304h91.4C368.2 304 448 383.8 448 482.3c0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3zM609.3 512H471.4c5.4-9.4 8.6-20.3 8.6-32v-8c0-60.7-27.1-115.2-69.8-151.8c2.4-.1 4.7-.2 7.1-.2h61.4C567.8 320 640 392.2 640 481.3c0 17-13.8 30.7-30.7 30.7zM432 256c-31 0-59-12.6-79.3-32.9C372.4 196.5 384 163.6 384 128c0-26.8-6.6-52.1-18.3-74.3C384.3 40.1 407.2 32 432 32c61.9 0 112 50.1 112 112s-50.1 112-112 112z"/></svg>
|
Before Width: | Height: | Size: 737 B |
@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 640 512"
|
||||
version="1.1"
|
||||
id="svg12"
|
||||
sodipodi:docname="user-group-solidplus.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs16" />
|
||||
<sodipodi:namedview
|
||||
id="namedview14"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.10144043"
|
||||
inkscape:cx="-872.43321"
|
||||
inkscape:cy="1044.9483"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg12" />
|
||||
<!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||
<path
|
||||
d="M96 128a128 128 0 1 1 256 0A128 128 0 1 1 96 128zM0 482.3C0 383.8 79.8 304 178.3 304h91.4C368.2 304 448 383.8 448 482.3c0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3zM609.3 512H471.4c5.4-9.4 8.6-20.3 8.6-32v-8c0-60.7-27.1-115.2-69.8-151.8c2.4-.1 4.7-.2 7.1-.2h61.4C567.8 320 640 392.2 640 481.3c0 17-13.8 30.7-30.7 30.7zM432 256c-31 0-59-12.6-79.3-32.9C372.4 196.5 384 163.6 384 128c0-26.8-6.6-52.1-18.3-74.3C384.3 40.1 407.2 32 432 32c61.9 0 112 50.1 112 112s-50.1 112-112 112z"
|
||||
id="path10" />
|
||||
<path
|
||||
id="rect1922"
|
||||
style="fill:#000000;stroke:#ffffff;stroke-width:50;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
d="m 519.31323,191.69297 v 65.34961 h -65.34961 v 47.05274 h 65.34961 v 65.3496 h 47.05274 v -65.3496 h 65.34961 v -47.05274 h -65.34961 v -65.34961 z" />
|
||||
</svg>
|
Before Width: | Height: | Size: 2.0 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H322.8c-3.1-8.8-3.7-18.4-1.4-27.8l15-60.1c2.8-11.3 8.6-21.5 16.8-29.7l40.3-40.3c-32.1-31-75.7-50.1-123.9-50.1H178.3zm435.5-68.3c-15.6-15.6-40.9-15.6-56.6 0l-29.4 29.4 71 71 29.4-29.4c15.6-15.6 15.6-40.9 0-56.6l-14.4-14.4zM375.9 417c-4.1 4.1-7 9.2-8.4 14.9l-15 60.1c-1.4 5.5 .2 11.2 4.2 15.2s9.7 5.6 15.2 4.2l60.1-15c5.6-1.4 10.8-4.3 14.9-8.4L576.1 358.7l-71-71L375.9 417z"/></svg>
|
Before Width: | Height: | Size: 728 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 128a128 128 0 1 1 256 0A128 128 0 1 1 96 128zM0 482.3C0 383.8 79.8 304 178.3 304h91.4C368.2 304 448 383.8 448 482.3c0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3zM504 312V248H440c-13.3 0-24-10.7-24-24s10.7-24 24-24h64V136c0-13.3 10.7-24 24-24s24 10.7 24 24v64h64c13.3 0 24 10.7 24 24s-10.7 24-24 24H552v64c0 13.3-10.7 24-24 24s-24-10.7-24-24z"/></svg>
|
Before Width: | Height: | Size: 605 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L353.3 251.6C407.9 237 448 187.2 448 128C448 57.3 390.7 0 320 0C250.2 0 193.5 55.8 192 125.2L38.8 5.1zM264.3 304.3C170.5 309.4 96 387.2 96 482.3c0 16.4 13.3 29.7 29.7 29.7H514.3c3.9 0 7.6-.7 11-2.1l-261-205.6z"/></svg>
|
Before Width: | Height: | Size: 564 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z"/></svg>
|
Before Width: | Height: | Size: 427 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M54.2 202.9C123.2 136.7 216.8 96 320 96s196.8 40.7 265.8 106.9c12.8 12.2 33 11.8 45.2-.9s11.8-33-.9-45.2C549.7 79.5 440.4 32 320 32S90.3 79.5 9.8 156.7C-2.9 169-3.3 189.2 8.9 202s32.5 13.2 45.2 .9zM320 256c56.8 0 108.6 21.1 148.2 56c13.3 11.7 33.5 10.4 45.2-2.8s10.4-33.5-2.8-45.2C459.8 219.2 393 192 320 192s-139.8 27.2-190.5 72c-13.3 11.7-14.5 31.9-2.8 45.2s31.9 14.5 45.2 2.8c39.5-34.9 91.3-56 148.2-56zm64 160a64 64 0 1 0 -128 0 64 64 0 1 0 128 0z"/></svg>
|
Before Width: | Height: | Size: 699 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/></svg>
|
Before Width: | Height: | Size: 527 B |
2510
public/index.html
@ -18,8 +18,14 @@
|
||||
<h2>Advanced Formatting</h2>
|
||||
<p>
|
||||
The settings provided in this section allow for a more control over the prompt building strategy.
|
||||
Most specifics of the prompt building depend on whether a Pygmalion model is selected or special formatting is force enabled.
|
||||
The core differences between the formatting schemas are listed below.
|
||||
</p>
|
||||
<h3>For <u>Pygmalion</u> models</h3>
|
||||
<h3>Custom Chat Separator</h3>
|
||||
<p>
|
||||
Overrides the default separators controlled by "Disable example chats formatting" and "Disable chat start formatting" options (see below).
|
||||
</p>
|
||||
<h3>For <u>Pygmalion</u> formatting</h3>
|
||||
<h4>Disable description formatting</h4>
|
||||
<p>
|
||||
<code><b>NAME's Persona: </b></code> won't be prepended to the content your character's Description box.
|
||||
@ -32,11 +38,21 @@
|
||||
<p>
|
||||
<code><b>Personality: </b></code> won't be prepended to the content your character's Personality box.
|
||||
</p>
|
||||
<h4>Disable example chats formatting</h4>
|
||||
<p>
|
||||
<code><START></code> is not added at the beginning of each example message block.<br>
|
||||
<i>(If custom separator is not set)</i>
|
||||
</p>
|
||||
<h4>Disable chat start formatting</h4>
|
||||
<p>
|
||||
<code><START></code> is not added before the between the character card and the chat log.<br>
|
||||
<i>(If custom separator is not set)</i>
|
||||
</p>
|
||||
<h4>Always add character's name to prompt</h4>
|
||||
<p>
|
||||
Doesn't do anything (Included in Pygmalion formatting).
|
||||
</p>
|
||||
<h3>For <u>non-Pygmalion</u> models</h3>
|
||||
<h3>For <u>non-Pygmalion</u> formatting</h3>
|
||||
<h4>Disable description formatting</h4>
|
||||
<p>
|
||||
Has no effect.
|
||||
@ -49,6 +65,16 @@
|
||||
<p>
|
||||
<code><b>NAME's personality: </b></code> won't be prepended to the content your character's Personality box.
|
||||
</p>
|
||||
<h4>Disable example chats formatting</h4>
|
||||
<p>
|
||||
<code>This is how <b>Character</b> should talk</code> is not added at the beginning of each example message block.<br>
|
||||
<i>(If custom separator is not set)</i>
|
||||
</p>
|
||||
<h4>Disable chat start formatting</h4>
|
||||
<p>
|
||||
<code>Then the roleplay chat between <b>User</b> and <b>Character</b> begins</code> is not added before the between the character card and the chat log.<br>
|
||||
<i>(If custom separator is not set)</i>
|
||||
</p>
|
||||
<h4>Always add character's name to prompt</h4>
|
||||
<p>
|
||||
Appends character's name to the prompt to force model to complete the message as a character:
|
||||
|
@ -24,7 +24,7 @@
|
||||
Plays at 80% volume.
|
||||
</p>
|
||||
<p>
|
||||
If "Sound only for unfocused window" option is enabled, the sound plays only if TavernAI window is <b>unfocused</b>.
|
||||
If "Background Sound Only" option is enabled, the sound plays only if TavernAI window is <b>unfocused</b>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -16,11 +16,14 @@
|
||||
<div id="main">
|
||||
<div id="content">
|
||||
<h2>Multigen</h2>
|
||||
<p>TavernAI tries to create longer responses by chaining the generation using smaller batches.</p>
|
||||
<p>TavernAI tries to create faster and longer responses by chaining the generation using smaller batches.</p>
|
||||
<h3>Default settings:</h3>
|
||||
<p>First batch = 50 tokens</p>
|
||||
<p>Next batches = 30 tokens</p>
|
||||
<h3>Algorithm:</h3>
|
||||
<p>1. If amount of generation is more than 50 tokens, then generate first 50 tokens.</p>
|
||||
<p>2. Generate by 30 tokens until one of the stopping conditions is reached.</p>
|
||||
<p>3. Append the generated batch to the next cycle's prompt.</p>
|
||||
<p>1. Generate the first batch (if amount of generation setting is more than batch length).</p>
|
||||
<p>2. Generate next batch of tokens until one of the stopping conditions is reached.</p>
|
||||
<p>3. Append the generated text to the next cycle's prompt.</p>
|
||||
<h3>Stopping conditions:</h3>
|
||||
<p>1. Generated enough text.</p>
|
||||
<p>2. Character starts speaking for You.</p>
|
||||
|
28
public/notes/textgen_streaming.html
Normal file
@ -0,0 +1,28 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Gradio Streaming Function ID</title>
|
||||
<link rel="stylesheet" href="/css/notes.css">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
|
||||
rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="main">
|
||||
<div id="content">
|
||||
<p>
|
||||
To use streaming with Text Generation Web UI, a Gradio function index needs to be provided.
|
||||
It is impossible to be determined programmatically and should be typed in manually.
|
||||
If the streaming doesn't work with the default value, get the most recent function ID here:
|
||||
<a href="https://github.com/oobabooga/text-generation-webui/blob/main/api-example-stream.py#L15">GRADIO_FN</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
68
public/notes/token-limits.html
Normal file
@ -0,0 +1,68 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Character Tokens</title>
|
||||
<link rel="stylesheet" href="/css/notes.css">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="main">
|
||||
<div id="content">
|
||||
<h2>Character Tokens</h2>
|
||||
|
||||
<p><b>TLDR: If you're working with an AI model with a 2048 context token limit, your 1000 token character definition is cutting the AI's 'memory' in half.</b></p>
|
||||
<p>To put this in perspective, a decent response from a good AI can easily be around 200-300 tokens. In this case, the AI would only be able to 'remember' about 3 exchanges worth of chat history.</p>
|
||||
<hr>
|
||||
|
||||
<h3>Why did my character's token counter turn red?</h3>
|
||||
<p>When we see your character has over 1000 tokens in its definitions, we highlight it for you because this can lower the AI's capabilities to provide an enjoyable conversation.</p>
|
||||
|
||||
<h3>What happens if my Character has too many tokens?</h3>
|
||||
<p>Don't Worry - it won't break anything. At worst, if the Character's permanent tokens are too large, it simply means there will be less room left in the context for other things (see below).</p>
|
||||
<p>The only negative side effect this can have is the AI will have less 'memory', as it will have less chat history available to process.</p>
|
||||
<p>This is because every AI model has a limit to the amount of context it can process at one time.</p>
|
||||
<h3>'Context'?</h3>
|
||||
<p>This is the information that gets sent to the AI each time you ask it to generate a response:</p>
|
||||
<ul>
|
||||
<li>Character definitions</li>
|
||||
<li>Chat history</li>
|
||||
<li>Author's Notes</li>
|
||||
<li>Special Format strings</li>
|
||||
<li>[bracket commands]</li>
|
||||
</ul>
|
||||
|
||||
<p>SillyTavern automatically calculates the best way to allocate the available context tokens before sending the information to the AI model.</p>
|
||||
|
||||
<h3>What are a Character's 'Permanent Tokens'?</h3>
|
||||
<p>These will always be sent to the AI with every generation request:</p>
|
||||
<ul>
|
||||
<li>Character Name (keep the name short! Sent at the start of EVERY Character message)</li>
|
||||
<li>Character Description Box</li>
|
||||
<li>Character Personality Box</li>
|
||||
<li>Scenario Box</li>
|
||||
</ul>
|
||||
<h3>What parts of a Character's Definitions are NOT permanent?</h3>
|
||||
<ul>
|
||||
<li>The first message box - only sent once at the start of the chat.</li>
|
||||
<li>Example messages box - only kept until chat history fills up the context (optionally these can be forced to be kept in context)</li>
|
||||
</ul>
|
||||
|
||||
<h3>Popular AI Model Context Token Limits</h3>
|
||||
<ul>
|
||||
<li>Older models below 6B parameters - 1024</li>
|
||||
<li>Pygmalion 6B - 2048</li>
|
||||
<li>Poe.com (Claude-instant or ChatGPT) - 2048</li>
|
||||
<li>OpenAI ChatGPT - 4000-ish?</li>
|
||||
<li>OpenAI GPT-4 - 8000?</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
850
public/script.js
@ -1,5 +1,4 @@
|
||||
esversion: 6
|
||||
import { encode } from "../scripts/gpt-2-3-tokenizer/mod.js";
|
||||
|
||||
import {
|
||||
Generate,
|
||||
@ -11,6 +10,8 @@ import {
|
||||
nai_settings,
|
||||
api_server_textgenerationwebui,
|
||||
is_send_press,
|
||||
getTokenCount,
|
||||
max_context,
|
||||
|
||||
} from "../script.js";
|
||||
|
||||
@ -121,51 +122,56 @@ function RA_CountCharTokens() {
|
||||
});
|
||||
|
||||
//count total tokens, including those that will be removed from context once chat history is long
|
||||
count_tokens = encode(JSON.stringify(
|
||||
count_tokens = getTokenCount(JSON.stringify(
|
||||
create_save_name +
|
||||
create_save_description +
|
||||
create_save_personality +
|
||||
create_save_scenario +
|
||||
create_save_first_message +
|
||||
create_save_mes_example
|
||||
)).length;
|
||||
));
|
||||
|
||||
//count permanent tokens that will never get flushed out of context
|
||||
perm_tokens = encode(JSON.stringify(
|
||||
perm_tokens = getTokenCount(JSON.stringify(
|
||||
create_save_name +
|
||||
create_save_description +
|
||||
create_save_personality +
|
||||
create_save_scenario
|
||||
)).length;
|
||||
));
|
||||
|
||||
} else {
|
||||
if (this_chid !== undefined && this_chid !== "invalid-safety-id") { // if we are counting a valid pre-saved char
|
||||
|
||||
//same as above, all tokens including temporary ones
|
||||
count_tokens = encode(
|
||||
count_tokens = getTokenCount(
|
||||
JSON.stringify(
|
||||
characters[this_chid].description +
|
||||
characters[this_chid].personality +
|
||||
characters[this_chid].scenario +
|
||||
characters[this_chid].first_mes +
|
||||
characters[this_chid].mes_example
|
||||
)).length;
|
||||
));
|
||||
|
||||
//permanent tokens count
|
||||
perm_tokens = encode(
|
||||
perm_tokens = getTokenCount(
|
||||
JSON.stringify(
|
||||
characters[this_chid].name +
|
||||
characters[this_chid].description +
|
||||
characters[this_chid].personality +
|
||||
characters[this_chid].scenario +
|
||||
(power_user.pin_examples ? characters[this_chid].mes_example : '') // add examples to permanent if they are pinned
|
||||
)).length;
|
||||
));
|
||||
} else { console.log("RA_TC -- no valid char found, closing."); } // if neither, probably safety char or some error in loading
|
||||
}
|
||||
// display the counted tokens
|
||||
if (count_tokens < 1024 && perm_tokens < 1024) {
|
||||
$("#result_info").html(count_tokens + " Tokens (" + perm_tokens + " Permanent Tokens)"); //display normal if both counts are under 1024
|
||||
} else { $("#result_info").html("<font color=red>" + count_tokens + " Tokens (" + perm_tokens + " Permanent Tokens)(TOO MANY)</font>"); } //warn if either are over 1024
|
||||
} else {
|
||||
$("#result_info").html(`
|
||||
<span class="neutral_warning">${count_tokens}</span> Tokens (<span class="neutral_warning">${perm_tokens}</span><span> Permanent Tokens)
|
||||
<br>
|
||||
<div id="chartokenwarning" class="menu_button whitespacenowrap"><a href="/notes/token-limits.html" target="_blank">Learn More About Token 'Limits'</a></div>`);
|
||||
} //warn if either are over 1024
|
||||
}
|
||||
//Auto Load Last Charcter -- (fires when active_character is defined and auto_load_chat is true)
|
||||
async function RA_autoloadchat() {
|
||||
@ -203,22 +209,21 @@ function RA_checkOnlineStatus() {
|
||||
$("#send_textarea").attr("placeholder", "Not connected to API!"); //Input bar placeholder tells users they are not connected
|
||||
$("#send_form").addClass('no-connection'); //entire input form area is red when not connected
|
||||
$("#send_but").css("display", "none"); //send button is hidden when not connected;
|
||||
$("#API-status-top").addClass("redOverlayGlow");
|
||||
$("#API-status-top").removeClass("fa-plug");
|
||||
$("#API-status-top").addClass("fa-plug-circle-exclamation redOverlayGlow");
|
||||
connection_made = false;
|
||||
} else {
|
||||
if (online_status !== undefined && online_status !== "no_connection") {
|
||||
$("#send_textarea").attr("placeholder", "Type a message..."); //on connect, placeholder tells user to type message
|
||||
const formColor = power_user.fast_ui_mode ? "var(--black90a)" : "var(--black60a)";
|
||||
/* console.log("RA-AC -- connected, coloring input as " + formColor); */
|
||||
$('#send_form').removeClass("no-connection");
|
||||
$("#send_form").css("background-color", formColor); //on connect, form BG changes to transprent black
|
||||
$("#API-status-top").removeClass("redOverlayGlow");
|
||||
$("#API-status-top").removeClass("fa-plug-circle-exclamation redOverlayGlow");
|
||||
$("#API-status-top").addClass("fa-plug");
|
||||
connection_made = true;
|
||||
retry_delay = 100;
|
||||
RA_AC_retries = 1;
|
||||
|
||||
if (!is_send_press && !(selected_group && is_group_generating)) {
|
||||
$("#send_but").css("display", "inline"); //on connect, send button shows
|
||||
$("#send_but").css("display", "flex"); //on connect, send button shows
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -286,10 +291,10 @@ function OpenNavPanels() {
|
||||
console.log("RA -- clicking right nav to open");
|
||||
$("#rightNavDrawerIcon").click();
|
||||
} else {
|
||||
console.log('didnt see reason to open right nav on load: ' +
|
||||
LoadLocalBool("NavLockOn")
|
||||
+ ' nav open pref' +
|
||||
LoadLocalBool("NavOpened" == true));
|
||||
/* console.log('didnt see reason to open right nav on load: R-nav locked? ' +
|
||||
LoadLocalBool("NavLockOn")
|
||||
+ ' R-nav was open before? ' +
|
||||
LoadLocalBool("NavOpened" == true)); */
|
||||
}
|
||||
|
||||
//auto-open L nav if locked and previously open
|
||||
@ -298,13 +303,162 @@ function OpenNavPanels() {
|
||||
console.log("RA -- clicking left nav to open");
|
||||
$("#leftNavDrawerIcon").click();
|
||||
} else {
|
||||
console.log('didnt see reason to open left nav on load: ' +
|
||||
LoadLocalBool("LNavLockOn")
|
||||
+ ' L-nav open pref' +
|
||||
LoadLocalBool("LNavOpened" == true));
|
||||
/* console.log('didnt see reason to open left nav on load: L-Nav Locked? ' +
|
||||
LoadLocalBool("LNavLockOn")
|
||||
+ ' L-nav was open before? ' +
|
||||
LoadLocalBool("LNavOpened" == true)); */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Make the DIV element draggable:
|
||||
dragElement(document.getElementById("sheld"));
|
||||
dragElement(document.getElementById("left-nav-panel"));
|
||||
dragElement(document.getElementById("right-nav-panel"));
|
||||
setTimeout(function () {
|
||||
dragElement(document.getElementById("expression-holder"))
|
||||
}, 2000);
|
||||
|
||||
|
||||
function dragElement(elmnt) {
|
||||
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
|
||||
if (document.getElementById(elmnt.id + "header")) { //ex: id="sheldheader"
|
||||
// if present, the header is where you move the DIV from, but this overrides everything else:
|
||||
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
|
||||
} else {
|
||||
// otherwise, move the DIV from anywhere inside the DIV, b:
|
||||
elmnt.onmousedown = dragMouseDown;
|
||||
}
|
||||
|
||||
function dragMouseDown(e) {
|
||||
e = e || window.event;
|
||||
e.preventDefault();
|
||||
// get the mouse cursor position at startup:
|
||||
pos3 = e.clientX; //mouse X at click
|
||||
pos4 = e.clientY; //mouse Y at click
|
||||
document.onmouseup = closeDragElement;
|
||||
// call a function whenever the cursor moves:
|
||||
document.onmousemove = elementDrag;
|
||||
}
|
||||
|
||||
function elementDrag(e) {
|
||||
//disable scrollbars when dragging to prevent jitter
|
||||
$("body").css("overflow", "hidden");
|
||||
|
||||
|
||||
//get window size
|
||||
let winWidth = window.innerWidth;
|
||||
let winHeight = window.innerHeight;
|
||||
|
||||
//get necessary data for calculating element footprint
|
||||
let draggableHeight = parseInt(getComputedStyle(elmnt).getPropertyValue('height').slice(0, -2));
|
||||
let draggableWidth = parseInt(getComputedStyle(elmnt).getPropertyValue('width').slice(0, -2));
|
||||
let draggableTop = parseInt(getComputedStyle(elmnt).getPropertyValue('top').slice(0, -2));
|
||||
let draggableLeft = parseInt(getComputedStyle(elmnt).getPropertyValue('left').slice(0, -2));
|
||||
let sheldWidth = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sheldWidth').slice(0, -2));
|
||||
let topBarFirstX = (winWidth - sheldWidth) / 2;
|
||||
let topBarLastX = topBarFirstX + sheldWidth;
|
||||
|
||||
//set the lowest and most-right pixel the element touches
|
||||
let maxX = (draggableWidth + draggableLeft);
|
||||
let maxY = (draggableHeight + draggableTop);
|
||||
|
||||
// calculate the new cursor position:
|
||||
e = e || window.event;
|
||||
e.preventDefault();
|
||||
|
||||
pos1 = pos3 - e.clientX; //X change amt
|
||||
pos2 = pos4 - e.clientY; //Y change amt
|
||||
pos3 = e.clientX; //new mouse X
|
||||
pos4 = e.clientY; //new mouse Y
|
||||
|
||||
|
||||
|
||||
//fix over/underflows:
|
||||
|
||||
setTimeout(function () {
|
||||
if (elmnt.offsetTop < 40) {
|
||||
/* console.log('6'); */
|
||||
if (maxX > topBarFirstX && maxX < topBarLastX) {
|
||||
/* console.log('maxX inside topBar!'); */
|
||||
elmnt.style.top = "42px";
|
||||
}
|
||||
if (elmnt.offsetLeft < topBarLastX && elmnt.offsetLeft > topBarFirstX) {
|
||||
/* console.log('offsetLeft inside TopBar!'); */
|
||||
elmnt.style.top = "42px";
|
||||
}
|
||||
}
|
||||
|
||||
if (elmnt.offsetTop - pos2 <= 0) {
|
||||
/* console.log('1'); */
|
||||
//prevent going out of window top + 42px barrier for TopBar (can hide grabber)
|
||||
elmnt.style.top = "0px";
|
||||
}
|
||||
|
||||
if (elmnt.offsetLeft - pos1 <= 0) {
|
||||
/* console.log('2'); */
|
||||
//prevent moving out of window left
|
||||
elmnt.style.left = "0px";
|
||||
}
|
||||
|
||||
if (maxX >= winWidth) {
|
||||
/* console.log('3'); */
|
||||
//bounce off right
|
||||
elmnt.style.left = elmnt.offsetLeft - 10 + "px";
|
||||
}
|
||||
|
||||
if (maxY >= winHeight) {
|
||||
/* console.log('4'); */
|
||||
//bounce off bottom
|
||||
elmnt.style.top = elmnt.offsetTop - 10 + "px";
|
||||
if (elmnt.offsetTop - pos2 <= 40) {
|
||||
/* console.log('5'); */
|
||||
//prevent going out of window top + 42px barrier for TopBar (can hide grabber)
|
||||
/* console.log('caught Y bounce to <40Y top'); */
|
||||
elmnt.style.top = "20px";
|
||||
}
|
||||
}
|
||||
// if no problems, set element's new position
|
||||
/* console.log('7'); */
|
||||
|
||||
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
|
||||
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
|
||||
$(elmnt).css("bottom", "unset");
|
||||
$(elmnt).css("right", "unset");
|
||||
|
||||
/* console.log(`
|
||||
offsetLeft: ${elmnt.offsetLeft}, offsetTop: ${elmnt.offsetTop}
|
||||
winWidth: ${winWidth}, winHeight: ${winHeight}
|
||||
sheldWidth: ${sheldWidth}
|
||||
X: ${elmnt.style.left}
|
||||
Y: ${elmnt.style.top}
|
||||
MaxX: ${maxX}, MaxY: ${maxY}
|
||||
Topbar 1st X: ${((winWidth - sheldWidth) / 2)}
|
||||
TopBar lastX: ${((winWidth - sheldWidth) / 2) + sheldWidth}
|
||||
`); */
|
||||
|
||||
|
||||
|
||||
}, 50)
|
||||
|
||||
/* console.log("left/top: " + (elmnt.offsetLeft - pos1) + "/" + (elmnt.offsetTop - pos2) +
|
||||
", win: " + winWidth + "/" + winHeight +
|
||||
", max X / Y: " + maxX + " / " + maxY); */
|
||||
|
||||
}
|
||||
|
||||
function closeDragElement() {
|
||||
// stop moving when mouse button is released:
|
||||
document.onmouseup = null;
|
||||
document.onmousemove = null;
|
||||
//revert scrolling to normal after drag to allow recovery of vastly misplaced elements
|
||||
$("body").css("overflow", "auto");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
$("document").ready(function () {
|
||||
// initial status check
|
||||
setTimeout(RA_checkOnlineStatus, 100);
|
||||
|
@ -7,6 +7,8 @@ import {
|
||||
system_message_types,
|
||||
this_chid,
|
||||
openCharacterChat,
|
||||
chat_metadata,
|
||||
callPopup,
|
||||
} from "../script.js";
|
||||
import { selected_group } from "./group-chats.js";
|
||||
|
||||
@ -36,27 +38,40 @@ async function getExistingChatNames() {
|
||||
}
|
||||
}
|
||||
|
||||
async function getBookmarkName(currentChat) {
|
||||
async function getBookmarkName() {
|
||||
const chatNames = await getExistingChatNames();
|
||||
let mainChat = getMainChatName(currentChat);
|
||||
let newChat = Date.now();
|
||||
let friendlyName = '';
|
||||
const popupText = `<h3>Enter the bookmark name:<h3>
|
||||
<small>Using existing name will overwrite your bookmark chat.
|
||||
<br>Leave empty to auto-generate.</small>`;
|
||||
let name = await callPopup(popupText, 'input');
|
||||
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
friendlyName = `${bookmarkNameToken}${i}`;
|
||||
newChat = `${mainChat} ${friendlyName}`;
|
||||
if (!chatNames.includes(newChat)) {
|
||||
break;
|
||||
if (name === false) {
|
||||
return null;
|
||||
}
|
||||
else if (name === '') {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
name = bookmarkNameToken + i;
|
||||
if (!chatNames.includes(name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { newChat, friendlyName };
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
function getMainChatName(currentChat) {
|
||||
if (currentChat.includes(bookmarkNameToken)) {
|
||||
currentChat = currentChat.substring(0, currentChat.lastIndexOf(bookmarkNameToken)).trim();
|
||||
function getMainChatName() {
|
||||
if (chat_metadata) {
|
||||
if (chat_metadata['main_chat']) {
|
||||
return chat_metadata['main_chat'];
|
||||
}
|
||||
else if (characters[this_chid].chat && characters[this_chid].chat.includes(bookmarkNameToken)) {
|
||||
const tokenIndex = characters[this_chid].chat.lastIndexOf(bookmarkNameToken);
|
||||
chat_metadata['main_chat'] = characters[this_chid].chat.substring(0, tokenIndex).trim();
|
||||
return chat_metadata['main_chat'];
|
||||
}
|
||||
}
|
||||
return currentChat;
|
||||
return null;
|
||||
}
|
||||
|
||||
function showBookmarksButtons() {
|
||||
@ -67,7 +82,7 @@ function showBookmarksButtons() {
|
||||
$("#option_new_bookmark").hide();
|
||||
}
|
||||
// In main chat
|
||||
else if (!characters[this_chid].chat.includes(bookmarkNameToken)) {
|
||||
else if (!chat_metadata['main_chat']) {
|
||||
$("#option_back_to_main").hide();
|
||||
$("#option_new_bookmark").show();
|
||||
|
||||
@ -91,10 +106,15 @@ $(document).ready(function () {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
let { newChat, friendlyName } = await getBookmarkName(characters[this_chid].chat);
|
||||
let name = await getBookmarkName(characters[this_chid].chat);
|
||||
|
||||
saveChat(newChat);
|
||||
let mainMessage = stringFormat(system_messages[system_message_types.BOOKMARK_CREATED].mes, newChat, friendlyName);
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newMetadata = { main_chat: characters[this_chid].chat };
|
||||
saveChat(name, newMetadata);
|
||||
let mainMessage = stringFormat(system_messages[system_message_types.BOOKMARK_CREATED].mes, name, name);
|
||||
sendSystemMessage(system_message_types.BOOKMARK_CREATED, mainMessage);
|
||||
saveChat();
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { callPopup, saveSettings, saveSettingsDebounced } from "../script.js";
|
||||
import { callPopup, saveSettings, saveSettingsDebounced, token } from "../script.js";
|
||||
import { isSubsetOf } from "./utils.js";
|
||||
export {
|
||||
getContext,
|
||||
@ -9,38 +9,13 @@ export {
|
||||
extension_settings,
|
||||
};
|
||||
|
||||
const extensionNames = ['caption', 'dice', 'expressions', 'floating-prompt', 'memory'];
|
||||
const manifests = await getManifests(extensionNames);
|
||||
|
||||
// TODO: Delete in next release
|
||||
function migrateFromLocalStorage() {
|
||||
const extensions_urlKey = 'extensions_url';
|
||||
const extensions_autoConnectKey = 'extensions_autoconnect';
|
||||
const extensions_disabledKey = 'extensions_disabled';
|
||||
|
||||
const apiUrl = localStorage.getItem(extensions_urlKey);
|
||||
const autoConnect = localStorage.getItem(extensions_autoConnectKey);
|
||||
const extensionsDisabled = localStorage.getItem(extensions_disabledKey);
|
||||
|
||||
if (apiUrl !== null) {
|
||||
extension_settings.apiUrl = apiUrl;
|
||||
localStorage.removeItem(extensions_urlKey);
|
||||
}
|
||||
|
||||
if (autoConnect !== null) {
|
||||
extension_settings.autoConnect = autoConnect;
|
||||
localStorage.removeItem(extensions_autoConnectKey);
|
||||
}
|
||||
|
||||
if (extensionsDisabled !== null) {
|
||||
extension_settings.disabledExtensions = JSON.parse(extensionsDisabled);
|
||||
localStorage.removeItem(extensions_disabledKey);
|
||||
}
|
||||
}
|
||||
let extensionNames = [];
|
||||
let manifests = [];
|
||||
const defaultUrl = "http://localhost:5100";
|
||||
|
||||
const extension_settings = {
|
||||
apiUrl: '',
|
||||
autoConnect: '',
|
||||
apiUrl: defaultUrl,
|
||||
autoConnect: false,
|
||||
disabledExtensions: [],
|
||||
memory: {},
|
||||
note: {
|
||||
@ -56,10 +31,27 @@ let activeExtensions = new Set();
|
||||
|
||||
const getContext = () => window['TavernAI'].getContext();
|
||||
const getApiUrl = () => extension_settings.apiUrl;
|
||||
const defaultUrl = "http://localhost:5100";
|
||||
const defaultRequestArgs = { method: 'GET', headers: { 'Bypass-Tunnel-Reminder': 'bypass' } };
|
||||
let connectedToApi = false;
|
||||
|
||||
async function discoverExtensions() {
|
||||
try {
|
||||
const response = await fetch('/discover_extensions', { headers: { 'X-CSRF-Token': token } });
|
||||
|
||||
if (response.ok) {
|
||||
const extensions = await response.json();
|
||||
return extensions;
|
||||
}
|
||||
else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function onDisableExtensionClick() {
|
||||
const name = $(this).data('name');
|
||||
disableExtension(name);
|
||||
@ -273,9 +265,7 @@ function showExtensionsDetails() {
|
||||
callPopup(`<div class="extensions_info">${html}</div>`, 'text');
|
||||
}
|
||||
|
||||
function loadExtensionSettings(settings) {
|
||||
migrateFromLocalStorage();
|
||||
|
||||
async function loadExtensionSettings(settings) {
|
||||
if (settings.extension_settings) {
|
||||
Object.assign(extension_settings, settings.extension_settings);
|
||||
}
|
||||
@ -284,6 +274,8 @@ function loadExtensionSettings(settings) {
|
||||
$("#extensions_autoconnect").prop('checked', extension_settings.autoConnect).trigger('input');
|
||||
|
||||
// Activate offline extensions
|
||||
extensionNames = await discoverExtensions();
|
||||
manifests = await getManifests(extensionNames)
|
||||
activateExtensions();
|
||||
}
|
||||
|
||||
|
129
public/scripts/extensions/backgrounds/index.js
Normal file
@ -0,0 +1,129 @@
|
||||
import { getContext } from "../../extensions.js";
|
||||
export { MODULE_NAME };
|
||||
|
||||
const MODULE_NAME = 'backgrounds';
|
||||
const METADATA_KEY = 'custom_background';
|
||||
const UPDATE_INTERVAL = 1000;
|
||||
|
||||
async function moduleWorker() {
|
||||
if (hasCustomBackground()) {
|
||||
$('#unlock_background').show();
|
||||
$('#lock_background').hide();
|
||||
setCustomBackground();
|
||||
}
|
||||
else {
|
||||
$('#unlock_background').hide();
|
||||
$('#lock_background').show();
|
||||
unsetCustomBackground();
|
||||
}
|
||||
}
|
||||
|
||||
function onLockBackgroundClick() {
|
||||
const bgImage = window.getComputedStyle(document.getElementById('bg1')).backgroundImage;
|
||||
|
||||
// Extract the URL from the CSS string
|
||||
const urlRegex = /url\((['"])?(.*?)\1\)/;
|
||||
const matches = bgImage.match(urlRegex);
|
||||
const url = matches[2];
|
||||
|
||||
// Remove the protocol and host, leaving the relative URL
|
||||
const relativeUrl = new URL(url).pathname;
|
||||
const relativeBgImage = `url("${relativeUrl}")`
|
||||
|
||||
saveBackgroundMetadata(relativeBgImage);
|
||||
setCustomBackground();
|
||||
$('#unlock_background').show();
|
||||
$('#lock_background').hide();
|
||||
}
|
||||
|
||||
function onUnlockBackgroundClick() {
|
||||
removeBackgroundMetadata();
|
||||
unsetCustomBackground();
|
||||
$('#unlock_background').hide();
|
||||
$('#lock_background').show();
|
||||
}
|
||||
|
||||
function hasCustomBackground() {
|
||||
const context = getContext();
|
||||
return !!context.chatMetadata[METADATA_KEY];
|
||||
}
|
||||
|
||||
function saveBackgroundMetadata(file) {
|
||||
const context = getContext();
|
||||
context.chatMetadata[METADATA_KEY] = file;
|
||||
context.saveChat();
|
||||
}
|
||||
|
||||
function removeBackgroundMetadata() {
|
||||
const context = getContext();
|
||||
delete context.chatMetadata[METADATA_KEY];
|
||||
context.saveChat();
|
||||
}
|
||||
|
||||
function setCustomBackground() {
|
||||
const context = getContext();
|
||||
const file = context.chatMetadata[METADATA_KEY];
|
||||
|
||||
// bg already set
|
||||
if (document.getElementById("bg_custom").style.backgroundImage == file) {
|
||||
return;
|
||||
}
|
||||
|
||||
$("#bg_custom").css("background-image", file);
|
||||
$("#custom_bg_preview").css("background-image", file);
|
||||
}
|
||||
|
||||
function unsetCustomBackground() {
|
||||
$("#bg_custom").css("background-image", 'none');
|
||||
$("#custom_bg_preview").css("background-image", 'none');
|
||||
}
|
||||
|
||||
function onSelectBackgroundClick() {
|
||||
const bgfile = $(this).attr("bgfile");
|
||||
|
||||
if (hasCustomBackground()) {
|
||||
saveBackgroundMetadata(`url("backgrounds/${bgfile}")`);
|
||||
setCustomBackground();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
function addSettings() {
|
||||
const html = `
|
||||
<div class="background_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Character Backgrounds</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<div class="background_controls">
|
||||
<div id="lock_background" class="menu_button">
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
Lock
|
||||
</div>
|
||||
<div id="unlock_background" class="menu_button">
|
||||
<i class="fa-solid fa-unlock"></i>
|
||||
Unlock
|
||||
</div>
|
||||
<small>
|
||||
Press "Lock" to assign a currently selected background to a character or group chat.<br>
|
||||
Any background image selected while lock is engaged will be saved automatically.
|
||||
</small>
|
||||
</div>
|
||||
<div>Preview</div>
|
||||
<div id="custom_bg_preview">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#extensions_settings').append(html);
|
||||
$('#lock_background').on('click', onLockBackgroundClick);
|
||||
$('#unlock_background').on('click', onUnlockBackgroundClick);
|
||||
$(document).on("click", ".bg_example", onSelectBackgroundClick);
|
||||
}
|
||||
|
||||
addSettings();
|
||||
setInterval(moduleWorker, UPDATE_INTERVAL);
|
||||
});
|
11
public/scripts/extensions/backgrounds/manifest.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"display_name": "Character Backgrounds",
|
||||
"loading_order": 7,
|
||||
"requires": [],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"version": "1.0.0",
|
||||
"homePage": "https://github.com/Cohee1207/SillyTavern"
|
||||
}
|
45
public/scripts/extensions/backgrounds/style.css
Normal file
@ -0,0 +1,45 @@
|
||||
#custom_bg_preview {
|
||||
width: 160px;
|
||||
height: 90px;
|
||||
background-color: var(--grey30a);
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
border-radius: 20px;
|
||||
border: 1px solid var(--black50a);
|
||||
box-shadow: 0 0 7px var(--black50a);
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
#custom_bg_preview::before {
|
||||
content: 'No Background';
|
||||
color: white;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#custom_bg_preview:not([style*="background-image: none"])::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.background_controls .menu_button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.background_controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.background_controls small {
|
||||
flex-grow: 1;
|
||||
}
|
@ -16,8 +16,8 @@ async function moduleWorker() {
|
||||
async function setImageIcon() {
|
||||
try {
|
||||
const sendButton = document.getElementById('send_picture');
|
||||
sendButton.style.backgroundImage = `url('/img/image-solid.svg')`;
|
||||
sendButton.classList.remove('spin');
|
||||
sendButton.classList.add('fa-image');
|
||||
sendButton.classList.remove('fa-hourglass-half', 'fa-fade');
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
@ -27,8 +27,8 @@ async function setImageIcon() {
|
||||
async function setSpinnerIcon() {
|
||||
try {
|
||||
const sendButton = document.getElementById('send_picture');
|
||||
sendButton.style.backgroundImage = `url('/img/spinner-solid.svg')`;
|
||||
sendButton.classList.add('spin');
|
||||
sendButton.classList.remove('fa-image');
|
||||
sendButton.classList.add('fa-hourglass-half', 'fa-fade');
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
@ -77,7 +77,8 @@ async function onSelectImage(e) {
|
||||
if (apiResult.ok) {
|
||||
const data = await apiResult.json();
|
||||
const caption = data.caption;
|
||||
await sendCaptionedMessage(caption, base64Img);
|
||||
const imageToSave = data.thumbnail ? `data:image/jpeg;base64,${data.thumbnail}` : base64Img;
|
||||
await sendCaptionedMessage(caption, imageToSave);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
@ -97,9 +98,9 @@ $(document).ready(function () {
|
||||
$('#send_form').css('grid-template-columns', columns.join(' '));
|
||||
}
|
||||
function addSendPictureButton() {
|
||||
const sendButton = document.createElement('input');
|
||||
sendButton.type = 'button';
|
||||
const sendButton = document.createElement('div');
|
||||
sendButton.id = 'send_picture';
|
||||
sendButton.classList.add('fa-solid');
|
||||
$(sendButton).hide();
|
||||
$(sendButton).on('click', () => $('#img_file').click());
|
||||
$('#send_but_sheld').prepend(sendButton);
|
||||
|
@ -6,5 +6,8 @@
|
||||
],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css"
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"version": "1.0.0",
|
||||
"homePage": "https://github.com/Cohee1207/SillyTavern"
|
||||
}
|
@ -4,15 +4,14 @@
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
padding: 1px;
|
||||
background: no-repeat;
|
||||
background-size: 26px auto;
|
||||
background-position: center center;
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
filter: invert(1);
|
||||
opacity: 0.5;
|
||||
filter: brightness(0.7);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#send_picture:hover {
|
||||
@ -22,15 +21,3 @@
|
||||
#img_form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.spin {
|
||||
animation-name: spin;
|
||||
animation-duration: 2000ms;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {transform:rotate(0deg);}
|
||||
to {transform:rotate(360deg);}
|
||||
}
|
@ -7,13 +7,13 @@ const UPDATE_INTERVAL = 1000;
|
||||
|
||||
function setDiceIcon() {
|
||||
const sendButton = document.getElementById('roll_dice');
|
||||
sendButton.style.backgroundImage = `url(/img/dice-solid.svg)`;
|
||||
/* sendButton.style.backgroundImage = `url(/img/dice-solid.svg)`; */
|
||||
sendButton.classList.remove('spin');
|
||||
}
|
||||
|
||||
async function doDiceRoll() {
|
||||
let value = $(this).data('value');
|
||||
|
||||
|
||||
if (value == 'custom') {
|
||||
value = await callPopup('Enter the dice formula:<br><i>(for example, <tt>2d6</tt>)</i>', 'input');
|
||||
}
|
||||
@ -29,22 +29,24 @@ async function doDiceRoll() {
|
||||
|
||||
function addDiceRollButton() {
|
||||
const buttonHtml = `
|
||||
<input id="roll_dice" type="button" />
|
||||
<div id="dice_dropdown">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item" data-value="d4">d4</li>
|
||||
<li class="list-group-item" data-value="d6">d6</li>
|
||||
<li class="list-group-item" data-value="d8">d8</li>
|
||||
<li class="list-group-item" data-value="d10">d10</li>
|
||||
<li class="list-group-item" data-value="d12">d12</li>
|
||||
<li class="list-group-item" data-value="d20">d20</li>
|
||||
<li class="list-group-item" data-value="d100">d100</li>
|
||||
<li class="list-group-item" data-value="custom">...</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="roll_dice" class="fa-solid fa-dice" /></div>
|
||||
`;
|
||||
const dropdownHtml = `
|
||||
<div id="dice_dropdown">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item" data-value="d4">d4</li>
|
||||
<li class="list-group-item" data-value="d6">d6</li>
|
||||
<li class="list-group-item" data-value="d8">d8</li>
|
||||
<li class="list-group-item" data-value="d10">d10</li>
|
||||
<li class="list-group-item" data-value="d12">d12</li>
|
||||
<li class="list-group-item" data-value="d20">d20</li>
|
||||
<li class="list-group-item" data-value="d100">d100</li>
|
||||
<li class="list-group-item" data-value="custom">...</li>
|
||||
</ul>
|
||||
</div>`;
|
||||
|
||||
$('#send_but_sheld').prepend(buttonHtml);
|
||||
$(document.body).append(dropdownHtml)
|
||||
$('#dice_dropdown li').on('click', doDiceRoll);
|
||||
const button = $('#roll_dice');
|
||||
const dropdown = $('#dice_dropdown');
|
||||
|
@ -4,5 +4,8 @@
|
||||
"requires": [],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css"
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"version": "1.0.0",
|
||||
"homePage": "https://github.com/Cohee1207/SillyTavern"
|
||||
}
|
@ -4,17 +4,23 @@
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
padding: 1px;
|
||||
background: no-repeat;
|
||||
background-size: 26px auto;
|
||||
background-position: center center;
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
filter: invert(1);
|
||||
opacity: 0.5;
|
||||
opacity: 0.7;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
#roll_dice:hover {
|
||||
opacity: 1;
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
#dice_dropdown {
|
||||
z-index: 100;
|
||||
backdrop-filter: blur(--SmartThemeBlurStrength);
|
||||
}
|
@ -4,11 +4,41 @@ export { MODULE_NAME };
|
||||
|
||||
const MODULE_NAME = 'expressions';
|
||||
const UPDATE_INTERVAL = 1000;
|
||||
const DEFAULT_EXPRESSIONS = ['anger', 'fear', 'joy', 'love', 'sadness', 'surprise'];
|
||||
const DEFAULT_EXPRESSIONS = [
|
||||
"admiration",
|
||||
"amusement",
|
||||
"anger",
|
||||
"annoyance",
|
||||
"approval",
|
||||
"caring",
|
||||
"confusion",
|
||||
"curiosity",
|
||||
"desire",
|
||||
"disappointment",
|
||||
"disapproval",
|
||||
"disgust",
|
||||
"embarrassment",
|
||||
"excitement",
|
||||
"fear",
|
||||
"gratitude",
|
||||
"grief",
|
||||
"joy",
|
||||
"love",
|
||||
"nervousness",
|
||||
"optimism",
|
||||
"pride",
|
||||
"realization",
|
||||
"relief",
|
||||
"remorse",
|
||||
"sadness",
|
||||
"surprise",
|
||||
"neutral"
|
||||
];
|
||||
|
||||
let expressionsList = null;
|
||||
let lastCharacter = undefined;
|
||||
let lastMessage = null;
|
||||
let existingExpressions = [];
|
||||
let inApiCall = false;
|
||||
|
||||
function onExpressionsShowDefaultInput() {
|
||||
@ -37,22 +67,22 @@ async function moduleWorker() {
|
||||
continue;
|
||||
}
|
||||
|
||||
return mes.mes;
|
||||
return { mes: mes.mes, name: mes.name };
|
||||
}
|
||||
|
||||
return '';
|
||||
return { mes: '', name: null };
|
||||
}
|
||||
|
||||
const context = getContext();
|
||||
|
||||
// group chats and non-characters not supported
|
||||
if (context.groupId || !context.characterId) {
|
||||
// non-characters not supported
|
||||
if (!context.groupId && !context.characterId) {
|
||||
removeExpression();
|
||||
return;
|
||||
}
|
||||
|
||||
// character changed
|
||||
if (lastCharacter !== context.characterId) {
|
||||
if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) {
|
||||
removeExpression();
|
||||
validateImages();
|
||||
}
|
||||
@ -67,9 +97,16 @@ async function moduleWorker() {
|
||||
$('.expression_settings .offline_mode').css('display', 'none');
|
||||
}
|
||||
|
||||
// character has no expressions or it is not loaded
|
||||
if (!context.groupId && existingExpressions.length === 0) {
|
||||
lastCharacter = context.groupId || context.characterId;
|
||||
return;
|
||||
}
|
||||
|
||||
// check if last message changed
|
||||
const currentLastMessage = getLastCharacterMessage();
|
||||
if (lastCharacter === context.characterId && lastMessage === currentLastMessage) {
|
||||
if ((lastCharacter === context.characterId || lastCharacter === context.groupId)
|
||||
&& lastMessage === currentLastMessage.mes) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -89,13 +126,21 @@ async function moduleWorker() {
|
||||
'Content-Type': 'application/json',
|
||||
'Bypass-Tunnel-Reminder': 'bypass',
|
||||
},
|
||||
body: JSON.stringify({ text: currentLastMessage })
|
||||
body: JSON.stringify({ text: currentLastMessage.mes })
|
||||
});
|
||||
|
||||
if (apiResult.ok) {
|
||||
const name = context.groupId ? currentLastMessage.name : context.name2;
|
||||
const force = !!context.groupId;
|
||||
const data = await apiResult.json();
|
||||
const expression = data.classification[0].label;
|
||||
setExpression(context.name2, expression);
|
||||
let expression = data.classification[0].label;
|
||||
|
||||
// Character won't be angry on you for swiping
|
||||
if (currentLastMessage.mes == '...' && expressionsList.includes('joy')) {
|
||||
expression = 'joy';
|
||||
}
|
||||
|
||||
setExpression(name, expression, force);
|
||||
}
|
||||
|
||||
}
|
||||
@ -104,8 +149,8 @@ async function moduleWorker() {
|
||||
}
|
||||
finally {
|
||||
inApiCall = false;
|
||||
lastCharacter = context.characterId;
|
||||
lastMessage = currentLastMessage;
|
||||
lastCharacter = context.groupId || context.characterId;
|
||||
lastMessage = currentLastMessage.mes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,6 +169,7 @@ async function validateImages() {
|
||||
}
|
||||
|
||||
imagesValidating = true;
|
||||
existingExpressions = [];
|
||||
const context = getContext();
|
||||
$('.expression_settings').show();
|
||||
$('#image_list').empty();
|
||||
@ -133,18 +179,19 @@ async function validateImages() {
|
||||
return;
|
||||
}
|
||||
|
||||
const IMAGE_LIST = (await getExpressionsList()).map(x => `${x}.png`);
|
||||
const IMAGE_LIST = (await getExpressionsList()).map(x => ({ name: x, file: `${x}.png` }));
|
||||
IMAGE_LIST.forEach((item) => {
|
||||
const image = document.createElement('img');
|
||||
image.src = `/characters/${context.name2}/${item}`;
|
||||
image.src = `/characters/${context.name2}/${item.file}`;
|
||||
image.classList.add('debug-image');
|
||||
image.width = '0px';
|
||||
image.height = '0px';
|
||||
image.onload = function () {
|
||||
$('#image_list').append(getListItem(item, image.src, 'success'));
|
||||
existingExpressions.push(item.name);
|
||||
$('#image_list').append(getListItem(item.file, image.src, 'success'));
|
||||
}
|
||||
image.onerror = function () {
|
||||
$('#image_list').append(getListItem(item, '/img/No-Image-Placeholder.svg', 'failure'));
|
||||
$('#image_list').append(getListItem(item.file, '/img/No-Image-Placeholder.svg', 'failure'));
|
||||
}
|
||||
$('#image_list').prepend(image);
|
||||
});
|
||||
@ -161,12 +208,15 @@ function getListItem(item, imageSrc, textClass) {
|
||||
}
|
||||
|
||||
async function getExpressionsList() {
|
||||
console.log('getting expressions list');
|
||||
// get something for offline mode (6 default images)
|
||||
if (!modules.includes('classify')) {
|
||||
console.log('classify not available, loading default');
|
||||
return DEFAULT_EXPRESSIONS;
|
||||
}
|
||||
|
||||
if (Array.isArray(expressionsList)) {
|
||||
console.log('got array, loading array');
|
||||
return expressionsList;
|
||||
}
|
||||
|
||||
@ -174,41 +224,57 @@ async function getExpressionsList() {
|
||||
url.pathname = '/api/classify/labels';
|
||||
|
||||
try {
|
||||
console.log('trying for API');
|
||||
const apiResult = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: { 'Bypass-Tunnel-Reminder': 'bypass' },
|
||||
});
|
||||
|
||||
if (apiResult.ok) {
|
||||
console.log('API ok, adding labels');
|
||||
const data = await apiResult.json();
|
||||
expressionsList = data.labels;
|
||||
return expressionsList;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log('got error!');
|
||||
console.log(error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function setExpression(character, expression, force) {
|
||||
console.log('entered setExpressions');
|
||||
const filename = `${expression}.png`;
|
||||
const debugImageStatus = document.querySelector(`#image_list div[id="${filename}"] span`);
|
||||
|
||||
if (force || (debugImageStatus && !debugImageStatus.classList.contains('failure'))) {
|
||||
//console.log('setting expression from character images folder');
|
||||
const img = $('img.expression');
|
||||
console.log('checking for expression images to show..');
|
||||
if (force || (existingExpressions.includes(expression))) {
|
||||
console.log('setting expression from character images folder');
|
||||
const imgUrl = `/characters/${character}/${filename}`;
|
||||
$('img.expression').prop('src', imgUrl);
|
||||
$('img.expression').removeClass('default');
|
||||
img.attr('src', imgUrl);
|
||||
img.removeClass('default');
|
||||
img.off('error');
|
||||
img.on('error', function () {
|
||||
$(this).attr('src', '');
|
||||
if (force && extension_settings.expressions.showDefault) {
|
||||
setDefault();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (extension_settings.expressions.showDefault) {
|
||||
//console.log('no character images, trying default expressions');
|
||||
const defImgUrl = `/img/default-expressions/${filename}`;
|
||||
//console.log(defImgUrl);
|
||||
$('img.expression').prop('src', defImgUrl);
|
||||
$('img.expression').addClass('default');
|
||||
console.log('no character images, trying default expressions');
|
||||
setDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function setDefault() {
|
||||
console.log('setting default');
|
||||
const defImgUrl = `/img/default-expressions/${filename}`;
|
||||
//console.log(defImgUrl);
|
||||
img.attr('src', defImgUrl);
|
||||
img.addClass('default');
|
||||
}
|
||||
}
|
||||
|
||||
function onClickExpressionImage() {
|
||||
@ -227,25 +293,30 @@ function onClickExpressionImage() {
|
||||
|
||||
(function () {
|
||||
function addExpressionImage() {
|
||||
const html = `<div class="expression-holder"><img class="expression"></div>`;
|
||||
console.log('entered addExpressionImage');
|
||||
const html = `
|
||||
<div id="expression-holder" class="expression-holder">
|
||||
<div id="expression-holderheader" class="fa-solid fa-grip drag-grabber"></div>
|
||||
<img class="expression">
|
||||
</div>`;
|
||||
$('body').append(html);
|
||||
}
|
||||
function addSettings() {
|
||||
console.log('entered addSettings');
|
||||
const html = `
|
||||
<div class="expression_settings">
|
||||
<h4>Expression images</h4>
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>View supported images</b>
|
||||
<div class="inline-drawer-icon down"></div>
|
||||
<b>Expression images</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<p class="offline_mode">You are in offline mode. Click on the image below to set the expression.</p>
|
||||
<div id="image_list"></div>
|
||||
<p class="hint"><b>Hint:</b> <i>Create new folder in the <b>public/characters/</b> folder and name it as the name of the character. Put PNG images with expressions there.</i></p>
|
||||
</div>
|
||||
<label for="expressions_show_default"><input id="expressions_show_default" type="checkbox">Show default images (emojis) if missing</label>
|
||||
</div>
|
||||
</div>
|
||||
<label for="expressions_show_default"><input id="expressions_show_default" type="checkbox">Show default images (emojis) if missing</label>
|
||||
</div>
|
||||
`;
|
||||
$('#extensions_settings').append(html);
|
||||
|
@ -6,5 +6,8 @@
|
||||
"classify"
|
||||
],
|
||||
"js": "index.js",
|
||||
"css": "style.css"
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"version": "1.0.0",
|
||||
"homePage": "https://github.com/Cohee1207/SillyTavern"
|
||||
}
|
@ -5,24 +5,30 @@
|
||||
}
|
||||
|
||||
.expression-holder {
|
||||
min-width: 100px;
|
||||
min-height: 100px;
|
||||
max-height: 90vh;
|
||||
max-width: calc((100vw - 800px)/2);
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
text-align: center;
|
||||
max-width: 90vh;
|
||||
width: calc((100vw - var(--sheldWidth)) /2);
|
||||
position: absolute;
|
||||
bottom: 1px;
|
||||
padding: 0;
|
||||
filter: drop-shadow(2px 2px 2px #51515199);
|
||||
transition: 500ms;
|
||||
z-index: 3;
|
||||
/* resize: both; */
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
|
||||
img.expression {
|
||||
max-width: 100%;
|
||||
max-height: 90vh;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
vertical-align: bottom;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
img.expression[src=""] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
img.expression.default {
|
||||
|
@ -51,76 +51,7 @@ function onExtensionFloatingDefaultInput() {
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
// TODO Remove in next release
|
||||
function getLocalStorageKeys() {
|
||||
const context = getContext();
|
||||
|
||||
let keySuffix;
|
||||
|
||||
if (context.groupId) {
|
||||
keySuffix = context.groupId;
|
||||
}
|
||||
else if (context.characterId) {
|
||||
keySuffix = `${context.characters[context.characterId].name}_${context.chatId}`;
|
||||
}
|
||||
else {
|
||||
keySuffix = 'undefined';
|
||||
}
|
||||
|
||||
return {
|
||||
prompt: `extensions_floating_prompt_${keySuffix}`,
|
||||
interval: `extensions_floating_interval_${keySuffix}`,
|
||||
depth: `extensions_floating_depth_${keySuffix}`,
|
||||
position: `extensions_floating_position_${keySuffix}`,
|
||||
default: 'extensions_default_note',
|
||||
};
|
||||
}
|
||||
|
||||
function migrateFromLocalStorage() {
|
||||
const keys = getLocalStorageKeys();
|
||||
const defaultNote = localStorage.getItem(keys.default);
|
||||
const prompt = localStorage.getItem(keys.prompt);
|
||||
const interval = localStorage.getItem(keys.interval);
|
||||
const position = localStorage.getItem(keys.position);
|
||||
const depth = localStorage.getItem(keys.depth);
|
||||
|
||||
if (defaultNote !== null) {
|
||||
if (typeof extension_settings.note !== 'object') {
|
||||
extension_settings.note = {};
|
||||
}
|
||||
|
||||
extension_settings.note.default = defaultNote;
|
||||
saveSettingsDebounced();
|
||||
localStorage.removeItem(keys.default);
|
||||
}
|
||||
|
||||
if (chat_metadata) {
|
||||
if (interval !== null) {
|
||||
chat_metadata[metadata_keys.interval] = interval;
|
||||
localStorage.removeItem(keys.interval);
|
||||
}
|
||||
|
||||
if (depth !== null) {
|
||||
chat_metadata[metadata_keys.depth] = depth;
|
||||
localStorage.removeItem(keys.depth);
|
||||
}
|
||||
|
||||
if (position !== null) {
|
||||
chat_metadata[metadata_keys.position] = position;
|
||||
localStorage.removeItem(keys.position);
|
||||
}
|
||||
|
||||
if (prompt !== null) {
|
||||
chat_metadata[metadata_keys.prompt] = prompt;
|
||||
localStorage.removeItem(keys.prompt);
|
||||
saveChatDebounced();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function loadSettings() {
|
||||
migrateFromLocalStorage();
|
||||
chat_metadata[metadata_keys.prompt] = chat_metadata[metadata_keys.prompt] ?? extension_settings.note.default ?? '';
|
||||
chat_metadata[metadata_keys.interval] = chat_metadata[metadata_keys.interval] ?? DEFAULT_INTERVAL;
|
||||
chat_metadata[metadata_keys.position] = chat_metadata[metadata_keys.position] ?? DEFAULT_POSITION;
|
||||
@ -150,6 +81,7 @@ async function moduleWorker() {
|
||||
}
|
||||
|
||||
if (lastMessageNumber <= 0 || chat_metadata[metadata_keys.interval] <= 0) {
|
||||
context.setExtensionPrompt(MODULE_NAME, '');
|
||||
$('#extension_floating_counter').text('No');
|
||||
return;
|
||||
}
|
||||
@ -163,35 +95,43 @@ async function moduleWorker() {
|
||||
$('#extension_floating_counter').text(shouldAddPrompt ? 'This' : messagesTillInsertion);
|
||||
}
|
||||
|
||||
(function() {
|
||||
(function () {
|
||||
function addExtensionsSettings() {
|
||||
const settingsHtml = `
|
||||
<h4>Author's Note / Character Bias</h4>
|
||||
<div class="floating_prompt_settings">
|
||||
<label for="extension_floating_prompt">Append the following text:</label>
|
||||
<textarea id="extension_floating_prompt" class="text_pole" rows="2"></textarea>
|
||||
<label>
|
||||
<input type="radio" name="extension_floating_position" value="0" />
|
||||
After scenario
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="extension_floating_position" value="1" />
|
||||
In-chat
|
||||
</label>
|
||||
<label for="extension_floating_interval">Every N messages <b>you</b> send (set to 0 to disable):</label>
|
||||
<input id="extension_floating_interval" class="text_pole" type="number" min="0" max="999" />
|
||||
<label for="extension_floating_interval">Insertion depth (for in-chat positioning):</label>
|
||||
<input id="extension_floating_depth" class="text_pole" type="number" min="0" max="99" />
|
||||
<span>Appending to the prompt in next: <span id="extension_floating_counter">No</span> message(s)</span>
|
||||
<br>
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Author's Note / Character Bias</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="extension_floating_prompt">Append the following text:</label>
|
||||
<textarea id="extension_floating_prompt" class="text_pole" rows="8"></textarea>
|
||||
<div class="floating_prompt_radio_group">
|
||||
<label>
|
||||
<input type="radio" name="extension_floating_position" value="0" />
|
||||
After scenario
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="extension_floating_position" value="1" />
|
||||
In-chat
|
||||
</label>
|
||||
</div>
|
||||
<label for="extension_floating_interval">Every N messages <b>you</b> send (set to 0 to disable):</label>
|
||||
<input id="extension_floating_interval" class="text_pole" type="number" min="0" max="999" />
|
||||
<label for="extension_floating_interval">Insertion depth (for in-chat positioning):</label>
|
||||
<input id="extension_floating_depth" class="text_pole" type="number" min="0" max="99" />
|
||||
<span>Appending to the prompt in next: <span id="extension_floating_counter">No</span> message(s)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Default note for new chats</b>
|
||||
<div class="inline-drawer-icon down"></div>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="extension_floating_default">Default Author's Note</label>
|
||||
<textarea id="extension_floating_default" class="text_pole" rows="3"
|
||||
<textarea id="extension_floating_default" class="text_pole" rows="8"
|
||||
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,5 +4,8 @@
|
||||
"requires": [],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css"
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"version": "1.0.0",
|
||||
"homePage": "https://github.com/Cohee1207/SillyTavern"
|
||||
}
|
@ -6,4 +6,14 @@
|
||||
#extension_floating_counter {
|
||||
font-weight: 600;
|
||||
color: orange;
|
||||
}
|
||||
|
||||
.floating_prompt_settings textarea {
|
||||
font-size: calc(var(--mainFontSize) * 0.9);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.floating_prompt_radio_group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
@ -26,7 +26,7 @@ const defaultSettings = {
|
||||
shortMemoryStep: 16,
|
||||
longMemoryStep: 8,
|
||||
repetitionPenaltyStep: 0.05,
|
||||
repetitionPenalty: 1.0,
|
||||
repetitionPenalty: 1.2,
|
||||
maxRepetitionPenalty: 2.0,
|
||||
minRepetitionPenalty: 1.0,
|
||||
temperature: 1.0,
|
||||
@ -34,28 +34,13 @@ const defaultSettings = {
|
||||
maxTemperature: 2.0,
|
||||
temperatureStep: 0.05,
|
||||
lengthPenalty: 1,
|
||||
minLengthPenalty: 0,
|
||||
maxLengthPenalty: 2,
|
||||
lengthPenaltyStep: 0.05,
|
||||
minLengthPenalty: -4,
|
||||
maxLengthPenalty: 4,
|
||||
lengthPenaltyStep: 0.1,
|
||||
memoryFrozen: false,
|
||||
};
|
||||
|
||||
// TODO Delete in next release
|
||||
function migrateFromLocalStorage() {
|
||||
const SETTINGS_KEY = 'extensions_memory_settings';
|
||||
const settings = localStorage.getItem(SETTINGS_KEY);
|
||||
|
||||
if (settings !== null) {
|
||||
const savedSettings = JSON.parse(settings);
|
||||
Object.assign(extension_settings.memory, savedSettings);
|
||||
localStorage.removeItem(SETTINGS_KEY);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
migrateFromLocalStorage();
|
||||
|
||||
if (Object.keys(extension_settings.memory).length === 0) {
|
||||
Object.assign(extension_settings.memory, defaultSettings);
|
||||
}
|
||||
@ -223,14 +208,14 @@ async function summarizeChat(context) {
|
||||
memoryBuffer.push(entry);
|
||||
|
||||
// check if token limit was reached
|
||||
if (context.encode(getMemoryString()).length >= extension_settings.memory.shortMemoryLength) {
|
||||
if (context.getTokenCount(getMemoryString()) >= extension_settings.memory.shortMemoryLength) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const resultingString = getMemoryString();
|
||||
|
||||
if (context.encode(resultingString).length < extension_settings.memory.shortMemoryLength) {
|
||||
if (context.getTokenCount(resultingString) < extension_settings.memory.shortMemoryLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -249,7 +234,7 @@ async function summarizeChat(context) {
|
||||
body: JSON.stringify({
|
||||
text: resultingString,
|
||||
params: {
|
||||
min_length: extension_settings.memory.longMemoryLength * 0.8,
|
||||
min_length: extension_settings.memory.longMemoryLength * 0, // testing how it behaves 0 min length
|
||||
max_length: extension_settings.memory.longMemoryLength,
|
||||
repetition_penalty: extension_settings.memory.repetitionPenalty,
|
||||
temperature: extension_settings.memory.temperature,
|
||||
@ -322,28 +307,35 @@ $(document).ready(function () {
|
||||
function addExtensionControls() {
|
||||
const settingsHtml = `
|
||||
<div id="memory_settings">
|
||||
<h4>Memory</h4>
|
||||
<label for="memory_contents">Memory contents</label>
|
||||
<textarea id="memory_contents" class="text_pole" rows="8" placeholder="Context will be generated here..."></textarea>
|
||||
<div class="memory_contents_controls">
|
||||
<input id="memory_restore" class="menu_button" type="submit" value="Restore previous state" />
|
||||
<label for="memory_frozen"><input id="memory_frozen" type="checkbox" /> Freeze context</label>
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Chat memory</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="memory_contents">Memory contents</label>
|
||||
<textarea id="memory_contents" class="text_pole" rows="8" placeholder="Context will be generated here..."></textarea>
|
||||
<div class="memory_contents_controls">
|
||||
<input id="memory_restore" class="menu_button" type="submit" value="Restore previous state" />
|
||||
<label for="memory_frozen"><input id="memory_frozen" type="checkbox" /> Freeze context</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Summarization settings</b>
|
||||
<div class="inline-drawer-icon down"></div>
|
||||
<b>Summarization parameters</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="memory_short_length">Memory summarization [short-term] length (<span id="memory_short_length_tokens"></span> tokens)</label>
|
||||
<label for="memory_short_length">Buffer <small>[short-term]</small> length (<span id="memory_short_length_tokens"></span> tokens)</label>
|
||||
<input id="memory_short_length" type="range" value="${defaultSettings.shortMemoryLength}" min="${defaultSettings.minShortMemory}" max="${defaultSettings.maxShortMemory}" step="${defaultSettings.shortMemoryStep}" />
|
||||
<label for="memory_long_length">Memory context [long-term] length (<span id="memory_long_length_tokens"></span> tokens)</label>
|
||||
<label for="memory_long_length">Summary <small>[long-term]</small> length (<span id="memory_long_length_tokens"></span> tokens)</label>
|
||||
<input id="memory_long_length" type="range" value="${defaultSettings.longMemoryLength}" min="${defaultSettings.minLongMemory}" max="${defaultSettings.maxLongMemory}" step="${defaultSettings.longMemoryStep}" />
|
||||
<label for="memory_temperature">Summarization temperature (<span id="memory_temperature_value"></span>)</label>
|
||||
<label for="memory_temperature">Temperature (<span id="memory_temperature_value"></span>)</label>
|
||||
<input id="memory_temperature" type="range" value="${defaultSettings.temperature}" min="${defaultSettings.minTemperature}" max="${defaultSettings.maxTemperature}" step="${defaultSettings.temperatureStep}" />
|
||||
<label for="memory_repetition_penalty">Summarization repetition penalty (<span id="memory_repetition_penalty_value"></span>)</label>
|
||||
<label for="memory_repetition_penalty">Repetition penalty (<span id="memory_repetition_penalty_value"></span>)</label>
|
||||
<input id="memory_repetition_penalty" type="range" value="${defaultSettings.repetitionPenalty}" min="${defaultSettings.minRepetitionPenalty}" max="${defaultSettings.maxRepetitionPenalty}" step="${defaultSettings.repetitionPenaltyStep}" />
|
||||
<label for="memory_length_penalty">Summarization length penalty (<span id="memory_length_penalty_value"></span>)</label>
|
||||
<label for="memory_length_penalty">Length penalty <small>[higher = longer summaries]</small> (<span id="memory_length_penalty_value"></span>)</label>
|
||||
<input id="memory_length_penalty" type="range" value="${defaultSettings.lengthPenalty}" min="${defaultSettings.minLengthPenalty}" max="${defaultSettings.maxLengthPenalty}" step="${defaultSettings.lengthPenaltyStep}" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,5 +6,8 @@
|
||||
],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css"
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"version": "1.0.0",
|
||||
"homePage": "https://github.com/Cohee1207/SillyTavern"
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
}
|
||||
|
||||
#memory_settings textarea {
|
||||
font-size: 14px;
|
||||
font-size: calc(var(--mainFontSize) * 0.9);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
|