sillytavern 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/.dockerignore +4 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +35 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. package/.github/workflows/npm-publish.yml +32 -0
  5. package/Dockerfile +49 -0
  6. package/Start.bat +3 -0
  7. package/colab/GPU.ipynb +339 -0
  8. package/colab/extras_server.py +40 -0
  9. package/colab/globals.py +2 -0
  10. package/colab/models.py +77 -0
  11. package/docker/docker-compose.yml +12 -0
  12. package/docker/docker-entrypoint.sh +28 -0
  13. package/faq.md +208 -0
  14. package/package.json +49 -0
  15. package/poe-client.js +638 -0
  16. package/poe-test.js +21 -0
  17. package/poe_graphql/AddHumanMessageMutation.graphql +52 -0
  18. package/poe_graphql/AddMessageBreakMutation.graphql +17 -0
  19. package/poe_graphql/AutoSubscriptionMutation.graphql +7 -0
  20. package/poe_graphql/BioFragment.graphql +8 -0
  21. package/poe_graphql/ChatAddedSubscription.graphql +5 -0
  22. package/poe_graphql/ChatFragment.graphql +6 -0
  23. package/poe_graphql/ChatListPaginationQuery.graphql +316 -0
  24. package/poe_graphql/ChatPaginationQuery.graphql +26 -0
  25. package/poe_graphql/ChatViewQuery.graphql +8 -0
  26. package/poe_graphql/DeleteHumanMessagesMutation.graphql +7 -0
  27. package/poe_graphql/DeleteMessageMutation.graphql +7 -0
  28. package/poe_graphql/HandleFragment.graphql +8 -0
  29. package/poe_graphql/LoginWithVerificationCodeMutation.graphql +13 -0
  30. package/poe_graphql/MessageAddedSubscription.graphql +115 -0
  31. package/poe_graphql/MessageDeletedSubscription.graphql +8 -0
  32. package/poe_graphql/MessageFragment.graphql +13 -0
  33. package/poe_graphql/MessageRemoveVoteMutation.graphql +7 -0
  34. package/poe_graphql/MessageSetVoteMutation.graphql +7 -0
  35. package/poe_graphql/SendVerificationCodeForLoginMutation.graphql +12 -0
  36. package/poe_graphql/ShareMessagesMutation.graphql +9 -0
  37. package/poe_graphql/SignupWithVerificationCodeMutation.graphql +13 -0
  38. package/poe_graphql/StaleChatUpdateMutation.graphql +7 -0
  39. package/poe_graphql/SubscriptionsMutation.graphql +9 -0
  40. package/poe_graphql/SummarizePlainPostQuery.graphql +3 -0
  41. package/poe_graphql/SummarizeQuotePostQuery.graphql +3 -0
  42. package/poe_graphql/SummarizeSharePostQuery.graphql +3 -0
  43. package/poe_graphql/UserSnippetFragment.graphql +14 -0
  44. package/poe_graphql/ViewerInfoQuery.graphql +21 -0
  45. package/poe_graphql/ViewerMessageLimitUpdatedSubscription.graphql +81 -0
  46. package/poe_graphql/ViewerStateFragment.graphql +30 -0
  47. package/poe_graphql/ViewerStateUpdatedSubscription.graphql +63 -0
  48. package/public/KoboldAI Settings/Ace of Spades 13B.settings +22 -0
  49. package/public/KoboldAI Settings/Adventurer-NeoX-20B-Erebus.settings +54 -0
  50. package/public/KoboldAI Settings/Basic Coherence 13B.settings +22 -0
  51. package/public/KoboldAI Settings/Best Guess 6B.settings +22 -0
  52. package/public/KoboldAI Settings/Calibrated-Pygmalion-6b.settings +47 -0
  53. package/public/KoboldAI Settings/Classic-Pygmalion-2.7b.settings +46 -0
  54. package/public/KoboldAI Settings/Classic-Pygmalion-6b.settings +47 -0
  55. package/public/KoboldAI Settings/Coherent Creativity 6B.settings +22 -0
  56. package/public/KoboldAI Settings/Default-TavernAI.settings +22 -0
  57. package/public/KoboldAI Settings/DragonSlayer-Pygmalion-6b.settings +47 -0
  58. package/public/KoboldAI Settings/GPU-Pygmalion-6b.settings +47 -0
  59. package/public/KoboldAI Settings/Genesis 13B.settings +22 -0
  60. package/public/KoboldAI Settings/Godlike.settings +22 -0
  61. package/public/KoboldAI Settings/Good Winds.settings +22 -0
  62. package/public/KoboldAI Settings/Lancer-OPT-2.7B-Erebus.settings +54 -0
  63. package/public/KoboldAI Settings/Liminal Drift.settings +22 -0
  64. package/public/KoboldAI Settings/Low Rider 13B.settings +22 -0
  65. package/public/KoboldAI Settings/Luna Moth 6B.settings +22 -0
  66. package/public/KoboldAI Settings/Mayday.settings +22 -0
  67. package/public/KoboldAI Settings/Ouroboros.settings +22 -0
  68. package/public/KoboldAI Settings/Pleasing Results 6B.settings +22 -0
  69. package/public/KoboldAI Settings/Pro Writer 13B.settings +22 -0
  70. package/public/KoboldAI Settings/RA - Pygmalion-1.3b.settings +46 -0
  71. package/public/KoboldAI Settings/Storywriter 6B.settings +22 -0
  72. package/public/NovelAI Settings/Classic-Euterpe.settings +14 -0
  73. package/public/NovelAI Settings/Classic-Krake.settings +14 -0
  74. package/public/OpenAI Settings/Default.settings +15 -0
  75. package/public/TextGen Settings/Beam Search.settings +15 -0
  76. package/public/TextGen Settings/Contrastive Search.settings +15 -0
  77. package/public/TextGen Settings/Default.settings +15 -0
  78. package/public/TextGen Settings/Deterministic.settings +15 -0
  79. package/public/TextGen Settings/Kobold (Godlike).settings +15 -0
  80. package/public/TextGen Settings/Kobold (Liminal Drift).settings +15 -0
  81. package/public/TextGen Settings/Naive.settings +15 -0
  82. package/public/TextGen Settings/NovelAI (Best Guess).settings +15 -0
  83. package/public/TextGen Settings/NovelAI (Decadence).settings +15 -0
  84. package/public/TextGen Settings/NovelAI (Genesis).settings +15 -0
  85. package/public/TextGen Settings/NovelAI (Lycaenidae).settings +15 -0
  86. package/public/TextGen Settings/NovelAI (Ouroboros).settings +15 -0
  87. package/public/TextGen Settings/NovelAI (Pleasing Results).settings +15 -0
  88. package/public/TextGen Settings/NovelAI (Sphinx Moth).settings +15 -0
  89. package/public/TextGen Settings/NovelAI (Storywriter).settings +15 -0
  90. package/public/TextGen Settings/Pygmalion.settings +15 -0
  91. package/public/css/fontawesome.css +8488 -0
  92. package/public/css/notes.css +46 -0
  93. package/public/css/solid.css +24 -0
  94. package/public/favicon.ico +0 -0
  95. package/public/img/No-Image-Placeholder.svg +309 -0
  96. package/public/img/addbg3.png +0 -0
  97. package/public/img/ai4.png +0 -0
  98. package/public/img/apple-icon-114x114.png +0 -0
  99. package/public/img/apple-icon-144x144.png +0 -0
  100. package/public/img/apple-icon-57x57.png +0 -0
  101. package/public/img/apple-icon-72x72.png +0 -0
  102. package/public/img/book2.png +0 -0
  103. package/public/img/default-expressions/admiration.png +0 -0
  104. package/public/img/default-expressions/amusement.png +0 -0
  105. package/public/img/default-expressions/anger.png +0 -0
  106. package/public/img/default-expressions/annoyance.png +0 -0
  107. package/public/img/default-expressions/approval.png +0 -0
  108. package/public/img/default-expressions/caring.png +0 -0
  109. package/public/img/default-expressions/confusion.png +0 -0
  110. package/public/img/default-expressions/curiosity.png +0 -0
  111. package/public/img/default-expressions/desire.png +0 -0
  112. package/public/img/default-expressions/desire1.png +0 -0
  113. package/public/img/default-expressions/desire2.png +0 -0
  114. package/public/img/default-expressions/disappointment.png +0 -0
  115. package/public/img/default-expressions/disapproval.png +0 -0
  116. package/public/img/default-expressions/disgust.png +0 -0
  117. package/public/img/default-expressions/embarrassment.png +0 -0
  118. package/public/img/default-expressions/excitement.png +0 -0
  119. package/public/img/default-expressions/fear.png +0 -0
  120. package/public/img/default-expressions/gratitude.png +0 -0
  121. package/public/img/default-expressions/grief.png +0 -0
  122. package/public/img/default-expressions/joy.png +0 -0
  123. package/public/img/default-expressions/love.png +0 -0
  124. package/public/img/default-expressions/nervousness.png +0 -0
  125. package/public/img/default-expressions/neutral.png +0 -0
  126. package/public/img/default-expressions/optimism.png +0 -0
  127. package/public/img/default-expressions/pride.png +0 -0
  128. package/public/img/default-expressions/realization.png +0 -0
  129. package/public/img/default-expressions/relief.png +0 -0
  130. package/public/img/default-expressions/remorse.png +0 -0
  131. package/public/img/default-expressions/sadness.png +0 -0
  132. package/public/img/default-expressions/surprise.png +0 -0
  133. package/public/img/five.png +0 -0
  134. package/public/img/times-circle.svg +1 -0
  135. package/public/img/you.png +0 -0
  136. package/public/index.html +1899 -0
  137. package/public/notes/1.html +44 -0
  138. package/public/notes/1.png +0 -0
  139. package/public/notes/10.html +20 -0
  140. package/public/notes/11.html +33 -0
  141. package/public/notes/12.html +27 -0
  142. package/public/notes/13.html +29 -0
  143. package/public/notes/13_1.html +24 -0
  144. package/public/notes/13_2.html +25 -0
  145. package/public/notes/13_3.html +89 -0
  146. package/public/notes/14.html +30 -0
  147. package/public/notes/2.html +37 -0
  148. package/public/notes/2.png +0 -0
  149. package/public/notes/3.html +37 -0
  150. package/public/notes/4.html +105 -0
  151. package/public/notes/6.html +33 -0
  152. package/public/notes/7.html +40 -0
  153. package/public/notes/8.html +19 -0
  154. package/public/notes/9.html +46 -0
  155. package/public/notes/advanced_formatting.html +91 -0
  156. package/public/notes/group_reply_strategy.html +63 -0
  157. package/public/notes/message_sound.html +33 -0
  158. package/public/notes/multigen.html +36 -0
  159. package/public/notes/oai_api_key.html +37 -0
  160. package/public/notes/textgen_streaming.html +29 -0
  161. package/public/notes/token-limits.html +68 -0
  162. package/public/script.js +5131 -0
  163. package/public/scripts/RossAscends-mods.js +750 -0
  164. package/public/scripts/bookmarks.js +130 -0
  165. package/public/scripts/extensions/backgrounds/index.js +129 -0
  166. package/public/scripts/extensions/backgrounds/manifest.json +11 -0
  167. package/public/scripts/extensions/backgrounds/style.css +45 -0
  168. package/public/scripts/extensions/caption/index.js +117 -0
  169. package/public/scripts/extensions/caption/manifest.json +13 -0
  170. package/public/scripts/extensions/caption/style.css +23 -0
  171. package/public/scripts/extensions/dice/droll.js +108 -0
  172. package/public/scripts/extensions/dice/index.js +96 -0
  173. package/public/scripts/extensions/dice/manifest.json +11 -0
  174. package/public/scripts/extensions/dice/style.css +26 -0
  175. package/public/scripts/extensions/expressions/index.js +387 -0
  176. package/public/scripts/extensions/expressions/manifest.json +13 -0
  177. package/public/scripts/extensions/expressions/style.css +115 -0
  178. package/public/scripts/extensions/floating-prompt/index.js +151 -0
  179. package/public/scripts/extensions/floating-prompt/manifest.json +11 -0
  180. package/public/scripts/extensions/floating-prompt/style.css +19 -0
  181. package/public/scripts/extensions/memory/index.js +358 -0
  182. package/public/scripts/extensions/memory/manifest.json +13 -0
  183. package/public/scripts/extensions/memory/style.css +34 -0
  184. package/public/scripts/extensions.js +288 -0
  185. package/public/scripts/f-localStorage.js +27 -0
  186. package/public/scripts/gpt-2-3-tokenizer/README.md +28 -0
  187. package/public/scripts/gpt-2-3-tokenizer/encoder.js +1 -0
  188. package/public/scripts/gpt-2-3-tokenizer/mod.js +169 -0
  189. package/public/scripts/gpt-2-3-tokenizer/vocab.bpe.js +1 -0
  190. package/public/scripts/gpt-3-tokenizer/array-keyed-map.js +210 -0
  191. package/public/scripts/gpt-3-tokenizer/gpt3-tokenizer.js +271 -0
  192. package/public/scripts/gpt-3-tokenizer/gpt3-tokenizer.js.map +1 -0
  193. package/public/scripts/group-chats.js +899 -0
  194. package/public/scripts/horde.js +214 -0
  195. package/public/scripts/jquery-3.5.1.min.js +2 -0
  196. package/public/scripts/jquery-cookie-1.4.1.min.js +2 -0
  197. package/public/scripts/jquery.transit.min.js +1 -0
  198. package/public/scripts/kai-settings.js +179 -0
  199. package/public/scripts/nai-settings.js +108 -0
  200. package/public/scripts/openai.js +973 -0
  201. package/public/scripts/poe.js +360 -0
  202. package/public/scripts/popper.js +2008 -0
  203. package/public/scripts/popper.js.map +1 -0
  204. package/public/scripts/power-user.js +571 -0
  205. package/public/scripts/purify.min.js +3 -0
  206. package/public/scripts/purify.min.js.map +1 -0
  207. package/public/scripts/showdown.min.js +3 -0
  208. package/public/scripts/showdown.min.js.map +1 -0
  209. package/public/scripts/swiped-events.js +165 -0
  210. package/public/scripts/textgen-settings.js +194 -0
  211. package/public/scripts/toolcool-color-picker.js +87 -0
  212. package/public/scripts/utils.js +109 -0
  213. package/public/scripts/world-info.js +661 -0
  214. package/public/sounds/message.mp3 +0 -0
  215. package/public/style.css +3633 -0
  216. package/public/webfonts/NotoSans/NotoSans-Black.woff +0 -0
  217. package/public/webfonts/NotoSans/NotoSans-Black.woff2 +0 -0
  218. package/public/webfonts/NotoSans/NotoSans-BlackItalic.woff +0 -0
  219. package/public/webfonts/NotoSans/NotoSans-BlackItalic.woff2 +0 -0
  220. package/public/webfonts/NotoSans/NotoSans-Bold.woff +0 -0
  221. package/public/webfonts/NotoSans/NotoSans-Bold.woff2 +0 -0
  222. package/public/webfonts/NotoSans/NotoSans-BoldItalic.woff +0 -0
  223. package/public/webfonts/NotoSans/NotoSans-BoldItalic.woff2 +0 -0
  224. package/public/webfonts/NotoSans/NotoSans-ExtraBold.woff +0 -0
  225. package/public/webfonts/NotoSans/NotoSans-ExtraBold.woff2 +0 -0
  226. package/public/webfonts/NotoSans/NotoSans-ExtraBoldItalic.woff +0 -0
  227. package/public/webfonts/NotoSans/NotoSans-ExtraBoldItalic.woff2 +0 -0
  228. package/public/webfonts/NotoSans/NotoSans-ExtraLight.woff +0 -0
  229. package/public/webfonts/NotoSans/NotoSans-ExtraLight.woff2 +0 -0
  230. package/public/webfonts/NotoSans/NotoSans-ExtraLightItalic.woff +0 -0
  231. package/public/webfonts/NotoSans/NotoSans-ExtraLightItalic.woff2 +0 -0
  232. package/public/webfonts/NotoSans/NotoSans-Italic.woff +0 -0
  233. package/public/webfonts/NotoSans/NotoSans-Italic.woff2 +0 -0
  234. package/public/webfonts/NotoSans/NotoSans-Light.woff +0 -0
  235. package/public/webfonts/NotoSans/NotoSans-Light.woff2 +0 -0
  236. package/public/webfonts/NotoSans/NotoSans-LightItalic.woff +0 -0
  237. package/public/webfonts/NotoSans/NotoSans-LightItalic.woff2 +0 -0
  238. package/public/webfonts/NotoSans/NotoSans-Medium.woff +0 -0
  239. package/public/webfonts/NotoSans/NotoSans-Medium.woff2 +0 -0
  240. package/public/webfonts/NotoSans/NotoSans-MediumItalic.woff +0 -0
  241. package/public/webfonts/NotoSans/NotoSans-MediumItalic.woff2 +0 -0
  242. package/public/webfonts/NotoSans/NotoSans-Regular.woff +0 -0
  243. package/public/webfonts/NotoSans/NotoSans-Regular.woff2 +0 -0
  244. package/public/webfonts/NotoSans/NotoSans-SemiBold.woff +0 -0
  245. package/public/webfonts/NotoSans/NotoSans-SemiBold.woff2 +0 -0
  246. package/public/webfonts/NotoSans/NotoSans-SemiBoldItalic.woff +0 -0
  247. package/public/webfonts/NotoSans/NotoSans-SemiBoldItalic.woff2 +0 -0
  248. package/public/webfonts/NotoSans/NotoSans-Thin.woff +0 -0
  249. package/public/webfonts/NotoSans/NotoSans-Thin.woff2 +0 -0
  250. package/public/webfonts/NotoSans/NotoSans-ThinItalic.woff +0 -0
  251. package/public/webfonts/NotoSans/NotoSans-ThinItalic.woff2 +0 -0
  252. package/public/webfonts/NotoSans/stylesheet.css +162 -0
  253. package/public/webfonts/fa-solid-900.ttf +0 -0
  254. package/public/webfonts/fa-solid-900.woff2 +0 -0
  255. package/readme.md +187 -0
  256. package/server.js +2593 -0
  257. package/start.sh +24 -0
  258. package/tools/charaverter/main.mjs +110 -0
  259. package/tools/charaverter/package.json +10 -0
