sillytavern 1.17.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/Dockerfile +1 -1
  2. package/Start.bat +1 -1
  3. package/UpdateAndStart.bat +1 -1
  4. package/UpdateForkAndStart.bat +1 -1
  5. package/default/config.yaml +48 -3
  6. package/default/{public/error → content/errors}/url-not-found.html +2 -2
  7. package/default/content/index.json +32 -0
  8. package/default/content/presets/context/Gemma 4.json +14 -0
  9. package/default/content/presets/instruct/Gemma 4.json +25 -0
  10. package/default/content/presets/openai/Default.json +2 -0
  11. package/default/content/presets/reasoning/Gemma 4.json +6 -0
  12. package/docker/docker-entrypoint.sh +3 -3
  13. package/index.d.ts +4 -0
  14. package/package.json +11 -8
  15. package/public/css/!USER-CSS-README.md +7 -0
  16. package/public/css/extensions-panel.css +12 -2
  17. package/public/css/mobile-styles.css +5 -0
  18. package/public/css/streaming-display.css +236 -0
  19. package/public/css/toggle-dependent.css +4 -0
  20. package/public/css/welcome.css +1 -0
  21. package/public/img/kobold.svg +5 -77
  22. package/public/img/koboldcpp.svg +5 -77
  23. package/public/img/koboldhorde.svg +6 -47
  24. package/public/img/logo.svg +2 -0
  25. package/public/img/minimax.svg +1 -0
  26. package/public/img/pollinations.svg +4 -1
  27. package/public/img/scale.svg +2 -60
  28. package/public/img/textgenerationwebui.svg +6 -87
  29. package/public/img/workers_ai.svg +9 -0
  30. package/public/index.html +147 -106
  31. package/public/lib.js +3 -0
  32. package/public/script.js +92 -36
  33. package/public/scripts/BulkEditOverlay.js +1 -0
  34. package/public/scripts/RossAscends-mods.js +2 -0
  35. package/public/scripts/a11y.js +1 -0
  36. package/public/scripts/action-loader-slashcommands.js +22 -7
  37. package/public/scripts/action-loader.js +47 -2
  38. package/public/scripts/bookmarks.js +1 -0
  39. package/public/scripts/browser-fixes.js +8 -0
  40. package/public/scripts/chats.js +4 -1
  41. package/public/scripts/custom-request.js +3 -2
  42. package/public/scripts/dynamic-styles.js +6 -0
  43. package/public/scripts/events.js +8 -0
  44. package/public/scripts/extensions/assets/index.js +311 -212
  45. package/public/scripts/extensions/assets/installation.html +19 -1
  46. package/public/scripts/extensions/assets/manifest.json +4 -1
  47. package/public/scripts/extensions/assets/style.css +16 -3
  48. package/public/scripts/extensions/attachments/index.js +2 -2
  49. package/public/scripts/extensions/attachments/manifest.json +4 -1
  50. package/public/scripts/extensions/caption/index.js +12 -6
  51. package/public/scripts/extensions/caption/manifest.json +4 -1
  52. package/public/scripts/extensions/caption/settings.html +15 -0
  53. package/public/scripts/extensions/connection-manager/index.js +336 -5
  54. package/public/scripts/extensions/connection-manager/manifest.json +4 -1
  55. package/public/scripts/extensions/expressions/index.js +65 -3
  56. package/public/scripts/extensions/expressions/manifest.json +4 -1
  57. package/public/scripts/extensions/gallery/index.js +2 -2
  58. package/public/scripts/extensions/gallery/manifest.json +4 -1
  59. package/public/scripts/extensions/memory/index.js +2 -2
  60. package/public/scripts/extensions/memory/manifest.json +4 -1
  61. package/public/scripts/extensions/quick-reply/index.js +4 -3
  62. package/public/scripts/extensions/quick-reply/manifest.json +4 -1
  63. package/public/scripts/extensions/regex/index.js +34 -3
  64. package/public/scripts/extensions/regex/manifest.json +4 -1
  65. package/public/scripts/extensions/shared.js +35 -1
  66. package/public/scripts/extensions/stable-diffusion/button.html +0 -4
  67. package/public/scripts/extensions/stable-diffusion/index.js +136 -89
  68. package/public/scripts/extensions/stable-diffusion/manifest.json +4 -1
  69. package/public/scripts/extensions/stable-diffusion/settings.html +36 -16
  70. package/public/scripts/extensions/stable-diffusion/style.css +0 -4
  71. package/public/scripts/extensions/token-counter/index.js +2 -2
  72. package/public/scripts/extensions/token-counter/manifest.json +4 -1
  73. package/public/scripts/extensions/translate/index.js +2 -2
  74. package/public/scripts/extensions/translate/manifest.json +4 -1
  75. package/public/scripts/extensions/tts/index.js +39 -14
  76. package/public/scripts/extensions/tts/manifest.json +4 -1
  77. package/public/scripts/extensions/vectors/index.js +270 -225
  78. package/public/scripts/extensions/vectors/manifest.json +4 -1
  79. package/public/scripts/extensions/vectors/settings.html +25 -0
  80. package/public/scripts/extensions.js +560 -122
  81. package/public/scripts/filters.js +11 -1
  82. package/public/scripts/i18n.js +2 -1
  83. package/public/scripts/instruct-mode.js +1 -1
  84. package/public/scripts/itemized-prompts.js +5 -0
  85. package/public/scripts/kai-settings.js +1 -0
  86. package/public/scripts/loader.js +1 -0
  87. package/public/scripts/macros.js +7 -6
  88. package/public/scripts/openai.js +610 -357
  89. package/public/scripts/personas.js +1042 -80
  90. package/public/scripts/popup.js +54 -4
  91. package/public/scripts/power-user.js +2 -11
  92. package/public/scripts/reasoning.js +72 -3
  93. package/public/scripts/secrets.js +186 -15
  94. package/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js +38 -4
  95. package/public/scripts/slash-commands.js +59 -145
  96. package/public/scripts/st-context.js +10 -1
  97. package/public/scripts/streaming-display.js +430 -0
  98. package/public/scripts/swipe-picker.js +51 -10
  99. package/public/scripts/tags.js +5 -31
  100. package/public/scripts/templates/thirdPartyExtensionWarning.html +18 -0
  101. package/public/scripts/templates/welcomePanel.html +3 -0
  102. package/public/scripts/textgen-models.js +297 -0
  103. package/public/scripts/textgen-settings.js +2 -0
  104. package/public/scripts/tokenizers.js +27 -0
  105. package/public/scripts/tool-calling.js +24 -4
  106. package/public/scripts/utils.js +121 -4
  107. package/public/scripts/welcome-screen.js +123 -6
  108. package/public/scripts/world-info.js +21 -5
  109. package/public/style.css +80 -0
  110. package/src/additional-headers.js +47 -32
  111. package/src/command-line.js +8 -0
  112. package/src/constants.js +14 -0
  113. package/src/electron/Start.bat +1 -1
  114. package/src/electron/package-lock.json +12 -12
  115. package/src/electron/package.json +1 -1
  116. package/src/endpoints/backends/chat-completions.js +280 -67
  117. package/src/endpoints/backends/kobold.js +1 -1
  118. package/src/endpoints/backends/text-completions.js +1 -1
  119. package/src/endpoints/characters.js +175 -33
  120. package/src/endpoints/content-manager.js +93 -23
  121. package/src/endpoints/extensions.js +111 -53
  122. package/src/endpoints/nanogpt.js +138 -0
  123. package/src/endpoints/novelai.js +1 -1
  124. package/src/endpoints/openai.js +56 -0
  125. package/src/endpoints/openrouter.js +45 -10
  126. package/src/endpoints/secrets.js +4 -2
  127. package/src/endpoints/speech.js +2 -2
  128. package/src/endpoints/stable-diffusion.js +192 -15
  129. package/src/endpoints/tokenizers.js +1 -1
  130. package/src/endpoints/users-private.js +8 -1
  131. package/src/endpoints/users-public.js +27 -15
  132. package/src/endpoints/vectors.js +15 -0
  133. package/src/express-common.js +82 -7
  134. package/src/middleware/accessLogWriter.js +2 -2
  135. package/src/middleware/basicAuth.js +60 -29
  136. package/src/middleware/corsProxy.js +6 -2
  137. package/src/middleware/hostWhitelist.js +1 -4
  138. package/src/middleware/userCss.js +19 -0
  139. package/src/middleware/validateFileName.js +2 -1
  140. package/src/middleware/whitelist.js +7 -51
  141. package/src/private-request-filter.js +231 -0
  142. package/src/prompt-converters.js +1 -1
  143. package/src/request-proxy.js +13 -2
  144. package/src/server-init.js +12 -0
  145. package/src/server-main.js +25 -2
  146. package/src/server-startup.js +2 -0
  147. package/src/users.js +122 -3
  148. package/src/util.js +18 -6
  149. package/src/vectors/openai-vectors.js +13 -1
  150. package/start.sh +1 -1
  151. package/tests/package-lock.json +6 -10
  152. package/tests/private-request-filter.test.js +130 -0
  153. package/tests/prompt-converters.test.js +1263 -0
  154. package/tests/tavern-card-validator.test.js +251 -0
  155. package/tests/util-pure.test.js +268 -0
  156. package/tests/util.test.js +61 -2
  157. package/config.yaml +0 -349
  158. package/post-install.js +0 -114
  159. package/public/css/user.css +0 -1
  160. package/public/error/forbidden-by-whitelist.html +0 -22
  161. package/public/error/host-not-allowed.html +0 -21
  162. package/public/error/unauthorized.html +0 -17
  163. package/public/error/url-not-found.html +0 -15
  164. /package/default/{public/error → content/errors}/forbidden-by-whitelist.html +0 -0
  165. /package/default/{public/error → content/errors}/host-not-allowed.html +0 -0
  166. /package/default/{public/error → content/errors}/unauthorized.html +0 -0
  167. /package/default/{public/css → content}/user.css +0 -0
