clay-server 5.1.0-beta.1 → 5.1.0-beta.2

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.
Files changed (157) hide show
  1. package/LICENSES/README.md +4 -0
  2. package/LICENSES/dicebear-avatars.md +16 -0
  3. package/lib/daemon-project-access.js +7 -1
  4. package/lib/daemon.js +2 -0
  5. package/lib/dicebear-avatar.js +62 -0
  6. package/lib/knowledge-db-service.js +175 -0
  7. package/lib/knowledge-db-validation.js +0 -0
  8. package/lib/knowledge-document-index.js +49 -0
  9. package/lib/knowledge-draft-store.js +56 -0
  10. package/lib/knowledge-file-store.js +199 -0
  11. package/lib/knowledge-markdown.js +128 -0
  12. package/lib/mate-knowledge-mcp-server.js +29 -6
  13. package/lib/mate-knowledge-service.js +23 -2
  14. package/lib/mate-knowledge-sync.js +36 -21
  15. package/lib/mate-workspace-color.js +4 -0
  16. package/lib/mates.js +18 -0
  17. package/lib/project-connection.js +36 -2
  18. package/lib/project-debate-proposal.js +6 -0
  19. package/lib/project-debate-workspace.js +43 -0
  20. package/lib/project-debate.js +1 -0
  21. package/lib/project-knowledge.js +315 -136
  22. package/lib/project-mate-creation-proposal.js +1 -0
  23. package/lib/project-sessions.js +39 -2
  24. package/lib/project-user-knowledge.js +60 -0
  25. package/lib/project.js +59 -18
  26. package/lib/public/app.js +73 -34
  27. package/lib/public/clay-studio-wordmark-bold.svg +20 -0
  28. package/lib/public/css/clay-workspace.css +105 -0
  29. package/lib/public/css/debates-workbench.css +47 -0
  30. package/lib/public/css/home-debate-live.css +26 -0
  31. package/lib/public/css/home-hub.css +3 -1
  32. package/lib/public/css/home-mate-model-picker.css +15 -131
  33. package/lib/public/css/home-mate-settings.css +168 -16
  34. package/lib/public/css/icon-strip.css +249 -32
  35. package/lib/public/css/mate-conversation.css +176 -0
  36. package/lib/public/css/mate-knowledge-workbench.css +118 -0
  37. package/lib/public/css/mate-workspace-color.css +16 -0
  38. package/lib/public/css/mates.css +28 -28
  39. package/lib/public/css/messages.css +1 -114
  40. package/lib/public/css/mobile-nav.css +16 -16
  41. package/lib/public/css/overlays.css +8 -0
  42. package/lib/public/css/project-logs.css +7 -0
  43. package/lib/public/css/project-mate-creation.css +105 -0
  44. package/lib/public/css/right-workbench.css +3 -3
  45. package/lib/public/css/session-folders.css +80 -21
  46. package/lib/public/css/sidebar.css +183 -107
  47. package/lib/public/css/title-bar.css +151 -0
  48. package/lib/public/css/worker-delegation.css +47 -0
  49. package/lib/public/css/worker-proposal.css +72 -150
  50. package/lib/public/css/you.css +74 -0
  51. package/lib/public/index.html +33 -101
  52. package/lib/public/modules/account-island.js +230 -0
  53. package/lib/public/modules/app-cursors.js +19 -43
  54. package/lib/public/modules/app-debate-ui.js +4 -3
  55. package/lib/public/modules/app-header.js +106 -0
  56. package/lib/public/modules/app-message-router.js +12 -3
  57. package/lib/public/modules/app-messages.js +34 -9
  58. package/lib/public/modules/app-notifications.js +4 -7
  59. package/lib/public/modules/app-projects.js +5 -38
  60. package/lib/public/modules/app-rendering.js +12 -13
  61. package/lib/public/modules/avatar.js +25 -9
  62. package/lib/public/modules/chat-render-runtime.js +16 -4
  63. package/lib/public/modules/command-palette.js +2 -15
  64. package/lib/public/modules/cursor-sharing-preference.js +3 -3
  65. package/lib/public/modules/debate-controls.js +299 -0
  66. package/lib/public/modules/debate.js +2 -0
  67. package/lib/public/modules/debates-workbench.js +339 -0
  68. package/lib/public/modules/default-ai.js +81 -65
  69. package/lib/public/modules/home-debate-controls.js +18 -289
  70. package/lib/public/modules/home-mate-avatar-editor.js +228 -0
  71. package/lib/public/modules/home-mate-color-picker.js +66 -0
  72. package/lib/public/modules/home-mate-creation.js +1 -1
  73. package/lib/public/modules/home-mate-instructions.js +90 -0
  74. package/lib/public/modules/home-mate-model-picker.js +80 -271
  75. package/lib/public/modules/home-mate-profile-editor.js +72 -0
  76. package/lib/public/modules/home-mate-settings.js +118 -125
  77. package/lib/public/modules/home-shell.js +3 -0
  78. package/lib/public/modules/home-surface-boot.js +1 -9
  79. package/lib/public/modules/icon-strip-tooltip.js +95 -0
  80. package/lib/public/modules/knowledge-db-edit-state.js +35 -0
  81. package/lib/public/modules/knowledge-db-workbench.js +234 -0
  82. package/lib/public/modules/knowledge-history-state.js +55 -0
  83. package/lib/public/modules/knowledge-markdown-editor.js +57 -0
  84. package/lib/public/modules/knowledge-preview-links.js +70 -0
  85. package/lib/public/modules/knowledge-workbench-shell.js +21 -0
  86. package/lib/public/modules/mate-knowledge-workbench-state.js +174 -0
  87. package/lib/public/modules/mate-knowledge-workbench.js +500 -0
  88. package/lib/public/modules/mate-knowledge.js +11 -3
  89. package/lib/public/modules/mate-management.js +54 -10
  90. package/lib/public/modules/mate-sidebar.js +11 -1
  91. package/lib/public/modules/mate-workspace-color.js +33 -0
  92. package/lib/public/modules/mention.js +5 -13
  93. package/lib/public/modules/profile.js +51 -18
  94. package/lib/public/modules/project-chat-identity.js +79 -0
  95. package/lib/public/modules/project-debate-planning-workspace.js +250 -0
  96. package/lib/public/modules/project-debate-workspace.js +185 -0
  97. package/lib/public/modules/project-header-identity.js +127 -0
  98. package/lib/public/modules/project-logs-render.js +9 -4
  99. package/lib/public/modules/project-mate-creation-workspace.js +414 -0
  100. package/lib/public/modules/project-mate-navigation.js +238 -0
  101. package/lib/public/modules/project-session-navigation.js +29 -0
  102. package/lib/public/modules/project-switcher.js +6 -8
  103. package/lib/public/modules/projects-hub-view.js +5 -6
  104. package/lib/public/modules/projects-hub.js +2 -6
  105. package/lib/public/modules/qrcode.js +27 -8
  106. package/lib/public/modules/search-clay-chat.js +8 -11
  107. package/lib/public/modules/session-activity-tooltip.js +12 -0
  108. package/lib/public/modules/session-create-form.js +86 -14
  109. package/lib/public/modules/session-create.js +50 -7
  110. package/lib/public/modules/session-list-visibility.js +41 -0
  111. package/lib/public/modules/session-presence-ui.js +4 -1
  112. package/lib/public/modules/session-title-marquee.js +51 -0
  113. package/lib/public/modules/sidebar-mates.js +3 -50
  114. package/lib/public/modules/sidebar-mobile.js +63 -60
  115. package/lib/public/modules/sidebar-projects.js +84 -97
  116. package/lib/public/modules/sidebar-session-folders-ui.js +2 -2
  117. package/lib/public/modules/sidebar-session-hierarchy.js +149 -70
  118. package/lib/public/modules/sidebar-sessions.js +49 -50
  119. package/lib/public/modules/sidebar.js +11 -13
  120. package/lib/public/modules/thinking-lifecycle.js +7 -6
  121. package/lib/public/modules/tool-palette-order.js +4 -3
  122. package/lib/public/modules/tool-palette.js +13 -3
  123. package/lib/public/modules/tools.js +22 -22
  124. package/lib/public/modules/worker-proposal.js +42 -8
  125. package/lib/public/modules/worker-runtime-picker.js +115 -0
  126. package/lib/public/modules/you-activity.js +121 -0
  127. package/lib/public/modules/you.js +251 -0
  128. package/lib/public/style.css +16 -8
  129. package/lib/public/vendor/codemirror/LICENSE +21 -0
  130. package/lib/public/vendor/codemirror/codemirror.css +344 -0
  131. package/lib/public/vendor/codemirror/codemirror.js +9884 -0
  132. package/lib/public/vendor/codemirror/continuelist.js +101 -0
  133. package/lib/public/vendor/codemirror/markdown.js +886 -0
  134. package/lib/public/vendor/codemirror/show-hint.css +37 -0
  135. package/lib/public/vendor/codemirror/show-hint.js +523 -0
  136. package/lib/sdk-bridge.js +15 -3
  137. package/lib/server-admin.js +11 -0
  138. package/lib/server-home-chat-events.js +1 -1
  139. package/lib/server-home-chat.js +25 -3
  140. package/lib/server-home-debate-planning.js +4 -1
  141. package/lib/server-home-debates.js +2 -0
  142. package/lib/server-home-mate-creation.js +4 -1
  143. package/lib/server-mate-instructions.js +44 -0
  144. package/lib/server-mates.js +12 -3
  145. package/lib/server-palette.js +1 -1
  146. package/lib/server-settings.js +65 -1
  147. package/lib/server-user-knowledge.js +119 -0
  148. package/lib/server.js +21 -1
  149. package/lib/session-visibility.js +7 -2
  150. package/lib/sessions.js +32 -6
  151. package/lib/user-knowledge-service.js +167 -0
  152. package/lib/users-permissions.js +7 -0
  153. package/lib/users-project-mate-filter-preferences.js +39 -0
  154. package/lib/users.js +6 -0
  155. package/lib/workspace-query-access.js +4 -1
  156. package/lib/ws-schema.js +50 -0
  157. package/package.json +10 -1
