mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Compare commits
742 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
06912dba0a | ||
|
429fe85e16 | ||
|
5807263681 | ||
|
ca3f8daa9d | ||
|
8d15b98391 | ||
|
ce64747705 | ||
|
f7237342df | ||
|
b66e3b3f25 | ||
|
853ab87e05 | ||
|
5e60202159 | ||
|
690dab49a0 | ||
|
76bac19fb5 | ||
|
671345efae | ||
|
ed9b46c980 | ||
|
4c976e58e2 | ||
|
7e127e9b68 | ||
|
3712e2957b | ||
|
f6e1c48ac9 | ||
|
c6a6a8352d | ||
|
4c3aafa3a8 | ||
|
7cf02beaa6 | ||
|
284fb68478 | ||
|
dfab4b8ea2 | ||
|
f63a69dd41 | ||
|
13f6cf3175 | ||
|
d5af1ec82e | ||
|
bd7c0463f3 | ||
|
e3e2b73b99 | ||
|
f5b4c6e10c | ||
|
fbbb7cc549 | ||
|
2305a536de | ||
|
f339f28b05 | ||
|
92f012fb6a | ||
|
8de791a9ee | ||
|
2f73506e25 | ||
|
656888f70a | ||
|
1886334516 | ||
|
d547f2650a | ||
|
f83f71097a | ||
|
c1b2a084d5 | ||
|
96c668296a | ||
|
fa6803f2de | ||
|
7a0f5a0111 | ||
|
9e21534fae | ||
|
af5f7199de | ||
|
623675d940 | ||
|
547b275768 | ||
|
28d22aa8c1 | ||
|
766349785d | ||
|
5209485f20 | ||
|
f327f4abbe | ||
|
b003c18abd | ||
|
7e310323b6 | ||
|
5090fe76a9 | ||
|
818416b1f2 | ||
|
31a159dee0 | ||
|
c501734d25 | ||
|
baf0fd7e41 | ||
|
b7c5ea9152 | ||
|
d61eba4cb4 | ||
|
eb90162579 | ||
|
b058f40ee6 | ||
|
f8e2730fd6 | ||
|
b1f1fa8a26 | ||
|
751894976e | ||
|
3af4598fc9 | ||
|
ff92f0dbbf | ||
|
41cf0c023f | ||
|
2e2ad6589e | ||
|
393d7c496d | ||
|
d50c44f747 | ||
|
4324bc239b | ||
|
0c130ecc53 | ||
|
28d4dfd718 | ||
|
0280bfa1bb | ||
|
e58dbec3de | ||
|
f77df227e7 | ||
|
7b2cb3e042 | ||
|
732cea5cf1 | ||
|
2bd64475da | ||
|
c44cfabbcd | ||
|
2ae2a953fd | ||
|
a67d831433 | ||
|
651774fe5e | ||
|
6018ea7288 | ||
|
0a99a0bb41 | ||
|
760a84d5ac | ||
|
3adcfecb5c | ||
|
7bfaa97ac7 | ||
|
fa988f08fe | ||
|
36b8aa0b4d | ||
|
44b235e368 | ||
|
5d7ab41dc9 | ||
|
5b98f2f329 | ||
|
46bf29e86d | ||
|
40dd845e51 | ||
|
0f3908216a | ||
|
02966ff48f | ||
|
37de77b20d | ||
|
1a8d8db102 | ||
|
f931932d31 | ||
|
8f96a74d1e | ||
|
2ac77b21ae | ||
|
eb4adb5a6c | ||
|
76359283a2 | ||
|
6dc1a86021 | ||
|
d5c816ed2b | ||
|
f5a25cad5b | ||
|
92fbba83dc | ||
|
07c78391e1 | ||
|
8987534403 | ||
|
5812e34dcb | ||
|
6f33cc6fea | ||
|
11982c30d3 | ||
|
3210dd29d3 | ||
|
8689703068 | ||
|
9951837f1d | ||
|
5db9a7b5ba | ||
|
4bf8e2c49f | ||
|
057ae5ce14 | ||
|
22108c5c9f | ||
|
101acd29da | ||
|
95700dbe3e | ||
|
02c4c7d1d0 | ||
|
94af882530 | ||
|
933729d914 | ||
|
da43c1c87e | ||
|
298952e591 | ||
|
51c6137f53 | ||
|
ae7ad6dbf0 | ||
|
edfafe4e7c | ||
|
184e662ab6 | ||
|
18272be918 | ||
|
2c4efe5509 | ||
|
e08889a348 | ||
|
ff8c9546ad | ||
|
be91af30b8 | ||
|
c91d32d273 | ||
|
ee6bfbf4cc | ||
|
2b8db6350e | ||
|
35336b1646 | ||
|
07b42e0fb4 | ||
|
eccae1056f | ||
|
cc7c42232e | ||
|
4fb65a9235 | ||
|
75080394ac | ||
|
396aaaf6e9 | ||
|
cb37fbd827 | ||
|
f513c54691 | ||
|
abdf1ac71e | ||
|
67195071c3 | ||
|
26b6d48a3d | ||
|
f9630acaf4 | ||
|
a20eff92f0 | ||
|
f1c5f26b86 | ||
|
dc788f6571 | ||
|
abe57f7e9a | ||
|
cb294983e7 | ||
|
9bbf23e56f | ||
|
4aeda77648 | ||
|
6b0e13e064 | ||
|
49ae2cbad6 | ||
|
27e3485127 | ||
|
b41d0a08c7 | ||
|
de3b39f825 | ||
|
2454963129 | ||
|
f67013f7ed | ||
|
53d45356a4 | ||
|
dedb913b67 | ||
|
4f11b38110 | ||
|
4a3e95d79f | ||
|
393fff6207 | ||
|
c9cc8fcf18 | ||
|
6b1965fcf4 | ||
|
bb6ff352b3 | ||
|
5660280c51 | ||
|
bd7d4beab5 | ||
|
33918d3e05 | ||
|
040380e0fb | ||
|
345992bb86 | ||
|
12908baaf9 | ||
|
f253286981 | ||
|
0fc10e8f7d | ||
|
c53e496687 | ||
|
6c1e4c429b | ||
|
f3a3613ac2 | ||
|
2387ff54c0 | ||
|
90c05988e1 | ||
|
8872492fcd | ||
|
7ee7e7b32a | ||
|
435a428587 | ||
|
1f1af8e631 | ||
|
e5fab05309 | ||
|
bd2ca40452 | ||
|
f33dd638b3 | ||
|
9ebb1cfe90 | ||
|
5c6c7fd3ca | ||
|
66a50f6afb | ||
|
a4b6cba596 | ||
|
43a4d553f1 | ||
|
eefbafdc08 | ||
|
f76db66e25 | ||
|
3ade04ed68 | ||
|
210abe452c | ||
|
1562045cc8 | ||
|
72dcc43b37 | ||
|
9ce7d2e31e | ||
|
a30754e1c2 | ||
|
d5c38077a4 | ||
|
9282b1942a | ||
|
35688c3eb3 | ||
|
ad001ea263 | ||
|
467649b676 | ||
|
5f9fd017ea | ||
|
d16e673930 | ||
|
1a3f90d39c | ||
|
dcb7932d72 | ||
|
797899c303 | ||
|
d35ed21f48 | ||
|
e883a37953 | ||
|
3b56c89503 | ||
|
c85b3253c5 | ||
|
42cd9a6e30 | ||
|
039d8b5b8c | ||
|
bdc4d213dd | ||
|
2befcd8712 | ||
|
47e01f6b6f | ||
|
3548f46782 | ||
|
497ca714a9 | ||
|
dae48e66d1 | ||
|
f03df10972 | ||
|
a15b2892a7 | ||
|
d25eca0f29 | ||
|
eaa14d2804 | ||
|
148966affe | ||
|
0f7dad7a5e | ||
|
5128b75216 | ||
|
0c7c9cad16 | ||
|
3c3eed0996 | ||
|
474a9cb99e | ||
|
68551ae15c | ||
|
f72b055bfb | ||
|
5a0c702f53 | ||
|
f2e4eb1696 | ||
|
8e5fd7938c | ||
|
46e1a25d83 | ||
|
ed0c185284 | ||
|
5983e50d21 | ||
|
1be05fa514 | ||
|
7026f7051f | ||
|
cd7df3e0e7 | ||
|
1852279723 | ||
|
5b40260170 | ||
|
ae3da169f1 | ||
|
00e7d3c270 | ||
|
880472df18 | ||
|
6a3282cbc4 | ||
|
078947b73e | ||
|
fe0d315bcb | ||
|
fca365de6c | ||
|
d6412d7b42 | ||
|
30ccb72017 | ||
|
f3d8f4a7da | ||
|
57ee954ad5 | ||
|
0d5cdcd0b1 | ||
|
6a30858579 | ||
|
be72b6f15f | ||
|
bd74ea12ea | ||
|
2edc34db81 | ||
|
3162cf0e29 | ||
|
1bd9b8c1bf | ||
|
243e89091a | ||
|
b4830f2b67 | ||
|
e5e275a827 | ||
|
f985b7eeb9 | ||
|
c879a93b75 | ||
|
cc98a0bd01 | ||
|
8fcc074ced | ||
|
c44310f38f | ||
|
49745b2b35 | ||
|
f854609512 | ||
|
e595f83590 | ||
|
02fb1bc26f | ||
|
82624ff55b | ||
|
08fd83ca5d | ||
|
3665947f54 | ||
|
a2fc3ec115 | ||
|
f93fb78bc7 | ||
|
48e9332db9 | ||
|
afea5d48f1 | ||
|
d6c3c6f26e | ||
|
afcd2b497d | ||
|
7d9c346d25 | ||
|
1acaea2a4c | ||
|
bc52df493e | ||
|
11bbb6e8e3 | ||
|
85e82f854b | ||
|
b6ac73631f | ||
|
35390c07ef | ||
|
87f436fe44 | ||
|
4740e872cd | ||
|
fb69397ac1 | ||
|
3168ee536e | ||
|
8212206d50 | ||
|
bbe08ece84 | ||
|
c9db2f7c9c | ||
|
1d640a2cbf | ||
|
13ba5cec49 | ||
|
892824df1a | ||
|
2a8f3e7334 | ||
|
d7db7885e5 | ||
|
4e8a2b8386 | ||
|
59f857262b | ||
|
a2a496a4c9 | ||
|
88429baa48 | ||
|
935a3d6c35 | ||
|
3c64c46daf | ||
|
a53cee20d2 | ||
|
cb741fd954 | ||
|
f3ebea6ad8 | ||
|
af6d9d48e0 | ||
|
04b5d73a85 | ||
|
9ed05725c6 | ||
|
15a2a61615 | ||
|
aed6e3413a | ||
|
df6b87fa23 | ||
|
f6f4a5199b | ||
|
d59eaa4912 | ||
|
26b55d47b4 | ||
|
5c39327450 | ||
|
9c3823a616 | ||
|
46330f0558 | ||
|
afdab4c5b6 | ||
|
b8f86d55da | ||
|
fee801c2a4 | ||
|
fb02c00402 | ||
|
7c0222a15b | ||
|
e6eae0aad1 | ||
|
0f8d07053e | ||
|
b362dba726 | ||
|
ee6a6603a3 | ||
|
ef7aa3941b | ||
|
6bc9535040 | ||
|
4e0cbdfbb3 | ||
|
7ceb936337 | ||
|
d3c3614147 | ||
|
9a8e036ff9 | ||
|
0d858bdefb | ||
|
27ab509caf | ||
|
093379dba9 | ||
|
872bbfad1a | ||
|
b8f3a7cbe0 | ||
|
deff2d24fb | ||
|
fde2a91d2a | ||
|
4ceb8cedef | ||
|
383a9f67a2 | ||
|
8cee880486 | ||
|
36149fffa1 | ||
|
80ac13ef20 | ||
|
b994dbb2d1 | ||
|
83d954246f | ||
|
368f3ea968 | ||
|
19502492c6 | ||
|
3426f80656 | ||
|
6770ccbe91 | ||
|
44a38f8588 | ||
|
823dd8c47c | ||
|
c922f17f09 | ||
|
8ad431bea6 | ||
|
dbb18ac895 | ||
|
856b835172 | ||
|
37000963d9 | ||
|
6ddd804749 | ||
|
2130338c1d | ||
|
e9ce2853cc | ||
|
b20f371a42 | ||
|
de425d97dd | ||
|
d6fd5455e6 | ||
|
f3c9f57cb9 | ||
|
3fcf232537 | ||
|
6be18e4212 | ||
|
9e3c55805f | ||
|
9ab7265053 | ||
|
25e3005de9 | ||
|
2b8f5d14e9 | ||
|
13deac2527 | ||
|
d566be077d | ||
|
7fe2ea31b9 | ||
|
d153488690 | ||
|
a61a8f9495 | ||
|
a904260614 | ||
|
5e24beef58 | ||
|
47e4d5925b | ||
|
52b994a45b | ||
|
ca2542d81a | ||
|
1fe2e4032a | ||
|
84cfe1c706 | ||
|
4afd616099 | ||
|
44bf31e602 | ||
|
6d33e44519 | ||
|
16e8c7a3c8 | ||
|
0c3f3f952d | ||
|
bef7d1492b | ||
|
6e15f7474f | ||
|
7a33042ea9 | ||
|
2e80de230e | ||
|
225bd5aa0a | ||
|
b14a85a96b | ||
|
febef5dfba | ||
|
9aab388531 | ||
|
549fb19676 | ||
|
8eb82cdcd9 | ||
|
c156e32ec7 | ||
|
002dbae8c5 | ||
|
bd9e739de2 | ||
|
5dbfe209f6 | ||
|
229ec5f255 | ||
|
8d18f2a80a | ||
|
43a28fdb05 | ||
|
faac9fe03a | ||
|
37219c3370 | ||
|
990a5faf7d | ||
|
080ecec5f2 | ||
|
6a2c4e13e6 | ||
|
b8c42307da | ||
|
715a6f1bff | ||
|
e01a2c3bcf | ||
|
6c33dff0ba | ||
|
596cd1762f | ||
|
9af05df6ad | ||
|
e43227691b | ||
|
f2cde4d40a | ||
|
3b4f8811e7 | ||
|
63bd4cd499 | ||
|
822e4b88f5 | ||
|
59b92d4356 | ||
|
309a2ed564 | ||
|
fcef55d900 | ||
|
cba2feb875 | ||
|
fe8db4ded8 | ||
|
8cda073d00 | ||
|
c134aed9f5 | ||
|
32441aa33e | ||
|
6be7d5704e | ||
|
1d2dc19359 | ||
|
dd028a9564 | ||
|
e6761f7293 | ||
|
8547f362c5 | ||
|
8251d15455 | ||
|
27c780c18b | ||
|
3353fe572c | ||
|
e2bbc7fbcf | ||
|
f532192726 | ||
|
757e9b672a | ||
|
0bfa9f0e29 | ||
|
0da4bce378 | ||
|
16915ae6a5 | ||
|
ad9599c2fc | ||
|
8687932896 | ||
|
10a5836893 | ||
|
f75930a75d | ||
|
d813ec4ef3 | ||
|
89f905f0e2 | ||
|
5af6874b5f | ||
|
60586e7720 | ||
|
4d3677dc5d | ||
|
c6f1ec696a | ||
|
9f5bd9d728 | ||
|
466bcd8833 | ||
|
05fd6d4a6c | ||
|
5d1edf7456 | ||
|
b9a067b79f | ||
|
6981151c8f | ||
|
650e7b0588 | ||
|
e9466916da | ||
|
bc7d7ee3ff | ||
|
2bbc40a796 | ||
|
0c55d36a2b | ||
|
fcc6448d7a | ||
|
215e34bb52 | ||
|
29e0a8335b | ||
|
5ab4179920 | ||
|
ebb93451b2 | ||
|
084d17dc19 | ||
|
2722813efb | ||
|
e81b867676 | ||
|
2dabcc28a5 | ||
|
3b99f7839b | ||
|
7c6c2ee8b6 | ||
|
52a2cee73c | ||
|
991d437749 | ||
|
8168a9205a | ||
|
332648973f | ||
|
fc8553a140 | ||
|
048d65c1e1 | ||
|
322ab9b47a | ||
|
0f0647c6e4 | ||
|
674a15b842 | ||
|
d0ab763d2e | ||
|
2f8b624578 | ||
|
e4e8cdfca5 | ||
|
df35fb0775 | ||
|
fca732c933 | ||
|
c18008725d | ||
|
38931e7a2f | ||
|
667cbf6f0f | ||
|
931fffaa5c | ||
|
f06ca28bbf | ||
|
ad11ec8d00 | ||
|
a1eb2b794e | ||
|
4ad328029e | ||
|
d66542e88e | ||
|
893d1fa9e4 | ||
|
4a9d9b69e9 | ||
|
ebf51f3a17 | ||
|
7bec130bf7 | ||
|
914282faf0 | ||
|
1d8ecacd8b | ||
|
a0814defff | ||
|
d410118cc4 | ||
|
5084ae9f9a | ||
|
93b1774135 | ||
|
0a5c226af6 | ||
|
2cde62f618 | ||
|
136ba40956 | ||
|
7fe758d697 | ||
|
762684ffea | ||
|
2b5a028af4 | ||
|
487b36a326 | ||
|
ea2c7973a9 | ||
|
2d34b54874 | ||
|
696f9083f3 | ||
|
db08d4eab3 | ||
|
2f2f88dedd | ||
|
a512e3bec0 | ||
|
06f2c920f0 | ||
|
9903e85a66 | ||
|
9949d5695c | ||
|
515a0af1b4 | ||
|
f5ba78be81 | ||
|
10e87dd5ca | ||
|
5db69d1ce0 | ||
|
a9009725ce | ||
|
d59174da77 | ||
|
679143967d | ||
|
59e833b6cc | ||
|
2e9bccf9e9 | ||
|
54f472a750 | ||
|
a0dbee6749 | ||
|
69fdb9090f | ||
|
43e5849015 | ||
|
92775e459c | ||
|
748bee74cb | ||
|
3cdec1cea3 | ||
|
76b7e24614 | ||
|
9737fda9ae | ||
|
06f580ed29 | ||
|
553a95fd39 | ||
|
3e30fb5d14 | ||
|
847961861f | ||
|
59dba15a4f | ||
|
2aa0c5d707 | ||
|
976a8fd65c | ||
|
5798c98f41 | ||
|
187a0925b0 | ||
|
45047fc6b2 | ||
|
9d5af39682 | ||
|
b6fbe41f93 | ||
|
47a5c9e9f6 | ||
|
c9fa19e8dd | ||
|
89a1378397 | ||
|
1739af3ef6 | ||
|
c1b9a30087 | ||
|
ca8b06f4cb | ||
|
68f967ea78 | ||
|
7354003db1 | ||
|
b2e541c6d9 | ||
|
7321b37799 | ||
|
9532ad4e5a | ||
|
7118b430d5 | ||
|
961139304d | ||
|
efe4a974be | ||
|
92127615e5 | ||
|
deb2efc16e | ||
|
9bbaa85a3b | ||
|
04cfedea7c | ||
|
16fd92b1a3 | ||
|
7984e3b818 | ||
|
da8beeb503 | ||
|
612db28bcb | ||
|
506aeb2e40 | ||
|
26ac519c55 | ||
|
bbec184d17 | ||
|
951e22ac8e | ||
|
861e0d017e | ||
|
f6526bbb4c | ||
|
d004a3141e | ||
|
bd74939a55 | ||
|
c0286150ed | ||
|
fc9c90c4ee | ||
|
2836704c4e | ||
|
71201377ef | ||
|
9de7db8f2d | ||
|
31057e1e81 | ||
|
66de4a1e09 | ||
|
4cc3d335a8 | ||
|
09eea3c8cd | ||
|
747f7829fd | ||
|
ab90d6ec3d | ||
|
3ce14883b9 | ||
|
f360706227 | ||
|
ef9b7187dc | ||
|
869e02dd42 | ||
|
e78abf9269 | ||
|
23287597ee | ||
|
9f0530f422 | ||
|
275f187719 | ||
|
97e1585152 | ||
|
8a2506d8a3 | ||
|
a79bae5975 | ||
|
01b4e1dae3 | ||
|
4fd714a1ee | ||
|
84e44d7c0a | ||
|
fed47d7477 | ||
|
2302785242 | ||
|
6cbfb56fff | ||
|
59c699c999 | ||
|
1d4746b743 | ||
|
82a09d2feb | ||
|
c873a6b04c | ||
|
e9f7ea16ce | ||
|
786ae619cb | ||
|
ad779129d3 | ||
|
e7af6892fb | ||
|
fa9df8f22e | ||
|
1672824416 | ||
|
c096a55697 | ||
|
d4332aa7ec | ||
|
2f497cf25b | ||
|
7d472f00f7 | ||
|
1e5f789f59 | ||
|
1f14c3669d | ||
|
40e2af4c73 | ||
|
bd34cab6e8 | ||
|
85876e9377 | ||
|
e5f37ee073 | ||
|
267db5166f | ||
|
0e45450912 | ||
|
4dac2126bf | ||
|
4230f3881d | ||
|
408f83804d | ||
|
4d299916be | ||
|
4b8711c8f8 | ||
|
8d6e6de200 | ||
|
df4586811d | ||
|
012f0237db | ||
|
23a6064a55 | ||
|
a37922ad59 | ||
|
2a235b7889 | ||
|
e4a6bdb389 | ||
|
4a29072e1c | ||
|
36d0244be4 | ||
|
fda152cef0 | ||
|
3723ae840f | ||
|
a513434b5f | ||
|
ec05937dd4 | ||
|
0ec9198ef5 | ||
|
64bba40c41 | ||
|
350e2108e2 | ||
|
5fa5edffba | ||
|
df184bd46a | ||
|
f0d0f38c4f | ||
|
2663a8370f | ||
|
3b66310dd2 | ||
|
9c28126ccd | ||
|
fb97d95dae | ||
|
2d6ed116e6 | ||
|
114d756a68 | ||
|
8c710a08a3 | ||
|
c5c921b0d6 | ||
|
3c68a4e2a0 | ||
|
72488b5900 | ||
|
b970bde972 | ||
|
10c836fcbc | ||
|
d979dd263a | ||
|
4c51b1ffe1 | ||
|
0490ca25b0 | ||
|
5ce41342c0 | ||
|
052089b3c0 | ||
|
21bb5d7808 | ||
|
f51af31850 | ||
|
7e975e9df0 | ||
|
56656b95cf | ||
|
2d97b4bd0a | ||
|
81d9cead5c | ||
|
511f762e54 | ||
|
04a645141c | ||
|
9ef8f0b069 | ||
|
e12242f44f | ||
|
976248b665 | ||
|
84d9113ed3 | ||
|
a43f99b492 | ||
|
28ba84ea6f | ||
|
93876b8189 | ||
|
040c4a8894 | ||
|
22a5def618 | ||
|
58a6ccd4a5 | ||
|
cefc10b405 | ||
|
6d649c716d | ||
|
ba545e44e3 | ||
|
d59024b4a5 | ||
|
6a5b44b3b3 | ||
|
75090c4fa4 | ||
|
b0db3686b1 | ||
|
468aafb384 | ||
|
b85605cac8 | ||
|
2edebec52c | ||
|
64fcb4b1f0 | ||
|
feecb1fa27 | ||
|
2ae467d14f | ||
|
0db9cec7c4 | ||
|
0c0baecb5f | ||
|
b34478f800 | ||
|
3b51252e9e | ||
|
3a8f4e4f76 | ||
|
a8341f7b57 | ||
|
db7578be8e | ||
|
536052af3d | ||
|
f4cc3932da | ||
|
c890da2877 | ||
|
b5d1ed048d | ||
|
ed0272efa6 | ||
|
7686ac0b28 | ||
|
bec6227aaf | ||
|
6a2a0efc84 | ||
|
b09ea054df | ||
|
024784e0b0 | ||
|
329158349f | ||
|
62d5f20590 | ||
|
e420c96e77 | ||
|
7af5a6ee5d | ||
|
e91cbe009f |
@@ -3,4 +3,5 @@ node_modules
|
||||
npm-debug.log
|
||||
readme*
|
||||
Start.bat
|
||||
/dist
|
||||
/dist
|
||||
/backups/
|
||||
|
69
.github/readme.md
vendored
69
.github/readme.md
vendored
@@ -1,16 +1,16 @@
|
||||