package/Dockerfile CHANGED
@@ -19,7 +19,7 @@ COPY --chown=node:node . ./
19
19
 
20
20
  RUN \
21
21
  echo "*** Install npm packages ***" && \
22
- npm ci --no-audit --no-fund --loglevel=error --no-progress --omit=dev && npm cache clean --force
22
+ npm ci --no-audit --no-fund --loglevel=error --no-progress --omit=dev --ignore-scripts && npm cache clean --force
23
23
 
24
24
  # Create config directory and link config.yaml. Added hardcoded dirs(constants.js?)
25
25
  # that must be present for Non-Root Mode and volumeless docker runs.
package/Start.bat CHANGED
@@ -1,7 +1,7 @@
1
1
  @echo off
2
2
  pushd %~dp0
3
3
  set NODE_ENV=production
4
- call npm install --no-save --no-audit --no-fund --loglevel=error --no-progress --omit=dev
4
+ call npm install --no-save --no-audit --no-fund --loglevel=error --no-progress --omit=dev --ignore-scripts
5
5
  node server.js %*
6
6
  pause
7
7
  popd
@@ -20,7 +20,7 @@ if %errorlevel% neq 0 (
20
20
  )
21
21
  )
22
22
  set NODE_ENV=production
23
- call npm install --no-save --no-audit --no-fund --loglevel=error --no-progress --omit=dev
23
+ call npm install --no-save --no-audit --no-fund --loglevel=error --no-progress --omit=dev --ignore-scripts
24
24
  node server.js %*
