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
package/lib/sessions.js CHANGED
@@ -13,6 +13,7 @@ var projectAutonomousRun = require("./project-autonomous-run").projectAutonomous
13
13
  var restoreStoredRun = require("./project-autonomous-run").restoreStoredRun;
14
14
 
15
15
  function createSessionManager(opts) {
16
+ var privateMate = opts.isMate === true;
16
17
  var cwd = opts.cwd;
17
18
  var send = opts.send; // function(obj) - broadcast to all clients
18
19
  var sendTo = opts.sendTo || null; // function(ws, obj) - send to specific client
@@ -182,6 +183,8 @@ function createSessionManager(opts) {
182
183
  if (session.vendor) metaObj.vendor = session.vendor;
183
184
  if (session.codexDynamicToolCatalogVersion) metaObj.codexDynamicToolCatalogVersion = session.codexDynamicToolCatalogVersion;
184
185
  if (session.codexUserInputToolCatalogVersion) metaObj.codexUserInputToolCatalogVersion = session.codexUserInputToolCatalogVersion;
186
+ if (session.userKnowledgeOwnerId) metaObj.userKnowledgeOwnerId = session.userKnowledgeOwnerId;
187
+ if (session.codexYouToolCatalogVersion) metaObj.codexYouToolCatalogVersion = session.codexYouToolCatalogVersion;
185
188
  if (session.codexLinearToolCatalogVersion) metaObj.codexLinearToolCatalogVersion = session.codexLinearToolCatalogVersion;
186
189
  if (session.codexSharedBrowserToolCatalogVersion) metaObj.codexSharedBrowserToolCatalogVersion = session.codexSharedBrowserToolCatalogVersion;
187
190
  if (session.codexIssuesToolCatalogVersion) metaObj.codexIssuesToolCatalogVersion = session.codexIssuesToolCatalogVersion;
@@ -206,6 +209,7 @@ function createSessionManager(opts) {
206
209
  if (session.scheduledTaskDraft) metaObj.scheduledTaskDraft = session.scheduledTaskDraft;
207
210
  if (session.scheduledTaskRun) metaObj.scheduledTaskRun = session.scheduledTaskRun;
208
211
  if (session.hidden) metaObj.hidden = true;
212
+ if (session.youCurator) metaObj.youCurator = true;
209
213
  metaObj.sessionVisibility = sessionVisibility.normalize(session.sessionVisibility);
210
214
  if (session.sessionVisibilityExplicit) metaObj.sessionVisibilityExplicit = true;
211
215
  if (session.bookmarked) metaObj.bookmarked = true;
@@ -222,6 +226,8 @@ function createSessionManager(opts) {
222
226
  if (session.homeDebatePlanning) metaObj.homeDebatePlanning = true;
223
227
  if (session.homeDebatePhase) metaObj.homeDebatePhase = session.homeDebatePhase;
224
228
  if (session.homeDebateInitialTopic) metaObj.homeDebateInitialTopic = session.homeDebateInitialTopic;
229
+ if (session.mateCreationMode) metaObj.mateCreationMode = true;
230
+ if (session.homeMateCreationPhase) metaObj.homeMateCreationPhase = session.homeMateCreationPhase;
225
231
  if (session.homeClayEntryRequestId) metaObj.homeClayEntryRequestId = session.homeClayEntryRequestId;
226
232
  if (session.homeClayEntryMode) metaObj.homeClayEntryMode = session.homeClayEntryMode;
227
233
  metaObj.sessionOriginId = provenanceMeta.sessionOriginId;
@@ -360,6 +366,8 @@ function createSessionManager(opts) {
360
366
  if (m.vendor) session.vendor = m.vendor;
361
367
  session.codexDynamicToolCatalogVersion = Number(m.codexDynamicToolCatalogVersion || 0);
362
368
  session.codexUserInputToolCatalogVersion = Number(m.codexUserInputToolCatalogVersion || 0);
369
+ session.userKnowledgeOwnerId = m.userKnowledgeOwnerId || null;
370
+ session.codexYouToolCatalogVersion = Number(m.codexYouToolCatalogVersion || 0);
363
371
  session.codexLinearToolCatalogVersion = Number(m.codexLinearToolCatalogVersion || 0);
364
372
  session.codexSharedBrowserToolCatalogVersion = Number(m.codexSharedBrowserToolCatalogVersion || 0);
365
373
  session.codexIssuesToolCatalogVersion = Number(m.codexIssuesToolCatalogVersion || 0);
@@ -376,6 +384,8 @@ function createSessionManager(opts) {
376
384
  if (m.homeDebatePlanning) session.homeDebatePlanning = true;
377
385
  if (m.homeDebatePhase) session.homeDebatePhase = m.homeDebatePhase;
378
386
  if (m.homeDebateInitialTopic) session.homeDebateInitialTopic = m.homeDebateInitialTopic;
387
+ if (m.mateCreationMode) session.mateCreationMode = true;
388
+ if (m.homeMateCreationPhase) session.homeMateCreationPhase = m.homeMateCreationPhase;
379
389
  if (m.homeClayEntryRequestId) session.homeClayEntryRequestId = m.homeClayEntryRequestId;
380
390
  if (m.homeClayEntryMode) session.homeClayEntryMode = m.homeClayEntryMode;
381
391
  if (m.ownerId) session.ownerId = m.ownerId;
@@ -404,10 +414,12 @@ function createSessionManager(opts) {
404
414
  session.scheduledTaskDraft = m.scheduledTaskDraft && typeof m.scheduledTaskDraft === "object" ? m.scheduledTaskDraft : null;
405
415
  session.scheduledTaskRun = m.scheduledTaskRun && typeof m.scheduledTaskRun === "object" ? m.scheduledTaskRun : null;
406
416
  session.hidden = m.hidden === true || !!session.scheduledTaskRun;
417
+ session.youCurator = m.youCurator === true;
407
418
  session.terminalId = null;
408
419
  session.runtimeMode = null;
409
420
  session.runtimeTerminalId = null;
410
- session.sessionVisibility = sessionVisibility.restore(m);
421
+ session.isMate = privateMate;
422
+ session.sessionVisibility = privateMate ? "private" : sessionVisibility.restore(m);
411
423
  session.sessionVisibilityExplicit = m.sessionVisibilityExplicit === true;
412
424
  session.bookmarked = !!m.bookmarked;
413
425
  session.favoriteOrder = typeof m.favoriteOrder === "number" ? m.favoriteOrder : null;
@@ -534,6 +546,7 @@ function createSessionManager(opts) {
534
546
  terminalId: null,
535
547
  runtimeMode: null,
536
548
  runtimeTerminalId: null,
549
+ isMate: privateMate,
537
550
  sessionVisibility: "private",
538
551
  bookmarked: false,
539
552
  favoriteOrder: null,
@@ -624,9 +637,12 @@ function createSessionManager(opts) {
624
637
  backgroundTaskCount: backgroundTaskTiming.countUserTasks(s.activeBackgroundTasks),
625
638
  lastActivity: s.lastActivity || s.createdAt || 0,
626
639
  loop: loop,
640
+ homeDebatePlanning: s.homeDebatePlanning === true,
641
+ homeDebatePhase: s.homeDebatePhase || null,
627
642
  spawn: s.spawn || null,
628
643
  ownerId: s.ownerId || null,
629
- sessionVisibility: sessionVisibility.normalize(s.sessionVisibility),
644
+ isMate: privateMate,
645
+ sessionVisibility: privateMate ? "private" : sessionVisibility.normalize(s.sessionVisibility),
630
646
  bookmarked: !!s.bookmarked,
631
647
  favoriteOrder: typeof s.favoriteOrder === "number" ? s.favoriteOrder : null,
632
648
  unread: unreadMap[s.localId] || 0,
@@ -735,7 +751,9 @@ function createSessionManager(opts) {
735
751
  history: [],
736
752
  messageUUIDs: [],
737
753
  ownerId: (sessionOpts && sessionOpts.ownerId) || null,
738
- sessionVisibility: sessionVisibility.normalize(sessionOpts && sessionOpts.sessionVisibility),
754
+ userKnowledgeOwnerId: (sessionOpts && sessionOpts.userKnowledgeOwnerId) || null,
755
+ isMate: privateMate,
756
+ sessionVisibility: privateMate ? "private" : sessionVisibility.normalize(sessionOpts && sessionOpts.sessionVisibility),
739
757
  sessionVisibilityExplicit: !!(sessionOpts && sessionOpts.sessionVisibility === "shared"),
740
758
  bookmarked: false,
741
759
  favoriteOrder: null,
@@ -786,7 +804,9 @@ function createSessionManager(opts) {
786
804
  history: [],
787
805
  messageUUIDs: [],
788
806
  ownerId: (sessionOpts && sessionOpts.ownerId) || null,
789
- sessionVisibility: sessionVisibility.normalize(sessionOpts && sessionOpts.sessionVisibility),
807
+ userKnowledgeOwnerId: (sessionOpts && sessionOpts.userKnowledgeOwnerId) || null,
808
+ isMate: privateMate,
809
+ sessionVisibility: privateMate ? "private" : sessionVisibility.normalize(sessionOpts && sessionOpts.sessionVisibility),
790
810
  sessionVisibilityExplicit: !!(sessionOpts && sessionOpts.sessionVisibility === "shared"),
791
811
  bookmarked: false,
792
812
  favoriteOrder: null,
@@ -900,7 +920,7 @@ function createSessionManager(opts) {
900
920
  var _sessionVendor = session.vendor || defaultVendor || "claude";
901
921
  var _vendorCaps = _capsByVendor[_sessionVendor] || {};
902
922
  var _permissionState = require("./session-permission-mode").clientState(session, "default", defaultVendor);
903
- _send({ type: "session_switched", id: localId, sessionOriginId: session.sessionOriginId || null, cliSessionId: session.cliSessionId || null, loop: session.loop || null, vendor: session.vendor || null, model: session.model || null, effort: session.effort || null, hasHistory: (session.history && session.history.length > 0), capabilities: _vendorCaps, isProcessing: !!session.isProcessing, mode: session.mode || "gui", terminalId: typeof session.terminalId === "number" ? session.terminalId : null, runtimeMode: session.runtimeMode || null, runtimeTerminalId: typeof session.runtimeTerminalId === "number" ? session.runtimeTerminalId : null, tuiSuspended: !!session.tuiSuspended, dangerouslySkipPermissions: !!session.dangerouslySkipPermissions, permissionMode: _permissionState.requestedPermissionMode, effectivePermissionMode: _permissionState.effectivePermissionMode, permissionCapabilities: _permissionState.permissionCapabilities, mcpPermissionModeOverrides: _permissionState.mcpPermissionModeOverrides, autonomousRun: projectAutonomousRun(session.autonomousRun), loopInterviewBrief: session.loopInterviewBrief || null, loopInterviewHandoff: session.loopInterviewHandoff || null, scheduledTaskDraft: session.scheduledTaskDraft || null });
923
+ _send({ type: "session_switched", id: localId, sessionOriginId: session.sessionOriginId || null, sessionRole: sessionProvenance.isWorker(session) ? "worker" : "driver", cliSessionId: session.cliSessionId || null, loop: session.loop || null, vendor: session.vendor || null, model: session.model || null, effort: session.effort || null, hasHistory: (session.history && session.history.length > 0), capabilities: _vendorCaps, isProcessing: !!session.isProcessing, mateCreation: session.mateCreationMode === true, mateCreationPhase: session.homeMateCreationPhase || null, debatePlanning: session.debateSetupMode === true, debatePhase: session.homeDebatePhase || null, mode: session.mode || "gui", terminalId: typeof session.terminalId === "number" ? session.terminalId : null, runtimeMode: session.runtimeMode || null, runtimeTerminalId: typeof session.runtimeTerminalId === "number" ? session.runtimeTerminalId : null, tuiSuspended: !!session.tuiSuspended, dangerouslySkipPermissions: !!session.dangerouslySkipPermissions, permissionMode: _permissionState.requestedPermissionMode, effectivePermissionMode: _permissionState.effectivePermissionMode, permissionCapabilities: _permissionState.permissionCapabilities, mcpPermissionModeOverrides: _permissionState.mcpPermissionModeOverrides, autonomousRun: projectAutonomousRun(session.autonomousRun), loopInterviewBrief: session.loopInterviewBrief || null, loopInterviewHandoff: session.loopInterviewHandoff || null, scheduledTaskDraft: session.scheduledTaskDraft || null });
904
924
  // Send vendor-specific slash commands
905
925
  var _vendorCmds = (session.slashCommandsByVendor && session.slashCommandsByVendor[_sessionVendor])
906
926
  || session.slashCommands
@@ -1201,13 +1221,15 @@ function createSessionManager(opts) {
1201
1221
  lastActivity: Date.now(),
1202
1222
  history: cliHistory,
1203
1223
  messageUUIDs: [],
1204
- sessionVisibility: sessionVisibility.normalize(opts && opts.sessionVisibility),
1224
+ isMate: privateMate,
1225
+ sessionVisibility: privateMate ? "private" : sessionVisibility.normalize(opts && opts.sessionVisibility),
1205
1226
  sessionVisibilityExplicit: !!(opts && opts.sessionVisibilityExplicit === true),
1206
1227
  bookmarked: false,
1207
1228
  favoriteOrder: null,
1208
1229
  };
1209
1230
  if (opts && opts.vendor) session.vendor = opts.vendor;
1210
1231
  if (opts && opts.ownerId) session.ownerId = opts.ownerId;
1232
+ if (opts && opts.userKnowledgeOwnerId) session.userKnowledgeOwnerId = opts.userKnowledgeOwnerId;
1211
1233
  sessions.set(localId, session);
1212
1234
  saveSessionFile(session);
1213
1235
  switchSession(localId, targetWs);
@@ -1490,6 +1512,8 @@ function createSessionManager(opts) {
1490
1512
  setSessionVisibility: function (localId, visibility) {
1491
1513
  var session = sessions.get(localId);
1492
1514
  if (!session) return { error: "Session not found" };
1515
+ if (session.userKnowledgeOwnerId && visibility === "shared") return { error: "Conversations containing private User Knowledge cannot be shared." };
1516
+ if (privateMate || session.isMate) return { error: "Clay and Mate conversations are always private." };
1493
1517
  if (visibility !== "shared" && visibility !== "private") return { error: "Invalid session visibility" };
1494
1518
  session.sessionVisibility = visibility;
1495
1519
  session.sessionVisibilityExplicit = true;
@@ -1559,6 +1583,8 @@ function createSessionManager(opts) {
1559
1583
  setSessionOwner: function (localId, ownerId) {
1560
1584
  var session = sessions.get(localId);
1561
1585
  if (!session) return { error: "Session not found" };
1586
+ if (session.userKnowledgeOwnerId && session.ownerId !== ownerId) return { error: "Private User Knowledge ownership cannot be transferred." };
1587
+ if (privateMate && session.ownerId !== ownerId) return { error: "Mate conversation ownership cannot be transferred." };
1562
1588
  session.ownerId = ownerId;
1563
1589
  saveSessionFile(session);
1564
1590
  return { ok: true };
@@ -0,0 +1,167 @@
1
+ // Owner-private user knowledge. Only canonical Clay sessions curate records.
2
+ var crypto = require('crypto');
3
+ var canUsePersonalConnections = require('./mcp-session-access').canUsePersonalConnections;
4
+ var createRecordStore = require('./knowledge-record-store').createRecordStore;
5
+
6
+ function attachUserKnowledgeService(deps) {
7
+ var stores = new Map();
8
+ function owner(id) {
9
+ if (deps.isMultiUser() && (!id || !deps.findUser(id))) throw new Error('User knowledge requires an authenticated owner.');
10
+ return deps.isMultiUser() ? id : 'default';
11
+ }
12
+ function storage(id) {
13
+ var key = crypto.createHash('sha256').update(owner(id)).digest('hex');
14
+ if (!stores.has(key)) stores.set(key, createRecordStore({scopeId:'user/' + key + '/you',baseDir:deps.baseDir}));
15
+ return stores.get(key);
16
+ }
17
+ function snapshot(id) {
18
+ var result = {entries:{},reports:{},activity:[],seen:{},version:0};
19
+ storage(id).all().forEach(function (record) {
20
+ if (record.kind !== 'user-knowledge') return;
21
+ result.version++;
22
+ if (record.seen) result.seen[record.seen.ref] = Math.max(result.seen[record.seen.ref] || 0, record.seen.revision);
23
+ if (record.entry) result.entries[record.entry.ref] = record.entry;
24
+ if (record.report) result.reports[record.report.ref] = record.report;
25
+ if (record.activity) result.activity.push(record.activity);
26
+ });
27
+ return result;
28
+ }
29
+ function text(value, max, required) {
30
+ if (typeof value !== 'string' || value.length > max || (required && !value.trim())) throw new Error('Invalid or oversized knowledge text.');
31
+ return value.trim();
32
+ }
33
+ function page(items, args) {
34
+ args = args || {};
35
+ var offset = Math.max(0, Number(args.offset) || 0);
36
+ offset = Number.isFinite(offset) ? Math.floor(offset) : 0;
37
+ var limit = Math.min(50, Math.max(1, Number(args.limit) || 30));
38
+ return {items:items.slice(offset,offset+limit),total:items.length,nextOffset:offset+limit < items.length ? offset+limit:null};
39
+ }
40
+ function unread(entry,state) { return !entry.archived && entry.revisions > (state.seen[entry.ref] || 0); }
41
+ function attention(id) {
42
+ var state = snapshot(id);
43
+ return { unread: Object.values(state.entries).filter(function (entry) { return unread(entry,state); }).length, version: state.version };
44
+ }
45
+ function acknowledge(id,args) {
46
+ var state = snapshot(id);
47
+ var entry = state.entries[args.ref];
48
+ if (!entry || entry.archived) throw new Error('User knowledge not found.');
49
+ if (!Number.isInteger(args.revision) || args.revision < 1 || args.revision > entry.revisions) throw new Error('Invalid memory revision.');
50
+ if ((state.seen[args.ref] || 0) < args.revision) {
51
+ storage(id).append({kind:'user-knowledge',seen:{ref:args.ref,revision:args.revision,at:Date.now()}});
52
+ try { deps.onChange(owner(id),{seen:true}); } catch (error) { /* Acknowledgement survives notification failures. */ }
53
+ }
54
+ return attention(id);
55
+ }
56
+ function list(id,args) {
57
+ var state = snapshot(id);
58
+ args = args || {};
59
+ var query = String(args.query || '').toLowerCase().slice(0,300);
60
+ var entries = Object.values(state.entries).filter(function (entry) {
61
+ return !entry.archived && (!args.category || entry.category === args.category) &&
62
+ (!query || (entry.title+' '+entry.summary+' '+entry.body).toLowerCase().indexOf(query)!==-1);
63
+ }).map(function(entry){return Object.assign({},entry,{unread:unread(entry,state)});}).sort(function (a,b) {return Number(b.unread)-Number(a.unread) || b.updatedAt-a.updatedAt;});
64
+ return Object.assign(page(entries,args),{categories:Array.from(new Set(Object.values(state.entries).filter(function (e) {return !e.archived;}).map(function(e){return e.category;}))).sort(),pending:Object.values(state.reports).filter(function(r){return r.status==='pending';}).length});
65
+ }
66
+ function read(id,ref) {
67
+ var entry = snapshot(id).entries[ref];
68
+ if (!entry || entry.archived) throw new Error('User knowledge not found.');
69
+ var comments = Object.values(snapshot(id).reports).filter(function (item) { return item.commentEntryRef === ref; }).map(function (item) {
70
+ return { id: item.ref, body: item.observation, at: item.createdAt, author: { type: 'user', displayName: 'You' },
71
+ status: item.status === 'accepted' ? 'incorporated' : item.status,
72
+ review: item.reviewedAt ? { response: item.reason, at: item.reviewedAt, author: { displayName: 'Clay' } } : null };
73
+ });
74
+ return Object.assign({}, entry, { comments: comments, commentCount: comments.length });
75
+ }
76
+ function comment(id,args,source) {
77
+ var entry = read(id,args.ref);
78
+ return report(id,{observation:args.body,evidence:'Comment on '+entry.ref+': '+args.body,evidenceType:'explicit'},source,entry.ref);
79
+ }
80
+ function report(id,args,source,commentEntryRef) {
81
+ var state = snapshot(id);
82
+ var observation = text(args.observation,4000,true);
83
+ var evidence = text(args.evidence,4000,true);
84
+ var evidenceType = args.evidenceType || 'explicit';
85
+ if (['explicit','inferred'].indexOf(evidenceType)===-1) throw new Error('Invalid evidence type.');
86
+ var existing = Object.values(state.reports).find(function (r) {return r.observation===observation && r.evidence===evidence && r.source.session===source.session && r.source.project===source.project && r.status==='pending';});
87
+ if (existing) return existing;
88
+ if (Object.values(state.reports).filter(function (r) {return r.status==='pending';}).length>=200) throw new Error('Clay has 200 pending observations. Review those before reporting more.');
89
+ var record = {ref:'observation:'+crypto.randomBytes(12).toString('hex'),observation:observation,evidence:evidence,evidenceType:evidenceType,source:source,commentEntryRef:commentEntryRef || null,status:'pending',createdAt:Date.now()};
90
+ storage(id).append({kind:'user-knowledge',report:record});
91
+ try {deps.onReport(owner(id));} catch (error) { /* Durable pending report remains available for retry. */ }
92
+ return record;
93
+ }
94
+ function bind(binding) {
95
+ var originalOwner = binding.session && binding.session.ownerId;
96
+ function principal() {
97
+ var project = deps.getProject(binding.projectSlug);
98
+ var session = binding.session;
99
+ if (!project || !session || project.sm.sessions.get(session.localId)!==session || session.destroying) throw new Error('A live owner-bound session is required.');
100
+ if (session.ownerId !== originalOwner) throw new Error('Session ownership changed.');
101
+ if (deps.isMultiUser() && session.sessionVisibility === 'shared') throw new Error('Private User Knowledge is unavailable in shared conversations.');
102
+ if (deps.isMultiUser() && !canUsePersonalConnections(session, project.sm.sessions)) throw new Error('User Knowledge requires an owner-only conversation and Driver.');
103
+ var id = owner(session.ownerId);
104
+ var status = project.getStatus();
105
+ if (deps.isMultiUser() && !deps.canAccess(id,binding.projectSlug)) throw new Error('Project access was revoked.');
106
+ var mate = status.isMate && deps.resolveMate(id,status.mateId);
107
+ var clay = !!(mate && mate.builtinKey==='clay' && (!deps.isMultiUser() || mate.createdBy===id));
108
+ return {id:id,clay:clay,source:{project:binding.projectSlug,session:session.cliSessionId || 'local:'+session.localId,mateId:status.mateId || null}};
109
+ }
110
+ function protect(p) {
111
+ if (!deps.isMultiUser()) return;
112
+ var session = binding.session;
113
+ var manager = deps.getProject(binding.projectSlug).sm;
114
+ function mark(target) {
115
+ if (target.userKnowledgeOwnerId === p.id) return;
116
+ var previous = target.userKnowledgeOwnerId;
117
+ target.userKnowledgeOwnerId = p.id;
118
+ try { manager.saveSessionFile(target); } catch (error) { target.userKnowledgeOwnerId = previous; throw error; }
119
+ }
120
+ var provenance = session.sessionProvenance;
121
+ if (provenance && provenance.kind === 'worker') manager.sessions.forEach(function (parent) {
122
+ if (parent.sessionOriginId === provenance.parentSessionOriginId) mark(parent);
123
+ });
124
+ mark(session);
125
+ }
126
+ function curator() {var p=principal();if(!p.clay) throw new Error('Only your canonical Clay can curate User Knowledge.');return p;}
127
+ return {
128
+ isClay:function () {return principal().clay;},
129
+ list:function(args){var p=principal();var result=list(p.id,args);if(result.items.length)protect(p);return result;},
130
+ read:function(args){var p=principal();var result=read(p.id,args.ref);protect(p);return result;},
131
+ report:function(args){var p=principal();return report(p.id,args,p.source);},
132
+ pending:function(args){var p=curator();return page(Object.values(snapshot(p.id).reports).filter(function(r){return r.status==='pending';}),args);},
133
+ curate:function(args) {
134
+ var p=curator();
135
+ var state=snapshot(p.id);
136
+ var observation=state.reports[args.reportRef];
137
+ if (!observation) throw new Error('Observation not found.');
138
+ if (observation.status!=='pending') return {report:observation,entry:observation.entryRef ? state.entries[observation.entryRef]:null};
139
+ var action=args.action;
140
+ if (['save','decline','archive'].indexOf(action)===-1) throw new Error('Invalid curation action.');
141
+ var reason=text(args.reason,2000,true);
142
+ var previous=args.ref ? state.entries[args.ref]:null;
143
+ if (args.ref && !previous) throw new Error('User knowledge not found.');
144
+ if (previous && args.expectedRevision!==previous.revisions) throw new Error('Knowledge changed. Read it again before updating.');
145
+ var entry=null;
146
+ var now=Date.now();
147
+ if (action!=='decline') {
148
+ if(action==='archive' && !previous) throw new Error('Choose an existing entry to archive.');
149
+ var category=action==='archive' ? previous.category:text(args.category,32,true);
150
+ if(!/^[a-z][a-z0-9-]*$/.test(category)) throw new Error('Use a lowercase category.');
151
+ entry=Object.assign({},previous || {},{ref:previous ? previous.ref:'you:'+crypto.randomBytes(12).toString('hex'),category:category,kind:category,
152
+ title:action==='archive' ? previous.title:text(args.title,160,true),summary:action==='archive' ? previous.summary:text(args.summary,600,true),
153
+ body:action==='archive' ? previous.body:text(args.body,8000,true),archived:action==='archive',
154
+ createdAt:previous ? previous.createdAt:now,updatedAt:now,revisions:previous ? previous.revisions+1:1,
155
+ updatedBy:{type:'system',displayName:'Clay'},source:observation.source,evidence:observation.evidence,evidenceType:observation.evidenceType,reason:reason});
156
+ }
157
+ var reviewed=Object.assign({},observation,{status:action==='decline'?'declined':'accepted',reviewedAt:now,reason:reason,entryRef:entry && entry.ref});
158
+ var activity=entry ? {id:crypto.randomBytes(12).toString('hex'),ref:entry.ref,title:entry.title,summary:entry.summary,at:now,action:action==='archive'?'archive':(previous?'update':'create'),revision:entry.revisions}:null;
159
+ storage(p.id).append({kind:'user-knowledge',entry:entry,report:reviewed,activity:activity});
160
+ if(activity) {try {deps.onChange(p.id,activity);} catch(error) { /* Saved record survives notification failures. */ }}
161
+ return {entry:entry,report:reviewed};
162
+ }
163
+ };
164
+ }
165
+ return {bind:bind,list:list,read:read,report:report,comment:comment,attention:attention,acknowledge:acknowledge,activity:function(id,args){return page(snapshot(id).activity.slice().reverse(),args);},pendingCount:function(id){return Object.values(snapshot(id).reports).filter(function(r){return r.status==='pending';}).length;}};
166
+ }
167
+ module.exports={attachUserKnowledgeService:attachUserKnowledgeService};
@@ -65,6 +65,9 @@ function attachPermissions(deps) {
65
65
 
66
66
  function canAccessProject(userId, project) {
67
67
  if (!project) return false;
68
+ if (project.isMate === true || (typeof project.slug === "string" && project.slug.indexOf("mate-") === 0)) {
69
+ return !!userId && !!project.ownerId && project.ownerId === userId;
70
+ }
68
71
  // Public projects are accessible to all authenticated users
69
72
  if (!project.visibility || project.visibility === "public") return true;
70
73
  // Admin always has access
@@ -89,6 +92,10 @@ function attachPermissions(deps) {
89
92
  function canAccessSession(userId, session, project) {
90
93
  // Must have project access first
91
94
  if (!canAccessProject(userId, project)) return false;
95
+ if (session.isMate === true || project.isMate === true || (typeof project.slug === "string" && project.slug.indexOf("mate-") === 0)) {
96
+ return !!userId && !!session.ownerId && session.ownerId === userId;
97
+ }
98
+ if (session.userKnowledgeOwnerId) return !!userId && session.userKnowledgeOwnerId === userId && session.ownerId === userId;
92
99
  // Resolve the stored user record so client-supplied roles cannot elevate access.
93
100
  var user = findUserById(userId);
94
101
  if (user && user.role === "admin") return true;
@@ -0,0 +1,39 @@
1
+ function attachProjectMateFilterPreferences(deps) {
2
+ var loadUsers = deps.loadUsers;
3
+ var saveUsers = deps.saveUsers;
4
+ var configModule = deps.config || require("./config");
5
+
6
+ function normalize(mode) {
7
+ return mode === "projects" || mode === "mates" ? mode : "all";
8
+ }
9
+
10
+ function get(userId) {
11
+ var data = loadUsers();
12
+ for (var i = 0; i < data.users.length; i++) {
13
+ if (data.users[i].id === userId) return normalize(data.users[i].projectMateFilterMode);
14
+ }
15
+ var current = configModule.loadConfig() || {};
16
+ return normalize(current.projectMateFilterMode);
17
+ }
18
+
19
+ function set(userId, mode) {
20
+ if (mode !== "all" && mode !== "projects" && mode !== "mates") {
21
+ return { error: "Invalid project and Mate filter mode" };
22
+ }
23
+ var data = loadUsers();
24
+ for (var i = 0; i < data.users.length; i++) {
25
+ if (data.users[i].id === userId) {
26
+ data.users[i].projectMateFilterMode = mode;
27
+ saveUsers(data);
28
+ return { ok: true, projectMateFilterMode: mode };
29
+ }
30
+ }
31
+ var current = configModule.loadConfig() || {};
32
+ configModule.saveConfig(Object.assign({}, current, { projectMateFilterMode: mode }));
33
+ return { ok: true, projectMateFilterMode: mode };
34
+ }
35
+
36
+ return { get: get, set: set };
37
+ }
38
+
39
+ module.exports = { attachProjectMateFilterPreferences: attachProjectMateFilterPreferences };
package/lib/users.js CHANGED
@@ -6,6 +6,7 @@ var { CONFIG_DIR } = require("./config");
6
6
  var { attachAuth } = require("./users-auth");
7
7
  var { DEFAULT_PERMISSIONS, ALL_PERMISSIONS, attachPermissions } = require("./users-permissions");
8
8
  var { attachPreferences } = require("./users-preferences");
9
+ var { attachProjectMateFilterPreferences } = require("./users-project-mate-filter-preferences");
9
10
  var { attachHomeDockPreferences } = require("./users-home-dock-preferences");
10
11
  var { attachHomeSurfacePreferences } = require("./users-home-surface-preferences");
11
12
  var { attachSessionFolderPreferences } = require("./users-session-folder-preferences");
@@ -402,6 +403,7 @@ function removeExpiredInvites() {
402
403
  var auth = attachAuth({ loadUsers: loadUsers, saveUsers: saveUsers, findAdmin: findAdmin });
403
404
  var permissions = attachPermissions({ loadUsers: loadUsers, saveUsers: saveUsers, findUserById: findUserById });
404
405
  var preferences = attachPreferences({ loadUsers: loadUsers, saveUsers: saveUsers });
406
+ var projectMateFilterPreferences = attachProjectMateFilterPreferences({ loadUsers: loadUsers, saveUsers: saveUsers });
405
407
  var homeDockPreferences = attachHomeDockPreferences({ loadUsers: loadUsers, saveUsers: saveUsers });
406
408
  var homeSurfacePreferences = attachHomeSurfacePreferences({ loadUsers: loadUsers, saveUsers: saveUsers });
407
409
  var sessionFolderPreferences = attachSessionFolderPreferences({ loadUsers: loadUsers, saveUsers: saveUsers });
@@ -445,6 +447,8 @@ var getChatLayout = preferences.getChatLayout;
445
447
  var setChatLayout = preferences.setChatLayout;
446
448
  var getAutoContinue = preferences.getAutoContinue;
447
449
  var setAutoContinue = preferences.setAutoContinue;
450
+ var getProjectMateFilterMode = projectMateFilterPreferences.get;
451
+ var setProjectMateFilterMode = projectMateFilterPreferences.set;
448
452
  var getClaudeOpenMode = preferences.getClaudeOpenMode;
449
453
  var setClaudeOpenMode = preferences.setClaudeOpenMode;
450
454
  var getCursorSharing = preferences.getCursorSharing;
@@ -531,6 +535,8 @@ module.exports = {
531
535
  setMateOnboarded: setMateOnboarded,
532
536
  getAutoContinue: getAutoContinue,
533
537
  setAutoContinue: setAutoContinue,
538
+ getProjectMateFilterMode: getProjectMateFilterMode,
539
+ setProjectMateFilterMode: setProjectMateFilterMode,
534
540
  getClaudeOpenMode: getClaudeOpenMode,
535
541
  setClaudeOpenMode: setClaudeOpenMode,
536
542
  getCursorSharing: getCursorSharing,
@@ -87,7 +87,10 @@ function attachWorkspaceQueryAccess(deps) {
87
87
  return { owned: owned, accessible: owned };
88
88
  }
89
89
  if (!principal.userId) return denied;
90
- if (ownsMateProject(principal, status)) return { owned: true, accessible: true };
90
+ if (status.isMate === true) {
91
+ var ownsMate = ownsMateProject(principal, status);
92
+ return { owned: ownsMate, accessible: ownsMate };
93
+ }
91
94
  // status.projectOwnerId is never trusted on its own in multi-user mode: it
92
95
  // is a snapshot that can outlive a transfer or a revocation, so treating it
93
96
  // as ownership would let a stale status skip the authoritative record.
package/lib/ws-schema.js CHANGED
@@ -572,6 +572,9 @@ var schema = {
572
572
  "mate_delete": { direction: "c2s", handler: "lib/server-mates.js", description: "Delete a mate" },
573
573
  "mate_deleted": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Mate was deleted" },
574
574
  "mate_update": { direction: "c2s", handler: "lib/server-mates.js", description: "Update a mate's properties" },
575
+ "mate_instructions_get": { direction: "c2s", handler: "lib/server-mate-instructions.js", description: "Read the owner-scoped Mate identity prompt" },
576
+ "mate_instructions_set": { direction: "c2s", handler: "lib/server-mate-instructions.js", description: "Save a Mate identity prompt with revision checking" },
577
+ "mate_instructions_result": { direction: "s2c", handler: "lib/public/modules/home-mate-instructions.js", description: "Correlated prompt read or save result" },
575
578
  "mate_updated": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Mate was updated" },
576
579
  "mate_readd_builtin": { direction: "c2s", handler: "lib/server-mates.js", description: "Re-add a previously deleted built-in mate" },
577
580
  "mate_list_available_builtins": { direction: "c2s", handler: "lib/server-mates.js", description: "List built-in mates available for re-adding" },
@@ -658,16 +661,63 @@ var schema = {
658
661
  // Knowledge (mate knowledge files)
659
662
  // -----------------------------------------------------------------------
660
663
  "knowledge_list": { direction: "both", handler: "lib/project-knowledge.js", description: "Request (c2s) or receive (s2c) knowledge file list" },
664
+ "knowledge_search": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Search bounded project Knowledge filenames and document content" },
665
+ "knowledge_search_results": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Correlated bounded Knowledge document search results" },
661
666
  "knowledge_read": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Read a knowledge file" },
662
667
  "knowledge_content": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Knowledge file content" },
663
668
  "knowledge_save": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Save a knowledge file" },
664
669
  "knowledge_saved": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Knowledge file was saved" },
670
+ "knowledge_rename": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Rename a knowledge Markdown document with a revision precondition" },
671
+ "knowledge_renamed": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge document was renamed" },
672
+ "knowledge_error": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Correlated Knowledge operation error or stale-write conflict" },
673
+ "knowledge_sync": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Retry common Knowledge record synchronization after a canonical file mutation" },
674
+ "knowledge_synced": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge record synchronization retry completed" },
665
675
  "knowledge_delete": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Delete a knowledge file" },
666
676
  "knowledge_deleted": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Knowledge file was deleted" },
677
+ "knowledge_draft_save": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Persist a versioned user- and workspace-bound Knowledge draft" },
678
+ "knowledge_draft_saved": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge draft persistence acknowledgement" },
679
+ "knowledge_draft_delete": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Remove a Knowledge draft through a submitted client version" },
680
+ "knowledge_draft_deleted": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge draft removal acknowledgement" },
681
+ "knowledge_discard_draft": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Discard a bounded draft version and read a guarded disk revision" },
682
+ "knowledge_draft_discarded":{ direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Guarded disk content returned after draft discard" },
683
+ "knowledge_history": { direction: "both", handler: "lib/project-knowledge.js", description: "Request or receive bounded document history" },
684
+ "knowledge_history_read": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Read one explicit bounded document history version" },
685
+ "knowledge_history_version":{ direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Content for one explicit document history version" },
686
+ "knowledge_restore": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Restore an explicit history version with a revision precondition" },
687
+ "knowledge_restored": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge history version was restored" },
688
+ "knowledge_deleted_list": { direction: "both", handler: "lib/project-knowledge.js", description: "Request or receive recoverable deleted Knowledge documents" },
667
689
  "knowledge_promote": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Promote a knowledge file to always-active" },
668
690
  "knowledge_promoted": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Knowledge file was promoted" },
669
691
  "knowledge_depromote": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Depromote a knowledge file from always-active" },
670
692
  "knowledge_depromoted": { direction: "s2c", handler: "lib/public/modules/app-messages.js", description: "Knowledge file was depromoted" },
693
+ "knowledge_db_create": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Create a first-class Mate Knowledge database" },
694
+ "knowledge_db_created": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database creation result" },
695
+ "knowledge_db_read": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Read Knowledge database schema and views" },
696
+ "knowledge_db_content": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database schema and views" },
697
+ "knowledge_db_rename": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Rename a Knowledge database with a revision precondition" },
698
+ "knowledge_db_renamed": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database rename result" },
699
+ "knowledge_db_archive": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Recoverably archive a Knowledge database" },
700
+ "knowledge_db_archived": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database archive result" },
701
+ "knowledge_db_recover": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Recover an archived Knowledge database" },
702
+ "knowledge_db_recovered": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database recovery result" },
703
+ "knowledge_db_schema_save": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Save a validated Knowledge database schema" },
704
+ "knowledge_db_schema_saved":{ direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database schema result" },
705
+ "knowledge_db_view_save": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Save a validated table view" },
706
+ "knowledge_db_view_saved": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database table view result" },
707
+ "knowledge_db_record_create": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Create a typed Knowledge database record" },
708
+ "knowledge_db_record_created": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database record creation result" },
709
+ "knowledge_db_record_read": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Read one Knowledge database record and history" },
710
+ "knowledge_db_record_content": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database record detail" },
711
+ "knowledge_db_record_update": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Update a typed Knowledge database record" },
712
+ "knowledge_db_record_updated": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database record update result" },
713
+ "knowledge_db_record_archive": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Recoverably archive a Knowledge database record" },
714
+ "knowledge_db_record_archived": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database record archive result" },
715
+ "knowledge_db_record_recover": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Recover an archived Knowledge database record" },
716
+ "knowledge_db_record_recovered": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database record recovery result" },
717
+ "knowledge_db_query": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Run a bounded validated deterministic Knowledge database query" },
718
+ "knowledge_db_query_results": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database query page and totals" },
719
+ "knowledge_db_sync": { direction: "c2s", handler: "lib/project-knowledge.js", description: "Retry Knowledge database summary projection" },
720
+ "knowledge_db_synced": { direction: "s2c", handler: "lib/public/modules/mate-knowledge-workbench.js", description: "Knowledge database summary projection retry result" },
671
721
 
672
722
  // -----------------------------------------------------------------------
673
723
  // Memory (mate memory)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "5.1.0-beta.1",
3
+ "version": "5.1.0-beta.2",
4
4
  "description": "Self-hosted team workspace for Claude Code and Codex. Multi-user, browser-based, with persistent AI mates.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js"
@@ -48,10 +48,19 @@
48
48
  "author": "Chad",
49
49
  "dependencies": {
50
50
  "@anthropic-ai/claude-agent-sdk": "^0.3.287",
51
+ "@dicebear/adventurer": "9.4.3",
52
+ "@dicebear/bottts": "9.4.3",
53
+ "@dicebear/core": "9.4.3",
54
+ "@dicebear/fun-emoji": "9.4.3",
55
+ "@dicebear/icons": "9.4.3",
56
+ "@dicebear/micah": "9.4.3",
57
+ "@dicebear/pixel-art": "9.4.3",
58
+ "@dicebear/thumbs": "9.4.3",
51
59
  "@lydell/node-pty": "^1.2.0-beta.3",
52
60
  "@modelcontextprotocol/sdk": "^1.32.1",
53
61
  "@openai/codex": "^0.160.0",
54
62
  "@seald-io/nedb": "^4.1.2",
63
+ "codemirror": "^5.65.21",
55
64
  "imapflow": "^1.7.8",
56
65
  "ipaddr.js": "^2.5.0",
57
66
  "nodemailer": "^9.1.1",