@agent-relay/dashboard 2.0.88 → 2.0.90

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 (69) hide show
  1. package/out/404.html +1 -1
  2. package/out/_next/static/chunks/270-8c0b8109123a0c5f.js +73 -0
  3. package/out/_next/static/chunks/{1028-ff682899d23dc669.js → 9626-10e71fc51b892784.js} +1 -1
  4. package/out/_next/static/chunks/app/app/[[...slug]]/{page-f33c6214e21ccfdd.js → page-4f01a33b51f23cea.js} +1 -1
  5. package/out/_next/static/chunks/app/{page-2e38080856c3c293.js → page-2644ed4067d978e0.js} +1 -1
  6. package/out/about.html +1 -1
  7. package/out/about.txt +1 -1
  8. package/out/app/onboarding.html +1 -1
  9. package/out/app/onboarding.txt +1 -1
  10. package/out/app.html +1 -1
  11. package/out/app.txt +2 -2
  12. package/out/blog/go-to-bed-wake-up-to-a-finished-product.html +1 -1
  13. package/out/blog/go-to-bed-wake-up-to-a-finished-product.txt +1 -1
  14. package/out/blog/let-them-cook-multi-agent-orchestration.html +1 -1
  15. package/out/blog/let-them-cook-multi-agent-orchestration.txt +1 -1
  16. package/out/blog.html +1 -1
  17. package/out/blog.txt +1 -1
  18. package/out/careers.html +1 -1
  19. package/out/careers.txt +1 -1
  20. package/out/changelog.html +1 -1
  21. package/out/changelog.txt +1 -1
  22. package/out/cloud/link.html +1 -1
  23. package/out/cloud/link.txt +1 -1
  24. package/out/complete-profile.html +1 -1
  25. package/out/complete-profile.txt +1 -1
  26. package/out/connect-repos.html +1 -1
  27. package/out/connect-repos.txt +1 -1
  28. package/out/contact.html +1 -1
  29. package/out/contact.txt +1 -1
  30. package/out/dev/cli-tools.html +1 -1
  31. package/out/dev/cli-tools.txt +1 -1
  32. package/out/dev/log-viewer.html +1 -1
  33. package/out/dev/log-viewer.txt +1 -1
  34. package/out/docs.html +1 -1
  35. package/out/docs.txt +1 -1
  36. package/out/history.html +1 -1
  37. package/out/history.txt +1 -1
  38. package/out/index.html +1 -1
  39. package/out/index.txt +2 -2
  40. package/out/login.html +1 -1
  41. package/out/login.txt +1 -1
  42. package/out/metrics.html +1 -1
  43. package/out/metrics.txt +1 -1
  44. package/out/pricing.html +1 -1
  45. package/out/pricing.txt +1 -1
  46. package/out/privacy.html +1 -1
  47. package/out/privacy.txt +1 -1
  48. package/out/providers/setup/claude.html +1 -1
  49. package/out/providers/setup/claude.txt +1 -1
  50. package/out/providers/setup/codex.html +1 -1
  51. package/out/providers/setup/codex.txt +1 -1
  52. package/out/providers/setup/cursor.html +1 -1
  53. package/out/providers/setup/cursor.txt +1 -1
  54. package/out/providers.html +1 -1
  55. package/out/providers.txt +1 -1
  56. package/out/security.html +1 -1
  57. package/out/security.txt +1 -1
  58. package/out/signup.html +1 -1
  59. package/out/signup.txt +1 -1
  60. package/out/terms.html +1 -1
  61. package/out/terms.txt +1 -1
  62. package/package.json +5 -4
  63. package/src/components/hooks/useAllDMs.ts +88 -0
  64. package/src/components/hooks/useDirectMessage.ts +12 -0
  65. package/src/components/log-viewer/index.ts +21 -0
  66. package/src/providers/MessageProvider.tsx +16 -18
  67. package/out/_next/static/chunks/3238-24c1e4b1cefe3c71.js +0 -73
  68. /package/out/_next/static/{hDG4FHMjeVX6ES941qVjL → pp6J1TkgtRc_o3BmtFoV0}/_buildManifest.js +0 -0
  69. /package/out/_next/static/{hDG4FHMjeVX6ES941qVjL → pp6J1TkgtRc_o3BmtFoV0}/_ssgManifest.js +0 -0