25
25
  :end
26
26
  pause
@@ -102,7 +102,7 @@ if %errorlevel% neq 0 (
102
102
 
103
103
  echo Installing npm packages and starting server
104
104
  set NODE_ENV=production
105
- call npm install --no-save --no-audit --no-fund --loglevel=error --no-progress --omit=dev
105
+ call npm install --no-save --no-audit --no-fund --loglevel=error --no-progress --omit=dev --ignore-scripts
106
106
  node server.js %*
107
107
 
108
108
  :end
@@ -41,6 +41,9 @@ port: 8000
41
41
  # Interval in seconds to write a heartbeat file. Set to 0 to disable.
42
42
  # This is used primarily for Docker healthchecks.
43
43
  heartbeatInterval: 0
44
+ # Enable HTTP/HTTPS keep-alive globally.
45
+ # Disabling restores old Node 18 behavior, can help if ECONNRESET and other network errors occur.
46
+ enableKeepAlive: false
44
47
  # -- SSL options --
45
48
  ssl:
46
49
  # Enable SSL/TLS encryption
@@ -55,7 +58,7 @@ ssl:
55
58
  # -- SECURITY CONFIGURATION --
56
59
  # Toggle whitelist mode
57
60
  whitelistMode: true
58
- # Whitelist will also verify IP in X-Forwarded-For / X-Real-IP headers
61
+ # When enabled, whitelist will also verify IP in headers enabled in `forwardedHeaders` section.
59
62
  enableForwardedWhitelist: true
60
63
  # Whitelist of allowed IP addresses
61
64
  whitelist:
@@ -127,6 +130,13 @@ sso:
127
130
  # as that used for authentik. (Ensure the username in authentik
128
131
  # is an exact match in lowercase with that in sillytavern).
129
132
  authentikAuth: false
133
+ # List of trusted proxy IPs for SSO authentication.
134
+ # Supports wildcards or CIDR notation for subnets.
135
+ # Example: ['127.0.0.1', '192.168.1.1']
136
+ # Set to ['*'] to trust all proxies (NOT RECOMMENDED unless you have other security measures in place)
137
+ trustedProxies:
138
+ - ::1
139
+ - 127.0.0.1
130
140
 
131
141
  # Host whitelist configuration. Recommended if you're using a listen mode
132
142
  hostWhitelist:
@@ -141,6 +151,26 @@ hostWhitelist:
141
151
  # - .trycloudflare.com
142
152
  hosts: []
143
153
 
154
+ # Perform whitelist checks against server-side HTTP requests that resolve to private IP addresses.
155
+ # This is an additional layer of security to prevent Server-Side Request Forgery (SSRF) attacks.
156
+ # Recommended when listen mode is enabled, or if your server is accessible by untrusted users.
157
+ privateAddressWhitelist:
158
+ # Enable private address whitelist to block requests to private IP ranges.
159
+ enabled: false
160
+ # If true, requests to hosts that cannot be resolved will be allowed instead of blocked.
161
+ allowUnresolvedHosts: false
162
+ # Log blocked and allowed requests to the console.
163
+ log:
164
+ # Log blocked requests to the console with a warning message
165
+ blockedRequests: true
166
+ # Log allowed requests to the console with an info message
167
+ allowedRequests: false
168
+ # List of allowed private IP ranges (in CIDR notation or wildcard format).
169
+ # Allows loopback IP ranges by default, but you can customize this list to fit your needs.
170
+ allowedRanges:
171
+ - '127.0.0.0/8' # Loopback (IPv4)
172
+ - '::1/128' # Loopback (IPv6)
173
+
144
174
  # User session timeout *in seconds* (defaults to 24 hours).
145
175
  ## Set to a positive number to expire session after a certain time of inactivity
146
176
  ## Set to 0 to expire session when the browser is closed
@@ -159,9 +189,24 @@ logging:
159
189
  minLogLevel: 0
160
190
  # -- RATE LIMITING CONFIGURATION --
161
191
  rateLimiting:
162
- # Use X-Real-IP header instead of socket IP for rate limiting
163
- # Only enable this if you are using a properly configured reverse proxy (like Nginx/traefik/Caddy)
192
+ # Use any of the enabled headers in the `forwardedHeaders` section to identify the client IP for rate limiting.
193
+ # If disabled, only the socket IP will be used, which may not work correctly if you are behind a reverse proxy.
164
194
  preferRealIpHeader: false
195
+ # Set the maximum number of allowed failed basic authentication attempts before rate limiting is applied. Set to 0 to disable rate limiting for basic auth.
196
+ basicAuthMaxAttempts: 5
197
+ # Set the maximum number of allowed failed account login attempts before rate limiting is applied. Set to 0 to disable rate limiting for account logins.
198
+ accountsLoginMaxAttempts: 5
199
+ # Set the maximum number of allowed failed account recovery attempts before rate limiting is applied. Set to 0 to disable rate limiting for account recovery.
200
+ accountsRecoverMaxAttempts: 5
201
+ # Set to true to enable support for real IPs in certain request headers for features like IP whitelisting, rate limiting and access logging.
202
+ # Only change if you are sure that you use a correctly configured reverse proxy, otherwise this may lead to IP spoofing.
203
+ forwardedHeaders:
204
+ # X-Real-IP header (common with Nginx and Caddy)
205
+ xRealIp: true
206
+ # X-Forwarded-For header (common with many proxies, but may contain multiple IPs - only the first one will be used)
207
+ xForwardedFor: true
208
+ # CF-Connecting-IP header (used by Cloudflare Tunnels)
209
+ cfConnectingIp: false
165
210
 
166
211
  ## BACKUP CONFIGURATION
167
212
  backups:
@@ -2,11 +2,11 @@
2
2
  <html>
3
3
 
4
4
  <head>
5
- <title>Not found</title>
5
+ <title>Not Found</title>
6
6
  </head>
7
7
 
8
8
  <body>
9
- <h1>Not found</h1>
9
+ <h1>Not Found</h1>
10
10
  <p>
11
11
  The requested URL was not found on this server.
12
12
  </p>
@@ -642,5 +642,37 @@
642
642
  {
643
643
  "filename": "presets/reasoning/Think XML.json",
644
644
  "type": "reasoning"
645
+ },
646
+ {
647
+ "filename": "presets/reasoning/Gemma 4.json",
648
+ "type": "reasoning"
649
+ },
650
+ {
651
+ "filename": "presets/instruct/Gemma 4.json",
652
+ "type": "instruct"
653
+ },
654
+ {
655
+ "filename": "presets/context/Gemma 4.json",
656
+ "type": "context"
657
+ },
658
+ {
659
+ "filename": "user.css",
660
+ "type": "stylesheet"
661
+ },
662
+ {
663
+ "filename": "errors/forbidden-by-whitelist.html",
664
+ "type": "error_page"
665
+ },
666
+ {
667
+ "filename": "errors/host-not-allowed.html",
668
+ "type": "error_page"
669
+ },
670
+ {
671
+ "filename": "errors/unauthorized.html",
672
+ "type": "error_page"
673
+ },
674
+ {
675
+ "filename": "errors/url-not-found.html",
676
+ "type": "error_page"
645
677
  }
646
678
  ]