|
||||
|
||||
Mobile-friendly, Multi-API (KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI+proxies, Poe, WindowAI(Claude!)), VN-like Waifu Mode, Horde SD, System TTS, WorldInfo (lorebooks), customizable UI, auto-translate, and more prompt options than you'd ever want or need. Optional Extras server for more SD/TTS options + ChromaDB/Summarize.
|
||||
Mobile-friendly, Multi-API (KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI+proxies, WindowAI(Claude!)), VN-like Waifu Mode, Horde SD, System TTS, WorldInfo (lorebooks), customizable UI, auto-translate, and more prompt options than you'd ever want or need. Optional Extras server for more SD/TTS options + ChromaDB/Summarize.
|
||||
|
||||
Based on a fork of TavernAI 1.2.8
|
||||
|
||||
### Brought to you by Cohee, RossAscends and the SillyTavern community
|
||||
### Brought to you by Cohee, RossAscends, and the SillyTavern community
|
||||
|
||||
NOTE: We have created a [Documentation website](https://docs.sillytavern.app/) to answer most of your questions and help you get started.
|
||||
|
||||
### What is SillyTavern or TavernAI?
|
||||
|
||||
Tavern is a user interface you can install on your computer (and Android phones) that allows you to interact with text generation AIs and chat/roleplay with characters you or the community create.
|
||||
SillyTavern is a user interface you can install on your computer (and Android phones) that allows you to interact with text generation AIs and chat/roleplay with characters you or the community create.
|
||||
|
||||
SillyTavern is a fork of TavernAI 1.2.8 which is under more active development and has added many major features. At this point, they can be thought of as completely independent programs.
|
||||
|
||||
@@ -53,7 +53,7 @@ Get support, share favorite characters and prompts:
|
||||
|
||||
Get in touch with the developers directly:
|
||||
|
||||
* Discord: Cohee#1207 or RossAscends#1779
|
||||
* Discord: cohee or rossascends
|
||||
* Reddit: /u/RossAscends or /u/sillylossy
|
||||
* [Post a GitHub issue](https://github.com/SillyTavern/SillyTavern/issues)
|
||||
|
||||
@@ -64,36 +64,35 @@ Get in touch with the developers directly:
|
||||
* Group chats: multi-bot rooms for characters to talk to you or each other
|
||||
* Chat bookmarks / branching (duplicates the dialogue in its current state)
|
||||
* Advanced KoboldAI / TextGen generation settings with a lot of community-made presets
|
||||
* World Info support: create a rich lore or save tokens on your character card
|
||||
* Window AI browser extension support (run models like Claude, GPT 4): https://windowai.io/
|
||||
* World Info support: create rich lore or save tokens on your character card
|
||||
* Window AI browser extension support (run models like Claude, GPT 4): <https://windowai.io/>
|
||||
* [Oobabooga's TextGen WebUI](https://github.com/oobabooga/text-generation-webui) API connection
|
||||
* [AI Horde](https://horde.koboldai.net/) connection
|
||||
* [Poe.com](https://poe.com) (ChatGPT / Claude) connection
|
||||
* Soft prompts selector for KoboldAI
|
||||
* Prompt generation formatting tweaking
|
||||
* webp character card interoperability (PNG is still an internal format)
|
||||
|
||||
## Extensions
|
||||
|
||||
SillyTavern has an extensibility support, with some additional AI modules hosted via [SillyTavern Extras API](https://github.com/SillyTavern/SillyTavern-extras)
|
||||
SillyTavern has extensibility support, with some additional AI modules hosted via [SillyTavern Extras API](https://github.com/SillyTavern/SillyTavern-extras)
|
||||
|
||||
* Author's Note / Character Bias
|
||||
* Character emotional expressions
|
||||
* Character emotional expressions (sprites)
|
||||
* Auto-Summary of the chat history
|
||||
* Sending images to chat, and the AI interpreting the content.
|
||||
* Sending images to chat, and the AI interpreting the content
|
||||
* Stable Diffusion image generation (5 chat-related presets plus 'free mode')
|
||||
* Text-to-speech for AI response messages (via ElevenLabs, Silero, or the OS's System TTS)
|
||||
* ChromaDB vector storage for smarter chat prompt formatting
|
||||
|
||||
Full list of included extenisons and tutorials how to use them can be found on [Wiki](https://github.com/SillyTavern/SillyTavern/wiki).
|
||||
A full list of included extensions and tutorials on how to use them can be found in the [Docs](https://docs.sillytavern.app/extras/extensions/).
|
||||
|
||||
## UI/CSS/Quality of Life tweaks by RossAscends
|
||||
|
||||
* Mobile UI with optimized for iOS, and supports saving a shortcut to home screen and opening in fullscreen mode.
|
||||
* Mobile UI optimized for iOS, and supports saving a shortcut to the home screen and opening in fullscreen mode.
|
||||
* HotKeys
|
||||
* Up = Edit last message in chat
|
||||
* Ctrl+Up = Edit last USER message in chat
|
||||
* Left = swipe left
|
||||
* Right = swipe right (NOTE: swipe hotkeys are disabled when chatbar has something typed into it)
|
||||
* Right = swipe right (NOTE: swipe hotkeys are disabled when the chat bar has something typed into it)
|
||||
* Ctrl+Left = view locally stored variables (in the browser console window)
|
||||
* Enter (with chat bar selected) = send your message to AI
|
||||
* Ctrl+Enter = Regenerate the last AI response
|
||||
@@ -118,7 +117,7 @@ Full list of included extenisons and tutorials how to use them can be found on [
|
||||
* Switch between round or rectangle avatar styles
|
||||
* Have a wider chat window on the desktop
|
||||
* Optional semi-transparent glass-like panels
|
||||
* Customizable page colors for 'main text', 'quoted text' 'italics text'.
|
||||
* Customizable page colors for 'main text', 'quoted text', and 'italics text'.
|
||||
* Customizable UI background color and blur amount
|
||||
|
||||
## Installation
|
||||
@@ -135,8 +134,8 @@ Full list of included extenisons and tutorials how to use them can be found on [
|
||||
|
||||
Installing via Git (recommended for easy updating)
|
||||
|
||||
Easy to follow guide with pretty pictures:
|
||||
<https://docs.alpindale.dev/pygmalion-extras/sillytavern/#windows-installation>
|
||||
An easy-to-follow guide with pretty pictures:
|
||||
<https://docs.sillytavern.app/installation/windows/>
|
||||
|
||||
1. Install [NodeJS](https://nodejs.org/en) (latest LTS version is recommended)
|
||||
2. Install [GitHub Desktop](https://central.github.com/deployments/desktop/desktop/latest/win32)
|
||||
@@ -148,15 +147,15 @@ Easy to follow guide with pretty pictures:
|
||||
* for Main Branch: `git clone https://github.com/SillyTavern/SillyTavern -b main`
|
||||
* for Dev Branch: `git clone https://github.com/SillyTavern/SillyTavern -b dev`
|
||||
|
||||
7. Once everything is cloned, double click `Start.bat` to make NodeJS install its requirements.
|
||||
8. The server will then start, and SillyTavern will popup in your browser.
|
||||
7. Once everything is cloned, double-click `Start.bat` to make NodeJS install its requirements.
|
||||
8. The server will then start, and SillyTavern will pop up in your browser.
|
||||
|
||||
Installing via zip download
|
||||
Installing via ZIP download (discouraged)
|
||||
|
||||
1. Install [NodeJS](https://nodejs.org/en) (latest LTS version is recommended)
|
||||
2. Download the zip from this GitHub repo. (Get the `Source code (zip)` from [Releases](https://github.com/SillyTavern/SillyTavern/releases/latest))
|
||||
3. Unzip it into a folder of your choice
|
||||
4. Run `Start.bat` via double-clicking or in a command line.
|
||||
4. Run `Start.bat` by double-clicking or in a command line.
|
||||
5. Once the server has prepared everything for you, it will open a tab in your browser.
|
||||
|
||||
### Linux
|
||||
@@ -168,7 +167,7 @@ Installing via zip download
|
||||
|
||||
SillyTavern saves your API keys to a `secrets.json` file in the server directory.
|
||||
|
||||
By default they will not be exposed to a frontend after you enter them and reload the page.
|
||||
By default, they will not be exposed to a frontend after you enter them and reload the page.
|
||||
|
||||
In order to enable viewing your keys by clicking a button in the API block:
|
||||
|
||||
@@ -186,9 +185,9 @@ However, it can be used to allow remote connections from anywhere as well.
|
||||
### 1. Managing whitelisted IPs
|
||||
|
||||
* Create a new text file inside your SillyTavern base install folder called `whitelist.txt`.
|
||||
* Open the file in a text editor, add a list of IPs you want to be allowed to connect.
|
||||
* Open the file in a text editor, and add a list of IPs you want to be allowed to connect.
|
||||
|
||||
*Both indidivual IPs, and wildcard IP ranges are accepted. Examples:*
|
||||
*Both individual IPs and wildcard IP ranges are accepted. Examples:*
|
||||
|
||||
```txt
|
||||
192.168.0.1
|
||||
@@ -220,15 +219,15 @@ If the ST-hosting device is on the same wifi network, you will use the ST-host's
|
||||
|
||||
* For Windows: windows button > type `cmd.exe` in the search bar > type `ipconfig` in the console, hit Enter > look for `IPv4` listing.
|
||||
|
||||
If you (or someone else) wants to connect to your hosted ST while not being on the same network, you will need the public IP of your ST-hosting device.
|
||||
If you (or someone else) want to connect to your hosted ST while not being on the same network, you will need the public IP of your ST-hosting device.
|
||||
|
||||
* While using the ST-hosting device, access [this page](https://whatismyipaddress.com/) and look for for `IPv4`. This is what you would use to connect from the remote device.
|
||||
|
||||
### 3. Connect the remote device to the ST host machine.
|
||||
### 3. Connect the remote device to the ST host machine
|
||||
|
||||
Whatever IP you ended up with for your situation, you will put that IP address and port number into the remote device's web browser.
|
||||
|
||||
A typical address for an ST host on the same wifi network would look like:
|
||||
A typical address for an ST host on the same wifi network would look like this:
|
||||
|
||||
`http://192.168.0.5:8000`
|
||||
|
||||
@@ -238,7 +237,7 @@ Use http:// NOT https://
|
||||
|
||||
We do not recommend doing this, but you can open `config.conf` and change `whitelist` to `false`.
|
||||
|
||||
You must remove (or rename) `whitelist.txt` in the SillyTavern base install folder, if it exists.
|
||||
You must remove (or rename) `whitelist.txt` in the SillyTavern base install folder if it exists.
|
||||
|
||||
This is usually an insecure practice, so we require you to set a username and password when you do this.
|
||||
|
||||
@@ -248,8 +247,8 @@ After restarting your ST server, any device will be able to connect to it, regar
|
||||
|
||||
### Still Unable To Connect?
|
||||
|
||||
* Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for portforwarding on your router, otherwise someone could find your chat logs and that's a big no-no.
|
||||
* Enable the Private Network profile type in Settings > Network and Internet > Ethernet. This is VERY important for Windows 11, otherwise you would be unable to connect even with the aforementioned firewall rules.
|
||||
* Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for port-forwarding on your router, otherwise, someone could find your chat logs and that's a big no-no.
|
||||
* Enable the Private Network profile type in Settings > Network and Internet > Ethernet. This is VERY important for Windows 11, otherwise, you would be unable to connect even with the aforementioned firewall rules.
|
||||
|
||||
## Performance issues?
|
||||
|
||||
@@ -271,7 +270,7 @@ Try enabling the No Blur Effect (Fast UI) mode on the User settings panel.
|
||||
|
||||
## Where can I find the old backgrounds?
|
||||
|
||||
We're moving to 100% original content only policy, so old background images have been removed from this repository.
|
||||
We're moving to a 100% original content only policy, so old background images have been removed from this repository.
|
||||
|
||||
You can find them archived here:
|
||||
|
||||
@@ -293,14 +292,16 @@ GNU Affero General Public License for more details.**
|
||||
* Cohee's modifications and derived code: AGPL v3
|
||||
* RossAscends' additions: AGPL v3
|
||||
* Portions of CncAnon's TavernAITurbo mod: Unknown license
|
||||
* kingbri's various commits and suggestions (<https://github.com/bdashore3>)
|
||||
* BlipRanger's miscellaneous UI & extension modifications (<https://github.com/BlipRanger>)
|
||||
* Waifu mode inspired by the work of PepperTaco (<https://github.com/peppertaco/Tavern/>)
|
||||
* Thanks Pygmalion University for being awesome testers and suggesting cool features!
|
||||
* Thanks oobabooga for compiling presets for TextGen
|
||||
* poe-api client adapted from <https://github.com/ading2210/poe-api> (GPL v3)
|
||||
* GraphQL files for poe: <https://github.com/muharamdani/poe> (ISC License)
|
||||
* KoboldAI Presets from KAI Lite: <https://lite.koboldai.net/>
|
||||
* Noto Sans font by Google (OFL license)
|
||||
* Icon theme by Font Awesome <https://fontawesome.com> (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* AI Horde client library by ZeldaFan0225: https://github.com/ZeldaFan0225/ai_horde
|
||||
* AI Horde client library by ZeldaFan0225: <https://github.com/ZeldaFan0225/ai_horde>
|
||||
* Linux startup script by AlpinDale
|
||||
* Thanks paniphons for providing a FAQ document
|
||||
* 10K Discord Users Celebratory Background by @kallmeflocc
|
||||
* Korean translation by @doloroushyeonse
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -9,6 +9,8 @@ public/worlds/
|
||||
public/css/bg_load.css
|
||||
public/themes/
|
||||
public/OpenAI Settings/
|
||||
public/scripts/extensions/third-party/
|
||||
public/stats.json
|
||||
/uploads/
|
||||
*.jsonl
|
||||
config.conf
|
||||
@@ -19,4 +21,5 @@ whitelist.txt
|
||||
.vscode
|
||||
secrets.json
|
||||
/dist
|
||||
poe_device.json
|
||||
/backups/
|
||||
public/movingUI/
|
||||
|
@@ -4,4 +4,4 @@ node_modules/
|
||||
/thumbnails
|
||||
secrets.json
|
||||
/dist
|
||||
poe_device.json
|
||||
/backups/
|
||||
|
@@ -1,5 +1,5 @@
|
||||
pushd %~dp0
|
||||
call npm install
|
||||
call npm install --no-audit
|
||||
node server.js
|
||||
pause
|
||||
popd
|
||||
popd
|
||||
|
@@ -32,6 +32,8 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@markdown (RECOMMENDED) Generates an API key for you to use with the API\n",
|
||||
"secure = False #@param {type:\"boolean\"}\n",
|
||||
"#@markdown Enables hosting of extensions backend for SillyTavern Extras\n",
|
||||
"use_cpu = False #@param {type:\"boolean\"}\n",
|
||||
"#@markdown Allows to run SillyTavern Extras on CPU (use if you're out of daily GPU allowance)\n",
|
||||
@@ -80,6 +82,8 @@
|
||||
" params.append('--cpu')\n",
|
||||
"if use_sd_cpu:\n",
|
||||
" params.append('--sd-cpu')\n",
|
||||
"if secure:\n",
|
||||
" params.append('--secure')\n",
|
||||
"params.append('--share')\n",
|
||||
"ExtrasModules = []\n",
|
||||
"\n",
|
||||
|
277
package-lock.json
generated
277
package-lock.json
generated
@@ -1,15 +1,16 @@
|
||||
{
|
||||
"name": "sillytavern",
|
||||
"version": "1.7.0",
|
||||
"version": "1.9.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "sillytavern",
|
||||
"version": "1.7.0",
|
||||
"version": "1.9.0",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@dqbd/tiktoken": "^1.0.2",
|
||||
"@mlc-ai/web-tokenizers": "^0.1.0",
|
||||
"axios": "^1.4.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"compression": "^1",
|
||||
@@ -37,10 +38,11 @@
|
||||
"png-chunks-encode": "^1.0.0",
|
||||
"png-chunks-extract": "^1.0.0",
|
||||
"response-time": "^2.3.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"sentencepiece-js": "^1.1.0",
|
||||
"simple-git": "^3.19.1",
|
||||
"uniqolor": "^1.1.0",
|
||||
"user-agents": "^1.0.1444",
|
||||
"webp-converter": "2.3.2",
|
||||
"ws": "^8.13.0",
|
||||
"yargs": "^17.7.1",
|
||||
@@ -70,18 +72,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz",
|
||||
"integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
|
||||
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
|
||||
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
|
||||
"integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -561,6 +563,45 @@
|
||||
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@kwsites/file-exists": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
|
||||
"integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@kwsites/file-exists/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@kwsites/file-exists/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/@kwsites/promise-deferred": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
|
||||
"integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
|
||||
},
|
||||
"node_modules/@mlc-ai/web-tokenizers": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@mlc-ai/web-tokenizers/-/web-tokenizers-0.1.0.tgz",
|
||||
"integrity": "sha512-whiQ+40ohtAFoFOGcje1Io7BMr434Wh3hM3nBCWlJMpXxL5Rlig/AH9wjyUPsytKwWTEe7RoYPyXSbFw5Vs6Tw=="
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@@ -607,9 +648,9 @@
|
||||
"integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
"version": "0.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.11.tgz",
|
||||
"integrity": "sha512-UDi3g6Jss/W5FnSzO9jCtQwEpfymt0M+sPPlmLhDH6h2TJ8j4ESE/LpmNPBij15J5NKkk4/cg/qoVMdWI3vnlQ==",
|
||||
"version": "0.8.9",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.9.tgz",
|
||||
"integrity": "sha512-4VSbbcMoxc4KLjb1gs96SRmi7w4h1SF+fCoiK0XaQX62buCc1G5d0DC5bJ9xJBNPDSVCmIrcl8BiYxzjrqaaJA==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
@@ -745,11 +786,6 @@
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
@@ -830,15 +866,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
@@ -1021,11 +1048,6 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/concat-stream": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||
@@ -1201,6 +1223,14 @@
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-indent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz",
|
||||
"integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
|
||||
@@ -1230,11 +1260,32 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/docopt": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz",
|
||||
"integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-walk": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
||||
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
|
||||
},
|
||||
"node_modules/dot-json": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-json/-/dot-json-1.3.0.tgz",
|
||||
"integrity": "sha512-Pu11Prog/Yjf2lBICow82/DSV46n3a2XT1Rqt/CeuhkO1fuacF7xydYhI0SwQx2Ue0jCyLtQzgKPFEO6ewv+bQ==",
|
||||
"dependencies": {
|
||||
"detect-indent": "~6.0.0",
|
||||
"docopt": "~0.6.2",
|
||||
"underscore-keypath": "~0.0.22"
|
||||
},
|
||||
"bin": {
|
||||
"dot-json": "bin/dot-json.js"
|
||||
}
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
@@ -1289,12 +1340,12 @@
|
||||
"integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="
|
||||
},
|
||||
"node_modules/exifreader": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/exifreader/-/exifreader-4.12.0.tgz",
|
||||
"integrity": "sha512-aRSmNyw2c6f6qPK4jmC56W/5XePDN7LVwt8tQjgMchxoY3MCxqEToegirKdS7A3CYCWAOPehfypMZWGWxtLhzw==",
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/exifreader/-/exifreader-4.13.0.tgz",
|
||||
"integrity": "sha512-IhJBpyXDLbCdgzVHkthadOvrMiZOR2XS7POVp0b5JoVfScRoCJ6YazZ+stTkbDTE5TRTP44bE5RKsujckAs45Q==",
|
||||
"hasInstallScript": true,
|
||||
"optionalDependencies": {
|
||||
"@xmldom/xmldom": "^0.7.8"
|
||||
"@xmldom/xmldom": "^0.8.8"
|
||||
}
|
||||
},
|
||||
"node_modules/expand-template": {
|
||||
@@ -1375,9 +1426,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.2.12",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
|
||||
"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz",
|
||||
"integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
@@ -1531,11 +1582,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@@ -1578,25 +1624,6 @@
|
||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
@@ -1800,15 +1827,6 @@
|
||||
"@types/node": "16.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
@@ -2019,6 +2037,11 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash.clonedeep": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
@@ -2124,17 +2147,6 @@
|
||||
"dom-walk": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
@@ -2249,9 +2261,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/node-abi": {
|
||||
"version": "3.43.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.43.0.tgz",
|
||||
"integrity": "sha512-QB0MMv+tn9Ur2DtJrc8y09n0n6sw88CyDniWSX2cHW10goQXYPK9ZpFJOktDS4ron501edPX6h9i7Pg+RnH5nQ==",
|
||||
"version": "3.45.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz",
|
||||
"integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"semver": "^7.3.5"
|
||||
@@ -2261,9 +2273,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
||||
"integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
|
||||
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
@@ -2357,6 +2369,7 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@@ -2435,14 +2448,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
@@ -2974,20 +2979,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
@@ -3035,9 +3026,9 @@
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
|
||||
"integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
@@ -3162,6 +3153,41 @@
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-git": {
|
||||
"version": "3.19.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.19.1.tgz",
|
||||
"integrity": "sha512-Ck+rcjVaE1HotraRAS8u/+xgTvToTuoMkT9/l9lvuP5jftwnYUp6DwuJzsKErHgfyRk8IB8pqGHWEbM3tLgV1w==",
|
||||
"dependencies": {
|
||||
"@kwsites/file-exists": "^1.1.1",
|
||||
"@kwsites/promise-deferred": "^1.1.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/steveukx/git-js?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-git/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/simple-git/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
@@ -3430,6 +3456,19 @@
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||
},
|
||||
"node_modules/underscore": {
|
||||
"version": "1.13.6",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
|
||||
"integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A=="
|
||||
},
|
||||
"node_modules/underscore-keypath": {
|
||||
"version": "0.0.22",
|
||||
"resolved": "https://registry.npmjs.org/underscore-keypath/-/underscore-keypath-0.0.22.tgz",
|
||||
"integrity": "sha512-fU7aYj1J2LQd+jqdQ67AlCOZKK3Pl+VErS8fGYcgZG75XB9/bY+RLM+F2xEcKHhHNtLvqqFyXAoZQlLYfec3Xg==",
|
||||
"dependencies": {
|
||||
"underscore": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/uniqolor": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uniqolor/-/uniqolor-1.1.0.tgz",
|
||||
@@ -3452,6 +3491,15 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/user-agents": {
|
||||
"version": "1.0.1444",
|
||||
"resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.0.1444.tgz",
|
||||
"integrity": "sha512-6WXJ0RZuUKgif1rW5FN02HnpoJ8EzH6COQoXCiVStZEVPz+YnAx3iA48etY3ZD4UwueYN9ALC7j4ayHvYEh7tA==",
|
||||
"dependencies": {
|
||||
"dot-json": "^1.3.0",
|
||||
"lodash.clonedeep": "^4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf8-byte-length": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
|
||||
@@ -3529,7 +3577,8 @@
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.13.0",
|
||||
|
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@dqbd/tiktoken": "^1.0.2",
|
||||
"@mlc-ai/web-tokenizers": "^0.1.0",
|
||||
"axios": "^1.4.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"compression": "^1",
|
||||
@@ -28,10 +29,11 @@
|
||||
"png-chunks-encode": "^1.0.0",
|
||||
"png-chunks-extract": "^1.0.0",
|
||||
"response-time": "^2.3.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"sentencepiece-js": "^1.1.0",
|
||||
"simple-git": "^3.19.1",
|
||||
"uniqolor": "^1.1.0",
|
||||
"user-agents": "^1.0.1444",
|
||||
"webp-converter": "2.3.2",
|
||||
"ws": "^8.13.0",
|
||||
"yargs": "^17.7.1",
|
||||
@@ -48,7 +50,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
||||
},
|
||||
"version": "1.7.0",
|
||||
"version": "1.9.0",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"pkg": "pkg --compress Gzip --no-bytecode --public ."
|
||||
@@ -68,8 +70,7 @@
|
||||
"node18-windows-x64"
|
||||
],
|
||||
"assets": [
|
||||
"node_modules/**/*",
|
||||
"src/poe_graphql/**/*"
|
||||
"node_modules/**/*"
|
||||
],
|
||||
"outputPath": "dist",
|
||||
"scripts": [
|
||||
|
21
poe-test.js
21
poe-test.js
@@ -1,21 +0,0 @@
|
||||
const poe = require('./src/poe-client');
|
||||
|
||||
async function test() {
|
||||
const client = new poe.Client();
|
||||
await client.init('pb-cookie');
|
||||
|
||||
const bots = client.get_bot_names();
|
||||
console.log(bots);
|
||||
|
||||
await client.purge_conversation('a2', -1);
|
||||
|
||||
let reply;
|
||||
for await (const mes of client.send_message('a2', 'Hello')) {
|
||||
reply = mes.text;
|
||||
}
|
||||
|
||||
console.log(reply);
|
||||
client.disconnect_ws();
|
||||
}
|
||||
|
||||
test();
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 1.15,
|
||||
"genamt": 100,
|
||||
"temp": 1.15,
|
||||
"top_k": 0,
|
||||
"top_p": 0.95,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 7,
|
||||
"sampler_order": [
|
||||
6,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
5,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,6 +1,16 @@
|
||||
{
|
||||
"apikey": "",
|
||||
"andepth": 1,
|
||||
"max_length": 2048,
|
||||
"genamt": 90,
|
||||
"temp": 0.8,
|
||||
"top_k": 28,
|
||||
"top_p": 0.94,
|
||||
"top_a": 0.00,
|
||||
"tfs": 0.96,
|
||||
"typical": 0.98,
|
||||
"rep_pen": 1.03,
|
||||
"rep_pen_slope": 0.8,
|
||||
"rep_pen_range": 120.0,
|
||||
"ikgen": 200,
|
||||
"sampler_order": [
|
||||
6,
|
||||
4,
|
||||
@@ -9,46 +19,5 @@
|
||||
0,
|
||||
1,
|
||||
5
|
||||
],
|
||||
"temp": 0.8,
|
||||
"top_p": 0.94,
|
||||
"top_k": 28,
|
||||
"tfs": 0.96,
|
||||
"typical": 0.98,
|
||||
"top_a": 0.00,
|
||||
"rep_pen": 1.03,
|
||||
"rep_pen_slope": 0.8,
|
||||
"rep_pen_range": 120.0,
|
||||
"genamt": 90,
|
||||
"max_length": 2048,
|
||||
"ikgen": 200,
|
||||
"formatoptns": {
|
||||
"frmttriminc": true,
|
||||
"frmtrmblln": false,
|
||||
"frmtrmspch": false,
|
||||
"frmtadsnsp": true,
|
||||
"singleline": false
|
||||
},
|
||||
"numseqs": 1,
|
||||
"widepth": 3,
|
||||
"useprompt": false,
|
||||
"adventure": false,
|
||||
"chatmode": false,
|
||||
"chatname": "You",
|
||||
"dynamicscan": false,
|
||||
"nopromptgen": false,
|
||||
"rngpersist": false,
|
||||
"nogenmod": false,
|
||||
"fulldeterminism": false,
|
||||
"autosave": false,
|
||||
"welcome": "## Warning: This model has a very heavy NSFW bias and is not suitable for use by minors!\n\nYou are currently running story-writing model `Erebus, version 1 (20B).`\n\n This model is made by [Mr. Seeker](https://www.patreon.com/mrseeker) with help of ProudNoob and the KoboldAI team.\n\n### How to use this model\n\nErebus is designed to generate short stories and novels. Use the author's note to give it a certain genre to follow, use memory to give an overview of the story and use World Information to give specific details about the characters. To start off, give the AI an idea of what you are writing about by setting the scene. Give the AI around 10 sentences that make your story interesting to read. Introduce your character, describe the world, blow something up, or let the AI use its creative mind.",
|
||||
"output_streaming": true,
|
||||
"show_probs": false,
|
||||
"show_budget": false,
|
||||
"seed": null,
|
||||
"newlinemode": "n",
|
||||
"antemplate": "",
|
||||
"userscripts": [],
|
||||
"corescript": "default.lua",
|
||||
"softprompt": ""
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 0.59,
|
||||
"genamt": 100,
|
||||
"temp": 0.59,
|
||||
"top_k": 0,
|
||||
"top_p": 1,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 0.3,
|
||||
"sampler_order": [
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 0.8,
|
||||
"genamt": 100,
|
||||
"temp": 0.8,
|
||||
"top_k": 100,
|
||||
"top_p": 0.9,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 3.4,
|
||||
"sampler_order": [
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,21 +1,15 @@
|
||||
{
|
||||
"file_version": 2,
|
||||
"max_length": 2048,
|
||||
"ikmax": 3000,
|
||||
"genamt": 180,
|
||||
"ikgen": 200,
|
||||
"rep_pen": 1.01,
|
||||
"rep_pen_slope": 0.9,
|
||||
"rep_pen_range": 1024,
|
||||
"temp": 1.0,
|
||||
"top_p": 0.9,
|
||||
"top_k": 40,
|
||||
"top_a": 0.0,
|
||||
"tfs": 0.9,
|
||||
"typical": 1.0,
|
||||
"numseqs": 1,
|
||||
"fp32_model": false,
|
||||
"modeldim": 4096,
|
||||
"rep_pen": 1.01,
|
||||
"rep_pen_slope": 0.9,
|
||||
"rep_pen_range": 1024,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
@@ -24,24 +18,5 @@
|
||||
3,
|
||||
4,
|
||||
5
|
||||
|
||||
],
|
||||
"newlinemode": "n",
|
||||
"lazy_load": true,
|
||||
"revision": null,
|
||||
"selected_preset": "",
|
||||
"horde_wait_time": 0,
|
||||
"horde_queue_position": 0,
|
||||
"horde_queue_size": 0,
|
||||
"model": "pygmalion-6b",
|
||||
"model_type": "gptj",
|
||||
"url": "https://api.inferkit.com/v1/models/standard/generate",
|
||||
"oaiurl": "",
|
||||
"oaiengines": "https://api.openai.com/v1/engines",
|
||||
"colaburl": "/request",
|
||||
"apikey": "",
|
||||
"oaiapikey": "",
|
||||
"configname": "pygmalion-6b",
|
||||
"online_model": "",
|
||||
"alt_multi_gen": false
|
||||
]
|
||||
}
|
@@ -1,21 +1,15 @@
|
||||
{
|
||||
"file_version": 2,
|
||||
"max_length": 2048,
|
||||
"ikmax": 3000,
|
||||
"genamt": 180,
|
||||
"ikgen": 200,
|
||||
"rep_pen": 1.17,
|
||||
"rep_pen_slope": 0.2,
|
||||
"rep_pen_range": 1024,
|
||||
"temp": 0.43,
|
||||
"top_p": 0.96,
|
||||
"top_k": 0,
|
||||
"top_a": 0.0,
|
||||
"tfs": 0.68,
|
||||
"typical": 1.0,
|
||||
"numseqs": 1,
|
||||
"fp32_model": false,
|
||||
"modeldim": 2560,
|
||||
"rep_pen": 1.17,
|
||||
"rep_pen_slope": 0.2,
|
||||
"rep_pen_range": 1024,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
@@ -24,23 +18,5 @@
|
||||
3,
|
||||
4,
|
||||
5
|
||||
],
|
||||
"newlinemode": "n",
|
||||
"lazy_load": true,
|
||||
"revision": null,
|
||||
"selected_preset": "",
|
||||
"horde_wait_time": 0,
|
||||
"horde_queue_position": 0,
|
||||
"horde_queue_size": 0,
|
||||
"model": "pygmalion-2.7b",
|
||||
"model_type": "gpt_neo",
|
||||
"url": "https://api.inferkit.com/v1/models/standard/generate",
|
||||
"oaiurl": "",
|
||||
"oaiengines": "https://api.openai.com/v1/engines",
|
||||
"colaburl": "/request",
|
||||
"apikey": "",
|
||||
"oaiapikey": "",
|
||||
"configname": "pygmalion-2.7b",
|
||||
"online_model": "",
|
||||
"alt_multi_gen": false
|
||||
]
|
||||
}
|
@@ -1,21 +1,15 @@
|
||||
{
|
||||
"file_version": 2,
|
||||
"max_length": 2048,
|
||||
"ikmax": 3000,
|
||||
"genamt": 180,
|
||||
"ikgen": 200,
|
||||
"rep_pen": 1.1,
|
||||
"rep_pen_slope": 0.9,
|
||||
"rep_pen_range": 1024,
|
||||
"temp": 0.65,
|
||||
"top_p": 0.9,
|
||||
"top_k": 0,
|
||||
"top_a": 0.0,
|
||||
"tfs": 0.9,
|
||||
"typical": 1.0,
|
||||
"numseqs": 1,
|
||||
"fp32_model": false,
|
||||
"modeldim": 4096,
|
||||
"rep_pen": 1.1,
|
||||
"rep_pen_slope": 0.9,
|
||||
"rep_pen_range": 1024,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
@@ -23,25 +17,6 @@
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
|
||||
],
|
||||
"newlinemode": "n",
|
||||
"lazy_load": true,
|
||||
"revision": null,
|
||||
"selected_preset": "",
|
||||
"horde_wait_time": 0,
|
||||
"horde_queue_position": 0,
|
||||
"horde_queue_size": 0,
|
||||
"model": "pygmalion-6b",
|
||||
"model_type": "gptj",
|
||||
"url": "https://api.inferkit.com/v1/models/standard/generate",
|
||||
"oaiurl": "",
|
||||
"oaiengines": "https://api.openai.com/v1/engines",
|
||||
"colaburl": "/request",
|
||||
"apikey": "",
|
||||
"oaiapikey": "",
|
||||
"configname": "pygmalion-6b",
|
||||
"online_model": "",
|
||||
"alt_multi_gen": false
|
||||
5
|
||||
]
|
||||
}
|
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"genamt": 100,
|
||||
"temp": 0.51,
|
||||
"top_p": 1,
|
||||
"top_k": 0,
|
||||
"tfs": 0.99,
|
||||
"top_a": 0,
|
||||
"typical": 1,
|
||||
"rep_pen": 1.2,
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 0,
|
||||
"sampler_order": [
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
],
|
||||
"temp": 0.51,
|
||||
"tfs": 0.99,
|
||||
"top_a": 0,
|
||||
"top_k": 0,
|
||||
"top_p": 1,
|
||||
"typical": 1
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 1600,
|
||||
"temp": 0.79,
|
||||
"genamt": 180,
|
||||
"temp": 0.79,
|
||||
"top_k": 0,
|
||||
"top_p": 0.9,
|
||||
"top_a": 0,
|
||||
|
@@ -1,21 +1,15 @@
|
||||
{
|
||||
"file_version": 2,
|
||||
"max_length": 2048,
|
||||
"ikmax": 3000,
|
||||
"genamt": 180,
|
||||
"ikgen": 200,
|
||||
"rep_pen": 1.19,
|
||||
"rep_pen_slope": 0.9,
|
||||
"rep_pen_range": 1024,
|
||||
"temp": 0.79,
|
||||
"top_p": 0.9,
|
||||
"top_k": 0,
|
||||
"top_a": 0.0,
|
||||
"tfs": 0.95,
|
||||
"typical": 1.0,
|
||||
"numseqs": 1,
|
||||
"fp32_model": false,
|
||||
"modeldim": 4096,
|
||||
"rep_pen": 1.19,
|
||||
"rep_pen_slope": 0.9,
|
||||
"rep_pen_range": 1024,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
@@ -24,24 +18,5 @@
|
||||
3,
|
||||
4,
|
||||
5
|
||||
|
||||
],
|
||||
"newlinemode": "n",
|
||||
"lazy_load": true,
|
||||
"revision": null,
|
||||
"selected_preset": "",
|
||||
"horde_wait_time": 0,
|
||||
"horde_queue_position": 0,
|
||||
"horde_queue_size": 0,
|
||||
"model": "pygmalion-6b",
|
||||
"model_type": "gptj",
|
||||
"url": "https://api.inferkit.com/v1/models/standard/generate",
|
||||
"oaiurl": "",
|
||||
"oaiengines": "https://api.openai.com/v1/engines",
|
||||
"colaburl": "/request",
|
||||
"apikey": "",
|
||||
"oaiapikey": "",
|
||||
"configname": "pygmalion-6b",
|
||||
"online_model": "",
|
||||
"alt_multi_gen": false
|
||||
]
|
||||
}
|
@@ -1,21 +1,15 @@
|
||||
{
|
||||
"file_version": 2,
|
||||
"max_length": 1400,
|
||||
"ikmax": 3000,
|
||||
"genamt": 180,
|
||||
"ikgen": 200,
|
||||
"rep_pen": 1.08,
|
||||
"rep_pen_slope": 0.9,
|
||||
"rep_pen_range": 1024,
|
||||
"temp": 0.65,
|
||||
"top_p": 0.9,
|
||||
"top_k": 0,
|
||||
"top_a": 0.0,
|
||||
"tfs": 0.9,
|
||||
"typical": 1.0,
|
||||
"numseqs": 1,
|
||||
"fp32_model": false,
|
||||
"modeldim": 4096,
|
||||
"rep_pen": 1.08,
|
||||
"rep_pen_slope": 0.9,
|
||||
"rep_pen_range": 1024,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
@@ -24,24 +18,5 @@
|
||||
3,
|
||||
4,
|
||||
5
|
||||
|
||||
],
|
||||
"newlinemode": "n",
|
||||
"lazy_load": true,
|
||||
"revision": null,
|
||||
"selected_preset": "",
|
||||
"horde_wait_time": 0,
|
||||
"horde_queue_position": 0,
|
||||
"horde_queue_size": 0,
|
||||
"model": "pygmalion-6b",
|
||||
"model_type": "gptj",
|
||||
"url": "https://api.inferkit.com/v1/models/standard/generate",
|
||||
"oaiurl": "",
|
||||
"oaiengines": "https://api.openai.com/v1/engines",
|
||||
"colaburl": "/request",
|
||||
"apikey": "",
|
||||
"oaiapikey": "",
|
||||
"configname": "pygmalion-6b",
|
||||
"online_model": "",
|
||||
"alt_multi_gen": false
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 0.63,
|
||||
"genamt": 100,
|
||||
"temp": 0.63,
|
||||
"top_k": 0,
|
||||
"top_p": 0.98,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 0.1,
|
||||
"sampler_order": [
|
||||
6,
|
||||
2,
|
||||
0,
|
||||
3,
|
||||
5,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 0.7,
|
||||
"genamt": 100,
|
||||
"temp": 0.7,
|
||||
"top_k": 0,
|
||||
"top_p": 0.5,
|
||||
"top_a": 0.75,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 1024,
|
||||
"rep_pen_slope": 0.7,
|
||||
"sampler_order": [
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
6
|
||||
0
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 0.7,
|
||||
"genamt": 100,
|
||||
"temp": 0.7,
|
||||
"top_k": 0,
|
||||
"top_p": 1,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 1024,
|
||||
"rep_pen_slope": 0.7,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
5
|
||||
]
|
||||
}
|
@@ -1,15 +1,6 @@
|
||||
{
|
||||
"apikey": "",
|
||||
"andepth": 1,
|
||||
"sampler_order": [
|
||||
6,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
5
|
||||
],
|
||||
"max_length": 2048,
|
||||
"genamt": 90,
|
||||
"temp": 0.8,
|
||||
"top_p": 0.94,
|
||||
"top_k": 15,
|
||||
@@ -19,36 +10,13 @@
|
||||
"rep_pen": 1.02,
|
||||
"rep_pen_slope": 0.8,
|
||||
"rep_pen_range": 256.0,
|
||||
"genamt": 90,
|
||||
"max_length": 2048,
|
||||
"ikgen": 200,
|
||||
"formatoptns": {
|
||||
"frmttriminc": true,
|
||||
"frmtrmblln": false,
|
||||
"frmtrmspch": false,
|
||||
"frmtadsnsp": true,
|
||||
"singleline": false
|
||||
},
|
||||
"numseqs": 1,
|
||||
"widepth": 3,
|
||||
"useprompt": false,
|
||||
"adventure": false,
|
||||
"chatmode": false,
|
||||
"chatname": "You",
|
||||
"dynamicscan": false,
|
||||
"nopromptgen": false,
|
||||
"rngpersist": false,
|
||||
"nogenmod": false,
|
||||
"fulldeterminism": false,
|
||||
"autosave": false,
|
||||
"welcome": "## Warning: This model has a very heavy NSFW bias and is not suitable for use by minors!\n\nYou are currently running story-writing model `Erebus, version 1 (20B).`\n\n This model is made by [Mr. Seeker](https://www.patreon.com/mrseeker) with help of ProudNoob and the KoboldAI team.\n\n### How to use this model\n\nErebus is designed to generate short stories and novels. Use the author's note to give it a certain genre to follow, use memory to give an overview of the story and use World Information to give specific details about the characters. To start off, give the AI an idea of what you are writing about by setting the scene. Give the AI around 10 sentences that make your story interesting to read. Introduce your character, describe the world, blow something up, or let the AI use its creative mind.",
|
||||
"output_streaming": true,
|
||||
"show_probs": false,
|
||||
"show_budget": false,
|
||||
"seed": null,
|
||||
"newlinemode": "n",
|
||||
"antemplate": "",
|
||||
"userscripts": [],
|
||||
"corescript": "default.lua",
|
||||
"softprompt": ""
|
||||
"sampler_order": [
|
||||
6,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
5
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 0.66,
|
||||
"genamt": 100,
|
||||
"temp": 0.66,
|
||||
"top_k": 0,
|
||||
"top_p": 1,
|
||||
"top_a": 0.96,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 1024,
|
||||
"rep_pen_slope": 0.7,
|
||||
"sampler_order": [
|
||||
6,
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
6
|
||||
3
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 0.94,
|
||||
"genamt": 100,
|
||||
"temp": 0.94,
|
||||
"top_k": 12,
|
||||
"top_p": 1,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 0.2,
|
||||
"sampler_order": [
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 1.5,
|
||||
"genamt": 100,
|
||||
"temp": 1.5,
|
||||
"top_k": 85,
|
||||
"top_p": 0.24,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 0,
|
||||
"sampler_order": [
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 1.05,
|
||||
"genamt": 100,
|
||||
"temp": 1.05,
|
||||
"top_k": 0,
|
||||
"top_p": 0.95,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 1024,
|
||||
"rep_pen_slope": 0.7,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
5
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 1.07,
|
||||
"genamt": 100,
|
||||
"temp": 1.07,
|
||||
"top_k": 100,
|
||||
"top_p": 1,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 404,
|
||||
"rep_pen_slope": 0.8,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
5,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 0.44,
|
||||
"genamt": 100,
|
||||
"temp": 0.44,
|
||||
"top_k": 0,
|
||||
"top_p": 1,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 6.8,
|
||||
"sampler_order": [
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"temp": 1.35,
|
||||
"genamt": 100,
|
||||
"temp": 1.35,
|
||||
"top_k": 0,
|
||||
"top_p": 1,
|
||||
"top_a": 0,
|
||||
@@ -11,12 +11,12 @@
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 0.1,
|
||||
"sampler_order": [
|
||||
6,
|
||||
3,
|
||||
2,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,21 +1,15 @@
|
||||
{
|
||||
"file_version": 2,
|
||||
"max_length": 1400,
|
||||
"ikmax": 3000,
|
||||
"genamt": 80,
|
||||
"ikgen": 200,
|
||||
"rep_pen": 1.04,
|
||||
"rep_pen_slope": 0.0,
|
||||
"rep_pen_range": 1400,
|
||||
"temp": 1,
|
||||
"top_p": 1,
|
||||
"top_k": 0,
|
||||
"top_a": 0.0,
|
||||
"tfs": 0.97,
|
||||
"typical": 1.0,
|
||||
"numseqs": 1,
|
||||
"fp32_model": false,
|
||||
"modeldim": 2560,
|
||||
"rep_pen": 1.04,
|
||||
"rep_pen_slope": 0.0,
|
||||
"rep_pen_range": 1400,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
@@ -24,23 +18,5 @@
|
||||
3,
|
||||
4,
|
||||
5
|
||||
],
|
||||
"newlinemode": "n",
|
||||
"lazy_load": true,
|
||||
"revision": null,
|
||||
"selected_preset": "",
|
||||
"horde_wait_time": 0,
|
||||
"horde_queue_position": 0,
|
||||
"horde_queue_size": 0,
|
||||
"model": "pygmalion-1.3b",
|
||||
"model_type": "gpt_neo",
|
||||
"url": "https://api.inferkit.com/v1/models/standard/generate",
|
||||
"oaiurl": "",
|
||||
"oaiengines": "https://api.openai.com/v1/engines",
|
||||
"colaburl": "/request",
|
||||
"apikey": "",
|
||||
"oaiapikey": "",
|
||||
"configname": "pygmalion-1.3b",
|
||||
"online_model": "",
|
||||
"alt_multi_gen": false
|
||||
]
|
||||
}
|
22
public/KoboldAI Settings/RecoveredRuins.settings
Normal file
22
public/KoboldAI Settings/RecoveredRuins.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"max_length": 100,
|
||||
"genamt": 100,
|
||||
"temp": 1,
|
||||
"top_k": 0,
|
||||
"top_p": 0.95,
|
||||
"top_a": 0,
|
||||
"typical": 1,
|
||||
"tfs": 1,
|
||||
"rep_pen": 1.1,
|
||||
"rep_pen_range": 600,
|
||||
"rep_pen_slope": 0,
|
||||
"sampler_order": [
|
||||
6,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
]
|
||||
}
|
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"max_length": 2048,
|
||||
"genamt": 100,
|
||||
"rep_pen": 1.1,
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 0.2,
|
||||
"sampler_order": [
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
6
|
||||
],
|
||||
"temp": 0.72,
|
||||
"tfs": 1,
|
||||
"top_a": 0,
|
||||
"top_k": 0,
|
||||
"top_p": 0.73,
|
||||
"typical": 1
|
||||
"typical": 1,
|
||||
"rep_pen": 1.1,
|
||||
"rep_pen_range": 2048,
|
||||
"rep_pen_slope": 0.2,
|
||||
"sampler_order": [
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
4
|
||||
]
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"order": [1, 0, 3]
|
||||
"order": [1, 0, 3],
|
||||
"temperature": 1.07,
|
||||
"max_length": 60,
|
||||
"min_length": 60,
|
||||
@@ -14,4 +14,4 @@
|
||||
"repetition_penalty_frequency": 0,
|
||||
"repetition_penalty_presence": 0,
|
||||
"max_context":2048
|
||||
}
|
||||
}
|
||||
|
22
public/TextGen Settings/Asterism.settings
Normal file
22
public/TextGen Settings/Asterism.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 1.68,
|
||||
"top_p": 0.17,
|
||||
"top_k": 77,
|
||||
"typical_p": 1,
|
||||
"top_a": 0.42,
|
||||
"tfs": 0.97,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.02,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 4.5,
|
||||
"no_repeat_ngram_size": 2,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 200,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": true
|
||||
"early_stopping": true,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
22
public/TextGen Settings/Big O.settings
Normal file
22
public/TextGen Settings/Big O.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 0.87,
|
||||
"top_p": 0.99,
|
||||
"top_k": 85,
|
||||
"typical_p": 0.68,
|
||||
"top_a": 0,
|
||||
"tfs": 0.68,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.01,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0.6,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": false,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.2,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": false,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
22
public/TextGen Settings/Divine Intellect.settings
Normal file
22
public/TextGen Settings/Divine Intellect.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 1.31,
|
||||
"top_p": 0.14,
|
||||
"top_k": 49,
|
||||
"typical_p": 1,
|
||||
"top_a": 0.52,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 1.49,
|
||||
"eta_cutoff": 10.42,
|
||||
"rep_pen": 1.17,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 0.19,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.1,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 0.6,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.1,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.18,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 200,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
22
public/TextGen Settings/Midnight Enigma.settings
Normal file
22
public/TextGen Settings/Midnight Enigma.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 0.98,
|
||||
"top_p": 0.37,
|
||||
"top_k": 100,
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.18,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
22
public/TextGen Settings/Mirostat.settings
Normal file
22
public/TextGen Settings/Mirostat.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 1,
|
||||
"top_p": 1,
|
||||
"top_k": 0,
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 2,
|
||||
"mirostat_tau": 8,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.15,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -6,6 +6,8 @@
|
||||
"rep_pen": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.05,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.15,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.05,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.15,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.15,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.1,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
@@ -13,5 +15,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
@@ -13,5 +13,8 @@
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
||||
|
22
public/TextGen Settings/Shortwave.settings
Normal file
22
public/TextGen Settings/Shortwave.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 1.53,
|
||||
"top_p": 0.64,
|
||||
"top_k": 33,
|
||||
"typical_p": 1,
|
||||
"top_a": 0.04,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.07,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
22
public/TextGen Settings/Simple-1.settings
Normal file
22
public/TextGen Settings/Simple-1.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 0.7,
|
||||
"top_p": 0.9,
|
||||
"top_k": 20,
|
||||
"typical_p": 1,
|
||||
"top_a": 0.75,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.15,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
22
public/TextGen Settings/Space Alien.settings
Normal file
22
public/TextGen Settings/Space Alien.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 1.31,
|
||||
"top_p": 0.29,
|
||||
"top_k": 72,
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.09,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
22
public/TextGen Settings/StarChat.settings
Normal file
22
public/TextGen Settings/StarChat.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 0.02,
|
||||
"top_p": 0.95,
|
||||
"top_k": 50,
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
22
public/TextGen Settings/TFS-with-Top-A.settings
Normal file
22
public/TextGen Settings/TFS-with-Top-A.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 0.7,
|
||||
"top_p": 1,
|
||||
"top_k": 0,
|
||||
"typical_p": 1,
|
||||
"top_a": 0.2,
|
||||
"tfs": 0.95,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.15,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
22
public/TextGen Settings/Titanic.settings
Normal file
22
public/TextGen Settings/Titanic.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 1.01,
|
||||
"top_p": 0.21,
|
||||
"top_k": 91,
|
||||
"typical_p": 1,
|
||||
"top_a": 0.75,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 10.78,
|
||||
"rep_pen": 1.21,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1.07,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
22
public/TextGen Settings/Yara.settings
Normal file
22
public/TextGen Settings/Yara.settings
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"temp": 0.82,
|
||||
"top_p": 0.21,
|
||||
"top_k": 72,
|
||||
"typical_p": 1,
|
||||
"top_a": 0,
|
||||
"tfs": 1,
|
||||
"epsilon_cutoff": 0,
|
||||
"eta_cutoff": 0,
|
||||
"rep_pen": 1.19,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 0,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false,
|
||||
"mirostat_mode": 0,
|
||||
"mirostat_tau": 5,
|
||||
"mirostat_eta": 0.1
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 501 KiB |
@@ -1,73 +0,0 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
background-color: rgb(36, 37, 37);
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
font-family: "Noto Sans", "Noto Color Emoji", sans-serif;
|
||||
font-size: 16px;
|
||||
/*1rem*/
|
||||
color: #999;
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
/*z-index:0;*/
|
||||
}
|
||||
|
||||
#main {
|
||||
padding-top: 20px;
|
||||
/*z-index:1;*/
|
||||
}
|
||||
|
||||
#content {
|
||||
margin: 0 auto;
|
||||
max-width: 700px;
|
||||
border: 1px solid #333;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
line-height: 1.5rem;
|
||||
box-shadow: 0 0 5px black;
|
||||
/*z-index: 2;*/
|
||||
}
|
||||
|
||||
code {
|
||||
border: 1px solid #999;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
display: block;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
a {
|
||||
color: orange;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted orange;
|
||||
}
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
border: 1px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table img {
|
||||
max-width: 200px;
|
||||
}
|
1
public/css/select2.min.css
vendored
Normal file
1
public/css/select2.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1528
public/i18n.json
1528
public/i18n.json
File diff suppressed because it is too large
Load Diff
BIN
public/img/quill.png
Normal file
BIN
public/img/quill.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
2001
public/index.html
2001
public/index.html
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "Metharme",
|
||||
"system_prompt": "Write {{char}}'s next reply in a fictional roleplay chat between {{user}} and {{char}}.",
|
||||
"system_prompt": "Enter roleplay mode. You must act as {{char}}, whose persona follows:",
|
||||
"system_sequence": "<|system|>",
|
||||
"stop_sequence": "</s>",
|
||||
"input_sequence": "<|user|>",
|
||||
"output_sequence": "<|model|>",
|
||||
"separator_sequence": "",
|
||||
"wrap": false
|
||||
}
|
||||
}
|
||||
|
45
public/movingUI/Black Magic Time.json
Normal file
45
public/movingUI/Black Magic Time.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "Black Magic Time",
|
||||
"movingUIState": {
|
||||
"sheld": {
|
||||
"top": 488,
|
||||
"left": 1407,
|
||||
"right": 1,
|
||||
"bottom": 4,
|
||||
"margin": "unset",
|
||||
"width": 471,
|
||||
"height": 439
|
||||
},
|
||||
"floatingPrompt": {
|
||||
"width": 369,
|
||||
"height": 441
|
||||
},
|
||||
"right-nav-panel": {
|
||||
"top": 0,
|
||||
"left": 1400,
|
||||
"right": 111,
|
||||
"bottom": 446,
|
||||
"margin": "unset",
|
||||
"width": 479,
|
||||
"height": 487
|
||||
},
|
||||
"WorldInfo": {
|
||||
"top": 41,
|
||||
"left": 369,
|
||||
"right": 642,
|
||||
"bottom": 51,
|
||||
"margin": "unset",
|
||||
"width": 1034,
|
||||
"height": 858
|
||||
},
|
||||
"left-nav-panel": {
|
||||
"top": 442,
|
||||
"left": 0,
|
||||
"right": 1546,
|
||||
"bottom": 25,
|
||||
"margin": "unset",
|
||||
"width": 368,
|
||||
"height": 483
|
||||
}
|
||||
}
|
||||
}
|
4
public/movingUI/Default.json
Normal file
4
public/movingUI/Default.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Default",
|
||||
"movingUIState": {}
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>SillyTavern Documentation</title>
|
||||
<link rel="stylesheet" href="/css/notes.css">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="main">
|
||||
<div id="content">
|
||||
<h2>You weren't supposed to be able to get here, you know.</h1>
|
||||
<h3>All help materials has been moved here:</h3>
|
||||
<h3><a href="https://docs.sillytavern.app/">SillyTavern Documentation</a></h3>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
2219
public/script.js
2219
public/script.js
File diff suppressed because it is too large
Load Diff
@@ -11,10 +11,14 @@ import {
|
||||
is_send_press,
|
||||
getTokenCount,
|
||||
menu_type,
|
||||
|
||||
|
||||
max_context,
|
||||
saveSettingsDebounced,
|
||||
} from "../script.js";
|
||||
|
||||
import {
|
||||
characterStatsHandler,
|
||||
} from "./stats.js";
|
||||
|
||||
|
||||
import {
|
||||
power_user,
|
||||
@@ -27,7 +31,7 @@ import {
|
||||
SECRET_KEYS,
|
||||
secret_state,
|
||||
} from "./secrets.js";
|
||||
import { sortByCssOrder, debounce } from "./utils.js";
|
||||
import { sortByCssOrder, debounce, delay } from "./utils.js";
|
||||
import { chat_completion_sources, oai_settings } from "./openai.js";
|
||||
|
||||
var NavToggle = document.getElementById("nav-toggle");
|
||||
@@ -104,22 +108,37 @@ function waitForElement(querySelector, timeout) {
|
||||
});
|
||||
}
|
||||
|
||||
waitForElement("#expression-image", 10000).then(function () {
|
||||
/**
|
||||
* Converts generation time from milliseconds to a human-readable format.
|
||||
*
|
||||
* The function takes total generation time as an input, then converts it to a format
|
||||
* of "_ Days, _ Hours, _ Minutes, _ Seconds". If the generation time does not exceed a
|
||||
* particular measure (like days or hours), that measure will not be included in the output.
|
||||
*
|
||||
* @param {number} total_gen_time - The total generation time in milliseconds.
|
||||
* @returns {string} - A human-readable string that represents the time spent generating characters.
|
||||
*/
|
||||
export function humanizeGenTime(total_gen_time) {
|
||||
|
||||
dragElement(document.getElementById("expression-holder"));
|
||||
dragElement(document.getElementById("floatingPrompt"));
|
||||
//convert time_spent to humanized format of "_ Hours, _ Minutes, _ Seconds" from milliseconds
|
||||
let time_spent = total_gen_time || 0;
|
||||
time_spent = Math.floor(time_spent / 1000);
|
||||
let seconds = time_spent % 60;
|
||||
time_spent = Math.floor(time_spent / 60);
|
||||
let minutes = time_spent % 60;
|
||||
time_spent = Math.floor(time_spent / 60);
|
||||
let hours = time_spent % 24;
|
||||
time_spent = Math.floor(time_spent / 24);
|
||||
let days = time_spent;
|
||||
time_spent = "";
|
||||
if (days > 0) { time_spent += `${days} Days, `; }
|
||||
if (hours > 0) { time_spent += `${hours} Hours, `; }
|
||||
if (minutes > 0) { time_spent += `${minutes} Minutes, `; }
|
||||
time_spent += `${seconds} Seconds`;
|
||||
return time_spent;
|
||||
}
|
||||
|
||||
}).catch(() => {
|
||||
console.log("expression holder not loaded yet");
|
||||
});
|
||||
|
||||
waitForElement("#floatingPrompt", 10000).then(function () {
|
||||
|
||||
dragElement(document.getElementById("floatingPrompt"));
|
||||
|
||||
}).catch(() => {
|
||||
console.log("floating prompt box not loaded yet");
|
||||
});
|
||||
|
||||
// Device detection
|
||||
export const deviceInfo = await getDeviceInfo();
|
||||
@@ -177,6 +196,29 @@ export function humanizedDateTime() {
|
||||
return HumanizedDateTime;
|
||||
}
|
||||
|
||||
//this is a common format version to display a timestamp on each chat message
|
||||
//returns something like: June 19, 2023 2:20pm
|
||||
export function getMessageTimeStamp() {
|
||||
const date = Date.now();
|
||||
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
||||
const d = new Date(date);
|
||||
const month = months[d.getMonth()];
|
||||
const day = d.getDate();
|
||||
const year = d.getFullYear();
|
||||
let hours = d.getHours();
|
||||
const minutes = ('0' + d.getMinutes()).slice(-2);
|
||||
let meridiem = 'am';
|
||||
if (hours >= 12) {
|
||||
meridiem = 'pm';
|
||||
hours -= 12;
|
||||
}
|
||||
if (hours === 0) {
|
||||
hours = 12;
|
||||
}
|
||||
const formattedDate = month + ' ' + day + ', ' + year + ' ' + hours + ':' + minutes + meridiem;
|
||||
return formattedDate;
|
||||
}
|
||||
|
||||
|
||||
// triggers:
|
||||
$("#rm_button_create").on("click", function () { //when "+New Character" is clicked
|
||||
@@ -263,21 +305,31 @@ export function RA_CountCharTokens() {
|
||||
// if neither, probably safety char or some error in loading
|
||||
} else { console.debug("RA_TC -- no valid char found, closing."); }
|
||||
}
|
||||
//label rm_stats_button with a tooltip indicating stats
|
||||
$("#result_info").html(`<small>${count_tokens} Tokens (${perm_tokens} Permanent)</small>
|
||||
|
||||
<i title='Click for stats!' class="fa-solid fa-circle-info rm_stats_button"></i>`);
|
||||
// display the counted tokens
|
||||
if (count_tokens < 1024 && perm_tokens < 1024) {
|
||||
//display normal if both counts are under 1024
|
||||
$("#result_info").html(`<small>${count_tokens} Tokens (${perm_tokens} Permanent)</small>`);
|
||||
const tokenLimit = Math.max(((main_api !== 'openai' ? max_context : oai_settings.openai_max_context) / 2), 1024);
|
||||
if (count_tokens < tokenLimit && perm_tokens < tokenLimit) {
|
||||
|
||||
} else {
|
||||
$("#result_info").html(`
|
||||
<div class="flex-container flexFlowColumn alignitemscenter">
|
||||
<div class="flex-container alignitemscenter">
|
||||
<div class="flex-container flexnowrap flexNoGap">
|
||||
<small class="flex-container flexnowrap flexNoGap">
|
||||
<div class="neutral_warning">${count_tokens}</div> Tokens (<div class="neutral_warning">${perm_tokens}</div><div> Permanent)</div>
|
||||
</small>
|
||||
<i title='Click for stats!' class="fa-solid fa-circle-info rm_stats_button"></i>
|
||||
</div>
|
||||
<div id="chartokenwarning" class="menu_button whitespacenowrap"><a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-tokens" target="_blank">About Token 'Limits'</a></div>
|
||||
<div id="chartokenwarning" class="menu_button margin0 whitespacenowrap"><a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-tokens" target="_blank">About Token 'Limits'</a></div>
|
||||
</div>`);
|
||||
|
||||
|
||||
} //warn if either are over 1024
|
||||
$(".rm_stats_button").on('click', function () {
|
||||
characterStatsHandler(characters, this_chid);
|
||||
});
|
||||
}
|
||||
//Auto Load Last Charcter -- (fires when active_character is defined and auto_load_chat is true)
|
||||
async function RA_autoloadchat() {
|
||||
@@ -396,15 +448,15 @@ function RA_autoconnect(PrevApi) {
|
||||
}
|
||||
break;
|
||||
case 'openai':
|
||||
if (secret_state[SECRET_KEYS.OPENAI] || secret_state[SECRET_KEYS.CLAUDE] || oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI) {
|
||||
if ((secret_state[SECRET_KEYS.OPENAI] && oai_settings.chat_completion_source == chat_completion_sources.OPENAI)
|
||||
|| (secret_state[SECRET_KEYS.CLAUDE] && oai_settings.chat_completion_source == chat_completion_sources.CLAUDE)
|
||||
|| (secret_state[SECRET_KEYS.SCALE] && oai_settings.chat_completion_source == chat_completion_sources.SCALE)
|
||||
|| (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI)
|
||||
|| (secret_state[SECRET_KEYS.OPENROUTER] && oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER)
|
||||
) {
|
||||
$("#api_button_openai").click();
|
||||
}
|
||||
break;
|
||||
case 'poe':
|
||||
if (secret_state[SECRET_KEYS.POE]) {
|
||||
$("#poe_connect").click();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!connection_made) {
|
||||
@@ -450,160 +502,263 @@ function OpenNavPanels() {
|
||||
|
||||
|
||||
// Make the DIV element draggable:
|
||||
dragElement(document.getElementById("sheld"));
|
||||
dragElement(document.getElementById("left-nav-panel"));
|
||||
dragElement(document.getElementById("right-nav-panel"));
|
||||
dragElement(document.getElementById("avatar_zoom_popup"));
|
||||
dragElement(document.getElementById("WorldInfo"));
|
||||
|
||||
|
||||
// THIRD UPDATE, prevent resize window breaks and smartly handle saving
|
||||
|
||||
export function dragElement(elmnt) {
|
||||
var hasBeenDraggedByUser = false;
|
||||
var isMouseDown = false;
|
||||
|
||||
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;
|
||||
var height, width, top, left, right, bottom,
|
||||
maxX, maxY, winHeight, winWidth,
|
||||
topbar, topbarWidth, topBarFirstX, topBarLastX, sheldWidth;
|
||||
|
||||
var elmntName = elmnt.attr('id');
|
||||
|
||||
const elmntNameEscaped = $.escapeSelector(elmntName);
|
||||
const elmntHeader = $(`#${elmntNameEscaped}header`);
|
||||
|
||||
if (elmntHeader.length) {
|
||||
elmntHeader.off('mousedown').on('mousedown', (e) => {
|
||||
|
||||
dragMouseDown(e);
|
||||
});
|
||||
$(elmnt).off('mousedown').on('mousedown', () => { isMouseDown = true })
|
||||
} else {
|
||||
// otherwise, move the DIV from anywhere inside the DIV, b:
|
||||
elmnt.onmousedown = dragMouseDown;
|
||||
elmnt.off('mousedown').on('mousedown', dragMouseDown);
|
||||
}
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
const target = mutations[0].target;
|
||||
if (!$(target).is(':visible')
|
||||
|| $(target).hasClass('resizing')
|
||||
|| Number((String(target.height).replace('px', ''))) < 50
|
||||
|| Number((String(target.width).replace('px', ''))) < 50
|
||||
|| power_user.movingUI === false
|
||||
|| isMobile() === true
|
||||
) {
|
||||
console.debug('aborting mutator')
|
||||
return
|
||||
}
|
||||
//console.debug(left + width, winWidth, hasBeenDraggedByUser, isMouseDown)
|
||||
const style = getComputedStyle(target); //use computed values because not all CSS are set by default
|
||||
height = target.offsetHeight;
|
||||
width = target.offsetWidth;
|
||||
top = parseInt(style.top);
|
||||
left = parseInt(style.left);
|
||||
right = parseInt(style.right);
|
||||
bottom = parseInt(style.bottom);
|
||||
maxX = parseInt(width + left);
|
||||
maxY = parseInt(height + top);
|
||||
winWidth = window.innerWidth;
|
||||
winHeight = window.innerHeight;
|
||||
sheldWidth = parseInt($('html').css('--sheldWidth').slice(0, -2));
|
||||
|
||||
topbar = document.getElementById("top-bar")
|
||||
const topbarstyle = getComputedStyle(topbar)
|
||||
topBarFirstX = parseInt(topbarstyle.marginInline)
|
||||
topbarWidth = parseInt(topbarstyle.width)
|
||||
topBarLastX = topBarFirstX + topbarWidth;
|
||||
|
||||
/*console.log(`
|
||||
winWidth: ${winWidth}, winHeight: ${winHeight}
|
||||
sheldWidth: ${sheldWidth}
|
||||
X: ${$(elmnt).css('left')}
|
||||
Y: ${$(elmnt).css('top')}
|
||||
MaxX: ${maxX}, MaxY: ${maxY}
|
||||
height: ${height}
|
||||
width: ${width}
|
||||
Topbar 1st X: ${topBarFirstX}
|
||||
TopBar lastX: ${topBarLastX}
|
||||
`);*/
|
||||
|
||||
|
||||
//prepare an empty poweruser object for the item being altered if we don't have one already
|
||||
if (!power_user.movingUIState[elmntName]) {
|
||||
console.debug(`adding config property for ${elmntName}`)
|
||||
power_user.movingUIState[elmntName] = {};
|
||||
}
|
||||
|
||||
//only record position changes if caused by a user click-drag
|
||||
if (hasBeenDraggedByUser && isMouseDown) {
|
||||
power_user.movingUIState[elmntName].top = top;
|
||||
power_user.movingUIState[elmntName].left = left;
|
||||
power_user.movingUIState[elmntName].right = right;
|
||||
power_user.movingUIState[elmntName].bottom = bottom;
|
||||
power_user.movingUIState[elmntName].margin = 'unset';
|
||||
}
|
||||
|
||||
//handle resizing
|
||||
if (!hasBeenDraggedByUser && isMouseDown) {
|
||||
console.debug('saw resize, NOT header drag')
|
||||
|
||||
//prevent resizing offscreen
|
||||
if (top + elmnt.height() >= winHeight) {
|
||||
console.debug('resizing height to prevent offscreen')
|
||||
elmnt.css('height', winHeight - top - 1 + "px");
|
||||
}
|
||||
|
||||
if (left + elmnt.width() >= winWidth) {
|
||||
console.debug('resizing width to prevent offscreen')
|
||||
elmnt.css('width', winWidth - left - 1 + "px");
|
||||
}
|
||||
|
||||
//prevent resizing from top left into the top bar
|
||||
if (top <= 40 && maxX >= topBarFirstX && left <= topBarFirstX
|
||||
) {
|
||||
console.debug('prevent topbar underlap resize')
|
||||
elmnt.css('width', width - 1 + "px");
|
||||
}
|
||||
|
||||
//set css to prevent weird resize behavior (does not save)
|
||||
elmnt.css('left', left)
|
||||
elmnt.css('top', top)
|
||||
|
||||
//set a listener for mouseup to save new width/height
|
||||
elmnt.off('mouseup').on('mouseup', () => {
|
||||
console.debug(`Saving ${elmntName} Height/Width`)
|
||||
power_user.movingUIState[elmntName].width = width;
|
||||
power_user.movingUIState[elmntName].height = height;
|
||||
saveSettingsDebounced();
|
||||
})
|
||||
}
|
||||
|
||||
//handle dragging hit detection
|
||||
if (hasBeenDraggedByUser && isMouseDown) {
|
||||
//prevent dragging offscreen
|
||||
if (top <= 0) {
|
||||
elmnt.css('top', '0px');
|
||||
} else if (maxY >= winHeight) {
|
||||
elmnt.css('top', winHeight - maxY + top - 1 + "px");
|
||||
}
|
||||
|
||||
if (left <= 0) {
|
||||
elmnt.css('left', '0px');
|
||||
} else if (maxX >= winWidth) {
|
||||
elmnt.css('left', winWidth - maxX + left - 1 + "px");
|
||||
}
|
||||
|
||||
//prevent underlap with topbar div
|
||||
if (top < 40
|
||||
&& (maxX >= topBarFirstX && left <= topBarFirstX //elmnt is hitting topbar from left side
|
||||
|| left <= topBarLastX && maxX >= topBarLastX //elmnt is hitting topbar from right side
|
||||
|| left >= topBarFirstX && maxX <= topBarLastX) //elmnt hitting topbar in the middle
|
||||
) {
|
||||
console.debug('topbar hit')
|
||||
elmnt.css('top', top + 1 + "px");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the element header exists and set the listener on the grabber
|
||||
if (elmntHeader.length) {
|
||||
elmntHeader.off('mousedown').on('mousedown', (e) => {
|
||||
console.debug('listener started from header')
|
||||
dragMouseDown(e);
|
||||
});
|
||||
} else {
|
||||
elmnt.off('mousedown').on('mousedown', dragMouseDown);
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] });
|
||||
|
||||
function dragMouseDown(e) {
|
||||
//console.log(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;
|
||||
|
||||
if (e) {
|
||||
hasBeenDraggedByUser = true;
|
||||
e.preventDefault();
|
||||
pos3 = e.clientX; //mouse X at click
|
||||
pos4 = e.clientY; //mouse Y at click
|
||||
}
|
||||
$(document).on('mouseup', closeDragElement);
|
||||
$(document).on('mousemove', elementDrag);
|
||||
}
|
||||
|
||||
function elementDrag(e) {
|
||||
//disable scrollbars when dragging to prevent jitter
|
||||
$("body").css("overflow", "hidden");
|
||||
if (!power_user.movingUIState[elmntName]) {
|
||||
power_user.movingUIState[elmntName] = {};
|
||||
}
|
||||
|
||||
|
||||
//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
|
||||
pos1 = pos3 - e.clientX; //X change amt (-1 or 1)
|
||||
pos2 = pos4 - e.clientY; //Y change amt (-1 or 1)
|
||||
pos3 = e.clientX; //new mouse X
|
||||
pos4 = e.clientY; //new mouse Y
|
||||
|
||||
elmnt.setAttribute('data-dragged', 'true');
|
||||
elmnt.attr('data-dragged', 'true');
|
||||
|
||||
//fix over/underflows:
|
||||
//first set css to computed values to avoid CSS NaN results from 'auto', etc
|
||||
elmnt.css('left', (elmnt.offset().left) + "px");
|
||||
elmnt.css("top", (elmnt.offset().top) + "px");
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
//then update element position styles to account for drag changes
|
||||
elmnt.css('margin', 'unset');
|
||||
elmnt.css('left', (elmnt.offset().left - pos1) + "px");
|
||||
elmnt.css("top", (elmnt.offset().top - pos2) + "px");
|
||||
elmnt.css("right", ((winWidth - maxX) + "px"));
|
||||
elmnt.css("bottom", ((winHeight - maxY) + "px"));
|
||||
|
||||
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");
|
||||
$(elmnt).css("margin", "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); */
|
||||
// Height/Width here are for visuals only, and are not saved to settings
|
||||
// required because some divs do hot have a set width/height..
|
||||
// and will defaults to shrink to min value of 100px set in CSS file
|
||||
elmnt.css('height', height)
|
||||
elmnt.css('width', width)
|
||||
/*
|
||||
console.log(`
|
||||
winWidth: ${winWidth}, winHeight: ${winHeight}
|
||||
sheldWidth: ${sheldWidth}
|
||||
X: ${$(elmnt).css('left')}
|
||||
Y: ${$(elmnt).css('top')}
|
||||
MaxX: ${maxX}, MaxY: ${maxY}
|
||||
height: ${height}
|
||||
width: ${width}
|
||||
Topbar 1st X: ${topBarFirstX}
|
||||
TopBar lastX: ${topBarLastX}
|
||||
`);
|
||||
*/
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
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");
|
||||
console.debug('drag finished')
|
||||
hasBeenDraggedByUser = false;
|
||||
isMouseDown = false;
|
||||
$(document).off('mouseup', closeDragElement);
|
||||
$(document).off('mousemove', elementDrag);
|
||||
$("body").css("overflow", "");
|
||||
// Clear the "data-dragged" attribute
|
||||
elmnt.attr('data-dragged', 'false');
|
||||
console.debug(`Saving ${elmntName} UI position`)
|
||||
saveSettingsDebounced();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export async function initMovingUI() {
|
||||
if (isMobile() === false && power_user.movingUI === true) {
|
||||
console.debug('START MOVING UI')
|
||||
dragElement($("#sheld"));
|
||||
dragElement($("#left-nav-panel"));
|
||||
dragElement($("#right-nav-panel"));
|
||||
dragElement($("#WorldInfo"));
|
||||
await delay(1000)
|
||||
console.debug('loading AN draggable function')
|
||||
dragElement($("#floatingPrompt"))
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
$("document").ready(function () {
|
||||
|
||||
// initial status check
|
||||
setTimeout(RA_checkOnlineStatus, 100);
|
||||
setTimeout(() => {
|
||||
RA_checkOnlineStatus();
|
||||
}, 100);
|
||||
|
||||
// read the state of AutoConnect and AutoLoadChat.
|
||||
$(AutoConnectCheckbox).prop("checked", LoadLocalBool("AutoConnectEnabled"));
|
||||
@@ -790,7 +945,7 @@ $("document").ready(function () {
|
||||
function isInputElementInFocus() {
|
||||
//return $(document.activeElement).is(":input");
|
||||
var focused = $(':focus');
|
||||
if (focused.is('input') || focused.is('textarea') || focused.attr('contenteditable') == 'true') {
|
||||
if (focused.is('input') || focused.is('textarea') || focused.prop('contenteditable') == 'true') {
|
||||
if (focused.attr('id') === 'send_textarea') {
|
||||
return false;
|
||||
}
|
||||
|
@@ -5,27 +5,33 @@ import {
|
||||
getTokenCount,
|
||||
saveSettingsDebounced,
|
||||
this_chid,
|
||||
} from "../../../script.js";
|
||||
import { selected_group } from "../../group-chats.js";
|
||||
import { ModuleWorkerWrapper, extension_settings, getContext, saveMetadataDebounced } from "../../extensions.js";
|
||||
import { registerSlashCommand } from "../../slash-commands.js";
|
||||
import { getCharaFilename, debounce } from "../../utils.js";
|
||||
export { MODULE_NAME };
|
||||
} from "../script.js";
|
||||
import { selected_group } from "./group-chats.js";
|
||||
import { extension_settings, getContext, saveMetadataDebounced } from "./extensions.js";
|
||||
import { registerSlashCommand } from "./slash-commands.js";
|
||||
import { getCharaFilename, debounce, waitUntilCondition, delay } from "./utils.js";
|
||||
export { MODULE_NAME as NOTE_MODULE_NAME };
|
||||
|
||||
const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory
|
||||
const UPDATE_INTERVAL = 1000;
|
||||
|
||||
const DEFAULT_DEPTH = 4;
|
||||
const DEFAULT_POSITION = 1;
|
||||
const DEFAULT_INTERVAL = 1;
|
||||
export var shouldWIAddPrompt = false;
|
||||
|
||||
const metadata_keys = {
|
||||
export const metadata_keys = {
|
||||
prompt: 'note_prompt',
|
||||
interval: 'note_interval',
|
||||
depth: 'note_depth',
|
||||
position: 'note_position',
|
||||
}
|
||||
|
||||
const chara_note_position = {
|
||||
replace: 0,
|
||||
before: 1,
|
||||
after: 2,
|
||||
}
|
||||
|
||||
function setNoteTextCommand(_, text) {
|
||||
$('#extension_floating_prompt').val(text).trigger('input');
|
||||
toastr.success("Author's Note text updated");
|
||||
@@ -72,6 +78,12 @@ function setNotePositionCommand(_, text) {
|
||||
toastr.info("Author's Note position updated");
|
||||
}
|
||||
|
||||
function updateSettings() {
|
||||
saveSettingsDebounced();
|
||||
loadSettings();
|
||||
setFloatingPrompt();
|
||||
}
|
||||
|
||||
const setMainPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_prompt_token_counter').text(getTokenCount(value)), 1000);
|
||||
const setCharaPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_chara_token_counter').text(getTokenCount(value)), 1000);
|
||||
const setDefaultPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_default_token_counter').text(getTokenCount(value)), 1000);
|
||||
@@ -79,11 +91,13 @@ const setDefaultPromptTokenCounterDebounced = debounce((value) => $('#extension_
|
||||
async function onExtensionFloatingPromptInput() {
|
||||
chat_metadata[metadata_keys.prompt] = $(this).val();
|
||||
setMainPromptTokenCounterDebounced(chat_metadata[metadata_keys.prompt]);
|
||||
updateSettings();
|
||||
saveMetadataDebounced();
|
||||
}
|
||||
|
||||
async function onExtensionFloatingIntervalInput() {
|
||||
chat_metadata[metadata_keys.interval] = Number($(this).val());
|
||||
updateSettings();
|
||||
saveMetadataDebounced();
|
||||
}
|
||||
|
||||
@@ -96,14 +110,26 @@ async function onExtensionFloatingDepthInput() {
|
||||
}
|
||||
|
||||
chat_metadata[metadata_keys.depth] = value;
|
||||
updateSettings();
|
||||
saveMetadataDebounced();
|
||||
}
|
||||
|
||||
async function onExtensionFloatingPositionInput(e) {
|
||||
chat_metadata[metadata_keys.position] = e.target.value;
|
||||
updateSettings();
|
||||
saveMetadataDebounced();
|
||||
}
|
||||
|
||||
async function onExtensionFloatingCharPositionInput(e) {
|
||||
const value = e.target.value;
|
||||
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||
|
||||
if (charaNote) {
|
||||
charaNote.position = Number(value);
|
||||
updateSettings();
|
||||
}
|
||||
}
|
||||
|
||||
function onExtensionFloatingCharaPromptInput() {
|
||||
const tempPrompt = $(this).val();
|
||||
const avatarName = getCharaFilename();
|
||||
@@ -136,7 +162,7 @@ function onExtensionFloatingCharaPromptInput() {
|
||||
if (!extension_settings.note.chara) {
|
||||
extension_settings.note.chara = []
|
||||
}
|
||||
Object.assign(tempCharaNote, { useChara: false })
|
||||
Object.assign(tempCharaNote, { useChara: false, position: chara_note_position.replace })
|
||||
|
||||
extension_settings.note.chara.push(tempCharaNote);
|
||||
} else {
|
||||
@@ -147,7 +173,7 @@ function onExtensionFloatingCharaPromptInput() {
|
||||
return;
|
||||
}
|
||||
|
||||
saveSettingsDebounced();
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
function onExtensionFloatingCharaCheckboxChanged() {
|
||||
@@ -157,14 +183,14 @@ function onExtensionFloatingCharaCheckboxChanged() {
|
||||
if (charaNote) {
|
||||
charaNote.useChara = value;
|
||||
|
||||
saveSettingsDebounced();
|
||||
updateSettings();
|
||||
}
|
||||
}
|
||||
|
||||
function onExtensionFloatingDefaultInput() {
|
||||
extension_settings.note.default = $(this).val();
|
||||
setDefaultPromptTokenCounterDebounced(extension_settings.note.default);
|
||||
saveSettingsDebounced();
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
@@ -177,28 +203,39 @@ function loadSettings() {
|
||||
$('#extension_floating_depth').val(chat_metadata[metadata_keys.depth]);
|
||||
$(`input[name="extension_floating_position"][value="${chat_metadata[metadata_keys.position]}"]`).prop('checked', true);
|
||||
|
||||
if (extension_settings.note.chara) {
|
||||
if (extension_settings.note.chara && getContext().characterId) {
|
||||
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||
|
||||
$('#extension_floating_chara').val(charaNote ? charaNote.prompt : '');
|
||||
$('#extension_use_floating_chara').prop('checked', charaNote ? charaNote.useChara : false);
|
||||
$(`input[name="extension_floating_char_position"][value="${charaNote?.position ?? chara_note_position.replace}"]`).prop('checked', true);
|
||||
} else {
|
||||
$('#extension_floating_chara').val('');
|
||||
$('#extension_use_floating_chara').prop('checked', false);
|
||||
$(`input[name="extension_floating_char_position"][value="${chara_note_position.replace}"]`).prop('checked', true);
|
||||
}
|
||||
|
||||
$('#extension_floating_default').val(extension_settings.note.default);
|
||||
}
|
||||
|
||||
async function moduleWorker() {
|
||||
export function setFloatingPrompt() {
|
||||
const context = getContext();
|
||||
|
||||
if (!context.groupId && context.characterId === undefined) {
|
||||
console.debug('setFloatingPrompt: Not in a chat. Skipping.');
|
||||
shouldWIAddPrompt = false;
|
||||
return;
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
|
||||
// take the count of messages
|
||||
let lastMessageNumber = Array.isArray(context.chat) && context.chat.length ? context.chat.filter(m => m.is_user).length : 0;
|
||||
|
||||
console.debug(`
|
||||
setFloatingPrompt entered
|
||||
------
|
||||
lastMessageNumber = ${lastMessageNumber}
|
||||
metadata_keys.interval = ${chat_metadata[metadata_keys.interval]}
|
||||
`)
|
||||
|
||||
// interval 1 should be inserted no matter what
|
||||
if (chat_metadata[metadata_keys.interval] === 1) {
|
||||
lastMessageNumber = 1;
|
||||
@@ -207,6 +244,7 @@ async function moduleWorker() {
|
||||
if (lastMessageNumber <= 0 || chat_metadata[metadata_keys.interval] <= 0) {
|
||||
context.setExtensionPrompt(MODULE_NAME, '');
|
||||
$('#extension_floating_counter').text('(disabled)');
|
||||
shouldWIAddPrompt = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -214,41 +252,64 @@ async function moduleWorker() {
|
||||
? (lastMessageNumber % chat_metadata[metadata_keys.interval])
|
||||
: (chat_metadata[metadata_keys.interval] - lastMessageNumber);
|
||||
const shouldAddPrompt = messagesTillInsertion == 0;
|
||||
shouldWIAddPrompt = shouldAddPrompt;
|
||||
|
||||
let prompt = shouldAddPrompt ? $('#extension_floating_prompt').val() : '';
|
||||
if (shouldAddPrompt && extension_settings.note.chara) {
|
||||
if (shouldAddPrompt && extension_settings.note.chara && getContext().characterId) {
|
||||
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||
|
||||
// Only replace with the chara note if the user checked the box
|
||||
if (charaNote && charaNote.useChara) {
|
||||
prompt = charaNote.prompt;
|
||||
switch (charaNote.position) {
|
||||
case chara_note_position.before:
|
||||
prompt = charaNote.prompt + '\n' + prompt;
|
||||
break;
|
||||
case chara_note_position.after:
|
||||
prompt = prompt + '\n' + charaNote.prompt;
|
||||
break;
|
||||
default:
|
||||
prompt = charaNote.prompt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.setExtensionPrompt(MODULE_NAME, prompt, chat_metadata[metadata_keys.position], chat_metadata[metadata_keys.depth]);
|
||||
$('#extension_floating_counter').text(shouldAddPrompt ? '0' : messagesTillInsertion);
|
||||
}
|
||||
|
||||
function onANMenuItemClick() {
|
||||
if (selected_group || this_chid) {
|
||||
//show AN if it's hidden
|
||||
if ($("#floatingPrompt").css("display") !== 'flex') {
|
||||
$("#floatingPrompt").addClass('resizing')
|
||||
$("#floatingPrompt").css("display", "flex");
|
||||
$("#floatingPrompt").css("opacity", 0.0);
|
||||
$("#floatingPrompt").transition({
|
||||
opacity: 1.0,
|
||||
duration: 250,
|
||||
}, async function () {
|
||||
await delay(50);
|
||||
$("#floatingPrompt").removeClass('resizing')
|
||||
});
|
||||
|
||||
//auto-open the main AN inline drawer
|
||||
if ($("#ANBlockToggle")
|
||||
.siblings('.inline-drawer-content')
|
||||
.css('display') !== 'block') {
|
||||
$("#floatingPrompt").addClass('resizing')
|
||||
$("#ANBlockToggle").click();
|
||||
}
|
||||
} else {
|
||||
//hide AN if it's already displayed
|
||||
$("#floatingPrompt").addClass('resizing')
|
||||
$("#floatingPrompt").transition({
|
||||
opacity: 0.0,
|
||||
duration: 250,
|
||||
});
|
||||
},
|
||||
async function () {
|
||||
await delay(50);
|
||||
$("#floatingPrompt").removeClass('resizing')
|
||||
});
|
||||
setTimeout(function () {
|
||||
$("#floatingPrompt").hide();
|
||||
}, 250);
|
||||
@@ -263,11 +324,18 @@ function onANMenuItemClick() {
|
||||
}
|
||||
|
||||
function onChatChanged() {
|
||||
loadSettings();
|
||||
setFloatingPrompt();
|
||||
const context = getContext();
|
||||
|
||||
// Disable the chara note if in a group
|
||||
$('#extension_floating_chara').prop('disabled', context.groupId ? true : false);
|
||||
|
||||
const tokenCounter1 = chat_metadata[metadata_keys.prompt] ? getTokenCount(chat_metadata[metadata_keys.prompt]) : 0;
|
||||
$('#extension_floating_prompt_token_counter').text(tokenCounter1);
|
||||
|
||||
let tokenCounter2;
|
||||
if (extension_settings.note.chara) {
|
||||
if (extension_settings.note.chara && context.characterId) {
|
||||
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||
|
||||
if (charaNote) {
|
||||
@@ -283,120 +351,31 @@ function onChatChanged() {
|
||||
$('#extension_floating_default_token_counter').text(tokenCounter3);
|
||||
}
|
||||
|
||||
(function () {
|
||||
function addExtensionsSettings() {
|
||||
const settingsHtml = `
|
||||
<div id="floatingPrompt" class="drawer-content flexGap5">
|
||||
<div class="panelControlBar flex-container">
|
||||
<div id="floatingPromptheader" class="fa-solid fa-grip drag-grabber"></div>
|
||||
<div id="ANClose" class="fa-solid fa-circle-xmark"></div>
|
||||
</div>
|
||||
<div name="floatingPromptHolder">
|
||||
<div class="inline-drawer">
|
||||
<div id="ANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Author's Note</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
// Inject extension when extensions_activating is fired
|
||||
// Inserts the extension first since it's statically imported
|
||||
jQuery(async () => {
|
||||
await waitUntilCondition(() => eventSource !== undefined);
|
||||
$('#extension_floating_prompt').on('input', onExtensionFloatingPromptInput);
|
||||
$('#extension_floating_interval').on('input', onExtensionFloatingIntervalInput);
|
||||
$('#extension_floating_depth').on('input', onExtensionFloatingDepthInput);
|
||||
$('#extension_floating_chara').on('input', onExtensionFloatingCharaPromptInput);
|
||||
$('#extension_use_floating_chara').on('input', onExtensionFloatingCharaCheckboxChanged);
|
||||
$('#extension_floating_default').on('input', onExtensionFloatingDefaultInput);
|
||||
$('input[name="extension_floating_position"]').on('change', onExtensionFloatingPositionInput);
|
||||
$('input[name="extension_floating_char_position"]').on('change', onExtensionFloatingCharPositionInput);
|
||||
$('#ANClose').on('click', function () {
|
||||
$("#floatingPrompt").transition({
|
||||
opacity: 0,
|
||||
duration: 200,
|
||||
easing: 'ease-in-out',
|
||||
});
|
||||
setTimeout(function () { $('#floatingPrompt').hide() }, 200);
|
||||
})
|
||||
$("#option_toggle_AN").on('click', onANMenuItemClick);
|
||||
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<small>
|
||||
<b>Unique to this chat</b>.<br>
|
||||
Bookmarks inherit the Note from their parent, and can be changed individually after that.<br>
|
||||
</small>
|
||||
|
||||
<textarea id="extension_floating_prompt" class="text_pole" rows="8" maxlength="10000"></textarea>
|
||||
<div class="extension_token_counter">Tokens: <span id="extension_floating_prompt_token_counter">0</small></div>
|
||||
|
||||
<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 @ Depth <input id="extension_floating_depth" class="text_pole widthUnset" type="number" min="0" max="99" />
|
||||
</label>
|
||||
</div>
|
||||
<!--<label for="extension_floating_interval">In-Chat Insertion Depth</label>-->
|
||||
|
||||
<label for="extension_floating_interval">Insertion Frequency</label>
|
||||
|
||||
<input id="extension_floating_interval" class="text_pole widthUnset" type="number" min="0" max="999" /><small> (0 = Disable, 1 = Always)</small>
|
||||
<br>
|
||||
|
||||
<span>User inputs until next insertion: <span id="extension_floating_counter">(disabled)</span></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<hr class="sysHR">
|
||||
<div class="inline-drawer">
|
||||
<div id="charaANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Character Author's Note</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<small>Will be automatically added as the author's note for this character.</small>
|
||||
|
||||
<textarea id="extension_floating_chara" class="text_pole" rows="8" maxlength="10000"
|
||||
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
|
||||
<div class="extension_token_counter">Tokens: <span id="extension_floating_chara_token_counter">0</small></div>
|
||||
|
||||
<label for="extension_use_floating_chara">
|
||||
<input id="extension_use_floating_chara" type="checkbox" />
|
||||
<span data-i18n="Use character author's note">Use character author's note</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="sysHR">
|
||||
<div class="inline-drawer">
|
||||
<div id="defaultANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Default Author's Note</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<small>Will be automatically added as the Author's Note for all new chats.</small>
|
||||
|
||||
<textarea id="extension_floating_default" class="text_pole" rows="8" maxlength="10000"
|
||||
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
|
||||
<div class="extension_token_counter">Tokens: <span id="extension_floating_default_token_counter">0</small></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const ANButtonHtml = `
|
||||
<a id="option_toggle_AN">
|
||||
<i class="fa-lg fa-solid fa-note-sticky"></i>
|
||||
<span data-i18n="Author's Note">Author's Note</span>
|
||||
</a>
|
||||
`;
|
||||
$('#options .options-content').prepend(ANButtonHtml);
|
||||
$('#movingDivs').append(settingsHtml);
|
||||
$('#extension_floating_prompt').on('input', onExtensionFloatingPromptInput);
|
||||
$('#extension_floating_interval').on('input', onExtensionFloatingIntervalInput);
|
||||
$('#extension_floating_depth').on('input', onExtensionFloatingDepthInput);
|
||||
$('#extension_floating_chara').on('input', onExtensionFloatingCharaPromptInput);
|
||||
$('#extension_use_floating_chara').on('input', onExtensionFloatingCharaCheckboxChanged);
|
||||
$('#extension_floating_default').on('input', onExtensionFloatingDefaultInput);
|
||||
$('input[name="extension_floating_position"]').on('change', onExtensionFloatingPositionInput);
|
||||
$('#ANClose').on('click', function () {
|
||||
$("#floatingPrompt").transition({
|
||||
opacity: 0,
|
||||
duration: 200,
|
||||
easing: 'ease-in-out',
|
||||
});
|
||||
setTimeout(function () { $('#floatingPrompt').hide() }, 200);
|
||||
})
|
||||
$("#option_toggle_AN").on('click', onANMenuItemClick);
|
||||
}
|
||||
|
||||
addExtensionsSettings();
|
||||
const wrapper = new ModuleWorkerWrapper(moduleWorker);
|
||||
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL);
|
||||
registerSlashCommand('note', setNoteTextCommand, [], "<span class='monospace'>(text)</span> – sets an author's note for the currently selected chat", true, true);
|
||||
registerSlashCommand('depth', setNoteDepthCommand, [], "<span class='monospace'>(number)</span> – sets an author's note depth for in-chat positioning", true, true);
|
||||
registerSlashCommand('freq', setNoteIntervalCommand, ['interval'], "<span class='monospace'>(number)</span> – sets an author's note insertion frequency", true, true);
|
||||
registerSlashCommand('pos', setNotePositionCommand, ['position'], "(<span class='monospace'>chat</span> or <span class='monospace'>scenario</span>) – sets an author's note position", true, true);
|
||||
eventSource.on(event_types.CHAT_CHANGED, onChatChanged);
|
||||
})();
|
||||
});
|
@@ -32,6 +32,7 @@ import {
|
||||
} from "./utils.js";
|
||||
|
||||
export {
|
||||
createNewBookmark,
|
||||
showBookmarksButtons,
|
||||
}
|
||||
|
||||
@@ -123,13 +124,26 @@ function showBookmarksButtons() {
|
||||
}
|
||||
}
|
||||
|
||||
async function createNewBookmark() {
|
||||
async function saveBookmarkMenu() {
|
||||
if (!chat.length) {
|
||||
toastr.warning('The chat is empty.', 'Bookmark creation failed');
|
||||
return;
|
||||
}
|
||||
|
||||
const mesId = chat.length - 1;
|
||||
return createNewBookmark(chat.length - 1);
|
||||
}
|
||||
|
||||
async function createNewBookmark(mesId) {
|
||||
if (!chat.length) {
|
||||
toastr.warning('The chat is empty.', 'Bookmark creation failed');
|
||||
return;
|
||||
}
|
||||
|
||||
if (mesId < 0 || mesId >= chat.length) {
|
||||
toastr.warning('Invalid message ID.', 'Bookmark creation failed');
|
||||
return;
|
||||
}
|
||||
|
||||
const lastMes = chat[mesId];
|
||||
|
||||
if (typeof lastMes.extra !== 'object') {
|
||||
@@ -155,9 +169,9 @@ async function createNewBookmark() {
|
||||
const newMetadata = { main_chat: mainChat };
|
||||
|
||||
if (selected_group) {
|
||||
await saveGroupBookmarkChat(selected_group, name, newMetadata);
|
||||
await saveGroupBookmarkChat(selected_group, name, newMetadata, mesId);
|
||||
} else {
|
||||
await saveChat(name, newMetadata);
|
||||
await saveChat(name, newMetadata, mesId);
|
||||
}
|
||||
|
||||
lastMes.extra['bookmark_link'] = name;
|
||||
@@ -294,7 +308,7 @@ async function convertSoloToGroupChat() {
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#option_new_bookmark').on('click', createNewBookmark);
|
||||
$('#option_new_bookmark').on('click', saveBookmarkMenu);
|
||||
$('#option_back_to_main').on('click', backToMainChat);
|
||||
$('#option_convert_to_group').on('click', convertSoloToGroupChat);
|
||||
});
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced } from "../script.js";
|
||||
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders } from "../script.js";
|
||||
import { isSubsetOf, debounce } from "./utils.js";
|
||||
export {
|
||||
getContext,
|
||||
@@ -51,16 +51,25 @@ const extension_settings = {
|
||||
note: {
|
||||
default: '',
|
||||
chara: [],
|
||||
wiAddition: [],
|
||||
},
|
||||
caption: {
|
||||
refine_mode: false,
|
||||
},
|
||||
caption: {},
|
||||
expressions: {},
|
||||
dice: {},
|
||||
regex: [],
|
||||
tts: {},
|
||||
sd: {},
|
||||
chromadb: {},
|
||||
translate: {},
|
||||
objective: {},
|
||||
quickReply: {},
|
||||
randomizer: {
|
||||
controls: [],
|
||||
fluctuation: 0.1,
|
||||
enabled: false,
|
||||
},
|
||||
};
|
||||
|
||||
let modules = [];
|
||||
@@ -158,6 +167,8 @@ async function getManifests(names) {
|
||||
const json = await response.json();
|
||||
obj[name] = json;
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
}).catch(err => reject() && console.log('Could not load manifest.json for ' + name, err));
|
||||
});
|
||||
@@ -369,40 +380,218 @@ function addExtensionScript(name, manifest) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function showExtensionsDetails() {
|
||||
let html = '<h3>Modules provided by your Extensions API:</h3>';
|
||||
html += modules.length ? DOMPurify.sanitize(modules.join(', ')) : '<p class="failure">Not connected to the API!</p>';
|
||||
html += '<h3>Available extensions:</h3>';
|
||||
|
||||
Object.entries(manifests).sort((a, b) => a[1].loading_order - b[1].loading_order).forEach(extension => {
|
||||
const name = extension[0];
|
||||
const manifest = extension[1];
|
||||
html += `<h4>${DOMPurify.sanitize(manifest.display_name)}</h4>`;
|
||||
if (activeExtensions.has(name)) {
|
||||
html += `<p class="success">Extension is active. <a href="javascript:void" data-name="${name}" class="disable_extension">Click to Disable</a></p>`;
|
||||
if (Array.isArray(manifest.optional)) {
|
||||
const optional = new Set(manifest.optional);
|
||||
modules.forEach(x => optional.delete(x));
|
||||
if (optional.size > 0) {
|
||||
const optionalString = DOMPurify.sanitize([...optional].join(', '));
|
||||
html += `<p>Optional modules: <span class="optional">${optionalString}</span></p>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (extension_settings.disabledExtensions.includes(name)) {
|
||||
html += `<p class="disabled">Extension is disabled. <a href="javascript:void" data-name=${name} class="enable_extension">Click to Enable</a></p>`;
|
||||
}
|
||||
else {
|
||||
const requirements = new Set(manifest.requires);
|
||||
modules.forEach(x => requirements.delete(x));
|
||||
const requirementsString = DOMPurify.sanitize([...requirements].join(', '));
|
||||
html += `<p>Missing modules: <span class="failure">${requirementsString}</span></p>`
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Generates HTML string for displaying an extension in the UI.
|
||||
*
|
||||
* @param {string} name - The name of the extension.
|
||||
* @param {object} manifest - The manifest of the extension.
|
||||
* @param {boolean} isActive - Whether the extension is active or not.
|
||||
* @param {boolean} isDisabled - Whether the extension is disabled or not.
|
||||
* @param {boolean} isExternal - Whether the extension is external or not.
|
||||
* @param {string} checkboxClass - The class for the checkbox HTML element.
|
||||
* @return {string} - The HTML string that represents the extension.
|
||||
*/
|
||||
async function generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal, checkboxClass) {
|
||||
const displayName = manifest.display_name;
|
||||
let displayVersion = manifest.version ? ` v${manifest.version}` : "";
|
||||
let isUpToDate = true;
|
||||
let updateButton = '';
|
||||
let originHtml = '';
|
||||
if (isExternal) {
|
||||
let data = await getExtensionVersion(name.replace('third-party', ''));
|
||||
let branch = data.currentBranchName;
|
||||
let commitHash = data.currentCommitHash;
|
||||
let origin = data.remoteUrl
|
||||
isUpToDate = data.isUpToDate;
|
||||
displayVersion = ` (${branch}-${commitHash.substring(0, 7)})`;
|
||||
updateButton = isUpToDate ?
|
||||
`<span class="update-button"><button class="btn_update menu_button" data-name="${name.replace('third-party', '')}" title="Up to date"><i class="fa-solid fa-code-commit"></i></button></span>` :
|
||||
`<span class="update-button"><button class="btn_update menu_button" data-name="${name.replace('third-party', '')}" title="Update available"><i class="fa-solid fa-download"></i></button></span>`;
|
||||
originHtml = `<a href="${origin}" target="_blank" rel="noopener noreferrer">`;
|
||||
}
|
||||
|
||||
let toggleElement = isActive || isDisabled ?
|
||||
`<input type="checkbox" title="Click to toggle" data-name="${name}" class="${isActive ? 'toggle_disable' : 'toggle_enable'} ${checkboxClass}" ${isActive ? 'checked' : ''}>` :
|
||||
`<input type="checkbox" title="Cannot enable extension" data-name="${name}" class="extension_missing ${checkboxClass}" disabled>`;
|
||||
|
||||
let deleteButton = isExternal ? `<span class="delete-button"><button class="btn_delete menu_button" data-name="${name.replace('third-party', '')}" title="Delete"><i class="fa-solid fa-trash-can"></i></button></span>` : '';
|
||||
|
||||
// if external, wrap the name in a link to the repo
|
||||
|
||||
let extensionHtml = `<hr>
|
||||
<h4>
|
||||
${updateButton}
|
||||
${deleteButton}
|
||||
${originHtml}
|
||||
<span class="${isActive ? "extension_enabled" : isDisabled ? "extension_disabled" : "extension_missing"}">
|
||||
${DOMPurify.sanitize(displayName)}${displayVersion}
|
||||
</span>
|
||||
${isExternal ? '</a>' : ''}
|
||||
|
||||
<span style="float:right;">${toggleElement}</span>
|
||||
</h4>`;
|
||||
|
||||
if (isActive && Array.isArray(manifest.optional)) {
|
||||
const optional = new Set(manifest.optional);
|
||||
modules.forEach(x => optional.delete(x));
|
||||
if (optional.size > 0) {
|
||||
const optionalString = DOMPurify.sanitize([...optional].join(', '));
|
||||
extensionHtml += `<p>Optional modules: <span class="optional">${optionalString}</span></p>`;
|
||||
}
|
||||
} else if (!isDisabled) { // Neither active nor disabled
|
||||
const requirements = new Set(manifest.requires);
|
||||
modules.forEach(x => requirements.delete(x));
|
||||
const requirementsString = DOMPurify.sanitize([...requirements].join(', '));
|
||||
extensionHtml += `<p>Missing modules: <span class="failure">${requirementsString}</span></p>`;
|
||||
}
|
||||
|
||||
return extensionHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extension data and generates the corresponding HTML for displaying the extension.
|
||||
*
|
||||
* @param {Array} extension - An array where the first element is the extension name and the second element is the extension manifest.
|
||||
* @return {object} - An object with 'isExternal' indicating whether the extension is external, and 'extensionHtml' for the extension's HTML string.
|
||||
*/
|
||||
async function getExtensionData(extension) {
|
||||
const name = extension[0];
|
||||
const manifest = extension[1];
|
||||
const isActive = activeExtensions.has(name);
|
||||
const isDisabled = extension_settings.disabledExtensions.includes(name);
|
||||
const isExternal = name.startsWith('third-party');
|
||||
|
||||
const checkboxClass = isDisabled ? "checkbox_disabled" : "";
|
||||
|
||||
const extensionHtml = await generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal, checkboxClass);
|
||||
|
||||
return { isExternal, extensionHtml };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the module information to be displayed.
|
||||
*
|
||||
* @return {string} - The HTML string for the module information.
|
||||
*/
|
||||
function getModuleInformation() {
|
||||
let moduleInfo = modules.length ? `<p>${DOMPurify.sanitize(modules.join(', '))}</p>` : '<p class="failure">Not connected to the API!</p>';
|
||||
return `
|
||||
<h3>Modules provided by your Extensions API:</h3>
|
||||
${moduleInfo}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the HTML strings for all extensions and displays them in a popup.
|
||||
*/
|
||||
async function showExtensionsDetails() {
|
||||
let htmlDefault = '<h3>Default Extensions:</h3>';
|
||||
let htmlExternal = '<h3>External Extensions:</h3>';
|
||||
|
||||
const extensions = Object.entries(manifests).sort((a, b) => a[1].loading_order - b[1].loading_order);
|
||||
|
||||
for (const extension of extensions) {
|
||||
const { isExternal, extensionHtml } = await getExtensionData(extension);
|
||||
if (isExternal) {
|
||||
htmlExternal += extensionHtml;
|
||||
} else {
|
||||
htmlDefault += extensionHtml;
|
||||
}
|
||||
}
|
||||
|
||||
const html = `
|
||||
${getModuleInformation()}
|
||||
${htmlDefault}
|
||||
${htmlExternal}
|
||||
`;
|
||||
callPopup(`<div class="extensions_info">${html}</div>`, 'text');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles the click event for the update button of an extension.
|
||||
* This function makes a POST request to '/update_extension' with the extension's name.
|
||||
* If the extension is already up to date, it displays a success message.
|
||||
* If the extension is not up to date, it updates the extension and displays a success message with the new commit hash.
|
||||
*/
|
||||
async function onUpdateClick() {
|
||||
const extensionName = $(this).data('name');
|
||||
try {
|
||||
const response = await fetch('/update_extension', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({ extensionName })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data.isUpToDate) {
|
||||
toastr.success('Extension is already up to date');
|
||||
} else {
|
||||
toastr.success(`Extension updated to ${data.shortCommitHash}`);
|
||||
}
|
||||
showExtensionsDetails();
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the click event for the delete button of an extension.
|
||||
* This function makes a POST request to '/delete_extension' with the extension's name.
|
||||
* If the extension is deleted, it displays a success message.
|
||||
* Creates a popup for the user to confirm before delete.
|
||||
*/
|
||||
async function onDeleteClick() {
|
||||
const extensionName = $(this).data('name');
|
||||
// use callPopup to create a popup for the user to confirm before delete
|
||||
const confirmation = await callPopup(`Are you sure you want to delete ${extensionName}?`, 'delete_extension');
|
||||
if (confirmation) {
|
||||
try {
|
||||
const response = await fetch('/delete_extension', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({ extensionName })
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
toastr.success(`Extension ${extensionName} deleted`);
|
||||
showExtensionsDetails();
|
||||
// reload the page to remove the extension from the list
|
||||
location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the version details of a specific extension.
|
||||
*
|
||||
* @param {string} extensionName - The name of the extension.
|
||||
* @return {object} - An object containing the extension's version details.
|
||||
* This object includes the currentBranchName, currentCommitHash, isUpToDate, and remoteUrl.
|
||||
* @throws {error} - If there is an error during the fetch operation, it logs the error to the console.
|
||||
*/
|
||||
async function getExtensionVersion(extensionName) {
|
||||
try {
|
||||
const response = await fetch('/get_extension_version', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({ extensionName })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function loadExtensionSettings(settings) {
|
||||
if (settings.extension_settings) {
|
||||
Object.assign(extension_settings, settings.extension_settings);
|
||||
@@ -413,6 +602,7 @@ async function loadExtensionSettings(settings) {
|
||||
$("#extensions_autoconnect").prop('checked', extension_settings.autoConnect);
|
||||
|
||||
// Activate offline extensions
|
||||
eventSource.emit(event_types.EXTENSIONS_FIRST_LOAD);
|
||||
extensionNames = await discoverExtensions();
|
||||
manifests = await getManifests(extensionNames)
|
||||
await activateExtensions();
|
||||
@@ -421,12 +611,12 @@ async function loadExtensionSettings(settings) {
|
||||
}
|
||||
}
|
||||
|
||||
async function runGenerationInterceptors(chat) {
|
||||
async function runGenerationInterceptors(chat, contextSize) {
|
||||
for (const manifest of Object.values(manifests)) {
|
||||
const interceptorKey = manifest.generate_interceptor;
|
||||
if (typeof window[interceptorKey] === 'function') {
|
||||
try {
|
||||
await window[interceptorKey](chat);
|
||||
await window[interceptorKey](chat, contextSize);
|
||||
} catch (e) {
|
||||
console.error(`Failed running interceptor for ${manifest.display_name}`, e);
|
||||
}
|
||||
@@ -443,6 +633,8 @@ $(document).ready(async function () {
|
||||
$("#extensions_connect").on('click', connectClickHandler);
|
||||
$("#extensions_autoconnect").on('input', autoConnectInputHandler);
|
||||
$("#extensions_details").on('click', showExtensionsDetails);
|
||||
$(document).on('click', '.disable_extension', onDisableExtensionClick);
|
||||
$(document).on('click', '.enable_extension', onEnableExtensionClick);
|
||||
$(document).on('click', '.toggle_disable', onDisableExtensionClick);
|
||||
$(document).on('click', '.toggle_enable', onEnableExtensionClick);
|
||||
$(document).on('click', '.btn_update', onUpdateClick);
|
||||
$(document).on('click', '.btn_delete', onDeleteClick);
|
||||
});
|
||||
|
@@ -120,7 +120,7 @@ $(document).ready(function () {
|
||||
<div class="background_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Character Backgrounds</b>
|
||||
<b>Chat Backgrounds</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"display_name": "Character Backgrounds",
|
||||
"display_name": "Chat Backgrounds",
|
||||
"loading_order": 7,
|
||||
"requires": [],
|
||||
"optional": [],
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { getBase64Async } from "../../utils.js";
|
||||
import { getContext, getApiUrl, doExtrasFetch } from "../../extensions.js";
|
||||
import { getContext, getApiUrl, doExtrasFetch, extension_settings } from "../../extensions.js";
|
||||
import { callPopup, saveSettingsDebounced } from "../../../script.js";
|
||||
export { MODULE_NAME };
|
||||
|
||||
const MODULE_NAME = 'caption';
|
||||
@@ -33,7 +34,20 @@ async function setSpinnerIcon() {
|
||||
|
||||
async function sendCaptionedMessage(caption, image) {
|
||||
const context = getContext();
|
||||
const messageText = `[${context.name1} sends ${context.name2 ?? ''} a picture that contains: ${caption}]`;
|
||||
let messageText = `[${context.name1} sends ${context.name2 ?? ''} a picture that contains: ${caption}]`;
|
||||
|
||||
if (extension_settings.caption.refine_mode) {
|
||||
messageText = await callPopup(
|
||||
'<h3>Review and edit the generated message:</h3>Press "Cancel" to abort the caption sending.',
|
||||
'input',
|
||||
messageText,
|
||||
{ rows: 5, okButton: 'Send' });
|
||||
|
||||
if (!messageText) {
|
||||
throw new Error('User aborted the caption sending.');
|
||||
}
|
||||
}
|
||||
|
||||
const message = {
|
||||
name: context.name1,
|
||||
is_user: true,
|
||||
@@ -42,12 +56,12 @@ async function sendCaptionedMessage(caption, image) {
|
||||
mes: messageText,
|
||||
extra: {
|
||||
image: image,
|
||||
title: caption,
|
||||
title: messageText,
|
||||
},
|
||||
};
|
||||
context.chat.push(message);
|
||||
context.addOneMessage(message);
|
||||
await context.generate();
|
||||
await context.generate('caption');
|
||||
}
|
||||
|
||||
async function onSelectImage(e) {
|
||||
@@ -88,6 +102,11 @@ async function onSelectImage(e) {
|
||||
}
|
||||
}
|
||||
|
||||
function onRefineModeInput() {
|
||||
extension_settings.caption.refine_mode = $('#caption_refine_mode').prop('checked');
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
jQuery(function () {
|
||||
function addSendPictureButton() {
|
||||
const sendButton = $(`
|
||||
@@ -109,10 +128,32 @@ jQuery(function () {
|
||||
$('#form_sheld').append(imgForm);
|
||||
$('#img_file').on('change', onSelectImage);
|
||||
}
|
||||
function addSettings() {
|
||||
const html = `
|
||||
<div class="background_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Image Captioning</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label class="checkbox_label" for="caption_refine_mode">
|
||||
<input id="caption_refine_mode" type="checkbox" class="checkbox">
|
||||
Edit captions before generation
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
$('#extensions_settings2').append(html);
|
||||
}
|
||||
|
||||
addSettings();
|
||||
addPictureSendForm();
|
||||
addSendPictureButton();
|
||||
setImageIcon();
|
||||
moduleWorker();
|
||||
$('#caption_refine_mode').prop('checked', !!(extension_settings.caption.refine_mode));
|
||||
$('#caption_refine_mode').on('input', onRefineModeInput);
|
||||
setInterval(moduleWorker, UPDATE_INTERVAL);
|
||||
});
|
||||
|
@@ -10,7 +10,7 @@ async function doDiceRoll(customDiceFormula) {
|
||||
let value = typeof customDiceFormula === 'string' ? customDiceFormula.trim() : $(this).data('value');
|
||||
|
||||
if (value == 'custom') {
|
||||
value = await callPopup('Enter the dice formula:<br><i>(for example, <tt>2d6</tt>)</i>', 'input');x
|
||||
value = await callPopup('Enter the dice formula:<br><i>(for example, <tt>2d6</tt>)</i>', 'input');
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
@@ -76,20 +76,11 @@ function addDiceRollButton() {
|
||||
});
|
||||
}
|
||||
|
||||
function addDiceScript() {
|
||||
if (!window.droll) {
|
||||
const script = document.createElement('script');
|
||||
script.src = "/scripts/extensions/dice/droll.js";
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
}
|
||||
|
||||
async function moduleWorker() {
|
||||
$('#roll_dice').toggle(getContext().onlineStatus !== 'no_connection');
|
||||
}
|
||||
|
||||
jQuery(function () {
|
||||
addDiceScript();
|
||||
addDiceRollButton();
|
||||
moduleWorker();
|
||||
setInterval(moduleWorker, UPDATE_INTERVAL);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { callPopup, eventSource, event_types, getRequestHeaders, saveSettingsDebounced } from "../../../script.js";
|
||||
import { dragElement, isMobile } from "../../RossAscends-mods.js";
|
||||
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch } from "../../extensions.js";
|
||||
import { power_user } from "../../power-user.js";
|
||||
import { loadMovingUIState, power_user } from "../../power-user.js";
|
||||
import { onlyUnique, debounce, getCharaFilename } from "../../utils.js";
|
||||
export { MODULE_NAME };
|
||||
|
||||
@@ -152,7 +152,7 @@ async function visualNovelSetCharacterSprites(container, name, expression) {
|
||||
|
||||
const path = currentSpritePath || defaultSpritePath || '';
|
||||
const img = expressionImage.find('img');
|
||||
setImage(img, path);
|
||||
await setImage(img, path);
|
||||
}
|
||||
expressionImage.toggleClass('hidden', noSprites);
|
||||
} else {
|
||||
@@ -161,9 +161,9 @@ async function visualNovelSetCharacterSprites(container, name, expression) {
|
||||
template.attr('data-avatar', avatar);
|
||||
template.find('.drag-grabber').attr('id', `expression-${avatar}header`);
|
||||
$('#visual-novel-wrapper').append(template);
|
||||
dragElement(template[0]);
|
||||
dragElement($(template[0]));
|
||||
template.toggleClass('hidden', noSprites);
|
||||
setImage(template.find('img'), defaultSpritePath || '');
|
||||
await setImage(template.find('img'), defaultSpritePath || '');
|
||||
const fadeInPromise = new Promise(resolve => {
|
||||
template.fadeIn(250, () => resolve());
|
||||
});
|
||||
@@ -182,20 +182,20 @@ async function visualNovelUpdateLayers(container) {
|
||||
const group = context.groups.find(x => x.id == context.groupId);
|
||||
const recentMessages = context.chat.map(x => x.original_avatar).filter(x => x).reverse().filter(onlyUnique);
|
||||
const filteredMembers = group.members.filter(x => !group.disabled_members.includes(x));
|
||||
const layerIndices = filteredMembers.slice().sort((a, b) => {
|
||||
const layerIndices = filteredMembers.slice().sort((a, b) => {
|
||||
const aRecentIndex = recentMessages.indexOf(a);
|
||||
const bRecentIndex = recentMessages.indexOf(b);
|
||||
const aFilteredIndex = filteredMembers.indexOf(a);
|
||||
const bFilteredIndex = filteredMembers.indexOf(b);
|
||||
|
||||
if (aRecentIndex !== -1 && bRecentIndex !== -1) {
|
||||
return bRecentIndex - aRecentIndex;
|
||||
return bRecentIndex - aRecentIndex;
|
||||
} else if (aRecentIndex !== -1) {
|
||||
return 1;
|
||||
return 1;
|
||||
} else if (bRecentIndex !== -1) {
|
||||
return -1;
|
||||
return -1;
|
||||
} else {
|
||||
return aFilteredIndex - bFilteredIndex;
|
||||
return aFilteredIndex - bFilteredIndex;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -232,10 +232,15 @@ async function visualNovelUpdateLayers(container) {
|
||||
|
||||
images.sort(sortFunction).each((index, current) => {
|
||||
const element = $(current);
|
||||
const elementID = element.attr('id')
|
||||
|
||||
// skip repositioning of dragged elements
|
||||
if (element.data('dragged')) {
|
||||
currentPosition += imagesWidth[index];
|
||||
if (element.data('dragged')
|
||||
|| (power_user.movingUIState[elementID]
|
||||
&& (typeof power_user.movingUIState[elementID] === 'object')
|
||||
&& Object.keys(power_user.movingUIState[elementID]).length > 0)) {
|
||||
loadMovingUIState()
|
||||
//currentPosition += imagesWidth[index];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -284,7 +289,9 @@ async function setLastMessageSprite(img, avatar, labels) {
|
||||
}
|
||||
}
|
||||
|
||||
function setImage(img, path) {
|
||||
async function setImage(img, path) {
|
||||
// Cohee: If something goes wrong, uncomment this to return to the old behavior
|
||||
/*
|
||||
img.attr('src', path);
|
||||
img.removeClass('default');
|
||||
img.off('error');
|
||||
@@ -293,6 +300,79 @@ function setImage(img, path) {
|
||||
$(this).off('error');
|
||||
$(this).attr('src', '');
|
||||
});
|
||||
*/
|
||||
|
||||
return new Promise(resolve => {
|
||||
const prevExpressionSrc = img.attr('src');
|
||||
const expressionClone = img.clone();
|
||||
const originalId = img.attr('id');
|
||||
|
||||
//only swap expressions when necessary
|
||||
if (prevExpressionSrc !== path && !img.hasClass('expression-animating')) {
|
||||
//clone expression
|
||||
expressionClone.addClass('expression-clone')
|
||||
//make invisible and remove id to prevent double ids
|
||||
//must be made invisible to start because they share the same Z-index
|
||||
expressionClone.attr('id', '').css({ opacity: 0 });
|
||||
//add new sprite path to clone src
|
||||
expressionClone.attr('src', path);
|
||||
//add invisible clone to html
|
||||
expressionClone.appendTo(img.parent());
|
||||
|
||||
const duration = 200;
|
||||
|
||||
//add animation flags to both images
|
||||
//to prevent multiple expression changes happening simultaneously
|
||||
img.addClass('expression-animating');
|
||||
|
||||
// Set the parent container's min width and height before running the transition
|
||||
const imgWidth = img.width();
|
||||
const imgHeight = img.height();
|
||||
const expressionHolder = img.parent();
|
||||
expressionHolder.css('min-width', imgWidth > 100 ? imgWidth : 100);
|
||||
expressionHolder.css('min-height', imgHeight > 100 ? imgHeight : 100);
|
||||
|
||||
//position absolute prevent the original from jumping around during transition
|
||||
img.css('position', 'absolute');
|
||||
expressionClone.addClass('expression-animating');
|
||||
//fade the clone in
|
||||
expressionClone.css({
|
||||
opacity: 0
|
||||
}).animate({
|
||||
opacity: 1
|
||||
}, duration)
|
||||
//when finshed fading in clone, fade out the original
|
||||
.promise().done(function () {
|
||||
img.animate({
|
||||
opacity: 0
|
||||
}, duration);
|
||||
//remove old expression
|
||||
img.remove();
|
||||
//replace ID so it becomes the new 'original' expression for next change
|
||||
expressionClone.attr('id', originalId);
|
||||
expressionClone.removeClass('expression-animating');
|
||||
|
||||
// Reset the expression holder min height and width
|
||||
expressionHolder.css('min-width', 100);
|
||||
expressionHolder.css('min-height', 100);
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
expressionClone.removeClass('expression-clone');
|
||||
|
||||
expressionClone.removeClass('default');
|
||||
expressionClone.off('error');
|
||||
expressionClone.on('error', function () {
|
||||
console.debug('Expression image error', sprite.path);
|
||||
$(this).attr('src', '');
|
||||
$(this).off('error');
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onExpressionsShowDefaultInput() {
|
||||
@@ -533,6 +613,11 @@ function drawSpritesList(character, labels, sprites) {
|
||||
$('.expression_settings').show();
|
||||
$('#image_list').empty();
|
||||
$('#image_list').data('name', character);
|
||||
|
||||
if (!Array.isArray(labels)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
labels.sort().forEach((item) => {
|
||||
const sprite = sprites.find(x => x.label == item);
|
||||
|
||||
@@ -561,7 +646,7 @@ function getListItem(item, imageSrc, textClass) {
|
||||
<span class="expression_list_title ${textClass}">${item}</span>
|
||||
<img class="expression_list_image" src="${imageSrc}" />
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
async function getSpritesList(name) {
|
||||
@@ -615,6 +700,8 @@ async function setExpression(character, expression, force) {
|
||||
console.debug('entered setExpressions');
|
||||
await validateImages(character);
|
||||
const img = $('img.expression');
|
||||
const prevExpressionSrc = img.attr('src');
|
||||
const expressionClone = img.clone()
|
||||
|
||||
const sprite = (spriteCache[character] && spriteCache[character].find(x => x.label === expression));
|
||||
console.debug('checking for expression images to show..');
|
||||
@@ -633,26 +720,79 @@ async function setExpression(character, expression, force) {
|
||||
}
|
||||
|
||||
if (groupMember.name == character) {
|
||||
setImage($(`.expression-holder[data-avatar="${member}"] img`), sprite.path);
|
||||
await setImage($(`.expression-holder[data-avatar="${member}"] img`), sprite.path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
//only swap expressions when necessary
|
||||
if (prevExpressionSrc !== sprite.path
|
||||
&& !img.hasClass('expression-animating')) {
|
||||
//clone expression
|
||||
expressionClone.addClass('expression-clone')
|
||||
//make invisible and remove id to prevent double ids
|
||||
//must be made invisible to start because they share the same Z-index
|
||||
expressionClone.attr('id', '').css({ opacity: 0 });
|
||||
//add new sprite path to clone src
|
||||
expressionClone.attr('src', sprite.path);
|
||||
//add invisible clone to html
|
||||
expressionClone.appendTo($("#expression-holder"))
|
||||
|
||||
img.attr('src', sprite.path);
|
||||
img.removeClass('default');
|
||||
img.off('error');
|
||||
img.on('error', function () {
|
||||
console.debug('Expression image error', sprite.path);
|
||||
$(this).attr('src', '');
|
||||
$(this).off('error');
|
||||
if (force && extension_settings.expressions.showDefault) {
|
||||
const duration = 200;
|
||||
|
||||
//add animation flags to both images
|
||||
//to prevent multiple expression changes happening simultaneously
|
||||
img.addClass('expression-animating');
|
||||
|
||||
// Set the parent container's min width and height before running the transition
|
||||
const imgWidth = img.width();
|
||||
const imgHeight = img.height();
|
||||
const expressionHolder = img.parent();
|
||||
expressionHolder.css('min-width', imgWidth > 100 ? imgWidth : 100);
|
||||
expressionHolder.css('min-height', imgHeight > 100 ? imgHeight : 100);
|
||||
|
||||
//position absolute prevent the original from jumping around during transition
|
||||
img.css('position', 'absolute');
|
||||
expressionClone.addClass('expression-animating');
|
||||
//fade the clone in
|
||||
expressionClone.css({
|
||||
opacity: 0
|
||||
}).animate({
|
||||
opacity: 1
|
||||
}, duration)
|
||||
//when finshed fading in clone, fade out the original
|
||||
.promise().done(function () {
|
||||
img.animate({
|
||||
opacity: 0
|
||||
}, duration);
|
||||
//remove old expression
|
||||
img.remove();
|
||||
//replace ID so it becomes the new 'original' expression for next change
|
||||
expressionClone.attr('id', 'expression-image');
|
||||
expressionClone.removeClass('expression-animating');
|
||||
|
||||
// Reset the expression holder min height and width
|
||||
expressionHolder.css('min-width', 100);
|
||||
expressionHolder.css('min-height', 100);
|
||||
});
|
||||
|
||||
|
||||
expressionClone.removeClass('expression-clone');
|
||||
|
||||
expressionClone.removeClass('default');
|
||||
expressionClone.off('error');
|
||||
expressionClone.on('error', function () {
|
||||
console.debug('Expression image error', sprite.path);
|
||||
$(this).attr('src', '');
|
||||
$(this).off('error');
|
||||
if (force && extension_settings.expressions.showDefault) {
|
||||
setDefault();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (extension_settings.expressions.showDefault) {
|
||||
setDefault();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (extension_settings.expressions.showDefault) {
|
||||
setDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,8 +800,8 @@ async function setExpression(character, expression, force) {
|
||||
console.debug('setting default');
|
||||
const defImgUrl = `/img/default-expressions/${expression}.png`;
|
||||
//console.log(defImgUrl);
|
||||
img.attr('src', defImgUrl);
|
||||
img.addClass('default');
|
||||
expressionClone.attr('src', defImgUrl);
|
||||
expressionClone.addClass('default');
|
||||
}
|
||||
document.getElementById("expression-holder").style.display = '';
|
||||
}
|
||||
@@ -900,6 +1040,7 @@ function setExpressionOverrideHtml(forceClear = false) {
|
||||
</div>
|
||||
</div>`;
|
||||
$('body').append(html);
|
||||
loadMovingUIState();
|
||||
}
|
||||
function addVisualNovelMode() {
|
||||
const html = `
|
||||
@@ -954,6 +1095,10 @@ function setExpressionOverrideHtml(forceClear = false) {
|
||||
$('#expression_upload_pack_button').on('click', onClickExpressionUploadPackButton);
|
||||
$('#expressions_show_default').prop('checked', extension_settings.expressions.showDefault).trigger('input');
|
||||
$('#expression_override_cleanup_button').on('click', onClickExpressionOverrideRemoveAllButton);
|
||||
$(document).on('dragstart', '.expression', (e) => {
|
||||
e.preventDefault()
|
||||
return false
|
||||
})
|
||||
$(document).on('click', '.expression_list_item', onClickExpressionImage);
|
||||
$(document).on('click', '.expression_list_upload', onClickExpressionUpload);
|
||||
$(document).on('click', '.expression_list_delete', onClickExpressionDelete);
|
||||
@@ -968,6 +1113,7 @@ function setExpressionOverrideHtml(forceClear = false) {
|
||||
const updateFunction = wrapper.update.bind(wrapper);
|
||||
setInterval(updateFunction, UPDATE_INTERVAL);
|
||||
moduleWorker();
|
||||
dragElement($("#expression-holder"))
|
||||
eventSource.on(event_types.CHAT_CHANGED, () => {
|
||||
setExpressionOverrideHtml();
|
||||
|
||||
|
@@ -20,6 +20,9 @@
|
||||
|
||||
#visual-novel-wrapper .expression-holder {
|
||||
width: max-content;
|
||||
display: flex;
|
||||
left: unset;
|
||||
right: unset;
|
||||
}
|
||||
|
||||
#visual-novel-wrapper .hidden {
|
||||
@@ -38,17 +41,25 @@
|
||||
max-width: 90vh;
|
||||
width: calc((100vw - var(--sheldWidth)) /2);
|
||||
position: absolute;
|
||||
bottom: 1px;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
left: 0;
|
||||
filter: drop-shadow(2px 2px 2px #51515199);
|
||||
z-index: 2;
|
||||
overflow: hidden;
|
||||
resize: both;
|
||||
|
||||
}
|
||||
|
||||
img.expression {
|
||||
min-width: 100px;
|
||||
min-height: 100px;
|
||||
max-height: 90vh;
|
||||
max-width: 90vh;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
vertical-align: bottom;
|
||||
object-fit: contain;
|
||||
}
|
||||
@@ -64,6 +75,10 @@ img.expression.default {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.expression-clone {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.debug-image {
|
||||
display: none;
|
||||
visibility: collapse;
|
||||
@@ -166,4 +181,4 @@ img.expression.default {
|
||||
div.expression {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
#floatingPrompt {
|
||||
overflow-y: auto;
|
||||
max-width: 90svw;
|
||||
max-height: 90svh;
|
||||
min-width: 100px;
|
||||
min-height: 100px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--white30a);
|
||||
position: fixed;
|
||||
padding: 10px;
|
||||
padding-top: 25px;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 0 10px var(--black70a);
|
||||
z-index: 3000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: 0;
|
||||
right: unset;
|
||||
width: calc(((100svw - var(--sheldWidth)) / 2) - 1px);
|
||||
|
||||
}
|
||||
|
||||
.floating_prompt_radio_group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#extension_floating_counter {
|
||||
font-weight: 600;
|
||||
color: orange;
|
||||
}
|
||||
|
||||
.extension_token_counter {
|
||||
font-size: calc(var(--mainFontSize) * 0.9);
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.floating_prompt_settings textarea {
|
||||
font-size: calc(var(--mainFontSize) * 0.9);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
#ANClose {
|
||||
height: 15px;
|
||||
aspect-ratio: 1 / 1;
|
||||
font-size: 20px;
|
||||
opacity: 0.5;
|
||||
transition: all 250ms;
|
||||
}
|
||||
|
||||
#ANClose:hover {
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.panelControlBar {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#floatingPrompt .drag-grabber {
|
||||
position: unset;
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
import { saveSettingsDebounced, getCurrentChatId, system_message_types, eventSource, event_types } from "../../../script.js";
|
||||
import { saveSettingsDebounced, getCurrentChatId, system_message_types, extension_prompt_types, eventSource, event_types, getRequestHeaders, CHARACTERS_PER_TOKEN_RATIO, substituteParams, max_context, } from "../../../script.js";
|
||||
import { humanizedDateTime } from "../../RossAscends-mods.js";
|
||||
import { getApiUrl, extension_settings, getContext, doExtrasFetch } from "../../extensions.js";
|
||||
import { getFileText, onlyUnique, splitRecursive, IndexedDBStore } from "../../utils.js";
|
||||
@@ -9,6 +9,7 @@ const dbStore = new IndexedDBStore('SillyTavern', MODULE_NAME);
|
||||
|
||||
const defaultSettings = {
|
||||
strategy: 'original',
|
||||
sort_strategy: 'date',
|
||||
|
||||
keep_context: 10,
|
||||
keep_context_min: 1,
|
||||
@@ -20,6 +21,15 @@ const defaultSettings = {
|
||||
n_results_max: 500,
|
||||
n_results_step: 1,
|
||||
|
||||
chroma_depth: 20,
|
||||
chroma_depth_min: -1,
|
||||
chroma_depth_max: 500,
|
||||
chroma_depth_step: 1,
|
||||
chroma_default_msg: "In a past conversation: [{{memories}}]",
|
||||
chroma_default_hhaa_wrapper: "Previous messages exchanged between {{user}} and {{char}}:\n{{memories}}",
|
||||
chroma_default_hhaa_memory: "- {{name}}: {{message}}\n",
|
||||
hhaa_token_limit: 512,
|
||||
|
||||
split_length: 384,
|
||||
split_length_min: 64,
|
||||
split_length_max: 4096,
|
||||
@@ -29,6 +39,15 @@ const defaultSettings = {
|
||||
file_split_length_min: 512,
|
||||
file_split_length_max: 4096,
|
||||
file_split_length_step: 128,
|
||||
|
||||
keep_context_proportion: 0.5,
|
||||
keep_context_proportion_min: 0.0,
|
||||
keep_context_proportion_max: 1.0,
|
||||
keep_context_proportion_step: 0.05,
|
||||
|
||||
auto_adjust: true,
|
||||
freeze: false,
|
||||
query_last_only: true,
|
||||
};
|
||||
|
||||
const postHeaders = {
|
||||
@@ -88,18 +107,60 @@ async function loadSettings() {
|
||||
"selected",
|
||||
"true"
|
||||
);
|
||||
$("#chromadb_sort_strategy option[value=" + extension_settings.chromadb.sort_strategy + "]").attr(
|
||||
"selected",
|
||||
"true"
|
||||
);
|
||||
$('#chromadb_keep_context').val(extension_settings.chromadb.keep_context).trigger('input');
|
||||
$('#chromadb_n_results').val(extension_settings.chromadb.n_results).trigger('input');
|
||||
$('#chromadb_split_length').val(extension_settings.chromadb.split_length).trigger('input');
|
||||
$('#chromadb_file_split_length').val(extension_settings.chromadb.file_split_length).trigger('input');
|
||||
$('#chromadb_keep_context_proportion').val(extension_settings.chromadb.keep_context_proportion).trigger('input');
|
||||
$('#chromadb_custom_depth').val(extension_settings.chromadb.chroma_depth).trigger('input');
|
||||
$('#chromadb_custom_msg').val(extension_settings.chromadb.recall_msg).trigger('input');
|
||||
|
||||
$('#chromadb_hhaa_wrapperfmt').val(extension_settings.chromadb.hhaa_wrapper_msg).trigger('input');
|
||||
$('#chromadb_hhaa_memoryfmt').val(extension_settings.chromadb.hhaa_memory_msg).trigger('input');
|
||||
$('#chromadb_hhaa_token_limit').val(extension_settings.chromadb.hhaa_token_limit).trigger('input');
|
||||
|
||||
$('#chromadb_auto_adjust').prop('checked', extension_settings.chromadb.auto_adjust);
|
||||
$('#chromadb_freeze').prop('checked', extension_settings.chromadb.freeze);
|
||||
$('#chromadb_query_last_only').val(extension_settings.chromadb.query_last_only).trigger('input');
|
||||
enableDisableSliders();
|
||||
onStrategyChange();
|
||||
}
|
||||
|
||||
function onStrategyChange() {
|
||||
console.debug('changing chromadb strat');
|
||||
extension_settings.chromadb.strategy = $('#chromadb_strategy').val();
|
||||
if (extension_settings.chromadb.strategy === "custom") {
|
||||
$('#chromadb_custom_depth').show();
|
||||
$('label[for="chromadb_custom_depth"]').show();
|
||||
$('#chromadb_custom_msg').show();
|
||||
$('label[for="chromadb_custom_msg"]').show();
|
||||
}
|
||||
else if(extension_settings.chromadb.strategy === "hh_aa"){
|
||||
$('#chromadb_hhaa_wrapperfmt').show();
|
||||
$('label[for="chromadb_hhaa_wrapperfmt"]').show();
|
||||
$('#chromadb_hhaa_memoryfmt').show();
|
||||
$('label[for="chromadb_hhaa_memoryfmt"]').show();
|
||||
$('#chromadb_hhaa_token_limit').show();
|
||||
$('label[for="chromadb_hhaa_token_limit"]').show();
|
||||
}
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onRecallStrategyChange() {
|
||||
console.log('changing chromadb recall strat');
|
||||
extension_settings.chromadb.recall_strategy = $('#chromadb_recall_strategy').val();
|
||||
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onSortStrategyChange() {
|
||||
console.log('changing chromadb sort strat');
|
||||
extension_settings.chromadb.sort_strategy = $('#chromadb_sort_strategy').val();
|
||||
|
||||
//$('#chromadb_strategy').select(extension_settings.chromadb.strategy);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
@@ -115,6 +176,31 @@ function onNResultsInput() {
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onChromaDepthInput() {
|
||||
extension_settings.chromadb.chroma_depth = Number($('#chromadb_custom_depth').val());
|
||||
$('#chromadb_custom_depth_value').text(extension_settings.chromadb.chroma_depth);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onChromaMsgInput() {
|
||||
extension_settings.chromadb.recall_msg = $('#chromadb_custom_msg').val();
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onChromaHHAAWrapper() {
|
||||
extension_settings.chromadb.hhaa_wrapper_msg = $('#chromadb_hhaa_wrapperfmt').val();
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
function onChromaHHAAMemory() {
|
||||
extension_settings.chromadb.hhaa_memory_msg = $('#chromadb_hhaa_memoryfmt').val();
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
function onChromaHHAATokens() {
|
||||
extension_settings.chromadb.hhaa_token_limit = Number($('#chromadb_hhaa_token_limit').val());
|
||||
$('#chromadb_hhaa_token_limit_value').text(extension_settings.chromadb.hhaa_token_limit);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onSplitLengthInput() {
|
||||
extension_settings.chromadb.split_length = Number($('#chromadb_split_length').val());
|
||||
$('#chromadb_split_length_value').text(extension_settings.chromadb.split_length);
|
||||
@@ -127,6 +213,16 @@ function onFileSplitLengthInput() {
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onChunkNLInput() {
|
||||
let shouldSplit = $('#onChunkNLInput').is(':checked');
|
||||
if (shouldSplit) {
|
||||
extension_settings.chromadb.file_split_type = "newline";
|
||||
} else {
|
||||
extension_settings.chromadb.file_split_type = "length";
|
||||
}
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function checkChatId(chat_id) {
|
||||
if (!chat_id || chat_id.trim() === '') {
|
||||
toastr.error('Please select a character and try again.');
|
||||
@@ -259,10 +355,24 @@ async function onExportClick() {
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
} else {
|
||||
toastr.error('An error occurred while attempting to download the data');
|
||||
//Show the error from the result without the html, only what's in the body paragraph
|
||||
let parser = new DOMParser();
|
||||
let error = await exportResult.text();
|
||||
let doc = parser.parseFromString(error, 'text/html');
|
||||
let errorMessage = doc.querySelector('p').textContent;
|
||||
toastr.error(`An error occurred while attempting to download the data from ChromaDB: ${errorMessage}`);
|
||||
}
|
||||
}
|
||||
|
||||
function tinyhash(text) {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < text.length; ++i) {
|
||||
hash = ((hash<<5) - hash) + text.charCodeAt(i);
|
||||
hash = hash & hash; // Keeps it 32-bit allegedly.
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
async function onSelectImportFile(e) {
|
||||
const file = e.target.files[0];
|
||||
const currentChatId = getCurrentChatId();
|
||||
@@ -280,6 +390,11 @@ async function onSelectImportFile(e) {
|
||||
const text = await getFileText(file);
|
||||
const imported = JSON.parse(text);
|
||||
|
||||
const id_salt = "-" + tinyhash(imported.chat_id).toString(36);
|
||||
for (let entry of imported.content) {
|
||||
entry.id = entry.id + id_salt;
|
||||
}
|
||||
|
||||
imported.chat_id = currentChatId;
|
||||
|
||||
const url = new URL(getApiUrl());
|
||||
@@ -328,6 +443,39 @@ async function queryMessages(chat_id, query) {
|
||||
return [];
|
||||
}
|
||||
|
||||
async function queryMultiMessages(chat_id, query) {
|
||||
const context = getContext();
|
||||
const response = await fetch("/getallchatsofcharacter", {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ avatar_url: context.characters[context.characterId].avatar }),
|
||||
headers: getRequestHeaders(),
|
||||
});
|
||||
if (!response.ok) {
|
||||
return;
|
||||
}
|
||||
let data = await response.json();
|
||||
data = Object.values(data);
|
||||
let chat_list = data.sort((a, b) => a["file_name"].localeCompare(b["file_name"])).reverse();
|
||||
|
||||
// Extracting chat_ids from the chat_list
|
||||
chat_list = chat_list.map(chat => chat.file_name.replace(/\.[^/.]+$/, ""));
|
||||
const url = new URL(getApiUrl());
|
||||
url.pathname = '/api/chromadb/multiquery';
|
||||
|
||||
const queryMessagesResult = await fetch(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ chat_list, query, n_results: extension_settings.chromadb.n_results }),
|
||||
headers: postHeaders,
|
||||
});
|
||||
|
||||
if (queryMessagesResult.ok) {
|
||||
const queryMessagesData = await queryMessagesResult.json();
|
||||
return queryMessagesData;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
async function onSelectInjectFile(e) {
|
||||
const file = e.target.files[0];
|
||||
const currentChatId = getCurrentChatId();
|
||||
@@ -341,8 +489,14 @@ async function onSelectInjectFile(e) {
|
||||
try {
|
||||
toastr.info('This may take some time, depending on the file size', 'Processing...');
|
||||
const text = await getFileText(file);
|
||||
|
||||
const split = splitRecursive(text, extension_settings.chromadb.file_split_length).filter(onlyUnique);
|
||||
extension_settings.chromadb.file_split_type = "newline";
|
||||
//allow splitting on newlines or splitrecursively
|
||||
let split = [];
|
||||
if (extension_settings.chromadb.file_split_type == "newline") {
|
||||
split = text.split(/\r?\n/).filter(onlyUnique);
|
||||
} else {
|
||||
split = splitRecursive(text, extension_settings.chromadb.file_split_length).filter(onlyUnique);
|
||||
}
|
||||
const baseDate = Date.now();
|
||||
|
||||
const messages = split.map((m, i) => ({
|
||||
@@ -390,68 +544,251 @@ async function onSelectInjectFile(e) {
|
||||
}
|
||||
}
|
||||
|
||||
window.chromadb_interceptGeneration = async (chat) => {
|
||||
/*
|
||||
* Automatically adjusts the extension settings for the optimal number of messages to keep and query based
|
||||
* on the chat history and a specified maximum context length.
|
||||
*/
|
||||
function doAutoAdjust(chat, maxContext) {
|
||||
console.debug('CHROMADB: Auto-adjusting sliders (messages: %o, maxContext: %o)', chat.length, maxContext);
|
||||
// Get mean message length
|
||||
const meanMessageLength = chat.reduce((acc, cur) => acc + cur.mes.length, 0) / chat.length;
|
||||
|
||||
if (Number.isNaN(meanMessageLength)) {
|
||||
console.debug('CHROMADB: Mean message length is NaN, aborting auto-adjust');
|
||||
return;
|
||||
}
|
||||
|
||||
console.debug('CHROMADB: Mean message length (characters): %o', meanMessageLength);
|
||||
// Convert to number of "tokens"
|
||||
const meanMessageLengthTokens = Math.ceil(meanMessageLength / CHARACTERS_PER_TOKEN_RATIO);
|
||||
console.debug('CHROMADB: Mean message length (tokens): %o', meanMessageLengthTokens);
|
||||
// Get number of messages in context
|
||||
const contextMessages = Math.max(1, Math.ceil(maxContext / meanMessageLengthTokens));
|
||||
// Round up to nearest 10
|
||||
const contextMessagesRounded = Math.ceil(contextMessages / 10) * 10;
|
||||
console.debug('CHROMADB: Estimated context messages (rounded): %o', contextMessagesRounded);
|
||||
// Messages to keep (proportional, rounded to nearest 5, minimum 5, maximum 500)
|
||||
const messagesToKeep = Math.min(defaultSettings.keep_context_max, Math.max(5, Math.floor(contextMessagesRounded * extension_settings.chromadb.keep_context_proportion / 5) * 5));
|
||||
console.debug('CHROMADB: Estimated messages to keep: %o', messagesToKeep);
|
||||
// Messages to query (rounded, maximum 500)
|
||||
const messagesToQuery = Math.min(defaultSettings.n_results_max, contextMessagesRounded - messagesToKeep);
|
||||
console.debug('CHROMADB: Estimated messages to query: %o', messagesToQuery);
|
||||
// Set extension settings
|
||||
extension_settings.chromadb.keep_context = messagesToKeep;
|
||||
extension_settings.chromadb.n_results = messagesToQuery;
|
||||
// Update sliders
|
||||
$('#chromadb_keep_context').val(messagesToKeep);
|
||||
$('#chromadb_n_results').val(messagesToQuery);
|
||||
// Update labels
|
||||
$('#chromadb_keep_context_value').text(extension_settings.chromadb.keep_context);
|
||||
$('#chromadb_n_results_value').text(extension_settings.chromadb.n_results);
|
||||
}
|
||||
|
||||
window.chromadb_interceptGeneration = async (chat, maxContext) => {
|
||||
if (extension_settings.chromadb.auto_adjust) {
|
||||
doAutoAdjust(chat, maxContext);
|
||||
}
|
||||
|
||||
const currentChatId = getCurrentChatId();
|
||||
if (!currentChatId)
|
||||
return;
|
||||
|
||||
//log the current settings
|
||||
console.debug("CHROMADB: Current settings: %o", extension_settings.chromadb);
|
||||
|
||||
const selectedStrategy = extension_settings.chromadb.strategy;
|
||||
if (currentChatId) {
|
||||
const messagesToStore = chat.slice(0, -extension_settings.chromadb.keep_context);
|
||||
const recallStrategy = extension_settings.chromadb.recall_strategy;
|
||||
let recallMsg = extension_settings.chromadb.recall_msg || defaultSettings.chroma_default_msg;
|
||||
const chromaDepth = extension_settings.chromadb.chroma_depth;
|
||||
const chromaSortStrategy = extension_settings.chromadb.sort_strategy;
|
||||
const chromaQueryLastOnly = extension_settings.chromadb.query_last_only;
|
||||
const messagesToStore = chat.slice(0, -extension_settings.chromadb.keep_context);
|
||||
|
||||
if (messagesToStore.length > 0 || extension_settings.chromadb.freeze) {
|
||||
await addMessages(currentChatId, messagesToStore);
|
||||
if (messagesToStore.length > 0 && !extension_settings.chromadb.freeze) {
|
||||
//log the messages to store
|
||||
console.debug("CHROMADB: Messages to store: %o", messagesToStore);
|
||||
//log the messages to store length vs keep context
|
||||
console.debug("CHROMADB: Messages to store length vs keep context: %o vs %o", messagesToStore.length, extension_settings.chromadb.keep_context);
|
||||
await addMessages(currentChatId, messagesToStore);
|
||||
}
|
||||
|
||||
const lastMessage = chat[chat.length - 1];
|
||||
|
||||
const lastMessage = chat[chat.length - 1];
|
||||
|
||||
if (lastMessage) {
|
||||
const queriedMessages = await queryMessages(currentChatId, lastMessage.mes);
|
||||
|
||||
queriedMessages.sort((a, b) => a.date - b.date);
|
||||
|
||||
const newChat = [];
|
||||
|
||||
if (selectedStrategy === 'ross') {
|
||||
//adds chroma to the end of chat and allows Generate() to cull old messages naturally.
|
||||
const context = getContext();
|
||||
const charname = context.name2;
|
||||
newChat.push(
|
||||
{
|
||||
is_name: false,
|
||||
is_user: false,
|
||||
mes: `[Use these past chat exchanges to inform ${charname}'s next response:`,
|
||||
name: "system",
|
||||
send_date: 0,
|
||||
}
|
||||
);
|
||||
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
|
||||
newChat.push(
|
||||
{
|
||||
is_name: false,
|
||||
is_user: false,
|
||||
mes: `]\n`,
|
||||
name: "system",
|
||||
send_date: 0,
|
||||
}
|
||||
);
|
||||
chat.splice(chat.length, 0, ...newChat);
|
||||
}
|
||||
|
||||
if (selectedStrategy === 'original') {
|
||||
//removes .length # messages from the start of 'kept messages'
|
||||
//replaces them with chromaDB results (with no separator)
|
||||
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
|
||||
chat.splice(0, messagesToStore.length, ...newChat);
|
||||
|
||||
}
|
||||
console.log('ChromaDB chat after injection', chat);
|
||||
let queriedMessages;
|
||||
if (lastMessage) {
|
||||
let queryBlob = "";
|
||||
if (chromaQueryLastOnly) {
|
||||
queryBlob = lastMessage.mes;
|
||||
}
|
||||
else {
|
||||
for (let msg of chat.slice(-extension_settings.chromadb.keep_context)) {
|
||||
queryBlob += `${msg.mes}\n`
|
||||
}
|
||||
}
|
||||
console.debug("CHROMADB: Query text:", queryBlob);
|
||||
|
||||
if (recallStrategy === 'multichat') {
|
||||
console.log("Utilizing multichat")
|
||||
queriedMessages = await queryMultiMessages(currentChatId, queryBlob);
|
||||
}
|
||||
else {
|
||||
queriedMessages = await queryMessages(currentChatId, queryBlob);
|
||||
}
|
||||
|
||||
if (chromaSortStrategy === "date") {
|
||||
queriedMessages.sort((a, b) => a.date - b.date);
|
||||
}
|
||||
else {
|
||||
queriedMessages.sort((a, b) => b.distance - a.distance);
|
||||
}
|
||||
console.debug("CHROMADB: Query results: %o", queriedMessages);
|
||||
|
||||
|
||||
let newChat = [];
|
||||
|
||||
if (selectedStrategy === 'ross') {
|
||||
//adds chroma to the end of chat and allows Generate() to cull old messages naturally.
|
||||
const context = getContext();
|
||||
const charname = context.name2;
|
||||
newChat.push(
|
||||
{
|
||||
is_name: false,
|
||||
is_user: false,
|
||||
mes: `[Use these past chat exchanges to inform ${charname}'s next response:`,
|
||||
name: "system",
|
||||
send_date: 0,
|
||||
}
|
||||
);
|
||||
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
|
||||
newChat.push(
|
||||
{
|
||||
is_name: false,
|
||||
is_user: false,
|
||||
mes: `]\n`,
|
||||
name: "system",
|
||||
send_date: 0,
|
||||
}
|
||||
);
|
||||
chat.splice(chat.length, 0, ...newChat);
|
||||
}
|
||||
if (selectedStrategy === 'hh_aa') {
|
||||
// Insert chroma history messages as a list at the AFTER_SCENARIO anchor point
|
||||
const context = getContext();
|
||||
const chromaTokenLimit = extension_settings.chromadb.hhaa_token_limit;
|
||||
|
||||
let wrapperMsg = extension_settings.chromadb.hhaa_wrapper_msg || defaultSettings.chroma_default_hhaa_wrapper;
|
||||
wrapperMsg = substituteParams(wrapperMsg, context.name1, context.name2);
|
||||
if (!wrapperMsg.includes("{{memories}}")) {
|
||||
wrapperMsg += " {{memories}}";
|
||||
}
|
||||
let memoryMsg = extension_settings.chromadb.hhaa_memory_msg || defaultSettings.chroma_default_hhaa_memory;
|
||||
memoryMsg = substituteParams(memoryMsg, context.name1, context.name2);
|
||||
if (!memoryMsg.includes("{{message}}")) {
|
||||
memoryMsg += " {{message}}";
|
||||
}
|
||||
|
||||
// Reversed because we want the most 'important' messages at the bottom.
|
||||
let recalledMemories = queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse).reverse();
|
||||
let tokenApprox = 0;
|
||||
let allMemoryBlob = "";
|
||||
let seenMemories = new Set(); // Why are there even duplicates in chromadb anyway?
|
||||
for (const msg of recalledMemories) {
|
||||
const memoryBlob = memoryMsg.replace('{{name}}', msg.name).replace('{{message}}', msg.mes);
|
||||
const memoryTokens = (memoryBlob.length / CHARACTERS_PER_TOKEN_RATIO);
|
||||
if (!seenMemories.has(memoryBlob) && tokenApprox + memoryTokens <= chromaTokenLimit) {
|
||||
allMemoryBlob += memoryBlob;
|
||||
tokenApprox += memoryTokens;
|
||||
seenMemories.add(memoryBlob);
|
||||
}
|
||||
}
|
||||
|
||||
// No memories? No prompt.
|
||||
const promptBlob = (tokenApprox == 0) ? "" : wrapperMsg.replace('{{memories}}', allMemoryBlob);
|
||||
console.debug("CHROMADB: prompt blob: %o", promptBlob);
|
||||
context.setExtensionPrompt(MODULE_NAME, promptBlob, extension_prompt_types.AFTER_SCENARIO);
|
||||
}
|
||||
if (selectedStrategy === 'custom') {
|
||||
const context = getContext();
|
||||
recallMsg = substituteParams(recallMsg, context.name1, context.name2);
|
||||
if (!recallMsg.includes("{{memories}}")) {
|
||||
recallMsg += " {{memories}}";
|
||||
}
|
||||
let recallStart = recallMsg.split('{{memories}}')[0]
|
||||
let recallEnd = recallMsg.split('{{memories}}')[1]
|
||||
|
||||
newChat.push(
|
||||
{
|
||||
is_name: false,
|
||||
is_user: false,
|
||||
mes: recallStart,
|
||||
name: "system",
|
||||
send_date: 0,
|
||||
}
|
||||
);
|
||||
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
|
||||
newChat.push(
|
||||
{
|
||||
is_name: false,
|
||||
is_user: false,
|
||||
mes: recallEnd + `\n`,
|
||||
name: "system",
|
||||
send_date: 0,
|
||||
}
|
||||
);
|
||||
|
||||
//prototype chroma duplicate removal
|
||||
let chatset = new Set(chat.map(obj => obj.mes));
|
||||
newChat = newChat.filter(obj => !chatset.has(obj.mes));
|
||||
|
||||
if(chromaDepth === -1) {
|
||||
chat.splice(chat.length, 0, ...newChat);
|
||||
}
|
||||
else {
|
||||
chat.splice(chromaDepth, 0, ...newChat);
|
||||
}
|
||||
}
|
||||
if (selectedStrategy === 'original') {
|
||||
//removes .length # messages from the start of 'kept messages'
|
||||
//replaces them with chromaDB results (with no separator)
|
||||
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
|
||||
chat.splice(0, messagesToStore.length, ...newChat);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onFreezeInput() {
|
||||
extension_settings.chromadb.freeze = $('#chromadb_freeze').is(':checked');
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onAutoAdjustInput() {
|
||||
extension_settings.chromadb.auto_adjust = $('#chromadb_auto_adjust').is(':checked');
|
||||
enableDisableSliders();
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
function onFullLogQuery() {
|
||||
extension_settings.chromadb.query_last_only = $('#chromadb_query_last_only').is(':checked');
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function enableDisableSliders() {
|
||||
const auto_adjust = extension_settings.chromadb.auto_adjust;
|
||||
$('label[for="chromadb_keep_context"]').prop('hidden', auto_adjust);
|
||||
$('#chromadb_keep_context').prop('hidden', auto_adjust)
|
||||
$('label[for="chromadb_n_results"]').prop('hidden', auto_adjust);
|
||||
$('#chromadb_n_results').prop('hidden', auto_adjust)
|
||||
$('label[for="chromadb_keep_context_proportion"]').prop('hidden', !auto_adjust);
|
||||
$('#chromadb_keep_context_proportion').prop('hidden', !auto_adjust)
|
||||
}
|
||||
|
||||
function onKeepContextProportionInput() {
|
||||
extension_settings.chromadb.keep_context_proportion = $('#chromadb_keep_context_proportion').val();
|
||||
$('#chromadb_keep_context_proportion_value').text(Math.round(extension_settings.chromadb.keep_context_proportion * 100));
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
jQuery(async () => {
|
||||
const settingsHtml = `
|
||||
<div class="chromadb_settings">
|
||||
@@ -467,11 +804,39 @@ jQuery(async () => {
|
||||
<select id="chromadb_strategy">
|
||||
<option value="original">Replace non-kept chat items with memories</option>
|
||||
<option value="ross">Add memories after chat with a header tag</option>
|
||||
<option value="hh_aa">Add memory list to character description</option>
|
||||
<option value="custom">Add memories at custom depth with custom msg</option>
|
||||
</select>
|
||||
<label for="chromadb_custom_msg" hidden><small>Custom injection message:</small></label>
|
||||
<textarea id="chromadb_custom_msg" hidden class="text_pole textarea_compact" rows="2" placeholder="${defaultSettings.chroma_default_msg}" style="height: 61px; display: none;"></textarea>
|
||||
<label for="chromadb_custom_depth" hidden><small>How deep should the memory messages be injected?: (<span id="chromadb_custom_depth_value"></span>)</small></label>
|
||||
<input id="chromadb_custom_depth" type="range" min="${defaultSettings.chroma_depth_min}" max="${defaultSettings.chroma_depth_max}" step="${defaultSettings.chroma_depth_step}" value="${defaultSettings.chroma_depth}" hidden/>
|
||||
|
||||
<label for="chromadb_hhaa_wrapperfmt" hidden><small>Custom wrapper format:</small></label>
|
||||
<textarea id="chromadb_hhaa_wrapperfmt" hidden class="text_pole textarea_compact" rows="2" placeholder="${defaultSettings.chroma_default_hhaa_wrapper}" style="height: 61px; display: none;"></textarea>
|
||||
<label for="chromadb_hhaa_memoryfmt" hidden><small>Custom memory format:</small></label>
|
||||
<textarea id="chromadb_hhaa_memoryfmt" hidden class="text_pole textarea_compact" rows="2" placeholder="${defaultSettings.chroma_default_hhaa_memory}" style="height: 61px; display: none;"></textarea>
|
||||
<label for="chromadb_hhaa_token_limit" hidden><small>Maximum tokens allowed for memories: (<span id="chromadb_hhaa_token_limit_value"></span>)</small></label>
|
||||
<input id="chromadb_hhaa_token_limit" type="range" min="0" max="2048" step="64" value="${defaultSettings.hhaa_token_limit}" hidden/>
|
||||
|
||||
|
||||
<span>Memory Recall Strategy</span>
|
||||
<select id="chromadb_recall_strategy">
|
||||
<option value="original">Recall only from this chat</option>
|
||||
<option value="multichat">Recall from all character chats (experimental)</option>
|
||||
</select>
|
||||
<span>Memory Sort Strategy</span>
|
||||
<select id="chromadb_sort_strategy">
|
||||
<option value="date">Sort memories by date</option>
|
||||
<option value="distance">Sort memories by relevance</option>
|
||||
</select>
|
||||
<label for="chromadb_keep_context"><small>How many original chat messages to keep: (<span id="chromadb_keep_context_value"></span>) messages</small></label>
|
||||
<input id="chromadb_keep_context" type="range" min="${defaultSettings.keep_context_min}" max="${defaultSettings.keep_context_max}" step="${defaultSettings.keep_context_step}" value="${defaultSettings.keep_context}" />
|
||||
<label for="chromadb_n_results"><small>Maximum number of ChromaDB 'memories' to inject: (<span id="chromadb_n_results_value"></span>) messages</small></label>
|
||||
<input id="chromadb_n_results" type="range" min="${defaultSettings.n_results_min}" max="${defaultSettings.n_results_max}" step="${defaultSettings.n_results_step}" value="${defaultSettings.n_results}" />
|
||||
|
||||
<label for="chromadb_keep_context_proportion"><small>Keep (<span id="chromadb_keep_context_proportion_value"></span>%) of in-context chat messages; replace the rest with memories</small></label>
|
||||
<input id="chromadb_keep_context_proportion" type="range" min="${defaultSettings.keep_context_proportion_min}" max="${defaultSettings.keep_context_proportion_max}" step="${defaultSettings.keep_context_proportion_step}" value="${defaultSettings.keep_context_proportion}" />
|
||||
<label for="chromadb_split_length"><small>Max length for each 'memory' pulled from the current chat history: (<span id="chromadb_split_length_value"></span>) characters</small></label>
|
||||
<input id="chromadb_split_length" type="range" min="${defaultSettings.split_length_min}" max="${defaultSettings.split_length_max}" step="${defaultSettings.split_length_step}" value="${defaultSettings.split_length}" />
|
||||
<label for="chromadb_file_split_length"><small>Max length for each 'memory' pulled from imported text files: (<span id="chromadb_file_split_length_value"></span>) characters</small></label>
|
||||
@@ -480,6 +845,18 @@ jQuery(async () => {
|
||||
<input type="checkbox" id="chromadb_freeze" />
|
||||
<span>Freeze ChromaDB state</span>
|
||||
</label>
|
||||
<label class="checkbox_label for="chromadb_auto_adjust" title="Automatically adjusts the number of messages to keep based on the average number of messages in the current chat and the chosen proportion.">
|
||||
<input type="checkbox" id="chromadb_auto_adjust" />
|
||||
<span>Use % strategy</span>
|
||||
</label>
|
||||
<label class="checkbox_label" for="chromadb_chunk_nl" title="Chunk injected documents on newline instead of at set character size." >
|
||||
<input type="checkbox" id="chromadb_chunk_nl" />
|
||||
<span>Chunk on Newlines</span>
|
||||
</label>
|
||||
<label class="checkbox_label for="chromadb_query_last_only" title="ChromaDB queries only use the most recent message. (Instead of using all messages still in the context.)">
|
||||
<input type="checkbox" id="chromadb_query_last_only" />
|
||||
<span>Query last message only</span>
|
||||
</label>
|
||||
<div class="flex-container spaceEvenly">
|
||||
<div id="chromadb_inject" title="Upload custom textual data to use in the context of the current chat" class="menu_button">
|
||||
<i class="fa-solid fa-file-arrow-up"></i>
|
||||
@@ -506,8 +883,17 @@ jQuery(async () => {
|
||||
|
||||
$('#extensions_settings2').append(settingsHtml);
|
||||
$('#chromadb_strategy').on('change', onStrategyChange);
|
||||
$('#chromadb_recall_strategy').on('change', onRecallStrategyChange);
|
||||
$('#chromadb_sort_strategy').on('change', onSortStrategyChange);
|
||||
$('#chromadb_keep_context').on('input', onKeepContextInput);
|
||||
$('#chromadb_n_results').on('input', onNResultsInput);
|
||||
$('#chromadb_custom_depth').on('input', onChromaDepthInput);
|
||||
$('#chromadb_custom_msg').on('input', onChromaMsgInput);
|
||||
|
||||
$('#chromadb_hhaa_wrapperfmt').on('input', onChromaHHAAWrapper);
|
||||
$('#chromadb_hhaa_memoryfmt').on('input', onChromaHHAAMemory);
|
||||
$('#chromadb_hhaa_token_limit').on('input', onChromaHHAATokens);
|
||||
|
||||
$('#chromadb_split_length').on('input', onSplitLengthInput);
|
||||
$('#chromadb_file_split_length').on('input', onFileSplitLengthInput);
|
||||
$('#chromadb_inject').on('click', () => $('#chromadb_inject_file').trigger('click'));
|
||||
@@ -517,6 +903,10 @@ jQuery(async () => {
|
||||
$('#chromadb_purge').on('click', onPurgeClick);
|
||||
$('#chromadb_export').on('click', onExportClick);
|
||||
$('#chromadb_freeze').on('input', onFreezeInput);
|
||||
$('#chromadb_chunk_nl').on('input', onChunkNLInput);
|
||||
$('#chromadb_auto_adjust').on('input', onAutoAdjustInput);
|
||||
$('#chromadb_query_last_only').on('input', onFullLogQuery);
|
||||
$('#chromadb_keep_context_proportion').on('input', onKeepContextProportionInput);
|
||||
await loadSettings();
|
||||
|
||||
// Not sure if this is needed, but it's here just in case
|
||||
|
@@ -1,10 +1,9 @@
|
||||
import { getStringHash, debounce } from "../../utils.js";
|
||||
import { getContext, getApiUrl, extension_settings, ModuleWorkerWrapper, doExtrasFetch } from "../../extensions.js";
|
||||
import { extension_prompt_types, is_send_press, saveSettingsDebounced } from "../../../script.js";
|
||||
import { getStringHash, debounce, waitUntilCondition } from "../../utils.js";
|
||||
import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules } from "../../extensions.js";
|
||||
import { eventSource, event_types, extension_prompt_types, generateQuietPrompt, is_send_press, saveSettingsDebounced, substituteParams } from "../../../script.js";
|
||||
export { MODULE_NAME };
|
||||
|
||||
const MODULE_NAME = '1_memory';
|
||||
const UPDATE_INTERVAL = 5000;
|
||||
|
||||
let lastCharacterId = null;
|
||||
let lastGroupId = null;
|
||||
@@ -13,9 +12,16 @@ let lastMessageHash = null;
|
||||
let lastMessageId = null;
|
||||
let inApiCall = false;
|
||||
|
||||
const formatMemoryValue = (value) => value ? `Context: ${value.trim()}` : '';
|
||||
const formatMemoryValue = (value) => value ? `Summary: ${value.trim()}` : '';
|
||||
const saveChatDebounced = debounce(() => getContext().saveChat(), 2000);
|
||||
|
||||
const summary_sources = {
|
||||
'extras': 'extras',
|
||||
'main': 'main',
|
||||
};
|
||||
|
||||
const defaultPrompt = '[Pause your roleplay. Summarize the most important facts and events that have happened in the chat so far. If a summary already exists in your memory, use that as a base and expand with new facts. Limit the summary to {{words}} words or less. Your response should include nothing but the summary.]';
|
||||
|
||||
const defaultSettings = {
|
||||
minLongMemory: 16,
|
||||
maxLongMemory: 1024,
|
||||
@@ -38,6 +44,16 @@ const defaultSettings = {
|
||||
maxLengthPenalty: 4,
|
||||
lengthPenaltyStep: 0.1,
|
||||
memoryFrozen: false,
|
||||
source: summary_sources.extras,
|
||||
prompt: defaultPrompt,
|
||||
promptWords: 200,
|
||||
promptMinWords: 25,
|
||||
promptMaxWords: 1000,
|
||||
promptWordsStep: 25,
|
||||
promptInterval: 10,
|
||||
promptMinInterval: 1,
|
||||
promptMaxInterval: 100,
|
||||
promptIntervalStep: 1,
|
||||
};
|
||||
|
||||
function loadSettings() {
|
||||
@@ -45,12 +61,42 @@ function loadSettings() {
|
||||
Object.assign(extension_settings.memory, defaultSettings);
|
||||
}
|
||||
|
||||
if (extension_settings.memory.source === undefined) {
|
||||
extension_settings.memory.source = defaultSettings.source;
|
||||
}
|
||||
|
||||
if (extension_settings.memory.prompt === undefined) {
|
||||
extension_settings.memory.prompt = defaultSettings.prompt;
|
||||
}
|
||||
|
||||
if (extension_settings.memory.promptWords === undefined) {
|
||||
extension_settings.memory.promptWords = defaultSettings.promptWords;
|
||||
}
|
||||
|
||||
if (extension_settings.memory.promptInterval === undefined) {
|
||||
extension_settings.memory.promptInterval = defaultSettings.promptInterval;
|
||||
}
|
||||
|
||||
$('#summary_source').val(extension_settings.memory.source).trigger('change');
|
||||
$('#memory_long_length').val(extension_settings.memory.longMemoryLength).trigger('input');
|
||||
$('#memory_short_length').val(extension_settings.memory.shortMemoryLength).trigger('input');
|
||||
$('#memory_repetition_penalty').val(extension_settings.memory.repetitionPenalty).trigger('input');
|
||||
$('#memory_temperature').val(extension_settings.memory.temperature).trigger('input');
|
||||
$('#memory_length_penalty').val(extension_settings.memory.lengthPenalty).trigger('input');
|
||||
$('#memory_frozen').prop('checked', extension_settings.memory.memoryFrozen).trigger('input');
|
||||
$('#memory_prompt').val(extension_settings.memory.prompt).trigger('input');
|
||||
$('#memory_prompt_words').val(extension_settings.memory.promptWords).trigger('input');
|
||||
$('#memory_prompt_interval').val(extension_settings.memory.promptInterval).trigger('input');
|
||||
}
|
||||
|
||||
function onSummarySourceChange(event) {
|
||||
const value = event.target.value;
|
||||
extension_settings.memory.source = value;
|
||||
$('#memory_settings [data-source]').each((_, element) => {
|
||||
const source = $(element).data('source');
|
||||
$(element).toggle(source === value);
|
||||
});
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onMemoryShortInput() {
|
||||
@@ -104,6 +150,26 @@ function onMemoryFrozenInput() {
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onMemoryPromptWordsInput() {
|
||||
const value = $(this).val();
|
||||
extension_settings.memory.promptWords = Number(value);
|
||||
$('#memory_prompt_words_value').text(extension_settings.memory.promptWords);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onMemoryPromptIntervalInput() {
|
||||
const value = $(this).val();
|
||||
extension_settings.memory.promptInterval = Number(value);
|
||||
$('#memory_prompt_interval_value').text(extension_settings.memory.promptInterval);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onMemoryPromptInput() {
|
||||
const value = $(this).val();
|
||||
extension_settings.memory.prompt = value;
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function saveLastValues() {
|
||||
const context = getContext();
|
||||
lastGroupId = context.groupId;
|
||||
@@ -129,7 +195,14 @@ function getLatestMemoryFromChat(chat) {
|
||||
return '';
|
||||
}
|
||||
|
||||
async function moduleWorker() {
|
||||
async function onChatEvent() {
|
||||
// Module not enabled
|
||||
if (extension_settings.memory.source === summary_sources.extras) {
|
||||
if (!modules.includes('summarize')) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const context = getContext();
|
||||
const chat = context.chat;
|
||||
|
||||
@@ -187,7 +260,93 @@ async function moduleWorker() {
|
||||
}
|
||||
}
|
||||
|
||||
async function forceSummarizeChat() {
|
||||
const context = getContext();
|
||||
|
||||
if (!context.chatId) {
|
||||
toastr.warning('No chat selected');
|
||||
return;
|
||||
}
|
||||
|
||||
toastr.info('Summarizing chat...', 'Please wait');
|
||||
const value = await summarizeChatMain(context, true);
|
||||
|
||||
if (!value) {
|
||||
toastr.warning('Failed to summarize chat');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async function summarizeChat(context) {
|
||||
switch (extension_settings.memory.source) {
|
||||
case summary_sources.extras:
|
||||
await summarizeChatExtras(context);
|
||||
break;
|
||||
case summary_sources.main:
|
||||
await summarizeChatMain(context, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async function summarizeChatMain(context, force) {
|
||||
try {
|
||||
// Wait for the send button to be released
|
||||
waitUntilCondition(() => is_send_press === false, 10000, 100);
|
||||
} catch {
|
||||
console.debug('Timeout waiting for is_send_press');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!context.chat.length) {
|
||||
console.debug('No messages in chat to summarize');
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.chat.length < extension_settings.memory.promptInterval && !force) {
|
||||
console.debug(`Not enough messages in chat to summarize (chat: ${context.chat.length}, interval: ${extension_settings.memory.promptInterval})`);
|
||||
return;
|
||||
}
|
||||
|
||||
let messagesSinceLastSummary = 0;
|
||||
for (let i = context.chat.length - 1; i >= 0; i--) {
|
||||
if (context.chat[i].extra && context.chat[i].extra.memory) {
|
||||
break;
|
||||
}
|
||||
messagesSinceLastSummary++;
|
||||
}
|
||||
|
||||
if (messagesSinceLastSummary < extension_settings.memory.promptInterval && !force) {
|
||||
console.debug(`Not enough messages since last summary (messages: ${messagesSinceLastSummary}, interval: ${extension_settings.memory.promptInterval}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Summarizing chat, messages since last summary: ' + messagesSinceLastSummary);
|
||||
const prompt = substituteParams(extension_settings.memory.prompt)
|
||||
.replace(/{{words}}/gi, extension_settings.memory.promptWords);
|
||||
|
||||
if (!prompt) {
|
||||
console.debug('Summarization prompt is empty. Skipping summarization.');
|
||||
return;
|
||||
}
|
||||
|
||||
const summary = await generateQuietPrompt(prompt);
|
||||
const newContext = getContext();
|
||||
|
||||
// something changed during summarization request
|
||||
if (newContext.groupId !== context.groupId
|
||||
|| newContext.chatId !== context.chatId
|
||||
|| (!newContext.groupId && (newContext.characterId !== context.characterId))) {
|
||||
console.log('Context changed, summary discarded');
|
||||
return;
|
||||
}
|
||||
|
||||
setMemoryContext(summary, true);
|
||||
return summary;
|
||||
}
|
||||
|
||||
async function summarizeChatExtras(context) {
|
||||
function getMemoryString() {
|
||||
return (longMemory + '\n\n' + memoryBuffer.slice().reverse().join('\n\n')).trim();
|
||||
}
|
||||
@@ -301,6 +460,7 @@ function setMemoryContext(value, saveToMessage) {
|
||||
const context = getContext();
|
||||
context.setExtensionPrompt(MODULE_NAME, formatMemoryValue(value), extension_prompt_types.AFTER_SCENARIO);
|
||||
$('#memory_contents').val(value);
|
||||
console.log('Memory set to: ' + value);
|
||||
|
||||
if (saveToMessage && context.chat.length) {
|
||||
const idx = context.chat.length - 2;
|
||||
@@ -315,40 +475,55 @@ function setMemoryContext(value, saveToMessage) {
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
jQuery(function () {
|
||||
function addExtensionControls() {
|
||||
const settingsHtml = `
|
||||
<div id="memory_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Summarize</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="memory_contents">Current summary: </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" />Stop summarization updates</label>
|
||||
</div>
|
||||
<!--</div>
|
||||
</div>
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Summarization parameters</b>
|
||||
<b>Summarize</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">Chat to Summarize buffer 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">Summary output 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">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">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">Length preference <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 class="inline-drawer-content">
|
||||
<label for="summary_source">Summarization source:</label>
|
||||
<select id="summary_source">
|
||||
<option value="main">Main API</option>
|
||||
<option value="extras">Extras API</option>
|
||||
</select>
|
||||
<label for="memory_contents">Current summary: </label>
|
||||
<textarea id="memory_contents" class="text_pole textarea_compact" rows="6" placeholder="Summary will be generated here..."></textarea>
|
||||
<div class="memory_contents_controls">
|
||||
<input id="memory_restore" class="menu_button" type="button" value="Restore previous state" />
|
||||
<label for="memory_frozen"><input id="memory_frozen" type="checkbox" />Pause summarization</label>
|
||||
</div>
|
||||
<div data-source="main" class="memory_contents_controls">
|
||||
</div>
|
||||
<div data-source="main">
|
||||
<label for="memory_prompt" class="title_restorable">
|
||||
Summarization Prompt
|
||||
<div id="memory_force_summarize" class="menu_button menu_button_icon">
|
||||
<i class="fa-solid fa-database"></i>
|
||||
<span>Generate now</span>
|
||||
</div>
|
||||
</label>
|
||||
<textarea id="memory_prompt" class="text_pole textarea_compact" rows="6" placeholder="This prompt will be used in summary generation. Insert {{words}} macro to use the "Number of words" parameter."></textarea>
|
||||
<label for="memory_prompt_words">Number of words in the summary (<span id="memory_prompt_words_value"></span> words)</label>
|
||||
<input id="memory_prompt_words" type="range" value="${defaultSettings.promptWords}" min="${defaultSettings.promptMinWords}" max="${defaultSettings.promptMaxWords}" step="${defaultSettings.promptWordsStep}" />
|
||||
<label for="memory_prompt_interval">Update interval (<span id="memory_prompt_interval_value"></span> messages)</label>
|
||||
<input id="memory_prompt_interval" type="range" value="${defaultSettings.promptInterval}" min="${defaultSettings.promptMinInterval}" max="${defaultSettings.promptMaxInterval}" step="${defaultSettings.promptIntervalStep}" />
|
||||
</div>
|
||||
<div data-source="extras">
|
||||
<label for="memory_short_length">Chat to Summarize buffer 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">Summary output 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">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">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">Length preference <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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -362,10 +537,18 @@ $(document).ready(function () {
|
||||
$('#memory_temperature').on('input', onMemoryTemperatureInput);
|
||||
$('#memory_length_penalty').on('input', onMemoryLengthPenaltyInput);
|
||||
$('#memory_frozen').on('input', onMemoryFrozenInput);
|
||||
$('#summary_source').on('change', onSummarySourceChange);
|
||||
$('#memory_prompt_words').on('input', onMemoryPromptWordsInput);
|
||||
$('#memory_prompt_interval').on('input', onMemoryPromptIntervalInput);
|
||||
$('#memory_prompt').on('input', onMemoryPromptInput);
|
||||
$('#memory_force_summarize').on('click', forceSummarizeChat);
|
||||
}
|
||||
|
||||
addExtensionControls();
|
||||
loadSettings();
|
||||
const wrapper = new ModuleWorkerWrapper(moduleWorker);
|
||||
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL);
|
||||
eventSource.on(event_types.MESSAGE_RECEIVED, onChatEvent);
|
||||
eventSource.on(event_types.MESSAGE_DELETED, onChatEvent);
|
||||
eventSource.on(event_types.MESSAGE_EDITED, onChatEvent);
|
||||
eventSource.on(event_types.MESSAGE_SWIPED, onChatEvent);
|
||||
eventSource.on(event_types.CHAT_CHANGED, onChatEvent);
|
||||
});
|
||||
|
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"display_name": "Memory",
|
||||
"loading_order": 9,
|
||||
"requires": [
|
||||
"requires": [],
|
||||
"optional": [
|
||||
"summarize"
|
||||
],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
|
@@ -8,17 +8,9 @@ const MODULE_NAME = 'quick-reply';
|
||||
const UPDATE_INTERVAL = 1000;
|
||||
|
||||
const defaultSettings = {
|
||||
quickReply1Mes: '',
|
||||
quickReply1Label: '',
|
||||
quickReply2Mes: '',
|
||||
quickReply2Label: '',
|
||||
quickReply3Mes: '',
|
||||
quickReply3Label: '',
|
||||
quickReply4Mes: '',
|
||||
quickReply4Label: '',
|
||||
quickReply5Mes: '',
|
||||
quickReply5Label: '',
|
||||
quickReplyEnabled: false,
|
||||
numberOfSlots: 5,
|
||||
quickReplySlots: [],
|
||||
}
|
||||
|
||||
async function loadSettings() {
|
||||
@@ -26,33 +18,44 @@ async function loadSettings() {
|
||||
Object.assign(extension_settings.quickReply, defaultSettings);
|
||||
}
|
||||
|
||||
// If the user has an old version of the extension, update it
|
||||
if (!Array.isArray(extension_settings.quickReply.quickReplySlots)) {
|
||||
extension_settings.quickReply.quickReplySlots = [];
|
||||
extension_settings.quickReply.numberOfSlots = defaultSettings.numberOfSlots;
|
||||
|
||||
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
|
||||
extension_settings.quickReply.quickReplySlots.push({
|
||||
mes: extension_settings.quickReply[`quickReply${i}Mes`],
|
||||
label: extension_settings.quickReply[`quickReply${i}Label`],
|
||||
enabled: true,
|
||||
});
|
||||
|
||||
delete extension_settings.quickReply[`quickReply${i}Mes`];
|
||||
delete extension_settings.quickReply[`quickReply${i}Label`];
|
||||
}
|
||||
}
|
||||
|
||||
initializeEmptySlots(extension_settings.quickReply.numberOfSlots);
|
||||
generateQuickReplyElements();
|
||||
|
||||
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
|
||||
$(`#quickReply${i}Mes`).val(extension_settings.quickReply.quickReplySlots[i - 1]?.mes).trigger('input');
|
||||
$(`#quickReply${i}Label`).val(extension_settings.quickReply.quickReplySlots[i - 1]?.label).trigger('input');
|
||||
}
|
||||
|
||||
$('#quickReplyEnabled').prop('checked', extension_settings.quickReply.quickReplyEnabled);
|
||||
|
||||
$('#quickReply1Mes').val(extension_settings.quickReply.quickReply1Mes).trigger('input');
|
||||
$('#quickReply1Label').val(extension_settings.quickReply.quickReply1Label).trigger('input');
|
||||
|
||||
$('#quickReply2Mes').val(extension_settings.quickReply.quickReply2Mes).trigger('input');
|
||||
$('#quickReply2Label').val(extension_settings.quickReply.quickReply2Label).trigger('input');
|
||||
|
||||
$('#quickReply3Mes').val(extension_settings.quickReply.quickReply3Mes).trigger('input');
|
||||
$('#quickReply3Label').val(extension_settings.quickReply.quickReply3Label).trigger('input');
|
||||
|
||||
$('#quickReply4Mes').val(extension_settings.quickReply.quickReply4Mes).trigger('input');
|
||||
$('#quickReply4Label').val(extension_settings.quickReply.quickReply4Label).trigger('input');
|
||||
|
||||
$('#quickReply5Mes').val(extension_settings.quickReply.quickReply5Mes).trigger('input');
|
||||
$('#quickReply5Label').val(extension_settings.quickReply.quickReply5Label).trigger('input');
|
||||
$('#quickReplyNumberOfSlots').val(extension_settings.quickReply.numberOfSlots);
|
||||
}
|
||||
|
||||
function onQuickReplyInput(id) {
|
||||
extension_settings.quickReply[`quickReply${id}Mes`] = $(`#quickReply${id}Mes`).val();
|
||||
extension_settings.quickReply.quickReplySlots[id - 1].mes = $(`#quickReply${id}Mes`).val();
|
||||
$(`#quickReply${id}`).attr('title', ($(`#quickReply${id}Mes`).val()));
|
||||
resetScrollHeight($(`#quickReply${id}Mes`));
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function onQuickReplyLabelInput(id) {
|
||||
extension_settings.quickReply[`quickReply${id}Label`] = $(`#quickReply${id}Label`).val();
|
||||
extension_settings.quickReply.quickReplySlots[id - 1].label = $(`#quickReply${id}Label`).val();
|
||||
$(`#quickReply${id}`).text($(`#quickReply${id}Label`).val());
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
@@ -66,44 +69,115 @@ async function onQuickReplyEnabledInput() {
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
async function sendQuickReply(id) {
|
||||
var prompt = extension_settings.quickReply[`${id}Mes`];
|
||||
async function sendQuickReply(index) {
|
||||
const prompt = extension_settings.quickReply.quickReplySlots[index]?.mes || '';
|
||||
|
||||
if (!prompt) {
|
||||
console.warn(`Quick reply slot ${index} is empty! Aborting.`);
|
||||
return;
|
||||
}
|
||||
|
||||
$("#send_textarea").val(prompt);
|
||||
$("#send_but").trigger('click');
|
||||
}
|
||||
|
||||
function addQuickReplyBar(numButtons) {
|
||||
var numButtons = 5;
|
||||
const quickReplyBarStartHtml = `
|
||||
<div id="quickReplyBar" class="flex-container flexGap5">
|
||||
<div id="quickReplies">
|
||||
`;
|
||||
function addQuickReplyBar() {
|
||||
$('#quickReplyBar').remove();
|
||||
let quickReplyButtonHtml = '';
|
||||
for (let i = 0; i < numButtons; i++) {
|
||||
let quickReplyMes = extension_settings.quickReply[`quickReply${i + 1}Mes`];
|
||||
let quickReplyLabel = extension_settings.quickReply[`quickReply${i + 1}Label`];
|
||||
//console.log(quickReplyMes);
|
||||
quickReplyButtonHtml += `<div title="${quickReplyMes}" class="quickReplyButton" id="quickReply${i + 1}">${quickReplyLabel}</div>`;
|
||||
|
||||
for (let i = 0; i < extension_settings.quickReply.numberOfSlots; i++) {
|
||||
let quickReplyMes = extension_settings.quickReply.quickReplySlots[i]?.mes || '';
|
||||
let quickReplyLabel = extension_settings.quickReply.quickReplySlots[i]?.label || '';
|
||||
quickReplyButtonHtml += `<div title="${quickReplyMes}" class="quickReplyButton" data-index="${i}" id="quickReply${i + 1}">${quickReplyLabel}</div>`;
|
||||
}
|
||||
const quickReplyEndHtml = `</div></div>`
|
||||
const quickReplyBarFullHtml = [quickReplyBarStartHtml, quickReplyButtonHtml, quickReplyEndHtml].join('');
|
||||
|
||||
const quickReplyBarFullHtml = `
|
||||
<div id="quickReplyBar" class="flex-container flexGap5">
|
||||
<div id="quickReplies">
|
||||
${quickReplyButtonHtml}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$('#send_form').prepend(quickReplyBarFullHtml);
|
||||
|
||||
$('.quickReplyButton').on('click', function () {
|
||||
console.log('got quick reply click');
|
||||
let quickReplyButtonID = $(this).attr('id');
|
||||
sendQuickReply(quickReplyButtonID);
|
||||
let index = $(this).data('index');
|
||||
sendQuickReply(index);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async function moduleWorker() {
|
||||
if (extension_settings.quickReply.quickReplyEnabled === true) {
|
||||
$('#quickReplyBar').toggle(getContext().onlineStatus !== 'no_connection');
|
||||
}
|
||||
}
|
||||
|
||||
async function onQuickReplyNumberOfSlotsInput() {
|
||||
const $input = $('#quickReplyNumberOfSlots');
|
||||
let numberOfSlots = Number($input.val());
|
||||
|
||||
if (isNaN(numberOfSlots)) {
|
||||
numberOfSlots = defaultSettings.numberOfSlots;
|
||||
}
|
||||
|
||||
// Clamp min and max values (from input attributes)
|
||||
if (numberOfSlots < Number($input.attr('min'))) {
|
||||
numberOfSlots = Number($input.attr('min'));
|
||||
} else if (numberOfSlots > Number($input.attr('max'))) {
|
||||
numberOfSlots = Number($input.attr('max'));
|
||||
}
|
||||
|
||||
extension_settings.quickReply.numberOfSlots = numberOfSlots;
|
||||
extension_settings.quickReply.quickReplySlots.length = numberOfSlots;
|
||||
|
||||
// Initialize new slots
|
||||
initializeEmptySlots(numberOfSlots);
|
||||
|
||||
await loadSettings();
|
||||
addQuickReplyBar();
|
||||
moduleWorker();
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function initializeEmptySlots(numberOfSlots) {
|
||||
for (let i = 0; i < numberOfSlots; i++) {
|
||||
if (!extension_settings.quickReply.quickReplySlots[i]) {
|
||||
extension_settings.quickReply.quickReplySlots[i] = {
|
||||
mes: '',
|
||||
label: '',
|
||||
enabled: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateQuickReplyElements() {
|
||||
let quickReplyHtml = '';
|
||||
|
||||
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
|
||||
quickReplyHtml += `
|
||||
<div class="flex-container alignitemsflexstart">
|
||||
<input class="text_pole wide30p" id="quickReply${i}Label" placeholder="(Add a button label)">
|
||||
<textarea id="quickReply${i}Mes" placeholder="(custom message here)" class="text_pole widthUnset flex1" rows="2"></textarea>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
$('#quickReplyContainer').empty().append(quickReplyHtml);
|
||||
|
||||
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
|
||||
$(`#quickReply${i}Mes`).on('input', function () { onQuickReplyInput(i); });
|
||||
$(`#quickReply${i}Label`).on('input', function () { onQuickReplyLabelInput(i); });
|
||||
}
|
||||
|
||||
$('.quickReplySettings .inline-drawer-toggle').off('click').on('click', function () {
|
||||
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
|
||||
initScrollHeight($(`#quickReply${i}Mes`));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
jQuery(async () => {
|
||||
|
||||
moduleWorker();
|
||||
@@ -116,57 +190,28 @@ jQuery(async () => {
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label class="checkbox_label">
|
||||
<label class="checkbox_label marginBot10">
|
||||
<input id="quickReplyEnabled" type="checkbox" />
|
||||
Enable Quick Replies
|
||||
</label>
|
||||
<label for="quickReplyNumberOfSlots">Number of slots:</label>
|
||||
<div class="flex-container flexGap5 flexnowrap">
|
||||
<input id="quickReplyNumberOfSlots" class="text_pole" type="number" min="1" max="100" value="" />
|
||||
<div class="menu_button menu_button_icon" id="quickReplyNumberOfSlotsApply">
|
||||
<div class="fa-solid fa-check"></div>
|
||||
<span>Apply</span>
|
||||
</div>
|
||||
</div>
|
||||
<small><i>Customize your Quick Replies:</i></small><br>
|
||||
<div class="flex-container alignitemsflexstart">
|
||||
<input class="text_pole wide30p" id="quickReply1Label" placeholder="(Add a button label)">
|
||||
<textarea id="quickReply1Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
|
||||
</div>
|
||||
<div class="flex-container alignitemsflexstart">
|
||||
<input class="text_pole wide30p" id="quickReply2Label" placeholder="(Add a button label)">
|
||||
<textarea id="quickReply2Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
|
||||
</div>
|
||||
<div class="flex-container alignitemsflexstart">
|
||||
<input class="text_pole wide30p" id="quickReply3Label" placeholder="(Add a button label)">
|
||||
<textarea id="quickReply3Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
|
||||
</div>
|
||||
<div class="flex-container alignitemsflexstart">
|
||||
<input class="text_pole wide30p" id="quickReply4Label" placeholder="(Add a button label)">
|
||||
<textarea id="quickReply4Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
|
||||
</div>
|
||||
<div class="flex-container alignitemsflexstart">
|
||||
<input class="text_pole wide30p" id="quickReply5Label" placeholder="(Add a button label)">
|
||||
<textarea id="quickReply5Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
|
||||
<div id="quickReplyContainer">
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
$('#extensions_settings2').append(settingsHtml);
|
||||
|
||||
$('#quickReply1Mes').on('input', function () { onQuickReplyInput(1); });
|
||||
$('#quickReply2Mes').on('input', function () { onQuickReplyInput(2); });
|
||||
$('#quickReply3Mes').on('input', function () { onQuickReplyInput(3); });
|
||||
$('#quickReply4Mes').on('input', function () { onQuickReplyInput(4); });
|
||||
$('#quickReply5Mes').on('input', function () { onQuickReplyInput(5); });
|
||||
|
||||
$('#quickReply1Label').on('input', function () { onQuickReplyLabelInput(1); });
|
||||
$('#quickReply2Label').on('input', function () { onQuickReplyLabelInput(2); });
|
||||
$('#quickReply3Label').on('input', function () { onQuickReplyLabelInput(3); });
|
||||
$('#quickReply4Label').on('input', function () { onQuickReplyLabelInput(4); });
|
||||
$('#quickReply5Label').on('input', function () { onQuickReplyLabelInput(5); });
|
||||
|
||||
$('#quickReplyEnabled').on('input', onQuickReplyEnabledInput);
|
||||
|
||||
$('.quickReplySettings .inline-drawer-toggle').on('click', function () {
|
||||
initScrollHeight($("#quickReply1Mes"));
|
||||
initScrollHeight($("#quickReply2Mes"));
|
||||
initScrollHeight($("#quickReply3Mes"));
|
||||
initScrollHeight($("#quickReply4Mes"));
|
||||
initScrollHeight($("#quickReply5Mes"));
|
||||
})
|
||||
$('#quickReplyNumberOfSlotsApply').on('click', onQuickReplyNumberOfSlotsInput);
|
||||
|
||||
await loadSettings();
|
||||
addQuickReplyBar();
|
||||
|
@@ -10,6 +10,8 @@
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
display: none;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#quickReplies {
|
||||
@@ -17,7 +19,7 @@
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -41,4 +43,4 @@
|
||||
opacity: 1;
|
||||
filter: brightness(1.2);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
152
public/scripts/extensions/randomize/index.js
Normal file
152
public/scripts/extensions/randomize/index.js
Normal file
@@ -0,0 +1,152 @@
|
||||
import { saveSettingsDebounced } from "../../../script.js";
|
||||
import { extension_settings } from "../../extensions.js";
|
||||
|
||||
function toggleRandomizedSetting(buttonRef, forId) {
|
||||
if (extension_settings.randomizer.controls.indexOf(forId) === -1) {
|
||||
extension_settings.randomizer.controls.push(forId);
|
||||
} else {
|
||||
extension_settings.randomizer.controls = extension_settings.randomizer.controls.filter(x => x !== forId);
|
||||
}
|
||||
|
||||
buttonRef.toggleClass('active');
|
||||
console.debug('Randomizer controls:', extension_settings.randomizer.controls);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function addRandomizeButton() {
|
||||
const counterRef = $(this);
|
||||
const labelRef = $(this).find('div[data-for]');
|
||||
const isDisabled = counterRef.data('randomization-disabled');
|
||||
|
||||
if (labelRef.length === 0 || isDisabled == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
const forId = labelRef.data('for');
|
||||
const buttonRef = $('<div class="randomize_button menu_button fa-solid fa-shuffle"></div>');
|
||||
buttonRef.toggleClass('active', extension_settings.randomizer.controls.indexOf(forId) !== -1);
|
||||
buttonRef.hide();
|
||||
buttonRef.on('click', () => toggleRandomizedSetting(buttonRef, forId));
|
||||
counterRef.append(buttonRef);
|
||||
}
|
||||
|
||||
function onRandomizerEnabled() {
|
||||
extension_settings.randomizer.enabled = $(this).prop('checked');
|
||||
$('.randomize_button').toggle(extension_settings.randomizer.enabled);
|
||||
console.debug('Randomizer enabled:', extension_settings.randomizer.enabled);
|
||||
}
|
||||
|
||||
window['randomizerInterceptor'] = (function () {
|
||||
if (extension_settings.randomizer.enabled === false) {
|
||||
console.debug('Randomizer skipped: disabled.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (extension_settings.randomizer.fluctuation === 0 || extension_settings.randomizer.controls.length === 0) {
|
||||
console.debug('Randomizer skipped: nothing to do.');
|
||||
return;
|
||||
}
|
||||
|
||||
for (const control of extension_settings.randomizer.controls) {
|
||||
const controlRef = $('#' + control);
|
||||
|
||||
if (controlRef.length === 0) {
|
||||
console.debug(`Randomizer skipped: control ${control} not found.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!controlRef.is(':visible')) {
|
||||
console.debug(`Randomizer skipped: control ${control} is not visible.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
let previousValue = parseFloat(controlRef.data('previous-value'));
|
||||
let originalValue = parseFloat(controlRef.data('original-value'));
|
||||
let currentValue = parseFloat(controlRef.val());
|
||||
|
||||
let value;
|
||||
|
||||
// Initialize originalValue and previousValue if they are NaN
|
||||
if (isNaN(originalValue)) {
|
||||
originalValue = currentValue;
|
||||
controlRef.data('original-value', originalValue);
|
||||
}
|
||||
if (isNaN(previousValue)) {
|
||||
previousValue = currentValue;
|
||||
controlRef.data('previous-value', previousValue);
|
||||
}
|
||||
|
||||
// If the current value hasn't changed compared to the previous value, use the original value as a base for the calculation
|
||||
if (currentValue === previousValue) {
|
||||
console.debug(`Randomizer for ${control} reusing original value: ${originalValue}`);
|
||||
value = originalValue;
|
||||
} else {
|
||||
console.debug(`Randomizer for ${control} using current value: ${currentValue}`);
|
||||
value = currentValue;
|
||||
controlRef.data('previous-value', currentValue); // Update the previous value when using the current value
|
||||
controlRef.data('original-value', currentValue); // Update the original value when using the current value
|
||||
}
|
||||
|
||||
if (isNaN(value)) {
|
||||
console.debug('Randomizer skipped: NaN.');
|
||||
continue;
|
||||
}
|
||||
|
||||
const fluctuation = extension_settings.randomizer.fluctuation;
|
||||
const min = parseFloat(controlRef.attr('min'));
|
||||
const max = parseFloat(controlRef.attr('max'));
|
||||
const delta = (Math.random() * fluctuation * 2 - fluctuation) * value;
|
||||
const newValue = Math.min(Math.max(value + delta, min), max);
|
||||
console.debug(`Randomizer for ${control}: ${value} -> ${newValue} (delta: ${delta}, min: ${min}, max: ${max})`);
|
||||
controlRef.val(newValue).trigger('input');
|
||||
controlRef.data('previous-value', parseFloat(controlRef.val()));
|
||||
}
|
||||
});
|
||||
|
||||
jQuery(() => {
|
||||
const html = `
|
||||
<div class="randomizer_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Parameter Randomizer</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<label for="randomizer_enabled" class="checkbox_label">
|
||||
<input type="checkbox" id="randomizer_enabled" name="randomizer_enabled" >
|
||||
Enabled
|
||||
</label>
|
||||
<div class="range-block">
|
||||
<div class="range-block-title">
|
||||
Fluctuation (0-1)
|
||||
</div>
|
||||
<div class="range-block-range-and-counter">
|
||||
<div class="range-block-range-and-counter">
|
||||
<div class="range-block-range">
|
||||
<input type="range" id="randomizer_fluctuation" min="0" max="1" step="0.1">
|
||||
</div>
|
||||
<div class="range-block-counter">
|
||||
<div contenteditable="true" data-for="randomizer_fluctuation" id="randomizer_fluctuation_counter">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
$('#extensions_settings').append(html);
|
||||
$('#ai_response_configuration .range-block-counter').each(addRandomizeButton);
|
||||
$('#randomizer_enabled').on('input', onRandomizerEnabled);
|
||||
$('#randomizer_enabled').prop('checked', extension_settings.randomizer.enabled).trigger('input');
|
||||
$('#randomizer_fluctuation').val(extension_settings.randomizer.fluctuation).trigger('input');
|
||||
$('#randomizer_fluctuation_counter').text(extension_settings.randomizer.fluctuation);
|
||||
$('#randomizer_fluctuation').on('input', function () {
|
||||
const value = parseFloat($(this).val());
|
||||
$('#randomizer_fluctuation_counter').text(value);
|
||||
extension_settings.randomizer.fluctuation = value;
|
||||
console.debug('Randomizer fluctuation:', extension_settings.randomizer.fluctuation);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
});
|
12
public/scripts/extensions/randomize/manifest.json
Normal file
12
public/scripts/extensions/randomize/manifest.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"display_name": "Parameter Randomizer",
|
||||
"loading_order": 15,
|
||||
"requires": [],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"version": "1.0.0",
|
||||
"generate_interceptor": "randomizerInterceptor",
|
||||
"homePage": "https://github.com/SillyTavern/SillyTavern"
|
||||
}
|
0
public/scripts/extensions/randomize/style.css
Normal file
0
public/scripts/extensions/randomize/style.css
Normal file
17
public/scripts/extensions/regex/dropdown.html
Normal file
17
public/scripts/extensions/regex/dropdown.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<div class="regex_settings">
|
||||
<div class="inline-drawer">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b>Regex</b>
|
||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<div id="open_regex_editor" class="menu_button">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
<span>Open Editor</span>
|
||||
</div>
|
||||
<hr />
|
||||
<label>Saved Scripts</label>
|
||||
<div id="saved_regex_scripts" class="flex-container regex-script-container flexFlowColumn"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
107
public/scripts/extensions/regex/editor.html
Normal file
107
public/scripts/extensions/regex/editor.html
Normal file
@@ -0,0 +1,107 @@
|
||||
<div id="regex_editor_template">
|
||||
<div class="regex_editor">
|
||||
<h3><strong data-i18n="Regex Editor">Regex Editor</strong>
|
||||
<a href="https://regexr.com/" class="notes-link" target="_blank">
|
||||
<span class="note-link-span">?</span>
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<small class="flex-container extensions_info">
|
||||
Regex is a tool to find/replace strings using regular expressions. If you want to learn more, click on the ? next to the title.
|
||||
</small>
|
||||
<hr />
|
||||
|
||||
<div class="flex-container flexFlowColumn">
|
||||
<div class="flex1">
|
||||
<label for="regex_script_name" class="title_restorable">
|
||||
<small data-i18n="Script Name">Script Name</small>
|
||||
</label>
|
||||
<div>
|
||||
<input class="regex_script_name text_pole textarea_compact" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex1">
|
||||
<label for="find_regex" class="title_restorable">
|
||||
<small data-i18n="Find Regex">Find Regex</small>
|
||||
</label>
|
||||
<div>
|
||||
<input class="find_regex text_pole textarea_compact" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex1">
|
||||
<label for="regex_replace_string" class="title_restorable">
|
||||
<small data-i18n="Replace With">Replace With</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea
|
||||
class="regex_replace_string text_pole wide100p textarea_compact"
|
||||
placeholder="Use {{match}} to include the matched text from the Find Regex"
|
||||
rows="2"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex1">
|
||||
<label for="regex_trim_strings" class="title_restorable">
|
||||
<small data-i18n="Trim Out">Trim Out</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea
|
||||
class="regex_trim_strings text_pole wide100p textarea_compact"
|
||||
placeholder="Globally trims any unwanted parts from a regex match before replacement. Separate each element by an enter."
|
||||
rows="3"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-container">
|
||||
<div class="wi-enter-footer-text flex-container flexFlowColumn flexNoGap alignitemsstart">
|
||||
<small>Affects</small>
|
||||
<div>
|
||||
<label class="checkbox flex-container">
|
||||
<input type="checkbox" name="replace_position" value="1">
|
||||
<span data-i18n="Before Char">User Input</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label class="checkbox flex-container">
|
||||
<input type="checkbox" name="replace_position" value="2">
|
||||
<span data-i18n="After Char">AI Output</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label class="checkbox flex-container">
|
||||
<input type="checkbox" name="replace_position" value="3">
|
||||
<span data-i18n="Slash Commands">Slash Commands</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wi-enter-footer-text flex-container flexFlowColumn flexNoGap alignitemsstart">
|
||||
<small>Other Options</small>
|
||||
<label class="checkbox flex-container">
|
||||
<input type="checkbox" name="disabled" />
|
||||
<span data-i18n="Disabled">Disabled</span>
|
||||
</label>
|
||||
<label class="checkbox flex-container">
|
||||
<input type="checkbox" name="only_format_display" />
|
||||
<span data-i18n="Only Format Display">Only Format Display</span>
|
||||
</label>
|
||||
<label class="checkbox flex-container">
|
||||
<input type="checkbox" name="run_on_edit" />
|
||||
<span data-i18n="Run On Edit">Run On Edit</span>
|
||||
</label>
|
||||
<label class="checkbox flex-container">
|
||||
<input type="checkbox" name="substitute_regex" />
|
||||
<span data-i18n="Substitute Regex">Substitute Regex</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex-container flexFlowColumn alignitemsstart">
|
||||
<small>Replacement Strategy</small>
|
||||
<select name="replace_strategy_select" class="margin0">
|
||||
<option value="0">Replace</option>
|
||||
<option value="1">Overlay</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
194
public/scripts/extensions/regex/engine.js
Normal file
194
public/scripts/extensions/regex/engine.js
Normal file
@@ -0,0 +1,194 @@
|
||||
import { substituteParams } from "../../../script.js";
|
||||
import { extension_settings } from "../../extensions.js";
|
||||
export {
|
||||
regex_placement,
|
||||
getRegexedString,
|
||||
runRegexScript
|
||||
}
|
||||
|
||||
const regex_placement = {
|
||||
// MD Display is deprecated. Do not use.
|
||||
MD_DISPLAY: 0,
|
||||
USER_INPUT: 1,
|
||||
AI_OUTPUT: 2,
|
||||
SLASH_COMMAND: 3
|
||||
}
|
||||
|
||||
const regex_replace_strategy = {
|
||||
REPLACE: 0,
|
||||
OVERLAY: 1
|
||||
}
|
||||
|
||||
// Originally from: https://github.com/IonicaBizau/regex-parser.js/blob/master/lib/index.js
|
||||
function regexFromString(input) {
|
||||
try {
|
||||
// Parse input
|
||||
var m = input.match(/(\/?)(.+)\1([a-z]*)/i);
|
||||
|
||||
// Invalid flags
|
||||
if (m[3] && !/^(?!.*?(.).*?\1)[gmixXsuUAJ]+$/.test(m[3])) {
|
||||
return RegExp(input);
|
||||
}
|
||||
|
||||
// Create the regular expression
|
||||
return new RegExp(m[2], m[3]);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Parent function to fetch a regexed version of a raw string
|
||||
function getRegexedString(rawString, placement, { characterOverride, isMarkdown } = {}) {
|
||||
let finalString = rawString;
|
||||
if (extension_settings.disabledExtensions.includes("regex") || !rawString || placement === undefined) {
|
||||
return finalString;
|
||||
}
|
||||
|
||||
extension_settings.regex.forEach((script) => {
|
||||
if ((script.markdownOnly && !isMarkdown) || (!script.markdownOnly && isMarkdown)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (script.placement.includes(placement)) {
|
||||
finalString = runRegexScript(script, finalString, { characterOverride });
|
||||
}
|
||||
});
|
||||
|
||||
return finalString;
|
||||
}
|
||||
|
||||
// Runs the provided regex script on the given string
|
||||
function runRegexScript(regexScript, rawString, { characterOverride } = {}) {
|
||||
let newString = rawString;
|
||||
if (!regexScript || !!(regexScript.disabled) || !regexScript?.findRegex || !rawString) {
|
||||
return newString;
|
||||
}
|
||||
|
||||
let match;
|
||||
const findRegex = regexFromString(regexScript.substituteRegex ? substituteParams(regexScript.findRegex) : regexScript.findRegex);
|
||||
|
||||
// The user skill issued. Return with nothing.
|
||||
if (!findRegex) {
|
||||
return newString;
|
||||
}
|
||||
|
||||
while ((match = findRegex.exec(rawString)) !== null) {
|
||||
const fencedMatch = match[0];
|
||||
const capturedMatch = match[1];
|
||||
|
||||
let trimCapturedMatch;
|
||||
let trimFencedMatch;
|
||||
if (capturedMatch) {
|
||||
const tempTrimCapture = filterString(capturedMatch, regexScript.trimStrings, { characterOverride });
|
||||
trimFencedMatch = fencedMatch.replaceAll(capturedMatch, tempTrimCapture);
|
||||
trimCapturedMatch = tempTrimCapture;
|
||||
} else {
|
||||
trimFencedMatch = filterString(fencedMatch, regexScript.trimStrings, { characterOverride });
|
||||
}
|
||||
|
||||
// TODO: Use substrings for replacement. But not necessary at this time.
|
||||
// A substring is from match.index to match.index + match[0].length or fencedMatch.length
|
||||
const subReplaceString = substituteRegexParams(
|
||||
regexScript.replaceString,
|
||||
trimCapturedMatch ?? trimFencedMatch,
|
||||
{
|
||||
characterOverride,
|
||||
replaceStrategy: regexScript.replaceStrategy ?? regex_replace_strategy.REPLACE
|
||||
}
|
||||
);
|
||||
if (!newString) {
|
||||
newString = rawString.replace(fencedMatch, subReplaceString);
|
||||
} else {
|
||||
newString = newString.replace(fencedMatch, subReplaceString);
|
||||
}
|
||||
|
||||
// If the regex isn't global, break out of the loop
|
||||
if (!findRegex.flags.includes('g')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
// Filters anything to trim from the regex match
|
||||
function filterString(rawString, trimStrings, { characterOverride } = {}) {
|
||||
let finalString = rawString;
|
||||
trimStrings.forEach((trimString) => {
|
||||
const subTrimString = substituteParams(trimString, undefined, characterOverride);
|
||||
finalString = finalString.replaceAll(subTrimString, "");
|
||||
});
|
||||
|
||||
return finalString;
|
||||
}
|
||||
|
||||
// Substitutes regex-specific and normal parameters
|
||||
function substituteRegexParams(rawString, regexMatch, { characterOverride, replaceStrategy } = {}) {
|
||||
let finalString = rawString;
|
||||
finalString = substituteParams(finalString, undefined, characterOverride);
|
||||
|
||||
let overlaidMatch = regexMatch;
|
||||
// TODO: Maybe move the for loops into a separate function?
|
||||
if (replaceStrategy === regex_replace_strategy.OVERLAY) {
|
||||
const splitReplace = finalString.split("{{match}}");
|
||||
|
||||
// There's a prefix
|
||||
if (splitReplace[0]) {
|
||||
// Fetch the prefix
|
||||
const splicedPrefix = spliceSymbols(splitReplace[0], false);
|
||||
|
||||
// Sequentially remove all occurrences of prefix from start of split
|
||||
const splitMatch = overlaidMatch.split(splicedPrefix);
|
||||
let sliceNum = 0;
|
||||
for (let index = 0; index < splitMatch.length; index++) {
|
||||
if (splitMatch[index].length === 0) {
|
||||
sliceNum++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
overlaidMatch = splitMatch.slice(sliceNum, splitMatch.length).join(splicedPrefix);
|
||||
}
|
||||
|
||||
// There's a suffix
|
||||
if (splitReplace[1]) {
|
||||
// Fetch the suffix
|
||||
const splicedSuffix = spliceSymbols(splitReplace[1], true);
|
||||
|
||||
// Sequential removal of all suffix occurrences from end of split
|
||||
const splitMatch = overlaidMatch.split(splicedSuffix);
|
||||
let sliceNum = 0;
|
||||
for (let index = splitMatch.length - 1; index >= 0; index--) {
|
||||
if (splitMatch[index].length === 0) {
|
||||
sliceNum++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
overlaidMatch = splitMatch.slice(0, splitMatch.length - sliceNum).join(splicedSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
// Only one match is replaced. This is by design
|
||||
finalString = finalString.replace("{{match}}", overlaidMatch) || finalString.replace("{{match}}", regexMatch);
|
||||
|
||||
return finalString;
|
||||
}
|
||||
|
||||
// Splices common sentence symbols and whitespace from the beginning and end of a string
|
||||
// Using a for loop due to sequential ordering
|
||||
function spliceSymbols(rawString, isSuffix) {
|
||||
let offset = 0;
|
||||
|
||||
for (const ch of isSuffix ? rawString.split('').reverse() : rawString) {
|
||||
if (ch.match(/[^\w.,?'!]/)) {
|
||||
offset++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isSuffix ? rawString.substring(0, rawString.length - offset) : rawString.substring(offset);
|
||||
}
|
260
public/scripts/extensions/regex/index.js
Normal file
260
public/scripts/extensions/regex/index.js
Normal file
@@ -0,0 +1,260 @@
|
||||
import { callPopup, eventSource, event_types, getCurrentChatId, reloadCurrentChat, saveSettingsDebounced } from "../../../script.js";
|
||||
import { extension_settings } from "../../extensions.js";
|
||||
import { uuidv4, waitUntilCondition } from "../../utils.js";
|
||||
import { regex_placement } from "./engine.js";
|
||||
|
||||
async function saveRegexScript(regexScript, existingScriptIndex) {
|
||||
// If not editing
|
||||
if (existingScriptIndex === -1) {
|
||||
// Is the script name undefined?
|
||||
if (!regexScript.scriptName) {
|
||||
toastr.error(`Could not save regex script: The script name was undefined or empty!`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Does the script name already exist?
|
||||
if (extension_settings.regex.find((e) => e.scriptName === regexScript.scriptName)) {
|
||||
toastr.error(`Could not save regex script: A script with name ${regexScript.scriptName} already exists.`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Does the script name already exist somewhere else?
|
||||
// (If this fails, make it a .filter().map() to index array)
|
||||
const foundIndex = extension_settings.regex.findIndex((e) => e.scriptName === regexScript.scriptName);
|
||||
if (foundIndex !== existingScriptIndex && foundIndex !== -1) {
|
||||
toastr.error(`Could not save regex script: A script with name ${regexScript.scriptName} already exists.`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Is a find regex present?
|
||||
if (regexScript.findRegex.length === 0) {
|
||||
toastr.error(`Could not save regex script: A find regex is required!`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Is there someplace to place results?
|
||||
if (regexScript.placement.length === 0) {
|
||||
toastr.error(`Could not save regex script: One placement checkbox must be selected!`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (existingScriptIndex !== -1) {
|
||||
extension_settings.regex[existingScriptIndex] = regexScript;
|
||||
} else {
|
||||
extension_settings.regex.push(regexScript);
|
||||
}
|
||||
|
||||
saveSettingsDebounced();
|
||||
await loadRegexScripts();
|
||||
|
||||
// Reload the current chat to undo previous markdown
|
||||
const currentChatId = getCurrentChatId();
|
||||
if (currentChatId !== undefined && currentChatId !== null) {
|
||||
await reloadCurrentChat();
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteRegexScript({ existingId }) {
|
||||
let scriptName = $(`#${existingId}`).find('.regex_script_name').text();
|
||||
|
||||
const existingScriptIndex = extension_settings.regex.findIndex((script) => script.scriptName === scriptName);
|
||||
if (!existingScriptIndex || existingScriptIndex !== -1) {
|
||||
extension_settings.regex.splice(existingScriptIndex, 1);
|
||||
|
||||
saveSettingsDebounced();
|
||||
await loadRegexScripts();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadRegexScripts() {
|
||||
$("#saved_regex_scripts").empty();
|
||||
|
||||
const scriptTemplate = $(await $.get("scripts/extensions/regex/scriptTemplate.html"));
|
||||
|
||||
extension_settings.regex.forEach((script) => {
|
||||
// Have to clone here
|
||||
const scriptHtml = scriptTemplate.clone();
|
||||
scriptHtml.attr('id', uuidv4());
|
||||
scriptHtml.find('.regex_script_name').text(script.scriptName);
|
||||
scriptHtml.find('.edit_existing_regex').on('click', async function() {
|
||||
await onRegexEditorOpenClick(scriptHtml.attr("id"));
|
||||
});
|
||||
scriptHtml.find('.delete_regex').on('click', async function() {
|
||||
await deleteRegexScript({ existingId: scriptHtml.attr("id") });
|
||||
});
|
||||
|
||||
$("#saved_regex_scripts").append(scriptHtml);
|
||||
});
|
||||
}
|
||||
|
||||
async function onRegexEditorOpenClick(existingId) {
|
||||
const editorHtml = $(await $.get("scripts/extensions/regex/editor.html"));
|
||||
|
||||
// If an ID exists, fill in all the values
|
||||
let existingScriptIndex = -1;
|
||||
if (existingId) {
|
||||
const existingScriptName = $(`#${existingId}`).find('.regex_script_name').text();
|
||||
existingScriptIndex = extension_settings.regex.findIndex((script) => script.scriptName === existingScriptName);
|
||||
if (existingScriptIndex !== -1) {
|
||||
const existingScript = extension_settings.regex[existingScriptIndex];
|
||||
if (existingScript.scriptName) {
|
||||
editorHtml.find(`.regex_script_name`).val(existingScript.scriptName);
|
||||
} else {
|
||||
toastr.error("This script doesn't have a name! Please delete it.")
|
||||
return;
|
||||
}
|
||||
|
||||
editorHtml.find(`.find_regex`).val(existingScript.findRegex || "");
|
||||
editorHtml.find(`.regex_replace_string`).val(existingScript.replaceString || "");
|
||||
editorHtml.find(`.regex_trim_strings`).val(existingScript.trimStrings?.join("\n") || []);
|
||||
editorHtml
|
||||
.find(`input[name="disabled"]`)
|
||||
.prop("checked", existingScript.disabled ?? false);
|
||||
editorHtml
|
||||
.find(`input[name="only_format_display"]`)
|
||||
.prop("checked", existingScript.markdownOnly ?? false);
|
||||
editorHtml
|
||||
.find(`input[name="run_on_edit"]`)
|
||||
.prop("checked", existingScript.runOnEdit ?? false);
|
||||
editorHtml
|
||||
.find(`input[name="substitute_regex"]`)
|
||||
.prop("checked", existingScript.substituteRegex ?? false);
|
||||
editorHtml
|
||||
.find(`select[name="replace_strategy_select"]`)
|
||||
.val(existingScript.replaceStrategy ?? 0);
|
||||
|
||||
existingScript.placement.forEach((element) => {
|
||||
editorHtml
|
||||
.find(`input[name="replace_position"][value="${element}"]`)
|
||||
.prop("checked", true);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
editorHtml
|
||||
.find(`input[name="only_format_display"]`)
|
||||
.prop("checked", true);
|
||||
|
||||
editorHtml
|
||||
.find(`input[name="run_on_edit"]`)
|
||||
.prop("checked", true);
|
||||
|
||||
editorHtml
|
||||
.find(`input[name="replace_position"][value="0"]`)
|
||||
.prop("checked", true);
|
||||
}
|
||||
|
||||
const popupResult = await callPopup(editorHtml, "confirm", undefined, { okButton: "Save" });
|
||||
if (popupResult) {
|
||||
const newRegexScript = {
|
||||
scriptName: editorHtml.find(".regex_script_name").val(),
|
||||
findRegex: editorHtml.find(".find_regex").val(),
|
||||
replaceString: editorHtml.find(".regex_replace_string").val(),
|
||||
trimStrings: editorHtml.find(".regex_trim_strings").val().split("\n").filter((e) => e.length !== 0) || [],
|
||||
placement:
|
||||
editorHtml
|
||||
.find(`input[name="replace_position"]`)
|
||||
.filter(":checked")
|
||||
.map(function() { return parseInt($(this).val()) })
|
||||
.get()
|
||||
.filter((e) => e !== NaN) || [],
|
||||
disabled:
|
||||
editorHtml
|
||||
.find(`input[name="disabled"]`)
|
||||
.prop("checked"),
|
||||
markdownOnly:
|
||||
editorHtml
|
||||
.find(`input[name="only_format_display"]`)
|
||||
.prop("checked"),
|
||||
runOnEdit:
|
||||
editorHtml
|
||||
.find(`input[name="run_on_edit"]`)
|
||||
.prop("checked"),
|
||||
substituteRegex:
|
||||
editorHtml
|
||||
.find(`input[name="substitute_regex"]`)
|
||||
.prop("checked"),
|
||||
replaceStrategy:
|
||||
parseInt(editorHtml
|
||||
.find(`select[name="replace_strategy_select"]`)
|
||||
.find(`:selected`)
|
||||
.val()) ?? 0
|
||||
};
|
||||
|
||||
saveRegexScript(newRegexScript, existingScriptIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Common settings migration function. Some parts will eventually be removed
|
||||
// TODO: Maybe migrate placement to strings?
|
||||
function migrateSettings() {
|
||||
let performSave = false;
|
||||
|
||||
// Current: If MD Display is present in placement, remove it and add new placements/MD option
|
||||
extension_settings.regex.forEach((script) => {
|
||||
if (script.placement.includes(regex_placement.MD_DISPLAY)) {
|
||||
script.placement = script.placement.length === 1 ?
|
||||
Object.values(regex_placement).filter((e) => e !== regex_placement.MD_DISPLAY) :
|
||||
script.placement = script.placement.filter((e) => e !== regex_placement.MD_DISPLAY);
|
||||
|
||||
script.markdownOnly = true
|
||||
|
||||
performSave = true;
|
||||
}
|
||||
|
||||
// Old system and sendas placement migration
|
||||
// 4 - sendAs
|
||||
if (script.placement.includes(4)) {
|
||||
script.placement = script.placement.length === 1 ?
|
||||
[regex_placement.SLASH_COMMAND] :
|
||||
script.placement = script.placement.filter((e) => e !== 4);
|
||||
|
||||
performSave = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (performSave) {
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for loading in sequence with other extensions
|
||||
// NOTE: Always puts extension at the top of the list, but this is fine since it's static
|
||||
jQuery(async () => {
|
||||
if (extension_settings.regex) {
|
||||
migrateSettings();
|
||||
}
|
||||
|
||||
// Manually disable the extension since static imports auto-import the JS file
|
||||
if (extension_settings.disabledExtensions.includes("regex")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const settingsHtml = await $.get("scripts/extensions/regex/dropdown.html");
|
||||
$("#extensions_settings2").append(settingsHtml);
|
||||
$("#open_regex_editor").on("click", function() {
|
||||
onRegexEditorOpenClick(false);
|
||||
});
|
||||
|
||||
$('#saved_regex_scripts').sortable({
|
||||
stop: function () {
|
||||
let newScripts = [];
|
||||
$('#saved_regex_scripts').children().each(function () {
|
||||
const scriptName = $(this).find(".regex_script_name").text();
|
||||
const existingScript = extension_settings.regex.find((e) => e.scriptName === scriptName);
|
||||
if (existingScript) {
|
||||
newScripts.push(existingScript);
|
||||
}
|
||||
});
|
||||
|
||||
extension_settings.regex = newScripts;
|
||||
saveSettingsDebounced();
|
||||
|
||||
console.debug("Regex scripts reordered");
|
||||
// TODO: Maybe reload regex scripts after move
|
||||
},
|
||||
});
|
||||
|
||||
await loadRegexScripts();
|
||||
$("#saved_regex_scripts").sortable("enable");
|
||||
});
|
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"display_name": "Author's Note (Located in Lower Left Options Menu)",
|
||||
"display_name": "Regex",
|
||||
"loading_order": 1,
|
||||
"requires": [],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
"author": "kingbri",
|
||||
"version": "1.0.0",
|
||||
"homePage": "https://github.com/SillyTavern/SillyTavern"
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user