@agent-relay/dashboard-server 2.0.92 → 2.0.94

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 (205) hide show
  1. package/dist/lib/types.d.ts +3 -2
  2. package/dist/lib/types.d.ts.map +1 -1
  3. package/dist/lib/utils.d.ts +5 -0
  4. package/dist/lib/utils.d.ts.map +1 -1
  5. package/dist/lib/utils.js +16 -0
  6. package/dist/lib/utils.js.map +1 -1
  7. package/dist/proxy-server.d.ts.map +1 -1
  8. package/dist/proxy-server.js +32 -19
  9. package/dist/proxy-server.js.map +1 -1
  10. package/dist/relaycast-provider-helpers.d.ts +6 -0
  11. package/dist/relaycast-provider-helpers.d.ts.map +1 -1
  12. package/dist/relaycast-provider-helpers.js +10 -9
  13. package/dist/relaycast-provider-helpers.js.map +1 -1
  14. package/dist/relaycast-provider.d.ts +3 -7
  15. package/dist/relaycast-provider.d.ts.map +1 -1
  16. package/dist/relaycast-provider.js +5 -28
  17. package/dist/relaycast-provider.js.map +1 -1
  18. package/dist/routes/channels.d.ts.map +1 -1
  19. package/dist/routes/channels.js +7 -8
  20. package/dist/routes/channels.js.map +1 -1
  21. package/dist/routes/health.d.ts.map +1 -1
  22. package/dist/routes/health.js +2 -3
  23. package/dist/routes/health.js.map +1 -1
  24. package/dist/routes/models.d.ts.map +1 -1
  25. package/dist/routes/models.js +39 -3
  26. package/dist/routes/models.js.map +1 -1
  27. package/dist/routes/relay-config.d.ts.map +1 -1
  28. package/dist/routes/relay-config.js +19 -6
  29. package/dist/routes/relay-config.js.map +1 -1
  30. package/dist/routes/thread-replies.d.ts.map +1 -1
  31. package/dist/routes/thread-replies.js +4 -4
  32. package/dist/routes/thread-replies.js.map +1 -1
  33. package/dist/services/index.d.ts +0 -1
  34. package/dist/services/index.d.ts.map +1 -1
  35. package/dist/services/index.js +0 -1
  36. package/dist/services/index.js.map +1 -1
  37. package/dist/types/index.d.ts +0 -75
  38. package/dist/types/index.d.ts.map +1 -1
  39. package/dist/websocket/logs.d.ts +1 -25
  40. package/dist/websocket/logs.d.ts.map +1 -1
  41. package/dist/websocket/logs.js +0 -397
  42. package/dist/websocket/logs.js.map +1 -1
  43. package/out/404.html +1 -1
  44. package/out/_next/static/chunks/{3663-47290254b8f6f5dd.js → 3663-191a9aa9104061af.js} +1 -1
  45. package/out/_next/static/chunks/4201-d11188cf35739bff.js +1 -0
  46. package/out/_next/static/chunks/5787-f6fd7a3fbfe5eae6.js +73 -0
  47. package/out/_next/static/chunks/app/app/[[...slug]]/{page-c1376e695ba19e38.js → page-2b872f60e3d64014.js} +1 -1
  48. package/out/_next/static/chunks/app/{page-f2ebc7d0bc08e395.js → page-ca5511e5d65100a5.js} +1 -1
  49. package/out/about.html +1 -1
  50. package/out/about.txt +1 -1
  51. package/out/app/onboarding.html +1 -1
  52. package/out/app/onboarding.txt +1 -1
  53. package/out/app.html +1 -1
  54. package/out/app.txt +2 -2
  55. package/out/blog/go-to-bed-wake-up-to-a-finished-product.html +1 -1
  56. package/out/blog/go-to-bed-wake-up-to-a-finished-product.txt +1 -1
  57. package/out/blog/let-them-cook-multi-agent-orchestration.html +1 -1
  58. package/out/blog/let-them-cook-multi-agent-orchestration.txt +1 -1
  59. package/out/blog.html +1 -1
  60. package/out/blog.txt +1 -1
  61. package/out/careers.html +1 -1
  62. package/out/careers.txt +1 -1
  63. package/out/changelog.html +1 -1
  64. package/out/changelog.txt +1 -1
  65. package/out/cloud/link.html +1 -1
  66. package/out/cloud/link.txt +1 -1
  67. package/out/complete-profile.html +1 -1
  68. package/out/complete-profile.txt +1 -1
  69. package/out/connect-repos.html +1 -1
  70. package/out/connect-repos.txt +1 -1
  71. package/out/contact.html +1 -1
  72. package/out/contact.txt +1 -1
  73. package/out/dev/cli-tools.html +1 -1
  74. package/out/dev/cli-tools.txt +1 -1
  75. package/out/dev/log-viewer.html +1 -1
  76. package/out/dev/log-viewer.txt +1 -1
  77. package/out/docs.html +1 -1
  78. package/out/docs.txt +1 -1
  79. package/out/history.html +1 -1
  80. package/out/history.txt +2 -2
  81. package/out/index.html +1 -1
  82. package/out/index.txt +2 -2
  83. package/out/login.html +1 -1
  84. package/out/login.txt +1 -1
  85. package/out/metrics.html +1 -1
  86. package/out/metrics.txt +2 -2
  87. package/out/pricing.html +1 -1
  88. package/out/pricing.txt +1 -1
  89. package/out/privacy.html +1 -1
  90. package/out/privacy.txt +1 -1
  91. package/out/providers/setup/claude.html +1 -1
  92. package/out/providers/setup/claude.txt +1 -1
  93. package/out/providers/setup/codex.html +1 -1
  94. package/out/providers/setup/codex.txt +1 -1
  95. package/out/providers/setup/cursor.html +1 -1
  96. package/out/providers/setup/cursor.txt +1 -1
  97. package/out/providers.html +1 -1
  98. package/out/providers.txt +1 -1
  99. package/out/security.html +1 -1
  100. package/out/security.txt +1 -1
  101. package/out/signup.html +1 -1
  102. package/out/signup.txt +1 -1
  103. package/out/terms.html +1 -1
  104. package/out/terms.txt +1 -1
  105. package/package.json +6 -9
  106. package/dist/lib/attachment-storage.d.ts +0 -10
  107. package/dist/lib/attachment-storage.d.ts.map +0 -1
  108. package/dist/lib/attachment-storage.js +0 -53
  109. package/dist/lib/attachment-storage.js.map +0 -1
  110. package/dist/lib/broadcast.d.ts +0 -18
  111. package/dist/lib/broadcast.d.ts.map +0 -1
  112. package/dist/lib/broadcast.js +0 -118
  113. package/dist/lib/broadcast.js.map +0 -1
  114. package/dist/lib/channel-state.d.ts +0 -32
  115. package/dist/lib/channel-state.d.ts.map +0 -1
  116. package/dist/lib/channel-state.js +0 -146
  117. package/dist/lib/channel-state.js.map +0 -1
  118. package/dist/lib/cli-auth.d.ts +0 -40
  119. package/dist/lib/cli-auth.d.ts.map +0 -1
  120. package/dist/lib/cli-auth.js +0 -144
  121. package/dist/lib/cli-auth.js.map +0 -1
  122. package/dist/lib/data-assembly.d.ts +0 -136
  123. package/dist/lib/data-assembly.d.ts.map +0 -1
  124. package/dist/lib/data-assembly.js +0 -550
  125. package/dist/lib/data-assembly.js.map +0 -1
  126. package/dist/lib/server-state.d.ts +0 -115
  127. package/dist/lib/server-state.d.ts.map +0 -1
  128. package/dist/lib/server-state.js +0 -138
  129. package/dist/lib/server-state.js.map +0 -1
  130. package/dist/lib/websocket-runtime.d.ts +0 -17
  131. package/dist/lib/websocket-runtime.d.ts.map +0 -1
  132. package/dist/lib/websocket-runtime.js +0 -76
  133. package/dist/lib/websocket-runtime.js.map +0 -1
  134. package/dist/routes/auth.d.ts +0 -45
  135. package/dist/routes/auth.d.ts.map +0 -1
  136. package/dist/routes/auth.js +0 -261
  137. package/dist/routes/auth.js.map +0 -1
  138. package/dist/routes/channels-integrated.d.ts +0 -84
  139. package/dist/routes/channels-integrated.d.ts.map +0 -1
  140. package/dist/routes/channels-integrated.js +0 -644
  141. package/dist/routes/channels-integrated.js.map +0 -1
  142. package/dist/routes/decisions.d.ts +0 -31
  143. package/dist/routes/decisions.d.ts.map +0 -1
  144. package/dist/routes/decisions.js +0 -109
  145. package/dist/routes/decisions.js.map +0 -1
  146. package/dist/routes/fleet.d.ts +0 -24
  147. package/dist/routes/fleet.d.ts.map +0 -1
  148. package/dist/routes/fleet.js +0 -131
  149. package/dist/routes/fleet.js.map +0 -1
  150. package/dist/routes/history.d.ts +0 -13
  151. package/dist/routes/history.d.ts.map +0 -1
  152. package/dist/routes/history.js +0 -205
  153. package/dist/routes/history.js.map +0 -1
  154. package/dist/routes/messaging.d.ts +0 -34
  155. package/dist/routes/messaging.d.ts.map +0 -1
  156. package/dist/routes/messaging.js +0 -306
  157. package/dist/routes/messaging.js.map +0 -1
  158. package/dist/routes/settings.d.ts +0 -6
  159. package/dist/routes/settings.d.ts.map +0 -1
  160. package/dist/routes/settings.js +0 -119
  161. package/dist/routes/settings.js.map +0 -1
  162. package/dist/routes/spawn.d.ts +0 -75
  163. package/dist/routes/spawn.d.ts.map +0 -1
  164. package/dist/routes/spawn.js +0 -521
  165. package/dist/routes/spawn.js.map +0 -1
  166. package/dist/routes/system.d.ts +0 -21
  167. package/dist/routes/system.d.ts.map +0 -1
  168. package/dist/routes/system.js +0 -186
  169. package/dist/routes/system.js.map +0 -1
  170. package/dist/routes/tasks.d.ts +0 -27
  171. package/dist/routes/tasks.d.ts.map +0 -1
  172. package/dist/routes/tasks.js +0 -103
  173. package/dist/routes/tasks.js.map +0 -1
  174. package/dist/routes/ui.d.ts +0 -6
  175. package/dist/routes/ui.d.ts.map +0 -1
  176. package/dist/routes/ui.js +0 -114
  177. package/dist/routes/ui.js.map +0 -1
  178. package/dist/server.d.ts +0 -4
  179. package/dist/server.d.ts.map +0 -1
  180. package/dist/server.js +0 -481
  181. package/dist/server.js.map +0 -1
  182. package/dist/services/broker-spawn-reader.d.ts +0 -40
  183. package/dist/services/broker-spawn-reader.d.ts.map +0 -1
  184. package/dist/services/broker-spawn-reader.js +0 -155
  185. package/dist/services/broker-spawn-reader.js.map +0 -1
  186. package/dist/services/user-bridge.d.ts +0 -155
  187. package/dist/services/user-bridge.d.ts.map +0 -1
  188. package/dist/services/user-bridge.js +0 -385
  189. package/dist/services/user-bridge.js.map +0 -1
  190. package/dist/websocket/bridge.d.ts +0 -12
  191. package/dist/websocket/bridge.d.ts.map +0 -1
  192. package/dist/websocket/bridge.js +0 -33
  193. package/dist/websocket/bridge.js.map +0 -1
  194. package/dist/websocket/main.d.ts +0 -15
  195. package/dist/websocket/main.d.ts.map +0 -1
  196. package/dist/websocket/main.js +0 -84
  197. package/dist/websocket/main.js.map +0 -1
  198. package/dist/websocket/presence.d.ts +0 -74
  199. package/dist/websocket/presence.d.ts.map +0 -1
  200. package/dist/websocket/presence.js +0 -330
  201. package/dist/websocket/presence.js.map +0 -1
  202. package/out/_next/static/chunks/270-8c0b8109123a0c5f.js +0 -73
  203. package/out/_next/static/chunks/5518-6d77237eefc8d5ae.js +0 -1
  204. /package/out/_next/static/{5cqIVzlh9DbJT28EbNrcC → wgSCX8AQnjVl_Rnx1gUp5}/_buildManifest.js +0 -0
  205. /package/out/_next/static/{5cqIVzlh9DbJT28EbNrcC → wgSCX8AQnjVl_Rnx1gUp5}/_ssgManifest.js +0 -0
