mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Compare commits
1072 Commits
secrets-ma
...
1.12.13
Author | SHA1 | Date | |
---|---|---|---|
|
d8c8bfa8a4 | ||
|
1041d2ae9d | ||
|
a1586694b6 | ||
|
a7aa1ff79d | ||
|
0c7d5c76e2 | ||
|
aa94774963 | ||
|
628fc810c7 | ||
|
fb9b0569b6 | ||
|
dc4612a0e2 | ||
|
e57396040d | ||
|
bafb2cba95 | ||
|
f607c3bc0d | ||
|
0017358f8b | ||
|
0d2bf00810 | ||
|
f362f94c2d | ||
|
c9e716d42f | ||
|
bef466a5a1 | ||
|
f180d22680 | ||
|
18fa33d816 | ||
|
e60796548b | ||
|
0f5f8e163d | ||
|
95e60b0f79 | ||
|
669cd49574 | ||
|
9917be0233 | ||
|
7537192c9a | ||
|
eaa7b91f1d | ||
|
ea989df6a1 | ||
|
166b404ea7 | ||
|
25792b53f2 | ||
|
aad4b449ee | ||
|
5743972a26 | ||
|
be37b6ff8f | ||
|
cd0ca0363e | ||
|
fdcff7a7f0 | ||
|
d9c868b2fe | ||
|
15dbadbfe0 | ||
|
707efac5b9 | ||
|
972eea1efd | ||
|
a77f4045f8 | ||
|
cc3e08ddaa | ||
|
eb17e37002 | ||
|
ecaee2dbbf | ||
|
84e7ddbf74 | ||
|
4f7695b0ce | ||
|
5f726d2b25 | ||
|
e43b9a3d2c | ||
|
34363e6875 | ||
|
79a8080b7d | ||
|
92dacdb386 | ||
|
4fdc28afbc | ||
|
874affb2f2 | ||
|
37819df542 | ||
|
160f7431d6 | ||
|
12824bb680 | ||
|
6af3f2ee7e | ||
|
d7085b119d | ||
|
1b817cd897 | ||
|
e65b72ea41 | ||
|
c9c5dfa8c0 | ||
|
f11ebb032b | ||
|
58e714fce4 | ||
|
ddb77732f2 | ||
|
01ef823da9 | ||
|
1b02426df1 | ||
|
c4021525ac | ||
|
e7189a1260 | ||
|
843bd1cf3c | ||
|
fc151284e4 | ||
|
f6f87f6d5b | ||
|
7543a24ca7 | ||
|
89ab138882 | ||
|
0237b6a872 | ||
|
c22ad7c2e8 | ||
|
26c4d231a8 | ||
|
1026e1f8e9 | ||
|
d6dcededc9 | ||
|
ebe30dceac | ||
|
370bd9a3a8 | ||
|
137927bb43 | ||
|
90cfdebff8 | ||
|
0cde7e7a7f | ||
|
cf63b70997 | ||
|
ad225138b4 | ||
|
68b5be063f | ||
|
bdbe043259 | ||
|
57a229d5fd | ||
|
e23f3a6314 | ||
|
c722d251ff | ||
|
a104de38b6 | ||
|
26093c1ae4 | ||
|
c8fbd51554 | ||
|
bf75e88931 | ||
|
13a3f4772e | ||
|
a3b2cc456f | ||
|
1e6f8c6637 | ||
|
594cba30ca | ||
|
e3bcc79bb7 | ||
|
73230272f3 | ||
|
71a3aefe86 | ||
|
6024b29ea7 | ||
|
ee13cef37f | ||
|
67d013e40a | ||
|
64206d6f47 | ||
|
fc1c767280 | ||
|
d4f6373bbc | ||
|
fa03443fe7 | ||
|
0f8a17b652 | ||
|
070de9df2d | ||
|
34b2ef0fd7 | ||
|
eef9c3ef62 | ||
|
6f0f32d83d | ||
|
7845994315 | ||
|
d94c301b10 | ||
|
67699d9cfa | ||
|
a392593e53 | ||
|
cabd6de85b | ||
|
c03da65821 | ||
|
5d74507e50 | ||
|
19b7deaed0 | ||
|
6aaa533410 | ||
|
96d79ac4e9 | ||
|
b52b11d7bb | ||
|
1cb9287684 | ||
|
0ea64050ff | ||
|
d0068ecbab | ||
|
ca14352972 | ||
|
50a0f41736 | ||
|
7e3946c152 | ||
|
edabd1128b | ||
|
f38898e03f | ||
|
98f92f6270 | ||
|
5d275998ed | ||
|
c3b5382882 | ||
|
de0e65fe13 | ||
|
ff5835278b | ||
|
980ed76cc3 | ||
|
91fe2841e3 | ||
|
b813bcad8a | ||
|
0423cb7ad3 | ||
|
5ff4c457c0 | ||
|
c593c9fe2a | ||
|
e476063f32 | ||
|
95e0be7e9e | ||
|
a9c2af19e3 | ||
|
1a52314812 | ||
|
7de516e5e7 | ||
|
381956652b | ||
|
7fd0f3e2bf | ||
|
bcb2096020 | ||
|
fa699956e6 | ||
|
c9277cec28 | ||
|
e9cf606c70 | ||
|
50f1e3f0f2 | ||
|
4d81dfb085 | ||
|
8161690ce6 | ||
|
02a8c8c460 | ||
|
8565df13e4 | ||
|
35b72cc6e6 | ||
|
6b821409e0 | ||
|
fc94ed64c1 | ||
|
c36607be6f | ||
|
3b9fcfae60 | ||
|
2d2bf48d3d | ||
|
c167890d26 | ||
|
a09b9fa746 | ||
|
fb5f3e0f97 | ||
|
3cb24507a7 | ||
|
5398684ea2 | ||
|
d3263b0e0f | ||
|
06beaccdae | ||
|
17d2771a75 | ||
|
858b750346 | ||
|
f1b50caf1a | ||
|
782d866fcf | ||
|
49db89fef0 | ||
|
507ce78c27 | ||
|
28bad6479c | ||
|
13cfe1650f | ||
|
5d69189f8f | ||
|
c48ecc67b2 | ||
|
3d813e4ef6 | ||
|
8d608bcd72 | ||
|
73d4922d70 | ||
|
383806325a | ||
|
70f762c006 | ||
|
bdbddd4ed3 | ||
|
d14b5e51a9 | ||
|
28fc498ee6 | ||
|
5d255d758e | ||
|
7be6e0d5af | ||
|
7d568dd4e0 | ||
|
0088333ebf | ||
|
c9ebea1d0a | ||
|
59ee2e1302 | ||
|
074f54d995 | ||
|
155956f45b | ||
|
5ecfbf3933 | ||
|
b1acfec825 | ||
|
6e6d1b24eb | ||
|
6e15e4875d | ||
|
0a89d9ca6f | ||
|
810d954d12 | ||
|
64e1fd5f71 | ||
|
590ad6235b | ||
|
696a999238 | ||
|
7522fa2e79 | ||
|
ede9f242af | ||
|
3a2d29b5cb | ||
|
f1f7a14349 | ||
|
108d9fd74f | ||
|
4c242fefe8 | ||
|
55a295f827 | ||
|
a161118308 | ||
|
947a307b25 | ||
|
61132dd7b9 | ||
|
1d995fb92d | ||
|
8aa7ed8635 | ||
|
68db63b629 | ||
|
743f07167c | ||
|
b95dd04fbe | ||
|
afdf56ce68 | ||
|
0bedb6e0ff | ||
|
ccd6a1631a | ||
|
661b84033f | ||
|
45d8cac5a9 | ||
|
8271bf36c7 | ||
|
d788c2fbb5 | ||
|
8a750c6341 | ||
|
868e97804a | ||
|
63b95ef504 | ||
|
385ef46a2b | ||
|
7e8471f28f | ||
|
8fded75069 | ||
|
969156d819 | ||
|
639c0235f9 | ||
|
284bac9b49 | ||
|
af5e9aa518 | ||
|
e91387c60b | ||
|
b3eb6e071f | ||
|
40720971c5 | ||
|
abe55ec905 | ||
|
ea59dcc30e | ||
|
4f224550f6 | ||
|
12335f4860 | ||
|
b2ce76c84c | ||
|
b6af55134a | ||
|
1aae08be5b | ||
|
2461913f85 | ||
|
5555b3e7db | ||
|
76e45abfc6 | ||
|
50e49cd67b | ||
|
16b62d9fb3 | ||
|
14aec43064 | ||
|
76cb34fd06 | ||
|
83e75439ab | ||
|
f33464527b | ||
|
2df140a6a9 | ||
|
eac0d04fd3 | ||
|
73035c1d1c | ||
|
7c72c1d9f3 | ||
|
60e8ffbf90 | ||
|
50ad31f8e8 | ||
|
978b2cdb21 | ||
|
58fe54954a | ||
|
d286fff42c | ||
|
5c146bdd67 | ||
|
9c4bffc487 | ||
|
20b5c962db | ||
|
a8f05c92ae | ||
|
549fae4015 | ||
|
0bc4396427 | ||
|
ea643cce6e | ||
|
f11a834895 | ||
|
f43b42544b | ||
|
b98556855d | ||
|
94441c54ae | ||
|
c6a2b4e429 | ||
|
08e184de26 | ||
|
60448f4ce8 | ||
|
d5056a5563 | ||
|
ae51c39c09 | ||
|
6905fcd0a4 | ||
|
d3006cc720 | ||
|
73786610a6 | ||
|
aaf066699b | ||
|
e312ae6b3b | ||
|
d613e1ee77 | ||
|
c60af6659c | ||
|
02ab882e63 | ||
|
7c7de3d965 | ||
|
02cdec5a10 | ||
|
813ec537cd | ||
|
a20928b02c | ||
|
1ef04ffc4d | ||
|
68eecc77bb | ||
|
b64273ab94 | ||
|
e7fcd0072b | ||
|
6c0538854d | ||
|
cf14b75091 | ||
|
eab4e8aebc | ||
|
2a65688148 | ||
|
22d551be3a | ||
|
4e1cb1eba4 | ||
|
6947ca7433 | ||
|
12ef33bca4 | ||
|
2cfaa034fb | ||
|
e98172bb0e | ||
|
90be2eee71 | ||
|
4aa8672925 | ||
|
acd8b817f4 | ||
|
6541dcbc66 | ||
|
0274d800f9 | ||
|
cf792c8195 | ||
|
5af4217fda | ||
|
fec0e248c5 | ||
|
582b710d3c | ||
|
0776f65193 | ||
|
4edb069bd8 | ||
|
861c502e44 | ||
|
11d56a407d | ||
|
7b55d91d35 | ||
|
8b135f9ca3 | ||
|
422517ec93 | ||
|
5545a425ea | ||
|
eceaa9cacc | ||
|
7def85a174 | ||
|
5955327f7b | ||
|
d28f39d77a | ||
|
8bdc00e0b9 | ||
|
4ab54016ad | ||
|
f0c7ea062b | ||
|
7064ce81c7 | ||
|
20a982491a | ||
|
5f024823a9 | ||
|
092ef26144 | ||
|
19fba66d2c | ||
|
f2e47d9276 | ||
|
b8ebed0f4c | ||
|
db148d5142 | ||
|
c855cd2bf0 | ||
|
82b74628c6 | ||
|
68234cdcef | ||
|
e71427953b | ||
|
5dc8450559 | ||
|
01b0a84b70 | ||
|
e0d1b21006 | ||
|
d2df04550a | ||
|
10a72b8c80 | ||
|
7eff895e88 | ||
|
296037d1c8 | ||
|
ae666c9012 | ||
|
7fc26c1d53 | ||
|
7a54b0cad7 | ||
|
919df98c6e | ||
|
2faaabbf5f | ||
|
26c9c7e56b | ||
|
7249d4470a | ||
|
810bca46a0 | ||
|
e27e045054 | ||
|
76fa90ed9e | ||
|
5a22e64466 | ||
|
6df2dc11f7 | ||
|
8aadada0e2 | ||
|
7f9960fa7a | ||
|
e0f3a22b80 | ||
|
49d1a16a18 | ||
|
ac8c2799b8 | ||
|
ee6202c379 | ||
|
2194bdfd56 | ||
|
bb03c60c39 | ||
|
8f38298f90 | ||
|
9e7f485b65 | ||
|
4a9503c056 | ||
|
f37541d629 | ||
|
caf3a64a0f | ||
|
8bd4fd76ae | ||
|
252ae9f534 | ||
|
a73dfa7586 | ||
|
fb06e7afa1 | ||
|
3cf4be8e85 | ||
|
f2cac8e7f7 | ||
|
4802e4bed2 | ||
|
1a1afd00a1 | ||
|
e7d38d95d0 | ||
|
15769a7643 | ||
|
9b631ed048 | ||
|
7188060ac8 | ||
|
3e26b93971 | ||
|
159852233f | ||
|
a2ecb81378 | ||
|
b12cd9fe05 | ||
|
d21b0f1b5e | ||
|
42f850239f | ||
|
db988411fd | ||
|
3a25550f5b | ||
|
5c79c8e162 | ||
|
30f97e0e64 | ||
|
938c8a9a36 | ||
|
13f76c974e | ||
|
afbe21b6b4 | ||
|
d32adb8d1d | ||
|
6e5db5c41a | ||
|
a7d7b6fb0f | ||
|
1adde74f38 | ||
|
1ad3f3d6c7 | ||
|
0cc0d6763e | ||
|
e8cdad0bf2 | ||
|
b0a2f241d2 | ||
|
29c71fe8f1 | ||
|
f755c3d4cb | ||
|
9c3e8c935b | ||
|
bfc609c2a8 | ||
|
4c7ede67f3 | ||
|
b17fdcbfd9 | ||
|
db500188d8 | ||
|
aadae85a2a | ||
|
cb6adc30ce | ||
|
bdbcf8623e | ||
|
e35217e7e3 | ||
|
aca1cb7f99 | ||
|
07160e0e60 | ||
|
179153ae67 | ||
|
94f53835f4 | ||
|
ab4d296b22 | ||
|
8ad7b5dcc5 | ||
|
00bb36f764 | ||
|
73784642d2 | ||
|
2b28065c9f | ||
|
eb31d7baa2 | ||
|
3f03936125 | ||
|
3f5b63bba0 | ||
|
7571552fef | ||
|
f6fe5fea77 | ||
|
3574527780 | ||
|
2834681a4b | ||
|
7ea2c5f8cf | ||
|
19e2a2f7d2 | ||
|
a58e026a40 | ||
|
a40f568409 | ||
|
bad806312d | ||
|
3bb8b887e1 | ||
|
135bf8a55b | ||
|
3d8a897c19 | ||
|
bd6da695c8 | ||
|
531999dc04 | ||
|
58bbfc0d4e | ||
|
380bd4ef4b | ||
|
bb64e9b5c5 | ||
|
1ef5154770 | ||
|
57aa820dc3 | ||
|
c12f26441e | ||
|
e4269f5d1d | ||
|
947d4f215e | ||
|
826e4f6d16 | ||
|
0f46128980 | ||
|
1a4bcbb794 | ||
|
441e5c6f7e | ||
|
da3b620f74 | ||
|
fa4a75215b | ||
|
0cdc389794 | ||
|
434bdab585 | ||
|
ce67f3a658 | ||
|
277fc00f38 | ||
|
36a3a7d615 | ||
|
d15d49b295 | ||
|
87afb1633b | ||
|
e5e2c9fe49 | ||
|
580856064e | ||
|
1a5b1f77d7 | ||
|
f5d68f1cd9 | ||
|
2e77171137 | ||
|
ab27b29819 | ||
|
231068f729 | ||
|
7b65427236 | ||
|
9f21f7771c | ||
|
1c0ca414b9 | ||
|
4f0921856f | ||
|
994d69508b | ||
|
1ad3a2b968 | ||
|
cd2d6e85e0 | ||
|
058c86f3c1 | ||
|
a771dd5478 | ||
|
baa4632071 | ||
|
ebe877e6b6 | ||
|
1156b648eb | ||
|
ec49b19aff | ||
|
75aec77271 | ||
|
7348e0274d | ||
|
362470da18 | ||
|
4d323ec76f | ||
|
0039b48d1b | ||
|
050e65861c | ||
|
a434d217cc | ||
|
890d10d811 | ||
|
1723ce0f22 | ||
|
b3688087d5 | ||
|
bcea4248c4 | ||
|
9590127bae | ||
|
eb6a158781 | ||
|
cc369d25c5 | ||
|
59928d37ff | ||
|
1f41124844 | ||
|
3d492523e2 | ||
|
fc488bd4fe | ||
|
fd38ca503a | ||
|
9a15890745 | ||
|
37d9d4c253 | ||
|
bae02a44ed | ||
|
23f0b6ed09 | ||
|
c87e203b4a | ||
|
dd50f49176 | ||
|
c37c9051a6 | ||
|
8a4cf86b65 | ||
|
a2a15b9978 | ||
|
96d6a6df07 | ||
|
dbbf069e85 | ||
|
d276d23310 | ||
|
c98d241f3c | ||
|
961a71877b | ||
|
13e38c7c86 | ||
|
61e056004a | ||
|
b029ae98dc | ||
|
f5bfbce0ad | ||
|
a4c124dff0 | ||
|
2445b6d9dc | ||
|
ad8f0f564f | ||
|
c47d997a2d | ||
|
dd55b2770a | ||
|
83f74a5d22 | ||
|
09aaa9181c | ||
|
5477586ce4 | ||
|
76becb43ae | ||
|
b033b98532 | ||
|
412d638e9e | ||
|
6e0ed8552f | ||
|
dd7391caaf | ||
|
f101dd571f | ||
|
1a52d3c293 | ||
|
d6bf3439b4 | ||
|
54a9e0afee | ||
|
5de2f8ea2d | ||
|
93f3334ad0 | ||
|
25a2582d15 | ||
|
d076a210a1 | ||
|
b5fc7d6d4d | ||
|
a204325136 | ||
|
0decd4d1b6 | ||
|
34db46d84b | ||
|
c2377f0c13 | ||
|
829888bda7 | ||
|
43f524bb5f | ||
|
34d17a4fcb | ||
|
340c03cedf | ||
|
5085f6cdc9 | ||
|
798f8d92a3 | ||
|
d4061cc139 | ||
|
93b6612c75 | ||
|
48dfee39ae | ||
|
6c0ea67d3d | ||
|
58b8e7908d | ||
|
4e94e83540 | ||
|
d1018a824c | ||
|
4c8ae0afd3 | ||
|
d9b2311e17 | ||
|
21af0243d6 | ||
|
63e3816e92 | ||
|
d60609716b | ||
|
76bd2547e1 | ||
|
ee101353d8 | ||
|
d5bdf1cb90 | ||
|
c8b103a9e8 | ||
|
c3dd3e246e | ||
|
47b06b4978 | ||
|
ad845b5fbf | ||
|
c7958a4bb8 | ||
|
aee8441fc4 | ||
|
703e876f4a | ||
|
d4e77280fc | ||
|
31f19d0d8a | ||
|
32ec475ca2 | ||
|
e8d8cebd8e | ||
|
d48db9aded | ||
|
33fa5aaab8 | ||
|
c501673241 | ||
|
0792c17f55 | ||
|
9697322f1e | ||
|
d8eeab0c00 | ||
|
b2bd73fa78 | ||
|
6e4a51b37f | ||
|
8b4414b799 | ||
|
a2cfcd4ca6 | ||
|
0bf18e7413 | ||
|
5e540f4f97 | ||
|
f83dccda39 | ||
|
98ea463e0e | ||
|
d5959a4681 | ||
|
c886de5deb | ||
|
c8e05a34d6 | ||
|
d94ac48b65 | ||
|
5886bb6b3a | ||
|
8387431534 | ||
|
754a14ff3e | ||
|
ca7d2aeec3 | ||
|
28ba262087 | ||
|
23d2c40e05 | ||
|
4094887624 | ||
|
4492828b9f | ||
|
a2aef5ea4a | ||
|
cc401b2c9d | ||
|
95a31cdd98 | ||
|
d1ec9eb8ab | ||
|
0bcf8b5d21 | ||
|
f32938981c | ||
|
25d1db3852 | ||
|
9d3ad0d69d | ||
|
3ec3d71c5f | ||
|
79b8229b1b | ||
|
06303bb62f | ||
|
1acee3d4c9 | ||
|
b6d6727135 | ||
|
92a83ed01b | ||
|
f85e464ffd | ||
|
852ec86e26 | ||
|
72ae3aa33d | ||
|
d35bd3b073 | ||
|
b074f9fa89 | ||
|
ed46b96ba2 | ||
|
acf71fd702 | ||
|
5f564343ec | ||
|
dfb062af41 | ||
|
d9bb5e6b1f | ||
|
363d8a4121 | ||
|
d9fc76f336 | ||
|
e2c3af2114 | ||
|
7aa9b857c2 | ||
|
327f4b1074 | ||
|
4a58948b27 | ||
|
1f206c3a36 | ||
|
c9144cd824 | ||
|
dd2154c19b | ||
|
dade4eafa5 | ||
|
4f63b471d1 | ||
|
16bb9b3679 | ||
|
6ececb2ceb | ||
|
6edbb23903 | ||
|
50baaaae81 | ||
|
da531f12c2 | ||
|
ba0e852f20 | ||
|
d0ebac37c1 | ||
|
3f9af45493 | ||
|
fd3c427f07 | ||
|
524ecf8acd | ||
|
c4be4d7d61 | ||
|
89a16f2030 | ||
|
1dfc09e4d2 | ||
|
bfd57b66ef | ||
|
71e1fc91f1 | ||
|
14703846a7 | ||
|
5494e89fdb | ||
|
4ca55d3b9b | ||
|
5aa82eda2b | ||
|
d9f2ee0d48 | ||
|
ff83ae975d | ||
|
02130b848c | ||
|
900c0caffa | ||
|
4e74fd0467 | ||
|
6fe26f7f77 | ||
|
fb83a3ca3f | ||
|
14c3dae180 | ||
|
50869757d3 | ||
|
aecbc48d43 | ||
|
0c8a11e28b | ||
|
ffeb6b45aa | ||
|
76d1661768 | ||
|
a14e3b0657 | ||
|
2d335e27ff | ||
|
8fb95f9a84 | ||
|
a5399b6614 | ||
|
199be15f4b | ||
|
055a6527fc | ||
|
842b59605b | ||
|
3818290e4d | ||
|
c5dad20fc4 | ||
|
e5e931356b | ||
|
e7c799ae2a | ||
|
6deaa31d41 | ||
|
1f0aa29307 | ||
|
eeaec2697b | ||
|
630c7980d3 | ||
|
890c0c4723 | ||
|
9c31c21d79 | ||
|
1ea2134936 | ||
|
b35a746470 | ||
|
d26f99b496 | ||
|
a1abe14e02 | ||
|
ae9296f989 | ||
|
ea1d9e1d1a | ||
|
b8821acb95 | ||
|
c11e64a782 | ||
|
cc7355358d | ||
|
d2cc8b36b8 | ||
|
3fe3430006 | ||
|
fb2ee756dd | ||
|
25ffc4ac4a | ||
|
5c30244627 | ||
|
72e1dcb3f9 | ||
|
a2a6afb731 | ||
|
e59114c1c5 | ||
|
6180210170 | ||
|
2b98e96784 | ||
|
364078ce27 | ||
|
fda64ffb1f | ||
|
5257a45bde | ||
|
9a03aac224 | ||
|
f155cc7e92 | ||
|
cee7170763 | ||
|
a969d34c03 | ||
|
515a5f6943 | ||
|
47bb7ad6a1 | ||
|
7d937b36da | ||
|
9243a68b18 | ||
|
371208c24d | ||
|
26030f6ee4 | ||
|
5bd3d9a518 | ||
|
9710d88a88 | ||
|
a83e7318b0 | ||
|
ae376b4195 | ||
|
f7eab66026 | ||
|
9de142b9ad | ||
|
67a4d10b75 | ||
|
56c9b21a28 | ||
|
94af9fc1a3 | ||
|
4bf3bd8343 | ||
|
753a99faf9 | ||
|
9ecf261a76 | ||
|
dfc2eb32c8 | ||
|
2a904c4aea | ||
|
2a322faa6a | ||
|
e4dda3c488 | ||
|
07ef5122bb | ||
|
578c3dda73 | ||
|
0c121ee95a | ||
|
3a6d5faa8a | ||
|
44343e8ec9 | ||
|
198fbe1a1f | ||
|
2318df8b74 | ||
|
198d10e759 | ||
|
73393a5d5e | ||
|
cbeb7ddcec | ||
|
3d817352ec | ||
|
1df209c284 | ||
|
f9324c74cd | ||
|
80b29ed5cb | ||
|
4b2575f301 | ||
|
4e7326b61b | ||
|
e3f0a8d35b | ||
|
e5db40cf2d | ||
|
a1cacbe904 | ||
|
c32e0bdde7 | ||
|
7bc8087d02 | ||
|
91b2dc57fa | ||
|
7fc0ddb60c | ||
|
d0abba23dc | ||
|
15a3cfcb8a | ||
|
ee57675c12 | ||
|
249e2555d0 | ||
|
a6a7810be2 | ||
|
9e8fd3f5a0 | ||
|
cd05650164 | ||
|
d5f6ecf3c3 | ||
|
7f321c9cf6 | ||
|
4f456b2b80 | ||
|
6dde068e71 | ||
|
2aa1dd41f5 | ||
|
26feb448a3 | ||
|
0c9676e7fc | ||
|
bab8a09a80 | ||
|
b0e80137da | ||
|
2344d98e20 | ||
|
35e8561bff | ||
|
6081b9f0ce | ||
|
552a418bae | ||
|
0c9b301a57 | ||
|
3a8a329b0f | ||
|
63e7acb87b | ||
|
145136059e | ||
|
283ceb6bbf | ||
|
6348d1f19a | ||
|
d316d51c0b | ||
|
d616dfef38 | ||
|
84a8a2bc2b | ||
|
0fb9884ab8 | ||
|
0a413d63aa | ||
|
7063af7363 | ||
|
6fc342d446 | ||
|
3d6f48786d | ||
|
65ad79adce | ||
|
fad4e4e75e | ||
|
3b8fd6f62f | ||
|
abe240397d | ||
|
8b5e0df2d7 | ||
|
2b919d0cf2 | ||
|
a03193b2f7 | ||
|
a5a8f6057b | ||
|
fd1fdc6466 | ||
|
ef127df623 | ||
|
3282c9426c | ||
|
5c34c93a84 | ||
|
239c3f1db7 | ||
|
913509f887 | ||
|
1f116d9afe | ||
|
2cfb9e8dab | ||
|
8448d6c6e6 | ||
|
9f54adbeb4 | ||
|
6d43eea1bd | ||
|
312969462e | ||
|
999da4945a | ||
|
bf294aa684 | ||
|
a58476d079 | ||
|
adede8b6be | ||
|
65e32f720d | ||
|
35ab677ff1 | ||
|
bfedf20db5 | ||
|
a7516937f7 | ||
|
a42337ad0a | ||
|
c9ab987658 | ||
|
eb798fa4f1 | ||
|
17d4175b47 | ||
|
45d4d1bb3e | ||
|
8fc880b69b | ||
|
30426d21e7 | ||
|
9aac5a22f1 | ||
|
96143177ce | ||
|
a072951102 | ||
|
c9a1a3eb94 | ||
|
44ade6ad64 | ||
|
44ad69ceca | ||
|
f78bf5e46f | ||
|
94ed548353 | ||
|
6099ffece1 | ||
|
347a515c25 | ||
|
9e54070c1d | ||
|
9a79c6b1a4 | ||
|
3fc4207cdb | ||
|
ef73ab43da | ||
|
2ff1957ca8 | ||
|
0141a60eb8 | ||
|
2253990898 | ||
|
076e5e3186 | ||
|
2d8da60ffc | ||
|
5ff402aabf | ||
|
e07faea874 | ||
|
a5dc505e61 | ||
|
538d66191e | ||
|
928487985d | ||
|
e1bf781b10 | ||
|
608e1c195b | ||
|
9d73189133 | ||
|
536d4218c2 | ||
|
e3885c2b5c | ||
|
9250be348d | ||
|
7c12a286c3 | ||
|
7454532641 | ||
|
8d35ca90e1 | ||
|
24c16f622f | ||
|
9a2968d1eb | ||
|
0937f44f39 | ||
|
91dabeff53 | ||
|
7c9b347116 | ||
|
075368b5ae | ||
|
a611a3ac59 | ||
|
90459116e3 | ||
|
d4672b3517 | ||
|
bbf28c74f7 | ||
|
bbd85fc823 | ||
|
291a5f42cd | ||
|
1dd73e74ab | ||
|
03c98fb55a | ||
|
7f9b139ae0 | ||
|
6aaeb754ef | ||
|
144277bdcc | ||
|
823b9db6f6 | ||
|
adad1fde19 | ||
|
8b2d97b946 | ||
|
515f78619f | ||
|
71be63dbb1 | ||
|
a503f58d0c | ||
|
afae8d02be | ||
|
6fef696268 | ||
|
e4290140bc | ||
|
7c93acedc3 | ||
|
ae29f06e44 | ||
|
a2f71d387f | ||
|
8f18d35109 | ||
|
f1923c5364 | ||
|
636c8cb165 | ||
|
513ea97769 | ||
|
93b18e6440 | ||
|
11882827c7 | ||
|
9f1d431c99 | ||
|
d45e9a0c30 | ||
|
2b00cdce7b | ||
|
636e79c438 | ||
|
1641b1f91f | ||
|
7877e6601d | ||
|
08b6ee0297 | ||
|
d7bb92be54 | ||
|
cc010643ad | ||
|
d87b925488 | ||
|
5e396e2a91 | ||
|
4fdff9fce2 | ||
|
4d18ddba6d | ||
|
a53ebe7572 | ||
|
df28c2c676 | ||
|
b5a6199784 | ||
|
75f36b992d | ||
|
6e2b5d5dc8 | ||
|
f98d27f187 | ||
|
af987143b7 | ||
|
2723d3b73b | ||
|
0441a8725f | ||
|
ac455ebb45 | ||
|
8acba00655 | ||
|
94d69b764a | ||
|
e7bcac0171 | ||
|
1f9fa74786 | ||
|
a06270fc85 | ||
|
c1535f1b34 | ||
|
6b494af146 | ||
|
beced225a3 | ||
|
776dedea82 | ||
|
08a4cee48f | ||
|
78e67080c9 | ||
|
bb0c662713 | ||
|
fb15480f6b | ||
|
f8c6a62c23 | ||
|
eee45281ea | ||
|
3770410bed | ||
|
15cc825f43 | ||
|
5734722c5d | ||
|
aaeb26e2b7 | ||
|
3674c9d020 | ||
|
5120b8fbf5 | ||
|
255e75c6cf | ||
|
74fc259c9c | ||
|
0773a86922 | ||
|
749c5df29a | ||
|
82422b4500 | ||
|
4322197aba | ||
|
4ebff0ffcc | ||
|
7e691143d0 | ||
|
f840d63bdb | ||
|
e38cd31ca7 | ||
|
218f198ec6 | ||
|
d78c8b7cc8 | ||
|
977e7a40bc | ||
|
d769798ba3 | ||
|
867a9950d5 | ||
|
6ab79ae689 | ||
|
40d29bd453 | ||
|
1f66bc7756 | ||
|
b177affd81 | ||
|
89c984830b | ||
|
1d5cf8d25c | ||
|
1dccb08cd6 | ||
|
f462436450 | ||
|
fc5debc660 | ||
|
b89d41a701 | ||
|
3455da404a | ||
|
0f45ebda03 | ||
|
4c1c62a56b | ||
|
7f5ce54b1f | ||
|
1528e2afed | ||
|
a66f9bf494 | ||
|
faaa4ba6bc | ||
|
aa10dd98c9 | ||
|
a62fa3b073 | ||
|
9f98bee362 | ||
|
f372e1a69d | ||
|
5b5b9a91aa | ||
|
b43ac187ec | ||
|
adc5940d15 | ||
|
e33c3771f5 | ||
|
d78577c46d | ||
|
2ab59f5a7a | ||
|
1807af355b | ||
|
efeedc1274 | ||
|
f869b26664 | ||
|
7a2276c176 | ||
|
b604588638 | ||
|
a585f3abcc | ||
|
0a03793d7b | ||
|
667ab77651 | ||
|
9be04fd69f | ||
|
ba73d278ae | ||
|
a8b5f8a95f | ||
|
45e7edc9b8 | ||
|
874127a4f9 | ||
|
d177314676 | ||
|
bab4f21056 | ||
|
188a043967 | ||
|
5e881e5944 | ||
|
23779fe565 | ||
|
d1f1299d43 | ||
|
126e4fa698 | ||
|
2b3e44cca3 | ||
|
5ea8309a30 | ||
|
1557dec2bc | ||
|
de8ecc6903 | ||
|
5b37d22e2d | ||
|
7b5baad5cd | ||
|
d791b54528 | ||
|
49fb2f4d79 | ||
|
41a0d6919f | ||
|
68d8d322a9 | ||
|
d7b3a56c3d | ||
|
81841ca2a6 | ||
|
5af7852465 | ||
|
57d6938d6c | ||
|
d4f23de003 | ||
|
c22ed52c72 | ||
|
6029b51f7e | ||
|
8bc515c6a1 | ||
|
f91e1b3d2f | ||
|
b66c4d7206 | ||
|
9062b6bc4d | ||
|
0f03dcfc0f | ||
|
2103e6238c | ||
|
b6e7f4f493 | ||
|
d13ec29158 | ||
|
96cd683d0e | ||
|
c7cbeed9bb | ||
|
9264008766 | ||
|
9db9c5c9ca | ||
|
efa80267f6 | ||
|
e75d03fea9 | ||
|
48be0ceb16 | ||
|
0e3ff1699a | ||
|
446a9adcf1 | ||
|
0bda86c352 | ||
|
ee6eb5572d | ||
|
dec4a7d31e | ||
|
8a321a7450 | ||
|
092d11bbe6 | ||
|
d956e0ebdc | ||
|
93e0efa241 | ||
|
f27b3361e5 | ||
|
f67abf9e03 | ||
|
7744be3319 | ||
|
07cff878e5 | ||
|
dd6dcf1c5b | ||
|
0382afc488 | ||
|
19eae8cb49 | ||
|
1a1ab1d18a | ||
|
ae79616c73 | ||
|
9c0993908a | ||
|
647b89f8ad | ||
|
591a61a61c | ||
|
4a8b47a6ff | ||
|
1689baa2a4 | ||
|
ca283c0da6 | ||
|
9e049f44e2 | ||
|
0bc0569932 | ||
|
e861b18992 | ||
|
26c0b620f8 | ||
|
324eb695f5 | ||
|
b5139e3ff9 | ||
|
38b1c26396 | ||
|
418a2564b2 | ||
|
8d0261bab3 | ||
|
dc3b18de94 | ||
|
b0cb982978 |
@@ -75,6 +75,7 @@ module.exports = {
|
||||
'plugins/**',
|
||||
'**/*.min.js',
|
||||
'public/scripts/extensions/quick-reply/lib/**',
|
||||
'public/scripts/extensions/tts/lib/**',
|
||||
],
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { args: 'none' }],
|
||||
|
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -1,4 +1,5 @@
|
||||
name: Bug Report 🐛
|
||||
type: Bug
|
||||
description: Report something that's not working the intended way. Support requests for external programs (reverse proxies, 3rd party servers, other peoples' forks) will be refused! Please use English only.
|
||||
title: '[BUG] <title>'
|
||||
labels: ['🐛 Bug']
|
||||
@@ -80,6 +81,8 @@ body:
|
||||
required: true
|
||||
- label: I have checked the [docs](https://docs.sillytavern.app/) 
|
||||
required: true
|
||||
- label: I confirm that my issue is not related to third-party content, unofficial extension or patch. If in doubt, check with a new [user account](https://docs.sillytavern.app/administration/multi-user/) and with extensions disabled
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
3
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
3
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -1,4 +1,5 @@
|
||||
name: Feature Request ✨
|
||||
type: Feature
|
||||
description: Suggest an idea for future development of this project. Please use English only.
|
||||
title: '[FEATURE_REQUEST] <title>'
|
||||
labels: ['🦄 Feature Request']
|
||||
@@ -32,7 +33,7 @@ body:
|
||||
id: solution
|
||||
attributes:
|
||||
label: Describe the solution you'd like
|
||||
placeholder: An outline of how you would like this to be implemented, include as much details as possible
|
||||
placeholder: An outline of how you would like this to be implemented, include as much details as possible
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
2
.github/close-label.yml
vendored
2
.github/close-label.yml
vendored
@@ -1,2 +0,0 @@
|
||||
🐛 Bug: ✅ Fixed
|
||||
🦄 Feature Request: ✅ Implemented
|
62
.github/issue-auto-comments.yml
vendored
62
.github/issue-auto-comments.yml
vendored
@@ -1,62 +0,0 @@
|
||||
comment:
|
||||
footer: |
|
||||
---
|
||||
> I am a bot, and this is an automated message 🤖
|
||||
labels:
|
||||
- name: ✖️ Invalid
|
||||
labeled:
|
||||
issue:
|
||||
action: close
|
||||
body: >
|
||||
Hello @{{ issue.user.login }} your ticket has been marked as invalid.
|
||||
Please ensure you follow the issue template, provide all requested info,
|
||||
and be sure to check the docs + previous issues prior to raising tickets.
|
||||
pr:
|
||||
body: Thank you @{{ pull_request.user.login }} for suggesting this. Please follow the pull request templates.
|
||||
action: close
|
||||
|
||||
- name: 👩💻 Good First Issue
|
||||
labeled:
|
||||
issue:
|
||||
body: >
|
||||
This issue has been marked as a good first issue for first-time contributors to implement!
|
||||
This is a great way to support the project, while also improving your skills, you'll also be credited as a contributor once your PR is merged.
|
||||
If you're new to SillyTavern [here are a collection of resources](https://docs.sillytavern.app/)
|
||||
If you need any support at all, feel free to reach out via [Discord](https://discord.gg/sillytavern).
|
||||
|
||||
- name: ❌ wontfix
|
||||
labeled:
|
||||
issue:
|
||||
action: close
|
||||
body: >
|
||||
This ticked has been marked as 'wontfix', which usually means it is out-of-scope, or not feasible at this time.
|
||||
You can still fork the project and make the changes yourself.
|
||||
|
||||
- name: ✅ Fixed
|
||||
labeled:
|
||||
issue:
|
||||
body: >
|
||||
Hello @{{ issue.user.login }}! It looks like all or part of this issue has now been implemented.
|
||||
|
||||
|
||||
- name: ‼️ High Priority
|
||||
labeled:
|
||||
issue:
|
||||
body: >
|
||||
This ticket has been marked as high priority, and has been bumped to the top of the priority list.
|
||||
You should expect an implementation to be pushed out soon. Thank you for your patience.
|
||||
|
||||
- name: 💀 Spam
|
||||
labeled:
|
||||
issue:
|
||||
action: close
|
||||
locking: lock
|
||||
lock_reason: spam
|
||||
body: >
|
||||
This issue has been identified as spam, and is now locked.
|
||||
Users who repeatedly raise spam issues may be blocked or reported.
|
||||
|
||||
- name: ⛔ Don't Merge
|
||||
labeled:
|
||||
pr:
|
||||
body: This PR has been temporarily blocked from merging.
|
69
.github/issues-auto-comments.yml
vendored
Normal file
69
.github/issues-auto-comments.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
labels:
|
||||
- name: ✖️ Invalid
|
||||
labeled:
|
||||
issue:
|
||||
action: close
|
||||
body: >
|
||||
Hey @{{ issue.user.login }}, this issue has been marked as invalid.
|
||||
|
||||
Please double-check that you've followed the issue template, included all necessary details, and reviewed the docs & previous issues before submitting.
|
||||
If provided, follow the instructions given by maintainers.
|
||||
|
||||
- name: 👩💻 Good First Issue
|
||||
labeled:
|
||||
issue:
|
||||
body: >
|
||||
🏆 This issue has been marked as a good first issue for contributors to implement!
|
||||
This is a great way to support the project. While also improving your skills, you'll also be credited as a contributor once your PR is merged.
|
||||
|
||||
If you're new to SillyTavern [here is the official documentation](https://docs.sillytavern.app/). The official contribution guide can be found [here](https://github.com/SillyTavern/SillyTavern/blob/release/CONTRIBUTING.md).
|
||||
If you need any support, feel free to reach out via [Discord](https://discord.gg/sillytavern), or let us know in this issue or via [discussions](https://github.com/SillyTavern/SillyTavern/discussions).
|
||||
|
||||
- name: ❌ wontfix
|
||||
labeled:
|
||||
issue:
|
||||
action: close
|
||||
body: >
|
||||
❌ This issue has been marked as 'wontfix', which usually means it is out-of-scope, not feasible at this time or will not be implemented for various reasons.
|
||||
If you have any questions about this, feel free to reach out.
|
||||
|
||||
- name: 🛑 Out of Scope
|
||||
labeled:
|
||||
issue:
|
||||
action: close
|
||||
body: >
|
||||
🛑 This issue has been marked as 'out of scope', as this can't or won't be implemented.
|
||||
If you have any questions about this, feel free to reach out.
|
||||
|
||||
- name: ✅ Done (staging)
|
||||
labeled:
|
||||
issue:
|
||||
body: >
|
||||
✅ It looks like all or part of this issue has now been implemented as part of the `staging` branch.
|
||||
If you currently are on the `release` branch, you can switch to `staging` to test this right away.
|
||||
|
||||
Note that `staging` is considered less stable than the official releases. To switch, follow existing instructions,
|
||||
or simply enter the following command: `git switch staging`
|
||||
|
||||
- name: ✅ Done
|
||||
labeled:
|
||||
issue:
|
||||
body: >
|
||||
✅ It looks like all or part of this issue has now been implemented as part of the latest release.
|
||||
|
||||
- name: ‼️ High Priority
|
||||
labeled:
|
||||
issue:
|
||||
body: >
|
||||
🚨 This issue has been marked high priority, meaning it's important to the maintainers or community.
|
||||
While we can't promise immediate changes, it is on our radar and will be addressed whenever possible. Thanks for your patience!
|
||||
|
||||
- name: 💀 Spam
|
||||
labeled:
|
||||
issue:
|
||||
action: close
|
||||
locking: lock
|
||||
lock_reason: spam
|
||||
body: >
|
||||
💀 This issue has been flagged as spam and is now locked.
|
||||
Please avoid posting spam - it disrupts the community and wastes everyone's time.
|
@@ -1,7 +1,3 @@
|
||||
# Add/remove 'critical' label if issue contains the words 'urgent' or 'critical'
|
||||
#critical:
|
||||
# - '(critical|urgent)'
|
||||
|
||||
🪟 Windows:
|
||||
- '(🪟 Windows)'
|
||||
|
||||
@@ -15,4 +11,10 @@
|
||||
- '(📱 Termux)'
|
||||
|
||||
🐧 Linux:
|
||||
- '(🐧 Linux)'
|
||||
- '(🐧 Linux)'
|
||||
|
||||
🦊 Firefox:
|
||||
- '(firefox|mozilla)'
|
||||
|
||||
📱 Mobile:
|
||||
- '(iphone|ios|android|📱 Termux)'
|
51
.github/pr-auto-comments.yml
vendored
Normal file
51
.github/pr-auto-comments.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
labels:
|
||||
- name: ✖️ Invalid
|
||||
labeled:
|
||||
pr:
|
||||
action: close
|
||||
body: >
|
||||
Hey @{{ pull_request.user.login }}, thanks for your contribution!
|
||||
Unfortunately, this PR has been marked as invalid.
|
||||
|
||||
Please check that you've followed the PR template, included all relevant details, and are targeting the correct branch (`staging` for regular contributions, `release` only for hotfixes).
|
||||
|
||||
If you need help, feel free to ask!
|
||||
|
||||
- name: ⛔ Don't Merge
|
||||
labeled:
|
||||
pr:
|
||||
body: >
|
||||
🚨 This PR has been temporarily blocked from merging.
|
||||
|
||||
- name: 💥💣 Breaking Changes
|
||||
labeled:
|
||||
pr:
|
||||
body: >
|
||||
⚠️ Heads up! This PR introduces breaking changes.
|
||||
|
||||
Make sure these changes are well-documented and that users will be properly informed when this is released.
|
||||
|
||||
- name: ⛔ Waiting For External/Upstream
|
||||
labeled:
|
||||
pr:
|
||||
body: >
|
||||
⛔ This PR is awaiting external or upstream changes or approval.
|
||||
It can only be merged once those changes have been implemented and approved.
|
||||
|
||||
Please inform us of any progress on the upstream changes or approval.
|
||||
|
||||
- name: 🔬 Needs Testing
|
||||
labeled:
|
||||
pr:
|
||||
body: >
|
||||
🔬 This PR needs testing!
|
||||
Any contributor can test and leave reviews, so feel free to help us out!
|
||||
|
||||
- name: 🟥 ⬤⬤⬤⬤⬤
|
||||
labeled:
|
||||
pr:
|
||||
body: >
|
||||
⚠️ This PR is over 1000 lines, which is larger than recommended.
|
||||
|
||||
Please make sure that it only addresses a single issue - PRs this large are hard to test and may be rejected.
|
||||
|
77
.github/pr-auto-labels-by-branch.yml
vendored
Normal file
77
.github/pr-auto-labels-by-branch.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
####################################
|
||||
# Label PRs against 'release' #
|
||||
####################################
|
||||
❗ Against Release Branch:
|
||||
- base-branch: 'release'
|
||||
|
||||
####################################
|
||||
# Labels based on PR branch name #
|
||||
####################################
|
||||
🦋 Bug Fix:
|
||||
- head-branch: ['^fix[/-]', '\bfixes\b']
|
||||
|
||||
🚑 Hot Fix:
|
||||
- head-branch: ['^hotfix[/-]']
|
||||
|
||||
✨ New Feature:
|
||||
- head-branch: ['^feat(ure)?[/-].*?\badd', '^add-']
|
||||
|
||||
✨ Feature Changes:
|
||||
- head-branch: ['^feat(ure)?[/-](?!.*\badd\b)', '\bchanges?\b']
|
||||
|
||||
🤖 API / Model:
|
||||
- head-branch: ['\bapi\b', '\bmodels?\b']
|
||||
|
||||
🏭 Backend Changes:
|
||||
- head-branch: ['\bbackend\b', '\bendpoints?\b']
|
||||
|
||||
🐋 Docker:
|
||||
- head-branch: ['\bdocker\b']
|
||||
|
||||
➕ Extension:
|
||||
- head-branch: ['\bextension\b', '\bext\b']
|
||||
|
||||
🦊 Firefox:
|
||||
- head-branch: ['\bfirefox\b']
|
||||
|
||||
🖼️ Image Gen:
|
||||
- head-branch: ['\bimage-gen\b']
|
||||
|
||||
🌐 Language:
|
||||
- head-branch: ['\btranslations?\b', '\blanguages?\b']
|
||||
|
||||
🐧 Linux:
|
||||
- head-branch: ['\blinux\b']
|
||||
|
||||
🧩 Macros:
|
||||
- head-branch: ['\bmacros?\b']
|
||||
|
||||
📱 Mobile:
|
||||
- head-branch: ['\bmobile\b', '\bios\b', '\bandroid\b']
|
||||
|
||||
🚄 Performance:
|
||||
- head-branch: ['\bperformance\b']
|
||||
|
||||
⚙️ Preset:
|
||||
- head-branch: ['\bpresets?\b']
|
||||
|
||||
📜 Prompt:
|
||||
- head-branch: ['\bprompt\b']
|
||||
|
||||
🚚 Refactor:
|
||||
- head-branch: ['\brefactor(s|ed)?\b']
|
||||
|
||||
📜 STscript:
|
||||
- head-branch: ['\bstscript\b', '\bslash-commands\b']
|
||||
|
||||
🏷️ Tags / Folders:
|
||||
- head-branch: ['\btags\b']
|
||||
|
||||
🎙️ TTS / Voice:
|
||||
- head-branch: ['\btts\b', '\bvoice\b']
|
||||
|
||||
🌟 UX:
|
||||
- head-branch: ['\bux\b']
|
||||
|
||||
🗺️ World Info:
|
||||
- head-branch: ['\bworld-info\b', '\bwi\b']
|
46
.github/pr-auto-labels-by-files.yml
vendored
Normal file
46
.github/pr-auto-labels-by-files.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
####################################
|
||||
# Labels based on changed files #
|
||||
####################################
|
||||
🏭 Backend Changes:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/**"
|
||||
- "default/config.yaml"
|
||||
- "server.js"
|
||||
- "plugins.js"
|
||||
- "recover.js"
|
||||
- "webpack.config.js"
|
||||
- "Start.bat"
|
||||
- "start.sh"
|
||||
- "UpdateAndStart.bat"
|
||||
- "UpdateForkAndStart.bat"
|
||||
|
||||
⚙️ config.yaml:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "default/config.yaml"
|
||||
|
||||
🛠️ Build Changes:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ".github/workflows/**"
|
||||
- "docker/**"
|
||||
- ".dockerignore"
|
||||
- "Dockerfile"
|
||||
- "webpack.config.js"
|
||||
|
||||
🌐 Language:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "public/locales/**"
|
||||
|
||||
📥 Dependencies:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "public/lib/**" # Every frontend lib counts as a dependency as well
|
||||
- "package.json"
|
||||
- "package-lock.json"
|
||||
- "tests/package.json"
|
||||
- "tests/package-lock.json"
|
||||
- "src/electron/package.json"
|
||||
- "src/electron/package-lock.json"
|
22
.github/readme-zh_tw.md
vendored
22
.github/readme-zh_tw.md
vendored
@@ -1,5 +1,5 @@
|
||||
> [!IMPORTANT]
|
||||
> 這裡的資訊可能已經過時或不完整,僅供您參考。請使用英文版本以取得最新資訊。
|
||||
> 此處資訊可能已經過時或不完整,僅供您參考。請使用英文版本以取得最新資訊。
|
||||
|
||||
<a name="readme-top"></a>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
---
|
||||
|
||||
SillyTavern 提供一個統一的前端介面,整合多種大型語言模型的 API(包括:KoboldAI/CPP、Horde、NovelAI、Ooba、Tabby、OpenAI、OpenRouter、Claude、Mistral 等)。同時具備行動裝置友善的佈局、視覺小說模式(Visual Novel Mode)、Automatic1111 與 ComfyUI 的影像生成 API 整合、TTS(語音合成)、世界資訊(Lorebook)、可自訂 UI、自動翻譯功能,以及強大的提示詞(prompt)設定選項和無限的第三方擴充潛力。
|
||||
SillyTavern 提供一個統一的前端介面,整合多種大型語言模型的 API(包括:KoboldAI/CPP、Horde、NovelAI、Ooba、Tabby、OpenAI、OpenRouter、Claude、Mistral 等)。同時具備對行動裝置友善的佈局、視覺小說模式(Visual Novel Mode)、Automatic1111 與 ComfyUI 的影像生成 API 整合、TTS(語音合成)、世界資訊(Lorebook)、可自訂 UI、自動翻譯功能,以及強大的提示詞(prompt)設定選項和無限的第三方擴充潛力。
|
||||
|
||||
我們擁有一個 [官方文件網站](https://docs.sillytavern.app/) 可以幫助解答絕大多數的使用問題,並幫助您順利入門。
|
||||
|
||||
@@ -30,18 +30,18 @@ SillyTavern 起源於 2023 年 2 月,作為 TavernAI 1.2.8 的分支版本發
|
||||
|
||||
## 我們的願景
|
||||
|
||||
1. 我們致力於賦予使用者對 LLM 提示詞的最大控制權與實用性,並認為學習過程中的挑戰是樂趣的一部分
|
||||
1. 我們致力於賦予使用者對 LLM 提示詞的最大控制權與實用性,並認為學習過程中的挑戰是樂趣的一部分。
|
||||
2. 我們不提供任何線上或託管服務,也不會程式化追蹤任何使用者數據。
|
||||
3. SillyTavern 是由一群熱衷於 LLM 的開發者社群所打造的熱情專案,並將永遠保持免費與開源。
|
||||
3. SillyTavern 是由一群熱衷於 LLM 的開發者社群所打造的專案,並將永遠保持免費與開源。
|
||||
|
||||
## 分支介紹
|
||||
|
||||
SillyTavern 採用雙分支開發模式,確保為所有使用者提供流暢的使用體驗。
|
||||
SillyTavern 採用雙分支開發模式,確保為所有使用者提供流暢的體驗。
|
||||
|
||||
* `release`(穩定版):🌟 **推薦給大部分的使用者使用。** 此分支最為穩定,僅在主要版本發布時更新。適合大多數人,通常每月更新一次。
|
||||
* `staging`(開發版):⚠️ **不建議普通使用者使用。** 此分支包含最新功能,但可能隨時出現問題。適合進階使用者與愛好者,每日多次更新。
|
||||
|
||||
如果您不熟悉 git CLI 或對分支概念不清楚,請放心對您來說,`release`(穩定版)分支永遠是首選。
|
||||
如果您不熟悉 git CLI 或對分支概念不清楚,請放心,對您來說,`release`(穩定版)分支永遠是首選。
|
||||
|
||||
## 使用 SillyTavern 需要什麼?
|
||||
|
||||
@@ -84,18 +84,18 @@ SillyTavern 的硬體需求相當低。任何能夠運行 NodeJS 18 或更高版
|
||||
|
||||
## 角色卡
|
||||
|
||||
SillyTavern 的核心概念是「角色卡」(Character Cards)。角色卡是一組設定 LLM 行為的提示詞,用於 SillyTavern 中進行持續性對話。其功能類似於 ChatGPT 的 GPT 或 Poe 的聊天機器人。角色卡的內容可以是任何形式:抽象場景、針對特定任務設計的助手、知名人物,或者虛構角色。
|
||||
SillyTavern 的核心概念是「角色卡」(Character Cards)。角色卡是一組設定 LLM 行為的提示詞,用於 SillyTavern 中進行持續性對話。功能類似於 ChatGPT 的 GPT 或 Poe 的聊天機器人。角色卡的內容可以是任何形式:抽象場景、針對特定任務設計的助手、知名人物,或者虛構角色。
|
||||
|
||||
角色卡中唯一必填的項目是名稱欄位。若想與語言模型開始一般對話,您只需創建一個名稱為「Assistant」的新卡片,其餘欄位皆可保持空白。若希望進行更具主題性的對話,則可以提供語言模型背景資訊、行為模式、寫作風格以及特定情境來啟動聊天。
|
||||
|
||||
如果您僅想進行快速對話而不選擇角色卡片,或想測試 LLM 的連線,則可在打開 SillyTavern 後,於歡迎頁面的輸入欄位中直接輸入您的提示內容。請注意,這類對話是暫時的,不會被永久保存。
|
||||
如果僅想進行快速對話而不選擇角色卡片,或想測試 LLM 的連線,則可在開啟 SillyTavern 後,於歡迎頁面的輸入欄位中直接輸入您的提示內容。請注意,這類對話是暫時的,不會被永久保存。
|
||||
|
||||
若想了解如何設定角色卡,可參考預設角色(如 Seraphina)或從「下載擴充功能 & 資源」(Download Extensions & Assets)選單中下載社群製作的角色卡。
|
||||
|
||||
## 核心功能
|
||||
|
||||
* 進階文本生成設定:內含許多社群製作的預設設定
|
||||
* 支援世界資訊(World Info):創建豐富的背景故事,或節省角色卡片中的 Token(符記)使用
|
||||
* 支援世界資訊(World Info):創建豐富的背景故事,或節省角色卡中的 Token(符元)使用
|
||||
* 群組聊天:多角色聊天室,可讓角色與您或彼此對話
|
||||
* 豐富的 UI 自定義選項:主題顏色、背景圖片、自定義 CSS 等
|
||||
* 使用者設定:讓 AI 更了解您並提升沉浸感
|
||||
@@ -110,7 +110,7 @@ SillyTavern 支持多種擴充功能。
|
||||
* 聊天記錄自動摘要
|
||||
* 自動化介面與聊天翻譯
|
||||
* 穩定擴散(Stable Diffusion)、FLUX 和 DALL-E 的影像生成整合
|
||||
* 語音合成:AI 回應訊息可透過 ElevenLabs、Silero 或系統 TTS 語音合成
|
||||
* 語音合成:AI 回應的訊息可使用 ElevenLabs、Silero 或系統 TTS 語音合成
|
||||
* 網頁搜尋功能:為提示詞添加真實世界的上下文資訊
|
||||
* 更多擴展:可從「下載擴充功能 & 資源」(Download Extensions & Assets)選單中下載
|
||||
|
||||
@@ -367,7 +367,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* 經授權使用部分來自 CncAnon 的 TavernAITurbo 模組
|
||||
* 視覺小說模式(Visual Novel Mode)的靈感,來源於 PepperTaco 的貢獻(<https://github.com/peppertaco/Tavern/>)
|
||||
* Noto Sans 字體由 Google 提供(OFL 許可)
|
||||
* 主題圖示由 Font Awesome <https://fontawesome.com> 提供(圖示:CC BY 4.0,字體:SIL OFL 1.1,代碼:MIT 許可)
|
||||
* 主題圖示由 Font Awesome <https://fontawesome.com> 提供(圖示:CC BY 4.0,字體:SIL OFL 1.1,程式碼:MIT 許可)
|
||||
* 預設資源來源於 @OtisAlejandro(包含角色 Seraphina 與知識書)與 @kallmeflocc(SillyTavern 官方 Discord 伺服器成員突破 10K 的慶祝背景)
|
||||
* Docker 安裝指南由 [@mrguymiah](https://github.com/mrguymiah) 和 [@Bronya-Rand](https://github.com/Bronya-Rand) 編寫
|
||||
|
||||
|
175
.github/readme.md
vendored
175
.github/readme.md
vendored
@@ -23,7 +23,7 @@ We have a [Documentation website](https://docs.sillytavern.app/) to answer most
|
||||
|
||||
SillyTavern (or ST for short) is a locally installed user interface that allows you to interact with text generation LLMs, image generation engines, and TTS voice models.
|
||||
|
||||
Beginning in February 2023 as a fork of TavernAI 1.2.8, SillyTavern now has over 100 contributors and 2 years of independent development under its belt, and continues to serve as a leading software for savvy AI hobbyists.
|
||||
Beginning in February 2023 as a fork of TavernAI 1.2.8, SillyTavern now has over 200 contributors and 2 years of independent development under its belt, and continues to serve as a leading software for savvy AI hobbyists.
|
||||
|
||||
## Our Vision
|
||||
|
||||
@@ -113,7 +113,9 @@ SillyTavern has extensibility support.
|
||||
|
||||
Tutorials on how to use them can be found in the [Docs](https://docs.sillytavern.app/).
|
||||
|
||||
# ⌛ Installation
|
||||
## ⌛ Installation
|
||||
|
||||
### 🪟 Windows
|
||||
|
||||
> \[!WARNING]
|
||||
>
|
||||
@@ -121,9 +123,7 @@ Tutorials on how to use them can be found in the [Docs](https://docs.sillytavern
|
||||
> * DO NOT RUN START.BAT WITH ADMIN PERMISSIONS
|
||||
> * INSTALLATION ON WINDOWS 7 IS IMPOSSIBLE AS IT CAN NOT RUN NODEJS 18.16
|
||||
|
||||
## 🪟 Windows
|
||||
|
||||
### Installing via Git
|
||||
#### Installing via Git (recommended)
|
||||
|
||||
1. Install [NodeJS](https://nodejs.org/en) (latest LTS version is recommended)
|
||||
2. Install [Git for Windows](https://gitforwindows.org/)
|
||||
@@ -138,7 +138,7 @@ Tutorials on how to use them can be found in the [Docs](https://docs.sillytavern
|
||||
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 GitHub Desktop
|
||||
#### Installing via GitHub Desktop
|
||||
|
||||
(This allows git usage **only** in GitHub Desktop, if you want to use `git` on the command line too, you also need to install [Git for Windows](https://gitforwindows.org/))
|
||||
|
||||
@@ -152,7 +152,7 @@ Tutorials on how to use them can be found in the [Docs](https://docs.sillytavern
|
||||
9. After the installation process, if everything is working, the command console window should look like this and a SillyTavern tab should be open in your browser:
|
||||
10. Connect to any of the [supported APIs](https://docs.sillytavern.app/usage/api-connections/) and start chatting!
|
||||
|
||||
## 🐧 Linux & 🍎 MacOS
|
||||
### 🐧 Linux & 🍎 MacOS
|
||||
|
||||
For MacOS / Linux all of these will be done in a Terminal.
|
||||
|
||||
@@ -168,6 +168,57 @@ For MacOS / Linux all of these will be done in a Terminal.
|
||||
* `./start.sh`
|
||||
* `bash start.sh`
|
||||
|
||||
## 🐋 Installing via Docker
|
||||
|
||||
These instructions assume you have installed Docker, are able to access your command line for the installation of containers, and familiar with their general operation.
|
||||
|
||||
### Using the GitHub Container Registry
|
||||
|
||||
#### Docker Compose (easiest)
|
||||
|
||||
Grab the `docker-compose.yml` file from the [GitHub Repository](https://github.com/SillyTavern/SillyTavern/blob/release/docker/docker-compose.yml) and run the following command in the directory where the file is located. This will pull the latest release image from the GitHub Container Registry and start the container, automatically creating the necessary volumes.
|
||||
|
||||
```shell
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
Customize the `docker-compose.yml` file to your needs. The default port is 8000. If you want to adjust the server configuration using environment variables, read the documentation [here](https://docs.sillytavern.app/administration/config-yaml/#environment-variables).
|
||||
|
||||
#### Docker CLI (advanced)
|
||||
|
||||
You will need two mandatory directory mappings and a port mapping to allow SillyTavern to function. In the command, replace your selections in the following places:
|
||||
|
||||
#### Container Variables
|
||||
|
||||
##### Volume Mappings
|
||||
|
||||
* [config] - The directory where SillyTavern configuration files will be stored on your host machine
|
||||
* [data] - The directory where SillyTavern user data (including characters) will be stored on your host machine
|
||||
* [plugins] - (optional) The directory where SillyTavern server plugins will be stored on your host machine
|
||||
* [extensions] - (optional) The directory where global UI extensions will be stored on your host machine
|
||||
|
||||
##### Port Mappings
|
||||
|
||||
* [PublicPort] - The port to expose the traffic on. This is mandatory, as you will be accessing the instance from outside of its virtual machine container. DO NOT expose this to the internet without implementing a separate service for security.
|
||||
|
||||
##### Additional Settings
|
||||
|
||||
* [DockerNet] - The docker network that the container should be created with a connection to. If you don't know what it is, see the [official Docker documentation](https://docs.docker.com/reference/cli/docker/network/).
|
||||
* [version] - On the right-hand side of this GitHub page, you'll see "Packages". Select the "sillytavern" package and you'll see the image versions. The image tag "latest" will keep you up-to-date with the current release. You can also utilize "staging" and "release" tags that point to the nightly images of the respective branches, but this may not be appropriate, if you are utilizing extensions that could be broken, and may need time to update.
|
||||
|
||||
#### Install command
|
||||
|
||||
1. Open your Command Line
|
||||
2. Run the following command
|
||||
|
||||
`docker run --name='sillytavern' --net='[DockerNet]' -p '8000:8000/tcp' -v '[plugins]':'/home/node/app/plugins':'rw' -v '[config]':'/home/node/app/config':'rw' -v '[data]':'/home/node/app/data':'rw' -v '[extensions]':'/home/node/app/public/scripts/extensions/third-party':'rw' 'ghcr.io/sillytavern/sillytavern:[version]'`
|
||||
|
||||
> Note that 8000 is a default listening port. Don't forget to use an appropriate port if you change it in the config.
|
||||
|
||||
### Building the image yourself
|
||||
|
||||
We have a comprehensive guide on using SillyTavern in Docker [here](http://docs.sillytavern.app/installation/docker/) which covers installations on Windows, macOS and Linux! Give it a read if you wish to build the image yourself.
|
||||
|
||||
## ⚡ Installing via SillyTavern Launcher
|
||||
|
||||
SillyTavern Launcher is an installation wizard that will help you get setup with many options, including installing a backend for local inference.
|
||||
@@ -239,45 +290,6 @@ chmod +x install.sh && ./install.sh
|
||||
chmod +x launcher.sh && ./launcher.sh
|
||||
```
|
||||
|
||||
## 🐋 Installing via Docker
|
||||
|
||||
These instructions assume you have installed Docker, are able to access your command line for the installation of containers, and familiar with their general operation.
|
||||
|
||||
### Building the image yourself
|
||||
|
||||
We have a comprehensive guide on using SillyTavern in Docker [here](http://docs.sillytavern.app/installation/docker/) which covers installations on Windows, macOS and Linux! Give it a read if you wish to build the image yourself.
|
||||
|
||||
### Using the GitHub Container Registry (easiest)
|
||||
|
||||
You will need two mandatory directory mappings and a port mapping to allow SillyTavern to function. In the command, replace your selections in the following places:
|
||||
|
||||
#### Container Variables
|
||||
|
||||
##### Volume Mappings
|
||||
|
||||
* [config] - The directory where SillyTavern configuration files will be stored on your host machine
|
||||
* [data] - The directory where SillyTavern user data (including characters) will be stored on your host machine
|
||||
* [plugins] - (optional) The directory where SillyTavern server plugins will be stored on your host machine
|
||||
* [extensions] - (optional) The directory where global UI extensions will be stored on your host machine
|
||||
|
||||
##### Port Mappings
|
||||
|
||||
* [PublicPort] - The port to expose the traffic on. This is mandatory, as you will be accessing the instance from outside of its virtual machine container. DO NOT expose this to the internet without implementing a separate service for security.
|
||||
|
||||
##### Additional Settings
|
||||
|
||||
* [DockerNet] - The docker network that the container should be created with a connection to. If you don't know what it is, see the [official Docker documentation](https://docs.docker.com/reference/cli/docker/network/).
|
||||
* [version] - On the right-hand side of this GitHub page, you'll see "Packages". Select the "sillytavern" package and you'll see the image versions. The image tag "latest" will keep you up-to-date with the current release. You can also utilize "staging" and "release" tags that point to the nightly images of the respective branches, but this may not be appropriate, if you are utilizing extensions that could be broken, and may need time to update.
|
||||
|
||||
#### Install command
|
||||
|
||||
1. Open your Command Line
|
||||
2. Run the following command
|
||||
|
||||
`docker create --name='sillytavern' --net='[DockerNet]' -p '8000:8000/tcp' -v '[plugins]':'/home/node/app/plugins':'rw' -v '[config]':'/home/node/app/config':'rw' -v '[data]':'/home/node/app/data':'rw' -v '[extensions]':'/home/node/app/public/scripts/extensions/third-party':'rw' 'ghcr.io/sillytavern/sillytavern:[version]'`
|
||||
|
||||
> Note that 8000 is a default listening port. Don't forget to use an appropriate port if you change it in the config.
|
||||
|
||||
## 📱 Installing via Termux on Android OS
|
||||
|
||||
> \[!NOTE]
|
||||
@@ -317,29 +329,34 @@ Start.bat --port 8000 --listen false
|
||||
|
||||
### Supported arguments
|
||||
|
||||
| Option | Description | Type |
|
||||
|-------------------------|------------------------------------------------------------------------------------------------------|----------|
|
||||
| `--version` | Show version number | boolean |
|
||||
| `--enableIPv6` | Enables IPv6. | boolean |
|
||||
| `--enableIPv4` | Enables IPv4. | boolean |
|
||||
| `--port` | Sets the port under which SillyTavern will run. If not provided falls back to yaml config 'port'. | number |
|
||||
| `--dnsPreferIPv6` | Prefers IPv6 for dns. If not provided falls back to yaml config 'preferIPv6'. | boolean |
|
||||
| `--autorun` | Automatically launch SillyTavern in the browser. If not provided falls back to yaml config 'autorun'.| boolean |
|
||||
| `--autorunHostname` | The autorun hostname, probably best left on 'auto'. | string |
|
||||
| `--autorunPortOverride` | Overrides the port for autorun. | string |
|
||||
| `--listen` | SillyTavern is listening on all network interfaces. If not provided falls back to yaml config 'listen'.| boolean |
|
||||
| `--corsProxy` | Enables CORS proxy. If not provided falls back to yaml config 'enableCorsProxy'. | boolean |
|
||||
| `--disableCsrf` | Disables CSRF protection | boolean |
|
||||
| `--ssl` | Enables SSL | boolean |
|
||||
| `--certPath` | Path to your certificate file. | string |
|
||||
| `--keyPath` | Path to your private key file. | string |
|
||||
| `--whitelist` | Enables whitelist mode | boolean |
|
||||
| `--dataRoot` | Root directory for data storage | string |
|
||||
| `--avoidLocalhost` | Avoids using 'localhost' for autorun in auto mode. | boolean |
|
||||
| `--basicAuthMode` | Enables basic authentication | boolean |
|
||||
| `--requestProxyEnabled` | Enables a use of proxy for outgoing requests | boolean |
|
||||
| `--requestProxyUrl` | Request proxy URL (HTTP or SOCKS protocols) | string |
|
||||
| `--requestProxyBypass` | Request proxy bypass list (space separated list of hosts) | array |
|
||||
> \[!TIP]
|
||||
> None of the arguments are required. If you don't provide them, SillyTavern will use the settings in `config.yaml`.
|
||||
|
||||
| Option | Description | Type |
|
||||
|-------------------------|----------------------------------------------------------------------|----------|
|
||||
| `--version` | Show version number | boolean |
|
||||
| `--dataRoot` | Root directory for data storage | string |
|
||||
| `--port` | Sets the port under which SillyTavern will run | number |
|
||||
| `--listen` | SillyTavern will listen on all network interfaces | boolean |
|
||||
| `--whitelist` | Enables whitelist mode | boolean |
|
||||
| `--basicAuthMode` | Enables basic authentication | boolean |
|
||||
| `--enableIPv4` | Enables IPv4 protocol | boolean |
|
||||
| `--enableIPv6` | Enables IPv6 protocol | boolean |
|
||||
| `--listenAddressIPv4` | Specific IPv4 address to listen to | string |
|
||||
| `--listenAddressIPv6` | Specific IPv6 address to listen to | string |
|
||||
| `--dnsPreferIPv6` | Prefers IPv6 for DNS | boolean |
|
||||
| `--ssl` | Enables SSL | boolean |
|
||||
| `--certPath` | Path to your certificate file | string |
|
||||
| `--keyPath` | Path to your private key file | string |
|
||||
| `--autorun` | Automatically launch SillyTavern in the browser | boolean |
|
||||
| `--autorunHostname` | Autorun hostname | string |
|
||||
| `--autorunPortOverride` | Overrides the port for autorun | string |
|
||||
| `--avoidLocalhost` | Avoids using 'localhost' for autorun in auto mode | boolean |
|
||||
| `--corsProxy` | Enables CORS proxy | boolean |
|
||||
| `--requestProxyEnabled` | Enables a use of proxy for outgoing requests | boolean |
|
||||
| `--requestProxyUrl` | Request proxy URL (HTTP or SOCKS protocols) | string |
|
||||
| `--requestProxyBypass` | Request proxy bypass list (space separated list of hosts) | array |
|
||||
| `--disableCsrf` | Disables CSRF protection (NOT RECOMMENDED) | boolean |
|
||||
|
||||
## Remote connections
|
||||
|
||||
@@ -351,10 +368,29 @@ You may also want to configure SillyTavern user profiles with (optional) passwor
|
||||
|
||||
## Performance issues?
|
||||
|
||||
### General tips
|
||||
|
||||
1. Disable the Blur Effect and enable Reduced Motion on the User Settings panel (UI Theme toggles category).
|
||||
2. If using response streaming, set the streaming FPS to a lower value (10-15 FPS is recommended).
|
||||
3. Make sure the browser is enabled to use GPU acceleration for rendering.
|
||||
|
||||
### Input lag
|
||||
|
||||
Performance degradation, particularly input lag, is most commonly attributed to browser extensions. Known problematic extensions include:
|
||||
|
||||
* iCloud Password Manager
|
||||
* DeepL Translation
|
||||
* AI-based grammar correction tools
|
||||
* Various ad-blocking extensions
|
||||
|
||||
If you experience performance issues and cannot identify the cause, or suspect an issue with SillyTavern itself, please:
|
||||
|
||||
1. [Record a performance profile](https://developer.chrome.com/docs/devtools/performance/reference)
|
||||
2. Export the profile as a JSON file
|
||||
3. Submit it to the development team for analysis
|
||||
|
||||
We recommend first testing with all browser extensions and third-party SillyTavern extensions disabled to isolate the source of the performance degradation.
|
||||
|
||||
## License and credits
|
||||
|
||||
**This program is distributed in the hope that it will be useful,
|
||||
@@ -369,6 +405,7 @@ GNU Affero General Public License for more details.**
|
||||
* Icon theme by Font Awesome <https://fontawesome.com> (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Default content by @OtisAlejandro (Seraphina character and lorebook) and @kallmeflocc (10K Discord Users Celebratory Background)
|
||||
* Docker guide by [@mrguymiah](https://github.com/mrguymiah) and [@Bronya-Rand](https://github.com/Bronya-Rand)
|
||||
* kokoro-js library by [@hexgrad](https://github.com/hexgrad) (Apache-2.0 License)
|
||||
|
||||
## Top Contributors
|
||||
|
||||
|
28
.github/workflows/add-comment-from-tag.yml
vendored
28
.github/workflows/add-comment-from-tag.yml
vendored
@@ -1,28 +0,0 @@
|
||||
# Based on a label applied to an issue, the bot will add a comment with some additional info
|
||||
|
||||
name: 🎯 Auto-Reply to Labeled Tickets
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- labeled
|
||||
- unlabeled
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled
|
||||
- unlabeled
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Label Commenter
|
||||
uses: peaceiris/actions-label-commenter@v1
|
||||
with:
|
||||
config_file: .github/issue-auto-comments.yml
|
||||
github_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
17
.github/workflows/check-merge-conflicts.yml
vendored
17
.github/workflows/check-merge-conflicts.yml
vendored
@@ -1,17 +0,0 @@
|
||||
# Detect and label pull requests that have merge conflicts
|
||||
name: 🏗️ Check Merge Conflicts
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- staging
|
||||
jobs:
|
||||
check-conflicts:
|
||||
if: github.repository == 'SillyTavern/SillyTavern'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: mschilde/auto-label-merge-conflicts@master
|
||||
with:
|
||||
CONFLICT_LABEL_NAME: "🚫 Merge Conflicts"
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
MAX_RETRIES: 5
|
||||
WAIT_MS: 5000
|
82
.github/workflows/close-stale-issues.yml
vendored
82
.github/workflows/close-stale-issues.yml
vendored
@@ -1,82 +0,0 @@
|
||||
# Closes any issues that no longer have user interaction
|
||||
name: 🎯 Close Stale Issues
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # Runs every day at midnight UTC
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Comment on, then close issues that haven't been updated for ages
|
||||
- name: Close Stale Issues
|
||||
uses: actions/stale@v4
|
||||
with:
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 183
|
||||
days-before-close: 7
|
||||
operations-per-run: 30
|
||||
remove-stale-when-updated: true
|
||||
enable-statistics: true
|
||||
stale-issue-message: >
|
||||
This issue has gone 6 months without an update. To keep the ticket open, please indicate that it is still relevant in a comment below.
|
||||
Otherwise it will be closed in 7 days.
|
||||
stale-pr-message: >
|
||||
This PR is stale because it has been open 6 months with no activity. Either remove the stale label or comment below with a short update,
|
||||
otherwise this PR will be closed in 7 days.
|
||||
close-issue-message: >
|
||||
This issue was automatically closed because it has been stalled for over 6 months with no activity.
|
||||
close-pr-message: >
|
||||
This pull request was automatically closed because it has been stalled for over 6 months with no activity.
|
||||
stale-issue-label: '⚰️ Stale'
|
||||
close-issue-label: '🕸️ Inactive'
|
||||
stale-pr-label: '⚰️ Stale'
|
||||
close-pr-label: '🕸️ Inactive'
|
||||
exempt-issue-labels: '📌 Keep Open'
|
||||
exempt-pr-labels: '📌 Keep Open'
|
||||
labels-to-add-when-unstale: '📌 Keep Open'
|
||||
|
||||
# Comment on, then close issues that required a response from the user, but didn't get one
|
||||
- name: Close Issues without Response
|
||||
uses: actions/stale@v4
|
||||
with:
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 7
|
||||
days-before-close: 7
|
||||
operations-per-run: 30
|
||||
remove-stale-when-updated: true
|
||||
stale-issue-message: >
|
||||
Hi! Looks like additional info is required for this issue to be addressed.
|
||||
Don't forget to provide this within the next few days to keep your ticket open.
|
||||
close-issue-message: 'Issue closed due to no response from user.'
|
||||
only-labels: '🚏 Awaiting User Response'
|
||||
labels-to-remove-when-unstale: '🚏 Awaiting User Response, 🛑 No Response'
|
||||
stale-issue-label: '🛑 No Response'
|
||||
close-issue-label: '🕸️ Inactive'
|
||||
exempt-issue-labels: '📌 Keep Open'
|
||||
exempt-pr-labels: '📌 Keep Open'
|
||||
|
||||
# Comment on issues that we should have replied to
|
||||
- name: Notify Repo Owner to Respond
|
||||
uses: actions/stale@v4
|
||||
with:
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 7
|
||||
days-before-close: 183
|
||||
operations-per-run: 30
|
||||
remove-stale-when-updated: true
|
||||
stale-issue-message: Hey SillyTavern, - Don't forget to respond!
|
||||
stale-pr-message: Hey SillyTavern, - Don't forget to respond!
|
||||
only-labels: '👤 Awaiting Maintainer Response'
|
||||
labels-to-remove-when-unstale: '👤 Awaiting Maintainer Response'
|
||||
close-issue-message: 'Closed due to no response from repo author for over a year'
|
||||
close-pr-message: 'Closed due to no response from repo author for over a year'
|
||||
stale-issue-label: '👤 Awaiting Maintainer Response'
|
||||
stale-pr-label: '👤 Awaiting Maintainer Response'
|
||||
close-issue-label: '🕸️ Inactive'
|
||||
close-pr-label: '🕸️ Inactive'
|
||||
exempt-issue-labels: '📌 Keep Open'
|
||||
exempt-pr-labels: '📌 Keep Open'
|
39
.github/workflows/get-pr-size.yml
vendored
39
.github/workflows/get-pr-size.yml
vendored
@@ -1,39 +0,0 @@
|
||||
# Adds a comment to new PRs, showing the compressed size and size difference of new code
|
||||
# And also labels the PR based on the number of lines changes
|
||||
|
||||
name: 🌈 Check PR Size
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
# Find and comment with compressed size
|
||||
- name: Get Compressed Size
|
||||
uses: preactjs/compressed-size-action@v2
|
||||
with:
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
pattern: './dist/**/*.{js,css,html}'
|
||||
strip-hash: '\\b\\w{8}\\.'
|
||||
exclude: '**/node_modules/**'
|
||||
minimum-change-threshold: 100
|
||||
# Check number of lines of code added
|
||||
- name: Label based on Lines of Code
|
||||
uses: codelytv/pr-size-labeler@v1
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
xs_max_size: '10'
|
||||
s_max_size: '100'
|
||||
m_max_size: '500'
|
||||
l_max_size: '1000'
|
||||
s_label: '🟩 PR - Small'
|
||||
m_label: '🟨 PR - Medium'
|
||||
l_label: '🟧 PR - Large'
|
||||
xl_label: '🟥 PR - XL'
|
||||
fail_if_xl: 'false'
|
||||
message_if_xl: >
|
||||
It looks like this PR is very large (over 1000 lines).
|
||||
Try to avoid addressing multiple issues in a single PR, and
|
||||
in the future consider breaking large tasks down into smaller steps.
|
||||
This it to make reviewing, testing, reverting and general quality management easier.
|
112
.github/workflows/issues-auto-manager.yml
vendored
Normal file
112
.github/workflows/issues-auto-manager.yml
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
name: 🛠️ Issues Manager
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited, labeled, unlabeled]
|
||||
# Re also listen to comments, to remove stale labels right away
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
label-on-content:
|
||||
name: 🏷️ Label Issues by Content
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
# Checkout
|
||||
# https://github.com/marketplace/actions/checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Auto-Label Issues (Based on Issue Content)
|
||||
# only auto label based on issue content once, on open (to prevent re-labeling removed labels)
|
||||
if: github.event.action == 'opened'
|
||||
|
||||
# Issue Labeler
|
||||
# https://github.com/marketplace/actions/regex-issue-labeler
|
||||
uses: github/issue-labeler@v3
|
||||
with:
|
||||
configuration-path: .github/issues-auto-labels.yml
|
||||
enable-versioned-regex: 0
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
||||
label-on-labels:
|
||||
name: 🏷️ Label Issues by Labels
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: ✅ Add "👍 Approved" for relevant labels
|
||||
if: contains(fromJSON('["👩💻 Good First Issue", "🙏 Help Wanted", "🪲 Confirmed", "⚠️ High Priority", "❕ Medium Priority", "💤 Low Priority"]'), github.event.label.name)
|
||||
# 🤖 Issues Helper
|
||||
# https://github.com/marketplace/actions/issues-helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'add-labels'
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
labels: '👍 Approved'
|
||||
|
||||
- name: ❌ Remove progress labels when issue is marked done or stale
|
||||
if: contains(fromJSON('["✅ Done", "✅ Done (staging)", "⚰️ Stale", "❌ wontfix"]'), github.event.label.name)
|
||||
# 🤖 Issues Helper
|
||||
# https://github.com/marketplace/actions/issues-helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
labels: '🧑💻 In Progress,🤔 Unsure,🤔 Under Consideration'
|
||||
|
||||
- name: ❌ Remove temporary labels when confirmed labels are added
|
||||
if: contains(fromJSON('["❌ wontfix","👍 Approved","👩💻 Good First Issue"]'), github.event.label.name)
|
||||
# 🤖 Issues Helper
|
||||
# https://github.com/marketplace/actions/issues-helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
labels: '🤔 Unsure,🤔 Under Consideration'
|
||||
|
||||
- name: ❌ Remove no bug labels when "🪲 Confirmed" is added
|
||||
if: github.event.label.name == '🪲 Confirmed'
|
||||
# 🤖 Issues Helper
|
||||
# https://github.com/marketplace/actions/issues-helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
labels: '✖️ Not Reproducible,✖️ Not A Bug'
|
||||
|
||||
remove-stale-label:
|
||||
name: 🗑️ Remove Stale Label on Comment
|
||||
runs-on: ubuntu-latest
|
||||
# Only run this on new comments, to automatically remove the stale label
|
||||
if: github.event_name == 'issue_comment' && github.actor != 'github-actions[bot]'
|
||||
|
||||
steps:
|
||||
- name: Remove Stale Label
|
||||
# 🤖 Issues Helper
|
||||
# https://github.com/marketplace/actions/issues-helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: '⚰️ Stale,🕸️ Inactive,🚏 Awaiting User Response,🛑 No Response'
|
||||
|
||||
write-auto-comments:
|
||||
name: 💬 Post Issue Comments Based on Labels
|
||||
needs: [label-on-content, label-on-labels]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
# Checkout
|
||||
# https://github.com/marketplace/actions/checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Post Issue Comments Based on Labels
|
||||
# Label Commenter
|
||||
# https://github.com/marketplace/actions/label-commenter
|
||||
uses: peaceiris/actions-label-commenter@v1
|
||||
with:
|
||||
config_file: .github/issues-auto-comments.yml
|
||||
github_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
41
.github/workflows/issues-updates-on-merge.yml
vendored
Normal file
41
.github/workflows/issues-updates-on-merge.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: 🔄 Update Issues on Push
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- staging
|
||||
- release
|
||||
|
||||
jobs:
|
||||
# This runs commits to staging/release, reading the commit messages. Check `pr-auto-manager.yml`:`update-linked-issues` for PR-linked updates.
|
||||
update-linked-issues:
|
||||
name: 🔗 Mark Linked Issues Done on Push
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
# Checkout
|
||||
# https://github.com/marketplace/actions/checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Extract Linked Issues from Commit Message
|
||||
id: extract_issues
|
||||
run: |
|
||||
ISSUES=$(git log -1 --pretty=%B | grep -oiE '(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved) #([0-9]+)' | awk '{print $2}' | tr -d '#' | jq -R -s -c 'split("\n")[:-1]')
|
||||
echo "issues=$ISSUES" >> $GITHUB_ENV
|
||||
|
||||
- name: Label Linked Issues
|
||||
id: label_linked_issues
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
for ISSUE in $(echo $issues | jq -r '.[]'); do
|
||||
if [ "${{ github.ref }}" == "refs/heads/staging" ]; then
|
||||
LABEL="✅ Done (staging)"
|
||||
gh issue edit $ISSUE -R ${{ github.repository }} --add-label "$LABEL"
|
||||
elif [ "${{ github.ref }}" == "refs/heads/release" ]; then
|
||||
LABEL="✅ Done"
|
||||
gh issue edit $ISSUE -R ${{ github.repository }} --add-label "$LABEL"
|
||||
fi
|
||||
echo "Added label '$LABEL' to issue #$ISSUE"
|
||||
done
|
95
.github/workflows/job-close-stale.yml
vendored
Normal file
95
.github/workflows/job-close-stale.yml
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
name: 🕒 Close Stale Issues/PRs Workflow
|
||||
|
||||
on:
|
||||
# Run the workflow every day
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # Runs every day at midnight UTC
|
||||
|
||||
jobs:
|
||||
mark-inactivity:
|
||||
name: ⏳ Mark Issues/PRs without Activity
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Mark Issues/PRs without Activity
|
||||
# Close Stale Issues and PRs
|
||||
# https://github.com/marketplace/actions/close-stale-issues
|
||||
uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 183
|
||||
days-before-close: 7
|
||||
operations-per-run: 30
|
||||
remove-stale-when-updated: true
|
||||
enable-statistics: true
|
||||
stale-issue-message: >
|
||||
⏳ This issue has been inactive for 6 months. If it's still relevant, drop a comment below to keep it open.
|
||||
Otherwise, it will be auto-closed in 7 days.
|
||||
stale-pr-message: >
|
||||
⏳ This PR has been inactive for 6 months. If it's still relevant, update it or remove the stale label.
|
||||
Otherwise, it will be auto-closed in 7 days.
|
||||
close-issue-message: >
|
||||
🔒 This issue was auto-closed due to inactivity for over 6 months.
|
||||
close-pr-message: >
|
||||
🔒 This PR was auto-closed due to inactivity for over 6 months.
|
||||
stale-issue-label: '⚰️ Stale'
|
||||
close-issue-label: '🕸️ Inactive'
|
||||
stale-pr-label: '⚰️ Stale'
|
||||
close-pr-label: '🕸️ Inactive'
|
||||
exempt-issue-labels: '📌 Keep Open'
|
||||
exempt-pr-labels: '📌 Keep Open'
|
||||
|
||||
await-user-response:
|
||||
name: ⚠️ Mark Issues/PRs Awaiting User Response
|
||||
runs-on: ubuntu-latest
|
||||
needs: mark-inactivity
|
||||
|
||||
steps:
|
||||
- name: Mark Issues/PRs Awaiting User Response
|
||||
# Close Stale Issues and PRs
|
||||
# https://github.com/marketplace/actions/close-stale-issues
|
||||
uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 7
|
||||
days-before-close: 7
|
||||
operations-per-run: 30
|
||||
remove-stale-when-updated: true
|
||||
stale-issue-message: >
|
||||
⚠️ Hey! We need some more info to move forward with this issue.
|
||||
Please provide the requested details in the next few days to keep this ticket open.
|
||||
close-issue-message: >
|
||||
🔒 This issue was auto-closed due to no response from user.
|
||||
only-labels: '🚏 Awaiting User Response'
|
||||
labels-to-remove-when-unstale: '🚏 Awaiting User Response'
|
||||
stale-issue-label: '🛑 No Response'
|
||||
close-issue-label: '🕸️ Inactive'
|
||||
exempt-issue-labels: '🚧 Alternative Exists'
|
||||
|
||||
alternative-exists:
|
||||
name: 🔄 Mark Issues with Alternative Exists
|
||||
runs-on: ubuntu-latest
|
||||
needs: await-user-response
|
||||
|
||||
steps:
|
||||
- name: Mark Issues with Alternative Exists
|
||||
# Close Stale Issues and PRs
|
||||
# https://github.com/marketplace/actions/close-stale-issues
|
||||
uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 7
|
||||
days-before-close: 7
|
||||
operations-per-run: 30
|
||||
remove-stale-when-updated: true
|
||||
stale-issue-message: >
|
||||
🔄 An alternative solution has been provided for this issue.
|
||||
Did this solve your problem? If so, we'll go ahead and close it.
|
||||
If you still need help, drop a comment within the next 7 days to keep this open.
|
||||
close-issue-message: >
|
||||
✅ Closing this issue due to no confirmation on the alternative solution.
|
||||
only-labels: '🚧 Alternative Exists'
|
||||
stale-issue-label: '🚏 Awaiting User Response'
|
||||
close-issue-label: '🕸️ Inactive'
|
||||
exempt-issue-labels: '📌 Keep Open'
|
19
.github/workflows/labeler.yml
vendored
19
.github/workflows/labeler.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: "Issue Labeler"
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: github/issue-labeler@v3.4
|
||||
with:
|
||||
configuration-path: .github/labeler.yml
|
||||
# not-before: 2020-01-15T02:54:32Z # optional and will result in any issues prior to this timestamp to be ignored.
|
||||
enable-versioned-regex: 0
|
||||
repo-token: ${{ github.token }}
|
@@ -1,17 +0,0 @@
|
||||
# When a new comment is added to an issue, if it had the Stale or Awaiting User Response labels, then those labels will be removed
|
||||
|
||||
name: 🎯 Remove Pending Labels on Close
|
||||
on:
|
||||
issues:
|
||||
types: [closed]
|
||||
jobs:
|
||||
remove-labels:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Remove Labels when Closed
|
||||
uses: actions-cool/issues-helper@v2
|
||||
with:
|
||||
actions: remove-labels
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: '🚏 Awaiting User Response,⚰️ Stale,👤 Awaiting Maintainer Response'
|
42
.github/workflows/manage-pending-labels.yml
vendored
42
.github/workflows/manage-pending-labels.yml
vendored
@@ -1,42 +0,0 @@
|
||||
# When a new comment is added to an issue, if it had the Stale or Awaiting User Response labels, then those labels will be removed
|
||||
|
||||
name: 🎯 Add/ Remove Awaiting Response Labels
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
jobs:
|
||||
remove-stale:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.comment.author_association != 'COLLABORATOR' && github.event.comment.author_association != 'OWNER' }}
|
||||
steps:
|
||||
- name: Remove Stale labels when Updated
|
||||
uses: actions-cool/issues-helper@v2
|
||||
with:
|
||||
actions: remove-labels
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: '🚏 Awaiting User Response,⚰️ Stale'
|
||||
|
||||
add-awaiting-author:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{!github.event.issue.pull_request && github.event.comment.author_association != 'COLLABORATOR' && github.event.comment.author_association != 'OWNER' && github.event.issue.state == 'open' }}
|
||||
steps:
|
||||
- name: Add Awaiting Author labels when Updated
|
||||
uses: actions-cool/issues-helper@v2
|
||||
with:
|
||||
actions: add-labels
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: '👤 Awaiting Maintainer Response'
|
||||
|
||||
remove-awaiting-author:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.comment.author_association == 'OWNER' }}
|
||||
steps:
|
||||
- name: Remove Awaiting Author labels when Updated
|
||||
uses: actions-cool/issues-helper@v2
|
||||
with:
|
||||
actions: remove-labels
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: '👤 Awaiting Maintainer Response'
|
23
.github/workflows/on-close-handler.yml
vendored
Normal file
23
.github/workflows/on-close-handler.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: 🚪 Issues/PRs On Close Handler
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [closed]
|
||||
pull_request_target:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
remove-labels:
|
||||
name: 🗑️ Remove Pending Labels on Close
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Remove Pending Labels on Close
|
||||
# 🤖 Issues Helper
|
||||
# https://github.com/marketplace/actions/issues-helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: remove-labels
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number || github.event.pull_request.number }}
|
||||
labels: '🚏 Awaiting User Response,🧑💻 In Progress,📌 Keep Open,🚫 Merge Conflicts,🔬 Needs Testing,🔨 Needs Work,⚰️ Stale,⛔ Waiting For External/Upstream'
|
24
.github/workflows/on-open-handler.yml
vendored
Normal file
24
.github/workflows/on-open-handler.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: 📨 Issues/PRs Open Handler
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
label-maintainer:
|
||||
name: 🏷️ Label if Author is a Repo Maintainer
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(fromJson('["Cohee1207", "RossAscends", "Wolfsblvt"]'), github.actor)
|
||||
|
||||
steps:
|
||||
- name: Label if Author is a Repo Maintainer
|
||||
# 🤖 Issues Helper
|
||||
# https://github.com/marketplace/actions/issues-helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'add-labels'
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number || github.event.pull_request.number }}
|
||||
labels: '👷 Maintainer'
|
192
.github/workflows/pr-auto-manager.yml
vendored
Normal file
192
.github/workflows/pr-auto-manager.yml
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
name: 🔀 Pull Request Manager
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, edited, labeled, unlabeled, closed]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
label-by-size:
|
||||
name: 🏷️ Label PR by Size
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Label PR Size
|
||||
# Pull Request Size Labeler
|
||||
# https://github.com/marketplace/actions/pull-request-size-labeler
|
||||
uses: codelytv/pr-size-labeler@v1
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
xs_label: '🟩 ⬤○○○○'
|
||||
xs_max_size: '20'
|
||||
s_label: '🟩 ⬤⬤○○○'
|
||||
s_max_size: '100'
|
||||
m_label: '🟨 ⬤⬤⬤○○'
|
||||
m_max_size: '500'
|
||||
l_label: '🟧 ⬤⬤⬤⬤○'
|
||||
l_max_size: '1000'
|
||||
xl_label: '🟥 ⬤⬤⬤⬤⬤'
|
||||
fail_if_xl: 'false'
|
||||
github_api_url: 'https://api.github.com'
|
||||
files_to_ignore: |
|
||||
"package-lock.json"
|
||||
"public/lib/*"
|
||||
|
||||
label-by-branches:
|
||||
name: 🏷️ Label PR by Branches
|
||||
runs-on: ubuntu-latest
|
||||
# Only label once when PR is created or branches are changed, to allow manual label removal
|
||||
if: github.event.action == 'opened' || (github.event.action == 'synchronize' && (github.event.changes.base || github.event.changes.head))
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
# Checkout
|
||||
# https://github.com/marketplace/actions/checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Apply Labels Based on Branch Name and Target Branch
|
||||
# Pull Request Labeler
|
||||
# https://github.com/marketplace/actions/labeler
|
||||
uses: actions/labeler@v5
|
||||
with:
|
||||
configuration-path: .github/pr-auto-labels-by-branch.yml
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
||||
label-by-files:
|
||||
name: 🏷️ Label PR by Files
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
# Checkout
|
||||
# https://github.com/marketplace/actions/checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Apply Labels Based on Changed Files
|
||||
# Pull Request Labeler
|
||||
# https://github.com/marketplace/actions/labeler
|
||||
uses: actions/labeler@v5
|
||||
with:
|
||||
configuration-path: .github/pr-auto-labels-by-files.yml
|
||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
||||
remove-stale-label:
|
||||
name: 🗑️ Remove Stale Label on Comment
|
||||
runs-on: ubuntu-latest
|
||||
# Only runs when this is not done by the github actions bot
|
||||
if: github.actor != 'github-actions[bot]'
|
||||
|
||||
steps:
|
||||
- name: Remove Stale Label
|
||||
# 🤖 Issues Helper
|
||||
# https://github.com/marketplace/actions/issues-helper
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
labels: '⚰️ Stale'
|
||||
|
||||
check-merge-blocking-labels:
|
||||
name: 🚫 Check Merge Blocking Labels
|
||||
needs: [label-by-branches, label-by-files]
|
||||
runs-on: ubuntu-latest
|
||||
# Run, even if the previous jobs were skipped/failed
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Check Merge Blocking
|
||||
# GitHub Script
|
||||
# https://github.com/marketplace/actions/github-scriptLabels
|
||||
id: label-check
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const prLabels = context.payload.pull_request.labels.map(label => label.name);
|
||||
const blockingLabels = [
|
||||
"⛔ Don't Merge",
|
||||
"🔨 Needs Work",
|
||||
"🔬 Needs Testing",
|
||||
"⛔ Waiting For External/Upstream",
|
||||
"❗ Against Release Branch",
|
||||
"💥💣 Breaking Changes"
|
||||
];
|
||||
const hasBlockingLabel = prLabels.some(label => blockingLabels.includes(label));
|
||||
|
||||
if (hasBlockingLabel) {
|
||||
console.log("Blocking label detected. Setting warning status.");
|
||||
await github.rest.checks.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: "PR Label Warning",
|
||||
head_sha: context.payload.pull_request.head.sha,
|
||||
status: "completed",
|
||||
conclusion: "neutral",
|
||||
output: {
|
||||
title: "Potential Merge Issue",
|
||||
summary: "This PR has a merge-blocking label. Proceed with caution."
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log("No merge-blocking labels found.");
|
||||
}
|
||||
|
||||
write-auto-comments:
|
||||
name: 💬 Post PR Comments Based on Labels
|
||||
needs: [label-by-size, label-by-branches, label-by-files]
|
||||
runs-on: ubuntu-latest
|
||||
# Run, even if the previous jobs were skipped/failed
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
# Checkout
|
||||
# https://github.com/marketplace/actions/checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Post PR Comments Based on Labels
|
||||
# Label Commenter for PRs
|
||||
# https://github.com/marketplace/actions/label-commenter
|
||||
uses: peaceiris/actions-label-commenter@v1
|
||||
with:
|
||||
config_file: .github/pr-auto-comments.yml
|
||||
github_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
||||
# This runs on merged PRs to staging, reading the PR body and directly linked issues. Check `issues-updates-on-merge.yml`:`update-linked-issues` for commit-based updates.
|
||||
update-linked-issues:
|
||||
name: 🔗 Mark Linked Issues Done on Staging Merge
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'staging'
|
||||
|
||||
steps:
|
||||
- name: Extract Linked Issues From PR Description
|
||||
id: extract_issues
|
||||
run: |
|
||||
ISSUES=$(jq -r '.pull_request.body' "$GITHUB_EVENT_PATH" | grep -oiE '(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved) #([0-9]+)' | awk '{print $2}' | tr -d '#' | jq -R -s -c 'split("\n")[:-1]')
|
||||
echo "issues=$ISSUES" >> $GITHUB_ENV
|
||||
|
||||
- name: Fetch Directly Linked Issues
|
||||
id: fetch_linked_issues
|
||||
run: |
|
||||
PR_NUMBER=${{ github.event.pull_request.number }}
|
||||
REPO=${{ github.repository }}
|
||||
API_URL="https://api.github.com/repos/$REPO/pulls/$PR_NUMBER/issues"
|
||||
ISSUES=$(curl -s -H "Authorization: token ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}" "$API_URL" | jq -r '.[].number' | jq -R -s -c 'split("\n")[:-1]')
|
||||
echo "linked_issues=$ISSUES" >> $GITHUB_ENV
|
||||
|
||||
- name: Merge Issue Lists
|
||||
id: merge_issues
|
||||
run: |
|
||||
ISSUES=$(jq -c -n --argjson a "$issues" --argjson b "$linked_issues" '$a + $b | unique')
|
||||
echo "final_issues=$ISSUES" >> $GITHUB_ENV
|
||||
|
||||
- name: Label Linked Issues
|
||||
id: label_linked_issues
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
for ISSUE in $(echo $final_issues | jq -r '.[]'); do
|
||||
gh issue edit $ISSUE -R ${{ github.repository }} --add-label "✅ Done (staging)"
|
||||
echo "Added label '✅ Done (staging)' to issue #$ISSUE"
|
||||
done
|
24
.github/workflows/pr-check-merge-conflicts.yaml
vendored
Normal file
24
.github/workflows/pr-check-merge-conflicts.yaml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: ⚔️ Check Merge Conflicts
|
||||
|
||||
on:
|
||||
# So that PRs touching the same files as the push are updated
|
||||
push:
|
||||
# So that the `dirtyLabel` is removed if conflicts are resolved
|
||||
pull_request_target:
|
||||
types: [synchronize]
|
||||
|
||||
jobs:
|
||||
check-merge-conflicts:
|
||||
name: ⚔️ Check Merge Conflicts
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check Merge Conflicts
|
||||
# Label Conflicting Pull Requests
|
||||
# https://github.com/marketplace/actions/label-conflicting-pull-requests
|
||||
uses: eps1lon/actions-label-merge-conflict@v3
|
||||
with:
|
||||
dirtyLabel: '🚫 Merge Conflicts'
|
||||
repoToken: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
commentOnDirty: >
|
||||
⚠️ This PR has conflicts that need to be resolved before it can be merged.
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -45,6 +45,7 @@ access.log
|
||||
/vectors/
|
||||
/cache/
|
||||
public/css/user.css
|
||||
public/error/
|
||||
/plugins/
|
||||
/data
|
||||
/default/scaffold
|
||||
@@ -52,3 +53,5 @@ public/scripts/extensions/third-party
|
||||
/certs
|
||||
.aider*
|
||||
.env
|
||||
/StartDev.bat
|
||||
|
||||
|
@@ -4,7 +4,7 @@ FROM node:lts-alpine3.19
|
||||
ARG APP_HOME=/home/node/app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apk add gcompat tini git
|
||||
RUN apk add --no-cache gcompat tini git
|
||||
|
||||
# Create app directory
|
||||
WORKDIR ${APP_HOME}
|
||||
|
13
default/!DO-NOT-EDIT-THESE-FILES.txt
Normal file
13
default/!DO-NOT-EDIT-THESE-FILES.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
These are master copies of the default content files and are managed by SillyTavern.
|
||||
|
||||
Editing any of these files would not only have no effect, but will also cause merge conflicts during update pulls.
|
||||
|
||||
You should edit their respective copies instead, for example:
|
||||
|
||||
1. /default/config.yaml => /config.yaml
|
||||
2. /default/public/css/user.css => /public/css/user.css
|
||||
etc.
|
||||
|
||||
Any questions? You're always welcome at our official documentation website:
|
||||
|
||||
https://docs.sillytavern.app/
|
@@ -1,12 +1,16 @@
|
||||
# -- DATA CONFIGURATION --
|
||||
# Root directory for user data storage
|
||||
dataRoot: ./data
|
||||
# The maximum amount of memory that parsed character cards can use in MB
|
||||
cardsCacheCapacity: 100
|
||||
# -- SERVER CONFIGURATION --
|
||||
# Listen for incoming connections
|
||||
listen: false
|
||||
# Listen on a specific address, supports IPv4 and IPv6
|
||||
listenAddress:
|
||||
ipv4: 0.0.0.0
|
||||
ipv6: '[::]'
|
||||
# Enables IPv6 and/or IPv4 protocols. Need to have at least one enabled!
|
||||
# - Use option "auto" to automatically detect support
|
||||
# - Use true or false (no qoutes) to enable or disable each protocol
|
||||
protocol:
|
||||
ipv4: true
|
||||
ipv6: false
|
||||
@@ -22,6 +26,11 @@ port: 8000
|
||||
# - Use -1 to use the server port.
|
||||
# - Specify a port to override the default.
|
||||
autorunPortOverride: -1
|
||||
# -- SSL options --
|
||||
ssl:
|
||||
enabled: false
|
||||
certPath: "./certs/cert.pem"
|
||||
keyPath: "./certs/privkey.pem"
|
||||
# -- SECURITY CONFIGURATION --
|
||||
# Toggle whitelist mode
|
||||
whitelistMode: true
|
||||
@@ -31,6 +40,8 @@ enableForwardedWhitelist: true
|
||||
whitelist:
|
||||
- ::1
|
||||
- 127.0.0.1
|
||||
# Automatically whitelist Docker host and gateway IPs
|
||||
whitelistDockerHosts: true
|
||||
# Toggle basic authentication for endpoints
|
||||
basicAuthMode: false
|
||||
# Basic authentication credentials
|
||||
@@ -70,13 +81,23 @@ perUserBasicAuth: false
|
||||
## Set to a positive number to expire session after a certain time of inactivity
|
||||
## Set to 0 to expire session when the browser is closed
|
||||
## Set to a negative number to disable session expiration
|
||||
sessionTimeout: 86400
|
||||
# Used to sign session cookies. Will be auto-generated if not set
|
||||
cookieSecret: ''
|
||||
sessionTimeout: -1
|
||||
# Disable CSRF protection - NOT RECOMMENDED
|
||||
disableCsrfProtection: false
|
||||
# Disable startup security checks - NOT RECOMMENDED
|
||||
securityOverride: false
|
||||
# -- LOGGING CONFIGURATION --
|
||||
logging:
|
||||
# Enable access logging to access.log file
|
||||
# Records new connections with timestamp, IP address and user agent
|
||||
enableAccessLog: true
|
||||
# Minimum log level to display in the terminal (DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3)
|
||||
minLogLevel: 0
|
||||
# -- RATE LIMITING CONFIGURATION --
|
||||
rateLimiting:
|
||||
# Use X-Real-IP header instead of socket IP for rate limiting
|
||||
# Only enable this if you are using a properly configured reverse proxy (like Nginx/traefik/Caddy)
|
||||
preferRealIpHeader: false
|
||||
# -- ADVANCED CONFIGURATION --
|
||||
# Open the browser automatically
|
||||
autorun: true
|
||||
@@ -84,6 +105,20 @@ autorun: true
|
||||
# use if you don't have 'localhost' in your hosts file
|
||||
avoidLocalhost: false
|
||||
|
||||
## BACKUP CONFIGURATION
|
||||
backups:
|
||||
# Common settings for all backup types
|
||||
common:
|
||||
# Number of backups to keep for each chat and settings file
|
||||
numberOfBackups: 50
|
||||
chat:
|
||||
# Enable automatic chat backups
|
||||
enabled: true
|
||||
# Maximum number of chat backups to keep per user (starting from the most recent). Set to -1 to keep all backups.
|
||||
maxTotalBackups: -1
|
||||
# Interval in milliseconds to throttle chat backups per user
|
||||
throttleInterval: 10000
|
||||
|
||||
# THUMBNAILING CONFIGURATION
|
||||
thumbnails:
|
||||
# Enable thumbnail generation
|
||||
@@ -98,18 +133,18 @@ thumbnails:
|
||||
# Maximum thumbnail dimensions per type [width, height]
|
||||
dimensions: { 'bg': [160, 90], 'avatar': [96, 144] }
|
||||
|
||||
# PERFORMANCE-RELATED CONFIGURATION
|
||||
performance:
|
||||
# Enables lazy loading of character cards. Improves performances with large card libraries.
|
||||
# May have compatibility issues with some extensions.
|
||||
lazyLoadCharacters: false
|
||||
# The maximum amount of memory that parsed character cards can use. Set to 0 to disable memory caching.
|
||||
memoryCacheCapacity: '100mb'
|
||||
|
||||
# Allow secret keys exposure via API
|
||||
allowKeysExposure: false
|
||||
# Skip new default content checks
|
||||
skipContentCheck: false
|
||||
# Disable automatic chats backup
|
||||
disableChatBackup: false
|
||||
# Number of backups to keep for each chat and settings file
|
||||
numberOfBackups: 50
|
||||
# Maximum number of chat backups to keep per user (starting from the most recent). Set to -1 to keep all backups.
|
||||
maxTotalChatBackups: -1
|
||||
# Interval in milliseconds to throttle chat backups per user
|
||||
chatBackupThrottleInterval: 10000
|
||||
# Allowed hosts for card downloads
|
||||
whitelistImportDomains:
|
||||
- localhost
|
||||
@@ -127,24 +162,26 @@ whitelistImportDomains:
|
||||
## headers:
|
||||
## User-Agent: "Googlebot/2.1 (+http://www.google.com/bot.html)"
|
||||
requestOverrides: []
|
||||
# -- EXTENSIONS CONFIGURATION --
|
||||
# Enable UI extensions
|
||||
enableExtensions: true
|
||||
# Automatically update extensions when a release version changes
|
||||
enableExtensionsAutoUpdate: true
|
||||
|
||||
# EXTENSIONS CONFIGURATION
|
||||
extensions:
|
||||
# Enable UI extensions
|
||||
enabled: true
|
||||
# Automatically update extensions when a release version changes
|
||||
autoUpdate: true
|
||||
models:
|
||||
# Enables automatic model download from HuggingFace
|
||||
autoDownload: true
|
||||
# Additional models for extensions. Expects model IDs from HuggingFace model hub in ONNX format
|
||||
classification: Cohee/distilbert-base-uncased-go-emotions-onnx
|
||||
captioning: Xenova/vit-gpt2-image-captioning
|
||||
embedding: Cohee/jina-embeddings-v2-base-en
|
||||
speechToText: Xenova/whisper-small
|
||||
textToSpeech: Xenova/speecht5_tts
|
||||
|
||||
# Additional model tokenizers can be downloaded on demand.
|
||||
# Disabling will fallback to another locally available tokenizer.
|
||||
enableDownloadableTokenizers: true
|
||||
# Extension settings
|
||||
extras:
|
||||
# Disables automatic model download from HuggingFace
|
||||
disableAutoDownload: false
|
||||
# Extra models for plugins. Expects model IDs from HuggingFace model hub in ONNX format
|
||||
classificationModel: Cohee/distilbert-base-uncased-go-emotions-onnx
|
||||
captioningModel: Xenova/vit-gpt2-image-captioning
|
||||
embeddingModel: Cohee/jina-embeddings-v2-base-en
|
||||
speechToTextModel: Xenova/whisper-small
|
||||
textToSpeechModel: Xenova/speecht5_tts
|
||||
# -- OPENAI CONFIGURATION --
|
||||
# A placeholder message to use in strict prompt post-processing mode when the prompt doesn't start with a user message
|
||||
promptPlaceholder: "[Start a new chat]"
|
||||
@@ -171,6 +208,10 @@ ollama:
|
||||
# * 0: Unload the model immediately after the request
|
||||
# * N (any positive number): Keep the model loaded for N seconds after the request.
|
||||
keepAlive: -1
|
||||
# Controls the "num_batch" (batch size) parameter of the generation request
|
||||
# * -1: Use the default value of the model
|
||||
# * N (positive number): Use the specified value. Must be a power of 2, e.g. 128, 256, 512, etc.
|
||||
batchSize: -1
|
||||
# -- ANTHROPIC CLAUDE API CONFIGURATION --
|
||||
claude:
|
||||
# Enables caching of the system prompt (if supported).
|
||||
@@ -190,3 +231,5 @@ claude:
|
||||
cachingAtDepth: -1
|
||||
# -- SERVER PLUGIN CONFIGURATION --
|
||||
enableServerPlugins: false
|
||||
# Attempt to automatically update server plugins on startup
|
||||
enableServerPluginsAutoUpdate: true
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 8.1 KiB |
@@ -671,10 +671,6 @@
|
||||
"filename": "presets/moving-ui/Default.json",
|
||||
"type": "moving_ui"
|
||||
},
|
||||
{
|
||||
"filename": "presets/moving-ui/Black Magic Time.json",
|
||||
"type": "moving_ui"
|
||||
},
|
||||
{
|
||||
"filename": "presets/quick-replies/Default.json",
|
||||
"type": "quick_replies"
|
||||
@@ -782,5 +778,13 @@
|
||||
{
|
||||
"filename": "presets/context/Mistral V7.json",
|
||||
"type": "context"
|
||||
},
|
||||
{
|
||||
"filename": "presets/instruct/DeepSeek-V2.5.json",
|
||||
"type": "instruct"
|
||||
},
|
||||
{
|
||||
"filename": "presets/context/DeepSeek-V2.5.json",
|
||||
"type": "context"
|
||||
}
|
||||
]
|
||||
|
11
default/content/presets/context/DeepSeek-V2.5.json
Normal file
11
default/content/presets/context/DeepSeek-V2.5.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"story_string": "{{#if system}}{{system}}\n{{/if}}{{#if wiBefore}}{{wiBefore}}\n{{/if}}{{#if description}}{{description}}\n{{/if}}{{#if personality}}{{char}}'s personality: {{personality}}\n{{/if}}{{#if scenario}}Scenario: {{scenario}}\n{{/if}}{{#if wiAfter}}{{wiAfter}}\n{{/if}}{{#if persona}}{{persona}}\n{{/if}}{{trim}}\n",
|
||||
"example_separator": "",
|
||||
"chat_start": "",
|
||||
"use_stop_strings": false,
|
||||
"allow_jailbreak": false,
|
||||
"always_force_name2": true,
|
||||
"trim_sentences": false,
|
||||
"single_line": false,
|
||||
"name": "DeepSeek-V2.5"
|
||||
}
|
22
default/content/presets/instruct/DeepSeek-V2.5.json
Normal file
22
default/content/presets/instruct/DeepSeek-V2.5.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"input_sequence": "<|User|>",
|
||||
"output_sequence": "<|Assistant|>",
|
||||
"first_output_sequence": "",
|
||||
"last_output_sequence": "",
|
||||
"system_sequence_prefix": "",
|
||||
"system_sequence_suffix": "",
|
||||
"stop_sequence": "",
|
||||
"wrap": false,
|
||||
"macro": true,
|
||||
"names_behavior": "force",
|
||||
"activation_regex": "",
|
||||
"skip_examples": false,
|
||||
"output_suffix": "<|end▁of▁sentence|>",
|
||||
"input_suffix": "",
|
||||
"system_sequence": "",
|
||||
"system_suffix": "",
|
||||
"user_alignment_message": "",
|
||||
"last_system_sequence": "",
|
||||
"system_same_as_user": true,
|
||||
"name": "DeepSeek-V2.5"
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
@@ -28,12 +28,11 @@
|
||||
"wrap_in_quotes": false,
|
||||
"names_behavior": 0,
|
||||
"send_if_empty": "",
|
||||
"jailbreak_system": false,
|
||||
"impersonation_prompt": "[Write your next reply from the point of view of {{user}}, using the chat history so far as a guideline for the writing style of {{user}}. Don't write as {{char}} or system. Don't describe actions of {{char}}.]",
|
||||
"new_chat_prompt": "[Start a new Chat]",
|
||||
"new_group_chat_prompt": "[Start a new group chat. Group members: {{group}}]",
|
||||
"new_example_chat_prompt": "[Example Chat]",
|
||||
"continue_nudge_prompt": "[Continue the following message. Do not include ANY parts of the original message. Use capitalization and punctuation as if your reply is a part of the original message: {{lastChatMessage}}]",
|
||||
"continue_nudge_prompt": "[Continue your last message without repeating its original content.]",
|
||||
"bias_preset_selected": "Default (none)",
|
||||
"reverse_proxy": "",
|
||||
"proxy_password": "",
|
||||
|
@@ -593,7 +593,7 @@
|
||||
"new_chat_prompt": "[Start a new Chat]",
|
||||
"new_group_chat_prompt": "[Start a new group chat. Group members: {{group}}]",
|
||||
"new_example_chat_prompt": "[Example Chat]",
|
||||
"continue_nudge_prompt": "[Continue the following message. Do not include ANY parts of the original message. Use capitalization and punctuation as if your reply is a part of the original message: {{lastChatMessage}}]",
|
||||
"continue_nudge_prompt": "[Continue your last message without repeating its original content.]",
|
||||
"bias_preset_selected": "Default (none)",
|
||||
"bias_presets": {
|
||||
"Default (none)": [],
|
||||
@@ -626,7 +626,6 @@
|
||||
"ai21_model": "jamba-1.5-large",
|
||||
"windowai_model": "",
|
||||
"openrouter_model": "OR_Website",
|
||||
"jailbreak_system": true,
|
||||
"reverse_proxy": "",
|
||||
"chat_completion_source": "openai",
|
||||
"max_context_unlocked": false,
|
||||
|
22
default/public/error/forbidden-by-whitelist.html
Normal file
22
default/public/error/forbidden-by-whitelist.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Forbidden</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Forbidden</h1>
|
||||
<p>
|
||||
If you are the system administrator, add your IP address to the
|
||||
whitelist or disable whitelist mode by editing
|
||||
<code>config.yaml</code> in the root directory of your installation.
|
||||
</p>
|
||||
<hr />
|
||||
<p>
|
||||
<em>Connection from {{ipDetails}} has been blocked. This attempt
|
||||
has been logged.</em>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
17
default/public/error/unauthorized.html
Normal file
17
default/public/error/unauthorized.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Unauthorized</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Unauthorized</h1>
|
||||
<p>
|
||||
If you are the system administrator, you can configure the
|
||||
<code>basicAuthUser</code> credentials by editing
|
||||
<code>config.yaml</code> in the root directory of your installation.
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
15
default/public/error/url-not-found.html
Normal file
15
default/public/error/url-not-found.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Not found</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Not found</h1>
|
||||
<p>
|
||||
The requested URL was not found on this server.
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
@@ -1,4 +1,4 @@
|
||||
import getWebpackServeMiddleware from '../src/middleware/webpack-serve.js';
|
||||
|
||||
const middleware = getWebpackServeMiddleware();
|
||||
await middleware.runWebpackCompiler();
|
||||
await middleware.runWebpackCompiler({ forceDist: true });
|
||||
|
@@ -1,10 +1,12 @@
|
||||
version: "3"
|
||||
services:
|
||||
sillytavern:
|
||||
build: ..
|
||||
container_name: sillytavern
|
||||
hostname: sillytavern
|
||||
image: ghcr.io/sillytavern/sillytavern:latest
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- FORCE_COLOR=1
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
|
@@ -5,5 +5,8 @@ if [ ! -e "config/config.yaml" ]; then
|
||||
cp -r "default/config.yaml" "config/config.yaml"
|
||||
fi
|
||||
|
||||
# Execute postinstall to auto-populate config.yaml with missing values
|
||||
npm run postinstall
|
||||
|
||||
# Start the server
|
||||
exec node server.js --listen "$@"
|
||||
|
62
index.d.ts
vendored
62
index.d.ts
vendored
@@ -1,6 +1,53 @@
|
||||
import { UserDirectoryList, User } from "./src/users";
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { CsrfSyncedToken } from 'csrf-sync';
|
||||
import { UserDirectoryList, User } from './src/users.js';
|
||||
import { CommandLineArguments } from './src/command-line.js';
|
||||
import { EVENT_NAMES } from './src/server-events.js';
|
||||
|
||||
/**
|
||||
* Event payload for SERVER_STARTED event.
|
||||
*/
|
||||
export interface ServerStartedEvent {
|
||||
/**
|
||||
* The URL the server is listening on.
|
||||
*/
|
||||
url: URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of all server events to their payload types.
|
||||
*/
|
||||
export interface ServerEventMap {
|
||||
[EVENT_NAMES.SERVER_STARTED]: [ServerStartedEvent];
|
||||
}
|
||||
|
||||
declare global {
|
||||
declare namespace NodeJS {
|
||||
export interface Process {
|
||||
/**
|
||||
* A global instance of the server events emitter.
|
||||
*/
|
||||
serverEvents: EventEmitter<ServerEventMap>;
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace CookieSessionInterfaces {
|
||||
export interface CookieSessionObject {
|
||||
/**
|
||||
* The CSRF token for the session.
|
||||
*/
|
||||
csrfToken: CsrfSyncedToken;
|
||||
/**
|
||||
* Authenticated user handle.
|
||||
*/
|
||||
handle: string;
|
||||
/**
|
||||
* Last time the session was extended.
|
||||
*/
|
||||
touch: number;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Express {
|
||||
export interface Request {
|
||||
user: {
|
||||
@@ -14,12 +61,9 @@ declare global {
|
||||
* The root directory for user data.
|
||||
*/
|
||||
var DATA_ROOT: string;
|
||||
}
|
||||
|
||||
declare module 'express-session' {
|
||||
export interface SessionData {
|
||||
handle: string;
|
||||
touch: number;
|
||||
// other properties...
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parsed command line arguments.
|
||||
*/
|
||||
var COMMAND_LINE_ARGS: CommandLineArguments;
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
"**/node_modules/**",
|
||||
"**/dist/**",
|
||||
"**/.git/**",
|
||||
"public/lib/**",
|
||||
"public/**",
|
||||
"backups/**",
|
||||
"data/**",
|
||||
"cache/**",
|
||||
|
1159
package-lock.json
generated
1159
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
67
package.json
67
package.json
@@ -1,37 +1,41 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@adobe/css-tools": "^4.4.0",
|
||||
"@adobe/css-tools": "^4.4.2",
|
||||
"@agnai/sentencepiece-js": "^1.1.1",
|
||||
"@agnai/web-tokenizers": "^0.1.3",
|
||||
"@iconfu/svg-inject": "^1.2.3",
|
||||
"@mozilla/readability": "^0.5.0",
|
||||
"@mozilla/readability": "^0.6.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@zeldafan0225/ai_horde": "^5.1.0",
|
||||
"@zeldafan0225/ai_horde": "^5.2.0",
|
||||
"archiver": "^7.0.1",
|
||||
"bing-translate-api": "^4.0.2",
|
||||
"body-parser": "^1.20.2",
|
||||
"bowser": "^2.11.0",
|
||||
"bytes": "^3.1.2",
|
||||
"chalk": "^5.4.1",
|
||||
"command-exists": "^1.2.9",
|
||||
"compression": "^1",
|
||||
"compression": "^1.8.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"cookie-session": "^2.1.0",
|
||||
"cors": "^2.8.5",
|
||||
"csrf-csrf": "^2.2.3",
|
||||
"csrf-sync": "^4.0.3",
|
||||
"diff-match-patch": "^1.0.5",
|
||||
"dompurify": "^3.1.7",
|
||||
"dompurify": "^3.2.4",
|
||||
"droll": "^0.2.1",
|
||||
"express": "^4.21.0",
|
||||
"form-data": "^4.0.0",
|
||||
"fuse.js": "^7.0.0",
|
||||
"form-data": "^4.0.2",
|
||||
"fuse.js": "^7.1.0",
|
||||
"google-translate-api-browser": "^3.0.1",
|
||||
"google-translate-api-x": "^10.7.1",
|
||||
"google-translate-api-x": "^10.7.2",
|
||||
"handlebars": "^4.7.8",
|
||||
"helmet": "^7.1.0",
|
||||
"highlight.js": "^11.10.0",
|
||||
"helmet": "^7.2.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
"html-entities": "^2.5.2",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"ip-matching": "^2.1.2",
|
||||
"ipaddr.js": "^2.0.1",
|
||||
"ip-regex": "^5.0.0",
|
||||
"ipaddr.js": "^2.2.0",
|
||||
"is-docker": "^3.0.0",
|
||||
"jimp": "^0.22.10",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -40,28 +44,28 @@
|
||||
"morphdom": "^2.7.4",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-fetch": "^3.3.2",
|
||||
"node-persist": "^4.0.1",
|
||||
"node-persist": "^4.0.4",
|
||||
"open": "^8.4.2",
|
||||
"png-chunk-text": "^1.0.0",
|
||||
"png-chunks-encode": "^1.0.0",
|
||||
"png-chunks-extract": "^1.0.0",
|
||||
"proxy-agent": "^6.4.0",
|
||||
"rate-limiter-flexible": "^5.0.0",
|
||||
"response-time": "^2.3.2",
|
||||
"proxy-agent": "^6.5.0",
|
||||
"rate-limiter-flexible": "^5.0.5",
|
||||
"response-time": "^2.3.3",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"seedrandom": "^3.0.5",
|
||||
"showdown": "^2.1.0",
|
||||
"sillytavern-transformers": "2.14.6",
|
||||
"simple-git": "^3.19.1",
|
||||
"simple-git": "^3.27.0",
|
||||
"slidetoggle": "^4.0.0",
|
||||
"tiktoken": "^1.0.16",
|
||||
"tiktoken": "^1.0.20",
|
||||
"url-join": "^5.0.0",
|
||||
"vectra": "^0.2.2",
|
||||
"wavefile": "^11.0.0",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack": "^5.98.0",
|
||||
"write-file-atomic": "^5.0.1",
|
||||
"ws": "^8.17.1",
|
||||
"yaml": "^2.3.4",
|
||||
"ws": "^8.18.1",
|
||||
"yaml": "^2.7.0",
|
||||
"yargs": "^17.7.1",
|
||||
"yauzl": "^2.10.0"
|
||||
},
|
||||
@@ -86,9 +90,11 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
||||
},
|
||||
"version": "1.12.10",
|
||||
"version": "1.12.13",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"debug": "node --inspect server.js",
|
||||
"start:electron": "cd ./src/electron && npm run start",
|
||||
"start:deno": "deno run --allow-run --allow-net --allow-read --allow-write --allow-sys --allow-env server.js",
|
||||
"start:bun": "bun server.js",
|
||||
"start:no-csrf": "node server.js --disableCsrf",
|
||||
@@ -107,22 +113,23 @@
|
||||
},
|
||||
"main": "server.js",
|
||||
"devDependencies": {
|
||||
"@types/archiver": "^6.0.2",
|
||||
"@types/archiver": "^6.0.3",
|
||||
"@types/bytes": "^3.1.5",
|
||||
"@types/command-exists": "^1.2.3",
|
||||
"@types/compression": "^1.7.5",
|
||||
"@types/cookie-parser": "^1.4.7",
|
||||
"@types/cookie-parser": "^1.4.8",
|
||||
"@types/cookie-session": "^2.0.49",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/deno": "^2.0.0",
|
||||
"@types/deno": "^2.2.0",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/jquery": "^3.5.29",
|
||||
"@types/jquery": "^3.5.32",
|
||||
"@types/jquery-cropper": "^1.0.4",
|
||||
"@types/jquery.transit": "^0.9.33",
|
||||
"@types/jqueryui": "^1.12.23",
|
||||
"@types/lodash": "^4.17.10",
|
||||
"@types/jqueryui": "^1.12.24",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/mime-types": "^2.1.4",
|
||||
"@types/multer": "^1.4.12",
|
||||
"@types/node": "^18.19.55",
|
||||
"@types/node": "^18.19.80",
|
||||
"@types/node-persist": "^3.1.8",
|
||||
"@types/png-chunk-text": "^1.0.3",
|
||||
"@types/png-chunks-encode": "^1.0.2",
|
||||
@@ -133,6 +140,6 @@
|
||||
"@types/write-file-atomic": "^4.0.3",
|
||||
"@types/yargs": "^17.0.33",
|
||||
"@types/yauzl": "^2.10.3",
|
||||
"eslint": "^8.57.0"
|
||||
"eslint": "^8.57.1"
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { default as git } from 'simple-git';
|
||||
import { default as git, CheckRepoActions } from 'simple-git';
|
||||
import { color } from './src/util.js';
|
||||
|
||||
const __dirname = import.meta.dirname ?? path.dirname(fileURLToPath(import.meta.url));
|
||||
@@ -48,6 +48,13 @@ async function updatePlugins() {
|
||||
console.log(`Updating plugin ${color.green(directory)}...`);
|
||||
const pluginPath = path.join(pluginsPath, directory);
|
||||
const pluginRepo = git(pluginPath);
|
||||
|
||||
const isRepo = await pluginRepo.checkIsRepo(CheckRepoActions.IS_REPO_ROOT);
|
||||
if (!isRepo) {
|
||||
console.log(`Directory ${color.yellow(directory)} is not a Git repository`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await pluginRepo.fetch();
|
||||
const commitHash = await pluginRepo.revparse(['HEAD']);
|
||||
const trackingBranch = await pluginRepo.revparse(['--abbrev-ref', '@{u}']);
|
||||
|
169
post-install.js
169
post-install.js
@@ -7,26 +7,13 @@ import crypto from 'node:crypto';
|
||||
import process from 'node:process';
|
||||
import yaml from 'yaml';
|
||||
import _ from 'lodash';
|
||||
import chalk from 'chalk';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
/**
|
||||
* Colorizes console output.
|
||||
*/
|
||||
const color = {
|
||||
byNum: (mess, fgNum) => {
|
||||
mess = mess || '';
|
||||
fgNum = fgNum === undefined ? 31 : fgNum;
|
||||
return '\u001b[' + fgNum + 'm' + mess + '\u001b[39m';
|
||||
},
|
||||
black: (mess) => color.byNum(mess, 30),
|
||||
red: (mess) => color.byNum(mess, 31),
|
||||
green: (mess) => color.byNum(mess, 32),
|
||||
yellow: (mess) => color.byNum(mess, 33),
|
||||
blue: (mess) => color.byNum(mess, 34),
|
||||
magenta: (mess) => color.byNum(mess, 35),
|
||||
cyan: (mess) => color.byNum(mess, 36),
|
||||
white: (mess) => color.byNum(mess, 37),
|
||||
};
|
||||
const color = chalk;
|
||||
|
||||
const keyMigrationMap = [
|
||||
{
|
||||
@@ -44,6 +31,85 @@ const keyMigrationMap = [
|
||||
newKey: 'thumbnails.format',
|
||||
migrate: (value) => (value ? 'png' : 'jpg'),
|
||||
},
|
||||
{
|
||||
oldKey: 'disableChatBackup',
|
||||
newKey: 'backups.chat.enabled',
|
||||
migrate: (value) => !value,
|
||||
},
|
||||
{
|
||||
oldKey: 'numberOfBackups',
|
||||
newKey: 'backups.common.numberOfBackups',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'maxTotalChatBackups',
|
||||
newKey: 'backups.chat.maxTotalBackups',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'chatBackupThrottleInterval',
|
||||
newKey: 'backups.chat.throttleInterval',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'enableExtensions',
|
||||
newKey: 'extensions.enabled',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'enableExtensionsAutoUpdate',
|
||||
newKey: 'extensions.autoUpdate',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'extras.disableAutoDownload',
|
||||
newKey: 'extensions.models.autoDownload',
|
||||
migrate: (value) => !value,
|
||||
},
|
||||
{
|
||||
oldKey: 'extras.classificationModel',
|
||||
newKey: 'extensions.models.classification',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'extras.captioningModel',
|
||||
newKey: 'extensions.models.captioning',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'extras.embeddingModel',
|
||||
newKey: 'extensions.models.embedding',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'extras.speechToTextModel',
|
||||
newKey: 'extensions.models.speechToText',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'extras.textToSpeechModel',
|
||||
newKey: 'extensions.models.textToSpeech',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'minLogLevel',
|
||||
newKey: 'logging.minLogLevel',
|
||||
migrate: (value) => value,
|
||||
},
|
||||
{
|
||||
oldKey: 'cardsCacheCapacity',
|
||||
newKey: 'performance.memoryCacheCapacity',
|
||||
migrate: (value) => `${value}mb`,
|
||||
},
|
||||
// uncomment one release after 1.12.13
|
||||
/*
|
||||
{
|
||||
oldKey: 'cookieSecret',
|
||||
newKey: 'cookieSecret',
|
||||
migrate: () => void 0,
|
||||
remove: true,
|
||||
},
|
||||
*/
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -53,7 +119,7 @@ const keyMigrationMap = [
|
||||
* @returns {string[]} Array of all keys in the object
|
||||
*/
|
||||
function getAllKeys(obj, prefix = '') {
|
||||
if (typeof obj !== 'object' || Array.isArray(obj)) {
|
||||
if (typeof obj !== 'object' || Array.isArray(obj) || obj === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -103,8 +169,17 @@ function addMissingConfigValues() {
|
||||
|
||||
// Migrate old keys to new keys
|
||||
const migratedKeys = [];
|
||||
for (const { oldKey, newKey, migrate } of keyMigrationMap) {
|
||||
for (const { oldKey, newKey, migrate, remove } of keyMigrationMap) {
|
||||
if (_.has(config, oldKey)) {
|
||||
if (remove) {
|
||||
_.unset(config, oldKey);
|
||||
migratedKeys.push({
|
||||
oldKey,
|
||||
newValue: void 0,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const oldValue = _.get(config, oldKey);
|
||||
const newValue = migrate(oldValue);
|
||||
_.set(config, newKey, newValue);
|
||||
@@ -153,20 +228,60 @@ function addMissingConfigValues() {
|
||||
* Creates the default config files if they don't exist yet.
|
||||
*/
|
||||
function createDefaultFiles() {
|
||||
const files = {
|
||||
config: './config.yaml',
|
||||
user: './public/css/user.css',
|
||||
};
|
||||
/**
|
||||
* @typedef DefaultItem
|
||||
* @type {object}
|
||||
* @property {'file' | 'directory'} type - Whether the item should be copied as a single file or merged into a directory structure.
|
||||
* @property {string} defaultPath - The path to the default item (typically in `default/`).
|
||||
* @property {string} productionPath - The path to the copied item for production use.
|
||||
*/
|
||||
|
||||
for (const file of Object.values(files)) {
|
||||
/** @type {DefaultItem[]} */
|
||||
const defaultItems = [
|
||||
{
|
||||
type: 'file',
|
||||
defaultPath: './default/config.yaml',
|
||||
productionPath: './config.yaml',
|
||||
},
|
||||
{
|
||||
type: 'directory',
|
||||
defaultPath: './default/public/',
|
||||
productionPath: './public/',
|
||||
},
|
||||
];
|
||||
|
||||
for (const defaultItem of defaultItems) {
|
||||
try {
|
||||
if (!fs.existsSync(file)) {
|
||||
const defaultFilePath = path.join('./default', path.parse(file).base);
|
||||
fs.copyFileSync(defaultFilePath, file);
|
||||
console.log(color.green(`Created default file: ${file}`));
|
||||
if (defaultItem.type === 'file') {
|
||||
if (!fs.existsSync(defaultItem.productionPath)) {
|
||||
fs.copyFileSync(
|
||||
defaultItem.defaultPath,
|
||||
defaultItem.productionPath,
|
||||
);
|
||||
console.log(
|
||||
color.green(`Created default file: ${defaultItem.productionPath}`),
|
||||
);
|
||||
}
|
||||
} else if (defaultItem.type === 'directory') {
|
||||
fs.cpSync(defaultItem.defaultPath, defaultItem.productionPath, {
|
||||
force: false, // Don't overwrite existing files!
|
||||
recursive: true,
|
||||
});
|
||||
console.log(
|
||||
color.green(`Synchronized missing files: ${defaultItem.productionPath}`),
|
||||
);
|
||||
} else {
|
||||
throw new Error(
|
||||
'FATAL: Unexpected default file format in `post-install.js#createDefaultFiles()`.',
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(color.red(`FATAL: Could not write default file: ${file}`), error);
|
||||
console.error(
|
||||
color.red(
|
||||
`FATAL: Could not write default ${defaultItem.type}: ${defaultItem.productionPath}`,
|
||||
),
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -216,8 +216,6 @@
|
||||
|
||||
}
|
||||
|
||||
#showRawPrompt,
|
||||
#copyPromptToClipboard,
|
||||
#groupCurrentMemberPopoutButton,
|
||||
#summaryExtensionPopoutButton {
|
||||
display: none;
|
||||
|
@@ -72,6 +72,10 @@ dialog {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.popup.left_aligned_dialogue_popup .popup-content {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
/* Opening animation */
|
||||
.popup[opening] {
|
||||
animation: pop-in var(--popup-animation-speed) ease-in-out;
|
||||
|
@@ -271,6 +271,24 @@
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
#completion_prompt_manager #completion_prompt_manager_list .completion_prompt_manager_prompt .drag-handle:not(.ui-sortable-handle) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#completion_prompt_manager #completion_prompt_manager_list .completion_prompt_manager_prompt:has(.drag-handle.ui-sortable-handle) {
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
#completion_prompt_manager #completion_prompt_manager_list .completion_prompt_manager_prompt .drag-handle {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
padding: 0 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#completion_prompt_manager_footer_append_prompt {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
.scrollable-buttons-container {
|
||||
max-height: 50vh; /* Use viewport height instead of fixed pixels */
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch; /* Momentum scrolling on iOS */
|
||||
margin-top: 1rem; /* m-t-1 is equivalent to margin-top: 1rem; */
|
||||
flex-shrink: 1;
|
||||
|
@@ -100,6 +100,13 @@
|
||||
border: 1px solid var(--SmartThemeBorderColor);
|
||||
}
|
||||
|
||||
.select2-container .select2-results .select2-results__option--disabled {
|
||||
color: inherit;
|
||||
background-color: inherit;
|
||||
cursor: not-allowed;
|
||||
filter: brightness(0.5);
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--multiple .select2-selection__choice,
|
||||
.select2-container .select2-selection--single .select2-selection__choice {
|
||||
border-radius: 5px;
|
||||
|
@@ -96,11 +96,6 @@ body.charListGrid #rm_print_characters_block .group_select .group_name_block,
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#user_avatar_block.gridView .avatar-container .avatar-buttons {
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
body.charListGrid #rm_print_characters_block .bogus_folder_select .character_select_container,
|
||||
body.charListGrid #rm_print_characters_block .character_select .character_select_container,
|
||||
body.charListGrid #rm_print_characters_block .group_select .group_select_container,
|
||||
@@ -231,10 +226,16 @@ body.big-avatars .avatars_inline_small .avatar img {
|
||||
body.big-avatars .avatars_inline {
|
||||
max-height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor) + 2 * var(--avatar-base-border-radius));
|
||||
}
|
||||
body.big-avatars .avatars_inline.avatars_multiline {
|
||||
max-height: fit-content;
|
||||
}
|
||||
|
||||
body.big-avatars .avatars_inline.avatars_inline_small {
|
||||
height: calc(var(--avatar-base-height) * var(--big-avatar-height-factor) * var(--inline-avatar-small-factor) + 2 * var(--avatar-base-border-radius));
|
||||
}
|
||||
body.big-avatars .avatars_inline.avatars_inline_small.avatars_multiline {
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
body:not(.big-avatars) .avatars_inline_small .avatar_collage {
|
||||
min-width: calc(var(--avatar-base-width) * var(--inline-avatar-small-factor));
|
||||
@@ -472,6 +473,11 @@ label[for="trim_spaces"]:has(input:checked) i.warning {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label[for="trim_spaces"]:not(:has(input:checked)) small {
|
||||
color: var(--warning);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#claude_function_prefill_warning {
|
||||
display: none;
|
||||
color: red;
|
||||
@@ -488,3 +494,7 @@ label[for="trim_spaces"]:has(input:checked) i.warning {
|
||||
#mistralai_other_models:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#banned_tokens_block_ooba:not(:has(#send_banned_tokens_textgenerationwebui:checked)) #banned_tokens_controls_ooba {
|
||||
filter: brightness(0.5);
|
||||
}
|
||||
|
33
public/global.d.ts
vendored
33
public/global.d.ts
vendored
@@ -1,18 +1,21 @@
|
||||
import libs from './lib';
|
||||
import getContext from './scripts/st-context';
|
||||
|
||||
// Global namespace modules
|
||||
declare var ai;
|
||||
declare var pdfjsLib;
|
||||
declare var ePub;
|
||||
|
||||
declare var SillyTavern: {
|
||||
getContext(): typeof getContext;
|
||||
llm: any;
|
||||
libs: typeof libs;
|
||||
};
|
||||
|
||||
declare global {
|
||||
// Global namespace modules
|
||||
interface Window {
|
||||
ai: any;
|
||||
}
|
||||
|
||||
declare var pdfjsLib;
|
||||
declare var ePub;
|
||||
|
||||
declare var SillyTavern: {
|
||||
getContext(): typeof getContext;
|
||||
llm: any;
|
||||
libs: typeof libs;
|
||||
};
|
||||
|
||||
// Jquery plugins
|
||||
interface JQuery {
|
||||
nanogallery2(options?: any): JQuery;
|
||||
@@ -40,4 +43,12 @@ declare global {
|
||||
searchInputCssClass?: string;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a text to a target language using a translation provider.
|
||||
* @param text Text to translate
|
||||
* @param lang Target language
|
||||
* @param provider Translation provider
|
||||
*/
|
||||
async function translate(text: string, lang: string, provider: string = null): Promise<string>;
|
||||
}
|
||||
|
1
public/img/vllm.svg
Normal file
1
public/img/vllm.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg version="1.0" width="565.752" height="586.537" viewBox="0 0 424.314 439.903" preserveAspectRatio="xMidYMid" xmlns="http://www.w3.org/2000/svg"><path d="M344.6 41.703c-43.4 23-79.3 42.4-79.7 43.2-.8 1.4-72.3 276.1-84.3 323.5-6.2 24.9-7.1 27.7-8 25.5-.4-.8-.5-77.7-.4-170.8l.3-169.2H86.3c-47.5 0-86.3.2-86.3.5 0 1 162.2 325 166.9 333.3 2.5 4.6 5 9.2 5.6 10.3.9 1.8 2.7 1.9 68.2 1.9 63.1 0 67.2-.1 67.7-1.8.3-.9 24.2-90.8 53-199.7 51-192.7 58.9-222.4 62-233.3.8-2.8 1.1-5.2.8-5.1-.4 0-36.2 18.8-79.6 41.7z"/></svg>
|
After Width: | Height: | Size: 516 B |
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,8 @@
|
||||
"**/.git/**",
|
||||
"lib/**",
|
||||
"**/*.min.js",
|
||||
"scripts/extensions/quick-reply/lib/**"
|
||||
"scripts/extensions/quick-reply/lib/**",
|
||||
"scripts/extensions/tts/lib/**"
|
||||
],
|
||||
"typeAcquisition": {
|
||||
"include": []
|
||||
|
@@ -20,6 +20,7 @@ import * as Popper from '@popperjs/core';
|
||||
import droll from 'droll';
|
||||
import morphdom from 'morphdom';
|
||||
import { toggle as slideToggle } from 'slidetoggle';
|
||||
import chalk from 'chalk';
|
||||
|
||||
/**
|
||||
* Expose the libraries to the 'window' object.
|
||||
@@ -96,6 +97,7 @@ export default {
|
||||
droll,
|
||||
morphdom,
|
||||
slideToggle,
|
||||
chalk,
|
||||
};
|
||||
|
||||
export {
|
||||
@@ -118,4 +120,5 @@ export {
|
||||
droll,
|
||||
morphdom,
|
||||
slideToggle,
|
||||
chalk,
|
||||
};
|
||||
|
@@ -24,10 +24,22 @@ if (typeof Array.prototype.indexOf === 'function') {
|
||||
|
||||
|
||||
/* Polyfill EventEmitter. */
|
||||
var EventEmitter = function () {
|
||||
/**
|
||||
* Creates an event emitter.
|
||||
* @param {string[]} autoFireAfterEmit Auto-fire event names
|
||||
*/
|
||||
var EventEmitter = function (autoFireAfterEmit = []) {
|
||||
this.events = {};
|
||||
this.autoFireLastArgs = new Map();
|
||||
this.autoFireAfterEmit = new Set(autoFireAfterEmit);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a listener to an event.
|
||||
* @param {string} event Event name
|
||||
* @param {function} listener Event listener
|
||||
* @returns
|
||||
*/
|
||||
EventEmitter.prototype.on = function (event, listener) {
|
||||
// Unknown event used by external libraries?
|
||||
if (event === undefined) {
|
||||
@@ -40,6 +52,10 @@ EventEmitter.prototype.on = function (event, listener) {
|
||||
}
|
||||
|
||||
this.events[event].push(listener);
|
||||
|
||||
if (this.autoFireAfterEmit.has(event) && this.autoFireLastArgs.has(event)) {
|
||||
listener.apply(this, this.autoFireLastArgs.get(event));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -60,6 +76,10 @@ EventEmitter.prototype.makeLast = function (event, listener) {
|
||||
}
|
||||
|
||||
events.push(listener);
|
||||
|
||||
if (this.autoFireAfterEmit.has(event) && this.autoFireLastArgs.has(event)) {
|
||||
listener.apply(this, this.autoFireLastArgs.get(event));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,8 +100,17 @@ EventEmitter.prototype.makeFirst = function (event, listener) {
|
||||
}
|
||||
|
||||
events.unshift(listener);
|
||||
|
||||
if (this.autoFireAfterEmit.has(event) && this.autoFireLastArgs.has(event)) {
|
||||
listener.apply(this, this.autoFireLastArgs.get(event));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener from an event.
|
||||
* @param {string} event Event name
|
||||
* @param {function} listener Event listener
|
||||
*/
|
||||
EventEmitter.prototype.removeListener = function (event, listener) {
|
||||
var idx;
|
||||
|
||||
@@ -94,6 +123,10 @@ EventEmitter.prototype.removeListener = function (event, listener) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Emits an event with optional arguments.
|
||||
* @param {string} event Event name
|
||||
*/
|
||||
EventEmitter.prototype.emit = async function (event) {
|
||||
let args = [].slice.call(arguments, 1);
|
||||
if (localStorage.getItem('eventTracing') === 'true') {
|
||||
@@ -118,6 +151,10 @@ EventEmitter.prototype.emit = async function (event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.autoFireAfterEmit.has(event)) {
|
||||
this.autoFireLastArgs.set(event, args);
|
||||
}
|
||||
};
|
||||
|
||||
EventEmitter.prototype.emitAndWait = function (event) {
|
||||
@@ -144,10 +181,14 @@ EventEmitter.prototype.emitAndWait = function (event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.autoFireAfterEmit.has(event)) {
|
||||
this.autoFireLastArgs.set(event, args);
|
||||
}
|
||||
};
|
||||
|
||||
EventEmitter.prototype.once = function (event, listener) {
|
||||
this.on(event, function g () {
|
||||
this.on(event, function g() {
|
||||
this.removeListener(event, g);
|
||||
listener.apply(this, arguments);
|
||||
});
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "فصل بفواصل دون مسافة بينها",
|
||||
"Custom Stopping Strings": "سلاسل توقف مخصصة",
|
||||
"JSON serialized array of strings": "مصفوفة سلسلة JSON متسلسلة",
|
||||
"Replace Macro in Custom Stopping Strings": "استبدال الماكرو في سلاسل التوقف المخصصة",
|
||||
"Replace Macro in Stop Strings": "استبدال الماكرو في سلاسل التوقف المخصصة",
|
||||
"Auto-Continue": "المتابعة التلقائية",
|
||||
"Allow for Chat Completion APIs": "السماح بواجهات برمجة التطبيقات لإكمال الدردشة",
|
||||
"Target length (tokens)": "الطول المستهدف (رموز)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "حذف موضوع",
|
||||
"Update a theme file": "تحديث ملف السمة",
|
||||
"Save as a new theme": "حفظ كسمة جديدة",
|
||||
"Avatar Style": "نمط الصورة الرمزية",
|
||||
"Avatar Style:": "نمط الصورة الرمزية",
|
||||
"Circle": "دائرة",
|
||||
"Square": "مربع",
|
||||
"Rectangle": "مستطيل",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "تفضيل التعليمات من بطاقة الشخصية",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "إذا تم التحقق وكانت بطاقة الشخصية تحتوي على تجاوز للكسر (تعليمات تاريخ المشاركة)، استخدم ذلك بدلاً من ذلك",
|
||||
"Prefer Character Card Jailbreak": "تفضيل كسر الحصار من بطاقة الشخصية",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "تجنب اقتصاص صور الأحرف المستوردة وتغيير حجمها. عند إيقاف التشغيل، قم بالقص/تغيير الحجم إلى 512 × 768.",
|
||||
"never_resize_avatars_tooltip": "تجنب اقتصاص صور الأحرف المستوردة وتغيير حجمها. عند إيقاف التشغيل، قم بالقص/تغيير الحجم إلى 512 × 768.",
|
||||
"Never resize avatars": "لا تغيير حجم الصور الرمزية أبدًا",
|
||||
"Show actual file names on the disk, in the characters list display only": "عرض الأسماء الفعلية للملفات على القرص، في عرض قائمة الشخصيات فقط",
|
||||
"Show avatar filenames": "عرض أسماء ملفات الصور الرمزية",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "السحب التلقائي",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "تمكين وظيفة السحب التلقائي. الإعدادات في هذا القسم تؤثر فقط عند تمكين السحب التلقائي",
|
||||
"Minimum generated message length": "الحد الأدنى لطول الرسالة المولدة",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "إذا كانت الرسالة المولدة أقصر من هذا، فتحريض السحب التلقائي",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "إذا كانت الرسالة المولدة أقصر من هذا، فتحريض السحب التلقائي",
|
||||
"Blacklisted words": "الكلمات الممنوعة",
|
||||
"words you dont want generated separated by comma ','": "الكلمات التي لا تريد توليدها مفصولة بفاصلة ','",
|
||||
"Blacklisted word count to swipe": "عدد الكلمات الممنوعة للسحب",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "لا",
|
||||
"popup-button-cancel": "يلغي",
|
||||
"popup-button-import": "يستورد",
|
||||
"Advanced Defininitions": "تعريفات متقدمة",
|
||||
"Advanced Definitions": "تعريفات متقدمة",
|
||||
"Prompt Overrides": "التجاوزات السريعة",
|
||||
"(For Chat Completion and Instruct Mode)": "(لاستكمال الدردشة ووضع التعليمات)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "أدخل {{original}} في أي مربع لتضمين التعليمات الافتراضية المعنية من إعدادات النظام.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Chub Lorebook (رابط مباشر أو معرف)",
|
||||
"char_import_3": "حرف JanitorAI (رابط مباشر أو UUID)",
|
||||
"char_import_4": "حرف Pygmalion.chat (رابط مباشر أو UUID)",
|
||||
"char_import_5": "حرف AICharacterCard.com (رابط مباشر أو معرف)",
|
||||
"char_import_5": "حرف AICharacterCards.com (رابط مباشر أو معرف)",
|
||||
"char_import_6": "رابط PNG المباشر (راجع",
|
||||
"char_import_7": "للمضيفين المسموح بهم)",
|
||||
"char_import_8": "شخصية RisuRealm (رابط مباشر)",
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "getrennt durch Kommas ohne Leerzeichen dazwischen",
|
||||
"Custom Stopping Strings": "Benutzerdefinierte Stoppzeichenfolgen",
|
||||
"JSON serialized array of strings": "JSON serialisierte Reihe von Zeichenfolgen",
|
||||
"Replace Macro in Custom Stopping Strings": "Makro in benutzerdefinierten Stoppzeichenfolgen ersetzen",
|
||||
"Replace Macro in Stop Strings": "Makro in benutzerdefinierten Stoppzeichenfolgen ersetzen",
|
||||
"Auto-Continue": "Automatisch fortsetzen",
|
||||
"Allow for Chat Completion APIs": "Erlaube Chat-Vervollständigungs-APIs",
|
||||
"Target length (tokens)": "Ziel-Länge (Tokens)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "Löschen eines Designs",
|
||||
"Update a theme file": "Ein Theme-Datei aktualisieren",
|
||||
"Save as a new theme": "Als neues Theme speichern",
|
||||
"Avatar Style": "Avatar-Stil",
|
||||
"Avatar Style:": "Avatar-Stil",
|
||||
"Circle": "Kreis",
|
||||
"Square": "Quadrat",
|
||||
"Rectangle": "Rechteck",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "Bevorzuge Charakterkarten-Prompt",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "Wenn aktiviert und die Charakterkarte eine Jailbreak-Überschreibung enthält (Post-History-Instruction), verwende stattdessen diese",
|
||||
"Prefer Character Card Jailbreak": "Bevorzuge Charakterkarten-Jailbreak",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Vermeiden Sie das Zuschneiden und Ändern der Größe importierter Zeichenbilder. Wenn deaktiviert, wird die Größe auf 512 x 768 zugeschnitten/angepasst.",
|
||||
"never_resize_avatars_tooltip": "Vermeiden Sie das Zuschneiden und Ändern der Größe importierter Zeichenbilder. Wenn deaktiviert, wird die Größe auf 512 x 768 zugeschnitten/angepasst.",
|
||||
"Never resize avatars": "Avatare niemals verkleinern",
|
||||
"Show actual file names on the disk, in the characters list display only": "Zeige tatsächliche Dateinamen auf der Festplatte, nur in der Anzeige der Charakterliste",
|
||||
"Show avatar filenames": "Avatar-Dateinamen anzeigen",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "Automatisches Wischen",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Aktiviere die Auto-Wisch-Funktion. Einstellungen in diesem Abschnitt haben nur dann Auswirkungen, wenn das automatische Wischen aktiviert ist",
|
||||
"Minimum generated message length": "Minimale generierte Nachrichtenlänge",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Wenn die generierte Nachricht kürzer ist als diese, löse automatisches Wischen aus",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Wenn die generierte Nachricht kürzer ist als diese, löse automatisches Wischen aus",
|
||||
"Blacklisted words": "Verbotene Wörter",
|
||||
"words you dont want generated separated by comma ','": "Wörter, die du nicht generiert haben möchtest, durch Komma ',' getrennt",
|
||||
"Blacklisted word count to swipe": "Anzahl der verbotenen Wörter, um zu wischen",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "NEIN",
|
||||
"popup-button-cancel": "Stornieren",
|
||||
"popup-button-import": "Importieren",
|
||||
"Advanced Defininitions": "Erweiterte Definitionen",
|
||||
"Advanced Definitions": "Erweiterte Definitionen",
|
||||
"Prompt Overrides": "Eingabeaufforderungsüberschreibungen",
|
||||
"(For Chat Completion and Instruct Mode)": "(Für Chat-Abschluss und Anweisungsmodus)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Füge {{original}} in eines der Felder ein, um den jeweiligen Standardprompt aus den Systemeinstellungen einzuschließen.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Chub Lorebook (Direktlink oder ID)",
|
||||
"char_import_3": "JanitorAI-Charakter (Direktlink oder UUID)",
|
||||
"char_import_4": "Pygmalion.chat-Charakter (Direktlink oder UUID)",
|
||||
"char_import_5": "AICharacterCard.com-Charakter (Direktlink oder ID)",
|
||||
"char_import_5": "AICharacterCards.com-Charakter (Direktlink oder ID)",
|
||||
"char_import_6": "Direkter PNG-Link (siehe",
|
||||
"char_import_7": "für erlaubte Hosts)",
|
||||
"char_import_8": "RisuRealm-Charakter (Direktlink)",
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "separe con comas sin espacio entre ellas",
|
||||
"Custom Stopping Strings": "Cadenas de Detención Personalizadas",
|
||||
"JSON serialized array of strings": "Arreglo de cadenas serializado en JSON",
|
||||
"Replace Macro in Custom Stopping Strings": "Reemplazar macro en Cadenas de Detención Personalizadas",
|
||||
"Replace Macro in Stop Strings": "Reemplazar macro en Cadenas de Detención Personalizadas",
|
||||
"Auto-Continue": "Autocontinuar",
|
||||
"Allow for Chat Completion APIs": "Permitir para APIs de Completado de Chat",
|
||||
"Target length (tokens)": "Longitud objetivo (tokens)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "Eliminar un tema",
|
||||
"Update a theme file": "Actualizar un archivo de tema",
|
||||
"Save as a new theme": "Guardar como nuevo tema",
|
||||
"Avatar Style": "Estilo de Avatar",
|
||||
"Avatar Style:": "Estilo de Avatar",
|
||||
"Circle": "Círculo",
|
||||
"Square": "Cuadrado",
|
||||
"Rectangle": "Rectángulo",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "Preferir Indicaciones en Tarjeta de Personaje",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "Si está marcado y la tarjeta de personaje contiene una anulación de jailbreak (Instrucciones Post Historial), usar eso en su lugar",
|
||||
"Prefer Character Card Jailbreak": "Preferir Jailbreak en Tarjeta de Personaje",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Evite recortar y cambiar el tamaño de las imágenes de personajes importados. Cuando esté desactivado, recorte/cambie el tamaño a 512x768.",
|
||||
"never_resize_avatars_tooltip": "Evite recortar y cambiar el tamaño de las imágenes de personajes importados. Cuando esté desactivado, recorte/cambie el tamaño a 512x768.",
|
||||
"Never resize avatars": "Nunca redimensionar avatares",
|
||||
"Show actual file names on the disk, in the characters list display only": "Mostrar nombres de archivo reales en el disco, solo en la visualización de la lista de personajes",
|
||||
"Show avatar filenames": "Mostrar nombres de archivo de avatares",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "Deslizamiento automático",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Habilitar la función de deslizamiento automático. La configuración en esta sección solo tiene efecto cuando el deslizamiento automático está habilitado",
|
||||
"Minimum generated message length": "Longitud mínima del mensaje generado",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Si el mensaje generado es más corto que esto, activar un deslizamiento automático",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Si el mensaje generado es más corto que esto, activar un deslizamiento automático",
|
||||
"Blacklisted words": "Palabras prohibidas",
|
||||
"words you dont want generated separated by comma ','": "palabras que no desea generar separadas por coma ','",
|
||||
"Blacklisted word count to swipe": "Número de palabras prohibidas para deslizar",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "No",
|
||||
"popup-button-cancel": "Cancelar",
|
||||
"popup-button-import": "Importar",
|
||||
"Advanced Defininitions": "Definiciones avanzadas",
|
||||
"Advanced Definitions": "Definiciones avanzadas",
|
||||
"Prompt Overrides": "Anulaciones rápidas",
|
||||
"(For Chat Completion and Instruct Mode)": "(Para completar el chat y el modo de instrucción)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Inserte {{original}} en cualquiera de las casillas para incluir las indicaciones predeterminadas respectivas de la configuración del sistema.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Chub Lorebook (enlace directo o ID)",
|
||||
"char_import_3": "Carácter de JanitorAI (enlace directo o UUID)",
|
||||
"char_import_4": "Carácter Pygmalion.chat (enlace directo o UUID)",
|
||||
"char_import_5": "Carácter AICharacterCard.com (enlace directo o ID)",
|
||||
"char_import_5": "Carácter AICharacterCards.com (enlace directo o ID)",
|
||||
"char_import_6": "Enlace PNG directo (consulte",
|
||||
"char_import_7": "para hosts permitidos)",
|
||||
"char_import_8": "Personaje RisuRealm (Enlace directo)",
|
||||
@@ -1439,5 +1439,112 @@
|
||||
"Still have questions?": "¿Todavía tienes preguntas?",
|
||||
"Join the SillyTavern Discord": "Únete al Discord de SillyTavern",
|
||||
"Post a GitHub issue": "Publicar un problema en GitHub",
|
||||
"Contact the developers": "Contactar a los desarrolladores"
|
||||
"Contact the developers": "Contactar a los desarrolladores",
|
||||
"Prome (Visual Novel Extension)": "Prome (Extensión de Modo Waifu/Novela Visual)",
|
||||
"Brought to you by": "Presentado por",
|
||||
"and Prometheus.": "y Prometheus.",
|
||||
"Enable Prome": "Iniciar Prome",
|
||||
"Toggles Prome, VN Mode and other Prome features.": "Activa Prome, el modo VN y otras funciones de Prome.",
|
||||
"Features marked with a": "Las funciones marcadas con un",
|
||||
"require Prome to be enabled.": "requieren que Prome esté iniciado.",
|
||||
"Sheld Configuration": "Configuración de interfaz (Sheld)",
|
||||
"Hide Sheld (Message Box)": "Ocultar Sheld (cuadro de mensajes)",
|
||||
"Hide the message box (sheld) in the ST UI.": "Ocultar el cuadro de mensajes (sheld) en la interfaz de usuario de SillyTavern.",
|
||||
"Enable Traditional VN Mode": "Modo VN tradicional*",
|
||||
"Only Show Last Message in Chat (Requires Prome to be enabled).": "Mostrar solo el último mensaje en el chat (Requiere que Prome esté iniciado).",
|
||||
"Letterbox Configuration*": "Configuración de la franja negra*",
|
||||
"Letterbox Mode": "Modo de franja negra",
|
||||
"Select the letterbox mode for the Prome VN UI.": "Seleccione el modo de franja negra para la interfaz de usuario VN de Prome.",
|
||||
"Horizontal Letterbox": "Franja negra horizontal",
|
||||
"Vertical Letterbox": "Franja negra vertical",
|
||||
"Letterbox Color": "Color de la franja negra",
|
||||
"Select the color of the letterbox.": "Seleccione el color de la franja negra.",
|
||||
"Letterbox Size": "Tamaño de la franja negra",
|
||||
"Set the size of the letterbox.": "Establezca el tamaño de la franja negra.",
|
||||
"Sprite Configuration": "Configuración de sprites",
|
||||
"Emulate Character Card as Sprite": "[BETA] Emular tarjeta de personaje como sprite",
|
||||
"Emulates the character card of a character to be a sprite. (Requires Prome to be enabled).": "Emula la tarjeta de personaje de un personaje para que sea un sprite. (Requiere que Prome esté iniciado).",
|
||||
"Enable Sprite Shake": "[BETA] Sprite Shake",
|
||||
"Shakes the character sprite when the character is speaking (Only works if Streaming is enabled in Preset Settings).": "Agita el sprite del personaje cuando el personaje está hablando (solo funciona si la transmisión está habilitada en la configuración preestablecida).",
|
||||
"Enable Focus Mode": "Modo de enfoque",
|
||||
"Focuses the current speaking character in chat. (Requires Prome to be enabled).": "Enfoca al personaje que está hablando en el chat. (Requiere que Prome esté iniciado).",
|
||||
"Darken Unfocused Character Sprites": "Oscurecer sprites de personajes",
|
||||
"Darkens non-speaking (unfocused) characters. (Requires Prome to be enabled).": "Oscurece a los personajes que no hablan (no enfocados). (Requiere que Prome esté iniciado).",
|
||||
"Auto-Hide Sprites": "Ocultar sprites automáticamente",
|
||||
"Auto-hides characters from the screen that haven't been in the conversation for a while up to X characters. (Requires Prome to be enabled).": "Oculta automáticamente a los personajes de la pantalla que no han estado en la conversación durante un tiempo hasta X personajes. (Requiere que Prome esté iniciado).",
|
||||
"Max Visible Sprites": "Máximo de personajes visibles",
|
||||
"Set the maximum number of visible sprites that appears in the VN screen.": "Establezca el número máximo de sprites visibles que aparecen en la pantalla VN.",
|
||||
"Sprite Shadow Configuration": "Configuración de sombra de sprites",
|
||||
"Enable Sprite Shadow": "Sombra de sprite",
|
||||
"Adds a shadow to the character sprite.": "Agrega una sombra al sprite del personaje.",
|
||||
"Shadow X Offset": "Desplazamiento X de la sombra",
|
||||
"Set the X offset of the character shadow.": "Establezca el desplazamiento X de la sombra del personaje.",
|
||||
"Shadow Y Offset": "Desplazamiento Y de la sombra",
|
||||
"Set the Y offset of the character shadow.": "Establezca el desplazamiento Y de la sombra del personaje.",
|
||||
"Shadow Blur": "Desenfoque de sombra",
|
||||
"Set the blur of the character shadow.": "Establezca el desenfoque de la sombra del personaje.",
|
||||
"Focus Mode Settings": "Configuración del modo de enfoque",
|
||||
"Focus Mode Animation": "Animación de modo de enfoque",
|
||||
"Select the animation for focus mode.": "Seleccione la animación para el modo de enfoque.",
|
||||
"Focus Mode Animation Speed": "Velocidad de animación del modo de enfoque",
|
||||
"Set the speed of the focus animation.": "Establezca la velocidad de la animación de enfoque.",
|
||||
"User Sprite Configuration": "[BETA] Configuración de sprites de usuario",
|
||||
"Enable User Sprite": "Sprites de usuario",
|
||||
"Enables the ability to use a user sprite for your persona.": "Habilita la capacidad de usar un sprite de usuario para tu persona.",
|
||||
"Sprite set": "Conjunto de sprites",
|
||||
"Type the name of the sprite set to use for your persona. (Place your sprites in the 'characters' folder in SillyTavern).": "Escriba el nombre del conjunto de sprites que desea utilizar para su persona. (Coloque sus sprites en la carpeta 'characters' en SillyTavern).",
|
||||
"Note: Create a sprite folder in the ": "Nota: Cree una carpeta de sprites en el ",
|
||||
" folder of your user directory (typically 'data/default-user'). Place your expressions there.": " carpeta de su directorio de usuario (normalmente 'data/default-user'). Coloque sus expresiones allí.",
|
||||
"Tint Configuration": "Configuración de tono",
|
||||
"Enable Chat Tint": "Tinte de chat",
|
||||
"Tints the chat background and/or character sprites.": "Tinta el fondo del chat y/o los sprites de personajes.",
|
||||
"Share World Tint With Characters": "Compartir tinte mundial con personajes*",
|
||||
"Applies the world tint to character sprites (Requires Prome to be enabled. This will override your character tint settings).": "Aplica el tinte mundial a los sprites de personajes (Requiere que Prome esté iniciado. Esto anulará la configuración de tinte de su personaje).",
|
||||
"Tint Presets": "Preajustes de tinte",
|
||||
"Select the tint preset to use for the Prome VN UI.": "Seleccione el preajuste de tinte que desea utilizar para la interfaz de usuario VN de Prome.",
|
||||
"World Tint Settings": "Configuración de tinte mundial",
|
||||
"Tints the world background.": "Tinta el fondo mundial.",
|
||||
"Enable World Tint": "Tinte mundial",
|
||||
"Set the strength of the world blur.": "Establezca la fuerza del desenfoque mundial.",
|
||||
"Brightness": "Brillo",
|
||||
"Set the brightness of the world.": "Establezca el brillo del mundo.",
|
||||
"Contrast": "Contraste",
|
||||
"Set the contrast of the world.": "Establezca el contraste del mundial.",
|
||||
"Grayscale": "Escala de grises",
|
||||
"Makes the world black and white.": "Hace que el mundo sea en blanco y negro.",
|
||||
"Hue": "Matiz",
|
||||
"Set the hue of the world tint.": "Establezca el matiz del tinte mundial.",
|
||||
"Invert": "Invertir",
|
||||
"Inverts the world colors.": "Invierte los colores del mundo.",
|
||||
"Saturate": "Saturar",
|
||||
"Saturates the world colors.": "Satura los colores del mundo.",
|
||||
"Makes the world warmer in color.": "Hace que el mundo sea más cálido en color.",
|
||||
"Character Tint Settings": "Configuración de tinte de sprites*",
|
||||
"Enable Character Tint (Requires Prome to be enabled)": "Tinte de sprites (Requiere que Prome esté iniciado)",
|
||||
"Set the strength of the character blur.": "Establezca la fuerza del desenfoque de personajes.",
|
||||
"Set the brightness of the character.": "Establezca el brillo de personaje.",
|
||||
"Set the contrast of the character.": "Establezca el contraste de personajes.",
|
||||
"Makes the character black and white.": "Hace que el personaje sea en blanco y negro.",
|
||||
"Set the hue of the character.": "Establezca el matiz del tinte de personajes.",
|
||||
"Inverts the character colors.": "Invierte los colores del personaje.",
|
||||
"Saturates the character colors.": "Satura los colores del personaje.",
|
||||
"Makes the character warmer in color.": "Hace que el personaje sea más cálido en color.",
|
||||
"Keybinds": "Atajos de teclado",
|
||||
"Commands": "Comandos",
|
||||
"Prome Keybinds": "Combinaciones de teclas de Prome",
|
||||
"Hide/Show SillyTavern's Sheld (Message Box)": "Ocultar/Mostrar el estante de SillyTavern (cuadro de mensaje)",
|
||||
"Prome Commands": "Comandos de Prome",
|
||||
"Show/Hide the letterbox (black bars) in the VN UI": "Mostrar/Ocultar la franja negra (barras negras) en la interfaz VN",
|
||||
"Toggles focus mode on character sprites": "Alterna el modo de enfoque en los sprites de personajes",
|
||||
"Sets the focus mode animation": "Establece la animación del modo de enfoque",
|
||||
"Toggles the defocus tint on non-speaking character sprites": "Alterna el tinte de desenfoque en los sprites de personajes que no hablan",
|
||||
"Toggles the shake animation when a character speaks on character sprites": "Alterna la animación de sacudida cuando un personaje habla en los sprites de personajes",
|
||||
"Toggles sprite shadows on character sprites": "Alterna las sombras de los sprites de personajes",
|
||||
"Toggles world/character tint on the VN UI": "Alterna el tinte mundial/de personajes en la interfaz VN",
|
||||
"Toggles world tint on the VN UI": "Alterna el tinte mundial en la interfaz VN",
|
||||
"Toggles character tint on the VN UI": "Alterna el tinte de personajes en la interfaz VN",
|
||||
"Toggles sharing world tint with character sprites (This will override Character Tint)": "Alterna el tinte mundial compartido con los sprites de personajes (esto anulará el tinte de personajes)",
|
||||
"Sets the expression of the user sprite": "Establece la expresión del sprite de usuario",
|
||||
"Sets the user sprite set to use for the user sprite": "Establece el conjunto de sprites de usuario para usar en el sprite de usuario",
|
||||
"Toggles the user sprite on the VN UI": "Alterna el sprite de usuario en la interfaz VN"
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "aðskilið með kommum án bila milli",
|
||||
"Custom Stopping Strings": "Eigin stopp-strengir",
|
||||
"JSON serialized array of strings": "JSON raðað fylki af strengjum",
|
||||
"Replace Macro in Custom Stopping Strings": "Skiptu út í macro í sérsniðnum stoppa strengjum",
|
||||
"Replace Macro in Stop Strings": "Skiptu út í macro í sérsniðnum stoppa strengjum",
|
||||
"Auto-Continue": "Sjálfvirk Forná",
|
||||
"Allow for Chat Completion APIs": "Leyfa fyrir spjall Loka APIs",
|
||||
"Target length (tokens)": "Markaðarlengd (texti)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "Eyða þema",
|
||||
"Update a theme file": "Uppfæra þemu skrá",
|
||||
"Save as a new theme": "Vista sem nýja þemu",
|
||||
"Avatar Style": "Avatar Stíll",
|
||||
"Avatar Style:": "Avatar Stíll",
|
||||
"Circle": "Hring",
|
||||
"Square": "Reitur",
|
||||
"Rectangle": "Ferhyrningur",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "Kosstu kvenkortu fyrirspurn",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "Ef merkt er og kortið inniheldur fangabrotsskil, notaðu það í staðinn",
|
||||
"Prefer Character Card Jailbreak": "Kosstu kvenkortu fangabrot",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Forðastu að klippa og breyta stærð innfluttra stafamynda. Þegar slökkt er á því skaltu skera/breyta stærð í 512x768.",
|
||||
"never_resize_avatars_tooltip": "Forðastu að klippa og breyta stærð innfluttra stafamynda. Þegar slökkt er á því skaltu skera/breyta stærð í 512x768.",
|
||||
"Never resize avatars": "Aldrei breyta stærðinni á merkjum",
|
||||
"Show actual file names on the disk, in the characters list display only": "Sýna raunveruleg nöfn skráa á diskinum, í lista yfir persónur sýna aðeins",
|
||||
"Show avatar filenames": "Sýna nöfn merkja",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "Sjálfvirkur sveip",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Virkjaðu sjálfvirka sveiflugerð. Stillingar í þessum hluta hafa aðeins áhrif þegar sjálfvirkur sveiflugerð er virk",
|
||||
"Minimum generated message length": "Lágmarks lengd á mynduðum skilaboðum",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Ef mynduðu skilaboðin eru styttri en þessi, kallaðu fram sjálfvirkar sveiflugerðar",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Ef mynduðu skilaboðin eru styttri en þessi, kallaðu fram sjálfvirkar sveiflugerðar",
|
||||
"Blacklisted words": "Svört orð",
|
||||
"words you dont want generated separated by comma ','": "orð sem þú vilt ekki að framleiða aðskilin með kommu ','",
|
||||
"Blacklisted word count to swipe": "Fjöldi svörtra orða til að sveipa",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "Nei",
|
||||
"popup-button-cancel": "Hætta við",
|
||||
"popup-button-import": "Flytja inn",
|
||||
"Advanced Defininitions": "Ítarleg skilgreiningar",
|
||||
"Advanced Definitions": "Ítarleg skilgreiningar",
|
||||
"Prompt Overrides": "Hnekkja hvetjandi",
|
||||
"(For Chat Completion and Instruct Mode)": "(Til að ljúka spjalli og leiðbeiningarham)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Settu inn {{original}} í hvora kassa til að innifela viðkomandi sjálfgefna framkallan frá kerfisstillingum.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Chub Lorebook (beinn hlekkur eða auðkenni)",
|
||||
"char_import_3": "JanitorAI karakter (beinn hlekkur eða UUID)",
|
||||
"char_import_4": "Pygmalion.chat karakter (beinn hlekkur eða UUID)",
|
||||
"char_import_5": "AICharacterCard.com Karakter (beinn hlekkur eða auðkenni)",
|
||||
"char_import_5": "AICharacterCards.com Karakter (beinn hlekkur eða auðkenni)",
|
||||
"char_import_6": "Beinn PNG hlekkur (sjá",
|
||||
"char_import_7": "fyrir leyfilega gestgjafa)",
|
||||
"char_import_8": "RisuRealm karakter (beinn hlekkur)",
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "separati con virgole senza spazio tra loro",
|
||||
"Custom Stopping Strings": "Stringhe di Stop Personalizzate",
|
||||
"JSON serialized array of strings": "Matrice serializzata JSON di stringhe",
|
||||
"Replace Macro in Custom Stopping Strings": "Sostituisci Macro in Stringhe di Arresto Personalizzate",
|
||||
"Replace Macro in Stop Strings": "Sostituisci Macro in Stringhe di Arresto Personalizzate",
|
||||
"Auto-Continue": "Auto-continua",
|
||||
"Allow for Chat Completion APIs": "Consenti per API di completamento chat",
|
||||
"Target length (tokens)": "Lunghezza obiettivo (token)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "Elimina un tema",
|
||||
"Update a theme file": "Aggiorna un file di tema",
|
||||
"Save as a new theme": "Salva come nuovo tema",
|
||||
"Avatar Style": "Stile avatar",
|
||||
"Avatar Style:": "Stile avatar",
|
||||
"Circle": "Cerchio",
|
||||
"Square": "Quadrato",
|
||||
"Rectangle": "Rettangolo",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "Preferisci Prompt della Scheda Personaggio",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "Se selezionato e la scheda del personaggio contiene una sovrascrittura jailbreak (Istruzione Storico Post), usalo invece",
|
||||
"Prefer Character Card Jailbreak": "Preferisci Jailbreak della Scheda Personaggio",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Evita di ritagliare e ridimensionare le immagini dei personaggi importati. Quando è disattivato, ritaglia/ridimensiona a 512x768.",
|
||||
"never_resize_avatars_tooltip": "Evita di ritagliare e ridimensionare le immagini dei personaggi importati. Quando è disattivato, ritaglia/ridimensiona a 512x768.",
|
||||
"Never resize avatars": "Non ridimensionare mai gli avatar",
|
||||
"Show actual file names on the disk, in the characters list display only": "Mostra i nomi file effettivi sul disco, solo nella visualizzazione dell'elenco dei personaggi",
|
||||
"Show avatar filenames": "Mostra nomi file avatar",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "Auto-swipe",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Abilita la funzione di auto-swipe. Le impostazioni in questa sezione hanno effetto solo quando l'auto-swipe è abilitato",
|
||||
"Minimum generated message length": "Lunghezza minima del messaggio generato",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Se il messaggio generato è più breve di questo, attiva un'automatica rimozione",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Se il messaggio generato è più breve di questo, attiva un'automatica rimozione",
|
||||
"Blacklisted words": "Parole in blacklist",
|
||||
"words you dont want generated separated by comma ','": "parole che non vuoi generate separate da virgola ','",
|
||||
"Blacklisted word count to swipe": "Numero di parole in blacklist per attivare un'automatica rimozione",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "NO",
|
||||
"popup-button-cancel": "Annulla",
|
||||
"popup-button-import": "Importare",
|
||||
"Advanced Defininitions": "Definizioni avanzate",
|
||||
"Advanced Definitions": "Definizioni avanzate",
|
||||
"Prompt Overrides": "Sostituzioni richieste",
|
||||
"(For Chat Completion and Instruct Mode)": "(Per il completamento della chat e la modalità istruzione)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Inserisci {{originale}} in uno dei due riquadri per includere il prompt predefinito corrispondente dalle impostazioni di sistema.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Lorebook di Chub (collegamento diretto o ID)",
|
||||
"char_import_3": "Carattere JanitorAI (collegamento diretto o UUID)",
|
||||
"char_import_4": "Carattere Pygmalion.chat (collegamento diretto o UUID)",
|
||||
"char_import_5": "Carattere AICharacterCard.com (Link diretto o ID)",
|
||||
"char_import_5": "Carattere AICharacterCards.com (Link diretto o ID)",
|
||||
"char_import_6": "Collegamento PNG diretto (fare riferimento a",
|
||||
"char_import_7": "per gli host consentiti)",
|
||||
"char_import_8": "Personaggio RisuRealm (collegamento diretto)",
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "間にスペースのないカンマで区切ります",
|
||||
"Custom Stopping Strings": "カスタム停止文字列",
|
||||
"JSON serialized array of strings": "文字列のJSONシリアル化配列",
|
||||
"Replace Macro in Custom Stopping Strings": "カスタム停止文字列内のマクロを置換する",
|
||||
"Replace Macro in Stop Strings": "カスタム停止文字列内のマクロを置換する",
|
||||
"Auto-Continue": "自動継続",
|
||||
"Allow for Chat Completion APIs": "チャット補完APIを許可",
|
||||
"Target length (tokens)": "ターゲット長さ(トークン)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "テーマを削除する",
|
||||
"Update a theme file": "テーマファイルを更新",
|
||||
"Save as a new theme": "新しいテーマとして保存",
|
||||
"Avatar Style": "アバタースタイル",
|
||||
"Avatar Style:": "アバタースタイル",
|
||||
"Circle": "円",
|
||||
"Square": "正方形",
|
||||
"Rectangle": "長方形",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "キャラクターカードのプロンプトを優先",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "チェックされていてキャラクターカードにジェイルブレイクオーバーライド(投稿履歴指示)が含まれている場合、それを代わりに使用します",
|
||||
"Prefer Character Card Jailbreak": "キャラクターカードのJailbreakを優先",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "インポートした文字画像の切り取りやサイズ変更を避けます。オフにすると、512x768 に切り取り/サイズ変更されます。",
|
||||
"never_resize_avatars_tooltip": "インポートした文字画像の切り取りやサイズ変更を避けます。オフにすると、512x768 に切り取り/サイズ変更されます。",
|
||||
"Never resize avatars": "アバターを常にリサイズしない",
|
||||
"Show actual file names on the disk, in the characters list display only": "ディスク上の実際のファイル名を表示します。キャラクターリストの表示にのみ",
|
||||
"Show avatar filenames": "アバターのファイル名を表示",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "オートスワイプ",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "自動スワイプ機能を有効にします。このセクションの設定は、自動スワイプが有効になっている場合にのみ効果があります",
|
||||
"Minimum generated message length": "生成されたメッセージの最小長",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "生成されたメッセージがこれよりも短い場合、自動スワイプをトリガーします",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "生成されたメッセージがこれよりも短い場合、自動スワイプをトリガーします",
|
||||
"Blacklisted words": "ブラックリストされた単語",
|
||||
"words you dont want generated separated by comma ','": "コンマ ',' で区切られた生成したくない単語",
|
||||
"Blacklisted word count to swipe": "スワイプするブラックリストされた単語の数",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "いいえ",
|
||||
"popup-button-cancel": "キャンセル",
|
||||
"popup-button-import": "インポート",
|
||||
"Advanced Defininitions": "高度な定義",
|
||||
"Advanced Definitions": "高度な定義",
|
||||
"Prompt Overrides": "プロンプトのオーバーライド",
|
||||
"(For Chat Completion and Instruct Mode)": "(チャット補完と指示モード用)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "システム設定からの対応するデフォルトのプロンプトを含めるには、どちらかのボックスに{{original}}を挿入します。",
|
||||
@@ -1378,7 +1378,7 @@
|
||||
"char_import_2": "Chub ロアブック (直接リンクまたは ID)",
|
||||
"char_import_3": "JanitorAI キャラクター (直接リンクまたは UUID)",
|
||||
"char_import_4": "Pygmalion.chat キャラクター (直接リンクまたは UUID)",
|
||||
"char_import_5": "AICharacterCard.com キャラクター (直接リンクまたは ID)",
|
||||
"char_import_5": "AICharacterCards.com キャラクター (直接リンクまたは ID)",
|
||||
"char_import_6": "直接PNGリンク(参照",
|
||||
"char_import_7": "許可されたホストの場合)",
|
||||
"char_import_8": "RisuRealm キャラクター (直接リンク)",
|
||||
|
@@ -211,7 +211,7 @@
|
||||
"Sampler Priority": "샘플러 우선 순위",
|
||||
"Ooba only. Determines the order of samplers.": "Ooba 전용. 샘플러의 순서를 결정합니다.",
|
||||
"Character Names Behavior": "캐릭터 이름 동작",
|
||||
"[title]character_names_none": "캐릭터 이름 접두사를 추가하지 않습니다. 그룹 채팅에서는 좋지 않을 수 있으므로, 이 설정을 선택할 때는 주의해야 합니다.",
|
||||
"character_names_none": "캐릭터 이름 접두사를 추가하지 않습니다. 그룹 채팅에서는 좋지 않을 수 있으므로, 이 설정을 선택할 때는 주의해야 합니다.",
|
||||
"Helps the model to associate messages with characters.": "모델이 메시지를 캐릭터와 연관시키는 데 도움이 됩니다.",
|
||||
"None": "없음",
|
||||
"None (not injected)": "없음 (삽입되지 않음)",
|
||||
@@ -404,7 +404,7 @@
|
||||
"Custom API Key": "커스텀 API 키",
|
||||
"Available Models": "사용 가능한 모델",
|
||||
"Prompt Post-Processing": "신속한 후처리",
|
||||
"[title]API Connections;[no_connection_text]api_no_connection": "연결이 되지 않았습니다...",
|
||||
"api_no_connection": "연결이 되지 않았습니다...",
|
||||
"Applies additional processing to the prompt before sending it to the API.": "API로 보내기 전에 프롬프트에 추가 처리를 적용합니다.",
|
||||
"Verifies your API connection by sending a short test message. Be aware that you'll be credited for it!": "짧은 테스트 메시지를 보내어 API 연결을 확인합니다. 이에 대해 유료 크레딧이 지불될 수 있음을 인식하세요!",
|
||||
"Test Message": "테스트 메시지",
|
||||
@@ -492,7 +492,7 @@
|
||||
"separate with commas w/o space between": "쉼표로 구분 (공백 없이)",
|
||||
"Custom Stopping Strings": "사용자 정의 중지 문자열",
|
||||
"JSON serialized array of strings": "문자열의 JSON 직렬화된 배열",
|
||||
"Replace Macro in Custom Stopping Strings": "사용자 정의 중단 문자열에서 매크로 교체",
|
||||
"Replace Macro in Stop Strings": "사용자 정의 중단 문자열에서 매크로 교체",
|
||||
"Auto-Continue": "자동 계속하기",
|
||||
"Allow for Chat Completion APIs": "채팅 완성 API 허용",
|
||||
"Target length (tokens)": "대상 길이 (토큰)",
|
||||
@@ -568,7 +568,7 @@
|
||||
"Delete a theme": "테마 삭제",
|
||||
"Update a theme file": "테마 파일 업데이트",
|
||||
"Save as a new theme": "새 테마로 저장",
|
||||
"Avatar Style": "캐릭터 프로필 스타일",
|
||||
"Avatar Style:": "캐릭터 프로필 스타일",
|
||||
"Circle": "원",
|
||||
"Square": "정사각형",
|
||||
"Rectangle": "사각형",
|
||||
@@ -625,7 +625,7 @@
|
||||
"Single-row message input area. Mobile only, no effect on PC": "한 줄짜리 메시지 입력 영역. 모바일 전용, PC에는 영향 없음",
|
||||
"Compact Input Area (Mobile)": "조그마한 입력 영역 (모바일)",
|
||||
"Swipe # for All Messages": "모든 스와이프 메시지에 대해 번호 매기기",
|
||||
"[title]Display swipe numbers for all messages, not just the last.": "마지막 메시지만이 아니라 모든 메시지에 대한 스와이프 번호를 표시합니다.",
|
||||
"Display swipe numbers for all messages, not just the last.": "마지막 메시지만이 아니라 모든 메시지에 대한 스와이프 번호를 표시합니다.",
|
||||
"In the Character Management panel, show quick selection buttons for favorited characters": "캐릭터 관리 패널에서 즐겨찾는 캐릭터에 대한 빠른 선택 버튼을 표시합니다",
|
||||
"Characters Hotswap": "캐릭터 핫스왑",
|
||||
"Enable magnification for zoomed avatar display.": "마우스 포인터를 아바타 위에 올려두면 아바타가 확대 됩니다.",
|
||||
@@ -646,7 +646,7 @@
|
||||
"Prefer Character Card Prompt": "캐릭터 카드 프롬프트 선호",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "선택되어 있고 캐릭터 카드에 (Post-History 지시)탈옥 재정의가 포함 된 경우, 그것을 대신 사용합니다.",
|
||||
"Prefer Character Card Jailbreak": "캐릭터 카드 탈옥 선호",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "가져온 캐릭터 이미지를 자르거나 크기를 조정하지 마세요. 꺼져 있으면 512x768로 자르거나 크기를 조정합니다.",
|
||||
"never_resize_avatars_tooltip": "가져온 캐릭터 이미지를 자르거나 크기를 조정하지 마세요. 꺼져 있으면 512x768로 자르거나 크기를 조정합니다.",
|
||||
"Never resize avatars": "아바타 크기 변경하지 않음",
|
||||
"Show actual file names on the disk, in the characters list display only": "실제 파일 이름을 디스크에 표시하며 캐릭터 목록 디스플레이에만",
|
||||
"Show avatar filenames": "아바타 파일 이름 표시",
|
||||
@@ -724,7 +724,7 @@
|
||||
"Auto-swipe": "자동 스와이프",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "자동 스와이프 기능을 활성화합니다. 이 섹션의 설정은 자동 스와이프가 활성화되었을 때만 영향을 미칩니다",
|
||||
"Minimum generated message length": "생성된 메시지 최소 길이",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "생성된 메시지가이보다 짧으면 자동 스와이프를 트리거합니다",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "생성된 메시지가이보다 짧으면 자동 스와이프를 트리거합니다",
|
||||
"Blacklisted words": "금지어",
|
||||
"words you dont want generated separated by comma ','": "쉼표로 구분된 생성하지 않으려는 단어",
|
||||
"Blacklisted word count to swipe": "스와이프할 금지어 개수",
|
||||
@@ -895,7 +895,7 @@
|
||||
"popup-button-no": "아니요",
|
||||
"popup-button-cancel": "취소",
|
||||
"popup-button-import": "불러오기",
|
||||
"Advanced Defininitions": "고급 정의",
|
||||
"Advanced Definitions": "고급 정의",
|
||||
"Prompt Overrides": "프롬프트 무시",
|
||||
"(For Chat Completion and Instruct Mode)": "(채팅 완료 및 지시 모드의 경우)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "{{original}}를 해당 상자에 넣어 시스템 설정의 기본 프롬프트를 포함합니다.",
|
||||
@@ -1395,7 +1395,7 @@
|
||||
"char_import_2": "Chub Lorebook(직접 링크 또는 ID)",
|
||||
"char_import_3": "JanitorAI 캐릭터(직접 링크 또는 UUID)",
|
||||
"char_import_4": "Pygmalion.chat 문자(직접 링크 또는 UUID)",
|
||||
"char_import_5": "AICharacterCard.com 캐릭터(직접 링크 또는 ID)",
|
||||
"char_import_5": "AICharacterCards.com 캐릭터(직접 링크 또는 ID)",
|
||||
"char_import_6": "직접 PNG 링크(참조",
|
||||
"char_import_7": "허용된 호스트의 경우)",
|
||||
"char_import_8": "RisuRealm 캐릭터 (직접링크)",
|
||||
@@ -1467,7 +1467,6 @@
|
||||
"menu within": "내의 메뉴",
|
||||
"Translate text to English before classification": "분류 전에 텍스트를 영어로 번역합니다.",
|
||||
"Show default images (emojis) if sprite missing": "해당하는 스프라이트가 없으면 기본 이미지 (이모지들)을 표시합니다.",
|
||||
"Image Type - talkinghead (extras)": "이미지 유형 - 토킹 헤드 (부가 사항)",
|
||||
"Classifier API": "분류를 위한 API",
|
||||
"Select the API for classifying expressions.": "감정 이미지들을 분류할 API를 선택하세요.",
|
||||
"Local": "로컬",
|
||||
@@ -1538,7 +1537,7 @@
|
||||
"Only apply color as accent": "색상은 오직 강조로써만 적용됩니다",
|
||||
"qr--colorClear": "색상 지우기",
|
||||
"Color": "색상",
|
||||
"[title]world_button_title": "캐릭터 로어. 클릭하여 로드하세요. Shift를 클릭하면 '월드 인포 링크' 팝업이 열립니다.",
|
||||
"world_button_title": "캐릭터 로어. 클릭하여 로드하세요. Shift를 클릭하면 '월드 인포 링크' 팝업이 열립니다.",
|
||||
"Select TTS Provider": "TTS 공급자 선택",
|
||||
"tts_enabled": "활성화",
|
||||
"Narrate user messages": "사용자 메시지 나레이션",
|
||||
@@ -1583,15 +1582,15 @@
|
||||
"Prompt Content": "프롬프트 내용",
|
||||
"Instruct Sequences": "지시 시퀀스",
|
||||
"Prefer Character Card Instructions": "캐릭터 카드의 지시사항을 선호",
|
||||
"[title]If checked and the character card contains a Post-History Instructions override, use that instead": "활성화 된 경우, 캐릭터 카드에 Post-History 지시 무시 항목이 포함되어 있으면, 카드 지시사항의 내용으로 대신 사용합니다.",
|
||||
"If checked and the character card contains a Post-History Instructions override, use that instead": "활성화 된 경우, 캐릭터 카드에 Post-History 지시 무시 항목이 포함되어 있으면, 카드 지시사항의 내용으로 대신 사용합니다.",
|
||||
"Auto-select Input Text": "입력 텍스트 자동 선택",
|
||||
"[title]Enable auto-select of input text in some text fields when clicking/selecting them. Applies to popup input textboxes, and possible other custom input fields.": "일부 텍스트 필드를 클릭하거나 선택할 때 자동으로 입력된 텍스트가 선택되도록 설정합니다. 팝업 입력창과 기타 커스텀 입력 필드에 적용됩니다.",
|
||||
"Enable auto-select of input text in some text fields when clicking/selecting them. Applies to popup input textboxes, and possible other custom input fields.": "일부 텍스트 필드를 클릭하거나 선택할 때 자동으로 입력된 텍스트가 선택되도록 설정합니다. 팝업 입력창과 기타 커스텀 입력 필드에 적용됩니다.",
|
||||
"Markdown Hotkeys": "마크다운 입력 단축키",
|
||||
"[title]markdown_hotkeys_desc": "특정 텍스트 입력창에서 마크다운 형식 문자를 입력하기 위한 단축키를 활성화합니다. '/help hotkeys'를 참고하세요.",
|
||||
"markdown_hotkeys_desc": "특정 텍스트 입력창에서 마크다운 형식 문자를 입력하기 위한 단축키를 활성화합니다. '/help hotkeys'를 참고하세요.",
|
||||
"Show group chat queue": "그룹 채팅 대기열 표시",
|
||||
"[title]In group chat, highlight the character(s) that are currently queued to generate responses and the order in which they will respond.": "그룹 채팅에서 응답을 생성하기 위해 현재 대기 중인 캐릭터와 응답할 순서를 강조 표시합니다.",
|
||||
"In group chat, highlight the character(s) that are currently queued to generate responses and the order in which they will respond.": "그룹 채팅에서 응답을 생성하기 위해 현재 대기 중인 캐릭터와 응답할 순서를 강조 표시합니다.",
|
||||
"Quick 'Impersonate' button": "빠른 '사칭' 버튼",
|
||||
"[title]Show a button in the input area to ask the AI to impersonate your character for a single message": "입력 영역에 AI에게 한 메시지 동안 당신의 캐릭터 연기를 사칭하도록 요청하는 버튼을 표시합니다.",
|
||||
"Show a button in the input area to ask the AI to impersonate your character for a single message": "입력 영역에 AI에게 한 메시지 동안 당신의 캐릭터 연기를 사칭하도록 요청하는 버튼을 표시합니다.",
|
||||
"Injection Template": "삽입 템플릿",
|
||||
"Query messages": "쿼리 메시지 수",
|
||||
"Score threshold": "점수 임계값",
|
||||
@@ -1614,7 +1613,7 @@
|
||||
"Ask": "묻기",
|
||||
"tag_import_none": "불러오지 않음",
|
||||
"tag_import_all": "전부",
|
||||
"Existing": "기존 태그 참조",
|
||||
"tag_import_existing": "기존 태그 참조",
|
||||
"You can add more": "원한다면",
|
||||
"or_welcome": "또는",
|
||||
"from other websites": "를 통해 다른 웹사이트들로부터 불러올 수 있습니다.",
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "gescheiden met komma's zonder spatie ertussen",
|
||||
"Custom Stopping Strings": "Aangepaste Stopreeksen",
|
||||
"JSON serialized array of strings": "JSON geserialiseerde reeks van strings",
|
||||
"Replace Macro in Custom Stopping Strings": "Macro vervangen in aangepaste stopreeksen",
|
||||
"Replace Macro in Stop Strings": "Macro vervangen in aangepaste stopreeksen",
|
||||
"Auto-Continue": "Automatisch doorgaan",
|
||||
"Allow for Chat Completion APIs": "Chatvervolledigings-API's toestaan",
|
||||
"Target length (tokens)": "Doellengte (tokens)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "Verwijder een thema",
|
||||
"Update a theme file": "Werk een themabestand bij",
|
||||
"Save as a new theme": "Opslaan als nieuw thema",
|
||||
"Avatar Style": "Avatarstijl",
|
||||
"Avatar Style:": "Avatarstijl",
|
||||
"Circle": "Cirkel",
|
||||
"Square": "Vierkant",
|
||||
"Rectangle": "Rechthoek",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "Voorkeur karakterkaart prompt",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "Als aangevinkt en de karakterkaart bevat een jailbreak-override (Post History Instruction), gebruik die in plaats daarvan",
|
||||
"Prefer Character Card Jailbreak": "Voorkeur karakterkaart jailbreak",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Vermijd het bijsnijden en vergroten/verkleinen van geïmporteerde karakterafbeeldingen. Indien uitgeschakeld, bijsnijden/formaat wijzigen naar 512 x 768.",
|
||||
"never_resize_avatars_tooltip": "Vermijd het bijsnijden en vergroten/verkleinen van geïmporteerde karakterafbeeldingen. Indien uitgeschakeld, bijsnijden/formaat wijzigen naar 512 x 768.",
|
||||
"Never resize avatars": "Avatars nooit verkleinen",
|
||||
"Show actual file names on the disk, in the characters list display only": "Toon de werkelijke bestandsnamen op de schijf, alleen in de weergave van de lijst met personages",
|
||||
"Show avatar filenames": "Toon avatar bestandsnamen",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "Automatisch vegen",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Schakel de automatische-vegen functie in. Instellingen in dit gedeelte hebben alleen effect wanneer automatisch vegen is ingeschakeld",
|
||||
"Minimum generated message length": "Minimale gegenereerde berichtlengte",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Als het gegenereerde bericht korter is dan dit, activeer dan een automatische veeg",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Als het gegenereerde bericht korter is dan dit, activeer dan een automatische veeg",
|
||||
"Blacklisted words": "Verboden woorden",
|
||||
"words you dont want generated separated by comma ','": "woorden die je niet gegenereerd wilt hebben gescheiden door komma ','",
|
||||
"Blacklisted word count to swipe": "Aantal verboden woorden om te vegen",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "Nee",
|
||||
"popup-button-cancel": "Annuleren",
|
||||
"popup-button-import": "Importeren",
|
||||
"Advanced Defininitions": "Geavanceerde definities",
|
||||
"Advanced Definitions": "Geavanceerde definities",
|
||||
"Prompt Overrides": "Prompt-overschrijvingen",
|
||||
"(For Chat Completion and Instruct Mode)": "(Voor voltooiing van chat en instructiemodus)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Voeg {{original}} in in elk vak in om de respectievelijke standaardprompt vanuit systeeminstellingen op te nemen.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Chub Lorebook (directe link of ID)",
|
||||
"char_import_3": "JanitorAI-personage (directe link of UUID)",
|
||||
"char_import_4": "Pygmalion.chat-teken (directe link of UUID)",
|
||||
"char_import_5": "AICharacterCard.com-teken (directe link of ID)",
|
||||
"char_import_5": "AICharacterCards.com-teken (directe link of ID)",
|
||||
"char_import_6": "Directe PNG-link (zie",
|
||||
"char_import_7": "voor toegestane hosts)",
|
||||
"char_import_8": "RisuRealm-personage (directe link)",
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "separe com vírgulas sem espaço entre",
|
||||
"Custom Stopping Strings": "Cadeias de parada personalizadas",
|
||||
"JSON serialized array of strings": "Matriz de strings serializada em JSON",
|
||||
"Replace Macro in Custom Stopping Strings": "Substituir Macro em Strings de Parada Personalizadas",
|
||||
"Replace Macro in Stop Strings": "Substituir Macro em Strings de Parada Personalizadas",
|
||||
"Auto-Continue": "Auto-Continuar",
|
||||
"Allow for Chat Completion APIs": "Permitir APIs de Completar Chat",
|
||||
"Target length (tokens)": "Comprimento alvo (tokens)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "Excluir um tema",
|
||||
"Update a theme file": "Atualizar um arquivo de tema",
|
||||
"Save as a new theme": "Salvar como um novo tema",
|
||||
"Avatar Style": "Estilo de Avatar",
|
||||
"Avatar Style:": "Estilo de Avatar",
|
||||
"Circle": "Círculo",
|
||||
"Square": "Quadrado",
|
||||
"Rectangle": "Retângulo",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "Preferir Prompt do Cartão de Personagem",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "Se marcado e o cartão de personagem contiver uma substituição de jailbreak (Instrução de Histórico de Postagens), use isso em vez disso",
|
||||
"Prefer Character Card Jailbreak": "Preferir Jailbreak do Cartão de Personagem",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Evite cortar e redimensionar imagens de personagens importados. Quando desativado, corte/redimensione para 512x768.",
|
||||
"never_resize_avatars_tooltip": "Evite cortar e redimensionar imagens de personagens importados. Quando desativado, corte/redimensione para 512x768.",
|
||||
"Never resize avatars": "Nunca redimensionar avatares",
|
||||
"Show actual file names on the disk, in the characters list display only": "Mostrar nomes de arquivo reais no disco, apenas na exibição da lista de personagens",
|
||||
"Show avatar filenames": "Mostrar nomes de arquivo de avatar",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "Auto-swipe",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Ativar a função de auto-swipe. As configurações nesta seção só têm efeito quando o auto-swipe está ativado",
|
||||
"Minimum generated message length": "Comprimento mínimo da mensagem gerada",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Se a mensagem gerada for mais curta que isso, acione um auto-swipe",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Se a mensagem gerada for mais curta que isso, acione um auto-swipe",
|
||||
"Blacklisted words": "Palavras proibidas",
|
||||
"words you dont want generated separated by comma ','": "palavras que você não quer geradas separadas por vírgula ','",
|
||||
"Blacklisted word count to swipe": "Contagem de palavras proibidas para swipe",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "Não",
|
||||
"popup-button-cancel": "Cancelar",
|
||||
"popup-button-import": "Importar",
|
||||
"Advanced Defininitions": "Definições Avançadas",
|
||||
"Advanced Definitions": "Definições Avançadas",
|
||||
"Prompt Overrides": "Substituições de prompt",
|
||||
"(For Chat Completion and Instruct Mode)": "(Para conclusão de bate-papo e modo de instrução)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Insira {{original}} em qualquer caixa para incluir o prompt padrão respectivo das configurações do sistema.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Chub Lorebook (link direto ou ID)",
|
||||
"char_import_3": "Personagem JanitorAI (Link Direto ou UUID)",
|
||||
"char_import_4": "Caractere Pygmalion.chat (Link Direto ou UUID)",
|
||||
"char_import_5": "Personagem AICharacterCard.com (link direto ou ID)",
|
||||
"char_import_5": "Personagem AICharacterCards.com (link direto ou ID)",
|
||||
"char_import_6": "Link PNG direto (consulte",
|
||||
"char_import_7": "para hosts permitidos)",
|
||||
"char_import_8": "Personagem RisuRealm (link direto)",
|
||||
|
@@ -161,7 +161,7 @@
|
||||
"View hidden API keys": "Посмотреть скрытые API-ключи",
|
||||
"Advanced Formatting": "Расширенное форматирование",
|
||||
"Context Template": "Шаблон контекста",
|
||||
"Replace Macro in Custom Stopping Strings": "Заменять макросы в пользовательских стоп-строках",
|
||||
"Replace Macro in Stop Strings": "Заменять макросы в пользовательских стоп-строках",
|
||||
"Story String": "Строка истории",
|
||||
"Example Separator": "Разделитель примеров сообщений",
|
||||
"Chat Start": "Начало чата",
|
||||
@@ -195,12 +195,12 @@
|
||||
"Yes": "Да",
|
||||
"No": "Нет",
|
||||
"Context %": "Процент контекста",
|
||||
"Budget Cap": "Бюджетный лимит",
|
||||
"Budget Cap": "Лимит бюджета",
|
||||
"(0 = disabled)": "(0 = отключено)",
|
||||
"None": "Отсутствует",
|
||||
"User Settings": "Настройки пользователя",
|
||||
"UI Language": "Язык интерфейса",
|
||||
"Avatar Style": "Аватарки",
|
||||
"Avatar Style:": "Аватарки",
|
||||
"Circle": "Круглые",
|
||||
"Rectangle": "Прямоугольные",
|
||||
"Square": "Квадратные",
|
||||
@@ -265,7 +265,7 @@
|
||||
"Current Members": "Текущие участники",
|
||||
"Delete": "Удалить",
|
||||
"Cancel": "Отменить",
|
||||
"Advanced Defininitions": "Расширенное описание",
|
||||
"Advanced Definitions": "Расширенное описание",
|
||||
"Personality summary": "Резюме по личности",
|
||||
"Scenario": "Сценарий",
|
||||
"Talkativeness": "Разговорчивость",
|
||||
@@ -294,7 +294,7 @@
|
||||
"Avoid sending sensitive information to the Horde.": "Избегайте отправки личной информации Horde",
|
||||
"Review the Privacy statement": "Ознакомиться с заявлением о конфиденциальности",
|
||||
"Trusted workers only": "Только доверенные рабочие машины",
|
||||
"For privacy reasons, your API key will be hidden after you reload the page.": "По причинам безопасности ваш API-ключ будет скрыт после перезагрузки страницы.",
|
||||
"For privacy reasons, your API key will be hidden after you reload the page.": "Из соображений безопасности ваш API-ключ будет скрыт после перезагрузки страницы.",
|
||||
"-- Horde models not loaded --": "--Модель Horde не загружена--",
|
||||
"Example: http://127.0.0.1:5000/api ": "Пример: http://127.0.0.1:5000/api",
|
||||
"No connection...": "Нет соединения...",
|
||||
@@ -331,7 +331,6 @@
|
||||
"UID ↘": "UID ↘",
|
||||
"Trigger% ↗": "Триггер% ↗",
|
||||
"Trigger% ↘": "Триггер% ↘",
|
||||
"Order:": "Порядок:",
|
||||
"Depth:": "Глубина:",
|
||||
"Character Lore First": "Сначала лор персонажа",
|
||||
"Global Lore First": "Сначала глобальный лор",
|
||||
@@ -347,7 +346,7 @@
|
||||
"After Char Defs": "↓Перс.",
|
||||
"Before AN": "↑АЗ",
|
||||
"After AN": "↓АЗ",
|
||||
"Order": "Порядок:",
|
||||
"Order": "Очерёдность:",
|
||||
"Update a theme file": "Обновить файл темы",
|
||||
"Save as a new theme": "Сохранить как новую тему",
|
||||
"Minimum number of blacklisted words detected to trigger an auto-swipe": "Минимальное количество обнаруженных запрещённых слов, при котором срабатывает авто-свайп.",
|
||||
@@ -427,7 +426,7 @@
|
||||
"Requests logprobs from the API for the Token Probabilities feature": "Запросить логпробы из API для функции Token Probabilities.",
|
||||
"Automatically reject and re-generate AI message based on configurable criteria": "Автоматическое отклонение и повторная генерация сообщений AI на основе настраиваемых критериев.",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Включить авто-свайп. Настройки в этом разделе действуют только при включенном авто-свайпе.",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Если сгенерированное сообщение короче этого значения, срабатывает авто-свайп.",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Если сгенерированное сообщение короче этого значения, срабатывает авто-свайп.",
|
||||
"Reload and redraw the currently open chat": "Перезагрузить и перерисовать открытый в данный момент чат.",
|
||||
"Auto-Expand Message Actions": "Развернуть действия",
|
||||
"Persona Management": "Управление персоной",
|
||||
@@ -497,7 +496,7 @@
|
||||
"What this keyword should mean to the AI, sent verbatim": "Что это ключевое слово должно означать для ИИ, отправляется дословно",
|
||||
"Filter to Character(s)": "Фильтр по персонажу(ам)",
|
||||
"Character Exclusion": "Исключить персонажей",
|
||||
"Inclusion Group": "Включить персонажей",
|
||||
"Inclusion Group": "Группа записей",
|
||||
"Only one entry with the same label will be activated": "Будет активна только одна запись с одинаковой меткой",
|
||||
"-- Characters not found --": "-- Персонажей не найдено --",
|
||||
"(This will be the first message from the character that starts every chat)": "(Это будет первое сообщение от персонажа, когда вы начинаете новый чат)",
|
||||
@@ -541,7 +540,7 @@
|
||||
"NOT ANY": "НЕ ЛЮБОЙ",
|
||||
"Optional Filter": "Дополнительный фильтр",
|
||||
"New Entry": "Новая запись",
|
||||
"Fill empty Memo/Titles with Keywords": "Заполните пустые Заметки/Названия ключевыми словами",
|
||||
"Fill empty Memo/Titles with Keywords": "Заполнить пустые названия ключевыми словами",
|
||||
"AI Response Formatting": "Формат ответа ИИ",
|
||||
"Change Background Image": "Изменить фон",
|
||||
"Extensions": "Расширения",
|
||||
@@ -576,10 +575,10 @@
|
||||
"Characters sorting order": "Порядок сортировки персонажей",
|
||||
"Remove": "Убрать",
|
||||
"Select a World Info file for": "Выбрать файл с миром для",
|
||||
"Primary Lorebook": "Основного лорбука",
|
||||
"A selected World Info will be bound to this character as its own Lorebook.": "Информация о мире будет привязана к персонажу как его собственный лорбук",
|
||||
"When generating an AI reply, it will be combined with the entries from a global World Info selector.": "Когда ИИ генерирует ответ, он будет совмещён с записями из глобально выбранного мира",
|
||||
"Exporting a character would also export the selected Lorebook file embedded in the JSON data.": "При экспорте персонажа вместе с ним также выгрузится выбранный лорбук в виде JSON",
|
||||
"Primary Lorebook": "Основной лорбук",
|
||||
"A selected World Info will be bound to this character as its own Lorebook.": "Информация о мире будет привязана к персонажу как его собственный лорбук.",
|
||||
"When generating an AI reply, it will be combined with the entries from a global World Info selector.": "Когда ИИ генерирует ответ, он будет совмещён с записями из глобально выбранного мира.",
|
||||
"Exporting a character would also export the selected Lorebook file embedded in the JSON data.": "При экспорте персонажа вместе с ним также выгрузится выбранный лорбук в виде JSON.",
|
||||
"Additional Lorebooks": "Вспомогательные лорбуки",
|
||||
"Associate one or more auxillary Lorebooks with this character.": "Привязать к этому персонажу один или больше вспомогательных лорбуков",
|
||||
"NOTE: These choices are optional and won't be preserved on character export!": "ВНИМАНИЕ: эти выборы необязательные и не будут сохранены при экспорте персонажа!",
|
||||
@@ -594,7 +593,7 @@
|
||||
"Prompt": "Промпт",
|
||||
"Copy": "Скопировать",
|
||||
"Confirm": "Подтвердить",
|
||||
"Copy this message": "Скопировать сообщение",
|
||||
"Copy this message": "Продублировать сообщение",
|
||||
"Delete this message": "Удалить сообщение",
|
||||
"Move message up": "Переместить сообщение вверх",
|
||||
"Move message down": "Переместить сообщение вниз",
|
||||
@@ -613,7 +612,7 @@
|
||||
"Ask AI to write your message for you": "Попросить ИИ написать сообщение за вас",
|
||||
"Continue the last message": "Продолжить текущее сообщение",
|
||||
"Bind user name to that avatar": "Закрепить имя за этим аватаром",
|
||||
"Select this as default persona for the new chats.": "Выберать эту Персону в качестве персоны по умолчанию для новых чатов.",
|
||||
"Select this as default persona for the new chats.": "Выбирать эту персону по умолчанию для всех новых чатов.",
|
||||
"Change persona image": "Сменить аватар персоны",
|
||||
"Delete persona": "Удалить персону",
|
||||
"Reduced Motion": "Сокращение анимаций",
|
||||
@@ -628,7 +627,7 @@
|
||||
"UI Theme": "Тема UI",
|
||||
"This message is invisible for the AI": "Это сообщение невидимо для ИИ",
|
||||
"Sampler Priority": "Приоритет сэмплеров",
|
||||
"Ooba only. Determines the order of samplers.": "Только Ooba. Определяет порядок сэмплеров.",
|
||||
"Ooba only. Determines the order of samplers.": "Только oobabooga. Определяет порядок сэмплеров.",
|
||||
"Load default order": "Загрузить стандартный порядок",
|
||||
"Max Tokens Second": "Макс. кол-во токенов в секунду",
|
||||
"CFG": "CFG",
|
||||
@@ -641,7 +640,7 @@
|
||||
"Token Probabilities": "Вероятности токенов",
|
||||
"Close chat": "Закрыть чат",
|
||||
"Manage chat files": "Все чаты",
|
||||
"Import Extension From Git Repo": "Импортировать расширение из Git Repository",
|
||||
"Import Extension From Git Repo": "Импортировать расширение из Git-репозитория.",
|
||||
"Install extension": "Установить расширение",
|
||||
"Manage extensions": "Управление расширениями",
|
||||
"Tokens persona description": "Токенов",
|
||||
@@ -967,7 +966,7 @@
|
||||
"char_import_2": "Лорбук с Chub (прямая ссылка или ID)",
|
||||
"char_import_3": "Персонаж с JanitorAI (прямая ссылка или UUID)",
|
||||
"char_import_4": "Персонаж с Pygmalion.chat (прямая ссылка или UUID)",
|
||||
"char_import_5": "Персонаж с AICharacterCard.com (прямая ссылка или ID)",
|
||||
"char_import_5": "Персонаж с AICharacterCards.com (прямая ссылка или ID)",
|
||||
"char_import_6": "Прямая ссылка на PNG-файл (чтобы узнать список разрешённых хостов, загляните в",
|
||||
"char_import_7": ")",
|
||||
"Grammar String": "Грамматика",
|
||||
@@ -996,7 +995,7 @@
|
||||
"Set your custom avatar.": "Установить аватарку",
|
||||
"Remove your custom avatar.": "Сбросить аватарку",
|
||||
"Make a Snapshot": "Сделать снимок",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Не менять размер картинок у импортируемых персонажей. При отключении все картинки будут приводиться к размеру 512х768",
|
||||
"never_resize_avatars_tooltip": "Не менять размер картинок у импортируемых персонажей. При отключении все картинки будут приводиться к размеру 512х768",
|
||||
"Char List Subheader": "Доп. заголовок в списке персонажей",
|
||||
"# Messages to Load": "Сколько сообщений загружать",
|
||||
"(0 = All)": "(0 = все)",
|
||||
@@ -1123,16 +1122,15 @@
|
||||
"help_hotkeys_0": "Горячие клавиши",
|
||||
"You can browse a list of bundled characters in the": "Комплектных персонажей можно найти в меню",
|
||||
"Download Extensions & Assets": "Загрузить расширения и ресурсы",
|
||||
"menu within": "внутри этих кубиков",
|
||||
"menu within": "в меню",
|
||||
"Assets URL": "URL с описанием ресурсов",
|
||||
"Custom (OpenAI-compatible)": "Кастомный (совместимый с OpenAI)",
|
||||
"Custom Endpoint (Base URL)": "Кастомный эндпоинт (базовый URL)",
|
||||
"Example: http://localhost:1234/v1": "Пример: http://localhost:1234/v1",
|
||||
"at the end of the URL!": "!",
|
||||
"Custom API Key": "Ключ от кастомного API",
|
||||
"(Optional)": "(необязательно)",
|
||||
"Enter a Model ID": "Введите идентификатор модели",
|
||||
"Example: gpt-3.5-turbo": "Пример: gpt-3.5-turbo",
|
||||
"Example: gpt-4o": "Пример: gpt-4o",
|
||||
"Available Models": "Доступные модели",
|
||||
"Prompt Post-Processing": "Постобработка промпта",
|
||||
"Applies additional processing to the prompt before sending it to the API.": "Позволяет обработать промпт перед отправкой в API.",
|
||||
@@ -1342,7 +1340,7 @@
|
||||
"Chat Lorebook": "Chat Lorebook for",
|
||||
"chat_world_template_txt": "A selected World Info will be bound to this chat. When generating an AI reply,\n it will be combined with the entries from global and character lorebooks.",
|
||||
"Use tag as folder": "Tag as folder",
|
||||
"WI Entry Status:🔵 Constant🟢 Normal🔗 Vectorized❌ Disabled": "Статус записи:\n 🔵 Постоянная\n 🟢 Обычная\n 🔗 Векторизованная\n ❌ Отключена",
|
||||
"WI Entry Status:🔵 Constant🟢 Normal🔗 Vectorized": "Статус записи:\n 🔵 Постоянная\n 🟢 Обычная\n 🔗 Векторизованная",
|
||||
"WI_Entry_Status_Constant": "Постоянная",
|
||||
"WI_Entry_Status_Normal": "Обычная",
|
||||
"WI_Entry_Status_Vectorized": "Векторизованная",
|
||||
@@ -1366,13 +1364,7 @@
|
||||
"Can be used to automatically activate Quick Replies": "Can be used to automatically activate Quick Replies",
|
||||
"Automation ID": "Automation ID",
|
||||
"( None )": "( None )",
|
||||
"Delay until recursion (this entry can only be activated on recursive checking)": "Delay until recursion (this entry can only be activated on recursive checking)",
|
||||
"Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.Documentation: World Info - Inclusion Group": "Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.\rSupports multiple comma-separated groups.\r\rDocumentation: World Info - Inclusion Group",
|
||||
"Prioritize this entry: When checked, this entry is prioritized out of all selections.If multiple are prioritized, the one with the highest 'Order' is chosen.": "Prioritize this entry: When checked, this entry is prioritized out of all selections.\rIf multiple are prioritized, the one with the highest 'Order' is chosen.\r",
|
||||
"A relative likelihood of entry activation within the group": "A relative likelihood of entry activation within the group",
|
||||
"Group Weight": "Group Weight",
|
||||
"Add Memo": "Add Memo",
|
||||
"close": "close",
|
||||
"reset": "reset",
|
||||
"save": "save",
|
||||
"Open checkpoint chat": "Открыть чат из чекпоинта",
|
||||
@@ -1629,7 +1621,7 @@
|
||||
"Defines on importing cards which action should be chosen for importing its listed tags. 'Ask' will always display the dialog.": "Выберите, какие действия следует предпринять по отношению к тегам импортируемой карточки. При выборе опции \"Спрашивать\" вы будете решать это индивидуально для каждой карточки.",
|
||||
"Ask": "Спрашивать",
|
||||
"tag_import_all": "Все",
|
||||
"Existing": "Только существующие",
|
||||
"tag_import_existing": "Только существующие",
|
||||
"tag_import_none": "Не импортировать",
|
||||
"Using a proxy that you're not running yourself is a risk to your data privacy.": "Помните, что используя чужую прокси, вы подвергаете риску конфиденциальность своих данных.",
|
||||
"ANY support requests will be REFUSED if you are using a proxy.": "НЕ РАССЧИТЫВАЙТЕ на нашу поддержку, если используете прокси.",
|
||||
@@ -1950,7 +1942,7 @@
|
||||
"and connect to an": "и подключитесь к",
|
||||
"You can add more": "Можете добавить больше",
|
||||
"from other websites": "с других сайтов.",
|
||||
"Go to the": "Загляните в",
|
||||
"Go to the": "Заходите в",
|
||||
"to install additional features.": ", чтобы установить разные дополнительные ресурсы.",
|
||||
"or_welcome": "; также доступен",
|
||||
"Claude API Key": "Ключ от API Claude",
|
||||
@@ -1965,7 +1957,7 @@
|
||||
"Save": "Сохранить",
|
||||
"Chat Lorebook": "Лорбук для чата",
|
||||
"chat_world_template_txt": "Выбранный мир будет привязан к этому чату. Будет добавляться в промпт наряду с глобальным лорбуком и лором персонажа.",
|
||||
"world_button_title": "Лор персонажа\n\nНажмите, чтобы загрузить\nShift + клик, чтобы открыть диалог привязки мира",
|
||||
"world_button_title": "Лор персонажа\n\nНажмите, чтобы загрузить\nShift + ЛКМ, чтобы открыть диалог привязки мира",
|
||||
"No auxillary Lorebooks set. Click here to select.": "Вспомогательный лорбук не выбран. Нажмите, чтобы выбрать.",
|
||||
"ext_regex_user_input_desc": "Отправленные вами сообщения.",
|
||||
"ext_regex_ai_input_desc": "Полученные от API ответы.",
|
||||
@@ -2035,5 +2027,181 @@
|
||||
"tags_sorting_desc": "Автоматически сортировать теги по алфавиту после создания или переименования одного из них.\nПри выключении новые теги будут просто добавляться в конец.\n\nЕсли вручную перетащить один из тегов на другое место, автосортировка отключится.",
|
||||
"Imported tags:": "Импортируемые теги:",
|
||||
"Importing Tags": "Импорт тегов",
|
||||
"Couldn't import tags:": "Не удалось импортировать теги:"
|
||||
"Couldn't import tags:": "Не удалось импортировать теги:",
|
||||
"Allow fallback models": "Разрешить fallback-модели",
|
||||
"Allow fallback providers": "Разрешить fallback-провайдеров",
|
||||
"To use instruct formatting, switch to OpenRouter under Text Completion API.": "Переключитесь на OpenRouter в Text Completion API, чтобы использовать форматирование Instruct-режима.",
|
||||
"Select providers. No selection = all providers.": "Выберите провайдера. Нет выбранного = выбраны все.",
|
||||
"Model Providers": "Провайдеры моделей",
|
||||
"Select a model": "Выберите модель",
|
||||
"Search models...": "Искать по моделям...",
|
||||
"[Currently loaded]": "[Загруженная сейчас]",
|
||||
"Search providers...": "Искать по провайдерам...",
|
||||
"Automatically chooses an alternative provider if chosen providers can't serve your request.": "Автоматически переключаться на другого провайдера, если текущий не может обслужить запрос.",
|
||||
"Example: 127.0.0.1:8000": "Пример: 127.0.0.1:8000",
|
||||
"Edit a connection profile": "Редактировать профиль соединения",
|
||||
"System Prompt Name": "Название системного промпта",
|
||||
"Use System Prompt": "Использовать системный промпт",
|
||||
"Hint:": "Подсказка:",
|
||||
"Click on the setting name to omit it from the profile.": "Нажмите на название настройки, чтобы исключить её из профиля",
|
||||
"Included settings:": "Сохранённые параметры:",
|
||||
"Server URL": "Адрес сервера",
|
||||
"NanoGPT API Key": "Ключ от API NanoGPT",
|
||||
"NanoGPT Model": "Модель NanoGPT",
|
||||
"Use extension settings": "Использовать настройки из расширения",
|
||||
"DeepSeek API Key": "Ключ от API DeepSeek",
|
||||
"DeepSeek Model": "Модель DeepSeek",
|
||||
"prompt_post_processing_merge": "Объединять идущие подряд сообщения с одной ролью",
|
||||
"prompt_post_processing_semi": "Semi-strict (чередовать роли)",
|
||||
"prompt_post_processing_strict": "Strict (чередовать роли, сначала пользователь)",
|
||||
"Select Horde models": "Выбрать модель из Horde",
|
||||
"Model ID (optional)": "Идентификатор модели (необязательно)",
|
||||
"Derive context size from backend": "Использовать бэкенд для определения размера контекста",
|
||||
"Rename current preset": "Переименовать пресет",
|
||||
"No Worlds active. Click here to select.": "Нет активных миров. Нажмите, чтобы выбрать.",
|
||||
"Title/Memo": "Название",
|
||||
"Strategy": "Статус",
|
||||
"Position": "Позиция",
|
||||
"Trigger %": "% срабатывания",
|
||||
"Use global": "Глоб. настройка",
|
||||
"Whole Words": "Целые слова",
|
||||
"Non-recursable (will not be activated by another)": "Не рекурсивная (не активируется другими)",
|
||||
"Delay until recursion (can only be activated on recursive checking)": "Рекурсивная (активируется только рекурсией)",
|
||||
"Toggle entry's active state.": "Вкл/выкл запись.",
|
||||
"Prioritize": "Важная",
|
||||
"Prioritize this entry: When checked, this entry is prioritized out of all selections.If multiple are prioritized, the one with the highest 'Order' is chosen.": "Важная запись получает приоритет среди всех выбранных. Если важных записей несколько, выбирается та, у которой выше \"Очерёдность\".",
|
||||
"Group Weight": "Вес в группе",
|
||||
"A relative likelihood of entry activation within the group": "Относительная вероятность активации записи в рамках группы",
|
||||
"Sticky": "Липучка",
|
||||
"Sticky entries will stay active for N messages after being triggered.": "Запись-\"липучка\" останется активной в течение N сообщений после срабатывания.",
|
||||
"Cooldown": "Кулдаун",
|
||||
"Entries with a cooldown can't be activated N messages after being triggered.": "Запись с заданным кулдауном не активируется следующие N сообщений после срабатывания.",
|
||||
"Delay": "Задержка",
|
||||
"Entries with a delay can't be activated until there are N messages present in the chat.": "Запись с заданной задержкой может активироваться только после того, как в чате наберётся N сообщений.",
|
||||
"Non-sticky": "Нет",
|
||||
"No cooldown": "Нет",
|
||||
"No delay": "Нет",
|
||||
"Filter to Characters or Tags": "Фильтровать по персонажам или тегам",
|
||||
"Switch to plaintext mode": "Вкл/выкл режим чистого текста",
|
||||
"Exclude": "Режим исключения",
|
||||
"Switch the Character/Tags filter around to exclude the listed characters and tags from matching for this entry": "Инвертировать логику: для выбранных в фильтре персонажей/тегов данная запись активна НЕ БУДЕТ",
|
||||
"Apply current sorting as Order": "Настроить Очерёдность в соответствии с текущей сортировкой",
|
||||
"Create a new World Info": "Создать новый мир",
|
||||
"Enter a name for the new file:": "Название нового файла:",
|
||||
"Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.Documentation: World Info - Inclusion Group": "Если сразу несколько записей из одной группы окажутся активированными, по факту сработает только одна. Одна запись может входить в несколько групп, отделяются запятыми. Раздел в документации: World Info - Inclusion Group",
|
||||
"Valid World Info file name is required": "Требуется корректное имя для файла мира",
|
||||
"World Info file has an invalid format": "Файл мира имеет неизвестный формат",
|
||||
"World Info file has no entries": "В файле нет ни одной записи",
|
||||
"Character not found.": "Персонаж не найден",
|
||||
"Open a chat to get a name of the chat-bound lorebook": "Чтобы получить название привязанного к чату лорбука, требуется открыть чат.",
|
||||
"File is not valid: ${0}": "Файл повреждён или имеет неизвестный формат: ${0}",
|
||||
"The world with ${0} is invalid or corrupted.": "Мир ${0} повреждён или имеет неизвестный формат.",
|
||||
"Deactivated all worlds": "Все миры отключены",
|
||||
"No world found named: ${0}": "Не найдено мира с название ${0}",
|
||||
"Activated world: ${0}": "Мир ${0} включён",
|
||||
"Deactivated world: ${0}": "Мир ${0} отключён",
|
||||
"World was not active: ${0}": "Мир ${0} не включён",
|
||||
"The world '${0}' has been imported and linked to the character successfully.": "Мир ${0} успешно импортирован и привязан к персонажу.",
|
||||
"World/Lorebook imported": "Мир/лорбук импортирован",
|
||||
"Are you sure you want to import '${0}'?": "Вы точно хотите импортировать '${0}'?",
|
||||
"It will overwrite the World/Lorebook with the same name.": "Существующий мир с таким же названием будет перезаписан.",
|
||||
"Automatically 'continue' a response if the model stopped before reaching a certain amount of tokens.": "Автоматически \"продолжать\" ответ, если он оказался короче, чем целевая длина (в токенах).",
|
||||
"None (not injected)": "Никуда",
|
||||
"ext_sum_injection_position_none": "Пересказ не будет вставляться в промпт. Однако его по-прежнему можно будет вставить с помощью макроса {{summary}}",
|
||||
"ext_sum_include_wi_scan": "Учитывать при сканировании лорбуком",
|
||||
"ext_sum_include_wi_scan_desc": "Учитывать актуальный пересказ при сканировании промпта лорбуком.",
|
||||
"ext_sum_force_tip": "Отправить запрос на создание пересказа прямо сейчас.",
|
||||
"ext_sum_restore_tip": "Откатиться к предыдущему пересказу; используйте несколько раз, чтобы очистить историю пересказов для чата",
|
||||
"Built-in Extensions:": "Комплектные расширения:",
|
||||
"Installed Extensions:": "Установленные расширения:",
|
||||
"Loading third-party extensions... Please wait...": "Загрузка сторонних расширений... Пожалуйста, подождите...",
|
||||
"The page will be reloaded shortly...": "Страница будет перезагружена...",
|
||||
"Extensions state changed": "Изменено состояние расширения",
|
||||
"Error loading extensions. See browser console for details.": "Не удалось загрузить расширения. Подробности см. в консоли браузера.",
|
||||
"You don't have permission to update global extensions.": "Отсутствуют права на обновление глобальных расширений.",
|
||||
"Extension update failed": "Не удалось обновить расширение",
|
||||
"Extension ${0} updated to ${1}": "Расширение ${0} обновлено до ${1}",
|
||||
"Reload the page to apply updates": "Чтобы изменения вступили в силу, обновите страницу",
|
||||
"You don't have permission to delete global extensions.": "Отсутствуют права на удаление глобальных расширений.",
|
||||
"Are you sure you want to delete ${0}?": "Вы точно хотите удалить ${0}?",
|
||||
"You don't have permission to move extensions.": "Отсутствуют права на перемещение расширений.",
|
||||
"Are you sure you want to move ${0} to your local extensions? This will make it available only for you.": "Вы точно хотите сделать ${0} локальным расширением? После этого оно будет доступно только вам.",
|
||||
"Are you sure you want to move ${0} to the global extensions? This will make it available for all users.": "Вы точно хотите сделать ${0} глобальным расширением? После этого оно будет доступно всем пользователям.",
|
||||
"Extension ${0} moved.": "Расширение ${0} перемещено.",
|
||||
"Extension ${0} deleted": "Расширение ${0} удалено.",
|
||||
"Please wait...": "Пожалуйста, подождите...",
|
||||
"Installing extension": "Идёт установка расширения",
|
||||
"Extension installation failed": "Не удалось установить расширение",
|
||||
"Extension '${0}' by ${1} (version ${2}) has been installed successfully!": "Расширение ${0} от автора ${1} (версия ${2}) успешно установлено!",
|
||||
"Extension installation successful": "Расширение установлено",
|
||||
"Extension updates available": "Доступных обновлений расширений",
|
||||
"Auto-updating extensions. This may take several minutes.": "Запущено автоматическое обновление расширений. Это может занять несколько минут.",
|
||||
"Install just for me": "Установить только мне",
|
||||
"Install": "Установить",
|
||||
"Install for all users": "Установить для всех пользователей",
|
||||
"Modules provided by your Extras API:": "Модули из Extras API:",
|
||||
"Not connected to the API!": "Нет соединения с API!",
|
||||
"ext_type_system": "Это комплектное расширение. Его нельзя удалить, а обновляется оно вместе со всей системой.",
|
||||
"Update all": "Обновить все",
|
||||
"Close": "Закрыть",
|
||||
"Optional modules:": "Необязательные модули:",
|
||||
"Sort: Display Name": "Сортировать: по названию",
|
||||
"Sort: Loading Order": "Сортировать: в порядке загрузки",
|
||||
"Click to toggle": "Нажмите, чтобы включить или выключить",
|
||||
"Loading Asset List": "Загрузить список ресурсов",
|
||||
"Don't ask again for this URL": "Запомнить выбор для этого адреса",
|
||||
"Are you sure you want to connect to the following url?": "Вы точно хотите подключиться к этому адресу?",
|
||||
"All": "Всё",
|
||||
"Characters": "Персонажи",
|
||||
"Ambient sounds": "Звуковой эмбиент",
|
||||
"Blip sounds": "Звуки уведомлений",
|
||||
"Background music": "Фоновая музыка",
|
||||
"Search": "Поиск",
|
||||
"extension_install_1": "Чтобы загружать расширения из этого списка, у вас должен быть установлен ",
|
||||
"extension_install_2": ".",
|
||||
"extension_install_3": "Нажмите на иконку ",
|
||||
"extension_install_4": ", чтобы перейти в репозиторий расширения и получить более подробную информацию о нём.",
|
||||
"Extension repo/guide:": "Репозиторий расширения:",
|
||||
"Preview in browser": "Предпросмотр",
|
||||
"Adds a function tool": "Частично или полностью работает через вызов функций",
|
||||
"Tool": "Функции",
|
||||
"Move extension": "Переместить расширение",
|
||||
"ext_type_local": "Это локальное расширение, доступно только вам",
|
||||
"ext_type_global": "Это глобальное расширение, доступно всем пользователям",
|
||||
"Move": "Переместить",
|
||||
"Enter the Git URL of the extension to install": "Введите Git-адрес расширения",
|
||||
"Please be aware that using external extensions can have unintended side effects and may pose security risks. Always make sure you trust the source before importing an extension. We are not responsible for any damage caused by third-party extensions.": "помните, что используя расширения от сторонних авторов, вы можете подвергать систему опасности. Устанавливайте расширения только от проверенных разработчиков. Мы не несём ответственности за любой ущерб, причинённый сторонними расширениями.",
|
||||
"Disclaimer:": "Внимание:",
|
||||
"Example:": "Пример:",
|
||||
"context_derived": "Считывать из метаданных модели (по возможности)",
|
||||
"instruct_derived": "Считывать из метаданных модели (по возможности)",
|
||||
"Confirm token parsing with": "Чтобы убедиться в правильности выделения токенов, используйте",
|
||||
"Reasoning Effort": "Рассуждения",
|
||||
"Constrains effort on reasoning for reasoning models.": "Регулирует объём внутренних рассуждений модели (reasoning), для моделей которые поддерживают эту возможность.\nНа данный момент поддерживаются три значения: Подробные, Обычные, Поверхностные.\nПри менее подробном рассуждении ответ получается быстрее, а также экономятся токены, уходящие на рассуждения.",
|
||||
"openai_reasoning_effort_low": "Поверхностные",
|
||||
"openai_reasoning_effort_medium": "Обычные",
|
||||
"openai_reasoning_effort_high": "Подробные",
|
||||
"Persona Lore Alt+Click to open the lorebook": "Лорбук данной персоны\nAlt + ЛКМ чтобы открыть лорбук",
|
||||
"Persona Lorebook for": "Лорбук для персоны",
|
||||
"persona_world_template_txt": "Выбранная Информация о мире будет привязана к этой персоне. Информация будет добавляться в каждом промпте вместе с глобальным лорбуком и лорбуками персонажа и чата.",
|
||||
"Global list": "Глобальный список",
|
||||
"Preset-specific list": "Список для данного пресета",
|
||||
"Banned tokens/strings are being sent in the request.": "Запрещённые токены и строки отсылаются в запросе.",
|
||||
"Banned tokens/strings are NOT being sent in the request.": "Запрещённые токены и строки НЕ отсылаются в запросе.",
|
||||
"Add a reasoning block": "Добавить блок рассуждений",
|
||||
"Create a copy of this message?": "Продублировать это сообщение?",
|
||||
"Max Recursion Steps": "Макс. глубина рекурсии",
|
||||
"0 = unlimited, 1 = scans once and doesn't recurse, 2 = scans once and recurses once, etc": "0 = неограничено, 1 = сканировать единожды, 2 = сканировать единожды и сделать один повторный проход, и т.д.\n(неактивно при указанном мин. числе активаций)",
|
||||
"(disabled when max recursion steps are used)": "(неактивно при указанной макс. глубине рекурсии)",
|
||||
"Enter a valid API URL": "Введите корректный адрес API",
|
||||
"No Ollama model selected.": "Не выбрана модель Ollama",
|
||||
"Background Fitting": "Способ подгонки фона под разрешение",
|
||||
"Chat Lore Alt+Click to open the lorebook": "Лорбук данного чата\nAlt + ЛКМ чтобы открыть лорбук",
|
||||
"Token Counter": "Подсчитать токены",
|
||||
"Type / paste in the box below to see the number of tokens in the text.": "Введите или вставьте текст в окошко ниже, чтобы подсчитать количество токенов в нём.",
|
||||
"Selected tokenizer:": "Выбранный токенайзер:",
|
||||
"Input:": "Входные данные:",
|
||||
"Tokenized text:": "Токенизированный текст:",
|
||||
"Token IDs:": "Идентификаторы токенов:",
|
||||
"Tokens:": "Токенов:"
|
||||
}
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "розділяйте комами без пропусків між ними",
|
||||
"Custom Stopping Strings": "Власні рядки зупинки",
|
||||
"JSON serialized array of strings": "JSON-серіалізований масив рядків",
|
||||
"Replace Macro in Custom Stopping Strings": "Замінювати макроси у власних рядках зупинки",
|
||||
"Replace Macro in Stop Strings": "Замінювати макроси у власних рядках зупинки",
|
||||
"Auto-Continue": "Автоматичне продовження",
|
||||
"Allow for Chat Completion APIs": "Дозволити для Chat Completion API",
|
||||
"Target length (tokens)": "Цільова довжина (токени)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "Видалити тему",
|
||||
"Update a theme file": "Оновити файл теми",
|
||||
"Save as a new theme": "Зберегти як нову тему",
|
||||
"Avatar Style": "Стиль аватара",
|
||||
"Avatar Style:": "Стиль аватара",
|
||||
"Circle": "Коло",
|
||||
"Square": "Квадрат",
|
||||
"Rectangle": "Прямокутник",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "Перевага запиту персонажа",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "Якщо відмічено і картка персонажа містить заміну джейлбрейку (Інструкцію), використовуйте її замість цього",
|
||||
"Prefer Character Card Jailbreak": "Перевага джейлбрейку персонажа",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Уникайте обрізання та зміни розміру імпортованих зображень символів. Коли вимкнено, обрізати/змінити розмір до 512x768.",
|
||||
"never_resize_avatars_tooltip": "Уникайте обрізання та зміни розміру імпортованих зображень символів. Коли вимкнено, обрізати/змінити розмір до 512x768.",
|
||||
"Never resize avatars": "Ніколи не змінювати розмір аватарів",
|
||||
"Show actual file names on the disk, in the characters list display only": "Показувати фактичні назви файлів на диску, тільки у відображенні списку персонажів",
|
||||
"Show avatar filenames": "Показувати імена файлів аватарів",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "Автоматичний змах",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Вмикає функцію автоматичного змаху. Налаштування в цьому розділі діють лише тоді, коли увімкнено автоматичний змах",
|
||||
"Minimum generated message length": "Мінімальна довжина згенерованого повідомлення",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Якщо згенероване повідомлення коротше за це, викликайте автоматичний змаху",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Якщо згенероване повідомлення коротше за це, викликайте автоматичний змаху",
|
||||
"Blacklisted words": "Список заборонених слів",
|
||||
"words you dont want generated separated by comma ','": "слова, які ви не хочете генерувати, розділені комою ','",
|
||||
"Blacklisted word count to swipe": "Кількість заборонених слів для змаху",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "Немає",
|
||||
"popup-button-cancel": "Скасувати",
|
||||
"popup-button-import": "Імпорт",
|
||||
"Advanced Defininitions": "Розширені визначення",
|
||||
"Advanced Definitions": "Розширені визначення",
|
||||
"Prompt Overrides": "Перевизначення підказок",
|
||||
"(For Chat Completion and Instruct Mode)": "(Для завершення чату та режиму інструктажу)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Вставте {{original}} в будь-яке поле, щоб включити відповідний запит з налаштувань системи.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Chub Lorebook (пряме посилання або ID)",
|
||||
"char_import_3": "Символ JanitorAI (пряме посилання або UUID)",
|
||||
"char_import_4": "Символ Pygmalion.chat (пряме посилання або UUID)",
|
||||
"char_import_5": "Символ AICharacterCard.com (пряме посилання або ідентифікатор)",
|
||||
"char_import_5": "Символ AICharacterCards.com (пряме посилання або ідентифікатор)",
|
||||
"char_import_6": "Пряме посилання на PNG (див",
|
||||
"char_import_7": "для дозволених хостів)",
|
||||
"char_import_8": "Персонаж RisuRealm (пряме посилання)",
|
||||
|
@@ -482,7 +482,7 @@
|
||||
"separate with commas w/o space between": "phân tách bằng dấu phẩy không có khoảng trắng giữa",
|
||||
"Custom Stopping Strings": "Chuỗi dừng tùy chỉnh",
|
||||
"JSON serialized array of strings": "Mảng chuỗi được tuần tự hóa JSON",
|
||||
"Replace Macro in Custom Stopping Strings": "Thay thế Macro trong Chuỗi Dừng Tùy chỉnh",
|
||||
"Replace Macro in Stop Strings": "Thay thế Macro trong Chuỗi Dừng Tùy chỉnh",
|
||||
"Auto-Continue": "Tự động Tiếp tục",
|
||||
"Allow for Chat Completion APIs": "Cho phép các API hoàn thành Trò chuyện",
|
||||
"Target length (tokens)": "Độ dài mục tiêu (token)",
|
||||
@@ -558,7 +558,7 @@
|
||||
"Delete a theme": "Xóa một chủ đề",
|
||||
"Update a theme file": "Cập nhật một tập tin chủ đề",
|
||||
"Save as a new theme": "Lưu dưới dạng chủ đề mới",
|
||||
"Avatar Style": "Kiểu hình đại diện",
|
||||
"Avatar Style:": "Kiểu hình đại diện",
|
||||
"Circle": "Hình tròn",
|
||||
"Square": "Hình vuông",
|
||||
"Rectangle": "Hình chữ nhật",
|
||||
@@ -633,7 +633,7 @@
|
||||
"Prefer Character Card Prompt": "Ưu tiên Gợi ý từ Card",
|
||||
"If checked and the character card contains a jailbreak override (Post History Instruction), use that instead": "Nếu được kiểm tra và thẻ nhân vật chứa một lệnh phá vỡ giam giữ (Hướng dẫn Lịch sử Bài viết), hãy sử dụng thay vào đó",
|
||||
"Prefer Character Card Jailbreak": "Ưu tiên Jailbreak từ Card",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "Tránh cắt xén và thay đổi kích thước hình ảnh ký tự đã nhập. Khi tắt, hãy cắt/thay đổi kích thước thành 512x768.",
|
||||
"never_resize_avatars_tooltip": "Tránh cắt xén và thay đổi kích thước hình ảnh ký tự đã nhập. Khi tắt, hãy cắt/thay đổi kích thước thành 512x768.",
|
||||
"Never resize avatars": "Không bao giờ thay đổi kích thước hình đại diện",
|
||||
"Show actual file names on the disk, in the characters list display only": "Hiển thị tên tệp thực tế trên đĩa, chỉ trong danh sách nhân vật",
|
||||
"Show avatar filenames": "Hiển thị tên tệp hình đại diện",
|
||||
@@ -709,7 +709,7 @@
|
||||
"Auto-swipe": "Tự động vuốt",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "Bật chức năng tự động vuốt. Các cài đặt trong phần này chỉ có tác dụng khi tự động vuốt được bật",
|
||||
"Minimum generated message length": "Độ dài tối thiểu của tin nhắn được tạo",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "Nếu tin nhắn được tạo ra ngắn hơn điều này, kích hoạt tự động vuốt",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "Nếu tin nhắn được tạo ra ngắn hơn điều này, kích hoạt tự động vuốt",
|
||||
"Blacklisted words": "Từ trong danh sách đen",
|
||||
"words you dont want generated separated by comma ','": "các từ bạn không muốn được tạo ra được phân tách bằng dấu phẩy ','",
|
||||
"Blacklisted word count to swipe": "Số từ trong danh sách đen để vuốt",
|
||||
@@ -879,7 +879,7 @@
|
||||
"popup-button-no": "KHÔNG",
|
||||
"popup-button-cancel": "Hủy",
|
||||
"popup-button-import": "Nhập",
|
||||
"Advanced Defininitions": "Các Định nghĩa Nâng cao",
|
||||
"Advanced Definitions": "Các Định nghĩa Nâng cao",
|
||||
"Prompt Overrides": "Ghi đè Prompt",
|
||||
"(For Chat Completion and Instruct Mode)": "(Đối với chế độ hoàn thành trò chuyện và hướng dẫn)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Chèn {{original}} vào bất kỳ hộp nào để bao gồm Prompt mặc định tương ứng từ cài đặt hệ thống.",
|
||||
@@ -1376,7 +1376,7 @@
|
||||
"char_import_2": "Chub (Nhập URL trực tiếp hoặc ID)",
|
||||
"char_import_3": "JanitorAI (Nhập URL trực tiếp hoặc UUID)",
|
||||
"char_import_4": "Pygmalion.chat (Nhập URL trực tiếp hoặc UUID)",
|
||||
"char_import_5": "AICharacterCard.com (Nhập URL trực tiếp hoặc ID)",
|
||||
"char_import_5": "AICharacterCards.com (Nhập URL trực tiếp hoặc ID)",
|
||||
"char_import_6": "Nhập PNG trực tiếp (tham khảo",
|
||||
"char_import_7": "đối với các máy chủ được phép)",
|
||||
"char_import_8": "RisuRealm (URL trực tiếp)",
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"Favorite": "星标",
|
||||
"Tag": "标签",
|
||||
"Duplicate": "复制",
|
||||
"Persona": "角色",
|
||||
"Persona": "用户角色",
|
||||
"Delete": "删除",
|
||||
"AI Response Configuration": "AI响应配置",
|
||||
"AI Configuration panel will stay open": "AI配置面板将保持打开",
|
||||
@@ -78,7 +78,7 @@
|
||||
"Allow": "Allow",
|
||||
"Forbid": "Forbid",
|
||||
"Enable OpenAI completion streaming": "启用OpenAI文本补全流式传输",
|
||||
"Display the response bit by bit as it is generated.": "随着回复的生成,逐位显示结果。",
|
||||
"Display the response bit by bit as it is generated.": "随着回复的生成,逐词逐句地显示结果。",
|
||||
"When this is off, responses will be displayed all at once when they are complete.": "当此选项关闭时,回复将在完成后一次性显示。",
|
||||
"Frequency Penalty": "频率惩罚",
|
||||
"Presence Penalty": "存在惩罚",
|
||||
@@ -185,13 +185,13 @@
|
||||
"Mirostat Eta": "Mirostat η",
|
||||
"Learning rate of Mirostat": "Mirostat 的学习率。",
|
||||
"Beam search": "束搜索",
|
||||
"A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.": "A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.",
|
||||
"# of Beams": "# of Beams",
|
||||
"A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.": "一种在LLM采样中使用的贪婪暴力算法,用于找到最可能的单词或标记序列。它一次扩展多个候选序列,在每一步保留固定数量(光束宽度)的最佳序列。",
|
||||
"# of Beams": "光束数量",
|
||||
"The number of sequences generated at each step with Beam Search.": "The number of sequences generated at each step with Beam Search.",
|
||||
"Length Penalty": "长度惩罚",
|
||||
"Penalize sequences based on their length.": "Penalize sequences based on their length.",
|
||||
"Early Stopping": "提前停止",
|
||||
"Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.": "Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.",
|
||||
"Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.": "控制光束搜索的停止条件。勾选时,当生成到达‘光束数量’的序列时停止。如果未勾选,则采用启发式方法,当几乎不可能找到更好的候选项时停止生成。",
|
||||
"Contrastive search": "对比搜索",
|
||||
"Contrastive_search_txt": "通过利用大多数 LLM 表示空间的各向同性以鼓励多样性同时保持一致性的采样器。详见 Su 等人在 2022 年发表的论文 《A Contrastive Framework for Neural Text Generation》。",
|
||||
"Penalty Alpha": "惩罚系数 α",
|
||||
@@ -203,19 +203,22 @@
|
||||
"Ignore EOS Token": "忽略序列结束词符",
|
||||
"Ignore the EOS Token even if it generates.": "即使生成了序列结束词符,也忽略它。",
|
||||
"Skip Special Tokens": "跳过特殊词符",
|
||||
"Request Model Reasoning": "Request Model Reasoning",
|
||||
"Temperature Last": "温度放最后",
|
||||
"Temperature_Last_desc": "温度采样器放到最后使用。这通常是合理的。\n当启用时:首先进行潜在词符的选择,然后应用温度来修正它们的相对概率(技术上是对数似然)。\n当禁用时:首先应用温度来修正所有词符的相对概率,然后从中选择潜在词符。\n禁用此项可以增大分布在尾部的词符概率,这可能加大得到不相关回复的几率。",
|
||||
"Speculative Ngram": "推测性 Ngram",
|
||||
"Use a different speculative decoding method without a draft model": "使用不同的推测解码方法(不采用草稿模型)。最好使用草稿模型。推测性 Ngram 的效果不太好。",
|
||||
"Spaces Between Special Tokens": "特殊词符之间的空格",
|
||||
"Seed_desc": "A random seed to use for deterministic and reproducable outputs. Set to -1 to use a random seed.",
|
||||
"Seed_desc": "一个用于生成确定性和可复现的输出的随机种子。设置为 -1 时会使用随机种子。",
|
||||
"LLaMA / Mistral / Yi models only": "LLaMA / Mistral / Yi模型专用。首先确保您选择了适当的词符化器。\n这项设置决定了你不想在结果中看到的字符串。\n每行一个字符串。可以是文本或者[词符id]。\n许多词符以空格开头。如果不确定,请使用词符计数器。",
|
||||
"Global list": "Global list",
|
||||
"Example: some text [42, 69, 1337]": "例如:\n一些文本\n[42, 69, 1337]",
|
||||
"Preset-specific list": "Preset-specific list",
|
||||
"CFG": "CFG",
|
||||
"Classifier Free Guidance. More helpful tip coming soon": "无分类器指导(CFG)。更多有用的提示敬请期待。",
|
||||
"Scale": "缩放比例",
|
||||
"Negative Prompt": "负面提示词",
|
||||
"Used if CFG Scale is unset globally, per chat or character": "如果无分类器指导(CFG)缩放比例未在全局设置,它将作用于每个聊天或每个角色",
|
||||
"Used if CFG Scale is unset globally, per chat or character": "如果CFG缩放比例未被全局设置,它将作用于所有聊天或角色",
|
||||
"Add text here that would make the AI generate things you don't want in your outputs.": "请在此处添加文本,以避免生成您不希望出现在输出中的内容。",
|
||||
"Grammar String": "语法字符串",
|
||||
"GBNF or EBNF, depends on the backend in use. If you're using this you should know which.": "GBNF 或 EBNF,取决于使用的后端。如果您使用这个,您应该知道该用哪一个。",
|
||||
@@ -227,8 +230,8 @@
|
||||
"llama.cpp only. Determines the order of samplers. If Mirostat mode is not 0, sampler order is ignored.": "仅限 llama.cpp。确定采样器的顺序。如果 Mirostat 模式不为 0,则忽略采样器顺序。",
|
||||
"Sampler Priority": "采样器优先级",
|
||||
"Ooba only. Determines the order of samplers.": "确定采样器的顺序(仅适用于Ooba)",
|
||||
"Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.": "Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.",
|
||||
"Aphrodite only. Determines the order of samplers.": "Aphrodite only. Determines the order of samplers.",
|
||||
"Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.": "仅适用于 Aphrodite,用于确定采样器的顺序。偏移(Skew)始终在 softmax 后应用,因此不包含在这里。",
|
||||
"Aphrodite only. Determines the order of samplers.": "仅适用于 Aphrodite。用于确定采样器的顺序。",
|
||||
"Character Names Behavior": "角色名称行为",
|
||||
"Helps the model to associate messages with characters.": "有助于模型将消息与角色关联起来。",
|
||||
"None": "无",
|
||||
@@ -255,24 +258,31 @@
|
||||
"enable_functions_desc_1": "允许使用",
|
||||
"enable_functions_desc_2": "功能工具",
|
||||
"enable_functions_desc_3": "可以被各种扩展利用来提供附加功能。",
|
||||
"Send inline images": "发送内联图像",
|
||||
"image_inlining_hint_1": "如果模型支持,则在提示词中发送图像(例如 GPT-4V、Claude 3 或 Llava 13B)。\n对任何消息使用",
|
||||
"image_inlining_hint_2": "或",
|
||||
"image_inlining_hint_3": "菜单将图像文件附加到聊天中。",
|
||||
"Inline Image Quality": "内联图像质量",
|
||||
"Send inline images": "发送图片",
|
||||
"image_inlining_hint_1": "如果模型支持,就可以在提示词中发送图片(例如 GPT-4V、Claude 3 或 Llava 13B)。\n发送消息时,点击",
|
||||
"image_inlining_hint_2": "在这里(",
|
||||
"image_inlining_hint_3": ")将图片添加到消息中。",
|
||||
"Inline Image Quality": "图片画质",
|
||||
"openai_inline_image_quality_auto": "自动",
|
||||
"openai_inline_image_quality_low": "低",
|
||||
"openai_inline_image_quality_high": "高",
|
||||
"Use system prompt": "使用系统提示词",
|
||||
"Merges_all_system_messages_desc_1": "合并所有系统消息,直到第一条具有非系统角色的消息,然后通过",
|
||||
"Merges_all_system_messages_desc_2": "字段发送。",
|
||||
"Request model reasoning": "请求思维链",
|
||||
"Allows the model to return its thinking process.": "允许模型返回其思维过程。",
|
||||
"Constrains effort on reasoning for reasoning models.": "限定模型推理的强度。\n当前支持低、中、高三种强度。\n降低推理强度可以让模型更快回复,并节省推理所用的词符数。。",
|
||||
"Reasoning Effort": "推理强度",
|
||||
"openai_reasoning_effort_low": "低",
|
||||
"openai_reasoning_effort_medium": "中",
|
||||
"openai_reasoning_effort_high": "高",
|
||||
"Assistant Prefill": "AI预填",
|
||||
"Expand the editor": "展开编辑器",
|
||||
"Start Claude's answer with...": "以如下内容开始Claude的回答...",
|
||||
"Assistant Impersonation Prefill": "AI帮答预填",
|
||||
"Use system prompt (Claude 2.1+ only)": "使用系统提示词(仅适用于Claude 2.1+)",
|
||||
"Send the system prompt for supported models. If disabled, the user message is added to the beginning of the prompt.": "为支持的模型发送系统提示词。如果禁用,则用户消息将添加到提示词的开头。",
|
||||
"Confirm token parsing with": "Confirm token parsing with",
|
||||
"Confirm token parsing with": "确认使用以下工具进行词符解析",
|
||||
"Tokenizer": "词符化器",
|
||||
"New preset": "新预设",
|
||||
"Delete preset": "删除预设",
|
||||
@@ -316,9 +326,9 @@
|
||||
"Get your NovelAI API Key": "获取您的 NovelAI API 密钥",
|
||||
"Enter it in the box below": "在下面的框中输入",
|
||||
"Novel AI Model": "Novel AI 模型",
|
||||
"No connection...": "没有连接...",
|
||||
"No connection...": "无连接...",
|
||||
"API Type": "API 类型",
|
||||
"Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]": "Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]",
|
||||
"Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]": "通用(兼容 OpenAI)[LM Studio、LiteLLM 等]",
|
||||
"TogetherAI API Key": "TogetherAI API 密钥",
|
||||
"TogetherAI Model": "TogetherAI 模型",
|
||||
"-- Connect to the API --": "-- 连接到API --",
|
||||
@@ -326,7 +336,8 @@
|
||||
"Click Authorize below or get the key from": "点击下方授权或从以下位置获取密钥",
|
||||
"View Remaining Credits": "查看剩余额度",
|
||||
"OpenRouter Model": "OpenRouter 模型",
|
||||
"Model Providers": "模型提供者",
|
||||
"Model Providers": "模型提供商",
|
||||
"Automatically chooses an alternative provider if chosen providers can't serve your request.": "在当前选择的模型提供商无效时,自动选择备用的提供商。",
|
||||
"Allow fallback providers": "允许后备提供者",
|
||||
"InfermaticAI API Key": "InfermaticAI API 密钥",
|
||||
"InfermaticAI Model": "InfermaticAI 模型",
|
||||
@@ -350,7 +361,7 @@
|
||||
"All": "All",
|
||||
"class": "All Classes",
|
||||
"Toggle grid view": "切换网格视图",
|
||||
"No model description": "[No description]",
|
||||
"No model description": "[无描述]",
|
||||
"vllm-project/vllm": "vllm-project/vllm(OpenAI API 包装器模式)",
|
||||
"vLLM API key": "vLLM API 密钥",
|
||||
"Example: 127.0.0.1:8000": "示例:http://127.0.0.1:8000",
|
||||
@@ -372,7 +383,7 @@
|
||||
"Use an admin API key.": "使用管理员API密钥。",
|
||||
"koboldcpp API key (optional)": "koboldcpp API 密钥(可选)",
|
||||
"Example: 127.0.0.1:5001": "示例:127.0.0.1:5001",
|
||||
"Bypass status check": "绕过状态检查",
|
||||
"Bypass status check": "跳过状态检查",
|
||||
"Derive context size from backend": "从后端获取上下文长度",
|
||||
"Authorize": "授权",
|
||||
"Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "使用OAuth流程获取您的OpenRouter API令牌。您将被重定向到openrouter.ai",
|
||||
@@ -387,8 +398,8 @@
|
||||
"This will show up as your saved preset.": "这将显示为您保存的预设。",
|
||||
"Proxy Server URL": "代理服务器 URL",
|
||||
"Alternative server URL (leave empty to use the default value).": "备用服务器 URL(留空以使用默认值)。",
|
||||
"Doesn't work? Try adding": "不起作用?尝试添加",
|
||||
"at the end!": "!",
|
||||
"Doesn't work? Try adding": "不起作用?在末尾添加",
|
||||
"at the end!": "试试!",
|
||||
"Proxy Password": "代理密码",
|
||||
"Will be used as a password for the proxy instead of API key.": "将用作代理的密码,而不是 API 密钥。",
|
||||
"Peek a password": "查看密码",
|
||||
@@ -399,16 +410,17 @@
|
||||
"View API Usage Metrics": "查看API使用情况",
|
||||
"Follow": "按照",
|
||||
"these directions": "这些步骤",
|
||||
"to get your OpenAI API key.": "获取您的OpenAI API密钥。",
|
||||
"to get your OpenAI API key.": "获取您的 OpenAI API 密钥。",
|
||||
"Use Proxy password field instead. This input will be ignored.": "请使用“代理密码”字段。此输入将被忽略。",
|
||||
"OpenAI Model": "OpenAI 模型",
|
||||
"Bypass API status check": "绕过API状态检查",
|
||||
"Show External models (provided by API)": "显示外部模型(由API提供)",
|
||||
"Claude API Key": "Claude API Key",
|
||||
"Claude API Key": "Claude API 密钥",
|
||||
"Get your key from": "从以下位置获取您的密钥",
|
||||
"Anthropic's developer console": "Anthropic 开发者控制台",
|
||||
"Claude Model": "Claude 模型",
|
||||
"Window AI Model": "Window AI 模型",
|
||||
"Use extension settings": "使用扩展程序中的设定",
|
||||
"Allow fallback routes Description": "如果所选模型无法响应您的请求,则自动选择备用模型。",
|
||||
"Allow fallback models": "允许后备模型",
|
||||
"Model Order": "OpenRouter 模型顺序",
|
||||
@@ -417,6 +429,7 @@
|
||||
"Context Size": "上下文长度",
|
||||
"Group by vendors": "按厂商分组",
|
||||
"Group by vendors Description": "将 OpenAI 模型放在一组,将 Anthropic 模型放在另一组,等等。可以与排序结合。",
|
||||
"To use instruct formatting, switch to OpenRouter under Text Completion API.": "To use instruct formatting, switch to OpenRouter under Text Completion API.",
|
||||
"Scale API Key": "Scale API密钥",
|
||||
"Clear your cookie": "清除你的 Cookie",
|
||||
"Alt Method": "备用方法",
|
||||
@@ -430,23 +443,27 @@
|
||||
"Groq Model": "Groq 模型",
|
||||
"NanoGPT API Key": "NanoGPT API Key",
|
||||
"NanoGPT Model": "NanoGPT Model",
|
||||
"DeepSeek API Key": "DeepSeek API 密钥",
|
||||
"DeepSeek Model": "DeepSeek 模型",
|
||||
"Perplexity API Key": "Perplexity API 密钥",
|
||||
"Perplexity Model": "Perplexity 模型",
|
||||
"Cohere API Key": "Cohere API 密钥",
|
||||
"Cohere Model": "Cohere 模型",
|
||||
"Block Entropy API Key": "Block Entropy API Key",
|
||||
"Select a Model": "Select a Model",
|
||||
"Custom Endpoint (Base URL)": "自定义端点(基本 URL)",
|
||||
"Block Entropy API Key": "Block Entropy API 密钥",
|
||||
"Select a Model": "选择一个模型",
|
||||
"Custom Endpoint (Base URL)": "自定义端点(基础 URL)",
|
||||
"Example: http://localhost:1234/v1": "例如:http://localhost:1234/v1",
|
||||
"at the end of the URL!": "到 URL 的末尾!",
|
||||
"Custom API Key": "自定义 API 密钥",
|
||||
"(Optional)": "(可选)",
|
||||
"Enter a Model ID": "输入模型名",
|
||||
"Example: gpt-3.5-turbo": "例如:gpt-3.5-turbo",
|
||||
"Example: gpt-4o": "例如:gpt-4o",
|
||||
"Available Models": "可用模型",
|
||||
"Prompt Post-Processing": "提示词后处理",
|
||||
"Applies additional processing to the prompt before sending it to the API.": "在将提示词发送到 API 之前对其进行额外处理。",
|
||||
"prompt_post_processing_none": "未选择",
|
||||
"prompt_post_processing_merge": "合并相同角色连续的发言",
|
||||
"prompt_post_processing_semi": "半严格(强制对话角色交替)",
|
||||
"prompt_post_processing_strict": "严格(强制对话角色交替、用户最先)",
|
||||
"01.AI API Key": "01.AI API密钥",
|
||||
"01.AI Model": "01.AI 模型",
|
||||
"Additional Parameters": "附加参数",
|
||||
@@ -459,9 +476,9 @@
|
||||
"AI Response Formatting": "AI回复格式化",
|
||||
"Advanced Formatting": "高级格式化设置",
|
||||
"Import Advanced Formatting settings": "导入高级格式化设置\n\n对于指导和上下文模板,你也可以提供旧版文件。",
|
||||
"Master Import": "Master Import",
|
||||
"Master Import": "全局导入",
|
||||
"Export Advanced Formatting settings": "导出高级格式化设置",
|
||||
"Master Export": "Master Export",
|
||||
"Master Export": "全局导出",
|
||||
"Context Template": "上下文模板",
|
||||
"context_derived": "若可能,从模型的元数据获取。",
|
||||
"Select your current Context Template": "选择你当前的上下文模板",
|
||||
@@ -501,27 +518,27 @@
|
||||
"Skip Example Dialogues Formatting": "跳过示例对话格式化",
|
||||
"Include Names": "包括名称",
|
||||
"Never": "永不",
|
||||
"Groups and Past Personas": "Groups and Past Personas",
|
||||
"Groups and Past Personas": "群聊和过去的用户角色",
|
||||
"Always": "永远",
|
||||
"Instruct Sequences": "Instruct Sequences",
|
||||
"User Message Sequences": "User Message Sequences",
|
||||
"Instruct Sequences": "指令序列",
|
||||
"User Message Sequences": "用户消息序列",
|
||||
"Inserted before a User message and as a last prompt line when impersonating.": "插入到用户消息之前并作为模拟时的最后一行提示词。",
|
||||
"User Prefix": "用户消息前缀",
|
||||
"Inserted after a User message.": "插入到用户消息之后。",
|
||||
"User Suffix": "用户消息后缀",
|
||||
"Assistant Message Sequences": "Assistant Message Sequences",
|
||||
"Assistant Message Sequences": "助手消息序列",
|
||||
"Inserted before an Assistant message and as a last prompt line when generating an AI reply.": "插入到助手消息之前并作为生成 AI 回复时的最后一行提示词。",
|
||||
"Assistant Prefix": "助手消息前缀",
|
||||
"Inserted after an Assistant message.": "插入于助手消息之后。",
|
||||
"Assistant Suffix": "助手消息后缀",
|
||||
"System Message Sequences": "System Message Sequences",
|
||||
"System Message Sequences": "系统消息序列",
|
||||
"Inserted before a System (added by slash commands or extensions) message.": "插入到系统(由快捷命令或扩展添加)消息之前。",
|
||||
"System Prefix": "System Message Prefix",
|
||||
"System Prefix": "系统消息前缀",
|
||||
"Inserted after a System message.": "插入到系统消息之后。",
|
||||
"System Suffix": "System Message Suffix",
|
||||
"System Suffix": "系统消息后缀",
|
||||
"If enabled, System Sequences will be the same as User Sequences.": "如果启用,系统序列将与用户序列相同。",
|
||||
"System same as User": "系统与用户相同",
|
||||
"System Prompt Sequences": "System Prompt Sequences",
|
||||
"System Prompt Sequences": "系统提示词序列",
|
||||
"Inserted before a System prompt.": "插入到系统提示词之前。",
|
||||
"System Prompt Prefix": "系统提示词前缀",
|
||||
"Inserted after a System prompt.": "在系统提示词后插入。",
|
||||
@@ -552,11 +569,29 @@
|
||||
"Prompt Content": "提示词内容",
|
||||
"Custom Stopping Strings": "自定义停止字符串",
|
||||
"JSON serialized array of strings": "JSON序列化的字符串数组",
|
||||
"Replace Macro in Custom Stopping Strings": "替换自定义停止字符串中的宏",
|
||||
"Replace Macro in Stop Strings": "替换自定义停止字符串中的宏",
|
||||
"Token Padding": "词符填充",
|
||||
"Reasoning": "推理",
|
||||
"reasoning_auto_parse": "Automatically parse reasoning blocks from main content between the reasoning prefix/suffix. Both fields must be defined and non-empty.",
|
||||
"Auto-Parse": "自动解析",
|
||||
"reasoning_auto_expand": "自动展开推理内容块。",
|
||||
"Auto-Expand": "自动展开",
|
||||
"reasoning_show_hidden": "对于隐藏推理内容的模型,展示其推理用时。",
|
||||
"Show Hidden": "显示隐藏内容",
|
||||
"reasoning_add_to_prompts": "将已有的推理块添加到提示词。若需新增一个推理块,请使用消息编辑菜单。",
|
||||
"Add to Prompts": "添加到提示词",
|
||||
"reasoning_max_additions": "Maximum number of reasoning blocks to be added per prompt, counting from the last message.",
|
||||
"Max": "最大值",
|
||||
"Reasoning Formatting": "推理内容格式化",
|
||||
"reasoning_prefix": "插入在推理内容之前。",
|
||||
"Prefix": "前缀",
|
||||
"reasoning_suffix": "插入在推理内容之后。",
|
||||
"Suffix": "后缀",
|
||||
"reasoning_separator": "插入在推理内容和消息内容之间。",
|
||||
"Separator": "分隔符",
|
||||
"Miscellaneous": "杂项",
|
||||
"Non-markdown strings": "非 Markdown 字符串",
|
||||
"comma delimited,no spaces between": "comma delimited,no spaces between",
|
||||
"comma delimited,no spaces between": "以逗号分隔,无需空格",
|
||||
"Start Reply With": "以...开始回复",
|
||||
"Show reply prefix in chat": "在聊天中显示回复前缀",
|
||||
"World Info": "世界信息",
|
||||
@@ -577,7 +612,7 @@
|
||||
"(0 = unlimited, use budget)": "(“0”为无限制,使用预算)",
|
||||
"Cap the number of entry activation recursions": "限制条目激活递归的次数",
|
||||
"Max Recursion Steps": "最大递归深度",
|
||||
"0 = unlimited, 1 = scans once and doesn't recurse, 2 = scans once and recurses once, etc\\n(disabled when min activations are used)": "“0”为无限制,“1”为扫描一次且不递归,“2”为扫描一次且递归一次,依此类推\n(当使用最小激活次数时,此功能被禁用)",
|
||||
"0 = unlimited, 1 = scans once and doesn't recurse, 2 = scans once and recurses once, etc": "“0”为无限制,“1”为扫描一次且不递归,“2”为扫描一次且递归一次,依此类推\n(当使用最小激活次数时,此功能被禁用)",
|
||||
"Insertion Strategy": "插入策略",
|
||||
"Sorted Evenly": "均匀排序",
|
||||
"Character Lore First": "角色世界书优先",
|
||||
@@ -632,7 +667,7 @@
|
||||
"Delete a theme": "删除主题",
|
||||
"Update a theme file": "更新主题文件",
|
||||
"Save as a new theme": "另存为新主题",
|
||||
"Avatar Style": "头像样式",
|
||||
"Avatar Style:": "头像样式:",
|
||||
"Circle": "圆形",
|
||||
"Square": "正方形",
|
||||
"Rectangle": "矩形",
|
||||
@@ -688,8 +723,8 @@
|
||||
"Show Message Token Count": "显示消息词符数",
|
||||
"Single-row message input area. Mobile only, no effect on PC": "将输入框限制为一行。仅适用于移动设备,对PC无影响",
|
||||
"Compact Input Area (Mobile)": "紧凑输入区域(移动端)",
|
||||
"Display swipe numbers for all messages, not just the last.": "Display swipe numbers for all messages, not just the last.",
|
||||
"Swipe # for All Messages": "Swipe # for All Messages",
|
||||
"Display swipe numbers for all messages, not just the last.": "显示所有信息的滑动编号,而非仅限最后一条。",
|
||||
"Swipe # for All Messages": "给所有信息分配滑动编号 #",
|
||||
"In the Character Management panel, show quick selection buttons for favorited characters": "在角色管理面板中,显示快速选择按钮以选择收藏的角色",
|
||||
"Characters Hotswap": "角色卡热切换",
|
||||
"Enable magnification for zoomed avatar display.": "启用放大功能以放大头像显示。",
|
||||
@@ -706,16 +741,16 @@
|
||||
"Defines on importing cards which action should be chosen for importing its listed tags. 'Ask' will always display the dialog.": "定义在导入卡片时应选择哪种操作来导入其列出的标签。“询问”将始终显示对话框。",
|
||||
"Import Card Tags": "导入卡片标签",
|
||||
"Ask": "询问",
|
||||
"tag_import_none": "无",
|
||||
"tag_import_all": "全部",
|
||||
"Existing": "现存的",
|
||||
"tag_import_none": "不导入",
|
||||
"tag_import_all": "导入全部",
|
||||
"tag_import_existing": "仅导入现有的",
|
||||
"Use fuzzy matching, and search characters in the list by all data fields, not just by a name substring": "使用模糊匹配,在列表中通过所有数据字段搜索角色,而不仅仅是名称子字符串",
|
||||
"Advanced Character Search": "高级角色搜索",
|
||||
"If checked and the character card contains a prompt override (System Prompt), use that instead": "开启后,如果角色卡已包含系统提示词,则覆盖当前的系统提示词。",
|
||||
"Prefer Character Card Prompt": "角色卡提示词优先",
|
||||
"If checked and the character card contains a Post-History Instructions override, use that instead": "开启后,如果角色卡包含后历史指令覆盖,则使用它。",
|
||||
"Prefer Character Card Instructions": "首选角色卡说明",
|
||||
"Avoid cropping and resizing imported character images. When off, crop/resize to 512x768": "避免裁剪和调整导入的角色图像的大小。关闭时,裁剪/调整大小为 512x768。",
|
||||
"never_resize_avatars_tooltip": "避免裁剪和调整导入的角色图像的大小。关闭时,裁剪/调整大小为 512x768。",
|
||||
"Never resize avatars": "永不调整头像大小",
|
||||
"Show actual file names on the disk, in the characters list display only": "在角色列表显示中,显示磁盘上实际的文件名。",
|
||||
"Show avatar filenames": "显示头像文件名",
|
||||
@@ -744,7 +779,7 @@
|
||||
"Restore User Input": "恢复用户输入",
|
||||
"Allow repositioning certain UI elements by dragging them. PC only, no effect on mobile": "允许通过拖动重新定位某些UI元素。仅适用于PC,对移动设备无影响",
|
||||
"Movable UI Panels": "可移动 UI 面板",
|
||||
"Reset MovingUI panel sizes/locations.": "重置 MovingUI 面板大小/位置。",
|
||||
"Reset MovingUI panel sizes/locations.": "重置 可移动UI 面板大小/位置。",
|
||||
"mui_reset": "Reset",
|
||||
"MovingUI preset. Predefined/saved draggable positions": "可移动UI预设。预定义/保存的可拖动位置",
|
||||
"MUI Preset": "可移动 UI 预设",
|
||||
@@ -752,7 +787,7 @@
|
||||
"Apply a custom CSS style to all of the ST GUI": "将自定义CSS样式应用于所有ST GUI",
|
||||
"Custom CSS": "自定义 CSS",
|
||||
"Chat/Message Handling": "聊天/消息处理",
|
||||
"# Messages to Load": "# 要加载的消息",
|
||||
"# Messages to Load": "要加载 # 条消息",
|
||||
"The number of chat history messages to load before pagination.": "分页前要加载的聊天历史消息数。",
|
||||
"(0 = All)": "(“0”为全部)",
|
||||
"Streaming FPS": "流式传输帧速率",
|
||||
@@ -797,11 +832,12 @@
|
||||
"Auto-swipe": "自动滑动",
|
||||
"Enable the auto-swipe function. Settings in this section only have an effect when auto-swipe is enabled": "启用自动滑动功能。仅当启用自动滑动时,本节中的设置才会生效",
|
||||
"Minimum generated message length": "生成的消息的最小长度",
|
||||
"If the generated message is shorter than this, trigger an auto-swipe": "如果生成的消息短于此长度,则触发自动滑动",
|
||||
"If the generated message is shorter than these many characters, trigger an auto-swipe": "如果生成的消息短于此长度,则触发自动滑动",
|
||||
"Blacklisted words": "屏蔽词",
|
||||
"words you dont want generated separated by comma ','": "不想生成的词语,用半角逗号“,”分隔",
|
||||
"Blacklisted word count to swipe": "触发滑动的黑名单词语数量",
|
||||
"Minimum number of blacklisted words detected to trigger an auto-swipe": "触发自动滑动刷新回复所需检测到的最少违禁词数量。",
|
||||
"Automatically 'continue' a response if the model stopped before reaching a certain amount of tokens.": "当回复没有达到特定词符数时,自动让模型“继续”这个回复。",
|
||||
"Auto-Continue": "自动继续",
|
||||
"Allow for Chat Completion APIs": "允许使用聊天补全API",
|
||||
"Target length (tokens)": "目标长度(以词符数计)",
|
||||
@@ -836,12 +872,12 @@
|
||||
"Change Background Image": "更改背景图片",
|
||||
"Background Image": "背景图片",
|
||||
"Filter": "搜索",
|
||||
"Background Fitting": "Background Fitting",
|
||||
"Classic": "Classic",
|
||||
"Cover": "Cover",
|
||||
"Contain": "Contain",
|
||||
"Stretch": "Stretch",
|
||||
"Center": "Center",
|
||||
"Background Fitting": "背景图片尺寸",
|
||||
"Classic": "经典",
|
||||
"Cover": "填充",
|
||||
"Contain": "不变换",
|
||||
"Stretch": "拉伸",
|
||||
"Center": "居中",
|
||||
"Automatically select a background based on the chat context": "根据聊天上下文自动选择背景",
|
||||
"Auto-select": "自动选择",
|
||||
"System Backgrounds": "系统背景",
|
||||
@@ -894,7 +930,7 @@
|
||||
"Favorite characters to add them to HotSwaps": "收藏角色以将它们添加到快速热切换区",
|
||||
"Token counts may be inaccurate and provided just for reference.": "词符计数可能不准确,仅供参考。",
|
||||
"Total tokens": "总词符数",
|
||||
"Calculating...": "正在计算…",
|
||||
"Calculating...": "正在计算...",
|
||||
"Tokens": "词符数",
|
||||
"Permanent tokens": "永久词符",
|
||||
"Permanent": "恒定的",
|
||||
@@ -923,6 +959,7 @@
|
||||
"Search / Create Tags": "搜索/创建标签",
|
||||
"View all tags": "查看所有标签",
|
||||
"Creator's Notes": "创作者的注释",
|
||||
"Character details are hidden.": "角色详情已隐藏。",
|
||||
"Show / Hide Description and First Message": "显示/隐藏描述和第一条消息",
|
||||
"Character Description": "角色描述",
|
||||
"Click to allow/forbid the use of external media for this character.": "单击以允许/禁止此角色使用外部媒体。",
|
||||
@@ -936,10 +973,10 @@
|
||||
"Chat Name (Optional)": "聊天名称(可选)",
|
||||
"Chat Lore": "聊天知识",
|
||||
"Click to select a new avatar for this group": "单击选择该群聊的新头像",
|
||||
"Group reply strategy": "群聊回复策略",
|
||||
"Group reply strategy": "群聊发言顺序",
|
||||
"Manual": "手动",
|
||||
"Natural order": "自然顺序",
|
||||
"List order": "上下顺序",
|
||||
"List order": "从上到下",
|
||||
"Group generation handling mode": "群组生成处理模式",
|
||||
"Swap character cards": "交换角色卡",
|
||||
"Join character cards (exclude muted)": "加入角色卡(不包括被禁言的)",
|
||||
@@ -990,7 +1027,7 @@
|
||||
"popup-button-import": "导入",
|
||||
"popup-button-crop": "裁剪",
|
||||
"Close popup": "关闭弹出窗口",
|
||||
"Advanced Defininitions": "高级定义",
|
||||
"Advanced Definitions": "高级定义",
|
||||
"Prompt Overrides": "提示词覆盖",
|
||||
"(For Chat Completion and Instruct Mode)": "(用于聊天补全和指导模式)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "将{{original}}插入到任一框中,以包含系统设置中的相应默认提示词。",
|
||||
@@ -1023,7 +1060,7 @@
|
||||
"Chatty": "高",
|
||||
"Examples of dialogue": "对话示例",
|
||||
"Important to set the character's writing style.": "设置角色的写作风格,很重要!",
|
||||
"(Examples of chat dialog. Begin each example with START on a new line.)": "(聊天对话的示例,每个示例都另起一行以<START>开头。)",
|
||||
"(Examples of chat dialog. Begin each example with START on a new line.)": "(聊天对话的示例,每个示例都另起一行以<START>开头。)",
|
||||
"Save": "保存",
|
||||
"Chat History": "聊天记录",
|
||||
"Import Chat": "导入聊天",
|
||||
@@ -1047,6 +1084,7 @@
|
||||
"Drag to reorder tag": "拖动以排序",
|
||||
"Use tag as folder": "标记为文件夹",
|
||||
"Delete tag": "删除标签",
|
||||
"Toggle entry's active state.": "切换条目激活状态。",
|
||||
"Entry Title/Memo": "条目标题/备忘录",
|
||||
"WI Entry Status:🔵 Constant🟢 Normal🔗 Vectorized": "世界书条目状态:\r🔵 永久\r🟢 关键词\r🔗 向量化",
|
||||
"WI_Entry_Status_Constant": "永久",
|
||||
@@ -1065,7 +1103,7 @@
|
||||
"Depth": "深度",
|
||||
"Order:": "顺序:",
|
||||
"Order": "顺序",
|
||||
"Trigger %:": "触发 %:",
|
||||
"Trigger %:": "触发 %:",
|
||||
"Duplicate world info entry": "重复的世界信息条目",
|
||||
"Delete world info entry": "删除世界信息条目",
|
||||
"Comma separated (required)": "逗号分隔(必填)",
|
||||
@@ -1107,12 +1145,15 @@
|
||||
"A relative likelihood of entry activation within the group": "组内进入激活的相对可能性",
|
||||
"Group Weight": "组权重",
|
||||
"Sticky entries will stay active for N messages after being triggered.": "粘性条目在被触发后将保持活跃状态 N 条消息。",
|
||||
"Sticky": "粘性",
|
||||
"Sticky": "黏性",
|
||||
"Non-sticky": "无黏性",
|
||||
"Entries with a cooldown can't be activated N messages after being triggered.": "具有冷却时间的条目在触发后 N 条消息内无法被激活。",
|
||||
"Cooldown": "冷却",
|
||||
"No cooldown": "无冷却",
|
||||
"Entries with a delay can't be activated until there are N messages present in the chat.": "直到聊天中出现 N 条消息时,延迟的条目才能被激活。",
|
||||
"Delay": "延迟",
|
||||
"Filter to Characters or Tags": "应用到角色或标签",
|
||||
"No delay": "无延迟",
|
||||
"Filter to Characters or Tags": "绑定到角色或标签",
|
||||
"Switch the Character/Tags filter around to exclude the listed characters and tags from matching for this entry": "切换角色/标签筛选方式,将列出的角色和标签排除在匹配范围之外",
|
||||
"Exclude": "排除",
|
||||
"-- Characters not found --": "-- 未找到角色 --",
|
||||
@@ -1132,8 +1173,8 @@
|
||||
"prompt_manager_relative": "相对",
|
||||
"prompt_manager_in_chat": "聊天中",
|
||||
"prompt_manager_depth": "深度",
|
||||
"Injection depth. 0 = after the last message, 1 = before the last message, etc.": "注入深度。0 = 在最后一条消息之后,1 = 在最后一条消息之前,等等。",
|
||||
"The content of this prompt is pulled from elsewhere and cannot be edited here.": "The content of this prompt is pulled from elsewhere and cannot be edited here.",
|
||||
"Injection depth. 0 = after the last message, 1 = before the last message, etc.": "注入深度。“0”为在最后一条消息之后,“1”为在最后一条消息之前,等等。",
|
||||
"The content of this prompt is pulled from elsewhere and cannot be edited here.": "此提示词的内容是从其他地方提取的,无法在此处进行编辑。",
|
||||
"Prompt": "提示词",
|
||||
"The prompt to be sent.": "要发送的提示词。",
|
||||
"This prompt cannot be overridden by character cards, even if overrides are preferred.": "即使选择覆盖,此提示词也不能被角色卡覆盖。",
|
||||
@@ -1144,7 +1185,7 @@
|
||||
"Message Actions": "消息操作",
|
||||
"Translate message": "翻译消息",
|
||||
"Generate Image": "生成图片",
|
||||
"Narrate": "叙述",
|
||||
"Narrate": "朗读",
|
||||
"Exclude message from prompts": "从提示词中排除消息",
|
||||
"Include message in prompts": "将消息包含在提示词中",
|
||||
"Embed file or image": "嵌入文件或图像",
|
||||
@@ -1155,9 +1196,16 @@
|
||||
"Edit": "编辑",
|
||||
"Confirm": "确认",
|
||||
"Copy this message": "复制此消息",
|
||||
"Add a reasoning block": "添加一个推理块",
|
||||
"Delete this message": "删除此消息",
|
||||
"Move message up": "将消息上移",
|
||||
"Move message down": "将消息下移",
|
||||
"Thought for some time": "思考了一会",
|
||||
"Confirm Edit": "确认",
|
||||
"Remove reasoning": "删除推理内容",
|
||||
"Cancel edit": "Cancel edit",
|
||||
"Copy reasoning": "复制推理内容",
|
||||
"Edit reasoning": "编辑推理内容",
|
||||
"Enlarge": "放大",
|
||||
"Caption": "标题",
|
||||
"Swipe left": "Swipe left",
|
||||
@@ -1181,9 +1229,9 @@
|
||||
"welcome_message_part_8": "您可随时通过",
|
||||
"welcome_message_part_9": "图标来更改此设置。",
|
||||
"Persona Name:": "用户角色名称:",
|
||||
"Temporarily disable automatic replies from this character": "暂时禁用此角色的自动回复",
|
||||
"Enable automatic replies from this character": "启用此角色的自动回复",
|
||||
"Trigger a message from this character": "从此角色触发消息",
|
||||
"Temporarily disable automatic replies from this character": "临时禁言此角色",
|
||||
"Enable automatic replies from this character": "解除禁言此角色",
|
||||
"Trigger a message from this character": "强制触发该角色发言",
|
||||
"Move up": "向上移动",
|
||||
"Move down": "向下移动",
|
||||
"View character card": "查看角色卡片",
|
||||
@@ -1194,11 +1242,11 @@
|
||||
"alternate_greetings_hint_1": "点击",
|
||||
"alternate_greetings_hint_2": "按钮即可开始!",
|
||||
"Alternate Greeting #": "额外问候语 #",
|
||||
"(This will be the first message from the character that starts every chat)": "(这是每次聊天开始时角色的第一条消息)",
|
||||
"(This will be the first message from the character that starts every chat)": "(这是每次聊天开始时角色的第一条消息)",
|
||||
"View contents": "查看内容",
|
||||
"Remove the file": "删除文件",
|
||||
"Author's Note": "作者注释",
|
||||
"Unique to this chat": "此聊天独有",
|
||||
"Unique to this chat": "仅对此聊天生效",
|
||||
"Checkpoints inherit the Note from their parent, and can be changed individually after that.": "检查点从其父级继承注释,之后可以单独更改。",
|
||||
"Include in World Info Scanning": "纳入世界信息扫描",
|
||||
"Before Main Prompt / Story String": "主提示词/故事线之前",
|
||||
@@ -1207,20 +1255,20 @@
|
||||
"Insertion Frequency": "插入频率",
|
||||
"(0 = Disable, 1 = Always)": "(“0”为禁用,“1”为始终)",
|
||||
"User inputs until next insertion:": "用户输入直到下一次插入:",
|
||||
"Character Author's Note (Private)": "人物作者注(私有)",
|
||||
"Character Author's Note (Private)": "人物作者注(私密)",
|
||||
"Won't be shared with the character card on export.": "导出时不会与角色卡共享。",
|
||||
"Will be automatically added as the author's note for this character. Will be used in groups, but can't be modified when a group chat is open.": "会自动添加为该角色的作者注解,在群聊中使用,但群聊开启时无法修改。",
|
||||
"Use character author's note": "使用角色作者的注释",
|
||||
"Replace Author's Note": "替换作者注",
|
||||
"Default Author's Note": "默认作者注",
|
||||
"Will be automatically added as the Author's Note for all new chats.": "将自动添加为所有新聊天的作者注释。",
|
||||
"Chat CFG": "聊天CFG",
|
||||
"1 = disabled": "“1”为已禁用",
|
||||
"Chat CFG": "本聊天的CFG缩放",
|
||||
"1 = disabled": "“1”为禁用",
|
||||
"write short replies, write replies using past tense": "写简短的回复,用过去时写回复",
|
||||
"Positive Prompt": "正面提示词",
|
||||
"Use character CFG scales": "单独为各个角色设置CFG缩放",
|
||||
"Character CFG": "角色CFG配置",
|
||||
"Will be automatically added as the CFG for this character.": "将自动添加为该角色的 CFG。",
|
||||
"Will be automatically added as the CFG for this character.": "将自动添加到该角色的CFG设置中。",
|
||||
"Global CFG": "全局CFG",
|
||||
"Will be used as the default CFG options for every chat unless overridden.": "除非被覆盖,否则将用作每次聊天的默认 CFG 选项。",
|
||||
"CFG Prompt Cascading": "CFG 提示词级联",
|
||||
@@ -1234,9 +1282,9 @@
|
||||
"Insertion Depth:": "插入深度:",
|
||||
"Token Probabilities": "词符概率",
|
||||
"Select a token to see alternatives considered by the AI.": "选择一个词符来查看 AI 考虑的替代方案。",
|
||||
"Reroll with the entire prefix": "Reroll with the entire prefix",
|
||||
"Reroll with the entire prefix": "使用完整前缀重新生成",
|
||||
"Not connected to API!": "未连接到API!",
|
||||
"Type a message, or /? for help": "键入消息,或 /? 获取帮助",
|
||||
"Type a message, or /? for help": "输入想发送的消息,或输入 /? 获取帮助",
|
||||
"Continue script execution": "继续执行脚本",
|
||||
"Pause script execution": "暂停执行脚本",
|
||||
"Abort script execution": "中止执行脚本",
|
||||
@@ -1256,6 +1304,10 @@
|
||||
"Regenerate": "重新生成",
|
||||
"Impersonate": "AI 帮答",
|
||||
"Continue": "继续",
|
||||
"extension_install_1": "若想从此页安装扩展程序,你需要提前安装",
|
||||
"extension_install_2": "。",
|
||||
"extension_install_3": "点这个图标(",
|
||||
"extension_install_4": ")前往扩展程序的代码仓库以了解如何使用它。",
|
||||
"These characters are the winners of character design contests and have outstandable quality.": "这些角色都是角色设计大赛的获奖者,品质非常出色。",
|
||||
"Contest Winners": "比赛获胜者",
|
||||
"These characters are the finalists of character design contests and have remarkable quality.": "这些角色都是角色设计大赛的入围作品,品质十分出色。",
|
||||
@@ -1324,9 +1376,11 @@
|
||||
"macro)": "宏指令)",
|
||||
"Automatically caption images": "自动为图像添加标题",
|
||||
"Edit captions before saving": "保存前编辑标题",
|
||||
"Included settings:": "包含的设置:",
|
||||
"{{@key}}": "{{@key}}:",
|
||||
"Profile name:": "配置名称:",
|
||||
"Creating a Connection Profile": "新建API连接配置",
|
||||
"{{@key}}": "{{@key}}:",
|
||||
"Click on the setting name to omit it from the profile.": "点击设置名称以将其从连接配置中删除。",
|
||||
"Enter a name:": "输入名字:",
|
||||
"Connection Profile": "API连接配置",
|
||||
"View connection profile details": "查看API连接配置详情",
|
||||
@@ -1335,14 +1389,17 @@
|
||||
"Edit a connection profile": "编辑API连接配置",
|
||||
"Reload a connection profile": "重载API连接配置",
|
||||
"Delete a connection profile": "删除API连接配置",
|
||||
"Omitted Settings:": "Omitted Settings:",
|
||||
"Omitted Settings:": "排除的设置:",
|
||||
"Character Expressions": "角色表情",
|
||||
"Use the selected API from Chat Translation extension settings.": "使用聊天翻译扩展程序中已选择的API。",
|
||||
"Translate text to English before classification": "分类之前将文本翻译成英文",
|
||||
"Show default images (emojis) if sprite missing": "如果表情包缺失,则显示默认图像(表情符号)",
|
||||
"Image Type - talkinghead (extras)": "图像类型 - 说话头像(附加内容)",
|
||||
"A single expression can have multiple sprites. Whenever the expression is chosen, a random sprite for this expression will be selected.": "A single expression can have multiple sprites. Whenever the expression is chosen, a random sprite for this expression will be selected.",
|
||||
"Allow multiple sprites per expression": "Allow multiple sprites per expression",
|
||||
"If the same expression is used again, re-roll the sprite. This only applies to expressions that have multiple available sprites assigned.": "If the same expression is used again, re-roll the sprite. This only applies to expressions that have multiple available sprites assigned.",
|
||||
"Re-roll if same expression is used again": "Re-roll if same sprite is used again",
|
||||
"Classifier API": "分类器 API",
|
||||
"Select the API for classifying expressions.": "选择用于对表达式进行分类的API。",
|
||||
"Main API": "主要 API",
|
||||
"Main API": "当前连接的 API",
|
||||
"WebLLM Extension": "WebLLM Extension",
|
||||
"LLM Prompt": "大语言模型提示词",
|
||||
"Will be used if the API doesn't support JSON schemas or function calling.": "如果 API 不支持 JSON 模式或函数调用,则会使用它。",
|
||||
@@ -1355,13 +1412,17 @@
|
||||
"You are in offline mode. Click on the image below to set the expression.": "您处于离线模式。点击下方图片即可设置表情。",
|
||||
"Sprite Folder Override": "表情文件夹覆盖",
|
||||
"Use a forward slash to specify a subfolder. Example: _space": "使用正斜杠指定子文件夹。例如:",
|
||||
"Upload sprite pack (ZIP)": "上传表情包 (ZIP)",
|
||||
"Upload sprite pack (ZIP)": "上传表情包(ZIP)",
|
||||
"Remove all image overrides": "删除所有图片覆盖",
|
||||
"Create new folder in the _space": "创建新文件夹到",
|
||||
"folder of your user data directory and name it as the name of the character.": "用户数据目录的文件夹并将其命名为角色的名称。",
|
||||
"Put images with expressions there. File names should follow the pattern:": "将带有表情的图像放在那里。文件名应遵循以下模式:",
|
||||
"expression_label_pattern": "[表达式标签].[图像格式]",
|
||||
"Sprite set:": "表情集:",
|
||||
"upload_expression_request": "请输入表情名称(不用加后缀)。",
|
||||
"upload_expression_naming_1": "素材名称必须符合所选表情 {{expression}} 的命名规范",
|
||||
"upload_expression_naming_2": "当存在多个表情时,名称应由表情名称与合法后缀构成,允许使用横杠'-'或英文句号'.'作为分隔符。",
|
||||
"upload_expression_replace": "点击“替换”以替换当前表情:",
|
||||
"Show Gallery": "展示图库",
|
||||
"ext_sum_title": "总结",
|
||||
"ext_sum_with": "总结如下:",
|
||||
@@ -1460,12 +1521,12 @@
|
||||
"ext_regex_global_scripts": "全局正则脚本",
|
||||
"ext_regex_global_scripts_desc": "影响所有角色,保存在本地设定中",
|
||||
"ext_regex_scoped_scripts": "局部正则脚本",
|
||||
"ext_regex_disallow_scoped": "Disallow using scoped regex",
|
||||
"ext_regex_allow_scoped": "允许使用范围正则表达式",
|
||||
"ext_regex_disallow_scoped": "不允许使用局部正则",
|
||||
"ext_regex_allow_scoped": "允许使用局部正则",
|
||||
"ext_regex_scoped_scripts_desc": "只影响当前角色,保存在角色卡片中",
|
||||
"Regex Editor": "正则表达式编辑器",
|
||||
"Test Mode": "测试模式",
|
||||
"ext_regex_desc": "正则是一款使用正则表达式查找/替换字符串的工具。如果您想了解更多信息,请点击标题旁边的 ?。",
|
||||
"ext_regex_desc": "“正则”是一个使用“正则表达式”来查找/替换字符串的工具。如果您想了解更多信息,请点击标题旁边的“?”。",
|
||||
"Input": "输入",
|
||||
"ext_regex_test_input_placeholder": "在此输入...",
|
||||
"Output": "输出",
|
||||
@@ -1476,7 +1537,7 @@
|
||||
"ext_regex_replace_string_placeholder": "使用 {{match}} 包含来自“查找正则表达式”或“$1”、“$2”等的匹配文本作为捕获组。",
|
||||
"Trim Out": "修剪掉",
|
||||
"ext_regex_trim_placeholder": "在替换之前全局修剪正则表达式匹配中任何不需要的部分。用回车键分隔每个元素。",
|
||||
"ext_regex_affects": "影响",
|
||||
"ext_regex_affects": "作用范围",
|
||||
"ext_regex_user_input_desc": "用户发送的消息",
|
||||
"ext_regex_user_input": "用户输入",
|
||||
"ext_regex_ai_input_desc": "从生成式API中获取的信息。",
|
||||
@@ -1484,6 +1545,7 @@
|
||||
"ext_regex_slash_desc": "通过 STscript 命令发送的消息。",
|
||||
"Slash Commands": "快捷命令",
|
||||
"ext_regex_wi_desc": "知识书/世界书 条目的内容。需要勾选“仅格式提示词”!",
|
||||
"ext_regex_reasoning_desc": "推理块内容。当'仅格式提示词'被选中时,它会影响提示词里的推理内容。",
|
||||
"ext_regex_min_depth_desc": "当应用于提示或显示时,仅影响深度至少为 N 级的消息。“0”为最后一条消息,“1”为倒数第二条消息等。仅计算 WI 条目 @Depth 和可用消息,即非隐藏或系统消息。",
|
||||
"Min Depth": "最小深度",
|
||||
"ext_regex_min_depth_placeholder": "无限",
|
||||
@@ -1566,7 +1628,7 @@
|
||||
"Click to set": "点击设置",
|
||||
"You can find your API key in the Stability AI dashboard.": "您可以在 Stability AI 仪表板中找到您的 API 密钥。",
|
||||
"Style Preset": "风格预设",
|
||||
"Prompt Upsampling": "Prompt Upsampling",
|
||||
"Prompt Upsampling": "提示词增强(Upsampling)",
|
||||
"Sampling method": "采样方法",
|
||||
"Scheduler": "调度器",
|
||||
"Resolution": "分辨率",
|
||||
@@ -1584,7 +1646,7 @@
|
||||
"Karras": "Karras",
|
||||
"Not all samplers supported.": "并非所有采样器都受支持。",
|
||||
"sd_adetailer_face": "Use ADetailer with face model during the generation. The ADetailer extension must be installed on the backend.",
|
||||
"Use ADetailer (Face)": "使用 ADetailer (Face)",
|
||||
"Use ADetailer (Face)": "使用 ADetailer(脸部)",
|
||||
"SMEA versions of samplers are modified to perform better at high resolution.": "SMEA 版本的采样器经过修改,在高分辨率下性能更佳。",
|
||||
"SMEA": "中小企业协会",
|
||||
"DYN variants of SMEA samplers often lead to more varied output, but may fail at very high resolutions.": "SMEA 采样器的 DYN 变体通常会产生更加多样化的输出,但在非常高的分辨率下可能会失败。",
|
||||
@@ -1611,6 +1673,13 @@
|
||||
"Interactive Mode": "交互模式",
|
||||
"Function Tool": "Function Tool",
|
||||
"Image Prompt Templates": "图像提示模板",
|
||||
"Token Counter": "词符计数器",
|
||||
"Type / paste in the box below to see the number of tokens in the text.": "在下方框中输入或粘贴你想要统计词符数量的文本。",
|
||||
"Selected tokenizer:": "已选分词器:",
|
||||
"Input:": "输入:",
|
||||
"Tokens:": "词符:",
|
||||
"Tokenized text:": "词符化文本:",
|
||||
"Token IDs:": "词符ID:",
|
||||
"ext_translate_btn_chat": "翻译聊天",
|
||||
"ext_translate_btn_input": "翻译输入",
|
||||
"ext_translate_delete_confirm_1": "你确定吗?",
|
||||
@@ -1627,14 +1696,15 @@
|
||||
"Select TTS Provider": "选择 文本转语音 的服务提供商",
|
||||
"tts_enabled": "已启用",
|
||||
"Narrate user messages": "朗读用户消息",
|
||||
"Auto Generation": "Auto Generation",
|
||||
"Requires auto generation to be enabled.": "Requires auto generation to be enabled.",
|
||||
"Narrate by paragraphs (when streaming)": "Narrate by paragraphs (when streaming)",
|
||||
"Auto Generation": "自动生成",
|
||||
"Requires auto generation to be enabled.": "需要启用自动生成功能。",
|
||||
"Narrate by paragraphs (when streaming)": "按段朗读(流式播放时)",
|
||||
"Narrate by paragraphs (when not streaming)": "按段朗读(非流式播放时)",
|
||||
"Only narrate quotes": "只朗读引号内文本",
|
||||
"Ignore text, even quotes, inside asterisk": "不朗读所有*星号内文本*,即使其被引号包裹",
|
||||
"Narrate only the translated text": "只朗读翻译后文本",
|
||||
"Skip codeblocks": "跳过代码块",
|
||||
"Skip tagged blocks": "跳过标签化的块(<tagged>)",
|
||||
"Skip tagged blocks": "跳过标签块里的内容(<标签>跳过这里</标签>)",
|
||||
"Pass Asterisks to TTS Engine": "将星号传递给文本转语音服务",
|
||||
"Audio Playback Speed": "音频播放速度",
|
||||
"Vector Storage": "向量存储",
|
||||
@@ -1656,11 +1726,12 @@
|
||||
"Max Entries": "最大条目数",
|
||||
"File vectorization settings": "文件向量化设置",
|
||||
"Enable for files": "为文件启用",
|
||||
"Only chunk on custom boundary": "仅按自定义边界分块",
|
||||
"Translate files into English before processing": "处理之前将文件翻译成英文",
|
||||
"Message attachments": "消息附件",
|
||||
"Size threshold (KB)": "大小阈值 (KB)",
|
||||
"Size threshold (KB)": "大小阈值(KB)",
|
||||
"Chunk size (chars)": "块大小(字符)",
|
||||
"Chunk overlap (%)": "块重叠 (%)",
|
||||
"Chunk overlap (%)": "块重叠(%)",
|
||||
"Retrieve chunks": "检索块",
|
||||
"Data Bank files": "数据库文件",
|
||||
"Injection Template": "注入模板",
|
||||
@@ -1691,6 +1762,7 @@
|
||||
"This will create a new subfolder...": "这将在 /data/ 目录中创建一个新的子文件夹,以用户的句柄作为文件夹名称。",
|
||||
"Note:": "提示:",
|
||||
"this chat is temporary and will be deleted as soon as you leave it.": "此聊天会话是临时的,会在你离开时被删除。",
|
||||
"Enter a new display name:": "输入一个新的昵称:",
|
||||
"Current Password:": "当前密码:",
|
||||
"New Password:": "新密码:",
|
||||
"Confirm New Password:": "确认新密码:",
|
||||
@@ -1709,24 +1781,27 @@
|
||||
"Chat Lorebook for": "聊天知识书",
|
||||
"chat_world_template_txt": "选定的世界信息将绑定到此聊天。生成 AI 回复时,\n它将与全球和角色传说书中的条目相结合。",
|
||||
"chat_rename_1": "输入聊天的新名称:",
|
||||
"chat_rename_2": "注意!!使用已有文件名会导致错误!!",
|
||||
"chat_rename_3": "此举会将次聊天与标记为“检查点”的聊天解绑。",
|
||||
"chat_rename_4": "不需要在结尾添加 '.jsonl'",
|
||||
"chat_rename_2": "注意!!与其他文件重名会导致错误!!",
|
||||
"chat_rename_3": "此举会将此聊天与标记为“检查点”的聊天解绑。",
|
||||
"chat_rename_4": "(不需要在结尾添加 '.JSONL' 后缀)",
|
||||
"Enter Checkpoint Name:": "输入检查点名称:",
|
||||
"(Leave empty to auto-generate)": "(留空以自动生成)",
|
||||
"The currently existing checkpoint will be unlinked and replaced with the new checkpoint, but can still be found in the Chat Management.": "当前检查点将会被解绑并替换为新的检查点,但仍可在聊天管理中找到。",
|
||||
"Include Body Parameters": "包括主体参数",
|
||||
"custom_include_body_desc": "聊天完成请求主体中要包含的参数(YAML 对象)\n\n示例:\n- top_k:20\n- repetition_penalty:1.1",
|
||||
"Exclude Body Parameters": "排除主体参数",
|
||||
"custom_exclude_body_desc": "要从聊天完成请求主体中排除的参数(YAML 数组)\n\n示例:\n- frequency_penalty\n- presence_penalty",
|
||||
"Include Request Headers": "包含请求标头",
|
||||
"custom_include_headers_desc": "聊天完成请求的附加标头(YAML 对象)\n\n示例:\n- CustomHeader:自定义值\n- AnotherHeader:自定义值",
|
||||
"Debug Warning": "此类别中的功能仅供高级用户使用。如果您不确定后果,请不要点击任何内容。",
|
||||
"Functions in this category are for advanced users only. Don't click anything if you're not sure about the consequences.": "此类别中的功能仅供高级用户使用。如果您不确定后果,请不要点击任何内容。",
|
||||
"THIS IS PERMANENT!": "此操作不可逆!",
|
||||
"Also delete the chat files": "同时删除聊天文件",
|
||||
"Are you sure you want to delete this user?": "您确定要删除该用户吗?",
|
||||
"Deleting:": "删除:",
|
||||
"Also wipe user data.": "也清空用户数据。",
|
||||
"Also wipe user data.": "同时清空用户数据",
|
||||
"Warning:": "警告:",
|
||||
"This action is irreversible.": "此操作不可逆。",
|
||||
"Type the user's handle below to confirm:": "在下面输入用户的名称以确认:",
|
||||
"Type the user's handle below to confirm:": "在下面输入此用户的用户句柄以确认删除操作:",
|
||||
"Are you sure you want to duplicate this character?": "你确定要复制这个角色吗?",
|
||||
"If you just want to start a new chat with the same character...": "如果你只是想要与此角色开启一个新的聊天,只需点击聊天左下方菜单中的“开始新聊天”按钮。",
|
||||
"Forbid Media Override explanation": "当前角色/群聊成员使用外部媒体的能力。",
|
||||
@@ -1764,11 +1839,11 @@
|
||||
"help_format_26": "内联代码",
|
||||
"help_format_27": "> 文本",
|
||||
"help_format_28": "显示为块引用(请注意 > 后面的空格)",
|
||||
"help_format_29": "# 文本",
|
||||
"help_format_29": "# 文本",
|
||||
"help_format_30": "显示为大标题(注意空格)",
|
||||
"help_format_32": "## 文本",
|
||||
"help_format_32": "## 文本",
|
||||
"help_format_33": "显示为中等标题(注意空格)",
|
||||
"help_format_35": "### 文本",
|
||||
"help_format_35": "### 文本",
|
||||
"help_format_36": "显示为小标题(注意空格)",
|
||||
"help_1": "您好!请选择您想要详细了解的帮助主题:",
|
||||
"help_2": "斜线命令",
|
||||
@@ -1815,15 +1890,32 @@
|
||||
"char_import_2": "Chub 知识书(直链或ID)",
|
||||
"char_import_3": "JanitorAI 角色(直链或UUID)",
|
||||
"char_import_4": "Pygmalion.chat 角色(直链或UUID)",
|
||||
"char_import_5": "AICharacterCard.com 角色(直链或ID)",
|
||||
"char_import_5": "AICharacterCards.com 角色(直链或ID)",
|
||||
"char_import_6": "被允许的PNG直链(请参阅",
|
||||
"char_import_7": ")",
|
||||
"char_import_8": "RisuRealm 角色(直链)",
|
||||
"Supports importing multiple characters.": "支持导入多个角色。",
|
||||
"Write each URL or ID into a new line.": "将每个 URL 或 ID 写入新行。",
|
||||
"Show Raw Prompt": "显示原始提示",
|
||||
"Copy Prompt": "复制提示",
|
||||
"Show Prompt Differences": "显示提示差异",
|
||||
"Enter the Git URL of the extension to install": "输入扩展程序的 Git URL 以安装",
|
||||
"Disclaimer:": "免责声明:",
|
||||
"Please be aware that using external extensions can have unintended side effects and may pose security risks. Always make sure you trust the source before importing an extension. We are not responsible for any damage caused by third-party extensions.": "使用外部的扩展程序可能存在意料外的副作用和安全隐患。在导入扩展程序前,请一定确认其来源可信。我们不为第三方扩展程序造成的任何损失负责。",
|
||||
"Prompt Itemization": "提示词拆分",
|
||||
"Show Raw Prompt": "显示原始提示词",
|
||||
"Copy Prompt": "复制提示词",
|
||||
"Show Prompt Differences": "显示提示词差异",
|
||||
"API/Model:": "API/模型:",
|
||||
"Preset:": "预设:",
|
||||
"Tokenizer:": "分词器:",
|
||||
"Only the white numbers really matter. All numbers are estimates. Grey color items may not have been included in the context due to certain prompt format settings.": "只有白色的数字作数。所有数字均为估算。\n 灰色的数字可能因特定的提示词处理规则而被排除在外。",
|
||||
"System Info:": "系统信息:",
|
||||
"Prompt Tokens:": "提示词Token:",
|
||||
"World Info:": "世界书:",
|
||||
"Chat History:": "聊天记录:",
|
||||
"Extensions:": "扩展程序:",
|
||||
"Bias:": "Bias:",
|
||||
"Total Tokens in Prompt:": "提示词的总Token数量:",
|
||||
"Max Context": "最大上下文:",
|
||||
"(Context Size - Response Length)": "(上下文长度 - 回复长度)",
|
||||
"System-wide Replacement Macros (in order of evaluation):": "系统范围的替换宏(按评估顺序):",
|
||||
"help_macros_1": "仅适用于斜线命令批处理。替换为上一个命令的返回结果。",
|
||||
"help_macros_2": "仅插入一个换行符。",
|
||||
@@ -1841,18 +1933,19 @@
|
||||
"help_macros_14": "未格式化的对话示例",
|
||||
"(only for Story String)": "(仅适用于故事字符串)",
|
||||
"help_macros_summary": "“Summarize”扩展生成的最新聊天摘要(如果有)。",
|
||||
"help_macros_15": "您当前的 Persona 用户名",
|
||||
"help_macros_15": "您当前的用户角色名称",
|
||||
"help_macros_16": "角色的名字",
|
||||
"help_macros_17": "角色的版本号",
|
||||
"help_macros_18": "以逗号分隔的群成员名称列表或单人聊天中的角色名称。别名:{{charIfNotGroup}}",
|
||||
"help_groupNotMuted": "与 {{group}} 相同,但排除被禁言的成员",
|
||||
"help_macros_19": "当前选定的 API 的文本生成模型名称。",
|
||||
"Can be inaccurate!": "可能不准确!",
|
||||
"Can be inaccurate!": "不一定准确!",
|
||||
"help_macros_20": "最新聊天消息的文本。",
|
||||
"help_macros_lastUser": "最后的用户聊天消息文本。",
|
||||
"help_macros_lastChar": "最后的角色聊天消息文本。",
|
||||
"help_macros_21": "最新聊天消息的索引号。对于斜线命令批处理很有用。",
|
||||
"help_macros_22": "上下文中包含的第一条消息的 ID。要求在当前会话中至少运行一次生成。",
|
||||
"help_macros_firstDisplayedMessageId": "第一条载入可见聊天的消息的ID",
|
||||
"help_macros_23": "最后一条聊天消息中当前滑动的 ID(以 1 为基数)。如果最后一条消息是用户或提示隐藏的,则为空字符串。",
|
||||
"help_macros_24": "最后一条聊天消息中的滑动次数。如果最后一条消息是用户隐藏或提示隐藏的,则为空字符串。",
|
||||
"help_macros_reverse": "反转宏的内容。",
|
||||
@@ -1913,7 +2006,9 @@
|
||||
"help_macros_68": "替换为全局变量“name”的值减 1 的结果",
|
||||
"help_macros_69": "替换为范围变量“name”的值",
|
||||
"help_macros_70": "用范围变量“name”的索引处的项目值(对于数组/列表或对象/字典)替换",
|
||||
"Choose what to export": "选择您想要导出什么:",
|
||||
"{{name}}": "{{name}}",
|
||||
"Choose what to import": "选择您想要导入什么:",
|
||||
"If necessary, you can later restore this chat file from the /backups folder": "若需要,您可稍后在 /backups 文件夹中恢复此聊天文件。",
|
||||
"Also delete the current chat file": "同时删除当前聊天文件",
|
||||
"Persona Lorebook for": "Persona Lorebook for",
|
||||
@@ -1938,8 +2033,13 @@
|
||||
"If you have sufficient credits, please try again later.": "若您有足够的余额,请稍后再试。",
|
||||
"Are you sure you want to reset your settings to factory defaults?": "您确定要将您的设置重置为出厂默认设置吗?",
|
||||
"Don't forget to save a snapshot of your settings before proceeding.": "在继续之前,不要忘记保存您的设置快照。",
|
||||
"Enter your password below to confirm:": "输入您的密码以确认:",
|
||||
"Chat Scenario Override": "聊天场景覆盖",
|
||||
"Remove": "移除",
|
||||
"Unique to this chat.": "仅对此聊天生效。",
|
||||
"All group members will use the following scenario text instead of what is specified in their character cards.": "All group members will use the following scenario text instead of what is specified in their character cards.",
|
||||
"The following scenario text will be used instead of the value set in the character card.": "The following scenario text will be used instead of the value set in the character card.",
|
||||
"Checkpoints inherit the scenario override from their parent, and can be changed individually after that.": "Checkpoints inherit the scenario override from their parent, and can be changed individually after that.",
|
||||
"Settings Snapshots": "设置快照",
|
||||
"Record a snapshot of your current settings.": "记录当前设置的快照。",
|
||||
"Make a Snapshot": "制作快照",
|
||||
@@ -1962,6 +2062,7 @@
|
||||
"Click on the folder icon to use this tag as a folder.": "点击文件夹图标来将此标签作为一个文件夹。",
|
||||
"Use alphabetical sorting": "按字母顺序排列",
|
||||
"tags_sorting_desc": "启用后,标签在创建或重命名时会自动按字母顺序排序。\n禁用后,新标签会追加到末尾。\n\n如果通过拖动手动重新排列标签,则自动排序将被禁用。",
|
||||
"Are you sure you want to delete the theme?": "你确定要删除这个主题吗?",
|
||||
"Hi,": "嗨,",
|
||||
"To enable multi-account features, restart the SillyTavern server with": "要启用多帐户功能,请使用以下命令重新启动 SillyTavern 服务器",
|
||||
"set to true in the config.yaml file.": "在 config.yaml 文件中设置为 true。",
|
||||
@@ -1982,6 +2083,8 @@
|
||||
"Reset Settings": "重置设置",
|
||||
"Wipe all user data and reset your account to factory settings.": "删除所有用户数据并将您的账号重置为默认设置。",
|
||||
"Reset Everything": "重置一切",
|
||||
"This will delete all your settings and data. There will be no undo button. Make sure you have a backup before proceeding.": "This will delete all your settings and data. There will be no undo button.\n Make sure you have a backup before proceeding.",
|
||||
"Account reset code has been posted to the server console.": "Account reset code has been posted to the server console.",
|
||||
"Reset Code:": "重置代码:",
|
||||
"Want to update?": "获取最新版本",
|
||||
"How to start chatting?": "如何快速开始聊天?",
|
||||
@@ -1999,12 +2102,12 @@
|
||||
"in the chat bar": "至聊天框",
|
||||
"SillyTavern Documentation Site": "访问 SillyTavern 帮助文档",
|
||||
"Still have questions?": "仍有疑问?",
|
||||
"Join the SillyTavern Discord": "加入 SillyTavern Discord群组",
|
||||
"Join the SillyTavern Discord": "加入 SillyTavern 的 Discord群组",
|
||||
"Post a GitHub issue": "在 GitHub 发布问题",
|
||||
"Contact the developers": "联系开发者",
|
||||
"If you're connected to an API, try asking me something!": "若您已经配置好API,尝试发送些什么吧!",
|
||||
"Title/Memo": "标题/备忘录",
|
||||
"Strategy": "Strategy",
|
||||
"Position": "位置",
|
||||
"Trigger %": "触发率 %"
|
||||
"Title/Memo": "标题(备忘)",
|
||||
"Strategy": "触发策略",
|
||||
"Position": "插入位置",
|
||||
"Trigger %": "触发概率%"
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
1434
public/script.js
1434
public/script.js
File diff suppressed because it is too large
Load Diff
@@ -395,7 +395,7 @@ class BulkEditOverlay {
|
||||
|
||||
/**
|
||||
* @typedef {object} LastSelected - An object noting the last selected character and its state.
|
||||
* @property {string} [characterId] - The character id of the last selected character.
|
||||
* @property {number} [characterId] - The character id of the last selected character.
|
||||
* @property {boolean} [select] - The selected state of the last selected character. <c>true</c> if it was selected, <c>false</c> if it was deselected.
|
||||
*/
|
||||
|
||||
@@ -672,10 +672,10 @@ class BulkEditOverlay {
|
||||
* @param {HTMLElement} currentCharacter - The html element of the currently toggled character
|
||||
*/
|
||||
handleShiftClick = (currentCharacter) => {
|
||||
const characterId = currentCharacter.getAttribute('chid');
|
||||
const characterId = Number(currentCharacter.getAttribute('data-chid'));
|
||||
const select = !this.selectedCharacters.includes(characterId);
|
||||
|
||||
if (this.lastSelected.characterId && this.lastSelected.select !== undefined) {
|
||||
if (this.lastSelected.characterId >= 0 && this.lastSelected.select !== undefined) {
|
||||
// Only if select state and the last select state match we execute the range select
|
||||
if (select === this.lastSelected.select) {
|
||||
this.toggleCharactersInRange(currentCharacter, select);
|
||||
@@ -691,7 +691,7 @@ class BulkEditOverlay {
|
||||
* @param {boolean} [param1.markState] - Whether the toggle of this character should be remembered as the last done toggle
|
||||
*/
|
||||
toggleSingleCharacter = (character, { markState = true } = {}) => {
|
||||
const characterId = character.getAttribute('chid');
|
||||
const characterId = Number(character.getAttribute('data-chid'));
|
||||
|
||||
const select = !this.selectedCharacters.includes(characterId);
|
||||
const legacyBulkEditCheckbox = character.querySelector('.' + BulkEditOverlay.legacySelectedClass);
|
||||
@@ -699,11 +699,11 @@ class BulkEditOverlay {
|
||||
if (select) {
|
||||
character.classList.add(BulkEditOverlay.selectedClass);
|
||||
if (legacyBulkEditCheckbox) legacyBulkEditCheckbox.checked = true;
|
||||
this.#selectedCharacters.push(String(characterId));
|
||||
this.#selectedCharacters.push(characterId);
|
||||
} else {
|
||||
character.classList.remove(BulkEditOverlay.selectedClass);
|
||||
if (legacyBulkEditCheckbox) legacyBulkEditCheckbox.checked = false;
|
||||
this.#selectedCharacters = this.#selectedCharacters.filter(item => String(characterId) !== item);
|
||||
this.#selectedCharacters = this.#selectedCharacters.filter(item => characterId !== item);
|
||||
}
|
||||
|
||||
this.updateSelectedCount();
|
||||
@@ -732,15 +732,15 @@ class BulkEditOverlay {
|
||||
* @param {boolean} select - <c>true</c> if the characters in the range are to be selected, <c>false</c> if deselected
|
||||
*/
|
||||
toggleCharactersInRange = (currentCharacter, select) => {
|
||||
const currentCharacterId = currentCharacter.getAttribute('chid');
|
||||
const currentCharacterId = Number(currentCharacter.getAttribute('data-chid'));
|
||||
const characters = Array.from(document.querySelectorAll('#' + BulkEditOverlay.containerId + ' .' + BulkEditOverlay.characterClass));
|
||||
|
||||
const startIndex = characters.findIndex(c => c.getAttribute('chid') === this.lastSelected.characterId);
|
||||
const endIndex = characters.findIndex(c => c.getAttribute('chid') === currentCharacterId);
|
||||
const startIndex = characters.findIndex(c => Number(c.getAttribute('data-chid')) === Number(this.lastSelected.characterId));
|
||||
const endIndex = characters.findIndex(c => Number(c.getAttribute('data-chid')) === currentCharacterId);
|
||||
|
||||
for (let i = Math.min(startIndex, endIndex); i <= Math.max(startIndex, endIndex); i++) {
|
||||
const character = characters[i];
|
||||
const characterId = character.getAttribute('chid');
|
||||
const characterId = Number(character.getAttribute('data-chid'));
|
||||
const isCharacterSelected = this.selectedCharacters.includes(characterId);
|
||||
|
||||
// Only toggle the character if it wasn't on the state we have are toggling towards.
|
||||
|
@@ -11,6 +11,7 @@ import { debounce_timeout } from './constants.js';
|
||||
import { renderTemplateAsync } from './templates.js';
|
||||
import { Popup } from './popup.js';
|
||||
import { t } from './i18n.js';
|
||||
import { isMobile } from './RossAscends-mods.js';
|
||||
|
||||
function debouncePromise(func, delay) {
|
||||
let timeoutId;
|
||||
@@ -1562,6 +1563,7 @@ class PromptManager {
|
||||
|
||||
listItemHtml += `
|
||||
<li class="${prefix}prompt_manager_prompt ${draggableClass} ${enabledClass} ${markerClass} ${importantClass}" data-pm-identifier="${escapeHtml(prompt.identifier)}">
|
||||
<span class="drag-handle">☰</span>
|
||||
<span class="${prefix}prompt_manager_prompt_name" data-pm-name="${encodedName}">
|
||||
${isMarkerPrompt ? '<span class="fa-fw fa-solid fa-thumb-tack" title="Marker"></span>' : ''}
|
||||
${isSystemPrompt ? '<span class="fa-fw fa-solid fa-square-poll-horizontal" title="Global Prompt"></span>' : ''}
|
||||
@@ -1741,6 +1743,7 @@ class PromptManager {
|
||||
makeDraggable() {
|
||||
$(`#${this.configuration.prefix}prompt_manager_list`).sortable({
|
||||
delay: this.configuration.sortableDelay,
|
||||
handle: isMobile() ? '.drag-handle' : null,
|
||||
items: `.${this.configuration.prefix}prompt_manager_prompt_draggable`,
|
||||
update: (event, ui) => {
|
||||
const promptOrder = this.getPromptOrderForCharacter(this.activeCharacter);
|
||||
|
@@ -27,7 +27,6 @@ import {
|
||||
send_on_enter_options,
|
||||
} from './power-user.js';
|
||||
|
||||
import { LoadLocal, SaveLocal, LoadLocalBool } from './f-localStorage.js';
|
||||
import { selected_group, is_group_generating, openGroupById } from './group-chats.js';
|
||||
import { getTagKeyForEntity, applyTagsOnCharacterSelect } from './tags.js';
|
||||
import {
|
||||
@@ -41,6 +40,8 @@ import { textgen_types, textgenerationwebui_settings as textgen_settings, getTex
|
||||
import { debounce_timeout } from './constants.js';
|
||||
|
||||
import { Popup } from './popup.js';
|
||||
import { accountStorage } from './util/AccountStorage.js';
|
||||
import { getCurrentUserHandle } from './user.js';
|
||||
|
||||
var RPanelPin = document.getElementById('rm_button_panel_pin');
|
||||
var LPanelPin = document.getElementById('lm_button_panel_pin');
|
||||
@@ -279,17 +280,32 @@ async function RA_autoloadchat() {
|
||||
// active character is the name, we should look it up in the character list and get the id
|
||||
if (active_character !== null && active_character !== undefined) {
|
||||
const active_character_id = characters.findIndex(x => getTagKeyForEntity(x) === active_character);
|
||||
if (active_character_id !== null) {
|
||||
await selectCharacterById(String(active_character_id));
|
||||
if (active_character_id !== -1) {
|
||||
await selectCharacterById(active_character_id);
|
||||
|
||||
// Do a little tomfoolery to spoof the tag selector
|
||||
const selectedCharElement = $(`#rm_print_characters_block .character_select[chid="${active_character_id}"]`);
|
||||
applyTagsOnCharacterSelect.call(selectedCharElement);
|
||||
} else {
|
||||
setActiveCharacter(null);
|
||||
saveSettingsDebounced();
|
||||
console.warn(`Currently active character with ID ${active_character} not found. Resetting to no active character.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (active_group !== null && active_group !== undefined) {
|
||||
await openGroupById(String(active_group));
|
||||
if (active_character) {
|
||||
console.warn('Active character and active group are both set. Only active character will be loaded. Resetting active group.');
|
||||
setActiveGroup(null);
|
||||
saveSettingsDebounced();
|
||||
} else {
|
||||
const result = await openGroupById(String(active_group));
|
||||
if (!result) {
|
||||
setActiveGroup(null);
|
||||
saveSettingsDebounced();
|
||||
console.warn(`Currently active group with ID ${active_group} not found. Resetting to no active group.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the character list hadn't been loaded yet, try again.
|
||||
@@ -300,7 +316,10 @@ export async function favsToHotswap() {
|
||||
const entities = getEntitiesList({ doFilter: false });
|
||||
const container = $('#right-nav-panel .hotswap');
|
||||
|
||||
const favs = entities.filter(x => x.item.fav || x.item.fav == 'true');
|
||||
// Hard limit is required because even if all hotswaps don't fit the screen, their images would still be loaded
|
||||
// 25 is roughly calculated as the maximum number of favs that can fit an ultrawide monitor with the default theme
|
||||
const FAVS_LIMIT = 25;
|
||||
const favs = entities.filter(x => x.item.fav || x.item.fav == 'true').slice(0, FAVS_LIMIT);
|
||||
|
||||
//helpful instruction message if no characters are favorited
|
||||
if (favs.length == 0) {
|
||||
@@ -409,32 +428,34 @@ function RA_autoconnect(PrevApi) {
|
||||
function OpenNavPanels() {
|
||||
if (!isMobile()) {
|
||||
//auto-open R nav if locked and previously open
|
||||
if (LoadLocalBool('NavLockOn') == true && LoadLocalBool('NavOpened') == true) {
|
||||
if (accountStorage.getItem('NavLockOn') == 'true' && accountStorage.getItem('NavOpened') == 'true') {
|
||||
//console.log("RA -- clicking right nav to open");
|
||||
$('#rightNavDrawerIcon').click();
|
||||
}
|
||||
|
||||
//auto-open L nav if locked and previously open
|
||||
if (LoadLocalBool('LNavLockOn') == true && LoadLocalBool('LNavOpened') == true) {
|
||||
if (accountStorage.getItem('LNavLockOn') == 'true' && accountStorage.getItem('LNavOpened') == 'true') {
|
||||
console.debug('RA -- clicking left nav to open');
|
||||
$('#leftNavDrawerIcon').click();
|
||||
}
|
||||
|
||||
//auto-open WI if locked and previously open
|
||||
if (LoadLocalBool('WINavLockOn') == true && LoadLocalBool('WINavOpened') == true) {
|
||||
if (accountStorage.getItem('WINavLockOn') == 'true' && accountStorage.getItem('WINavOpened') == 'true') {
|
||||
console.debug('RA -- clicking WI to open');
|
||||
$('#WIDrawerIcon').click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getUserInputKey = () => getCurrentUserHandle() + '_userInput';
|
||||
|
||||
function restoreUserInput() {
|
||||
if (!power_user.restore_user_input) {
|
||||
console.debug('restoreUserInput disabled');
|
||||
return;
|
||||
}
|
||||
|
||||
const userInput = LoadLocal('userInput');
|
||||
const userInput = localStorage.getItem(getUserInputKey());
|
||||
if (userInput) {
|
||||
$('#send_textarea').val(userInput)[0].dispatchEvent(new Event('input', { bubbles: true }));
|
||||
}
|
||||
@@ -442,7 +463,8 @@ function restoreUserInput() {
|
||||
|
||||
function saveUserInput() {
|
||||
const userInput = String($('#send_textarea').val());
|
||||
SaveLocal('userInput', userInput);
|
||||
localStorage.setItem(getUserInputKey(), userInput);
|
||||
console.debug('User Input -- ', userInput);
|
||||
}
|
||||
const saveUserInputDebounced = debounce(saveUserInput);
|
||||
|
||||
@@ -739,7 +761,7 @@ export function initRossMods() {
|
||||
|
||||
//toggle pin class when lock toggle clicked
|
||||
$(RPanelPin).on('click', function () {
|
||||
SaveLocal('NavLockOn', $(RPanelPin).prop('checked'));
|
||||
accountStorage.setItem('NavLockOn', $(RPanelPin).prop('checked'));
|
||||
if ($(RPanelPin).prop('checked') == true) {
|
||||
//console.log('adding pin class to right nav');
|
||||
$(RightNavPanel).addClass('pinnedOpen');
|
||||
@@ -757,7 +779,7 @@ export function initRossMods() {
|
||||
}
|
||||
});
|
||||
$(LPanelPin).on('click', function () {
|
||||
SaveLocal('LNavLockOn', $(LPanelPin).prop('checked'));
|
||||
accountStorage.setItem('LNavLockOn', $(LPanelPin).prop('checked'));
|
||||
if ($(LPanelPin).prop('checked') == true) {
|
||||
//console.log('adding pin class to Left nav');
|
||||
$(LeftNavPanel).addClass('pinnedOpen');
|
||||
@@ -776,7 +798,7 @@ export function initRossMods() {
|
||||
});
|
||||
|
||||
$(WIPanelPin).on('click', function () {
|
||||
SaveLocal('WINavLockOn', $(WIPanelPin).prop('checked'));
|
||||
accountStorage.setItem('WINavLockOn', $(WIPanelPin).prop('checked'));
|
||||
if ($(WIPanelPin).prop('checked') == true) {
|
||||
console.debug('adding pin class to WI');
|
||||
$(WorldInfo).addClass('pinnedOpen');
|
||||
@@ -796,8 +818,8 @@ export function initRossMods() {
|
||||
});
|
||||
|
||||
// read the state of right Nav Lock and apply to rightnav classlist
|
||||
$(RPanelPin).prop('checked', LoadLocalBool('NavLockOn'));
|
||||
if (LoadLocalBool('NavLockOn') == true) {
|
||||
$(RPanelPin).prop('checked', accountStorage.getItem('NavLockOn') == 'true');
|
||||
if (accountStorage.getItem('NavLockOn') == 'true') {
|
||||
//console.log('setting pin class via local var');
|
||||
$(RightNavPanel).addClass('pinnedOpen');
|
||||
$(RightNavDrawerIcon).addClass('drawerPinnedOpen');
|
||||
@@ -808,8 +830,8 @@ export function initRossMods() {
|
||||
$(RightNavDrawerIcon).addClass('drawerPinnedOpen');
|
||||
}
|
||||
// read the state of left Nav Lock and apply to leftnav classlist
|
||||
$(LPanelPin).prop('checked', LoadLocalBool('LNavLockOn'));
|
||||
if (LoadLocalBool('LNavLockOn') == true) {
|
||||
$(LPanelPin).prop('checked', accountStorage.getItem('LNavLockOn') === 'true');
|
||||
if (accountStorage.getItem('LNavLockOn') == 'true') {
|
||||
//console.log('setting pin class via local var');
|
||||
$(LeftNavPanel).addClass('pinnedOpen');
|
||||
$(LeftNavDrawerIcon).addClass('drawerPinnedOpen');
|
||||
@@ -821,8 +843,8 @@ export function initRossMods() {
|
||||
}
|
||||
|
||||
// read the state of left Nav Lock and apply to leftnav classlist
|
||||
$(WIPanelPin).prop('checked', LoadLocalBool('WINavLockOn'));
|
||||
if (LoadLocalBool('WINavLockOn') == true) {
|
||||
$(WIPanelPin).prop('checked', accountStorage.getItem('WINavLockOn') === 'true');
|
||||
if (accountStorage.getItem('WINavLockOn') == 'true') {
|
||||
//console.log('setting pin class via local var');
|
||||
$(WorldInfo).addClass('pinnedOpen');
|
||||
$(WIDrawerIcon).addClass('drawerPinnedOpen');
|
||||
@@ -837,22 +859,22 @@ export function initRossMods() {
|
||||
//save state of Right nav being open or closed
|
||||
$('#rightNavDrawerIcon').on('click', function () {
|
||||
if (!$('#rightNavDrawerIcon').hasClass('openIcon')) {
|
||||
SaveLocal('NavOpened', 'true');
|
||||
} else { SaveLocal('NavOpened', 'false'); }
|
||||
accountStorage.setItem('NavOpened', 'true');
|
||||
} else { accountStorage.setItem('NavOpened', 'false'); }
|
||||
});
|
||||
|
||||
//save state of Left nav being open or closed
|
||||
$('#leftNavDrawerIcon').on('click', function () {
|
||||
if (!$('#leftNavDrawerIcon').hasClass('openIcon')) {
|
||||
SaveLocal('LNavOpened', 'true');
|
||||
} else { SaveLocal('LNavOpened', 'false'); }
|
||||
accountStorage.setItem('LNavOpened', 'true');
|
||||
} else { accountStorage.setItem('LNavOpened', 'false'); }
|
||||
});
|
||||
|
||||
//save state of Left nav being open or closed
|
||||
$('#WorldInfo').on('click', function () {
|
||||
if (!$('#WorldInfo').hasClass('openIcon')) {
|
||||
SaveLocal('WINavOpened', 'true');
|
||||
} else { SaveLocal('WINavOpened', 'false'); }
|
||||
accountStorage.setItem('WINavOpened', 'true');
|
||||
} else { accountStorage.setItem('WINavOpened', 'false'); }
|
||||
});
|
||||
|
||||
var chatbarInFocus = false;
|
||||
@@ -868,21 +890,21 @@ export function initRossMods() {
|
||||
OpenNavPanels();
|
||||
}, 300);
|
||||
|
||||
$(SelectedCharacterTab).click(function () { SaveLocal('SelectedNavTab', 'rm_button_selected_ch'); });
|
||||
$('#rm_button_characters').click(function () { SaveLocal('SelectedNavTab', 'rm_button_characters'); });
|
||||
$(SelectedCharacterTab).click(function () { accountStorage.setItem('SelectedNavTab', 'rm_button_selected_ch'); });
|
||||
$('#rm_button_characters').click(function () { accountStorage.setItem('SelectedNavTab', 'rm_button_characters'); });
|
||||
|
||||
// when a char is selected from the list, save them as the auto-load character for next page load
|
||||
|
||||
// when a char is selected from the list, save their name as the auto-load character for next page load
|
||||
$(document).on('click', '.character_select', function () {
|
||||
const characterId = $(this).attr('chid') || $(this).data('id');
|
||||
const characterId = $(this).attr('data-chid');
|
||||
setActiveCharacter(characterId);
|
||||
setActiveGroup(null);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$(document).on('click', '.group_select', function () {
|
||||
const groupId = $(this).attr('chid') || $(this).attr('grid') || $(this).data('id');
|
||||
const groupId = $(this).attr('data-chid') || $(this).attr('data-grid');
|
||||
setActiveCharacter(null);
|
||||
setActiveGroup(groupId);
|
||||
saveSettingsDebounced();
|
||||
@@ -996,6 +1018,14 @@ export function initRossMods() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isModifiedKeyboardEvent(event) {
|
||||
return (event instanceof KeyboardEvent &&
|
||||
event.shiftKey ||
|
||||
event.ctrlKey ||
|
||||
event.altKey ||
|
||||
event.metaKey);
|
||||
}
|
||||
|
||||
$(document).on('keydown', async function (event) {
|
||||
await processHotkeys(event.originalEvent);
|
||||
});
|
||||
@@ -1063,14 +1093,21 @@ export function initRossMods() {
|
||||
// Ctrl+Enter for Regeneration Last Response. If editing, accept the edits instead
|
||||
if (event.ctrlKey && event.key == 'Enter') {
|
||||
const editMesDone = $('.mes_edit_done:visible');
|
||||
const reasoningMesDone = $('.mes_reasoning_edit_done:visible');
|
||||
if (editMesDone.length > 0) {
|
||||
console.debug('Accepting edits with Ctrl+Enter');
|
||||
$('#send_textarea').focus();
|
||||
$('#send_textarea').trigger('focus');
|
||||
editMesDone.trigger('click');
|
||||
return;
|
||||
} else if (is_send_press == false) {
|
||||
} else if (reasoningMesDone.length > 0) {
|
||||
console.debug('Accepting edits with Ctrl+Enter');
|
||||
$('#send_textarea').trigger('focus');
|
||||
reasoningMesDone.trigger('click');
|
||||
return;
|
||||
}
|
||||
else if (is_send_press == false) {
|
||||
const skipConfirmKey = 'RegenerateWithCtrlEnter';
|
||||
const skipConfirm = LoadLocalBool(skipConfirmKey);
|
||||
const skipConfirm = accountStorage.getItem(skipConfirmKey) === 'true';
|
||||
function doRegenerate() {
|
||||
console.debug('Regenerating with Ctrl+Enter');
|
||||
$('#option_regenerate').trigger('click');
|
||||
@@ -1082,13 +1119,15 @@ export function initRossMods() {
|
||||
let regenerateWithCtrlEnter = false;
|
||||
const result = await Popup.show.confirm('Regenerate Message', 'Are you sure you want to regenerate the latest message?', {
|
||||
customInputs: [{ id: 'regenerateWithCtrlEnter', label: 'Don\'t ask again' }],
|
||||
onClose: (popup) => regenerateWithCtrlEnter = popup.inputResults.get('regenerateWithCtrlEnter') ?? false,
|
||||
onClose: (popup) => {
|
||||
regenerateWithCtrlEnter = popup.inputResults.get('regenerateWithCtrlEnter') ?? false;
|
||||
},
|
||||
});
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
SaveLocal(skipConfirmKey, regenerateWithCtrlEnter);
|
||||
accountStorage.setItem(skipConfirmKey, String(regenerateWithCtrlEnter));
|
||||
doRegenerate();
|
||||
}
|
||||
return;
|
||||
@@ -1110,9 +1149,10 @@ export function initRossMods() {
|
||||
$('#send_textarea').val() === '' &&
|
||||
$('#character_popup').css('display') === 'none' &&
|
||||
$('#shadow_select_chat_popup').css('display') === 'none' &&
|
||||
!isInputElementInFocus()
|
||||
!isInputElementInFocus() &&
|
||||
!isModifiedKeyboardEvent(event)
|
||||
) {
|
||||
$('.swipe_left:last').click();
|
||||
$('.swipe_left:last').trigger('click', { source: 'keyboard', repeated: event.repeat });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1123,9 +1163,10 @@ export function initRossMods() {
|
||||
$('#send_textarea').val() === '' &&
|
||||
$('#character_popup').css('display') === 'none' &&
|
||||
$('#shadow_select_chat_popup').css('display') === 'none' &&
|
||||
!isInputElementInFocus()
|
||||
!isInputElementInFocus() &&
|
||||
!isModifiedKeyboardEvent(event)
|
||||
) {
|
||||
$('.swipe_right:last').click();
|
||||
$('.swipe_right:last').trigger('click', { source: 'keyboard', repeated: event.repeat });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -299,7 +299,7 @@ function loadSettings() {
|
||||
$('#extension_floating_role').val(chat_metadata[metadata_keys.role]);
|
||||
$(`input[name="extension_floating_position"][value="${chat_metadata[metadata_keys.position]}"]`).prop('checked', true);
|
||||
|
||||
if (extension_settings.note.chara && getContext().characterId) {
|
||||
if (extension_settings.note.chara && getContext().characterId !== undefined) {
|
||||
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||
|
||||
$('#extension_floating_chara').val(charaNote ? charaNote.prompt : '');
|
||||
@@ -389,49 +389,49 @@ export function setFloatingPrompt() {
|
||||
}
|
||||
|
||||
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: animation_duration,
|
||||
}, 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: animation_duration,
|
||||
},
|
||||
async function () {
|
||||
await delay(50);
|
||||
$('#floatingPrompt').removeClass('resizing');
|
||||
});
|
||||
setTimeout(function () {
|
||||
$('#floatingPrompt').hide();
|
||||
}, animation_duration);
|
||||
|
||||
}
|
||||
//duplicate options menu close handler from script.js
|
||||
//because this listener takes priority
|
||||
$('#options').stop().fadeOut(animation_duration);
|
||||
} else {
|
||||
if (!selected_group && this_chid === undefined) {
|
||||
toastr.warning(t`Select a character before trying to use Author's Note`, '', { timeOut: 2000 });
|
||||
return;
|
||||
}
|
||||
|
||||
//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: animation_duration,
|
||||
}, 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: animation_duration,
|
||||
}, async function () {
|
||||
await delay(50);
|
||||
$('#floatingPrompt').removeClass('resizing');
|
||||
});
|
||||
setTimeout(function () {
|
||||
$('#floatingPrompt').hide();
|
||||
}, animation_duration);
|
||||
}
|
||||
|
||||
//duplicate options menu close handler from script.js
|
||||
//because this listener takes priority
|
||||
$('#options').stop().fadeOut(animation_duration);
|
||||
}
|
||||
|
||||
async function onChatChanged() {
|
||||
@@ -446,7 +446,7 @@ async function onChatChanged() {
|
||||
$('#extension_floating_prompt_token_counter').text(tokenCounter1);
|
||||
|
||||
let tokenCounter2;
|
||||
if (extension_settings.note.chara && context.characterId) {
|
||||
if (extension_settings.note.chara && context.characterId !== undefined) {
|
||||
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||
|
||||
if (charaNote) {
|
||||
@@ -566,7 +566,7 @@ export function initAuthorsNote() {
|
||||
namedArgumentList: [],
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument(
|
||||
'position', [ARGUMENT_TYPE.STRING], false, false, null, ['system', 'user', 'assistant'],
|
||||
'role', [ARGUMENT_TYPE.STRING], false, false, null, ['system', 'user', 'assistant'],
|
||||
),
|
||||
],
|
||||
helpString: `
|
||||
|
@@ -96,8 +96,13 @@ function highlightLockedBackground() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the background for the current chat
|
||||
* @param {Event} e Click event
|
||||
* @returns {string} Empty string
|
||||
*/
|
||||
function onLockBackgroundClick(e) {
|
||||
e.stopPropagation();
|
||||
e?.stopPropagation();
|
||||
|
||||
const chatName = getCurrentChatId();
|
||||
|
||||
@@ -106,7 +111,7 @@ function onLockBackgroundClick(e) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const relativeBgImage = getUrlParameter(this);
|
||||
const relativeBgImage = getUrlParameter(this) ?? background_settings.url;
|
||||
|
||||
saveBackgroundMetadata(relativeBgImage);
|
||||
setCustomBackground();
|
||||
@@ -114,8 +119,13 @@ function onLockBackgroundClick(e) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the background for the current chat
|
||||
* @param {Event} e Click event
|
||||
* @returns {string} Empty string
|
||||
*/
|
||||
function onUnlockBackgroundClick(e) {
|
||||
e.stopPropagation();
|
||||
e?.stopPropagation();
|
||||
removeBackgroundMetadata();
|
||||
unsetCustomBackground();
|
||||
highlightLockedBackground();
|
||||
@@ -482,10 +492,10 @@ function highlightNewBackground(bg) {
|
||||
*/
|
||||
function setFittingClass(fitting) {
|
||||
const backgrounds = $('#bg1, #bg_custom');
|
||||
backgrounds.toggleClass('cover', fitting === 'cover');
|
||||
backgrounds.toggleClass('contain', fitting === 'contain');
|
||||
backgrounds.toggleClass('stretch', fitting === 'stretch');
|
||||
backgrounds.toggleClass('center', fitting === 'center');
|
||||
for (const option of ['cover', 'contain', 'stretch', 'center']) {
|
||||
backgrounds.toggleClass(option, option === fitting);
|
||||
}
|
||||
background_settings.fitting = fitting;
|
||||
}
|
||||
|
||||
function onBackgroundFilterInput() {
|
||||
@@ -513,12 +523,12 @@ export function initBackgrounds() {
|
||||
$('#add_bg_button').on('change', onBackgroundUploadSelected);
|
||||
$('#bg-filter').on('input', onBackgroundFilterInput);
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'lockbg',
|
||||
callback: onLockBackgroundClick,
|
||||
callback: () => onLockBackgroundClick(new CustomEvent('click')),
|
||||
aliases: ['bglock'],
|
||||
helpString: 'Locks a background for the currently selected chat',
|
||||
}));
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'unlockbg',
|
||||
callback: onUnlockBackgroundClick,
|
||||
callback: () => onUnlockBackgroundClick(new CustomEvent('click')),
|
||||
aliases: ['bgunlock'],
|
||||
helpString: 'Unlocks a background for the currently selected chat',
|
||||
}));
|
||||
|
@@ -318,16 +318,6 @@ export async function convertSoloToGroupChat() {
|
||||
const groupChat = chat.slice();
|
||||
const genIdFirst = Date.now();
|
||||
|
||||
// Add something if the chat is empty
|
||||
if (groupChat.length === 0) {
|
||||
const newMessage = {
|
||||
...system_messages[system_message_types.GROUP],
|
||||
send_date: getMessageTimeStamp(),
|
||||
extra: { type: system_message_types.GROUP },
|
||||
};
|
||||
groupChat.push(newMessage);
|
||||
}
|
||||
|
||||
for (let index = 0; index < groupChat.length; index++) {
|
||||
const message = groupChat[index];
|
||||
|
||||
|
@@ -40,7 +40,7 @@ function setCharCfg(tempValue, setting) {
|
||||
name: avatarName,
|
||||
};
|
||||
|
||||
switch(setting) {
|
||||
switch (setting) {
|
||||
case settingType.guidance_scale:
|
||||
tempCharaCfg['guidance_scale'] = Number(tempValue);
|
||||
break;
|
||||
@@ -69,8 +69,7 @@ function setCharCfg(tempValue, setting) {
|
||||
if (!existingCharaCfg.useChara &&
|
||||
(tempAssign.guidance_scale ?? 1.00) === 1.00 &&
|
||||
(tempAssign.negative_prompt?.length ?? 0) === 0 &&
|
||||
(tempAssign.positive_prompt?.length ?? 0) === 0)
|
||||
{
|
||||
(tempAssign.positive_prompt?.length ?? 0) === 0) {
|
||||
extension_settings.cfg.chara.splice(existingCharaCfgIndex, 1);
|
||||
}
|
||||
} else if (avatarName && tempValue.length > 0) {
|
||||
@@ -92,7 +91,7 @@ function setCharCfg(tempValue, setting) {
|
||||
}
|
||||
|
||||
function setChatCfg(tempValue, setting) {
|
||||
switch(setting) {
|
||||
switch (setting) {
|
||||
case settingType.guidance_scale:
|
||||
chat_metadata[metadataKeys.guidance_scale] = tempValue;
|
||||
break;
|
||||
@@ -113,49 +112,49 @@ function setChatCfg(tempValue, setting) {
|
||||
|
||||
// TODO: Only change CFG when character is selected
|
||||
function onCfgMenuItemClick() {
|
||||
if (selected_group || this_chid) {
|
||||
//show CFG config if it's hidden
|
||||
if ($('#cfgConfig').css('display') !== 'flex') {
|
||||
$('#cfgConfig').addClass('resizing');
|
||||
$('#cfgConfig').css('display', 'flex');
|
||||
$('#cfgConfig').css('opacity', 0.0);
|
||||
$('#cfgConfig').transition({
|
||||
opacity: 1.0,
|
||||
duration: animation_duration,
|
||||
}, async function () {
|
||||
await delay(50);
|
||||
$('#cfgConfig').removeClass('resizing');
|
||||
});
|
||||
|
||||
//auto-open the main AN inline drawer
|
||||
if ($('#CFGBlockToggle')
|
||||
.siblings('.inline-drawer-content')
|
||||
.css('display') !== 'block') {
|
||||
$('#floatingPrompt').addClass('resizing');
|
||||
$('#CFGBlockToggle').click();
|
||||
}
|
||||
} else {
|
||||
//hide AN if it's already displayed
|
||||
$('#cfgConfig').addClass('resizing');
|
||||
$('#cfgConfig').transition({
|
||||
opacity: 0.0,
|
||||
duration: animation_duration,
|
||||
},
|
||||
async function () {
|
||||
await delay(50);
|
||||
$('#cfgConfig').removeClass('resizing');
|
||||
});
|
||||
setTimeout(function () {
|
||||
$('#cfgConfig').hide();
|
||||
}, animation_duration);
|
||||
|
||||
}
|
||||
//duplicate options menu close handler from script.js
|
||||
//because this listener takes priority
|
||||
$('#options').stop().fadeOut(animation_duration);
|
||||
} else {
|
||||
if (!selected_group && this_chid === undefined) {
|
||||
toastr.warning('Select a character before trying to configure CFG', '', { timeOut: 2000 });
|
||||
return;
|
||||
}
|
||||
|
||||
//show CFG config if it's hidden
|
||||
if ($('#cfgConfig').css('display') !== 'flex') {
|
||||
$('#cfgConfig').addClass('resizing');
|
||||
$('#cfgConfig').css('display', 'flex');
|
||||
$('#cfgConfig').css('opacity', 0.0);
|
||||
$('#cfgConfig').transition({
|
||||
opacity: 1.0,
|
||||
duration: animation_duration,
|
||||
}, async function () {
|
||||
await delay(50);
|
||||
$('#cfgConfig').removeClass('resizing');
|
||||
});
|
||||
|
||||
//auto-open the main AN inline drawer
|
||||
if ($('#CFGBlockToggle')
|
||||
.siblings('.inline-drawer-content')
|
||||
.css('display') !== 'block') {
|
||||
$('#floatingPrompt').addClass('resizing');
|
||||
$('#CFGBlockToggle').click();
|
||||
}
|
||||
} else {
|
||||
//hide AN if it's already displayed
|
||||
$('#cfgConfig').addClass('resizing');
|
||||
$('#cfgConfig').transition({
|
||||
opacity: 0.0,
|
||||
duration: animation_duration,
|
||||
}, async function () {
|
||||
await delay(50);
|
||||
$('#cfgConfig').removeClass('resizing');
|
||||
});
|
||||
setTimeout(function () {
|
||||
$('#cfgConfig').hide();
|
||||
}, animation_duration);
|
||||
|
||||
}
|
||||
//duplicate options menu close handler from script.js
|
||||
//because this listener takes priority
|
||||
$('#options').stop().fadeOut(animation_duration);
|
||||
}
|
||||
|
||||
async function onChatChanged() {
|
||||
@@ -288,7 +287,7 @@ export function initCfg() {
|
||||
setTimeout(function () { $('#cfgConfig').hide(); }, animation_duration);
|
||||
});
|
||||
|
||||
$('#chat_cfg_guidance_scale').on('input', function() {
|
||||
$('#chat_cfg_guidance_scale').on('input', function () {
|
||||
const numberValue = Number($(this).val());
|
||||
const success = setChatCfg(numberValue, settingType.guidance_scale);
|
||||
if (success) {
|
||||
@@ -296,15 +295,15 @@ export function initCfg() {
|
||||
}
|
||||
});
|
||||
|
||||
$('#chat_cfg_negative_prompt').on('input', function() {
|
||||
$('#chat_cfg_negative_prompt').on('input', function () {
|
||||
setChatCfg($(this).val(), settingType.negative_prompt);
|
||||
});
|
||||
|
||||
$('#chat_cfg_positive_prompt').on('input', function() {
|
||||
$('#chat_cfg_positive_prompt').on('input', function () {
|
||||
setChatCfg($(this).val(), settingType.positive_prompt);
|
||||
});
|
||||
|
||||
$('#chara_cfg_guidance_scale').on('input', function() {
|
||||
$('#chara_cfg_guidance_scale').on('input', function () {
|
||||
const value = $(this).val();
|
||||
const success = setCharCfg(value, settingType.guidance_scale);
|
||||
if (success) {
|
||||
@@ -312,34 +311,34 @@ export function initCfg() {
|
||||
}
|
||||
});
|
||||
|
||||
$('#chara_cfg_negative_prompt').on('input', function() {
|
||||
$('#chara_cfg_negative_prompt').on('input', function () {
|
||||
setCharCfg($(this).val(), settingType.negative_prompt);
|
||||
});
|
||||
|
||||
$('#chara_cfg_positive_prompt').on('input', function() {
|
||||
$('#chara_cfg_positive_prompt').on('input', function () {
|
||||
setCharCfg($(this).val(), settingType.positive_prompt);
|
||||
});
|
||||
|
||||
$('#global_cfg_guidance_scale').on('input', function() {
|
||||
$('#global_cfg_guidance_scale').on('input', function () {
|
||||
extension_settings.cfg.global.guidance_scale = Number($(this).val());
|
||||
$('#global_cfg_guidance_scale_counter').val(extension_settings.cfg.global.guidance_scale.toFixed(2));
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#global_cfg_negative_prompt').on('input', function() {
|
||||
$('#global_cfg_negative_prompt').on('input', function () {
|
||||
extension_settings.cfg.global.negative_prompt = $(this).val();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#global_cfg_positive_prompt').on('input', function() {
|
||||
$('#global_cfg_positive_prompt').on('input', function () {
|
||||
extension_settings.cfg.global.positive_prompt = $(this).val();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('input[name="cfg_prompt_combine"]').on('input', function() {
|
||||
$('input[name="cfg_prompt_combine"]').on('input', function () {
|
||||
const values = $('#cfgConfig').find('input[name="cfg_prompt_combine"]')
|
||||
.filter(':checked')
|
||||
.map(function() { return Number($(this).val()); })
|
||||
.map(function () { return Number($(this).val()); })
|
||||
.get()
|
||||
.filter((e) => !Number.isNaN(e)) || [];
|
||||
|
||||
@@ -347,17 +346,17 @@ export function initCfg() {
|
||||
saveMetadataDebounced();
|
||||
});
|
||||
|
||||
$('#cfg_prompt_insertion_depth').on('input', function() {
|
||||
$('#cfg_prompt_insertion_depth').on('input', function () {
|
||||
chat_metadata[metadataKeys.prompt_insertion_depth] = Number($(this).val());
|
||||
saveMetadataDebounced();
|
||||
});
|
||||
|
||||
$('#cfg_prompt_separator').on('input', function() {
|
||||
$('#cfg_prompt_separator').on('input', function () {
|
||||
chat_metadata[metadataKeys.prompt_separator] = $(this).val();
|
||||
saveMetadataDebounced();
|
||||
});
|
||||
|
||||
$('#groupchat_cfg_use_chara').on('input', function() {
|
||||
$('#groupchat_cfg_use_chara').on('input', function () {
|
||||
const checked = !!$(this).prop('checked');
|
||||
chat_metadata[metadataKeys.groupchat_individual_chars] = checked;
|
||||
|
||||
|
@@ -113,5 +113,6 @@
|
||||
* @property {string} chat - name of the current chat file chat
|
||||
* @property {string} avatar - file name of the avatar image (acts as a unique identifier)
|
||||
* @property {string} json_data - the full raw JSON data of the character
|
||||
* @property {boolean?} shallow - if the data is shallow (lazy-loaded)
|
||||
*/
|
||||
export default 0;// now this file is a module
|
||||
|
@@ -47,6 +47,10 @@ const hash_derivations = {
|
||||
// gemma-2-2b-it
|
||||
'Gemma 2'
|
||||
,
|
||||
'7de1c58e208eda46e9c7f86397df37ec49883aeece39fb961e0a6b24088dd3c4':
|
||||
// gemma-3
|
||||
'Gemma 2'
|
||||
,
|
||||
|
||||
// Cohere
|
||||
'3b54f5c219ae1caa5c0bb2cdc7c001863ca6807cf888e4240e8739fa7eb9e02e':
|
||||
@@ -59,6 +63,17 @@ const hash_derivations = {
|
||||
// Tulu-3-8B
|
||||
// Tulu-3-70B
|
||||
'Tulu'
|
||||
,
|
||||
|
||||
// DeepSeek V2.5
|
||||
'54d400beedcd17f464e10063e0577f6f798fa896266a912d8a366f8a2fcc0bca':
|
||||
'DeepSeek-V2.5'
|
||||
,
|
||||
|
||||
// DeepSeek R1
|
||||
'b6835114b7303ddd78919a82e4d9f7d8c26ed0d7dfc36beeb12d524f6144eab1':
|
||||
'DeepSeek-V2.5'
|
||||
,
|
||||
};
|
||||
|
||||
const substr_derivations = {
|
||||
@@ -87,6 +102,6 @@ export async function deriveTemplatesFromChatTemplate(chat_template, hash) {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Unknown chat template hash: ${hash} for [${chat_template}]`);
|
||||
console.warn(`Unknown chat template hash: ${hash} for [${chat_template}]`);
|
||||
return null;
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ import {
|
||||
getCurrentChatId,
|
||||
getRequestHeaders,
|
||||
hideSwipeButtons,
|
||||
name1,
|
||||
name2,
|
||||
reloadCurrentChat,
|
||||
saveChatDebounced,
|
||||
@@ -21,6 +22,7 @@ import {
|
||||
chat_metadata,
|
||||
neutralCharacterName,
|
||||
updateChatMetadata,
|
||||
system_message_types,
|
||||
} from '../script.js';
|
||||
import { selected_group } from './group-chats.js';
|
||||
import { power_user } from './power-user.js';
|
||||
@@ -34,6 +36,7 @@ import {
|
||||
humanFileSize,
|
||||
saveBase64AsFile,
|
||||
extractTextFromOffice,
|
||||
download,
|
||||
} from './utils.js';
|
||||
import { extension_settings, renderExtensionTemplateAsync, saveMetadataDebounced } from './extensions.js';
|
||||
import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
|
||||
@@ -41,6 +44,8 @@ import { ScraperManager } from './scrapers.js';
|
||||
import { DragAndDropHandler } from './dragdrop.js';
|
||||
import { renderTemplateAsync } from './templates.js';
|
||||
import { t } from './i18n.js';
|
||||
import { humanizedDateTime } from './RossAscends-mods.js';
|
||||
import { accountStorage } from './util/AccountStorage.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} FileAttachment
|
||||
@@ -125,9 +130,10 @@ function getConverter(type) {
|
||||
* @param {number} start Starting message ID
|
||||
* @param {number} end Ending message ID (inclusive)
|
||||
* @param {boolean} unhide If true, unhide the messages instead.
|
||||
* @param {string} nameFitler Optional name filter
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function hideChatMessageRange(start, end, unhide) {
|
||||
export async function hideChatMessageRange(start, end, unhide, nameFitler = null) {
|
||||
if (isNaN(start)) return;
|
||||
if (!end) end = start;
|
||||
const hide = !unhide;
|
||||
@@ -135,6 +141,7 @@ export async function hideChatMessageRange(start, end, unhide) {
|
||||
for (let messageId = start; messageId <= end; messageId++) {
|
||||
const message = chat[messageId];
|
||||
if (!message) continue;
|
||||
if (nameFitler && message.name !== nameFitler) continue;
|
||||
|
||||
message.is_system = hide;
|
||||
|
||||
@@ -585,10 +592,12 @@ async function enlargeMessageImage() {
|
||||
const imgHolder = document.createElement('div');
|
||||
imgHolder.classList.add('img_enlarged_holder');
|
||||
imgHolder.append(img);
|
||||
const imgContainer = $('<div><pre><code></code></pre></div>');
|
||||
const imgContainer = $('<div><pre><code class="img_enlarged_title"></code></pre></div>');
|
||||
imgContainer.prepend(imgHolder);
|
||||
imgContainer.addClass('img_enlarged_container');
|
||||
imgContainer.find('code').addClass('txt').text(title);
|
||||
|
||||
const codeTitle = imgContainer.find('.img_enlarged_title');
|
||||
codeTitle.addClass('txt').text(title);
|
||||
const titleEmpty = !title || title.trim().length === 0;
|
||||
imgContainer.find('pre').toggle(!titleEmpty);
|
||||
addCopyToCodeBlocks(imgContainer);
|
||||
@@ -598,30 +607,73 @@ async function enlargeMessageImage() {
|
||||
popup.dlg.style.width = 'unset';
|
||||
popup.dlg.style.height = 'unset';
|
||||
|
||||
img.addEventListener('click', () => {
|
||||
img.addEventListener('click', event => {
|
||||
const shouldZoom = !img.classList.contains('zoomed');
|
||||
img.classList.toggle('zoomed', shouldZoom);
|
||||
event.stopPropagation();
|
||||
});
|
||||
codeTitle[0]?.addEventListener('click', event => {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
popup.dlg.addEventListener('click', event => {
|
||||
popup.completeCancelled();
|
||||
});
|
||||
|
||||
await popup.show();
|
||||
}
|
||||
|
||||
async function deleteMessageImage() {
|
||||
const value = await callGenericPopup('<h3>Delete image from message?<br>This action can\'t be undone.</h3>', POPUP_TYPE.CONFIRM);
|
||||
const value = await callGenericPopup('<h3>Delete image from message?<br>This action can\'t be undone.</h3>', POPUP_TYPE.TEXT, '', {
|
||||
okButton: t`Delete one`,
|
||||
customButtons: [
|
||||
{
|
||||
text: t`Delete all`,
|
||||
appendAtEnd: true,
|
||||
result: POPUP_RESULT.CUSTOM1,
|
||||
},
|
||||
{
|
||||
text: t`Cancel`,
|
||||
appendAtEnd: true,
|
||||
result: POPUP_RESULT.CANCELLED,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (value !== POPUP_RESULT.AFFIRMATIVE) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mesBlock = $(this).closest('.mes');
|
||||
const mesId = mesBlock.attr('mesid');
|
||||
const message = chat[mesId];
|
||||
delete message.extra.image;
|
||||
delete message.extra.inline_image;
|
||||
delete message.extra.title;
|
||||
delete message.extra.append_title;
|
||||
mesBlock.find('.mes_img_container').removeClass('img_extra');
|
||||
mesBlock.find('.mes_img').attr('src', '');
|
||||
|
||||
let isLastImage = true;
|
||||
|
||||
if (Array.isArray(message.extra.image_swipes)) {
|
||||
const indexOf = message.extra.image_swipes.indexOf(message.extra.image);
|
||||
if (indexOf > -1) {
|
||||
message.extra.image_swipes.splice(indexOf, 1);
|
||||
isLastImage = message.extra.image_swipes.length === 0;
|
||||
if (!isLastImage) {
|
||||
const newIndex = Math.min(indexOf, message.extra.image_swipes.length - 1);
|
||||
message.extra.image = message.extra.image_swipes[newIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLastImage || value === POPUP_RESULT.CUSTOM1) {
|
||||
delete message.extra.image;
|
||||
delete message.extra.inline_image;
|
||||
delete message.extra.title;
|
||||
delete message.extra.append_title;
|
||||
delete message.extra.image_swipes;
|
||||
mesBlock.find('.mes_img_container').removeClass('img_extra');
|
||||
mesBlock.find('.mes_img').attr('src', '');
|
||||
} else {
|
||||
appendMediaToMessage(message, mesBlock);
|
||||
}
|
||||
|
||||
await saveChatConditional();
|
||||
}
|
||||
|
||||
@@ -1029,8 +1081,8 @@ async function openAttachmentManager() {
|
||||
renderAttachments();
|
||||
});
|
||||
|
||||
let sortField = localStorage.getItem('DataBank_sortField') || 'created';
|
||||
let sortOrder = localStorage.getItem('DataBank_sortOrder') || 'desc';
|
||||
let sortField = accountStorage.getItem('DataBank_sortField') || 'created';
|
||||
let sortOrder = accountStorage.getItem('DataBank_sortOrder') || 'desc';
|
||||
let filterString = '';
|
||||
|
||||
const template = $(await renderExtensionTemplateAsync('attachments', 'manager', {}));
|
||||
@@ -1046,8 +1098,8 @@ async function openAttachmentManager() {
|
||||
|
||||
sortField = this.selectedOptions[0].dataset.sortField;
|
||||
sortOrder = this.selectedOptions[0].dataset.sortOrder;
|
||||
localStorage.setItem('DataBank_sortField', sortField);
|
||||
localStorage.setItem('DataBank_sortOrder', sortOrder);
|
||||
accountStorage.setItem('DataBank_sortField', sortField);
|
||||
accountStorage.setItem('DataBank_sortOrder', sortOrder);
|
||||
renderAttachments();
|
||||
});
|
||||
function handleBulkAction(action) {
|
||||
@@ -1427,6 +1479,19 @@ jQuery(function () {
|
||||
await viewMessageFile(messageId);
|
||||
});
|
||||
|
||||
$(document).on('click', '.assistant_note_export', async function () {
|
||||
const chatToSave = [
|
||||
{
|
||||
user_name: name1,
|
||||
character_name: name2,
|
||||
chat_metadata: chat_metadata,
|
||||
},
|
||||
...chat.filter(x => x?.extra?.type !== system_message_types.ASSISTANT_NOTE),
|
||||
];
|
||||
|
||||
download(chatToSave.map((m) => JSON.stringify(m)).join('\n'), `Assistant - ${humanizedDateTime()}.jsonl`, 'application/json');
|
||||
});
|
||||
|
||||
// Do not change. #attachFile is added by extension.
|
||||
$(document).on('click', '#attachFile', function () {
|
||||
$('#file_form_input').trigger('click');
|
||||
@@ -1443,7 +1508,7 @@ jQuery(function () {
|
||||
embedMessageFile(messageId, messageBlock);
|
||||
});
|
||||
|
||||
$(document).on('click', '.editor_maximize', function () {
|
||||
$(document).on('click', '.editor_maximize', async function () {
|
||||
const broId = $(this).attr('data-for');
|
||||
const bro = $(`#${broId}`);
|
||||
const contentEditable = bro.is('[contenteditable]');
|
||||
@@ -1462,6 +1527,7 @@ jQuery(function () {
|
||||
textarea.value = String(contentEditable ? bro[0].innerText : bro.val());
|
||||
textarea.classList.add('height100p', 'wide100p', 'maximized_textarea');
|
||||
bro.hasClass('monospace') && textarea.classList.add('monospace');
|
||||
bro.hasClass('mdHotkeys') && textarea.classList.add('mdHotkeys');
|
||||
textarea.addEventListener('input', function () {
|
||||
if (contentEditable) {
|
||||
bro[0].innerText = textarea.value;
|
||||
@@ -1502,7 +1568,7 @@ jQuery(function () {
|
||||
});
|
||||
}
|
||||
|
||||
callGenericPopup(wrapper, POPUP_TYPE.TEXT, '', { wide: true, large: true });
|
||||
await callGenericPopup(wrapper, POPUP_TYPE.TEXT, '', { wide: true, large: true });
|
||||
});
|
||||
|
||||
$(document).on('click', 'body.documentstyle .mes .mes_text', function () {
|
||||
|
189
public/scripts/custom-request.js
Normal file
189
public/scripts/custom-request.js
Normal file
@@ -0,0 +1,189 @@
|
||||
import { getPresetManager } from './preset-manager.js';
|
||||
import { extractMessageFromData, getGenerateUrl, getRequestHeaders } from '../script.js';
|
||||
import { getTextGenServer } from './textgen-settings.js';
|
||||
|
||||
// #region Type Definitions
|
||||
/**
|
||||
* @typedef {Object} TextCompletionRequestBase
|
||||
* @property {string} prompt - The text prompt for completion
|
||||
* @property {number} max_tokens - Maximum number of tokens to generate
|
||||
* @property {string} [model] - Optional model name
|
||||
* @property {string} api_type - Type of API to use
|
||||
* @property {string} [api_server] - Optional API server URL
|
||||
* @property {number} [temperature] - Optional temperature parameter
|
||||
*/
|
||||
|
||||
/** @typedef {Record<string, any> & TextCompletionRequestBase} TextCompletionRequest */
|
||||
|
||||
/**
|
||||
* @typedef {Object} TextCompletionPayloadBase
|
||||
* @property {string} prompt - The text prompt for completion
|
||||
* @property {number} max_tokens - Maximum number of tokens to generate
|
||||
* @property {number} max_new_tokens - Alias for max_tokens
|
||||
* @property {string} [model] - Optional model name
|
||||
* @property {string} api_type - Type of API to use
|
||||
* @property {string} api_server - API server URL
|
||||
* @property {number} [temperature] - Optional temperature parameter
|
||||
*/
|
||||
|
||||
/** @typedef {Record<string, any> & TextCompletionPayloadBase} TextCompletionPayload */
|
||||
|
||||
/**
|
||||
* @typedef {Object} ChatCompletionMessage
|
||||
* @property {string} role - The role of the message author (e.g., "user", "assistant", "system")
|
||||
* @property {string} content - The content of the message
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ChatCompletionPayloadBase
|
||||
* @property {ChatCompletionMessage[]} messages - Array of chat messages
|
||||
* @property {string} [model] - Optional model name to use for completion
|
||||
* @property {string} chat_completion_source - Source provider for chat completion
|
||||
* @property {number} max_tokens - Maximum number of tokens to generate
|
||||
* @property {number} [temperature] - Optional temperature parameter for response randomness
|
||||
*/
|
||||
|
||||
/** @typedef {Record<string, any> & ChatCompletionPayloadBase} ChatCompletionPayload */
|
||||
// #endregion
|
||||
|
||||
/**
|
||||
* Creates & sends a text completion request. Streaming is not supported.
|
||||
*/
|
||||
export class TextCompletionService {
|
||||
static TYPE = 'textgenerationwebui';
|
||||
|
||||
/**
|
||||
* @param {TextCompletionRequest} custom
|
||||
* @returns {TextCompletionPayload}
|
||||
*/
|
||||
static createRequestData({ prompt, max_tokens, model, api_type, api_server, temperature, ...props }) {
|
||||
return {
|
||||
...props,
|
||||
prompt,
|
||||
max_tokens,
|
||||
max_new_tokens: max_tokens,
|
||||
model,
|
||||
api_type,
|
||||
api_server: api_server ?? getTextGenServer(api_type),
|
||||
temperature,
|
||||
stream: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a text completion request to the specified server
|
||||
* @param {TextCompletionPayload} data Request data
|
||||
* @param {boolean?} extractData Extract message from the response. Default true
|
||||
* @returns {Promise<string | any>} Extracted data or the raw response
|
||||
* @throws {Error}
|
||||
*/
|
||||
static async sendRequest(data, extractData = true) {
|
||||
const response = await fetch(getGenerateUrl(this.TYPE), {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
cache: 'no-cache',
|
||||
body: JSON.stringify(data),
|
||||
signal: new AbortController().signal,
|
||||
});
|
||||
|
||||
const json = await response.json();
|
||||
if (!response.ok || json.error) {
|
||||
throw json;
|
||||
}
|
||||
|
||||
return extractData ? extractMessageFromData(json, this.TYPE) : json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} presetName
|
||||
* @param {TextCompletionRequest} custom
|
||||
* @param {boolean?} extractData Extract message from the response. Default true
|
||||
* @returns {Promise<string | any>} Extracted data or the raw response
|
||||
* @throws {Error}
|
||||
*/
|
||||
static async sendRequestWithPreset(presetName, custom, extractData = true) {
|
||||
const presetManager = getPresetManager(this.TYPE);
|
||||
if (!presetManager) {
|
||||
throw new Error('Preset manager not found');
|
||||
}
|
||||
|
||||
const preset = presetManager.getCompletionPresetByName(presetName);
|
||||
if (!preset) {
|
||||
throw new Error('Preset not found');
|
||||
}
|
||||
|
||||
const data = this.createRequestData({ ...preset, ...custom });
|
||||
|
||||
return await this.sendRequest(data, extractData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates & sends a chat completion request. Streaming is not supported.
|
||||
*/
|
||||
export class ChatCompletionService {
|
||||
static TYPE = 'openai';
|
||||
|
||||
/**
|
||||
* @param {ChatCompletionPayload} custom
|
||||
* @returns {ChatCompletionPayload}
|
||||
*/
|
||||
static createRequestData({ messages, model, chat_completion_source, max_tokens, temperature, ...props }) {
|
||||
return {
|
||||
...props,
|
||||
messages,
|
||||
model,
|
||||
chat_completion_source,
|
||||
max_tokens,
|
||||
temperature,
|
||||
stream: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a chat completion request
|
||||
* @param {ChatCompletionPayload} data Request data
|
||||
* @param {boolean?} extractData Extract message from the response. Default true
|
||||
* @returns {Promise<string | any>} Extracted data or the raw response
|
||||
* @throws {Error}
|
||||
*/
|
||||
static async sendRequest(data, extractData = true) {
|
||||
const response = await fetch('/api/backends/chat-completions/generate', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
cache: 'no-cache',
|
||||
body: JSON.stringify(data),
|
||||
signal: new AbortController().signal,
|
||||
});
|
||||
|
||||
const json = await response.json();
|
||||
if (!response.ok || json.error) {
|
||||
throw json;
|
||||
}
|
||||
|
||||
return extractData ? extractMessageFromData(json, this.TYPE) : json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} presetName
|
||||
* @param {ChatCompletionPayload} custom
|
||||
* @param {boolean} extractData Extract message from the response. Default true
|
||||
* @returns {Promise<string | any>} Extracted data or the raw response
|
||||
* @throws {Error}
|
||||
*/
|
||||
static async sendRequestWithPreset(presetName, custom, extractData = true) {
|
||||
const presetManager = getPresetManager(this.TYPE);
|
||||
if (!presetManager) {
|
||||
throw new Error('Preset manager not found');
|
||||
}
|
||||
|
||||
const preset = presetManager.getCompletionPresetByName(presetName);
|
||||
if (!preset) {
|
||||
throw new Error('Preset not found');
|
||||
}
|
||||
|
||||
const data = this.createRequestData({ ...preset, ...custom });
|
||||
|
||||
return await this.sendRequest(data, extractData);
|
||||
}
|
||||
}
|
@@ -4,11 +4,12 @@ import { eventSource, event_types, saveSettings, saveSettingsDebounced, getReque
|
||||
import { showLoader } from './loader.js';
|
||||
import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
|
||||
import { renderTemplate, renderTemplateAsync } from './templates.js';
|
||||
import { delay, isSubsetOf, setValueByPath } from './utils.js';
|
||||
import { delay, isSubsetOf, sanitizeSelector, setValueByPath } from './utils.js';
|
||||
import { getContext } from './st-context.js';
|
||||
import { isAdmin } from './user.js';
|
||||
import { t } from './i18n.js';
|
||||
import { addLocaleData, getCurrentLocale, t } from './i18n.js';
|
||||
import { debounce_timeout } from './constants.js';
|
||||
import { accountStorage } from './util/AccountStorage.js';
|
||||
|
||||
export {
|
||||
getContext,
|
||||
@@ -38,7 +39,8 @@ export let modules = [];
|
||||
let activeExtensions = new Set();
|
||||
|
||||
const getApiUrl = () => extension_settings.apiUrl;
|
||||
const sortManifests = (a, b) => parseInt(a.loading_order) - parseInt(b.loading_order) || String(a.display_name).localeCompare(String(b.display_name));
|
||||
const sortManifestsByOrder = (a, b) => parseInt(a.loading_order) - parseInt(b.loading_order) || String(a.display_name).localeCompare(String(b.display_name));
|
||||
const sortManifestsByName = (a, b) => String(a.display_name).localeCompare(String(b.display_name)) || parseInt(a.loading_order) - parseInt(b.loading_order);
|
||||
let connectedToApi = false;
|
||||
|
||||
/**
|
||||
@@ -152,8 +154,18 @@ export const extension_settings = {
|
||||
refine_mode: false,
|
||||
},
|
||||
expressions: {
|
||||
/** @type {number} see `EXPRESSION_API` */
|
||||
api: undefined,
|
||||
/** @type {string[]} */
|
||||
custom: [],
|
||||
showDefault: false,
|
||||
translate: false,
|
||||
/** @type {string} */
|
||||
fallback_expression: undefined,
|
||||
/** @type {string} */
|
||||
llmPrompt: undefined,
|
||||
allowMultiple: true,
|
||||
rerollIfSame: false,
|
||||
},
|
||||
connectionManager: {
|
||||
selectedProfile: '',
|
||||
@@ -198,6 +210,12 @@ export const extension_settings = {
|
||||
* @type {string[]}
|
||||
*/
|
||||
disabled_attachments: [],
|
||||
gallery: {
|
||||
/** @type {{[characterKey: string]: string}} */
|
||||
folders: {},
|
||||
/** @type {string} */
|
||||
sort: 'dateAsc',
|
||||
},
|
||||
};
|
||||
|
||||
function showHideExtensionsMenu() {
|
||||
@@ -355,7 +373,7 @@ async function getManifests(names) {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function activateExtensions() {
|
||||
const extensions = Object.entries(manifests).sort((a, b) => sortManifests(a[1], b[1]));
|
||||
const extensions = Object.entries(manifests).sort((a, b) => sortManifestsByOrder(a[1], b[1]));
|
||||
const promises = [];
|
||||
|
||||
for (let entry of extensions) {
|
||||
@@ -372,7 +390,7 @@ async function activateExtensions() {
|
||||
if (meetsModuleRequirements && !isDisabled) {
|
||||
try {
|
||||
console.debug('Activating extension', name);
|
||||
const promise = Promise.all([addExtensionScript(name, manifest), addExtensionStyle(name, manifest)]);
|
||||
const promise = addExtensionLocale(name, manifest).finally(() => Promise.all([addExtensionScript(name, manifest), addExtensionStyle(name, manifest)]));
|
||||
await promise
|
||||
.then(() => activeExtensions.add(name))
|
||||
.catch(err => console.log('Could not activate extension', name, err));
|
||||
@@ -509,10 +527,11 @@ function addExtensionStyle(name, manifest) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `/scripts/extensions/${name}/${manifest.css}`;
|
||||
const id = sanitizeSelector(`${name}-css`);
|
||||
|
||||
if ($(`link[id="${name}"]`).length === 0) {
|
||||
if ($(`link[id="${id}"]`).length === 0) {
|
||||
const link = document.createElement('link');
|
||||
link.id = name;
|
||||
link.id = id;
|
||||
link.rel = 'stylesheet';
|
||||
link.type = 'text/css';
|
||||
link.href = url;
|
||||
@@ -540,11 +559,12 @@ function addExtensionScript(name, manifest) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `/scripts/extensions/${name}/${manifest.js}`;
|
||||
const id = sanitizeSelector(`${name}-js`);
|
||||
let ready = false;
|
||||
|
||||
if ($(`script[id="${name}"]`).length === 0) {
|
||||
if ($(`script[id="${id}"]`).length === 0) {
|
||||
const script = document.createElement('script');
|
||||
script.id = name;
|
||||
script.id = id;
|
||||
script.type = 'module';
|
||||
script.src = url;
|
||||
script.async = true;
|
||||
@@ -562,6 +582,42 @@ function addExtensionScript(name, manifest) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a localization data for an extension.
|
||||
* @param {string} name Extension name
|
||||
* @param {object} manifest Manifest object
|
||||
*/
|
||||
function addExtensionLocale(name, manifest) {
|
||||
// No i18n data in the manifest
|
||||
if (!manifest.i18n || typeof manifest.i18n !== 'object') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const currentLocale = getCurrentLocale();
|
||||
const localeFile = manifest.i18n[currentLocale];
|
||||
|
||||
// Manifest doesn't provide a locale file for the current locale
|
||||
if (!localeFile) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return fetch(`/scripts/extensions/${name}/${localeFile}`)
|
||||
.then(async response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data && typeof data === 'object') {
|
||||
addLocaleData(currentLocale, data);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('Could not load extension locale data for ' + name, err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates HTML string for displaying an extension in the UI.
|
||||
*
|
||||
@@ -599,12 +655,12 @@ function generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal,
|
||||
}
|
||||
|
||||
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="' + t`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 ? `<button class="btn_delete menu_button" data-name="${externalId}" title="Delete"><i class="fa-fw fa-solid fa-trash-can"></i></button>` : '';
|
||||
let deleteButton = isExternal ? `<button class="btn_delete menu_button" data-name="${externalId}" data-i18n="[title]Delete" title="Delete"><i class="fa-fw fa-solid fa-trash-can"></i></button>` : '';
|
||||
let updateButton = isExternal ? `<button class="btn_update menu_button displayNone" data-name="${externalId}" title="Update available"><i class="fa-solid fa-download fa-fw"></i></button>` : '';
|
||||
let moveButton = isExternal && isUserAdmin ? `<button class="btn_move menu_button" data-name="${externalId}" title="Move"><i class="fa-solid fa-folder-tree fa-fw"></i></button>` : '';
|
||||
let moveButton = isExternal && isUserAdmin ? `<button class="btn_move menu_button" data-name="${externalId}" data-i18n="[title]Move" title="Move"><i class="fa-solid fa-folder-tree fa-fw"></i></button>` : '';
|
||||
let modulesInfo = '';
|
||||
|
||||
if (isActive && Array.isArray(manifest.optional)) {
|
||||
@@ -612,7 +668,7 @@ function generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal,
|
||||
modules.forEach(x => optional.delete(x));
|
||||
if (optional.size > 0) {
|
||||
const optionalString = DOMPurify.sanitize([...optional].join(', '));
|
||||
modulesInfo = `<div class="extension_modules">Optional modules: <span class="optional">${optionalString}</span></div>`;
|
||||
modulesInfo = '<div class="extension_modules">' + t`Optional modules:` + ` <span class="optional">${optionalString}</span></div>`;
|
||||
}
|
||||
} else if (!isDisabled) { // Neither active nor disabled
|
||||
const requirements = new Set(manifest.requires);
|
||||
@@ -680,9 +736,9 @@ function getExtensionData(extension) {
|
||||
* @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>';
|
||||
let moduleInfo = modules.length ? `<p>${DOMPurify.sanitize(modules.join(', '))}</p>` : '<p class="failure">' + t`Not connected to the API!` + '</p>';
|
||||
return `
|
||||
<h3>Modules provided by your Extras API:</h3>
|
||||
<h3>` + t`Modules provided by your Extras API:` + `</h3>
|
||||
${moduleInfo}
|
||||
`;
|
||||
}
|
||||
@@ -701,16 +757,19 @@ async function showExtensionsDetails() {
|
||||
initialScrollTop = oldPopup.content.scrollTop;
|
||||
await oldPopup.completeCancelled();
|
||||
}
|
||||
const htmlDefault = $('<div class="marginBot10"><h3 class="textAlignCenter">Built-in Extensions:</h3></div>');
|
||||
const htmlExternal = $('<div class="marginBot10"><h3 class="textAlignCenter">Installed Extensions:</h3></div>');
|
||||
const htmlDefault = $('<div class="marginBot10"><h3 class="textAlignCenter">' + t`Built-in Extensions:` + '</h3></div>');
|
||||
const htmlExternal = $('<div class="marginBot10"><h3 class="textAlignCenter">' + t`Installed Extensions:` + '</h3></div>');
|
||||
const htmlLoading = $(`<div class="flex-container alignItemsCenter justifyCenter marginTop10 marginBot5">
|
||||
<i class="fa-solid fa-spinner fa-spin"></i>
|
||||
<span>Loading third-party extensions... Please wait...</span>
|
||||
<span>` + t`Loading third-party extensions... Please wait...` + `</span>
|
||||
</div>`);
|
||||
|
||||
htmlExternal.append(htmlLoading);
|
||||
|
||||
const extensions = Object.entries(manifests).sort((a, b) => sortManifests(a[1], b[1])).map(getExtensionData);
|
||||
const sortOrderKey = 'extensions_sortByName';
|
||||
const sortByName = accountStorage.getItem(sortOrderKey) === 'true';
|
||||
const sortFn = sortByName ? sortManifestsByName : sortManifestsByOrder;
|
||||
const extensions = Object.entries(manifests).sort((a, b) => sortFn(a[1], b[1])).map(getExtensionData);
|
||||
|
||||
extensions.forEach(value => {
|
||||
const { isExternal, extensionHtml } = value;
|
||||
@@ -726,8 +785,7 @@ async function showExtensionsDetails() {
|
||||
|
||||
/** @type {import('./popup.js').CustomPopupButton} */
|
||||
const updateAllButton = {
|
||||
text: 'Update all',
|
||||
appendAtEnd: true,
|
||||
text: t`Update all`,
|
||||
action: async () => {
|
||||
requiresReload = true;
|
||||
await autoUpdateExtensions(true);
|
||||
@@ -735,13 +793,23 @@ async function showExtensionsDetails() {
|
||||
},
|
||||
};
|
||||
|
||||
/** @type {import('./popup.js').CustomPopupButton} */
|
||||
const sortOrderButton = {
|
||||
text: sortByName ? t`Sort: Display Name` : t`Sort: Loading Order`,
|
||||
action: async () => {
|
||||
abortController.abort();
|
||||
accountStorage.setItem(sortOrderKey, sortByName ? 'false' : 'true');
|
||||
await showExtensionsDetails();
|
||||
},
|
||||
};
|
||||
|
||||
let waitingForSave = false;
|
||||
|
||||
const popup = new Popup(html, POPUP_TYPE.TEXT, '', {
|
||||
okButton: 'Close',
|
||||
okButton: t`Close`,
|
||||
wide: true,
|
||||
large: true,
|
||||
customButtons: [updateAllButton],
|
||||
customButtons: [sortOrderButton, updateAllButton],
|
||||
allowVerticalScrolling: true,
|
||||
onClosing: async () => {
|
||||
if (waitingForSave) {
|
||||
@@ -760,7 +828,7 @@ async function showExtensionsDetails() {
|
||||
});
|
||||
popupPromise = popup.show();
|
||||
popup.content.scrollTop = initialScrollTop;
|
||||
checkForUpdatesManual(abortController.signal).finally(() => htmlLoading.remove());
|
||||
checkForUpdatesManual(sortFn, abortController.signal).finally(() => htmlLoading.remove());
|
||||
} catch (error) {
|
||||
toastr.error(t`Error loading extensions. See browser console for details.`);
|
||||
console.error(error);
|
||||
@@ -831,7 +899,7 @@ async function updateExtension(extensionName, quiet) {
|
||||
toastr.success('Extension is already up to date');
|
||||
}
|
||||
} else {
|
||||
toastr.success(`Extension ${extensionName} updated to ${data.shortCommitHash}`, 'Reload the page to apply updates');
|
||||
toastr.success(t`Extension ${extensionName} updated to ${data.shortCommitHash}`, t`Reload the page to apply updates`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
@@ -999,10 +1067,10 @@ export async function installExtension(url, global) {
|
||||
}
|
||||
|
||||
const response = await request.json();
|
||||
toastr.success(`Extension "${response.display_name}" by ${response.author} (version ${response.version}) has been installed successfully!`, 'Extension installation successful');
|
||||
toastr.success(t`Extension '${response.display_name}' by ${response.author} (version ${response.version}) has been installed successfully!`, t`Extension installation successful`);
|
||||
console.debug(`Extension "${response.display_name}" has been installed successfully at ${response.extensionPath}`);
|
||||
await loadExtensionSettings({}, false, false);
|
||||
await eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED);
|
||||
await eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED, response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1071,12 +1139,13 @@ function processVersionCheckQueue() {
|
||||
|
||||
/**
|
||||
* Performs a manual check for updates on all 3rd-party extensions.
|
||||
* @param {function} sortFn Sort function
|
||||
* @param {AbortSignal} abortSignal Signal to abort the operation
|
||||
* @returns {Promise<any[]>}
|
||||
*/
|
||||
async function checkForUpdatesManual(abortSignal) {
|
||||
async function checkForUpdatesManual(sortFn, abortSignal) {
|
||||
const promises = [];
|
||||
for (const id of Object.keys(manifests).filter(x => x.startsWith('third-party')).sort((a, b) => sortManifests(manifests[a], manifests[b]))) {
|
||||
for (const id of Object.keys(manifests).filter(x => x.startsWith('third-party')).sort((a, b) => sortFn(manifests[a], manifests[b]))) {
|
||||
const externalId = id.replace('third-party', '');
|
||||
const promise = enqueueVersionCheck(async () => {
|
||||
try {
|
||||
@@ -1137,11 +1206,11 @@ async function checkForExtensionUpdates(force) {
|
||||
const currentDate = new Date().toDateString();
|
||||
|
||||
// Don't nag more than once a day
|
||||
if (localStorage.getItem(STORAGE_NAG_KEY) === currentDate) {
|
||||
if (accountStorage.getItem(STORAGE_NAG_KEY) === currentDate) {
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem(STORAGE_NAG_KEY, currentDate);
|
||||
accountStorage.setItem(STORAGE_NAG_KEY, currentDate);
|
||||
}
|
||||
|
||||
const isCurrentUserAdmin = isAdmin();
|
||||
@@ -1173,7 +1242,7 @@ async function checkForExtensionUpdates(force) {
|
||||
await Promise.allSettled(promises);
|
||||
|
||||
if (updatesAvailable.length > 0) {
|
||||
toastr.info(`${updatesAvailable.map(x => `• ${x}`).join('\n')}`, 'Extension updates available');
|
||||
toastr.info(`${updatesAvailable.map(x => `• ${x}`).join('\n')}`, t`Extension updates available`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1187,7 +1256,7 @@ async function autoUpdateExtensions(forceAll) {
|
||||
return;
|
||||
}
|
||||
|
||||
const banner = toastr.info('Auto-updating extensions. This may take several minutes.', 'Please wait...', { timeOut: 10000, extendedTimeOut: 10000 });
|
||||
const banner = toastr.info(t`Auto-updating extensions. This may take several minutes.`, t`Please wait...`, { timeOut: 10000, extendedTimeOut: 10000 });
|
||||
const isCurrentUserAdmin = isAdmin();
|
||||
const promises = [];
|
||||
for (const [id, manifest] of Object.entries(manifests)) {
|
||||
@@ -1221,7 +1290,7 @@ export async function runGenerationInterceptors(chat, contextSize, type) {
|
||||
exitImmediately = immediately;
|
||||
};
|
||||
|
||||
for (const manifest of Object.values(manifests).filter(x => x.generate_interceptor).sort((a, b) => sortManifests(a, b))) {
|
||||
for (const manifest of Object.values(manifests).filter(x => x.generate_interceptor).sort((a, b) => sortManifestsByOrder(a, b))) {
|
||||
const interceptorKey = manifest.generate_interceptor;
|
||||
if (typeof globalThis[interceptorKey] === 'function') {
|
||||
try {
|
||||
|
@@ -8,7 +8,9 @@ import { getRequestHeaders, processDroppedFiles, eventSource, event_types } from
|
||||
import { deleteExtension, extensionNames, getContext, installExtension, renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
import { POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js';
|
||||
import { executeSlashCommands } from '../../slash-commands.js';
|
||||
import { accountStorage } from '../../util/AccountStorage.js';
|
||||
import { flashHighlight, getStringHash, isValidUrl } from '../../utils.js';
|
||||
import { t } from '../../i18n.js';
|
||||
export { MODULE_NAME };
|
||||
|
||||
const MODULE_NAME = 'assets';
|
||||
@@ -58,11 +60,11 @@ const KNOWN_TYPES = {
|
||||
'blip': 'Blip sounds',
|
||||
};
|
||||
|
||||
function downloadAssetsList(url) {
|
||||
updateCurrentAssets().then(function () {
|
||||
async function downloadAssetsList(url) {
|
||||
updateCurrentAssets().then(async function () {
|
||||
fetch(url, { cache: 'no-cache' })
|
||||
.then(response => response.json())
|
||||
.then(json => {
|
||||
.then(async function(json) {
|
||||
|
||||
availableAssets = {};
|
||||
$('#assets_menu').empty();
|
||||
@@ -83,10 +85,10 @@ function downloadAssetsList(url) {
|
||||
|
||||
$('#assets_type_select').empty();
|
||||
$('#assets_search').val('');
|
||||
$('#assets_type_select').append($('<option />', { value: '', text: 'All' }));
|
||||
$('#assets_type_select').append($('<option />', { value: '', text: t`All` }));
|
||||
|
||||
for (const type of assetTypes) {
|
||||
const option = $('<option />', { value: type, text: KNOWN_TYPES[type] || type });
|
||||
const option = $('<option />', { value: type, text: t([KNOWN_TYPES[type] || type]) });
|
||||
$('#assets_type_select').append(option);
|
||||
}
|
||||
|
||||
@@ -103,11 +105,7 @@ function downloadAssetsList(url) {
|
||||
assetTypeMenu.append(`<h3>${KNOWN_TYPES[assetType] || assetType}</h3>`).hide();
|
||||
|
||||
if (assetType == 'extension') {
|
||||
assetTypeMenu.append(`
|
||||
<div class="assets-list-git">
|
||||
To download extensions from this page, you need to have <a href="https://git-scm.com/downloads" target="_blank">Git</a> installed.<br>
|
||||
Click the <i class="fa-solid fa-sm fa-arrow-up-right-from-square"></i> icon to visit the Extension's repo for tips on how to use it.
|
||||
</div>`);
|
||||
assetTypeMenu.append(await renderExtensionTemplateAsync('assets', 'installation'));
|
||||
}
|
||||
|
||||
for (const i in availableAssets[assetType].sort((a, b) => a?.name && b?.name && a['name'].localeCompare(b['name']))) {
|
||||
@@ -183,7 +181,7 @@ function downloadAssetsList(url) {
|
||||
const displayName = DOMPurify.sanitize(asset['name'] || asset['id']);
|
||||
const description = DOMPurify.sanitize(asset['description'] || '');
|
||||
const url = isValidUrl(asset['url']) ? asset['url'] : '';
|
||||
const title = assetType === 'extension' ? `Extension repo/guide: ${url}` : 'Preview in browser';
|
||||
const title = assetType === 'extension' ? t`Extension repo/guide:` + ` ${url}` : t`Preview in browser`;
|
||||
const previewIcon = (assetType === 'extension' || assetType === 'character') ? 'fa-arrow-up-right-from-square' : 'fa-headphones-simple';
|
||||
const toolTag = assetType === 'extension' && asset['tool'];
|
||||
|
||||
@@ -194,9 +192,10 @@ function downloadAssetsList(url) {
|
||||
<b>${displayName}</b>
|
||||
<a class="asset_preview" href="${url}" target="_blank" title="${title}">
|
||||
<i class="fa-solid fa-sm ${previewIcon}"></i>
|
||||
</a>
|
||||
${toolTag ? '<span class="tag" title="Adds a function tool"><i class="fa-solid fa-sm fa-wrench"></i> Tool</span>' : ''}
|
||||
</span>
|
||||
</a>` +
|
||||
(toolTag ? '<span class="tag" title="' + t`Adds a function tool` + '"><i class="fa-solid fa-sm fa-wrench"></i> ' +
|
||||
t`Tool` + '</span>' : '') +
|
||||
`</span>
|
||||
<small class="asset-description">
|
||||
${description}
|
||||
</small>
|
||||
@@ -432,14 +431,14 @@ jQuery(async () => {
|
||||
connectButton.on('click', async function () {
|
||||
const url = DOMPurify.sanitize(String(assetsJsonUrl.val()));
|
||||
const rememberKey = `Assets_SkipConfirm_${getStringHash(url)}`;
|
||||
const skipConfirm = localStorage.getItem(rememberKey) === 'true';
|
||||
const skipConfirm = accountStorage.getItem(rememberKey) === 'true';
|
||||
|
||||
const confirmation = skipConfirm || await Popup.show.confirm('Loading Asset List', `<span>Are you sure you want to connect to the following url?</span><var>${url}</var>`, {
|
||||
const confirmation = skipConfirm || await Popup.show.confirm(t`Loading Asset List`, '<span>' + t`Are you sure you want to connect to the following url?` + `</span><var>${url}</var>`, {
|
||||
customInputs: [{ id: 'assets-remember', label: 'Don\'t ask again for this URL' }],
|
||||
onClose: popup => {
|
||||
if (popup.result) {
|
||||
const rememberValue = popup.inputResults.get('assets-remember');
|
||||
localStorage.setItem(rememberKey, String(rememberValue));
|
||||
accountStorage.setItem(rememberKey, String(rememberValue));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
4
public/scripts/extensions/assets/installation.html
Normal file
4
public/scripts/extensions/assets/installation.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<div class="assets-list-git">
|
||||
<span data-i18n="extension_install_1">To download extensions from this page, you need to have </span><a href="https://git-scm.com/downloads" target="_blank">Git</a><span data-i18n="extension_install_2"> installed.</span><br>
|
||||
<span data-i18n="extension_install_3">Click the </span><i class="fa-solid fa-sm fa-arrow-up-right-from-square"></i><span data-i18n="extension_install_4"> icon to visit the Extension's repo for tips on how to use it.</span>
|
||||
</div>
|
@@ -33,7 +33,7 @@ To install a single 3rd party extension, use the "Install Extensions"
|
||||
<div id="assets_filters" class="flex-container">
|
||||
<select id="assets_type_select" class="text_pole flex1">
|
||||
</select>
|
||||
<input id="assets_search" class="text_pole flex1" placeholder="Search" type="search">
|
||||
<input id="assets_search" class="text_pole flex1" data-i18n="[placeholder]Search" placeholder="Search" type="search">
|
||||
<div id="assets-characters-button" class="menu_button menu_button_icon">
|
||||
<i class="fa-solid fa-image-portrait"></i>
|
||||
<span data-i18n="Characters">Characters</span>
|
||||
|
@@ -398,23 +398,62 @@ jQuery(async function () {
|
||||
|
||||
$('#caption_wand_container').append(sendButton);
|
||||
$(sendButton).on('click', () => {
|
||||
const hasCaptionModule =
|
||||
(modules.includes('caption') && extension_settings.caption.source === 'extras') ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openai' && (secret_state[SECRET_KEYS.OPENAI] || extension_settings.caption.allow_reverse_proxy)) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openrouter' && secret_state[SECRET_KEYS.OPENROUTER]) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'zerooneai' && secret_state[SECRET_KEYS.ZEROONEAI]) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'groq' && secret_state[SECRET_KEYS.GROQ]) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'mistral' && (secret_state[SECRET_KEYS.MISTRALAI] || extension_settings.caption.allow_reverse_proxy)) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'google' && (secret_state[SECRET_KEYS.MAKERSUITE] || extension_settings.caption.allow_reverse_proxy)) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'anthropic' && (secret_state[SECRET_KEYS.CLAUDE] || extension_settings.caption.allow_reverse_proxy)) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'ollama' && textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'llamacpp' && textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'ooba' && textgenerationwebui_settings.server_urls[textgen_types.OOBA]) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'koboldcpp' && textgenerationwebui_settings.server_urls[textgen_types.KOBOLDCPP]) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'vllm' && textgenerationwebui_settings.server_urls[textgen_types.VLLM]) ||
|
||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'custom') ||
|
||||
extension_settings.caption.source === 'local' ||
|
||||
extension_settings.caption.source === 'horde';
|
||||
const hasCaptionModule = (() => {
|
||||
const settings = extension_settings.caption;
|
||||
|
||||
// Handle non-multimodal sources
|
||||
if (settings.source === 'extras' && modules.includes('caption')) return true;
|
||||
if (settings.source === 'local' || settings.source === 'horde') return true;
|
||||
|
||||
// Handle multimodal sources
|
||||
if (settings.source === 'multimodal') {
|
||||
const api = settings.multimodal_api;
|
||||
|
||||
// APIs that support reverse proxy
|
||||
const reverseProxyApis = {
|
||||
'openai': SECRET_KEYS.OPENAI,
|
||||
'mistral': SECRET_KEYS.MISTRALAI,
|
||||
'google': SECRET_KEYS.MAKERSUITE,
|
||||
'anthropic': SECRET_KEYS.CLAUDE,
|
||||
};
|
||||
|
||||
if (reverseProxyApis[api]) {
|
||||
if (secret_state[reverseProxyApis[api]] || settings.allow_reverse_proxy) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const chatCompletionApis = {
|
||||
'openrouter': SECRET_KEYS.OPENROUTER,
|
||||
'zerooneai': SECRET_KEYS.ZEROONEAI,
|
||||
'groq': SECRET_KEYS.GROQ,
|
||||
'cohere': SECRET_KEYS.COHERE,
|
||||
};
|
||||
|
||||
if (chatCompletionApis[api] && secret_state[chatCompletionApis[api]]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const textCompletionApis = {
|
||||
'ollama': textgen_types.OLLAMA,
|
||||
'llamacpp': textgen_types.LLAMACPP,
|
||||
'ooba': textgen_types.OOBA,
|
||||
'koboldcpp': textgen_types.KOBOLDCPP,
|
||||
'vllm': textgen_types.VLLM,
|
||||
};
|
||||
|
||||
if (textCompletionApis[api] && textgenerationwebui_settings.server_urls[textCompletionApis[api]]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Custom API doesn't need additional checks
|
||||
if (api === 'custom') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
})();
|
||||
|
||||
if (!hasCaptionModule) {
|
||||
toastr.error('Choose other captioning source in the extension settings.', 'Captioning is not available');
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<select id="caption_source" class="text_pole">
|
||||
<option value="local" data-i18n="Local">Local</option>
|
||||
<option value="multimodal" data-i18n="Multimodal (OpenAI / Anthropic / llama / Google)">Multimodal (OpenAI / Anthropic / llama / Google)</option>
|
||||
<option value="extras" data-i18n="Extras">Extras</option>
|
||||
<option value="extras" data-i18n="Extras">Extras (deprecated)</option>
|
||||
<option value="horde" data-i18n="Horde">Horde</option>
|
||||
</select>
|
||||
<div id="caption_multimodal_block" class="flex-container wide100p">
|
||||
@@ -19,6 +19,7 @@
|
||||
<select id="caption_multimodal_api" class="flex1 text_pole">
|
||||
<option value="zerooneai">01.AI (Yi)</option>
|
||||
<option value="anthropic">Anthropic</option>
|
||||
<option value="cohere">Cohere</option>
|
||||
<option value="custom" data-i18n="Custom (OpenAI-compatible)">Custom (OpenAI-compatible)</option>
|
||||
<option value="google">Google AI Studio</option>
|
||||
<option value="groq">Groq</option>
|
||||
@@ -35,6 +36,8 @@
|
||||
<div class="flex1 flex-container flexFlowColumn flexNoGap">
|
||||
<label for="caption_multimodal_model" data-i18n="Model">Model</label>
|
||||
<select id="caption_multimodal_model" class="flex1 text_pole">
|
||||
<option data-type="cohere" value="c4ai-aya-vision-8b">c4ai-aya-vision-8b</option>
|
||||
<option data-type="cohere" value="c4ai-aya-vision-32b">c4ai-aya-vision-32b</option>
|
||||
<option data-type="mistral" value="pixtral-12b-latest">pixtral-12b-latest</option>
|
||||
<option data-type="mistral" value="pixtral-12b-2409">pixtral-12b-2409</option>
|
||||
<option data-type="mistral" value="pixtral-large-latest">pixtral-large-latest</option>
|
||||
@@ -45,6 +48,12 @@
|
||||
<option data-type="openai" value="gpt-4o">gpt-4o</option>
|
||||
<option data-type="openai" value="gpt-4o-mini">gpt-4o-mini</option>
|
||||
<option data-type="openai" value="chatgpt-4o-latest">chatgpt-4o-latest</option>
|
||||
<option data-type="openai" value="o1">o1</option>
|
||||
<option data-type="openai" value="o1-2024-12-17">o1-2024-12-17</option>
|
||||
<option data-type="openai" value="gpt-4.5-preview">gpt-4.5-preview</option>
|
||||
<option data-type="openai" value="gpt-4.5-preview-2025-02-27">gpt-4.5-preview-2025-02-27</option>
|
||||
<option data-type="anthropic" value="claude-3-7-sonnet-latest">claude-3-7-sonnet-latest</option>
|
||||
<option data-type="anthropic" value="claude-3-7-sonnet-20250219">claude-3-7-sonnet-20250219</option>
|
||||
<option data-type="anthropic" value="claude-3-5-sonnet-latest">claude-3-5-sonnet-latest</option>
|
||||
<option data-type="anthropic" value="claude-3-5-sonnet-20241022">claude-3-5-sonnet-20241022</option>
|
||||
<option data-type="anthropic" value="claude-3-5-sonnet-20240620">claude-3-5-sonnet-20240620</option>
|
||||
@@ -53,7 +62,16 @@
|
||||
<option data-type="anthropic" value="claude-3-opus-20240229">claude-3-opus-20240229</option>
|
||||
<option data-type="anthropic" value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</option>
|
||||
<option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option>
|
||||
<option data-type="google" value="gemini-2.0-pro-exp">gemini-2.0-pro-exp</option>
|
||||
<option data-type="google" value="gemini-2.0-pro-exp-02-05">gemini-2.0-pro-exp-02-05</option>
|
||||
<option data-type="google" value="gemini-2.0-flash-lite-preview">gemini-2.0-flash-lite-preview</option>
|
||||
<option data-type="google" value="gemini-2.0-flash-lite-preview-02-05">gemini-2.0-flash-lite-preview-02-05</option>
|
||||
<option data-type="google" value="gemini-2.0-flash">gemini-2.0-flash</option>
|
||||
<option data-type="google" value="gemini-2.0-flash-001">gemini-2.0-flash-001</option>
|
||||
<option data-type="google" value="gemini-2.0-flash-exp">gemini-2.0-flash-exp</option>
|
||||
<option data-type="google" value="gemini-2.0-flash-exp-image-generation">gemini-2.0-flash-exp-image-generation</option>
|
||||
<option data-type="google" value="gemini-2.0-flash-thinking-exp">gemini-2.0-flash-thinking-exp</option>
|
||||
<option data-type="google" value="gemini-2.0-flash-thinking-exp-01-21">gemini-2.0-flash-thinking-exp-01-21</option>
|
||||
<option data-type="google" value="gemini-2.0-flash-thinking-exp-1219">gemini-2.0-flash-thinking-exp-1219</option>
|
||||
<option data-type="google" value="gemini-1.5-flash">gemini-1.5-flash</option>
|
||||
<option data-type="google" value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option>
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<div>
|
||||
<h3>Included settings:</h3>
|
||||
<h3 data-i18n="Included settings:">Included settings:</h3>
|
||||
<div class="justifyLeft flex-container flexFlowColumn flexNoGap">
|
||||
{{#each settings}}
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" value="{{@key}}" name="exclude"{{#if this}} checked{{/if}}>
|
||||
<span>{{@key}}</span>
|
||||
<span data-i18n="{{@key}}">{{@key}}</span>
|
||||
</label>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
@@ -16,12 +16,19 @@ import { t } from '../../i18n.js';
|
||||
|
||||
const MODULE_NAME = 'connection-manager';
|
||||
const NONE = '<None>';
|
||||
const EMPTY = '<Empty>';
|
||||
|
||||
const DEFAULT_SETTINGS = {
|
||||
profiles: [],
|
||||
selectedProfile: null,
|
||||
};
|
||||
|
||||
// Commands that can record an empty value into the profile
|
||||
const ALLOW_EMPTY = [
|
||||
'stop-strings',
|
||||
'start-reply-with',
|
||||
];
|
||||
|
||||
const CC_COMMANDS = [
|
||||
'api',
|
||||
'preset',
|
||||
@@ -30,6 +37,8 @@ const CC_COMMANDS = [
|
||||
'api-url',
|
||||
'model',
|
||||
'proxy',
|
||||
'stop-strings',
|
||||
'start-reply-with',
|
||||
];
|
||||
|
||||
const TC_COMMANDS = [
|
||||
@@ -43,6 +52,8 @@ const TC_COMMANDS = [
|
||||
'context',
|
||||
'instruct-state',
|
||||
'tokenizer',
|
||||
'stop-strings',
|
||||
'start-reply-with',
|
||||
];
|
||||
|
||||
const FANCY_NAMES = {
|
||||
@@ -57,6 +68,8 @@ const FANCY_NAMES = {
|
||||
'instruct': 'Instruct Template',
|
||||
'context': 'Context Template',
|
||||
'tokenizer': 'Tokenizer',
|
||||
'stop-strings': 'Custom Stopping Strings',
|
||||
'start-reply-with': 'Start Reply With',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -104,6 +117,7 @@ class ConnectionManagerSpinner {
|
||||
/**
|
||||
* Get named arguments for the command callback.
|
||||
* @param {object} [args] Additional named arguments
|
||||
* @param {string} [args.force] Whether to force setting the value
|
||||
* @returns {object} Named arguments
|
||||
*/
|
||||
function getNamedArguments(args = {}) {
|
||||
@@ -138,6 +152,8 @@ const profilesProvider = () => [
|
||||
* @property {string} [context] Context Template
|
||||
* @property {string} [instruct-state] Instruct Mode
|
||||
* @property {string} [tokenizer] Tokenizer
|
||||
* @property {string} [stop-strings] Custom Stopping Strings
|
||||
* @property {string} [start-reply-with] Start Reply With
|
||||
* @property {string[]} [exclude] Commands to exclude
|
||||
*/
|
||||
|
||||
@@ -182,9 +198,10 @@ async function readProfileFromCommands(mode, profile, cleanUp = false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const allowEmpty = ALLOW_EMPTY.includes(command);
|
||||
const args = getNamedArguments();
|
||||
const result = await SlashCommandParser.commands[command].callback(args, '');
|
||||
if (result) {
|
||||
if (result || (allowEmpty && result === '')) {
|
||||
profile[command] = result;
|
||||
continue;
|
||||
}
|
||||
@@ -305,7 +322,14 @@ async function deleteConnectionProfile() {
|
||||
*/
|
||||
function makeFancyProfile(profile) {
|
||||
return Object.entries(FANCY_NAMES).reduce((acc, [key, value]) => {
|
||||
if (!profile[key]) return acc;
|
||||
const allowEmpty = ALLOW_EMPTY.includes(key);
|
||||
if (!profile[key]) {
|
||||
if (profile[key] === '' && allowEmpty) {
|
||||
acc[value] = EMPTY;
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc[value] = profile[key];
|
||||
return acc;
|
||||
}, {});
|
||||
@@ -335,11 +359,12 @@ async function applyConnectionProfile(profile) {
|
||||
}
|
||||
|
||||
const argument = profile[command];
|
||||
if (!argument) {
|
||||
const allowEmpty = ALLOW_EMPTY.includes(command);
|
||||
if (!argument && !(allowEmpty && argument === '')) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const args = getNamedArguments();
|
||||
const args = getNamedArguments(allowEmpty ? { force: 'true' } : {});
|
||||
await SlashCommandParser.commands[command].callback(args, argument);
|
||||
} catch (error) {
|
||||
console.error(`Failed to execute command: ${command} ${argument}`, error);
|
||||
@@ -535,6 +560,7 @@ async function renderDetailsContent(detailsContent) {
|
||||
}, {});
|
||||
const template = $(await renderExtensionTemplateAsync(MODULE_NAME, 'edit', { name: profile.name, settings }));
|
||||
const newName = await callGenericPopup(template, POPUP_TYPE.INPUT, profile.name, {
|
||||
rows: 2,
|
||||
customButtons: [{
|
||||
text: t`Save and Update`,
|
||||
classes: ['popup-button-ok'],
|
||||
|
@@ -12,8 +12,8 @@
|
||||
</div>
|
||||
<div class="marginTop5">
|
||||
<small>
|
||||
<b>Hint:</b>
|
||||
<i>Click on the setting name to omit it from the profile.</i>
|
||||
<b data-i18n="Hint:">Hint:</b>
|
||||
<i data-i18n="Click on the setting name to omit it from the profile.">Click on the setting name to omit it from the profile.</i>
|
||||
</small>
|
||||
</div>
|
||||
<h3 data-i18n="Enter a name:">
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user