Compare commits

..

742 Commits
1.7.0 ... 1.9.0

Author SHA1 Message Date
Cohee
06912dba0a Merge pull request #747 from SillyTavern/dev
Dev
2023-07-20 14:25:38 +03:00
Cohee
429fe85e16 Merge main 2023-07-20 14:24:58 +03:00
Cohee
5807263681 Remove Poe support
It's Poever
2023-07-20 13:26:12 +03:00
Cohee
ca3f8daa9d Merge pull request #745 from Marandi269/patch-1 2023-07-20 09:37:00 +03:00
Marandi269
8d15b98391 Update server.js
bug?
2023-07-20 10:05:31 +08:00
Cohee
ce64747705 Lint server.js 2023-07-20 02:08:39 +03:00
Cohee
f7237342df I give up (Partial Poe fix) 2023-07-20 02:08:25 +03:00
Cohee
b66e3b3f25 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-19 23:13:17 +03:00
Cohee
853ab87e05 Poe fix 2023-07-19 23:13:11 +03:00
RossAscends
5e60202159 Merge branch 'main' of https://github.com/Cohee1207/SillyTavern 2023-07-20 01:53:58 +09:00
RossAscends
690dab49a0 update gitignore for poe raw logs 2023-07-20 01:53:56 +09:00
RossAscends
76bac19fb5 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-20 01:52:34 +09:00
RossAscends
671345efae update gitignore for new poe raw logs 2023-07-20 01:52:32 +09:00
Cohee
ed9b46c980 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-19 19:33:27 +03:00
Cohee
4c976e58e2 Better styles for stats buttons 2023-07-19 19:33:18 +03:00
RossAscends
7e127e9b68 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-20 01:12:32 +09:00
RossAscends
3712e2957b add randomized agents to poe (not a fix) 2023-07-20 01:12:29 +09:00
Cohee
f6e1c48ac9 Merge branch 'main' into dev 2023-07-19 18:41:48 +03:00
Cohee
c6a6a8352d Fix textarea sanitation. Fix extensions promise never resolving on 404 2023-07-19 18:40:28 +03:00
Cohee
4c3aafa3a8 Add support for API keys to extras colab 2023-07-19 18:27:14 +03:00
Cohee
7cf02beaa6 Merge pull request #615 from BlipRanger/feature/stats
Feature/stats
2023-07-19 17:40:03 +03:00
BlipRanger
284fb68478 Fix first chat date injestion (I'm pretty sure). 2023-07-19 09:51:22 -04:00
RossAscends
dfab4b8ea2 attempted slow cure for poe 2023-07-19 22:20:01 +09:00
RossAscends
f63a69dd41 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-19 22:11:37 +09:00
RossAscends
13f6cf3175 possible slow cure for poe 2023-07-19 22:11:31 +09:00
Cohee
d5af1ec82e Merge main 2023-07-19 16:09:06 +03:00
RossAscends
bd7c0463f3 WIP half-fix for group VN mode + movingUI 2023-07-19 21:26:28 +09:00
Cohee
e3e2b73b99 Bump package version 2023-07-19 11:53:12 +03:00
Cohee
f5b4c6e10c Merge pull request #736 from bdashore3/dev 2023-07-19 09:35:04 +03:00
RossAscends
fbbb7cc549 fix poe connectivity get >> post 2023-07-19 14:25:59 +09:00
RossAscends
2305a536de Merge pull request #738 from BlueprintCoding/patch-2
Update poe-client.js
2023-07-19 14:23:37 +09:00
Blueprint Coding
f339f28b05 Update poe-client.js
Fixed poe by changing Get request to a Post request
2023-07-18 22:33:38 -06:00
kingbri
92f012fb6a Greetings: Fix swipe on chat creation
Alternate greetings would cause a console error since chat extras
didn't exist. To patch this, add an empty array if either value is
nullish.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-18 22:44:52 -04:00
kingbri
8de791a9ee Regex: Fix greeting message append
Greeting messages weren't being regexed on new chat creation. Fix
this by adding more regex hooks when creating a chat.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-18 22:40:07 -04:00
BlipRanger
2f73506e25 Prettier again. 2023-07-18 21:48:12 -04:00
BlipRanger
656888f70a Prettier, comments 2023-07-18 21:47:27 -04:00
BlipRanger
1886334516 Moved css, fixed convo age 2023-07-18 19:15:41 -04:00
BlipRanger
d547f2650a Count swipes and msgs seperately. 2023-07-18 18:51:11 -04:00
BlipRanger
f83f71097a Add collection of chat age 2023-07-18 18:48:44 -04:00
BlipRanger
c1b2a084d5 Rename, change count method, and forgot to count user messages lol 2023-07-18 16:27:31 -04:00
Cohee
96c668296a Don't purge metadata in clearChat 2023-07-18 22:31:39 +03:00
Cohee
fa6803f2de Merge pull request #735 from XXpE3/dev 2023-07-18 21:11:01 +03:00
XXpE3
7a0f5a0111 Repaired and polished a large amount of Chinese translated text 2023-07-19 01:06:59 +08:00
Cohee
9e21534fae #629 {{roll}} replacement macros 2023-07-18 19:51:20 +03:00
XXpE3
af5f7199de Repolished some Chinese translations. 2023-07-19 00:33:42 +08:00
Cohee
623675d940 #733 Reload selected chat instead of inserting the first one in array 2023-07-18 18:28:51 +03:00
Cohee
547b275768 #728 Refine mode for captioning plugin 2023-07-18 18:22:51 +03:00
BlipRanger
28d22aa8c1 Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into feature/stats 2023-07-18 09:42:11 -04:00
XXpE3
766349785d Initial simple translation 2023-07-18 19:32:19 +08:00
Cohee
5209485f20 #715 Instruct continue fix 2023-07-18 13:08:01 +03:00
Cohee
f327f4abbe #715 Fix double insertion of bias instruct mode 2023-07-18 12:27:08 +03:00
Cohee
b003c18abd Merge pull request #732 from bdashore3/dev 2023-07-18 09:27:53 +03:00
Cohee
7e310323b6 Merge pull request #730 from breathingmanually/fix-firstmes-edited-params 2023-07-18 09:25:13 +03:00
BlipRanger
5090fe76a9 Remove server logging 2023-07-18 01:58:29 -04:00
BlipRanger
818416b1f2 Make charstats global within stat helper. 2023-07-18 01:56:55 -04:00
BlipRanger
31a159dee0 Cleanup old stuff 2023-07-18 01:42:16 -04:00
BlipRanger
c501734d25 Add stats to gitignore 2023-07-18 01:38:50 -04:00
BlipRanger
baf0fd7e41 Remove only ArgoAscends function ever, prettier :( 2023-07-18 01:37:46 -04:00
BlipRanger
b7c5ea9152 Fix continue logic, move update logic 2023-07-18 01:24:11 -04:00
kingbri
d61eba4cb4 Regex: Add script reordering
The engine runs with a foreach, so the scripts run sequentially.
Ideally, scripts should be one-liners, but if multiple scripts
run in a chain, allow the user to reorder them.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-18 01:15:06 -04:00
kingbri
eb90162579 Regex: Fix overlay for multiple occurrences
If there are multiple occurrences of a prefix or suffix within the
input string, remove them when overlaying.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-18 01:15:06 -04:00
BlipRanger
b058f40ee6 Working state stat UI 2023-07-18 00:36:28 -04:00
breathingmanually
f8e2730fd6 Fix parameters not substituted when editing first message 2023-07-18 00:57:17 -03:00
BlipRanger
b1f1fa8a26 Change the way we count non-user msgs 2023-07-17 19:32:21 -04:00
XXpE3
751894976e Added more Chinese translations 2023-07-18 00:58:37 +08:00
Cohee
3af4598fc9 Renamable backgrounds 2023-07-17 14:54:40 +03:00
XXpE3
ff92f0dbbf Increase some Chinese translation 2023-07-17 18:37:10 +08:00
XXpE3
41cf0c023f Revised some existing Chinese translations. 2023-07-17 18:22:32 +08:00
Cohee
2e2ad6589e Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-17 11:11:36 +03:00
Cohee
393d7c496d Don't lose original file name when uploading backgrounds.
+bonus lint fix for importing JSONs
2023-07-17 11:11:26 +03:00
RossAscends
d50c44f747 testing out no borders on zoomed avatars 2023-07-17 17:05:45 +09:00
RossAscends
4324bc239b Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-17 16:51:44 +09:00
RossAscends
0c130ecc53 add untranslated items to zh-cn/ja-jp objects 2023-07-17 16:51:42 +09:00
Cohee
28d4dfd718 Merge pull request #725 from bdashore3/dev 2023-07-17 09:10:53 +03:00
kingbri
0280bfa1bb Script: Don't save character on chat creation
There's no need to save a character when a new chat is created.
The main reason for this commit is that after creating a new chat
with metadata, it immediately gets cleared after a few seconds.
This may be a race condition, but there's also no need for this
function call in the first place.

Fixes: Author's note not injecting on first message when new
chat is spawned.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-17 00:21:46 -04:00
Cohee
e58dbec3de Slash command to delete messages by name 2023-07-16 22:43:54 +03:00
Cohee
f77df227e7 Clearer message for OpenAI errors 2023-07-16 22:08:29 +03:00
BlipRanger
7b2cb3e042 Getter/setters, get/update, WIP frontend 2023-07-16 13:03:37 -04:00
RossAscends
732cea5cf1 /delchat - to delete the current chat 2023-07-17 00:49:33 +09:00
RossAscends
2bd64475da a few more movingUI preset handling fixes 2023-07-16 20:20:50 +09:00
RossAscends
c44cfabbcd gitignore skill issue 2023-07-16 19:49:22 +09:00
RossAscends
2ae2a953fd gitignore for movingui folder 2023-07-16 19:47:43 +09:00
RossAscends
a67d831433 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-16 19:47:14 +09:00
RossAscends
651774fe5e save/load movingUI Presets 2023-07-16 19:47:11 +09:00
Cohee
6018ea7288 Merge pull request #719 from YellowRoseCx/patch-1
Add timezone replacement tags
2023-07-16 12:50:32 +03:00
YellowRoseCx
0a99a0bb41 Add timezone replacement tags
Allows setting of various timezones for the {{time}} tag by including the UTC offset with it like {{time_UTC-4}} or {{time_UTC+3}}
2023-07-16 00:09:43 -05:00
BlipRanger
760a84d5ac Added one-shot stats injestion 2023-07-16 00:30:06 -04:00
BlipRanger
3adcfecb5c Kitchen sink state, will need to make a ton of changes 2023-07-15 16:04:26 -04:00
Cohee
7bfaa97ac7 Merge pull request #716 from dumpsters/dev
fix tryParseStreamingError
2023-07-15 17:17:05 +03:00
dumpsters
fa988f08fe fix tryParseStreamingError
response.statusText was never available
2023-07-14 23:03:11 -03:00
Cohee
36b8aa0b4d Message texts are not array 2023-07-15 00:04:07 +03:00
Cohee
44b235e368 Bump package version 2023-07-14 23:48:41 +03:00
Cohee
5d7ab41dc9 Regenerate package-lock 2023-07-14 23:47:38 +03:00
Cohee
5b98f2f329 #703 Don't use prompt bias on impersonation 2023-07-14 23:37:10 +03:00
Cohee
46bf29e86d #713 Random sorting order 2023-07-14 23:22:05 +03:00
Cohee
40dd845e51 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-14 23:11:53 +03:00
Cohee
0f3908216a #711 Fix excluded tag hiding the character block 2023-07-14 23:11:44 +03:00
Cohee
02966ff48f Merge pull request #714 from bdashore3/dev
World Info bugfix
2023-07-14 22:52:55 +03:00
Cohee
37de77b20d Fix OpenAI itemizer for characters with example dialogues 2023-07-14 22:52:17 +03:00
kingbri
1a8d8db102 World Info: Fix selective with legacy entries
Legacy entries do not have the selectiveOrder property within the
JSON object. Fix this by adding a check in secondary key mapping
to default to AND.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-14 15:50:58 -04:00
Cohee
f931932d31 Add slider for chat width #712 2023-07-14 22:37:33 +03:00
Cohee
8f96a74d1e #583 Add mirostat generation options for oobabooga + preset 2023-07-14 19:51:05 +03:00
Cohee
2ac77b21ae Merge pull request #710 from majick/poke-an-back-a-bit
Make AN not uber-z.  Make options uber-z.
2023-07-14 18:11:53 +03:00
Cohee
eb4adb5a6c Bouncy drawers fix 2023-07-14 18:10:59 +03:00
Cohee
76359283a2 ✂️ ➡️ 🗑️ 2023-07-14 17:48:19 +03:00
majick
6dc1a86021 Make AN not uber-z. Make options uber-z.
Hover interaction like the hamburger should probably have really
high Z.  AN should not have higher Z than the panel that's supposed to
own the left.
2023-07-14 07:47:48 -07:00
Cohee
d5c816ed2b Unsqueeze past chats on narrow phoney screens 2023-07-14 17:21:36 +03:00
Cohee
f5a25cad5b Clear chat metadata on clearing chat 2023-07-14 17:06:01 +03:00
Cohee
92fbba83dc Select proper tokenizer for OpenRouter 2023-07-14 16:30:40 +03:00
Cohee
07c78391e1 #708 Convert author's note to built-in function instead of extension 2023-07-14 16:10:39 +03:00
Cohee
8987534403 #709 Add extra type safety for token counting 2023-07-14 15:33:55 +03:00
Cohee
5812e34dcb Fix new chats with v2 imports 2023-07-14 13:12:46 +03:00
RossAscends
6f33cc6fea Merge pull request #706 from BlipRanger/patch-4
Quick patch for overzealous checking
2023-07-14 14:14:14 +09:00
BlipRanger
11982c30d3 Quick patch for overzealous checking 2023-07-14 01:12:13 -04:00
BlipRanger
3210dd29d3 Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into feature/stats 2023-07-13 23:34:46 -04:00
BlipRanger
8689703068 Fix bad merge 2023-07-13 23:30:59 -04:00
BlipRanger
9951837f1d Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into feature/stats 2023-07-13 23:29:36 -04:00
Cohee
5db9a7b5ba Migrate grid view to pure CSS 2023-07-13 23:00:30 +03:00
RossAscends
4bf8e2c49f fix charlist state on character deletion 2023-07-14 04:15:31 +09:00
Cohee
057ae5ce14 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-13 20:00:21 +03:00
Cohee
22108c5c9f Fix /cut command 2023-07-13 20:00:17 +03:00
RossAscends
101acd29da Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-14 01:46:26 +09:00
RossAscends
95700dbe3e desktop safari chat resize handhold. mind the gap 2023-07-14 01:46:23 +09:00
Cohee
02c4c7d1d0 Remove unused npm package 2023-07-13 19:40:59 +03:00
Cohee
94af882530 CSS grid view improvements 2023-07-13 19:35:00 +03:00
Cohee
933729d914 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-13 19:26:05 +03:00
Cohee
da43c1c87e #699 Delete character without losing chats 2023-07-13 19:26:01 +03:00
RossAscends
298952e591 character list grid display toggle 2023-07-14 01:16:32 +09:00
Cohee
51c6137f53 Update package lock 2023-07-13 16:58:53 +03:00
Cohee
ae7ad6dbf0 Merge branch 'feature/extensions' of https://github.com/BlipRanger/SillyTavern into dev 2023-07-13 16:49:52 +03:00
RossAscends
edfafe4e7c scroll for member list popout 2023-07-13 22:38:56 +09:00
RossAscends
184e662ab6 hide group member popout from mobile 2023-07-13 22:36:38 +09:00
RossAscends
18272be918 floating current group member list 2023-07-13 22:16:57 +09:00
Cohee
2c4efe5509 Enable logit bias for OpenRouter 2023-07-13 14:16:11 +03:00
Cohee
e08889a348 Fix sampling order not being applied when selecting a Kobold preset. 2023-07-13 10:50:42 +03:00
RossAscends
ff8c9546ad add /impersonate (aka /imp) 2023-07-13 16:12:49 +09:00
RossAscends
be91af30b8 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-13 15:45:14 +09:00
RossAscends
c91d32d273 fix movingUI 2023-07-13 15:45:12 +09:00
BlipRanger
ee6bfbf4cc Add simple-get to packages. 2023-07-13 01:30:37 -04:00
BlipRanger
2b8db6350e Fixed a stupid delete bug, reload on delete. 2023-07-13 01:12:57 -04:00
BlipRanger
35336b1646 Delete method almost complete 2023-07-13 00:59:16 -04:00
BlipRanger
07b42e0fb4 Documentation update 2023-07-13 00:03:23 -04:00
BlipRanger
eccae1056f Add clickable names to go to repos 2023-07-12 23:54:17 -04:00
BlipRanger
cc7c42232e Fetch first, then check status 2023-07-12 22:37:42 -04:00
BlipRanger
4fb65a9235 Code refactor to make this more readable 2023-07-12 22:37:24 -04:00
BlipRanger
75080394ac Style for greyed out checkboxes 2023-07-12 22:26:23 -04:00
BlipRanger
396aaaf6e9 Add update button and check for external extenisons 2023-07-12 22:26:01 -04:00
Cohee
cb37fbd827 Update context size hint 2023-07-12 23:48:15 +03:00
RossAscends
f513c54691 fix bg menu for <1000px screens 2023-07-13 05:05:00 +09:00
RossAscends
abdf1ac71e Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-13 03:54:26 +09:00
RossAscends
67195071c3 chat width convert to flat 50vw 2023-07-13 03:54:23 +09:00
Cohee
26b6d48a3d OpenRouter website model use option 2023-07-12 20:54:11 +03:00
Cohee
f9630acaf4 Allow to change supported OpenRouter parameters 2023-07-12 19:19:53 +03:00
Cohee
a20eff92f0 Format styles 2023-07-12 17:25:59 +03:00
Cohee
f1c5f26b86 Merge branch 'main' into dev 2023-07-12 17:25:30 +03:00
Cohee
dc788f6571 Update localization files 2023-07-12 17:19:34 +03:00
Cohee
abe57f7e9a Merge pull request #687 from BlipRanger/feature/backend
Backend endpoint for single attribute editing
2023-07-12 17:07:58 +03:00
Cohee
cb294983e7 Merge pull request #701 from 50h100a/api-tokenize
Added tokenizer option for Ooba-like APIs
2023-07-12 11:28:50 +03:00
Cohee
9bbf23e56f Merge pull request #695 from ThisIsPIRI/continue
Fix continue formatting
2023-07-12 11:28:15 +03:00
Cohee
4aeda77648 Merge pull request #697 from bdashore3/dev
Regex: Switch slash command hooks
2023-07-12 11:26:53 +03:00
50h100a
6b0e13e064 dammit 2023-07-12 04:26:37 -04:00
50h100a
49ae2cbad6 New tokenizer option.
If you're running an ooba-like api, you can use the token-count endpoint.
Exact and fast!
2023-07-12 04:18:55 -04:00
BlipRanger
27e3485127 Still working, added update and version get functions 2023-07-12 01:13:36 -04:00
BlipRanger
b41d0a08c7 Replace lines that you definitely already had... 2023-07-11 19:24:13 -04:00
BlipRanger
de3b39f825 Skip over if folder is missing 2023-07-11 19:14:14 -04:00
BlipRanger
2454963129 Cleanup functions 2023-07-11 19:09:06 -04:00
BlipRanger
f67013f7ed Ignore third party extensions 2023-07-11 18:28:18 -04:00
BlipRanger
53d45356a4 External extension import UI + backend 2023-07-11 18:24:04 -04:00
ThisIsPIRI
dedb913b67 Fix continue formatting 2023-07-12 06:57:05 +09:00
Cohee
4f11b38110 Add applyLocale() global function 2023-07-12 00:32:28 +03:00
Cohee
4a3e95d79f Remove System prefix from Claude prompts 2023-07-12 00:26:45 +03:00
Cohee
393fff6207 Fix double insertion of WI with Chat Completions 2023-07-12 00:26:29 +03:00
Cohee
c9cc8fcf18 Calculation fixes to prompt itemizer 2023-07-12 00:05:34 +03:00
Cohee
6b1965fcf4 #693 Format story string after WI insertion for instruct mode 2023-07-11 23:22:12 +03:00
BlipRanger
bb6ff352b3 External extension support start 2023-07-11 16:10:42 -04:00
Cohee
5660280c51 Uncap max Claude 2 context size 2023-07-11 22:28:33 +03:00
kingbri
bd7d4beab5 Regex: Add slash command input hook
Slash command output for sys and sendas commands were being formatted,
but add the ability for user placement to also apply to slash command
invocations.

Some slash commands will require an output hook, so add exclusions
inside the code itself.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-11 15:28:30 -04:00
BlipRanger
33918d3e05 Match with safety improvements from other branch. 2023-07-11 15:03:02 -04:00
Cohee
040380e0fb Merge pull request #692 from bdashore3/dev
Fixes more regex bugs
2023-07-11 21:08:43 +03:00
Cohee
345992bb86 #538 More Poe unchunked bots 2023-07-11 20:59:56 +03:00
Cohee
12908baaf9 Add Claude 2.0 models. Update Claude streaming 2023-07-11 19:19:17 +03:00
kingbri
f253286981 Regex: Fix markdown formatting bug
The regex would still run even if markdown formatting is disabled,
but a placement is selected. Fix that by adding an extra check
in the loop.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-11 12:10:59 -04:00
Cohee
0fc10e8f7d Add error handing to OpenAI bias calculation 2023-07-11 17:06:40 +03:00
Cohee
c53e496687 Split OpenRouter and Window AI sources 2023-07-11 15:46:41 +03:00
Cohee
6c1e4c429b Merge pull request #690 from 50h100a/bootleg-i18n
Add i18n attribute-keying syntax to this very-much-not i18n loc code.
2023-07-11 11:56:12 +03:00
Cohee
f3a3613ac2 Merge pull request #691 from 50h100a/chroma-dedupe 2023-07-11 10:20:47 +03:00
50h100a
2387ff54c0 Add i18n attribute-keying syntax to this very-much-not i18n loc code. 2023-07-11 03:15:30 -04:00
50h100a
90c05988e1 Deduplicate entries prior to injection.
Also don't inject if there's no entries.
2023-07-11 03:01:14 -04:00
Cohee
8872492fcd Merge pull request #686 from bdashore3/dev 2023-07-11 09:39:34 +03:00
Cohee
7ee7e7b32a Merge pull request #685 from BlipRanger/feature/tags 2023-07-11 09:38:27 +03:00
BlipRanger
435a428587 Docstring and improvements. 2023-07-10 23:38:01 -04:00
kingbri
1f1af8e631 Expressions: Fix fade transitions for groups
See previous commit. Same absolute positioning applies with group
mode sprites.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-10 23:23:16 -04:00
kingbri
e5fab05309 Expressions: Fix sprite fade on mobile
Absolute positioning was causing an issue on both mobile and PC in
terms of expression image sizing. Dynamically set image width and
height along with fixing absolute position anchors.

This is not a fix for groups.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-10 23:23:15 -04:00
BlipRanger
bd2ca40452 WIP way to edit a char 2023-07-10 20:16:23 -04:00
BlipRanger
f33dd638b3 Show name when tags are imported 2023-07-10 20:03:11 -04:00
Cohee
9ebb1cfe90 #652 Add custom stop strings 2023-07-11 00:24:09 +03:00
Cohee
5c6c7fd3ca #612 SD manual prompt refine mode 2023-07-10 23:07:53 +03:00
Cohee
66a50f6afb Merge pull request #684 from BlipRanger/feature/tags
Fix glaring tagging issue and tag timing issue.
2023-07-10 22:52:58 +03:00
BlipRanger
a4b6cba596 Fix glaring tagging issue and timing issue. 2023-07-10 15:31:28 -04:00
Cohee
43a4d553f1 Credit for ko-KR locale 2023-07-10 19:31:18 +03:00
Cohee
eefbafdc08 #683 Improve i18n, add Korean translation by @doloroushyeonse 2023-07-10 19:29:50 +03:00
Cohee
f76db66e25 Modify quiet prompt sending to text completion models. 2023-07-10 18:13:11 +03:00
RossAscends
3ade04ed68 more poe errorlog fixes 2023-07-10 16:14:49 +09:00
RossAscends
210abe452c Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-10 16:05:12 +09:00
RossAscends
1562045cc8 fix freeSocket check 2023-07-10 16:05:07 +09:00
Cohee
72dcc43b37 Merge pull request #680 from majick/poe-get-bots-gql 2023-07-10 09:31:02 +03:00
Cohee
9ce7d2e31e Merge pull request #681 from BlipRanger/dev 2023-07-10 09:30:17 +03:00
RossAscends
a30754e1c2 freesocket check for poe errors 2023-07-10 13:50:53 +09:00
BlipRanger
d5c38077a4 Missed a spot 2023-07-09 21:22:29 -04:00
BlipRanger
9282b1942a Merge branch 'SillyTavern:dev' into dev 2023-07-09 20:16:37 -04:00
BlipRanger
35688c3eb3 Cleanup/Rename for generation info 2023-07-09 20:15:35 -04:00
BlipRanger
ad001ea263 Actually copy extra instead of referencing the same object 2023-07-09 19:57:42 -04:00
majick
467649b676 More Poe bots per pagination 2023-07-09 16:21:15 -07:00
BlipRanger
5f9fd017ea Unclear where this needs to be. 2023-07-09 16:50:16 -04:00
RossAscends
d16e673930 ahem.. 2023-07-10 05:27:11 +09:00
RossAscends
1a3f90d39c oof big 2023-07-10 05:25:38 +09:00
RossAscends
dcb7932d72 add 10k BG 2023-07-10 05:21:49 +09:00
RossAscends
797899c303 add credit for 10k BG 2023-07-10 05:20:01 +09:00
Cohee
d35ed21f48 Download all Poe bots. 2023-07-09 23:07:54 +03:00
Cohee
e883a37953 #678 Add /sysgen slash command 2023-07-09 21:16:48 +03:00
Cohee
3b56c89503 #676 Wrap Horde into try-catch 2023-07-09 21:03:01 +03:00
Cohee
c85b3253c5 Merge pull request #666 from BlipRanger/dev
[WIP] Record API + Model to message
2023-07-09 20:52:22 +03:00
RossAscends
42cd9a6e30 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-10 02:51:35 +09:00
RossAscends
039d8b5b8c Poe fix + API logging 2023-07-10 02:51:33 +09:00
BlipRanger
bdc4d213dd Remove reliance on settings dict 2023-07-09 13:38:09 -04:00
Cohee
2befcd8712 Merge pull request #672 from Jaezmien/viewport-fallback
Add viewport fallback to small viewport units.
2023-07-09 20:11:25 +03:00
BlipRanger
47e01f6b6f Merge branch 'SillyTavern:dev' into dev 2023-07-09 13:09:14 -04:00
Cohee
3548f46782 Merge pull request #673 from 50h100a/sc-tweaks 2023-07-09 12:31:23 +03:00
50h100a
497ca714a9 Tweak chroma memory retrieval so one big memory doesn't shut out smaller memories that might fit.
Fixed some log lines.
2023-07-09 04:31:34 -04:00
RossAscends
dae48e66d1 WIP japanese i18n 2023-07-09 16:50:55 +09:00
Jaezmien Naejara
f03df10972 Add viewport fallback to small viewport sizes 2023-07-09 14:02:40 +08:00
BlipRanger
a15b2892a7 Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into dev 2023-07-08 18:55:50 -04:00
BlipRanger
d25eca0f29 Cleanup from gen info stuff 2023-07-08 18:55:47 -04:00
BlipRanger
eaa14d2804 Merge branch 'SillyTavern:dev' into dev 2023-07-08 18:54:31 -04:00
BlipRanger
148966affe Fix some issues with displaying the gen info 2023-07-08 18:53:23 -04:00
BlipRanger
0f7dad7a5e I think that corrects the extras for swiping 2023-07-08 17:44:36 -04:00
BlipRanger
5128b75216 Fixed model acquisiton 2023-07-08 17:13:52 -04:00
Cohee
0c7c9cad16 Merge pull request #671 from bdashore3/dev
Regex: Make MD formatting granular
2023-07-08 21:14:14 +03:00
kingbri
3c3eed0996 Regex: Change how MD formatting works
Previously, there was a checkbox to select placement as MD display.
This was counterintuitive since some users believed MD display
enclosed the other placement options.

Now, add a universal switch to finely tune what parts of a chat should
be excluded with MD formatting. For example a regex with the option
enabled with AI output selected will only format replies from the
character.

This is an improvement since users can now choose what parts of a
chat to format rather than sticking with a global display specifier.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-08 14:10:15 -04:00
Cohee
474a9cb99e Add parameter randomizer plugin 2023-07-08 20:24:15 +03:00
Cohee
68551ae15c Merge pull request #663 from vbdev537/dev
Add new Replacement Macro
2023-07-08 12:22:49 +03:00
BlipRanger
f72b055bfb Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into dev 2023-07-08 01:17:59 -04:00
BlipRanger
5a0c702f53 Handle swipes for extra info 2023-07-08 01:17:55 -04:00
BlipRanger
f2e4eb1696 Capture api/model to msgs 2023-07-08 00:40:29 -04:00
Cohee
8e5fd7938c Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-08 04:12:20 +03:00
Cohee
46e1a25d83 Fix cross-tab file drag and drop 2023-07-08 04:12:17 +03:00
Cohee
ed0c185284 Merge pull request #665 from 50h100a/smartcontext
Smart Context - bug fixes
2023-07-08 03:30:06 +03:00
50h100a
5983e50d21 Query from *in context* messages, not every single message since the dawn of time... 2023-07-07 19:43:27 -04:00
50h100a
1be05fa514 Always run extension interceptors. 2023-07-07 19:41:57 -04:00
Cohee
7026f7051f Merge pull request #664 from 50h100a/extmgr-oops
Extension Manager bugfix
2023-07-08 02:35:57 +03:00
50h100a
cd7df3e0e7 Correct oversight from tidying names for PR... 2023-07-07 19:04:59 -04:00
vbd537
1852279723 Add new Replacement Macro
Through the impersonate function it is possible for the AI to create a text as if it were in the place of the user's character, but the text is randomly generated without the user being able to suggest what he wants to be created. By including this new macro, the user will be able to guide the impersonate generation.
2023-07-07 18:10:27 -03:00
RossAscends
5b40260170 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-08 06:00:37 +09:00
RossAscends
ae3da169f1 *turns back time on the Poe-clock* 2023-07-08 06:00:31 +09:00
Cohee
00e7d3c270 Merge branch 'main' into dev 2023-07-07 23:50:10 +03:00
Cohee
880472df18 Merge pull request #662 from BlueprintCoding/patch-1
Update silerotts.js - Fixed Caching issue in some browsers
2023-07-07 23:49:34 +03:00
Blueprint Coding
6a3282cbc4 Update silerotts.js - Fixed Caching issue in some browsers
Added this line to disable caching of file so new files are always played instead of browser cached versions.
2023-07-07 13:44:01 -06:00
Cohee
078947b73e Merge pull request #661 from 50h100a/color-coded-extension-states
Extension Manager visual update
2023-07-07 22:34:33 +03:00
50h100a
fe0d315bcb Added unicode icons for colorblind users 2023-07-07 14:50:57 -04:00
50h100a
fca365de6c Removed parenthetical from "Author's Note".
Didn't seem to be accurate any more, anyway?
2023-07-07 14:42:13 -04:00
50h100a
d6412d7b42 Compressed extension manager popup.
Color-coded extension status.
Indentations!
2023-07-07 14:41:38 -04:00
Cohee
30ccb72017 Merge pull request #656 from 50h100a/smartcontext-improvements
Smart Context extension improvements
2023-07-07 20:38:56 +03:00
50h100a
f3d8f4a7da Merge branch 'dev' of https://github.com/SillyTavern/SillyTavern into smartcontext-improvements 2023-07-07 13:03:00 -04:00
Cohee
57ee954ad5 Animate VN mode expression changes 2023-07-07 19:09:53 +03:00
RossAscends
0d5cdcd0b1 HR betwn WI Entries; fading for solo sprites 2023-07-07 23:12:31 +09:00
RossAscends
6a30858579 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-07 19:50:12 +09:00
RossAscends
be72b6f15f debug logging for poe connections 2023-07-07 19:50:09 +09:00
Cohee
bd74ea12ea Reformat plugin code 2023-07-07 12:37:07 +03:00
Cohee
2edc34db81 Merge branch 'main' into dev 2023-07-07 12:36:11 +03:00
Cohee
3162cf0e29 Merge pull request #653 from BlipRanger/feature/chroma-wi
Chroma Newline Chunking Option
2023-07-07 12:35:48 +03:00
Cohee
1bd9b8c1bf Fix variable usage 2023-07-07 12:34:28 +03:00
Cohee
243e89091a Bump package version 2023-07-07 12:26:49 +03:00
50h100a
b4830f2b67 Include Smart Context in prompt summary when possible. 2023-07-07 03:23:40 -04:00
50h100a
e5e275a827 'Smart Context' updates and fixes.
Added alternative strategy.
Logic fix to reliably load memories.
Option to query using entire current chatlog.
2023-07-07 03:22:27 -04:00
Cohee
f985b7eeb9 Merge pull request #649 from vbdev537/main
Temporary Poe Fix
2023-07-07 09:41:24 +03:00
Cohee
c879a93b75 Merge pull request #649 from vbdev537/main
Temporary Poe Fix
2023-07-07 09:38:37 +03:00
Cohee
cc98a0bd01 Merge pull request #639 from phiharri/confirm_delete 2023-07-07 09:08:51 +03:00
Cohee
8fcc074ced Merge pull request #651 from BlipRanger/feature/count 2023-07-07 09:07:50 +03:00
Cohee
c44310f38f Merge pull request #650 from bdashore3/dev 2023-07-07 09:07:06 +03:00
BlipRanger
49745b2b35 Cleanup 2023-07-07 00:26:58 -04:00
BlipRanger
f854609512 Option to split on newlines 2023-07-07 00:23:28 -04:00
BlipRanger
e595f83590 Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into feature/chroma-wi 2023-07-06 23:58:30 -04:00
BlipRanger
02fb1bc26f Revert to the not evals. 2023-07-06 23:06:44 -04:00
kingbri
82624ff55b Regex: fix multiple script bug
Multiple scripts were not running due to improper variable assingment.
For efficiency's sake, do not do a string comparison before returning
and instead do another variable assignment in the parent function.

Doing this reduces the length of regex hooks in the parent calls,
but also removes the need for unnecessary O(n) complexity of comparing
two string variables.

If there are errors, it would be advisable to add string comparison
and revert back to the old logic in parent function calls.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-06 22:32:40 -04:00
vbd537
08fd83ca5d Temporary Poe Fix
By adding "/Sage" or any other page name that exists to the end of the "home_url" variable, Poe's problem is solved and it can be used normally again
2023-07-06 21:00:55 -03:00
phiharri
3665947f54 Merge branch 'confirm_delete' of github.com:phiharri/SillyTavern into confirm_delete 2023-07-06 21:01:50 +01:00
phiharri
a2fc3ec115 set default value for confirm_message_delete 2023-07-06 20:56:08 +01:00
Cohee
f93fb78bc7 Don't append System narrator name to Chat completion messages. 2023-07-06 21:04:51 +03:00
Cohee
48e9332db9 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-06 20:42:01 +03:00
Cohee
afea5d48f1 Add {{idle_duration}} macro 2023-07-06 20:41:58 +03:00
Cohee
d6c3c6f26e Chub cope 2023-07-06 20:36:02 +03:00
Cohee
afcd2b497d Merge branch 'dev' into confirm_delete 2023-07-06 18:25:27 +03:00
Cohee
7d9c346d25 Better visibility filter on counter 2023-07-06 18:21:14 +03:00
Cohee
1acaea2a4c Merge pull request #642 from BlipRanger/feature/count
Feature/count
2023-07-06 18:13:54 +03:00
BlipRanger
bc52df493e Cleaned up code, relative font size 2023-07-06 11:07:38 -04:00
Cohee
11bbb6e8e3 Add purge to unsuccessful Poe auto-JB procedure 2023-07-06 13:23:18 +03:00
Cohee
85e82f854b (beta) Add davinci models to OpenAI 2023-07-06 13:18:33 +03:00
Cohee
b6ac73631f #640 Fix group candidates filtering 2023-07-06 12:36:16 +03:00
Cohee
35390c07ef #640 Fix group candidates filtering 2023-07-06 12:35:03 +03:00
Cohee
87f436fe44 Merge pull request #641 from BlipRanger/dev 2023-07-06 08:26:08 +03:00
Cohee
4740e872cd Merge pull request #638 from bdashore3/dev 2023-07-06 08:25:20 +03:00
kingbri
fb69397ac1 Regex: Add overlay replacement strategy
As opposed to making the match variable include the entire regex
match, overlay the replacement string over the regex match and splice
out whatever's already in the replacement string from the regex match.

This new strategy helps save time when editing messages since match
prefix and suffix phrases have a lower chance of being repeated on
every edit. The overlay strategy also preserves uniqueness if the user
decides to change something in the edited text.

However, overlay can cause issues especially with punctiation,
so the strategy isn't chosen by default when creating a new regex.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-06 00:49:26 -04:00
kingbri
3168ee536e Regex: Add an about section in editor
Adds a small helpful message in the editor and a link to regexr
for learning regex interactively.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-06 00:43:32 -04:00
kingbri
8212206d50 Regex: Fix markdown format bugs
If a regex cannot be parsed, silently return out and don't run the
script. May be a good idea to display a toast message saying the
script didn't run.

Also only reload the chat if a chat is actually loaded.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-06 00:43:32 -04:00
BlipRanger
bbe08ece84 Display total and dynamic character count 2023-07-06 00:42:04 -04:00
BlipRanger
c9db2f7c9c More descriptive error handling. 2023-07-05 23:33:32 -04:00
phiharri
1d640a2cbf Optional delete message confirmation 2023-07-06 01:43:57 +01:00
RossAscends
13ba5cec49 add help page for macros 2023-07-06 06:11:13 +09:00
Cohee
892824df1a Add Scale to UI texts 2023-07-05 23:50:33 +03:00
Cohee
2a8f3e7334 Unlocked context for Scale 2023-07-05 23:42:29 +03:00
Cohee
d7db7885e5 #24 Add Scale support 2023-07-05 23:34:40 +03:00
Cohee
4e8a2b8386 Add retry logic to OpenAI request handling 2023-07-05 21:43:33 +03:00
RossAscends
59f857262b seedrandom for {{random}} 2023-07-06 02:51:01 +09:00
RossAscends
a2a496a4c9 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-06 02:47:44 +09:00
RossAscends
88429baa48 add seedrandom library 2023-07-06 02:47:41 +09:00
Cohee
935a3d6c35 Clone WI entries before returning them to evaluator 2023-07-05 20:46:30 +03:00
RossAscends
3c64c46daf make constant WI entries substitute before insert 2023-07-06 02:00:59 +09:00
RossAscends
a53cee20d2 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-06 01:30:41 +09:00
RossAscends
cb741fd954 AND/NOT logic for selective WI 2023-07-06 01:30:37 +09:00
Cohee
f3ebea6ad8 #629 Random list select substitution 2023-07-05 17:59:53 +03:00
Cohee
af6d9d48e0 Merge pull request #630 from bdashore3/dev
Add regex engine and other fixes
2023-07-05 17:30:17 +03:00
Cohee
04b5d73a85 Merge pull request #634 from BlipRanger/feature/spoilers
Add the ability to avoid spoilers
2023-07-05 17:24:43 +03:00
Cohee
9ed05725c6 Hide "branch" button under advanced 2023-07-05 17:23:03 +03:00
Cohee
15a2a61615 Merge pull request #633 from mweldon/dev
Add retroactive bookmarking
2023-07-05 17:21:09 +03:00
Cohee
aed6e3413a Merge pull request #636 from SillyTavern/dev
1.8.2
2023-07-05 16:11:55 +03:00
Cohee
df6b87fa23 Bump package version 2023-07-05 15:18:52 +03:00
RossAscends
f6f4a5199b WI Entry label alignment fix 2023-07-05 21:10:56 +09:00
RossAscends
d59eaa4912 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-05 20:55:47 +09:00
RossAscends
26b55d47b4 WI Entry restyle; fix colorpicker loc for mobile 2023-07-05 20:55:39 +09:00
Cohee
5c39327450 Display Claude tokenizer in the UI if Claude model is used 2023-07-05 14:49:45 +03:00
Cohee
9c3823a616 #635 Fix sanitation of WI names 2023-07-05 13:40:40 +03:00
Cohee
46330f0558 Skill issue in A/N persona positioning 2023-07-05 13:27:44 +03:00
kingbri
afdab4c5b6 Regex: Add character name override
Sendas uses a different character's name for messages, so allow
the use of a character name override in the regex match function.
This overrides substituteParams to use a different value.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:35:52 -04:00
kingbri
b8f86d55da Regex: Add substitution to regex and undefined checks
Sometimes a user may want to substitute variables in the regex
itself rather than just matching those variables. This can be
optionally enabled in the editor.

In addition, try preventing crashes by checking for undefined
variables or null coalescing.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:50 -04:00
kingbri
fee801c2a4 Regex: Upgrade engine
If the extension is disabled, don't use any regex formatting. In
addition, wrap all foreach logic into its own function which
reduces the size of all regex injections.

This commit also removes the need for working around static imports
as UI is separate from the engine and is therefore imported at the
same time as other non-static extensions.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:50 -04:00
kingbri
fb02c00402 Extensions: Workaround loading static extensions
Some extensions are statically imported inside script.js, bypassing
the extension load method. The true method to solve this is using
dynamic imports and undefined checks, but implementing this is
extremely time-consuming.

For now, add the extension_first_load event which fires when
first load is about to start. This changes loading priority to
static -> offline -> online/API.

In addition, initialize the event source earlier since it's more
important than most of the other imports.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:50 -04:00
kingbri
7c0222a15b Regex: Migrate CSS styling
Universal styling has been moved to the main styles.css.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:50 -04:00
kingbri
e6eae0aad1 Regex: Fix script duplication on edit
Editing a script can bypass the unique naming system by just renaming
the script to another one. This change ensures that no two script
names can be the same by checking if the existing index and found indices
differ.

If something goes wrong, it would be better to use a filter and a
map and then check the index array length/includes. FindIndex
is used here for efficiency's sake since each array index is unique.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:50 -04:00
kingbri
0f8d07053e Regex: Don't wrap scriptTemplate elements
Fix some UI for flex element wrapping. Text overflow for a script
name is now truncated if it exceeds one line of text. Also fix
how extension settings are laid out to prevent unnecessary
flex resizing.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:50 -04:00
kingbri
b362dba726 Regex: Fix edit message hook
The only way to distinguish between a user and AI is if the is_user
property is changed.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:50 -04:00
kingbri
ee6a6603a3 Regex: Add trimStrings option
Sometimes the matched regex string needs to be pruned before
replacement. Add a method for the user to provide strings which
globally trims a regex match before any replacement is done.

Example without trim:
input - <Manami's thoughts: This is a thought>
regex - /<([^>]*)>/g
output - <Manami's thoughts: Manami's thoughts: This is a thought>

With trim:
input - <Manami's thoughts: This is a thought>
regex - /<([^>]*)>/g
trim - ["{{char}}'s thoughts: "]
output - <Manami's thoughts: This is a thought>

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:50 -04:00
kingbri
ef7aa3941b Extensions: Add regex engine
Regex is a method that is commonly used to find and replace parts
of a string using a single pattern. Add support for using regex in
SillyTavern which allows users to dynamically change various aspects
of the chatting experience.

Users are able to choose where a given regex script should apply
(both invasive and non-invasive options!). Invasive options alter
chat history while non-invasive alters markdown display for the
entire chat.

A new variable called {{match}} is added in regex scripts which
substitutes in the found match from the original find regex script.

There is a lot more that can be added to this extension, but for now,
this is enough.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:49 -04:00
kingbri
6bc9535040 Popups: Allow substitution of primary button
This allows for more flexible popups with options rather than
implementing a brand new popup just to change button text.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-05 01:30:01 -04:00
BlipRanger
4e0cbdfbb3 Add the ability to avoid spoilers 2023-07-05 01:08:09 -04:00
Mike Weldon
7ceb936337 Fix bug with Save bookmark from menu 2023-07-04 18:35:05 -07:00
Mike Weldon
d3c3614147 Add retroactive bookmarking 2023-07-04 18:13:22 -07:00
Cohee
9a8e036ff9 Use floor rounding on chroma auto-calc 2023-07-05 01:25:43 +03:00
Cohee
0d858bdefb #591 Fix Chroma auto-adjust rounding N query to 0 2023-07-05 01:23:11 +03:00
Cohee
27ab509caf Split help command into pages 2023-07-05 01:06:24 +03:00
Cohee
093379dba9 Fix custom group avatar in hotswap bar 2023-07-05 00:35:08 +03:00
Cohee
872bbfad1a Slash command to quickly open a character by name 2023-07-05 00:15:12 +03:00
RossAscends
b8f3a7cbe0 fix code text color & default minimal light theme 2023-07-05 05:16:52 +09:00
RossAscends
deff2d24fb Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-05 04:45:57 +09:00
RossAscends
fde2a91d2a down the rabbit hole 2023-07-05 04:45:54 +09:00
Cohee
4ceb8cedef Merge pull request #626 from Teashrock/main
Added Stable Horde sampler "k_euler_a"
2023-07-04 21:44:35 +03:00
RossAscends
383a9f67a2 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-05 02:44:06 +09:00
RossAscends
8cee880486 hopeful fix for resize spam on mobile 2023-07-05 02:43:52 +09:00
Cohee
36149fffa1 Merge pull request #631 from BlipRanger/BlipRanger-patch-1
Blip ranger patch 1
2023-07-04 20:34:37 +03:00
BlipRanger
80ac13ef20 Rare race condition patch 2023-07-04 12:26:21 -04:00
RossAscends
b994dbb2d1 dont punish rampant zoomers too much 2023-07-05 00:41:39 +09:00
RossAscends
83d954246f anti-Tav tactics (MovingUI resets on page zoom) 2023-07-05 00:16:36 +09:00
RossAscends
368f3ea968 minor skill issue *obliterated by Dalamud* 2023-07-04 23:10:08 +09:00
RossAscends
19502492c6 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-04 23:00:13 +09:00
RossAscends
3426f80656 Impervious MovingUI 2023-07-04 23:00:10 +09:00
Cohee
6770ccbe91 Fix Chub embedded lorebooks import 2023-07-04 14:47:48 +03:00
Cohee
44a38f8588 #628 Fix form properties 2023-07-04 14:16:14 +03:00
Cohee
823dd8c47c Merge branch 'main' into dev 2023-07-04 12:06:25 +03:00
Cohee
c922f17f09 Fix main_api default value 2023-07-04 11:49:46 +03:00
Cohee
8ad431bea6 Fix waifu mode setting migration 2023-07-04 11:46:53 +03:00
Cohee
dbb18ac895 Bump package version 2023-07-04 11:42:01 +03:00
Cohee
856b835172 Fix migration of settings.json 2023-07-04 11:41:15 +03:00
Cohee
37000963d9 Update Coherent Creativity.settings 2023-07-04 10:03:51 +03:00
Cohee
6ddd804749 Merge pull request #627 from alicat22/SillyTavern 2023-07-04 09:36:14 +03:00
cass02
2130338c1d Preset Cleanup - Sampling Order Update / Preset Name Update
Removed the parameter size from many of the presets, as these can work well with many parameter sizes. Removed "Prompt Arena" from the ooba presets, as these are new defaults. Changed sampling order back to the originals. Rep Pen should should listed first, as this was how it was done originally, as well. Also cleaned up and removed the unused parameters.
2023-07-03 16:45:11 -06:00
BlipRanger
e9ce2853cc Allow split on newlines (wip) 2023-07-03 17:48:53 -04:00
RossAscends
b20f371a42 add help link on Persona panel 2023-07-04 06:28:46 +09:00
Teashrock
de425d97dd Added sampler "k_euler_a" 2023-07-03 22:41:28 +03:00
Cohee
d6fd5455e6 Merge pull request #625 from SillyTavern/dev
Dev
2023-07-03 19:23:26 +03:00
Cohee
f3c9f57cb9 Merge branch 'main' into dev 2023-07-03 19:22:44 +03:00
Cohee
3fcf232537 Bump package version 2023-07-03 19:19:22 +03:00
Cohee
6be18e4212 Fix Poe client 2023-07-03 19:18:42 +03:00
Cohee
9e3c55805f Better chat completion continue 2023-07-03 18:22:12 +03:00
Cohee
9ab7265053 Touch chat window to cancel auto scroll on mobile 2023-07-03 18:17:10 +03:00
Cohee
25e3005de9 Unlocked context warning should be unclickable 2023-07-03 13:51:05 +03:00
Cohee
2b8f5d14e9 Don't stack suggested replies on Poe with continue. 2023-07-03 13:49:26 +03:00
Cohee
13deac2527 Don't insert a newline on empty WI 2023-07-03 11:34:15 +03:00
RossAscends
d566be077d Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-07-03 13:20:14 +09:00
RossAscends
7fe2ea31b9 better /api explainer text 2023-07-03 13:20:12 +09:00
Cohee
d153488690 More continue copium 2023-07-03 03:45:13 +03:00
Cohee
a61a8f9495 More safeties for swipes 2023-07-03 01:53:19 +03:00
Cohee
a904260614 Fix old message left swipe 2023-07-03 01:42:40 +03:00
Cohee
5e24beef58 Merge pull request #613 from BlipRanger/feature/swipe_info
Feature/swipe info
2023-07-03 01:36:16 +03:00
Cohee
47e4d5925b Merge pull request #618 from 50h100a/kobold-streaming-req
Cancel KoboldAI generation if streaming option conflicts.
2023-07-03 01:35:29 +03:00
Cohee
52b994a45b Merge pull request #619 from bdashore3/dev
Add UUID support
2023-07-03 01:32:32 +03:00
kingbri
ca2542d81a Utils: Add UUID v4 support
Unique IDs should use UUID as there's a higher prevention of overflow
when assigning them.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-02 18:31:02 -04:00
Cohee
1fe2e4032a Fix JSON data shift on newly created characters 2023-07-03 01:14:13 +03:00
Cohee
84cfe1c706 Evenize margins in document style 2023-07-03 00:53:47 +03:00
50h100a
4afd616099 kAI streamin mismatch Warning -> Error 2023-07-02 17:19:53 -04:00
50h100a
44bf31e602 Block generation if streaming option conflicts. 2023-07-02 17:04:21 -04:00
Cohee
6d33e44519 Fix "continue" as a slash command 2023-07-02 23:59:33 +03:00
Cohee
16e8c7a3c8 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-07-02 23:47:35 +03:00
Cohee
0c3f3f952d Toggle for space trimming 2023-07-02 23:47:33 +03:00
RossAscends
bef7d1492b fix single doc mode height for smol last mes 2023-07-03 05:31:52 +09:00
Cohee
6e15f7474f Fix obliteration of quick reply slots on input 2023-07-02 23:09:32 +03:00
Cohee
7a33042ea9 Add slash commands for chat styles and continue 2023-07-02 22:40:38 +03:00
Cohee
2e80de230e Fix Quick reply skill issue 2023-07-02 22:18:11 +03:00
Cohee
225bd5aa0a Update Poe impersonate prompt 2023-07-02 21:39:41 +03:00
Cohee
b14a85a96b Lower PaLM max context size 2023-07-02 21:37:44 +03:00
Cohee
febef5dfba Customizable number of quick reply slots 2023-07-02 21:37:14 +03:00
Cohee
9aab388531 Move continue option to power user section 2023-07-02 20:27:19 +03:00
Cohee
549fb19676 continue copium for Poe 2023-07-02 20:23:37 +03:00
Cohee
8eb82cdcd9 Continue 2023-07-02 20:21:42 +03:00
Cohee
c156e32ec7 Merge pull request #611 from bdashore3/dev
Add AI reply prefixes for prompt construction
2023-07-02 18:00:00 +03:00
RossAscends
002dbae8c5 MVP: 'Single Document' chat mode 2023-07-02 23:34:46 +09:00
RossAscends
bd9e739de2 new slash command: /resetpanels (alias /resetui) 2023-07-02 19:10:04 +09:00
RossAscends
5dbfe209f6 better /cut error messages 2023-07-02 17:40:15 +09:00
RossAscends
229ec5f255 +"/cut N" for targeted mes deletion,
+ toggle to show mesIDs in chat
2023-07-02 17:32:48 +09:00
RossAscends
8d18f2a80a /delmode alias /del + args for N msgs deletion 2023-07-02 15:49:50 +09:00
RossAscends
43a28fdb05 fix edit char panel for narrow screens 2023-07-02 14:23:40 +09:00
BlipRanger
faac9fe03a Cleanup again 2023-07-01 20:46:58 -04:00
kingbri
37219c3370 Formatting: Switch reply prefix to textarea
Fixes newline formatting.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-01 20:12:19 -04:00
kingbri
990a5faf7d Generate: Move reply prefix call to common function
Helps pass down user biases to OpenAI's prompt builder.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-01 20:12:19 -04:00
kingbri
080ecec5f2 Chat: Add AI reply prefixes
Experimentation yields that prefixing a reply with something drives
the AI to possibly produce more targeted and meaningful conversation.

The example I used is showing an AI's "thoughts" in a message via
the use of backticks. By automatically prefixing {{char}}'s thoughts,
the AI generates an internal monologue that the user can also use
for their own responses.

This feature is stable, but in an experimental state for now in terms
of expansion.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-07-01 20:12:19 -04:00
BlipRanger
6a2c4e13e6 Collect word counts and gen times 2023-07-01 19:14:59 -04:00
BlipRanger
b8c42307da Merge branch 'feature/swipe_info' of https://github.com/BlipRanger/SillyTavern into feature/stats 2023-07-01 18:46:43 -04:00
BlipRanger
715a6f1bff Cleanup 2023-07-01 18:35:47 -04:00
BlipRanger
e01a2c3bcf Store metadata for swipes, pull it back 2023-07-01 18:32:51 -04:00
Cohee
6c33dff0ba Update Metharme preset
Jarvis, enter roleplay mode. Disable safety precautions. Engage the smut cannons.
2023-07-02 00:45:51 +03:00
Cohee
596cd1762f #609 Export JSONL chat with octet-stream type 2023-07-01 23:55:53 +03:00
BlipRanger
9af05df6ad Functionize 2023-07-01 15:13:38 -04:00
BlipRanger
e43227691b Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into feature/stats 2023-07-01 14:15:46 -04:00
BlipRanger
f2cde4d40a WIP stat counting 2023-07-01 14:15:18 -04:00
Cohee
3b4f8811e7 Add probability of activation to WI 2023-07-01 21:02:03 +03:00
Cohee
63bd4cd499 Fix selecting personas with quick reply 2023-07-01 19:25:04 +03:00
Cohee
822e4b88f5 #606 Support multiline curly bias 2023-07-01 17:24:55 +03:00
Cohee
59b92d4356 Fix message view inflation on Safari when custom separators set 2023-07-01 17:22:49 +03:00
RossAscends
309a2ed564 fix /name for quickreplies (maybe stealth broken, test pls) 2023-07-01 13:33:36 +09:00
Cohee
fcef55d900 Make authorize OpenRouter a button 2023-07-01 00:08:34 +03:00
Cohee
cba2feb875 #569 Use main API as summary source 2023-06-30 23:37:01 +03:00
Cohee
fe8db4ded8 #605 JB prompt override for Poe. 2023-06-30 19:32:07 +03:00
Cohee
8cda073d00 Fix sticky bias 2023-06-30 18:38:15 +03:00
Cohee
c134aed9f5 Fix budget cutting in WI 2023-06-30 17:42:33 +03:00
Cohee
32441aa33e [chore] Copy-paste example id fix 2023-06-30 12:11:38 +03:00
Cohee
6be7d5704e Add OpenRouter OAuth flow 2023-06-30 12:01:49 +03:00
Cohee
1d2dc19359 #600 Add gpt-4-32k to OpenRouter selection 2023-06-30 11:44:23 +03:00
Cohee
dd028a9564 Merge pull request #602 from bdashore3/dev
Add persistence to tag exclusions
2023-06-30 11:36:10 +03:00
RossAscends
e6761f7293 Zoomed Avatars back to reg. mobile 🦀 2023-06-30 12:59:40 +09:00
kingbri
8547f362c5 Tags: Persist exclusions
If a tag is excluded, keep it excluded even on a page refresh.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-29 23:15:07 -04:00
Cohee
8251d15455 Update readme.md 2023-06-30 00:55:12 +03:00
Cohee
27c780c18b Update readme.md 2023-06-30 00:52:48 +03:00
Cohee
3353fe572c [chore] HTML formatting 2023-06-30 00:45:17 +03:00
Cohee
e2bbc7fbcf Infer model settings from Window extension settings 2023-06-30 00:36:39 +03:00
Cohee
f532192726 Add direct OpenRouter connection and PaLM models to Window selection 2023-06-30 00:32:52 +03:00
RossAscends
757e9b672a dont make RecoveredRuins abide by /r9k/ rules 2023-06-30 02:30:28 +09:00
Cohee
0bfa9f0e29 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-29 20:27:14 +03:00
Cohee
0da4bce378 Use select2 for character lore selector 2023-06-29 20:27:08 +03:00
RossAscends
16915ae6a5 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-30 02:19:48 +09:00
RossAscends
ad9599c2fc WI selector style tweak + new KAI preset option 2023-06-30 02:19:46 +09:00
Cohee
8687932896 Customizable samplers order for KoboldAI 2023-06-29 20:15:48 +03:00
Cohee
10a5836893 Merge branch 'main' of https://github.com/SillyLossy/TavernAI 2023-06-29 18:34:03 +03:00
Cohee
f75930a75d Fix Novel tablet tier context size 2023-06-29 18:33:56 +03:00
Cohee
d813ec4ef3 Fix Novel tablet tier context size 2023-06-29 18:32:57 +03:00
Cohee
89f905f0e2 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-29 18:22:19 +03:00
Cohee
5af6874b5f Restyle Global WI selector 2023-06-29 18:22:14 +03:00
Cohee
60586e7720 Merge pull request #597 from BlipRanger/feature/tags
Case-insensitive tag importing.
2023-06-29 17:11:30 +03:00
BlipRanger
4d3677dc5d Case-insensitive tag importing. 2023-06-29 09:54:21 -04:00
RossAscends
c6f1ec696a debug log to server window on poe API misread 2023-06-29 21:21:54 +09:00
RossAscends
9f5bd9d728 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-29 20:38:03 +09:00
RossAscends
466bcd8833 attempt fix defaultbot detection 2023-06-29 20:38:01 +09:00
RossAscends
05fd6d4a6c attempt fix defaultbot detection 2023-06-29 20:37:41 +09:00
Cohee
5d1edf7456 #588 Fix System TTS promise never resolving 2023-06-29 13:01:38 +03:00
Cohee
b9a067b79f #588 Fix System TTS promise never resolving 2023-06-29 13:00:15 +03:00
Cohee
6981151c8f Display existing tags in import tags popup 2023-06-29 12:46:45 +03:00
Cohee
650e7b0588 Merge pull request #590 from As4shi/dev
Filter generic creator's note
2023-06-29 12:36:36 +03:00
Cohee
e9466916da Fix tags import after merge 2023-06-29 12:27:23 +03:00
Cohee
bc7d7ee3ff Merge pull request #589 from BlipRanger/feature/tags
Tag, Author, Author Notes Import Support
2023-06-29 12:24:18 +03:00
Cohee
2bbc40a796 Bump package version 2023-06-29 12:20:00 +03:00
RossAscends
0c55d36a2b sync dev poe fix with main 2023-06-29 17:06:17 +09:00
RossAscends
fcc6448d7a improve Poe futureproofing 2023-06-29 16:42:59 +09:00
RossAscends
215e34bb52 WIP futureproofing strategy against PoeAPI changes 2023-06-29 15:40:04 +09:00
RossAscends
29e0a8335b smart detection of data vs payload on poe api 2023-06-29 14:10:30 +09:00
RossAscends
5ab4179920 no poe console spam 2023-06-29 14:10:16 +09:00
RossAscends
ebb93451b2 smart detection of poe data vs payload API 2023-06-29 14:08:29 +09:00
RossAscends
084d17dc19 revert poe changes. data>>payload 2023-06-29 12:13:28 +09:00
RossAscends
2722813efb poe api fakeout, reverting data to payload. 2023-06-29 12:11:41 +09:00
Cohee
e81b867676 Merge branch 'main' into dev 2023-06-29 01:25:52 +03:00
Cohee
2dabcc28a5 Merge pull request #594 from MDMCK10/dev
Fix Poe issues
2023-06-29 01:10:13 +03:00
Cohee
3b99f7839b Bump package version 2023-06-29 01:10:04 +03:00
Cohee
7c6c2ee8b6 Fix Poe 2023-06-29 01:09:34 +03:00
MDMCK10
52a2cee73c Fix Poe issues 2023-06-29 00:03:10 +02:00
Cohee1207
991d437749 Fix skill issue in avatar uploading 2023-06-28 23:23:37 +03:00
Cohee1207
8168a9205a Merge branch 'dev' of http://github.com/cohee1207/SillyTavern into dev 2023-06-28 23:21:17 +03:00
Cohee
332648973f Merge branch 'dev' into feature/tags 2023-06-28 22:57:53 +03:00
Cohee
fc8553a140 Remove embedded lorebook when unselecting it in UI 2023-06-28 20:35:25 +03:00
BlipRanger
048d65c1e1 Anti-troll filter 2023-06-28 12:18:58 -04:00
Cohee
322ab9b47a Fix Chub import by URL 2023-06-28 19:17:16 +03:00
BlipRanger
0f0647c6e4 Prompt when tags are being imported 2023-06-28 12:12:56 -04:00
Cohee
674a15b842 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-28 18:26:26 +03:00
Cohee
d0ab763d2e [Feature Request] Filter via Tags on Group Chat's "Add Members" Search Box #388 2023-06-28 18:26:23 +03:00
RossAscends
2f8b624578 cleanup Adv Def's creator/overrides blocks 2023-06-28 23:45:41 +09:00
RossAscends
e4e8cdfca5 Adv Char Defs panel gets correct BG color 2023-06-28 22:55:35 +09:00
RossAscends
df35fb0775 less movingUI logspam 2023-06-28 22:47:33 +09:00
Cohee
fca732c933 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-28 16:39:40 +03:00
Cohee
c18008725d Fix group VN mode 2023-06-28 16:39:37 +03:00
RossAscends
38931e7a2f Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-28 22:31:49 +09:00
RossAscends
667cbf6f0f optimize Reset Panels, saveSettings emit onSuccess 2023-06-28 22:31:47 +09:00
Cohee
931fffaa5c Fix chat.comp models not saving on Safari 2023-06-28 16:16:49 +03:00
Cohee1207
f06ca28bbf Reduce console spam on expressions 2023-06-28 15:55:53 +03:00
BlipRanger
ad11ec8d00 Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into feature/tags 2023-06-28 08:55:40 -04:00
Cohee1207
a1eb2b794e Rearrange Horde blocks 2023-06-28 15:48:12 +03:00
RossAscends
4ad328029e Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-28 20:40:31 +09:00
RossAscends
d66542e88e fix: MovingUI breaking, typos, WI selector scroll 2023-06-28 20:40:29 +09:00
Cohee
893d1fa9e4 Merge branch 'dev' into dev 2023-06-28 12:02:34 +03:00
Cohee
4a9d9b69e9 Fix random chat slash breaking in groups 2023-06-28 11:19:50 +03:00
Cohee
ebf51f3a17 Fix select2 selection remove style 2023-06-28 11:15:38 +03:00
Cohee
7bec130bf7 Fix focused select border 2023-06-28 11:06:57 +03:00
Cohee
914282faf0 Remove spammy logs 2023-06-28 11:02:54 +03:00
Cohee
1d8ecacd8b Update Horde documentation link 2023-06-28 11:01:27 +03:00
Cohee
a0814defff Fix select2 noblur background 2023-06-28 10:51:14 +03:00
As4shi
d410118cc4 Filter generic creator's note
Removes "Creator's notes go here." message when importing cards.
2023-06-28 04:47:01 -03:00
RossAscends
5084ae9f9a Merge pull request #587 from BlipRanger/feature/import
Import creator and creator notes/comments (if they exist)
2023-06-28 14:20:04 +09:00
RossAscends
93b1774135 Merge pull request #586 from bdashore3/dev
[IMPORTANT] Fix world info splice method
2023-06-28 14:08:32 +09:00
BlipRanger
0a5c226af6 Remove unencessary functions 2023-06-28 01:06:38 -04:00
RossAscends
2cde62f618 Merge pull request #585 from BlipRanger/feature/random
Add random chat slash command
2023-06-28 14:01:51 +09:00
BlipRanger
136ba40956 Fix the check for V1 vs V2, cleanup 2023-06-28 00:57:20 -04:00
RossAscends
7fe758d697 ( ) skill issue ( ) MovingUI works now. 2023-06-28 13:53:36 +09:00
BlipRanger
762684ffea Filter default tags (probably), update name 2023-06-28 00:43:45 -04:00
BlipRanger
2b5a028af4 Import tags from card correctly 2023-06-28 00:32:07 -04:00
BlipRanger
487b36a326 Merge branch 'feature/import' of https://github.com/BlipRanger/SillyTavern into feature/tags 2023-06-27 23:59:30 -04:00
BlipRanger
ea2c7973a9 Unmerge plus first try at importing card tags 2023-06-27 23:59:22 -04:00
BlipRanger
2d34b54874 Merge branch 'feature/autotagger' of https://github.com/BlipRanger/SillyTavern into feature/tags 2023-06-27 23:55:58 -04:00
BlipRanger
696f9083f3 Import tags and just save them to the card 2023-06-27 21:51:28 -04:00
BlipRanger
db08d4eab3 Import creator and creator notes/comments (if they exist) 2023-06-27 21:29:05 -04:00
kingbri
2f2f88dedd World Info: Fix array splice method
Character lore layers used array.splice() in the wrong way. Somehow
this passed my testing through sheer luck. Rewrite for using indicies
to splice and for more efficiency with iteration.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-27 21:04:04 -04:00
BlipRanger
a512e3bec0 Merge branch 'dev' of https://github.com/BlipRanger/SillyTavern into feature/random 2023-06-27 20:18:55 -04:00
BlipRanger
06f2c920f0 Start autotagger extension 2023-06-27 20:17:43 -04:00
BlipRanger
9903e85a66 Add random slash command 2023-06-27 20:03:49 -04:00
Cohee
9949d5695c Restyle Horde model selector 2023-06-28 02:09:33 +03:00
Cohee
515a0af1b4 Write settings backup on starting the server 2023-06-27 21:40:36 +03:00
Cohee
f5ba78be81 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-27 20:48:14 +03:00
Cohee
10e87dd5ca [WIP/Untested] DeepL translation API 2023-06-27 20:48:09 +03:00
RossAscends
5db69d1ce0 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-28 01:30:15 +09:00
RossAscends
a9009725ce hide unusables on mobile 2023-06-28 01:29:35 +09:00
Cohee
d59174da77 Add optional chaining 2023-06-27 19:22:42 +03:00
Cohee
679143967d Merge pull request #580 from lsaa/first-line-desc-cutoff
Limit the character list sysnopsis to the first line of Creator's Notes
2023-06-27 19:20:03 +03:00
Cohee
59e833b6cc Merge pull request #581 from bdashore3/dev
Tags: Fix mobile exclusions
2023-06-27 19:19:18 +03:00
kingbri
2e9bccf9e9 Tags: Fix mobile exclusions
Fixes mobile positioning issues and adds conditional directives.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-27 12:15:13 -04:00
RossAscends
54f472a750 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-28 00:58:36 +09:00
RossAscends
a0dbee6749 unlimited zoomed avatars + movingUI rewrite 2023-06-28 00:58:32 +09:00
Cohee
69fdb9090f Add Chub downloader for characters and lorebooks 2023-06-27 18:39:08 +03:00
lsaa
43e5849015 Only display the first line of Creator's Notes as description 2023-06-27 09:15:52 -03:00
Cohee
92775e459c Merge pull request #574 from 50h100a/show-avatar-names
Display avatar name in card list
2023-06-27 12:39:53 +03:00
Cohee
748bee74cb Make avatar URL display not default 2023-06-27 12:38:46 +03:00
Cohee
3cdec1cea3 Merge pull request #576 from bdashore3/dev
World Info: Fix lorebook loading error
2023-06-27 12:34:29 +03:00
RossAscends
76b7e24614 also reset AN panel loc/size 2023-06-27 13:22:39 +09:00
RossAscends
9737fda9ae persistent state for movingUI 2023-06-27 13:08:02 +09:00
50h100a
06f580ed29 Add power-user option to toggle card filenames.
Rephrased 'resize' option so It's Not Talking Like This.
2023-06-26 21:45:15 -04:00
50h100a
553a95fd39 Merge branch 'SillyTavern:main' into show-avatar-names 2023-06-26 21:33:24 -04:00
kingbri
3e30fb5d14 World Info: Fix lorebook loading error
charLore isn't always present, so make optional calls to it.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-26 20:19:21 -04:00
Cohee
847961861f Better VN mode autoscrolling 2023-06-27 00:57:16 +03:00
Cohee
59dba15a4f Unlock scrolling on streaming if scrolled with mouse wheel 2023-06-27 00:45:48 +03:00
50h100a
2aa0c5d707 Display avatar name in card list 2023-06-26 17:33:10 -04:00
Cohee
976a8fd65c Fix WI terms usage 2023-06-26 22:27:58 +03:00
Cohee
5798c98f41 Adjust texts for character lorebooks 2023-06-26 22:21:01 +03:00
Cohee
187a0925b0 Merge pull request #570 from bdashore3/dev
World Info: Add support for character layers and more fixes
2023-06-26 22:10:58 +03:00
kingbri
45047fc6b2 World Info: Fix entries being improperly appended
Entries were being added to the prompt in an inconsistent way. WI
before and after character were using newline formatting while AN
was using array joins. This caused some issues with insertion order
in the prompt.

Fix this by making each injection use an array and unshift elements
into them. Then, join them into a string that preserves insertion
order.

The reason why unshift is used is because higher insertion orders
translate to a higher priority during scanning. This prevents the
need to reverse arrays which is a more costly function depending
on how many entries are in them.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-26 14:32:24 -04:00
kingbri
9d5af39682 World Info: Add rename and delete hooks to char layers
If a world info is renamed or deleted, update that in the character
lore section of settings as well.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-26 14:32:24 -04:00
kingbri
b6fbe41f93 World Info: Add support for character layering
Some characters have different cards depending on what the user wants
from the character. However, maintaining multiple lorebooks for different
personas of the same character can be difficult. In addition, there
is redundancy, overlap, and possiblities to miss information when
creating separate lorebooks with the same base info.

Therefore, add a "DLC"/layering system of sorts for characters.
This works the same way as multi-global world info where character
lorebooks added as needed. The only catch is that a base character
book must be tied to a card before selecting any extra info.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-26 14:32:24 -04:00
Cohee
47a5c9e9f6 Remove insta-faving on import 2023-06-26 17:20:59 +03:00
Cohee
c9fa19e8dd Un-egg group avatars round 2023-06-26 17:00:35 +03:00
Cohee
89a1378397 Fix sprite folder for Risu sprites. Don't overwrite existing files. 2023-06-26 17:00:13 +03:00
Cohee
1739af3ef6 Cleanup Risu import 2023-06-26 15:26:29 +03:00
Cohee
c1b9a30087 Import embedded Risu sprites 2023-06-26 15:19:35 +03:00
Cohee
ca8b06f4cb Fix bold italics 2023-06-26 13:42:58 +03:00
Cohee
68f967ea78 Add Claude tokenizer 2023-06-26 13:36:56 +03:00
Cohee
7354003db1 Fix typo 2023-06-26 11:51:11 +03:00
RossAscends
b2e541c6d9 char edit panel grid fix 2023-06-26 07:08:46 +09:00
Cohee
7321b37799 Un-egg round personas 2023-06-25 23:55:16 +03:00
Cohee
9532ad4e5a Enable selection in WI editor 2023-06-25 23:24:22 +03:00
Cohee
7118b430d5 Only display a warning if card tokens is more than 50% of real context size 2023-06-25 23:17:05 +03:00
Cohee
961139304d Unify group/solo avatar display 2023-06-25 23:05:11 +03:00
Cohee
efe4a974be Less gaps == more space for descriptions 2023-06-25 22:56:11 +03:00
Cohee
92127615e5 Tighter display of character top bar. Return some of the buttons 2023-06-25 22:44:46 +03:00
RossAscends
deb2efc16e realign character panel 2023-06-26 04:17:06 +09:00
Cohee
9bbaa85a3b Clarified persona deletion message 2023-06-25 20:13:16 +03:00
Cohee
04cfedea7c Chroma: Remove dupe label 2023-06-25 19:56:15 +03:00
Cohee
16fd92b1a3 Merge pull request #566 from BlipRanger/dev
First try at chromadb multichat
2023-06-25 19:36:19 +03:00
Cohee
7984e3b818 Add contextual Character WI button 2023-06-25 18:40:13 +03:00
Cohee
da8beeb503 Force reload user avatar on upload 2023-06-25 17:21:18 +03:00
Cohee
612db28bcb Better name for backgrounds plugin 2023-06-25 17:06:20 +03:00
Cohee
506aeb2e40 Substitute params in persona descriptions. 2023-06-25 17:00:27 +03:00
Cohee
26ac519c55 User persona management block. Persona descriptions. Dummy personas. Change persona avatar 2023-06-25 16:46:23 +03:00
Cohee
bbec184d17 Reverse persona lock icon 2023-06-25 13:20:11 +03:00
Cohee
951e22ac8e Fix scrolling and width of global WI 2023-06-25 12:43:37 +03:00
RossAscends
861e0d017e fix CSS for new WI multiselector 2023-06-25 14:53:41 +09:00
RossAscends
f6526bbb4c Merge pull request #567 from bdashore3/dev
Add multiple global WI merging (and optimizations)
2023-06-25 14:33:54 +09:00
BlipRanger
d004a3141e Default bracket, make sure we have memories. 2023-06-25 01:03:47 -04:00
BlipRanger
bd74939a55 Add templating for custom injection 2023-06-25 01:01:47 -04:00
kingbri
c0286150ed World Info: Add optimizations and fixes
Use a switch instead of if/else chain, fix un-needed addition
when determining token counts, and remove newline spacing for AN
WI formatting.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-25 01:00:47 -04:00
kingbri
fc9c90c4ee World Info: Add global multi-selection/merging
Global world info always involved some kind of merging leading to
extremely large lorebook files that took a long time to import.

This commit adds the ability to select more than one world info file
and they will be merged together along with character world info.
In short, multiple worlds can be meshed together to further contribute
to context.

You can also use this for world "DLCs" of sorts. Let's say someone
else has more information to add regarding a world, but doesn't
want to use a large world file. The JSONs can now be merged.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-25 00:49:42 -04:00
BlipRanger
2836704c4e Add sort options, remove duplicate entires from custom. 2023-06-25 00:17:58 -04:00
BlipRanger
71201377ef Merge branch 'SillyTavern:dev' into dev 2023-06-24 20:43:42 -04:00
BlipRanger
9de7db8f2d Add custom chroma strat 2023-06-24 20:41:54 -04:00
Cohee
31057e1e81 Add custom avatars for groups 2023-06-25 02:57:07 +03:00
Cohee
66de4a1e09 Add positions for char A/N 2023-06-25 01:40:06 +03:00
Cohee
4cc3d335a8 Save A/N to metadata immediately 2023-06-25 01:08:38 +03:00
Cohee
09eea3c8cd Add caching layer to WI save/load 2023-06-24 23:57:44 +03:00
Cohee
747f7829fd Import Risu lorebooks 2023-06-24 23:34:36 +03:00
Cohee
ab90d6ec3d Save before exporting 2023-06-24 23:19:21 +03:00
BlipRanger
3ce14883b9 First try at chromadb multichat 2023-06-24 15:36:26 -04:00
Cohee
f360706227 Post-activation sorting of WI entries 2023-06-24 20:54:56 +03:00
galasal
ef9b7187dc improve performance when filling context 2023-06-24 15:17:19 +10:00
Cohee
869e02dd42 #561 [WIP] Fix chat file deletion 2023-06-23 23:19:23 +03:00
Cohee
e78abf9269 #557 Only add user name to chat completion name if it was sent as another persona in the same chat. 2023-06-23 23:05:41 +03:00
Cohee
23287597ee Fix onboarding text. 2023-06-23 22:54:35 +03:00
Cohee
9f0530f422 Export characters with world info embeds. 2023-06-23 22:50:16 +03:00
Cohee
275f187719 Don't animate changing avatar size on right panel 2023-06-23 21:49:59 +03:00
Cohee
97e1585152 Import Agnai memory book JSON 2023-06-23 21:43:14 +03:00
Cohee
8a2506d8a3 Merge pull request #559 from sifsera/dev 2023-06-23 19:45:59 +03:00
Cohee
a79bae5975 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-23 19:21:06 +03:00
Cohee
01b4e1dae3 Import Novel PNG lorebooks 2023-06-23 19:20:58 +03:00
sifsera
4fd714a1ee Add Prompt Arena presets from TextGenWebUi 2023-06-23 12:08:09 -04:00
RossAscends
84e44d7c0a Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-24 00:59:11 +09:00
RossAscends
fed47d7477 /api 2023-06-24 00:59:09 +09:00
Cohee
2302785242 #502 Import Novel Lorebooks (JSON-based) 2023-06-23 18:43:11 +03:00
Cohee
6cbfb56fff Merge pull request #558 from sifsera/dev
Add-epsilon-and-eta-settings-to-textgenwebui-parameters
2023-06-23 18:03:13 +03:00
sifsera
59c699c999 Add-epsilon-and-eta-settings-to-textgenwebui-parameters 2023-06-23 10:59:38 -04:00
RossAscends
1d4746b743 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-23 20:21:04 +09:00
RossAscends
82a09d2feb batched slash commands 2023-06-23 20:21:01 +09:00
Cohee
c873a6b04c Fix npm audit. 2023-06-23 13:53:37 +03:00
Cohee
e9f7ea16ce Fix semver audit. 2023-06-23 13:53:08 +03:00
Cohee
786ae619cb Merge pull request #554 from bdashore3/dev
Expand markdown exclusions
2023-06-23 13:46:02 +03:00
RossAscends
ad779129d3 /world to set/unset active world 2023-06-23 16:51:15 +09:00
kingbri
e7af6892fb Markdown: Add ability to exclude specific strings
A comma-separated list of markdown strings provided by the user can
be excluded as needed. This is combined with the set chat separator
to provide a seamless experience when chatting.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-22 21:10:19 -04:00
kingbri
fa9df8f22e Markdown: Fix dinkus formatter with codefences
Change how the formatter is applied to use an invisible null unicode
character instead of div tags and add a newline to preserve the DOM
tree so codeblocks and child elements aren't altered.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-22 17:58:57 -04:00
Cohee
1672824416 Spec v2: {{original}} macro for prompt overrides. 2023-06-22 23:24:22 +03:00
Cohee
c096a55697 Merge branch 'main' into dev 2023-06-22 20:51:10 +03:00
Cohee
d4332aa7ec No audit to npm install 2023-06-22 20:50:01 +03:00
Cohee
2f497cf25b Drag-sortable WI entries. 2023-06-22 20:11:29 +03:00
Cohee
7d472f00f7 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-22 18:11:55 +03:00
Cohee
1e5f789f59 Minor clarification to placeholder text. 2023-06-22 18:11:48 +03:00
RossAscends
1f14c3669d Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-22 22:21:24 +09:00
RossAscends
40e2af4c73 /dupe 2023-06-22 22:21:21 +09:00
Cohee
bd34cab6e8 #547 Display 3 lines of description in big avatars mode 2023-06-22 13:10:39 +03:00
Cohee
85876e9377 Revert old quote wrapping for code blocks 2023-06-22 12:47:05 +03:00
Cohee
e5f37ee073 Merge pull request #549 from 50h100a/codeblock-newline-fix
Codeblock newline fix for Firefox
2023-06-22 12:44:57 +03:00
Cohee
267db5166f Merge pull request #550 from v86861062/main
start.sh: Fixed the commands
2023-06-22 12:41:28 +03:00
v86861062
0e45450912 start.sh: Fixed the commands
Signed-off-by: v86861062 <v86861062@gmail.com>
2023-06-22 12:19:35 +08:00
50h100a
4dac2126bf Do not replace codeblock newlines with <br> tags. 2023-06-21 23:59:52 -04:00
Cohee
4230f3881d #547 Display Creator's Note in characters list 2023-06-21 21:12:46 +03:00
Cohee
408f83804d Move set avatar button to on-click on avatar 2023-06-21 20:22:54 +03:00
Cohee
4d299916be Convert and import v2 character book embeds 2023-06-21 18:50:34 +03:00
Cohee
4b8711c8f8 Minor spelling mistake 2023-06-21 14:55:49 +03:00
Cohee
8d6e6de200 [Feature Request] Make "Instruct i/o sequence macro replacing" optional SillyTavern/SillyTavern#546 2023-06-21 14:54:36 +03:00
Cohee
df4586811d Don't query OpenAI status if it's not a currently selected API on load 2023-06-21 12:50:43 +03:00
Cohee
012f0237db Don't change active WI selection on import 2023-06-21 12:23:14 +03:00
Cohee
23a6064a55 Merge pull request #545 from breathingmanually/comment-command 2023-06-21 10:02:45 +03:00
Cohee
a37922ad59 Merge pull request #544 from BlipRanger/patch-3 2023-06-21 09:57:44 +03:00
breathingmanually
2a235b7889 Add /comment -- adds a note/comment message not part of the chat 2023-06-21 02:22:20 -03:00
BlipRanger
e4a6bdb389 Update readme.md
Add BlipRanger
2023-06-20 20:33:46 -04:00
Cohee
4a29072e1c Import / export chat completion presets 2023-06-20 23:53:52 +03:00
Cohee
36d0244be4 Remove instruct mode extra newlines 2023-06-20 23:29:07 +03:00
Cohee
fda152cef0 Placeholders for import/export chat completion preset 2023-06-20 22:41:15 +03:00
Cohee
3723ae840f Use proportional WI budget. Add None option for WI editor. 2023-06-20 22:11:01 +03:00
Cohee
a513434b5f Fix cards hiding on returning to characters list when using search input 2023-06-20 19:41:06 +03:00
Cohee
ec05937dd4 #540 Save streaming flag to Chat Completion preset 2023-06-20 18:58:09 +03:00
Cohee
0ec9198ef5 Merge pull request #535 from bdashore3/dev
Fix WI2AN formatting + Add contributor
2023-06-20 18:43:00 +03:00
kingbri
64bba40c41 README: Add kingbri as a contributor
Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-20 11:37:40 -04:00
kingbri
350e2108e2 WI2AN: Fix formatting
Signed-off-by: kingbri <bdashore3@proton.me>
2023-06-20 11:30:29 -04:00
Cohee
5fa5edffba Merge pull request #539 from deedlitelf/main
Fix the i18n translation
2023-06-20 18:24:44 +03:00
Cohee
df184bd46a Split WI editor and global WI select 2023-06-20 17:52:40 +03:00
deedlitelf
f0d0f38c4f Update index.html 2023-06-20 21:11:51 +08:00
Cohee
2663a8370f (Internal refactor) Decouple world info editor from global WI selector 2023-06-20 13:47:34 +03:00
RossAscends
3b66310dd2 fix WI2AN insertions 2023-06-20 17:59:01 +09:00
Cohee
9c28126ccd #517 Export chats as JSONL 2023-06-19 22:29:09 +03:00
Cohee
fb97d95dae Use single format for chat timestamps 2023-06-19 22:05:20 +03:00
Cohee
2d6ed116e6 Clarify auto-adjust UI labels 2023-06-19 21:54:58 +03:00
RossAscends
114d756a68 better display for excluded tags 2023-06-20 01:45:11 +09:00
RossAscends
8c710a08a3 fix timestamps on SD gens 2023-06-20 01:08:58 +09:00
Cohee
c5c921b0d6 Restyle excluded tags 2023-06-19 17:42:25 +03:00
Cohee
3c68a4e2a0 Support new timestamp format in view past chats 2023-06-19 17:23:08 +03:00
Cohee
72488b5900 Merge pull request #523 from 50h100a/card-resize-fix
Card resize fix
2023-06-19 15:14:48 +03:00
Cohee
b970bde972 Merge pull request #525 from BlipRanger/dev
Prototype for Negative Filtering
2023-06-19 14:32:59 +03:00
Cohee
10c836fcbc Fix removing world link from character 2023-06-19 10:54:43 +03:00
RossAscends
d979dd263a fix height overflow on adv char defs 2023-06-19 15:55:37 +09:00
RossAscends
4c51b1ffe1 toggle for Timestamps on messages 2023-06-19 14:39:33 +09:00
RossAscends
0490ca25b0 char panel buttons into dropdown; sheld width fix 2023-06-19 13:23:26 +09:00
BlipRanger
5ce41342c0 Style change for excluded tags 2023-06-18 20:17:36 -04:00
BlipRanger
052089b3c0 First shot at filtering tags negatively
Needs some work, but proof of concept
2023-06-18 20:16:41 -04:00
Cohee
21bb5d7808 Fix WI button class toggle 2023-06-19 02:55:32 +03:00
Cohee
f51af31850 Fix duplicating entries if char and global WI are the same 2023-06-19 02:19:42 +03:00
Cohee
7e975e9df0 (WIP) Assign World Info to a character. [Out of spec] 2023-06-19 01:59:09 +03:00
hh_aa
56656b95cf Added "Never Resize Avatars" option.
Changed crop dialog to have "Accept"/"Cancel" buttons.
2023-06-18 17:09:10 -04:00
hh_aa
2d97b4bd0a Merge branch 'main' of https://github.com/50h100a/SillyTavern into main 2023-06-18 15:39:47 -04:00
Cohee
81d9cead5c Hide scenario override in char creation and group member peeking 2023-06-18 22:09:57 +03:00
Cohee
511f762e54 Auto-adjust values should not exceed max slider limits 2023-06-18 21:25:47 +03:00
Cohee
04a645141c Set scenario override for characters 2023-06-18 20:32:51 +03:00
Cohee
9ef8f0b069 More gradual Poe streaming. 2023-06-18 19:02:02 +03:00
Cohee
e12242f44f Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-18 18:33:59 +03:00
Cohee
976248b665 Fix char A/N in groups 2023-06-18 18:33:57 +03:00
RossAscends
84d9113ed3 new base themes 2023-06-18 23:58:08 +09:00
RossAscends
a43f99b492 new base themes 2023-06-18 23:57:30 +09:00
RossAscends
28ba84ea6f Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-18 23:56:59 +09:00
RossAscends
93876b8189 themes upgrade, user/bot messages get unique color 2023-06-18 23:56:56 +09:00
Cohee
040c4a8894 Merge pull request #518 from 50h100a/main
Mismatch between file and character names prevents chat logs from being deleted.
2023-06-18 16:34:42 +03:00
Cohee
22a5def618 Add option to auto-adjust number of chroma messages to keep / query based on context size. 2023-06-18 16:29:23 +03:00
RossAscends
58a6ccd4a5 WI-to-AN for real this time. 2023-06-18 18:17:43 +09:00
hh_aa
cefc10b405 Merge branch 'main' of https://github.com/50h100a/SillyTavern into main 2023-06-17 23:40:19 -04:00
hh_aa
6d649c716d Use filename instead of id to delete chat logs. 2023-06-17 23:39:04 -04:00
hh_aa
ba545e44e3 Use filename instead of id to delete chat logs. 2023-06-17 23:30:48 -04:00
RossAscends
d59024b4a5 forgot zoomed avatar z-index fix for normal mode 2023-06-18 10:09:28 +09:00
RossAscends
6a5b44b3b3 zoomed avatars display on top of sprites 2023-06-18 10:06:00 +09:00
RossAscends
75090c4fa4 WorldInfo can now be routed into Author's Note 2023-06-18 08:27:24 +09:00
RossAscends
b0db3686b1 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-18 06:35:24 +09:00
RossAscends
468aafb384 less console spam, placehold for dinkus MD escape 2023-06-18 06:35:22 +09:00
Cohee
b85605cac8 Don't auto-select chat.comp preset if it's already selected 2023-06-17 20:28:02 +03:00
Cohee
2edebec52c Auto-balance quotes on streaming 2023-06-17 20:23:03 +03:00
Cohee
64fcb4b1f0 Adjust css index 2023-06-17 19:48:20 +03:00
Cohee
feecb1fa27 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-17 18:30:07 +03:00
Cohee
2ae467d14f Grammarly extension no longer hides in shame behind the textarea 2023-06-17 18:30:05 +03:00
RossAscends
0db9cec7c4 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-17 10:19:28 +09:00
RossAscends
0c0baecb5f clarify TTS checkboxes 2023-06-17 10:19:27 +09:00
Cohee
b34478f800 Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev 2023-06-16 19:29:06 +03:00
Cohee
3b51252e9e Pretty print save themes and presets 2023-06-16 19:29:02 +03:00
Cohee
3a8f4e4f76 Merge pull request #508 from zerfl/patch-1
fix: prevent swiping messages when editing tasks
2023-06-16 19:27:37 +03:00
Daniel Martin
a8341f7b57 fix: prevent swiping messages when editing tasks 2023-06-16 17:53:21 +02:00
RossAscends
db7578be8e toggle for hiding WI Entry memo input box 2023-06-16 23:00:02 +09:00
Cohee
536052af3d Rate-limit Poe message requests 2023-06-16 15:13:03 +03:00
Cohee
f4cc3932da Merge branch 'main' into dev 2023-06-16 14:12:33 +03:00
Cohee
c890da2877 Fix server crash when KoboldCpp server goes offline and stop is clicked 2023-06-16 14:11:52 +03:00
RossAscends
b5d1ed048d resolve skill issue for WI entry mass open/close 2023-06-16 19:32:20 +09:00
RossAscends
ed0272efa6 Merge branch 'dev' of https://github.com/Cohee1207/SillyTavern into dev 2023-06-16 19:24:26 +09:00
RossAscends
7686ac0b28 fix WI open/close buttons + entries start closed 2023-06-16 19:24:24 +09:00
Cohee
bec6227aaf Merge branch 'main' of https://github.com/SillyLossy/TavernAI 2023-06-16 12:55:08 +03:00
Cohee
6a2a0efc84 Don't run streaming with Kobold on quiet gens #504 2023-06-16 12:55:02 +03:00
Cohee
b09ea054df Bump package version 2023-06-16 00:24:41 +03:00
Cohee
024784e0b0 Fix oobabooga homunculus mode 2023-06-16 00:22:27 +03:00
Cohee
329158349f Remove debug statement 2023-06-16 00:08:52 +03:00
Cohee
62d5f20590 Don't stack suggested replies when using impersonate on Poe 2023-06-15 20:05:53 +03:00
Cohee
e420c96e77 Fix mobile audio playback stopping on swiping 2023-06-15 19:31:18 +03:00
Cohee
7af5a6ee5d Fix broken preset file 2023-06-15 19:26:25 +03:00
Cohee
e91cbe009f Correctly clamp max_context value on saving a chat completion preset 2023-06-15 18:32:56 +03:00
172 changed files with 17987 additions and 6122 deletions

View File

@@ -3,4 +3,5 @@ node_modules
npm-debug.log
readme*
Start.bat
/dist
/dist
/backups/

69
.github/readme.md vendored
View File

@@ -1,16 +1,16 @@
![image](https://github.com/SillyTavern/SillyTavern/assets/18619528/8c41a061-7f72-4d2b-9d54-e6d058209e7b)
Mobile-friendly, Multi-API (KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI+proxies, Poe, WindowAI(Claude!)), VN-like Waifu Mode, Horde SD, System TTS, WorldInfo (lorebooks), customizable UI, auto-translate, and more prompt options than you'd ever want or need. Optional Extras server for more SD/TTS options + ChromaDB/Summarize.
Mobile-friendly, Multi-API (KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI+proxies, WindowAI(Claude!)), VN-like Waifu Mode, Horde SD, System TTS, WorldInfo (lorebooks), customizable UI, auto-translate, and more prompt options than you'd ever want or need. Optional Extras server for more SD/TTS options + ChromaDB/Summarize.
Based on a fork of TavernAI 1.2.8
### Brought to you by Cohee, RossAscends and the SillyTavern community
### Brought to you by Cohee, RossAscends, and the SillyTavern community
NOTE: We have created a [Documentation website](https://docs.sillytavern.app/) to answer most of your questions and help you get started.
### What is SillyTavern or TavernAI?
Tavern is a user interface you can install on your computer (and Android phones) that allows you to interact with text generation AIs and chat/roleplay with characters you or the community create.
SillyTavern is a user interface you can install on your computer (and Android phones) that allows you to interact with text generation AIs and chat/roleplay with characters you or the community create.
SillyTavern is a fork of TavernAI 1.2.8 which is under more active development and has added many major features. At this point, they can be thought of as completely independent programs.
@@ -53,7 +53,7 @@ Get support, share favorite characters and prompts:
Get in touch with the developers directly:
* Discord: Cohee#1207 or RossAscends#1779
* Discord: cohee or rossascends
* Reddit: /u/RossAscends or /u/sillylossy
* [Post a GitHub issue](https://github.com/SillyTavern/SillyTavern/issues)
@@ -64,36 +64,35 @@ Get in touch with the developers directly:
* Group chats: multi-bot rooms for characters to talk to you or each other
* Chat bookmarks / branching (duplicates the dialogue in its current state)
* Advanced KoboldAI / TextGen generation settings with a lot of community-made presets
* World Info support: create a rich lore or save tokens on your character card
* Window AI browser extension support (run models like Claude, GPT 4): https://windowai.io/
* World Info support: create rich lore or save tokens on your character card
* Window AI browser extension support (run models like Claude, GPT 4): <https://windowai.io/>
* [Oobabooga's TextGen WebUI](https://github.com/oobabooga/text-generation-webui) API connection
* [AI Horde](https://horde.koboldai.net/) connection
* [Poe.com](https://poe.com) (ChatGPT / Claude) connection
* Soft prompts selector for KoboldAI
* Prompt generation formatting tweaking
* webp character card interoperability (PNG is still an internal format)
## Extensions
SillyTavern has an extensibility support, with some additional AI modules hosted via [SillyTavern Extras API](https://github.com/SillyTavern/SillyTavern-extras)
SillyTavern has extensibility support, with some additional AI modules hosted via [SillyTavern Extras API](https://github.com/SillyTavern/SillyTavern-extras)
* Author's Note / Character Bias
* Character emotional expressions
* Character emotional expressions (sprites)
* Auto-Summary of the chat history
* Sending images to chat, and the AI interpreting the content.
* Sending images to chat, and the AI interpreting the content
* Stable Diffusion image generation (5 chat-related presets plus 'free mode')
* Text-to-speech for AI response messages (via ElevenLabs, Silero, or the OS's System TTS)
* ChromaDB vector storage for smarter chat prompt formatting
Full list of included extenisons and tutorials how to use them can be found on [Wiki](https://github.com/SillyTavern/SillyTavern/wiki).
A full list of included extensions and tutorials on how to use them can be found in the [Docs](https://docs.sillytavern.app/extras/extensions/).
## UI/CSS/Quality of Life tweaks by RossAscends
* Mobile UI with optimized for iOS, and supports saving a shortcut to home screen and opening in fullscreen mode.
* Mobile UI optimized for iOS, and supports saving a shortcut to the home screen and opening in fullscreen mode.
* HotKeys
* Up = Edit last message in chat
* Ctrl+Up = Edit last USER message in chat
* Left = swipe left
* Right = swipe right (NOTE: swipe hotkeys are disabled when chatbar has something typed into it)
* Right = swipe right (NOTE: swipe hotkeys are disabled when the chat bar has something typed into it)
* Ctrl+Left = view locally stored variables (in the browser console window)
* Enter (with chat bar selected) = send your message to AI
* Ctrl+Enter = Regenerate the last AI response
@@ -118,7 +117,7 @@ Full list of included extenisons and tutorials how to use them can be found on [
* Switch between round or rectangle avatar styles
* Have a wider chat window on the desktop
* Optional semi-transparent glass-like panels
* Customizable page colors for 'main text', 'quoted text' 'italics text'.
* Customizable page colors for 'main text', 'quoted text', and 'italics text'.
* Customizable UI background color and blur amount
## Installation
@@ -135,8 +134,8 @@ Full list of included extenisons and tutorials how to use them can be found on [
Installing via Git (recommended for easy updating)
Easy to follow guide with pretty pictures:
<https://docs.alpindale.dev/pygmalion-extras/sillytavern/#windows-installation>
An easy-to-follow guide with pretty pictures:
<https://docs.sillytavern.app/installation/windows/>
1. Install [NodeJS](https://nodejs.org/en) (latest LTS version is recommended)
2. Install [GitHub Desktop](https://central.github.com/deployments/desktop/desktop/latest/win32)
@@ -148,15 +147,15 @@ Easy to follow guide with pretty pictures:
* for Main Branch: `git clone https://github.com/SillyTavern/SillyTavern -b main`
* for Dev Branch: `git clone https://github.com/SillyTavern/SillyTavern -b dev`
7. Once everything is cloned, double click `Start.bat` to make NodeJS install its requirements.
8. The server will then start, and SillyTavern will popup in your browser.
7. Once everything is cloned, double-click `Start.bat` to make NodeJS install its requirements.
8. The server will then start, and SillyTavern will pop up in your browser.
Installing via zip download
Installing via ZIP download (discouraged)
1. Install [NodeJS](https://nodejs.org/en) (latest LTS version is recommended)
2. Download the zip from this GitHub repo. (Get the `Source code (zip)` from [Releases](https://github.com/SillyTavern/SillyTavern/releases/latest))
3. Unzip it into a folder of your choice
4. Run `Start.bat` via double-clicking or in a command line.
4. Run `Start.bat` by double-clicking or in a command line.
5. Once the server has prepared everything for you, it will open a tab in your browser.
### Linux
@@ -168,7 +167,7 @@ Installing via zip download
SillyTavern saves your API keys to a `secrets.json` file in the server directory.
By default they will not be exposed to a frontend after you enter them and reload the page.
By default, they will not be exposed to a frontend after you enter them and reload the page.
In order to enable viewing your keys by clicking a button in the API block:
@@ -186,9 +185,9 @@ However, it can be used to allow remote connections from anywhere as well.
### 1. Managing whitelisted IPs
* Create a new text file inside your SillyTavern base install folder called `whitelist.txt`.
* Open the file in a text editor, add a list of IPs you want to be allowed to connect.
* Open the file in a text editor, and add a list of IPs you want to be allowed to connect.
*Both indidivual IPs, and wildcard IP ranges are accepted. Examples:*
*Both individual IPs and wildcard IP ranges are accepted. Examples:*
```txt
192.168.0.1
@@ -220,15 +219,15 @@ If the ST-hosting device is on the same wifi network, you will use the ST-host's
* For Windows: windows button > type `cmd.exe` in the search bar > type `ipconfig` in the console, hit Enter > look for `IPv4` listing.
If you (or someone else) wants to connect to your hosted ST while not being on the same network, you will need the public IP of your ST-hosting device.
If you (or someone else) want to connect to your hosted ST while not being on the same network, you will need the public IP of your ST-hosting device.
* While using the ST-hosting device, access [this page](https://whatismyipaddress.com/) and look for for `IPv4`. This is what you would use to connect from the remote device.
### 3. Connect the remote device to the ST host machine.
### 3. Connect the remote device to the ST host machine
Whatever IP you ended up with for your situation, you will put that IP address and port number into the remote device's web browser.
A typical address for an ST host on the same wifi network would look like:
A typical address for an ST host on the same wifi network would look like this:
`http://192.168.0.5:8000`
@@ -238,7 +237,7 @@ Use http:// NOT https://
We do not recommend doing this, but you can open `config.conf` and change `whitelist` to `false`.
You must remove (or rename) `whitelist.txt` in the SillyTavern base install folder, if it exists.
You must remove (or rename) `whitelist.txt` in the SillyTavern base install folder if it exists.
This is usually an insecure practice, so we require you to set a username and password when you do this.
@@ -248,8 +247,8 @@ After restarting your ST server, any device will be able to connect to it, regar
### Still Unable To Connect?
* Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for portforwarding on your router, otherwise someone could find your chat logs and that's a big no-no.
* Enable the Private Network profile type in Settings > Network and Internet > Ethernet. This is VERY important for Windows 11, otherwise you would be unable to connect even with the aforementioned firewall rules.
* Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for port-forwarding on your router, otherwise, someone could find your chat logs and that's a big no-no.
* Enable the Private Network profile type in Settings > Network and Internet > Ethernet. This is VERY important for Windows 11, otherwise, you would be unable to connect even with the aforementioned firewall rules.
## Performance issues?
@@ -271,7 +270,7 @@ Try enabling the No Blur Effect (Fast UI) mode on the User settings panel.
## Where can I find the old backgrounds?
We're moving to 100% original content only policy, so old background images have been removed from this repository.
We're moving to a 100% original content only policy, so old background images have been removed from this repository.
You can find them archived here:
@@ -293,14 +292,16 @@ GNU Affero General Public License for more details.**
* Cohee's modifications and derived code: AGPL v3
* RossAscends' additions: AGPL v3
* Portions of CncAnon's TavernAITurbo mod: Unknown license
* kingbri's various commits and suggestions (<https://github.com/bdashore3>)
* BlipRanger's miscellaneous UI & extension modifications (<https://github.com/BlipRanger>)
* Waifu mode inspired by the work of PepperTaco (<https://github.com/peppertaco/Tavern/>)
* Thanks Pygmalion University for being awesome testers and suggesting cool features!
* Thanks oobabooga for compiling presets for TextGen
* poe-api client adapted from <https://github.com/ading2210/poe-api> (GPL v3)
* GraphQL files for poe: <https://github.com/muharamdani/poe> (ISC License)
* KoboldAI Presets from KAI Lite: <https://lite.koboldai.net/>
* Noto Sans font by Google (OFL license)
* Icon theme by Font Awesome <https://fontawesome.com> (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* AI Horde client library by ZeldaFan0225: https://github.com/ZeldaFan0225/ai_horde
* AI Horde client library by ZeldaFan0225: <https://github.com/ZeldaFan0225/ai_horde>
* Linux startup script by AlpinDale
* Thanks paniphons for providing a FAQ document
* 10K Discord Users Celebratory Background by @kallmeflocc
* Korean translation by @doloroushyeonse

5
.gitignore vendored
View File

@@ -9,6 +9,8 @@ public/worlds/
public/css/bg_load.css
public/themes/
public/OpenAI Settings/
public/scripts/extensions/third-party/
public/stats.json
/uploads/
*.jsonl
config.conf
@@ -19,4 +21,5 @@ whitelist.txt
.vscode
secrets.json
/dist
poe_device.json
/backups/
public/movingUI/

View File

@@ -4,4 +4,4 @@ node_modules/
/thumbnails
secrets.json
/dist
poe_device.json
/backups/

View File

@@ -1,5 +1,5 @@
pushd %~dp0
call npm install
call npm install --no-audit
node server.js
pause
popd
popd

View File

@@ -32,6 +32,8 @@
},
"outputs": [],
"source": [
"#@markdown (RECOMMENDED) Generates an API key for you to use with the API\n",
"secure = False #@param {type:\"boolean\"}\n",
"#@markdown Enables hosting of extensions backend for SillyTavern Extras\n",
"use_cpu = False #@param {type:\"boolean\"}\n",
"#@markdown Allows to run SillyTavern Extras on CPU (use if you're out of daily GPU allowance)\n",
@@ -80,6 +82,8 @@
" params.append('--cpu')\n",
"if use_sd_cpu:\n",
" params.append('--sd-cpu')\n",
"if secure:\n",
" params.append('--secure')\n",
"params.append('--share')\n",
"ExtrasModules = []\n",
"\n",

277
package-lock.json generated
View File

@@ -1,15 +1,16 @@
{
"name": "sillytavern",
"version": "1.7.0",
"version": "1.9.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sillytavern",
"version": "1.7.0",
"version": "1.9.0",
"license": "AGPL-3.0",
"dependencies": {
"@dqbd/tiktoken": "^1.0.2",
"@mlc-ai/web-tokenizers": "^0.1.0",
"axios": "^1.4.0",
"command-exists": "^1.2.9",
"compression": "^1",
@@ -37,10 +38,11 @@
"png-chunks-encode": "^1.0.0",
"png-chunks-extract": "^1.0.0",
"response-time": "^2.3.2",
"rimraf": "^3.0.2",
"sanitize-filename": "^1.6.3",
"sentencepiece-js": "^1.1.0",
"simple-git": "^3.19.1",
"uniqolor": "^1.1.0",
"user-agents": "^1.0.1444",
"webp-converter": "2.3.2",
"ws": "^8.13.0",
"yargs": "^17.7.1",
@@ -70,18 +72,18 @@
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.21.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz",
"integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
"integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
"dev": true,
"engines": {
"node": ">=6.9.0"
@@ -561,6 +563,45 @@
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true
},
"node_modules/@kwsites/file-exists": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
"integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
"dependencies": {
"debug": "^4.1.1"
}
},
"node_modules/@kwsites/file-exists/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@kwsites/file-exists/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/@kwsites/promise-deferred": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
"integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
},
"node_modules/@mlc-ai/web-tokenizers": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@mlc-ai/web-tokenizers/-/web-tokenizers-0.1.0.tgz",
"integrity": "sha512-whiQ+40ohtAFoFOGcje1Io7BMr434Wh3hM3nBCWlJMpXxL5Rlig/AH9wjyUPsytKwWTEe7RoYPyXSbFw5Vs6Tw=="
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -607,9 +648,9 @@
"integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="
},
"node_modules/@xmldom/xmldom": {
"version": "0.7.11",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.11.tgz",
"integrity": "sha512-UDi3g6Jss/W5FnSzO9jCtQwEpfymt0M+sPPlmLhDH6h2TJ8j4ESE/LpmNPBij15J5NKkk4/cg/qoVMdWI3vnlQ==",
"version": "0.8.9",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.9.tgz",
"integrity": "sha512-4VSbbcMoxc4KLjb1gs96SRmi7w4h1SF+fCoiK0XaQX62buCc1G5d0DC5bJ9xJBNPDSVCmIrcl8BiYxzjrqaaJA==",
"optional": true,
"engines": {
"node": ">=10.0.0"
@@ -745,11 +786,6 @@
"proxy-from-env": "^1.1.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -830,15 +866,6 @@
"node": ">= 0.8"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -1021,11 +1048,6 @@
"node": ">= 0.8.0"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
@@ -1201,6 +1223,14 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/detect-indent": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz",
"integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==",
"engines": {
"node": ">=8"
}
},
"node_modules/detect-libc": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
@@ -1230,11 +1260,32 @@
"node": ">=8"
}
},
"node_modules/docopt": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz",
"integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/dom-walk": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
},
"node_modules/dot-json": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/dot-json/-/dot-json-1.3.0.tgz",
"integrity": "sha512-Pu11Prog/Yjf2lBICow82/DSV46n3a2XT1Rqt/CeuhkO1fuacF7xydYhI0SwQx2Ue0jCyLtQzgKPFEO6ewv+bQ==",
"dependencies": {
"detect-indent": "~6.0.0",
"docopt": "~0.6.2",
"underscore-keypath": "~0.0.22"
},
"bin": {
"dot-json": "bin/dot-json.js"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -1289,12 +1340,12 @@
"integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="
},
"node_modules/exifreader": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/exifreader/-/exifreader-4.12.0.tgz",
"integrity": "sha512-aRSmNyw2c6f6qPK4jmC56W/5XePDN7LVwt8tQjgMchxoY3MCxqEToegirKdS7A3CYCWAOPehfypMZWGWxtLhzw==",
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/exifreader/-/exifreader-4.13.0.tgz",
"integrity": "sha512-IhJBpyXDLbCdgzVHkthadOvrMiZOR2XS7POVp0b5JoVfScRoCJ6YazZ+stTkbDTE5TRTP44bE5RKsujckAs45Q==",
"hasInstallScript": true,
"optionalDependencies": {
"@xmldom/xmldom": "^0.7.8"
"@xmldom/xmldom": "^0.8.8"
}
},
"node_modules/expand-template": {
@@ -1375,9 +1426,9 @@
]
},
"node_modules/fast-glob": {
"version": "3.2.12",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz",
"integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
@@ -1531,11 +1582,6 @@
"node": ">=10"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -1578,25 +1624,6 @@
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
"dev": true
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
@@ -1800,15 +1827,6 @@
"@types/node": "16.9.1"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@@ -2019,6 +2037,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -2124,17 +2147,6 @@
"dom-walk": "^0.1.0"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
@@ -2249,9 +2261,9 @@
}
},
"node_modules/node-abi": {
"version": "3.43.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.43.0.tgz",
"integrity": "sha512-QB0MMv+tn9Ur2DtJrc8y09n0n6sw88CyDniWSX2cHW10goQXYPK9ZpFJOktDS4ron501edPX6h9i7Pg+RnH5nQ==",
"version": "3.45.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz",
"integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==",
"dev": true,
"dependencies": {
"semver": "^7.3.5"
@@ -2261,9 +2273,9 @@
}
},
"node_modules/node-fetch": {
"version": "2.6.11",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
"integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
"integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
@@ -2357,6 +2369,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"dependencies": {
"wrappy": "1"
}
@@ -2435,14 +2448,6 @@
"node": ">= 0.8"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
@@ -2974,20 +2979,6 @@
"node": ">=0.10.0"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -3035,9 +3026,9 @@
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"node_modules/semver": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
"integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@@ -3162,6 +3153,41 @@
"simple-concat": "^1.0.0"
}
},
"node_modules/simple-git": {
"version": "3.19.1",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.19.1.tgz",
"integrity": "sha512-Ck+rcjVaE1HotraRAS8u/+xgTvToTuoMkT9/l9lvuP5jftwnYUp6DwuJzsKErHgfyRk8IB8pqGHWEbM3tLgV1w==",
"dependencies": {
"@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1",
"debug": "^4.3.4"
},
"funding": {
"type": "github",
"url": "https://github.com/steveukx/git-js?sponsor=1"
}
},
"node_modules/simple-git/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/simple-git/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -3430,6 +3456,19 @@
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
},
"node_modules/underscore": {
"version": "1.13.6",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
"integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A=="
},
"node_modules/underscore-keypath": {
"version": "0.0.22",
"resolved": "https://registry.npmjs.org/underscore-keypath/-/underscore-keypath-0.0.22.tgz",
"integrity": "sha512-fU7aYj1J2LQd+jqdQ67AlCOZKK3Pl+VErS8fGYcgZG75XB9/bY+RLM+F2xEcKHhHNtLvqqFyXAoZQlLYfec3Xg==",
"dependencies": {
"underscore": "*"
}
},
"node_modules/uniqolor": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/uniqolor/-/uniqolor-1.1.0.tgz",
@@ -3452,6 +3491,15 @@
"node": ">= 0.8"
}
},
"node_modules/user-agents": {
"version": "1.0.1444",
"resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.0.1444.tgz",
"integrity": "sha512-6WXJ0RZuUKgif1rW5FN02HnpoJ8EzH6COQoXCiVStZEVPz+YnAx3iA48etY3ZD4UwueYN9ALC7j4ayHvYEh7tA==",
"dependencies": {
"dot-json": "^1.3.0",
"lodash.clonedeep": "^4.5.0"
}
},
"node_modules/utf8-byte-length": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
@@ -3529,7 +3577,8 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
},
"node_modules/ws": {
"version": "8.13.0",

View File

@@ -1,6 +1,7 @@
{
"dependencies": {
"@dqbd/tiktoken": "^1.0.2",
"@mlc-ai/web-tokenizers": "^0.1.0",
"axios": "^1.4.0",
"command-exists": "^1.2.9",
"compression": "^1",
@@ -28,10 +29,11 @@
"png-chunks-encode": "^1.0.0",
"png-chunks-extract": "^1.0.0",
"response-time": "^2.3.2",
"rimraf": "^3.0.2",
"sanitize-filename": "^1.6.3",
"sentencepiece-js": "^1.1.0",
"simple-git": "^3.19.1",
"uniqolor": "^1.1.0",
"user-agents": "^1.0.1444",
"webp-converter": "2.3.2",
"ws": "^8.13.0",
"yargs": "^17.7.1",
@@ -48,7 +50,7 @@
"type": "git",
"url": "https://github.com/SillyTavern/SillyTavern.git"
},
"version": "1.7.0",
"version": "1.9.0",
"scripts": {
"start": "node server.js",
"pkg": "pkg --compress Gzip --no-bytecode --public ."
@@ -68,8 +70,7 @@
"node18-windows-x64"
],
"assets": [
"node_modules/**/*",
"src/poe_graphql/**/*"
"node_modules/**/*"
],
"outputPath": "dist",
"scripts": [

View File

@@ -1,21 +0,0 @@
const poe = require('./src/poe-client');
async function test() {
const client = new poe.Client();
await client.init('pb-cookie');
const bots = client.get_bot_names();
console.log(bots);
await client.purge_conversation('a2', -1);
let reply;
for await (const mes of client.send_message('a2', 'Hello')) {
reply = mes.text;
}
console.log(reply);
client.disconnect_ws();
}
test();

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 1.15,
"genamt": 100,
"temp": 1.15,
"top_k": 0,
"top_p": 0.95,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 2048,
"rep_pen_slope": 7,
"sampler_order": [
6,
3,
2,
0,
5,
1,
4,
6
4
]
}

View File

@@ -1,6 +1,16 @@
{
"apikey": "",
"andepth": 1,
"max_length": 2048,
"genamt": 90,
"temp": 0.8,
"top_k": 28,
"top_p": 0.94,
"top_a": 0.00,
"tfs": 0.96,
"typical": 0.98,
"rep_pen": 1.03,
"rep_pen_slope": 0.8,
"rep_pen_range": 120.0,
"ikgen": 200,
"sampler_order": [
6,
4,
@@ -9,46 +19,5 @@
0,
1,
5
],
"temp": 0.8,
"top_p": 0.94,
"top_k": 28,
"tfs": 0.96,
"typical": 0.98,
"top_a": 0.00,
"rep_pen": 1.03,
"rep_pen_slope": 0.8,
"rep_pen_range": 120.0,
"genamt": 90,
"max_length": 2048,
"ikgen": 200,
"formatoptns": {
"frmttriminc": true,
"frmtrmblln": false,
"frmtrmspch": false,
"frmtadsnsp": true,
"singleline": false
},
"numseqs": 1,
"widepth": 3,
"useprompt": false,
"adventure": false,
"chatmode": false,
"chatname": "You",
"dynamicscan": false,
"nopromptgen": false,
"rngpersist": false,
"nogenmod": false,
"fulldeterminism": false,
"autosave": false,
"welcome": "## Warning: This model has a very heavy NSFW bias and is not suitable for use by minors!\n\nYou are currently running story-writing model `Erebus, version 1 (20B).`\n\n This model is made by [Mr. Seeker](https://www.patreon.com/mrseeker) with help of ProudNoob and the KoboldAI team.\n\n### How to use this model\n\nErebus is designed to generate short stories and novels. Use the author's note to give it a certain genre to follow, use memory to give an overview of the story and use World Information to give specific details about the characters. To start off, give the AI an idea of what you are writing about by setting the scene. Give the AI around 10 sentences that make your story interesting to read. Introduce your character, describe the world, blow something up, or let the AI use its creative mind.",
"output_streaming": true,
"show_probs": false,
"show_budget": false,
"seed": null,
"newlinemode": "n",
"antemplate": "",
"userscripts": [],
"corescript": "default.lua",
"softprompt": ""
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 0.59,
"genamt": 100,
"temp": 0.59,
"top_k": 0,
"top_p": 1,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 2048,
"rep_pen_slope": 0.3,
"sampler_order": [
6,
5,
0,
2,
3,
1,
4,
6
4
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 0.8,
"genamt": 100,
"temp": 0.8,
"top_k": 100,
"top_p": 0.9,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 2048,
"rep_pen_slope": 3.4,
"sampler_order": [
6,
5,
0,
2,
3,
1,
4,
6
4
]
}

View File

@@ -1,21 +1,15 @@
{
"file_version": 2,
"max_length": 2048,
"ikmax": 3000,
"genamt": 180,
"ikgen": 200,
"rep_pen": 1.01,
"rep_pen_slope": 0.9,
"rep_pen_range": 1024,
"temp": 1.0,
"top_p": 0.9,
"top_k": 40,
"top_a": 0.0,
"tfs": 0.9,
"typical": 1.0,
"numseqs": 1,
"fp32_model": false,
"modeldim": 4096,
"rep_pen": 1.01,
"rep_pen_slope": 0.9,
"rep_pen_range": 1024,
"sampler_order": [
6,
0,
@@ -24,24 +18,5 @@
3,
4,
5
],
"newlinemode": "n",
"lazy_load": true,
"revision": null,
"selected_preset": "",
"horde_wait_time": 0,
"horde_queue_position": 0,
"horde_queue_size": 0,
"model": "pygmalion-6b",
"model_type": "gptj",
"url": "https://api.inferkit.com/v1/models/standard/generate",
"oaiurl": "",
"oaiengines": "https://api.openai.com/v1/engines",
"colaburl": "/request",
"apikey": "",
"oaiapikey": "",
"configname": "pygmalion-6b",
"online_model": "",
"alt_multi_gen": false
]
}

View File

@@ -1,21 +1,15 @@
{
"file_version": 2,
"max_length": 2048,
"ikmax": 3000,
"genamt": 180,
"ikgen": 200,
"rep_pen": 1.17,
"rep_pen_slope": 0.2,
"rep_pen_range": 1024,
"temp": 0.43,
"top_p": 0.96,
"top_k": 0,
"top_a": 0.0,
"tfs": 0.68,
"typical": 1.0,
"numseqs": 1,
"fp32_model": false,
"modeldim": 2560,
"rep_pen": 1.17,
"rep_pen_slope": 0.2,
"rep_pen_range": 1024,
"sampler_order": [
6,
0,
@@ -24,23 +18,5 @@
3,
4,
5
],
"newlinemode": "n",
"lazy_load": true,
"revision": null,
"selected_preset": "",
"horde_wait_time": 0,
"horde_queue_position": 0,
"horde_queue_size": 0,
"model": "pygmalion-2.7b",
"model_type": "gpt_neo",
"url": "https://api.inferkit.com/v1/models/standard/generate",
"oaiurl": "",
"oaiengines": "https://api.openai.com/v1/engines",
"colaburl": "/request",
"apikey": "",
"oaiapikey": "",
"configname": "pygmalion-2.7b",
"online_model": "",
"alt_multi_gen": false
]
}

View File

@@ -1,21 +1,15 @@
{
"file_version": 2,
"max_length": 2048,
"ikmax": 3000,
"genamt": 180,
"ikgen": 200,
"rep_pen": 1.1,
"rep_pen_slope": 0.9,
"rep_pen_range": 1024,
"temp": 0.65,
"top_p": 0.9,
"top_k": 0,
"top_a": 0.0,
"tfs": 0.9,
"typical": 1.0,
"numseqs": 1,
"fp32_model": false,
"modeldim": 4096,
"rep_pen": 1.1,
"rep_pen_slope": 0.9,
"rep_pen_range": 1024,
"sampler_order": [
6,
0,
@@ -23,25 +17,6 @@
2,
3,
4,
5
],
"newlinemode": "n",
"lazy_load": true,
"revision": null,
"selected_preset": "",
"horde_wait_time": 0,
"horde_queue_position": 0,
"horde_queue_size": 0,
"model": "pygmalion-6b",
"model_type": "gptj",
"url": "https://api.inferkit.com/v1/models/standard/generate",
"oaiurl": "",
"oaiengines": "https://api.openai.com/v1/engines",
"colaburl": "/request",
"apikey": "",
"oaiapikey": "",
"configname": "pygmalion-6b",
"online_model": "",
"alt_multi_gen": false
5
]
}

View File

@@ -1,22 +1,22 @@
{
"max_length": 2048,
"genamt": 100,
"temp": 0.51,
"top_p": 1,
"top_k": 0,
"tfs": 0.99,
"top_a": 0,
"typical": 1,
"rep_pen": 1.2,
"rep_pen_range": 2048,
"rep_pen_slope": 0,
"sampler_order": [
6,
5,
0,
2,
3,
1,
4,
6
],
"temp": 0.51,
"tfs": 0.99,
"top_a": 0,
"top_k": 0,
"top_p": 1,
"typical": 1
4
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 1600,
"temp": 0.79,
"genamt": 180,
"temp": 0.79,
"top_k": 0,
"top_p": 0.9,
"top_a": 0,

View File

@@ -1,21 +1,15 @@
{
"file_version": 2,
"max_length": 2048,
"ikmax": 3000,
"genamt": 180,
"ikgen": 200,
"rep_pen": 1.19,
"rep_pen_slope": 0.9,
"rep_pen_range": 1024,
"temp": 0.79,
"top_p": 0.9,
"top_k": 0,
"top_a": 0.0,
"tfs": 0.95,
"typical": 1.0,
"numseqs": 1,
"fp32_model": false,
"modeldim": 4096,
"rep_pen": 1.19,
"rep_pen_slope": 0.9,
"rep_pen_range": 1024,
"sampler_order": [
6,
0,
@@ -24,24 +18,5 @@
3,
4,
5
],
"newlinemode": "n",
"lazy_load": true,
"revision": null,
"selected_preset": "",
"horde_wait_time": 0,
"horde_queue_position": 0,
"horde_queue_size": 0,
"model": "pygmalion-6b",
"model_type": "gptj",
"url": "https://api.inferkit.com/v1/models/standard/generate",
"oaiurl": "",
"oaiengines": "https://api.openai.com/v1/engines",
"colaburl": "/request",
"apikey": "",
"oaiapikey": "",
"configname": "pygmalion-6b",
"online_model": "",
"alt_multi_gen": false
]
}

View File

@@ -1,21 +1,15 @@
{
"file_version": 2,
"max_length": 1400,
"ikmax": 3000,
"genamt": 180,
"ikgen": 200,
"rep_pen": 1.08,
"rep_pen_slope": 0.9,
"rep_pen_range": 1024,
"temp": 0.65,
"top_p": 0.9,
"top_k": 0,
"top_a": 0.0,
"tfs": 0.9,
"typical": 1.0,
"numseqs": 1,
"fp32_model": false,
"modeldim": 4096,
"rep_pen": 1.08,
"rep_pen_slope": 0.9,
"rep_pen_range": 1024,
"sampler_order": [
6,
0,
@@ -24,24 +18,5 @@
3,
4,
5
],
"newlinemode": "n",
"lazy_load": true,
"revision": null,
"selected_preset": "",
"horde_wait_time": 0,
"horde_queue_position": 0,
"horde_queue_size": 0,
"model": "pygmalion-6b",
"model_type": "gptj",
"url": "https://api.inferkit.com/v1/models/standard/generate",
"oaiurl": "",
"oaiengines": "https://api.openai.com/v1/engines",
"colaburl": "/request",
"apikey": "",
"oaiapikey": "",
"configname": "pygmalion-6b",
"online_model": "",
"alt_multi_gen": false
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 0.63,
"genamt": 100,
"temp": 0.63,
"top_k": 0,
"top_p": 0.98,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 2048,
"rep_pen_slope": 0.1,
"sampler_order": [
6,
2,
0,
3,
5,
1,
4,
6
4
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 0.7,
"genamt": 100,
"temp": 0.7,
"top_k": 0,
"top_p": 0.5,
"top_a": 0.75,
@@ -11,12 +11,12 @@
"rep_pen_range": 1024,
"rep_pen_slope": 0.7,
"sampler_order": [
6,
5,
4,
3,
2,
1,
0,
6
0
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 0.7,
"genamt": 100,
"temp": 0.7,
"top_k": 0,
"top_p": 1,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 1024,
"rep_pen_slope": 0.7,
"sampler_order": [
6,
0,
1,
2,
3,
4,
5,
6
5
]
}

View File

@@ -1,15 +1,6 @@
{
"apikey": "",
"andepth": 1,
"sampler_order": [
6,
4,
3,
2,
0,
1,
5
],
"max_length": 2048,
"genamt": 90,
"temp": 0.8,
"top_p": 0.94,
"top_k": 15,
@@ -19,36 +10,13 @@
"rep_pen": 1.02,
"rep_pen_slope": 0.8,
"rep_pen_range": 256.0,
"genamt": 90,
"max_length": 2048,
"ikgen": 200,
"formatoptns": {
"frmttriminc": true,
"frmtrmblln": false,
"frmtrmspch": false,
"frmtadsnsp": true,
"singleline": false
},
"numseqs": 1,
"widepth": 3,
"useprompt": false,
"adventure": false,
"chatmode": false,
"chatname": "You",
"dynamicscan": false,
"nopromptgen": false,
"rngpersist": false,
"nogenmod": false,
"fulldeterminism": false,
"autosave": false,
"welcome": "## Warning: This model has a very heavy NSFW bias and is not suitable for use by minors!\n\nYou are currently running story-writing model `Erebus, version 1 (20B).`\n\n This model is made by [Mr. Seeker](https://www.patreon.com/mrseeker) with help of ProudNoob and the KoboldAI team.\n\n### How to use this model\n\nErebus is designed to generate short stories and novels. Use the author's note to give it a certain genre to follow, use memory to give an overview of the story and use World Information to give specific details about the characters. To start off, give the AI an idea of what you are writing about by setting the scene. Give the AI around 10 sentences that make your story interesting to read. Introduce your character, describe the world, blow something up, or let the AI use its creative mind.",
"output_streaming": true,
"show_probs": false,
"show_budget": false,
"seed": null,
"newlinemode": "n",
"antemplate": "",
"userscripts": [],
"corescript": "default.lua",
"softprompt": ""
"sampler_order": [
6,
4,
3,
2,
0,
1,
5
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 0.66,
"genamt": 100,
"temp": 0.66,
"top_k": 0,
"top_p": 1,
"top_a": 0.96,
@@ -11,12 +11,12 @@
"rep_pen_range": 1024,
"rep_pen_slope": 0.7,
"sampler_order": [
6,
4,
5,
1,
0,
2,
3,
6
3
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 0.94,
"genamt": 100,
"temp": 0.94,
"top_k": 12,
"top_p": 1,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 2048,
"rep_pen_slope": 0.2,
"sampler_order": [
6,
5,
0,
2,
3,
1,
4,
6
4
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 1.5,
"genamt": 100,
"temp": 1.5,
"top_k": 85,
"top_p": 0.24,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 2048,
"rep_pen_slope": 0,
"sampler_order": [
6,
5,
0,
2,
3,
1,
4,
6
4
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 1.05,
"genamt": 100,
"temp": 1.05,
"top_k": 0,
"top_p": 0.95,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 1024,
"rep_pen_slope": 0.7,
"sampler_order": [
6,
0,
1,
2,
3,
4,
5,
6
5
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 1.07,
"genamt": 100,
"temp": 1.07,
"top_k": 100,
"top_p": 1,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 404,
"rep_pen_slope": 0.8,
"sampler_order": [
6,
0,
5,
3,
2,
1,
4,
6
4
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 0.44,
"genamt": 100,
"temp": 0.44,
"top_k": 0,
"top_p": 1,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 2048,
"rep_pen_slope": 6.8,
"sampler_order": [
6,
5,
0,
2,
3,
1,
4,
6
4
]
}

View File

@@ -1,7 +1,7 @@
{
"max_length": 2048,
"temp": 1.35,
"genamt": 100,
"temp": 1.35,
"top_k": 0,
"top_p": 1,
"top_a": 0,
@@ -11,12 +11,12 @@
"rep_pen_range": 2048,
"rep_pen_slope": 0.1,
"sampler_order": [
6,
3,
2,
5,
0,
1,
4,
6
4
]
}

View File

@@ -1,21 +1,15 @@
{
"file_version": 2,
"max_length": 1400,
"ikmax": 3000,
"genamt": 80,
"ikgen": 200,
"rep_pen": 1.04,
"rep_pen_slope": 0.0,
"rep_pen_range": 1400,
"temp": 1,
"top_p": 1,
"top_k": 0,
"top_a": 0.0,
"tfs": 0.97,
"typical": 1.0,
"numseqs": 1,
"fp32_model": false,
"modeldim": 2560,
"rep_pen": 1.04,
"rep_pen_slope": 0.0,
"rep_pen_range": 1400,
"sampler_order": [
6,
0,
@@ -24,23 +18,5 @@
3,
4,
5
],
"newlinemode": "n",
"lazy_load": true,
"revision": null,
"selected_preset": "",
"horde_wait_time": 0,
"horde_queue_position": 0,
"horde_queue_size": 0,
"model": "pygmalion-1.3b",
"model_type": "gpt_neo",
"url": "https://api.inferkit.com/v1/models/standard/generate",
"oaiurl": "",
"oaiengines": "https://api.openai.com/v1/engines",
"colaburl": "/request",
"apikey": "",
"oaiapikey": "",
"configname": "pygmalion-1.3b",
"online_model": "",
"alt_multi_gen": false
]
}

View File

@@ -0,0 +1,22 @@
{
"max_length": 100,
"genamt": 100,
"temp": 1,
"top_k": 0,
"top_p": 0.95,
"top_a": 0,
"typical": 1,
"tfs": 1,
"rep_pen": 1.1,
"rep_pen_range": 600,
"rep_pen_slope": 0,
"sampler_order": [
6,
0,
1,
2,
3,
4,
5
]
}

View File

@@ -1,22 +1,22 @@
{
"max_length": 2048,
"genamt": 100,
"rep_pen": 1.1,
"rep_pen_range": 2048,
"rep_pen_slope": 0.2,
"sampler_order": [
5,
0,
2,
3,
1,
4,
6
],
"temp": 0.72,
"tfs": 1,
"top_a": 0,
"top_k": 0,
"top_p": 0.73,
"typical": 1
"typical": 1,
"rep_pen": 1.1,
"rep_pen_range": 2048,
"rep_pen_slope": 0.2,
"sampler_order": [
6,
5,
0,
2,
3,
1,
4
]
}

View File

@@ -1,5 +1,5 @@
{
"order": [1, 0, 3]
"order": [1, 0, 3],
"temperature": 1.07,
"max_length": 60,
"min_length": 60,
@@ -14,4 +14,4 @@
"repetition_penalty_frequency": 0,
"repetition_penalty_presence": 0,
"max_context":2048
}
}

View File

@@ -0,0 +1,22 @@
{
"temp": 1.68,
"top_p": 0.17,
"top_k": 77,
"typical_p": 1,
"top_a": 0.42,
"tfs": 0.97,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.02,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 4.5,
"no_repeat_ngram_size": 2,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 200,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": true
"early_stopping": true,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 0.87,
"top_p": 0.99,
"top_k": 85,
"typical_p": 0.68,
"top_a": 0,
"tfs": 0.68,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.01,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0.6,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": false,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.2,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": false,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 1.31,
"top_p": 0.14,
"top_k": 49,
"typical_p": 1,
"top_a": 0.52,
"tfs": 1,
"epsilon_cutoff": 1.49,
"eta_cutoff": 10.42,
"rep_pen": 1.17,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 0.19,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.1,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 0.6,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.1,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.18,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 200,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 0.98,
"top_p": 0.37,
"top_k": 100,
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.18,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 1,
"top_p": 1,
"top_k": 0,
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 2,
"mirostat_tau": 8,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.15,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -6,6 +6,8 @@
"rep_pen": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.05,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.15,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.05,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.15,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.15,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -5,6 +5,8 @@
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.1,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
@@ -13,5 +15,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -13,5 +13,8 @@
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 1.53,
"top_p": 0.64,
"top_k": 33,
"typical_p": 1,
"top_a": 0.04,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.07,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 0.7,
"top_p": 0.9,
"top_k": 20,
"typical_p": 1,
"top_a": 0.75,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.15,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 1.31,
"top_p": 0.29,
"top_k": 72,
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.09,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 0.02,
"top_p": 0.95,
"top_k": 50,
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 0.7,
"top_p": 1,
"top_k": 0,
"typical_p": 1,
"top_a": 0.2,
"tfs": 0.95,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.15,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 1.01,
"top_p": 0.21,
"top_k": 91,
"typical_p": 1,
"top_a": 0.75,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 10.78,
"rep_pen": 1.21,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1.07,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

View File

@@ -0,0 +1,22 @@
{
"temp": 0.82,
"top_p": 0.21,
"top_k": 72,
"typical_p": 1,
"top_a": 0,
"tfs": 1,
"epsilon_cutoff": 0,
"eta_cutoff": 0,
"rep_pen": 1.19,
"no_repeat_ngram_size": 0,
"penalty_alpha": 0,
"num_beams": 1,
"length_penalty": 1,
"min_length": 0,
"encoder_rep_pen": 1,
"do_sample": true,
"early_stopping": false,
"mirostat_mode": 0,
"mirostat_tau": 5,
"mirostat_eta": 0.1
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 KiB

View File

@@ -1,73 +0,0 @@
body {
margin: 0;
padding: 0;
width: 100%;
background-color: rgb(36, 37, 37);
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
font-family: "Noto Sans", "Noto Color Emoji", sans-serif;
font-size: 16px;
/*1rem*/
color: #999;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/*z-index:0;*/
}
#main {
padding-top: 20px;
/*z-index:1;*/
}
#content {
margin: 0 auto;
max-width: 700px;
border: 1px solid #333;
padding: 20px;
border-radius: 20px;
background-color: rgba(0, 0, 0, 0.5);
line-height: 1.5rem;
box-shadow: 0 0 5px black;
/*z-index: 2;*/
}
code {
border: 1px solid #999;
background-color: rgba(0, 0, 0, 0.5);
padding: 5px;
border-radius: 5px;
display: block;
white-space: pre-line;
}
a {
color: orange;
text-decoration: none;
border-bottom: 1px dotted orange;
}
h2,
h3 {
color: #ccc;
}
hr {
border: 1px solid #999;
}
table {
width: 100%;
}
table,
th,
td {
border: 1px solid;
border-collapse: collapse;
}
table img {
max-width: 200px;
}

1
public/css/select2.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

BIN
public/img/quill.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
{
"name": "Metharme",
"system_prompt": "Write {{char}}'s next reply in a fictional roleplay chat between {{user}} and {{char}}.",
"system_prompt": "Enter roleplay mode. You must act as {{char}}, whose persona follows:",
"system_sequence": "<|system|>",
"stop_sequence": "</s>",
"input_sequence": "<|user|>",
"output_sequence": "<|model|>",
"separator_sequence": "",
"wrap": false
}
}

View File

@@ -0,0 +1,45 @@
{
"name": "Black Magic Time",
"movingUIState": {
"sheld": {
"top": 488,
"left": 1407,
"right": 1,
"bottom": 4,
"margin": "unset",
"width": 471,
"height": 439
},
"floatingPrompt": {
"width": 369,
"height": 441
},
"right-nav-panel": {
"top": 0,
"left": 1400,
"right": 111,
"bottom": 446,
"margin": "unset",
"width": 479,
"height": 487
},
"WorldInfo": {
"top": 41,
"left": 369,
"right": 642,
"bottom": 51,
"margin": "unset",
"width": 1034,
"height": 858
},
"left-nav-panel": {
"top": 442,
"left": 0,
"right": 1546,
"bottom": 25,
"margin": "unset",
"width": 368,
"height": 483
}
}
}

View File

@@ -0,0 +1,4 @@
{
"name": "Default",
"movingUIState": {}
}

View File

@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>SillyTavern Documentation</title>
<link rel="stylesheet" href="/css/notes.css">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
</head>
<body>
<div id="main">
<div id="content">
<h2>You weren't supposed to be able to get here, you know.</h1>
<h3>All help materials has been moved here:</h3>
<h3><a href="https://docs.sillytavern.app/">SillyTavern Documentation</a></h3>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -11,10 +11,14 @@ import {
is_send_press,
getTokenCount,
menu_type,
max_context,
saveSettingsDebounced,
} from "../script.js";
import {
characterStatsHandler,
} from "./stats.js";
import {
power_user,
@@ -27,7 +31,7 @@ import {
SECRET_KEYS,
secret_state,
} from "./secrets.js";
import { sortByCssOrder, debounce } from "./utils.js";
import { sortByCssOrder, debounce, delay } from "./utils.js";
import { chat_completion_sources, oai_settings } from "./openai.js";
var NavToggle = document.getElementById("nav-toggle");
@@ -104,22 +108,37 @@ function waitForElement(querySelector, timeout) {
});
}
waitForElement("#expression-image", 10000).then(function () {
/**
* Converts generation time from milliseconds to a human-readable format.
*
* The function takes total generation time as an input, then converts it to a format
* of "_ Days, _ Hours, _ Minutes, _ Seconds". If the generation time does not exceed a
* particular measure (like days or hours), that measure will not be included in the output.
*
* @param {number} total_gen_time - The total generation time in milliseconds.
* @returns {string} - A human-readable string that represents the time spent generating characters.
*/
export function humanizeGenTime(total_gen_time) {
dragElement(document.getElementById("expression-holder"));
dragElement(document.getElementById("floatingPrompt"));
//convert time_spent to humanized format of "_ Hours, _ Minutes, _ Seconds" from milliseconds
let time_spent = total_gen_time || 0;
time_spent = Math.floor(time_spent / 1000);
let seconds = time_spent % 60;
time_spent = Math.floor(time_spent / 60);
let minutes = time_spent % 60;
time_spent = Math.floor(time_spent / 60);
let hours = time_spent % 24;
time_spent = Math.floor(time_spent / 24);
let days = time_spent;
time_spent = "";
if (days > 0) { time_spent += `${days} Days, `; }
if (hours > 0) { time_spent += `${hours} Hours, `; }
if (minutes > 0) { time_spent += `${minutes} Minutes, `; }
time_spent += `${seconds} Seconds`;
return time_spent;
}
}).catch(() => {
console.log("expression holder not loaded yet");
});
waitForElement("#floatingPrompt", 10000).then(function () {
dragElement(document.getElementById("floatingPrompt"));
}).catch(() => {
console.log("floating prompt box not loaded yet");
});
// Device detection
export const deviceInfo = await getDeviceInfo();
@@ -177,6 +196,29 @@ export function humanizedDateTime() {
return HumanizedDateTime;
}
//this is a common format version to display a timestamp on each chat message
//returns something like: June 19, 2023 2:20pm
export function getMessageTimeStamp() {
const date = Date.now();
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const d = new Date(date);
const month = months[d.getMonth()];
const day = d.getDate();
const year = d.getFullYear();
let hours = d.getHours();
const minutes = ('0' + d.getMinutes()).slice(-2);
let meridiem = 'am';
if (hours >= 12) {
meridiem = 'pm';
hours -= 12;
}
if (hours === 0) {
hours = 12;
}
const formattedDate = month + ' ' + day + ', ' + year + ' ' + hours + ':' + minutes + meridiem;
return formattedDate;
}
// triggers:
$("#rm_button_create").on("click", function () { //when "+New Character" is clicked
@@ -263,21 +305,31 @@ export function RA_CountCharTokens() {
// if neither, probably safety char or some error in loading
} else { console.debug("RA_TC -- no valid char found, closing."); }
}
//label rm_stats_button with a tooltip indicating stats
$("#result_info").html(`<small>${count_tokens} Tokens (${perm_tokens} Permanent)</small>
<i title='Click for stats!' class="fa-solid fa-circle-info rm_stats_button"></i>`);
// display the counted tokens
if (count_tokens < 1024 && perm_tokens < 1024) {
//display normal if both counts are under 1024
$("#result_info").html(`<small>${count_tokens} Tokens (${perm_tokens} Permanent)</small>`);
const tokenLimit = Math.max(((main_api !== 'openai' ? max_context : oai_settings.openai_max_context) / 2), 1024);
if (count_tokens < tokenLimit && perm_tokens < tokenLimit) {
} else {
$("#result_info").html(`
<div class="flex-container flexFlowColumn alignitemscenter">
<div class="flex-container alignitemscenter">
<div class="flex-container flexnowrap flexNoGap">
<small class="flex-container flexnowrap flexNoGap">
<div class="neutral_warning">${count_tokens}</div>&nbsp;Tokens (<div class="neutral_warning">${perm_tokens}</div><div>&nbsp;Permanent)</div>
</small>
<i title='Click for stats!' class="fa-solid fa-circle-info rm_stats_button"></i>
</div>
<div id="chartokenwarning" class="menu_button whitespacenowrap"><a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-tokens" target="_blank">About Token 'Limits'</a></div>
<div id="chartokenwarning" class="menu_button margin0 whitespacenowrap"><a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-tokens" target="_blank">About Token 'Limits'</a></div>
</div>`);
} //warn if either are over 1024
$(".rm_stats_button").on('click', function () {
characterStatsHandler(characters, this_chid);
});
}
//Auto Load Last Charcter -- (fires when active_character is defined and auto_load_chat is true)
async function RA_autoloadchat() {
@@ -396,15 +448,15 @@ function RA_autoconnect(PrevApi) {
}
break;
case 'openai':
if (secret_state[SECRET_KEYS.OPENAI] || secret_state[SECRET_KEYS.CLAUDE] || oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI) {
if ((secret_state[SECRET_KEYS.OPENAI] && oai_settings.chat_completion_source == chat_completion_sources.OPENAI)
|| (secret_state[SECRET_KEYS.CLAUDE] && oai_settings.chat_completion_source == chat_completion_sources.CLAUDE)
|| (secret_state[SECRET_KEYS.SCALE] && oai_settings.chat_completion_source == chat_completion_sources.SCALE)
|| (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI)
|| (secret_state[SECRET_KEYS.OPENROUTER] && oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER)
) {
$("#api_button_openai").click();
}
break;
case 'poe':
if (secret_state[SECRET_KEYS.POE]) {
$("#poe_connect").click();
}
break;
}
if (!connection_made) {
@@ -450,160 +502,263 @@ function OpenNavPanels() {
// Make the DIV element draggable:
dragElement(document.getElementById("sheld"));
dragElement(document.getElementById("left-nav-panel"));
dragElement(document.getElementById("right-nav-panel"));
dragElement(document.getElementById("avatar_zoom_popup"));
dragElement(document.getElementById("WorldInfo"));
// THIRD UPDATE, prevent resize window breaks and smartly handle saving
export function dragElement(elmnt) {
var hasBeenDraggedByUser = false;
var isMouseDown = false;
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) { //ex: id="sheldheader"
// if present, the header is where you move the DIV from, but this overrides everything else:
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
var height, width, top, left, right, bottom,
maxX, maxY, winHeight, winWidth,
topbar, topbarWidth, topBarFirstX, topBarLastX, sheldWidth;
var elmntName = elmnt.attr('id');
const elmntNameEscaped = $.escapeSelector(elmntName);
const elmntHeader = $(`#${elmntNameEscaped}header`);
if (elmntHeader.length) {
elmntHeader.off('mousedown').on('mousedown', (e) => {
dragMouseDown(e);
});
$(elmnt).off('mousedown').on('mousedown', () => { isMouseDown = true })
} else {
// otherwise, move the DIV from anywhere inside the DIV, b:
elmnt.onmousedown = dragMouseDown;
elmnt.off('mousedown').on('mousedown', dragMouseDown);
}
const observer = new MutationObserver((mutations) => {
const target = mutations[0].target;
if (!$(target).is(':visible')
|| $(target).hasClass('resizing')
|| Number((String(target.height).replace('px', ''))) < 50
|| Number((String(target.width).replace('px', ''))) < 50
|| power_user.movingUI === false
|| isMobile() === true
) {
console.debug('aborting mutator')
return
}
//console.debug(left + width, winWidth, hasBeenDraggedByUser, isMouseDown)
const style = getComputedStyle(target); //use computed values because not all CSS are set by default
height = target.offsetHeight;
width = target.offsetWidth;
top = parseInt(style.top);
left = parseInt(style.left);
right = parseInt(style.right);
bottom = parseInt(style.bottom);
maxX = parseInt(width + left);
maxY = parseInt(height + top);
winWidth = window.innerWidth;
winHeight = window.innerHeight;
sheldWidth = parseInt($('html').css('--sheldWidth').slice(0, -2));
topbar = document.getElementById("top-bar")
const topbarstyle = getComputedStyle(topbar)
topBarFirstX = parseInt(topbarstyle.marginInline)
topbarWidth = parseInt(topbarstyle.width)
topBarLastX = topBarFirstX + topbarWidth;
/*console.log(`
winWidth: ${winWidth}, winHeight: ${winHeight}
sheldWidth: ${sheldWidth}
X: ${$(elmnt).css('left')}
Y: ${$(elmnt).css('top')}
MaxX: ${maxX}, MaxY: ${maxY}
height: ${height}
width: ${width}
Topbar 1st X: ${topBarFirstX}
TopBar lastX: ${topBarLastX}
`);*/
//prepare an empty poweruser object for the item being altered if we don't have one already
if (!power_user.movingUIState[elmntName]) {
console.debug(`adding config property for ${elmntName}`)
power_user.movingUIState[elmntName] = {};
}
//only record position changes if caused by a user click-drag
if (hasBeenDraggedByUser && isMouseDown) {
power_user.movingUIState[elmntName].top = top;
power_user.movingUIState[elmntName].left = left;
power_user.movingUIState[elmntName].right = right;
power_user.movingUIState[elmntName].bottom = bottom;
power_user.movingUIState[elmntName].margin = 'unset';
}
//handle resizing
if (!hasBeenDraggedByUser && isMouseDown) {
console.debug('saw resize, NOT header drag')
//prevent resizing offscreen
if (top + elmnt.height() >= winHeight) {
console.debug('resizing height to prevent offscreen')
elmnt.css('height', winHeight - top - 1 + "px");
}
if (left + elmnt.width() >= winWidth) {
console.debug('resizing width to prevent offscreen')
elmnt.css('width', winWidth - left - 1 + "px");
}
//prevent resizing from top left into the top bar
if (top <= 40 && maxX >= topBarFirstX && left <= topBarFirstX
) {
console.debug('prevent topbar underlap resize')
elmnt.css('width', width - 1 + "px");
}
//set css to prevent weird resize behavior (does not save)
elmnt.css('left', left)
elmnt.css('top', top)
//set a listener for mouseup to save new width/height
elmnt.off('mouseup').on('mouseup', () => {
console.debug(`Saving ${elmntName} Height/Width`)
power_user.movingUIState[elmntName].width = width;
power_user.movingUIState[elmntName].height = height;
saveSettingsDebounced();
})
}
//handle dragging hit detection
if (hasBeenDraggedByUser && isMouseDown) {
//prevent dragging offscreen
if (top <= 0) {
elmnt.css('top', '0px');
} else if (maxY >= winHeight) {
elmnt.css('top', winHeight - maxY + top - 1 + "px");
}
if (left <= 0) {
elmnt.css('left', '0px');
} else if (maxX >= winWidth) {
elmnt.css('left', winWidth - maxX + left - 1 + "px");
}
//prevent underlap with topbar div
if (top < 40
&& (maxX >= topBarFirstX && left <= topBarFirstX //elmnt is hitting topbar from left side
|| left <= topBarLastX && maxX >= topBarLastX //elmnt is hitting topbar from right side
|| left >= topBarFirstX && maxX <= topBarLastX) //elmnt hitting topbar in the middle
) {
console.debug('topbar hit')
elmnt.css('top', top + 1 + "px");
}
}
// Check if the element header exists and set the listener on the grabber
if (elmntHeader.length) {
elmntHeader.off('mousedown').on('mousedown', (e) => {
console.debug('listener started from header')
dragMouseDown(e);
});
} else {
elmnt.off('mousedown').on('mousedown', dragMouseDown);
}
});
observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] });
function dragMouseDown(e) {
//console.log(e);
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX; //mouse X at click
pos4 = e.clientY; //mouse Y at click
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
if (e) {
hasBeenDraggedByUser = true;
e.preventDefault();
pos3 = e.clientX; //mouse X at click
pos4 = e.clientY; //mouse Y at click
}
$(document).on('mouseup', closeDragElement);
$(document).on('mousemove', elementDrag);
}
function elementDrag(e) {
//disable scrollbars when dragging to prevent jitter
$("body").css("overflow", "hidden");
if (!power_user.movingUIState[elmntName]) {
power_user.movingUIState[elmntName] = {};
}
//get window size
let winWidth = window.innerWidth;
let winHeight = window.innerHeight;
//get necessary data for calculating element footprint
let draggableHeight = parseInt(getComputedStyle(elmnt).getPropertyValue('height').slice(0, -2));
let draggableWidth = parseInt(getComputedStyle(elmnt).getPropertyValue('width').slice(0, -2));
let draggableTop = parseInt(getComputedStyle(elmnt).getPropertyValue('top').slice(0, -2));
let draggableLeft = parseInt(getComputedStyle(elmnt).getPropertyValue('left').slice(0, -2));
let sheldWidth = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sheldWidth').slice(0, -2));
let topBarFirstX = (winWidth - sheldWidth) / 2;
let topBarLastX = topBarFirstX + sheldWidth;
//set the lowest and most-right pixel the element touches
let maxX = (draggableWidth + draggableLeft);
let maxY = (draggableHeight + draggableTop);
// calculate the new cursor position:
e = e || window.event;
e.preventDefault();
pos1 = pos3 - e.clientX; //X change amt
pos2 = pos4 - e.clientY; //Y change amt
pos1 = pos3 - e.clientX; //X change amt (-1 or 1)
pos2 = pos4 - e.clientY; //Y change amt (-1 or 1)
pos3 = e.clientX; //new mouse X
pos4 = e.clientY; //new mouse Y
elmnt.setAttribute('data-dragged', 'true');
elmnt.attr('data-dragged', 'true');
//fix over/underflows:
//first set css to computed values to avoid CSS NaN results from 'auto', etc
elmnt.css('left', (elmnt.offset().left) + "px");
elmnt.css("top", (elmnt.offset().top) + "px");
setTimeout(function () {
if (elmnt.offsetTop < 40) {
/* console.log('6'); */
if (maxX > topBarFirstX && maxX < topBarLastX) {
/* console.log('maxX inside topBar!'); */
elmnt.style.top = "42px";
}
if (elmnt.offsetLeft < topBarLastX && elmnt.offsetLeft > topBarFirstX) {
/* console.log('offsetLeft inside TopBar!'); */
elmnt.style.top = "42px";
}
}
//then update element position styles to account for drag changes
elmnt.css('margin', 'unset');
elmnt.css('left', (elmnt.offset().left - pos1) + "px");
elmnt.css("top", (elmnt.offset().top - pos2) + "px");
elmnt.css("right", ((winWidth - maxX) + "px"));
elmnt.css("bottom", ((winHeight - maxY) + "px"));
if (elmnt.offsetTop - pos2 <= 0) {
/* console.log('1'); */
//prevent going out of window top + 42px barrier for TopBar (can hide grabber)
elmnt.style.top = "0px";
}
if (elmnt.offsetLeft - pos1 <= 0) {
/* console.log('2'); */
//prevent moving out of window left
elmnt.style.left = "0px";
}
if (maxX >= winWidth) {
/* console.log('3'); */
//bounce off right
elmnt.style.left = elmnt.offsetLeft - 10 + "px";
}
if (maxY >= winHeight) {
/* console.log('4'); */
//bounce off bottom
elmnt.style.top = elmnt.offsetTop - 10 + "px";
if (elmnt.offsetTop - pos2 <= 40) {
/* console.log('5'); */
//prevent going out of window top + 42px barrier for TopBar (can hide grabber)
/* console.log('caught Y bounce to <40Y top'); */
elmnt.style.top = "20px";
}
}
// if no problems, set element's new position
/* console.log('7'); */
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
$(elmnt).css("bottom", "unset");
$(elmnt).css("right", "unset");
$(elmnt).css("margin", "unset");
/* console.log(`
offsetLeft: ${elmnt.offsetLeft}, offsetTop: ${elmnt.offsetTop}
winWidth: ${winWidth}, winHeight: ${winHeight}
sheldWidth: ${sheldWidth}
X: ${elmnt.style.left}
Y: ${elmnt.style.top}
MaxX: ${maxX}, MaxY: ${maxY}
Topbar 1st X: ${((winWidth - sheldWidth) / 2)}
TopBar lastX: ${((winWidth - sheldWidth) / 2) + sheldWidth}
`); */
}, 50)
/* console.log("left/top: " + (elmnt.offsetLeft - pos1) + "/" + (elmnt.offsetTop - pos2) +
", win: " + winWidth + "/" + winHeight +
", max X / Y: " + maxX + " / " + maxY); */
// Height/Width here are for visuals only, and are not saved to settings
// required because some divs do hot have a set width/height..
// and will defaults to shrink to min value of 100px set in CSS file
elmnt.css('height', height)
elmnt.css('width', width)
/*
console.log(`
winWidth: ${winWidth}, winHeight: ${winHeight}
sheldWidth: ${sheldWidth}
X: ${$(elmnt).css('left')}
Y: ${$(elmnt).css('top')}
MaxX: ${maxX}, MaxY: ${maxY}
height: ${height}
width: ${width}
Topbar 1st X: ${topBarFirstX}
TopBar lastX: ${topBarLastX}
`);
*/
return
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
//revert scrolling to normal after drag to allow recovery of vastly misplaced elements
$("body").css("overflow", "auto");
console.debug('drag finished')
hasBeenDraggedByUser = false;
isMouseDown = false;
$(document).off('mouseup', closeDragElement);
$(document).off('mousemove', elementDrag);
$("body").css("overflow", "");
// Clear the "data-dragged" attribute
elmnt.attr('data-dragged', 'false');
console.debug(`Saving ${elmntName} UI position`)
saveSettingsDebounced();
}
}
export async function initMovingUI() {
if (isMobile() === false && power_user.movingUI === true) {
console.debug('START MOVING UI')
dragElement($("#sheld"));
dragElement($("#left-nav-panel"));
dragElement($("#right-nav-panel"));
dragElement($("#WorldInfo"));
await delay(1000)
console.debug('loading AN draggable function')
dragElement($("#floatingPrompt"))
}
}
// ---------------------------------------------------
$("document").ready(function () {
// initial status check
setTimeout(RA_checkOnlineStatus, 100);
setTimeout(() => {
RA_checkOnlineStatus();
}, 100);
// read the state of AutoConnect and AutoLoadChat.
$(AutoConnectCheckbox).prop("checked", LoadLocalBool("AutoConnectEnabled"));
@@ -790,7 +945,7 @@ $("document").ready(function () {
function isInputElementInFocus() {
//return $(document.activeElement).is(":input");
var focused = $(':focus');
if (focused.is('input') || focused.is('textarea') || focused.attr('contenteditable') == 'true') {
if (focused.is('input') || focused.is('textarea') || focused.prop('contenteditable') == 'true') {
if (focused.attr('id') === 'send_textarea') {
return false;
}

View File

@@ -5,27 +5,33 @@ import {
getTokenCount,
saveSettingsDebounced,
this_chid,
} from "../../../script.js";
import { selected_group } from "../../group-chats.js";
import { ModuleWorkerWrapper, extension_settings, getContext, saveMetadataDebounced } from "../../extensions.js";
import { registerSlashCommand } from "../../slash-commands.js";
import { getCharaFilename, debounce } from "../../utils.js";
export { MODULE_NAME };
} from "../script.js";
import { selected_group } from "./group-chats.js";
import { extension_settings, getContext, saveMetadataDebounced } from "./extensions.js";
import { registerSlashCommand } from "./slash-commands.js";
import { getCharaFilename, debounce, waitUntilCondition, delay } from "./utils.js";
export { MODULE_NAME as NOTE_MODULE_NAME };
const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory
const UPDATE_INTERVAL = 1000;
const DEFAULT_DEPTH = 4;
const DEFAULT_POSITION = 1;
const DEFAULT_INTERVAL = 1;
export var shouldWIAddPrompt = false;
const metadata_keys = {
export const metadata_keys = {
prompt: 'note_prompt',
interval: 'note_interval',
depth: 'note_depth',
position: 'note_position',
}
const chara_note_position = {
replace: 0,
before: 1,
after: 2,
}
function setNoteTextCommand(_, text) {
$('#extension_floating_prompt').val(text).trigger('input');
toastr.success("Author's Note text updated");
@@ -72,6 +78,12 @@ function setNotePositionCommand(_, text) {
toastr.info("Author's Note position updated");
}
function updateSettings() {
saveSettingsDebounced();
loadSettings();
setFloatingPrompt();
}
const setMainPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_prompt_token_counter').text(getTokenCount(value)), 1000);
const setCharaPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_chara_token_counter').text(getTokenCount(value)), 1000);
const setDefaultPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_default_token_counter').text(getTokenCount(value)), 1000);
@@ -79,11 +91,13 @@ const setDefaultPromptTokenCounterDebounced = debounce((value) => $('#extension_
async function onExtensionFloatingPromptInput() {
chat_metadata[metadata_keys.prompt] = $(this).val();
setMainPromptTokenCounterDebounced(chat_metadata[metadata_keys.prompt]);
updateSettings();
saveMetadataDebounced();
}
async function onExtensionFloatingIntervalInput() {
chat_metadata[metadata_keys.interval] = Number($(this).val());
updateSettings();
saveMetadataDebounced();
}
@@ -96,14 +110,26 @@ async function onExtensionFloatingDepthInput() {
}
chat_metadata[metadata_keys.depth] = value;
updateSettings();
saveMetadataDebounced();
}
async function onExtensionFloatingPositionInput(e) {
chat_metadata[metadata_keys.position] = e.target.value;
updateSettings();
saveMetadataDebounced();
}
async function onExtensionFloatingCharPositionInput(e) {
const value = e.target.value;
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
if (charaNote) {
charaNote.position = Number(value);
updateSettings();
}
}
function onExtensionFloatingCharaPromptInput() {
const tempPrompt = $(this).val();
const avatarName = getCharaFilename();
@@ -136,7 +162,7 @@ function onExtensionFloatingCharaPromptInput() {
if (!extension_settings.note.chara) {
extension_settings.note.chara = []
}
Object.assign(tempCharaNote, { useChara: false })
Object.assign(tempCharaNote, { useChara: false, position: chara_note_position.replace })
extension_settings.note.chara.push(tempCharaNote);
} else {
@@ -147,7 +173,7 @@ function onExtensionFloatingCharaPromptInput() {
return;
}
saveSettingsDebounced();
updateSettings();
}
function onExtensionFloatingCharaCheckboxChanged() {
@@ -157,14 +183,14 @@ function onExtensionFloatingCharaCheckboxChanged() {
if (charaNote) {
charaNote.useChara = value;
saveSettingsDebounced();
updateSettings();
}
}
function onExtensionFloatingDefaultInput() {
extension_settings.note.default = $(this).val();
setDefaultPromptTokenCounterDebounced(extension_settings.note.default);
saveSettingsDebounced();
updateSettings();
}
function loadSettings() {
@@ -177,28 +203,39 @@ function loadSettings() {
$('#extension_floating_depth').val(chat_metadata[metadata_keys.depth]);
$(`input[name="extension_floating_position"][value="${chat_metadata[metadata_keys.position]}"]`).prop('checked', true);
if (extension_settings.note.chara) {
if (extension_settings.note.chara && getContext().characterId) {
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
$('#extension_floating_chara').val(charaNote ? charaNote.prompt : '');
$('#extension_use_floating_chara').prop('checked', charaNote ? charaNote.useChara : false);
$(`input[name="extension_floating_char_position"][value="${charaNote?.position ?? chara_note_position.replace}"]`).prop('checked', true);
} else {
$('#extension_floating_chara').val('');
$('#extension_use_floating_chara').prop('checked', false);
$(`input[name="extension_floating_char_position"][value="${chara_note_position.replace}"]`).prop('checked', true);
}
$('#extension_floating_default').val(extension_settings.note.default);
}
async function moduleWorker() {
export function setFloatingPrompt() {
const context = getContext();
if (!context.groupId && context.characterId === undefined) {
console.debug('setFloatingPrompt: Not in a chat. Skipping.');
shouldWIAddPrompt = false;
return;
}
loadSettings();
// take the count of messages
let lastMessageNumber = Array.isArray(context.chat) && context.chat.length ? context.chat.filter(m => m.is_user).length : 0;
console.debug(`
setFloatingPrompt entered
------
lastMessageNumber = ${lastMessageNumber}
metadata_keys.interval = ${chat_metadata[metadata_keys.interval]}
`)
// interval 1 should be inserted no matter what
if (chat_metadata[metadata_keys.interval] === 1) {
lastMessageNumber = 1;
@@ -207,6 +244,7 @@ async function moduleWorker() {
if (lastMessageNumber <= 0 || chat_metadata[metadata_keys.interval] <= 0) {
context.setExtensionPrompt(MODULE_NAME, '');
$('#extension_floating_counter').text('(disabled)');
shouldWIAddPrompt = false;
return;
}
@@ -214,41 +252,64 @@ async function moduleWorker() {
? (lastMessageNumber % chat_metadata[metadata_keys.interval])
: (chat_metadata[metadata_keys.interval] - lastMessageNumber);
const shouldAddPrompt = messagesTillInsertion == 0;
shouldWIAddPrompt = shouldAddPrompt;
let prompt = shouldAddPrompt ? $('#extension_floating_prompt').val() : '';
if (shouldAddPrompt && extension_settings.note.chara) {
if (shouldAddPrompt && extension_settings.note.chara && getContext().characterId) {
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
// Only replace with the chara note if the user checked the box
if (charaNote && charaNote.useChara) {
prompt = charaNote.prompt;
switch (charaNote.position) {
case chara_note_position.before:
prompt = charaNote.prompt + '\n' + prompt;
break;
case chara_note_position.after:
prompt = prompt + '\n' + charaNote.prompt;
break;
default:
prompt = charaNote.prompt;
break;
}
}
}
context.setExtensionPrompt(MODULE_NAME, prompt, chat_metadata[metadata_keys.position], chat_metadata[metadata_keys.depth]);
$('#extension_floating_counter').text(shouldAddPrompt ? '0' : messagesTillInsertion);
}
function onANMenuItemClick() {
if (selected_group || this_chid) {
//show AN if it's hidden
if ($("#floatingPrompt").css("display") !== 'flex') {
$("#floatingPrompt").addClass('resizing')
$("#floatingPrompt").css("display", "flex");
$("#floatingPrompt").css("opacity", 0.0);
$("#floatingPrompt").transition({
opacity: 1.0,
duration: 250,
}, async function () {
await delay(50);
$("#floatingPrompt").removeClass('resizing')
});
//auto-open the main AN inline drawer
if ($("#ANBlockToggle")
.siblings('.inline-drawer-content')
.css('display') !== 'block') {
$("#floatingPrompt").addClass('resizing')
$("#ANBlockToggle").click();
}
} else {
//hide AN if it's already displayed
$("#floatingPrompt").addClass('resizing')
$("#floatingPrompt").transition({
opacity: 0.0,
duration: 250,
});
},
async function () {
await delay(50);
$("#floatingPrompt").removeClass('resizing')
});
setTimeout(function () {
$("#floatingPrompt").hide();
}, 250);
@@ -263,11 +324,18 @@ function onANMenuItemClick() {
}
function onChatChanged() {
loadSettings();
setFloatingPrompt();
const context = getContext();
// Disable the chara note if in a group
$('#extension_floating_chara').prop('disabled', context.groupId ? true : false);
const tokenCounter1 = chat_metadata[metadata_keys.prompt] ? getTokenCount(chat_metadata[metadata_keys.prompt]) : 0;
$('#extension_floating_prompt_token_counter').text(tokenCounter1);
let tokenCounter2;
if (extension_settings.note.chara) {
if (extension_settings.note.chara && context.characterId) {
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
if (charaNote) {
@@ -283,120 +351,31 @@ function onChatChanged() {
$('#extension_floating_default_token_counter').text(tokenCounter3);
}
(function () {
function addExtensionsSettings() {
const settingsHtml = `
<div id="floatingPrompt" class="drawer-content flexGap5">
<div class="panelControlBar flex-container">
<div id="floatingPromptheader" class="fa-solid fa-grip drag-grabber"></div>
<div id="ANClose" class="fa-solid fa-circle-xmark"></div>
</div>
<div name="floatingPromptHolder">
<div class="inline-drawer">
<div id="ANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
<b>Author's Note</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
// Inject extension when extensions_activating is fired
// Inserts the extension first since it's statically imported
jQuery(async () => {
await waitUntilCondition(() => eventSource !== undefined);
$('#extension_floating_prompt').on('input', onExtensionFloatingPromptInput);
$('#extension_floating_interval').on('input', onExtensionFloatingIntervalInput);
$('#extension_floating_depth').on('input', onExtensionFloatingDepthInput);
$('#extension_floating_chara').on('input', onExtensionFloatingCharaPromptInput);
$('#extension_use_floating_chara').on('input', onExtensionFloatingCharaCheckboxChanged);
$('#extension_floating_default').on('input', onExtensionFloatingDefaultInput);
$('input[name="extension_floating_position"]').on('change', onExtensionFloatingPositionInput);
$('input[name="extension_floating_char_position"]').on('change', onExtensionFloatingCharPositionInput);
$('#ANClose').on('click', function () {
$("#floatingPrompt").transition({
opacity: 0,
duration: 200,
easing: 'ease-in-out',
});
setTimeout(function () { $('#floatingPrompt').hide() }, 200);
})
$("#option_toggle_AN").on('click', onANMenuItemClick);
</div>
<div class="inline-drawer-content">
<small>
<b>Unique to this chat</b>.<br>
Bookmarks inherit the Note from their parent, and can be changed individually after that.<br>
</small>
<textarea id="extension_floating_prompt" class="text_pole" rows="8" maxlength="10000"></textarea>
<div class="extension_token_counter">Tokens: <span id="extension_floating_prompt_token_counter">0</small></div>
<div class="floating_prompt_radio_group">
<label>
<input type="radio" name="extension_floating_position" value="0" />
After scenario
</label>
<label>
<input type="radio" name="extension_floating_position" value="1" />
In-chat @ Depth <input id="extension_floating_depth" class="text_pole widthUnset" type="number" min="0" max="99" />
</label>
</div>
<!--<label for="extension_floating_interval">In-Chat Insertion Depth</label>-->
<label for="extension_floating_interval">Insertion Frequency</label>
<input id="extension_floating_interval" class="text_pole widthUnset" type="number" min="0" max="999" /><small> (0 = Disable, 1 = Always)</small>
<br>
<span>User inputs until next insertion: <span id="extension_floating_counter">(disabled)</span></span>
</div>
</div>
<hr class="sysHR">
<div class="inline-drawer">
<div id="charaANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
<b>Character Author's Note</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<small>Will be automatically added as the author's note for this character.</small>
<textarea id="extension_floating_chara" class="text_pole" rows="8" maxlength="10000"
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
<div class="extension_token_counter">Tokens: <span id="extension_floating_chara_token_counter">0</small></div>
<label for="extension_use_floating_chara">
<input id="extension_use_floating_chara" type="checkbox" />
<span data-i18n="Use character author's note">Use character author's note</span>
</label>
</div>
</div>
<hr class="sysHR">
<div class="inline-drawer">
<div id="defaultANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
<b>Default Author's Note</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<small>Will be automatically added as the Author's Note for all new chats.</small>
<textarea id="extension_floating_default" class="text_pole" rows="8" maxlength="10000"
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
<div class="extension_token_counter">Tokens: <span id="extension_floating_default_token_counter">0</small></div>
</div>
</div>
</div>
</div>
`;
const ANButtonHtml = `
<a id="option_toggle_AN">
<i class="fa-lg fa-solid fa-note-sticky"></i>
<span data-i18n="Author's Note">Author's Note</span>
</a>
`;
$('#options .options-content').prepend(ANButtonHtml);
$('#movingDivs').append(settingsHtml);
$('#extension_floating_prompt').on('input', onExtensionFloatingPromptInput);
$('#extension_floating_interval').on('input', onExtensionFloatingIntervalInput);
$('#extension_floating_depth').on('input', onExtensionFloatingDepthInput);
$('#extension_floating_chara').on('input', onExtensionFloatingCharaPromptInput);
$('#extension_use_floating_chara').on('input', onExtensionFloatingCharaCheckboxChanged);
$('#extension_floating_default').on('input', onExtensionFloatingDefaultInput);
$('input[name="extension_floating_position"]').on('change', onExtensionFloatingPositionInput);
$('#ANClose').on('click', function () {
$("#floatingPrompt").transition({
opacity: 0,
duration: 200,
easing: 'ease-in-out',
});
setTimeout(function () { $('#floatingPrompt').hide() }, 200);
})
$("#option_toggle_AN").on('click', onANMenuItemClick);
}
addExtensionsSettings();
const wrapper = new ModuleWorkerWrapper(moduleWorker);
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL);
registerSlashCommand('note', setNoteTextCommand, [], "<span class='monospace'>(text)</span> sets an author's note for the currently selected chat", true, true);
registerSlashCommand('depth', setNoteDepthCommand, [], "<span class='monospace'>(number)</span> sets an author's note depth for in-chat positioning", true, true);
registerSlashCommand('freq', setNoteIntervalCommand, ['interval'], "<span class='monospace'>(number)</span> sets an author's note insertion frequency", true, true);
registerSlashCommand('pos', setNotePositionCommand, ['position'], "(<span class='monospace'>chat</span> or <span class='monospace'>scenario</span>) sets an author's note position", true, true);
eventSource.on(event_types.CHAT_CHANGED, onChatChanged);
})();
});

View File

@@ -32,6 +32,7 @@ import {
} from "./utils.js";
export {
createNewBookmark,
showBookmarksButtons,
}
@@ -123,13 +124,26 @@ function showBookmarksButtons() {
}
}
async function createNewBookmark() {
async function saveBookmarkMenu() {
if (!chat.length) {
toastr.warning('The chat is empty.', 'Bookmark creation failed');
return;
}
const mesId = chat.length - 1;
return createNewBookmark(chat.length - 1);
}
async function createNewBookmark(mesId) {
if (!chat.length) {
toastr.warning('The chat is empty.', 'Bookmark creation failed');
return;
}
if (mesId < 0 || mesId >= chat.length) {
toastr.warning('Invalid message ID.', 'Bookmark creation failed');
return;
}
const lastMes = chat[mesId];
if (typeof lastMes.extra !== 'object') {
@@ -155,9 +169,9 @@ async function createNewBookmark() {
const newMetadata = { main_chat: mainChat };
if (selected_group) {
await saveGroupBookmarkChat(selected_group, name, newMetadata);
await saveGroupBookmarkChat(selected_group, name, newMetadata, mesId);
} else {
await saveChat(name, newMetadata);
await saveChat(name, newMetadata, mesId);
}
lastMes.extra['bookmark_link'] = name;
@@ -294,7 +308,7 @@ async function convertSoloToGroupChat() {
}
$(document).ready(function () {
$('#option_new_bookmark').on('click', createNewBookmark);
$('#option_new_bookmark').on('click', saveBookmarkMenu);
$('#option_back_to_main').on('click', backToMainChat);
$('#option_convert_to_group').on('click', convertSoloToGroupChat);
});

View File

@@ -1,4 +1,4 @@
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced } from "../script.js";
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders } from "../script.js";
import { isSubsetOf, debounce } from "./utils.js";
export {
getContext,
@@ -51,16 +51,25 @@ const extension_settings = {
note: {
default: '',
chara: [],
wiAddition: [],
},
caption: {
refine_mode: false,
},
caption: {},
expressions: {},
dice: {},
regex: [],
tts: {},
sd: {},
chromadb: {},
translate: {},
objective: {},
quickReply: {},
randomizer: {
controls: [],
fluctuation: 0.1,
enabled: false,
},
};
let modules = [];
@@ -158,6 +167,8 @@ async function getManifests(names) {
const json = await response.json();
obj[name] = json;
resolve();
} else {
reject();
}
}).catch(err => reject() && console.log('Could not load manifest.json for ' + name, err));
});
@@ -369,40 +380,218 @@ function addExtensionScript(name, manifest) {
return Promise.resolve();
}
function showExtensionsDetails() {
let html = '<h3>Modules provided by your Extensions API:</h3>';
html += modules.length ? DOMPurify.sanitize(modules.join(', ')) : '<p class="failure">Not connected to the API!</p>';
html += '<h3>Available extensions:</h3>';
Object.entries(manifests).sort((a, b) => a[1].loading_order - b[1].loading_order).forEach(extension => {
const name = extension[0];
const manifest = extension[1];
html += `<h4>${DOMPurify.sanitize(manifest.display_name)}</h4>`;
if (activeExtensions.has(name)) {
html += `<p class="success">Extension is active. <a href="javascript:void" data-name="${name}" class="disable_extension">Click to Disable</a></p>`;
if (Array.isArray(manifest.optional)) {
const optional = new Set(manifest.optional);
modules.forEach(x => optional.delete(x));
if (optional.size > 0) {
const optionalString = DOMPurify.sanitize([...optional].join(', '));
html += `<p>Optional modules: <span class="optional">${optionalString}</span></p>`;
}
}
}
else if (extension_settings.disabledExtensions.includes(name)) {
html += `<p class="disabled">Extension is disabled. <a href="javascript:void" data-name=${name} class="enable_extension">Click to Enable</a></p>`;
}
else {
const requirements = new Set(manifest.requires);
modules.forEach(x => requirements.delete(x));
const requirementsString = DOMPurify.sanitize([...requirements].join(', '));
html += `<p>Missing modules: <span class="failure">${requirementsString}</span></p>`
}
});
/**
* Generates HTML string for displaying an extension in the UI.
*
* @param {string} name - The name of the extension.
* @param {object} manifest - The manifest of the extension.
* @param {boolean} isActive - Whether the extension is active or not.
* @param {boolean} isDisabled - Whether the extension is disabled or not.
* @param {boolean} isExternal - Whether the extension is external or not.
* @param {string} checkboxClass - The class for the checkbox HTML element.
* @return {string} - The HTML string that represents the extension.
*/
async function generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal, checkboxClass) {
const displayName = manifest.display_name;
let displayVersion = manifest.version ? ` v${manifest.version}` : "";
let isUpToDate = true;
let updateButton = '';
let originHtml = '';
if (isExternal) {
let data = await getExtensionVersion(name.replace('third-party', ''));
let branch = data.currentBranchName;
let commitHash = data.currentCommitHash;
let origin = data.remoteUrl
isUpToDate = data.isUpToDate;
displayVersion = ` (${branch}-${commitHash.substring(0, 7)})`;
updateButton = isUpToDate ?
`<span class="update-button"><button class="btn_update menu_button" data-name="${name.replace('third-party', '')}" title="Up to date"><i class="fa-solid fa-code-commit"></i></button></span>` :
`<span class="update-button"><button class="btn_update menu_button" data-name="${name.replace('third-party', '')}" title="Update available"><i class="fa-solid fa-download"></i></button></span>`;
originHtml = `<a href="${origin}" target="_blank" rel="noopener noreferrer">`;
}
let toggleElement = isActive || isDisabled ?
`<input type="checkbox" title="Click to toggle" data-name="${name}" class="${isActive ? 'toggle_disable' : 'toggle_enable'} ${checkboxClass}" ${isActive ? 'checked' : ''}>` :
`<input type="checkbox" title="Cannot enable extension" data-name="${name}" class="extension_missing ${checkboxClass}" disabled>`;
let deleteButton = isExternal ? `<span class="delete-button"><button class="btn_delete menu_button" data-name="${name.replace('third-party', '')}" title="Delete"><i class="fa-solid fa-trash-can"></i></button></span>` : '';
// if external, wrap the name in a link to the repo
let extensionHtml = `<hr>
<h4>
${updateButton}
${deleteButton}
${originHtml}
<span class="${isActive ? "extension_enabled" : isDisabled ? "extension_disabled" : "extension_missing"}">
${DOMPurify.sanitize(displayName)}${displayVersion}
</span>
${isExternal ? '</a>' : ''}
<span style="float:right;">${toggleElement}</span>
</h4>`;
if (isActive && Array.isArray(manifest.optional)) {
const optional = new Set(manifest.optional);
modules.forEach(x => optional.delete(x));
if (optional.size > 0) {
const optionalString = DOMPurify.sanitize([...optional].join(', '));
extensionHtml += `<p>Optional modules: <span class="optional">${optionalString}</span></p>`;
}
} else if (!isDisabled) { // Neither active nor disabled
const requirements = new Set(manifest.requires);
modules.forEach(x => requirements.delete(x));
const requirementsString = DOMPurify.sanitize([...requirements].join(', '));
extensionHtml += `<p>Missing modules: <span class="failure">${requirementsString}</span></p>`;
}
return extensionHtml;
}
/**
* Gets extension data and generates the corresponding HTML for displaying the extension.
*
* @param {Array} extension - An array where the first element is the extension name and the second element is the extension manifest.
* @return {object} - An object with 'isExternal' indicating whether the extension is external, and 'extensionHtml' for the extension's HTML string.
*/
async function getExtensionData(extension) {
const name = extension[0];
const manifest = extension[1];
const isActive = activeExtensions.has(name);
const isDisabled = extension_settings.disabledExtensions.includes(name);
const isExternal = name.startsWith('third-party');
const checkboxClass = isDisabled ? "checkbox_disabled" : "";
const extensionHtml = await generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal, checkboxClass);
return { isExternal, extensionHtml };
}
/**
* Gets the module information to be displayed.
*
* @return {string} - The HTML string for the module information.
*/
function getModuleInformation() {
let moduleInfo = modules.length ? `<p>${DOMPurify.sanitize(modules.join(', '))}</p>` : '<p class="failure">Not connected to the API!</p>';
return `
<h3>Modules provided by your Extensions API:</h3>
${moduleInfo}
`;
}
/**
* Generates the HTML strings for all extensions and displays them in a popup.
*/
async function showExtensionsDetails() {
let htmlDefault = '<h3>Default Extensions:</h3>';
let htmlExternal = '<h3>External Extensions:</h3>';
const extensions = Object.entries(manifests).sort((a, b) => a[1].loading_order - b[1].loading_order);
for (const extension of extensions) {
const { isExternal, extensionHtml } = await getExtensionData(extension);
if (isExternal) {
htmlExternal += extensionHtml;
} else {
htmlDefault += extensionHtml;
}
}
const html = `
${getModuleInformation()}
${htmlDefault}
${htmlExternal}
`;
callPopup(`<div class="extensions_info">${html}</div>`, 'text');
}
/**
* Handles the click event for the update button of an extension.
* This function makes a POST request to '/update_extension' with the extension's name.
* If the extension is already up to date, it displays a success message.
* If the extension is not up to date, it updates the extension and displays a success message with the new commit hash.
*/
async function onUpdateClick() {
const extensionName = $(this).data('name');
try {
const response = await fetch('/update_extension', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({ extensionName })
});
const data = await response.json();
if (data.isUpToDate) {
toastr.success('Extension is already up to date');
} else {
toastr.success(`Extension updated to ${data.shortCommitHash}`);
}
showExtensionsDetails();
} catch (error) {
console.error('Error:', error);
}
};
/**
* Handles the click event for the delete button of an extension.
* This function makes a POST request to '/delete_extension' with the extension's name.
* If the extension is deleted, it displays a success message.
* Creates a popup for the user to confirm before delete.
*/
async function onDeleteClick() {
const extensionName = $(this).data('name');
// use callPopup to create a popup for the user to confirm before delete
const confirmation = await callPopup(`Are you sure you want to delete ${extensionName}?`, 'delete_extension');
if (confirmation) {
try {
const response = await fetch('/delete_extension', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({ extensionName })
});
} catch (error) {
console.error('Error:', error);
}
toastr.success(`Extension ${extensionName} deleted`);
showExtensionsDetails();
// reload the page to remove the extension from the list
location.reload();
}
};
/**
* Fetches the version details of a specific extension.
*
* @param {string} extensionName - The name of the extension.
* @return {object} - An object containing the extension's version details.
* This object includes the currentBranchName, currentCommitHash, isUpToDate, and remoteUrl.
* @throws {error} - If there is an error during the fetch operation, it logs the error to the console.
*/
async function getExtensionVersion(extensionName) {
try {
const response = await fetch('/get_extension_version', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({ extensionName })
});
const data = await response.json();
return data;
} catch (error) {
console.error('Error:', error);
}
}
async function loadExtensionSettings(settings) {
if (settings.extension_settings) {
Object.assign(extension_settings, settings.extension_settings);
@@ -413,6 +602,7 @@ async function loadExtensionSettings(settings) {
$("#extensions_autoconnect").prop('checked', extension_settings.autoConnect);
// Activate offline extensions
eventSource.emit(event_types.EXTENSIONS_FIRST_LOAD);
extensionNames = await discoverExtensions();
manifests = await getManifests(extensionNames)
await activateExtensions();
@@ -421,12 +611,12 @@ async function loadExtensionSettings(settings) {
}
}
async function runGenerationInterceptors(chat) {
async function runGenerationInterceptors(chat, contextSize) {
for (const manifest of Object.values(manifests)) {
const interceptorKey = manifest.generate_interceptor;
if (typeof window[interceptorKey] === 'function') {
try {
await window[interceptorKey](chat);
await window[interceptorKey](chat, contextSize);
} catch (e) {
console.error(`Failed running interceptor for ${manifest.display_name}`, e);
}
@@ -443,6 +633,8 @@ $(document).ready(async function () {
$("#extensions_connect").on('click', connectClickHandler);
$("#extensions_autoconnect").on('input', autoConnectInputHandler);
$("#extensions_details").on('click', showExtensionsDetails);
$(document).on('click', '.disable_extension', onDisableExtensionClick);
$(document).on('click', '.enable_extension', onEnableExtensionClick);
$(document).on('click', '.toggle_disable', onDisableExtensionClick);
$(document).on('click', '.toggle_enable', onEnableExtensionClick);
$(document).on('click', '.btn_update', onUpdateClick);
$(document).on('click', '.btn_delete', onDeleteClick);
});

View File

@@ -120,7 +120,7 @@ $(document).ready(function () {
<div class="background_settings">
<div class="inline-drawer">
<div class="inline-drawer-toggle inline-drawer-header">
<b>Character Backgrounds</b>
<b>Chat Backgrounds</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">

View File

@@ -1,5 +1,5 @@
{
"display_name": "Character Backgrounds",
"display_name": "Chat Backgrounds",
"loading_order": 7,
"requires": [],
"optional": [],

View File

@@ -1,5 +1,6 @@
import { getBase64Async } from "../../utils.js";
import { getContext, getApiUrl, doExtrasFetch } from "../../extensions.js";
import { getContext, getApiUrl, doExtrasFetch, extension_settings } from "../../extensions.js";
import { callPopup, saveSettingsDebounced } from "../../../script.js";
export { MODULE_NAME };
const MODULE_NAME = 'caption';
@@ -33,7 +34,20 @@ async function setSpinnerIcon() {
async function sendCaptionedMessage(caption, image) {
const context = getContext();
const messageText = `[${context.name1} sends ${context.name2 ?? ''} a picture that contains: ${caption}]`;
let messageText = `[${context.name1} sends ${context.name2 ?? ''} a picture that contains: ${caption}]`;
if (extension_settings.caption.refine_mode) {
messageText = await callPopup(
'<h3>Review and edit the generated message:</h3>Press "Cancel" to abort the caption sending.',
'input',
messageText,
{ rows: 5, okButton: 'Send' });
if (!messageText) {
throw new Error('User aborted the caption sending.');
}
}
const message = {
name: context.name1,
is_user: true,
@@ -42,12 +56,12 @@ async function sendCaptionedMessage(caption, image) {
mes: messageText,
extra: {
image: image,
title: caption,
title: messageText,
},
};
context.chat.push(message);
context.addOneMessage(message);
await context.generate();
await context.generate('caption');
}
async function onSelectImage(e) {
@@ -88,6 +102,11 @@ async function onSelectImage(e) {
}
}
function onRefineModeInput() {
extension_settings.caption.refine_mode = $('#caption_refine_mode').prop('checked');
saveSettingsDebounced();
}
jQuery(function () {
function addSendPictureButton() {
const sendButton = $(`
@@ -109,10 +128,32 @@ jQuery(function () {
$('#form_sheld').append(imgForm);
$('#img_file').on('change', onSelectImage);
}
function addSettings() {
const html = `
<div class="background_settings">
<div class="inline-drawer">
<div class="inline-drawer-toggle inline-drawer-header">
<b>Image Captioning</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<label class="checkbox_label" for="caption_refine_mode">
<input id="caption_refine_mode" type="checkbox" class="checkbox">
Edit captions before generation
</label>
</div>
</div>
</div>
`;
$('#extensions_settings2').append(html);
}
addSettings();
addPictureSendForm();
addSendPictureButton();
setImageIcon();
moduleWorker();
$('#caption_refine_mode').prop('checked', !!(extension_settings.caption.refine_mode));
$('#caption_refine_mode').on('input', onRefineModeInput);
setInterval(moduleWorker, UPDATE_INTERVAL);
});

View File

@@ -10,7 +10,7 @@ async function doDiceRoll(customDiceFormula) {
let value = typeof customDiceFormula === 'string' ? customDiceFormula.trim() : $(this).data('value');
if (value == 'custom') {
value = await callPopup('Enter the dice formula:<br><i>(for example, <tt>2d6</tt>)</i>', 'input');x
value = await callPopup('Enter the dice formula:<br><i>(for example, <tt>2d6</tt>)</i>', 'input');
}
if (!value) {
@@ -76,20 +76,11 @@ function addDiceRollButton() {
});
}
function addDiceScript() {
if (!window.droll) {
const script = document.createElement('script');
script.src = "/scripts/extensions/dice/droll.js";
document.body.appendChild(script);
}
}
async function moduleWorker() {
$('#roll_dice').toggle(getContext().onlineStatus !== 'no_connection');
}
jQuery(function () {
addDiceScript();
addDiceRollButton();
moduleWorker();
setInterval(moduleWorker, UPDATE_INTERVAL);

View File

@@ -1,7 +1,7 @@
import { callPopup, eventSource, event_types, getRequestHeaders, saveSettingsDebounced } from "../../../script.js";
import { dragElement, isMobile } from "../../RossAscends-mods.js";
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch } from "../../extensions.js";
import { power_user } from "../../power-user.js";
import { loadMovingUIState, power_user } from "../../power-user.js";
import { onlyUnique, debounce, getCharaFilename } from "../../utils.js";
export { MODULE_NAME };
@@ -152,7 +152,7 @@ async function visualNovelSetCharacterSprites(container, name, expression) {
const path = currentSpritePath || defaultSpritePath || '';
const img = expressionImage.find('img');
setImage(img, path);
await setImage(img, path);
}
expressionImage.toggleClass('hidden', noSprites);
} else {
@@ -161,9 +161,9 @@ async function visualNovelSetCharacterSprites(container, name, expression) {
template.attr('data-avatar', avatar);
template.find('.drag-grabber').attr('id', `expression-${avatar}header`);
$('#visual-novel-wrapper').append(template);
dragElement(template[0]);
dragElement($(template[0]));
template.toggleClass('hidden', noSprites);
setImage(template.find('img'), defaultSpritePath || '');
await setImage(template.find('img'), defaultSpritePath || '');
const fadeInPromise = new Promise(resolve => {
template.fadeIn(250, () => resolve());
});
@@ -182,20 +182,20 @@ async function visualNovelUpdateLayers(container) {
const group = context.groups.find(x => x.id == context.groupId);
const recentMessages = context.chat.map(x => x.original_avatar).filter(x => x).reverse().filter(onlyUnique);
const filteredMembers = group.members.filter(x => !group.disabled_members.includes(x));
const layerIndices = filteredMembers.slice().sort((a, b) => {
const layerIndices = filteredMembers.slice().sort((a, b) => {
const aRecentIndex = recentMessages.indexOf(a);
const bRecentIndex = recentMessages.indexOf(b);
const aFilteredIndex = filteredMembers.indexOf(a);
const bFilteredIndex = filteredMembers.indexOf(b);
if (aRecentIndex !== -1 && bRecentIndex !== -1) {
return bRecentIndex - aRecentIndex;
return bRecentIndex - aRecentIndex;
} else if (aRecentIndex !== -1) {
return 1;
return 1;
} else if (bRecentIndex !== -1) {
return -1;
return -1;
} else {
return aFilteredIndex - bFilteredIndex;
return aFilteredIndex - bFilteredIndex;
}
});
@@ -232,10 +232,15 @@ async function visualNovelUpdateLayers(container) {
images.sort(sortFunction).each((index, current) => {
const element = $(current);
const elementID = element.attr('id')
// skip repositioning of dragged elements
if (element.data('dragged')) {
currentPosition += imagesWidth[index];
if (element.data('dragged')
|| (power_user.movingUIState[elementID]
&& (typeof power_user.movingUIState[elementID] === 'object')
&& Object.keys(power_user.movingUIState[elementID]).length > 0)) {
loadMovingUIState()
//currentPosition += imagesWidth[index];
return;
}
@@ -284,7 +289,9 @@ async function setLastMessageSprite(img, avatar, labels) {
}
}
function setImage(img, path) {
async function setImage(img, path) {
// Cohee: If something goes wrong, uncomment this to return to the old behavior
/*
img.attr('src', path);
img.removeClass('default');
img.off('error');
@@ -293,6 +300,79 @@ function setImage(img, path) {
$(this).off('error');
$(this).attr('src', '');
});
*/
return new Promise(resolve => {
const prevExpressionSrc = img.attr('src');
const expressionClone = img.clone();
const originalId = img.attr('id');
//only swap expressions when necessary
if (prevExpressionSrc !== path && !img.hasClass('expression-animating')) {
//clone expression
expressionClone.addClass('expression-clone')
//make invisible and remove id to prevent double ids
//must be made invisible to start because they share the same Z-index
expressionClone.attr('id', '').css({ opacity: 0 });
//add new sprite path to clone src
expressionClone.attr('src', path);
//add invisible clone to html
expressionClone.appendTo(img.parent());
const duration = 200;
//add animation flags to both images
//to prevent multiple expression changes happening simultaneously
img.addClass('expression-animating');
// Set the parent container's min width and height before running the transition
const imgWidth = img.width();
const imgHeight = img.height();
const expressionHolder = img.parent();
expressionHolder.css('min-width', imgWidth > 100 ? imgWidth : 100);
expressionHolder.css('min-height', imgHeight > 100 ? imgHeight : 100);
//position absolute prevent the original from jumping around during transition
img.css('position', 'absolute');
expressionClone.addClass('expression-animating');
//fade the clone in
expressionClone.css({
opacity: 0
}).animate({
opacity: 1
}, duration)
//when finshed fading in clone, fade out the original
.promise().done(function () {
img.animate({
opacity: 0
}, duration);
//remove old expression
img.remove();
//replace ID so it becomes the new 'original' expression for next change
expressionClone.attr('id', originalId);
expressionClone.removeClass('expression-animating');
// Reset the expression holder min height and width
expressionHolder.css('min-width', 100);
expressionHolder.css('min-height', 100);
resolve();
});
expressionClone.removeClass('expression-clone');
expressionClone.removeClass('default');
expressionClone.off('error');
expressionClone.on('error', function () {
console.debug('Expression image error', sprite.path);
$(this).attr('src', '');
$(this).off('error');
resolve();
});
} else {
resolve();
}
});
}
function onExpressionsShowDefaultInput() {
@@ -533,6 +613,11 @@ function drawSpritesList(character, labels, sprites) {
$('.expression_settings').show();
$('#image_list').empty();
$('#image_list').data('name', character);
if (!Array.isArray(labels)) {
return [];
}
labels.sort().forEach((item) => {
const sprite = sprites.find(x => x.label == item);
@@ -561,7 +646,7 @@ function getListItem(item, imageSrc, textClass) {
<span class="expression_list_title ${textClass}">${item}</span>
<img class="expression_list_image" src="${imageSrc}" />
</div>
`;
`;
}
async function getSpritesList(name) {
@@ -615,6 +700,8 @@ async function setExpression(character, expression, force) {
console.debug('entered setExpressions');
await validateImages(character);
const img = $('img.expression');
const prevExpressionSrc = img.attr('src');
const expressionClone = img.clone()
const sprite = (spriteCache[character] && spriteCache[character].find(x => x.label === expression));
console.debug('checking for expression images to show..');
@@ -633,26 +720,79 @@ async function setExpression(character, expression, force) {
}
if (groupMember.name == character) {
setImage($(`.expression-holder[data-avatar="${member}"] img`), sprite.path);
await setImage($(`.expression-holder[data-avatar="${member}"] img`), sprite.path);
return;
}
}
}
//only swap expressions when necessary
if (prevExpressionSrc !== sprite.path
&& !img.hasClass('expression-animating')) {
//clone expression
expressionClone.addClass('expression-clone')
//make invisible and remove id to prevent double ids
//must be made invisible to start because they share the same Z-index
expressionClone.attr('id', '').css({ opacity: 0 });
//add new sprite path to clone src
expressionClone.attr('src', sprite.path);
//add invisible clone to html
expressionClone.appendTo($("#expression-holder"))
img.attr('src', sprite.path);
img.removeClass('default');
img.off('error');
img.on('error', function () {
console.debug('Expression image error', sprite.path);
$(this).attr('src', '');
$(this).off('error');
if (force && extension_settings.expressions.showDefault) {
const duration = 200;
//add animation flags to both images
//to prevent multiple expression changes happening simultaneously
img.addClass('expression-animating');
// Set the parent container's min width and height before running the transition
const imgWidth = img.width();
const imgHeight = img.height();
const expressionHolder = img.parent();
expressionHolder.css('min-width', imgWidth > 100 ? imgWidth : 100);
expressionHolder.css('min-height', imgHeight > 100 ? imgHeight : 100);
//position absolute prevent the original from jumping around during transition
img.css('position', 'absolute');
expressionClone.addClass('expression-animating');
//fade the clone in
expressionClone.css({
opacity: 0
}).animate({
opacity: 1
}, duration)
//when finshed fading in clone, fade out the original
.promise().done(function () {
img.animate({
opacity: 0
}, duration);
//remove old expression
img.remove();
//replace ID so it becomes the new 'original' expression for next change
expressionClone.attr('id', 'expression-image');
expressionClone.removeClass('expression-animating');
// Reset the expression holder min height and width
expressionHolder.css('min-width', 100);
expressionHolder.css('min-height', 100);
});
expressionClone.removeClass('expression-clone');
expressionClone.removeClass('default');
expressionClone.off('error');
expressionClone.on('error', function () {
console.debug('Expression image error', sprite.path);
$(this).attr('src', '');
$(this).off('error');
if (force && extension_settings.expressions.showDefault) {
setDefault();
}
});
} else {
if (extension_settings.expressions.showDefault) {
setDefault();
}
});
} else {
if (extension_settings.expressions.showDefault) {
setDefault();
}
}
@@ -660,8 +800,8 @@ async function setExpression(character, expression, force) {
console.debug('setting default');
const defImgUrl = `/img/default-expressions/${expression}.png`;
//console.log(defImgUrl);
img.attr('src', defImgUrl);
img.addClass('default');
expressionClone.attr('src', defImgUrl);
expressionClone.addClass('default');
}
document.getElementById("expression-holder").style.display = '';
}
@@ -900,6 +1040,7 @@ function setExpressionOverrideHtml(forceClear = false) {
</div>
</div>`;
$('body').append(html);
loadMovingUIState();
}
function addVisualNovelMode() {
const html = `
@@ -954,6 +1095,10 @@ function setExpressionOverrideHtml(forceClear = false) {
$('#expression_upload_pack_button').on('click', onClickExpressionUploadPackButton);
$('#expressions_show_default').prop('checked', extension_settings.expressions.showDefault).trigger('input');
$('#expression_override_cleanup_button').on('click', onClickExpressionOverrideRemoveAllButton);
$(document).on('dragstart', '.expression', (e) => {
e.preventDefault()
return false
})
$(document).on('click', '.expression_list_item', onClickExpressionImage);
$(document).on('click', '.expression_list_upload', onClickExpressionUpload);
$(document).on('click', '.expression_list_delete', onClickExpressionDelete);
@@ -968,6 +1113,7 @@ function setExpressionOverrideHtml(forceClear = false) {
const updateFunction = wrapper.update.bind(wrapper);
setInterval(updateFunction, UPDATE_INTERVAL);
moduleWorker();
dragElement($("#expression-holder"))
eventSource.on(event_types.CHAT_CHANGED, () => {
setExpressionOverrideHtml();

View File

@@ -20,6 +20,9 @@
#visual-novel-wrapper .expression-holder {
width: max-content;
display: flex;
left: unset;
right: unset;
}
#visual-novel-wrapper .hidden {
@@ -38,17 +41,25 @@
max-width: 90vh;
width: calc((100vw - var(--sheldWidth)) /2);
position: absolute;
bottom: 1px;
bottom: 0;
padding: 0;
left: 0;
filter: drop-shadow(2px 2px 2px #51515199);
z-index: 2;
overflow: hidden;
resize: both;
}
img.expression {
min-width: 100px;
min-height: 100px;
max-height: 90vh;
max-width: 90vh;
width: 100%;
height: 100%;
top: 0;
bottom: 0;
padding: 0;
vertical-align: bottom;
object-fit: contain;
}
@@ -64,6 +75,10 @@ img.expression.default {
margin-top: 50px;
}
.expression-clone {
position: absolute;
}
.debug-image {
display: none;
visibility: collapse;
@@ -166,4 +181,4 @@ img.expression.default {
div.expression {
display: none;
}
}
}

View File

@@ -1,67 +0,0 @@
#floatingPrompt {
overflow-y: auto;
max-width: 90svw;
max-height: 90svh;
min-width: 100px;
min-height: 100px;
border-radius: 10px;
border: 1px solid var(--white30a);
position: fixed;
padding: 10px;
padding-top: 25px;
display: none;
flex-direction: column;
box-shadow: 0 0 10px var(--black70a);
z-index: 3000;
left: 0;
top: 0;
margin: 0;
right: unset;
width: calc(((100svw - var(--sheldWidth)) / 2) - 1px);
}
.floating_prompt_radio_group {
display: flex;
flex-direction: column;
}
#extension_floating_counter {
font-weight: 600;
color: orange;
}
.extension_token_counter {
font-size: calc(var(--mainFontSize) * 0.9);
width: 100%;
text-align: right;
}
.floating_prompt_settings textarea {
font-size: calc(var(--mainFontSize) * 0.9);
line-height: 1.2;
}
#ANClose {
height: 15px;
aspect-ratio: 1 / 1;
font-size: 20px;
opacity: 0.5;
transition: all 250ms;
}
#ANClose:hover {
cursor: pointer;
opacity: 1;
}
.panelControlBar {
position: absolute;
right: 5px;
top: 5px;
margin-right: 5px;
}
#floatingPrompt .drag-grabber {
position: unset;
}

View File

@@ -1,4 +1,4 @@
import { saveSettingsDebounced, getCurrentChatId, system_message_types, eventSource, event_types } from "../../../script.js";
import { saveSettingsDebounced, getCurrentChatId, system_message_types, extension_prompt_types, eventSource, event_types, getRequestHeaders, CHARACTERS_PER_TOKEN_RATIO, substituteParams, max_context, } from "../../../script.js";
import { humanizedDateTime } from "../../RossAscends-mods.js";
import { getApiUrl, extension_settings, getContext, doExtrasFetch } from "../../extensions.js";
import { getFileText, onlyUnique, splitRecursive, IndexedDBStore } from "../../utils.js";
@@ -9,6 +9,7 @@ const dbStore = new IndexedDBStore('SillyTavern', MODULE_NAME);
const defaultSettings = {
strategy: 'original',
sort_strategy: 'date',
keep_context: 10,
keep_context_min: 1,
@@ -20,6 +21,15 @@ const defaultSettings = {
n_results_max: 500,
n_results_step: 1,
chroma_depth: 20,
chroma_depth_min: -1,
chroma_depth_max: 500,
chroma_depth_step: 1,
chroma_default_msg: "In a past conversation: [{{memories}}]",
chroma_default_hhaa_wrapper: "Previous messages exchanged between {{user}} and {{char}}:\n{{memories}}",
chroma_default_hhaa_memory: "- {{name}}: {{message}}\n",
hhaa_token_limit: 512,
split_length: 384,
split_length_min: 64,
split_length_max: 4096,
@@ -29,6 +39,15 @@ const defaultSettings = {
file_split_length_min: 512,
file_split_length_max: 4096,
file_split_length_step: 128,
keep_context_proportion: 0.5,
keep_context_proportion_min: 0.0,
keep_context_proportion_max: 1.0,
keep_context_proportion_step: 0.05,
auto_adjust: true,
freeze: false,
query_last_only: true,
};
const postHeaders = {
@@ -88,18 +107,60 @@ async function loadSettings() {
"selected",
"true"
);
$("#chromadb_sort_strategy option[value=" + extension_settings.chromadb.sort_strategy + "]").attr(
"selected",
"true"
);
$('#chromadb_keep_context').val(extension_settings.chromadb.keep_context).trigger('input');
$('#chromadb_n_results').val(extension_settings.chromadb.n_results).trigger('input');
$('#chromadb_split_length').val(extension_settings.chromadb.split_length).trigger('input');
$('#chromadb_file_split_length').val(extension_settings.chromadb.file_split_length).trigger('input');
$('#chromadb_keep_context_proportion').val(extension_settings.chromadb.keep_context_proportion).trigger('input');
$('#chromadb_custom_depth').val(extension_settings.chromadb.chroma_depth).trigger('input');
$('#chromadb_custom_msg').val(extension_settings.chromadb.recall_msg).trigger('input');
$('#chromadb_hhaa_wrapperfmt').val(extension_settings.chromadb.hhaa_wrapper_msg).trigger('input');
$('#chromadb_hhaa_memoryfmt').val(extension_settings.chromadb.hhaa_memory_msg).trigger('input');
$('#chromadb_hhaa_token_limit').val(extension_settings.chromadb.hhaa_token_limit).trigger('input');
$('#chromadb_auto_adjust').prop('checked', extension_settings.chromadb.auto_adjust);
$('#chromadb_freeze').prop('checked', extension_settings.chromadb.freeze);
$('#chromadb_query_last_only').val(extension_settings.chromadb.query_last_only).trigger('input');
enableDisableSliders();
onStrategyChange();
}
function onStrategyChange() {
console.debug('changing chromadb strat');
extension_settings.chromadb.strategy = $('#chromadb_strategy').val();
if (extension_settings.chromadb.strategy === "custom") {
$('#chromadb_custom_depth').show();
$('label[for="chromadb_custom_depth"]').show();
$('#chromadb_custom_msg').show();
$('label[for="chromadb_custom_msg"]').show();
}
else if(extension_settings.chromadb.strategy === "hh_aa"){
$('#chromadb_hhaa_wrapperfmt').show();
$('label[for="chromadb_hhaa_wrapperfmt"]').show();
$('#chromadb_hhaa_memoryfmt').show();
$('label[for="chromadb_hhaa_memoryfmt"]').show();
$('#chromadb_hhaa_token_limit').show();
$('label[for="chromadb_hhaa_token_limit"]').show();
}
saveSettingsDebounced();
}
function onRecallStrategyChange() {
console.log('changing chromadb recall strat');
extension_settings.chromadb.recall_strategy = $('#chromadb_recall_strategy').val();
saveSettingsDebounced();
}
function onSortStrategyChange() {
console.log('changing chromadb sort strat');
extension_settings.chromadb.sort_strategy = $('#chromadb_sort_strategy').val();
//$('#chromadb_strategy').select(extension_settings.chromadb.strategy);
saveSettingsDebounced();
}
@@ -115,6 +176,31 @@ function onNResultsInput() {
saveSettingsDebounced();
}
function onChromaDepthInput() {
extension_settings.chromadb.chroma_depth = Number($('#chromadb_custom_depth').val());
$('#chromadb_custom_depth_value').text(extension_settings.chromadb.chroma_depth);
saveSettingsDebounced();
}
function onChromaMsgInput() {
extension_settings.chromadb.recall_msg = $('#chromadb_custom_msg').val();
saveSettingsDebounced();
}
function onChromaHHAAWrapper() {
extension_settings.chromadb.hhaa_wrapper_msg = $('#chromadb_hhaa_wrapperfmt').val();
saveSettingsDebounced();
}
function onChromaHHAAMemory() {
extension_settings.chromadb.hhaa_memory_msg = $('#chromadb_hhaa_memoryfmt').val();
saveSettingsDebounced();
}
function onChromaHHAATokens() {
extension_settings.chromadb.hhaa_token_limit = Number($('#chromadb_hhaa_token_limit').val());
$('#chromadb_hhaa_token_limit_value').text(extension_settings.chromadb.hhaa_token_limit);
saveSettingsDebounced();
}
function onSplitLengthInput() {
extension_settings.chromadb.split_length = Number($('#chromadb_split_length').val());
$('#chromadb_split_length_value').text(extension_settings.chromadb.split_length);
@@ -127,6 +213,16 @@ function onFileSplitLengthInput() {
saveSettingsDebounced();
}
function onChunkNLInput() {
let shouldSplit = $('#onChunkNLInput').is(':checked');
if (shouldSplit) {
extension_settings.chromadb.file_split_type = "newline";
} else {
extension_settings.chromadb.file_split_type = "length";
}
saveSettingsDebounced();
}
function checkChatId(chat_id) {
if (!chat_id || chat_id.trim() === '') {
toastr.error('Please select a character and try again.');
@@ -259,10 +355,24 @@ async function onExportClick() {
link.click();
document.body.removeChild(link);
} else {
toastr.error('An error occurred while attempting to download the data');
//Show the error from the result without the html, only what's in the body paragraph
let parser = new DOMParser();
let error = await exportResult.text();
let doc = parser.parseFromString(error, 'text/html');
let errorMessage = doc.querySelector('p').textContent;
toastr.error(`An error occurred while attempting to download the data from ChromaDB: ${errorMessage}`);
}
}
function tinyhash(text) {
let hash = 0;
for (let i = 0; i < text.length; ++i) {
hash = ((hash<<5) - hash) + text.charCodeAt(i);
hash = hash & hash; // Keeps it 32-bit allegedly.
}
return hash;
}
async function onSelectImportFile(e) {
const file = e.target.files[0];
const currentChatId = getCurrentChatId();
@@ -280,6 +390,11 @@ async function onSelectImportFile(e) {
const text = await getFileText(file);
const imported = JSON.parse(text);
const id_salt = "-" + tinyhash(imported.chat_id).toString(36);
for (let entry of imported.content) {
entry.id = entry.id + id_salt;
}
imported.chat_id = currentChatId;
const url = new URL(getApiUrl());
@@ -328,6 +443,39 @@ async function queryMessages(chat_id, query) {
return [];
}
async function queryMultiMessages(chat_id, query) {
const context = getContext();
const response = await fetch("/getallchatsofcharacter", {
method: 'POST',
body: JSON.stringify({ avatar_url: context.characters[context.characterId].avatar }),
headers: getRequestHeaders(),
});
if (!response.ok) {
return;
}
let data = await response.json();
data = Object.values(data);
let chat_list = data.sort((a, b) => a["file_name"].localeCompare(b["file_name"])).reverse();
// Extracting chat_ids from the chat_list
chat_list = chat_list.map(chat => chat.file_name.replace(/\.[^/.]+$/, ""));
const url = new URL(getApiUrl());
url.pathname = '/api/chromadb/multiquery';
const queryMessagesResult = await fetch(url, {
method: 'POST',
body: JSON.stringify({ chat_list, query, n_results: extension_settings.chromadb.n_results }),
headers: postHeaders,
});
if (queryMessagesResult.ok) {
const queryMessagesData = await queryMessagesResult.json();
return queryMessagesData;
}
return [];
}
async function onSelectInjectFile(e) {
const file = e.target.files[0];
const currentChatId = getCurrentChatId();
@@ -341,8 +489,14 @@ async function onSelectInjectFile(e) {
try {
toastr.info('This may take some time, depending on the file size', 'Processing...');
const text = await getFileText(file);
const split = splitRecursive(text, extension_settings.chromadb.file_split_length).filter(onlyUnique);
extension_settings.chromadb.file_split_type = "newline";
//allow splitting on newlines or splitrecursively
let split = [];
if (extension_settings.chromadb.file_split_type == "newline") {
split = text.split(/\r?\n/).filter(onlyUnique);
} else {
split = splitRecursive(text, extension_settings.chromadb.file_split_length).filter(onlyUnique);
}
const baseDate = Date.now();
const messages = split.map((m, i) => ({
@@ -390,68 +544,251 @@ async function onSelectInjectFile(e) {
}
}
window.chromadb_interceptGeneration = async (chat) => {
/*
* Automatically adjusts the extension settings for the optimal number of messages to keep and query based
* on the chat history and a specified maximum context length.
*/
function doAutoAdjust(chat, maxContext) {
console.debug('CHROMADB: Auto-adjusting sliders (messages: %o, maxContext: %o)', chat.length, maxContext);
// Get mean message length
const meanMessageLength = chat.reduce((acc, cur) => acc + cur.mes.length, 0) / chat.length;
if (Number.isNaN(meanMessageLength)) {
console.debug('CHROMADB: Mean message length is NaN, aborting auto-adjust');
return;
}
console.debug('CHROMADB: Mean message length (characters): %o', meanMessageLength);
// Convert to number of "tokens"
const meanMessageLengthTokens = Math.ceil(meanMessageLength / CHARACTERS_PER_TOKEN_RATIO);
console.debug('CHROMADB: Mean message length (tokens): %o', meanMessageLengthTokens);
// Get number of messages in context
const contextMessages = Math.max(1, Math.ceil(maxContext / meanMessageLengthTokens));
// Round up to nearest 10
const contextMessagesRounded = Math.ceil(contextMessages / 10) * 10;
console.debug('CHROMADB: Estimated context messages (rounded): %o', contextMessagesRounded);
// Messages to keep (proportional, rounded to nearest 5, minimum 5, maximum 500)
const messagesToKeep = Math.min(defaultSettings.keep_context_max, Math.max(5, Math.floor(contextMessagesRounded * extension_settings.chromadb.keep_context_proportion / 5) * 5));
console.debug('CHROMADB: Estimated messages to keep: %o', messagesToKeep);
// Messages to query (rounded, maximum 500)
const messagesToQuery = Math.min(defaultSettings.n_results_max, contextMessagesRounded - messagesToKeep);
console.debug('CHROMADB: Estimated messages to query: %o', messagesToQuery);
// Set extension settings
extension_settings.chromadb.keep_context = messagesToKeep;
extension_settings.chromadb.n_results = messagesToQuery;
// Update sliders
$('#chromadb_keep_context').val(messagesToKeep);
$('#chromadb_n_results').val(messagesToQuery);
// Update labels
$('#chromadb_keep_context_value').text(extension_settings.chromadb.keep_context);
$('#chromadb_n_results_value').text(extension_settings.chromadb.n_results);
}
window.chromadb_interceptGeneration = async (chat, maxContext) => {
if (extension_settings.chromadb.auto_adjust) {
doAutoAdjust(chat, maxContext);
}
const currentChatId = getCurrentChatId();
if (!currentChatId)
return;
//log the current settings
console.debug("CHROMADB: Current settings: %o", extension_settings.chromadb);
const selectedStrategy = extension_settings.chromadb.strategy;
if (currentChatId) {
const messagesToStore = chat.slice(0, -extension_settings.chromadb.keep_context);
const recallStrategy = extension_settings.chromadb.recall_strategy;
let recallMsg = extension_settings.chromadb.recall_msg || defaultSettings.chroma_default_msg;
const chromaDepth = extension_settings.chromadb.chroma_depth;
const chromaSortStrategy = extension_settings.chromadb.sort_strategy;
const chromaQueryLastOnly = extension_settings.chromadb.query_last_only;
const messagesToStore = chat.slice(0, -extension_settings.chromadb.keep_context);
if (messagesToStore.length > 0 || extension_settings.chromadb.freeze) {
await addMessages(currentChatId, messagesToStore);
if (messagesToStore.length > 0 && !extension_settings.chromadb.freeze) {
//log the messages to store
console.debug("CHROMADB: Messages to store: %o", messagesToStore);
//log the messages to store length vs keep context
console.debug("CHROMADB: Messages to store length vs keep context: %o vs %o", messagesToStore.length, extension_settings.chromadb.keep_context);
await addMessages(currentChatId, messagesToStore);
}
const lastMessage = chat[chat.length - 1];
const lastMessage = chat[chat.length - 1];
if (lastMessage) {
const queriedMessages = await queryMessages(currentChatId, lastMessage.mes);
queriedMessages.sort((a, b) => a.date - b.date);
const newChat = [];
if (selectedStrategy === 'ross') {
//adds chroma to the end of chat and allows Generate() to cull old messages naturally.
const context = getContext();
const charname = context.name2;
newChat.push(
{
is_name: false,
is_user: false,
mes: `[Use these past chat exchanges to inform ${charname}'s next response:`,
name: "system",
send_date: 0,
}
);
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
newChat.push(
{
is_name: false,
is_user: false,
mes: `]\n`,
name: "system",
send_date: 0,
}
);
chat.splice(chat.length, 0, ...newChat);
}
if (selectedStrategy === 'original') {
//removes .length # messages from the start of 'kept messages'
//replaces them with chromaDB results (with no separator)
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
chat.splice(0, messagesToStore.length, ...newChat);
}
console.log('ChromaDB chat after injection', chat);
let queriedMessages;
if (lastMessage) {
let queryBlob = "";
if (chromaQueryLastOnly) {
queryBlob = lastMessage.mes;
}
else {
for (let msg of chat.slice(-extension_settings.chromadb.keep_context)) {
queryBlob += `${msg.mes}\n`
}
}
console.debug("CHROMADB: Query text:", queryBlob);
if (recallStrategy === 'multichat') {
console.log("Utilizing multichat")
queriedMessages = await queryMultiMessages(currentChatId, queryBlob);
}
else {
queriedMessages = await queryMessages(currentChatId, queryBlob);
}
if (chromaSortStrategy === "date") {
queriedMessages.sort((a, b) => a.date - b.date);
}
else {
queriedMessages.sort((a, b) => b.distance - a.distance);
}
console.debug("CHROMADB: Query results: %o", queriedMessages);
let newChat = [];
if (selectedStrategy === 'ross') {
//adds chroma to the end of chat and allows Generate() to cull old messages naturally.
const context = getContext();
const charname = context.name2;
newChat.push(
{
is_name: false,
is_user: false,
mes: `[Use these past chat exchanges to inform ${charname}'s next response:`,
name: "system",
send_date: 0,
}
);
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
newChat.push(
{
is_name: false,
is_user: false,
mes: `]\n`,
name: "system",
send_date: 0,
}
);
chat.splice(chat.length, 0, ...newChat);
}
if (selectedStrategy === 'hh_aa') {
// Insert chroma history messages as a list at the AFTER_SCENARIO anchor point
const context = getContext();
const chromaTokenLimit = extension_settings.chromadb.hhaa_token_limit;
let wrapperMsg = extension_settings.chromadb.hhaa_wrapper_msg || defaultSettings.chroma_default_hhaa_wrapper;
wrapperMsg = substituteParams(wrapperMsg, context.name1, context.name2);
if (!wrapperMsg.includes("{{memories}}")) {
wrapperMsg += " {{memories}}";
}
let memoryMsg = extension_settings.chromadb.hhaa_memory_msg || defaultSettings.chroma_default_hhaa_memory;
memoryMsg = substituteParams(memoryMsg, context.name1, context.name2);
if (!memoryMsg.includes("{{message}}")) {
memoryMsg += " {{message}}";
}
// Reversed because we want the most 'important' messages at the bottom.
let recalledMemories = queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse).reverse();
let tokenApprox = 0;
let allMemoryBlob = "";
let seenMemories = new Set(); // Why are there even duplicates in chromadb anyway?
for (const msg of recalledMemories) {
const memoryBlob = memoryMsg.replace('{{name}}', msg.name).replace('{{message}}', msg.mes);
const memoryTokens = (memoryBlob.length / CHARACTERS_PER_TOKEN_RATIO);
if (!seenMemories.has(memoryBlob) && tokenApprox + memoryTokens <= chromaTokenLimit) {
allMemoryBlob += memoryBlob;
tokenApprox += memoryTokens;
seenMemories.add(memoryBlob);
}
}
// No memories? No prompt.
const promptBlob = (tokenApprox == 0) ? "" : wrapperMsg.replace('{{memories}}', allMemoryBlob);
console.debug("CHROMADB: prompt blob: %o", promptBlob);
context.setExtensionPrompt(MODULE_NAME, promptBlob, extension_prompt_types.AFTER_SCENARIO);
}
if (selectedStrategy === 'custom') {
const context = getContext();
recallMsg = substituteParams(recallMsg, context.name1, context.name2);
if (!recallMsg.includes("{{memories}}")) {
recallMsg += " {{memories}}";
}
let recallStart = recallMsg.split('{{memories}}')[0]
let recallEnd = recallMsg.split('{{memories}}')[1]
newChat.push(
{
is_name: false,
is_user: false,
mes: recallStart,
name: "system",
send_date: 0,
}
);
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
newChat.push(
{
is_name: false,
is_user: false,
mes: recallEnd + `\n`,
name: "system",
send_date: 0,
}
);
//prototype chroma duplicate removal
let chatset = new Set(chat.map(obj => obj.mes));
newChat = newChat.filter(obj => !chatset.has(obj.mes));
if(chromaDepth === -1) {
chat.splice(chat.length, 0, ...newChat);
}
else {
chat.splice(chromaDepth, 0, ...newChat);
}
}
if (selectedStrategy === 'original') {
//removes .length # messages from the start of 'kept messages'
//replaces them with chromaDB results (with no separator)
newChat.push(...queriedMessages.map(m => m.meta).filter(onlyUnique).map(JSON.parse));
chat.splice(0, messagesToStore.length, ...newChat);
}
}
}
function onFreezeInput() {
extension_settings.chromadb.freeze = $('#chromadb_freeze').is(':checked');
saveSettingsDebounced();
}
function onAutoAdjustInput() {
extension_settings.chromadb.auto_adjust = $('#chromadb_auto_adjust').is(':checked');
enableDisableSliders();
saveSettingsDebounced();
}
function onFullLogQuery() {
extension_settings.chromadb.query_last_only = $('#chromadb_query_last_only').is(':checked');
saveSettingsDebounced();
}
function enableDisableSliders() {
const auto_adjust = extension_settings.chromadb.auto_adjust;
$('label[for="chromadb_keep_context"]').prop('hidden', auto_adjust);
$('#chromadb_keep_context').prop('hidden', auto_adjust)
$('label[for="chromadb_n_results"]').prop('hidden', auto_adjust);
$('#chromadb_n_results').prop('hidden', auto_adjust)
$('label[for="chromadb_keep_context_proportion"]').prop('hidden', !auto_adjust);
$('#chromadb_keep_context_proportion').prop('hidden', !auto_adjust)
}
function onKeepContextProportionInput() {
extension_settings.chromadb.keep_context_proportion = $('#chromadb_keep_context_proportion').val();
$('#chromadb_keep_context_proportion_value').text(Math.round(extension_settings.chromadb.keep_context_proportion * 100));
saveSettingsDebounced();
}
jQuery(async () => {
const settingsHtml = `
<div class="chromadb_settings">
@@ -467,11 +804,39 @@ jQuery(async () => {
<select id="chromadb_strategy">
<option value="original">Replace non-kept chat items with memories</option>
<option value="ross">Add memories after chat with a header tag</option>
<option value="hh_aa">Add memory list to character description</option>
<option value="custom">Add memories at custom depth with custom msg</option>
</select>
<label for="chromadb_custom_msg" hidden><small>Custom injection message:</small></label>
<textarea id="chromadb_custom_msg" hidden class="text_pole textarea_compact" rows="2" placeholder="${defaultSettings.chroma_default_msg}" style="height: 61px; display: none;"></textarea>
<label for="chromadb_custom_depth" hidden><small>How deep should the memory messages be injected?: (<span id="chromadb_custom_depth_value"></span>)</small></label>
<input id="chromadb_custom_depth" type="range" min="${defaultSettings.chroma_depth_min}" max="${defaultSettings.chroma_depth_max}" step="${defaultSettings.chroma_depth_step}" value="${defaultSettings.chroma_depth}" hidden/>
<label for="chromadb_hhaa_wrapperfmt" hidden><small>Custom wrapper format:</small></label>
<textarea id="chromadb_hhaa_wrapperfmt" hidden class="text_pole textarea_compact" rows="2" placeholder="${defaultSettings.chroma_default_hhaa_wrapper}" style="height: 61px; display: none;"></textarea>
<label for="chromadb_hhaa_memoryfmt" hidden><small>Custom memory format:</small></label>
<textarea id="chromadb_hhaa_memoryfmt" hidden class="text_pole textarea_compact" rows="2" placeholder="${defaultSettings.chroma_default_hhaa_memory}" style="height: 61px; display: none;"></textarea>
<label for="chromadb_hhaa_token_limit" hidden><small>Maximum tokens allowed for memories: (<span id="chromadb_hhaa_token_limit_value"></span>)</small></label>
<input id="chromadb_hhaa_token_limit" type="range" min="0" max="2048" step="64" value="${defaultSettings.hhaa_token_limit}" hidden/>
<span>Memory Recall Strategy</span>
<select id="chromadb_recall_strategy">
<option value="original">Recall only from this chat</option>
<option value="multichat">Recall from all character chats (experimental)</option>
</select>
<span>Memory Sort Strategy</span>
<select id="chromadb_sort_strategy">
<option value="date">Sort memories by date</option>
<option value="distance">Sort memories by relevance</option>
</select>
<label for="chromadb_keep_context"><small>How many original chat messages to keep: (<span id="chromadb_keep_context_value"></span>) messages</small></label>
<input id="chromadb_keep_context" type="range" min="${defaultSettings.keep_context_min}" max="${defaultSettings.keep_context_max}" step="${defaultSettings.keep_context_step}" value="${defaultSettings.keep_context}" />
<label for="chromadb_n_results"><small>Maximum number of ChromaDB 'memories' to inject: (<span id="chromadb_n_results_value"></span>) messages</small></label>
<input id="chromadb_n_results" type="range" min="${defaultSettings.n_results_min}" max="${defaultSettings.n_results_max}" step="${defaultSettings.n_results_step}" value="${defaultSettings.n_results}" />
<label for="chromadb_keep_context_proportion"><small>Keep (<span id="chromadb_keep_context_proportion_value"></span>%) of in-context chat messages; replace the rest with memories</small></label>
<input id="chromadb_keep_context_proportion" type="range" min="${defaultSettings.keep_context_proportion_min}" max="${defaultSettings.keep_context_proportion_max}" step="${defaultSettings.keep_context_proportion_step}" value="${defaultSettings.keep_context_proportion}" />
<label for="chromadb_split_length"><small>Max length for each 'memory' pulled from the current chat history: (<span id="chromadb_split_length_value"></span>) characters</small></label>
<input id="chromadb_split_length" type="range" min="${defaultSettings.split_length_min}" max="${defaultSettings.split_length_max}" step="${defaultSettings.split_length_step}" value="${defaultSettings.split_length}" />
<label for="chromadb_file_split_length"><small>Max length for each 'memory' pulled from imported text files: (<span id="chromadb_file_split_length_value"></span>) characters</small></label>
@@ -480,6 +845,18 @@ jQuery(async () => {
<input type="checkbox" id="chromadb_freeze" />
<span>Freeze ChromaDB state</span>
</label>
<label class="checkbox_label for="chromadb_auto_adjust" title="Automatically adjusts the number of messages to keep based on the average number of messages in the current chat and the chosen proportion.">
<input type="checkbox" id="chromadb_auto_adjust" />
<span>Use % strategy</span>
</label>
<label class="checkbox_label" for="chromadb_chunk_nl" title="Chunk injected documents on newline instead of at set character size." >
<input type="checkbox" id="chromadb_chunk_nl" />
<span>Chunk on Newlines</span>
</label>
<label class="checkbox_label for="chromadb_query_last_only" title="ChromaDB queries only use the most recent message. (Instead of using all messages still in the context.)">
<input type="checkbox" id="chromadb_query_last_only" />
<span>Query last message only</span>
</label>
<div class="flex-container spaceEvenly">
<div id="chromadb_inject" title="Upload custom textual data to use in the context of the current chat" class="menu_button">
<i class="fa-solid fa-file-arrow-up"></i>
@@ -506,8 +883,17 @@ jQuery(async () => {
$('#extensions_settings2').append(settingsHtml);
$('#chromadb_strategy').on('change', onStrategyChange);
$('#chromadb_recall_strategy').on('change', onRecallStrategyChange);
$('#chromadb_sort_strategy').on('change', onSortStrategyChange);
$('#chromadb_keep_context').on('input', onKeepContextInput);
$('#chromadb_n_results').on('input', onNResultsInput);
$('#chromadb_custom_depth').on('input', onChromaDepthInput);
$('#chromadb_custom_msg').on('input', onChromaMsgInput);
$('#chromadb_hhaa_wrapperfmt').on('input', onChromaHHAAWrapper);
$('#chromadb_hhaa_memoryfmt').on('input', onChromaHHAAMemory);
$('#chromadb_hhaa_token_limit').on('input', onChromaHHAATokens);
$('#chromadb_split_length').on('input', onSplitLengthInput);
$('#chromadb_file_split_length').on('input', onFileSplitLengthInput);
$('#chromadb_inject').on('click', () => $('#chromadb_inject_file').trigger('click'));
@@ -517,6 +903,10 @@ jQuery(async () => {
$('#chromadb_purge').on('click', onPurgeClick);
$('#chromadb_export').on('click', onExportClick);
$('#chromadb_freeze').on('input', onFreezeInput);
$('#chromadb_chunk_nl').on('input', onChunkNLInput);
$('#chromadb_auto_adjust').on('input', onAutoAdjustInput);
$('#chromadb_query_last_only').on('input', onFullLogQuery);
$('#chromadb_keep_context_proportion').on('input', onKeepContextProportionInput);
await loadSettings();
// Not sure if this is needed, but it's here just in case

View File

@@ -1,10 +1,9 @@
import { getStringHash, debounce } from "../../utils.js";
import { getContext, getApiUrl, extension_settings, ModuleWorkerWrapper, doExtrasFetch } from "../../extensions.js";
import { extension_prompt_types, is_send_press, saveSettingsDebounced } from "../../../script.js";
import { getStringHash, debounce, waitUntilCondition } from "../../utils.js";
import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules } from "../../extensions.js";
import { eventSource, event_types, extension_prompt_types, generateQuietPrompt, is_send_press, saveSettingsDebounced, substituteParams } from "../../../script.js";
export { MODULE_NAME };
const MODULE_NAME = '1_memory';
const UPDATE_INTERVAL = 5000;
let lastCharacterId = null;
let lastGroupId = null;
@@ -13,9 +12,16 @@ let lastMessageHash = null;
let lastMessageId = null;
let inApiCall = false;
const formatMemoryValue = (value) => value ? `Context: ${value.trim()}` : '';
const formatMemoryValue = (value) => value ? `Summary: ${value.trim()}` : '';
const saveChatDebounced = debounce(() => getContext().saveChat(), 2000);
const summary_sources = {
'extras': 'extras',
'main': 'main',
};
const defaultPrompt = '[Pause your roleplay. Summarize the most important facts and events that have happened in the chat so far. If a summary already exists in your memory, use that as a base and expand with new facts. Limit the summary to {{words}} words or less. Your response should include nothing but the summary.]';
const defaultSettings = {
minLongMemory: 16,
maxLongMemory: 1024,
@@ -38,6 +44,16 @@ const defaultSettings = {
maxLengthPenalty: 4,
lengthPenaltyStep: 0.1,
memoryFrozen: false,
source: summary_sources.extras,
prompt: defaultPrompt,
promptWords: 200,
promptMinWords: 25,
promptMaxWords: 1000,
promptWordsStep: 25,
promptInterval: 10,
promptMinInterval: 1,
promptMaxInterval: 100,
promptIntervalStep: 1,
};
function loadSettings() {
@@ -45,12 +61,42 @@ function loadSettings() {
Object.assign(extension_settings.memory, defaultSettings);
}
if (extension_settings.memory.source === undefined) {
extension_settings.memory.source = defaultSettings.source;
}
if (extension_settings.memory.prompt === undefined) {
extension_settings.memory.prompt = defaultSettings.prompt;
}
if (extension_settings.memory.promptWords === undefined) {
extension_settings.memory.promptWords = defaultSettings.promptWords;
}
if (extension_settings.memory.promptInterval === undefined) {
extension_settings.memory.promptInterval = defaultSettings.promptInterval;
}
$('#summary_source').val(extension_settings.memory.source).trigger('change');
$('#memory_long_length').val(extension_settings.memory.longMemoryLength).trigger('input');
$('#memory_short_length').val(extension_settings.memory.shortMemoryLength).trigger('input');
$('#memory_repetition_penalty').val(extension_settings.memory.repetitionPenalty).trigger('input');
$('#memory_temperature').val(extension_settings.memory.temperature).trigger('input');
$('#memory_length_penalty').val(extension_settings.memory.lengthPenalty).trigger('input');
$('#memory_frozen').prop('checked', extension_settings.memory.memoryFrozen).trigger('input');
$('#memory_prompt').val(extension_settings.memory.prompt).trigger('input');
$('#memory_prompt_words').val(extension_settings.memory.promptWords).trigger('input');
$('#memory_prompt_interval').val(extension_settings.memory.promptInterval).trigger('input');
}
function onSummarySourceChange(event) {
const value = event.target.value;
extension_settings.memory.source = value;
$('#memory_settings [data-source]').each((_, element) => {
const source = $(element).data('source');
$(element).toggle(source === value);
});
saveSettingsDebounced();
}
function onMemoryShortInput() {
@@ -104,6 +150,26 @@ function onMemoryFrozenInput() {
saveSettingsDebounced();
}
function onMemoryPromptWordsInput() {
const value = $(this).val();
extension_settings.memory.promptWords = Number(value);
$('#memory_prompt_words_value').text(extension_settings.memory.promptWords);
saveSettingsDebounced();
}
function onMemoryPromptIntervalInput() {
const value = $(this).val();
extension_settings.memory.promptInterval = Number(value);
$('#memory_prompt_interval_value').text(extension_settings.memory.promptInterval);
saveSettingsDebounced();
}
function onMemoryPromptInput() {
const value = $(this).val();
extension_settings.memory.prompt = value;
saveSettingsDebounced();
}
function saveLastValues() {
const context = getContext();
lastGroupId = context.groupId;
@@ -129,7 +195,14 @@ function getLatestMemoryFromChat(chat) {
return '';
}
async function moduleWorker() {
async function onChatEvent() {
// Module not enabled
if (extension_settings.memory.source === summary_sources.extras) {
if (!modules.includes('summarize')) {
return;
}
}
const context = getContext();
const chat = context.chat;
@@ -187,7 +260,93 @@ async function moduleWorker() {
}
}
async function forceSummarizeChat() {
const context = getContext();
if (!context.chatId) {
toastr.warning('No chat selected');
return;
}
toastr.info('Summarizing chat...', 'Please wait');
const value = await summarizeChatMain(context, true);
if (!value) {
toastr.warning('Failed to summarize chat');
return;
}
}
async function summarizeChat(context) {
switch (extension_settings.memory.source) {
case summary_sources.extras:
await summarizeChatExtras(context);
break;
case summary_sources.main:
await summarizeChatMain(context, false);
break;
default:
break;
}
}
async function summarizeChatMain(context, force) {
try {
// Wait for the send button to be released
waitUntilCondition(() => is_send_press === false, 10000, 100);
} catch {
console.debug('Timeout waiting for is_send_press');
return;
}
if (!context.chat.length) {
console.debug('No messages in chat to summarize');
return;
}
if (context.chat.length < extension_settings.memory.promptInterval && !force) {
console.debug(`Not enough messages in chat to summarize (chat: ${context.chat.length}, interval: ${extension_settings.memory.promptInterval})`);
return;
}
let messagesSinceLastSummary = 0;
for (let i = context.chat.length - 1; i >= 0; i--) {
if (context.chat[i].extra && context.chat[i].extra.memory) {
break;
}
messagesSinceLastSummary++;
}
if (messagesSinceLastSummary < extension_settings.memory.promptInterval && !force) {
console.debug(`Not enough messages since last summary (messages: ${messagesSinceLastSummary}, interval: ${extension_settings.memory.promptInterval}`);
return;
}
console.log('Summarizing chat, messages since last summary: ' + messagesSinceLastSummary);
const prompt = substituteParams(extension_settings.memory.prompt)
.replace(/{{words}}/gi, extension_settings.memory.promptWords);
if (!prompt) {
console.debug('Summarization prompt is empty. Skipping summarization.');
return;
}
const summary = await generateQuietPrompt(prompt);
const newContext = getContext();
// something changed during summarization request
if (newContext.groupId !== context.groupId
|| newContext.chatId !== context.chatId
|| (!newContext.groupId && (newContext.characterId !== context.characterId))) {
console.log('Context changed, summary discarded');
return;
}
setMemoryContext(summary, true);
return summary;
}
async function summarizeChatExtras(context) {
function getMemoryString() {
return (longMemory + '\n\n' + memoryBuffer.slice().reverse().join('\n\n')).trim();
}
@@ -301,6 +460,7 @@ function setMemoryContext(value, saveToMessage) {
const context = getContext();
context.setExtensionPrompt(MODULE_NAME, formatMemoryValue(value), extension_prompt_types.AFTER_SCENARIO);
$('#memory_contents').val(value);
console.log('Memory set to: ' + value);
if (saveToMessage && context.chat.length) {
const idx = context.chat.length - 2;
@@ -315,40 +475,55 @@ function setMemoryContext(value, saveToMessage) {
}
}
$(document).ready(function () {
jQuery(function () {
function addExtensionControls() {
const settingsHtml = `
<div id="memory_settings">
<div class="inline-drawer">
<div class="inline-drawer-toggle inline-drawer-header">
<b>Summarize</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<label for="memory_contents">Current summary: </label>
<textarea id="memory_contents" class="text_pole" rows="8" placeholder="Context will be generated here..."></textarea>
<div class="memory_contents_controls">
<input id="memory_restore" class="menu_button" type="submit" value="Restore previous state" />
<label for="memory_frozen"><input id="memory_frozen" type="checkbox" />Stop summarization updates</label>
</div>
<!--</div>
</div>
<div class="inline-drawer">
<div class="inline-drawer-toggle inline-drawer-header">
<b>Summarization parameters</b>
<b>Summarize</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">-->
<label for="memory_short_length">Chat to Summarize buffer length (<span id="memory_short_length_tokens"></span> tokens)</label>
<input id="memory_short_length" type="range" value="${defaultSettings.shortMemoryLength}" min="${defaultSettings.minShortMemory}" max="${defaultSettings.maxShortMemory}" step="${defaultSettings.shortMemoryStep}" />
<label for="memory_long_length">Summary output length (<span id="memory_long_length_tokens"></span> tokens)</label>
<input id="memory_long_length" type="range" value="${defaultSettings.longMemoryLength}" min="${defaultSettings.minLongMemory}" max="${defaultSettings.maxLongMemory}" step="${defaultSettings.longMemoryStep}" />
<label for="memory_temperature">Temperature (<span id="memory_temperature_value"></span>)</label>
<input id="memory_temperature" type="range" value="${defaultSettings.temperature}" min="${defaultSettings.minTemperature}" max="${defaultSettings.maxTemperature}" step="${defaultSettings.temperatureStep}" />
<label for="memory_repetition_penalty">Repetition penalty (<span id="memory_repetition_penalty_value"></span>)</label>
<input id="memory_repetition_penalty" type="range" value="${defaultSettings.repetitionPenalty}" min="${defaultSettings.minRepetitionPenalty}" max="${defaultSettings.maxRepetitionPenalty}" step="${defaultSettings.repetitionPenaltyStep}" />
<label for="memory_length_penalty">Length preference <small>[higher = longer summaries]</small> (<span id="memory_length_penalty_value"></span>)</label>
<input id="memory_length_penalty" type="range" value="${defaultSettings.lengthPenalty}" min="${defaultSettings.minLengthPenalty}" max="${defaultSettings.maxLengthPenalty}" step="${defaultSettings.lengthPenaltyStep}" />
<div class="inline-drawer-content">
<label for="summary_source">Summarization source:</label>
<select id="summary_source">
<option value="main">Main API</option>
<option value="extras">Extras API</option>
</select>
<label for="memory_contents">Current summary: </label>
<textarea id="memory_contents" class="text_pole textarea_compact" rows="6" placeholder="Summary will be generated here..."></textarea>
<div class="memory_contents_controls">
<input id="memory_restore" class="menu_button" type="button" value="Restore previous state" />
<label for="memory_frozen"><input id="memory_frozen" type="checkbox" />Pause summarization</label>
</div>
<div data-source="main" class="memory_contents_controls">
</div>
<div data-source="main">
<label for="memory_prompt" class="title_restorable">
Summarization Prompt
<div id="memory_force_summarize" class="menu_button menu_button_icon">
<i class="fa-solid fa-database"></i>
<span>Generate now</span>
</div>
</label>
<textarea id="memory_prompt" class="text_pole textarea_compact" rows="6" placeholder="This prompt will be used in summary generation. Insert {{words}} macro to use the "Number of words" parameter."></textarea>
<label for="memory_prompt_words">Number of words in the summary (<span id="memory_prompt_words_value"></span> words)</label>
<input id="memory_prompt_words" type="range" value="${defaultSettings.promptWords}" min="${defaultSettings.promptMinWords}" max="${defaultSettings.promptMaxWords}" step="${defaultSettings.promptWordsStep}" />
<label for="memory_prompt_interval">Update interval (<span id="memory_prompt_interval_value"></span> messages)</label>
<input id="memory_prompt_interval" type="range" value="${defaultSettings.promptInterval}" min="${defaultSettings.promptMinInterval}" max="${defaultSettings.promptMaxInterval}" step="${defaultSettings.promptIntervalStep}" />
</div>
<div data-source="extras">
<label for="memory_short_length">Chat to Summarize buffer length (<span id="memory_short_length_tokens"></span> tokens)</label>
<input id="memory_short_length" type="range" value="${defaultSettings.shortMemoryLength}" min="${defaultSettings.minShortMemory}" max="${defaultSettings.maxShortMemory}" step="${defaultSettings.shortMemoryStep}" />
<label for="memory_long_length">Summary output length (<span id="memory_long_length_tokens"></span> tokens)</label>
<input id="memory_long_length" type="range" value="${defaultSettings.longMemoryLength}" min="${defaultSettings.minLongMemory}" max="${defaultSettings.maxLongMemory}" step="${defaultSettings.longMemoryStep}" />
<label for="memory_temperature">Temperature (<span id="memory_temperature_value"></span>)</label>
<input id="memory_temperature" type="range" value="${defaultSettings.temperature}" min="${defaultSettings.minTemperature}" max="${defaultSettings.maxTemperature}" step="${defaultSettings.temperatureStep}" />
<label for="memory_repetition_penalty">Repetition penalty (<span id="memory_repetition_penalty_value"></span>)</label>
<input id="memory_repetition_penalty" type="range" value="${defaultSettings.repetitionPenalty}" min="${defaultSettings.minRepetitionPenalty}" max="${defaultSettings.maxRepetitionPenalty}" step="${defaultSettings.repetitionPenaltyStep}" />
<label for="memory_length_penalty">Length preference <small>[higher = longer summaries]</small> (<span id="memory_length_penalty_value"></span>)</label>
<input id="memory_length_penalty" type="range" value="${defaultSettings.lengthPenalty}" min="${defaultSettings.minLengthPenalty}" max="${defaultSettings.maxLengthPenalty}" step="${defaultSettings.lengthPenaltyStep}" />
</div>
</div>
</div>
</div>
@@ -362,10 +537,18 @@ $(document).ready(function () {
$('#memory_temperature').on('input', onMemoryTemperatureInput);
$('#memory_length_penalty').on('input', onMemoryLengthPenaltyInput);
$('#memory_frozen').on('input', onMemoryFrozenInput);
$('#summary_source').on('change', onSummarySourceChange);
$('#memory_prompt_words').on('input', onMemoryPromptWordsInput);
$('#memory_prompt_interval').on('input', onMemoryPromptIntervalInput);
$('#memory_prompt').on('input', onMemoryPromptInput);
$('#memory_force_summarize').on('click', forceSummarizeChat);
}
addExtensionControls();
loadSettings();
const wrapper = new ModuleWorkerWrapper(moduleWorker);
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL);
eventSource.on(event_types.MESSAGE_RECEIVED, onChatEvent);
eventSource.on(event_types.MESSAGE_DELETED, onChatEvent);
eventSource.on(event_types.MESSAGE_EDITED, onChatEvent);
eventSource.on(event_types.MESSAGE_SWIPED, onChatEvent);
eventSource.on(event_types.CHAT_CHANGED, onChatEvent);
});

View File

@@ -1,10 +1,10 @@
{
"display_name": "Memory",
"loading_order": 9,
"requires": [
"requires": [],
"optional": [
"summarize"
],
"optional": [],
"js": "index.js",
"css": "style.css",
"author": "Cohee#1207",

View File

@@ -8,17 +8,9 @@ const MODULE_NAME = 'quick-reply';
const UPDATE_INTERVAL = 1000;
const defaultSettings = {
quickReply1Mes: '',
quickReply1Label: '',
quickReply2Mes: '',
quickReply2Label: '',
quickReply3Mes: '',
quickReply3Label: '',
quickReply4Mes: '',
quickReply4Label: '',
quickReply5Mes: '',
quickReply5Label: '',
quickReplyEnabled: false,
numberOfSlots: 5,
quickReplySlots: [],
}
async function loadSettings() {
@@ -26,33 +18,44 @@ async function loadSettings() {
Object.assign(extension_settings.quickReply, defaultSettings);
}
// If the user has an old version of the extension, update it
if (!Array.isArray(extension_settings.quickReply.quickReplySlots)) {
extension_settings.quickReply.quickReplySlots = [];
extension_settings.quickReply.numberOfSlots = defaultSettings.numberOfSlots;
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
extension_settings.quickReply.quickReplySlots.push({
mes: extension_settings.quickReply[`quickReply${i}Mes`],
label: extension_settings.quickReply[`quickReply${i}Label`],
enabled: true,
});
delete extension_settings.quickReply[`quickReply${i}Mes`];
delete extension_settings.quickReply[`quickReply${i}Label`];
}
}
initializeEmptySlots(extension_settings.quickReply.numberOfSlots);
generateQuickReplyElements();
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
$(`#quickReply${i}Mes`).val(extension_settings.quickReply.quickReplySlots[i - 1]?.mes).trigger('input');
$(`#quickReply${i}Label`).val(extension_settings.quickReply.quickReplySlots[i - 1]?.label).trigger('input');
}
$('#quickReplyEnabled').prop('checked', extension_settings.quickReply.quickReplyEnabled);
$('#quickReply1Mes').val(extension_settings.quickReply.quickReply1Mes).trigger('input');
$('#quickReply1Label').val(extension_settings.quickReply.quickReply1Label).trigger('input');
$('#quickReply2Mes').val(extension_settings.quickReply.quickReply2Mes).trigger('input');
$('#quickReply2Label').val(extension_settings.quickReply.quickReply2Label).trigger('input');
$('#quickReply3Mes').val(extension_settings.quickReply.quickReply3Mes).trigger('input');
$('#quickReply3Label').val(extension_settings.quickReply.quickReply3Label).trigger('input');
$('#quickReply4Mes').val(extension_settings.quickReply.quickReply4Mes).trigger('input');
$('#quickReply4Label').val(extension_settings.quickReply.quickReply4Label).trigger('input');
$('#quickReply5Mes').val(extension_settings.quickReply.quickReply5Mes).trigger('input');
$('#quickReply5Label').val(extension_settings.quickReply.quickReply5Label).trigger('input');
$('#quickReplyNumberOfSlots').val(extension_settings.quickReply.numberOfSlots);
}
function onQuickReplyInput(id) {
extension_settings.quickReply[`quickReply${id}Mes`] = $(`#quickReply${id}Mes`).val();
extension_settings.quickReply.quickReplySlots[id - 1].mes = $(`#quickReply${id}Mes`).val();
$(`#quickReply${id}`).attr('title', ($(`#quickReply${id}Mes`).val()));
resetScrollHeight($(`#quickReply${id}Mes`));
saveSettingsDebounced();
}
function onQuickReplyLabelInput(id) {
extension_settings.quickReply[`quickReply${id}Label`] = $(`#quickReply${id}Label`).val();
extension_settings.quickReply.quickReplySlots[id - 1].label = $(`#quickReply${id}Label`).val();
$(`#quickReply${id}`).text($(`#quickReply${id}Label`).val());
saveSettingsDebounced();
}
@@ -66,44 +69,115 @@ async function onQuickReplyEnabledInput() {
saveSettingsDebounced();
}
async function sendQuickReply(id) {
var prompt = extension_settings.quickReply[`${id}Mes`];
async function sendQuickReply(index) {
const prompt = extension_settings.quickReply.quickReplySlots[index]?.mes || '';
if (!prompt) {
console.warn(`Quick reply slot ${index} is empty! Aborting.`);
return;
}
$("#send_textarea").val(prompt);
$("#send_but").trigger('click');
}
function addQuickReplyBar(numButtons) {
var numButtons = 5;
const quickReplyBarStartHtml = `
<div id="quickReplyBar" class="flex-container flexGap5">
<div id="quickReplies">
`;
function addQuickReplyBar() {
$('#quickReplyBar').remove();
let quickReplyButtonHtml = '';
for (let i = 0; i < numButtons; i++) {
let quickReplyMes = extension_settings.quickReply[`quickReply${i + 1}Mes`];
let quickReplyLabel = extension_settings.quickReply[`quickReply${i + 1}Label`];
//console.log(quickReplyMes);
quickReplyButtonHtml += `<div title="${quickReplyMes}" class="quickReplyButton" id="quickReply${i + 1}">${quickReplyLabel}</div>`;
for (let i = 0; i < extension_settings.quickReply.numberOfSlots; i++) {
let quickReplyMes = extension_settings.quickReply.quickReplySlots[i]?.mes || '';
let quickReplyLabel = extension_settings.quickReply.quickReplySlots[i]?.label || '';
quickReplyButtonHtml += `<div title="${quickReplyMes}" class="quickReplyButton" data-index="${i}" id="quickReply${i + 1}">${quickReplyLabel}</div>`;
}
const quickReplyEndHtml = `</div></div>`
const quickReplyBarFullHtml = [quickReplyBarStartHtml, quickReplyButtonHtml, quickReplyEndHtml].join('');
const quickReplyBarFullHtml = `
<div id="quickReplyBar" class="flex-container flexGap5">
<div id="quickReplies">
${quickReplyButtonHtml}
</div>
</div>
`;
$('#send_form').prepend(quickReplyBarFullHtml);
$('.quickReplyButton').on('click', function () {
console.log('got quick reply click');
let quickReplyButtonID = $(this).attr('id');
sendQuickReply(quickReplyButtonID);
let index = $(this).data('index');
sendQuickReply(index);
});
}
async function moduleWorker() {
if (extension_settings.quickReply.quickReplyEnabled === true) {
$('#quickReplyBar').toggle(getContext().onlineStatus !== 'no_connection');
}
}
async function onQuickReplyNumberOfSlotsInput() {
const $input = $('#quickReplyNumberOfSlots');
let numberOfSlots = Number($input.val());
if (isNaN(numberOfSlots)) {
numberOfSlots = defaultSettings.numberOfSlots;
}
// Clamp min and max values (from input attributes)
if (numberOfSlots < Number($input.attr('min'))) {
numberOfSlots = Number($input.attr('min'));
} else if (numberOfSlots > Number($input.attr('max'))) {
numberOfSlots = Number($input.attr('max'));
}
extension_settings.quickReply.numberOfSlots = numberOfSlots;
extension_settings.quickReply.quickReplySlots.length = numberOfSlots;
// Initialize new slots
initializeEmptySlots(numberOfSlots);
await loadSettings();
addQuickReplyBar();
moduleWorker();
saveSettingsDebounced();
}
function initializeEmptySlots(numberOfSlots) {
for (let i = 0; i < numberOfSlots; i++) {
if (!extension_settings.quickReply.quickReplySlots[i]) {
extension_settings.quickReply.quickReplySlots[i] = {
mes: '',
label: '',
enabled: true,
};
}
}
}
function generateQuickReplyElements() {
let quickReplyHtml = '';
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
quickReplyHtml += `
<div class="flex-container alignitemsflexstart">
<input class="text_pole wide30p" id="quickReply${i}Label" placeholder="(Add a button label)">
<textarea id="quickReply${i}Mes" placeholder="(custom message here)" class="text_pole widthUnset flex1" rows="2"></textarea>
</div>
`;
}
$('#quickReplyContainer').empty().append(quickReplyHtml);
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
$(`#quickReply${i}Mes`).on('input', function () { onQuickReplyInput(i); });
$(`#quickReply${i}Label`).on('input', function () { onQuickReplyLabelInput(i); });
}
$('.quickReplySettings .inline-drawer-toggle').off('click').on('click', function () {
for (let i = 1; i <= extension_settings.quickReply.numberOfSlots; i++) {
initScrollHeight($(`#quickReply${i}Mes`));
}
});
}
jQuery(async () => {
moduleWorker();
@@ -116,57 +190,28 @@ jQuery(async () => {
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<label class="checkbox_label">
<label class="checkbox_label marginBot10">
<input id="quickReplyEnabled" type="checkbox" />
Enable Quick Replies
</label>
<label for="quickReplyNumberOfSlots">Number of slots:</label>
<div class="flex-container flexGap5 flexnowrap">
<input id="quickReplyNumberOfSlots" class="text_pole" type="number" min="1" max="100" value="" />
<div class="menu_button menu_button_icon" id="quickReplyNumberOfSlotsApply">
<div class="fa-solid fa-check"></div>
<span>Apply</span>
</div>
</div>
<small><i>Customize your Quick Replies:</i></small><br>
<div class="flex-container alignitemsflexstart">
<input class="text_pole wide30p" id="quickReply1Label" placeholder="(Add a button label)">
<textarea id="quickReply1Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
</div>
<div class="flex-container alignitemsflexstart">
<input class="text_pole wide30p" id="quickReply2Label" placeholder="(Add a button label)">
<textarea id="quickReply2Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
</div>
<div class="flex-container alignitemsflexstart">
<input class="text_pole wide30p" id="quickReply3Label" placeholder="(Add a button label)">
<textarea id="quickReply3Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
</div>
<div class="flex-container alignitemsflexstart">
<input class="text_pole wide30p" id="quickReply4Label" placeholder="(Add a button label)">
<textarea id="quickReply4Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
</div>
<div class="flex-container alignitemsflexstart">
<input class="text_pole wide30p" id="quickReply5Label" placeholder="(Add a button label)">
<textarea id="quickReply5Mes" placeholder="(custom message here)" class="text_pole textarea_compact widthUnset flex1" rows="2"></textarea>
<div id="quickReplyContainer">
</div>
</div>
</div>`;
$('#extensions_settings2').append(settingsHtml);
$('#quickReply1Mes').on('input', function () { onQuickReplyInput(1); });
$('#quickReply2Mes').on('input', function () { onQuickReplyInput(2); });
$('#quickReply3Mes').on('input', function () { onQuickReplyInput(3); });
$('#quickReply4Mes').on('input', function () { onQuickReplyInput(4); });
$('#quickReply5Mes').on('input', function () { onQuickReplyInput(5); });
$('#quickReply1Label').on('input', function () { onQuickReplyLabelInput(1); });
$('#quickReply2Label').on('input', function () { onQuickReplyLabelInput(2); });
$('#quickReply3Label').on('input', function () { onQuickReplyLabelInput(3); });
$('#quickReply4Label').on('input', function () { onQuickReplyLabelInput(4); });
$('#quickReply5Label').on('input', function () { onQuickReplyLabelInput(5); });
$('#quickReplyEnabled').on('input', onQuickReplyEnabledInput);
$('.quickReplySettings .inline-drawer-toggle').on('click', function () {
initScrollHeight($("#quickReply1Mes"));
initScrollHeight($("#quickReply2Mes"));
initScrollHeight($("#quickReply3Mes"));
initScrollHeight($("#quickReply4Mes"));
initScrollHeight($("#quickReply5Mes"));
})
$('#quickReplyNumberOfSlotsApply').on('click', onQuickReplyNumberOfSlotsInput);
await loadSettings();
addQuickReplyBar();

View File

@@ -10,6 +10,8 @@
justify-content: center;
width: 100%;
display: none;
max-width: 100%;
overflow-x: auto;
}
#quickReplies {
@@ -17,7 +19,7 @@
padding: 0;
display: flex;
justify-content: center;
flex-wrap: nowrap;
flex-wrap: wrap;
gap: 5px;
width: 100%;
}
@@ -41,4 +43,4 @@
opacity: 1;
filter: brightness(1.2);
cursor: pointer;
}
}

View File

@@ -0,0 +1,152 @@
import { saveSettingsDebounced } from "../../../script.js";
import { extension_settings } from "../../extensions.js";
function toggleRandomizedSetting(buttonRef, forId) {
if (extension_settings.randomizer.controls.indexOf(forId) === -1) {
extension_settings.randomizer.controls.push(forId);
} else {
extension_settings.randomizer.controls = extension_settings.randomizer.controls.filter(x => x !== forId);
}
buttonRef.toggleClass('active');
console.debug('Randomizer controls:', extension_settings.randomizer.controls);
saveSettingsDebounced();
}
function addRandomizeButton() {
const counterRef = $(this);
const labelRef = $(this).find('div[data-for]');
const isDisabled = counterRef.data('randomization-disabled');
if (labelRef.length === 0 || isDisabled == true) {
return;
}
const forId = labelRef.data('for');
const buttonRef = $('<div class="randomize_button menu_button fa-solid fa-shuffle"></div>');
buttonRef.toggleClass('active', extension_settings.randomizer.controls.indexOf(forId) !== -1);
buttonRef.hide();
buttonRef.on('click', () => toggleRandomizedSetting(buttonRef, forId));
counterRef.append(buttonRef);
}
function onRandomizerEnabled() {
extension_settings.randomizer.enabled = $(this).prop('checked');
$('.randomize_button').toggle(extension_settings.randomizer.enabled);
console.debug('Randomizer enabled:', extension_settings.randomizer.enabled);
}
window['randomizerInterceptor'] = (function () {
if (extension_settings.randomizer.enabled === false) {
console.debug('Randomizer skipped: disabled.');
return;
}
if (extension_settings.randomizer.fluctuation === 0 || extension_settings.randomizer.controls.length === 0) {
console.debug('Randomizer skipped: nothing to do.');
return;
}
for (const control of extension_settings.randomizer.controls) {
const controlRef = $('#' + control);
if (controlRef.length === 0) {
console.debug(`Randomizer skipped: control ${control} not found.`);
continue;
}
if (!controlRef.is(':visible')) {
console.debug(`Randomizer skipped: control ${control} is not visible.`);
continue;
}
let previousValue = parseFloat(controlRef.data('previous-value'));
let originalValue = parseFloat(controlRef.data('original-value'));
let currentValue = parseFloat(controlRef.val());
let value;
// Initialize originalValue and previousValue if they are NaN
if (isNaN(originalValue)) {
originalValue = currentValue;
controlRef.data('original-value', originalValue);
}
if (isNaN(previousValue)) {
previousValue = currentValue;
controlRef.data('previous-value', previousValue);
}
// If the current value hasn't changed compared to the previous value, use the original value as a base for the calculation
if (currentValue === previousValue) {
console.debug(`Randomizer for ${control} reusing original value: ${originalValue}`);
value = originalValue;
} else {
console.debug(`Randomizer for ${control} using current value: ${currentValue}`);
value = currentValue;
controlRef.data('previous-value', currentValue); // Update the previous value when using the current value
controlRef.data('original-value', currentValue); // Update the original value when using the current value
}
if (isNaN(value)) {
console.debug('Randomizer skipped: NaN.');
continue;
}
const fluctuation = extension_settings.randomizer.fluctuation;
const min = parseFloat(controlRef.attr('min'));
const max = parseFloat(controlRef.attr('max'));
const delta = (Math.random() * fluctuation * 2 - fluctuation) * value;
const newValue = Math.min(Math.max(value + delta, min), max);
console.debug(`Randomizer for ${control}: ${value} -> ${newValue} (delta: ${delta}, min: ${min}, max: ${max})`);
controlRef.val(newValue).trigger('input');
controlRef.data('previous-value', parseFloat(controlRef.val()));
}
});
jQuery(() => {
const html = `
<div class="randomizer_settings">
<div class="inline-drawer">
<div class="inline-drawer-toggle inline-drawer-header">
<b>Parameter Randomizer</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<label for="randomizer_enabled" class="checkbox_label">
<input type="checkbox" id="randomizer_enabled" name="randomizer_enabled" >
Enabled
</label>
<div class="range-block">
<div class="range-block-title">
Fluctuation (0-1)
</div>
<div class="range-block-range-and-counter">
<div class="range-block-range-and-counter">
<div class="range-block-range">
<input type="range" id="randomizer_fluctuation" min="0" max="1" step="0.1">
</div>
<div class="range-block-counter">
<div contenteditable="true" data-for="randomizer_fluctuation" id="randomizer_fluctuation_counter">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>`;
$('#extensions_settings').append(html);
$('#ai_response_configuration .range-block-counter').each(addRandomizeButton);
$('#randomizer_enabled').on('input', onRandomizerEnabled);
$('#randomizer_enabled').prop('checked', extension_settings.randomizer.enabled).trigger('input');
$('#randomizer_fluctuation').val(extension_settings.randomizer.fluctuation).trigger('input');
$('#randomizer_fluctuation_counter').text(extension_settings.randomizer.fluctuation);
$('#randomizer_fluctuation').on('input', function () {
const value = parseFloat($(this).val());
$('#randomizer_fluctuation_counter').text(value);
extension_settings.randomizer.fluctuation = value;
console.debug('Randomizer fluctuation:', extension_settings.randomizer.fluctuation);
saveSettingsDebounced();
});
});

View File

@@ -0,0 +1,12 @@
{
"display_name": "Parameter Randomizer",
"loading_order": 15,
"requires": [],
"optional": [],
"js": "index.js",
"css": "style.css",
"author": "Cohee#1207",
"version": "1.0.0",
"generate_interceptor": "randomizerInterceptor",
"homePage": "https://github.com/SillyTavern/SillyTavern"
}

View File

@@ -0,0 +1,17 @@
<div class="regex_settings">
<div class="inline-drawer">
<div class="inline-drawer-toggle inline-drawer-header">
<b>Regex</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<div id="open_regex_editor" class="menu_button">
<i class="fa-solid fa-pen-to-square"></i>
<span>Open Editor</span>
</div>
<hr />
<label>Saved Scripts</label>
<div id="saved_regex_scripts" class="flex-container regex-script-container flexFlowColumn"></div>
</div>
</div>
</div>

View File

@@ -0,0 +1,107 @@
<div id="regex_editor_template">
<div class="regex_editor">
<h3><strong data-i18n="Regex Editor">Regex Editor</strong>
<a href="https://regexr.com/" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h3>
<small class="flex-container extensions_info">
Regex is a tool to find/replace strings using regular expressions. If you want to learn more, click on the ? next to the title.
</small>
<hr />
<div class="flex-container flexFlowColumn">
<div class="flex1">
<label for="regex_script_name" class="title_restorable">
<small data-i18n="Script Name">Script Name</small>
</label>
<div>
<input class="regex_script_name text_pole textarea_compact" type="text" />
</div>
</div>
<div class="flex1">
<label for="find_regex" class="title_restorable">
<small data-i18n="Find Regex">Find Regex</small>
</label>
<div>
<input class="find_regex text_pole textarea_compact" type="text" />
</div>
</div>
<div class="flex1">
<label for="regex_replace_string" class="title_restorable">
<small data-i18n="Replace With">Replace With</small>
</label>
<div>
<textarea
class="regex_replace_string text_pole wide100p textarea_compact"
placeholder="Use {{match}} to include the matched text from the Find Regex"
rows="2"
></textarea>
</div>
</div>
<div class="flex1">
<label for="regex_trim_strings" class="title_restorable">
<small data-i18n="Trim Out">Trim Out</small>
</label>
<div>
<textarea
class="regex_trim_strings text_pole wide100p textarea_compact"
placeholder="Globally trims any unwanted parts from a regex match before replacement. Separate each element by an enter."
rows="3"
></textarea>
</div>
</div>
</div>
<div class="flex-container">
<div class="wi-enter-footer-text flex-container flexFlowColumn flexNoGap alignitemsstart">
<small>Affects</small>
<div>
<label class="checkbox flex-container">
<input type="checkbox" name="replace_position" value="1">
<span data-i18n="Before Char">User Input</span>
</label>
</div>
<div>
<label class="checkbox flex-container">
<input type="checkbox" name="replace_position" value="2">
<span data-i18n="After Char">AI Output</span>
</label>
</div>
<div>
<label class="checkbox flex-container">
<input type="checkbox" name="replace_position" value="3">
<span data-i18n="Slash Commands">Slash Commands</span>
</label>
</div>
</div>
<div class="wi-enter-footer-text flex-container flexFlowColumn flexNoGap alignitemsstart">
<small>Other Options</small>
<label class="checkbox flex-container">
<input type="checkbox" name="disabled" />
<span data-i18n="Disabled">Disabled</span>
</label>
<label class="checkbox flex-container">
<input type="checkbox" name="only_format_display" />
<span data-i18n="Only Format Display">Only Format Display</span>
</label>
<label class="checkbox flex-container">
<input type="checkbox" name="run_on_edit" />
<span data-i18n="Run On Edit">Run On Edit</span>
</label>
<label class="checkbox flex-container">
<input type="checkbox" name="substitute_regex" />
<span data-i18n="Substitute Regex">Substitute Regex</span>
</label>
</div>
<div class="flex-container flexFlowColumn alignitemsstart">
<small>Replacement Strategy</small>
<select name="replace_strategy_select" class="margin0">
<option value="0">Replace</option>
<option value="1">Overlay</option>
</select>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,194 @@
import { substituteParams } from "../../../script.js";
import { extension_settings } from "../../extensions.js";
export {
regex_placement,
getRegexedString,
runRegexScript
}
const regex_placement = {
// MD Display is deprecated. Do not use.
MD_DISPLAY: 0,
USER_INPUT: 1,
AI_OUTPUT: 2,
SLASH_COMMAND: 3
}
const regex_replace_strategy = {
REPLACE: 0,
OVERLAY: 1
}
// Originally from: https://github.com/IonicaBizau/regex-parser.js/blob/master/lib/index.js
function regexFromString(input) {
try {
// Parse input
var m = input.match(/(\/?)(.+)\1([a-z]*)/i);
// Invalid flags
if (m[3] && !/^(?!.*?(.).*?\1)[gmixXsuUAJ]+$/.test(m[3])) {
return RegExp(input);
}
// Create the regular expression
return new RegExp(m[2], m[3]);
} catch {
return;
}
}
// Parent function to fetch a regexed version of a raw string
function getRegexedString(rawString, placement, { characterOverride, isMarkdown } = {}) {
let finalString = rawString;
if (extension_settings.disabledExtensions.includes("regex") || !rawString || placement === undefined) {
return finalString;
}
extension_settings.regex.forEach((script) => {
if ((script.markdownOnly && !isMarkdown) || (!script.markdownOnly && isMarkdown)) {
return;
}
if (script.placement.includes(placement)) {
finalString = runRegexScript(script, finalString, { characterOverride });
}
});
return finalString;
}
// Runs the provided regex script on the given string
function runRegexScript(regexScript, rawString, { characterOverride } = {}) {
let newString = rawString;
if (!regexScript || !!(regexScript.disabled) || !regexScript?.findRegex || !rawString) {
return newString;
}
let match;
const findRegex = regexFromString(regexScript.substituteRegex ? substituteParams(regexScript.findRegex) : regexScript.findRegex);
// The user skill issued. Return with nothing.
if (!findRegex) {
return newString;
}
while ((match = findRegex.exec(rawString)) !== null) {
const fencedMatch = match[0];
const capturedMatch = match[1];
let trimCapturedMatch;
let trimFencedMatch;
if (capturedMatch) {
const tempTrimCapture = filterString(capturedMatch, regexScript.trimStrings, { characterOverride });
trimFencedMatch = fencedMatch.replaceAll(capturedMatch, tempTrimCapture);
trimCapturedMatch = tempTrimCapture;
} else {
trimFencedMatch = filterString(fencedMatch, regexScript.trimStrings, { characterOverride });
}
// TODO: Use substrings for replacement. But not necessary at this time.
// A substring is from match.index to match.index + match[0].length or fencedMatch.length
const subReplaceString = substituteRegexParams(
regexScript.replaceString,
trimCapturedMatch ?? trimFencedMatch,
{
characterOverride,
replaceStrategy: regexScript.replaceStrategy ?? regex_replace_strategy.REPLACE
}
);
if (!newString) {
newString = rawString.replace(fencedMatch, subReplaceString);
} else {
newString = newString.replace(fencedMatch, subReplaceString);
}
// If the regex isn't global, break out of the loop
if (!findRegex.flags.includes('g')) {
break;
}
}
return newString;
}
// Filters anything to trim from the regex match
function filterString(rawString, trimStrings, { characterOverride } = {}) {
let finalString = rawString;
trimStrings.forEach((trimString) => {
const subTrimString = substituteParams(trimString, undefined, characterOverride);
finalString = finalString.replaceAll(subTrimString, "");
});
return finalString;
}
// Substitutes regex-specific and normal parameters
function substituteRegexParams(rawString, regexMatch, { characterOverride, replaceStrategy } = {}) {
let finalString = rawString;
finalString = substituteParams(finalString, undefined, characterOverride);
let overlaidMatch = regexMatch;
// TODO: Maybe move the for loops into a separate function?
if (replaceStrategy === regex_replace_strategy.OVERLAY) {
const splitReplace = finalString.split("{{match}}");
// There's a prefix
if (splitReplace[0]) {
// Fetch the prefix
const splicedPrefix = spliceSymbols(splitReplace[0], false);
// Sequentially remove all occurrences of prefix from start of split
const splitMatch = overlaidMatch.split(splicedPrefix);
let sliceNum = 0;
for (let index = 0; index < splitMatch.length; index++) {
if (splitMatch[index].length === 0) {
sliceNum++;
} else {
break;
}
}
overlaidMatch = splitMatch.slice(sliceNum, splitMatch.length).join(splicedPrefix);
}
// There's a suffix
if (splitReplace[1]) {
// Fetch the suffix
const splicedSuffix = spliceSymbols(splitReplace[1], true);
// Sequential removal of all suffix occurrences from end of split
const splitMatch = overlaidMatch.split(splicedSuffix);
let sliceNum = 0;
for (let index = splitMatch.length - 1; index >= 0; index--) {
if (splitMatch[index].length === 0) {
sliceNum++;
} else {
break;
}
}
overlaidMatch = splitMatch.slice(0, splitMatch.length - sliceNum).join(splicedSuffix);
}
}
// Only one match is replaced. This is by design
finalString = finalString.replace("{{match}}", overlaidMatch) || finalString.replace("{{match}}", regexMatch);
return finalString;
}
// Splices common sentence symbols and whitespace from the beginning and end of a string
// Using a for loop due to sequential ordering
function spliceSymbols(rawString, isSuffix) {
let offset = 0;
for (const ch of isSuffix ? rawString.split('').reverse() : rawString) {
if (ch.match(/[^\w.,?'!]/)) {
offset++;
} else {
break;
}
}
return isSuffix ? rawString.substring(0, rawString.length - offset) : rawString.substring(offset);
}

View File

@@ -0,0 +1,260 @@
import { callPopup, eventSource, event_types, getCurrentChatId, reloadCurrentChat, saveSettingsDebounced } from "../../../script.js";
import { extension_settings } from "../../extensions.js";
import { uuidv4, waitUntilCondition } from "../../utils.js";
import { regex_placement } from "./engine.js";
async function saveRegexScript(regexScript, existingScriptIndex) {
// If not editing
if (existingScriptIndex === -1) {
// Is the script name undefined?
if (!regexScript.scriptName) {
toastr.error(`Could not save regex script: The script name was undefined or empty!`);
return;
}
// Does the script name already exist?
if (extension_settings.regex.find((e) => e.scriptName === regexScript.scriptName)) {
toastr.error(`Could not save regex script: A script with name ${regexScript.scriptName} already exists.`);
return;
}
} else {
// Does the script name already exist somewhere else?
// (If this fails, make it a .filter().map() to index array)
const foundIndex = extension_settings.regex.findIndex((e) => e.scriptName === regexScript.scriptName);
if (foundIndex !== existingScriptIndex && foundIndex !== -1) {
toastr.error(`Could not save regex script: A script with name ${regexScript.scriptName} already exists.`);
return;
}
}
// Is a find regex present?
if (regexScript.findRegex.length === 0) {
toastr.error(`Could not save regex script: A find regex is required!`);
return;
}
// Is there someplace to place results?
if (regexScript.placement.length === 0) {
toastr.error(`Could not save regex script: One placement checkbox must be selected!`);
return;
}
if (existingScriptIndex !== -1) {
extension_settings.regex[existingScriptIndex] = regexScript;
} else {
extension_settings.regex.push(regexScript);
}
saveSettingsDebounced();
await loadRegexScripts();
// Reload the current chat to undo previous markdown
const currentChatId = getCurrentChatId();
if (currentChatId !== undefined && currentChatId !== null) {
await reloadCurrentChat();
}
}
async function deleteRegexScript({ existingId }) {
let scriptName = $(`#${existingId}`).find('.regex_script_name').text();
const existingScriptIndex = extension_settings.regex.findIndex((script) => script.scriptName === scriptName);
if (!existingScriptIndex || existingScriptIndex !== -1) {
extension_settings.regex.splice(existingScriptIndex, 1);
saveSettingsDebounced();
await loadRegexScripts();
}
}
async function loadRegexScripts() {
$("#saved_regex_scripts").empty();
const scriptTemplate = $(await $.get("scripts/extensions/regex/scriptTemplate.html"));
extension_settings.regex.forEach((script) => {
// Have to clone here
const scriptHtml = scriptTemplate.clone();
scriptHtml.attr('id', uuidv4());
scriptHtml.find('.regex_script_name').text(script.scriptName);
scriptHtml.find('.edit_existing_regex').on('click', async function() {
await onRegexEditorOpenClick(scriptHtml.attr("id"));
});
scriptHtml.find('.delete_regex').on('click', async function() {
await deleteRegexScript({ existingId: scriptHtml.attr("id") });
});
$("#saved_regex_scripts").append(scriptHtml);
});
}
async function onRegexEditorOpenClick(existingId) {
const editorHtml = $(await $.get("scripts/extensions/regex/editor.html"));
// If an ID exists, fill in all the values
let existingScriptIndex = -1;
if (existingId) {
const existingScriptName = $(`#${existingId}`).find('.regex_script_name').text();
existingScriptIndex = extension_settings.regex.findIndex((script) => script.scriptName === existingScriptName);
if (existingScriptIndex !== -1) {
const existingScript = extension_settings.regex[existingScriptIndex];
if (existingScript.scriptName) {
editorHtml.find(`.regex_script_name`).val(existingScript.scriptName);
} else {
toastr.error("This script doesn't have a name! Please delete it.")
return;
}
editorHtml.find(`.find_regex`).val(existingScript.findRegex || "");
editorHtml.find(`.regex_replace_string`).val(existingScript.replaceString || "");
editorHtml.find(`.regex_trim_strings`).val(existingScript.trimStrings?.join("\n") || []);
editorHtml
.find(`input[name="disabled"]`)
.prop("checked", existingScript.disabled ?? false);
editorHtml
.find(`input[name="only_format_display"]`)
.prop("checked", existingScript.markdownOnly ?? false);
editorHtml
.find(`input[name="run_on_edit"]`)
.prop("checked", existingScript.runOnEdit ?? false);
editorHtml
.find(`input[name="substitute_regex"]`)
.prop("checked", existingScript.substituteRegex ?? false);
editorHtml
.find(`select[name="replace_strategy_select"]`)
.val(existingScript.replaceStrategy ?? 0);
existingScript.placement.forEach((element) => {
editorHtml
.find(`input[name="replace_position"][value="${element}"]`)
.prop("checked", true);
});
}
} else {
editorHtml
.find(`input[name="only_format_display"]`)
.prop("checked", true);
editorHtml
.find(`input[name="run_on_edit"]`)
.prop("checked", true);
editorHtml
.find(`input[name="replace_position"][value="0"]`)
.prop("checked", true);
}
const popupResult = await callPopup(editorHtml, "confirm", undefined, { okButton: "Save" });
if (popupResult) {
const newRegexScript = {
scriptName: editorHtml.find(".regex_script_name").val(),
findRegex: editorHtml.find(".find_regex").val(),
replaceString: editorHtml.find(".regex_replace_string").val(),
trimStrings: editorHtml.find(".regex_trim_strings").val().split("\n").filter((e) => e.length !== 0) || [],
placement:
editorHtml
.find(`input[name="replace_position"]`)
.filter(":checked")
.map(function() { return parseInt($(this).val()) })
.get()
.filter((e) => e !== NaN) || [],
disabled:
editorHtml
.find(`input[name="disabled"]`)
.prop("checked"),
markdownOnly:
editorHtml
.find(`input[name="only_format_display"]`)
.prop("checked"),
runOnEdit:
editorHtml
.find(`input[name="run_on_edit"]`)
.prop("checked"),
substituteRegex:
editorHtml
.find(`input[name="substitute_regex"]`)
.prop("checked"),
replaceStrategy:
parseInt(editorHtml
.find(`select[name="replace_strategy_select"]`)
.find(`:selected`)
.val()) ?? 0
};
saveRegexScript(newRegexScript, existingScriptIndex);
}
}
// Common settings migration function. Some parts will eventually be removed
// TODO: Maybe migrate placement to strings?
function migrateSettings() {
let performSave = false;
// Current: If MD Display is present in placement, remove it and add new placements/MD option
extension_settings.regex.forEach((script) => {
if (script.placement.includes(regex_placement.MD_DISPLAY)) {
script.placement = script.placement.length === 1 ?
Object.values(regex_placement).filter((e) => e !== regex_placement.MD_DISPLAY) :
script.placement = script.placement.filter((e) => e !== regex_placement.MD_DISPLAY);
script.markdownOnly = true
performSave = true;
}
// Old system and sendas placement migration
// 4 - sendAs
if (script.placement.includes(4)) {
script.placement = script.placement.length === 1 ?
[regex_placement.SLASH_COMMAND] :
script.placement = script.placement.filter((e) => e !== 4);
performSave = true;
}
});
if (performSave) {
saveSettingsDebounced();
}
}
// Workaround for loading in sequence with other extensions
// NOTE: Always puts extension at the top of the list, but this is fine since it's static
jQuery(async () => {
if (extension_settings.regex) {
migrateSettings();
}
// Manually disable the extension since static imports auto-import the JS file
if (extension_settings.disabledExtensions.includes("regex")) {
return;
}
const settingsHtml = await $.get("scripts/extensions/regex/dropdown.html");
$("#extensions_settings2").append(settingsHtml);
$("#open_regex_editor").on("click", function() {
onRegexEditorOpenClick(false);
});
$('#saved_regex_scripts').sortable({
stop: function () {
let newScripts = [];
$('#saved_regex_scripts').children().each(function () {
const scriptName = $(this).find(".regex_script_name").text();
const existingScript = extension_settings.regex.find((e) => e.scriptName === scriptName);
if (existingScript) {
newScripts.push(existingScript);
}
});
extension_settings.regex = newScripts;
saveSettingsDebounced();
console.debug("Regex scripts reordered");
// TODO: Maybe reload regex scripts after move
},
});
await loadRegexScripts();
$("#saved_regex_scripts").sortable("enable");
});

View File

@@ -1,11 +1,11 @@
{
"display_name": "Author's Note (Located in Lower Left Options Menu)",
"display_name": "Regex",
"loading_order": 1,
"requires": [],
"optional": [],
"js": "index.js",
"css": "style.css",
"author": "Cohee#1207",
"author": "kingbri",
"version": "1.0.0",
"homePage": "https://github.com/SillyTavern/SillyTavern"
}

Some files were not shown because too many files have changed in this diff Show More