clay-server 2.30.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/email-accounts.js +299 -0
- package/lib/email-mcp-server.js +646 -0
- package/lib/project-connection.js +26 -2
- package/lib/project-email.js +418 -0
- package/lib/project-sessions.js +16 -0
- package/lib/project-user-message.js +26 -5
- package/lib/project.js +72 -25
- package/lib/public/app.js +18 -5
- package/lib/public/css/filebrowser.css +80 -2
- package/lib/public/css/input.css +196 -0
- package/lib/public/css/notifications-center.css +3 -0
- package/lib/public/css/sidebar.css +77 -2
- package/lib/public/css/sticky-notes.css +0 -48
- package/lib/public/css/user-settings.css +85 -0
- package/lib/public/icons/email/gmail.svg +7 -0
- package/lib/public/icons/email/outlook.svg +35 -0
- package/lib/public/icons/email/yahoo.svg +1 -0
- package/lib/public/index.html +36 -3
- package/lib/public/modules/app-dm.js +4 -9
- package/lib/public/modules/app-messages.js +37 -2
- package/lib/public/modules/app-panels.js +2 -1
- package/lib/public/modules/context-sources.js +527 -1
- package/lib/public/modules/filebrowser.js +72 -0
- package/lib/public/modules/mate-sidebar.js +7 -0
- package/lib/public/modules/sidebar-mobile.js +1 -1
- package/lib/public/modules/sidebar.js +144 -2
- package/lib/public/modules/sticky-notes.js +1 -91
- package/lib/public/modules/terminal.js +0 -12
- package/lib/public/modules/theme.js +4 -0
- package/lib/public/modules/tools.js +23 -0
- package/lib/public/modules/user-settings.js +74 -0
- package/lib/sdk-bridge.js +16 -0
- package/lib/sdk-message-processor.js +33 -0
- package/lib/server-email.js +148 -0
- package/lib/server.js +5 -0
- package/package.json +3 -2
package/lib/project.js
CHANGED
|
@@ -28,15 +28,17 @@ var { attachUserMessage } = require("./project-user-message");
|
|
|
28
28
|
var { attachConnection } = require("./project-connection");
|
|
29
29
|
var { attachMcp } = require("./project-mcp");
|
|
30
30
|
var { createLocalMcp } = require("./mcp-local");
|
|
31
|
+
var { attachEmail: attachEmailModule } = require("./project-email");
|
|
31
32
|
// project-notifications is attached globally in server.js, passed via opts.notificationsModule
|
|
32
33
|
|
|
33
34
|
// --- Context Sources persistence ---
|
|
34
35
|
var _ctxSrcConfig = require("./config");
|
|
35
36
|
var _ctxSrcDir = path.join(_ctxSrcConfig.CONFIG_DIR, "context-sources");
|
|
36
37
|
|
|
37
|
-
function loadContextSources(slug) {
|
|
38
|
+
function loadContextSources(slug, sessionId) {
|
|
38
39
|
try {
|
|
39
|
-
var
|
|
40
|
+
var key = sessionId ? slug + "--" + sessionId : slug;
|
|
41
|
+
var filePath = path.join(_ctxSrcDir, key + ".json");
|
|
40
42
|
var data = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
41
43
|
return data.active || [];
|
|
42
44
|
} catch (e) {
|
|
@@ -44,12 +46,13 @@ function loadContextSources(slug) {
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
function saveContextSources(slug, activeIds) {
|
|
49
|
+
function saveContextSources(slug, sessionId, activeIds) {
|
|
48
50
|
try {
|
|
49
51
|
if (!fs.existsSync(_ctxSrcDir)) {
|
|
50
52
|
fs.mkdirSync(_ctxSrcDir, { recursive: true });
|
|
51
53
|
}
|
|
52
|
-
var
|
|
54
|
+
var key = sessionId ? slug + "--" + sessionId : slug;
|
|
55
|
+
var filePath = path.join(_ctxSrcDir, key + ".json");
|
|
53
56
|
fs.writeFileSync(filePath, JSON.stringify({ active: activeIds }), "utf8");
|
|
54
57
|
} catch (e) {
|
|
55
58
|
console.error("[context-sources] Failed to save:", e.message);
|
|
@@ -255,15 +258,19 @@ function createProjectContext(opts) {
|
|
|
255
258
|
return sendExtensionCommand(browserState._extensionWs, command, args, timeout);
|
|
256
259
|
}
|
|
257
260
|
|
|
258
|
-
function requestTabContext(
|
|
261
|
+
function requestTabContext(tabId) {
|
|
262
|
+
if (!browserState._extensionWs || browserState._extensionWs.readyState !== 1) {
|
|
263
|
+
return Promise.resolve(null);
|
|
264
|
+
}
|
|
265
|
+
var extWs = browserState._extensionWs;
|
|
259
266
|
// Try inject first (best-effort), then request all data in parallel.
|
|
260
267
|
// Even if inject fails (CSP etc.), page text and screenshot still work.
|
|
261
|
-
return sendExtensionCommand(
|
|
268
|
+
return sendExtensionCommand(extWs, "tab_inject", { tabId: tabId }).then(function() {}, function() {}).then(function() {
|
|
262
269
|
return Promise.all([
|
|
263
|
-
sendExtensionCommand(
|
|
264
|
-
sendExtensionCommand(
|
|
265
|
-
sendExtensionCommand(
|
|
266
|
-
sendExtensionCommand(
|
|
270
|
+
sendExtensionCommand(extWs, "tab_console", { tabId: tabId }),
|
|
271
|
+
sendExtensionCommand(extWs, "tab_network", { tabId: tabId }),
|
|
272
|
+
sendExtensionCommand(extWs, "tab_page_text", { tabId: tabId }),
|
|
273
|
+
sendExtensionCommand(extWs, "tab_screenshot", { tabId: tabId })
|
|
267
274
|
]);
|
|
268
275
|
}).then(function(results) {
|
|
269
276
|
return {
|
|
@@ -432,6 +439,18 @@ function createProjectContext(opts) {
|
|
|
432
439
|
localMcp: _localMcp,
|
|
433
440
|
});
|
|
434
441
|
|
|
442
|
+
// --- Email module (delegated to project-email.js) ---
|
|
443
|
+
var _email = attachEmailModule({
|
|
444
|
+
slug: slug,
|
|
445
|
+
send: send,
|
|
446
|
+
sendTo: sendTo,
|
|
447
|
+
clients: clients,
|
|
448
|
+
loadContextSources: loadContextSources,
|
|
449
|
+
getUserIdForWs: function (ws) {
|
|
450
|
+
return (ws._clayUser && ws._clayUser.id) || "default";
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
|
|
435
454
|
// --- SDK bridge ---
|
|
436
455
|
var sdk = createSDKBridge({
|
|
437
456
|
cwd: cwd,
|
|
@@ -476,24 +495,31 @@ function createProjectContext(opts) {
|
|
|
476
495
|
}, {
|
|
477
496
|
watchTab: function (tabId) {
|
|
478
497
|
var key = "tab:" + tabId;
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
var
|
|
484
|
-
|
|
498
|
+
// Apply to all connected clients' active sessions
|
|
499
|
+
for (var c of clients) {
|
|
500
|
+
if (c.readyState !== 1) continue;
|
|
501
|
+
var sid = c._clayActiveSession || null;
|
|
502
|
+
var active = loadContextSources(slug, sid);
|
|
503
|
+
if (active.indexOf(key) === -1) {
|
|
504
|
+
active.push(key);
|
|
505
|
+
saveContextSources(slug, sid, active);
|
|
506
|
+
c.send(JSON.stringify({ type: "context_sources_state", active: active }));
|
|
507
|
+
}
|
|
485
508
|
}
|
|
486
|
-
return
|
|
509
|
+
return [];
|
|
487
510
|
},
|
|
488
511
|
unwatchTab: function (tabId) {
|
|
489
512
|
var key = "tab:" + tabId;
|
|
490
|
-
var
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
active
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
513
|
+
for (var c of clients) {
|
|
514
|
+
if (c.readyState !== 1) continue;
|
|
515
|
+
var sid = c._clayActiveSession || null;
|
|
516
|
+
var active = loadContextSources(slug, sid);
|
|
517
|
+
var idx = active.indexOf(key);
|
|
518
|
+
if (idx !== -1) {
|
|
519
|
+
active.splice(idx, 1);
|
|
520
|
+
saveContextSources(slug, sid, active);
|
|
521
|
+
c.send(JSON.stringify({ type: "context_sources_state", active: active }));
|
|
522
|
+
}
|
|
497
523
|
}
|
|
498
524
|
return active;
|
|
499
525
|
},
|
|
@@ -504,6 +530,17 @@ function createProjectContext(opts) {
|
|
|
504
530
|
}
|
|
505
531
|
}
|
|
506
532
|
|
|
533
|
+
// Email MCP server (available to both mates and main project)
|
|
534
|
+
try {
|
|
535
|
+
var emailMcp = require("./email-mcp-server");
|
|
536
|
+
// Use "default" userId initially; the actual userId is resolved per-tool-call
|
|
537
|
+
// via the deps closures which read from the active WS connection.
|
|
538
|
+
var emailMcpConfig = emailMcp.create(_email.createMcpDeps());
|
|
539
|
+
if (emailMcpConfig) servers[emailMcpConfig.name || "clay-email"] = emailMcpConfig;
|
|
540
|
+
} catch (e) {
|
|
541
|
+
console.error("[project] Failed to create email MCP server:", e.message);
|
|
542
|
+
}
|
|
543
|
+
|
|
507
544
|
return Object.keys(servers).length > 0 ? servers : undefined;
|
|
508
545
|
})(),
|
|
509
546
|
getRemoteMcpServers: function () { return _mcp.getMcpServers(); },
|
|
@@ -651,7 +688,7 @@ function createProjectContext(opts) {
|
|
|
651
688
|
}
|
|
652
689
|
|
|
653
690
|
// --- DM messages (delegated to server-level handler) ---
|
|
654
|
-
if (msg.type === "dm_open" || msg.type === "dm_send" || msg.type === "dm_list" || msg.type === "dm_typing" || msg.type === "dm_add_favorite" || msg.type === "dm_remove_favorite" || msg.type === "mate_create" || msg.type === "mate_list" || msg.type === "mate_delete" || msg.type === "mate_update" || msg.type === "mate_readd_builtin" || msg.type === "mate_list_available_builtins") {
|
|
691
|
+
if (msg.type === "dm_open" || msg.type === "dm_send" || msg.type === "dm_list" || msg.type === "dm_typing" || msg.type === "dm_add_favorite" || msg.type === "dm_remove_favorite" || msg.type === "mate_create" || msg.type === "mate_list" || msg.type === "mate_delete" || msg.type === "mate_update" || msg.type === "mate_readd_builtin" || msg.type === "mate_list_available_builtins" || msg.type === "email_accounts_list" || msg.type === "email_account_add" || msg.type === "email_account_remove" || msg.type === "email_account_test") {
|
|
655
692
|
if (typeof opts.onDmMessage === "function") {
|
|
656
693
|
opts.onDmMessage(ws, msg);
|
|
657
694
|
}
|
|
@@ -733,6 +770,9 @@ function createProjectContext(opts) {
|
|
|
733
770
|
return;
|
|
734
771
|
}
|
|
735
772
|
|
|
773
|
+
// --- Email defaults (project-level) ---
|
|
774
|
+
if (_email.handleEmailMessage(ws, msg)) return;
|
|
775
|
+
|
|
736
776
|
// --- MCP bridge (remote MCP servers via extension) ---
|
|
737
777
|
if (_mcp.handleMcpMessage(ws, msg)) return;
|
|
738
778
|
|
|
@@ -929,6 +969,9 @@ function createProjectContext(opts) {
|
|
|
929
969
|
setLatestVersion: function (v) { latestVersion = v; },
|
|
930
970
|
onCreateWorktree: onCreateWorktree,
|
|
931
971
|
IGNORED_DIRS: IGNORED_DIRS,
|
|
972
|
+
loadContextSources: loadContextSources,
|
|
973
|
+
saveContextSources: saveContextSources,
|
|
974
|
+
_email: _email,
|
|
932
975
|
});
|
|
933
976
|
|
|
934
977
|
// --- User message handler (delegated to project-user-message.js) ---
|
|
@@ -970,6 +1013,7 @@ function createProjectContext(opts) {
|
|
|
970
1013
|
getSDK: getSDK,
|
|
971
1014
|
getHubSchedules: getHubSchedules,
|
|
972
1015
|
getProjectOwnerId: function () { return projectOwnerId; },
|
|
1016
|
+
_email: _email,
|
|
973
1017
|
});
|
|
974
1018
|
|
|
975
1019
|
// --- Filesystem handler (delegated to project-filesystem.js) ---
|
|
@@ -1041,6 +1085,8 @@ function createProjectContext(opts) {
|
|
|
1041
1085
|
getProjectList: getProjectList,
|
|
1042
1086
|
getHubSchedules: getHubSchedules,
|
|
1043
1087
|
loadContextSources: loadContextSources,
|
|
1088
|
+
saveContextSources: saveContextSources,
|
|
1089
|
+
_email: _email,
|
|
1044
1090
|
restoreDebateState: restoreDebateState,
|
|
1045
1091
|
stopFileWatch: stopFileWatch,
|
|
1046
1092
|
stopAllDirWatches: stopAllDirWatches,
|
|
@@ -1054,6 +1100,7 @@ function createProjectContext(opts) {
|
|
|
1054
1100
|
// --- Destroy ---
|
|
1055
1101
|
function destroy() {
|
|
1056
1102
|
_loop.stopTimer();
|
|
1103
|
+
_email.destroy();
|
|
1057
1104
|
stopFileWatch();
|
|
1058
1105
|
stopAllDirWatches();
|
|
1059
1106
|
// Abort all active sessions and clean up mention sessions
|
package/lib/public/app.js
CHANGED
|
@@ -26,8 +26,8 @@ import { initInput, clearPendingImages, handleInputSync, autoResize, builtinComm
|
|
|
26
26
|
import { initQrCode, triggerShare } from './modules/qrcode.js';
|
|
27
27
|
import { initFileBrowser, loadRootDirectory, refreshTree, handleFsList, handleFsRead, handleDirChanged, refreshIfOpen, handleFileChanged, handleFileHistory, handleGitDiff, handleFileAt, getPendingNavigate, closeFileViewer, resetFileBrowser } from './modules/filebrowser.js';
|
|
28
28
|
import { initTerminal, openTerminal, closeTerminal, resetTerminals, handleTermList, handleTermCreated, handleTermOutput, handleTermResized, handleTermExited, handleTermClosed, sendTerminalCommand } from './modules/terminal.js';
|
|
29
|
-
import { initContextSources, updateTerminalList, updateBrowserTabList, handleContextSourcesState, getActiveSources, hasActiveSources } from './modules/context-sources.js';
|
|
30
|
-
import { initStickyNotes, handleNotesList, handleNoteCreated, handleNoteUpdated, handleNoteDeleted, openArchive, closeArchive, isArchiveOpen, hideNotes, showNotes, isNotesVisible } from './modules/sticky-notes.js';
|
|
29
|
+
import { initContextSources, initEmailDefaultsModal, updateTerminalList, updateBrowserTabList, handleContextSourcesState, getActiveSources, hasActiveSources } from './modules/context-sources.js';
|
|
30
|
+
import { initStickyNotes, handleNotesList, handleNoteCreated, handleNoteUpdated, handleNoteDeleted, openArchive, closeArchive, isArchiveOpen, hideNotes, showNotes, isNotesVisible, createNote } from './modules/sticky-notes.js';
|
|
31
31
|
import { initTheme, getThemeColor, getComputedVar, onThemeChange, getCurrentTheme, getChatLayout } from './modules/theme.js';
|
|
32
32
|
import { initTools, resetToolState, saveToolState, restoreToolState, renderAskUserQuestion, markAskUserAnswered, renderPermissionRequest, markPermissionResolved, markPermissionCancelled, renderElicitationRequest, markElicitationResolved, renderPlanBanner, renderPlanCard, handleTodoWrite, handleTaskCreate, handleTaskUpdate, startThinking, appendThinking, stopThinking, resetThinkingGroup, createToolItem, updateToolExecuting, updateToolResult, markAllToolsDone, addTurnMeta, resetTurnMetaCost, enableMainInput, getTools, getPlanContent, setPlanContent, isPlanFilePath, getTodoTools, updateSubagentActivity, addSubagentToolEntry, markSubagentDone, updateSubagentProgress, initSubagentStop, closeToolGroup, removeToolFromGroup } from './modules/tools.js';
|
|
33
33
|
import { initServerSettings, updateSettingsStats, updateSettingsModels, updateDaemonConfig, handleSetPinResult, handleKeepAwakeChanged, handleAutoContinueChanged, handleRestartResult, handleShutdownResult, handleSharedEnv, handleSharedEnvSaved, handleGlobalClaudeMdRead, handleGlobalClaudeMdWrite } from './modules/server-settings.js';
|
|
@@ -264,6 +264,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
264
264
|
historyTotal: 0,
|
|
265
265
|
replayingHistory: false,
|
|
266
266
|
projectName: projectName,
|
|
267
|
+
cwd: "",
|
|
267
268
|
currentSlug: currentSlug,
|
|
268
269
|
currentProjectOwnerId: null,
|
|
269
270
|
isOsUsers: false,
|
|
@@ -850,8 +851,6 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
850
851
|
// Apply RBAC UI gating
|
|
851
852
|
if (myPermissions) {
|
|
852
853
|
if (!myPermissions.terminal) {
|
|
853
|
-
var termBtn = document.getElementById("terminal-toggle-btn");
|
|
854
|
-
if (termBtn) termBtn.style.display = "none";
|
|
855
854
|
var termSideBtn = document.getElementById("terminal-sidebar-btn");
|
|
856
855
|
if (termSideBtn) termSideBtn.style.display = "none";
|
|
857
856
|
}
|
|
@@ -941,6 +940,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
941
940
|
get ws() { return ws; },
|
|
942
941
|
get connected() { return store.getState().connected; },
|
|
943
942
|
get activeSessionId() { return store.getState().activeSessionId; },
|
|
943
|
+
get cwd() { return store.getState().cwd; },
|
|
944
944
|
messagesEl: messagesEl,
|
|
945
945
|
fileTreeEl: $("file-tree"),
|
|
946
946
|
fileViewerEl: $("file-viewer"),
|
|
@@ -1002,10 +1002,22 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1002
1002
|
get connected() { return store.getState().connected; },
|
|
1003
1003
|
});
|
|
1004
1004
|
|
|
1005
|
-
// --- Sticky Notes sidebar button (
|
|
1005
|
+
// --- Sticky Notes sidebar button (create new note) ---
|
|
1006
1006
|
var stickyNotesSidebarBtn = $("sticky-notes-sidebar-btn");
|
|
1007
1007
|
if (stickyNotesSidebarBtn) {
|
|
1008
1008
|
stickyNotesSidebarBtn.addEventListener("click", function () {
|
|
1009
|
+
if (isSchedulerOpen()) closeScheduler();
|
|
1010
|
+
if (isArchiveOpen()) closeArchive();
|
|
1011
|
+
showNotes();
|
|
1012
|
+
createNote();
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// Sticky Notes badge click → archive toggle
|
|
1017
|
+
var stickyNotesBadge = $("sticky-notes-sidebar-count");
|
|
1018
|
+
if (stickyNotesBadge) {
|
|
1019
|
+
stickyNotesBadge.addEventListener("click", function (e) {
|
|
1020
|
+
e.stopPropagation();
|
|
1009
1021
|
if (isSchedulerOpen()) closeScheduler();
|
|
1010
1022
|
if (isArchiveOpen()) {
|
|
1011
1023
|
closeArchive();
|
|
@@ -1084,6 +1096,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1084
1096
|
|
|
1085
1097
|
// --- MCP Servers ---
|
|
1086
1098
|
initMcp();
|
|
1099
|
+
initEmailDefaultsModal();
|
|
1087
1100
|
|
|
1088
1101
|
// --- Skills ---
|
|
1089
1102
|
initSkills({
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
#session-actions button.active { background: var(--sidebar-hover); color: var(--text); }
|
|
32
32
|
|
|
33
33
|
.sidebar-badge {
|
|
34
|
-
background: var(--
|
|
35
|
-
color:
|
|
34
|
+
background: rgba(var(--overlay-rgb), 0.1);
|
|
35
|
+
color: var(--text-dimmer);
|
|
36
36
|
font-size: 10px;
|
|
37
37
|
font-weight: 700;
|
|
38
38
|
min-width: 16px;
|
|
@@ -47,6 +47,32 @@
|
|
|
47
47
|
}
|
|
48
48
|
.sidebar-badge.hidden { display: none; }
|
|
49
49
|
|
|
50
|
+
#sticky-notes-sidebar-count {
|
|
51
|
+
cursor: pointer;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
transition: padding 0.2s ease, background 0.15s ease, color 0.15s ease;
|
|
54
|
+
}
|
|
55
|
+
#sticky-notes-sidebar-count::after {
|
|
56
|
+
content: "Open Archive";
|
|
57
|
+
display: inline-block;
|
|
58
|
+
max-width: 0;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
white-space: nowrap;
|
|
61
|
+
vertical-align: middle;
|
|
62
|
+
margin-left: 0;
|
|
63
|
+
opacity: 0;
|
|
64
|
+
transition: max-width 0.2s ease, margin-left 0.2s ease, opacity 0.15s ease;
|
|
65
|
+
}
|
|
66
|
+
#sticky-notes-sidebar-count:hover {
|
|
67
|
+
background: var(--accent);
|
|
68
|
+
color: #fff;
|
|
69
|
+
}
|
|
70
|
+
#sticky-notes-sidebar-count:hover::after {
|
|
71
|
+
max-width: 80px;
|
|
72
|
+
margin-left: 4px;
|
|
73
|
+
opacity: 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
50
76
|
/* --- Panels --- */
|
|
51
77
|
.sidebar-panel { flex: 1; overflow-y: auto; min-height: 0; }
|
|
52
78
|
.sidebar-panel.hidden { display: none; }
|
|
@@ -61,6 +87,58 @@
|
|
|
61
87
|
#file-viewer-refresh.spinning { animation: spin-once 0.5s ease; }
|
|
62
88
|
@keyframes spin-once { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
|
|
63
89
|
|
|
90
|
+
/* --- File browser panel background --- */
|
|
91
|
+
#sidebar-panel-files {
|
|
92
|
+
background: var(--filebrowser-bg);
|
|
93
|
+
border: 1px solid var(--filebrowser-border);
|
|
94
|
+
border-radius: 8px;
|
|
95
|
+
margin: 0 6px 12px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#sidebar-panel-files.fb-enter { animation: fb-in 0.2s ease-out both; }
|
|
99
|
+
#sidebar-panel-files.fb-exit { animation: fb-out 0.15s ease-in both; }
|
|
100
|
+
|
|
101
|
+
@keyframes fb-in {
|
|
102
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
103
|
+
to { opacity: 1; transform: translateY(0); }
|
|
104
|
+
}
|
|
105
|
+
@keyframes fb-out {
|
|
106
|
+
from { opacity: 1; transform: translateY(0); }
|
|
107
|
+
to { opacity: 0; transform: translateY(6px); }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* --- Drag-and-drop file path into input --- */
|
|
111
|
+
.file-tree-item[draggable="true"] { cursor: grab; }
|
|
112
|
+
.file-tree-item[draggable="true"]:active { cursor: grabbing; }
|
|
113
|
+
|
|
114
|
+
#input.drop-target {
|
|
115
|
+
outline: 2px solid var(--accent);
|
|
116
|
+
outline-offset: -2px;
|
|
117
|
+
background: var(--accent-8);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.fb-drop-hint {
|
|
121
|
+
position: absolute;
|
|
122
|
+
top: -32px;
|
|
123
|
+
left: 50%;
|
|
124
|
+
transform: translateX(-50%) translateY(4px);
|
|
125
|
+
background: var(--accent);
|
|
126
|
+
color: var(--bg);
|
|
127
|
+
font-size: 11px;
|
|
128
|
+
font-weight: 600;
|
|
129
|
+
padding: 5px 12px;
|
|
130
|
+
border-radius: 6px;
|
|
131
|
+
white-space: nowrap;
|
|
132
|
+
pointer-events: none;
|
|
133
|
+
opacity: 0;
|
|
134
|
+
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.25);
|
|
135
|
+
transition: opacity 0.15s, transform 0.15s;
|
|
136
|
+
}
|
|
137
|
+
.fb-drop-hint.visible {
|
|
138
|
+
opacity: 1;
|
|
139
|
+
transform: translateX(-50%) translateY(0);
|
|
140
|
+
}
|
|
141
|
+
|
|
64
142
|
/* --- File tree --- */
|
|
65
143
|
#file-tree { padding: 4px 8px; }
|
|
66
144
|
|
package/lib/public/css/input.css
CHANGED
|
@@ -479,6 +479,202 @@
|
|
|
479
479
|
object-fit: contain;
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
+
.context-picker-unread-badge {
|
|
483
|
+
margin-left: auto;
|
|
484
|
+
margin-right: 4px;
|
|
485
|
+
font-size: 11px;
|
|
486
|
+
font-weight: 600;
|
|
487
|
+
background: var(--accent, #DA7756);
|
|
488
|
+
color: #fff;
|
|
489
|
+
border-radius: 8px;
|
|
490
|
+
padding: 1px 6px;
|
|
491
|
+
min-width: 16px;
|
|
492
|
+
text-align: center;
|
|
493
|
+
line-height: 1.3;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.context-picker-add-item {
|
|
497
|
+
color: var(--text-dimmer);
|
|
498
|
+
font-size: 13px;
|
|
499
|
+
opacity: 0.8;
|
|
500
|
+
}
|
|
501
|
+
.context-picker-add-item:hover {
|
|
502
|
+
opacity: 1;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/* --- Email setup modal --- */
|
|
506
|
+
#email-defaults-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; }
|
|
507
|
+
#email-defaults-modal.hidden { display: none; }
|
|
508
|
+
|
|
509
|
+
.email-setup-overlay {
|
|
510
|
+
position: fixed;
|
|
511
|
+
inset: 0;
|
|
512
|
+
background: rgba(0, 0, 0, 0.45);
|
|
513
|
+
z-index: 10000;
|
|
514
|
+
display: flex;
|
|
515
|
+
align-items: center;
|
|
516
|
+
justify-content: center;
|
|
517
|
+
}
|
|
518
|
+
.email-setup-dialog {
|
|
519
|
+
background: var(--bg);
|
|
520
|
+
border: 1px solid var(--border);
|
|
521
|
+
border-radius: 12px;
|
|
522
|
+
padding: 24px;
|
|
523
|
+
width: 420px;
|
|
524
|
+
max-width: 90vw;
|
|
525
|
+
max-height: 90vh;
|
|
526
|
+
overflow-y: auto;
|
|
527
|
+
color: var(--text);
|
|
528
|
+
}
|
|
529
|
+
.email-setup-title {
|
|
530
|
+
margin: 0 0 16px;
|
|
531
|
+
font-size: 16px;
|
|
532
|
+
font-weight: 600;
|
|
533
|
+
color: var(--text);
|
|
534
|
+
}
|
|
535
|
+
.email-setup-field {
|
|
536
|
+
margin-bottom: 12px;
|
|
537
|
+
}
|
|
538
|
+
.email-setup-label {
|
|
539
|
+
display: block;
|
|
540
|
+
font-size: 13px;
|
|
541
|
+
margin-bottom: 4px;
|
|
542
|
+
color: var(--text-muted);
|
|
543
|
+
}
|
|
544
|
+
.email-setup-input {
|
|
545
|
+
width: 100%;
|
|
546
|
+
padding: 8px;
|
|
547
|
+
border-radius: 6px;
|
|
548
|
+
border: 1px solid var(--border);
|
|
549
|
+
background: var(--input-bg);
|
|
550
|
+
color: var(--text);
|
|
551
|
+
font-size: 14px;
|
|
552
|
+
box-sizing: border-box;
|
|
553
|
+
font-family: inherit;
|
|
554
|
+
}
|
|
555
|
+
.email-setup-input:focus {
|
|
556
|
+
outline: none;
|
|
557
|
+
border-color: var(--accent);
|
|
558
|
+
}
|
|
559
|
+
.email-setup-port {
|
|
560
|
+
width: 70px;
|
|
561
|
+
flex: none !important;
|
|
562
|
+
}
|
|
563
|
+
.email-setup-row {
|
|
564
|
+
display: flex;
|
|
565
|
+
gap: 8px;
|
|
566
|
+
}
|
|
567
|
+
.email-setup-email-wrap {
|
|
568
|
+
display: flex;
|
|
569
|
+
align-items: center;
|
|
570
|
+
border-radius: 6px;
|
|
571
|
+
border: 1px solid var(--border);
|
|
572
|
+
background: var(--input-bg);
|
|
573
|
+
overflow: hidden;
|
|
574
|
+
}
|
|
575
|
+
.email-setup-email-wrap .email-setup-input {
|
|
576
|
+
border: none;
|
|
577
|
+
background: transparent;
|
|
578
|
+
border-radius: 0;
|
|
579
|
+
flex: 1;
|
|
580
|
+
min-width: 0;
|
|
581
|
+
}
|
|
582
|
+
.email-setup-email-wrap .email-setup-input:focus {
|
|
583
|
+
outline: none;
|
|
584
|
+
border: none;
|
|
585
|
+
}
|
|
586
|
+
.email-setup-email-wrap:focus-within {
|
|
587
|
+
border-color: var(--accent);
|
|
588
|
+
}
|
|
589
|
+
.email-setup-domain {
|
|
590
|
+
padding: 8px 10px 8px 0;
|
|
591
|
+
font-size: 14px;
|
|
592
|
+
color: var(--text-dimmer);
|
|
593
|
+
white-space: nowrap;
|
|
594
|
+
user-select: none;
|
|
595
|
+
pointer-events: none;
|
|
596
|
+
}
|
|
597
|
+
.email-setup-password-wrap {
|
|
598
|
+
position: relative;
|
|
599
|
+
}
|
|
600
|
+
.email-setup-password-wrap .email-setup-input {
|
|
601
|
+
padding-right: 36px;
|
|
602
|
+
}
|
|
603
|
+
.email-setup-password-eye {
|
|
604
|
+
position: absolute;
|
|
605
|
+
right: 6px;
|
|
606
|
+
top: 50%;
|
|
607
|
+
transform: translateY(-50%);
|
|
608
|
+
background: none;
|
|
609
|
+
border: none;
|
|
610
|
+
color: var(--text-dimmer);
|
|
611
|
+
cursor: pointer;
|
|
612
|
+
padding: 4px;
|
|
613
|
+
border-radius: 4px;
|
|
614
|
+
display: flex;
|
|
615
|
+
align-items: center;
|
|
616
|
+
justify-content: center;
|
|
617
|
+
}
|
|
618
|
+
.email-setup-password-eye:hover {
|
|
619
|
+
color: var(--text);
|
|
620
|
+
}
|
|
621
|
+
.email-setup-password-eye .lucide {
|
|
622
|
+
width: 15px;
|
|
623
|
+
height: 15px;
|
|
624
|
+
}
|
|
625
|
+
.email-setup-help {
|
|
626
|
+
font-size: 12px;
|
|
627
|
+
color: var(--accent);
|
|
628
|
+
display: inline-block;
|
|
629
|
+
margin-top: 4px;
|
|
630
|
+
}
|
|
631
|
+
.email-setup-help:hover {
|
|
632
|
+
text-decoration: underline;
|
|
633
|
+
}
|
|
634
|
+
.email-setup-status {
|
|
635
|
+
margin-bottom: 12px;
|
|
636
|
+
font-size: 13px;
|
|
637
|
+
display: none;
|
|
638
|
+
}
|
|
639
|
+
.email-setup-actions {
|
|
640
|
+
display: flex;
|
|
641
|
+
gap: 8px;
|
|
642
|
+
justify-content: flex-end;
|
|
643
|
+
}
|
|
644
|
+
.email-setup-btn {
|
|
645
|
+
padding: 8px 16px;
|
|
646
|
+
border-radius: 6px;
|
|
647
|
+
cursor: pointer;
|
|
648
|
+
font-size: 13px;
|
|
649
|
+
font-family: inherit;
|
|
650
|
+
}
|
|
651
|
+
.email-setup-btn-primary {
|
|
652
|
+
border: none;
|
|
653
|
+
background: var(--accent);
|
|
654
|
+
color: #fff;
|
|
655
|
+
font-weight: 600;
|
|
656
|
+
}
|
|
657
|
+
.email-setup-btn-primary:hover {
|
|
658
|
+
background: var(--accent-hover);
|
|
659
|
+
}
|
|
660
|
+
.email-setup-btn-secondary {
|
|
661
|
+
border: 1px solid var(--border);
|
|
662
|
+
background: var(--bg-alt);
|
|
663
|
+
color: var(--text);
|
|
664
|
+
}
|
|
665
|
+
.email-setup-btn-secondary:hover {
|
|
666
|
+
background: var(--input-bg);
|
|
667
|
+
}
|
|
668
|
+
.email-setup-btn-ghost {
|
|
669
|
+
border: 1px solid var(--border);
|
|
670
|
+
background: transparent;
|
|
671
|
+
color: var(--text-muted);
|
|
672
|
+
}
|
|
673
|
+
.email-setup-btn-ghost:hover {
|
|
674
|
+
color: var(--text);
|
|
675
|
+
background: rgba(var(--overlay-rgb), 0.05);
|
|
676
|
+
}
|
|
677
|
+
|
|
482
678
|
/* ==========================================================================
|
|
483
679
|
Input Area — Claude-style unified container
|
|
484
680
|
========================================================================== */
|
|
@@ -271,9 +271,53 @@
|
|
|
271
271
|
#sidebar-tools {
|
|
272
272
|
flex-shrink: 0;
|
|
273
273
|
border-bottom: 1px solid var(--border-subtle);
|
|
274
|
-
padding-top: 8px;
|
|
275
274
|
padding-bottom: 4px;
|
|
276
275
|
}
|
|
276
|
+
#sidebar-tools-toggle {
|
|
277
|
+
display: flex;
|
|
278
|
+
align-items: center;
|
|
279
|
+
justify-content: space-between;
|
|
280
|
+
width: 100%;
|
|
281
|
+
margin: 0;
|
|
282
|
+
padding: 8px 8px 4px 0;
|
|
283
|
+
box-sizing: border-box;
|
|
284
|
+
background: none;
|
|
285
|
+
border: none;
|
|
286
|
+
cursor: pointer;
|
|
287
|
+
font-size: 11px;
|
|
288
|
+
font-weight: 600;
|
|
289
|
+
color: var(--text-dimmer);
|
|
290
|
+
text-transform: uppercase;
|
|
291
|
+
letter-spacing: 0.5px;
|
|
292
|
+
font-family: inherit;
|
|
293
|
+
}
|
|
294
|
+
#sidebar-tools-toggle:hover {
|
|
295
|
+
color: var(--text-muted);
|
|
296
|
+
}
|
|
297
|
+
.sidebar-tools-chevron {
|
|
298
|
+
width: 14px;
|
|
299
|
+
height: 14px;
|
|
300
|
+
transition: transform 0.15s;
|
|
301
|
+
}
|
|
302
|
+
#sidebar-tools #session-actions {
|
|
303
|
+
max-height: 300px;
|
|
304
|
+
overflow: hidden;
|
|
305
|
+
transition: max-height 0.2s ease, opacity 0.2s ease;
|
|
306
|
+
opacity: 1;
|
|
307
|
+
}
|
|
308
|
+
#sidebar-tools.collapsed .sidebar-tools-chevron {
|
|
309
|
+
transform: rotate(-90deg);
|
|
310
|
+
}
|
|
311
|
+
#sidebar-tools.collapsed #session-actions {
|
|
312
|
+
max-height: 0;
|
|
313
|
+
opacity: 0;
|
|
314
|
+
padding-bottom: 0;
|
|
315
|
+
}
|
|
316
|
+
.sidebar-tools-divider {
|
|
317
|
+
height: 1px;
|
|
318
|
+
background: var(--border-subtle);
|
|
319
|
+
margin: 4px 12px;
|
|
320
|
+
}
|
|
277
321
|
|
|
278
322
|
/* --- Sessions header (pinned above scroll) --- */
|
|
279
323
|
#sidebar-sessions-header {
|
|
@@ -1332,8 +1376,39 @@
|
|
|
1332
1376
|
display: none;
|
|
1333
1377
|
}
|
|
1334
1378
|
|
|
1379
|
+
/* Mate sidebar resize handle (same style) */
|
|
1380
|
+
#mate-sidebar-resize-handle {
|
|
1381
|
+
position: absolute;
|
|
1382
|
+
top: 0;
|
|
1383
|
+
bottom: 0;
|
|
1384
|
+
width: 8px;
|
|
1385
|
+
margin-left: -4px;
|
|
1386
|
+
cursor: col-resize;
|
|
1387
|
+
z-index: 10;
|
|
1388
|
+
}
|
|
1389
|
+
#mate-sidebar-resize-handle::before {
|
|
1390
|
+
content: "";
|
|
1391
|
+
position: absolute;
|
|
1392
|
+
top: 0;
|
|
1393
|
+
bottom: 0;
|
|
1394
|
+
left: 50%;
|
|
1395
|
+
width: 2px;
|
|
1396
|
+
margin-left: -1px;
|
|
1397
|
+
background: var(--accent);
|
|
1398
|
+
opacity: 0;
|
|
1399
|
+
transition: opacity 0.2s;
|
|
1400
|
+
}
|
|
1401
|
+
#mate-sidebar-resize-handle:hover::before,
|
|
1402
|
+
#mate-sidebar-resize-handle.dragging::before {
|
|
1403
|
+
opacity: 1;
|
|
1404
|
+
}
|
|
1405
|
+
#mate-sidebar-resize-handle.hidden {
|
|
1406
|
+
display: none;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1335
1409
|
@media (max-width: 768px) {
|
|
1336
|
-
#sidebar-resize-handle
|
|
1410
|
+
#sidebar-resize-handle,
|
|
1411
|
+
#mate-sidebar-resize-handle {
|
|
1337
1412
|
display: none;
|
|
1338
1413
|
}
|
|
1339
1414
|
|