clay-server 2.34.0-beta.1 → 2.34.0-beta.3

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.
@@ -3,10 +3,12 @@ var path = require("path");
3
3
  var config = require("./config");
4
4
 
5
5
  var sqlite;
6
+ var _availabilityError = null;
6
7
  try {
7
8
  sqlite = require("node:sqlite");
8
9
  } catch (e) {
9
- throw new Error("Mate datastores require Node 22.13.0 or newer with node:sqlite available.");
10
+ sqlite = null;
11
+ _availabilityError = "Mate datastores require Node 22.13.0 or newer with node:sqlite available.";
10
12
  }
11
13
 
12
14
  function parseNodeVersion(version) {
@@ -24,10 +26,13 @@ function assertNodeVersion() {
24
26
  throw new Error("Mate datastores require Node 22.13.0 or newer.");
25
27
  }
26
28
  }
29
+ try {
30
+ assertNodeVersion();
31
+ } catch (e) {
32
+ if (!_availabilityError) _availabilityError = e.message;
33
+ }
27
34
 
28
- assertNodeVersion();
29
-
30
- var DatabaseSync = sqlite.DatabaseSync;
35
+ var DatabaseSync = sqlite ? sqlite.DatabaseSync : null;
31
36
 
32
37
  var MAX_ROWS = 200;
33
38
  var MAX_RESULT_BYTES = 1024 * 1024;
@@ -37,6 +42,20 @@ var CLAY_META_VERSION = "1";
37
42
 
38
43
  var _dbCache = {};
39
44
 