@@ -0,0 +1,14 @@
1
+ {
2
+ "story_string": "{{#if anchorBefore}}{{anchorBefore}}\n{{/if}}{{#if system}}{{system}}\n{{/if}}{{#if wiBefore}}{{wiBefore}}\n{{/if}}{{#if description}}{{description}}\n{{/if}}{{#if personality}}{{personality}}\n{{/if}}{{#if scenario}}{{scenario}}\n{{/if}}{{#if wiAfter}}{{wiAfter}}\n{{/if}}{{#if persona}}{{persona}}\n{{/if}}{{#if anchorAfter}}{{anchorAfter}}\n{{/if}}{{trim}}",
3
+ "example_separator": "",
4
+ "chat_start": "",
5
+ "use_stop_strings": false,
6
+ "names_as_stop_strings": true,
7
+ "story_string_position": 0,
8
+ "story_string_depth": 1,
9
+ "story_string_role": 0,
10
+ "always_force_name2": true,
11
+ "trim_sentences": false,
12
+ "single_line": false,
13
+ "name": "Gemma 4"
14
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "input_sequence": "<|turn>user\n",
3
+ "output_sequence": "<|turn>model\n",
4
+ "last_output_sequence": "",
5
+ "system_sequence": "<|turn>system\n",
6
+ "stop_sequence": "<turn|>",
7
+ "wrap": false,
8
+ "macro": true,
9
+ "names_behavior": "force",
10
+ "activation_regex": "",
11
+ "first_output_sequence": "",
12
+ "skip_examples": false,
13
+ "output_suffix": "<turn|>\n",
14
+ "input_suffix": "<turn|>\n",
15
+ "system_suffix": "<turn|>\n",
16
+ "user_alignment_message": "",
17
+ "system_same_as_user": false,
18
+ "last_system_sequence": "",
19
+ "first_input_sequence": "",
20
+ "last_input_sequence": "",
21
+ "sequences_as_stop_strings": true,
22
+ "story_string_prefix": "<|turn>system\n",
23
+ "story_string_suffix": "<turn|>\n",
24
+ "name": "Gemma 4"
25
+ }
@@ -10,6 +10,8 @@
10
10
  "mistralai_model": "mistral-large-latest",
