@agent-link/server 0.1.162 → 0.1.164

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.
@@ -0,0 +1,306 @@
1
+ /* ── Tool use lines (collapsible, compact, subdued) ── */
2
+ .tool-line-wrapper {
3
+ max-width: 100%;
4
+ padding-left: 0.25rem;
5
+ overflow: hidden;
6
+ }
7
+
8
+ .tool-line {
9
+ display: flex;
10
+ align-items: center;
11
+ gap: 6px;
12
+ padding: 3px 6px;
13
+ border-radius: 4px;
14
+ font-size: 0.8rem;
15
+ cursor: pointer;
16
+ user-select: none;
17
+ transition: background 0.15s;
18
+ color: var(--text-secondary);
19
+ min-width: 0;
20
+ overflow: hidden;
21
+ }
22
+
23
+ .tool-line:hover {
24
+ background: var(--bg-tertiary);
25
+ }
26
+
27
+ .tool-icon {
28
+ flex-shrink: 0;
29
+ display: flex;
30
+ align-items: center;
31
+ color: var(--text-secondary);
32
+ opacity: 0.6;
33
+ }
34
+
35
+ .tool-name {
36
+ font-weight: 500;
37
+ color: var(--text-secondary);
38
+ overflow: hidden;
39
+ text-overflow: ellipsis;
40
+ white-space: nowrap;
41
+ min-width: 0;
42
+ }
43
+
44
+ .tool-summary {
45
+ color: var(--text-secondary);
46
+ overflow: hidden;
47
+ text-overflow: ellipsis;
48
+ white-space: nowrap;
49
+ flex: 1;
50
+ min-width: 0;
51
+ }
52
+
53
+ .tool-status-icon {
54
+ color: var(--text-secondary);
55
+ font-weight: normal;
56
+ flex-shrink: 0;
57
+ font-size: 0.75rem;
58
+ opacity: 0.7;
59
+ }
60
+
61
+ .tool-line.completed .tool-status-icon {
62
+ color: var(--success);
63
+ opacity: 0.6;
64
+ }
65
+
66
+ .running-dots {
67
+ display: inline-flex;
68
+ gap: 2px;
69
+ }
70
+
71
+ .running-dots span {
72
+ width: 3px;
73
+ height: 3px;
74
+ border-radius: 50%;
75
+ background: var(--text-secondary);
76
+ animation: typing 1.2s infinite ease-in-out;
77
+ }
78
+
79
+ .running-dots span:nth-child(2) { animation-delay: 0.2s; }
80
+ .running-dots span:nth-child(3) { animation-delay: 0.4s; }
81
+
82
+ .tool-toggle {
83
+ color: var(--text-secondary);
84
+ font-size: 0.6rem;
85
+ flex-shrink: 0;
86
+ margin-left: auto;
87
+ opacity: 0.5;
88
+ }
89
+
90
+ .tool-expand {
91
+ margin-top: 2px;
92
+ margin-left: 20px;
93
+ border-left: 1px solid var(--border);
94
+ padding-left: 8px;
95
+ overflow: hidden;
96
+ animation: toolExpand 0.15s ease-out;
97
+ }
98
+
99
+ @keyframes toolExpand {
100
+ from { opacity: 0; max-height: 0; }
101
+ to { opacity: 1; max-height: 500px; }
102
+ }
103
+
104
+ .tool-block {
105
+ background: var(--bg-secondary);
106
+ border-radius: 4px;
107
+ padding: 0.4rem 0.6rem;
108
+ margin-top: 0.25rem;
109
+ overflow-x: auto;
110
+ font-size: 0.75rem;
111
+ line-height: 1.4;
112
+ max-height: 200px;
113
+ overflow-y: auto;
114
+ white-space: pre-wrap;
115
+ word-break: break-all;
116
+ color: var(--text-secondary);
117
+ }
118
+
119
+ .tool-output {
120
+ border-left: 2px solid var(--success);
121
+ color: var(--text-primary);
122
+ }
123
+
124
+ /* ── Formatted tool input (Read, Write, Bash, Glob, Grep) ── */
125
+ .tool-input-formatted {
126
+ padding: 0.3rem 0.5rem;
127
+ margin-top: 0.25rem;
128
+ font-size: 0.75rem;
129
+ line-height: 1.5;
130
+ color: var(--text-secondary);
131
+ word-break: break-all;
132
+ }
133
+
134
+ .tool-input-meta {
135
+ color: var(--text-secondary);
136
+ opacity: 0.6;
137
+ }
138
+
139
+ .tool-input-cmd {
140
+ background: var(--bg-secondary);
141
+ padding: 0.1rem 0.4rem;
142
+ border-radius: 3px;
143
+ font-size: 0.73rem;
144
+ word-break: break-all;
145
+ white-space: pre-wrap;
146
+ }
147
+
148
+ /* ── TodoWrite checklist ── */
149
+ .todo-list {
150
+ display: flex;
151
+ flex-direction: column;
152
+ gap: 2px;
153
+ }
154
+
155
+ .todo-item {
156
+ display: flex;
157
+ align-items: baseline;
158
+ gap: 6px;
159
+ font-size: 0.75rem;
160
+ line-height: 1.4;
161
+ color: var(--text-secondary);
162
+ }
163
+
164
+ .todo-item.todo-done {
165
+ opacity: 0.55;
166
+ }
167
+
168
+ .todo-item.todo-active {
169
+ color: var(--text-primary);
170
+ }
171
+
172
+ .todo-icon {
173
+ flex-shrink: 0;
174
+ width: 1em;
175
+ text-align: center;
176
+ font-size: 0.7rem;
177
+ opacity: 0.5;
178
+ }
179
+
180
+ .todo-icon.done {
181
+ color: var(--success);
182
+ opacity: 0.8;
183
+ }
184
+
185
+ .todo-icon.active {
186
+ color: var(--accent);
187
+ opacity: 1;
188
+ font-size: 0.55rem;
189
+ }
190
+
191
+ .todo-text {
192
+ word-break: break-word;
193
+ }
194
+
195
+ /* ── Task / WebFetch formatted fields ── */
196
+ .task-field {
197
+ font-size: 0.75rem;
198
+ line-height: 1.5;
199
+ color: var(--text-secondary);
200
+ }
201
+
202
+ .task-field + .task-field {
203
+ margin-top: 2px;
204
+ }
205
+
206
+ .task-prompt {
207
+ background: var(--bg-secondary);
208
+ border-radius: 3px;
209
+ padding: 0.3rem 0.5rem;
210
+ margin-top: 3px;
211
+ font-size: 0.73rem;
212
+ line-height: 1.4;
213
+ color: var(--text-secondary);
214
+ white-space: pre-wrap;
215
+ word-break: break-word;
216
+ max-height: 150px;
217
+ overflow-y: auto;
218
+ }
219
+
220
+ .tool-link {
221
+ color: var(--accent);
222
+ font-size: 0.75rem;
223
+ word-break: break-all;
224
+ text-decoration: none;
225
+ }
226
+
227
+ .tool-link:hover {
228
+ text-decoration: underline;
229
+ }
230
+
231
+ [data-theme="light"] .todo-icon.active {
232
+ color: #0969da;
233
+ }
234
+
235
+ [data-theme="light"] .tool-link {
236
+ color: #0969da;
237
+ }
238
+
239
+ /* ── Edit tool diff view ── */
240
+ .tool-diff {
241
+ background: var(--bg-secondary);
242
+ border-radius: 4px;
243
+ padding: 0.4rem 0.6rem;
244
+ margin-top: 0.25rem;
245
+ overflow-x: auto;
246
+ font-size: 0.75rem;
247
+ line-height: 1.5;
248
+ max-height: 300px;
249
+ overflow-y: auto;
250
+ font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', monospace;
251
+ }
252
+
253
+ .diff-file {
254
+ color: var(--text-secondary);
255
+ margin-bottom: 0.35rem;
256
+ font-weight: 500;
257
+ }
258
+
259
+ .diff-replace-all {
260
+ opacity: 0.6;
261
+ font-weight: 400;
262
+ }
263
+
264
+ .diff-lines {
265
+ border-radius: 3px;
266
+ overflow: hidden;
267
+ }
268
+
269
+ .diff-removed, .diff-added {
270
+ white-space: pre-wrap;
271
+ word-break: break-all;
272
+ padding: 0 0.4rem;
273
+ }
274
+
275
+ .diff-removed {
276
+ background: rgba(212, 84, 84, 0.12);
277
+ color: #d4716b;
278
+ }
279
+
280
+ .diff-added {
281
+ background: rgba(78, 173, 106, 0.12);
282
+ color: #5cb87a;
283
+ }
284
+
285
+ .diff-sign {
286
+ display: inline-block;
287
+ width: 1.2em;
288
+ user-select: none;
289
+ opacity: 0.7;
290
+ }
291
+
292
+ [data-theme="light"] .diff-removed {
293
+ background: rgba(208, 46, 38, 0.12);
294
+ color: #b31d28;
295
+ }
296
+
297
+ [data-theme="light"] .diff-added {
298
+ background: rgba(34, 134, 58, 0.12);
299
+ color: #22863a;
300
+ }
301
+
302
+ /* ── Context summary (collapsible continuation notice) ── */
303
+ .context-summary-wrapper {
304
+ margin: 0.75rem 0;
305
+ }
306
+
package/web/index.html CHANGED
@@ -5,7 +5,17 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content">
6
6
  <title>AgentLink</title>
