clay-server 5.2.0-beta.9 → 5.2.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/README.md +0 -4
- package/lib/clay-product-control-tools.js +1 -0
- package/lib/clay-product-control.js +14 -11
- package/lib/clay-vendor-usage.js +44 -0
- package/lib/github-star-count.js +147 -0
- package/lib/notes-checklist.js +43 -1
- package/lib/notes.js +2 -1
- package/lib/project-session-notes.js +33 -8
- package/lib/project-sessions.js +63 -24
- package/lib/project-start-protocol.js +29 -0
- package/lib/project-vendor-login.js +2 -0
- package/lib/project.js +5 -1
- package/lib/public/app.js +27 -18
- package/lib/public/css/contextual-clay.css +1 -1
- package/lib/public/css/filebrowser.css +1 -1
- package/lib/public/css/mate-loading-scene.css +21 -0
- package/lib/public/css/overlays.css +64 -256
- package/lib/public/css/project-mate-creation.css +5 -6
- package/lib/public/css/project-start.css +108 -0
- package/lib/public/css/projects-hub.css +53 -14
- package/lib/public/css/settings-shell.css +103 -0
- package/lib/public/css/sidebar.css +7 -0
- package/lib/public/css/title-bar.css +83 -0
- package/lib/public/index.html +50 -63
- package/lib/public/modules/account-transport-settings.js +8 -2
- package/lib/public/modules/admin-settings-email.js +7 -2
- package/lib/public/modules/admin-settings-invitations.js +2 -2
- package/lib/public/modules/admin-settings-projects.js +2 -2
- package/lib/public/modules/admin-settings-ui.js +20 -4
- package/lib/public/modules/admin-settings-users.js +4 -4
- package/lib/public/modules/app-home-hub.js +2 -1
- package/lib/public/modules/app-messages.js +10 -2
- package/lib/public/modules/app-projects.js +1 -407
- package/lib/public/modules/app-rate-limit.js +12 -1
- package/lib/public/modules/clay-tool-presentation.js +1 -0
- package/lib/public/modules/contextual-clay.js +3 -1
- package/lib/public/modules/github-star.js +66 -0
- package/lib/public/modules/home-surface-boot.js +0 -1
- package/lib/public/modules/mate-loading-scene.js +17 -0
- package/lib/public/modules/pane-appearance-bridge.js +59 -0
- package/lib/public/modules/profile.js +11 -3
- package/lib/public/modules/project-mate-creation-workspace.js +13 -4
- package/lib/public/modules/project-session-visibility-settings.js +19 -16
- package/lib/public/modules/project-settings-environment.js +12 -1
- package/lib/public/modules/project-settings.js +119 -129
- package/lib/public/modules/project-start-dialog.js +130 -0
- package/lib/public/modules/project-start-folder-state.js +78 -0
- package/lib/public/modules/project-start-folder-view.js +190 -0
- package/lib/public/modules/project-start-forms.js +66 -0
- package/lib/public/modules/project-start-path.js +60 -0
- package/lib/public/modules/project-start-state.js +54 -0
- package/lib/public/modules/project-start-submit.js +67 -0
- package/lib/public/modules/projects-hub-view.js +32 -44
- package/lib/public/modules/projects-hub.js +39 -28
- package/lib/public/modules/server-settings.js +36 -91
- package/lib/public/modules/settings-project-target.js +56 -0
- package/lib/public/modules/settings-select.js +1 -1
- package/lib/public/modules/settings-shell-registry.js +88 -0
- package/lib/public/modules/settings-shell-view.js +104 -0
- package/lib/public/modules/settings-shell.js +342 -0
- package/lib/public/modules/sidebar-mobile.js +8 -30
- package/lib/public/modules/sidebar-projects.js +2 -1
- package/lib/public/modules/theme.js +31 -3
- package/lib/public/modules/user-settings-integrations.js +2 -1
- package/lib/public/modules/user-settings-layout.js +12 -34
- package/lib/public/modules/user-settings-profile.js +1 -1
- package/lib/public/modules/user-settings.js +18 -85
- package/lib/public/modules/vendor-usage-format.js +93 -0
- package/lib/public/modules/vendor-usage-list.js +45 -0
- package/lib/public/modules/vendor-usage-model.js +215 -0
- package/lib/public/modules/vendor-usage-overview.js +323 -0
- package/lib/public/style.css +10 -7
- package/lib/public/welcome-art/conversation-desk.png +0 -0
- package/lib/public/welcome-art/mate-clay.png +0 -0
- package/lib/public/welcome-art/project-clay.png +0 -0
- package/lib/sdk-bridge.js +6 -1
- package/lib/sdk-message-processor.js +9 -1
- package/lib/sdk-quota-snapshot.js +20 -2
- package/lib/server-github-stars.js +39 -0
- package/lib/server-global-ws.js +21 -17
- package/lib/server.js +11 -0
- package/lib/session-notes-mcp-server.js +26 -4
- package/lib/session-notes-writes.js +88 -0
- package/lib/session-visibility.js +20 -8
- package/lib/sessions.js +12 -2
- package/lib/vendor-usage-acp-readers.js +97 -0
- package/lib/vendor-usage-capabilities.js +88 -0
- package/lib/vendor-usage-http-readers.js +214 -0
- package/lib/vendor-usage-metrics.js +47 -0
- package/lib/vendor-usage-native-readers.js +106 -0
- package/lib/vendor-usage-overview.js +406 -0
- package/lib/vendor-usage-service.js +281 -0
- package/lib/ws-schema.js +4 -2
- package/lib/yoke/adapters/claude.js +12 -0
- package/lib/yoke/adapters/codex-query-contract.js +1 -0
- package/lib/yoke/adapters/codex.js +45 -12
- package/lib/yoke/claude-hook-installer.js +1 -0
- package/lib/yoke/codex-dynamic-tool-names.js +80 -0
- package/lib/yoke/codex-model-catalog.js +37 -3
- package/lib/yoke/muse-services.js +16 -3
- package/lib/yoke/providers/claude-model-descriptions.js +22 -2
- package/lib/yoke/vendor-registry.js +6 -2
- package/package.json +2 -1
- package/lib/public/modules/server-settings-navigation.js +0 -39
package/lib/project-sessions.js
CHANGED
|
@@ -5,12 +5,16 @@ var { execFileSync } = require("child_process");
|
|
|
5
5
|
var providerSettings = require("./yoke/settings");
|
|
6
6
|
var updateSnooze = require("./update-snooze");
|
|
7
7
|
var yoke = require("./yoke");
|
|
8
|
+
var startProtocol = require("./project-start-protocol");
|
|
9
|
+
var startReply = startProtocol.withRequestId;
|
|
10
|
+
var browseMeta = startProtocol.browseMeta;
|
|
8
11
|
var sessionVisibility = require("./session-visibility");
|
|
9
12
|
var contextUsageModule = require("./context-usage");
|
|
10
13
|
var sessionDeleteModule = require("./project-session-delete");
|
|
11
14
|
var sessionFoldersModule = require("./project-session-folders");
|
|
12
15
|
var elicitationResponse = require("./project-elicitation-response");
|
|
13
16
|
var sessionCreationModule = require("./project-session-creation");
|
|
17
|
+
var vendorUsageOverviewModule = require("./vendor-usage-overview");
|
|
14
18
|
|
|
15
19
|
function vendorSupportsTui(vendor) {
|
|
16
20
|
var info = yoke.getVendorInfo(vendor);
|
|
@@ -223,6 +227,10 @@ function attachSessions(ctx) {
|
|
|
223
227
|
resolveSessionHome: resolveSessionHome, cancelPendingAskUser: cancelPendingAskUser,
|
|
224
228
|
}));
|
|
225
229
|
|
|
230
|
+
function boundedRequestId(msg) {
|
|
231
|
+
return typeof msg.requestId === "string" ? msg.requestId.substring(0, 200) : undefined;
|
|
232
|
+
}
|
|
233
|
+
|
|
226
234
|
function canAccessProjectSlug(ws, targetSlug) {
|
|
227
235
|
if (!targetSlug) return false;
|
|
228
236
|
if (!usersModule || typeof usersModule.isMultiUser !== "function" || !usersModule.isMultiUser()) return true;
|
|
@@ -361,6 +369,11 @@ function attachSessions(ctx) {
|
|
|
361
369
|
getProjectAccess: getProjectAccess,
|
|
362
370
|
getVendorAvailability: function (ws) { return ctx.getVendorAvailability(ws); },
|
|
363
371
|
});
|
|
372
|
+
var vendorUsage = vendorUsageOverviewModule.attachVendorUsageOverview({
|
|
373
|
+
slug: slug, sm: sm, usersModule: usersModule, clients: clients, sendTo: sendTo, getProjectAccess: getProjectAccess,
|
|
374
|
+
getVendorAvailability: function (ws) { return ctx.getVendorAvailability(ws); },
|
|
375
|
+
adapters: ctx.adapters, osUsers: osUsers, getLinuxUserForWs: ctx.getLinuxUserForWs,
|
|
376
|
+
});
|
|
364
377
|
// Kick off watchers for any TUI sessions already loaded from disk so
|
|
365
378
|
// their titles refresh as soon as Claude Code rewrites the jsonl, even
|
|
366
379
|
// before the user clicks them.
|
|
@@ -755,13 +768,15 @@ function attachSessions(ctx) {
|
|
|
755
768
|
if (msg.type === "set_project_session_visibility_default") {
|
|
756
769
|
sessionVisibility.handleDefaultChange({
|
|
757
770
|
slug: slug, isMate: isMate, osUsers: osUsers, usersModule: usersModule, getProjectAccess: getProjectAccess,
|
|
758
|
-
|
|
771
|
+
getTargetAccess: typeof opts.onGetProjectAccess === "function" ? opts.onGetProjectAccess : null,
|
|
772
|
+
canAccessProjectSlug: canAccessProjectSlug, opts: opts, sendTo: sendTo,
|
|
759
773
|
}, ws, msg);
|
|
760
774
|
return true;
|
|
761
775
|
}
|
|
762
776
|
|
|
763
777
|
if (sessionFolders.handleMessage(ws, msg)) return true;
|
|
764
778
|
if (sessionCreation.handleMessage(ws, msg)) return true;
|
|
779
|
+
if (vendorUsage.handleMessage(ws, msg)) return true;
|
|
765
780
|
|
|
766
781
|
if (msg.type === "bulk_delete_sessions") {
|
|
767
782
|
sessionDelete.bulkDeleteSessions(ws, msg);
|
|
@@ -1656,8 +1671,9 @@ function attachSessions(ctx) {
|
|
|
1656
1671
|
parentDir = path.dirname(absTarget);
|
|
1657
1672
|
prefix = path.basename(absTarget).toLowerCase();
|
|
1658
1673
|
}
|
|
1659
|
-
|
|
1660
|
-
|
|
1674
|
+
var canList = function (candidate) { return !opts.canUsePath || opts.canUsePath(ws._clayUser && ws._clayUser.id, candidate); };
|
|
1675
|
+
if (!canList(parentDir)) {
|
|
1676
|
+
sendTo(ws, startReply(msg, { type: "browse_dir_result", path: msg.path, entries: [], error: "Directory access is not permitted" }));
|
|
1661
1677
|
return true;
|
|
1662
1678
|
}
|
|
1663
1679
|
try {
|
|
@@ -1673,9 +1689,9 @@ function attachSessions(ctx) {
|
|
|
1673
1689
|
dirEntries.push({ name: d.name, path: path.join(parentDir, d.name) });
|
|
1674
1690
|
}
|
|
1675
1691
|
dirEntries.sort(function (a, b) { return a.name.localeCompare(b.name); });
|
|
1676
|
-
sendTo(ws, { type: "browse_dir_result", path: msg.path, entries: dirEntries });
|
|
1692
|
+
sendTo(ws, Object.assign(browseMeta(msg, parentDir, prefix, canList), { type: "browse_dir_result", path: msg.path, entries: dirEntries }));
|
|
1677
1693
|
} catch (e) {
|
|
1678
|
-
sendTo(ws, { type: "browse_dir_result", path: msg.path, entries: [], error: e.message });
|
|
1694
|
+
sendTo(ws, startReply(msg, { type: "browse_dir_result", path: msg.path, entries: [], error: e.message }));
|
|
1679
1695
|
}
|
|
1680
1696
|
return true;
|
|
1681
1697
|
}
|
|
@@ -1685,24 +1701,24 @@ function attachSessions(ctx) {
|
|
|
1685
1701
|
var addPath = (msg.path || "").replace(/^~/, require("./config").REAL_HOME);
|
|
1686
1702
|
var addAbs = path.resolve(addPath);
|
|
1687
1703
|
if (opts.canUsePath && !opts.canUsePath(ws._clayUser && ws._clayUser.id, addAbs)) {
|
|
1688
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Directory access is not permitted" });
|
|
1704
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Directory access is not permitted" }));
|
|
1689
1705
|
return true;
|
|
1690
1706
|
}
|
|
1691
1707
|
try {
|
|
1692
1708
|
var addStat = fs.statSync(addAbs);
|
|
1693
1709
|
if (!addStat.isDirectory()) {
|
|
1694
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Not a directory" });
|
|
1710
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Not a directory" }));
|
|
1695
1711
|
return true;
|
|
1696
1712
|
}
|
|
1697
1713
|
} catch (e) {
|
|
1698
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Directory not found" });
|
|
1714
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Directory not found" }));
|
|
1699
1715
|
return true;
|
|
1700
1716
|
}
|
|
1701
1717
|
if (typeof opts.onAddProject === "function") {
|
|
1702
1718
|
var result = opts.onAddProject(addAbs, ws._clayUser);
|
|
1703
|
-
sendTo(ws, Object.assign({}, result, { type: "add_project_result" }));
|
|
1719
|
+
sendTo(ws, startReply(msg, Object.assign({}, result, { type: "add_project_result" })));
|
|
1704
1720
|
} else {
|
|
1705
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
|
|
1721
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Not supported" }));
|
|
1706
1722
|
}
|
|
1707
1723
|
return true;
|
|
1708
1724
|
}
|
|
@@ -1712,7 +1728,7 @@ function attachSessions(ctx) {
|
|
|
1712
1728
|
if (ws._clayUser) {
|
|
1713
1729
|
var cpPerms = usersModule.getEffectivePermissions(ws._clayUser, osUsers);
|
|
1714
1730
|
if (!cpPerms.createProject) {
|
|
1715
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "You do not have permission to create projects" });
|
|
1731
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "You do not have permission to create projects" }));
|
|
1716
1732
|
return true;
|
|
1717
1733
|
}
|
|
1718
1734
|
}
|
|
@@ -1720,14 +1736,14 @@ function attachSessions(ctx) {
|
|
|
1720
1736
|
if (msg.type === "create_project") {
|
|
1721
1737
|
var createName = (msg.name || "").trim();
|
|
1722
1738
|
if (!createName || !/^[a-zA-Z0-9_-]+$/.test(createName)) {
|
|
1723
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Invalid name. Use only letters, numbers, dashes, and underscores." });
|
|
1739
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Invalid name. Use only letters, numbers, dashes, and underscores." }));
|
|
1724
1740
|
return true;
|
|
1725
1741
|
}
|
|
1726
1742
|
if (typeof opts.onCreateProject === "function") {
|
|
1727
1743
|
var createResult = opts.onCreateProject(createName, ws._clayUser);
|
|
1728
|
-
sendTo(ws, Object.assign({}, createResult, { type: "add_project_result" }));
|
|
1744
|
+
sendTo(ws, startReply(msg, Object.assign({}, createResult, { type: "add_project_result" })));
|
|
1729
1745
|
} else {
|
|
1730
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
|
|
1746
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Not supported" }));
|
|
1731
1747
|
}
|
|
1732
1748
|
return true;
|
|
1733
1749
|
}
|
|
@@ -1736,16 +1752,16 @@ function attachSessions(ctx) {
|
|
|
1736
1752
|
if (msg.type === "clone_project") {
|
|
1737
1753
|
var cloneUrl = (msg.url || "").trim();
|
|
1738
1754
|
if (!cloneUrl || (!/^https?:\/\//.test(cloneUrl) && !/^git@/.test(cloneUrl))) {
|
|
1739
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Invalid URL. Use https:// or git@ format." });
|
|
1755
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Invalid URL. Use https:// or git@ format." }));
|
|
1740
1756
|
return true;
|
|
1741
1757
|
}
|
|
1742
|
-
sendTo(ws, { type: "clone_project_progress", status: "cloning" });
|
|
1758
|
+
sendTo(ws, startReply(msg, { type: "clone_project_progress", status: "cloning" }));
|
|
1743
1759
|
if (typeof opts.onCloneProject === "function") {
|
|
1744
1760
|
opts.onCloneProject(cloneUrl, ws._clayUser, function (cloneResult) {
|
|
1745
|
-
sendTo(ws, { type: "add_project_result", ok: cloneResult.ok, slug: cloneResult.slug, error: cloneResult.error });
|
|
1761
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: cloneResult.ok, slug: cloneResult.slug, error: cloneResult.error }));
|
|
1746
1762
|
});
|
|
1747
1763
|
} else {
|
|
1748
|
-
sendTo(ws, { type: "add_project_result", ok: false, error: "Not supported" });
|
|
1764
|
+
sendTo(ws, startReply(msg, { type: "add_project_result", ok: false, error: "Not supported" }));
|
|
1749
1765
|
}
|
|
1750
1766
|
return true;
|
|
1751
1767
|
}
|
|
@@ -1858,30 +1874,41 @@ function attachSessions(ctx) {
|
|
|
1858
1874
|
|
|
1859
1875
|
// --- Set project title (rename) ---
|
|
1860
1876
|
if (msg.type === "set_project_title") {
|
|
1877
|
+
var titleRequestId = boundedRequestId(msg);
|
|
1861
1878
|
if (!msg.slug) {
|
|
1862
|
-
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Missing slug" });
|
|
1879
|
+
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Missing slug", requestId: titleRequestId });
|
|
1880
|
+
return true;
|
|
1881
|
+
}
|
|
1882
|
+
// The target is named by the client; it must be a project this account can access.
|
|
1883
|
+
if (!canAccessProjectSlug(ws, msg.slug)) {
|
|
1884
|
+
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Project access is not permitted", slug: msg.slug, requestId: titleRequestId });
|
|
1863
1885
|
return true;
|
|
1864
1886
|
}
|
|
1865
1887
|
if (typeof opts.onSetProjectTitle === "function") {
|
|
1866
1888
|
var titleResult = opts.onSetProjectTitle(msg.slug, msg.title || null);
|
|
1867
|
-
sendTo(ws, Object.assign({}, titleResult, { type: "set_project_title_result", slug: msg.slug }));
|
|
1889
|
+
sendTo(ws, Object.assign({}, titleResult, { type: "set_project_title_result", slug: msg.slug, requestId: titleRequestId }));
|
|
1868
1890
|
} else {
|
|
1869
|
-
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Not supported" });
|
|
1891
|
+
sendTo(ws, { type: "set_project_title_result", ok: false, error: "Not supported", requestId: titleRequestId });
|
|
1870
1892
|
}
|
|
1871
1893
|
return true;
|
|
1872
1894
|
}
|
|
1873
1895
|
|
|
1874
1896
|
// --- Set project icon (emoji) ---
|
|
1875
1897
|
if (msg.type === "set_project_icon") {
|
|
1898
|
+
var iconRequestId = boundedRequestId(msg);
|
|
1876
1899
|
if (!msg.slug) {
|
|
1877
|
-
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Missing slug" });
|
|
1900
|
+
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Missing slug", requestId: iconRequestId });
|
|
1901
|
+
return true;
|
|
1902
|
+
}
|
|
1903
|
+
if (!canAccessProjectSlug(ws, msg.slug)) {
|
|
1904
|
+
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Project access is not permitted", slug: msg.slug, requestId: iconRequestId });
|
|
1878
1905
|
return true;
|
|
1879
1906
|
}
|
|
1880
1907
|
if (typeof opts.onSetProjectIcon === "function") {
|
|
1881
1908
|
var iconResult = opts.onSetProjectIcon(msg.slug, msg.icon || null);
|
|
1882
|
-
sendTo(ws, { type: "set_project_icon_result", ok: iconResult.ok, slug: msg.slug, error: iconResult.error });
|
|
1909
|
+
sendTo(ws, { type: "set_project_icon_result", ok: iconResult.ok, slug: msg.slug, error: iconResult.error, requestId: iconRequestId });
|
|
1883
1910
|
} else {
|
|
1884
|
-
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Not supported" });
|
|
1911
|
+
sendTo(ws, { type: "set_project_icon_result", ok: false, error: "Not supported", requestId: iconRequestId });
|
|
1885
1912
|
}
|
|
1886
1913
|
return true;
|
|
1887
1914
|
}
|
|
@@ -2007,6 +2034,18 @@ function attachSessions(ctx) {
|
|
|
2007
2034
|
}
|
|
2008
2035
|
|
|
2009
2036
|
return {
|
|
2037
|
+
invalidateVendorUsage: function () { vendorUsage.invalidateAll(); },
|
|
2038
|
+
// Canonical read-only inspection: the caller has already proven the owner and
|
|
2039
|
+
// project access; the OS user is re-derived from the live user record.
|
|
2040
|
+
readVendorUsage: function (request) {
|
|
2041
|
+
var installed = null;
|
|
2042
|
+
if (Array.isArray(sm.installedVendors)) {
|
|
2043
|
+
installed = Object.create(null);
|
|
2044
|
+
sm.installedVendors.forEach(function (vendor) { installed[vendor] = true; });
|
|
2045
|
+
}
|
|
2046
|
+
var linuxUser = osUsers && request.owner !== "default" ? ctx.getLinuxUserForSession({ ownerId: request.owner }) : null;
|
|
2047
|
+
return vendorUsage.readForOwner({ owner: request.owner, linuxUser: linuxUser, installed: installed, isCurrent: request.isCurrent });
|
|
2048
|
+
},
|
|
2010
2049
|
handleSessionsMessage: handleSessionsMessage,
|
|
2011
2050
|
resolveSessionForView: resolveSessionForView,
|
|
2012
2051
|
sendSessionFoldersState: sessionFolders.sendStateTo,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Shared reply helpers for the project-start dialog (browse_dir and add/create/clone results).
|
|
2
|
+
// A string requestId on the request is echoed on its reply so the client can drop stale answers.
|
|
3
|
+
|
|
4
|
+
var path = require("path");
|
|
5
|
+
|
|
6
|
+
function requestIdOf(msg) {
|
|
7
|
+
return msg && typeof msg.requestId === "string" && msg.requestId.length <= 64 ? msg.requestId : undefined;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Canonical listing metadata. `dir` is the directory whose children are listed, `prefix` is
|
|
11
|
+
// non-empty when the requested path did not exist or was not a directory, and `parent` is set
|
|
12
|
+
// only when the caller may list the parent as well.
|
|
13
|
+
function browseMeta(msg, dir, prefix, canList) {
|
|
14
|
+
var parent = path.dirname(dir);
|
|
15
|
+
return {
|
|
16
|
+
requestId: requestIdOf(msg),
|
|
17
|
+
dir: dir,
|
|
18
|
+
prefix: prefix || "",
|
|
19
|
+
parent: parent !== dir && (!canList || canList(parent)) ? parent : null,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function withRequestId(msg, payload) {
|
|
24
|
+
var id = requestIdOf(msg);
|
|
25
|
+
if (id !== undefined) payload.requestId = id;
|
|
26
|
+
return payload;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = { requestIdOf: requestIdOf, browseMeta: browseMeta, withRequestId: withRequestId };
|
|
@@ -171,6 +171,8 @@ function attachVendorLogin(ctx) {
|
|
|
171
171
|
// reused by every project, so tearing one down here would kill unrelated
|
|
172
172
|
// sessions; those runtimes pick up new credentials on their own.
|
|
173
173
|
function refreshVendorAuth(vendor, linuxUser) {
|
|
174
|
+
// Cached account usage described the previous credentials.
|
|
175
|
+
if (typeof ctx.onVendorAuthChanged === "function") { try { ctx.onVendorAuthChanged(vendor, linuxUser || null); } catch (e) {} }
|
|
174
176
|
var adapter = adapters[vendor];
|
|
175
177
|
if (!adapter || typeof adapter.shutdown !== "function") return Promise.resolve(false);
|
|
176
178
|
if (adapter.shared) {
|
package/lib/project.js
CHANGED
|
@@ -658,7 +658,8 @@ function createProjectContext(opts) {
|
|
|
658
658
|
var access = opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
659
659
|
if (!viewer || (opts.canAccessProjectSlug && !opts.canAccessProjectSlug(viewer.id, slug)) || !usersModule.canAccessSession(viewer.id, session, access)) return;
|
|
660
660
|
}
|
|
661
|
-
ws.
|
|
661
|
+
var panePayload = ws._clayPaneActivation ? require('./pane-session-transport').outbound(ws, message, session.localId) : message;
|
|
662
|
+
if (panePayload) ws.send(panePayload === message ? data : JSON.stringify(panePayload));
|
|
662
663
|
});
|
|
663
664
|
},
|
|
664
665
|
authorize: function (session, actor) {
|
|
@@ -2186,6 +2187,7 @@ function createProjectContext(opts) {
|
|
|
2186
2187
|
resolveDefaultAi: opts.resolveDefaultAi,
|
|
2187
2188
|
resolveMateSessionDefaults: opts.resolveMateSessionDefaults,
|
|
2188
2189
|
getVendorAvailability: function (ws) { return _models.getVendorAvailability(ws); },
|
|
2190
|
+
getLinuxUserForWs: getLinuxUserForWs,
|
|
2189
2191
|
canCreateScheduledTaskInterview: function (ws, session) { return !!(_scheduledTasks && _scheduledTasks.canCreateInterview(ws, session)); },
|
|
2190
2192
|
canStartScheduledTaskInterview: function (ws, session) { return !!(_scheduledTasks && _scheduledTasks.canStartInterview(ws, session)); },
|
|
2191
2193
|
onHumanPairStop: function (session) {
|
|
@@ -2398,6 +2400,7 @@ function createProjectContext(opts) {
|
|
|
2398
2400
|
|
|
2399
2401
|
// --- Vendor login flow (delegated to project-vendor-login.js) ---
|
|
2400
2402
|
var _vendorLogin = attachVendorLogin({
|
|
2403
|
+
onVendorAuthChanged: function () { _sessions.invalidateVendorUsage(); },
|
|
2401
2404
|
requestAccess: _requestAccess,
|
|
2402
2405
|
clients: clients,
|
|
2403
2406
|
slug: slug,
|
|
@@ -3039,6 +3042,7 @@ function createProjectContext(opts) {
|
|
|
3039
3042
|
requestProductControlReview: _productControl.requestProductControlReview,
|
|
3040
3043
|
applyProductSessionAction: _productControl.applyProductSessionAction,
|
|
3041
3044
|
inspectProductSessionQueue: _productControl.inspectProductSessionQueue,
|
|
3045
|
+
readVendorUsage: function (request) { return _sessions.readVendorUsage(request); },
|
|
3042
3046
|
inspectProductSessionRuntime: _sessions.sessionRuntimeActions.inspect,
|
|
3043
3047
|
inspectMateLifecycleRuntime: _sessions.sessionRuntimeActions.inspectLifecycle,
|
|
3044
3048
|
inspectDelegatedFollowUp: _delegatedFollowUp.inspectDelegatedFollowUp,
|
package/lib/public/app.js
CHANGED
|
@@ -31,7 +31,7 @@ import { initMateMemory, renderMemoryList, hideMemory } from './modules/mate-mem
|
|
|
31
31
|
import { initRewind, setRewindMode, showRewindModal, clearPendingRewindUuid, addRewindButton, onRewindComplete, onRewindError } from './modules/rewind.js';
|
|
32
32
|
import { initNotifications, showDoneNotification, playDoneSound, isNotifAlertEnabled, isNotifSoundEnabled } from './modules/notifications.js';
|
|
33
33
|
import { initInput, clearPendingImages, handleInputSync, autoResize, builtinCommands, sendMessage, hasSendableContent, setScheduleBtnDisabled, setScheduleDelayMs, clearScheduleDelay } from './modules/input.js';
|
|
34
|
-
import { initQrCode
|
|
34
|
+
import { initQrCode } from './modules/qrcode.js';
|
|
35
35
|
import { initFileBrowser, loadRootDirectory, reopenFileViewer, refreshTree, handleFsList, handleFsRead, handleDirChanged, refreshIfOpen, handleFileChanged, handleFileHistory, handleGitDiff, handleFileAt, getPendingNavigate, closeFileViewer, resetFileBrowser } from './modules/filebrowser.js';
|
|
36
36
|
import { initGitPanel } from './modules/git-panel.js';
|
|
37
37
|
import { initWorkerPaneLock } from './modules/worker-pane-lock.js';
|
|
@@ -46,6 +46,7 @@ import { initTheme, getThemeColor, getComputedVar, onThemeChange, getCurrentThem
|
|
|
46
46
|
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';
|
|
47
47
|
import { initServerSettings, updateSettingsStats, updateDaemonConfig, handleSetPinResult, handleKeepAwakeChanged, handleAutoContinueChanged, handleRestartResult, handleShutdownResult, handleSharedEnv, handleSharedEnvSaved } from './modules/server-settings.js';
|
|
48
48
|
import { initProjectSettings } from './modules/project-settings.js';
|
|
49
|
+
import { initSettingsShell, openSettings } from './modules/settings-shell.js';
|
|
49
50
|
import { initSkills, handleSkillInstalled, handleSkillUninstalled } from './modules/skills.js';
|
|
50
51
|
import { initMcp } from './modules/mcp-ui.js';
|
|
51
52
|
import { initScheduler, resetScheduler, handleLoopRegistryUpdated, handleScheduleRunStarted, handleScheduleRunFinished, handleLoopScheduled, openSchedulerToTab, isSchedulerOpen, closeScheduler, enterCraftingMode, exitCraftingMode, handleLoopRegistryFiles, getUpcomingSchedules } from './modules/scheduler.js';
|
|
@@ -63,6 +64,7 @@ import { initProjectLogs, closeProjectLogs } from './modules/project-logs.js';
|
|
|
63
64
|
import { initProjectSwitcher } from './modules/project-switcher.js';
|
|
64
65
|
import { initSplitView } from './modules/split-view.js';
|
|
65
66
|
import { initPaneBridge } from './modules/pane-bridge.js';
|
|
67
|
+
import { initPaneAppearanceBridge } from './modules/pane-appearance-bridge.js';
|
|
66
68
|
import { initAdmin, checkAdminAccess } from './modules/admin.js';
|
|
67
69
|
import { initSessionSearch, toggleSearch, closeSearch, isSearchOpen, handleFindInSessionResults, onHistoryPrepended as onSessionSearchHistoryPrepended } from './modules/session-search.js';
|
|
68
70
|
import { initTooltips, registerTooltip } from './modules/tooltip.js';
|
|
@@ -72,10 +74,15 @@ import { initShellCommand } from './modules/shell-command.js';
|
|
|
72
74
|
import { initConnection, connect as _connConnect, setStatus as _connSetStatus, scheduleReconnect as _connScheduleReconnect, cancelReconnect as _connCancelReconnect } from './modules/app-connection.js';
|
|
73
75
|
import { processMessage as _msgProcessMessage } from './modules/app-messages.js';
|
|
74
76
|
import { getWs as _getWsRef, setWs as _setWsRef } from './modules/ws-ref.js';
|
|
77
|
+
import { initialProjectStart } from './modules/project-start-state.js';
|
|
78
|
+
import { emptyFolderState } from './modules/project-start-folder-state.js';
|
|
79
|
+
import { openAddProjectModal, initProjectStart } from './modules/project-start-dialog.js';
|
|
75
80
|
import { initProjectsHub, showProjectsHub, hideProjectsHub } from './modules/projects-hub.js';
|
|
76
81
|
import { initHomeSurfaceBoot } from './modules/home-surface-boot.js';
|
|
77
82
|
import { rememberHomePrimarySurface } from './modules/home-surface.js';
|
|
78
83
|
import { initRateLimit, handleRateLimitEvent as _rlHandleRateLimitEvent, updateRateLimitUsage as _rlUpdateRateLimitUsage, handleFastModeState as _rlHandleFastModeState, resetRateLimitState } from './modules/app-rate-limit.js';
|
|
84
|
+
import { initVendorUsageOverview } from './modules/vendor-usage-overview.js';
|
|
85
|
+
import { initGithubStar } from './modules/github-star.js';
|
|
79
86
|
import { initCursors, handleRemoteCursorMove as _curHandleRemoteCursorMove, handleRemoteCursorLeave as _curHandleRemoteCursorLeave, handleRemoteSelection as _curHandleRemoteSelection, clearRemoteCursors as _curClearRemoteCursors, initCursorToggle } from './modules/app-cursors.js';
|
|
80
87
|
import { initDefaultAi } from './modules/default-ai.js';
|
|
81
88
|
import { requestDefaultVendor } from './modules/default-vendor.js';
|
|
@@ -97,7 +104,7 @@ import { initProjectMateCreationWorkspace } from './modules/project-mate-creatio
|
|
|
97
104
|
import { initProjectDebatePlanningWorkspace } from './modules/project-debate-planning-workspace.js';
|
|
98
105
|
import { initProjectSessionNavigation } from './modules/project-session-navigation.js';
|
|
99
106
|
import { initPanels, updateConfigChip as _panUpdateConfigChip, getModelEffortLevels as _panGetModelEffortLevels, accumulateUsage as _panAccumulateUsage, updateUsagePanel as _panUpdateUsagePanel, resetUsage as _panResetUsage, toggleUsagePanel as _panToggleUsagePanel, formatTokens as _panFormatTokens, updateStatusPanel as _panUpdateStatusPanel, requestProcessStats as _panRequestProcessStats, toggleStatusPanel as _panToggleStatusPanel, accumulateContext as _panAccumulateContext, updateContextPanel as _panUpdateContextPanel, resetContext as _panResetContext, resetContextData as _panResetContextData, minimizeContext as _panMinimizeContext, expandContext as _panExpandContext, toggleContextPanel as _panToggleContextPanel, getContextView as _panGetContextView, renderCtxPopover as _panRenderCtxPopover, hideCtxPopover as _panHideCtxPopover, formatBytes as _panFormatBytes, formatUptime as _panFormatUptime, getModelSupportsEffort as _panGetModelSupportsEffort, getSessionUsage, setSessionUsage, getContextData, setContextData, setContextView as _panSetContextView, applyContextView as _panApplyContextView } from './modules/app-panels.js';
|
|
100
|
-
import {
|
|
107
|
+
import { updateProjectList as _projUpdateProjectList, renderProjectList as _projRenderProjectList, renderTopbarPresence as _projRenderTopbarPresence, switchProject as _projSwitchProject, resetClientState as _projResetClientState, confirmRemoveProject as _projConfirmRemoveProject, handleRemoveProjectCheckResult as _projHandleRemoveProjectCheckResult, handleRemoveProjectResult as _projHandleRemoveProjectResult, showUpdateAvailable as _projShowUpdateAvailable, getCachedProjects, setCachedProjects, getCachedProjectCount, getCachedRemovedProjects, setCachedRemovedProjects } from './modules/app-projects.js';
|
|
101
108
|
import { initRendering, addToMessages as _renAddToMessages, scrollToBottom as _renScrollToBottom, forceScrollToBottom as _renForceScrollToBottom, addUserMessage as _renAddUserMessage, getMsgTime as _renGetMsgTime, shouldGroupMessage as _renShouldGroupMessage, ensureAssistantBlock as _renEnsureAssistantBlock, addCopyHandler as _renAddCopyHandler, appendDelta as _renAppendDelta, flushStreamBuffer as _renFlushStreamBuffer, finalizeAssistantBlock as _renFinalizeAssistantBlock, addSystemMessage as _renAddSystemMessage, addConflictMessage as _renAddConflictMessage, addContextOverflowMessage as _renAddContextOverflowMessage, showClaudePreThinking as _renShowClaudePreThinking, showMatePreThinking as _renShowMatePreThinking, removeMatePreThinking as _renRemoveMatePreThinking, showSuggestionChips as _renShowSuggestionChips, hideSuggestionChips as _renHideSuggestionChips, getGhostSuggestion as _renGetGhostSuggestion, getTurnCounter, setTurnCounter, getPrependAnchor, setPrependAnchor, getActivityEl, setActivityEl, getIsUserScrolledUp, setIsUserScrolledUp, getStickyBottom, armStickyBottom, disarmStickyBottom } from './modules/app-rendering.js';
|
|
102
109
|
import { initDm, openDm as _dmOpenDm, enterDmMode as _dmEnterDmMode, exitDmMode as _dmExitDmMode, handleMateCreatedInApp as _dmHandleMateCreatedInApp, buildMateInterviewPrompt as _dmBuildMateInterviewPrompt, updateMateIconStatus as _dmUpdateMateIconStatus, connectMateProject as _dmConnectMateProject, disconnectMateProject as _dmDisconnectMateProject, appendDmMessage as _dmAppendDmMessage, showDmTypingIndicator as _dmShowDmTypingIndicator, handleDmSend as _dmHandleDmSend } from './modules/app-dm.js';
|
|
103
110
|
import { initMention, handleMentionStart, handleMentionStream, handleMentionDone, handleMentionError, handleMentionActivity, renderMentionUser, renderMentionResponse } from './modules/mention.js';
|
|
@@ -192,7 +199,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
192
199
|
function updateProjectList(msg) { _projUpdateProjectList(msg); }
|
|
193
200
|
function renderTopbarPresence(serverUsers) { _projRenderTopbarPresence(serverUsers); }
|
|
194
201
|
function renderProjectList() { _projRenderProjectList(); }
|
|
195
|
-
// projectListAddBtn listener -> modules/
|
|
202
|
+
// projectListAddBtn listener -> modules/project-start-dialog.js (initProjectStart)
|
|
196
203
|
|
|
197
204
|
// Prevent Cmd+Z / Cmd+Shift+Z from triggering browser back/forward (Arc, etc.)
|
|
198
205
|
// Always block browser default for Cmd+Z and manually invoke undo/redo via execCommand
|
|
@@ -280,6 +287,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
280
287
|
createStore({
|
|
281
288
|
networkSettings: { loaded: false, busy: false, confirming: false, draft: "", saved: "", status: "", errorKind: "", requestId: 0 },
|
|
282
289
|
vendorLoginBrowser: null,
|
|
290
|
+
githubStarCount: null,
|
|
283
291
|
sharedBrowser: null,
|
|
284
292
|
sharedBrowsers: [],
|
|
285
293
|
mcpSkillsWorkbench: {},
|
|
@@ -420,7 +428,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
420
428
|
projectListLoaded: false,
|
|
421
429
|
projectsAccessLoaded: false,
|
|
422
430
|
projectsHubRestoreRequested: false,
|
|
423
|
-
|
|
431
|
+
projectStart: initialProjectStart(),
|
|
432
|
+
projectStartFolder: emptyFolderState(),
|
|
424
433
|
onboardingStep: 'welcome',
|
|
425
434
|
onboardingIntent: null,
|
|
426
435
|
currentProjectOwnerId: null,
|
|
@@ -645,6 +654,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
645
654
|
vendorInfo: {},
|
|
646
655
|
// Rate-limit data is projected only for the displayed session/vendor.
|
|
647
656
|
rateLimitState: {},
|
|
657
|
+
vendorUsageOverview: null,
|
|
658
|
+
vendorUsageOpen: null,
|
|
648
659
|
currentMode: "default",
|
|
649
660
|
effectivePermissionMode: null,
|
|
650
661
|
permissionCapabilities: { auto: false, mcpOverride: false },
|
|
@@ -698,6 +709,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
698
709
|
|
|
699
710
|
// --- Theme (module) ---
|
|
700
711
|
initTheme();
|
|
712
|
+
initPaneAppearanceBridge();
|
|
701
713
|
|
|
702
714
|
// --- Tooltips ---
|
|
703
715
|
initTooltips();
|
|
@@ -789,8 +801,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
789
801
|
switch (action) {
|
|
790
802
|
case "createMate": startClayMateCreation(); break;
|
|
791
803
|
case "openSettings":
|
|
792
|
-
|
|
793
|
-
if (sb) sb.click();
|
|
804
|
+
openSettings();
|
|
794
805
|
break;
|
|
795
806
|
case "showHome": showHomeHub(); break;
|
|
796
807
|
}
|
|
@@ -1162,7 +1173,10 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1162
1173
|
basePath: basePath,
|
|
1163
1174
|
});
|
|
1164
1175
|
|
|
1165
|
-
// ---
|
|
1176
|
+
// --- Unified full-screen settings shell (Personal, Project, Server panes) ---
|
|
1177
|
+
initSettingsShell();
|
|
1178
|
+
|
|
1179
|
+
// --- User settings (personal pane) ---
|
|
1166
1180
|
initUserSettings({
|
|
1167
1181
|
basePath: basePath,
|
|
1168
1182
|
});
|
|
@@ -1230,11 +1244,11 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1230
1244
|
}
|
|
1231
1245
|
}
|
|
1232
1246
|
}).catch(function () {});
|
|
1233
|
-
// Hide
|
|
1247
|
+
// Hide update controls for non-admin users in multi-user mode. The settings
|
|
1248
|
+
// gear stays for everyone: Personal and Project settings are not admin-only,
|
|
1249
|
+
// and the shell only offers Server settings to administrators.
|
|
1234
1250
|
checkAdminAccess().then(function (isAdmin) {
|
|
1235
1251
|
if (store.get('isMultiUserMode') && !isAdmin) {
|
|
1236
|
-
var settingsBtn = document.getElementById("server-settings-btn");
|
|
1237
|
-
if (settingsBtn) settingsBtn.style.display = "none";
|
|
1238
1252
|
var updatePill = document.getElementById("update-pill-wrap");
|
|
1239
1253
|
if (updatePill) updatePill.style.display = "none";
|
|
1240
1254
|
}
|
|
@@ -1262,8 +1276,6 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1262
1276
|
|
|
1263
1277
|
// --- QR code ---
|
|
1264
1278
|
initQrCode();
|
|
1265
|
-
var sharePill = document.getElementById("share-pill");
|
|
1266
|
-
if (sharePill) sharePill.addEventListener("click", triggerShare);
|
|
1267
1279
|
|
|
1268
1280
|
// --- File browser ---
|
|
1269
1281
|
initFileBrowser({
|
|
@@ -1447,11 +1459,6 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1447
1459
|
function confirmRemoveProject(slug, name) { _projConfirmRemoveProject(slug, name); }
|
|
1448
1460
|
function handleRemoveProjectCheckResult(msg) { _projHandleRemoveProjectCheckResult(msg); }
|
|
1449
1461
|
function handleRemoveProjectResult(msg) { _projHandleRemoveProjectResult(msg); }
|
|
1450
|
-
function openAddProjectModal() { _projOpenAddProjectModal(); }
|
|
1451
|
-
function closeAddProjectModal() { _projCloseAddProjectModal(); }
|
|
1452
|
-
function handleBrowseDirResult(msg) { _projHandleBrowseDirResult(msg); }
|
|
1453
|
-
function handleAddProjectResult(msg) { _projHandleAddProjectResult(msg); }
|
|
1454
|
-
function handleCloneProgress(msg) { _projHandleCloneProgress(msg); }
|
|
1455
1462
|
|
|
1456
1463
|
// --- PWA install prompt -> modules/app-misc.js (set up in initMisc)
|
|
1457
1464
|
|
|
@@ -1467,9 +1474,11 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1467
1474
|
|
|
1468
1475
|
// --- Rate Limit module ---
|
|
1469
1476
|
initRateLimit();
|
|
1477
|
+
initVendorUsageOverview();
|
|
1478
|
+
initGithubStar();
|
|
1470
1479
|
|
|
1471
1480
|
// --- Projects module ---
|
|
1472
|
-
|
|
1481
|
+
initProjectStart();
|
|
1473
1482
|
|
|
1474
1483
|
// --- Home Hub module ---
|
|
1475
1484
|
initProjectMateNavigation();
|
|
@@ -81,7 +81,7 @@ html.contextual-pane-boot #connect-overlay { display: none !important; }
|
|
|
81
81
|
#contextual-clay button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; color: var(--text); }
|
|
82
82
|
#contextual-clay button .lucide { width: 15px; height: 15px; }
|
|
83
83
|
#contextual-clay iframe { border: 0; flex: 1; width: 100%; min-height: 0; background: var(--bg); }
|
|
84
|
-
#contextual-clay [data-clay-loading]:not([hidden]) { position: absolute; inset: 0; margin: 0; padding: 18px 12px; display:
|
|
84
|
+
#contextual-clay [data-clay-loading]:not([hidden]) { position: absolute; inset: 0; margin: 0; padding: 18px 12px; display: flex; z-index: 1; color: var(--text-muted); font-size: 13px; background: var(--bg); pointer-events: none; }
|
|
85
85
|
body:is(.contextual-chat-pane, .contextual-clay-native) { --content-width: 760px; }
|
|
86
86
|
body:is(.contextual-chat-pane, .contextual-clay-native) #messages { padding-top: 14px; }
|
|
87
87
|
body:is(.contextual-chat-pane, .contextual-clay-native) #messages .msg-assistant .md-content,
|
|
@@ -390,7 +390,7 @@
|
|
|
390
390
|
|
|
391
391
|
/* --- Panel fullscreen --- */
|
|
392
392
|
@media (min-width: 1024px) {
|
|
393
|
-
#main-column:has(.panel-fullscreen:not(.hidden)) > .title-bar-content { display: none; }
|
|
393
|
+
#main-column:has(.panel-fullscreen:not(.hidden):not(#shared-browser-panel)) > .title-bar-content { display: none; }
|
|
394
394
|
#main-panels:has(.panel-fullscreen:not(.hidden)) > #app { display: none; }
|
|
395
395
|
}
|
|
396
396
|
@media (max-width: 1023px) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.mate-loading {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
gap: 12px;
|
|
7
|
+
color: var(--text-muted);
|
|
8
|
+
text-align: center;
|
|
9
|
+
}
|
|
10
|
+
.mate-loading[hidden] { display: none; }
|
|
11
|
+
.mate-loading-scene { position: relative; width: 210px; height: 148px; flex-shrink: 0; }
|
|
12
|
+
.mate-loading-avatar { position: absolute; width: 94px; height: 94px; object-fit: contain; left: 58px; top: 22px; }
|
|
13
|
+
.mate-loading-desk { position: absolute; width: 210px; height: auto; left: 0; bottom: 0; }
|
|
14
|
+
.mate-loading-label { margin: 0; max-width: 100%; font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
|
|
15
|
+
.mate-loading-dots { display: flex; gap: 6px; padding: 3px 0; }
|
|
16
|
+
.mate-loading-dots span { width: 6px; height: 6px; border-radius: 45%; background: var(--text-muted); opacity: .45; animation: mate-loading-bob 1.5s ease-in-out infinite; }
|
|
17
|
+
.mate-loading-dots span:nth-child(2) { animation-delay: .18s; }
|
|
18
|
+
.mate-loading-dots span:nth-child(3) { animation-delay: .36s; }
|
|
19
|
+
@keyframes mate-loading-bob { 0%, 60%, 100% { transform: translateY(0); opacity: .4; } 30% { transform: translateY(-4px); opacity: .8; } }
|
|
20
|
+
@media (prefers-reduced-motion: reduce) { .mate-loading-dots span { animation: none; } }
|
|
21
|
+
@media (max-height: 450px) { .mate-loading-scene { zoom: .7; } .mate-loading { gap: 8px; } }
|