45
+ function isMateDatastoreAvailable() {
46
+ return !!DatabaseSync && !_availabilityError;
47
+ }
48
+
49
+ function getMateDatastoreAvailabilityError() {
50
+ return _availabilityError || null;
51
+ }
52
+
53
+ function assertAvailable() {
54
+ if (!isMateDatastoreAvailable()) {
55
+ throw new Error(getMateDatastoreAvailabilityError() || "Mate datastore is unavailable.");
56
+ }
57
+ }
58
+
40
59
  function getMateDbPath(opts) {
41
60
  if (opts && opts.dbPath) return String(opts.dbPath);
42
61
  if (opts && opts.mateDir) return path.join(String(opts.mateDir), "store.db");
@@ -77,6 +96,7 @@ function initClayMeta(db) {
77
96
  }
78
97
 
79
98
  function ensureMateDatastore(opts) {
99
+ assertAvailable();
80
100
  var dbPath = getMateDbPath(opts);
81
101
  if (_dbCache[dbPath] && _dbCache[dbPath].db) return _dbCache[dbPath];
82
102
  ensureParentDir(dbPath);
@@ -257,7 +277,7 @@ function listSchemaObjects(handle) {
257
277
  }
258
278
  try {
259
279
  var rows = wrapper.db.prepare(
260
- "SELECT name, type, sql FROM sqlite_master WHERE type IN ('table', 'view', 'index') AND name NOT LIKE 'sqlite_%' ORDER BY type, name"
280
+ "SELECT name, type, sql FROM sqlite_master WHERE type IN ('table', 'view', 'index') AND name NOT LIKE 'sqlite_%' AND name NOT LIKE 'clay_%' ORDER BY type, name"
261
281
  ).all();
262
282
  return { ok: true, objects: rows };
263
283
  } catch (e) {
@@ -325,6 +345,8 @@ function normalizeSqliteError(err, fallbackCode, fallbackMessage) {
325
345
  }
326
346
 
327
347
  module.exports = {
348
+ isMateDatastoreAvailable: isMateDatastoreAvailable,
349
+ getMateDatastoreAvailabilityError: getMateDatastoreAvailabilityError,
328
350
  openMateDatastore: openMateDatastore,
329
351
  ensureMateDatastore: ensureMateDatastore,
330
352
  listSchemaObjects: listSchemaObjects,
@@ -1,5 +1,6 @@
1
1
  var z = require("zod");
2
2
  var datastore = require("./mate-datastore");
3
+ var FEATURE_ENABLED = false;
3
4
 
4
5
  function attachMateDatastore(ctx) {
5
6
  var cwd = ctx.cwd;
@@ -7,7 +8,14 @@ function attachMateDatastore(ctx) {
7
8
  var send = ctx.send;
8
9
  var sendTo = ctx.sendTo;
9
10
 
11
+ function isFeatureAvailable() {
12
+ return FEATURE_ENABLED && datastore.isMateDatastoreAvailable();
13
+ }
14
+
10
15
  function ensureProjectDatastore() {
16
+ if (!FEATURE_ENABLED) {
17
+ return { ok: false, code: "MATE_DATASTORE_NOT_ALLOWED", message: "Mate datastore is not enabled." };
18
+ }
11
19
  if (!isMate) {
12
20
  return { ok: false, code: "MATE_DATASTORE_NOT_ALLOWED", message: "Mate datastore is only available in Mate sessions." };
13
21
  }
@@ -87,6 +95,10 @@ function attachMateDatastore(ctx) {
87
95
  return false;
88
96
  }
89
97
 
98
+ if (!FEATURE_ENABLED) {
99
+ return false;
100
+ }
101
+
90
102
  if (!isMate) {
91
103
  sendTo(ws, {
92
104
  type: "mate_db_error",
@@ -127,7 +139,7 @@ function attachMateDatastore(ctx) {
127
139
  }
128
140
 
129
141
  function getToolDefinitions() {
130
- if (!isMate) return [];
142
+ if (!isMate || !isFeatureAvailable()) return [];
131
143
  return [
132
144
  {
133
145
  name: "clay_db_query",
@@ -174,6 +186,7 @@ function attachMateDatastore(ctx) {
174
186
 
175
187
  function createMcpServer() {
176
188
  var defs = getToolDefinitions();
189
+ if (!defs.length) return null;
177
190
  var registered = {};
178
191
  for (var i = 0; i < defs.length; i++) {
179
192
  registered[defs[i].name] = {
@@ -192,7 +205,7 @@ function attachMateDatastore(ctx) {
192
205
  }
193
206
 
194
207
  function getSessionToolDefinitions() {
195
- if (!isMate) return null;
208
+ if (!isMate || !isFeatureAvailable()) return null;
196
209
  return getToolDefinitions();
197
210
  }
198
211
 
@@ -205,6 +218,7 @@ function attachMateDatastore(ctx) {
205
218
  }
206
219
 
207
220
  return {
221
+ isFeatureAvailable: isFeatureAvailable,
208
222
  handleMateDatastoreMessage: handleMateDatastoreMessage,
209
223
  getToolDefinitions: getToolDefinitions,
210
224
  createMcpServer: createMcpServer,
@@ -1997,19 +1997,60 @@ body.mate-dm-active #layout.sidebar-collapsed .mate-collapsed-info {
1997
1997
  }
1998
1998
 
1999
1999
  /* Mate datastore inspector */
2000
- #mate-sidebar-datastore {
2000
+ #mate-datastore-panel {
2001
+ position: absolute;
2002
+ inset: 0;
2003
+ z-index: 40;
2004
+ background: var(--bg);
2001
2005
  display: flex;
2002
2006
  flex-direction: column;
2003
- flex: 1;
2004
- min-height: 0;
2007
+ overflow: hidden;
2008
+ }
2009
+
2010
+ #mate-datastore-panel.hidden {
2011
+ display: none !important;
2005
2012
  }
2006
2013
 
2007
- #mate-sidebar-datastore.hidden {
2014
+ #main-column.mate-datastore-open > .title-bar-content,
2015
+ #main-column.mate-datastore-open > .dm-header-bar,
2016
+ #main-column.mate-datastore-open > #main-panels {
2008
2017
  display: none !important;
2009
2018
  }
2010
2019
 
2020
+ .mate-datastore-top-bar {
2021
+ display: flex;
2022
+ align-items: center;
2023
+ justify-content: space-between;
2024
+ height: 48px;
2025
+ padding: 0 16px;
2026
+ border-bottom: 1px solid var(--border-subtle);
2027
+ flex-shrink: 0;
2028
+ }
2029
+
2030
+ .mate-datastore-top-title {
2031
+ display: flex;
2032
+ align-items: center;
2033
+ gap: 6px;
2034
+ font-weight: 700;
2035
+ font-size: 15px;
2036
+ color: var(--text);
2037
+ }
2038
+
2039
+ .mate-datastore-top-title .lucide {
2040
+ width: 14px;
2041
+ height: 14px;
2042
+ color: var(--accent);
2043
+ opacity: 0.85;
2044
+ }
2045
+
2046
+ .mate-datastore-top-actions {
2047
+ display: flex;
2048
+ align-items: center;
2049
+ gap: 8px;
2050
+ }
2051
+
2011
2052
  .mate-db-status {
2012
- padding: 8px 12px 0;
2053
+ padding: 10px 14px 0;
2013
2054
  font-size: 12px;
2014
2055
  color: var(--text-secondary, #8e8e8e);
2015
2056
  }
@@ -2028,9 +2069,9 @@ body.mate-dm-active #layout.sidebar-collapsed .mate-collapsed-info {
2028
2069
 
2029
2070
  .mate-db-layout {
2030
2071
  display: grid;
2031
- grid-template-columns: 130px minmax(0, 1fr);
2072
+ grid-template-columns: 220px minmax(0, 1fr);
2032
2073
  gap: 10px;
2033
- padding: 8px 8px 12px;
2074
+ padding: 12px 10px 10px;
2034
2075
  min-height: 0;
2035
2076
  flex: 1;
2036
2077
  }
@@ -2044,10 +2085,10 @@ body.mate-dm-active #layout.sidebar-collapsed .mate-collapsed-info {
2044
2085
 
2045
2086
  .mate-db-table-list {
2046
2087
  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;
2088
+ border: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
2089
+ border-radius: 12px;
2090
+ background: var(--sidebar-bg, rgba(255,255,255,0.03));
2091
+ padding: 6px;
2051
2092
  flex: 1;
2052
2093
  }
2053
2094
 
@@ -2123,46 +2164,32 @@ body.mate-dm-active #layout.sidebar-collapsed .mate-collapsed-info {
2123
2164
  }
2124
2165
 
2125
2166
  .mate-db-table-schema {
2126
- max-height: 120px;
2167
+ max-height: 180px;
2127
2168
  }
2128
2169
 
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;
2170
+ @media (max-width: 900px) {
2171
+ .mate-db-layout {
2172
+ grid-template-columns: 1fr;
2173
+ }
2141
2174
  }
2142
2175
 
2143
- .mate-db-params {
2144
- min-height: 54px;
2176
+ body.mate-dm-active .mate-datastore-top-bar {
2177
+ background: var(--mate-color);
2178
+ color: #fff;
2145
2179
  }
2146
2180
 
2147
- .mate-db-actions {
2148
- display: flex;
2149
- gap: 8px;
2181
+ body.mate-dm-active .mate-datastore-top-title,
2182
+ body.mate-dm-active .mate-datastore-top-title .lucide {
2183
+ color: #fff;
2150
2184
  }
2151
2185
 
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;
2186
+ body.mate-dm-active .mate-datastore-top-bar .scheduler-close-btn {
2187
+ color: rgba(255, 255, 255, 0.85);
2162
2188
  }
2163
2189
 
2164
- .mate-db-actions button:hover {
2165
- background: var(--sidebar-hover, rgba(255,255,255,0.12));
2190
+ body.mate-dm-active .mate-datastore-top-bar .scheduler-close-btn:hover {
2191
+ color: #fff;
2192
+ background: rgba(255, 255, 255, 0.15);
2166
2193
  }
2167
2194
 
2168
2195
  .mate-session-item.search-match {
@@ -270,7 +270,6 @@
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>
274
273
  <button id="mate-search-session-btn" type="button" title="Search sessions"><i data-lucide="search"></i></button>
275
274
  <button id="mate-new-session-btn" type="button" title="New session"><i data-lucide="plus"></i></button>
276
275
  </div>
@@ -281,33 +280,6 @@
281
280
  </div>
282
281
  <div id="mate-session-list" class="mate-session-list"></div>
283
282
  </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>
311
283
  <div id="mate-sidebar-memory" class="hidden"></div>
312
284
  <div id="mate-sidebar-knowledge" class="hidden">
313
285
  <div class="mate-sidebar-sessions-header">
@@ -14,7 +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
+ import { handleMateDatastoreTablesResult, handleMateDatastoreDescribeResult, handleMateDatastoreQueryResult, handleMateDatastoreError, handleMateDatastoreChange } from './mate-datastore-ui.js';
18
18
  import { renderKnowledgeList, handleKnowledgeContent } from './mate-knowledge.js';
19
19
  import { renderMemoryList } from './mate-memory.js';
20
20
  import { handlePaletteSessionSwitch, setPaletteVersion } from './command-palette.js';
@@ -288,10 +288,6 @@ export function processMessage(msg) {
288
288
  handleMateDatastoreQueryResult(msg);
289
289
  break;
290
290
 
291
- case "mate_db_exec_result":
292
- handleMateDatastoreExecResult(msg);
293
- break;
294
-
295
291
  case "mate_db_error":
296
292
  handleMateDatastoreError(msg);
297
293
  break;
@@ -17,12 +17,10 @@ import { getScheduledMsgEl } from './app-rate-limit.js';
17
17
  export var VENDOR_AVATARS = {
18
18
  claude: "/claude-code-avatar.png",
19
19
  codex: "/codex-avatar.png",
20
- gemini: "/claude-code-avatar.png",
21
20
  };
22
21
  export var VENDOR_NAMES = {
23
22
  claude: "Claude Code",
24
23
  codex: "Codex",
25
- gemini: "Gemini",
26
24
  };
27
25
  var NEW_MSG_BTN_DEFAULT = "\u2193 Latest";
28
26
  var NEW_MSG_BTN_ACTIVITY = "\u2193 New activity";
@@ -7,29 +7,85 @@ var panelEl = null;
7
7
  var tableListEl = null;
8
8
  var tableNameEl = null;
9
9
  var tableSchemaEl = null;
10
- var queryInputEl = null;
11
- var paramsInputEl = null;
12
10
  var resultEl = null;
13
11
  var statusEl = null;
14
12
  var dataBtnEl = null;
15
- var conversationsEl = null;
16
- var memoryEl = null;
17
- var knowledgeEl = null;
13
+ var mainColumnEl = null;
18
14
  var currentTables = [];
19
15
  var currentTable = null;
20
16
  var panelOpen = false;
17
+ var routingToScheduler = false;
21
18
 
22
19
  function sendWs(msg) {
23
20
  var ws = wsGetter ? wsGetter() : getWs();
24
21
  if (ws && ws.readyState === 1) ws.send(JSON.stringify(msg));
25
22
  }
26
23
 
24
+ function quoteIdentifier(name) {
25
+ return '"' + String(name || "").replace(/"/g, '""') + '"';
26
+ }
27
+
28
+ function ensurePanel() {
29
+ if (panelEl) return;
30
+ mainColumnEl = document.getElementById("main-column");
31
+ if (!mainColumnEl) return;
32
+
33
+ panelEl = document.createElement("div");
34
+ panelEl.id = "mate-datastore-panel";
35
+ panelEl.className = "hidden";
36
+
37
+ panelEl.innerHTML =
38
+ '<div class="scheduler-top-bar mate-datastore-top-bar">' +
39
+ '<span class="scheduler-top-title mate-datastore-top-title"><i data-lucide="database"></i>Data</span>' +
40
+ '<div class="mate-datastore-top-actions">' +
41
+ '<button id="mate-db-refresh-btn" class="scheduler-close-btn" type="button" title="Refresh tables"><i data-lucide="refresh-cw"></i></button>' +
42
+ '<button id="mate-db-back-btn" class="scheduler-close-btn" type="button" title="Close"><i data-lucide="x"></i></button>' +
43
+ '</div>' +
44
+ '</div>' +
45
+ '<div class="mate-db-status" id="mate-db-status"></div>' +
46
+ '<div class="mate-db-layout">' +
47
+ '<div class="mate-db-table-column">' +
48
+ '<div class="mate-db-section-title">Objects</div>' +
49
+ '<div id="mate-db-table-list" class="mate-db-table-list"></div>' +
50
+ '</div>' +
51
+ '<div class="mate-db-detail">' +
52
+ '<div class="mate-db-section-title" id="mate-db-table-name">No table selected</div>' +
53
+ '<pre id="mate-db-table-schema" class="mate-db-table-schema"></pre>' +
54
+ '<div class="mate-db-section-title">Rows</div>' +
55
+ '<pre id="mate-db-result" class="mate-db-result"></pre>' +
56
+ '</div>' +
57
+ '</div>';
58
+
59
+ mainColumnEl.appendChild(panelEl);
60
+ tableListEl = document.getElementById("mate-db-table-list");
61
+ tableNameEl = document.getElementById("mate-db-table-name");
62
+ tableSchemaEl = document.getElementById("mate-db-table-schema");
63
+ resultEl = document.getElementById("mate-db-result");
64
+ statusEl = document.getElementById("mate-db-status");
65
+
66
+ var refreshBtn = document.getElementById("mate-db-refresh-btn");
67
+ var backBtn = document.getElementById("mate-db-back-btn");
68
+
69
+ if (refreshBtn) {
70
+ refreshBtn.addEventListener("click", function () {
71
+ requestTables();
72
+ });
73
+ }
74
+
75
+ if (backBtn) {
76
+ backBtn.addEventListener("click", function () {
77
+ setSectionVisibility(false);
78
+ });
79
+ }
80
+
81
+ refreshIcons();
82
+ }
83
+
27
84
  function setSectionVisibility(open) {
85
+ ensurePanel();
28
86
  panelOpen = open;
29
87
  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);
88
+ if (mainColumnEl) mainColumnEl.classList.toggle("mate-datastore-open", open);
33
89
  if (dataBtnEl) dataBtnEl.classList.toggle("active", open);
34
90
  refreshIcons();
35
91
  }
@@ -49,6 +105,21 @@ function renderResult(payload) {
49
105
  resultEl.textContent = JSON.stringify(payload, null, 2);
50
106
  }
51
107
 
108
+ function formatColumns(columns) {
109
+ var list = Array.isArray(columns) ? columns : [];
110
+ if (!list.length) return "No column information available.";
111
+ var lines = [];
112
+ for (var i = 0; i < list.length; i++) {
113
+ var col = list[i] || {};
114
+ var line = (col.name || "?") + " " + (col.type || "");
115
+ if (col.pk) line += " PRIMARY KEY";
116
+ if (col.notnull) line += " NOT NULL";
117
+ if (typeof col.dflt_value !== "undefined" && col.dflt_value !== null) line += " DEFAULT " + col.dflt_value;
118
+ lines.push(line.trim());
119
+ }
120
+ return lines.join("\n");
121
+ }
122
+
52
123
  function renderTableList(objects) {
53
124
  currentTables = objects || [];
54
125
  if (!tableListEl) return;
@@ -101,94 +172,43 @@ function selectTable(tableName) {
101
172
  if (obj.type !== "table" && obj.type !== "view") {
102
173
  renderStatus("Selected " + (obj.type || "object") + " " + tableName + ".", "ok");
103
174
  if (tableNameEl) tableNameEl.textContent = tableName;
104
- if (tableSchemaEl) tableSchemaEl.textContent = obj.sql || "";
175
+ if (tableSchemaEl) tableSchemaEl.textContent = (obj.type || "object") + ": " + tableName;
105
176
  renderResult(obj);
106
177
  return;
107
178
  }
108
179
  renderStatus("Loading " + tableName + "...", "info");
109
180
  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 });
181
+ sendWs({ type: "mate_db_query", sql: "SELECT * FROM " + quoteIdentifier(tableName) + " LIMIT 100", params: [] });
136
182
  }
137
183
 
138
184
  export function initMateDatastoreUI(getWsFn) {
139
185
  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
186
  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
- }
187
+ if (!dataBtnEl) return;
168
188
 
169
- if (refreshBtn) {
170
- refreshBtn.addEventListener("click", function () {
189
+ dataBtnEl.addEventListener("click", function () {
190
+ if (panelOpen) {
191
+ setSectionVisibility(false);
192
+ } else {
193
+ setSectionVisibility(true);
171
194
  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
- }
195
+ }
196
+ });
186
197
 
187
- if (backBtn) {
188
- backBtn.addEventListener("click", function () {
189
- setSectionVisibility(false);
190
- });
191
- }
198
+ document.addEventListener("click", function (e) {
199
+ var btn = e.target && e.target.closest ? e.target.closest("#scheduler-btn, #mate-scheduler-btn") : null;
200
+ if (!btn || !panelOpen || routingToScheduler) return;
201
+ e.preventDefault();
202
+ e.stopPropagation();
203
+ if (typeof e.stopImmediatePropagation === "function") e.stopImmediatePropagation();
204
+ routingToScheduler = true;
205
+ setSectionVisibility(false);
206
+ setTimeout(function () {
207
+ var schedulerBtn = document.getElementById("scheduler-btn");
208
+ if (schedulerBtn) schedulerBtn.click();
209
+ routingToScheduler = false;
210
+ }, 0);
211
+ }, true);
192
212
 
193
213
  setSectionVisibility(false);
194
214
  }
@@ -234,8 +254,7 @@ export function handleMateDatastoreDescribeResult(msg) {
234
254
  }
235
255
  renderStatus(msg.warning || ("Described " + (msg.table || "table") + "."), msg.warning ? "warn" : "ok");
236
256
  if (tableNameEl) tableNameEl.textContent = msg.table || "Table";
237
- if (tableSchemaEl) tableSchemaEl.textContent = msg.createSql || "";
238
- renderResult(msg);
257
+ if (tableSchemaEl) tableSchemaEl.textContent = formatColumns(msg.columns);
239
258
  }
240
259
 
241
260
  export function handleMateDatastoreQueryResult(msg) {
@@ -244,19 +263,10 @@ export function handleMateDatastoreQueryResult(msg) {
244
263
  renderResult(msg);
245
264
  return;
246
265
  }
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();
266
+ var status = "Showing " + (msg.rows ? msg.rows.length : 0) + " row(s).";
267
+ if (msg.truncated) status = status.replace(".", " (truncated).");
268
+ renderStatus(msg.warning || status, msg.warning ? "warn" : "ok");
269
+ renderResult(msg.rows || []);
260
270
  }
261
271
 
262
272
  export function handleMateDatastoreError(msg) {
@@ -799,7 +799,7 @@ function resolvePermissionIdentity(mateId, vendor) {
799
799
  }
800
800
  }
801
801
  // Project chat: use vendor name and avatar
802
- var vendorAvatars = { claude: "/claude-code-avatar.png", codex: "/codex-avatar.png", gemini: "/gemini-avatar.png" };
802
+ var vendorAvatars = { claude: "/claude-code-avatar.png", codex: "/codex-avatar.png" };
803
803
  var vendorName = (vendor && VENDOR_NAMES[vendor]) || VENDOR_NAMES.claude;
804
804
  return {
805
805
  name: vendorName,