@@ -0,0 +1,88 @@
1
+ /**
2
+ * useAllDMs Hook
3
+ *
4
+ * Fetches ALL DM conversations in the workspace using the workspace-level API
5
+ * (`allDmConversations`). Unlike the SDK's built-in `useDMs` which only returns
6
+ * conversations the dashboard agent participates in, this hook returns agent-to-agent
7
+ * DMs as well, making them visible in the DM sidebar.
8
+ *
9
+ * Listens for `dm.received` and `group_dm.received` WebSocket events to
10
+ * automatically refetch when new DMs arrive.
11
+ */
12
+
13
+ import { useCallback, useEffect, useRef, useState } from 'react';
14
+ import { useRelay, useEvent } from '@relaycast/react';
15
+ import { useRelayConfigStatus } from '../../providers/RelayConfigProvider';
16
+
17
+ export interface AllDmConversation {
18
+ id: string;
19
+ channelId?: string;
20
+ type: string;
21
+ participants: string[];
22
+ lastMessage: {
23
+ text: string;
24
+ agentName: string;
25
+ createdAt: string;
26
+ } | null;
27
+ messageCount: number;
28
+ unreadCount?: number;
29
+ }
30
+
31
+ interface UseAllDMsResult {
32
+ conversations: AllDmConversation[];
33
+ loading: boolean;
34
+ error: Error | null;
35
+ refetch: () => void;
36
+ }
37
+
38
+ export function useAllDMs(): UseAllDMsResult {
39
+ const { configured } = useRelayConfigStatus();
40
+ const [conversations, setConversations] = useState<AllDmConversation[]>([]);
41
+ const [loading, setLoading] = useState(true);
42
+ const [error, setError] = useState<Error | null>(null);
43
+ const fetchingRef = useRef(false);
44
+
45
+ // useRelay() throws if not inside RelayProvider, but we always are.
46
+ // When relay is not configured, the provider uses dummy credentials and
47
+ // allDmConversations will fail — we guard with `configured`.
48
+ let relay: ReturnType<typeof useRelay> | null = null;
49
+ try {
50
+ relay = useRelay();
51
+ } catch {
52
+ // Not inside RelayProvider — relay stays null
53
+ }
54
+
55
+ const fetchConversations = useCallback(async () => {
56
+ if (!configured || !relay || fetchingRef.current) return;
57
+ fetchingRef.current = true;
58
+ try {
59
+ const data = await relay.allDmConversations();
60
+ setConversations(Array.isArray(data) ? data as AllDmConversation[] : []);
61
+ setError(null);
62
+ } catch (err) {
63
+ setError(err instanceof Error ? err : new Error(String(err)));
64
+ } finally {
65
+ setLoading(false);
66
+ fetchingRef.current = false;
67
+ }
68
+ }, [configured, relay]);
69
+
70
+ // Initial fetch
71
+ useEffect(() => {
72
+ if (!configured) {
73
+ setLoading(false);
74
+ return;
75
+ }
76
+ void fetchConversations();
77
+ }, [configured, fetchConversations]);
78
+
79
+ // Refetch when DM events arrive via WebSocket
80
+ useEvent('dm.received', () => {
81
+ void fetchConversations();
82
+ });
83
+ useEvent('group_dm.received', () => {
84
+ void fetchConversations();
85
+ });
86
+
87
+ return { conversations, loading, error, refetch: fetchConversations };
88
+ }
@@ -41,10 +41,22 @@ export function useDirectMessage({
41
41
  for (const msg of messages) {
42
42
  const { from, to } = msg;
43
43
  if (!from || !to) continue;
44
+ // Messages involving the selected human
44
45
  if (from === humanName && agentNameSet.has(to)) derived.add(to);
45
46
  if (to === humanName && agentNameSet.has(from)) derived.add(from);
46
47
  if (selectedDmAgents.includes(from) && agentNameSet.has(to)) derived.add(to);
47
48
  if (selectedDmAgents.includes(to) && agentNameSet.has(from)) derived.add(from);
49
+ // Include agents from DM messages (non-channel messages) so agent-to-agent
50
+ // DMs are visible in the DM view — but only if the message involves the
51
+ // current human or an already-selected DM agent to avoid cross-conversation leakage.
52
+ if (!to.startsWith('#')) {
53
+ const involvesHuman = (from === humanName || to === humanName);
54
+ const involvesSelected = selectedDmAgents.includes(from) || selectedDmAgents.includes(to);
55
+ if (involvesHuman || involvesSelected) {
56
+ if (agentNameSet.has(from)) derived.add(from);
57
+ if (agentNameSet.has(to)) derived.add(to);
58
+ }
59
+ }
48
60
  }
49
61
 
50
62
  const participants = new Set<string>([...selectedDmAgents, ...derived]);
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Log Viewer — public barrel export.
3
+ *
4
+ * Re-exports the core log-viewing components and utilities so they can be
5
+ * consumed by external packages via:
6
+ *
7
+ * import { LogViewer } from "@agent-relay/dashboard/components/log-viewer"
8
+ */
9
+
10
+ export { LogViewer, default as LogViewerDefault } from "../LogViewer";
11
+ export type { LogViewerProps, LogViewerMode } from "../LogViewer";
12
+
13
+ export { AgentLogPreview } from "../AgentLogPreview";
14
+ export type { AgentLogPreviewProps } from "../AgentLogPreview";
15
+
16
+ export {
17
+ sanitizeLogContent,
18
+ isSpinnerFragment,
19
+ isHarnessNoisyLine,
20
+ isRustWarningLine,
21
+ } from "../../lib/sanitize-logs";
@@ -12,13 +12,11 @@
12
12
  import React, { createContext, useContext, useState, useCallback, useEffect, useMemo, useRef } from 'react';
13
13
  import type { Message } from '../types';
14
14
  import type { HumanUser } from '../components/MentionAutocomplete';
15
- import {
16
- useDMs as useRelayDMs,
17
- } from '@relaycast/react';
18
15
  import { useMessages as useMessagesHook } from '../components/hooks/useMessages';
19
16
  import { useThread } from '../components/hooks/useThread';
20
17
  import { usePresence, type UserPresence } from '../components/hooks/usePresence';
21
18
  import { useDirectMessage } from '../components/hooks/useDirectMessage';
19
+ import { useAllDMs } from '../components/hooks/useAllDMs';
22
20
  import { useCloudWorkspace } from './CloudWorkspaceProvider';
23
21
  import { useAgentContext } from './AgentProvider';
24
22
  import { useRelayConfigStatus } from './RelayConfigProvider';
@@ -378,14 +376,14 @@ function MessageProviderInner({ children, data, rawData: _rawData, enableReactio
378
376
  // Relay DMs and message normalization
379
377
  // ---------------------------------------------------------------------------
380
378
 
381
- const relayDMsState = useRelayDMs();
379
+ const allDMsState = useAllDMs();
382
380
  const normalizedRelayMessages = useMemo(() => {
383
381
  const sourceMessages = data?.messages ?? [];
384
- if (!relayConfigured || relayDMsState.conversations.length === 0) {
382
+ if (!relayConfigured || allDMsState.conversations.length === 0) {
385
383
  return sourceMessages;
386
384
  }
387
- return normalizeRelayDmMessageTargets(sourceMessages, relayDMsState.conversations);
388
- }, [data?.messages, relayConfigured, relayDMsState.conversations]);
385
+ return normalizeRelayDmMessageTargets(sourceMessages, allDMsState.conversations);
386
+ }, [data?.messages, relayConfigured, allDMsState.conversations]);
389
387
 
390
388
  // ---------------------------------------------------------------------------
391
389
  // Core message hook
@@ -442,7 +440,7 @@ function MessageProviderInner({ children, data, rawData: _rawData, enableReactio
442
440
  const { visibleMessages: dedupedVisibleMessages, participantAgents: dmParticipantAgents } = useDirectMessage({
443
441
  currentHuman,
444
442
  currentUserName: currentUser?.displayName ?? null,
445
- messages,
443
+ messages: currentHuman ? normalizedRelayMessages : messages,
446
444
  agents,
447
445
  selectedDmAgents,
448
446
  removedDmAgents,
@@ -467,9 +465,9 @@ function MessageProviderInner({ children, data, rawData: _rawData, enableReactio
467
465
  });
468
466
  }
469
467
 
470
- if (relayConfigured && relayDMsState.conversations.length > 0) {
468
+ if (relayConfigured && allDMsState.conversations.length > 0) {
471
469
  const currentUserName = currentUser?.displayName.toLowerCase();
472
- for (const conversation of relayDMsState.conversations) {
470
+ for (const conversation of allDMsState.conversations) {
473
471
  for (const participant of conversation.participants) {
474
472
  const name = getRelayDmParticipantName(participant);
475
473
  if (!name) continue;
@@ -491,7 +489,7 @@ function MessageProviderInner({ children, data, rawData: _rawData, enableReactio
491
489
  }
492
490
 
493
491
  return Array.from(seenUsers.values());
494
- }, [normalizedRelayMessages, agents, currentUser, relayDMsState.conversations, relayConfigured, relayAgentName]);
492
+ }, [normalizedRelayMessages, agents, currentUser, allDMsState.conversations, relayConfigured, relayAgentName]);
495
493
 
496
494
  // ---------------------------------------------------------------------------
497
495
  // Human unread counts
@@ -500,12 +498,12 @@ function MessageProviderInner({ children, data, rawData: _rawData, enableReactio
500
498
  const humanUnreadCounts = useMemo(() => {
501
499
  if (!currentUser) return {};
502
500
 
503
- if (relayConfigured && relayDMsState.conversations.length > 0) {
501
+ if (relayConfigured && allDMsState.conversations.length > 0) {
504
502
  const counts: Record<string, number> = {};
505
503
  const currentUserName = currentUser.displayName.toLowerCase();
506
504
  const agentNames = new Set(agents.filter((a) => !a.isHuman).map((a) => a.name.toLowerCase()));
507
505
 
508
- for (const conversation of relayDMsState.conversations) {
506
+ for (const conversation of allDMsState.conversations) {
509
507
  if (!conversation.unreadCount) continue;
510
508
 
511
509
  const match = conversation.participants.find((p) => {
@@ -546,7 +544,7 @@ function MessageProviderInner({ children, data, rawData: _rawData, enableReactio
546
544
  }
547
545
 
548
546
  return counts;
549
- }, [combinedAgents, currentUser, normalizedRelayMessages, dmSeenAt, relayDMsState.conversations, agents, relayConfigured]);
547
+ }, [combinedAgents, currentUser, normalizedRelayMessages, dmSeenAt, allDMsState.conversations, agents, relayConfigured]);
550
548
 
551
549
  const markDmSeen = useCallback((username: string) => {
552
550
  setDmSeenAt((prev) => {
@@ -839,16 +837,16 @@ function MessageProviderInnerWithSend({ children, data, rawData, enableReactions
839
837
  // Since SendProvider only needs them for local (non-cloud) channel message rendering,
840
838
  // we derive them here at this level too.
841
839
  const { configured: relayConfigured } = useRelayConfigStatus();
842
- const relayDMsState = useRelayDMs();
840
+ const allDMsState = useAllDMs();
843
841
  const { currentUser } = useCloudWorkspace();
844
842
 
845
843
  const normalizedRelayMessages = useMemo(() => {
846
844
  const sourceMessages = data?.messages ?? [];
847
- if (!relayConfigured || relayDMsState.conversations.length === 0) {
845
+ if (!relayConfigured || allDMsState.conversations.length === 0) {
848
846
  return sourceMessages;
849
847
  }
850
- return normalizeRelayDmMessageTargets(sourceMessages, relayDMsState.conversations);
851
- }, [data?.messages, relayConfigured, relayDMsState.conversations]);
848
+ return normalizeRelayDmMessageTargets(sourceMessages, allDMsState.conversations);
849
+ }, [data?.messages, relayConfigured, allDMsState.conversations]);
852
850
 
853
851
  const [localUsername] = useState<string | null>(
854
852
  typeof window !== 'undefined' ? localStorage.getItem('relay_username') : null