@agent-link/server 0.1.187 → 0.1.188

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 (54) hide show
  1. package/dist/index.js +13 -15
  2. package/dist/index.js.map +1 -1
  3. package/package.json +3 -3
  4. package/web/dist/assets/index-C9bIrYkZ.js +320 -0
  5. package/web/dist/assets/index-C9bIrYkZ.js.map +1 -0
  6. package/web/dist/assets/index-Y1FN_mFe.css +1 -0
  7. package/web/{index.html → dist/index.html} +2 -19
  8. package/web/app.js +0 -2881
  9. package/web/css/ask-question.css +0 -333
  10. package/web/css/base.css +0 -270
  11. package/web/css/btw.css +0 -148
  12. package/web/css/chat.css +0 -176
  13. package/web/css/file-browser.css +0 -499
  14. package/web/css/input.css +0 -671
  15. package/web/css/loop.css +0 -674
  16. package/web/css/markdown.css +0 -169
  17. package/web/css/responsive.css +0 -314
  18. package/web/css/sidebar.css +0 -593
  19. package/web/css/team.css +0 -1277
  20. package/web/css/tools.css +0 -327
  21. package/web/encryption.js +0 -56
  22. package/web/modules/appHelpers.js +0 -100
  23. package/web/modules/askQuestion.js +0 -63
  24. package/web/modules/backgroundRouting.js +0 -269
  25. package/web/modules/connection.js +0 -731
  26. package/web/modules/fileAttachments.js +0 -125
  27. package/web/modules/fileBrowser.js +0 -398
  28. package/web/modules/filePreview.js +0 -213
  29. package/web/modules/i18n.js +0 -101
  30. package/web/modules/loop.js +0 -338
  31. package/web/modules/loopTemplates.js +0 -110
  32. package/web/modules/markdown.js +0 -83
  33. package/web/modules/messageHelpers.js +0 -206
  34. package/web/modules/sidebar.js +0 -402
  35. package/web/modules/streaming.js +0 -116
  36. package/web/modules/team.js +0 -396
  37. package/web/modules/teamTemplates.js +0 -360
  38. package/web/vendor/highlight.min.js +0 -1213
  39. package/web/vendor/marked.min.js +0 -6
  40. package/web/vendor/nacl-fast.min.js +0 -1
  41. package/web/vendor/nacl-util.min.js +0 -1
  42. package/web/vendor/pako.min.js +0 -2
  43. package/web/vendor/vue.global.prod.js +0 -13
  44. /package/web/{favicon.svg → dist/favicon.svg} +0 -0
  45. /package/web/{images → dist/images}/chat-iPad.webp +0 -0
  46. /package/web/{images → dist/images}/chat-iPhone.webp +0 -0
  47. /package/web/{images → dist/images}/loop-iPad.webp +0 -0
  48. /package/web/{images → dist/images}/team-iPad.webp +0 -0
  49. /package/web/{landing.html → dist/landing.html} +0 -0
  50. /package/web/{landing.zh.html → dist/landing.zh.html} +0 -0
  51. /package/web/{locales → dist/locales}/en.json +0 -0
  52. /package/web/{locales → dist/locales}/zh.json +0 -0
  53. /package/web/{vendor → dist/vendor}/github-dark.min.css +0 -0
  54. /package/web/{vendor → dist/vendor}/github.min.css +0 -0
