clay-server 4.1.0-beta.9 → 4.2.0-beta.1
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/daemon-project-access.js +14 -0
- package/lib/daemon.js +7 -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-issue-launch.js +3 -1
- 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 +39 -6
- package/lib/project-user-message.js +47 -0
- package/lib/project.js +57 -3
- package/lib/public/app.js +27 -9
- package/lib/public/css/avatar-imprints.css +1 -1
- package/lib/public/css/command-palette.css +57 -19
- package/lib/public/css/git-panel.css +13 -12
- package/lib/public/css/git-placard.css +4 -4
- package/lib/public/css/issues.css +79 -32
- 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/index.html +10 -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 +50 -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 +24 -2
- package/lib/public/modules/clay-log-links.js +12 -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/project-session-visibility-settings.js +138 -0
- package/lib/public/modules/project-settings.js +5 -0
- 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-projects.js +14 -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 +31 -7
- 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/session-visibility.js +62 -1
- package/lib/sessions.js +28 -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 +13 -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;
|
|
@@ -552,7 +555,7 @@ function attachSessions(ctx) {
|
|
|
552
555
|
}
|
|
553
556
|
sm.sweepBlankSessions();
|
|
554
557
|
var sessionOpts = {
|
|
555
|
-
sessionVisibility:
|
|
558
|
+
sessionVisibility: "private",
|
|
556
559
|
vendor: prepared.runtime.vendor,
|
|
557
560
|
model: prepared.runtime.model,
|
|
558
561
|
effort: prepared.runtime.effort || null,
|
|
@@ -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;
|
|
@@ -615,7 +619,15 @@ function attachSessions(ctx) {
|
|
|
615
619
|
sm.sweepBlankSessions();
|
|
616
620
|
var sessionOpts = {};
|
|
617
621
|
if (ws._clayUser && usersModule.isMultiUser()) sessionOpts.ownerId = ws._clayUser.id;
|
|
618
|
-
|
|
622
|
+
// Only ordinary project conversations may opt into this setting.
|
|
623
|
+
// Scheduled interviews and background/worker creation paths remain explicit.
|
|
624
|
+
var visibilityChoice = sessionVisibility.resolveNewSessionVisibility(getProjectAccess(), msg, isMate);
|
|
625
|
+
if (visibilityChoice.error) {
|
|
626
|
+
scheduledRequestError(ws, msg, visibilityChoice.error);
|
|
627
|
+
if (!msg.requestId) sendTo(ws, { type: "error", text: visibilityChoice.error });
|
|
628
|
+
return true;
|
|
629
|
+
}
|
|
630
|
+
sessionOpts.sessionVisibility = visibilityChoice.visibility;
|
|
619
631
|
if (msg.vendor) sessionOpts.vendor = msg.vendor;
|
|
620
632
|
// Mode resolution: vendors without a TUI session mode are always GUI.
|
|
621
633
|
// TUI-capable sessions honor the explicit msg.mode if provided, otherwise
|
|
@@ -697,8 +709,7 @@ function attachSessions(ctx) {
|
|
|
697
709
|
if (reusable) {
|
|
698
710
|
if (sessionOpts.vendor && reusable.vendor !== sessionOpts.vendor) reusable.vendor = sessionOpts.vendor;
|
|
699
711
|
if (!reusable.effort) reusable.effort = sessionOpts.effort;
|
|
700
|
-
|
|
701
|
-
sessionVisibility.revokeViewers(ctx, reusable);
|
|
712
|
+
// Reusable blanks already exist; do not retroactively change them.
|
|
702
713
|
sm.switchSession(reusable.localId, ws);
|
|
703
714
|
newSess = reusable;
|
|
704
715
|
} else {
|
|
@@ -731,6 +742,14 @@ function attachSessions(ctx) {
|
|
|
731
742
|
return true;
|
|
732
743
|
}
|
|
733
744
|
|
|
745
|
+
if (msg.type === "set_project_session_visibility_default") {
|
|
746
|
+
sessionVisibility.handleDefaultChange({
|
|
747
|
+
slug: slug, isMate: isMate, osUsers: osUsers, usersModule: usersModule, getProjectAccess: getProjectAccess,
|
|
748
|
+
opts: opts, sendTo: sendTo,
|
|
749
|
+
}, ws, msg);
|
|
750
|
+
return true;
|
|
751
|
+
}
|
|
752
|
+
|
|
734
753
|
if (msg.type === "set_session_bookmark") {
|
|
735
754
|
if (typeof msg.sessionId === "number") {
|
|
736
755
|
var bookmarkTarget = sm.sessions.get(msg.sessionId);
|
|
@@ -981,6 +1000,8 @@ function attachSessions(ctx) {
|
|
|
981
1000
|
if (msg.id && sm.sessions.has(msg.id) && msg.title) {
|
|
982
1001
|
var s = sm.sessions.get(msg.id);
|
|
983
1002
|
s.title = String(msg.title).substring(0, 100);
|
|
1003
|
+
s.titleProvisional = false;
|
|
1004
|
+
s.titleAutoGenerated = false;
|
|
984
1005
|
s.titleManuallySet = true;
|
|
985
1006
|
sm.saveSessionFile(s);
|
|
986
1007
|
sm.notifySessionRenamed(s.localId);
|
|
@@ -1487,7 +1508,11 @@ function attachSessions(ctx) {
|
|
|
1487
1508
|
} else {
|
|
1488
1509
|
forkHistory = session.history.slice();
|
|
1489
1510
|
}
|
|
1490
|
-
var forked = sm.createSession({
|
|
1511
|
+
var forked = sm.createSession({
|
|
1512
|
+
vendor: session.vendor,
|
|
1513
|
+
ownerId: session.ownerId || null,
|
|
1514
|
+
sessionVisibility: sessionVisibility.normalize(session.sessionVisibility),
|
|
1515
|
+
}, ws);
|
|
1491
1516
|
forked.cliSessionId = result.sessionId;
|
|
1492
1517
|
forked.title = forkTitle;
|
|
1493
1518
|
forked.history = forkHistory;
|
|
@@ -1505,7 +1530,14 @@ function attachSessions(ctx) {
|
|
|
1505
1530
|
// Read history from CLI session files
|
|
1506
1531
|
var cliSess = require("./cli-sessions");
|
|
1507
1532
|
return cliSess.readCliSessionHistory(resolveSessionHome(session), cwd, result.sessionId).then(function(history) {
|
|
1508
|
-
var forked = sm.resumeSession(result.sessionId, {
|
|
1533
|
+
var forked = sm.resumeSession(result.sessionId, {
|
|
1534
|
+
history: history,
|
|
1535
|
+
title: forkTitle,
|
|
1536
|
+
vendor: session.vendor,
|
|
1537
|
+
ownerId: session.ownerId || null,
|
|
1538
|
+
sessionVisibility: sessionVisibility.normalize(session.sessionVisibility),
|
|
1539
|
+
sessionVisibilityExplicit: session.sessionVisibilityExplicit === true,
|
|
1540
|
+
}, ws);
|
|
1509
1541
|
if (forked) {
|
|
1510
1542
|
ws._clayActiveSession = forked.localId;
|
|
1511
1543
|
sendTo(ws, { type: "fork_complete", sessionId: forked.localId });
|
|
@@ -1679,6 +1711,7 @@ function attachSessions(ctx) {
|
|
|
1679
1711
|
return true;
|
|
1680
1712
|
}
|
|
1681
1713
|
|
|
1714
|
+
if (decision === "allow_always" && pending.suppressAlwaysAllowRule) decision = "allow";
|
|
1682
1715
|
if (decision === "allow" || decision === "allow_always") {
|
|
1683
1716
|
if (decision === "allow_always") {
|
|
1684
1717
|
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) {
|
|
@@ -774,6 +794,10 @@ function createProjectContext(opts) {
|
|
|
774
794
|
var _issueWork = require("./project-issue-launch").attachIssueLaunch({
|
|
775
795
|
sm: sm, resolveDefaultAi: opts.resolveDefaultAi, getSdk: function () { return sdk; },
|
|
776
796
|
getLinuxUserForSession: getLinuxUserForSession, osUsers: osUsers,
|
|
797
|
+
getProjectAccess: function () {
|
|
798
|
+
if (isMate) return { visibility: "private", ownerId: projectOwnerId || null, allowedUsers: [] };
|
|
799
|
+
return opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null };
|
|
800
|
+
},
|
|
777
801
|
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
778
802
|
canStartWork: function (ws, actor) { return clients.has(ws) && ws.readyState === 1 && ws._clayUser === actor; },
|
|
779
803
|
onProcessingChanged: onProcessingChanged, sendTo: sendTo,
|
|
@@ -1217,6 +1241,7 @@ function createProjectContext(opts) {
|
|
|
1217
1241
|
clayPort: serverPort,
|
|
1218
1242
|
clayTls: serverTls,
|
|
1219
1243
|
clayAuthToken: serverAuthToken,
|
|
1244
|
+
clayBridgeToken: mcpBridgeToken,
|
|
1220
1245
|
getWorkerPermissionRouter: function () {
|
|
1221
1246
|
return isMate ? null : _sessionPair.workerPermission;
|
|
1222
1247
|
},
|
|
@@ -1413,6 +1438,9 @@ function createProjectContext(opts) {
|
|
|
1413
1438
|
canExecuteScheduledTask: function (record) {
|
|
1414
1439
|
return !!(_scheduledTaskExecution && _scheduledTaskExecution.runnable(record).ok);
|
|
1415
1440
|
},
|
|
1441
|
+
onScheduledRunTerminal: function (record, run) {
|
|
1442
|
+
if (_scheduledTaskExecution) _scheduledTaskExecution.recordTerminal(record, run);
|
|
1443
|
+
},
|
|
1416
1444
|
onProcessingChanged: onProcessingChanged,
|
|
1417
1445
|
hydrateImageRefs: hydrateImageRefs,
|
|
1418
1446
|
});
|
|
@@ -1428,6 +1456,7 @@ function createProjectContext(opts) {
|
|
|
1428
1456
|
getSdk: function () { return sdk; }, getLinuxUserForSession: getLinuxUserForSession,
|
|
1429
1457
|
requiresLinuxUser: function () { return osUsers; },
|
|
1430
1458
|
onProcessingChanged: onProcessingChanged,
|
|
1459
|
+
recordResult: function (result) { return _projectLogs.recordScheduledResult(result); },
|
|
1431
1460
|
authorize: function (record) {
|
|
1432
1461
|
return authorizeStoredOwner(record, {
|
|
1433
1462
|
usersModule: usersModule, osUsers: osUsers,
|
|
@@ -1437,6 +1466,7 @@ function createProjectContext(opts) {
|
|
|
1437
1466
|
});
|
|
1438
1467
|
},
|
|
1439
1468
|
});
|
|
1469
|
+
setTimeout(function () { _scheduledTaskExecution.syncTerminalResults(); }, 0);
|
|
1440
1470
|
|
|
1441
1471
|
_scheduledTasks = attachScheduledTasks({
|
|
1442
1472
|
cwd: cwd,
|
|
@@ -1583,8 +1613,8 @@ function createProjectContext(opts) {
|
|
|
1583
1613
|
}
|
|
1584
1614
|
|
|
1585
1615
|
// --- 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);
|
|
1616
|
+
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") {
|
|
1617
|
+
if (typeof opts.onDmMessage === "function") opts.onDmMessage(ws, msg, slug);
|
|
1588
1618
|
return;
|
|
1589
1619
|
}
|
|
1590
1620
|
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 +1893,12 @@ function createProjectContext(opts) {
|
|
|
1863
1893
|
}
|
|
1864
1894
|
|
|
1865
1895
|
// --- Sessions/config/project handler (delegated to project-sessions.js) ---
|
|
1896
|
+
var _sessionSkillCatalog = createSessionSkillCatalog({
|
|
1897
|
+
cwd: cwd,
|
|
1898
|
+
osUsers: osUsers,
|
|
1899
|
+
getLinuxUser: getLinuxUserForSession,
|
|
1900
|
+
});
|
|
1901
|
+
sm.setSessionHydrator(_sessionSkillCatalog.hydrate);
|
|
1866
1902
|
var _sessions = attachSessions({
|
|
1867
1903
|
cwd: cwd,
|
|
1868
1904
|
slug: slug,
|
|
@@ -1902,6 +1938,7 @@ function createProjectContext(opts) {
|
|
|
1902
1938
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
1903
1939
|
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
1904
1940
|
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
1941
|
+
hydrateSkillCatalog: _sessionSkillCatalog.hydrate,
|
|
1905
1942
|
hydrateImageRefs: hydrateImageRefs,
|
|
1906
1943
|
onProcessingChanged: onProcessingChanged,
|
|
1907
1944
|
broadcastPresence: broadcastPresence,
|
|
@@ -1931,6 +1968,7 @@ function createProjectContext(opts) {
|
|
|
1931
1968
|
saveContextSources: saveContextSources,
|
|
1932
1969
|
_email: _email,
|
|
1933
1970
|
_notifications: _notifications,
|
|
1971
|
+
_projectLogs: _projectLogs,
|
|
1934
1972
|
});
|
|
1935
1973
|
|
|
1936
1974
|
var _models = attachModels({
|
|
@@ -2030,6 +2068,8 @@ function createProjectContext(opts) {
|
|
|
2030
2068
|
getSessionForWs: getSessionForWs,
|
|
2031
2069
|
getLinuxUserForSession: getLinuxUserForSession,
|
|
2032
2070
|
ensureProjectAccessForSession: ensureProjectAccessForSession,
|
|
2071
|
+
getProjectAccess: function () { return opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public", ownerId: projectOwnerId || null }; },
|
|
2072
|
+
canAccessProjectSlug: opts.canAccessProjectSlug || function () { return !usersModule.isMultiUser(); },
|
|
2033
2073
|
getOsUserInfoForWs: getOsUserInfoForWs,
|
|
2034
2074
|
hydrateImageRefs: hydrateImageRefs,
|
|
2035
2075
|
saveImageFile: saveImageFile,
|
|
@@ -2112,6 +2152,12 @@ function createProjectContext(opts) {
|
|
|
2112
2152
|
function getMcpBridgeHandler(sessionId, sessionOnly, queryGeneration) {
|
|
2113
2153
|
var boundSession = Number.isInteger(sessionId) ? sm.sessions.get(sessionId) : null;
|
|
2114
2154
|
var queryToolBridge = createSessionQueryToolBridge({ session: boundSession, sdk: sdk });
|
|
2155
|
+
function sessionQueryValid() {
|
|
2156
|
+
return !!boundSession
|
|
2157
|
+
&& Number.isInteger(queryGeneration)
|
|
2158
|
+
&& sm.sessions.get(boundSession.localId) === boundSession
|
|
2159
|
+
&& Number(boundSession._sdkQueryGeneration || 0) === queryGeneration;
|
|
2160
|
+
}
|
|
2115
2161
|
// Build set of local MCP server names to exclude (Codex handles these natively)
|
|
2116
2162
|
var localMcpNames = {};
|
|
2117
2163
|
try {
|
|
@@ -2126,6 +2172,7 @@ function createProjectContext(opts) {
|
|
|
2126
2172
|
return {
|
|
2127
2173
|
listTools: function () {
|
|
2128
2174
|
var tools = [];
|
|
2175
|
+
if (sessionOnly && !sessionQueryValid()) return Promise.resolve(tools);
|
|
2129
2176
|
var toJSONSchema;
|
|
2130
2177
|
var zod;
|
|
2131
2178
|
try { zod = require("zod"); toJSONSchema = zod.toJSONSchema; } catch (e) { /* fallback */ }
|
|
@@ -2251,6 +2298,9 @@ function createProjectContext(opts) {
|
|
|
2251
2298
|
return Promise.resolve(tools);
|
|
2252
2299
|
},
|
|
2253
2300
|
callTool: function (serverName, toolName, args) {
|
|
2301
|
+
if (sessionOnly && !sessionQueryValid()) {
|
|
2302
|
+
return Promise.reject(new Error("Session tool unavailable or older query: " + serverName + "/" + toolName));
|
|
2303
|
+
}
|
|
2254
2304
|
var queryCall = queryToolBridge.callTool(queryGeneration, serverName, toolName, args);
|
|
2255
2305
|
if (queryCall) return queryCall;
|
|
2256
2306
|
if (boundSession && serverName === "clay-sessions") {
|
|
@@ -2409,6 +2459,7 @@ function createProjectContext(opts) {
|
|
|
2409
2459
|
getLatestVersion: function () { return latestVersion; },
|
|
2410
2460
|
getTitle: function () { return title; },
|
|
2411
2461
|
getProject: function () { return project; },
|
|
2462
|
+
hydrateSkillCatalog: _sessionSkillCatalog.hydrate,
|
|
2412
2463
|
// Exposed so the first websocket connection can lazily warm up the
|
|
2413
2464
|
// adapters for this project (see project-connection handleConnection).
|
|
2414
2465
|
warmup: function (linuxUser) {
|
|
@@ -2633,6 +2684,9 @@ function createProjectContext(opts) {
|
|
|
2633
2684
|
handleDisconnection: handleDisconnection,
|
|
2634
2685
|
handleHTTP: handleHTTP,
|
|
2635
2686
|
getMcpBridgeHandler: getMcpBridgeHandler,
|
|
2687
|
+
isMcpBridgeAuthenticated: function (req) {
|
|
2688
|
+
return !!(req && req.headers && req.headers["x-clay-bridge-token"] && req.headers["x-clay-bridge-token"] === mcpBridgeToken);
|
|
2689
|
+
},
|
|
2636
2690
|
getStatus: getStatus,
|
|
2637
2691
|
getSessionManager: function () { return sm; },
|
|
2638
2692
|
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,8 @@ 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: "" },
|
|
435
|
+
projectSessionVisibilityState: { active: null, pending: null },
|
|
421
436
|
|
|
422
437
|
// dm
|
|
423
438
|
dmTargetUser: null,
|
|
@@ -434,6 +449,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
434
449
|
pendingShellCommandId: null,
|
|
435
450
|
mateProjectSlug: null,
|
|
436
451
|
myUserId: null,
|
|
452
|
+
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: "" },
|
|
453
|
+
contextViewOverride: null,
|
|
437
454
|
isMultiUserMode: false,
|
|
438
455
|
dmUnread: {},
|
|
439
456
|
dmRemovedUsers: {},
|
|
@@ -469,6 +486,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
469
486
|
lastVendor: "",
|
|
470
487
|
// Static adapter metadata sent before any vendor is initialized.
|
|
471
488
|
vendorInfo: {},
|
|
489
|
+
// Rate-limit data is projected only for the displayed session/vendor.
|
|
490
|
+
rateLimitState: {},
|
|
472
491
|
// How Claude sessions open: "gui" (default) or "tui". The server sends
|
|
473
492
|
// claude_open_mode_changed on connect; this seeds it beforehand so the
|
|
474
493
|
// new-session menu doesn't flash the TUI-only entry.
|
|
@@ -544,7 +563,11 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
544
563
|
newSessionBtn: newSessionBtn,
|
|
545
564
|
headerTitleEl: headerTitleEl,
|
|
546
565
|
showConfirm: showConfirm,
|
|
547
|
-
onFilesTabOpen: function () {
|
|
566
|
+
onFilesTabOpen: function () {
|
|
567
|
+
reopenFileViewer();
|
|
568
|
+
loadRootDirectory();
|
|
569
|
+
if (isSchedulerOpen()) closeScheduler();
|
|
570
|
+
},
|
|
548
571
|
requestKnowledgeList: function () { requestKnowledgeList(); },
|
|
549
572
|
switchProject: function (slug) { switchProject(slug); },
|
|
550
573
|
openTerminal: function () { openTerminal(); },
|
|
@@ -1009,7 +1032,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1009
1032
|
// the project Mate DM preference therefore hides only Mate shortcuts.
|
|
1010
1033
|
if (document.body) document.body.classList.add('is-multi-user');
|
|
1011
1034
|
}
|
|
1012
|
-
if (d.user && d.user.id) { store.set({ myUserId: d.user.id }); }
|
|
1035
|
+
if (d.user && d.user.id) { store.set({ myUserId: d.user.id }); requestDefaultVendor(); }
|
|
1013
1036
|
if (d.permissions) store.set({ permissions: d.permissions });
|
|
1014
1037
|
if (d.mustChangePin) showForceChangePinOverlay();
|
|
1015
1038
|
// Single-user mode: clear user strip skeletons immediately (no presence message will arrive)
|
|
@@ -1188,9 +1211,6 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1188
1211
|
// The browser refreshes from note messages without the canvas module having
|
|
1189
1212
|
// to import it, which would be a cycle.
|
|
1190
1213
|
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
1214
|
|
|
1195
1215
|
// --- Sticky Notes sidebar button (create new note) ---
|
|
1196
1216
|
var stickyNotesSidebarBtn = $("sticky-notes-sidebar-btn");
|
|
@@ -1229,10 +1249,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1229
1249
|
}
|
|
1230
1250
|
|
|
1231
1251
|
// Close the notes browser / scheduler panel when switching to other sidebar panels
|
|
1232
|
-
var fileBrowserBtn = $("file-browser-btn");
|
|
1233
1252
|
var gitPlacardMoreBtn = $("git-placard-more");
|
|
1234
1253
|
var terminalSidebarBtn = $("terminal-sidebar-btn");
|
|
1235
|
-
if (fileBrowserBtn) fileBrowserBtn.addEventListener("click", function () { closeIssues(); closeProjectLogs(); closeScheduledTasks(); if (isNotesBrowserOpen()) closeNotesBrowser(); if (isSchedulerOpen()) closeScheduler(); });
|
|
1236
1254
|
if (gitPlacardMoreBtn) gitPlacardMoreBtn.addEventListener("click", function () { closeIssues(); closeProjectLogs(); closeScheduledTasks(); if (isNotesBrowserOpen()) closeNotesBrowser(); if (isSchedulerOpen()) closeScheduler(); });
|
|
1237
1255
|
if (terminalSidebarBtn) terminalSidebarBtn.addEventListener("click", function () { closeIssues(); closeProjectLogs(); closeScheduledTasks(); if (isNotesBrowserOpen()) closeNotesBrowser(); if (isSchedulerOpen()) closeScheduler(); });
|
|
1238
1256
|
|
|
@@ -512,8 +512,45 @@ body.mate-dm-active .search-clay-transcript .search-clay-message-user .bubble,
|
|
|
512
512
|
.search-clay-activity-item small { color: var(--text-dimmer); font-size: 10px; line-height: 1.35; }
|
|
513
513
|
@keyframes searchClaySpin { to { transform: rotate(360deg); } }
|
|
514
514
|
|
|
515
|
-
.clayos-
|
|
516
|
-
|
|
515
|
+
.clayos-record-link {
|
|
516
|
+
display: inline-flex;
|
|
517
|
+
align-items: center;
|
|
518
|
+
gap: 6px;
|
|
519
|
+
min-height: 28px;
|
|
520
|
+
margin: 2px 1px;
|
|
521
|
+
padding: 3px 8px 3px 6px;
|
|
522
|
+
border: 1px solid color-mix(in srgb, var(--record-color, var(--accent)) 32%, var(--border));
|
|
523
|
+
border-radius: 8px;
|
|
524
|
+
background: color-mix(in srgb, var(--record-color, var(--accent)) 7%, var(--bg-alt));
|
|
525
|
+
color: var(--text);
|
|
526
|
+
font: inherit;
|
|
527
|
+
font-size: 11px;
|
|
528
|
+
line-height: 1;
|
|
529
|
+
vertical-align: middle;
|
|
530
|
+
cursor: pointer;
|
|
531
|
+
}
|
|
532
|
+
.clayos-record-link::before {
|
|
533
|
+
content: "\2197";
|
|
534
|
+
display: grid;
|
|
535
|
+
place-items: center;
|
|
536
|
+
width: 17px;
|
|
537
|
+
height: 17px;
|
|
538
|
+
border-radius: 5px;
|
|
539
|
+
background: color-mix(in srgb, var(--record-color, var(--accent)) 14%, transparent);
|
|
540
|
+
color: var(--record-color, var(--accent));
|
|
541
|
+
font-size: 12px;
|
|
542
|
+
}
|
|
543
|
+
.clayos-record-link > span { font-weight: 620; }
|
|
544
|
+
.clayos-record-link > small { min-width: 0; max-width: 28em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-inline-start: 1px solid color-mix(in srgb, currentColor 22%, transparent); padding-inline-start: 6px; color: var(--text-muted); font-size: 11px; }
|
|
545
|
+
.clayos-record-link:hover { border-color: color-mix(in srgb, var(--record-color, var(--accent)) 58%, var(--border)); background: color-mix(in srgb, var(--record-color, var(--accent)) 11%, var(--bg-alt)); }
|
|
546
|
+
.clayos-record-link:focus-visible { outline: 2px solid var(--record-color, var(--accent)); outline-offset: 2px; }
|
|
547
|
+
.clayos-record-link.is-loading { opacity: 0.62; cursor: progress; }
|
|
548
|
+
.clayos-record-link.is-loading::before { animation: searchClaySpin 1.2s linear infinite; }
|
|
549
|
+
.clayos-record-link.is-error { border-color: color-mix(in srgb, var(--warning) 48%, var(--border)); }
|
|
550
|
+
.clayos-issue-link { --record-color: var(--link, var(--accent)); }
|
|
551
|
+
.clayos-log-link { --record-color: var(--accent); }
|
|
552
|
+
|
|
553
|
+
.clayos-session-link {
|
|
517
554
|
display: inline-flex;
|
|
518
555
|
align-items: center;
|
|
519
556
|
gap: 6px;
|
|
@@ -530,8 +567,7 @@ body.mate-dm-active .search-clay-transcript .search-clay-message-user .bubble,
|
|
|
530
567
|
vertical-align: middle;
|
|
531
568
|
cursor: pointer;
|
|
532
569
|
}
|
|
533
|
-
.clayos-session-link::before
|
|
534
|
-
.clayos-log-link::before {
|
|
570
|
+
.clayos-session-link::before {
|
|
535
571
|
content: "\2197";
|
|
536
572
|
display: grid;
|
|
537
573
|
place-items: center;
|
|
@@ -542,21 +578,13 @@ body.mate-dm-active .search-clay-transcript .search-clay-message-user .bubble,
|
|
|
542
578
|
color: var(--accent);
|
|
543
579
|
font-size: 12px;
|
|
544
580
|
}
|
|
545
|
-
.clayos-
|
|
546
|
-
.clayos-session-link >
|
|
547
|
-
.clayos-
|
|
548
|
-
.clayos-session-link
|
|
549
|
-
.clayos-
|
|
550
|
-
.clayos-session-link:
|
|
551
|
-
.clayos-
|
|
552
|
-
.clayos-session-link:focus-visible,
|
|
553
|
-
.clayos-log-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
554
|
-
.clayos-session-link.is-loading,
|
|
555
|
-
.clayos-log-link.is-loading { opacity: 0.62; cursor: progress; }
|
|
556
|
-
.clayos-session-link.is-loading::before,
|
|
557
|
-
.clayos-log-link.is-loading::before { animation: searchClaySpin 1.2s linear infinite; }
|
|
558
|
-
.clayos-session-link.is-error,
|
|
559
|
-
.clayos-log-link.is-error { border-color: color-mix(in srgb, var(--warning) 48%, var(--border)); }
|
|
581
|
+
.clayos-session-link > span { font-weight: 620; }
|
|
582
|
+
.clayos-session-link > small { color: var(--text-muted); font-size: 10px; }
|
|
583
|
+
.clayos-session-link:hover { border-color: color-mix(in srgb, var(--accent) 52%, var(--border)); background: color-mix(in srgb, var(--accent) 11%, var(--bg-alt)); }
|
|
584
|
+
.clayos-session-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
585
|
+
.clayos-session-link.is-loading { opacity: 0.62; cursor: progress; }
|
|
586
|
+
.clayos-session-link.is-loading::before { animation: searchClaySpin 1.2s linear infinite; }
|
|
587
|
+
.clayos-session-link.is-error { border-color: color-mix(in srgb, var(--warning) 48%, var(--border)); }
|
|
560
588
|
|
|
561
589
|
.search-clay-pending {
|
|
562
590
|
align-self: flex-start;
|
|
@@ -913,3 +941,13 @@ body.mate-dm-active .search-clay-transcript .search-clay-message-user .bubble,
|
|
|
913
941
|
font-family: inherit;
|
|
914
942
|
color: var(--text-muted);
|
|
915
943
|
}
|
|
944
|
+
|
|
945
|
+
.clayos-issue-link { max-width: min(100%, 30em); box-sizing: border-box; }
|
|
946
|
+
.clayos-issue-link::before,
|
|
947
|
+
.clayos-log-link::before { content: "\2261"; }
|
|
948
|
+
.clayos-issue-link::before { content: "\25CE"; flex: 0 0 17px; }
|
|
949
|
+
.clayos-issue-link[data-status="in_progress"]::before { color: var(--warning, var(--accent)); }
|
|
950
|
+
.clayos-issue-link[data-status="resolved"]::before { content: "\2713"; color: var(--success, var(--accent)); }
|
|
951
|
+
.clayos-issue-link[data-status="closed"]::before { content: "\00D7"; color: var(--text-dimmer); }
|
|
952
|
+
.clayos-issue-link > span { flex-shrink: 0; }
|
|
953
|
+
.clayos-log-link { max-width: 100%; box-sizing: border-box; }
|