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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/lib/ask-user-mcp-server.js +120 -0
  2. package/lib/daemon.js +97 -38
  3. package/lib/mate-datastore.js +27 -5
  4. package/lib/mates.js +2 -2
  5. package/lib/os-users.js +13 -0
  6. package/lib/project-connection.js +16 -9
  7. package/lib/project-mate-datastore.js +16 -2
  8. package/lib/project-sessions.js +110 -7
  9. package/lib/project-user-message.js +4 -3
  10. package/lib/project.js +97 -10
  11. package/lib/public/css/mates.css +94 -52
  12. package/lib/public/css/mobile-nav.css +0 -14
  13. package/lib/public/css/notifications-center.css +23 -19
  14. package/lib/public/css/sidebar.css +326 -101
  15. package/lib/public/index.html +24 -57
  16. package/lib/public/modules/app-dm.js +0 -2
  17. package/lib/public/modules/app-messages.js +3 -5
  18. package/lib/public/modules/app-rendering.js +0 -2
  19. package/lib/public/modules/diff.js +21 -7
  20. package/lib/public/modules/mate-datastore-ui.js +108 -98
  21. package/lib/public/modules/mate-sidebar.js +0 -9
  22. package/lib/public/modules/mate-wizard.js +15 -15
  23. package/lib/public/modules/sidebar-mobile.js +10 -20
  24. package/lib/public/modules/sidebar-sessions.js +490 -113
  25. package/lib/public/modules/sidebar.js +8 -6
  26. package/lib/public/modules/tools.js +58 -13
  27. package/lib/public/sw.js +1 -1
  28. package/lib/sdk-bridge.js +36 -28
  29. package/lib/sdk-message-processor.js +14 -3
  30. package/lib/server.js +28 -72
  31. package/lib/sessions.js +157 -20
  32. package/lib/ws-schema.js +2 -0
  33. package/lib/yoke/adapters/claude-worker.js +114 -2
  34. package/lib/yoke/adapters/claude.js +56 -5
  35. package/lib/yoke/adapters/codex.js +349 -58
  36. package/lib/yoke/index.js +73 -35
  37. package/lib/yoke/instructions.js +0 -1
  38. package/lib/yoke/mcp-bridge-server.js +14 -6
  39. package/package.json +1 -2
  40. package/lib/yoke/adapters/gemini.js +0 -709
@@ -197,17 +197,14 @@
197
197
  </div>
198
198
  <div id="sidebar-sessions-header">
199
199
  <div id="sessions-header-content">
200
- <div class="session-list-header">
201
- <span>Sessions</span>
202
- <div class="session-list-header-actions">
203
- <button id="new-session-btn" type="button" data-tip="New session"><i data-lucide="plus"></i></button>
204
- <button id="resume-session-btn" type="button" data-tip="Import CLI session"><i data-lucide="import"></i></button>
205
- <button id="search-session-btn" type="button" data-tip="Search sessions"><i data-lucide="search"></i></button>
200
+ <div class="sidebar-sessions-header-row">
201
+ <span class="sidebar-section-label">Sessions</span>
202
+ <span id="session-filter-count" class="session-filter-count hidden"></span>
203
+ <div id="session-header-search-inline" class="sidebar-sessions-search-inline hidden">
204
+ <input id="session-header-search-input" type="text" placeholder="Search sessions..." autocomplete="off" spellcheck="false" />
205
+ <button id="session-header-search-clear" type="button" aria-label="Clear search"><i data-lucide="x"></i></button>
206
206
  </div>
207
- </div>
208
- <div id="session-search" class="hidden">
209
- <input id="session-search-input" type="text" placeholder="Search sessions..." autocomplete="off" spellcheck="false" />
210
- <button id="session-search-clear" type="button" aria-label="Clear search"><i data-lucide="x"></i></button>
207
+ <button id="session-header-search-btn" type="button" aria-label="Search sessions" title="Search sessions"><i data-lucide="search"></i></button>
211
208
  </div>
212
209
  </div>
213
210
  <div id="files-header-content" class="hidden"></div>
