@agent-link/server 0.1.134 → 0.1.136

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-link/server",
3
- "version": "0.1.134",
3
+ "version": "0.1.136",
4
4
  "description": "AgentLink relay server",
5
5
  "license": "MIT",
6
6
  "repository": {
package/web/app.js CHANGED
@@ -78,6 +78,13 @@ const App = {
78
78
  const renamingSessionId = ref(null);
79
79
  const renameText = ref('');
80
80
 
81
+ // Team rename/delete state
82
+ const renamingTeamId = ref(null);
83
+ const renameTeamText = ref('');
84
+ const deleteTeamConfirmOpen = ref(false);
85
+ const deleteTeamConfirmTitle = ref('');
86
+ const pendingDeleteTeamId = ref(null);
87
+
81
88
  // Working directory history
82
89
  const workdirHistory = ref([]);
83
90
 
@@ -309,6 +316,10 @@ const App = {
309
316
  wsSend, scrollToBottom,
310
317
  });
311
318
  setTeam(team);
319
+ sidebar.setOnSwitchToChat(() => {
320
+ team.teamMode.value = 'chat';
321
+ team.historicalTeam.value = null;
322
+ });
312
323
 
313
324
  // File browser module
314
325
  const fileBrowser = createFileBrowser({
@@ -533,6 +544,40 @@ const App = {
533
544
  startRename: sidebar.startRename,
534
545
  confirmRename: sidebar.confirmRename,
535
546
  cancelRename: sidebar.cancelRename,
547
+ // Team rename/delete
548
+ renamingTeamId, renameTeamText,
549
+ deleteTeamConfirmOpen, deleteTeamConfirmTitle, pendingDeleteTeamId,
550
+ startTeamRename(t) {
551
+ renamingTeamId.value = t.teamId;
552
+ renameTeamText.value = t.title || '';
553
+ },
554
+ confirmTeamRename() {
555
+ const tid = renamingTeamId.value;
556
+ const title = renameTeamText.value.trim();
557
+ if (!tid || !title) { renamingTeamId.value = null; renameTeamText.value = ''; return; }
558
+ team.renameTeamById(tid, title);
559
+ renamingTeamId.value = null;
560
+ renameTeamText.value = '';
561
+ },
562
+ cancelTeamRename() {
563
+ renamingTeamId.value = null;
564
+ renameTeamText.value = '';
565
+ },
566
+ requestDeleteTeam(t) {
567
+ pendingDeleteTeamId.value = t.teamId;
568
+ deleteTeamConfirmTitle.value = t.title || t.teamId.slice(0, 8);
569
+ deleteTeamConfirmOpen.value = true;
570
+ },
571
+ confirmDeleteTeam() {
572
+ if (!pendingDeleteTeamId.value) return;
573
+ team.deleteTeamById(pendingDeleteTeamId.value);
574
+ deleteTeamConfirmOpen.value = false;
575
+ pendingDeleteTeamId.value = null;
576
+ },
577
+ cancelDeleteTeam() {
578
+ deleteTeamConfirmOpen.value = false;
579
+ pendingDeleteTeamId.value = null;
580
+ },
536
581
  // Working directory history
537
582
  filteredWorkdirHistory: sidebar.filteredWorkdirHistory,
538
583
  switchToWorkdir: sidebar.switchToWorkdir,
@@ -592,6 +637,8 @@ const App = {
592
637
  viewDashboard: team.viewDashboard,
593
638
  viewHistoricalTeam: team.viewHistoricalTeam,
594
639
  requestTeamsList: team.requestTeamsList,
640
+ deleteTeamById: team.deleteTeamById,
641
+ renameTeamById: team.renameTeamById,
595
642
  getAgentColor: team.getAgentColor,
596
643
  findAgent: team.findAgent,
597
644
  getAgentMessages: team.getAgentMessages,
@@ -816,22 +863,48 @@ const App = {
816
863
  <!-- Teams section -->
817
864
  <div v-if="teamsList.length > 0" class="sidebar-section sidebar-teams">
818
865
  <div class="sidebar-section-header">
819
- <span>Teams</span>
866
+ <span>Teams History</span>
820
867
  </div>
868
+
869
+ <button class="new-conversation-btn" @click="newTeam" :disabled="isTeamActive">
870
+ <svg viewBox="0 0 24 24" width="14" height="14"><path fill="currentColor" d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
871
+ New team
872
+ </button>
873
+
821
874
  <div class="team-history-list">
822
875
  <div
823
876
  v-for="t in teamsList" :key="t.teamId"
824
877
  :class="['team-history-item', { active: displayTeam && displayTeam.teamId === t.teamId }]"
825
- @click="viewHistoricalTeam(t.teamId)"
878
+ @click="renamingTeamId !== t.teamId && viewHistoricalTeam(t.teamId)"
826
879
  :title="t.title"
827
880
  >
828
881
  <svg class="team-history-icon" viewBox="0 0 24 24" width="14" height="14"><path fill="currentColor" d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></svg>
829
882
  <div class="team-history-info">
830
- <div class="team-history-title">{{ t.title || 'Untitled team' }}</div>
831
- <div class="team-history-meta">
883
+ <div v-if="renamingTeamId === t.teamId" class="session-rename-row">
884
+ <input
885
+ class="session-rename-input"
886
+ v-model="renameTeamText"
887
+ @click.stop
888
+ @keydown.enter.stop="confirmTeamRename"
889
+ @keydown.escape.stop="cancelTeamRename"
890
+ @vue:mounted="$event.el.focus()"
891
+ />
892
+ <button class="session-rename-ok" @click.stop="confirmTeamRename" title="Confirm">&#10003;</button>
893
+ <button class="session-rename-cancel" @click.stop="cancelTeamRename" title="Cancel">&times;</button>
894
+ </div>
895
+ <div v-else class="team-history-title">{{ t.title || 'Untitled team' }}</div>
896
+ <div v-if="renamingTeamId !== t.teamId" class="team-history-meta">
832
897
  <span :class="['team-status-badge', 'team-status-badge-sm', 'team-status-' + t.status]">{{ t.status }}</span>
833
898
  <span v-if="t.taskCount" class="team-history-tasks">{{ t.taskCount }} tasks</span>
834
899
  <span v-if="t.totalCost" class="team-history-tasks">{{'$' + t.totalCost.toFixed(2) }}</span>
900
+ <span class="session-actions">
901
+ <button class="session-rename-btn" @click.stop="startTeamRename(t)" title="Rename team">
902
+ <svg viewBox="0 0 24 24" width="12" height="12"><path fill="currentColor" d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>
903
+ </button>
904
+ <button class="session-delete-btn" @click.stop="requestDeleteTeam(t)" title="Delete team">
905
+ <svg viewBox="0 0 24 24" width="12" height="12"><path fill="currentColor" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg>
906
+ </button>
907
+ </span>
835
908
  </div>
836
909
  </div>
837
910
  </div>
@@ -840,7 +913,7 @@ const App = {
840
913
 
841
914
  <div class="sidebar-section sidebar-sessions">
842
915
  <div class="sidebar-section-header">
843
- <span>History</span>
916
+ <span>Chat History</span>
844
917
  <button class="sidebar-refresh-btn" @click="requestSessionList" title="Refresh" :disabled="loadingSessions">
845
918
  <svg :class="{ spinning: loadingSessions }" viewBox="0 0 24 24" width="14" height="14"><path fill="currentColor" d="M17.65 6.35A7.958 7.958 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0 1 12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>
846
919
  </button>
@@ -1622,6 +1695,22 @@ const App = {
1622
1695
  </div>
1623
1696
  </div>
1624
1697
 
1698
+ <!-- Delete Team Confirmation Dialog -->
1699
+ <div class="folder-picker-overlay" v-if="deleteTeamConfirmOpen" @click.self="cancelDeleteTeam">
1700
+ <div class="delete-confirm-dialog">
1701
+ <div class="delete-confirm-header">Delete Team</div>
1702
+ <div class="delete-confirm-body">
1703
+ <p>Are you sure you want to delete this team?</p>
1704
+ <p class="delete-confirm-title">{{ deleteTeamConfirmTitle }}</p>
1705
+ <p class="delete-confirm-warning">This action cannot be undone.</p>
1706
+ </div>
1707
+ <div class="delete-confirm-footer">
1708
+ <button class="folder-picker-cancel" @click="cancelDeleteTeam">Cancel</button>
1709
+ <button class="delete-confirm-btn" @click="confirmDeleteTeam">Delete</button>
1710
+ </div>
1711
+ </div>
1712
+ </div>
1713
+
1625
1714
  <!-- Password Authentication Dialog -->
1626
1715
  <div class="folder-picker-overlay" v-if="authRequired && !authLocked">
1627
1716
  <div class="auth-dialog">
@@ -37,6 +37,10 @@ export function createSidebar(deps) {
37
37
  switchConversation,
38
38
  } = deps;
39
39
 
40
+ // Late-binding callback: called when user switches to a normal chat session
41
+ let _onSwitchToChat = null;
42
+ function setOnSwitchToChat(fn) { _onSwitchToChat = fn; }
43
+
40
44
  // ── Workdir switching timeout ──
41
45
  let _workdirSwitchTimer = null;
42
46
  function setWorkdirSwitching() {
@@ -69,6 +73,7 @@ export function createSidebar(deps) {
69
73
 
70
74
  function resumeSession(session) {
71
75
  if (window.innerWidth <= 768) sidebarOpen.value = false;
76
+ if (_onSwitchToChat) _onSwitchToChat();
72
77
 
73
78
  // Multi-session: check if we already have a conversation loaded for this claudeSessionId
74
79
  if (switchConversation && conversationCache) {
@@ -117,6 +122,7 @@ export function createSidebar(deps) {
117
122
 
118
123
  function newConversation() {
119
124
  if (window.innerWidth <= 768) sidebarOpen.value = false;
125
+ if (_onSwitchToChat) _onSwitchToChat();
120
126
 
121
127
  // Multi-session: just switch to a new blank conversation
122
128
  if (switchConversation) {
@@ -375,6 +381,7 @@ export function createSidebar(deps) {
375
381
 
376
382
  return {
377
383
  requestSessionList, resumeSession, newConversation, toggleSidebar,
384
+ setOnSwitchToChat,
378
385
  deleteSession, confirmDeleteSession, cancelDeleteSession,
379
386
  startRename, confirmRename, cancelRename,
380
387
  openFolderPicker, folderPickerNavigateUp, folderPickerSelectItem,
@@ -96,6 +96,14 @@ export function createTeam(deps) {
96
96
  wsSend({ type: 'list_teams' });
97
97
  }
98
98
 
99
+ function deleteTeamById(teamId) {
100
+ wsSend({ type: 'delete_team', teamId });
101
+ }
102
+
103
+ function renameTeamById(teamId, newTitle) {
104
+ wsSend({ type: 'rename_team', teamId, newTitle });
105
+ }
106
+
99
107
  function requestAgentHistory(teamId, agentId) {
100
108
  wsSend({ type: 'get_team_agent_history', teamId, agentId });
101
109
  }
@@ -220,6 +228,28 @@ export function createTeam(deps) {
220
228
  teamsList.value = msg.teams || [];
221
229
  return true;
222
230
 
231
+ case 'team_deleted':
232
+ teamsList.value = teamsList.value.filter(t => t.teamId !== msg.teamId);
233
+ // If viewing the deleted team, go back
234
+ if (historicalTeam.value && historicalTeam.value.teamId === msg.teamId) {
235
+ historicalTeam.value = null;
236
+ }
237
+ return true;
238
+
239
+ case 'team_renamed': {
240
+ const item = teamsList.value.find(t => t.teamId === msg.teamId);
241
+ if (item) item.title = msg.newTitle;
242
+ // Update historical view if showing this team
243
+ if (historicalTeam.value && historicalTeam.value.teamId === msg.teamId) {
244
+ historicalTeam.value.title = msg.newTitle;
245
+ }
246
+ // Update active team if it's the same
247
+ if (teamState.value && teamState.value.teamId === msg.teamId) {
248
+ teamState.value.title = msg.newTitle;
249
+ }
250
+ return true;
251
+ }
252
+
223
253
  case 'team_detail':
224
254
  historicalTeam.value = msg.team;
225
255
  teamMode.value = 'team';
@@ -334,7 +364,8 @@ export function createTeam(deps) {
334
364
  pendingTasks, activeTasks, doneTasks, failedTasks,
335
365
  // Methods
336
366
  launchTeam, dissolveTeam, viewAgent, viewDashboard,
337
- viewHistoricalTeam, requestTeamsList, requestAgentHistory,
367
+ viewHistoricalTeam, requestTeamsList, deleteTeamById, renameTeamById,
368
+ requestAgentHistory,
338
369
  getAgentColor, findAgent, getAgentMessages, backToChat, newTeam,
339
370
  // Message handling
340
371
  handleTeamMessage, handleTeamAgentOutput, handleActiveTeamRestore,
package/web/style.css CHANGED
@@ -566,6 +566,10 @@ body {
566
566
  visibility: visible;
567
567
  }
568
568
 
569
+ .team-history-item:hover .session-actions {
570
+ visibility: visible;
571
+ }
572
+
569
573
  .session-delete-btn {
570
574
  display: flex;
571
575
  align-items: center;