clay-server 4.1.0-beta.9 → 4.1.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/context-usage.js +47 -0
- package/lib/issues-mcp-server.js +1 -1
- package/lib/issues-service.js +3 -1
- package/lib/loop-registry-occurrence.js +1 -0
- package/lib/notes.js +20 -3
- package/lib/os-users.js +6 -0
- package/lib/project-connection.js +14 -3
- package/lib/project-file-path.js +13 -0
- package/lib/project-file-watch.js +19 -8
- package/lib/project-filesystem.js +10 -16
- package/lib/project-http.js +53 -48
- package/lib/project-logs-mcp-server.js +8 -8
- package/lib/project-logs-schema.js +1 -1
- package/lib/project-logs-service.js +46 -13
- package/lib/project-logs-store.js +17 -15
- package/lib/project-logs.js +70 -0
- package/lib/project-loop.js +1 -0
- package/lib/project-notifications.js +1 -1
- package/lib/project-scheduled-result-store.js +131 -0
- package/lib/project-scheduled-task-execution.js +35 -2
- package/lib/project-session-notes.js +11 -4
- package/lib/project-sessions.js +7 -0
- package/lib/project-user-message.js +47 -0
- package/lib/project.js +53 -3
- package/lib/public/app.js +26 -9
- package/lib/public/css/avatar-imprints.css +1 -1
- package/lib/public/css/command-palette.css +20 -0
- package/lib/public/css/git-panel.css +13 -12
- package/lib/public/css/git-placard.css +4 -4
- package/lib/public/css/issues.css +78 -31
- package/lib/public/css/mobile-nav.css +7 -0
- package/lib/public/css/notifications-center.css +3 -3
- package/lib/public/css/project-logs.css +15 -0
- package/lib/public/css/sidebar.css +7 -0
- package/lib/public/css/sticky-notes.css +29 -0
- package/lib/public/modules/app-connection.js +9 -1
- package/lib/public/modules/app-favicon.js +10 -0
- package/lib/public/modules/app-messages.js +43 -12
- package/lib/public/modules/app-notifications.js +2 -0
- package/lib/public/modules/app-panels.js +77 -23
- package/lib/public/modules/app-projects.js +2 -0
- package/lib/public/modules/app-rate-limit.js +148 -61
- package/lib/public/modules/avatar-imprint.js +25 -70
- package/lib/public/modules/avatar.js +12 -4
- package/lib/public/modules/chat-render-runtime.js +20 -0
- package/lib/public/modules/clay-issue-links.js +23 -2
- package/lib/public/modules/clay-log-links.js +11 -1
- package/lib/public/modules/context-view-preference.js +143 -0
- package/lib/public/modules/default-vendor.js +116 -0
- package/lib/public/modules/filebrowser-tabs.js +1 -0
- package/lib/public/modules/filebrowser.js +45 -18
- package/lib/public/modules/issues-render.js +36 -10
- package/lib/public/modules/issues.js +95 -13
- package/lib/public/modules/markdown.js +3 -1
- package/lib/public/modules/pane-bridge.js +14 -8
- package/lib/public/modules/pane-issue-bridge.js +27 -0
- package/lib/public/modules/permission-hints.js +13 -0
- package/lib/public/modules/profile.js +9 -9
- package/lib/public/modules/project-activation.js +49 -0
- package/lib/public/modules/project-logs-render.js +13 -3
- package/lib/public/modules/project-logs.js +45 -15
- package/lib/public/modules/right-workbench.js +44 -0
- package/lib/public/modules/scheduled-result-client.js +33 -0
- package/lib/public/modules/scheduled-result-display.js +50 -0
- package/lib/public/modules/scheduled-result-notification.js +31 -0
- package/lib/public/modules/scheduled-task-presentation.js +15 -0
- package/lib/public/modules/scheduled-tasks.js +9 -21
- package/lib/public/modules/sidebar-mobile.js +51 -3
- package/lib/public/modules/sidebar-sessions.js +65 -5
- package/lib/public/modules/split-session-boundary.js +28 -0
- package/lib/public/modules/split-view.js +42 -7
- package/lib/public/modules/sticky-notes-browser.js +130 -18
- package/lib/public/modules/sticky-notes.js +2 -3
- package/lib/public/modules/terminal.js +4 -4
- package/lib/public/modules/thinking-lifecycle.js +4 -1
- package/lib/public/modules/tools.js +5 -1
- package/lib/scheduled-run-state.js +10 -2
- package/lib/scheduler.js +1 -0
- package/lib/sdk-bridge.js +97 -61
- package/lib/sdk-message-processor.js +44 -13
- package/lib/sdk-skill-discovery.js +6 -28
- package/lib/sdk-turn-queue.js +14 -0
- package/lib/server-context-view.js +53 -0
- package/lib/server-default-vendor.js +60 -0
- package/lib/server.js +23 -6
- package/lib/session-notes-mcp-server.js +3 -5
- package/lib/session-pair-factory.js +2 -2
- package/lib/session-title-generator.js +89 -0
- package/lib/session-title-policy.js +8 -2
- package/lib/sessions.js +26 -1
- package/lib/user-presence.js +6 -0
- package/lib/users-context-view-preferences.js +65 -0
- package/lib/users-default-vendor-preferences.js +80 -0
- package/lib/users.js +12 -0
- package/lib/ws-schema.js +11 -0
- package/lib/yoke/acp-agent-profiles.js +15 -2
- package/lib/yoke/adapters/acp.js +3 -2
- package/lib/yoke/adapters/antigravity.js +2 -2
- package/lib/yoke/adapters/claude-worker.js +11 -12
- package/lib/yoke/adapters/claude.js +75 -22
- package/lib/yoke/adapters/codex.js +216 -29
- package/lib/yoke/adapters/kiro.js +6 -5
- package/lib/yoke/claude-context-usage.js +57 -0
- package/lib/yoke/claude-message-correlation.js +31 -0
- package/lib/yoke/claude-model-switch.js +15 -0
- package/lib/yoke/index.js +5 -1
- package/lib/yoke/mcp-bridge-server.js +18 -5
- package/lib/yoke/session-skill-catalog.js +45 -0
- package/lib/yoke/skill-discovery.js +60 -20
- package/lib/yoke/vendor-registry.js +1 -1
- package/package.json +5 -7
package/lib/project-sessions.js
CHANGED
|
@@ -6,6 +6,7 @@ var { CODEX_DEFAULTS, getCodexConfig } = require("./codex-defaults");
|
|
|
6
6
|
var updateSnooze = require("./update-snooze");
|
|
7
7
|
var yoke = require("./yoke");
|
|
8
8
|
var sessionVisibility = require("./session-visibility");
|
|
9
|
+
var contextUsageModule = require("./context-usage");
|
|
9
10
|
|
|
10
11
|
function vendorSupportsTui(vendor) {
|
|
11
12
|
var info = yoke.getVendorInfo(vendor);
|
|
@@ -82,6 +83,7 @@ function formatAskUserAnswerAsMessage(input, answers) {
|
|
|
82
83
|
* getLatestVersion, setLatestVersion
|
|
83
84
|
*/
|
|
84
85
|
function attachSessions(ctx) {
|
|
86
|
+
var contextUsage = contextUsageModule.attachContextUsage(ctx);
|
|
85
87
|
var cwd = ctx.cwd;
|
|
86
88
|
var slug = ctx.slug;
|
|
87
89
|
var isMate = ctx.isMate;
|
|
@@ -108,6 +110,7 @@ function attachSessions(ctx) {
|
|
|
108
110
|
var getLinuxUserForSession = ctx.getLinuxUserForSession;
|
|
109
111
|
var ensureProjectAccessForSession = ctx.ensureProjectAccessForSession;
|
|
110
112
|
var getOsUserInfoForWs = ctx.getOsUserInfoForWs;
|
|
113
|
+
var hydrateSkillCatalog = ctx.hydrateSkillCatalog || function () { return []; };
|
|
111
114
|
function stopSession(session, actor) {
|
|
112
115
|
if (!session) return false;
|
|
113
116
|
session._pendingMessageDrainPaused = true;
|
|
@@ -568,6 +571,7 @@ function attachSessions(ctx) {
|
|
|
568
571
|
}
|
|
569
572
|
|
|
570
573
|
function handleSessionsMessage(ws, msg) {
|
|
574
|
+
if (contextUsage.handleMessage(ws, msg)) return true;
|
|
571
575
|
|
|
572
576
|
if (msg.type === "push_subscribe") {
|
|
573
577
|
var _pushUserId = ws._clayUser ? ws._clayUser.id : null;
|
|
@@ -981,6 +985,8 @@ function attachSessions(ctx) {
|
|
|
981
985
|
if (msg.id && sm.sessions.has(msg.id) && msg.title) {
|
|
982
986
|
var s = sm.sessions.get(msg.id);
|
|
983
987
|
s.title = String(msg.title).substring(0, 100);
|
|
988
|
+
s.titleProvisional = false;
|
|
989
|
+
s.titleAutoGenerated = false;
|
|
984
990
|
s.titleManuallySet = true;
|
|
985
991
|
sm.saveSessionFile(s);
|
|
986
992
|
sm.notifySessionRenamed(s.localId);
|
|
@@ -1679,6 +1685,7 @@ function attachSessions(ctx) {
|
|
|
1679
1685
|
return true;
|
|
1680
1686
|
}
|
|
1681
1687
|
|
|
1688
|
+
if (decision === "allow_always" && pending.suppressAlwaysAllowRule) decision = "allow";
|
|
1682
1689
|
if (decision === "allow" || decision === "allow_always") {
|
|
1683
1690
|
if (decision === "allow_always") {
|
|
1684
1691
|
if (!session.allowedTools) session.allowedTools = {};
|
|
@@ -24,6 +24,7 @@ var fs = require("fs");
|
|
|
24
24
|
* pendingMessageQueue,
|
|
25
25
|
* loadContextSources, saveContextSources,
|
|
26
26
|
* digestDmTurn, gateMemory,
|
|
27
|
+
* getProjectAccess, canAccessProjectSlug,
|
|
27
28
|
* adapter - YOKE adapter instance
|
|
28
29
|
*/
|
|
29
30
|
function attachUserMessage(ctx) {
|
|
@@ -55,6 +56,8 @@ function attachUserMessage(ctx) {
|
|
|
55
56
|
var getLinuxUserForSession = ctx.getLinuxUserForSession;
|
|
56
57
|
var ensureProjectAccessForSession = ctx.ensureProjectAccessForSession;
|
|
57
58
|
var getOsUserInfoForWs = ctx.getOsUserInfoForWs;
|
|
59
|
+
var getProjectAccess = ctx.getProjectAccess;
|
|
60
|
+
var canAccessProjectSlug = ctx.canAccessProjectSlug;
|
|
58
61
|
|
|
59
62
|
var hydrateImageRefs = ctx.hydrateImageRefs;
|
|
60
63
|
var saveImageFile = ctx.saveImageFile;
|
|
@@ -99,6 +102,21 @@ function attachUserMessage(ctx) {
|
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
|
|
105
|
+
function canHumanManageNotes(ws) {
|
|
106
|
+
if (!usersModule.isMultiUser()) return true;
|
|
107
|
+
if (!ws || !ws._clayUser || !ws._clayUser.id) return false;
|
|
108
|
+
var actor = usersModule.findUserById(ws._clayUser.id);
|
|
109
|
+
if (!actor) return false;
|
|
110
|
+
if (typeof canAccessProjectSlug === "function" && !canAccessProjectSlug(actor.id, slug)) return false;
|
|
111
|
+
var access = typeof getProjectAccess === "function" ? getProjectAccess() : null;
|
|
112
|
+
return !!(access && !access.error && usersModule.canAccessProject(actor.id, access));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function noteDeleteResult(ws, msg, ok, error) {
|
|
116
|
+
sendTo(ws, { type: "note_delete_result", projectSlug: slug, noteId: msg.id || null,
|
|
117
|
+
requestId: msg.requestId || null, ok: !!ok, error: error || null });
|
|
118
|
+
}
|
|
119
|
+
|
|
102
120
|
// --------------- Main handler ---------------
|
|
103
121
|
|
|
104
122
|
function handleUserMessage(ws, msg, forcedSession, internal) {
|
|
@@ -171,6 +189,31 @@ function attachUserMessage(ctx) {
|
|
|
171
189
|
return true;
|
|
172
190
|
}
|
|
173
191
|
|
|
192
|
+
if (msg.type === "note_delete_permanently") {
|
|
193
|
+
if (!msg.id || !canHumanManageNotes(ws)) {
|
|
194
|
+
noteDeleteResult(ws, msg, false, "You are not authorized to delete notes in this project.");
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
var current = nm.list().filter(function (item) { return item && item.id === msg.id; })[0];
|
|
198
|
+
if (!current) {
|
|
199
|
+
noteDeleteResult(ws, msg, false, "Note not found.");
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
if (!notesLifecycle.isClosed(current)) {
|
|
203
|
+
noteDeleteResult(ws, msg, false, "Only closed notes can be permanently deleted.");
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
var removed = nm.removeClosed(msg.id);
|
|
207
|
+
if (!removed) {
|
|
208
|
+
noteDeleteResult(ws, msg, false, "The note changed before it could be deleted.");
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
send({ type: "note_deleted", id: removed.id });
|
|
212
|
+
noteDeleteResult(ws, msg, true, null);
|
|
213
|
+
syncNotesKnowledge();
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
|
|
174
217
|
if (msg.type === "note_list_request") {
|
|
175
218
|
sendTo(ws, { type: "notes_list", notes: nm.list() });
|
|
176
219
|
return true;
|
|
@@ -479,6 +522,10 @@ function attachUserMessage(ctx) {
|
|
|
479
522
|
function recordSessionTitle() {
|
|
480
523
|
if (!session.title) {
|
|
481
524
|
session.title = (msg.text || "Image").substring(0, 50);
|
|
525
|
+
// This title is an optimistic first-message label, not a semantic or
|
|
526
|
+
// explicit title. Persist its provenance so startQuery can preserve
|
|
527
|
+
// eligibility for model generation after this function returns.
|
|
528
|
+
session.titleProvisional = true;
|
|
482
529
|
sm.saveSessionFile(session);
|
|
483
530
|
sm.broadcastSessionList();
|
|
484
531
|
// Sync auto-title to SDK
|
package/lib/project.js
CHANGED
|
@@ -46,6 +46,7 @@ var { attachVendorLogin } = require("./project-vendor-login");
|
|
|
46
46
|
var { attachConnection } = require("./project-connection");
|
|
47
47
|
var { attachProjectScheduledMessages } = require("./project-scheduled-messages");
|
|
48
48
|
var { attachMcp } = require("./project-mcp");
|
|
49
|
+
var { createSessionSkillCatalog } = require("./yoke/session-skill-catalog");
|
|
49
50
|
var { createLocalMcp } = require("./mcp-local");
|
|
50
51
|
var { attachEmail: attachEmailModule } = require("./project-email");
|
|
51
52
|
var { attachSessionSpawn } = require("./project-session-spawn");
|
|
@@ -256,11 +257,20 @@ function createProjectContext(opts) {
|
|
|
256
257
|
var serverPort = opts.port || 2633;
|
|
257
258
|
var serverTls = opts.tls || false;
|
|
258
259
|
var serverAuthToken = opts.authToken || null;
|
|
260
|
+
var mcpBridgeToken = opts.mcpBridgeToken || crypto.randomBytes(32).toString("hex");
|
|
259
261
|
var latestVersion = null;
|
|
260
262
|
var sessionTitleMigrationScheduled = false;
|
|
261
263
|
|
|
262
264
|
// --- YOKE adapters (multi-vendor, lazy init) ---
|
|
263
|
-
var _yokeState = yoke.createAdapters({
|
|
265
|
+
var _yokeState = yoke.createAdapters({
|
|
266
|
+
cwd: cwd,
|
|
267
|
+
slug: slug,
|
|
268
|
+
osUsers: osUsers,
|
|
269
|
+
clayPort: serverPort,
|
|
270
|
+
clayTls: serverTls,
|
|
271
|
+
clayAuthToken: serverAuthToken,
|
|
272
|
+
clayBridgeToken: mcpBridgeToken,
|
|
273
|
+
});
|
|
264
274
|
var adapters = _yokeState.adapters;
|
|
265
275
|
// A new project has no remembered vendor. Select the first installed
|
|
266
276
|
// provider by the shared Claude -> Codex -> Kiro preference order.
|
|
@@ -555,6 +565,7 @@ function createProjectContext(opts) {
|
|
|
555
565
|
// --- File/directory watcher engine (delegated to project-file-watch.js) ---
|
|
556
566
|
var _fileWatch = attachFileWatch({
|
|
557
567
|
requestAccess: _requestAccess, fsAsUser: fsAsUser,
|
|
568
|
+
osUsers: osUsers,
|
|
558
569
|
cwd: cwd,
|
|
559
570
|
send: send,
|
|
560
571
|
sendTo: sendTo,
|
|
@@ -717,6 +728,15 @@ function createProjectContext(opts) {
|
|
|
717
728
|
var nm = createNotesManager({ cwd: cwd, send: send, sendTo: sendTo });
|
|
718
729
|
var _sessionNotes = attachSessionNotes({
|
|
719
730
|
nm: nm,
|
|
731
|
+
canUseSession: function (session) {
|
|
732
|
+
if (!session || sm.sessions.get(session.localId) !== session) return false;
|
|
733
|
+
if (!usersModule.isMultiUser()) return true;
|
|
734
|
+
var owner = session.ownerId && usersModule.findUserById(session.ownerId);
|
|
735
|
+
if (!owner) return false;
|
|
736
|
+
var access = opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
737
|
+
if (opts.canAccessProjectSlug && !opts.canAccessProjectSlug(owner.id, slug)) return false;
|
|
738
|
+
return usersModule.canAccessSession(owner.id, session, access) && (!osUsers || !!getLinuxUserForSession(session));
|
|
739
|
+
},
|
|
720
740
|
send: send,
|
|
721
741
|
isMate: isMate,
|
|
722
742
|
broadcastWritten: function (message) {
|
|
@@ -1217,6 +1237,7 @@ function createProjectContext(opts) {
|
|
|
1217
1237
|
clayPort: serverPort,
|
|
1218
1238
|
clayTls: serverTls,
|
|
1219
1239
|
clayAuthToken: serverAuthToken,
|
|
1240
|
+
clayBridgeToken: mcpBridgeToken,
|
|
1220
1241
|
getWorkerPermissionRouter: function () {
|
|
1221
1242
|
return isMate ? null : _sessionPair.workerPermission;
|
|
1222
1243
|
},
|
|
@@ -1413,6 +1434,9 @@ function createProjectContext(opts) {
|
|
|
1413
1434
|
canExecuteScheduledTask: function (record) {
|
|
1414
1435
|
return !!(_scheduledTaskExecution && _scheduledTaskExecution.runnable(record).ok);
|
|
1415
1436
|
},
|
|
1437
|
+
onScheduledRunTerminal: function (record, run) {
|
|
1438
|
+
if (_scheduledTaskExecution) _scheduledTaskExecution.recordTerminal(record, run);
|
|
1439
|
+
},
|
|
1416
1440
|
onProcessingChanged: onProcessingChanged,
|
|
1417
1441
|
hydrateImageRefs: hydrateImageRefs,
|
|
1418
1442
|
});
|
|
@@ -1428,6 +1452,7 @@ function createProjectContext(opts) {
|
|
|
1428
1452
|
getSdk: function () { return sdk; }, getLinuxUserForSession: getLinuxUserForSession,
|
|
1429
1453
|
requiresLinuxUser: function () { return osUsers; },
|
|
1430
1454
|
onProcessingChanged: onProcessingChanged,
|
|
1455
|
+
recordResult: function (result) { return _projectLogs.recordScheduledResult(result); },
|
|
1431
1456
|
authorize: function (record) {
|
|
1432
1457
|
return authorizeStoredOwner(record, {
|
|
1433
1458
|
usersModule: usersModule, osUsers: osUsers,
|
|
@@ -1437,6 +1462,7 @@ function createProjectContext(opts) {
|
|
|
1437
1462
|
});
|
|
1438
1463
|
},
|
|
1439
1464
|
});
|
|
1465
|
+
setTimeout(function () { _scheduledTaskExecution.syncTerminalResults(); }, 0);
|
|
1440
1466
|
|
|
1441
1467
|
_scheduledTasks = attachScheduledTasks({
|
|
1442
1468
|
cwd: cwd,
|
|
@@ -1583,8 +1609,8 @@ function createProjectContext(opts) {
|
|
|
1583
1609
|
}
|
|
1584
1610
|
|
|
1585
1611
|
// --- DM messages (delegated to server-level handler) ---
|
|
1586
|
-
if (msg.type === "home_debate_question_response" || msg.type === "home_debate_control" || msg.type === "home_mate_creation_question_response" || msg.type === "default_ai_get" || msg.type === "default_ai_catalog_get" || msg.type === "default_ai_set" || msg.type === "cursor_sharing_get" || msg.type === "cursor_sharing_set") {
|
|
1587
|
-
if (typeof opts.onDmMessage === "function") opts.onDmMessage(ws, msg);
|
|
1612
|
+
if (msg.type === "home_debate_question_response" || msg.type === "home_debate_control" || msg.type === "home_mate_creation_question_response" || msg.type === "default_ai_get" || msg.type === "default_ai_catalog_get" || msg.type === "default_ai_set" || msg.type === "default_vendor_get" || msg.type === "default_vendor_set" || msg.type === "context_view_get" || msg.type === "context_view_set" || msg.type === "cursor_sharing_get" || msg.type === "cursor_sharing_set") {
|
|
1613
|
+
if (typeof opts.onDmMessage === "function") opts.onDmMessage(ws, msg, slug);
|
|
1588
1614
|
return;
|
|
1589
1615
|
}
|
|
1590
1616
|
if (msg.type === "issue_reference_resolve" || msg.type === "home_clay_ask" || msg.type === "home_clay_session_resolve" || msg.type === "home_clay_log_resolve") {
|
|
@@ -1863,6 +1889,12 @@ function createProjectContext(opts) {
|
|
|
1863
1889
|
}
|
|
1864
1890
|
|
|
1865
1891
|
// --- Sessions/config/project handler (delegated to project-sessions.js) ---
|
|
1892
|
+
var _sessionSkillCatalog = createSessionSkillCatalog({
|
|
1893
|
+
cwd: cwd,
|
|
1894
|
+
osUsers: osUsers,
|
|
1895
|
+
getLinuxUser: getLinuxUserForSession,
|
|
1896
|
+
});
|
|
1897
|
+
sm.setSessionHydrator(_sessionSkillCatalog.hydrate);
|
|
1866
1898
|
var _sessions = attachSessions({
|
|
1867
1899
|
cwd: cwd,
|
|
1868
1900
|
slug: slug,
|
|
@@ -1902,6 +1934,7 @@ function createProjectContext(opts) {
|
|
|
1902
1934
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
1903
1935
|
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
1904
1936
|
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
1937
|
+
hydrateSkillCatalog: _sessionSkillCatalog.hydrate,
|
|
1905
1938
|
hydrateImageRefs: hydrateImageRefs,
|
|
1906
1939
|
onProcessingChanged: onProcessingChanged,
|
|
1907
1940
|
broadcastPresence: broadcastPresence,
|
|
@@ -1931,6 +1964,7 @@ function createProjectContext(opts) {
|
|
|
1931
1964
|
saveContextSources: saveContextSources,
|
|
1932
1965
|
_email: _email,
|
|
1933
1966
|
_notifications: _notifications,
|
|
1967
|
+
_projectLogs: _projectLogs,
|
|
1934
1968
|
});
|
|
1935
1969
|
|
|
1936
1970
|
var _models = attachModels({
|
|
@@ -2030,6 +2064,8 @@ function createProjectContext(opts) {
|
|
|
2030
2064
|
getSessionForWs: getSessionForWs,
|
|
2031
2065
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
2032
2066
|
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
2067
|
+
getProjectAccess: function () { return opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null }; },
|
|
2068
|
+
canAccessProjectSlug: opts.canAccessProjectSlug || function () { return !usersModule.isMultiUser(); },
|
|
2033
2069
|
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
2034
2070
|
hydrateImageRefs: hydrateImageRefs,
|
|
2035
2071
|
saveImageFile: saveImageFile,
|
|
@@ -2112,6 +2148,12 @@ function createProjectContext(opts) {
|
|
|
2112
2148
|
function getMcpBridgeHandler(sessionId, sessionOnly, queryGeneration) {
|
|
2113
2149
|
var boundSession = Number.isInteger(sessionId) ? sm.sessions.get(sessionId) : null;
|
|
2114
2150
|
var queryToolBridge = createSessionQueryToolBridge({ session: boundSession, sdk: sdk });
|
|
2151
|
+
function sessionQueryValid() {
|
|
2152
|
+
return !!boundSession
|
|
2153
|
+
&& Number.isInteger(queryGeneration)
|
|
2154
|
+
&& sm.sessions.get(boundSession.localId) === boundSession
|
|
2155
|
+
&& Number(boundSession._sdkQueryGeneration || 0) === queryGeneration;
|
|
2156
|
+
}
|
|
2115
2157
|
// Build set of local MCP server names to exclude (Codex handles these natively)
|
|
2116
2158
|
var localMcpNames = {};
|
|
2117
2159
|
try {
|
|
@@ -2126,6 +2168,7 @@ function createProjectContext(opts) {
|
|
|
2126
2168
|
return {
|
|
2127
2169
|
listTools: function () {
|
|
2128
2170
|
var tools = [];
|
|
2171
|
+
if (sessionOnly && !sessionQueryValid()) return Promise.resolve(tools);
|
|
2129
2172
|
var toJSONSchema;
|
|
2130
2173
|
var zod;
|
|
2131
2174
|
try { zod = require("zod"); toJSONSchema = zod.toJSONSchema; } catch (e) { /* fallback */ }
|
|
@@ -2251,6 +2294,9 @@ function createProjectContext(opts) {
|
|
|
2251
2294
|
return Promise.resolve(tools);
|
|
2252
2295
|
},
|
|
2253
2296
|
callTool: function (serverName, toolName, args) {
|
|
2297
|
+
if (sessionOnly && !sessionQueryValid()) {
|
|
2298
|
+
return Promise.reject(new Error("Session tool unavailable or older query: " + serverName + "/" + toolName));
|
|
2299
|
+
}
|
|
2254
2300
|
var queryCall = queryToolBridge.callTool(queryGeneration, serverName, toolName, args);
|
|
2255
2301
|
if (queryCall) return queryCall;
|
|
2256
2302
|
if (boundSession && serverName === "clay-sessions") {
|
|
@@ -2409,6 +2455,7 @@ function createProjectContext(opts) {
|
|
|
2409
2455
|
getLatestVersion: function () { return latestVersion; },
|
|
2410
2456
|
getTitle: function () { return title; },
|
|
2411
2457
|
getProject: function () { return project; },
|
|
2458
|
+
hydrateSkillCatalog: _sessionSkillCatalog.hydrate,
|
|
2412
2459
|
// Exposed so the first websocket connection can lazily warm up the
|
|
2413
2460
|
// adapters for this project (see project-connection handleConnection).
|
|
2414
2461
|
warmup: function (linuxUser) {
|
|
@@ -2633,6 +2680,9 @@ function createProjectContext(opts) {
|
|
|
2633
2680
|
handleDisconnection: handleDisconnection,
|
|
2634
2681
|
handleHTTP: handleHTTP,
|
|
2635
2682
|
getMcpBridgeHandler: getMcpBridgeHandler,
|
|
2683
|
+
isMcpBridgeAuthenticated: function (req) {
|
|
2684
|
+
return !!(req && req.headers && req.headers["x-clay-bridge-token"] && req.headers["x-clay-bridge-token"] === mcpBridgeToken);
|
|
2685
|
+
},
|
|
2636
2686
|
getStatus: getStatus,
|
|
2637
2687
|
getSessionManager: function () { return sm; },
|
|
2638
2688
|
createDelegatedSession: _delegatedSession.createDelegatedSession,
|
package/lib/public/app.js
CHANGED
|
@@ -28,7 +28,7 @@ import { initRewind, setRewindMode, showRewindModal, clearPendingRewindUuid, add
|
|
|
28
28
|
import { initNotifications, showDoneNotification, playDoneSound, isNotifAlertEnabled, isNotifSoundEnabled } from './modules/notifications.js';
|
|
29
29
|
import { initInput, clearPendingImages, handleInputSync, autoResize, builtinCommands, sendMessage, hasSendableContent, setScheduleBtnDisabled, setScheduleDelayMs, clearScheduleDelay } from './modules/input.js';
|
|
30
30
|
import { initQrCode, triggerShare } from './modules/qrcode.js';
|
|
31
|
-
import { initFileBrowser, loadRootDirectory, refreshTree, handleFsList, handleFsRead, handleDirChanged, refreshIfOpen, handleFileChanged, handleFileHistory, handleGitDiff, handleFileAt, getPendingNavigate, closeFileViewer, resetFileBrowser } from './modules/filebrowser.js';
|
|
31
|
+
import { initFileBrowser, loadRootDirectory, reopenFileViewer, refreshTree, handleFsList, handleFsRead, handleDirChanged, refreshIfOpen, handleFileChanged, handleFileHistory, handleGitDiff, handleFileAt, getPendingNavigate, closeFileViewer, resetFileBrowser } from './modules/filebrowser.js';
|
|
32
32
|
import { initGitPanel } from './modules/git-panel.js';
|
|
33
33
|
import { initWorkerPaneLock } from './modules/worker-pane-lock.js';
|
|
34
34
|
import { initAutonomousRun } from './modules/autonomous-run.js';
|
|
@@ -36,7 +36,7 @@ import { initLoopInterview } from './modules/loop-interview.js';
|
|
|
36
36
|
import { initTerminal, openTerminal, closeTerminal, resetTerminals, handleTermList, handleTermCreated, handleTermOutput, handleTermResized, handleTermExited, handleTermClosed, sendTerminalCommand } from './modules/terminal.js';
|
|
37
37
|
import { initContextSources, updateTerminalList, updateBrowserTabList, handleContextSourcesState, getActiveSources, hasActiveSources } from './modules/context-sources.js';
|
|
38
38
|
import { initStickyNotes, handleNotesList, handleNoteCreated, handleNoteUpdated, handleNoteDeleted, hideNotes, showNotes, isNotesVisible, createNote, setBrowserRefresh, toggleNotesTemporaryVisibility } from './modules/sticky-notes.js';
|
|
39
|
-
import { initNotesBrowser, openNotesBrowser, closeNotesBrowser, isNotesBrowserOpen, renderNotesBrowser
|
|
39
|
+
import { initNotesBrowser, openNotesBrowser, closeNotesBrowser, isNotesBrowserOpen, renderNotesBrowser } from './modules/sticky-notes-browser.js';
|
|
40
40
|
import { initTheme, getThemeColor, getComputedVar, onThemeChange, getCurrentTheme, getChatLayout } from './modules/theme.js';
|
|
41
41
|
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';
|
|
42
42
|
import { initServerSettings, updateSettingsStats, updateDaemonConfig, handleSetPinResult, handleKeepAwakeChanged, handleAutoContinueChanged, handleRestartResult, handleShutdownResult, handleSharedEnv, handleSharedEnvSaved, handleGlobalClaudeMdRead, handleGlobalClaudeMdWrite } from './modules/server-settings.js';
|
|
@@ -71,6 +71,7 @@ import { rememberHomePrimarySurface } from './modules/home-surface.js';
|
|
|
71
71
|
import { initRateLimit, handleRateLimitEvent as _rlHandleRateLimitEvent, updateRateLimitUsage as _rlUpdateRateLimitUsage, handleFastModeState as _rlHandleFastModeState, resetRateLimitState } from './modules/app-rate-limit.js';
|
|
72
72
|
import { initCursors, handleRemoteCursorMove as _curHandleRemoteCursorMove, handleRemoteCursorLeave as _curHandleRemoteCursorLeave, handleRemoteSelection as _curHandleRemoteSelection, clearRemoteCursors as _curClearRemoteCursors, initCursorToggle } from './modules/app-cursors.js';
|
|
73
73
|
import { initDefaultAi } from './modules/default-ai.js';
|
|
74
|
+
import { requestDefaultVendor } from './modules/default-vendor.js';
|
|
74
75
|
import { initFavicon, updateFavicon as _favUpdateFavicon, setSendBtnMode as _favSetSendBtnMode, blinkIO as _favBlinkIO, blinkSessionDot as _favBlinkSessionDot, updateCrossProjectBlink as _favUpdateCrossProjectBlink, startUrgentBlink as _favStartUrgentBlink, stopUrgentBlink as _favStopUrgentBlink, setActivity as _favSetActivity } from './modules/app-favicon.js';
|
|
75
76
|
import { initHeader, closeSessionInfoPopover as _hdrCloseSessionInfoPopover, updateHistorySentinel as _hdrUpdateHistorySentinel, requestMoreHistory as _hdrRequestMoreHistory, prependOlderHistory as _hdrPrependOlderHistory } from './modules/app-header.js';
|
|
76
77
|
import { initSessionActions } from './modules/session-actions.js';
|
|
@@ -286,6 +287,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
286
287
|
currentSlug: currentSlug,
|
|
287
288
|
activeProjectSlug: null,
|
|
288
289
|
sessionActivatedProjectSlug: null,
|
|
290
|
+
sessionListProjectSlug: null,
|
|
291
|
+
splitGroupsProjectSlug: null,
|
|
289
292
|
socketPath: null,
|
|
290
293
|
pendingHomeProjectSlug: null,
|
|
291
294
|
currentProjectOwnerId: null,
|
|
@@ -323,6 +326,9 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
323
326
|
connected: false,
|
|
324
327
|
fileReadRequest: null,
|
|
325
328
|
pendingFileNavigation: null,
|
|
329
|
+
rightWorkbenchOwner: null,
|
|
330
|
+
rightWorkbenchRevision: 0,
|
|
331
|
+
fileViewerOpenRevision: 0,
|
|
326
332
|
cursorSharingEnabled: false,
|
|
327
333
|
cursorSharingHydrated: false,
|
|
328
334
|
pendingOutboundMessages: [],
|
|
@@ -381,6 +387,12 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
381
387
|
projectLogsCanDelete: false,
|
|
382
388
|
projectLogsUnread: 0,
|
|
383
389
|
projectLogsSeenRevisions: {},
|
|
390
|
+
scheduledResultUnread: 0,
|
|
391
|
+
scheduledResultAutoFocusHandled: false,
|
|
392
|
+
scheduledResultFocusRef: null,
|
|
393
|
+
scheduledResultPendingReadRef: null,
|
|
394
|
+
scheduledResultSeenRefs: {},
|
|
395
|
+
scheduledResultSessionRequestId: null,
|
|
384
396
|
issuesOpen: false,
|
|
385
397
|
issuesView: "list",
|
|
386
398
|
issuesSelected: null,
|
|
@@ -388,6 +400,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
388
400
|
issuesRequests: {},
|
|
389
401
|
issuesViewRequest: null,
|
|
390
402
|
issuesViewGeneration: 0,
|
|
403
|
+
issuesUpdateAvailable: null,
|
|
391
404
|
issuesCache: {},
|
|
392
405
|
issuesEpoch: 0,
|
|
393
406
|
issuesSearchTimer: null,
|
|
@@ -418,6 +431,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
418
431
|
defaultAiState: { loading: false, saving: false, refreshRequestId: null, saveRequestId: null, catalogRequestIds: {}, catalogs: {}, preference: null, selection: null, installedVendors: [], accountAvailable: true, accountId: null, serverEpoch: null, canonicalRevision: 0, error: "" },
|
|
419
432
|
defaultAiDraft: { vendor: "", model: "", effort: "" },
|
|
420
433
|
defaultAiDraftDirty: false,
|
|
434
|
+
defaultVendorState: { loading: false, saving: false, getRequestId: null, saveRequestId: null, preference: null, preferencePresent: false, installedVendors: [], accountId: null, projectSlug: null, serverEpoch: null, canonicalRevision: 0, error: "" },
|
|
421
435
|
|
|
422
436
|
// dm
|
|
423
437
|
dmTargetUser: null,
|
|
@@ -434,6 +448,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
434
448
|
pendingShellCommandId: null,
|
|
435
449
|
mateProjectSlug: null,
|
|
436
450
|
myUserId: null,
|
|
451
|
+
contextViewPreferenceState: { mode: "off", canonicalMode: "off", preferencePresent: false, loading: false, saving: false, requestId: null, saveRequestId: null, pendingSaves: [], accountId: null, serverEpoch: null, rejectedEpoch: null, canonicalRevision: 0, error: "" },
|
|
452
|
+
contextViewOverride: null,
|
|
437
453
|
isMultiUserMode: false,
|
|
438
454
|
dmUnread: {},
|
|
439
455
|
dmRemovedUsers: {},
|
|
@@ -469,6 +485,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
469
485
|
lastVendor: "",
|
|
470
486
|
// Static adapter metadata sent before any vendor is initialized.
|
|
471
487
|
vendorInfo: {},
|
|
488
|
+
// Rate-limit data is projected only for the displayed session/vendor.
|
|
489
|
+
rateLimitState: {},
|
|
472
490
|
// How Claude sessions open: "gui" (default) or "tui". The server sends
|
|
473
491
|
// claude_open_mode_changed on connect; this seeds it beforehand so the
|
|
474
492
|
// new-session menu doesn't flash the TUI-only entry.
|
|
@@ -544,7 +562,11 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
544
562
|
newSessionBtn: newSessionBtn,
|
|
545
563
|
headerTitleEl: headerTitleEl,
|
|
546
564
|
showConfirm: showConfirm,
|
|
547
|
-
onFilesTabOpen: function () {
|
|
565
|
+
onFilesTabOpen: function () {
|
|
566
|
+
reopenFileViewer();
|
|
567
|
+
loadRootDirectory();
|
|
568
|
+
if (isSchedulerOpen()) closeScheduler();
|
|
569
|
+
},
|
|
548
570
|
requestKnowledgeList: function () { requestKnowledgeList(); },
|
|
549
571
|
switchProject: function (slug) { switchProject(slug); },
|
|
550
572
|
openTerminal: function () { openTerminal(); },
|
|
@@ -1009,7 +1031,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1009
1031
|
// the project Mate DM preference therefore hides only Mate shortcuts.
|
|
1010
1032
|
if (document.body) document.body.classList.add('is-multi-user');
|
|
1011
1033
|
}
|
|
1012
|
-
if (d.user && d.user.id) { store.set({ myUserId: d.user.id }); }
|
|
1034
|
+
if (d.user && d.user.id) { store.set({ myUserId: d.user.id }); requestDefaultVendor(); }
|
|
1013
1035
|
if (d.permissions) store.set({ permissions: d.permissions });
|
|
1014
1036
|
if (d.mustChangePin) showForceChangePinOverlay();
|
|
1015
1037
|
// Single-user mode: clear user strip skeletons immediately (no presence message will arrive)
|
|
@@ -1188,9 +1210,6 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1188
1210
|
// The browser refreshes from note messages without the canvas module having
|
|
1189
1211
|
// to import it, which would be a cycle.
|
|
1190
1212
|
setBrowserRefresh(function () { if (isNotesBrowserOpen()) renderNotesBrowser(); });
|
|
1191
|
-
// Opening the browser claims the single right workbench slot. Registered here
|
|
1192
|
-
// so the browser module never imports the other tools.
|
|
1193
|
-
registerExclusiveClosers([closeIssues, closeProjectLogs, closeScheduledTasks, closeFileViewer, closeTerminal]);
|
|
1194
1213
|
|
|
1195
1214
|
// --- Sticky Notes sidebar button (create new note) ---
|
|
1196
1215
|
var stickyNotesSidebarBtn = $("sticky-notes-sidebar-btn");
|
|
@@ -1229,10 +1248,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1229
1248
|
}
|
|
1230
1249
|
|
|
1231
1250
|
// Close the notes browser / scheduler panel when switching to other sidebar panels
|
|
1232
|
-
var fileBrowserBtn = $("file-browser-btn");
|
|
1233
1251
|
var gitPlacardMoreBtn = $("git-placard-more");
|
|
1234
1252
|
var terminalSidebarBtn = $("terminal-sidebar-btn");
|
|
1235
|
-
if (fileBrowserBtn) fileBrowserBtn.addEventListener("click", function () { closeIssues(); closeProjectLogs(); closeScheduledTasks(); if (isNotesBrowserOpen()) closeNotesBrowser(); if (isSchedulerOpen()) closeScheduler(); });
|
|
1236
1253
|
if (gitPlacardMoreBtn) gitPlacardMoreBtn.addEventListener("click", function () { closeIssues(); closeProjectLogs(); closeScheduledTasks(); if (isNotesBrowserOpen()) closeNotesBrowser(); if (isSchedulerOpen()) closeScheduler(); });
|
|
1237
1254
|
if (terminalSidebarBtn) terminalSidebarBtn.addEventListener("click", function () { closeIssues(); closeProjectLogs(); closeScheduledTasks(); if (isNotesBrowserOpen()) closeNotesBrowser(); if (isSchedulerOpen()) closeScheduler(); });
|
|
1238
1255
|
|
|
@@ -513,6 +513,7 @@ body.mate-dm-active .search-clay-transcript .search-clay-message-user .bubble,
|
|
|
513
513
|
@keyframes searchClaySpin { to { transform: rotate(360deg); } }
|
|
514
514
|
|
|
515
515
|
.clayos-session-link,
|
|
516
|
+
.clayos-issue-link,
|
|
516
517
|
.clayos-log-link {
|
|
517
518
|
display: inline-flex;
|
|
518
519
|
align-items: center;
|
|
@@ -531,6 +532,7 @@ body.mate-dm-active .search-clay-transcript .search-clay-message-user .bubble,
|
|
|
531
532
|
cursor: pointer;
|
|
532
533
|
}
|
|
533
534
|
.clayos-session-link::before,
|
|
535
|
+
.clayos-issue-link::before,
|
|
534
536
|
.clayos-log-link::before {
|
|
535
537
|
content: "\2197";
|
|
536
538
|
display: grid;
|
|
@@ -542,20 +544,28 @@ body.mate-dm-active .search-clay-transcript .search-clay-message-user .bubble,
|
|
|
542
544
|
color: var(--accent);
|
|
543
545
|
font-size: 12px;
|
|
544
546
|
}
|
|
547
|
+
.clayos-issue-link::before,
|
|
545
548
|
.clayos-log-link::before { content: "\2261"; }
|
|
546
549
|
.clayos-session-link > span,
|
|
550
|
+
.clayos-issue-link > span,
|
|
547
551
|
.clayos-log-link > span { font-weight: 620; }
|
|
548
552
|
.clayos-session-link > small,
|
|
553
|
+
.clayos-issue-link > small,
|
|
549
554
|
.clayos-log-link > small { color: var(--text-muted); font-size: 10px; }
|
|
550
555
|
.clayos-session-link:hover,
|
|
556
|
+
.clayos-issue-link:hover,
|
|
551
557
|
.clayos-log-link:hover { border-color: color-mix(in srgb, var(--accent) 52%, var(--border)); background: color-mix(in srgb, var(--accent) 11%, var(--bg-alt)); }
|
|
552
558
|
.clayos-session-link:focus-visible,
|
|
559
|
+
.clayos-issue-link:focus-visible,
|
|
553
560
|
.clayos-log-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
554
561
|
.clayos-session-link.is-loading,
|
|
562
|
+
.clayos-issue-link.is-loading,
|
|
555
563
|
.clayos-log-link.is-loading { opacity: 0.62; cursor: progress; }
|
|
556
564
|
.clayos-session-link.is-loading::before,
|
|
565
|
+
.clayos-issue-link.is-loading::before,
|
|
557
566
|
.clayos-log-link.is-loading::before { animation: searchClaySpin 1.2s linear infinite; }
|
|
558
567
|
.clayos-session-link.is-error,
|
|
568
|
+
.clayos-issue-link.is-error,
|
|
559
569
|
.clayos-log-link.is-error { border-color: color-mix(in srgb, var(--warning) 48%, var(--border)); }
|
|
560
570
|
|
|
561
571
|
.search-clay-pending {
|
|
@@ -913,3 +923,13 @@ body.mate-dm-active .search-clay-transcript .search-clay-message-user .bubble,
|
|
|
913
923
|
font-family: inherit;
|
|
914
924
|
color: var(--text-muted);
|
|
915
925
|
}
|
|
926
|
+
|
|
927
|
+
.clayos-issue-link { max-width: min(100%, 30em); box-sizing: border-box; }
|
|
928
|
+
.clayos-issue-link::before { content: "\25CE"; flex: 0 0 17px; }
|
|
929
|
+
.clayos-issue-link[data-status="in_progress"]::before { color: #bd923f; }
|
|
930
|
+
.clayos-issue-link[data-status="resolved"]::before { content: "\2713"; color: var(--brand-green); }
|
|
931
|
+
.clayos-issue-link[data-status="closed"]::before { content: "\00D7"; color: var(--text-dimmer); }
|
|
932
|
+
.clayos-issue-link > span { flex-shrink: 0; }
|
|
933
|
+
.clayos-issue-link > small { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
934
|
+
.clayos-log-link { max-width: 100%; box-sizing: border-box; }
|
|
935
|
+
.clayos-log-link > small { min-width: 0; overflow-wrap: anywhere; line-height: 1.35; }
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
border-bottom: 1px solid var(--filebrowser-border);
|
|
26
26
|
color: var(--text-secondary);
|
|
27
27
|
font-size: 12px;
|
|
28
|
-
font-weight:
|
|
28
|
+
font-weight: 600;
|
|
29
29
|
text-align: center;
|
|
30
30
|
flex-shrink: 0;
|
|
31
31
|
}
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
.git-repo-primary > svg { width: 15px; height: 15px; color: var(--accent); flex-shrink: 0; }
|
|
109
|
-
.git-repo-name { color: var(--text); font-size: 12px; font-weight:
|
|
109
|
+
.git-repo-name { color: var(--text); font-size: 12px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
110
110
|
.git-branch-name { color: var(--text-muted); font-size: 11px; font-weight: 500; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
111
111
|
|
|
112
112
|
.git-badges { display: flex; gap: 4px; margin: 7px 0 0 22px; flex-wrap: wrap; }
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
color: var(--text-dimmer);
|
|
118
118
|
background: var(--bg);
|
|
119
119
|
font-size: 9px;
|
|
120
|
-
font-weight:
|
|
120
|
+
font-weight: 500;
|
|
121
121
|
letter-spacing: 0.02em;
|
|
122
122
|
text-transform: uppercase;
|
|
123
123
|
}
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
background: var(--bg-alt);
|
|
150
150
|
color: var(--text-muted);
|
|
151
151
|
font-size: 11px;
|
|
152
|
-
font-weight:
|
|
152
|
+
font-weight: 500;
|
|
153
153
|
display: inline-flex;
|
|
154
154
|
align-items: center;
|
|
155
155
|
justify-content: center;
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
.git-action-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--text); }
|
|
161
161
|
.git-action-btn:disabled { opacity: 0.42; cursor: default; }
|
|
162
162
|
.git-action-btn svg { width: 13px; height: 13px; }
|
|
163
|
-
.git-sync-count { color: var(--accent); font-size: 10px; font-weight:
|
|
163
|
+
.git-sync-count { color: var(--accent); font-size: 10px; font-weight: 500; font-variant-numeric: tabular-nums; }
|
|
164
164
|
|
|
165
165
|
.git-review-all {
|
|
166
166
|
width: 100%;
|
|
@@ -180,6 +180,7 @@
|
|
|
180
180
|
}
|
|
181
181
|
.git-review-all:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--bg)); }
|
|
182
182
|
.git-review-all > span { display: inline-flex; align-items: center; gap: 6px; }
|
|
183
|
+
.git-review-all strong { font-weight: 500; }
|
|
183
184
|
.git-review-all svg { width: 12px; height: 12px; color: var(--accent); }
|
|
184
185
|
.git-review-count { color: var(--text-dimmer); font-size: 9px; font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
185
186
|
.git-review-count svg { width: 9px; height: 9px; color: currentColor; }
|
|
@@ -201,12 +202,12 @@
|
|
|
201
202
|
padding: 0 2px;
|
|
202
203
|
color: var(--text-secondary);
|
|
203
204
|
font-size: 10px;
|
|
204
|
-
font-weight:
|
|
205
|
+
font-weight: 600;
|
|
205
206
|
letter-spacing: 0.055em;
|
|
206
207
|
text-transform: uppercase;
|
|
207
208
|
flex-shrink: 0;
|
|
208
209
|
}
|
|
209
|
-
.git-section-count { color: var(--text-dimmer); font-size: 9px; font-weight:
|
|
210
|
+
.git-section-count { color: var(--text-dimmer); font-size: 9px; font-weight: 500; font-variant-numeric: tabular-nums; }
|
|
210
211
|
.git-section-header .git-action-btn { min-height: 22px; margin-left: auto; padding: 2px 7px; font-size: 9px; }
|
|
211
212
|
|
|
212
213
|
.git-file-list {
|
|
@@ -239,7 +240,7 @@
|
|
|
239
240
|
color: var(--text-dimmer);
|
|
240
241
|
font-family: inherit;
|
|
241
242
|
font-size: 9px;
|
|
242
|
-
font-weight:
|
|
243
|
+
font-weight: 600;
|
|
243
244
|
line-height: 1;
|
|
244
245
|
letter-spacing: -0.02em;
|
|
245
246
|
}
|
|
@@ -247,7 +248,7 @@
|
|
|
247
248
|
.git-file-status.conflicted { color: var(--danger, #d85b5b); }
|
|
248
249
|
.git-file-main { min-width: 0; padding: 5px 2px; cursor: pointer; outline: none; }
|
|
249
250
|
.git-file-main:focus-visible { border-radius: 4px; box-shadow: 0 0 0 1px var(--accent); }
|
|
250
|
-
.git-file-name { color: var(--text); font-size: 11px; font-weight:
|
|
251
|
+
.git-file-name { color: var(--text); font-size: 11px; font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
251
252
|
.git-file-subline {
|
|
252
253
|
display: flex;
|
|
253
254
|
align-items: center;
|
|
@@ -257,7 +258,7 @@
|
|
|
257
258
|
height: 14px;
|
|
258
259
|
color: var(--text-dimmer);
|
|
259
260
|
font-size: 9px;
|
|
260
|
-
font-weight:
|
|
261
|
+
font-weight: 400;
|
|
261
262
|
line-height: 1.2;
|
|
262
263
|
}
|
|
263
264
|
.git-file-dir { min-width: 24px; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
@@ -327,7 +328,7 @@
|
|
|
327
328
|
justify-content: center;
|
|
328
329
|
gap: 4px;
|
|
329
330
|
font-size: 10px;
|
|
330
|
-
font-weight:
|
|
331
|
+
font-weight: 500;
|
|
331
332
|
cursor: pointer;
|
|
332
333
|
white-space: nowrap;
|
|
333
334
|
}
|
|
@@ -405,7 +406,7 @@
|
|
|
405
406
|
background: color-mix(in srgb, var(--accent) 8%, var(--bg));
|
|
406
407
|
}
|
|
407
408
|
.git-agent-commit-icon svg { width: 14px; height: 14px; }
|
|
408
|
-
.git-agent-commit-copy strong { display: block; color: var(--text); font-size: 11px; line-height: 1.3; }
|
|
409
|
+
.git-agent-commit-copy strong { display: block; color: var(--text); font-size: 11px; font-weight: 600; line-height: 1.3; }
|
|
409
410
|
.git-agent-commit-copy span:not(.git-agent-commit-icon) { display: block; color: var(--text-dimmer); font-size: 9px; line-height: 1.4; margin-top: 2px; }
|
|
410
411
|
.git-agent-commit-btn { width: 100%; background: var(--accent); border-color: var(--accent); color: #fff; }
|
|
411
412
|
.git-agent-commit-btn:hover:not(:disabled) { color: #fff; filter: brightness(1.05); }
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
display: block;
|
|
46
46
|
color: var(--text);
|
|
47
47
|
font-size: 11px;
|
|
48
|
-
font-weight:
|
|
48
|
+
font-weight: 600;
|
|
49
49
|
line-height: 1.3;
|
|
50
50
|
overflow: hidden;
|
|
51
51
|
text-overflow: ellipsis;
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
background: var(--bg);
|
|
79
79
|
color: var(--text-dimmer);
|
|
80
80
|
font-size: 9px;
|
|
81
|
-
font-weight:
|
|
81
|
+
font-weight: 500;
|
|
82
82
|
letter-spacing: 0.02em;
|
|
83
83
|
text-transform: uppercase;
|
|
84
84
|
white-space: nowrap;
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
gap: 2px;
|
|
95
95
|
color: var(--text-dimmer);
|
|
96
96
|
font-size: 9px;
|
|
97
|
-
font-weight:
|
|
97
|
+
font-weight: 500;
|
|
98
98
|
font-variant-numeric: tabular-nums;
|
|
99
99
|
white-space: nowrap;
|
|
100
100
|
}
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
color: var(--text-dimmer);
|
|
134
134
|
font-family: inherit;
|
|
135
135
|
font-size: 9px;
|
|
136
|
-
font-weight:
|
|
136
|
+
font-weight: 500;
|
|
137
137
|
letter-spacing: 0.02em;
|
|
138
138
|
text-transform: uppercase;
|
|
139
139
|
cursor: pointer;
|