@@ -270,7 +267,6 @@
270
267
  <div class="mate-sidebar-sessions-header">
271
268
  <span>Conversations</span>
272
269
  <div class="mate-sidebar-actions">
273
- <button id="mate-data-btn" type="button" title="Data inspector"><i data-lucide="database"></i></button>
274
270
  <button id="mate-search-session-btn" type="button" title="Search sessions"><i data-lucide="search"></i></button>
275
271
  <button id="mate-new-session-btn" type="button" title="New session"><i data-lucide="plus"></i></button>
276
272
  </div>
@@ -281,33 +277,6 @@
281
277
  </div>
282
278
  <div id="mate-session-list" class="mate-session-list"></div>
283
279
  </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
280
  <div id="mate-sidebar-memory" class="hidden"></div>
312
281
  <div id="mate-sidebar-knowledge" class="hidden">
313
282
  <div class="mate-sidebar-sessions-header">
@@ -1883,7 +1852,7 @@
1883
1852
  <div class="mate-intro-step"><span class="mate-intro-step-num">2</span> Have a short interview where your Mate gets to know you</div>
1884
1853
  <div class="mate-intro-step"><span class="mate-intro-step-num">3</span> Start talking</div>
1885
1854
  </div>
1886
- <p class="mate-intro-privacy">Mates run on Claude Code. No separate API keys or external services needed. Your conversations stay on your Clay server and are never stored elsewhere.</p>
1855
+ <p class="mate-intro-privacy">Mates run on Claude Code or ChatGPT Codex, your choice. No separate API keys or external services needed. Your conversations stay on your Clay server and are never stored elsewhere.</p>
1887
1856
  </div>
1888
1857
  </div>
1889
1858
  <!-- Step 1: Relationship -->
@@ -2024,26 +1993,24 @@
2024
1993
  </div>
2025
1994
  </div>
2026
1995
 
2027
- <!-- Step 4: Autonomy -->
1996
+ <!-- Step 4: Vendor -->
2028
1997
  <div class="mate-step" data-step="4">
2029
- <h3>How much should they do on their own?</h3>
2030
- <p class="mate-hint">This is about how much freedom your mate gets before checking with you.</p>
2031
- <div class="mate-autonomy-options">
2032
- <button class="mate-autonomy-btn" data-value="always_ask">
2033
- <span class="mate-autonomy-title">Ask me everything</span>
2034
- <span class="mate-autonomy-desc">"Before you do anything, run it by me first."</span>
2035
- </button>
2036
- <button class="mate-autonomy-btn active" data-value="minor_stuff_ok">
2037
- <span class="mate-autonomy-title">Small stuff is fine</span>
2038
- <span class="mate-autonomy-desc">"Little things, just do it. Anything big, ask me."</span>
2039
- </button>
2040
- <button class="mate-autonomy-btn" data-value="mostly_autonomous">
2041
- <span class="mate-autonomy-title">Mostly free</span>
2042
- <span class="mate-autonomy-desc">"Do your thing. Only check if it's really important."</span>
1998
+ <h3>Which model should power them?</h3>
1999
+ <p class="mate-hint">You can switch this anytime from the mate's settings.</p>
2000
+ <div class="mate-vendor-option-list">
2001
+ <button class="mate-vendor-option-btn active" data-value="claude">
2002
+ <img src="/claude-code-avatar.png" class="mate-vendor-option-icon" alt="Claude Code">
2003
+ <div class="mate-vendor-option-text">
2004
+ <span class="mate-vendor-option-title">Claude Code</span>
2005
+ <span class="mate-vendor-option-desc">Anthropic's Claude. Thoughtful, conversational, strong at nuanced reasoning and long-form writing. A good default for most mates.</span>
2006
+ </div>
2043
2007
  </button>