@@ -0,0 +1,26 @@
1
+ #roll_dice {
2
+ order: 100;
3
+ width: 40px;
4
+ height: 40px;
5
+ margin: 0;
6
+ padding: 1px;
7
+ outline: none;
8
+ border: none;
9
+ cursor: pointer;
10
+ transition: 0.3s;
11
+ opacity: 0.7;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+
16
+ }
17
+
18
+ #roll_dice:hover {
19
+ opacity: 1;
20
+ filter: brightness(1.2);
21
+ }
22
+
23
+ #dice_dropdown {
24
+ z-index: 100;
25
+ backdrop-filter: blur(--SmartThemeBlurStrength);
26
+ }
@@ -0,0 +1,387 @@
1
+ import { saveSettingsDebounced, token } from "../../../script.js";
2
+ import { getContext, getApiUrl, modules, extension_settings } from "../../extensions.js";
3
+ export { MODULE_NAME };
4
+
5
+ const MODULE_NAME = 'expressions';
6
+ const UPDATE_INTERVAL = 1000;
7
+ const DEFAULT_EXPRESSIONS = [
8
+ "admiration",
9
+ "amusement",
10
+ "anger",
11
+ "annoyance",
12
+ "approval",
13
+ "caring",
14
+ "confusion",
15
+ "curiosity",
16
+ "desire",
17
+ "disappointment",
18
+ "disapproval",
19
+ "disgust",
20
+ "embarrassment",
21
+ "excitement",
22
+ "fear",
23
+ "gratitude",
24
+ "grief",
25
+ "joy",
26
+ "love",
27
+ "nervousness",
28
+ "optimism",
29
+ "pride",
30
+ "realization",
31
+ "relief",
32
+ "remorse",
33
+ "sadness",
34
+ "surprise",
35
+ "neutral"
36
+ ];
37
+
38
+ let expressionsList = null;
39
+ let lastCharacter = undefined;
40
+ let lastMessage = null;
41
+ let spriteCache = {};
42
+ let inApiCall = false;
43
+
44
+ function onExpressionsShowDefaultInput() {
45
+ const value = $(this).prop('checked');
46
+ extension_settings.expressions.showDefault = value;
47
+ saveSettingsDebounced();
48
+
49
+ const existingImageSrc = $('img.expression').prop('src');
50
+ if (existingImageSrc !== undefined) { //if we have an image in src
51
+ if (!value && existingImageSrc.includes('/img/default-expressions/')) { //and that image is from /img/ (default)
52
+ $('img.expression').prop('src', ''); //remove it
53
+ lastMessage = null;
54
+ }
55
+ if (value) {
56
+ lastMessage = null;
57
+ }
58
+ }
59
+ }
60
+
61
+ let isWorkerBusy = false;
62
+
63
+ async function moduleWorkerWrapper() {
64
+ // Don't touch me I'm busy...
65
+ if (isWorkerBusy) {
66
+ return;
67
+ }
68
+
69
+ // I'm free. Let's update!
70
+ try {
71
+ isWorkerBusy = true;
72
+ await moduleWorker();
73
+ }
74
+ finally {
75
+ isWorkerBusy = false;
76
+ }
77
+ }
78
+
79
+ async function moduleWorker() {
80
+ const context = getContext();
81
+
82
+ // non-characters not supported
83
+ if (!context.groupId && !context.characterId) {
84
+ removeExpression();
85
+ return;
86
+ }
87
+
88
+ // character changed
89
+ if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) {
90
+ removeExpression();
91
+ spriteCache = {};
92
+ }
93
+
94
+ const currentLastMessage = getLastCharacterMessage();
95
+
96
+ // character has no expressions or it is not loaded
97
+ if (Object.keys(spriteCache).length === 0) {
98
+ await validateImages(currentLastMessage.name);
99
+ lastCharacter = context.groupId || context.characterId;
100
+ }
101
+
102
+ const offlineMode = $('.expression_settings .offline_mode');
103
+ if (!modules.includes('classify')) {
104
+ $('.expression_settings').show();
105
+ offlineMode.css('display', 'block');
106
+ lastCharacter = context.groupId || context.characterId;
107
+
108
+ if (context.groupId) {
109
+ await validateImages(currentLastMessage.name, true);
110
+ }
111
+
112
+ return;
113
+ }
114
+ else {
115
+ // force reload expressions list on connect to API
116
+ if (offlineMode.is(':visible')) {
117
+ expressionsList = null;
118
+ spriteCache = {};
119
+ expressionsList = await getExpressionsList();
120
+ await validateImages(currentLastMessage.name, true);
121
+ }
122
+
123
+ offlineMode.css('display', 'none');
124
+ }
125
+
126
+
127
+ // check if last message changed
128
+ if ((lastCharacter === context.characterId || lastCharacter === context.groupId)
129
+ && lastMessage === currentLastMessage.mes) {
130
+ return;
131
+ }
132
+
133
+ // API is busy
134
+ if (inApiCall) {
135
+ return;
136
+ }
137
+
138
+ try {
139
+ inApiCall = true;
140
+ const url = new URL(getApiUrl());
141
+ url.pathname = '/api/classify';
142
+
143
+ const apiResult = await fetch(url, {
144
+ method: 'POST',
145
+ headers: {
146
+ 'Content-Type': 'application/json',
147
+ 'Bypass-Tunnel-Reminder': 'bypass',
148
+ },
149
+ body: JSON.stringify({ text: currentLastMessage.mes })
150
+ });
151
+
152
+ if (apiResult.ok) {
153
+ const name = context.groupId ? currentLastMessage.name : context.name2;
154
+ const force = !!context.groupId;
155
+ const data = await apiResult.json();
156
+ let expression = data.classification[0].label;
157
+
158
+ // Character won't be angry on you for swiping
159
+ if (currentLastMessage.mes == '...' && expressionsList.includes('joy')) {
160
+ expression = 'joy';
161
+ }
162
+
163
+ setExpression(name, expression, force);
164
+ }
165
+
166
+ }
167
+ catch (error) {
168
+ console.log(error);
169
+ }
170
+ finally {
171
+ inApiCall = false;
172
+ lastCharacter = context.groupId || context.characterId;
173
+ lastMessage = currentLastMessage.mes;
174
+ }
175
+ }
176
+
177
+ function getLastCharacterMessage() {
178
+ const context = getContext();
179
+ const reversedChat = context.chat.slice().reverse();
180
+
181
+ for (let mes of reversedChat) {
182
+ if (mes.is_user || mes.is_system) {
183
+ continue;
184
+ }
185
+
186
+ return { mes: mes.mes, name: mes.name };
187
+ }
188
+
189
+ return { mes: '', name: null };
190
+ }
191
+
192
+ function removeExpression() {
193
+ lastMessage = null;
194
+ $('img.expression').off('error');
195
+ $('img.expression').prop('src', '');
196
+ $('img.expression').removeClass('default');
197
+ $('.expression_settings').hide();
198
+ }
199
+
200
+ async function validateImages(character, forceRedrawCached) {
201
+ if (!character) {
202
+ return;
203
+ }
204
+
205
+ const labels = await getExpressionsList();
206
+
207
+ if (spriteCache[character]) {
208
+ if (forceRedrawCached && $('#image_list').data('name') !== character) {
209
+ console.log('force redrawing character sprites list')
210
+ drawSpritesList(character, labels, spriteCache[character]);
211
+ }
212
+
213
+ return;
214
+ }
215
+
216
+ const sprites = await getSpritesList(character);
217
+ let validExpressions = drawSpritesList(character, labels, sprites);
218
+ spriteCache[character] = validExpressions;
219
+ }
220
+
221
+ function drawSpritesList(character, labels, sprites) {
222
+ let validExpressions = [];
223
+ $('.expression_settings').show();
224
+ $('#image_list').empty();
225
+ $('#image_list').data('name', character);
226
+ labels.sort().forEach((item) => {
227
+ const sprite = sprites.find(x => x.label == item);
228
+
229
+ if (sprite) {
230
+ validExpressions.push(sprite);
231
+ $('#image_list').append(getListItem(item, sprite.path, 'success'));
232
+ }
233
+ else {
234
+ $('#image_list').append(getListItem(item, '/img/No-Image-Placeholder.svg', 'failure'));
235
+ }
236
+ });
237
+ return validExpressions;
238
+ }
239
+
240
+ function getListItem(item, imageSrc, textClass) {
241
+ return `
242
+ <div id="${item}" class="expression_list_item">
243
+ <span class="expression_list_title ${textClass}">${item}</span>
244
+ <img class="expression_list_image" src="${imageSrc}" />
245
+ </div>
246
+ `;
247
+ }
248
+
249
+ async function getSpritesList(name) {
250
+ console.log('getting sprites list');
251
+
252
+ try {
253
+ const result = await fetch(`/get_sprites?name=${encodeURIComponent(name)}`, {
254
+ headers: {
255
+ 'X-CSRF-Token': token,
256
+ }
257
+ });
258
+
259
+ let sprites = result.ok ? (await result.json()) : [];
260
+ return sprites;
261
+ }
262
+ catch (err) {
263
+ console.log(err);
264
+ return [];
265
+ }
266
+ }
267
+
268
+ async function getExpressionsList() {
269
+ console.log('getting expressions list');
270
+ // get something for offline mode (default images)
271
+ if (!modules.includes('classify')) {
272
+ return DEFAULT_EXPRESSIONS;
273
+ }
274
+
275
+ if (Array.isArray(expressionsList)) {
276
+ return expressionsList;
277
+ }
278
+
279
+ const url = new URL(getApiUrl());
280
+ url.pathname = '/api/classify/labels';
281
+
282
+ try {
283
+ const apiResult = await fetch(url, {
284
+ method: 'GET',
285
+ headers: { 'Bypass-Tunnel-Reminder': 'bypass' },
286
+ });
287
+
288
+ if (apiResult.ok) {
289
+
290
+ const data = await apiResult.json();
291
+ expressionsList = data.labels;
292
+ return expressionsList;
293
+ }
294
+ }
295
+ catch (error) {
296
+ console.log(error);
297
+ return [];
298
+ }
299
+ }
300
+
301
+ async function setExpression(character, expression, force) {
302
+ console.log('entered setExpressions');
303
+ await validateImages(character);
304
+ const img = $('img.expression');
305
+
306
+ const sprite = (spriteCache[character] && spriteCache[character].find(x => x.label === expression));
307
+ console.log('checking for expression images to show..');
308
+ if (sprite) {
309
+ console.log('setting expression from character images folder');
310
+ img.attr('src', sprite.path);
311
+ img.removeClass('default');
312
+ img.off('error');
313
+ img.on('error', function () {
314
+ $(this).attr('src', '');
315
+ if (force && extension_settings.expressions.showDefault) {
316
+ setDefault();
317
+ }
318
+ });
319
+ } else {
320
+ if (extension_settings.expressions.showDefault) {
321
+ setDefault();
322
+ }
323
+ }
324
+
325
+ function setDefault() {
326
+ console.log('setting default');
327
+ const defImgUrl = `/img/default-expressions/${expression}.png`;
328
+ //console.log(defImgUrl);
329
+ img.attr('src', defImgUrl);
330
+ img.addClass('default');
331
+ }
332
+ document.getElementById("expression-holder").style.display = '';
333
+ }
334
+
335
+ function onClickExpressionImage() {
336
+ // online mode doesn't need force set
337
+ if (modules.includes('classify')) {
338
+ return;
339
+ }
340
+
341
+ const expression = $(this).attr('id');
342
+ const name = getLastCharacterMessage().name;
343
+
344
+ if ($(this).find('.failure').length === 0) {
345
+ setExpression(name, expression, true);
346
+ }
347
+ }
348
+
349
+ (function () {
350
+ function addExpressionImage() {
351
+ const html = `
352
+ <div id="expression-holder" class="expression-holder" style="display:none;">
353
+ <div id="expression-holderheader" class="fa-solid fa-grip drag-grabber"></div>
354
+ <img id="expression-image" class="expression">
355
+ </div>`;
356
+ $('body').append(html);
357
+ }
358
+ function addSettings() {
359
+
360
+ const html = `
361
+ <div class="expression_settings">
362
+ <div class="inline-drawer">
363
+ <div class="inline-drawer-toggle inline-drawer-header">
364
+ <b>Expression images</b>
365
+ <div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
366
+ </div>
367
+ <div class="inline-drawer-content">
368
+ <p class="offline_mode">You are in offline mode. Click on the image below to set the expression.</p>
369
+ <div id="image_list"></div>
370
+ <p class="hint"><b>Hint:</b> <i>Create new folder in the <b>public/characters/</b> folder and name it as the name of the character.
371
+ Put images with expressions there. File names should follow the pattern: <tt>[expression_label].[image_format]</tt></i></p>
372
+ <label for="expressions_show_default"><input id="expressions_show_default" type="checkbox">Show default images (emojis) if missing</label>
373
+ </div>
374
+ </div>
375
+ </div>
376
+ `;
377
+ $('#extensions_settings').append(html);
378
+ $('#expressions_show_default').on('input', onExpressionsShowDefaultInput);
379
+ $('#expressions_show_default').prop('checked', extension_settings.expressions.showDefault).trigger('input');
380
+ $(document).on('click', '.expression_list_item', onClickExpressionImage);
381
+ $('.expression_settings').hide();
382
+ }
383
+
384
+ addExpressionImage();
385
+ addSettings();
386
+ setInterval(moduleWorkerWrapper, UPDATE_INTERVAL);
387
+ })();
@@ -0,0 +1,13 @@
1
+ {
2
+ "display_name": "Character Expressions",
3
+ "loading_order": 6,
4
+ "requires": [],
5
+ "optional": [
6
+ "classify"
7
+ ],
8
+ "js": "index.js",
9
+ "css": "style.css",
10
+ "author": "Cohee#1207",
11
+ "version": "1.0.0",
12
+ "homePage": "https://github.com/Cohee1207/SillyTavern"
13
+ }
@@ -0,0 +1,115 @@
1
+ .expression-helper {
2
+ display: inline-block;
3
+ height: 100%;
4
+ vertical-align: middle;
5
+ }
6
+
7
+ .expression-holder {
8
+ min-width: 100px;
9
+ min-height: 100px;
10
+ max-height: 90vh;
11
+ max-width: 90vh;
12
+ width: calc((100vw - var(--sheldWidth)) /2);
13
+ position: absolute;
14
+ bottom: 1px;
15
+ padding: 0;
16
+ filter: drop-shadow(2px 2px 2px #51515199);
17
+ z-index: 1;
18
+ overflow: hidden;
19
+
20
+ }
21
+
22
+ img.expression {
23
+ width: 100%;
24
+ height: 100%;
25
+ vertical-align: bottom;
26
+ object-fit: contain;
27
+ }
28
+
29
+ img.expression[src=""] {
30
+ visibility: hidden;
31
+ }
32
+
33
+ img.expression.default {
34
+ vertical-align: middle;
35
+ }
36
+
37
+ .debug-image {
38
+ display: none;
39
+ visibility: collapse;
40
+ opacity: 0;
41
+ width: 0px;
42
+ height: 0px;
43
+ }
44
+
45
+ .expression_list_item {
46
+ position: relative;
47
+ max-width: 20%;
48
+ max-height: 200px;
49
+ background-color: #515151b0;
50
+ border-radius: 10px;
51
+ cursor: pointer;
52
+ display: flex;
53
+ flex-direction: column;
54
+ align-items: center;
55
+ justify-content: center;
56
+ }
57
+
58
+ .expression_list_title {
59
+ position: absolute;
60
+ bottom: 0;
61
+ left: 0;
62
+ text-align: center;
63
+ font-weight: 600;
64
+ background-color: #000000a8;
65
+ width: 100%;
66
+ height: 20%;
67
+ display: flex;
68
+ justify-content: center;
69
+ align-items: center;
70
+ }
71
+
72
+ .expression_list_image {
73
+ max-width: 100%;
74
+ height: 100%;
75
+ }
76
+
77
+ #image_list {
78
+ display: flex;
79
+ flex-direction: row;
80
+ column-gap: 1rem;
81
+ margin: 1rem;
82
+ flex-wrap: wrap;
83
+ justify-content: space-evenly;
84
+ row-gap: 1rem;
85
+ }
86
+
87
+ #image_list .success {
88
+ color: green;
89
+ }
90
+
91
+ #image_list .failure {
92
+ color: red;
93
+ }
94
+
95
+ .expression_settings p {
96
+ margin-top: 0.5rem;
97
+ margin-bottom: 0.5rem;
98
+ }
99
+
100
+ .expression_settings label {
101
+ display: flex;
102
+ align-items: center;
103
+ flex-direction: row;
104
+ margin-left: 0px;
105
+ }
106
+
107
+ .expression_settings label input {
108
+ margin-left: 0px !important;
109
+ }
110
+
111
+ @media screen and (max-width:1200px) {
112
+ div.expression {
113
+ display: none;
114
+ }
115
+ }
@@ -0,0 +1,151 @@
1
+ import { chat_metadata, saveSettingsDebounced } from "../../../script.js";
2
+ import { extension_settings, getContext } from "../../extensions.js";
3
+ import { debounce } from "../../utils.js";
4
+ export { MODULE_NAME };
5
+
6
+ const saveChatDebounced = debounce(async () => await getContext().saveChat(), 1000);
7
+
8
+ const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory
9
+ const UPDATE_INTERVAL = 1000;
10
+
11
+ const DEFAULT_DEPTH = 4;
12
+ const DEFAULT_POSITION = 1;
13
+ const DEFAULT_INTERVAL = 1;
14
+
15
+ const metadata_keys = {
16
+ prompt: 'note_prompt',
17
+ interval: 'note_interval',
18
+ depth: 'note_depth',
19
+ position: 'note_position',
20
+ }
21
+
22
+ async function onExtensionFloatingPromptInput() {
23
+ chat_metadata[metadata_keys.prompt] = $(this).val();
24
+ saveChatDebounced();
25
+ }
26
+
27
+ async function onExtensionFloatingIntervalInput() {
28
+ chat_metadata[metadata_keys.interval] = Number($(this).val());
29
+ saveChatDebounced();
30
+ }
31
+
32
+ async function onExtensionFloatingDepthInput() {
33
+ let value = Number($(this).val());
34
+
35
+ if (value < 0) {
36
+ value = Math.abs(value);
37
+ $(this).val(value);
38
+ }
39
+
40
+ chat_metadata[metadata_keys.depth] = value;
41
+ saveChatDebounced();
42
+ }
43
+
44
+ async function onExtensionFloatingPositionInput(e) {
45
+ chat_metadata[metadata_keys.position] = e.target.value;
46
+ saveChatDebounced();
47
+ }
48
+
49
+ function onExtensionFloatingDefaultInput() {
50
+ extension_settings.note.default = $(this).val();
51
+ saveSettingsDebounced();
52
+ }
53
+
54
+ function loadSettings() {
55
+ chat_metadata[metadata_keys.prompt] = chat_metadata[metadata_keys.prompt] ?? extension_settings.note.default ?? '';
56
+ chat_metadata[metadata_keys.interval] = chat_metadata[metadata_keys.interval] ?? DEFAULT_INTERVAL;
57
+ chat_metadata[metadata_keys.position] = chat_metadata[metadata_keys.position] ?? DEFAULT_POSITION;
58
+ chat_metadata[metadata_keys.depth] = chat_metadata[metadata_keys.depth] ?? DEFAULT_DEPTH;
59
+ $('#extension_floating_prompt').val(chat_metadata[metadata_keys.prompt]);
60
+ $('#extension_floating_interval').val(chat_metadata[metadata_keys.interval]);
61
+ $('#extension_floating_depth').val(chat_metadata[metadata_keys.depth]);
62
+ $(`input[name="extension_floating_position"][value="${chat_metadata[metadata_keys.position]}"]`).prop('checked', true);
63
+ $('#extension_floating_default').val(extension_settings.note.default);
64
+ }
65
+
66
+ async function moduleWorker() {
67
+ const context = getContext();
68
+
69
+ if (!context.groupId && !context.characterId) {
70
+ return;
71
+ }
72
+
73
+ loadSettings();
74
+
75
+ // take the count of messages
76
+ let lastMessageNumber = Array.isArray(context.chat) && context.chat.length ? context.chat.filter(m => m.is_user).length : 0;
77
+
78
+ // special case for new chat
79
+ if (Array.isArray(context.chat) && context.chat.length === 1) {
80
+ lastMessageNumber = 1;
81
+ }
82
+
83
+ if (lastMessageNumber <= 0 || chat_metadata[metadata_keys.interval] <= 0) {
84
+ context.setExtensionPrompt(MODULE_NAME, '');
85
+ $('#extension_floating_counter').text('No');
86
+ return;
87
+ }
88
+
89
+ const messagesTillInsertion = lastMessageNumber >= chat_metadata[metadata_keys.interval]
90
+ ? (lastMessageNumber % chat_metadata[metadata_keys.interval])
91
+ : (chat_metadata[metadata_keys.interval] - lastMessageNumber);
92
+ const shouldAddPrompt = messagesTillInsertion == 0;
93
+ const prompt = shouldAddPrompt ? $('#extension_floating_prompt').val() : '';
94
+ context.setExtensionPrompt(MODULE_NAME, prompt, chat_metadata[metadata_keys.position], chat_metadata[metadata_keys.depth]);
95
+ $('#extension_floating_counter').text(shouldAddPrompt ? 'This' : messagesTillInsertion);
96
+ }
97
+
98
+ (function () {
99
+ function addExtensionsSettings() {
100
+ const settingsHtml = `
101
+ <div class="floating_prompt_settings">
102
+ <div class="inline-drawer">
103
+ <div class="inline-drawer-toggle inline-drawer-header">
104
+ <b>Author's Note / Character Bias</b>
105
+ <div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
106
+ </div>
107
+ <div class="inline-drawer-content">
108
+ <label for="extension_floating_prompt">Append the following text:</label>
109
+ <textarea id="extension_floating_prompt" class="text_pole" rows="8"></textarea>
110
+ <div class="floating_prompt_radio_group">
111
+ <label>
112
+ <input type="radio" name="extension_floating_position" value="0" />
113
+ After scenario
114
+ </label>
115
+ <label>
116
+ <input type="radio" name="extension_floating_position" value="1" />
117
+ In-chat
118
+ </label>
119
+ </div>
120
+ <label for="extension_floating_interval">Every N messages <b>you</b> send (set to 0 to disable):</label>
121
+ <input id="extension_floating_interval" class="text_pole" type="number" min="0" max="999" />
122
+ <label for="extension_floating_interval">Insertion depth (for in-chat positioning):</label>
123
+ <input id="extension_floating_depth" class="text_pole" type="number" min="0" max="99" />
124
+ <span>Appending to the prompt in next: <span id="extension_floating_counter">No</span> message(s)</span>
125
+ </div>
126
+ </div>
127
+ <div class="inline-drawer">
128
+ <div class="inline-drawer-toggle inline-drawer-header">
129
+ <b>Default note for new chats</b>
130
+ <div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
131
+ </div>
132
+ <div class="inline-drawer-content">
133
+ <label for="extension_floating_default">Default Author's Note</label>
134
+ <textarea id="extension_floating_default" class="text_pole" rows="8"
135
+ placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ `;
140
+
141
+ $('#extensions_settings').append(settingsHtml);
142
+ $('#extension_floating_prompt').on('input', onExtensionFloatingPromptInput);
143
+ $('#extension_floating_interval').on('input', onExtensionFloatingIntervalInput);
144
+ $('#extension_floating_depth').on('input', onExtensionFloatingDepthInput);
145
+ $('#extension_floating_default').on('input', onExtensionFloatingDefaultInput);
146
+ $('input[name="extension_floating_position"]').on('change', onExtensionFloatingPositionInput);
147
+ }
148
+
149
+ addExtensionsSettings();
150
+ setInterval(moduleWorker, UPDATE_INTERVAL);
151
+ })();
@@ -0,0 +1,11 @@
1
+ {
2
+ "display_name": "Author's Note / Character Bias",
3
+ "loading_order": 1,
4
+ "requires": [],
5
+ "optional": [],
6
+ "js": "index.js",
7
+ "css": "style.css",
8
+ "author": "Cohee#1207",
9
+ "version": "1.0.0",
10
+ "homePage": "https://github.com/Cohee1207/SillyTavern"
11
+ }