11
11
  "chutes_model": "deepseek-ai/DeepSeek-V3-0324",
12
12
  "chutes_sort_models": "alphabetically",
13
+ "minimax_model": "MiniMax-M2.7",
14
+ "minimax_endpoint": "global",
13
15
  "electronhub_model": "gpt-4o-mini",
14
16
  "electronhub_sort_models": "alphabetically",
15
17
  "electronhub_group_models": false,
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "Gemma 4",
3
+ "prefix": "<|channel>thought\n",
4
+ "suffix": "<channel|>",
5
+ "separator": "\n\n"
6
+ }
@@ -1,6 +1,6 @@
1
1
  #!/bin/sh
2
2
 
3
- # Function to handle startup logic (Config check + Postinstall + Start)
3
+ # Function to handle startup logic (Config check + init + Start)
4
4
  start_sillytavern() {
5
5
  local PREFIX="$1"
6
6
  shift # Remove the first argument (PREFIX) so $@ contains the rest
@@ -11,8 +11,8 @@ start_sillytavern() {
11
11
  $PREFIX cp "default/config.yaml" "config/config.yaml"
12
12
  fi
13
13
 
14
- # Execute postinstall to auto-populate config.yaml with missing values
15
- $PREFIX npm run postinstall
14
+ # Execute init script to auto-populate config.yaml with missing values
15
+ $PREFIX npm run init
16
16
 
17
17
  # Start the server
18
18
  exec $PREFIX node server.js --listen "$@"
package/index.d.ts CHANGED
@@ -41,6 +41,10 @@ declare global {
41
41
  * Authenticated user handle.
42
42
  */
43
43
  handle: string | null;
44
+ /**
45
+ * Account version tag: shake256 derivative of password hash and salt.
46
+ */
47
+ version: string | null;
44
48
  /**
45
49
  * Last time the session was extended.
46
50
  */
package/package.json CHANGED
@@ -29,13 +29,14 @@
29
29
  "@mozilla/readability": "^0.6.0",
30
30
  "@popperjs/core": "^2.11.8",
31
31
  "@zeldafan0225/ai_horde": "^5.2.0",
32
+ "agent-base": "^7.1.3",
32
33
  "archiver": "^7.0.1",
33
34
  "bing-translate-api": "^4.1.0",
34
35
  "body-parser": "^1.20.2",
35
36
  "bowser": "^2.12.1",
36
37
  "bytes": "^3.1.2",
37
38
  "chalk": "^5.6.0",
38
- "chevrotain": "^11.1.1",
39
+ "chevrotain": "^11.2.0",
39
40
  "command-exists": "^1.2.9",
40
41
  "compression": "^1.8.1",
41
42
  "cookie-parser": "^1.4.6",
@@ -44,7 +45,7 @@
44
45
  "crc": "^4.3.2",
45
46
  "csrf-sync": "^4.2.1",
46
47
  "diff-match-patch": "^1.0.5",
47
- "dompurify": "^3.2.6",
48
+ "dompurify": "^3.4.2",
48
49
  "droll": "^0.2.1",
49
50
  "env-paths": "^3.0.0",
50
51
  "express": "^4.21.0",
@@ -64,8 +65,9 @@
64
65
  "ipaddr.js": "^2.2.0",
65
66
  "is-docker": "^3.0.0",
66
67
  "isomorphic-git": "^1.36.3",
68
+ "js-sha256": "^0.11.1",
67
69
  "localforage": "^1.10.0",
68
- "lodash": "^4.17.21",
70
+ "lodash": "^4.18.1",
69
71
  "mime-types": "^3.0.2",
70
72
  "moment": "^2.30.1",
71
73
  "morphdom": "^2.7.7",
@@ -113,8 +115,9 @@
113
115
  "type": "git",
114
116
  "url": "https://github.com/SillyTavern/SillyTavern.git"
115
117
  },
116
- "version": "1.17.0",
118
+ "version": "1.18.0",
117
119
  "scripts": {
120
+ "init": "node src/server-init.js",
118
121
  "start": "node server.js",
119
122
  "debug": "node --inspect server.js",
120
123
  "start:global": "node server.js --global",
@@ -122,7 +125,6 @@
122
125
  "start:deno": "deno run --allow-run --allow-net --allow-read --allow-write --allow-sys --allow-env server.js",
123
126
  "start:bun": "bun server.js",
124
127
  "start:no-csrf": "node server.js --disableCsrf",
125
- "postinstall": "node post-install.js",
126
128
  "lint": "eslint \"src/**/*.js\" \"public/**/*.js\" ./*.js",
127
129
  "lint:fix": "eslint \"src/**/*.js\" \"public/**/*.js\" ./*.js --fix",
128
130
  "plugins:update": "node plugins update",
@@ -137,7 +139,7 @@
137
139
  },
138
140
  "main": "server.js",
139
141
  "devDependencies": {
140
- "@chevrotain/types": "^11.0.3",
142
+ "@chevrotain/types": "^11.2.0",
141
143
  "@types/archiver": "^6.0.3",
142
144
  "@types/bytes": "^3.1.5",
143
145
  "@types/command-exists": "^1.2.3",
@@ -151,7 +153,7 @@
151
153
  "@types/jquery-cropper": "^1.0.4",
152
154
  "@types/jquery.transit": "^0.9.33",
153
155
  "@types/jqueryui": "^1.12.24",
154
- "@types/lodash": "^4.17.20",
156
+ "@types/lodash": "^4.17.24",
155
157
  "@types/mime-types": "^3.0.1",
156
158
  "@types/multer": "^2.1.0",
157
159
  "@types/node": "^18.19.84",
@@ -167,6 +169,7 @@
167
169
  "eslint": "^8.57.1",
168
170
  "eslint-plugin-jest": "^27.9.0",
169
171
  "eslint-plugin-jsdoc": "^48.10.0",
170
- "eslint-plugin-playwright": "^2.3.0"
172
+ "eslint-plugin-playwright": "^2.3.0",
173
+ "typescript": "^5.9.3"
171
174
  }
172
175
  }
@@ -0,0 +1,7 @@
1
+ # Looking for user.css?
2
+
3
+ user.css is now located under your data root directory in the "_css" folder.
4
+
5
+ Example for the default data root:
6
+
7
+ /data/_css/user.css
@@ -97,13 +97,23 @@ label[for="extensions_autoconnect"] {
97
97
  font-size: 1.05em;
98
98
  }
99
99
 
100
- .extensions_info .extension_version {
100
+ .extensions_info :is(.extension_version, .extension_author) {
101
101
  opacity: 0.8;
102
102
  font-size: 0.8em;
103
103
  font-weight: normal;
104
104
  margin-left: 2px;
105
105
  }
106
106
 
107
+ .extensions_info :is(.extension_version, .extension_author):empty {
108
+ display: none;
109
+ }
110
+
111
+ .extensions_info .extension_author {
112
+ display: inline-flex;
113
+ gap: 2px;
114
+ align-items: baseline;
115
+ }
116
+
107
117
  .extensions_info .extension_block a {
108
118
  color: var(--SmartThemeBodyColor);
109
119
  }
@@ -161,4 +171,4 @@ input.extension_missing[type="checkbox"] {
161
171
  z-index: 1;
162
172
  margin-bottom: 10px;
163
173
  padding: 5px;
164
- }
174
+ }
@@ -500,6 +500,11 @@
500
500
  .horde_multiple_hint {
501
501
  display: none;
502
502
  }
503
+
504
+ select[multiple] {
505
+ max-height: 50px;
506
+ overflow-y: auto;
507
+ }
503
508
  }