@@ -1,3 +1,4 @@
1
+ import { beginProjectDebatePrepend, endProjectDebatePrepend } from './project-debate-workspace.js';
1
2
  // app-header.js - Session rename, session info popover, progressive history loading
2
3
  // Extracted from app.js (PR-34)
3
4
 
@@ -12,6 +13,9 @@ import { saveToolState, resetToolState, restoreToolState } from './tools.js';
12
13
  import { getSessionUsage, setSessionUsage, getContextData, setContextData, updateContextPanel, updateUsagePanel } from './app-panels.js';
13
14
  import { onHistoryPrepended as onSessionSearchHistoryPrepended } from './session-search.js';
14
15
  import { getCachedSessions } from './sidebar-sessions.js';
16
+ import { buildSessionHierarchy } from './session-hierarchy.js';
17
+ import { splitGroupRoles } from './split-group-helpers.js';
18
+ import { createWorkerHistoryControl } from './sidebar-session-hierarchy.js';
15
19
  import { bindPermissionControl, renderPermissionControl } from './permission-control.js';
16
20
  import { startHeaderSessionInlineRename } from './session-context-menu.js';
17
21
 
@@ -19,11 +23,104 @@ import { startHeaderSessionInlineRename } from './session-context-menu.js';
19
23
  var sessionInfoPopover = null;
20
24
  var historySentinelObserver = null;
21
25
 