7
7
  <link rel="icon" type="image/svg+xml" href="/favicon.svg">
8
- <link rel="stylesheet" href="/style.css">
8
+ <link rel="stylesheet" href="/css/base.css">
9
+ <link rel="stylesheet" href="/css/sidebar.css">
10
+ <link rel="stylesheet" href="/css/chat.css">
11
+ <link rel="stylesheet" href="/css/markdown.css">
12
+ <link rel="stylesheet" href="/css/tools.css">
13
+ <link rel="stylesheet" href="/css/ask-question.css">
14
+ <link rel="stylesheet" href="/css/input.css">
15
+ <link rel="stylesheet" href="/css/file-browser.css">
16
+ <link rel="stylesheet" href="/css/team.css">
17
+ <link rel="stylesheet" href="/css/responsive.css">
18
+ <link rel="stylesheet" href="/css/loop.css">
9
19
  <link id="hljs-theme" rel="stylesheet" href="/vendor/github.min.css">
10
20
  <script>
11
21
  // Apply saved theme immediately to prevent flash
@@ -246,5 +246,22 @@
246
246
  "tool.replaceAll": "(replace all)",
247
247
 
248
248
  "usage.context": "Context",
249
- "usage.cost": "Cost"
249
+ "usage.cost": "Cost",
250
+
251
+ "sidebar.memory": "Memory",
252
+ "memory.title": "Memory Files",
253
+ "memory.loading": "Loading memory files...",
254
+ "memory.noFiles": "No memory files found.",
255
+ "memory.noFilesHint": "Claude will create memory files as you work.",
256
+ "memory.edit": "Edit",
257
+ "memory.editing": "Editing",
258
+ "memory.save": "Save",
259
+ "memory.saving": "Saving...",
260
+ "memory.deleteFile": "Delete",
261
+ "memory.deleteConfirm": "Delete {name}?",
262
+ "memory.discardChanges": "Discard changes?",
263
+
264
+ "slash.cost": "Show token usage and cost",
265
+ "slash.context": "Show context usage",
266
+ "slash.compact": "Compact context"
250
267
  }