2044
- <button class="mate-autonomy-btn" data-value="fully_autonomous">
2045
- <span class="mate-autonomy-title">Full freedom</span>
2046
- <span class="mate-autonomy-desc">"Just get it done and tell me after."</span>
2008
+ <button class="mate-vendor-option-btn" data-value="codex">
2009
+ <img src="/codex-avatar.png" class="mate-vendor-option-icon" alt="ChatGPT Codex">
2010
+ <div class="mate-vendor-option-text">
2011
+ <span class="mate-vendor-option-title">ChatGPT Codex</span>
2012
+ <span class="mate-vendor-option-desc">OpenAI's GPT coding agent. Fast and direct, strong at code generation and tight execution loops. Good for builder-type mates.</span>
2013
+ </div>
2047
2014
  </button>
2048
2015
  </div>
2049
2016
  </div>
@@ -474,8 +474,6 @@ export function buildMateInterviewPrompt(mate) {
474
474
  var styles = sd.communicationStyle.map(function (s) { return styleLabels[s] || s.replace(/_/g, " "); });
475
475
  parts.push("Communication: " + styles.join(", "));
476
476
  }
477
- if (sd.autonomy) parts.push("Autonomy: " + sd.autonomy.replace(/_/g, " "));
478
-
479
477
  return "Use the /clay-mate-interview skill to start the interview.\n\n" +
480
478
  "Mate ID: " + mate.id + "\n" +
481
479
  "Mate Directory: .claude/mates/" + mate.id + "\n\n" +
