clay-server 2.33.1 → 2.34.0-beta.2
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.
- package/lib/config.js +9 -13
- package/lib/daemon.js +19 -17
- package/lib/mate-datastore.js +337 -0
- package/lib/os-users.js +57 -37
- package/lib/project-http.js +3 -4
- package/lib/project-image.js +3 -2
- package/lib/project-mate-datastore.js +218 -0
- package/lib/project.js +29 -0
- package/lib/public/app.js +2 -0
- package/lib/public/css/mates.css +175 -0
- package/lib/public/css/messages.css +23 -0
- package/lib/public/css/notifications-center.css +76 -0
- package/lib/public/index.html +28 -0
- package/lib/public/modules/app-messages.js +25 -0
- package/lib/public/modules/mate-datastore-ui.js +270 -0
- package/lib/public/modules/mate-sidebar.js +3 -0
- package/lib/public/modules/tools.js +57 -5
- package/lib/sdk-bridge.js +32 -23
- package/lib/sdk-message-processor.js +7 -1
- package/lib/updater.js +2 -2
- package/lib/users.js +2 -2
- package/lib/ws-schema.js +14 -0
- package/lib/yoke/adapters/claude.js +5 -1
- package/lib/yoke/adapters/codex.js +1 -0
- package/lib/yoke/index.js +20 -13
- package/package.json +1 -1
package/lib/public/css/mates.css
CHANGED
|
@@ -1884,6 +1884,11 @@ body.mate-dm-active #layout.sidebar-collapsed .mate-collapsed-info {
|
|
|
1884
1884
|
height: 16px;
|
|
1885
1885
|
}
|
|
1886
1886
|
|
|
1887
|
+
.mate-sidebar-actions button.active {
|
|
1888
|
+
background: var(--bg-hover, rgba(255,255,255,0.1));
|
|
1889
|
+
color: var(--text-primary, #fff);
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1887
1892
|
.mate-session-list {
|
|
1888
1893
|
flex: 1;
|
|
1889
1894
|
overflow-y: auto;
|
|
@@ -1990,6 +1995,176 @@ body.mate-dm-active #layout.sidebar-collapsed .mate-collapsed-info {
|
|
|
1990
1995
|
#mate-search-session-btn.active {
|
|
1991
1996
|
color: var(--accent);
|
|
1992
1997
|
}
|
|
1998
|
+
|
|
1999
|
+
/* Mate datastore inspector */
|
|
2000
|
+
#mate-sidebar-datastore {
|
|
2001
|
+
display: flex;
|
|
2002
|
+
flex-direction: column;
|
|
2003
|
+
flex: 1;
|
|
2004
|
+
min-height: 0;
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
#mate-sidebar-datastore.hidden {
|
|
2008
|
+
display: none !important;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
.mate-db-status {
|
|
2012
|
+
padding: 8px 12px 0;
|
|
2013
|
+
font-size: 12px;
|
|
2014
|
+
color: var(--text-secondary, #8e8e8e);
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
.mate-db-status[data-kind="error"] {
|
|
2018
|
+
color: var(--error, #ff6b6b);
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
.mate-db-status[data-kind="warn"] {
|
|
2022
|
+
color: var(--warning, #f5a524);
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
.mate-db-status[data-kind="ok"] {
|
|
2026
|
+
color: var(--success, #36b37e);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
.mate-db-layout {
|
|
2030
|
+
display: grid;
|
|
2031
|
+
grid-template-columns: 130px minmax(0, 1fr);
|
|
2032
|
+
gap: 10px;
|
|
2033
|
+
padding: 8px 8px 12px;
|
|
2034
|
+
min-height: 0;
|
|
2035
|
+
flex: 1;
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
.mate-db-table-column,
|
|
2039
|
+
.mate-db-detail {
|
|
2040
|
+
min-height: 0;
|
|
2041
|
+
display: flex;
|
|
2042
|
+
flex-direction: column;
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
.mate-db-table-list {
|
|
2046
|
+
overflow-y: auto;
|
|
2047
|
+
border: 1px solid var(--border-subtle, rgba(255,255,255,0.08));
|
|
2048
|
+
border-radius: 10px;
|
|
2049
|
+
background: var(--bg-alt, rgba(255,255,255,0.03));
|
|
2050
|
+
padding: 4px;
|
|
2051
|
+
flex: 1;
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
.mate-db-table-item {
|
|
2055
|
+
width: 100%;
|
|
2056
|
+
display: flex;
|
|
2057
|
+
justify-content: space-between;
|
|
2058
|
+
gap: 6px;
|
|
2059
|
+
padding: 8px 10px;
|
|
2060
|
+
border: none;
|
|
2061
|
+
background: transparent;
|
|
2062
|
+
color: var(--text-secondary, #aaa);
|
|
2063
|
+
border-radius: 8px;
|
|
2064
|
+
text-align: left;
|
|
2065
|
+
cursor: pointer;
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
.mate-db-table-item:hover,
|
|
2069
|
+
.mate-db-table-item.active {
|
|
2070
|
+
background: var(--sidebar-active, rgba(255,255,255,0.08));
|
|
2071
|
+
color: var(--text, #fff);
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
.mate-db-table-item-name {
|
|
2075
|
+
overflow: hidden;
|
|
2076
|
+
text-overflow: ellipsis;
|
|
2077
|
+
white-space: nowrap;
|
|
2078
|
+
min-width: 0;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
.mate-db-table-item-type {
|
|
2082
|
+
font-size: 10px;
|
|
2083
|
+
text-transform: uppercase;
|
|
2084
|
+
letter-spacing: 0.05em;
|
|
2085
|
+
opacity: 0.7;
|
|
2086
|
+
flex-shrink: 0;
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
.mate-db-empty {
|
|
2090
|
+
padding: 16px 10px;
|
|
2091
|
+
color: var(--text-secondary, #8e8e8e);
|
|
2092
|
+
font-size: 12px;
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
.mate-db-section-title {
|
|
2096
|
+
font-size: 11px;
|
|
2097
|
+
font-weight: 700;
|
|
2098
|
+
text-transform: uppercase;
|
|
2099
|
+
letter-spacing: 0.08em;
|
|
2100
|
+
color: var(--text-muted, #9aa0a6);
|
|
2101
|
+
margin: 0 0 6px;
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
.mate-db-detail {
|
|
2105
|
+
gap: 8px;
|
|
2106
|
+
min-width: 0;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
.mate-db-table-schema,
|
|
2110
|
+
.mate-db-result {
|
|
2111
|
+
margin: 0;
|
|
2112
|
+
padding: 10px;
|
|
2113
|
+
border-radius: 10px;
|
|
2114
|
+
border: 1px solid var(--border-subtle, rgba(255,255,255,0.08));
|
|
2115
|
+
background: var(--bg-alt, rgba(255,255,255,0.03));
|
|
2116
|
+
color: var(--text-secondary, #b8b8b8);
|
|
2117
|
+
font-size: 11px;
|
|
2118
|
+
line-height: 1.5;
|
|
2119
|
+
overflow: auto;
|
|
2120
|
+
white-space: pre-wrap;
|
|
2121
|
+
word-break: break-word;
|
|
2122
|
+
min-height: 0;
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
.mate-db-table-schema {
|
|
2126
|
+
max-height: 120px;
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
.mate-db-query,
|
|
2130
|
+
.mate-db-params {
|
|
2131
|
+
width: 100%;
|
|
2132
|
+
min-height: 72px;
|
|
2133
|
+
padding: 10px;
|
|
2134
|
+
border-radius: 10px;
|
|
2135
|
+
border: 1px solid var(--border-subtle, rgba(255,255,255,0.1));
|
|
2136
|
+
background: var(--bg-secondary, rgba(255,255,255,0.04));
|
|
2137
|
+
color: var(--text, #fff);
|
|
2138
|
+
font-family: var(--mono-font, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
2139
|
+
font-size: 11px;
|
|
2140
|
+
resize: vertical;
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
.mate-db-params {
|
|
2144
|
+
min-height: 54px;
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
.mate-db-actions {
|
|
2148
|
+
display: flex;
|
|
2149
|
+
gap: 8px;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
.mate-db-actions button {
|
|
2153
|
+
flex: 1;
|
|
2154
|
+
height: 30px;
|
|
2155
|
+
border: none;
|
|
2156
|
+
border-radius: 8px;
|
|
2157
|
+
background: var(--sidebar-active, rgba(255,255,255,0.08));
|
|
2158
|
+
color: var(--text, #fff);
|
|
2159
|
+
font-size: 12px;
|
|
2160
|
+
font-weight: 600;
|
|
2161
|
+
cursor: pointer;
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
.mate-db-actions button:hover {
|
|
2165
|
+
background: var(--sidebar-hover, rgba(255,255,255,0.12));
|
|
2166
|
+
}
|
|
2167
|
+
|
|
1993
2168
|
.mate-session-item.search-match {
|
|
1994
2169
|
background: var(--accent-12, rgba(108, 92, 231, 0.12));
|
|
1995
2170
|
}
|
|
@@ -1233,6 +1233,29 @@ pre.mermaid-error {
|
|
|
1233
1233
|
.plan-card-body strong { font-weight: 600; }
|
|
1234
1234
|
.plan-card-body blockquote { border-left: 3px solid var(--border); padding-left: 12px; color: var(--text-muted); margin: 8px 0; }
|
|
1235
1235
|
|
|
1236
|
+
.todo-widget.todo-widget-plan .todo-header {
|
|
1237
|
+
background: linear-gradient(180deg, rgba(var(--overlay-rgb), 0.04), rgba(var(--overlay-rgb), 0.015));
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
.todo-widget.todo-widget-plan .todo-header-icon,
|
|
1241
|
+
.todo-widget.todo-widget-plan .todo-header-title {
|
|
1242
|
+
color: var(--accent);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
.todo-widget.todo-widget-plan .todo-header-count {
|
|
1246
|
+
color: var(--text-muted);
|
|
1247
|
+
font-weight: 500;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
.todo-widget.todo-widget-plan .todo-item.pending .todo-item-icon {
|
|
1251
|
+
opacity: 0.75;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
.todo-widget.todo-widget-plan .todo-item.in-progress .todo-item-text {
|
|
1255
|
+
color: var(--text);
|
|
1256
|
+
font-weight: 500;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1236
1259
|
/* --- Plan permission (ExitPlanMode) --- */
|
|
1237
1260
|
.plan-permission-header {
|
|
1238
1261
|
background: var(--success-8) !important;
|
|
@@ -307,6 +307,82 @@
|
|
|
307
307
|
.notif-banner-update-now:hover { opacity: 0.85; }
|
|
308
308
|
.notif-banner-update-now:disabled { opacity: 0.6; cursor: default; }
|
|
309
309
|
|
|
310
|
+
.light-theme .notif-banner-clear-all {
|
|
311
|
+
background:
|
|
312
|
+
linear-gradient(180deg, rgba(255,255,255,0.88), rgba(255,255,255,0.72)),
|
|
313
|
+
rgba(255,255,255,0.62);
|
|
314
|
+
border-color: rgba(24, 32, 56, 0.10);
|
|
315
|
+
color: rgba(36, 45, 66, 0.72);
|
|
316
|
+
box-shadow:
|
|
317
|
+
inset 0 1px 0 rgba(255,255,255,0.85),
|
|
318
|
+
0 8px 22px rgba(31, 41, 55, 0.08);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.light-theme .notif-banner-clear-all:hover {
|
|
322
|
+
color: rgba(22, 29, 45, 0.92);
|
|
323
|
+
background:
|
|
324
|
+
linear-gradient(180deg, rgba(255,255,255,0.94), rgba(255,255,255,0.78)),
|
|
325
|
+
rgba(255,255,255,0.7);
|
|
326
|
+
border-color: rgba(24, 32, 56, 0.14);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.light-theme .notif-banner {
|
|
330
|
+
background:
|
|
331
|
+
linear-gradient(180deg, rgba(255,255,255,0.92), rgba(255,255,255,0.74)),
|
|
332
|
+
rgba(255,255,255,0.60);
|
|
333
|
+
border-color: rgba(27, 35, 56, 0.08);
|
|
334
|
+
box-shadow:
|
|
335
|
+
inset 0 1px 0 rgba(255,255,255,0.88),
|
|
336
|
+
0 10px 30px rgba(31, 41, 55, 0.10);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.light-theme .notif-banner:hover {
|
|
340
|
+
border-color: rgba(27, 35, 56, 0.12);
|
|
341
|
+
box-shadow:
|
|
342
|
+
inset 0 1px 0 rgba(255,255,255,0.92),
|
|
343
|
+
0 12px 34px rgba(31, 41, 55, 0.12);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.light-theme .notif-banner-icon {
|
|
347
|
+
background: linear-gradient(180deg, rgba(255,255,255,0.92), rgba(244,247,252,0.82));
|
|
348
|
+
border-color: rgba(27, 35, 56, 0.08);
|
|
349
|
+
color: var(--text-secondary);
|
|
350
|
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.92);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.light-theme .notif-banner-project {
|
|
354
|
+
color: rgba(50, 62, 86, 0.74);
|
|
355
|
+
text-shadow: 0 1px 0 rgba(255,255,255,0.72);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.light-theme .notif-banner-title {
|
|
359
|
+
color: rgba(18, 24, 38, 0.95);
|
|
360
|
+
text-shadow: 0 1px 0 rgba(255,255,255,0.72);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.light-theme .notif-banner-text {
|
|
364
|
+
color: rgba(61, 73, 96, 0.76);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.light-theme .notif-banner-update .notif-banner-project,
|
|
368
|
+
.light-theme .notif-banner-auth .notif-banner-project {
|
|
369
|
+
color: rgba(50, 62, 86, 0.74);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.light-theme .notif-banner-auth .notif-banner-title,
|
|
373
|
+
.light-theme .notif-banner-update .notif-banner-title {
|
|
374
|
+
text-shadow: 0 1px 0 rgba(255,255,255,0.76);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.light-theme .notif-banner-close,
|
|
378
|
+
.light-theme .notif-banner-close:hover {
|
|
379
|
+
background: rgba(244, 246, 250, 0.98);
|
|
380
|
+
color: rgba(44, 52, 68, 0.88);
|
|
381
|
+
box-shadow:
|
|
382
|
+
0 2px 6px rgba(31, 41, 55, 0.12),
|
|
383
|
+
inset 0 1px 0 rgba(255,255,255,0.88);
|
|
384
|
+
}
|
|
385
|
+
|
|
310
386
|
/* ========================================================
|
|
311
387
|
Mobile
|
|
312
388
|
======================================================== */
|
package/lib/public/index.html
CHANGED
|
@@ -270,6 +270,7 @@
|
|
|
270
270
|
<div class="mate-sidebar-sessions-header">
|
|
271
271
|
<span>Conversations</span>
|
|
272
272
|
<div class="mate-sidebar-actions">
|
|
273
|
+
<button id="mate-data-btn" type="button" title="Data inspector"><i data-lucide="database"></i></button>
|
|
273
274
|
<button id="mate-search-session-btn" type="button" title="Search sessions"><i data-lucide="search"></i></button>
|
|
274
275
|
<button id="mate-new-session-btn" type="button" title="New session"><i data-lucide="plus"></i></button>
|
|
275
276
|
</div>
|
|
@@ -280,6 +281,33 @@
|
|
|
280
281
|
</div>
|
|
281
282
|
<div id="mate-session-list" class="mate-session-list"></div>
|
|
282
283
|
</div>
|
|
284
|
+
<div id="mate-sidebar-datastore" class="hidden">
|
|
285
|
+
<div class="mate-sidebar-sessions-header">
|
|
286
|
+
<span>Data</span>
|
|
287
|
+
<div class="mate-sidebar-actions">
|
|
288
|
+
<button id="mate-db-refresh-btn" type="button" title="Refresh tables"><i data-lucide="refresh-cw"></i></button>
|
|
289
|
+
<button id="mate-db-back-btn" type="button" title="Back to conversations"><i data-lucide="x"></i></button>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
<div class="mate-db-status" id="mate-db-status"></div>
|
|
293
|
+
<div class="mate-db-layout">
|
|
294
|
+
<div class="mate-db-table-column">
|
|
295
|
+
<div class="mate-db-section-title">Objects</div>
|
|
296
|
+
<div id="mate-db-table-list" class="mate-db-table-list"></div>
|
|
297
|
+
</div>
|
|
298
|
+
<div class="mate-db-detail">
|
|
299
|
+
<div class="mate-db-section-title" id="mate-db-table-name">No table selected</div>
|
|
300
|
+
<pre id="mate-db-table-schema" class="mate-db-table-schema"></pre>
|
|
301
|
+
<textarea id="mate-db-query" class="mate-db-query" spellcheck="false" placeholder="SELECT * FROM table LIMIT 50;"></textarea>
|
|
302
|
+
<textarea id="mate-db-params" class="mate-db-params" spellcheck="false" placeholder='[]'></textarea>
|
|
303
|
+
<div class="mate-db-actions">
|
|
304
|
+
<button id="mate-db-query-btn" type="button">Query</button>
|
|
305
|
+
<button id="mate-db-exec-btn" type="button">Exec</button>
|
|
306
|
+
</div>
|
|
307
|
+
<pre id="mate-db-result" class="mate-db-result"></pre>
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
283
311
|
<div id="mate-sidebar-memory" class="hidden"></div>
|
|
284
312
|
<div id="mate-sidebar-knowledge" class="hidden">
|
|
285
313
|
<div class="mate-sidebar-sessions-header">
|
|
@@ -14,6 +14,7 @@ import { renderSessionList, updateSessionPresence, populateCliSessionList, handl
|
|
|
14
14
|
import { updateDmBadge, renderSidebarPresence, setMentionActive, renderUserStrip } from './sidebar-mates.js';
|
|
15
15
|
import { refreshMobileChatSheet } from './sidebar-mobile.js';
|
|
16
16
|
import { renderMateSessionList, handleMateSearchResults, updateMateSidebarProfile } from './mate-sidebar.js';
|
|
17
|
+
import { handleMateDatastoreTablesResult, handleMateDatastoreDescribeResult, handleMateDatastoreQueryResult, handleMateDatastoreExecResult, handleMateDatastoreError, handleMateDatastoreChange } from './mate-datastore-ui.js';
|
|
17
18
|
import { renderKnowledgeList, handleKnowledgeContent } from './mate-knowledge.js';
|
|
18
19
|
import { renderMemoryList } from './mate-memory.js';
|
|
19
20
|
import { handlePaletteSessionSwitch, setPaletteVersion } from './command-palette.js';
|
|
@@ -275,6 +276,30 @@ export function processMessage(msg) {
|
|
|
275
276
|
updateProjectList(msg);
|
|
276
277
|
break;
|
|
277
278
|
|
|
279
|
+
case "mate_db_tables_result":
|
|
280
|
+
handleMateDatastoreTablesResult(msg);
|
|
281
|
+
break;
|
|
282
|
+
|
|
283
|
+
case "mate_db_describe_result":
|
|
284
|
+
handleMateDatastoreDescribeResult(msg);
|
|
285
|
+
break;
|
|
286
|
+
|
|
287
|
+
case "mate_db_query_result":
|
|
288
|
+
handleMateDatastoreQueryResult(msg);
|
|
289
|
+
break;
|
|
290
|
+
|
|
291
|
+
case "mate_db_exec_result":
|
|
292
|
+
handleMateDatastoreExecResult(msg);
|
|
293
|
+
break;
|
|
294
|
+
|
|
295
|
+
case "mate_db_error":
|
|
296
|
+
handleMateDatastoreError(msg);
|
|
297
|
+
break;
|
|
298
|
+
|
|
299
|
+
case "mate_db_change":
|
|
300
|
+
handleMateDatastoreChange(msg);
|
|
301
|
+
break;
|
|
302
|
+
|
|
278
303
|
case "update_available":
|
|
279
304
|
// In multi-user mode, only show update UI to admins
|
|
280
305
|
if (store.get('isMultiUserMode')) {
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { escapeHtml } from './utils.js';
|
|
2
|
+
import { refreshIcons } from './icons.js';
|
|
3
|
+
import { getWs } from './ws-ref.js';
|
|
4
|
+
|
|
5
|
+
var wsGetter = null;
|
|
6
|
+
var panelEl = null;
|
|
7
|
+
var tableListEl = null;
|
|
8
|
+
var tableNameEl = null;
|
|
9
|
+
var tableSchemaEl = null;
|
|
10
|
+
var queryInputEl = null;
|
|
11
|
+
var paramsInputEl = null;
|
|
12
|
+
var resultEl = null;
|
|
13
|
+
var statusEl = null;
|
|
14
|
+
var dataBtnEl = null;
|
|
15
|
+
var conversationsEl = null;
|
|
16
|
+
var memoryEl = null;
|
|
17
|
+
var knowledgeEl = null;
|
|
18
|
+
var currentTables = [];
|
|
19
|
+
var currentTable = null;
|
|
20
|
+
var panelOpen = false;
|
|
21
|
+
|
|
22
|
+
function sendWs(msg) {
|
|
23
|
+
var ws = wsGetter ? wsGetter() : getWs();
|
|
24
|
+
if (ws && ws.readyState === 1) ws.send(JSON.stringify(msg));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function setSectionVisibility(open) {
|
|
28
|
+
panelOpen = open;
|
|
29
|
+
if (panelEl) panelEl.classList.toggle("hidden", !open);
|
|
30
|
+
if (conversationsEl) conversationsEl.classList.toggle("hidden", open);
|
|
31
|
+
if (memoryEl) memoryEl.classList.toggle("hidden", true);
|
|
32
|
+
if (knowledgeEl) knowledgeEl.classList.toggle("hidden", true);
|
|
33
|
+
if (dataBtnEl) dataBtnEl.classList.toggle("active", open);
|
|
34
|
+
refreshIcons();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function requestTables() {
|
|
38
|
+
sendWs({ type: "mate_db_tables" });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function renderStatus(text, kind) {
|
|
42
|
+
if (!statusEl) return;
|
|
43
|
+
statusEl.textContent = text || "";
|
|
44
|
+
statusEl.dataset.kind = kind || "";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function renderResult(payload) {
|
|
48
|
+
if (!resultEl) return;
|
|
49
|
+
resultEl.textContent = JSON.stringify(payload, null, 2);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function renderTableList(objects) {
|
|
53
|
+
currentTables = objects || [];
|
|
54
|
+
if (!tableListEl) return;
|
|
55
|
+
tableListEl.innerHTML = "";
|
|
56
|
+
|
|
57
|
+
if (!currentTables.length) {
|
|
58
|
+
var empty = document.createElement("div");
|
|
59
|
+
empty.className = "mate-db-empty";
|
|
60
|
+
empty.textContent = "No tables or views found.";
|
|
61
|
+
tableListEl.appendChild(empty);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (var i = 0; i < currentTables.length; i++) {
|
|
66
|
+
(function (obj) {
|
|
67
|
+
var row = document.createElement("button");
|
|
68
|
+
row.type = "button";
|
|
69
|
+
row.className = "mate-db-table-item" + (currentTable === obj.name ? " active" : "");
|
|
70
|
+
var label = obj.type || "object";
|
|
71
|
+
row.innerHTML = '<span class="mate-db-table-item-name">' + escapeHtml(obj.name) + '</span>' +
|
|
72
|
+
'<span class="mate-db-table-item-type">' + escapeHtml(label) + '</span>';
|
|
73
|
+
row.addEventListener("click", function () {
|
|
74
|
+
selectTable(obj.name);
|
|
75
|
+
});
|
|
76
|
+
tableListEl.appendChild(row);
|
|
77
|
+
})(currentTables[i]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function findFirstDescribableObject(objects) {
|
|
82
|
+
var list = objects || [];
|
|
83
|
+
for (var i = 0; i < list.length; i++) {
|
|
84
|
+
if (list[i] && (list[i].type === "table" || list[i].type === "view")) return list[i];
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function findObjectByName(name) {
|
|
90
|
+
for (var i = 0; i < currentTables.length; i++) {
|
|
91
|
+
if (currentTables[i] && currentTables[i].name === name) return currentTables[i];
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function selectTable(tableName) {
|
|
97
|
+
currentTable = tableName;
|
|
98
|
+
renderTableList(currentTables);
|
|
99
|
+
var obj = findObjectByName(tableName);
|
|
100
|
+
if (!obj) return;
|
|
101
|
+
if (obj.type !== "table" && obj.type !== "view") {
|
|
102
|
+
renderStatus("Selected " + (obj.type || "object") + " " + tableName + ".", "ok");
|
|
103
|
+
if (tableNameEl) tableNameEl.textContent = tableName;
|
|
104
|
+
if (tableSchemaEl) tableSchemaEl.textContent = obj.sql || "";
|
|
105
|
+
renderResult(obj);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
renderStatus("Loading " + tableName + "...", "info");
|
|
109
|
+
sendWs({ type: "mate_db_describe", table: tableName });
|
|
110
|
+
if (queryInputEl) queryInputEl.value = 'SELECT * FROM "' + tableName.replace(/"/g, '""') + '" LIMIT 50;';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function parseParams() {
|
|
114
|
+
if (!paramsInputEl) return [];
|
|
115
|
+
var text = paramsInputEl.value.trim();
|
|
116
|
+
if (!text) return [];
|
|
117
|
+
try {
|
|
118
|
+
var parsed = JSON.parse(text);
|
|
119
|
+
if (Array.isArray(parsed)) return parsed;
|
|
120
|
+
renderStatus("Parameters must be a JSON array.", "error");
|
|
121
|
+
} catch (e) {
|
|
122
|
+
renderStatus("Parameters must be valid JSON.", "error");
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function sendQueryMessage(type) {
|
|
128
|
+
var sql = queryInputEl ? queryInputEl.value : "";
|
|
129
|
+
var params = parseParams();
|
|
130
|
+
if (params === null) return;
|
|
131
|
+
if (!sql || !sql.trim()) {
|
|
132
|
+
renderStatus("Enter SQL before running it.", "error");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
sendWs({ type: type, sql: sql, params: params });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function initMateDatastoreUI(getWsFn) {
|
|
139
|
+
wsGetter = getWsFn;
|
|
140
|
+
panelEl = document.getElementById("mate-sidebar-datastore");
|
|
141
|
+
tableListEl = document.getElementById("mate-db-table-list");
|
|
142
|
+
tableNameEl = document.getElementById("mate-db-table-name");
|
|
143
|
+
tableSchemaEl = document.getElementById("mate-db-table-schema");
|
|
144
|
+
queryInputEl = document.getElementById("mate-db-query");
|
|
145
|
+
paramsInputEl = document.getElementById("mate-db-params");
|
|
146
|
+
resultEl = document.getElementById("mate-db-result");
|
|
147
|
+
statusEl = document.getElementById("mate-db-status");
|
|
148
|
+
dataBtnEl = document.getElementById("mate-data-btn");
|
|
149
|
+
conversationsEl = document.getElementById("mate-sidebar-conversations");
|
|
150
|
+
memoryEl = document.getElementById("mate-sidebar-memory");
|
|
151
|
+
knowledgeEl = document.getElementById("mate-sidebar-knowledge");
|
|
152
|
+
|
|
153
|
+
var refreshBtn = document.getElementById("mate-db-refresh-btn");
|
|
154
|
+
var queryBtn = document.getElementById("mate-db-query-btn");
|
|
155
|
+
var execBtn = document.getElementById("mate-db-exec-btn");
|
|
156
|
+
var backBtn = document.getElementById("mate-db-back-btn");
|
|
157
|
+
|
|
158
|
+
if (dataBtnEl) {
|
|
159
|
+
dataBtnEl.addEventListener("click", function () {
|
|
160
|
+
if (panelOpen) {
|
|
161
|
+
setSectionVisibility(false);
|
|
162
|
+
} else {
|
|
163
|
+
setSectionVisibility(true);
|
|
164
|
+
requestTables();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (refreshBtn) {
|
|
170
|
+
refreshBtn.addEventListener("click", function () {
|
|
171
|
+
requestTables();
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (queryBtn) {
|
|
176
|
+
queryBtn.addEventListener("click", function () {
|
|
177
|
+
sendQueryMessage("mate_db_query");
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (execBtn) {
|
|
182
|
+
execBtn.addEventListener("click", function () {
|
|
183
|
+
sendQueryMessage("mate_db_exec");
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (backBtn) {
|
|
188
|
+
backBtn.addEventListener("click", function () {
|
|
189
|
+
setSectionVisibility(false);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
setSectionVisibility(false);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function showMateDatastorePanel() {
|
|
197
|
+
setSectionVisibility(true);
|
|
198
|
+
requestTables();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function hideMateDatastorePanel() {
|
|
202
|
+
setSectionVisibility(false);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function handleMateDatastoreTablesResult(msg) {
|
|
206
|
+
if (msg.ok === false) {
|
|
207
|
+
renderStatus(msg.message || "Failed to load datastore tables.", "error");
|
|
208
|
+
renderResult(msg);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
renderStatus(msg.warning || "Datastore tables loaded.", msg.warning ? "warn" : "ok");
|
|
212
|
+
renderTableList(msg.objects || []);
|
|
213
|
+
if (msg.objects && msg.objects.length > 0) {
|
|
214
|
+
var found = false;
|
|
215
|
+
for (var i = 0; i < msg.objects.length; i++) {
|
|
216
|
+
if (msg.objects[i].name === currentTable) {
|
|
217
|
+
found = true;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (!found) {
|
|
222
|
+
var firstObject = findFirstDescribableObject(msg.objects);
|
|
223
|
+
if (firstObject) selectTable(firstObject.name);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
renderResult(msg.objects || []);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function handleMateDatastoreDescribeResult(msg) {
|
|
230
|
+
if (msg.ok === false) {
|
|
231
|
+
renderStatus(msg.message || "Failed to describe table.", "error");
|
|
232
|
+
renderResult(msg);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
renderStatus(msg.warning || ("Described " + (msg.table || "table") + "."), msg.warning ? "warn" : "ok");
|
|
236
|
+
if (tableNameEl) tableNameEl.textContent = msg.table || "Table";
|
|
237
|
+
if (tableSchemaEl) tableSchemaEl.textContent = msg.createSql || "";
|
|
238
|
+
renderResult(msg);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function handleMateDatastoreQueryResult(msg) {
|
|
242
|
+
if (msg.ok === false) {
|
|
243
|
+
renderStatus(msg.message || "Query failed.", "error");
|
|
244
|
+
renderResult(msg);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
renderStatus(msg.warning || ("Returned " + (msg.rowCount || 0) + " row(s)."), msg.warning ? "warn" : "ok");
|
|
248
|
+
renderResult(msg);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function handleMateDatastoreExecResult(msg) {
|
|
252
|
+
if (msg.ok === false) {
|
|
253
|
+
renderStatus(msg.message || "Execution failed.", "error");
|
|
254
|
+
renderResult(msg);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
renderStatus(msg.warning || ("Applied " + (msg.changes || 0) + " change(s)."), msg.warning ? "warn" : "ok");
|
|
258
|
+
renderResult(msg);
|
|
259
|
+
requestTables();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function handleMateDatastoreError(msg) {
|
|
263
|
+
renderStatus(msg.message || "Mate datastore error.", "error");
|
|
264
|
+
renderResult(msg);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function handleMateDatastoreChange(msg) {
|
|
268
|
+
renderStatus("Datastore changed.", "info");
|
|
269
|
+
if (panelOpen) requestTables();
|
|
270
|
+
}
|
|
@@ -3,6 +3,7 @@ import { escapeHtml } from './utils.js';
|
|
|
3
3
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
4
4
|
import { store } from './store.js';
|
|
5
5
|
import { hideKnowledge } from './mate-knowledge.js';
|
|
6
|
+
import { hideMateDatastorePanel } from './mate-datastore-ui.js';
|
|
6
7
|
import { isSchedulerOpen, closeScheduler } from './scheduler.js';
|
|
7
8
|
import { hideNotes } from './sticky-notes.js';
|
|
8
9
|
import { openSearch as openSessionSearch } from './session-search.js';
|
|
@@ -134,6 +135,7 @@ export function initMateSidebar(wsGetter) {
|
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
export function showMateSidebar(mateId, mateData) {
|
|
138
|
+
if (hideMateDatastorePanel) hideMateDatastorePanel();
|
|
137
139
|
currentMateId = mateId;
|
|
138
140
|
currentMate = mateData;
|
|
139
141
|
cachedSessions = [];
|
|
@@ -366,6 +368,7 @@ export function getMateSessions() {
|
|
|
366
368
|
}
|
|
367
369
|
|
|
368
370
|
export function hideMateSidebar() {
|
|
371
|
+
if (hideMateDatastorePanel) hideMateDatastorePanel();
|
|
369
372
|
currentMateId = null;
|
|
370
373
|
currentMate = null;
|
|
371
374
|
cachedSessions = [];
|