mindroot 9.2.0__py3-none-any.whl → 9.5.0__py3-none-any.whl
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.
- mindroot/coreplugins/admin/__init__.py +3 -1
- mindroot/coreplugins/admin/agent_router.py +250 -7
- mindroot/coreplugins/admin/asset_manager.py +164 -0
- mindroot/coreplugins/admin/command_router.py +236 -1
- mindroot/coreplugins/admin/mcp_catalog_routes.py +156 -0
- mindroot/coreplugins/admin/mcp_publish_routes.py +450 -0
- mindroot/coreplugins/admin/mcp_registry_routes.py +495 -0
- mindroot/coreplugins/admin/mcp_routes.py +216 -0
- mindroot/coreplugins/admin/mod.py +62 -0
- mindroot/coreplugins/admin/oauth_callback_router.py +84 -0
- mindroot/coreplugins/admin/persona_handler.py +15 -6
- mindroot/coreplugins/admin/persona_router.py +158 -2
- mindroot/coreplugins/admin/plugin_manager.py +63 -0
- mindroot/coreplugins/admin/plugin_router.py +1 -1
- mindroot/coreplugins/admin/plugin_router_fixed.py +23 -0
- mindroot/coreplugins/admin/plugin_router_new_not_working.py +145 -0
- mindroot/coreplugins/admin/plugin_routes.py +114 -0
- mindroot/coreplugins/admin/registry_settings_routes.py +140 -0
- mindroot/coreplugins/admin/router.py +116 -15
- mindroot/coreplugins/admin/service_models.py +1 -1
- mindroot/coreplugins/admin/settings_router.py +1 -0
- mindroot/coreplugins/admin/static/css/admin-custom.css +357 -2
- mindroot/coreplugins/admin/static/css/dark.css +1 -0
- mindroot/coreplugins/admin/static/css/default.css +4 -0
- mindroot/coreplugins/admin/static/js/about-info.js +367 -0
- mindroot/coreplugins/admin/static/js/agent-form.js +83 -3
- mindroot/coreplugins/admin/static/js/api-key-script.js +307 -0
- mindroot/coreplugins/admin/static/js/mcp-manager.js +348 -0
- mindroot/coreplugins/admin/static/js/mcp-publisher.js +780 -0
- mindroot/coreplugins/admin/static/js/persona-editor.js +34 -5
- mindroot/coreplugins/admin/static/js/plugin-toggle.js +1 -1
- mindroot/coreplugins/admin/static/js/recommended-plugin-install.js +63 -0
- mindroot/coreplugins/admin/static/js/registry-auth-section.js +132 -0
- mindroot/coreplugins/admin/static/js/registry-manager-base.js +613 -0
- mindroot/coreplugins/admin/static/js/registry-manager-old.js +385 -0
- mindroot/coreplugins/admin/static/js/registry-manager-publish-old-delete.js +166 -0
- mindroot/coreplugins/admin/static/js/registry-manager.js +351 -0
- mindroot/coreplugins/admin/static/js/registry-publish-section.js +377 -0
- mindroot/coreplugins/admin/static/js/registry-search-section.js +400 -0
- mindroot/coreplugins/admin/static/js/registry-search-section.js.bak +3 -0
- mindroot/coreplugins/admin/static/js/registry-settings.js +69 -0
- mindroot/coreplugins/admin/static/js/registry-shared-services.js +857 -0
- mindroot/coreplugins/admin/static/js/registry-simple-sections.js +85 -0
- mindroot/coreplugins/admin/static/js/secure-widget-manager.js +438 -0
- mindroot/coreplugins/admin/static/logo.png +0 -0
- mindroot/coreplugins/admin/templates/admin.jinja2 +275 -110
- mindroot/coreplugins/agent/Assistant/agent.json +27 -11
- mindroot/coreplugins/agent/agent.py +2 -2
- mindroot/coreplugins/agent/command_parser.py +25 -10
- mindroot/coreplugins/agent/templates/system.jinja2 +0 -12
- mindroot/coreplugins/chat/__init__.py +4 -1
- mindroot/coreplugins/chat/router.py +132 -20
- mindroot/coreplugins/chat/router_dedup_patch.py +20 -0
- mindroot/coreplugins/chat/services.py +31 -1
- mindroot/coreplugins/chat/static/css/action-fix.css +32 -0
- mindroot/coreplugins/chat/static/css/admin-custom.css +5 -3
- mindroot/coreplugins/chat/static/css/dark.css +24 -3
- mindroot/coreplugins/chat/static/css/default.css +24 -3
- mindroot/coreplugins/chat/static/css/main.css +1 -0
- mindroot/coreplugins/chat/static/js/action.js +137 -60
- mindroot/coreplugins/chat/static/js/chat-history.js +3 -0
- mindroot/coreplugins/chat/static/js/chat.js +59 -16
- mindroot/coreplugins/chat/static/js/chat.js.diff +221 -0
- mindroot/coreplugins/chat/static/js/chatform.js +2 -2
- mindroot/coreplugins/chat/static/site.webmanifest +1 -1
- mindroot/coreplugins/chat/templates/chat.jinja2 +3 -3
- mindroot/coreplugins/chat/widget_manager.py +139 -0
- mindroot/coreplugins/chat/widget_routes.py +287 -0
- mindroot/coreplugins/check_list/inject/admin.jinja2 +1 -1
- mindroot/coreplugins/email/__init__.py +2 -0
- mindroot/coreplugins/email/email_provider.py +2 -2
- mindroot/coreplugins/email/mod.py +100 -0
- mindroot/coreplugins/email/services.py +5 -3
- mindroot/coreplugins/email/smtp_handler.py +9 -3
- mindroot/coreplugins/email/test_email_service.py +75 -0
- mindroot/coreplugins/env_manager/mod.py +61 -25
- mindroot/coreplugins/home/router.py +37 -2
- mindroot/coreplugins/home/static/imgs/logo.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo.png.bak +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal2.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal_detailed.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal_python.png +0 -0
- mindroot/coreplugins/home/templates/home.jinja2 +15 -6
- mindroot/coreplugins/index/handlers/plugin_ops.py +1 -1
- mindroot/coreplugins/index/indices/default/index.json +6 -6
- mindroot/coreplugins/jwt_auth/middleware.py +47 -1
- mindroot/coreplugins/jwt_auth/mod.py +40 -17
- mindroot/coreplugins/l8n/__init__.py +6 -0
- mindroot/coreplugins/l8n/debug_loader.py +85 -0
- mindroot/coreplugins/l8n/debug_middleware.py +74 -0
- mindroot/coreplugins/l8n/l8n_constants.py +19 -0
- mindroot/coreplugins/l8n/language_detection.py +183 -0
- mindroot/coreplugins/l8n/middleware.py +151 -0
- mindroot/coreplugins/l8n/mod.py +277 -0
- mindroot/coreplugins/l8n/monkey_patch_to_delete.py +186 -0
- mindroot/coreplugins/l8n/test_enhanced.py +298 -0
- mindroot/coreplugins/l8n/test_l8n.py +95 -0
- mindroot/coreplugins/l8n/test_l8n_standalone.py +251 -0
- mindroot/coreplugins/l8n/test_middleware.py +272 -0
- mindroot/coreplugins/l8n/utils.py +232 -0
- mindroot/coreplugins/mcp_/__init__.py +14 -0
- mindroot/coreplugins/mcp_/catalog_commands.py +328 -0
- mindroot/coreplugins/mcp_/catalog_manager.py +263 -0
- mindroot/coreplugins/mcp_/dynamic_commands.py +154 -0
- mindroot/coreplugins/mcp_/mcp_manager.py +1031 -0
- mindroot/coreplugins/mcp_/mod.py +367 -0
- mindroot/coreplugins/mcp_/oauth_storage.py +144 -0
- mindroot/coreplugins/mcp_/server_installer.py +79 -0
- mindroot/coreplugins/mcp_/setup.py +26 -0
- mindroot/coreplugins/mcp_/test_dynamic_commands.py +134 -0
- mindroot/coreplugins/mcp_/testmcpclient.py +92 -0
- mindroot/coreplugins/persona/mod.py +12 -7
- mindroot/coreplugins/signup/templates/signup.jinja2 +1 -1
- mindroot/coreplugins/subscriptions/__init__.py +1 -0
- mindroot/coreplugins/subscriptions/mod.py +14 -3
- mindroot/coreplugins/subscriptions/router.py +3 -0
- mindroot/coreplugins/user_service/__init__.py +1 -2
- mindroot/coreplugins/user_service/admin_init.py +1 -0
- mindroot/coreplugins/user_service/email_service.py +72 -17
- mindroot/coreplugins/user_service/mod.py +10 -2
- mindroot/coreplugins/user_service/password_reset_service.py +180 -27
- mindroot/coreplugins/user_service/router.py +84 -22
- mindroot/lib/auth/api_key.py +28 -0
- mindroot/lib/cli/plugins.py +94 -0
- mindroot/lib/plugins/default_plugin_manifest.json +20 -0
- mindroot/lib/plugins/installation.py +5 -5
- mindroot/lib/plugins/l8n_static_handler.py +225 -0
- mindroot/lib/plugins/loader.py +33 -3
- mindroot/lib/plugins/loader_with_l8n.py +281 -0
- mindroot/lib/plugins/manifest.py +238 -17
- mindroot/lib/providers/commands.py +3 -1
- mindroot/lib/route_decorators.py +5 -5
- mindroot/lib/templates.py +183 -11
- mindroot/lib/utils/merge_arrays.py +1 -1
- mindroot/migrate.py +49 -0
- mindroot/registry/data_access.py +1 -1
- mindroot/server.py +47 -13
- mindroot/server_missing_normal_args.py +197 -0
- mindroot/server_prev.py +173 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/METADATA +7 -2
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/RECORD +147 -114
- mindroot/coreplugins/admin/static/favicon/about.txt +0 -6
- mindroot/coreplugins/admin/static/favicon/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/admin/static/favicon/apple-touch-icon.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon-16x16.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon-32x32.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon.ico +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/about.txt +0 -6
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon.ico +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/site.webmanifest +0 -1
- mindroot/coreplugins/admin/static/favicon/logo.png +0 -0
- mindroot/coreplugins/admin/static/favicon/site.webmanifest +0 -1
- mindroot/coreplugins/admin/static/js/backup/agent-editor.js +0 -186
- mindroot/coreplugins/admin/static/js/backup/agent-form.js +0 -1133
- mindroot/coreplugins/admin/static/js/backup/agent-list.js +0 -94
- mindroot/coreplugins/chat/static/favicon/about.txt +0 -6
- mindroot/coreplugins/chat/static/favicon/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/chat/static/favicon/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/chat/static/favicon/apple-touch-icon.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon-16x16.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon-32x32.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon.ico +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/about.txt +0 -6
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon.ico +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/site.webmanifest +0 -1
- mindroot/coreplugins/chat/static/favicon/logo.png +0 -0
- mindroot/coreplugins/chat/static/favicon/site.webmanifest +0 -1
- mindroot/coreplugins/index/default.json +0 -76
- mindroot/coreplugins/user_service/file_trigger_service.py +0 -72
- mindroot/coreplugins/user_service/hooks.py +0 -23
- /mindroot/coreplugins/{admin/static/favicon/android-chrome-192x192.png → home/static/imgs/backuplogo.png} +0 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/WHEEL +0 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/entry_points.txt +0 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/licenses/LICENSE +0 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@ import {markedHighlight} from 'https://cdn.jsdelivr.net/npm/marked-highlight@2.1
|
|
|
9
9
|
|
|
10
10
|
function tryParse(markdown) {
|
|
11
11
|
//return renderMarkdown(markdown)
|
|
12
|
-
|
|
12
|
+
return markdownRenderer.parse(markdown);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
|
|
@@ -44,40 +44,84 @@ class ActionComponent extends BaseEl {
|
|
|
44
44
|
static properties = {
|
|
45
45
|
funcName: { type: String },
|
|
46
46
|
params: { type: String },
|
|
47
|
-
result: { type: String }
|
|
47
|
+
result: { type: String },
|
|
48
|
+
isExpanded: { type: Boolean },
|
|
49
|
+
isRunning: { type: Boolean }
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
static styles = [
|
|
51
53
|
css`
|
|
52
54
|
:host {
|
|
53
55
|
display: block;
|
|
56
|
+
width: 100%;
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
.action-container {
|
|
60
|
+
width: 100%;
|
|
61
|
+
border: 1px solid #333;
|
|
62
|
+
border-radius: 8px;
|
|
63
|
+
margin: 4px 0;
|
|
64
|
+
background-color: transparent;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.action-container.running {
|
|
68
|
+
border-color: #4a5eff;
|
|
69
|
+
animation: pulse-border 2s infinite;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@keyframes pulse-border {
|
|
73
|
+
0%, 100% {
|
|
74
|
+
border-color: #4a5eff;
|
|
75
|
+
box-shadow: 0 0 5px rgba(74, 94, 255, 0.3);
|
|
76
|
+
}
|
|
77
|
+
50% {
|
|
78
|
+
border-color: #6a7eff;
|
|
79
|
+
box-shadow: 0 0 10px rgba(74, 94, 255, 0.5);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.action-summary {
|
|
84
|
+
padding: 8px 12px;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
background: rgba(200, 200, 255, 0.1);
|
|
87
|
+
border-radius: 8px;
|
|
88
|
+
width: 100%;
|
|
89
|
+
box-sizing: border-box;
|
|
90
|
+
display: block;
|
|
91
|
+
color: #f0f0f0;
|
|
92
|
+
user-select: none;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.action-summary:hover {
|
|
96
|
+
background: #444;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.action-content {
|
|
100
|
+
padding: 8px 12px;
|
|
101
|
+
border-top: 1px solid #333;
|
|
102
|
+
color: #f0f0f0;
|
|
103
|
+
display: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.action-content.expanded {
|
|
107
|
+
display: block;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.param-preview {
|
|
111
|
+
color: #ddd;
|
|
112
|
+
font-style: italic;
|
|
113
|
+
margin-left: 8px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.fn_name {
|
|
117
|
+
color: #f0f0f0;
|
|
118
|
+
font-weight: normal;
|
|
59
119
|
}
|
|
60
120
|
|
|
61
121
|
@keyframes flash {
|
|
62
122
|
0% { opacity: 0; }
|
|
63
123
|
50% { opacity: 0.5; }
|
|
64
124
|
100% { opacity: 0; }
|
|
65
|
-
}
|
|
66
|
-
/*
|
|
67
|
-
.animated-element::before {
|
|
68
|
-
content: '';
|
|
69
|
-
display: inline-block;
|
|
70
|
-
top: 0;
|
|
71
|
-
left: 0;
|
|
72
|
-
right: 0;
|
|
73
|
-
bottom: 0;
|
|
74
|
-
background: rgba(200,200,200,0.5);
|
|
75
|
-
animation: flash 0.2s;
|
|
76
|
-
pointer-events: none;
|
|
77
|
-
} */
|
|
78
|
-
|
|
79
|
-
.animated-element {
|
|
80
|
-
/* position: relative; */
|
|
81
125
|
}
|
|
82
126
|
`
|
|
83
127
|
];
|
|
@@ -85,25 +129,34 @@ details {
|
|
|
85
129
|
constructor() {
|
|
86
130
|
super();
|
|
87
131
|
this.funcName = '';
|
|
88
|
-
//this.params = {};
|
|
89
132
|
this.result = '';
|
|
133
|
+
this.isExpanded = true;
|
|
134
|
+
this.isRunning = false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
connectedCallback() {
|
|
138
|
+
super.connectedCallback();
|
|
139
|
+
this.checkRunningState();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
checkRunningState() {
|
|
143
|
+
const chatMessages = document.querySelectorAll('chat-message');
|
|
144
|
+
const lastMessage = chatMessages[chatMessages.length - 1];
|
|
145
|
+
if (lastMessage && lastMessage.getAttribute('spinning') === 'yes') {
|
|
146
|
+
this.isRunning = true;
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
this.isRunning = false;
|
|
149
|
+
this.requestUpdate();
|
|
150
|
+
}, 1000);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_toggleExpanded() {
|
|
155
|
+
this.isExpanded = !this.isExpanded;
|
|
90
156
|
}
|
|
91
157
|
|
|
92
158
|
_paramsHTML(params) {
|
|
93
159
|
let paramshtml = '';
|
|
94
|
-
/* const format_ = (x) => {
|
|
95
|
-
// if it is a string then split, otherwise return the object
|
|
96
|
-
if (typeof(x) == 'string') {
|
|
97
|
-
return x.split('\n')[0].slice(0, 160)
|
|
98
|
-
} else {
|
|
99
|
-
if (x+"" == "[[object Object]]") {
|
|
100
|
-
return JSON.stringify(x)
|
|
101
|
-
} else {
|
|
102
|
-
return x
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
*/
|
|
107
160
|
if (Array.isArray(params)) {
|
|
108
161
|
for (let item of params) {
|
|
109
162
|
paramshtml += `<span class="param_value">(${format_(item)}), </span> `;
|
|
@@ -120,6 +173,31 @@ details {
|
|
|
120
173
|
return paramshtml;
|
|
121
174
|
}
|
|
122
175
|
|
|
176
|
+
_getFirstParamPreview(params) {
|
|
177
|
+
if (!params) return '';
|
|
178
|
+
|
|
179
|
+
let firstValue = '';
|
|
180
|
+
if (Array.isArray(params) && params.length > 0) {
|
|
181
|
+
firstValue = params[0];
|
|
182
|
+
} else if (typeof(params) == 'object') {
|
|
183
|
+
const keys = Object.keys(params);
|
|
184
|
+
if (keys.length > 0) {
|
|
185
|
+
firstValue = params[keys[0]];
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
firstValue = params;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (typeof(firstValue) === 'string') {
|
|
192
|
+
return firstValue.length > 100 ? firstValue.substring(0, 100) + '...' : firstValue;
|
|
193
|
+
} else if (typeof(firstValue) === 'object') {
|
|
194
|
+
const str = JSON.stringify(firstValue);
|
|
195
|
+
return str.length > 100 ? str.substring(0, 100) + '...' : str;
|
|
196
|
+
} else {
|
|
197
|
+
const str = String(firstValue);
|
|
198
|
+
return str.length > 100 ? str.substring(0, 100) + '...' : str;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
123
201
|
|
|
124
202
|
_render() {
|
|
125
203
|
let {funcName, params, result} = this;
|
|
@@ -136,18 +214,8 @@ details {
|
|
|
136
214
|
if (params.val) {
|
|
137
215
|
params = params.val
|
|
138
216
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
/* if (funcName != 'write') {
|
|
142
|
-
format_ = (str) => {
|
|
143
|
-
return str
|
|
144
|
-
}
|
|
145
|
-
} else {
|
|
146
|
-
format_ = (str) => {
|
|
147
|
-
return str.split('\n')[0].slice(0, 160)
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
*/
|
|
217
|
+
|
|
218
|
+
const paramPreview = this._getFirstParamPreview(params);
|
|
151
219
|
paramshtml = this._paramsHTML(params)
|
|
152
220
|
|
|
153
221
|
console.log('paramshtml', paramshtml)
|
|
@@ -164,7 +232,7 @@ details {
|
|
|
164
232
|
</details>`;
|
|
165
233
|
}
|
|
166
234
|
}
|
|
167
|
-
if (funcName === 'write' || funcName == 'think') {
|
|
235
|
+
if (funcName === 'overwrite' || funcName === 'write' || funcName == 'think') {
|
|
168
236
|
let {fname, text} = params;
|
|
169
237
|
if (params.extensive_chain_of_thoughts) {
|
|
170
238
|
text = params.extensive_chain_of_thoughts
|
|
@@ -173,7 +241,9 @@ details {
|
|
|
173
241
|
console.log("Displaying file")
|
|
174
242
|
if (fname?.endsWith('.md') || funcName == 'think') {
|
|
175
243
|
console.log("Displaying markdown")
|
|
176
|
-
|
|
244
|
+
if (true || Date.now() - window.lastParsed > 300) {
|
|
245
|
+
res = html`<div class="markdown-content">${unsafeHTML(tryParse(text, {breaks: true}))}</div>`;
|
|
246
|
+
}
|
|
177
247
|
} else {
|
|
178
248
|
console.log("Displaying code")
|
|
179
249
|
const hih = hljs.highlightAuto(text).value;
|
|
@@ -183,7 +253,9 @@ details {
|
|
|
183
253
|
} else {
|
|
184
254
|
if (typeof(params) === "string") {
|
|
185
255
|
try {
|
|
186
|
-
|
|
256
|
+
if (true || Date.now() - window.lastParsed > 300) {
|
|
257
|
+
res = html`<div class="markdown-content">${unsafeHTML(tryParse(params))}</div>`;
|
|
258
|
+
}
|
|
187
259
|
} catch (e) {
|
|
188
260
|
res = html`<pre><code>${params}</code></pre>`;
|
|
189
261
|
}
|
|
@@ -193,7 +265,9 @@ details {
|
|
|
193
265
|
if (typeof(params[key]) === 'string' && params[key].split('\n').length > 2) {
|
|
194
266
|
console.log('rendering markdown', params[key])
|
|
195
267
|
try {
|
|
196
|
-
|
|
268
|
+
if (true || Date.now() - window.lastParsed > 300) {
|
|
269
|
+
res = html`<div class="markdown-content">${unsafeHTML(tryParse(params[key]+" "))}</div>`;
|
|
270
|
+
}
|
|
197
271
|
} catch (e) {
|
|
198
272
|
res = html`<pre><code>${params[key]}</code></pre>`;
|
|
199
273
|
}
|
|
@@ -209,15 +283,18 @@ details {
|
|
|
209
283
|
}
|
|
210
284
|
|
|
211
285
|
return html`
|
|
212
|
-
<
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
286
|
+
<div class="action-container ${this.isRunning ? 'running' : ''}">
|
|
287
|
+
<div class="action-summary" @click="${this._toggleExpanded}">
|
|
288
|
+
<span class="fn_name">${funcName}</span>
|
|
289
|
+
${paramPreview ? html`<span class="param-preview">${paramPreview}</span>` : ''}
|
|
290
|
+
</div>
|
|
291
|
+
<div class="action-content ${this.isExpanded ? 'expanded' : ''}">
|
|
292
|
+
<div class="action">
|
|
293
|
+
<span class="fn_name"> ${unsafeHTML(paramshtml)}</span>
|
|
294
|
+
${res}
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
221
298
|
`;
|
|
222
299
|
}
|
|
223
300
|
}
|
|
@@ -89,6 +89,9 @@ export class ChatHistory {
|
|
|
89
89
|
console.log('user mesage: found command')
|
|
90
90
|
let parsed = cmd.result
|
|
91
91
|
try {
|
|
92
|
+
if (typeof parsed != 'string') {
|
|
93
|
+
parsed = JSON.stringify(parsed);
|
|
94
|
+
}
|
|
92
95
|
parsed = markdownRenderer.parse(parsed);
|
|
93
96
|
console.log("rendered command result markdown")
|
|
94
97
|
} catch (e) {
|
|
@@ -12,6 +12,11 @@ import { SSE } from './sse.js';
|
|
|
12
12
|
import { registerDelegate } from './delegate_task.js'
|
|
13
13
|
import showNotification from './notification.js';
|
|
14
14
|
|
|
15
|
+
if (!window.lastParsed) window.lastParsed = Date.now();
|
|
16
|
+
if (!window.lastScrolled) window.lastScrolled = Date.now();
|
|
17
|
+
|
|
18
|
+
window.lastScrolled = Date.now();
|
|
19
|
+
|
|
15
20
|
const commandHandlers = {};
|
|
16
21
|
|
|
17
22
|
// Function to register command handlers
|
|
@@ -26,6 +31,8 @@ function tryParse(markdown) {
|
|
|
26
31
|
return markdownRenderer.parse(markdown);
|
|
27
32
|
}
|
|
28
33
|
|
|
34
|
+
const noAction = [ 'say', 'json_encoded_md', 'wait_for_user_reply', 'markdown_await_user', 'tell_and_continue', 'think' ]
|
|
35
|
+
|
|
29
36
|
class Chat extends BaseEl {
|
|
30
37
|
static properties = {
|
|
31
38
|
sessionid: { type: String },
|
|
@@ -56,6 +63,7 @@ class Chat extends BaseEl {
|
|
|
56
63
|
this.history = new ChatHistory(this);
|
|
57
64
|
console.log(this);
|
|
58
65
|
}
|
|
66
|
+
|
|
59
67
|
|
|
60
68
|
exposeSubcomponents() {
|
|
61
69
|
// Get all chat-message elements
|
|
@@ -136,6 +144,8 @@ class Chat extends BaseEl {
|
|
|
136
144
|
showNotification('error', data.error);
|
|
137
145
|
}
|
|
138
146
|
|
|
147
|
+
|
|
148
|
+
|
|
139
149
|
_addMessage(event) {
|
|
140
150
|
const { content, sender, persona } = event.detail;
|
|
141
151
|
|
|
@@ -187,13 +197,24 @@ class Chat extends BaseEl {
|
|
|
187
197
|
}, 100)
|
|
188
198
|
}
|
|
189
199
|
|
|
190
|
-
_finished(event) {
|
|
200
|
+
async _finished(event) {
|
|
191
201
|
console.log('Chat finished');
|
|
192
202
|
this.task_id = null
|
|
193
203
|
this.userScrolling = false;
|
|
194
204
|
this._scrollToBottom()
|
|
195
205
|
}
|
|
196
206
|
|
|
207
|
+
textParam (data) {
|
|
208
|
+
if (data.params.text) {
|
|
209
|
+
return data.params.text;
|
|
210
|
+
} else if (data.params.markdown) {
|
|
211
|
+
return data.params.markdown;
|
|
212
|
+
} else if (data.params.extensive_chain_of_thoughts) {
|
|
213
|
+
return data.params.extensive_chain_of_thoughts;
|
|
214
|
+
}
|
|
215
|
+
return JSON.stringify(data.params);
|
|
216
|
+
}
|
|
217
|
+
|
|
197
218
|
async _partialCmd(event) {
|
|
198
219
|
console.log('Event received');
|
|
199
220
|
console.log(event);
|
|
@@ -211,28 +232,33 @@ class Chat extends BaseEl {
|
|
|
211
232
|
this.startNewMsg = false
|
|
212
233
|
}
|
|
213
234
|
|
|
214
|
-
if (
|
|
215
|
-
data.command == 'wait_for_user_reply' || data.command == 'markdown_await_user' ||
|
|
216
|
-
data.command == 'tell_and_continue' || data.command=='think') {
|
|
235
|
+
if (noAction.includes(data.command)) {
|
|
217
236
|
// Check if there's a registered handler for this command
|
|
218
237
|
if (handler) {
|
|
219
238
|
console.log('Used registered handler for', data.command);
|
|
220
239
|
this.msgSoFar = null
|
|
221
|
-
} else if (data.params.text) {
|
|
222
|
-
this.msgSoFar = data.params.text
|
|
223
|
-
} else if (data.params.markdown) {
|
|
224
|
-
this.msgSoFar = data.params.markdown
|
|
225
|
-
} else if (data.params.extensive_chain_of_thoughts) {
|
|
226
|
-
this.msgSoFar = data.params.extensive_chain_of_thoughts
|
|
227
240
|
} else {
|
|
228
|
-
this.msgSoFar = data
|
|
241
|
+
this.msgSoFar = this.textParam(data);
|
|
229
242
|
}
|
|
230
243
|
|
|
231
244
|
try {
|
|
245
|
+
if (!window.lastParsed) window.lastParsed = Date.now();
|
|
232
246
|
if (content) {
|
|
233
247
|
this.messages[this.messages.length - 1].content = content
|
|
234
248
|
} else if (this.msgSoFar) {
|
|
235
|
-
|
|
249
|
+
let elapsed_ = Date.now() - window.lastParsed;
|
|
250
|
+
if (elapsed_ > 40 || this.msgSoFar + '' == '[object Object]' ) {
|
|
251
|
+
const parsed_ = tryParse(this.msgSoFar);
|
|
252
|
+
if (false && parsed_+'' == '[object Object]') {
|
|
253
|
+
console.log('msgSoFar is an object, not parsing:', this.msgSoFar);
|
|
254
|
+
} else {
|
|
255
|
+
this.messages[this.messages.length - 1].content = parsed_;
|
|
256
|
+
console.log(' parsed ', elapsed_);
|
|
257
|
+
window.lastParsed = Date.now();
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
console.log('********************************* only ',elapsed_);
|
|
261
|
+
}
|
|
236
262
|
}
|
|
237
263
|
} catch (e) {
|
|
238
264
|
console.error("Could not parse markdown:", e)
|
|
@@ -263,12 +289,17 @@ class Chat extends BaseEl {
|
|
|
263
289
|
const paramStr = JSON.stringify(data.params)
|
|
264
290
|
const escaped = escapeJsonForHtml(paramStr)
|
|
265
291
|
if (content) {
|
|
292
|
+
console.log('found content, not using action component')
|
|
266
293
|
this.messages[this.messages.length - 1].content = content
|
|
267
294
|
} else {
|
|
268
|
-
this.messages[this.messages.length - 1].content
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
295
|
+
if (this.messages[this.messages.length - 1].content == '' ||
|
|
296
|
+
Date.now()- window.lastParsed > 40) {
|
|
297
|
+
window.lastParsed = Date.now();
|
|
298
|
+
this.messages[this.messages.length - 1].content = `
|
|
299
|
+
<action-component funcName="${data.command}" params="${escaped}"
|
|
300
|
+
result="">
|
|
301
|
+
</action-component>`;
|
|
302
|
+
}
|
|
272
303
|
}
|
|
273
304
|
}
|
|
274
305
|
this.requestUpdate();
|
|
@@ -308,6 +339,11 @@ class Chat extends BaseEl {
|
|
|
308
339
|
}
|
|
309
340
|
} else {
|
|
310
341
|
console.warn('No handler for command:', data.command)
|
|
342
|
+
if (!noAction.includes(data.command)) {
|
|
343
|
+
this.messages[this.messages.length - 1].content = `<action-component funcName="${data.command}" params="${escapeJsonForHtml(JSON.stringify(data.args))}" result=""></action-component>`;
|
|
344
|
+
} else {
|
|
345
|
+
this.messages[this.messages.length - 1].content = tryParse(this.textParam(data));
|
|
346
|
+
}
|
|
311
347
|
}
|
|
312
348
|
window.initializeCodeCopyButtons();
|
|
313
349
|
this.requestUpdate();
|
|
@@ -345,6 +381,7 @@ class Chat extends BaseEl {
|
|
|
345
381
|
this.messages = [...this.messages, { content: html, sender: 'ai', spinning: 'no' }]
|
|
346
382
|
}
|
|
347
383
|
|
|
384
|
+
|
|
348
385
|
_scrollToBottom(forceInstant = false) {
|
|
349
386
|
const chatLog = this.shadowRoot.querySelector('.chat-log');
|
|
350
387
|
if (!chatLog) return;
|
|
@@ -359,6 +396,12 @@ class Chat extends BaseEl {
|
|
|
359
396
|
if (window.access_token && window.access_token.length > 20) {
|
|
360
397
|
console.log('this is an embed probably, not scrolling messages')
|
|
361
398
|
} else {
|
|
399
|
+
const elapsed = Date.now() - window.lastScrolled;
|
|
400
|
+
if (elapsed < 300) {
|
|
401
|
+
console.log('Not scrolling to bottom, too soon after last scroll');
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
window.lastScrolled = Date.now();
|
|
362
405
|
lastEl.scrollIntoView({ behavior: forceInstant ? 'instant' : 'instant', block: 'end' });
|
|
363
406
|
}
|
|
364
407
|
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
diff --git a/src/mindroot/coreplugins/chat/static/js/chat.js b/src/mindroot/coreplugins/chat/static/js/chat.js
|
|
2
|
+
index 0f2ce57..53e28b9 100644
|
|
3
|
+
--- a/src/mindroot/coreplugins/chat/static/js/chat.js
|
|
4
|
+
+++ b/src/mindroot/coreplugins/chat/static/js/chat.js
|
|
5
|
+
@@ -34,7 +34,8 @@ function debounce(func, delay) {
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
-// Create a throttled parser that limits parsing frequency but doesn't skip updates
|
|
10
|
+
+// Single place to perform a safe markdown parse and update the message
|
|
11
|
+
+function updateParsedMessage(markdown, messageIndex, chatInstance) {
|
|
12
|
+
const throttledParse = throttle((markdown, messageIndex, chatInstance) => {
|
|
13
|
+
try {
|
|
14
|
+
const result = markdownRenderer.parse(markdown);
|
|
15
|
+
@@ -46,32 +47,44 @@ const throttledParse = throttle((markdown, messageIndex, chatInstance) => {
|
|
16
|
+
}
|
|
17
|
+
} catch (e) {
|
|
18
|
+
console.error("Could not parse markdown:", e);
|
|
19
|
+
+ console.error(\"Could not parse markdown:\", e);
|
|
20
|
+
if (chatInstance.messages[messageIndex]) {
|
|
21
|
+
chatInstance.messages[messageIndex].content = `<pre><code>${markdown}</code></pre>`;
|
|
22
|
+
chatInstance.requestUpdate();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
-}, 100); // Throttle to max 10 updates per second
|
|
26
|
+
-
|
|
27
|
+
-function tryParse(markdown, useThrottle = false, messageIndex = null, chatInstance = null) {
|
|
28
|
+
- if (!useThrottle || !chatInstance || messageIndex === null) {
|
|
29
|
+
- // Immediate parsing for cases where we don't need throttling
|
|
30
|
+
- try {
|
|
31
|
+
- return markdownRenderer.parse(markdown);
|
|
32
|
+
- } catch (e) {
|
|
33
|
+
- console.error("Could not parse markdown:", e);
|
|
34
|
+
- return `<pre><code>${markdown}</code></pre>`;
|
|
35
|
+
+}, 350); // Throttle to max 10 updates per second
|
|
36
|
+
+
|
|
37
|
+
+// Debounced parser to ensure we always flush the last update after a quiet period
|
|
38
|
+
+const debouncedParse = debounce((markdown, messageIndex, chatInstance) => {
|
|
39
|
+
+ try {
|
|
40
|
+
+ const result = markdownRenderer.parse(markdown);
|
|
41
|
+
+ if (chatInstance.messages[messageIndex]) {
|
|
42
|
+
+ chatInstance.messages[messageIndex].content = result;
|
|
43
|
+
+ chatInstance.requestUpdate();
|
|
44
|
+
+ chatInstance._scrollToBottom();
|
|
45
|
+
+ if (typeof window.initializeCodeCopyButtons === 'function') {
|
|
46
|
+
+ try { window.initializeCodeCopyButtons(); } catch (_) {}
|
|
47
|
+
+ }
|
|
48
|
+
}
|
|
49
|
+
- } else {
|
|
50
|
+
- // Throttled parsing - will update the message in place
|
|
51
|
+
- throttledParse(markdown, messageIndex, chatInstance);
|
|
52
|
+
- // Return current content immediately (might be partially parsed)
|
|
53
|
+
- try {
|
|
54
|
+
- return markdownRenderer.parse(markdown);
|
|
55
|
+
- } catch (e) {
|
|
56
|
+
- return `<pre><code>${markdown}</code></pre>`;
|
|
57
|
+
+ } catch (e) {
|
|
58
|
+
+ console.error("Could not parse markdown:", e);
|
|
59
|
+
+ if (chatInstance.messages[messageIndex]) {
|
|
60
|
+
+ chatInstance.messages[messageIndex].content = `<pre><code>${markdown}</code></pre>`;
|
|
61
|
+
+ chatInstance.requestUpdate();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
+}, 150);
|
|
65
|
+
+}
|
|
66
|
+
+
|
|
67
|
+
+function tryParse(markdown) {
|
|
68
|
+
+ // Immediate parse for non-streaming contexts
|
|
69
|
+
+ try {
|
|
70
|
+
+ return markdownRenderer.parse(markdown);
|
|
71
|
+
+ } catch (e) {
|
|
72
|
+
+ console.error("Could not parse markdown:", e);
|
|
73
|
+
+ return `<pre><code>${markdown}</code></pre>`;
|
|
74
|
+
+ }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
class Chat extends BaseEl {
|
|
78
|
+
@@ -103,6 +116,12 @@ class Chat extends BaseEl {
|
|
79
|
+
console.log('Chat component created');
|
|
80
|
+
this.history = new ChatHistory(this);
|
|
81
|
+
console.log(this);
|
|
82
|
+
+
|
|
83
|
+
+ // Per-message streaming schedulers (index -> state)
|
|
84
|
+
+ this._streamSchedulers = new Map();
|
|
85
|
+
+ this._lastCopyInit = 0;
|
|
86
|
+
+ // Throttle scroll to reduce layout thrash during streaming
|
|
87
|
+
+ this._scrollToBottomThrottled = throttle(() => this._scrollToBottom(), 150);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
exposeSubcomponents() {
|
|
91
|
+
@@ -178,6 +197,82 @@ class Chat extends BaseEl {
|
|
92
|
+
}, 100);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
+ // Hybrid scheduler: leading throttle + trailing debounce + guaranteed final flush
|
|
96
|
+
+ _ensureScheduler(messageIndex) {
|
|
97
|
+
+ if (!this._streamSchedulers.has(messageIndex)) {
|
|
98
|
+
+ this._streamSchedulers.set(messageIndex, {
|
|
99
|
+
+ lastText: '',
|
|
100
|
+
+ lastRun: 0,
|
|
101
|
+
+ leadingTimer: null,
|
|
102
|
+
+ trailingTimer: null,
|
|
103
|
+
+ running: false
|
|
104
|
+
+ });
|
|
105
|
+
+ }
|
|
106
|
+
+ return this._streamSchedulers.get(messageIndex);
|
|
107
|
+
+ }
|
|
108
|
+
+
|
|
109
|
+
+ _scheduleMarkdownUpdate(messageIndex, text, { final = false } = {}) {
|
|
110
|
+
+ const MIN_INTERVAL = 150; // ms between heavy parses while streaming
|
|
111
|
+
+ const QUIET_DEBOUNCE = 120; // flush after quiet period
|
|
112
|
+
+ const state = this._ensureScheduler(messageIndex);
|
|
113
|
+
+ state.lastText = text ?? '';
|
|
114
|
+
+
|
|
115
|
+
+ const parseNow = (isFinal) => {
|
|
116
|
+
+ if (!this.messages[messageIndex]) return;
|
|
117
|
+
+ // Avoid overlapping parses
|
|
118
|
+
+ if (state.running) return;
|
|
119
|
+
+ state.running = true;
|
|
120
|
+
+ try {
|
|
121
|
+
+ const result = markdownRenderer.parse(state.lastText);
|
|
122
|
+
+ this.messages[messageIndex].content = result;
|
|
123
|
+
+ } catch (e) {
|
|
124
|
+
+ console.error('Could not parse markdown:', e);
|
|
125
|
+
+ this.messages[messageIndex].content = `<pre><code>${state.lastText}</code></pre>`;
|
|
126
|
+
+ } finally {
|
|
127
|
+
+ state.lastRun = Date.now();
|
|
128
|
+
+ state.running = false;
|
|
129
|
+
+ }
|
|
130
|
+
+ // Only initialize copy buttons occasionally or on final
|
|
131
|
+
+ const now = Date.now();
|
|
132
|
+
+ if (isFinal || now - this._lastCopyInit > 1000) {
|
|
133
|
+
+ if (typeof window.initializeCodeCopyButtons === 'function') {
|
|
134
|
+
+ try { window.initializeCodeCopyButtons(); } catch (_) {}
|
|
135
|
+
+ }
|
|
136
|
+
+ this._lastCopyInit = now;
|
|
137
|
+
+ }
|
|
138
|
+
+ this.requestUpdate();
|
|
139
|
+
+ this._scrollToBottomThrottled();
|
|
140
|
+
+ };
|
|
141
|
+
+
|
|
142
|
+
+ // Final flush: cancel timers and render immediately
|
|
143
|
+
+ if (final) {
|
|
144
|
+
+ if (state.leadingTimer) clearTimeout(state.leadingTimer);
|
|
145
|
+
+ if (state.trailingTimer) clearTimeout(state.trailingTimer);
|
|
146
|
+
+ state.leadingTimer = null;
|
|
147
|
+
+ state.trailingTimer = null;
|
|
148
|
+
+ parseNow(true);
|
|
149
|
+
+ return;
|
|
150
|
+
+ }
|
|
151
|
+
+
|
|
152
|
+
+ const now = Date.now();
|
|
153
|
+
+ const elapsed = now - state.lastRun;
|
|
154
|
+
+
|
|
155
|
+
+ // Leading throttle: if enough time has passed, schedule a near-immediate parse
|
|
156
|
+
+ if (elapsed >= MIN_INTERVAL && !state.leadingTimer) {
|
|
157
|
+
+ state.leadingTimer = setTimeout(() => {
|
|
158
|
+
+ state.leadingTimer = null;
|
|
159
|
+
+ parseNow(false);
|
|
160
|
+
+ }, 0);
|
|
161
|
+
+ }
|
|
162
|
+
+
|
|
163
|
+
+ // Trailing debounce: always ensure a quiet-period flush happens
|
|
164
|
+
+ if (state.trailingTimer) clearTimeout(state.trailingTimer);
|
|
165
|
+
+ state.trailingTimer = setTimeout(() => {
|
|
166
|
+
+ state.trailingTimer = null;
|
|
167
|
+
+ parseNow(false);
|
|
168
|
+
+ }, QUIET_DEBOUNCE);
|
|
169
|
+
+ }
|
|
170
|
+
+
|
|
171
|
+
_showError(event) {
|
|
172
|
+
console.log("NOTIFICATION", event)
|
|
173
|
+
const data = JSON.parse(event.data);
|
|
174
|
+
@@ -276,18 +371,11 @@ class Chat extends BaseEl {
|
|
175
|
+
this.msgSoFar = data.params
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
- if (content) {
|
|
179
|
+
- this.messages[this.messages.length - 1].content = content
|
|
180
|
+
- this.requestUpdate();
|
|
181
|
+
- this._scrollToBottom()
|
|
182
|
+
} else if (this.msgSoFar) {
|
|
183
|
+
- // Use throttled parsing for frequent updates - this ensures all updates are shown
|
|
184
|
+
+ } else if (this.msgSoFar) {
|
|
185
|
+
+ // Hybrid scheduled parsing for frequent partial updates when no handler content
|
|
186
|
+
const messageIndex = this.messages.length - 1;
|
|
187
|
+
- const parsedContent = tryParse(this.msgSoFar, true, messageIndex, this);
|
|
188
|
+
- this.messages[messageIndex].content = parsedContent;
|
|
189
|
+
- this.requestUpdate();
|
|
190
|
+
- this._scrollToBottom();
|
|
191
|
+
- window.initializeCodeCopyButtons();
|
|
192
|
+
+ this._scheduleMarkdownUpdate(messageIndex, this.msgSoFar, { final: false });
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
console.log('partial. data.params', data.params)
|
|
196
|
+
@@ -320,8 +408,7 @@ class Chat extends BaseEl {
|
|
197
|
+
</action-component>`;
|
|
198
|
+
}
|
|
199
|
+
this.requestUpdate();
|
|
200
|
+
- this._scrollToBottom()
|
|
201
|
+
- window.initializeCodeCopyButtons();
|
|
202
|
+
+ this._scrollToBottomThrottled();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@@ -374,7 +461,14 @@ class Chat extends BaseEl {
|
|
207
|
+
msg.spinning = 'no'
|
|
208
|
+
console.log('Spinner set to false:', msg);
|
|
209
|
+
}
|
|
210
|
+
- window.initializeCodeCopyButtons();
|
|
211
|
+
+ // Ensure final flush of any in-flight partial markdown for the last AI message
|
|
212
|
+
+ const lastIndex = this.messages.length - 1;
|
|
213
|
+
+ const sched = this._streamSchedulers.get(lastIndex);
|
|
214
|
+
+ if (sched && typeof sched.lastText === 'string' && sched.lastText.length > 0) {
|
|
215
|
+
+ this._scheduleMarkdownUpdate(lastIndex, sched.lastText, { final: true });
|
|
216
|
+
+ } else if (typeof window.initializeCodeCopyButtons === 'function') {
|
|
217
|
+
+ try { window.initializeCodeCopyButtons(); } catch (_) {}
|
|
218
|
+
+ }
|
|
219
|
+
this.requestUpdate();
|
|
220
|
+
}
|
|
221
|
+
|
|
@@ -53,7 +53,7 @@ class ChatForm extends BaseEl {
|
|
|
53
53
|
position: absolute;
|
|
54
54
|
right: 21px; /* Original optimal position */
|
|
55
55
|
margin-right: 5px;
|
|
56
|
-
bottom:
|
|
56
|
+
bottom: 1.5em; /* Raised 5px to prevent bottom overlap */
|
|
57
57
|
/* background: transparent; */
|
|
58
58
|
background-color: #101020
|
|
59
59
|
|
|
@@ -64,7 +64,7 @@ class ChatForm extends BaseEl {
|
|
|
64
64
|
position: absolute;
|
|
65
65
|
margin-right: 5px;
|
|
66
66
|
right: 61px; /* Maintains 40px spacing from send button */
|
|
67
|
-
bottom:
|
|
67
|
+
bottom: 1.5em; /* Matches send button exactly */
|
|
68
68
|
background: #ff4d4d;
|
|
69
69
|
color: white;
|
|
70
70
|
border: none;
|