@@ -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;
@@ -736,6 +732,8 @@ export function processMessage(msg) {
736
732
  getTools()[msg.id] = { el: null, name: msg.name, input: null, done: true, hidden: true };
737
733
  } else if (msg.name === "propose_debate" || (msg.name && msg.name.indexOf("propose_debate") !== -1)) {
738
734
  getTools()[msg.id] = { el: null, name: msg.name, input: null, done: true, hidden: true };
735
+ } else if (msg.name === "ask_user_questions") {
736
+ getTools()[msg.id] = { el: null, name: msg.name, input: null, done: true, hidden: true };
739
737
  } else if (getTodoTools()[msg.name]) {
740
738
  getTools()[msg.id] = { el: null, name: msg.name, input: null, done: true, hidden: true };
741
739
  } else {
@@ -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";
@@ -238,25 +238,39 @@ export function renderSplitDiff(oldStr, newStr, lang) {
238
238
  * Parses hunk headers for line numbers. Optional lang for syntax highlighting.
239
239
  * Returns a DOM element.
240
240
  */
241
- export function renderPatchDiff(text, lang) {
241
+ /**
242
+ * Reconstruct old and new source text from a unified patch string.
243
+ * Skips file headers, "diff --git" lines, index lines, and hunk headers.
244
+ * Returns { oldStr, newStr }.
245
+ */
246
+ export function reconstructPatchSources(text) {
242
247
  var lines = text.split("\n");
243
-
244
- // Reconstruct old and new source for highlighting
245
248
  var oldSrc = [];
246
249
  var newSrc = [];
247
250
  for (var p = 0; p < lines.length; p++) {
248
251
  var pl = lines[p];
249
- if (pl.startsWith("-") && !pl.startsWith("---")) {
252
+ if (pl.startsWith("---") || pl.startsWith("+++")) continue;
253
+ if (pl.startsWith("diff ") || pl.startsWith("index ")) continue;
254
+ if (pl.startsWith("@@")) continue;
255
+ if (pl.startsWith("-")) {
250
256
  oldSrc.push(pl.substring(1));
251
- } else if (pl.startsWith("+") && !pl.startsWith("+++")) {
257
+ } else if (pl.startsWith("+")) {
252
258
  newSrc.push(pl.substring(1));
253
259
  } else if (pl.startsWith(" ")) {
254
260
  oldSrc.push(pl.substring(1));
255
261
  newSrc.push(pl.substring(1));
256
262
  }
257
263
  }
258
- var oldHL = highlightLines(oldSrc.join("\n"), lang);
259
- var newHL = highlightLines(newSrc.join("\n"), lang);
264
+ return { oldStr: oldSrc.join("\n"), newStr: newSrc.join("\n") };
265
+ }
266
+
267
+ export function renderPatchDiff(text, lang) {
268
+ var lines = text.split("\n");
269
+
270
+ // Reconstruct old and new source for highlighting
271
+ var sources = reconstructPatchSources(text);
272
+ var oldHL = highlightLines(sources.oldStr, lang);
273
+ var newHL = highlightLines(sources.newStr, lang);
260
274
  var oldHLIdx = 0;
261
275
  var newHLIdx = 0;
262
276
 
@@ -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) {
@@ -225,15 +225,6 @@ export function showMateSidebar(mateId, mateData) {
225
225
  if (sd.communicationStyle && sd.communicationStyle.length > 0) {
226
226
  seedTooltip.appendChild(makeSeedTags("Style", sd.communicationStyle.map(function (s) { return s.replace(/_/g, " "); })));
227
227
  }
228
- if (sd.autonomy) {
229
- var autonomyLabels = {
230
- always_ask: "Ask me everything",
231
- minor_stuff_ok: "Small stuff is fine",
232
- mostly_autonomous: "Mostly free",
233
- fully_autonomous: "Full freedom",
234
- };
235
- seedTooltip.appendChild(makeSeedRow("Autonomy", autonomyLabels[sd.autonomy] || sd.autonomy.replace(/_/g, " ")));
236
- }
237
228
  }
238
229
 
239
230
  // Clear session list
@@ -6,7 +6,7 @@ var mateWizardData = {
6
6
  relationship: null,
7
7
  activity: [],
8
8
  communicationStyle: [],
9
- autonomy: "minor_stuff_ok",
9
+ vendor: "claude",
10
10
  };
11
11
 
12
12
  var _sendWs = null;
@@ -85,19 +85,19 @@ export function initMateWizard(sendWs, onMateCreated) {
85
85
  })(styleCards[i]);
86
86
  }
87
87
 
88
- // Step 4: Autonomy button clicks
89
- var autonomyBtns = document.querySelectorAll("#mate-wizard .mate-autonomy-btn");
90
- for (var i = 0; i < autonomyBtns.length; i++) {
88
+ // Step 4: Vendor button clicks
89
+ var vendorBtns = document.querySelectorAll("#mate-wizard .mate-vendor-option-btn");
90
+ for (var i = 0; i < vendorBtns.length; i++) {
91
91
  (function (btn) {
92
92
  btn.addEventListener("click", function () {
93
- var allBtns = document.querySelectorAll("#mate-wizard .mate-autonomy-btn");
93
+ var allBtns = document.querySelectorAll("#mate-wizard .mate-vendor-option-btn");
94
94
  for (var j = 0; j < allBtns.length; j++) {
95
95
  allBtns[j].classList.remove("active");
96
96
  }
97
97
  btn.classList.add("active");
98
- mateWizardData.autonomy = btn.dataset.value;
98
+ mateWizardData.vendor = btn.dataset.value;
99
99
  });
100
- })(autonomyBtns[i]);
100
+ })(vendorBtns[i]);
101
101
  }
102
102
  }
103
103
 
@@ -107,7 +107,7 @@ export function openMateWizard() {
107
107
  relationship: null,
108
108
  activity: [],
109
109
  communicationStyle: [],
110
- autonomy: "minor_stuff_ok",
110
+ vendor: "claude",
111
111
  };
112
112
 
113
113
  // Reset UI
@@ -136,12 +136,12 @@ export function openMateWizard() {
136
136
  styleCards[i].classList.remove("selected");
137
137
  }
138
138
 
139
- // Reset autonomy
140
- var autonomyBtns = el.querySelectorAll(".mate-autonomy-btn");
141
- for (var i = 0; i < autonomyBtns.length; i++) {
142
- autonomyBtns[i].classList.remove("active");
143
- if (autonomyBtns[i].dataset.value === "minor_stuff_ok") {
144
- autonomyBtns[i].classList.add("active");
139
+ // Reset vendor
140
+ var vendorBtns = el.querySelectorAll(".mate-vendor-option-btn");
141
+ for (var i = 0; i < vendorBtns.length; i++) {
142
+ vendorBtns[i].classList.remove("active");
143
+ if (vendorBtns[i].dataset.value === "claude") {
144
+ vendorBtns[i].classList.add("active");
145
145
  }
146
146
  }
147
147
 
@@ -220,7 +220,7 @@ function collectMateWizardData() {
220
220
  mateWizardData.communicationStyle.push(selectedStyles[i].dataset.value);
221
221
  }
222
222
 
223
- // Autonomy (already set via button clicks)
223
+ // Vendor (already set via button clicks)
224
224
  }
225
225
 
226
226
  function mateWizardNext() {
@@ -11,7 +11,8 @@ import { getMateSessions } from './mate-sidebar.js';
11
11
  import { openProjectSettings } from './project-settings.js';
12
12
  import {
13
13
  getCachedSessions,
14
- getDateGroup
14
+ getDateGroup,
15
+ openResumePicker
15
16
  } from './sidebar-sessions.js';
16
17
  import {
17
18
  getCachedProjectList,
@@ -389,12 +390,6 @@ function createMobileSessionItem(s) {
389
390
 
390
391
  var titleSpan = document.createElement("span");
391
392
  titleSpan.className = "mobile-session-title";
392
- if (s.bookmarked) {
393
- var bookmarkIcon = document.createElement("span");
394
- bookmarkIcon.className = "mobile-session-bookmark";
395
- bookmarkIcon.innerHTML = iconHtml("star");
396
- titleSpan.appendChild(bookmarkIcon);
397
- }
398
393
  titleSpan.appendChild(document.createTextNode(s.title || "New Session"));
399
394
  el.appendChild(titleSpan);
400
395
 
@@ -720,8 +715,7 @@ function renderMobileSessionsInto(container) {
720
715
  importBtn.innerHTML = '<i data-lucide="import" style="width:16px;height:16px"></i> Import session';
721
716
  importBtn.addEventListener("click", function () {
722
717
  closeMobileSheet();
723
- var targetBtn = document.getElementById("resume-session-btn");
724
- if (targetBtn) setTimeout(function () { targetBtn.click(); }, 250);
718
+ setTimeout(function () { openResumePicker(); }, 250);
725
719
  });
726
720
  container.appendChild(importBtn);
727
721
 
@@ -784,7 +778,7 @@ function renderMobileSessionsInto(container) {
784
778
  if (bookmarkedItems.length > 0) {
785
779
  var bookmarkedHeader = document.createElement("div");
786
780
  bookmarkedHeader.className = "mobile-sheet-group";
787
- bookmarkedHeader.textContent = "Bookmarked";
781
+ bookmarkedHeader.textContent = "Favorites";
788
782
  container.appendChild(bookmarkedHeader);
789
783
 
790
784
  for (var bi = 0; bi < bookmarkedItems.length; bi++) {
@@ -798,10 +792,12 @@ function renderMobileSessionsInto(container) {
798
792
  var group = getDateGroup(item.lastActivity || 0);
799
793
  if (group !== currentGroup) {
800
794
  currentGroup = group;
801
- var header = document.createElement("div");
802
- header.className = "mobile-sheet-group";
803
- header.textContent = group;
804
- container.appendChild(header);
795
+ if (group !== "Today") {
796
+ var header = document.createElement("div");
797
+ header.className = "mobile-sheet-group";
798
+ header.textContent = group;
799
+ container.appendChild(header);
800
+ }
805
801
  }
806
802
  if (item.type === "loop") {
807
803
  container.appendChild(createMobileLoopGroup(item.loopId, item.children, item.groupKey));
@@ -977,12 +973,6 @@ function renderSearchResults(container, query) {
977
973
 
978
974
  var titleSpan = document.createElement("span");
979
975
  titleSpan.className = "mobile-session-title";
980
- if (s.bookmarked) {
981
- var bookmarkIcon = document.createElement("span");
982
- bookmarkIcon.className = "mobile-session-bookmark";
983
- bookmarkIcon.innerHTML = iconHtml("star");
984
- titleSpan.appendChild(bookmarkIcon);
985
- }
986
976
  titleSpan.appendChild(document.createTextNode(title));
987
977
  el.appendChild(titleSpan);
988
978