504
509
 
505
510
  /*landscape mode phones and ipads*/
@@ -0,0 +1,236 @@
1
+ /* ─────────────────────────────────────────────────────────────────────────────
2
+ Streaming Display — floating toast panel for live LLM generation output.
3
+ Shows reasoning (thinking) and content as they stream in.
4
+ Used by extensions that leverage ConnectionManagerRequestService streaming.
5
+ ───────────────────────────────────────────────────────────────────────────── */
6
+
7
+ .streaming-display {
8
+ position: fixed;
9
+ bottom: max(calc(var(--bottomFormBlockSize) + 5px), 20px);
10
+ right: 20px;
11
+ width: min(550px, calc(100vw - 40px));
12
+ max-height: 70vh;
13
+ background: var(--SmartThemeBlurTintColor);
14
+ border: 1px solid var(--SmartThemeBorderColor);
15
+ border-radius: 10px;
16
+ padding: 14px;
17
+ z-index: 9000;
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 10px;
21
+ opacity: 0;
22
+ transform: translateY(20px);
23
+ transition: opacity var(--animation-duration, 125ms) ease, transform var(--animation-duration, 125ms) ease;
24
+ overflow: hidden;
25
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.25);
26
+ backdrop-filter: blur(12px);
27
+ }
28
+
29
+ .streaming-display-visible {
30
+ opacity: 1;
31
+ transform: translateY(0);
32
+ }
33
+
34
+ /* Header label with animated activity indicator */
35
+ .streaming-display-label {
36
+ font-weight: 600;
37
+ font-size: 0.95em;
38
+ color: var(--SmartThemeBodyColor);
39
+ display: flex;
40
+ align-items: center;
41
+ gap: 8px;
42
+ user-select: none;
43
+ }
44
+
45
+ /* LED status indicator - pulsing while streaming */
46
+ .streaming-display-led {
47
+ display: inline-block;
48
+ width: 8px;
49
+ height: 8px;
50
+ border-radius: 50%;
51
+ background: rgb(225, 138, 36);
52
+ animation: streaming-display-pulse 1.5s ease-in-out infinite;
53
+ flex-shrink: 0;
54
+ }
55
+
56
+ /* Completed state: solid green LED */
57
+ .streaming-display-complete .streaming-display-led {
58
+ background: #4caf50;
59
+ animation: none;
60
+ opacity: 1;
61
+ box-shadow: 0 0 8px rgba(76, 175, 80, 0.6);
62
+ }
63
+
64
+ /* Stopped state: solid red LED */
65
+ .streaming-display-stopped .streaming-display-led {
66
+ background: #f44336;
67
+ animation: none;
68
+ opacity: 1;
69
+ box-shadow: 0 0 8px rgba(244, 67, 54, 0.6);
70
+ }
71
+
72
+ @keyframes streaming-display-pulse {
73
+ 0%, 100% { opacity: 0.4; transform: scale(0.9); }
74
+ 50% { opacity: 1; transform: scale(1.1); }
75
+ }
76
+
77
+ /* Label text takes available space */
78
+ .streaming-display-label-text {
79
+ flex: 1;
80
+ min-width: 0;
81
+ overflow: hidden;
82
+ text-overflow: ellipsis;
83
+ white-space: nowrap;
84
+ }
85
+
86
+ /* Window control buttons container */
87
+ .streaming-display-controls {
88
+ display: flex;
89
+ align-items: center;
90
+ gap: 4px;
91
+ margin-left: auto;
92
+ flex-shrink: 0;
93
+ }
94
+
95
+ /* Window control buttons */
96
+ .streaming-display-btn {
97
+ width: 22px;
98
+ height: 22px;
99
+ border: none;
100
+ border-radius: 4px;
101
+ background: transparent;
102
+ color: var(--SmartThemeBodyColor);
103
+ font-size: 14px;
104
+ line-height: 1;
105
+ cursor: pointer;
106
+ display: flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ opacity: 0.6;
110
+ transition: opacity 0.15s ease, background-color 0.15s ease;
111
+ }
112
+
113
+ .streaming-display-btn:hover {
114
+ opacity: 1;
115
+ background-color: rgba(255, 255, 255, 0.1);
116
+ }
117
+
118
+ .streaming-display-btn-close:hover {
119
+ background-color: rgba(244, 67, 54, 0.2);
120
+ }
121
+
122
+ .streaming-display-btn-stop {
123
+ font-size: 10px;
124
+ }
125
+
126
+ .streaming-display-btn-stop:hover {
127
+ background-color: rgba(244, 150, 36, 0.2);
128
+ color: rgb(225, 138, 36);
129
+ }
130
+
131
+ /* Content container - collapsible for minimize */
132
+ .streaming-display-content {
133
+ display: flex;
134
+ flex-direction: column;
135
+ gap: 10px;
136
+ overflow: hidden;
137
+ transition: max-height var(--animation-duration, 125ms) ease, opacity var(--animation-duration, 125ms) ease;
138
+ }
139
+
140
+ /* Minimized state - hide content sections */
141
+ .streaming-display-minimized .streaming-display-content {
142
+ max-height: 0;
143
+ opacity: 0;
144
+ }
145
+
146
+ .streaming-display-minimized {
147
+ gap: 0;
148
+ }
149
+
150
+ /* Model/API icon in the label */
151
+ .streaming-display-icon {
152
+ width: 1.1em;
153
+ height: 1.1em;
154
+ flex-shrink: 0;
155
+ }
156
+
157
+ /* Minimized state adjustments */
158
+ .streaming-display-minimized.streaming-display {
159
+ padding: 10px 14px;
160
+ }
161
+
162
+ /* Reasoning (thinking) section */
163
+ .streaming-display-reasoning {
164
+ background: color-mix(in srgb, var(--SmartThemeBodyColor) 5%, transparent);
165
+ border-radius: 6px;
166
+ padding: 8px 10px;
167
+ border-left: 3px solid color-mix(in srgb, var(--SmartThemeBodyColor) 25%, transparent);
168
+ }
169
+
170
+ .streaming-display-reasoning-label {
171
+ font-size: 0.8em;
172
+ font-weight: 600;
173
+ opacity: 0.5;
174
+ margin-bottom: 4px;
175
+ letter-spacing: 0.03em;
176
+ text-transform: uppercase;
177
+ }
178
+
179
+ .streaming-display-reasoning-content {
180
+ font-size: 0.82em;
181
+ opacity: 0.65;
182
+ max-height: 25vh;
183
+ overflow-y: auto;
184
+ word-break: break-word;
185
+ line-height: 1.45;
186
+ scrollbar-width: thin;
187
+ }
188
+
189
+ .streaming-display-reasoning-content p {
190
+ margin: 0.3em 0;
191
+ }
192
+
193
+ .streaming-display-reasoning-content p:first-child {
194
+ margin-top: 0;
195
+ }
196
+
197
+ .streaming-display-reasoning-content p:last-child {
198
+ margin-bottom: 0;
199
+ }
200
+
201
+ /* Main content section */
202
+ .streaming-display-text {
203
+ border-top: 1px solid color-mix(in srgb, var(--SmartThemeBorderColor) 50%, transparent);
204
+ padding-top: 8px;
205
+ min-height: 1.5em;
206
+ }
207
+
208
+ .streaming-display-text-content {
209
+ font-size: 0.9em;
210
+ color: var(--SmartThemeBodyColor);
211
+ max-height: 40vh;
212
+ overflow-y: auto;
213
+ word-break: break-word;
214
+ line-height: 1.5;
215
+ scrollbar-width: thin;
216
+ }
217
+
218
+ .streaming-display-text-content p {
219
+ margin: 0.4em 0;
220
+ }
221
+
222
+ .streaming-display-text-content p:first-child {
223
+ margin-top: 0;
224
+ }
225
+
226
+ .streaming-display-text-content p:last-child {
227
+ margin-bottom: 0;
228
+ }
229
+
230
+ /* Strip auto-added quotes from <q> tags, as message formatting adds them */
231
+ .streaming-display-reasoning-content q:before,
232
+ .streaming-display-reasoning-content q:after,
233
+ .streaming-display-text-content q:before,
234
+ .streaming-display-text-content q:after {
235
+ content: '';
236
+ }
@@ -565,6 +565,10 @@ label[for="bind_preset_to_connection"]:has(input:checked) {
565
565
  display: none;
566
566
  }
567
567
 
568
+ #openai_settings:has(#openai_function_calling:not(:checked)) #tool_call_recurse_limit_block {
569
+ display: none;
570
+ }
571
+
568
572
  #adaptive_p_block:has([data-tg-samplers="adaptive_target"][style*="display: none"]):has([data-tg-samplers="adaptive_decay"][style*="display: none"]) {
569
573
  display: none;
570
574
  }
@@ -17,6 +17,7 @@
17
17
  .welcomePanel.recentHidden .welcomeRecent,
18
18
  .welcomePanel.recentHidden .recentChatsTitle,
19
19
  .welcomePanel.recentHidden .hideRecentChats,
20
+ .welcomePanel.recentHidden .recentChatsSettings,
20
21
  .welcomePanel:not(.recentHidden) .showRecentChats {
21
22
  display: none;
22
23
  }