@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 +1 -1
- package/web/app.js +24 -0
- package/web/modules/connection.js +4 -0
- package/web/modules/sidebar.js +48 -0
- package/web/style.css +70 -4
package/package.json
CHANGED
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;
|
package/web/modules/sidebar.js
CHANGED
|
@@ -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
|
-
|
|
62
|
-
|
|
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:
|
|
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;
|