@@ -246,5 +246,22 @@
246
246
  "tool.replaceAll": "(全部替换)",
247
247
 
248
248
  "usage.context": "上下文",
249
- "usage.cost": "费用"
249
+ "usage.cost": "费用",
250
+
251
+ "sidebar.memory": "记忆",
252
+ "memory.title": "记忆文件",
253
+ "memory.loading": "加载记忆文件...",
254
+ "memory.noFiles": "未找到记忆文件。",
255
+ "memory.noFilesHint": "Claude 会在工作过程中自动创建记忆文件。",
256
+ "memory.edit": "编辑",
257
+ "memory.editing": "编辑中",
258
+ "memory.save": "保存",
259
+ "memory.saving": "保存中...",
260
+ "memory.deleteFile": "删除",
261
+ "memory.deleteConfirm": "删除 {name}?",
262
+ "memory.discardChanges": "放弃更改?",
263
+
264
+ "slash.cost": "显示 Token 用量和费用",
265
+ "slash.context": "显示上下文用量",
266
+ "slash.compact": "压缩上下文"
250
267
  }
@@ -25,6 +25,8 @@ export function createConnection(deps) {
25
25
  // Multi-session parallel
26
26
  currentConversationId, processingConversations, conversationCache,
27
27
  switchConversation,
28
+ // Memory management
29
+ memoryFiles, memoryDir, memoryLoading, memoryEditing, memoryEditContent, memorySaving, memoryPanelOpen,
28
30
  // i18n
29
31
  t,
30
32
  } = deps;