@@ -1,136 +0,0 @@
1
- import { type StorageAdapter, type StoredMessage } from '@agent-relay/storage/adapter';
2
- import type { ThreadMetadata } from '../types/threading.js';
3
- interface AgentStatus {
4
- name: string;
5
- role: string;
6
- cli: string;
7
- messageCount: number;
8
- status?: string;
9
- lastActive?: string;
10
- lastSeen?: string;
11
- needsAttention?: boolean;
12
- isProcessing?: boolean;
13
- processingStartedAt?: number;
14
- isSpawned?: boolean;
15
- team?: string;
16
- avatarUrl?: string;
17
- model?: string;
18
- cwd?: string;
19
- }
20
- interface Attachment {
21
- id: string;
22
- filename: string;
23
- mimeType: string;
24
- size: number;
25
- url: string;
26
- filePath?: string;
27
- width?: number;
28
- height?: number;
29
- data?: string;
30
- }
31
- interface Message {
32
- from: string;
33
- to: string;
34
- content: string;
35
- timestamp: string;
36
- id: string;
37
- thread?: string;
38
- isBroadcast?: boolean;
39
- status?: string;
40
- attachments?: Attachment[];
41
- channel?: string;
42
- replyCount?: number;
43
- threadSummary?: ThreadMetadata;
44
- }
45
- interface SessionInfo {
46
- id: string;
47
- agentName: string;
48
- cli?: string;
49
- startedAt: string;
50
- endedAt?: string;
51
- duration?: string;
52
- messageCount: number;
53
- summary?: string;
54
- isActive: boolean;
55
- closedBy?: 'agent' | 'disconnect' | 'error';
56
- }
57
- interface AgentSummary {
58
- agentName: string;
59
- lastUpdated: string;
60
- currentTask?: string;
61
- completedTasks?: string[];
62
- context?: string;
63
- }
64
- interface PresenceInfo {
65
- avatarUrl?: string;
66
- lastSeen: string;
67
- }
68
- interface PresenceStateLike {
69
- info: PresenceInfo;
70
- }
71
- interface ActiveWorkerLike {
72
- name: string;
73
- team?: string;
74
- cli?: string;
75
- cwd?: string;
76
- }
77
- interface SpawnReaderLike {
78
- getActiveWorkers: () => ActiveWorkerLike[];
79
- }
80
- interface BridgeLead {
81
- name: string;
82
- connected?: boolean;
83
- }
84
- interface BridgeAgent {
85
- name: string;
86
- status: string;
87
- cli?: string;
88
- lastSeen?: string;
89
- }
90
- interface BridgeProject {
91
- path?: string;
92
- lead?: BridgeLead;
93
- agents?: BridgeAgent[];
94
- }
95
- interface BridgeData {
96
- projects: BridgeProject[];
97
- messages: unknown[];
98
- connected: boolean;
99
- }
100
- export interface DataAssemblyDeps {
101
- dataDir: string;
102
- teamDir: string;
103
- projectRoot?: string;
104
- defaultWorkspaceId?: string;
105
- storage?: StorageAdapter;
106
- spawnReader?: SpawnReaderLike;
107
- onlineUsers: Map<string, PresenceStateLike>;
108
- agentCwdMap: Map<string, string>;
109
- debug?: (message: string) => void;
110
- }
111
- export interface DataAssembly {
112
- getAllData: () => Promise<{
113
- agents: Array<AgentStatus & {
114
- isHuman: false;
115
- }>;
116
- users: Array<AgentStatus & {
117
- isHuman: true;
118
- }>;
119
- messages: Message[];
120
- activity: Message[];
121
- sessions: SessionInfo[];
122
- summaries: AgentSummary[];
123
- } | null>;
124
- getBridgeData: () => Promise<BridgeData>;
125
- isInternalAgent: (name: string) => boolean;
126
- remapAgentName: (name: string) => string;
127
- buildThreadSummaryMap: (rows: StoredMessage[]) => Map<string, ThreadMetadata>;
128
- formatDuration: (startMs: number, endMs?: number) => string;
129
- }
130
- export declare const isInternalAgent: (name: string) => boolean;
131
- export declare const remapAgentName: (name: string) => string;
132
- export declare const buildThreadSummaryMap: (rows: StoredMessage[]) => Map<string, ThreadMetadata>;
133
- export declare const formatDuration: (startMs: number, endMs?: number) => string;
134
- export declare function createDataAssembly(deps: DataAssemblyDeps): DataAssembly;
135
- export {};
136
- //# sourceMappingURL=data-assembly.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data-assembly.d.ts","sourceRoot":"","sources":["../../src/lib/data-assembly.ts"],"names":[],"mappings":"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"}
@@ -1,550 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import crypto from 'crypto';
4
- import { loadTeamsConfig } from '@agent-relay/config';
5
- import { fetchCloudNeedsAttention, parseNeedsAttentionAgents } from '../services/needs-attention.js';
6
- // Helper to check if an agent name is internal/system (should be hidden from UI).
7
- // Convention: agent names starting with __ are internal (e.g., __spawner__, __DashboardBridge__).
8
- export const isInternalAgent = (name) => {
9
- if (name === '__cli_sender__')
10
- return false;
11
- return name.startsWith('__');
12
- };
13
- // Display-name remapping for CLI sender (used across message and history endpoints).
14
- export const remapAgentName = (name) => {
15
- if (name === '__cli_sender__')
16
- return 'CLI';
17
- return name;
18
- };
19
- export const buildThreadSummaryMap = (rows) => {
20
- const summaries = new Map();
21
- for (const row of rows) {
22
- if (!row.thread) {
23
- continue;
24
- }
25
- const threadId = row.thread;
26
- const existing = summaries.get(threadId);
27
- const participants = existing ? new Set(existing.participants) : new Set();
28
- participants.add(row.from);
29
- const isNewer = !existing || row.ts >= existing.lastReplyAt;
30
- summaries.set(threadId, {
31
- threadId,
32
- replyCount: existing ? existing.replyCount + 1 : 1,
33
- participants: Array.from(participants),
34
- lastReplyAt: isNewer ? row.ts : existing.lastReplyAt,
35
- lastReplyPreview: isNewer ? row.body : existing.lastReplyPreview,
36
- });
37
- }
38
- return summaries;
39
- };
40
- const mapStoredMessages = (rows, threadSummaries) => rows
41
- // Filter out messages from/to internal system agents (e.g., __spawner__).
42
- .filter((row) => !isInternalAgent(row.from) && !isInternalAgent(row.to))
43
- // Filter out channel messages - these are shown in the channels view, not the agent messages view.
44
- .filter((row) => {
45
- if (row.data && typeof row.data === 'object' && '_isChannelMessage' in row.data) {
46
- return false;
47
- }
48
- return true;
49
- })
50
- .map((row) => {
51
- const summaryFromReplies = threadSummaries?.get(row.id);
52
- const fallbackSummary = (!summaryFromReplies && row.replyCount && row.replyCount > 0)
53
- ? {
54
- threadId: row.id,
55
- replyCount: row.replyCount,
56
- participants: Array.from(new Set([row.from, row.to])),
57
- lastReplyAt: row.ts,
58
- }
59
- : undefined;
60
- const threadSummary = summaryFromReplies ?? fallbackSummary;
61
- let attachments;
62
- let channel;
63
- let effectiveFrom = row.from;
64
- let effectiveTo = row.to;
65
- if (row.data && typeof row.data === 'object') {
66
- if ('attachments' in row.data) {
67
- attachments = row.data.attachments;
68
- }
69
- if ('channel' in row.data) {
70
- channel = row.data.channel;
71
- }
72
- // For dashboard messages sent via Dashboard, use the actual sender name.
73
- if ('senderName' in row.data && row.from === 'Dashboard') {
74
- effectiveFrom = row.data.senderName;
75
- }
76
- }
77
- effectiveFrom = remapAgentName(effectiveFrom);
78
- effectiveTo = remapAgentName(effectiveTo);
79
- return {
80
- from: effectiveFrom,
81
- to: effectiveTo,
82
- content: row.body,
83
- timestamp: new Date(row.ts).toISOString(),
84
- id: row.id,
85
- thread: row.thread,
86
- isBroadcast: row.is_broadcast,
87
- replyCount: threadSummary?.replyCount ?? row.replyCount,
88
- threadSummary,
89
- status: row.status,
90
- attachments,
91
- channel,
92
- };
93
- });
94
- export const formatDuration = (startMs, endMs) => {
95
- const end = endMs ?? Date.now();
96
- const durationMs = end - startMs;
97
- const minutes = Math.floor(durationMs / 60000);
98
- const hours = Math.floor(minutes / 60);
99
- if (hours > 0) {
100
- return `${hours}h ${minutes % 60}m`;
101
- }
102
- return `${minutes}m`;
103
- };
104
- export function createDataAssembly(deps) {
105
- const { dataDir, teamDir, projectRoot, defaultWorkspaceId, storage, spawnReader, onlineUsers, agentCwdMap, debug, } = deps;
106
- const getTeamData = () => {
107
- // Try team.json first (file-based team mode).
108
- const teamPath = path.join(teamDir, 'team.json');
109
- if (fs.existsSync(teamPath)) {
110
- try {
111
- return JSON.parse(fs.readFileSync(teamPath, 'utf-8'));
112
- }
113
- catch (e) {
114
- console.error('Failed to read team.json', e);
115
- }
116
- }
117
- // Fall back to agents.json (daemon mode - live connected agents).
118
- const agentsPath = path.join(teamDir, 'agents.json');
119
- if (fs.existsSync(agentsPath)) {
120
- try {
121
- const data = JSON.parse(fs.readFileSync(agentsPath, 'utf-8'));
122
- // Convert agents.json format to team.json format.
123
- return {
124
- agents: data.agents.map((a) => ({
125
- name: a.name,
126
- role: 'Agent',
127
- cli: a.cli ?? 'Unknown',
128
- lastSeen: a.lastSeen ?? a.connectedAt,
129
- lastActive: a.lastSeen ?? a.connectedAt,
130
- team: a.team,
131
- })),
132
- };
133
- }
134
- catch (e) {
135
- console.error('Failed to read agents.json', e);
136
- }
137
- }
138
- return null;
139
- };
140
- const parseInbox = (agentName) => {
141
- const inboxPath = path.join(dataDir, agentName, 'inbox.md');
142
- if (!fs.existsSync(inboxPath))
143
- return [];
144
- try {
145
- const content = fs.readFileSync(inboxPath, 'utf-8');
146
- const messages = [];
147
- // Split by "## Message from ".
148
- const parts = content.split('## Message from ');
149
- parts.forEach((part, index) => {
150
- if (!part.trim())
151
- return;
152
- const firstLineEnd = part.indexOf('\n');
153
- if (firstLineEnd === -1)
154
- return;
155
- const header = part.substring(0, firstLineEnd).trim();
156
- const body = part.substring(firstLineEnd).trim();
157
- let sender = header;
158
- let timestamp = new Date().toISOString();
159
- if (header.includes('|')) {
160
- const split = header.split('|');
161
- sender = split[0].trim();
162
- timestamp = split.slice(1).join('|').trim();
163
- }
164
- messages.push({
165
- from: sender,
166
- to: agentName,
167
- content: body,
168
- timestamp,
169
- id: `${agentName}-${index}-${Date.now()}`,
170
- });
171
- });
172
- return messages;
173
- }
174
- catch (e) {
175
- console.error(`Failed to read inbox for ${agentName}`, e);
176
- return [];
177
- }
178
- };
179
- const getMessages = async (agents) => {
180
- // For local mode: use storage (SQLite) first - faster and avoids daemon query timeouts.
181
- if (storage) {
182
- const rows = await storage.getMessages({ limit: 100, order: 'desc' });
183
- const threadSummaries = buildThreadSummaryMap(rows);
184
- // Dashboard expects oldest first.
185
- return mapStoredMessages(rows, threadSummaries).reverse();
186
- }
187
- // Final fallback to file-based inbox parsing.
188
- let allMessages = [];
189
- agents.forEach((a) => {
190
- const msgs = parseInbox(a.name);
191
- allMessages = [...allMessages, ...msgs];
192
- });
193
- return allMessages;
194
- };
195
- const getRecentSessions = async () => {
196
- if (storage && typeof storage.getRecentSessions === 'function') {
197
- const sessions = await storage.getRecentSessions(20);
198
- return sessions.map((s) => ({
199
- id: s.id,
200
- agentName: s.agentName,
201
- cli: s.cli,
202
- startedAt: new Date(s.startedAt).toISOString(),
203
- endedAt: s.endedAt ? new Date(s.endedAt).toISOString() : undefined,
204
- duration: formatDuration(s.startedAt, s.endedAt),
205
- messageCount: s.messageCount,
206
- summary: s.summary,
207
- isActive: !s.endedAt,
208
- closedBy: s.closedBy,
209
- }));
210
- }
211
- return [];
212
- };
213
- const getAgentSummaries = async () => {
214
- if (storage && typeof storage.getAllAgentSummaries === 'function') {
215
- const summaries = await storage.getAllAgentSummaries();
216
- return summaries.map((s) => ({
217
- agentName: s.agentName,
218
- lastUpdated: new Date(s.lastUpdated).toISOString(),
219
- currentTask: s.currentTask,
220
- completedTasks: s.completedTasks,
221
- context: s.context,
222
- }));
223
- }
224
- return [];
225
- };
226
- const getAllData = async () => {
227
- const team = getTeamData();
228
- if (!team)
229
- return null;
230
- const agentsMap = new Map();
231
- const allMessages = await getMessages(team.agents);
232
- // Initialize agents from config.
233
- team.agents.forEach((a) => {
234
- agentsMap.set(a.name, {
235
- name: a.name,
236
- role: a.role,
237
- cli: a.cli ?? 'Unknown',
238
- messageCount: 0,
239
- status: 'Idle',
240
- lastSeen: a.lastSeen,
241
- lastActive: a.lastActive,
242
- needsAttention: false,
243
- team: a.team,
244
- });
245
- });
246
- // Inject online human users (connected via dashboard WebSocket) into agentsMap.
247
- for (const [username, state] of onlineUsers) {
248
- const existing = agentsMap.get(username);
249
- if (existing) {
250
- existing.cli = 'dashboard';
251
- existing.status = 'online';
252
- existing.avatarUrl = state.info.avatarUrl || existing.avatarUrl;
253
- }
254
- else {
255
- agentsMap.set(username, {
256
- name: username,
257
- role: 'User',
258
- cli: 'dashboard',
259
- messageCount: 0,
260
- status: 'online',
261
- lastSeen: state.info.lastSeen,
262
- lastActive: state.info.lastSeen,
263
- needsAttention: false,
264
- avatarUrl: state.info.avatarUrl,
265
- });
266
- }
267
- }
268
- // Inject remote users (connected via cloud dashboard) into agentsMap.
269
- const remoteUsersPath = path.join(teamDir, 'remote-users.json');
270
- if (fs.existsSync(remoteUsersPath)) {
271
- try {
272
- const remoteData = JSON.parse(fs.readFileSync(remoteUsersPath, 'utf-8'));
273
- // Only include if file is fresh (within 60 seconds).
274
- if (remoteData.updatedAt && Date.now() - remoteData.updatedAt <= 60 * 1000) {
275
- for (const user of remoteData.users || []) {
276
- // Don't override local users.
277
- if (onlineUsers.has(user.name))
278
- continue;
279
- const existing = agentsMap.get(user.name);
280
- if (existing) {
281
- existing.cli = 'dashboard';
282
- existing.status = 'online';
283
- if (user.avatarUrl)
284
- existing.avatarUrl = user.avatarUrl;
285
- }
286
- else {
287
- // Use stable timestamps from the user/file data, not new Date().
288
- const stableTimestamp = user.lastSeen || user.connectedAt || new Date(remoteData.updatedAt).toISOString();
289
- agentsMap.set(user.name, {
290
- name: user.name,
291
- role: 'User',
292
- cli: 'dashboard',
293
- messageCount: 0,
294
- status: 'online',
295
- lastSeen: stableTimestamp,
296
- lastActive: stableTimestamp,
297
- needsAttention: false,
298
- avatarUrl: user.avatarUrl,
299
- });
300
- }
301
- }
302
- }
303
- }
304
- catch {
305
- // Ignore parse errors for remote users file.
306
- }
307
- }
308
- // Update inbox counts if fallback mode; if storage, count messages addressed to agent.
309
- if (storage) {
310
- for (const msg of allMessages) {
311
- const agent = agentsMap.get(msg.to);
312
- if (agent) {
313
- agent.messageCount = (agent.messageCount ?? 0) + 1;
314
- }
315
- }
316
- }
317
- else {
318
- // Sort by timestamp.
319
- allMessages.sort((a, b) => {
320
- return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime();
321
- });
322
- }
323
- // Derive status from messages sent BY agents.
324
- allMessages.forEach((m) => {
325
- const agent = agentsMap.get(m.from);
326
- if (agent) {
327
- agent.lastActive = m.timestamp;
328
- // Don't overwrite lastSeen - it comes from registry (heartbeat/connection tracking).
329
- if (m.content.startsWith('STATUS:')) {
330
- agent.status = m.content.substring(7).trim();
331
- }
332
- }
333
- });
334
- // Needs-attention ownership moved to cloud; dashboard now consumes pass-through data.
335
- try {
336
- const response = await fetchCloudNeedsAttention({
337
- request: { workspaceId: defaultWorkspaceId },
338
- });
339
- if (response.ok) {
340
- const payload = await response.json();
341
- const needsAttentionAgents = parseNeedsAttentionAgents(payload);
342
- needsAttentionAgents.forEach((agentName) => {
343
- const agent = agentsMap.get(agentName);
344
- if (agent) {
345
- agent.needsAttention = true;
346
- }
347
- });
348
- }
349
- }
350
- catch (err) {
351
- debug?.(`[dashboard] cloud needs-attention proxy failed: ${err.message}`);
352
- }
353
- // Read processing state from daemon.
354
- const processingStatePath = path.join(teamDir, 'processing-state.json');
355
- if (fs.existsSync(processingStatePath)) {
356
- try {
357
- const processingData = JSON.parse(fs.readFileSync(processingStatePath, 'utf-8'));
358
- const processingAgents = processingData.processingAgents || {};
359
- for (const [agentName, state] of Object.entries(processingAgents)) {
360
- const agent = agentsMap.get(agentName);
361
- if (agent && state && typeof state === 'object') {
362
- agent.isProcessing = true;
363
- agent.processingStartedAt = state.startedAt;
364
- }
365
- }
366
- }
367
- catch {
368
- // Ignore errors reading processing state - it's optional.
369
- }
370
- }
371
- // Mark spawned agents with isSpawned flag, team, model, and cwd.
372
- if (spawnReader) {
373
- const activeWorkers = spawnReader.getActiveWorkers();
374
- for (const worker of activeWorkers) {
375
- const agent = agentsMap.get(worker.name);
376
- if (agent) {
377
- agent.isSpawned = true;
378
- if (worker.team) {
379
- agent.team = worker.team;
380
- }
381
- const workerCwd = agentCwdMap.get(worker.name) || worker.cwd;
382
- if (workerCwd) {
383
- agent.cwd = workerCwd;
384
- }
385
- if (worker.cli) {
386
- const modelMatch = worker.cli.match(/--model[=\s]+(\S+)/);
387
- if (modelMatch) {
388
- agent.model = modelMatch[1];
389
- }
390
- }
391
- }
392
- }
393
- }
394
- // Inject cwd from agentCwdMap for agents not in spawner's active workers.
395
- for (const [name, cwd] of agentCwdMap) {
396
- const agent = agentsMap.get(name);
397
- if (agent && !agent.cwd) {
398
- agent.cwd = cwd;
399
- }
400
- }
401
- // Also check workers.json for externally-spawned workers.
402
- const workersJsonPath = path.join(teamDir, 'workers.json');
403
- if (fs.existsSync(workersJsonPath)) {
404
- try {
405
- const workersData = JSON.parse(fs.readFileSync(workersJsonPath, 'utf-8'));
406
- for (const worker of workersData.workers || []) {
407
- const agent = agentsMap.get(worker.name);
408
- if (agent && !agent.isSpawned && worker.logFile && fs.existsSync(worker.logFile)) {
409
- agent.isSpawned = true;
410
- }
411
- }
412
- }
413
- catch {
414
- // Ignore errors reading workers.json.
415
- }
416
- }
417
- // Mark relay-protocol spawned agents by log-file presence.
418
- if (spawnReader) {
419
- for (const [name, agent] of agentsMap) {
420
- if (agent.isSpawned)
421
- continue;
422
- if (onlineUsers.has(name) || name === 'Dashboard')
423
- continue;
424
- const logPath = path.join(teamDir, `${name}.log`);
425
- if (fs.existsSync(logPath)) {
426
- agent.isSpawned = true;
427
- }
428
- }
429
- }
430
- // Set team from teams.json for agents that don't have a team yet.
431
- const teamsConfig = loadTeamsConfig(projectRoot || dataDir);
432
- if (teamsConfig) {
433
- for (const teamAgent of teamsConfig.agents) {
434
- const agent = agentsMap.get(teamAgent.name);
435
- if (agent && !agent.team) {
436
- agent.team = teamsConfig.team;
437
- }
438
- }
439
- }
440
- // Fetch sessions and summaries in parallel.
441
- const [sessions, summaries] = await Promise.all([
442
- getRecentSessions(),
443
- getAgentSummaries(),
444
- ]);
445
- // Filter and separate agents from human users.
446
- const now = Date.now();
447
- const OFFLINE_THRESHOLD_MS = 30 * 1000;
448
- const validEntries = Array.from(agentsMap.values())
449
- .filter((agent) => {
450
- if (agent.name === 'Dashboard')
451
- return false;
452
- if (agent.name.startsWith('__'))
453
- return false;
454
- if (agent.name === 'Dashboard')
455
- return false;
456
- if (!agent.cli || agent.cli === 'Unknown')
457
- return false;
458
- if (!agent.lastSeen)
459
- return false;
460
- const lastSeenTime = new Date(agent.lastSeen).getTime();
461
- if (now - lastSeenTime > OFFLINE_THRESHOLD_MS)
462
- return false;
463
- return true;
464
- });
465
- const filteredAgents = validEntries
466
- .filter((agent) => agent.cli !== 'dashboard')
467
- .map((agent) => ({
468
- ...agent,
469
- isHuman: false,
470
- }))
471
- .sort((a, b) => a.name.localeCompare(b.name));
472
- const humanUsers = validEntries
473
- .filter((agent) => agent.cli === 'dashboard')
474
- .map((agent) => ({
475
- ...agent,
476
- isHuman: true,
477
- }))
478
- .sort((a, b) => a.name.localeCompare(b.name));
479
- return {
480
- agents: filteredAgents,
481
- users: humanUsers,
482
- messages: allMessages,
483
- activity: allMessages,
484
- sessions,
485
- summaries,
486
- };
487
- };
488
- const getBridgeData = async () => {
489
- const bridgeStatePath = path.join(dataDir, 'bridge-state.json');
490
- if (fs.existsSync(bridgeStatePath)) {
491
- try {
492
- const bridgeState = JSON.parse(fs.readFileSync(bridgeStatePath, 'utf-8'));
493
- // Enrich each project with actual agent data from their team directories.
494
- if (bridgeState.projects && Array.isArray(bridgeState.projects)) {
495
- for (const project of bridgeState.projects) {
496
- if (project.path) {
497
- const projectHash = crypto.createHash('sha256').update(project.path).digest('hex').slice(0, 12);
498
- const projectDataDir = path.join(path.dirname(dataDir), projectHash);
499
- const projectTeamDir = path.join(projectDataDir, 'team');
500
- const agentsPath = path.join(projectTeamDir, 'agents.json');
501
- if (fs.existsSync(agentsPath)) {
502
- try {
503
- const agentsData = JSON.parse(fs.readFileSync(agentsPath, 'utf-8'));
504
- if (agentsData.agents && Array.isArray(agentsData.agents)) {
505
- // Filter to only show online agents (seen within 30 seconds - aligns with heartbeat timeout).
506
- const thirtySecondsAgo = Date.now() - 30 * 1000;
507
- project.agents = agentsData.agents
508
- .filter((a) => {
509
- if (!a.lastSeen)
510
- return false;
511
- return new Date(a.lastSeen).getTime() > thirtySecondsAgo;
512
- })
513
- .map((a) => ({
514
- name: a.name,
515
- status: 'active',
516
- cli: a.cli,
517
- lastSeen: a.lastSeen,
518
- }));
519
- // Update lead status based on actual agents.
520
- if (project.lead) {
521
- const leadAgent = project.agents.find((a) => a.name.toLowerCase() === project.lead.name.toLowerCase());
522
- project.lead.connected = !!leadAgent;
523
- }
524
- }
525
- }
526
- catch (e) {
527
- console.error(`Failed to read agents for ${project.path}:`, e);
528
- }
529
- }
530
- }
531
- }
532
- }
533
- return bridgeState;
534
- }
535
- catch {
536
- return { projects: [], messages: [], connected: false };
537
- }
538
- }
539
- return { projects: [], messages: [], connected: false };
540
- };
541
- return {
542
- getAllData,
543
- getBridgeData,
544
- isInternalAgent,
545
- remapAgentName,
546
- buildThreadSummaryMap,
547
- formatDuration,
548
- };
549
- }
550
- //# sourceMappingURL=data-assembly.js.map