@agent-link/server 0.1.187 → 0.1.189

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 (76) hide show
  1. package/dist/auth-manager.d.ts +36 -0
  2. package/dist/auth-manager.js +96 -0
  3. package/dist/auth-manager.js.map +1 -0
  4. package/dist/http.d.ts +4 -0
  5. package/dist/http.js +85 -0
  6. package/dist/http.js.map +1 -0
  7. package/dist/index.js +5 -84
  8. package/dist/index.js.map +1 -1
  9. package/dist/message-relay.d.ts +17 -0
  10. package/dist/message-relay.js +23 -0
  11. package/dist/message-relay.js.map +1 -0
  12. package/dist/session-manager.d.ts +44 -0
  13. package/dist/session-manager.js +83 -0
  14. package/dist/session-manager.js.map +1 -0
  15. package/dist/ws-agent.js +19 -27
  16. package/dist/ws-agent.js.map +1 -1
  17. package/dist/ws-client.js +31 -37
  18. package/dist/ws-client.js.map +1 -1
  19. package/package.json +3 -3
  20. package/web/dist/assets/index-DIO7Hox0.js +320 -0
  21. package/web/dist/assets/index-DIO7Hox0.js.map +1 -0
  22. package/web/dist/assets/index-Y1FN_mFe.css +1 -0
  23. package/web/{index.html → dist/index.html} +2 -19
  24. package/dist/auth.d.ts +0 -13
  25. package/dist/auth.js +0 -65
  26. package/dist/auth.js.map +0 -1
  27. package/dist/context.d.ts +0 -52
  28. package/dist/context.js +0 -60
  29. package/dist/context.js.map +0 -1
  30. package/web/app.js +0 -2881
  31. package/web/css/ask-question.css +0 -333
  32. package/web/css/base.css +0 -270
  33. package/web/css/btw.css +0 -148
  34. package/web/css/chat.css +0 -176
  35. package/web/css/file-browser.css +0 -499
  36. package/web/css/input.css +0 -671
  37. package/web/css/loop.css +0 -674
  38. package/web/css/markdown.css +0 -169
  39. package/web/css/responsive.css +0 -314
  40. package/web/css/sidebar.css +0 -593
  41. package/web/css/team.css +0 -1277
  42. package/web/css/tools.css +0 -327
  43. package/web/encryption.js +0 -56
  44. package/web/modules/appHelpers.js +0 -100
  45. package/web/modules/askQuestion.js +0 -63
  46. package/web/modules/backgroundRouting.js +0 -269
  47. package/web/modules/connection.js +0 -731
  48. package/web/modules/fileAttachments.js +0 -125
  49. package/web/modules/fileBrowser.js +0 -398
  50. package/web/modules/filePreview.js +0 -213
  51. package/web/modules/i18n.js +0 -101
  52. package/web/modules/loop.js +0 -338
  53. package/web/modules/loopTemplates.js +0 -110
  54. package/web/modules/markdown.js +0 -83
  55. package/web/modules/messageHelpers.js +0 -206
  56. package/web/modules/sidebar.js +0 -402
  57. package/web/modules/streaming.js +0 -116
  58. package/web/modules/team.js +0 -396
  59. package/web/modules/teamTemplates.js +0 -360
  60. package/web/vendor/highlight.min.js +0 -1213
  61. package/web/vendor/marked.min.js +0 -6
  62. package/web/vendor/nacl-fast.min.js +0 -1
  63. package/web/vendor/nacl-util.min.js +0 -1
  64. package/web/vendor/pako.min.js +0 -2
  65. package/web/vendor/vue.global.prod.js +0 -13
  66. /package/web/{favicon.svg → dist/favicon.svg} +0 -0
  67. /package/web/{images → dist/images}/chat-iPad.webp +0 -0
  68. /package/web/{images → dist/images}/chat-iPhone.webp +0 -0
  69. /package/web/{images → dist/images}/loop-iPad.webp +0 -0
  70. /package/web/{images → dist/images}/team-iPad.webp +0 -0
  71. /package/web/{landing.html → dist/landing.html} +0 -0
  72. /package/web/{landing.zh.html → dist/landing.zh.html} +0 -0
  73. /package/web/{locales → dist/locales}/en.json +0 -0
  74. /package/web/{locales → dist/locales}/zh.json +0 -0
  75. /package/web/{vendor → dist/vendor}/github-dark.min.css +0 -0
  76. /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
- }