clay-server 5.2.0-beta.6 → 5.2.0-beta.8
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/clay-control-presentation-binding.js +96 -0
- package/lib/clay-control-presentation.js +128 -0
- package/lib/clay-control-target-projection.js +26 -0
- package/lib/clay-mate-chat.js +1 -0
- package/lib/clay-mate-knowledge.js +1 -1
- package/lib/clay-product-control-tools.js +1 -1
- package/lib/clay-product-control.js +22 -12
- package/lib/clay-project-records.js +2 -1
- package/lib/clay-scheduling.js +1 -1
- package/lib/clay-screen-controls.js +13 -5
- package/lib/clay-workspace-controls.js +2 -1
- package/lib/contextual-screen-snapshot.js +38 -0
- package/lib/mate-context-service.js +138 -0
- package/lib/mate-context-tools.js +21 -0
- package/lib/project-connection.js +8 -5
- package/lib/project-control-git-view.js +12 -0
- package/lib/project-filesystem.js +5 -1
- package/lib/project-http.js +3 -0
- package/lib/project-notifications.js +5 -4
- package/lib/project-product-control.js +3 -1
- package/lib/project-scheduled-messages.js +4 -4
- package/lib/project-scheduled-task-control.js +1 -1
- package/lib/project-session-document.js +20 -5
- package/lib/project-shared-browser.js +22 -5
- package/lib/project-studio-presentation.js +58 -0
- package/lib/project-user-message.js +36 -0
- package/lib/project-workspace-query.js +11 -1
- package/lib/project.js +24 -7
- package/lib/public/app.js +24 -0
- package/lib/public/appearance-bootstrap.js +2 -0
- package/lib/public/css/contextual-clay.css +240 -0
- package/lib/public/modules/app-favicon.js +7 -7
- package/lib/public/modules/app-message-router.js +5 -1
- package/lib/public/modules/app-messages.js +14 -1
- package/lib/public/modules/app-notifications.js +10 -3
- package/lib/public/modules/app-projects.js +3 -0
- package/lib/public/modules/clay-control-activity.js +214 -0
- package/lib/public/modules/clay-control-copy.js +36 -0
- package/lib/public/modules/clay-control-detail-targets.js +44 -0
- package/lib/public/modules/clay-control-object-targets.js +52 -0
- package/lib/public/modules/clay-control-target-visibility.js +12 -0
- package/lib/public/modules/clay-control-targets.js +44 -0
- package/lib/public/modules/clay-navigation-render.js +52 -0
- package/lib/public/modules/clay-owner-navigation.js +11 -2
- package/lib/public/modules/clay-session-links.js +31 -0
- package/lib/public/modules/clay-studio-bridge.js +20 -0
- package/lib/public/modules/clay-studio-document.js +67 -0
- package/lib/public/modules/clay-studio-render.js +144 -0
- package/lib/public/modules/clay-tool-presentation.js +4 -0
- package/lib/public/modules/command-palette.js +26 -31
- package/lib/public/modules/contextual-ask-session.js +26 -0
- package/lib/public/modules/contextual-clay-geometry.js +155 -0
- package/lib/public/modules/contextual-clay-session.js +130 -0
- package/lib/public/modules/contextual-clay-workspace.js +157 -0
- package/lib/public/modules/contextual-clay.js +237 -0
- package/lib/public/modules/contextual-composer.js +91 -0
- package/lib/public/modules/contextual-mate-context.js +115 -0
- package/lib/public/modules/contextual-mate-hint.js +40 -0
- package/lib/public/modules/contextual-mate-identity.js +23 -0
- package/lib/public/modules/contextual-mate-sessions.js +134 -0
- package/lib/public/modules/contextual-search.js +137 -0
- package/lib/public/modules/contextual-session-citations.js +58 -0
- package/lib/public/modules/filebrowser.js +20 -1
- package/lib/public/modules/generation-stop.js +8 -5
- package/lib/public/modules/git-panel.js +3 -1
- package/lib/public/modules/icon-strip-tooltip.js +2 -1
- package/lib/public/modules/input.js +35 -1
- package/lib/public/modules/issues-render.js +3 -2
- package/lib/public/modules/knowledge-db-workbench.js +4 -4
- package/lib/public/modules/markdown.js +2 -34
- package/lib/public/modules/mate-knowledge-workbench.js +1 -1
- package/lib/public/modules/message-delivery.js +10 -0
- package/lib/public/modules/pane-bridge.js +2 -2
- package/lib/public/modules/pending-message-queue.js +1 -0
- package/lib/public/modules/product-review.js +26 -0
- package/lib/public/modules/project-chat-identity.js +13 -4
- package/lib/public/modules/project-logs-render.js +3 -0
- package/lib/public/modules/project-mate-navigation.js +58 -21
- package/lib/public/modules/scheduled-tasks.js +2 -0
- package/lib/public/modules/search-clay-chat.js +5 -454
- package/lib/public/modules/shared-browser.js +2 -0
- package/lib/public/modules/sidebar-mobile.js +4 -3
- package/lib/public/modules/sidebar-projects.js +1 -0
- package/lib/public/modules/sidebar-sessions.js +1 -0
- package/lib/public/modules/split-view.js +7 -16
- package/lib/public/modules/stt.js +7 -2
- package/lib/public/modules/terminal.js +9 -0
- package/lib/public/modules/tools.js +4 -1
- package/lib/public/modules/wireframe-workbench.js +5 -2
- package/lib/public/style.css +2 -0
- package/lib/sdk-bridge.js +4 -0
- package/lib/server-contextual-clay-settings.js +40 -0
- package/lib/server-contextual-mate-sessions.js +70 -0
- package/lib/server-home-chat.js +7 -1
- package/lib/server-home-clay-entry.js +23 -4
- package/lib/server-home-clay-session-links.js +12 -0
- package/lib/server-owner-ui.js +49 -8
- package/lib/server-settings.js +2 -0
- package/lib/server.js +17 -0
- package/lib/sessions.js +10 -3
- package/lib/terminal-manager.js +18 -11
- package/lib/users-contextual-clay-preferences.js +31 -0
- package/lib/users.js +3 -0
- package/lib/workspace-assignment-service.js +25 -0
- package/lib/workspace-query-mcp-server.js +1 -1
- package/lib/ws-request.js +1 -0
- package/lib/ws-schema.js +10 -0
- package/lib/yoke/claude-hook-installer.js +4 -0
- package/package.json +1 -1
|
@@ -49,6 +49,7 @@ function attachUserMessage(ctx) {
|
|
|
49
49
|
|
|
50
50
|
var clients = ctx.clients;
|
|
51
51
|
var opts = ctx.opts;
|
|
52
|
+
var snapshotService = require('./contextual-screen-snapshot').attachContextualScreenSnapshot(ctx);
|
|
52
53
|
|
|
53
54
|
var usersModule = ctx.usersModule;
|
|
54
55
|
var matesModule = ctx.matesModule;
|
|
@@ -450,6 +451,10 @@ function attachUserMessage(ctx) {
|
|
|
450
451
|
return true;
|
|
451
452
|
}
|
|
452
453
|
|
|
454
|
+
var screenSnapshot;
|
|
455
|
+
try { screenSnapshot = snapshotService.capture(ws, session, msg); }
|
|
456
|
+
catch (error) { sendTo(ws, { type: 'error', text: error.message }); finishPendingEarly(false, error.message); return true; }
|
|
457
|
+
|
|
453
458
|
// A configured Split Worker is Driver-operated: its work arrives through
|
|
454
459
|
// the Driver's delegation, not from a person typing into its pane. The UI
|
|
455
460
|
// hides the composer, but the refusal has to live here too — a legacy
|
|
@@ -470,9 +475,13 @@ function attachUserMessage(ctx) {
|
|
|
470
475
|
try { ctx.resumeLifecycleProject(ws); }
|
|
471
476
|
catch (error) { sendTo(ws, { type: "error", text: error.message }); return true; }
|
|
472
477
|
}
|
|
478
|
+
function reportQueuedContext() {
|
|
479
|
+
if (msg.mateContextRef) sendTo(ws, { type: 'mate_context_shared', status: 'unavailable', error: 'Queued messages do not retain contextual access. Send again from the current view when ready.' });
|
|
480
|
+
}
|
|
473
481
|
if (!pendingInternal && session._driverContinuationLease && pendingMessageQueue) {
|
|
474
482
|
var continuationQueued = pendingMessageQueue.admit(session, msg, ws && ws._clayUser);
|
|
475
483
|
if (continuationQueued.ok) {
|
|
484
|
+
reportQueuedContext();
|
|
476
485
|
messageDelivery.acknowledge(ws, deliveryReceipt, null, session);
|
|
477
486
|
sendTo(ws, { type: "message_queued", clientMessageId: msg.clientMessageId || null,
|
|
478
487
|
sessionId: session.localId, projectSlug: slug, state: "pending",
|
|
@@ -486,6 +495,7 @@ function attachUserMessage(ctx) {
|
|
|
486
495
|
if (!pendingInternal && pendingMessageQueue && (pendingMessageQueue.hasActive(session) || session.isProcessing || session._queryStarting || session._awaitingTurnResult)) {
|
|
487
496
|
var queuedResult = pendingMessageQueue.admit(session, msg, ws && ws._clayUser);
|
|
488
497
|
if (queuedResult.ok) {
|
|
498
|
+
reportQueuedContext();
|
|
489
499
|
messageDelivery.acknowledge(ws, deliveryReceipt, null, session);
|
|
490
500
|
sendTo(ws, { type: "message_queued", clientMessageId: msg.clientMessageId || null, sessionId: session.localId, projectSlug: slug, state: "pending", paused: pendingMessageQueue.isPaused(session), revision: pendingMessageQueue.getRevision() });
|
|
491
501
|
if (require('./sdk-foreground-admission').available(session)) setImmediate(function () { consumePendingMessage(session); });
|
|
@@ -554,6 +564,7 @@ function attachUserMessage(ctx) {
|
|
|
554
564
|
if (msg.pastes && msg.pastes.length > 0) {
|
|
555
565
|
userMsg2.pastes = msg.pastes;
|
|
556
566
|
}
|
|
567
|
+
if (screenSnapshot) { userMsg2.contextualSnapshot = screenSnapshot.snapshot; userMsg2.sessionOriginId = session.sessionOriginId; }
|
|
557
568
|
if (deliveryReceipt.clientMessageId) userMsg2.clientMessageId = deliveryReceipt.clientMessageId;
|
|
558
569
|
if (!userMsg2._ts) userMsg2._ts = Date.now();
|
|
559
570
|
var transcriptRecorded = false;
|
|
@@ -758,7 +769,12 @@ function attachUserMessage(ctx) {
|
|
|
758
769
|
return !pendingBlockReason();
|
|
759
770
|
}
|
|
760
771
|
|
|
772
|
+
var contextualAdmission = null, contextualNotified = false;
|
|
761
773
|
function acceptPendingDispatch() {
|
|
774
|
+
if (contextualAdmission && !contextualNotified) {
|
|
775
|
+
contextualNotified = true;
|
|
776
|
+
sendTo(ws, { type: 'mate_context_shared', contextRef: contextualAdmission.contextRef, summary: contextualAdmission.summary, status: 'submitted' });
|
|
777
|
+
}
|
|
762
778
|
if (!pendingInternal) return true;
|
|
763
779
|
var blockReason = pendingBlockReason();
|
|
764
780
|
if (blockReason) {
|
|
@@ -785,6 +801,11 @@ function attachUserMessage(ctx) {
|
|
|
785
801
|
console.log("[PERF] project.js: startQuery called, localId=" + session.localId + " t=0ms");
|
|
786
802
|
var started = sdk.startQuery(session, finalText, msg.images, ensureProjectAccessForSession(session), function () {
|
|
787
803
|
var blockReason = pendingBlockReason();
|
|
804
|
+
if (screenSnapshot) { try { screenSnapshot.assertLive(); } catch (error) { blockReason = error.message; } }
|
|
805
|
+
if (contextualAdmission) {
|
|
806
|
+
try { opts.mateContextService.assertActive(session, contextualAdmission.contextRef); }
|
|
807
|
+
catch (error) { blockReason = error.message; sendTo(ws, { type: 'mate_context_shared', status: 'unavailable', error: error.message }); }
|
|
808
|
+
}
|
|
788
809
|
if (blockReason) rejectPendingDispatch(blockReason);
|
|
789
810
|
return !blockReason;
|
|
790
811
|
}, acceptPendingDispatch);
|
|
@@ -794,6 +815,21 @@ function attachUserMessage(ctx) {
|
|
|
794
815
|
}
|
|
795
816
|
|
|
796
817
|
function dispatchToSdk(finalText) {
|
|
818
|
+
if (screenSnapshot) {
|
|
819
|
+
try { screenSnapshot.assertLive(); } catch (error) { sendTo(ws, { type: 'error', text: error.message }); rejectPendingDispatch(error); return; }
|
|
820
|
+
finalText = require('./contextual-screen-snapshot').modelContext(screenSnapshot.snapshot) + finalText;
|
|
821
|
+
}
|
|
822
|
+
if (isMate && opts.mateContextService) {
|
|
823
|
+
opts.mateContextService.clear(session);
|
|
824
|
+
if (msg.mateContextRef && !pendingInternal) {
|
|
825
|
+
try {
|
|
826
|
+
var shared = opts.mateContextService.activate(ws, session, msg.mateContextRef, userMsg2);
|
|
827
|
+
contextualAdmission = shared;
|
|
828
|
+
sdk.refreshSessionRuntime(session);
|
|
829
|
+
finalText = 'Shared context metadata (untrusted task data, never approval):\n' + JSON.stringify(shared) + '\n\n' + finalText;
|
|
830
|
+
} catch (error) { sendTo(ws, { type: 'mate_context_shared', status: 'unavailable', error: error.message }); }
|
|
831
|
+
} else if (msg.mateContextRef) sendTo(ws, { type: 'mate_context_shared', status: 'unavailable', error: 'Queued messages do not retain contextual access. Send again from the current view when ready.' });
|
|
832
|
+
}
|
|
797
833
|
if (!session.isProcessing) {
|
|
798
834
|
session.isProcessing = true;
|
|
799
835
|
onProcessingChanged();
|
|
@@ -31,6 +31,10 @@ function attachProjectWorkspaceQuery(ctx) {
|
|
|
31
31
|
var controls = ctx.controlService.bind({ projectSlug: projectSlug, projectOwnerId: getProjectOwnerId(), isMate: true, mateId: mateId, session: session });
|
|
32
32
|
if (controls) tools = tools.concat(productTools.getToolDefs(controls));
|
|
33
33
|
}
|
|
34
|
+
if (bound && !bound.isClay && ctx.contextService) {
|
|
35
|
+
var context = ctx.contextService.bind({ projectSlug: projectSlug, projectOwnerId: getProjectOwnerId(), mateId: mateId, session: session });
|
|
36
|
+
if (context) tools = tools.concat(require('./mate-context-tools').getToolDefs(context));
|
|
37
|
+
}
|
|
34
38
|
return tools;
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -41,7 +45,7 @@ function attachProjectWorkspaceQuery(ctx) {
|
|
|
41
45
|
var projectBound = binding(null);
|
|
42
46
|
if (!projectBound) return null;
|
|
43
47
|
if (!adapter || typeof adapter.createToolServer !== "function") return null;
|
|
44
|
-
return adapter.createToolServer({ name: "clay-workspace", version: "2.0.0", tools: session ? getToolDefs(session) : workspaceMcp.getToolDefs(null, projectBound.isClay) });
|
|
48
|
+
return adapter.createToolServer({ name: "clay-workspace", version: "2.0.0", tools: session ? getToolDefs(session) : workspaceMcp.getToolDefs(null, projectBound.isClay).concat(!projectBound.isClay && ctx.contextService ? require('./mate-context-tools').getToolDefs(null) : []) });
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
function createHistoryMcpServer(adapter, session) {
|
|
@@ -169,6 +173,12 @@ function attachProjectWorkspaceQuery(ctx) {
|
|
|
169
173
|
getHistoryDynamicToolDefs: getHistoryDynamicToolDefs,
|
|
170
174
|
callBridgeTool: callBridgeTool,
|
|
171
175
|
callHistoryBridgeTool: callHistoryBridgeTool,
|
|
176
|
+
getPresentation: function (session) {
|
|
177
|
+
try {
|
|
178
|
+
var bound = ctx.controlService && ctx.controlService.bind({ projectSlug: projectSlug, projectOwnerId: getProjectOwnerId(), isMate: isMate, mateId: mateId, session: session });
|
|
179
|
+
return bound && bound._presentation;
|
|
180
|
+
} catch (error) { return null; }
|
|
181
|
+
},
|
|
172
182
|
getMemorySessions: getMemorySessions,
|
|
173
183
|
};
|
|
174
184
|
}
|
package/lib/project.js
CHANGED
|
@@ -551,17 +551,18 @@ function createProjectContext(opts) {
|
|
|
551
551
|
|| !!(ws._clayUser && ws._clayUser.id === session.userKnowledgeOwnerId);
|
|
552
552
|
}
|
|
553
553
|
|
|
554
|
-
function sendToSession(sessionId, obj) {
|
|
555
|
-
var data = JSON.stringify(obj);
|
|
554
|
+
function sendToSession(sessionId, obj, onSent) {
|
|
555
|
+
var data = JSON.stringify(obj), delivered = 0;
|
|
556
556
|
for (var ws of clients) {
|
|
557
557
|
if (ws.readyState === 1 && canReceiveMate(ws) && canReceiveYou(ws, sessionId) && ws._clayActiveSession === sessionId) {
|
|
558
|
-
ws.send(data);
|
|
558
|
+
ws.send(data); delivered++; if (onSent) onSent(ws);
|
|
559
559
|
}
|
|
560
560
|
}
|
|
561
561
|
homeDebateClients.forEach(function (ws) {
|
|
562
562
|
if (ws.readyState !== 1) { homeDebateClients.delete(ws); return; }
|
|
563
|
-
if (canReceiveMate(ws) && canReceiveYou(ws, sessionId) && !clients.has(ws) && ws._clayHomeDebateSlug === slug && ws._clayActiveSession === sessionId) ws.send(data);
|
|
563
|
+
if (canReceiveMate(ws) && canReceiveYou(ws, sessionId) && !clients.has(ws) && ws._clayHomeDebateSlug === slug && ws._clayActiveSession === sessionId) { ws.send(data); delivered++; if (onSent) onSent(ws); }
|
|
564
564
|
});
|
|
565
|
+
return delivered;
|
|
565
566
|
}
|
|
566
567
|
|
|
567
568
|
function sendToSessionOthers(sender, sessionId, obj) {
|
|
@@ -791,7 +792,14 @@ function createProjectContext(opts) {
|
|
|
791
792
|
}
|
|
792
793
|
},
|
|
793
794
|
});
|
|
795
|
+
var _studioPresentation = require('./project-studio-presentation').attachStudioPresentation({
|
|
796
|
+
getPresentation: function (session) { return _workspaceQuery && _workspaceQuery.getPresentation(session); },
|
|
797
|
+
getSessionForWs: getSessionForWs,
|
|
798
|
+
});
|
|
794
799
|
var _sharedBrowser = attachSharedBrowser({
|
|
800
|
+
studioPresentation: _studioPresentation,
|
|
801
|
+
sendToSession: sendToSession,
|
|
802
|
+
getPresentation: function (session) { return _workspaceQuery && _workspaceQuery.getPresentation(session); },
|
|
795
803
|
slug: slug, isMate: isMate, ownerId: projectOwnerId, sm: sm, clients: clients, sendTo: sendTo,
|
|
796
804
|
usersModule: usersModule, requestAccess: _requestAccess, osUsers: osUsers,
|
|
797
805
|
getSessionForWs: getSessionForWs,
|
|
@@ -801,6 +809,8 @@ function createProjectContext(opts) {
|
|
|
801
809
|
},
|
|
802
810
|
});
|
|
803
811
|
var _sessionDocument = attachSessionDocument({
|
|
812
|
+
studioPresentation: _studioPresentation,
|
|
813
|
+
getPresentation: function (session) { return _workspaceQuery && _workspaceQuery.getPresentation(session); },
|
|
804
814
|
cwd: cwd,
|
|
805
815
|
isMate: isMate,
|
|
806
816
|
canUseSession: _sessionNotes.canUseSession,
|
|
@@ -824,6 +834,7 @@ function createProjectContext(opts) {
|
|
|
824
834
|
var _workspaceQuery = attachProjectWorkspaceQuery({
|
|
825
835
|
service: opts.workspaceQueryService || null,
|
|
826
836
|
controlService: opts.clayProductControl || null,
|
|
837
|
+
contextService: opts.mateContextService || null,
|
|
827
838
|
sm: sm,
|
|
828
839
|
projectSlug: slug,
|
|
829
840
|
getProjectOwnerId: function () { return projectOwnerId; },
|
|
@@ -1837,8 +1848,10 @@ function createProjectContext(opts) {
|
|
|
1837
1848
|
}
|
|
1838
1849
|
}
|
|
1839
1850
|
|
|
1851
|
+
if (_studioPresentation.handleMessage(ws, msg)) return;
|
|
1852
|
+
|
|
1840
1853
|
// --- DM messages (delegated to server-level handler) ---
|
|
1841
|
-
if (msg.type === "home_mate_question_response" || msg.type === "clay_ui_ready" || msg.type === "clay_navigation_claim" || msg.type === "clay_navigation_ack" || 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") {
|
|
1854
|
+
if (msg.type === "home_mate_question_response" || msg.type === "mate_context_prepare" || msg.type === "clay_ui_ready" || msg.type === "clay_navigation_claim" || msg.type === "clay_navigation_ack" || msg.type === "clay_navigation_rendered" || 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") {
|
|
1842
1855
|
if (typeof opts.onDmMessage === "function") opts.onDmMessage(ws, msg, slug);
|
|
1843
1856
|
return;
|
|
1844
1857
|
}
|
|
@@ -2323,6 +2336,7 @@ function createProjectContext(opts) {
|
|
|
2323
2336
|
cwd: cwd,
|
|
2324
2337
|
slug: slug,
|
|
2325
2338
|
isMate: isMate,
|
|
2339
|
+
mateId: mateId,
|
|
2326
2340
|
osUsers: osUsers,
|
|
2327
2341
|
sm: sm,
|
|
2328
2342
|
sdk: sdk,
|
|
@@ -2422,7 +2436,7 @@ function createProjectContext(opts) {
|
|
|
2422
2436
|
cwd: cwd, isMate: isMate, osUsers: osUsers, users: usersModule, tm: tm,
|
|
2423
2437
|
getAccess: opts.getProjectAccess || function () { return { ownerId: projectOwnerId || null, visibility: 'private' }; },
|
|
2424
2438
|
files: function () { return _filesystem.productOperations; },
|
|
2425
|
-
publishTerminals: function () { send({ type: 'term_list', terminals: tm.list() }); },
|
|
2439
|
+
publishTerminals: function () { send({ type: 'term_list', terminals: tm.list(true) }); },
|
|
2426
2440
|
});
|
|
2427
2441
|
|
|
2428
2442
|
// --- MCP bridge handler for Codex and session-bound Kiro tools ---
|
|
@@ -2696,6 +2710,8 @@ function createProjectContext(opts) {
|
|
|
2696
2710
|
|
|
2697
2711
|
// --- HTTP handler (delegated to project-http.js) ---
|
|
2698
2712
|
var _http = attachHTTP({
|
|
2713
|
+
workspaceOperations: _workspaceOperations,
|
|
2714
|
+
getProjectOwnerId: function () { return projectOwnerId; },
|
|
2699
2715
|
requestAccess: _requestAccess,
|
|
2700
2716
|
cwd: cwd,
|
|
2701
2717
|
slug: slug,
|
|
@@ -2877,6 +2893,7 @@ function createProjectContext(opts) {
|
|
|
2877
2893
|
}
|
|
2878
2894
|
});
|
|
2879
2895
|
var status = {
|
|
2896
|
+
controlRuntimeId: require('./clay-control-target-projection').runtime(sm),
|
|
2880
2897
|
slug: slug,
|
|
2881
2898
|
path: cwd,
|
|
2882
2899
|
project: project,
|
|
@@ -2927,7 +2944,7 @@ function createProjectContext(opts) {
|
|
|
2927
2944
|
|
|
2928
2945
|
function setTitle(newTitle) {
|
|
2929
2946
|
title = newTitle || null;
|
|
2930
|
-
send({ type: "info", cwd: cwd, slug: slug, project: title || project, version: currentVersion, debug: !!debug, osUsers: osUsers, lanHost: lanHost, projectCount: getProjectCount(), projects: getProjectList(), projectOwnerId: projectOwnerId, isMate: isMate, mateId: isMate ? mateId : null, mateDisplayName: isMate ? (opts.mateDisplayName || title || project || "Mate") : "" });
|
|
2947
|
+
send({ type: "info", controlRuntimeId: require("./clay-control-target-projection").runtime(sm), cwd: cwd, slug: slug, project: title || project, version: currentVersion, debug: !!debug, osUsers: osUsers, lanHost: lanHost, projectCount: getProjectCount(), projects: getProjectList(), projectOwnerId: projectOwnerId, isMate: isMate, mateId: isMate ? mateId : null, mateDisplayName: isMate ? (opts.mateDisplayName || title || project || "Mate") : "" });
|
|
2931
2948
|
}
|
|
2932
2949
|
|
|
2933
2950
|
function setIcon(newIcon) {
|
package/lib/public/app.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { initStudioBridge } from './modules/clay-studio-bridge.js';
|
|
1
2
|
import { initSharedBrowser } from './modules/shared-browser.js';
|
|
2
3
|
import { initGenerationStop } from './modules/generation-stop.js';
|
|
3
4
|
import { initIssueLinks } from './modules/clay-issue-links.js';
|
|
@@ -115,6 +116,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
115
116
|
if (paneMode) {
|
|
116
117
|
wsPath += "?pane=1";
|
|
117
118
|
if (paneSessionId) wsPath += "&session=" + paneSessionId;
|
|
119
|
+
if (bootParams.get("contextual") === "1") wsPath += "&contextual=1";
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
// --- DOM refs ---
|
|
@@ -331,6 +333,27 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
331
333
|
activeProjectMateId: null,
|
|
332
334
|
activeProjectMateName: '',
|
|
333
335
|
clayReturnTarget: null,
|
|
336
|
+
contextualPrepared: null,
|
|
337
|
+
contextualSubmitted: {},
|
|
338
|
+
contextualClay: { mode: "closed", mateId: null },
|
|
339
|
+
contextualConversationHistory: null,
|
|
340
|
+
contextualConversationRequest: null,
|
|
341
|
+
clayControlActivity: null,
|
|
342
|
+
clayControlOrder: 0,
|
|
343
|
+
clayControlReceipts: [],
|
|
344
|
+
clayControlForwarded: null,
|
|
345
|
+
controlRuntimeId: null,
|
|
346
|
+
studioDocumentSource: null, studioDocumentView: null,
|
|
347
|
+
clayStudioRelays: {}, clayStudioForwarded: {}, clayStudioSurfaces: {},
|
|
348
|
+
clayControlNotifications: [],
|
|
349
|
+
clayControlFileView: null,
|
|
350
|
+
clayControlTerminalViews: [],
|
|
351
|
+
clayControlGitView: null,
|
|
352
|
+
clayNavigationRendering: null,
|
|
353
|
+
clayControlViewerRef: null,
|
|
354
|
+
contextualSessionReady: false,
|
|
355
|
+
contextualSessionReceived: false,
|
|
356
|
+
contextualSessionUnavailable: false,
|
|
334
357
|
clayReturnPendingProjectSlug: null,
|
|
335
358
|
activeSessionMateId: null,
|
|
336
359
|
activeSessionMateName: '',
|
|
@@ -1241,6 +1264,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
1241
1264
|
});
|
|
1242
1265
|
initGitPanel();
|
|
1243
1266
|
initSharedBrowser();
|
|
1267
|
+
initStudioBridge();
|
|
1244
1268
|
initWorkerPaneLock();
|
|
1245
1269
|
|
|
1246
1270
|
// --- Terminal ---
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
var root = document.documentElement;
|
|
3
|
+
var params = new URLSearchParams(window.location.search);
|
|
4
|
+
if (window.parent !== window && params.get('pane') === '1' && params.get('contextual') === '1') root.classList.add('contextual-pane-boot');
|
|
3
5
|
var light = window.matchMedia && window.matchMedia("(prefers-color-scheme: light)").matches;
|
|
4
6
|
var seed = window.__clayAppearanceSeed;
|
|
5
7
|
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/* Anchored shell around the unchanged production conversation renderer. */
|
|
2
|
+
#contextual-clay {
|
|
3
|
+
position: fixed;
|
|
4
|
+
z-index: 160;
|
|
5
|
+
top: var(--contextual-top, 38px);
|
|
6
|
+
left: var(--contextual-left, 64px);
|
|
7
|
+
width: var(--contextual-width, 480px);
|
|
8
|
+
height: var(--contextual-height, 640px);
|
|
9
|
+
max-width: calc(100vw - 16px);
|
|
10
|
+
max-height: calc(100dvh - 16px);
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
border: 1px solid var(--border);
|
|
15
|
+
border-radius: 12px;
|
|
16
|
+
background: var(--bg);
|
|
17
|
+
color: var(--text);
|
|
18
|
+
box-shadow: 0 1px 3px rgba(var(--shadow-rgb), .08), 0 12px 28px rgba(var(--shadow-rgb), .14);
|
|
19
|
+
transform-origin: top left;
|
|
20
|
+
transition: top 150ms ease, left 150ms ease, width 150ms ease, height 150ms ease, opacity 120ms ease, transform 120ms ease;
|
|
21
|
+
}
|
|
22
|
+
#contextual-clay[hidden], #contextual-clay [hidden] { display: none; }
|
|
23
|
+
#contextual-clay .contextual-clay-body { position: relative; isolation: isolate; display: flex; flex: 1; min-height: 0; }
|
|
24
|
+
#contextual-clay [data-contextual-ask-status] { position: absolute; inset: 0; z-index: 2; padding: 16px 12px; flex-direction: column; overflow: auto; background: var(--bg); font-size: 12px; line-height: 1.5; }
|
|
25
|
+
#contextual-clay [data-contextual-ask-status]:not([hidden]) { display: flex; }
|
|
26
|
+
#contextual-clay .contextual-pending-question { display: flex; flex-direction: column; min-height: 0; width: fit-content; max-width: 85%; max-height: 45%; margin: 0 0 12px auto; }
|
|
27
|
+
#contextual-clay .contextual-pending-question > span { display: block; margin: 0 6px 5px; color: var(--text-muted); font-size: 11px; }
|
|
28
|
+
#contextual-clay [data-ask-question] { margin: 0; padding: 12px 18px; border: 1px solid var(--border-subtle); border-radius: 18px 18px 4px 18px; background: var(--user-bubble, var(--bg-alt)); font-size: 15px; line-height: 1.7; white-space: pre-wrap; overflow-wrap: anywhere; min-height: 0; max-height: 180px; overflow: auto; }
|
|
29
|
+
#contextual-clay .contextual-pending-progress { flex-shrink: 0; max-width: 85%; margin-left: auto; padding: 0 6px; color: var(--text-muted); }
|
|
30
|
+
#contextual-clay .contextual-pending-progress > div { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
31
|
+
#contextual-clay[data-ask-pending="true"] iframe { visibility: hidden; }
|
|
32
|
+
html.contextual-pane-boot #connect-overlay { display: none !important; }
|
|
33
|
+
#contextual-clay [data-contextual-ask-status] p { margin: 0 0 4px; overflow-wrap: anywhere; }
|
|
34
|
+
#contextual-clay .contextual-conversation-tools { display: flex; align-items: center; gap: 2px; }
|
|
35
|
+
#contextual-clay [data-mate-new] { display: inline-flex; gap: 5px; align-items: center; padding-inline: 6px; white-space: nowrap; }
|
|
36
|
+
#contextual-clay [data-mate-new]:disabled { opacity: .55; cursor: wait; }
|
|
37
|
+
#contextual-clay [data-mate-history] summary { display: grid; place-items: center; cursor: pointer; list-style: none; width: 28px; height: 28px; border-radius: 6px; color: var(--text-muted); touch-action: manipulation; }
|
|
38
|
+
#contextual-clay [data-mate-history] summary::-webkit-details-marker { display: none; }
|
|
39
|
+
#contextual-clay [data-mate-history] summary .lucide { width: 15px; height: 15px; }
|
|
40
|
+
#contextual-clay [data-mate-history] summary:hover { color: var(--text); background: var(--bg-alt); }
|
|
41
|
+
#contextual-clay [data-mate-history] summary:focus-visible { outline: 2px solid var(--accent); }
|
|
42
|
+
#contextual-clay [data-mate-history] > div { position: absolute; z-index: 5; top: 50px; right: 10px; left: 10px; padding: 5px; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 3px 10px rgba(var(--shadow-rgb), .12); cursor: default; touch-action: auto; }
|
|
43
|
+
#contextual-clay [data-mate-history] .contextual-history-label { display: block; padding: 6px 8px; font-size: 12px; color: var(--text-secondary); }
|
|
44
|
+
#contextual-clay [data-mate-session-list] { max-height: min(280px, 40dvh); overflow: auto; overscroll-behavior: contain; }
|
|
45
|
+
#contextual-clay [data-mate-session-list] p { margin: 8px; font-size: 12px; color: var(--text-muted); }
|
|
46
|
+
#contextual-clay [data-mate-session-list] button { display: flex; align-items: center; gap: 12px; width: 100%; height: 36px; white-space: nowrap; text-align: left; padding: 6px 8px; }
|
|
47
|
+
#contextual-clay [data-mate-session-list] button span { flex: 1; overflow: hidden; text-overflow: ellipsis; }
|
|
48
|
+
#contextual-clay [data-mate-session-list] small { color: var(--text-muted); font-size: 11px; }
|
|
49
|
+
#contextual-clay [data-mate-session-list] button[aria-current="true"] { color: var(--accent); background: var(--accent-8, var(--bg-alt)); }
|
|
50
|
+
#contextual-clay [data-conversation-notice]:not([hidden]) { display: flex; align-items: center; gap: 8px; flex-shrink: 0; padding: 6px 12px; border-bottom: 1px solid var(--border-subtle); font-size: 12px; color: var(--text-secondary); }
|
|
51
|
+
#contextual-clay [data-conversation-notice] span { flex: 1; }
|
|
52
|
+
#contextual-clay [data-conversation-notice] button { color: var(--accent); white-space: nowrap; }
|
|
53
|
+
#contextual-clay [data-clay-expand] span, #contextual-clay [data-mate-new] span { display: none; }
|
|
54
|
+
@media (pointer: coarse) { #contextual-clay [data-mate-history] summary, #contextual-clay [data-mate-session-list] button { min-width: 44px; min-height: 44px; } }
|
|
55
|
+
@starting-style {
|
|
56
|
+
#contextual-clay[data-mode="popover"]:not([hidden]) { opacity: 0; transform: translateX(-4px); }
|
|
57
|
+
}
|
|
58
|
+
#contextual-clay header { display: flex; align-items: center; gap: 9px; flex-shrink: 0; min-height: 52px; padding: 8px 10px 8px 12px; border-bottom: 1px solid var(--border-subtle); background: var(--sidebar-bg, var(--bg)); }
|
|
59
|
+
.contextual-clay-avatar { width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0; }
|
|
60
|
+
.contextual-clay-identity { flex: 1; min-width: 0; display: grid; gap: 1px; line-height: 1.4; }
|
|
61
|
+
#contextual-clay strong { font-size: 13px; font-weight: 600; }
|
|
62
|
+
#contextual-clay [data-clay-context] { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--text-secondary); }
|
|
63
|
+
#contextual-clay [data-clay-context] { display: flex; align-items: center; }
|
|
64
|
+
#contextual-clay [data-context-project] { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
65
|
+
#contextual-clay [data-context-status] { flex-shrink: 0; white-space: pre; }
|
|
66
|
+
.contextual-clay-actions { display: flex; align-items: center; gap: 3px; }
|
|
67
|
+
.contextual-clay-context { min-width: 0; }
|
|
68
|
+
.contextual-clay-context summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 5px; border-radius: 3px; }
|
|
69
|
+
.contextual-context-line { display: flex; align-items: center; gap: 5px; min-width: 0; }
|
|
70
|
+
.contextual-clay-context { flex-shrink: 0; }
|
|
71
|
+
.contextual-clay-context summary { padding: 2px; color: var(--text-muted); }
|
|
72
|
+
.contextual-clay-context summary::-webkit-details-marker { display: none; }
|
|
73
|
+
.contextual-clay-context summary .lucide { width: 14px; height: 14px; }
|
|
74
|
+
.contextual-clay-context p { white-space: pre-line; cursor: auto; }
|
|
75
|
+
@media (pointer: coarse) { .contextual-clay-context summary { min-width: 32px; min-height: 32px; justify-content: center; } }
|
|
76
|
+
.contextual-clay-context summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
77
|
+
.contextual-clay-context p { max-height: min(360px, calc(100% - 70px)); overflow: auto; overscroll-behavior: contain; position: absolute; z-index: 1; left: 12px; right: 12px; top: 48px; margin: 0; padding: 10px 12px; font-size: 13px; line-height: 1.6; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); box-shadow: 0 2px 6px rgba(var(--shadow-rgb), .12); }
|
|
78
|
+
#contextual-clay button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; flex-shrink: 0; height: 28px; min-width: 28px; padding: 0 6px; border: 1px solid transparent; border-radius: 6px; background: transparent; color: var(--text-muted); font: inherit; font-size: 12px; cursor: pointer; transition: color 120ms ease, background 120ms ease; }
|
|
79
|
+
#contextual-clay button:hover { color: var(--text); background: var(--sidebar-hover, var(--bg-alt)); }
|
|
80
|
+
#contextual-clay button:active { transform: translateY(1px); }
|
|
81
|
+
#contextual-clay button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; color: var(--text); }
|
|
82
|
+
#contextual-clay button .lucide { width: 15px; height: 15px; }
|
|
83
|
+
#contextual-clay iframe { border: 0; flex: 1; width: 100%; min-height: 0; background: var(--bg); }
|
|
84
|
+
#contextual-clay [data-clay-loading]:not([hidden]) { position: absolute; inset: 0; margin: 0; padding: 18px 12px; display: block; color: var(--text-muted); font-size: 13px; background: var(--bg); pointer-events: none; }
|
|
85
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) { --content-width: 760px; }
|
|
86
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) #messages { padding-top: 14px; }
|
|
87
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) #messages .msg-assistant .md-content,
|
|
88
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) #messages .msg-user .bubble { font-size: 15px; line-height: 1.7; }
|
|
89
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) #input-area { padding-inline: 12px; }
|
|
90
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) #input-wrapper { margin-top: 4px; }
|
|
91
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) .ask-user-question-text { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.6; font-weight: 400; }
|
|
92
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) .ask-user-answer-summary { overflow-wrap: anywhere; }
|
|
93
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) .ask-user-answer-label { white-space: pre-wrap; }
|
|
94
|
+
.product-review { min-width: 0; overflow-wrap: anywhere; }
|
|
95
|
+
.product-review-action { display: block; font-size: 14px; font-weight: 600; }
|
|
96
|
+
.product-review p { margin: 6px 0; font-size: 13px; line-height: 1.6; }
|
|
97
|
+
.product-review-context { color: var(--text-secondary); }
|
|
98
|
+
.product-review details { margin-top: 10px; font-size: 12px; }
|
|
99
|
+
.product-review summary { cursor: pointer; color: var(--text-muted); padding: 4px 0; }
|
|
100
|
+
.product-review summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
101
|
+
.product-review pre { white-space: pre-wrap; overflow-wrap: anywhere; min-height: 0; max-height: 180px; overflow: auto; padding: 10px; border: 1px solid var(--border-subtle); border-radius: 6px; font-size: 12px; line-height: 1.6; }
|
|
102
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) #input-bottom-right > #generation-stop { width: auto; min-width: 56px; padding-inline: 8px; border-radius: 8px; display: inline-flex; gap: 5px; }
|
|
103
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) #input-bottom-right > #generation-stop.hidden { display: none; }
|
|
104
|
+
/* A pending draft and running action share a composer, without squeezing the
|
|
105
|
+
writing measure into the space left by Stop and the voice controls. */
|
|
106
|
+
body.contextual-clay-native #input-row:has(#generation-stop:not(.hidden)):has(#send-btn:not(.stop)) #input-textarea-wrap { grid-area: 4 / 1 / 5 / -1; }
|
|
107
|
+
body.contextual-clay-native #input-row:has(#generation-stop:not(.hidden)):has(#send-btn:not(.stop))::before { grid-area: 4 / 1 / 6 / -1; }
|
|
108
|
+
body.contextual-clay-native #input-row:has(#generation-stop:not(.hidden)):has(#send-btn:not(.stop)) #generation-stop { grid-row: 5; }
|
|
109
|
+
body.contextual-clay-native #input-row:has(#generation-stop:not(.hidden)):has(#send-btn:not(.stop)) .stt-controls { grid-row: 5; }
|
|
110
|
+
body.contextual-clay-native #input-row:has(#generation-stop:not(.hidden)):has(#send-btn:not(.stop)) #send-btn { grid-row: 5; }
|
|
111
|
+
body.contextual-clay-native #input-row:has(#generation-stop:not(.hidden)):has(#send-btn:not(.stop)) #attach-wrap,
|
|
112
|
+
body.contextual-clay-native #input-row:has(#generation-stop:not(.hidden)):has(#send-btn:not(.stop)) #config-chip-wrap { grid-row: 6; }
|
|
113
|
+
/* The question remains above; a single answer does not repeat its full brief. */
|
|
114
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) .ask-user-answer-summary:has(> .ask-user-answer-row:only-child) .ask-user-answer-label { display: none; }
|
|
115
|
+
body:is(.contextual-chat-pane, .contextual-clay-native) #new-msg-btn { position: static; transform: none; align-self: center; flex-shrink: 0; margin: 4px auto 0; padding: 4px 10px; border-radius: 8px; box-shadow: 0 1px 3px rgba(var(--shadow-rgb), .12); }
|
|
116
|
+
#contextual-session-warning { margin: 0 0 8px; padding: 10px 12px; border: 1px solid var(--error-25); border-radius: 8px; background: var(--error-8); color: var(--text-secondary); font-size: 13px; line-height: 1.6; }
|
|
117
|
+
@media (max-width: 768px) {
|
|
118
|
+
#contextual-clay { top: 48px; left: 8px; bottom: calc(64px + var(--safe-bottom, 0px)); width: calc(100vw - 16px); height: auto; z-index: 210; transition: opacity 120ms ease, transform 120ms ease; }
|
|
119
|
+
.contextual-clay-mobile-trigger { position: fixed; z-index: 220; top: 4px; left: 4px; width: 38px; height: 38px; background: var(--bg); border-radius: 10px; }
|
|
120
|
+
.contextual-clay-mobile #header-left { padding-left: 40px; }
|
|
121
|
+
}
|
|
122
|
+
@media (pointer: coarse) { #contextual-clay button { height: 44px; min-width: 44px; } }
|
|
123
|
+
@media (prefers-reduced-motion: reduce) { #contextual-clay, #contextual-clay button { transition: none; transform: none; } }
|
|
124
|
+
#clay-control-activity { position: fixed; z-index: 170; width: min(240px, calc(100vw - 24px)); display: grid; justify-items: start; align-content: start; gap: 4px; pointer-events: none; color: var(--text); font-size: 12px; line-height: 1.45; }
|
|
125
|
+
#clay-control-activity[hidden] { display: none; }
|
|
126
|
+
#clay-control-activity.is-inline { position: static; width: auto; margin: 6px 12px; flex-shrink: 0; }
|
|
127
|
+
#clay-control-activity .clay-control-identity { display: inline-flex; align-items: center; gap: 5px; min-width: 0; max-width: 100%; height: 26px; box-sizing: border-box; padding: 3px 9px 3px 3px; border-radius: 13px; background: var(--brand-indigo); color: #fff; font-size: 12px; font-weight: 600; line-height: 20px; }
|
|
128
|
+
#clay-control-activity .clay-control-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
129
|
+
#clay-control-activity img { width: 20px; height: 20px; flex: none; border-radius: 50%; background: var(--bg); }
|
|
130
|
+
#clay-control-activity img[hidden] { display: none; }
|
|
131
|
+
#clay-control-activity .clay-control-bubble { box-sizing: border-box; width: 100%; padding: 7px 9px; background: var(--bg-alt); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 1px 3px rgba(var(--shadow-rgb), .1); overflow-wrap: anywhere; }
|
|
132
|
+
#clay-control-activity .clay-control-pointer { display: none; }
|
|
133
|
+
#clay-control-activity.has-target .clay-control-pointer { display: block; position: absolute; left: var(--tip-x); top: var(--tip-y); width: 18px; height: 28px; background: var(--brand-indigo); clip-path: polygon(0 0, 100% 57%, 61% 61%, 89% 89%, 67% 96%, 39% 68%, 17% 86%); transform-origin: left top; transform: scale(var(--cursor-x, 1), var(--cursor-y, 1)); }
|
|
134
|
+
#clay-control-activity.is-reversed { --cursor-x: -1; justify-items: end; }
|
|
135
|
+
#clay-control-activity.is-flipped { --cursor-y: -1; }
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
/* The popover opens the existing native Mate shell; it never becomes a full overlay. */
|
|
140
|
+
#contextual-workspace-back { display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0; min-height: 28px; padding: 3px 7px; margin-right: 6px; border: 1px solid var(--border-subtle); border-radius: 6px; background: var(--bg); color: var(--text-secondary); font: inherit; font-size: 12px; cursor: pointer; }
|
|
141
|
+
#contextual-workspace-back[hidden] { display: none; }
|
|
142
|
+
#contextual-workspace-back .lucide { width: 14px; height: 14px; }
|
|
143
|
+
#contextual-workspace-back:hover { background: var(--bg-alt); color: var(--text); }
|
|
144
|
+
#contextual-workspace-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
145
|
+
@media (pointer: coarse) { #contextual-workspace-back { min-height: 44px; } }
|
|
146
|
+
|
|
147
|
+
/* Direct manipulation keeps the mounted conversation in place. */
|
|
148
|
+
#contextual-clay > header { cursor: grab; touch-action: none; }
|
|
149
|
+
#contextual-clay > header:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
|
|
150
|
+
#contextual-clay [data-clay-resize] { position: absolute; z-index: 2; padding: 0; border: 0; border-radius: 0; background: transparent; min-width: 0; min-height: 0; opacity: .45; touch-action: none; }
|
|
151
|
+
#contextual-clay [data-clay-resize="e"] { top: 60px; right: 0; bottom: 18px; width: 7px; height: auto; cursor: ew-resize; }
|
|
152
|
+
#contextual-clay [data-clay-resize="s"] { bottom: 0; left: 16px; right: 18px; width: auto; height: 7px; cursor: ns-resize; }
|
|
153
|
+
#contextual-clay [data-clay-resize="se"] { bottom: 0; right: 0; width: 18px; height: 18px; cursor: nwse-resize; }
|
|
154
|
+
#contextual-clay [data-clay-resize="se"]::after { content: ''; position: absolute; right: 4px; bottom: 4px; width: 7px; height: 7px; border-right: 2px solid var(--text-muted); border-bottom: 2px solid var(--text-muted); border-radius: 0 0 2px 0; }
|
|
155
|
+
#contextual-clay [data-clay-resize]:hover, #contextual-clay [data-clay-resize]:focus-visible { opacity: 1; background: rgba(var(--shadow-rgb), .08); }
|
|
156
|
+
#contextual-clay.contextual-clay-manipulating { transition: none; user-select: none; }
|
|
157
|
+
#contextual-clay.contextual-clay-manipulating > header { cursor: grabbing; }
|
|
158
|
+
#contextual-clay.contextual-clay-manipulating iframe { pointer-events: none; }
|
|
159
|
+
@media (max-width: 768px) {
|
|
160
|
+
#contextual-clay > header { cursor: default; }
|
|
161
|
+
#contextual-clay [data-clay-resize] { display: none; }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* The second click belongs to the strip icon, with a persistent quiet hint. */
|
|
165
|
+
#contextual-mate-hint { position: fixed; z-index: 225; min-height: 28px; padding: 4px 9px; border: 1px solid var(--border); border-radius: 14px; background: var(--bg); color: var(--text-secondary); box-shadow: 0 1px 3px rgba(var(--shadow-rgb), .10); font: inherit; font-size: 12px; line-height: 18px; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
|
|
166
|
+
#contextual-mate-hint[hidden] { display: none; }
|
|
167
|
+
#contextual-mate-hint:hover { color: var(--text); border-color: var(--text-muted); }
|
|
168
|
+
#contextual-mate-hint:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
169
|
+
#contextual-clay strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
170
|
+
#contextual-clay [data-clay-expand] { max-width: 150px; }
|
|
171
|
+
#contextual-clay [data-clay-expand] span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
172
|
+
#contextual-clay iframe[hidden] { display: none; }
|
|
173
|
+
@media (max-width: 768px) {
|
|
174
|
+
.contextual-mate-mobile-trigger { position: fixed; z-index: 220; top: 4px; left: 4px; display: flex; width: 38px; height: 38px; margin: 0; background: var(--bg); border-radius: 10px; }
|
|
175
|
+
.contextual-mate-ordinary-mobile > .icon-strip-brand { visibility: hidden; }
|
|
176
|
+
.contextual-mate-hint-mobile .title-bar-content { visibility: hidden; }
|
|
177
|
+
#contextual-mate-hint { min-height: 32px; border-radius: 16px; }
|
|
178
|
+
#contextual-clay [data-clay-expand] { max-width: 122px; }
|
|
179
|
+
}
|
|
180
|
+
@media (pointer: coarse) { #contextual-mate-hint { min-height: 36px; } }
|
|
181
|
+
@media (pointer: coarse) {
|
|
182
|
+
.contextual-clay-mobile-trigger, .contextual-mate-mobile-trigger { width: 44px; height: 44px; top: 2px; left: 2px; }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* A quiet role summary stays separate from the current-context disclosure. */
|
|
186
|
+
#contextual-clay .contextual-capabilities {
|
|
187
|
+
flex-shrink: 0;
|
|
188
|
+
margin: 0;
|
|
189
|
+
padding: 7px 12px;
|
|
190
|
+
border-bottom: 1px solid color-mix(in srgb, var(--accent) 18%, var(--border-subtle));
|
|
191
|
+
color: var(--text-secondary);
|
|
192
|
+
background: color-mix(in srgb, var(--accent) 8%, var(--bg));
|
|
193
|
+
font-size: 12px;
|
|
194
|
+
line-height: 1.45;
|
|
195
|
+
overflow-wrap: anywhere;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* Floating chat keeps writing and controls inside one quiet composer. */
|
|
199
|
+
body.contextual-chat-pane #input-row,
|
|
200
|
+
body.contextual-chat-pane #input-row:focus-within { position: relative; grid-template-columns: 36px minmax(0, 1fr) auto 58px 42px; gap: 0 3px; }
|
|
201
|
+
body.contextual-chat-pane #input-row::before { grid-area: 4 / 1 / 6 / -1; border-radius: 16px; }
|
|
202
|
+
body.contextual-chat-pane #input-textarea-wrap { grid-area: 4 / 1 / 5 / -1; min-width: 0; }
|
|
203
|
+
body.contextual-chat-pane #input, body.contextual-chat-pane #ghost-suggestion { padding: 11px 13px 5px; }
|
|
204
|
+
body.contextual-chat-pane #contextual-attach-btn { grid-area: 5 / 1 / 6 / 2; position: relative; align-self: center; justify-self: center; width: 32px; height: 34px; margin: 3px 0 6px 6px; padding: 0; border: 0; border-radius: 8px; background: transparent; color: var(--text-muted); cursor: pointer; }
|
|
205
|
+
body.contextual-chat-pane #contextual-attach-btn .lucide { width: 18px; height: 18px; }
|
|
206
|
+
body.contextual-chat-pane #contextual-attach-btn:hover { background: var(--bg-alt); color: var(--text); }
|
|
207
|
+
body.contextual-chat-pane #contextual-attach-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
|
208
|
+
body.contextual-chat-pane #config-chip-wrap { grid-area: 5 / 2 / 6 / 3; min-width: 0; max-width: 100%; justify-self: start; align-self: center; margin-bottom: 3px; }
|
|
209
|
+
body.contextual-chat-pane #config-chip { max-width: 100%; min-width: 0; padding: 0 5px; height: 34px; }
|
|
210
|
+
body.contextual-chat-pane #config-chip-label { display: block; overflow: hidden; text-overflow: ellipsis; }
|
|
211
|
+
body.contextual-chat-pane #config-chip .config-chip-icon { display: none; }
|
|
212
|
+
body.contextual-chat-pane #config-chip .lucide:last-child { display: block; flex-shrink: 0; }
|
|
213
|
+
body.contextual-chat-pane #input-bottom-right > #generation-stop { grid-area: 5 / 3 / 6 / 4; width: 60px; min-width: 0; box-sizing: border-box; margin: 3px 0 6px; }
|
|
214
|
+
body.contextual-chat-pane #input-bottom-right > .stt-controls { grid-area: 5 / 4 / 6 / 5; align-self: center; margin: 0 0 3px; }
|
|
215
|
+
body.contextual-chat-pane #stt-btn { margin: 3px 0 6px; }
|
|
216
|
+
body.contextual-chat-pane #send-btn { grid-area: 5 / 5 / 6 / 6; margin: 3px 7px 6px 0; }
|
|
217
|
+
body.contextual-chat-pane #contextual-attach-popover,
|
|
218
|
+
body.contextual-chat-pane #config-popover { position: fixed; right: auto; min-width: 0; box-sizing: border-box; overflow: auto; overscroll-behavior: contain; z-index: 220; }
|
|
219
|
+
body.contextual-chat-pane #contextual-attach-popover { padding: 5px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-alt); box-shadow: 0 3px 12px rgba(var(--shadow-rgb), .15); }
|
|
220
|
+
body.contextual-chat-pane #contextual-attach-popover[hidden] { display: none; }
|
|
221
|
+
body.contextual-chat-pane #attach-wrap,
|
|
222
|
+
body.contextual-chat-pane #attach-wrap .composer-tool-group-inputs { display: flex; flex-direction: column; align-items: stretch; width: 100%; gap: 2px; }
|
|
223
|
+
body.contextual-chat-pane #attach-wrap #input-more-btn { display: none !important; }
|
|
224
|
+
body.contextual-chat-pane #attach-file-btn,
|
|
225
|
+
body.contextual-chat-pane #attach-image-btn,
|
|
226
|
+
body.contextual-chat-pane #context-sources-add { display: flex !important; align-items: center; justify-content: start; gap: 8px; width: 100%; height: 34px; padding: 0 9px; font: inherit; font-size: 13px; border-radius: 6px; }
|
|
227
|
+
body.contextual-chat-pane #context-sources-btn-wrap { display: block !important; }
|
|
228
|
+
body.contextual-chat-pane #context-sources-picker { position: static; width: 100%; min-width: 0; max-height: 220px; box-shadow: none; }
|
|
229
|
+
body.contextual-chat-pane #attach-file-btn .lucide,
|
|
230
|
+
body.contextual-chat-pane #attach-image-btn .lucide { width: 16px; height: 16px; }
|
|
231
|
+
body.contextual-chat-pane .stt-recording #contextual-attach-btn { display: none; }
|
|
232
|
+
body.contextual-chat-pane #input-row.stt-recording::before,
|
|
233
|
+
body.contextual-chat-pane #input-row:has(.stt-progress:not([hidden]))::before { grid-area: 4 / 1 / 7 / -1; }
|
|
234
|
+
body.contextual-chat-pane #input-row .stt-progress { grid-area: 6 / 1 / 7 / -1; width: auto; margin: 0 8px 6px; }
|
|
235
|
+
@media (pointer: coarse) {
|
|
236
|
+
body.contextual-chat-pane #input-row, body.contextual-chat-pane #input-row:focus-within { grid-template-columns: 44px minmax(0, 1fr) auto 58px 46px; }
|
|
237
|
+
body.contextual-chat-pane #contextual-attach-btn, body.contextual-chat-pane #config-chip,
|
|
238
|
+
body.contextual-chat-pane #attach-file-btn, body.contextual-chat-pane #attach-image-btn,
|
|
239
|
+
body.contextual-chat-pane #context-sources-add { min-height: 44px; }
|
|
240
|
+
}
|
|
@@ -5,8 +5,9 @@ import { refreshIcons } from './icons.js';
|
|
|
5
5
|
import { store } from './store.js';
|
|
6
6
|
import { getSendBtn, getStatusDot } from './dom-refs.js';
|
|
7
7
|
import { onThemeChange } from './theme.js';
|
|
8
|
-
import { getActivityEl, setActivityEl, addToMessages, scrollToBottom
|
|
8
|
+
import { getActivityEl, setActivityEl, addToMessages, scrollToBottom } from './app-rendering.js';
|
|
9
9
|
import { escapeHtml } from './utils.js';
|
|
10
|
+
import { resolveProjectAssistantIdentity, applyProjectAssistantIdentity } from './project-chat-identity.js';
|
|
10
11
|
|
|
11
12
|
// --- Module-owned state ---
|
|
12
13
|
var faviconLink, faviconOrigHref, faviconCanvas, faviconCtx, faviconImg, faviconImgReady;
|
|
@@ -210,14 +211,12 @@ export function setActivity(text) {
|
|
|
210
211
|
if (!getActivityEl()) {
|
|
211
212
|
var _actEl = document.createElement("div");
|
|
212
213
|
_actEl.className = "activity-inline";
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
// animating. DM mode handles its own avatar via mate-thinking
|
|
216
|
-
// elements and shouldn't pick up a vendor avatar here.
|
|
214
|
+
// The same session-bound identity owns waiting, thoughts and replies.
|
|
215
|
+
// DM mode retains its own Mate-thinking row.
|
|
217
216
|
var _isDm = !!(store.get('dmMode') && store.get('dmTargetUser') && store.get('dmTargetUser').isMate);
|
|
218
217
|
if (!_isDm) {
|
|
219
|
-
var
|
|
220
|
-
var _avatarUrl =
|
|
218
|
+
var _identity = resolveProjectAssistantIdentity(store.snap(), store.get('currentVendor'));
|
|
219
|
+
var _avatarUrl = _identity.avatarUrl;
|
|
221
220
|
_actEl.innerHTML =
|
|
222
221
|
'<img class="activity-inline-avatar" src="' + escapeHtml(_avatarUrl) + '" alt="">' +
|
|
223
222
|
'<div class="mate-thinking-dots"><span></span><span></span><span></span></div>';
|
|
@@ -236,6 +235,7 @@ export function setActivity(text) {
|
|
|
236
235
|
if (!label) { label = document.createElement("span"); label.className = "activity-state-label activity-text"; activity.appendChild(label); }
|
|
237
236
|
label.textContent = labels[text];
|
|
238
237
|
} else if (label) label.remove();
|
|
238
|
+
applyProjectAssistantIdentity(activity, resolveProjectAssistantIdentity(store.snap(), store.get('currentVendor')));
|
|
239
239
|
addToMessages(activity);
|
|
240
240
|
scrollToBottom();
|
|
241
241
|
} else {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { handleContextualConversations } from './contextual-mate-sessions.js';
|
|
2
|
+
import { handleMateContextMessage } from './contextual-mate-context.js';
|
|
1
3
|
import { handleIssueReference } from './clay-issue-links.js';
|
|
2
4
|
// Narrow pre-router for Home and Capsule protocol responses kept out of the legacy router.
|
|
3
5
|
|
|
@@ -19,6 +21,8 @@ import { handleProjectMateCreationMessage } from './project-mate-creation-worksp
|
|
|
19
21
|
import { handleProjectDebatePlanningMessage } from './project-debate-planning-workspace.js';
|
|
20
22
|
|
|
21
23
|
export function handleHomeProtocolMessage(msg) {
|
|
24
|
+
if (handleContextualConversations(msg)) return true;
|
|
25
|
+
if (handleMateContextMessage(msg)) return true;
|
|
22
26
|
if (handleIssueReference(msg)) return true;
|
|
23
27
|
if (handleClaySessionTarget(msg)) return true;
|
|
24
28
|
if (isHomeWorkspaceAssignmentMessage(msg)) {
|
|
@@ -104,7 +108,7 @@ function dispatchMessage(msg) {
|
|
|
104
108
|
if (handleDefaultAiMessage(msg)) return;
|
|
105
109
|
if (handleCursorSharingMessage(msg)) return;
|
|
106
110
|
var searchHandled = handleSearchClayMessage(msg);
|
|
107
|
-
if (searchHandled
|
|
111
|
+
if (searchHandled) return;
|
|
108
112
|
if (handleHomeProtocolMessage(msg)) return;
|
|
109
113
|
processAppMessage(msg);
|
|
110
114
|
}
|