@@ -539,6 +541,25 @@ export function createConnection(deps) {
539
541
  }
540
542
  } else if (msg.type === 'file_content') {
541
543
  if (filePreview) filePreview.handleFileContent(msg);
544
+ } else if (msg.type === 'memory_list') {
545
+ memoryLoading.value = false;
546
+ memoryFiles.value = msg.files || [];
547
+ memoryDir.value = msg.memoryDir || null;
548
+ } else if (msg.type === 'memory_updated') {
549
+ memorySaving.value = false;
550
+ if (msg.success) {
551
+ memoryEditing.value = false;
552
+ memoryEditContent.value = '';
553
+ // Refresh list and preview
554
+ wsSend({ type: 'list_memory' });
555
+ if (filePreview) filePreview.refreshPreview();
556
+ }
557
+ } else if (msg.type === 'memory_deleted') {
558
+ if (msg.success) {
559
+ memoryFiles.value = memoryFiles.value.filter(f => f.name !== msg.filename);
560
+ // Close preview if open (might be showing the deleted file)
561
+ if (filePreview) filePreview.closePreview();
562
+ }
542
563
  } else if (msg.type === 'workdir_changed') {
543
564
  workdirSwitching.value = false;
544
565
  workDir.value = msg.workDir;
@@ -573,6 +594,10 @@ export function createConnection(deps) {
573
594
  historySessions.value = [];
574
595
  if (team) team.teamsList.value = [];
575
596
  if (loop) loop.loopsList.value = [];
597
+ memoryFiles.value = [];
598
+ memoryDir.value = null;
599
+ memoryPanelOpen.value = false;
600
+ memoryEditing.value = false;
576
601
  sidebar.requestSessionList();
577
602
  if (team) team.requestTeamsList();
578
603
  if (loop) loop.requestLoopsList();
@@ -188,9 +188,19 @@ export function createFilePreview(deps) {
188
188
  return renderMarkdown(content || '');
189
189
  }
190
190
 
191
+ /** Force re-fetch the currently open preview file (e.g. after editing) */
192
+ function refreshPreview() {
193
+ if (!previewFile.value?.filePath) return;
194
+ const filePath = previewFile.value.filePath;
195
+ previewFile.value = null;
196
+ previewLoading.value = true;
197
+ wsSend({ type: 'read_file', filePath });
198
+ }
199
+
191
200
  return {
192
201
  openPreview,
193
202
  closePreview,
203
+ refreshPreview,
194
204
  handleFileContent,
195
205
  onWorkdirChanged,
196
206
  detectLanguage,