@agent-link/server 0.1.77 → 0.1.79

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.77",
3
+ "version": "0.1.79",
4
4
  "description": "AgentLink relay server",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/web/app.js CHANGED
@@ -68,6 +68,9 @@ const App = {
68
68
  const deleteConfirmOpen = ref(false);
69
69
  const deleteConfirmTitle = ref('');
70
70
 
71
+ // Working directory history
72
+ const workdirHistory = ref([]);
73
+
71
74
  // Authentication state
72
75
  const authRequired = ref(false);
73
76
  const authPassword = ref('');
@@ -148,6 +151,7 @@ const App = {
148
151
  folderPickerOpen, folderPickerPath, folderPickerEntries,
149
152
  folderPickerLoading, folderPickerSelected, streaming,
150
153
  deleteConfirmOpen, deleteConfirmTitle,
154
+ hostname, workdirHistory,
151
155
  });
152
156
 
153
157
  const { connect, wsSend, closeWs, submitPassword } = createConnection({
@@ -286,6 +290,10 @@ const App = {
286
290
  deleteSession: sidebar.deleteSession,
287
291
  confirmDeleteSession: sidebar.confirmDeleteSession,
288
292
  cancelDeleteSession: sidebar.cancelDeleteSession,
293
+ // Working directory history
294
+ filteredWorkdirHistory: sidebar.filteredWorkdirHistory,
295
+ switchToWorkdir: sidebar.switchToWorkdir,
296
+ removeFromWorkdirHistory: sidebar.removeFromWorkdirHistory,
289
297
  // Authentication
290
298
  authRequired, authPassword, authError, authAttempts, authLocked,
291
299
  submitPassword,
@@ -351,6 +359,22 @@ const App = {
351
359
  </button>
352
360
  </div>
353
361
  <div class="sidebar-workdir-path" :title="workDir">{{ workDir }}</div>
362
+ <div v-if="filteredWorkdirHistory.length > 0" class="workdir-history">
363
+ <div class="workdir-history-label">Recent Directories</div>
364
+ <div class="workdir-history-list">
365
+ <div
366
+ v-for="path in filteredWorkdirHistory" :key="path"
367
+ class="workdir-history-item"
368
+ @click="switchToWorkdir(path)"
369
+ :title="path"
370
+ >
371
+ <span class="workdir-history-path">{{ path }}</span>
372
+ <button class="workdir-history-delete" @click.stop="removeFromWorkdirHistory(path)" title="Remove from history">
373
+ <svg viewBox="0 0 24 24" width="12" height="12"><path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
374
+ </button>
375
+ </div>
376
+ </div>
377
+ </div>
354
378
  </div>
355
379
  </div>
356
380
 
@@ -185,6 +185,8 @@ export function createConnection(deps) {
185
185
  hostname.value = msg.agent.hostname || '';
186
186
  workDir.value = msg.agent.workDir;
187
187
  agentVersion.value = msg.agent.version || '';
188
+ sidebar.loadWorkdirHistory();
189
+ sidebar.addToWorkdirHistory(msg.agent.workDir);
188
190
  const savedDir = localStorage.getItem(`agentlink-workdir-${sessionId.value}`);
189
191
  if (savedDir && savedDir !== msg.agent.workDir) {
190
192
  wsSend({ type: 'change_workdir', workDir: savedDir });
@@ -210,6 +212,7 @@ export function createConnection(deps) {
210
212
  workDir.value = msg.agent.workDir;
211
213
  agentVersion.value = msg.agent.version || '';
212
214
  workDir.value = msg.agent.workDir;
215
+ sidebar.addToWorkdirHistory(msg.agent.workDir);
213
216
  }
214
217
  sidebar.requestSessionList();
215
218
  } else if (msg.type === 'error') {
@@ -381,6 +384,7 @@ export function createConnection(deps) {
381
384
  } else if (msg.type === 'workdir_changed') {
382
385
  workDir.value = msg.workDir;
383
386
  localStorage.setItem(`agentlink-workdir-${sessionId.value}`, msg.workDir);
387
+ sidebar.addToWorkdirHistory(msg.workDir);
384
388
  messages.value = [];
385
389
  toolMsgMap.clear();
386
390
  visibleLimit.value = 50;
@@ -21,6 +21,8 @@ const { computed } = Vue;
21
21
  * @param {import('vue').Ref} deps.folderPickerLoading
22
22
  * @param {import('vue').Ref} deps.folderPickerSelected
23
23
  * @param {object} deps.streaming - streaming controller
24
+ * @param {import('vue').Ref} deps.hostname
25
+ * @param {import('vue').Ref} deps.workdirHistory
24
26
  */
25
27
  export function createSidebar(deps) {
26
28
  const {
@@ -29,6 +31,7 @@ export function createSidebar(deps) {
29
31
  loadingSessions, loadingHistory, workDir, visibleLimit,
30
32
  folderPickerOpen, folderPickerPath, folderPickerEntries,
31
33
  folderPickerLoading, folderPickerSelected, streaming,
34
+ hostname, workdirHistory,
32
35
  } = deps;
33
36
 
34
37
  // ── Session management ──
@@ -181,6 +184,49 @@ export function createSidebar(deps) {
181
184
  wsSend({ type: 'change_workdir', workDir: path });
182
185
  }
183
186
 
187
+ // ── Working directory history ──
188
+
189
+ const WORKDIR_HISTORY_MAX = 10;
190
+
191
+ function getWorkdirHistoryKey() {
192
+ return `agentlink-workdir-history-${hostname.value}`;
193
+ }
194
+
195
+ function loadWorkdirHistory() {
196
+ try {
197
+ const stored = localStorage.getItem(getWorkdirHistoryKey());
198
+ workdirHistory.value = stored ? JSON.parse(stored) : [];
199
+ } catch {
200
+ workdirHistory.value = [];
201
+ }
202
+ }
203
+
204
+ function saveWorkdirHistory() {
205
+ localStorage.setItem(getWorkdirHistoryKey(), JSON.stringify(workdirHistory.value));
206
+ }
207
+
208
+ function addToWorkdirHistory(path) {
209
+ if (!path) return;
210
+ const filtered = workdirHistory.value.filter(p => p !== path);
211
+ filtered.unshift(path);
212
+ workdirHistory.value = filtered.slice(0, WORKDIR_HISTORY_MAX);
213
+ saveWorkdirHistory();
214
+ }
215
+
216
+ function removeFromWorkdirHistory(path) {
217
+ workdirHistory.value = workdirHistory.value.filter(p => p !== path);
218
+ saveWorkdirHistory();
219
+ }
220
+
221
+ function switchToWorkdir(path) {
222
+ if (isProcessing.value) return;
223
+ wsSend({ type: 'change_workdir', workDir: path });
224
+ }
225
+
226
+ const filteredWorkdirHistory = computed(() => {
227
+ return workdirHistory.value.filter(p => p !== workDir.value);
228
+ });
229
+
184
230
  // ── Grouped sessions ──
185
231
 
186
232
  const groupedSessions = computed(() => {
@@ -210,5 +256,7 @@ export function createSidebar(deps) {
210
256
  openFolderPicker, folderPickerNavigateUp, folderPickerSelectItem,
211
257
  folderPickerEnter, folderPickerGoToPath, confirmFolderPicker,
212
258
  groupedSessions,
259
+ loadWorkdirHistory, addToWorkdirHistory, removeFromWorkdirHistory,
260
+ switchToWorkdir, filteredWorkdirHistory,
213
261
  };
214
262
  }
package/web/style.css CHANGED
@@ -58,16 +58,15 @@ body {
58
58
  }
59
59
 
60
60
  #app {
61
- height: 100vh;
62
- height: 100dvh;
61
+ position: fixed;
62
+ inset: 0;
63
63
  }
64
64
 
65
65
  /* ── Layout ── */
66
66
  .layout {
67
67
  display: flex;
68
68
  flex-direction: column;
69
- height: 100vh;
70
- height: 100dvh;
69
+ height: 100%;
71
70
  }
72
71
 
73
72
  .top-bar {
@@ -283,6 +282,73 @@ body {
283
282
  line-height: 1.3;
284
283
  }
285
284
 
285
+ /* ── Working Directory History ── */
286
+ .workdir-history {
287
+ margin-top: 10px;
288
+ padding-top: 10px;
289
+ border-top: 1px solid var(--border);
290
+ }
291
+ .workdir-history-label {
292
+ font-size: 0.65rem;
293
+ text-transform: uppercase;
294
+ letter-spacing: 0.05em;
295
+ color: var(--text-secondary);
296
+ margin-bottom: 6px;
297
+ opacity: 0.7;
298
+ }
299
+ .workdir-history-list {
300
+ display: flex;
301
+ flex-direction: column;
302
+ gap: 2px;
303
+ }
304
+ .workdir-history-item {
305
+ display: flex;
306
+ align-items: center;
307
+ gap: 6px;
308
+ padding: 4px 6px;
309
+ border-radius: 4px;
310
+ cursor: pointer;
311
+ transition: background 0.15s;
312
+ }
313
+ .workdir-history-item:hover {
314
+ background: var(--bg-tertiary);
315
+ }
316
+ .workdir-history-path {
317
+ font-size: 0.72rem;
318
+ color: var(--text-secondary);
319
+ font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
320
+ overflow: hidden;
321
+ text-overflow: ellipsis;
322
+ white-space: nowrap;
323
+ flex: 1;
324
+ min-width: 0;
325
+ }
326
+ .workdir-history-item:hover .workdir-history-path {
327
+ color: var(--text-primary);
328
+ }
329
+ .workdir-history-delete {
330
+ display: none;
331
+ align-items: center;
332
+ justify-content: center;
333
+ width: 18px;
334
+ height: 18px;
335
+ background: none;
336
+ border: none;
337
+ border-radius: 3px;
338
+ color: var(--text-secondary);
339
+ cursor: pointer;
340
+ padding: 0;
341
+ flex-shrink: 0;
342
+ transition: color 0.15s, background 0.15s;
343
+ }
344
+ .workdir-history-item:hover .workdir-history-delete {
345
+ display: flex;
346
+ }
347
+ .workdir-history-delete:hover {
348
+ color: var(--error);
349
+ background: rgba(239, 68, 68, 0.1);
350
+ }
351
+
286
352
  .sidebar-sessions {
287
353
  flex: 1;
288
354
  display: flex;