26
+ function splitHistoryOwner(state, sessions) {
27
+ var split = state.splitPanes;
28
+ if (!split || !Array.isArray(split.panes)) return null;
29
+ var groups = state.splitGroups || [];
30
+ var group = null;
31
+ var roles = null;
32
+ for (var gi = 0; gi < groups.length; gi++) {
33
+ var candidateRoles = splitGroupRoles(groups[gi]);
34
+ if (!candidateRoles) continue;
35
+ var matches = false;
36
+ for (var pi = 0; pi < split.panes.length; pi++) {
37
+ if (candidateRoles.orderedIds.indexOf(split.panes[pi].sessionId) !== -1) matches = true;
38
+ }
39
+ if (matches) { group = groups[gi]; roles = candidateRoles; break; }
40
+ }
41
+ if (!group || !roles) return null;
42
+ var hierarchy = buildSessionHierarchy(sessions || []);
43
+ for (var hi = 0; hi < hierarchy.roots.length; hi++) {
44
+ var root = hierarchy.roots[hi];
45
+ if (root.driver.id === roles.driverId && root.workers.length) return { root: root, group: group, roles: roles };
46
+ }
47
+ return null;
48
+ }
49
+
50
+ function splitPaneHistoryUrl(slug, sessionId) {
51
+ return "/p/" + encodeURIComponent(slug) + "/?pane=1&session=" + encodeURIComponent(sessionId);
52
+ }
53
+
54
+ function createHeaderWorkerHistoryControl(root, context) {
55
+ var capturedWs = context.ws;
56
+ var capturedSlug = context.slug;
57
+ var capturedMateId = context.mateId;
58
+ var capturedActiveSessionId = context.activeSessionId;
59
+ var capturedSplit = context.split;
60
+ var historyControl = createWorkerHistoryControl(root.driver, root.workers, {
61
+ className: "header-worker-history-btn",
62
+ label: "Show Split Worker history",
63
+ validate: function (driver) {
64
+ var current = store.snap();
65
+ var ws = getWs();
66
+ if (!ws || ws !== capturedWs || ws.readyState !== 1 || !current.connected || current.currentSlug !== capturedSlug ||
67
+ (current.activeProjectMateId || null) !== capturedMateId || current.dmMode) return false;
68
+ if (!capturedSplit) return current.activeSessionId === driver.id && !current.splitPanes;
69
+ var split = current.splitPanes;
70
+ if (!split || split.groupId !== capturedSplit.groupId || !Array.isArray(split.panes) || split.panes.length !== capturedSplit.panes.length) return false;
71
+ if (current.activeSessionId !== capturedActiveSessionId) return false;
72
+ for (var i = 0; i < split.panes.length; i++) {
73
+ if (split.panes[i].sessionId !== capturedSplit.panes[i].sessionId || split.panes[i].slug !== capturedSplit.panes[i].slug) return false;
74
+ }
75
+ return true;
76
+ },
77
+ navigate: capturedSplit ? function (worker) {
78
+ var opened = window.open(splitPaneHistoryUrl(capturedSlug, worker.id), "_blank", "noopener");
79
+ return !!opened;
80
+ } : null,
81
+ });
82
+ return historyControl;
83
+ }
84
+
22
85
  export function initHeader() {
23
86
  var headerRenameBtn = document.getElementById("header-rename-btn");
24
87
  var headerTitleEl = document.getElementById("header-title");
25
88
  var headerInfoBtn = document.getElementById("header-info-btn");
26
89
  var headerFullAccessBtn = document.getElementById("header-full-access-btn");
90
+ var headerSearchBtn = document.getElementById("find-in-session-btn");
91
+ var headerWorkerHistoryBtn = null;
92
+
93
+ function refreshHeaderWorkerHistory() {
94
+ if (!headerSearchBtn) return;
95
+ if (headerWorkerHistoryBtn) {
96
+ headerWorkerHistoryBtn.remove();
97
+ headerWorkerHistoryBtn = null;
98
+ }
99
+ var state = store.snap();
100
+ var sessions = getCachedSessions() || [];
101
+ var hierarchy = buildSessionHierarchy(sessions);
102
+ var owner = null;
103
+ var context = null;
104
+ if (state.splitPanes && state.splitPanes.panes) {
105
+ var splitOwner = splitHistoryOwner(state, sessions);
106
+ owner = splitOwner ? splitOwner.root : null;
107
+ if (owner) {
108
+ context = {
109
+ ws: getWs(), slug: state.currentSlug, mateId: state.activeProjectMateId || null,
110
+ activeSessionId: state.activeSessionId,
111
+ split: { groupId: state.splitPanes.groupId, panes: state.splitPanes.panes.map(function (pane) { return { sessionId: pane.sessionId, slug: pane.slug }; }) },
112
+ };
113
+ }
114
+ } else {
115
+ for (var hi = 0; hi < hierarchy.roots.length; hi++) {
116
+ if (hierarchy.roots[hi].driver.id === state.activeSessionId && hierarchy.roots[hi].workers.length) { owner = hierarchy.roots[hi]; break; }
117
+ }
118
+ if (owner) context = { ws: getWs(), slug: state.currentSlug, mateId: state.activeProjectMateId || null, activeSessionId: state.activeSessionId, split: null };
119
+ }
120
+ if (!owner || !context) return;
121
+ headerWorkerHistoryBtn = createHeaderWorkerHistoryControl(owner, context);
122
+ if (headerWorkerHistoryBtn) headerSearchBtn.insertAdjacentElement("afterend", headerWorkerHistoryBtn);
123
+ }
27
124
 
28
125
  function permissionControlState() {
29
126
  var s = store.snap();
@@ -121,6 +218,12 @@ export function initHeader() {
121
218
 
122
219
  // --- Session info popover ---
123
220
  if (headerInfoBtn) {
221
+ store.subscribe(function (state, prev) {
222
+ if (state.activeSessionId !== prev.activeSessionId || state.currentSlug !== prev.currentSlug || state.activeProjectMateId !== prev.activeProjectMateId || state.splitPanes !== prev.splitPanes) {
223
+ closeSessionInfoPopover();
224
+ refreshHeaderWorkerHistory();
225
+ }
226
+ });
124
227
  headerInfoBtn.addEventListener("click", function (e) {
125
228
  e.stopPropagation();
126
229
  if (sessionInfoPopover) { closeSessionInfoPopover(); return; }
@@ -193,6 +296,7 @@ export function initHeader() {
193
296
  }
194
297
  });
195
298
  }
299
+ refreshHeaderWorkerHistory();
196
300
  }
197
301
 
198
302
  export function closeSessionInfoPopover() {
@@ -269,11 +373,13 @@ export function prependOlderHistory(items, meta) {
269
373
  var anchorEl = getPrependAnchor();
270
374
  var anchorOffset = anchorEl ? anchorEl.getBoundingClientRect().top : 0;
271
375
 
376
+ beginProjectDebatePrepend();
272
377
  // Process each item through the rendering pipeline
273
378
  for (var i = 0; i < items.length; i++) {
274
379
  processMessage(items[i]);
275
380
  }
276
381
 
382
+ endProjectDebatePrepend();
277
383
  // Finalize any open assistant block from the batch
278
384
  finalizeAssistantBlock();
279
385
 
@@ -2,11 +2,11 @@ import { handleIssueReference } from './clay-issue-links.js';
2
2
  // Narrow pre-router for Home and Capsule protocol responses kept out of the legacy router.
3
3
 
4
4
  import { processMessage as processAppMessage } from './app-messages.js';
5
- import { handleHomeMateModelsState, handleHomeMateModelResult } from './home-mate-settings.js';
5
+ import { handleMateInstructionsResult, handleHomeMateModelsState, handleHomeMateModelResult } from './home-mate-settings.js';
6
6
  import { handleHomeMateSessionIdentity, handleHomeDebateTranscript, handleHomeWorkspaceAssignment } from './home-mate-chat.js';
7
7
  import { handleToolLlmConfigState } from './tool-llm-status.js';
8
8
  import { handleToolSourceState, handleToolMateAccessState } from './home-tools.js';
9
- import { handleHomeDebatesState } from './home-debates-archive.js';
9
+ import { handleDebatesWorkbenchState } from './debates-workbench.js';
10
10
  import { renderProjectWorkspaceAssignment, showProjectWorkspaceAssignmentError } from './project-workspace-assignment.js';
11
11
  import { isHomeWorkspaceAssignmentMessage } from './workspace-assignment-routing.js';
12
12
  import { handleSearchClayMessage } from './search-clay-chat.js';
@@ -15,6 +15,8 @@ import { handleDefaultAiMessage } from './default-ai.js';
15
15
  import { handleCursorSharingMessage } from './cursor-sharing-preference.js';
16
16
  import { handlePendingMessageQueueMessage } from './pending-message-queue.js';
17
17
  import { receiveHistoryReplay } from './history-replay-batch.js';
18
+ import { handleProjectMateCreationMessage } from './project-mate-creation-workspace.js';
19
+ import { handleProjectDebatePlanningMessage } from './project-debate-planning-workspace.js';
18
20
 
19
21
  export function handleHomeProtocolMessage(msg) {
20
22
  if (handleIssueReference(msg)) return true;
@@ -32,9 +34,10 @@ export function handleHomeProtocolMessage(msg) {
32
34
  return true;
33
35
  }
34
36
  if (msg.type === "home_debates_state") {
35
- handleHomeDebatesState(msg);
37
+ handleDebatesWorkbenchState(msg);
36
38
  return true;
37
39
  }
40
+ if (msg.type === "mate_instructions_result") { handleMateInstructionsResult(msg); return true; }
38
41
  if (msg.type === "home_mate_models_state") {
39
42
  handleHomeMateModelsState(msg);
40
43
  return true;
@@ -87,6 +90,12 @@ export function processMessage(msg) {
87
90
  }
88
91
 
89
92
  function dispatchMessage(msg) {
93
+ if (typeof handleProjectDebatePlanningMessage === "function" && handleProjectDebatePlanningMessage(msg)) return;
94
+ if (msg.type === "home_debate_event" && msg.eventType) {
95
+ processAppMessage(Object.assign({}, msg, { type: msg.eventType, mateId: msg.speakerMateId || null }));
96
+ return;
97
+ }
98
+ if (handleProjectMateCreationMessage(msg)) return;
90
99
  if (handlePendingMessageQueueMessage(msg)) return;
91
100
  if (handleDefaultAiMessage(msg)) return;
92
101
  if (handleCursorSharingMessage(msg)) return;
@@ -1,3 +1,8 @@
1
+ import { handleYouMessage } from './you.js';
2
+ import { handleYouActivity } from './you-activity.js';
3
+ import { handleProjectDebateMessage } from './project-debate-workspace.js';
4
+ import { openMateWorkspace, renderProjectMates } from './project-mate-navigation.js';
5
+ import { refreshProjectAssistantIdentities } from './project-chat-identity.js';
1
6
  import { handleLinearResult } from './linear-panel.js';
2
7
  import { handleSharedBrowserMessage } from './shared-browser.js';
3
8
  import { openWireframe } from './wireframe-workbench.js';
@@ -25,12 +30,13 @@ import { updateDmBadge, setMentionActive, renderUserStrip } from './sidebar-mate
25
30
  import { renderSidebarPresence } from './sidebar-presence.js';
26
31
  import { refreshMobileChatSheet } from './sidebar-mobile.js';
27
32
  import { renderMateSessionList, handleMateSearchResults, updateMateSidebarProfile } from './mate-sidebar.js';
28
- import { openHomeChat, handleHomeMateHistory, handleHomeMateDelta, handleHomeMateSegment, handleHomeMateDone, handleHomeMateError, handleHomeMateSessionsState } from './home-mate-chat.js';
33
+ import { handleHomeMateHistory, handleHomeMateDelta, handleHomeMateSegment, handleHomeMateDone, handleHomeMateError, handleHomeMateSessionsState } from './home-mate-chat.js';
29
34
  import { handleHomeSurfaceState } from './home-surface.js';
30
35
  import { handleDefaultVendorMessage } from './default-vendor.js';
31
36
  import { handleContextViewMessage } from './context-view-preference.js';
32
- import { handleHomeMateMemoryState, handleHomeMateKnowledgeState } from './home-mate-settings.js';
33
- import { renderKnowledgeList, handleKnowledgeContent } from './mate-knowledge.js';
37
+ import { handleHomeMateMemoryState, handleHomeMateKnowledgeState, syncHomeMateSettingsTarget, handleHomeMateAvatarError } from './home-mate-settings.js';
38
+ import { renderKnowledgeList, handleKnowledgeContent, handleKnowledgeMutation } from './mate-knowledge.js';
39
+ import { handleKnowledgeWorkbenchMessage } from './mate-knowledge-workbench.js';
34
40
  import { renderMemoryList } from './mate-memory.js';
35
41
  import { handlePaletteSessionSwitch, setPaletteVersion } from './command-palette.js';
36
42
  import { handleFindInSessionResults } from './session-search.js';
@@ -83,7 +89,6 @@ import { getModelInfoUpdate, modelEntryValue, modelEntryMatches, handleModelSele
83
89
  import { getModelEffortLevels, accumulateUsage, updateUsagePanel, accumulateContext, updateContextPanel, renderCtxPopover, updateStatusPanel, markContextUnavailable } from './app-panels.js';
84
90
  import { updateProjectList, resetClientState, showUpdateAvailable, handleRemoveProjectCheckResult, handleRemoveProjectResult, handleBrowseDirResult, handleAddProjectResult, handleCloneProgress, finishProjectSessionActivation } from './app-projects.js';
85
91
  import { updateHistorySentinel, prependOlderHistory } from './app-header.js';
86
- import { hideHomeHub, showHomeHub } from './app-home-hub.js';
87
92
  import { handleToolsState, handleToolInstalled, handleToolRemoved, handleToolStorageResult, handleToolLlmResult, handleToolsError, handleToolControlRequest, handleToolServerState, handleToolServerEvent, handleCapsuleGameSession } from './home-tools.js';
88
93
  import { handleHomeDockState } from './home-dock.js';
89
94
  import { handleToolFrameUrlState } from './home-tool-frame.js';
@@ -110,6 +115,7 @@ var connectOverlay = document.getElementById("connect-overlay");
110
115
  initMessageDeliveryUi();
111
116
 
112
117
  export function processMessage(msg) {
118
+ if (handleProjectDebateMessage(msg)) return;
113
119
  if (handleMcpConnectionMessage(msg)) return;
114
120
  if (handleSharedBrowserMessage(msg)) return;
115
121
  if (msg.type === "vendor_login_browser_frame" || msg.type === "vendor_login_browser_status") {
@@ -120,6 +126,7 @@ export function processMessage(msg) {
120
126
  if (handleAutonomousRunMessage(msg)) return;
121
127
  if (handleLoopInterviewMessage(msg)) return;
122
128
  if (handleScheduledTaskMessage(msg)) return;
129
+ if (handleKnowledgeWorkbenchMessage(msg)) return;
123
130
  if (handleSessionCreateMessage(msg)) return;
124
131
  if (msg && msg.type === "new_session_result" && handleNewSessionResult(msg)) return;
125
132
  if (handleDefaultVendorMessage(msg)) return;
@@ -172,6 +179,7 @@ export function processMessage(msg) {
172
179
  return;
173
180
  }
174
181
  if (msg.type === "knowledge_saved" || msg.type === "knowledge_deleted" || msg.type === "knowledge_promoted" || msg.type === "knowledge_depromoted") {
182
+ handleKnowledgeMutation(msg);
175
183
  return;
176
184
  }
177
185
  if (msg.type === "memory_list") {
@@ -338,8 +346,7 @@ export function processMessage(msg) {
338
346
  store.set({ dmMode: false });
339
347
  }
340
348
  messagesEl.innerHTML = "";
341
- showHomeHub();
342
- openHomeChat(msg.mateId);
349
+ openMateWorkspace(msg.mateId);
343
350
  }
344
351
  // Clear the flag and notify server that mate DM is closed
345
352
  if (store.get('returningFromMateDm')) {
@@ -363,7 +370,12 @@ export function processMessage(msg) {
363
370
  clearProjectSplitState();
364
371
  }
365
372
  detachTuiView();
366
- store.set({ projectName: msg.project || msg.cwd, vendorInfo: msg.vendors || {} });
373
+ store.set({
374
+ projectName: msg.project || msg.cwd,
375
+ vendorInfo: msg.vendors || {},
376
+ activeProjectMateId: msg.isMate && msg.mateId ? msg.mateId : null,
377
+ activeProjectMateName: msg.isMate ? (msg.mateDisplayName || msg.project || "Mate") : "",
378
+ });
367
379
  if (msg.cwd) store.set({ cwd: msg.cwd });
368
380
  if (msg.slug) store.set({ currentSlug: msg.slug, activeProjectSlug: msg.slug, sessionListProjectSlug: null, splitGroupsProjectSlug: null });
369
381
  try { var _is = store.snap(); localStorage.setItem("clay-project-name-" + (_is.currentSlug || "default"), _is.projectName); } catch (e) {}
@@ -397,6 +409,7 @@ export function processMessage(msg) {
397
409
  var spBanner = document.getElementById("skip-perms-pill");
398
410
  if (spBanner) spBanner.classList.toggle("hidden", msg.dangerouslySkipPermissions !== true);
399
411
  updateProjectList(msg);
412
+ renderProjectMates();
400
413
  refreshProjectSessionVisibilitySettings(msg.projects);
401
414
  break;
402
415
 
@@ -877,7 +890,8 @@ export function processMessage(msg) {
877
890
  var _effectiveTerminalId = (typeof msg.runtimeTerminalId === "number")
878
891
  ? msg.runtimeTerminalId
879
892
  : (typeof msg.terminalId === "number" ? msg.terminalId : null);
880
- store.set({ activeSessionId: msg.id, sessionOriginId: msg.sessionOriginId || null, cliSessionId: msg.cliSessionId || null, currentModel: msg.model || "", currentEffort: msg.effort || store.get('currentEffort'), vendorCapabilities: msg.capabilities || {}, sessionIsProcessing: !!msg.isProcessing, activeSessionMode: _effectiveMode, activeTerminalId: _effectiveTerminalId, sessionHasHistory: !!msg.hasHistory, sessionVendorBound: !!msg.vendor || !!msg.hasHistory, sessionFullAccess: msg.permissionMode === "bypassPermissions", currentMode: msg.permissionMode || store.get('currentMode'), effectivePermissionMode: msg.effectivePermissionMode || null, permissionCapabilities: msg.permissionCapabilities || { auto: false, mcpOverride: false }, mcpPermissionModeOverrides: msg.mcpPermissionModeOverrides || {} });
893
+ var _sessionRole = msg.sessionRole === "worker" ? "worker" : "driver";
894
+ store.set({ activeSessionId: msg.id, sessionOriginId: msg.sessionOriginId || null, cliSessionId: msg.cliSessionId || null, currentModel: msg.model || "", currentEffort: msg.effort || store.get('currentEffort'), vendorCapabilities: msg.capabilities || {}, sessionIsProcessing: !!msg.isProcessing, activeSessionMode: _effectiveMode, activeTerminalId: _effectiveTerminalId, sessionHasHistory: !!msg.hasHistory, sessionVendorBound: !!msg.vendor || !!msg.hasHistory, sessionFullAccess: msg.permissionMode === "bypassPermissions", currentMode: msg.permissionMode || store.get('currentMode'), effectivePermissionMode: msg.effectivePermissionMode || null, permissionCapabilities: msg.permissionCapabilities || { auto: false, mcpOverride: false }, mcpPermissionModeOverrides: msg.mcpPermissionModeOverrides || {}, activeSessionMateId: _sessionRole === "worker" ? null : (store.get('activeProjectMateId') || null), activeSessionMateName: _sessionRole === "worker" ? "" : (store.get('activeProjectMateName') || "") });
881
895
  handleScheduledTaskSessionSwitched(msg);
882
896
  requestLoopInterviewState();
883
897
  activateDeliverySession(msg.id, msg.cliSessionId || null, msg.sessionOriginId || null);
@@ -958,7 +972,7 @@ export function processMessage(msg) {
958
972
  }
959
973
  // Reload survival: a restored active session that is a split-group
960
974
  // member reopens its group (no-op when a split is already open).
961
- if (finishProjectSessionActivation()) hideHomeHub();
975
+ finishProjectSessionActivation();
962
976
  maybeRestoreSplitGroup();
963
977
  break;
964
978
 
@@ -1745,6 +1759,13 @@ export function processMessage(msg) {
1745
1759
  handleNoteDeleteResult(msg);
1746
1760
  break;
1747
1761
 
1762
+ case "you_result":
1763
+ case "you_changed":
1764
+ case "you_reviewed":
1765
+ handleYouMessage(msg);
1766
+ handleYouActivity(msg);
1767
+ break;
1768
+
1748
1769
  case "project_logs_state":
1749
1770
  handleProjectLogsState(msg);
1750
1771
  break;
@@ -1930,6 +1951,8 @@ export function processMessage(msg) {
1930
1951
  }
1931
1952
  }
1932
1953
  store.set({ cachedMatesList: _cml });
1954
+ refreshProjectAssistantIdentities(messagesEl);
1955
+ syncHomeMateSettingsTarget(msg);
1933
1956
  // renderUserStrip is handled by the store subscriber
1934
1957
  // Update mate sidebar if currently viewing this mate
1935
1958
  if (store.get('dmMode') && store.get('dmTargetUser') && store.get('dmTargetUser').isMate && store.get('dmTargetUser').id === msg.mate.id) {
@@ -1966,6 +1989,7 @@ export function processMessage(msg) {
1966
1989
 
1967
1990
  case "mate_list":
1968
1991
  store.set({ cachedMatesList: msg.mates || [], cachedAvailableBuiltins: msg.availableBuiltins || [] });
1992
+ refreshProjectAssistantIdentities(messagesEl);
1969
1993
  // renderUserStrip is handled by the store subscriber
1970
1994
  break;
1971
1995
 
@@ -1974,6 +1998,7 @@ export function processMessage(msg) {
1974
1998
  break;
1975
1999
 
1976
2000
  case "mate_error":
2001
+ handleHomeMateAvatarError(msg);
1977
2002
  showToast(msg.error || "Mate operation failed", "error");
1978
2003
  break;
1979
2004
 
@@ -7,8 +7,8 @@ import { refreshIcons, iconHtml } from './icons.js';
7
7
  import { escapeHtml } from './utils.js';
8
8
  import { store } from './store.js';
9
9
  import { getWs } from './ws-ref.js';
10
- import { showHomeHub } from './app-home-hub.js';
11
- import { openHomeChat } from './home-mate-chat.js';
10
+ import { openProjectSession } from './project-session-navigation.js';
11
+ import { openMateWorkspace } from './project-mate-navigation.js';
12
12
  import { getCachedProjects, switchProject, renderProjectList } from './app-projects.js';
13
13
  import { mateAvatarUrl, userAvatarUrl } from './avatar.js';
14
14
  import { openTuiModal } from './tui-attention.js';
@@ -618,11 +618,8 @@ function navigateToNotification(notif) {
618
618
 
619
619
  var mateId = notif.mateId || deriveMateIdFromNotification(notif);
620
620
  if (mateId) {
621
- if (notif.sessionId) {
622
- try { sessionStorage.setItem("pending-notif-session", notif.sessionId); } catch (e) {}
623
- }
624
- showHomeHub();
625
- openHomeChat(mateId);
621
+ if (notif.sessionId) openProjectSession(notif.slug || 'mate-' + mateId, notif.sessionId);
622
+ else openMateWorkspace(mateId);
626
623
  return;
627
624
  }
628
625
 
@@ -17,7 +17,6 @@ import { updateCrossProjectBlink, stopUrgentBlink, setActivity } from './app-fav
17
17
  import { spawnDustParticles } from './sidebar.js';
18
18
  import { isSearchOpen, closeSearch } from './session-search.js';
19
19
  import { exitDmMode } from './app-dm.js';
20
- import { isHomeHubVisible, hideHomeHub, showHomeHub } from './app-home-hub.js';
21
20
  import { resetFileBrowser } from './filebrowser.js';
22
21
  import { closeNotesBrowser } from './sticky-notes-browser.js';
23
22
  import { hideMemory } from './mate-memory.js';
@@ -40,6 +39,7 @@ import { chooseProjectAfterRemoval } from './project-removal-target.js';
40
39
  import { isProjectActivated, isProjectActivationPending, isProjectContextConnected, projectWsPath } from './project-activation.js';
41
40
  import { rememberHomePrimarySurface } from './home-surface.js';
42
41
  import { clearProjectSplitState } from './split-session-boundary.js';
42
+ import { isMateHeaderWorkspace, renderOrdinaryProjectHeader } from './project-header-identity.js';
43
43
 
44
44
  // --- Module-owned state ---
45
45
  var cachedProjects = [];
@@ -273,17 +273,6 @@ export function updateProjectList(msg) {
273
273
  myMessageAvatars[avatarIndex].src = document.body.dataset.myAvatarUrl;
274
274
  }
275
275
  }
276
- // Render my avatar (always present, hidden behind user-island)
277
- var meEl = document.getElementById("icon-strip-me");
278
- if (meEl && !meEl.hasChildNodes()) {
279
- var myUser = st2.cachedAllUsers.find(function (u) { return u.id === st2.myUserId; });
280
- if (myUser) {
281
- var meAvatar = document.createElement("img");
282
- meAvatar.className = "icon-strip-me-avatar";
283
- meAvatar.src = userAvatarUrl(myUser, 34);
284
- meEl.appendChild(meAvatar);
285
- }
286
- }
287
276
  }
288
277
  }
289
278
 
@@ -338,29 +327,8 @@ export function renderProjectList() {
338
327
  var iconStripActiveSlug = (st.mateProjectSlug && st.savedMainSlug) ? st.savedMainSlug : st.currentSlug;
339
328
  renderIconStrip(iconStripProjects, iconStripActiveSlug);
340
329
  // Update title bar project name and icon if it changed
341
- if (!st.mateProjectSlug) {
342
- for (var pi = 0; pi < cachedProjects.length; pi++) {
343
- if (cachedProjects[pi].slug === st.currentSlug) {
344
- var updatedName = cachedProjects[pi].title || cachedProjects[pi].project;
345
- var tbName = document.getElementById("title-bar-project-name");
346
- if (tbName && updatedName) tbName.textContent = updatedName;
347
- var tbIcon = document.getElementById("title-bar-project-icon");
348
- if (tbIcon) {
349
- var pIcon = cachedProjects[pi].icon || null;
350
- if (pIcon) {
351
- tbIcon.textContent = pIcon;
352
- parseEmojis(tbIcon);
353
- tbIcon.classList.add("has-icon");
354
- try { localStorage.setItem("clay-project-icon-" + (st.currentSlug || "default"), pIcon); } catch (e) {}
355
- } else {
356
- tbIcon.textContent = "";
357
- tbIcon.classList.remove("has-icon");
358
- try { localStorage.removeItem("clay-project-icon-" + (st.currentSlug || "default")); } catch (e) {}
359
- }
360
- }
361
- break;
362
- }
363
- }
330
+ if (!st.mateProjectSlug && !isMateHeaderWorkspace(st)) {
331
+ renderOrdinaryProjectHeader(Object.assign({}, st, { projectsHubList: cachedProjects }));
364
332
  }
365
333
  // Re-apply current socket status to the active icon's dot
366
334
  var dot = getStatusDot();
@@ -425,14 +393,13 @@ export function switchProject(slug) {
425
393
  var st = store.snap();
426
394
  var ws = getWs();
427
395
  var targetWsPath = projectWsPath(slug);
428
- var homeVisible = isHomeHubVisible() || store.get('projectsHubVisible');
396
+ var homeVisible = store.get('projectsHubVisible');
429
397
  var alreadyInProject = isProjectActivated(st, slug, ws);
430
398
  var wasDm = st.dmMode;
431
399
  var wasMate = st.dmMode && st.dmTargetUser && st.dmTargetUser.isMate;
432
400
  if (st.dmMode) exitDmMode(wasMate);
433
401
  if (homeVisible && alreadyInProject) {
434
402
  rememberHomePrimarySurface("project", slug);
435
- hideHomeHub();
436
403
  hideProjectsHub();
437
404
  completeProjectsOnboarding();
438
405
  if (document.documentElement.classList.contains("pwa-standalone")) {
@@ -496,7 +463,7 @@ export function confirmCurrentProjectSessionActivation() {
496
463
  export function finishProjectSessionActivation() {
497
464
  var confirmed = confirmCurrentProjectSessionActivation();
498
465
  if (!confirmed) return false;
499
- if (!store.get('pendingHomeProjectSlug')) return !isHomeHubVisible() && !store.get('projectsHubVisible');
466
+ if (!store.get('pendingHomeProjectSlug')) return !store.get('projectsHubVisible');
500
467
  return completePendingProjectActivation();
501
468
  }
502
469
 
@@ -8,7 +8,8 @@ import { refreshIcons } from './icons.js';
8
8
  import { closeToolGroup } from './tools.js';
9
9
  import { sendMessage, hasSendableContent } from './input.js';
10
10
  import { getChatLayout } from './theme.js';
11
- import { addToMessages, scrollToBottom, forceScrollToBottom, getMsgTime, shouldGroupMessage, getTurnCounter, getActivityEl, VENDOR_AVATARS, VENDOR_NAMES } from './chat-render-runtime.js';
11
+ import { addToMessages, scrollToBottom, forceScrollToBottom, getMsgTime, shouldGroupMessage, getTurnCounter, getActivityEl } from './chat-render-runtime.js';
12
+ import { resolveProjectAssistantIdentity, applyProjectAssistantIdentity } from './project-chat-identity.js';
12
13
  export { VENDOR_ORDER, EXPERIMENTAL_VENDORS, isExperimentalVendor } from './vendor-priority.js';
13
14
  export { initRendering, addToMessages, scrollToBottom, forceScrollToBottom, getMsgTime, shouldGroupMessage, getTurnCounter, setTurnCounter, getPrependAnchor, setPrependAnchor, getActivityEl, setActivityEl, getIsUserScrolledUp, setIsUserScrolledUp, getStickyBottom, armStickyBottom, disarmStickyBottom, VENDOR_AVATARS, VENDOR_NAMES, VENDOR_HOMEPAGES } from './chat-render-runtime.js';
14
15
  export { addUserMessage, addSystemMessage, addConflictMessage, addContextOverflowMessage } from './app-message-cards.js';
@@ -22,15 +23,15 @@ var streamDrainTimer = null;
22
23
  export function ensureAssistantBlock() {
23
24
  var _el = store.get('currentMsgEl');
24
25
  if (!_el) {
25
- var _isDm2 = document.body.classList.contains("mate-dm-active") && document.body.dataset.mateAvatarUrl;
26
26
  var vendor = store.get('currentVendor') || "claude";
27
- var dmTarget = store.get('dmTargetUser');
27
+ var identity = resolveProjectAssistantIdentity(store.snap(), vendor);
28
28
  _el = createAssistantBubble({
29
29
  turn: getTurnCounter(),
30
- avatarUrl: _isDm2 ? document.body.dataset.mateAvatarUrl : (VENDOR_AVATARS[vendor] || VENDOR_AVATARS.claude),
31
- name: _isDm2 ? ((dmTarget && dmTarget.displayName) || "Mate") : (VENDOR_NAMES[vendor] || VENDOR_NAMES.claude),
30
+ avatarUrl: identity.avatarUrl,
31
+ name: identity.name,
32
32
  time: getMsgTime(),
33
33
  });
34
+ applyProjectAssistantIdentity(_el, identity);
34
35
  if (shouldGroupMessage("msg-assistant")) _el.classList.add("grouped");
35
36
  addToMessages(_el);
36
37
  store.set({ currentMsgEl: _el, currentFullText: "" });
@@ -119,20 +120,17 @@ export function showClaudePreThinking() {
119
120
  if (getChatLayout() !== "channel") return;
120
121
  removeMatePreThinking();
121
122
  var vendor = store.get('currentVendor') || "claude";
122
- var vendorAvatar = VENDOR_AVATARS[vendor] || VENDOR_AVATARS.claude;
123
- var vendorName = VENDOR_NAMES[vendor] || VENDOR_NAMES.claude;
124
- doShowMatePreThinking(vendorName, vendorAvatar);
123
+ var identity = resolveProjectAssistantIdentity(store.snap(), vendor);
124
+ doShowMatePreThinking(identity.name, identity.avatarUrl, identity);
125
125
  }
126
126
 
127
127
  export function showMatePreThinking() {
128
128
  removeMatePreThinking();
129
- var dmTarget = store.get('dmTargetUser');
130
- var mateName = dmTarget ? (dmTarget.displayName || "Mate") : "Mate";
131
- var mateAvatar = document.body.dataset.mateAvatarUrl || "";
132
- doShowMatePreThinking(mateName, mateAvatar);
129
+ var identity = resolveProjectAssistantIdentity(store.snap(), store.get('currentVendor'));
130
+ doShowMatePreThinking(identity.name, identity.avatarUrl, identity);
133
131
  }
134
132
 
135
- function doShowMatePreThinking(mateName, mateAvatar) {
133
+ function doShowMatePreThinking(mateName, mateAvatar, identity) {
136
134
  var _el = document.createElement("div");
137
135
  _el.className = "thinking-item mate-thinking mate-pre-thinking";
138
136
  _el.innerHTML =
@@ -141,6 +139,7 @@ function doShowMatePreThinking(mateName, mateAvatar) {
141
139
  '<div class="dm-bubble-header"><span class="dm-bubble-name">' + escapeHtml(mateName) + '</span></div>' +
142
140
  '<div class="mate-thinking-dots"><span></span><span></span><span></span></div>' +
143
141
  '</div>';
142
+ applyProjectAssistantIdentity(_el, identity);
144
143
  store.set({ matePreThinkingEl: _el });
145
144
  var activity = getActivityEl();
146
145
  if (activity && activity.parentNode) {
@@ -1,18 +1,30 @@
1
1
  // Centralized local avatar URL builder for people and Mates.
2
2
  import { imprintDataUrl, mateMarkDataUrl } from './avatar-imprint.js';
3
3
 
4
- var imprintCache = new Map();
5
4
  var mateMarkCache = new Map();
6
5
 
7
- // Legacy style remains part of the identity hash so existing selections map
8
- // deterministically into the local pixel identity system.
6
+ // Historical DiceBear 9.x choices, now generated by Clay's local server.
7
+ export var MATE_AVATAR_STYLES = [
8
+ { id: 'thumbs', name: 'Thumbs' },
9
+ { id: 'bottts', name: 'Bots' },
10
+ { id: 'pixel-art', name: 'Pixel' },
11
+ { id: 'adventurer', name: 'Adventurer' },
12
+ { id: 'micah', name: 'Micah' },
13
+ { id: 'fun-emoji', name: 'Emoji' },
14
+ { id: 'icons', name: 'Icons' },
15
+ ];
16
+
9
17
  export function avatarUrl(style, seed, size) {
10
- var cacheKey = [style || 'imprint', seed || 'anonymous', size || 64].join('|');
11
- if (imprintCache.has(cacheKey)) return imprintCache.get(cacheKey);
12
- var url = imprintDataUrl({ style: style || 'imprint', seed: seed || 'anonymous', size: size || 64 });
13
- if (imprintCache.size >= 512) imprintCache.delete(imprintCache.keys().next().value);
14
- imprintCache.set(cacheKey, url);
15
- return url;
18
+ var normalizedStyle = style || 'imprint';
19
+ var normalizedSeed = seed || 'anonymous';
20
+ var normalizedSize = size || 64;
21
+ var isHistorical = MATE_AVATAR_STYLES.some(function (entry) { return entry.id === normalizedStyle; });
22
+ if (isHistorical) {
23
+ return '/api/generated-avatar?style=' + encodeURIComponent(normalizedStyle)
24
+ + '&seed=' + encodeURIComponent(normalizedSeed)
25
+ + '&size=' + encodeURIComponent(normalizedSize);
26
+ }
27
+ return imprintDataUrl({ style: normalizedStyle, seed: normalizedSeed, size: normalizedSize });
16
28
  }
17
29
 
18
30
  // Use the same bounded account identity for fresh fallbacks across every surface.
@@ -46,5 +58,9 @@ export function mateAvatarUrl(mate, size) {
46
58
  var p = mate.profile || mate;
47
59
  if (p.avatarCustom || mate.avatarCustom) return p.avatarCustom || mate.avatarCustom;
48
60
  var identity = p.displayName || mate.name || mate.displayName || 'Mate';
61
+ var style = p.avatarStyle || mate.avatarStyle || 'imprint';
62
+ if (style !== 'imprint' && style !== 'initial') {
63
+ return avatarUrl(style, p.avatarSeed || mate.avatarSeed || mate.id || identity, size);
64
+ }
49
65
  return mateMarkUrl(identity, size);
50
66
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { store } from './store.js';
4
4
  import { getMessagesEl } from './dom-refs.js';
5
+ import { getProjectAssistantPlaceholder } from './project-chat-identity.js';
5
6
 
6
7
  export var VENDOR_AVATARS = {
7
8
  claude: "/claude-code-avatar.png",
@@ -124,11 +125,22 @@ export function disarmStickyBottom() {
124
125
  }
125
126
 
126
127
  export function initRendering() {
128
+ var lastAssistantPlaceholder = '';
129
+ function updateInputPlaceholder(state) {
130
+ var inputEl = document.getElementById("input");
131
+ if (!inputEl) return;
132
+ var nextPlaceholder = getProjectAssistantPlaceholder(state, state.currentVendor);
133
+ var ownsPlaceholder = !lastAssistantPlaceholder || inputEl.placeholder === lastAssistantPlaceholder;
134
+ lastAssistantPlaceholder = nextPlaceholder;
135
+ if (inputEl.disabled || document.getElementById("input-mention-chip") || !ownsPlaceholder) return;
136
+ inputEl.placeholder = nextPlaceholder;
137
+ }
138
+ updateInputPlaceholder(store.snap());
127
139
  store.subscribe(function (state, prev) {
128
- if (state.currentVendor !== prev.currentVendor) {
129
- var inputEl = document.getElementById("input");
130
- if (inputEl) inputEl.placeholder = "Message " + (VENDOR_NAMES[state.currentVendor] || VENDOR_NAMES.claude) + "...";
131
- }
140
+ if (state.currentVendor !== prev.currentVendor || state.activeSessionMateId !== prev.activeSessionMateId ||
141
+ state.activeSessionMateName !== prev.activeSessionMateName || state.activeProjectMateId !== prev.activeProjectMateId ||
142
+ state.activeProjectMateName !== prev.activeProjectMateName || state.cachedMatesList !== prev.cachedMatesList ||
143
+ state.dmMode !== prev.dmMode || state.dmTargetUser !== prev.dmTargetUser) updateInputPlaceholder(state);
132
144
  });
133
145
  }
134
146