@@ -1,396 +0,0 @@
1
- // ── Team mode: state management and message routing ───────────────────────
2
- const { ref, computed } = Vue;
3
-
4
- const MAX_FEED_ENTRIES = 200;
5
-
6
- // Color palette (matches agent/src/team.ts AGENT_COLORS)
7
- const AGENT_COLORS = [
8
- '#EF4444', '#EAB308', '#3B82F6', '#10B981', '#8B5CF6',
9
- '#F97316', '#EC4899', '#06B6D4', '#84CC16', '#6366F1',
10
- ];
11
-
12
- /**
13
- * Creates the team mode controller.
14
- * @param {object} deps
15
- * @param {Function} deps.wsSend
16
- * @param {Function} deps.scrollToBottom
17
- */
18
- export function createTeam(deps) {
19
- const { wsSend, scrollToBottom, loadingTeams } = deps;
20
-
21
- // ── Reactive state ──
22
-
23
- /** @type {import('vue').Ref<object|null>} Current team state (TeamStateSerialized or null) */
24
- const teamState = ref(null);
25
-
26
- /** @type {import('vue').Ref<string>} 'chat' | 'team' | 'loop' — current view mode */
27
- const viewMode = ref('chat');
28
-
29
- /** @type {import('vue').Ref<string|null>} Currently viewed agent ID, null = dashboard */
30
- const activeAgentView = ref(null);
31
-
32
- /** @type {import('vue').Ref<object|null>} Historical team loaded for read-only viewing */
33
- const historicalTeam = ref(null);
34
-
35
- /** @type {import('vue').Ref<Array>} Teams list from server */
36
- const teamsList = ref([]);
37
-
38
- /** Per-agent message accumulator: agentId → message[] */
39
- const agentMessages = ref({});
40
-
41
- /** Per-agent message ID counter */
42
- let agentMsgIdCounter = 0;
43
-
44
- // ── Computed ──
45
-
46
- const isTeamActive = computed(() => teamState.value !== null && teamState.value.status !== 'completed' && teamState.value.status !== 'failed');
47
- const isTeamRunning = computed(() => teamState.value !== null && (teamState.value.status === 'running' || teamState.value.status === 'planning' || teamState.value.status === 'summarizing'));
48
-
49
- /** The team being displayed: active or historical */
50
- const displayTeam = computed(() => historicalTeam.value || teamState.value);
51
-
52
- const pendingTasks = computed(() => {
53
- const t = displayTeam.value;
54
- if (!t) return [];
55
- return t.tasks.filter(task => task.status === 'pending');
56
- });
57
- const activeTasks = computed(() => {
58
- const t = displayTeam.value;
59
- if (!t) return [];
60
- return t.tasks.filter(task => task.status === 'active');
61
- });
62
- const doneTasks = computed(() => {
63
- const t = displayTeam.value;
64
- if (!t) return [];
65
- return t.tasks.filter(task => task.status === 'done');
66
- });
67
- const failedTasks = computed(() => {
68
- const t = displayTeam.value;
69
- if (!t) return [];
70
- return t.tasks.filter(task => task.status === 'failed');
71
- });
72
-
73
- // ── Methods ──
74
-
75
- /** Sync active team's status into the sidebar teamsList entry. */
76
- function syncTeamsListStatus() {
77
- if (!teamState.value) return;
78
- const item = teamsList.value.find(t => t.teamId === teamState.value.teamId);
79
- if (item) item.status = teamState.value.status;
80
- }
81
-
82
- function launchTeam(instruction, leadPrompt, agents) {
83
- wsSend({ type: 'create_team', instruction, leadPrompt, agents });
84
- }
85
-
86
- function dissolveTeam() {
87
- wsSend({ type: 'dissolve_team' });
88
- }
89
-
90
- function viewAgent(agentId) {
91
- activeAgentView.value = agentId;
92
- }
93
-
94
- function viewDashboard() {
95
- activeAgentView.value = null;
96
- }
97
-
98
- function viewHistoricalTeam(teamId) {
99
- wsSend({ type: 'get_team', teamId });
100
- }
101
-
102
- function requestTeamsList() {
103
- if (loadingTeams) loadingTeams.value = true;
104
- wsSend({ type: 'list_teams' });
105
- }
106
-
107
- function deleteTeamById(teamId) {
108
- wsSend({ type: 'delete_team', teamId });
109
- }
110
-
111
- function renameTeamById(teamId, newTitle) {
112
- wsSend({ type: 'rename_team', teamId, newTitle });
113
- }
114
-
115
- function requestAgentHistory(teamId, agentId) {
116
- wsSend({ type: 'get_team_agent_history', teamId, agentId });
117
- }
118
-
119
- function getAgentColor(agentId) {
120
- if (agentId === 'lead') return '#A78BFA'; // purple for lead
121
- const t = displayTeam.value;
122
- if (!t || !t.agents) return AGENT_COLORS[0];
123
- const idx = t.agents.findIndex(a => a.id === agentId);
124
- return idx >= 0 ? AGENT_COLORS[idx % AGENT_COLORS.length] : AGENT_COLORS[0];
125
- }
126
-
127
- function findAgent(agentId) {
128
- if (agentId === 'lead') return { id: 'lead', name: 'Lead', color: '#A78BFA', status: 'working' };
129
- const t = displayTeam.value;
130
- if (!t || !t.agents) return null;
131
- return t.agents.find(a => a.id === agentId) || null;
132
- }
133
-
134
- function getAgentMessages(agentId) {
135
- return agentMessages.value[agentId] || [];
136
- }
137
-
138
- function backToChat() {
139
- viewMode.value = 'chat';
140
- historicalTeam.value = null;
141
- activeAgentView.value = null;
142
- }
143
-
144
- function newTeam() {
145
- viewMode.value = 'team';
146
- historicalTeam.value = null;
147
- activeAgentView.value = null;
148
- // If completed team is still in teamState, clear it so create panel shows
149
- if (teamState.value && (teamState.value.status === 'completed' || teamState.value.status === 'failed')) {
150
- teamState.value = null;
151
- }
152
- requestTeamsList();
153
- }
154
-
155
- // ── Message routing ──
156
-
157
- /**
158
- * Handle incoming team-related messages from the WebSocket.
159
- * Returns true if the message was consumed (should not be processed further).
160
- */
161
- function handleTeamMessage(msg) {
162
- switch (msg.type) {
163
- case 'team_created':
164
- teamState.value = msg.team;
165
- viewMode.value = 'team';
166
- historicalTeam.value = null;
167
- activeAgentView.value = null;
168
- agentMessages.value = {};
169
- agentMsgIdCounter = 0;
170
- // Initialize lead message list
171
- agentMessages.value['lead'] = [];
172
- // Initialize agent message lists
173
- if (msg.team.agents) {
174
- for (const agent of msg.team.agents) {
175
- agentMessages.value[agent.id] = [];
176
- }
177
- }
178
- return true;
179
-
180
- case 'team_agent_status': {
181
- if (!teamState.value || teamState.value.teamId !== msg.teamId) return false;
182
- const agent = msg.agent;
183
- const existing = teamState.value.agents.find(a => a.id === agent.id);
184
- if (existing) {
185
- existing.status = agent.status;
186
- existing.taskId = agent.taskId;
187
- } else {
188
- // New agent joined
189
- teamState.value.agents.push(agent);
190
- if (!agentMessages.value[agent.id]) {
191
- agentMessages.value[agent.id] = [];
192
- }
193
- }
194
- // Update team status to running when first subagent appears
195
- if (teamState.value.status === 'planning') {
196
- teamState.value.status = 'running';
197
- syncTeamsListStatus();
198
- }
199
- return true;
200
- }
201
-
202
- case 'team_task_update': {
203
- if (!teamState.value || teamState.value.teamId !== msg.teamId) return false;
204
- const task = msg.task;
205
- const idx = teamState.value.tasks.findIndex(t => t.id === task.id);
206
- if (idx >= 0) {
207
- teamState.value.tasks[idx] = task;
208
- } else {
209
- teamState.value.tasks.push(task);
210
- }
211
- return true;
212
- }
213
-
214
- case 'team_feed': {
215
- if (!teamState.value || teamState.value.teamId !== msg.teamId) return false;
216
- teamState.value.feed.push(msg.entry);
217
- // Cap feed entries
218
- if (teamState.value.feed.length > MAX_FEED_ENTRIES) {
219
- teamState.value.feed = teamState.value.feed.slice(-MAX_FEED_ENTRIES);
220
- }
221
- return true;
222
- }
223
-
224
- case 'team_completed': {
225
- if (!teamState.value || teamState.value.teamId !== msg.teamId) return false;
226
- // Update with final state from server
227
- teamState.value = msg.team;
228
- syncTeamsListStatus();
229
- return true;
230
- }
231
-
232
- case 'team_lead_status': {
233
- if (!teamState.value || teamState.value.teamId !== msg.teamId) return false;
234
- teamState.value.leadStatus = msg.leadStatus;
235
- if (msg.teamStatus) {
236
- teamState.value.status = msg.teamStatus;
237
- syncTeamsListStatus();
238
- }
239
- return true;
240
- }
241
-
242
- case 'teams_list':
243
- teamsList.value = msg.teams || [];
244
- return true;
245
-
246
- case 'team_deleted':
247
- teamsList.value = teamsList.value.filter(t => t.teamId !== msg.teamId);
248
- // If viewing the deleted team, go back
249
- if (historicalTeam.value && historicalTeam.value.teamId === msg.teamId) {
250
- historicalTeam.value = null;
251
- }
252
- return true;
253
-
254
- case 'team_renamed': {
255
- const item = teamsList.value.find(t => t.teamId === msg.teamId);
256
- if (item) item.title = msg.newTitle;
257
- // Update historical view if showing this team
258
- if (historicalTeam.value && historicalTeam.value.teamId === msg.teamId) {
259
- historicalTeam.value.title = msg.newTitle;
260
- }
261
- // Update active team if it's the same
262
- if (teamState.value && teamState.value.teamId === msg.teamId) {
263
- teamState.value.title = msg.newTitle;
264
- }
265
- return true;
266
- }
267
-
268
- case 'team_detail':
269
- historicalTeam.value = msg.team;
270
- viewMode.value = 'team';
271
- activeAgentView.value = null;
272
- return true;
273
-
274
- case 'team_agent_history': {
275
- if (msg.agentId) {
276
- if (msg.messages && msg.messages.length > 0) {
277
- // Default expand tool messages in history view
278
- for (const m of msg.messages) {
279
- if (m.role === 'tool' && m.expanded === undefined) m.expanded = true;
280
- }
281
- agentMessages.value[msg.agentId] = msg.messages;
282
- } else {
283
- agentMessages.value[msg.agentId] = [];
284
- }
285
- }
286
- return true;
287
- }
288
-
289
- default:
290
- return false;
291
- }
292
- }
293
-
294
- /**
295
- * Handle claude_output messages tagged with teamId + agentRole.
296
- * Accumulates per-agent messages for agent detail view.
297
- * Returns true if consumed.
298
- */
299
- function handleTeamAgentOutput(msg) {
300
- if (!msg.teamId || !msg.agentRole) return false;
301
- if (!teamState.value || teamState.value.teamId !== msg.teamId) return false;
302
-
303
- const agentId = msg.agentRole;
304
- if (!agentMessages.value[agentId]) {
305
- agentMessages.value[agentId] = [];
306
- }
307
- const msgs = agentMessages.value[agentId];
308
- const data = msg.data;
309
- if (!data) return true;
310
-
311
- if (data.type === 'content_block_delta' && data.delta) {
312
- // Append text to last assistant message (or create new one)
313
- const last = msgs.length > 0 ? msgs[msgs.length - 1] : null;
314
- if (last && last.role === 'assistant' && last.isStreaming) {
315
- last.content += data.delta;
316
- } else {
317
- msgs.push({
318
- id: ++agentMsgIdCounter, role: 'assistant',
319
- content: data.delta, isStreaming: true, timestamp: Date.now(),
320
- });
321
- }
322
- } else if (data.type === 'tool_use' && data.tools) {
323
- // Finalize streaming message
324
- const last = msgs.length > 0 ? msgs[msgs.length - 1] : null;
325
- if (last && last.role === 'assistant' && last.isStreaming) {
326
- last.isStreaming = false;
327
- }
328
- for (const tool of data.tools) {
329
- msgs.push({
330
- id: ++agentMsgIdCounter, role: 'tool',
331
- toolId: tool.id, toolName: tool.name || 'unknown',
332
- toolInput: tool.input ? JSON.stringify(tool.input, null, 2) : '',
333
- hasResult: false, expanded: true, timestamp: Date.now(),
334
- });
335
- }
336
- } else if (data.type === 'user' && data.tool_use_result) {
337
- const result = data.tool_use_result;
338
- const results = Array.isArray(result) ? result : [result];
339
- for (const r of results) {
340
- const toolMsg = msgs.find(m => m.role === 'tool' && m.toolId === r.tool_use_id);
341
- if (toolMsg) {
342
- toolMsg.toolOutput = typeof r.content === 'string'
343
- ? r.content : JSON.stringify(r.content, null, 2);
344
- toolMsg.hasResult = true;
345
- }
346
- }
347
- }
348
-
349
- return true;
350
- }
351
-
352
- /**
353
- * Handle active_conversations response that includes activeTeam.
354
- * Called on initial connect + reconnect to restore team state.
355
- */
356
- function handleActiveTeamRestore(activeTeam, currentWorkDir) {
357
- if (!activeTeam) return;
358
- // Skip if the active team belongs to a different workdir
359
- if (currentWorkDir && activeTeam.workDir && activeTeam.workDir !== currentWorkDir) return;
360
-
361
- const wasAlreadyLoaded = teamState.value !== null;
362
- teamState.value = activeTeam;
363
- // Only switch to team view on first restore (initial connect / reconnect),
364
- // not on idle-check polls — otherwise the user gets yanked out of chat.
365
- if (!wasAlreadyLoaded) {
366
- viewMode.value = 'team';
367
- }
368
- // Re-initialize agent message lists (messages lost on reconnect)
369
- if (!agentMessages.value['lead']) {
370
- agentMessages.value['lead'] = [];
371
- }
372
- if (activeTeam.agents) {
373
- for (const agent of activeTeam.agents) {
374
- if (!agentMessages.value[agent.id]) {
375
- agentMessages.value[agent.id] = [];
376
- }
377
- }
378
- }
379
- }
380
-
381
- return {
382
- // State
383
- teamState, viewMode, activeAgentView, historicalTeam, teamsList,
384
- agentMessages,
385
- // Computed
386
- isTeamActive, isTeamRunning, displayTeam,
387
- pendingTasks, activeTasks, doneTasks, failedTasks,
388
- // Methods
389
- launchTeam, dissolveTeam, viewAgent, viewDashboard,
390
- viewHistoricalTeam, requestTeamsList, deleteTeamById, renameTeamById,
391
- requestAgentHistory,
392
- getAgentColor, findAgent, getAgentMessages, backToChat, newTeam,
393
- // Message handling
394
- handleTeamMessage, handleTeamAgentOutput, handleActiveTeamRestore,
395
- };
396
- }