daedalus-cli 3.73.0 → 3.75.0
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/CHANGELOG.md +19 -0
- package/dist/formatting.d.ts +1 -1
- package/dist/formatting.d.ts.map +1 -1
- package/dist/formatting.js +6 -2
- package/dist/formatting.js.map +1 -1
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +5 -1
- package/dist/repl.js.map +1 -1
- package/dist/webui/public/script.js +243 -78
- package/dist/webui/public/styles.css +285 -48
- package/dist/webui/server.d.ts.map +1 -1
- package/dist/webui/server.js +7 -0
- package/dist/webui/server.js.map +1 -1
- package/dist/webui/types.d.ts +3 -0
- package/dist/webui/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -106,8 +106,84 @@ function renderMarkdown(text) {
|
|
|
106
106
|
return tempDiv.innerHTML;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
function
|
|
110
|
-
if (!
|
|
109
|
+
function attachCliFooter(msgEl, modelName, toolCount, durationMs, tokenCount) {
|
|
110
|
+
if (!msgEl) return;
|
|
111
|
+
if (msgEl.querySelector('.msg-cli-footer')) return;
|
|
112
|
+
|
|
113
|
+
const footer = document.createElement('div');
|
|
114
|
+
footer.className = 'msg-cli-footer';
|
|
115
|
+
|
|
116
|
+
const left = document.createElement('div');
|
|
117
|
+
left.className = 'msg-cli-footer-left';
|
|
118
|
+
|
|
119
|
+
const intel = document.createElement('span');
|
|
120
|
+
intel.className = 'cli-pill cli-pill-intel';
|
|
121
|
+
intel.innerHTML = '<span class="cli-dot">●</span> intelligence';
|
|
122
|
+
left.appendChild(intel);
|
|
123
|
+
|
|
124
|
+
const divider1 = document.createElement('span');
|
|
125
|
+
divider1.className = 'msg-cli-footer-divider';
|
|
126
|
+
divider1.textContent = '·';
|
|
127
|
+
left.appendChild(divider1);
|
|
128
|
+
|
|
129
|
+
const modelPill = document.createElement('span');
|
|
130
|
+
modelPill.className = 'cli-pill cli-pill-model';
|
|
131
|
+
modelPill.textContent = modelName || 'auto';
|
|
132
|
+
left.appendChild(modelPill);
|
|
133
|
+
|
|
134
|
+
if (toolCount && toolCount > 0) {
|
|
135
|
+
const dividerTools = document.createElement('span');
|
|
136
|
+
dividerTools.className = 'msg-cli-footer-divider';
|
|
137
|
+
dividerTools.textContent = '·';
|
|
138
|
+
left.appendChild(dividerTools);
|
|
139
|
+
|
|
140
|
+
const toolsPill = document.createElement('span');
|
|
141
|
+
toolsPill.className = 'cli-pill cli-pill-tools';
|
|
142
|
+
toolsPill.textContent = `${toolCount} tool(s)`;
|
|
143
|
+
left.appendChild(toolsPill);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const durationSec = durationMs ? (durationMs / 1000).toFixed(1) : null;
|
|
147
|
+
if (durationSec) {
|
|
148
|
+
const dividerTime = document.createElement('span');
|
|
149
|
+
dividerTime.className = 'msg-cli-footer-divider';
|
|
150
|
+
dividerTime.textContent = '·';
|
|
151
|
+
left.appendChild(dividerTime);
|
|
152
|
+
|
|
153
|
+
const timePill = document.createElement('span');
|
|
154
|
+
timePill.className = 'cli-pill cli-pill-time';
|
|
155
|
+
timePill.textContent = `${durationSec}s`;
|
|
156
|
+
left.appendChild(timePill);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (tokenCount && tokenCount > 0 && durationMs && durationMs > 0) {
|
|
160
|
+
const tokPerSec = (tokenCount / (durationMs / 1000)).toFixed(1);
|
|
161
|
+
const dividerSpeed = document.createElement('span');
|
|
162
|
+
dividerSpeed.className = 'msg-cli-footer-divider';
|
|
163
|
+
dividerSpeed.textContent = '·';
|
|
164
|
+
left.appendChild(dividerSpeed);
|
|
165
|
+
|
|
166
|
+
const speedPill = document.createElement('span');
|
|
167
|
+
speedPill.className = 'cli-pill cli-pill-speed';
|
|
168
|
+
speedPill.textContent = `${tokPerSec} tok/s`;
|
|
169
|
+
left.appendChild(speedPill);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
footer.appendChild(left);
|
|
173
|
+
msgEl.appendChild(footer);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let userProfileName = 'YOU';
|
|
177
|
+
let activeAssistantBody = null;
|
|
178
|
+
let activeAssistantMsgEl = null;
|
|
179
|
+
let thinkingEl = null;
|
|
180
|
+
let currentToolTreeEl = null;
|
|
181
|
+
let currentTurnExecutedTools = [];
|
|
182
|
+
let currentTurnTokenCount = 0;
|
|
183
|
+
let turnStartTime = null;
|
|
184
|
+
|
|
185
|
+
function addChatMessage(role, text, roleBadge = null, imageBase64 = null, timestamp = null, meta = null) {
|
|
186
|
+
if (!chatMessages) return null;
|
|
111
187
|
const msgEl = document.createElement('div');
|
|
112
188
|
msgEl.className = `chat-msg ${role}`;
|
|
113
189
|
|
|
@@ -116,7 +192,7 @@ function addChatMessage(role, text, roleBadge = null, imageBase64 = null, timest
|
|
|
116
192
|
|
|
117
193
|
const sender = document.createElement('span');
|
|
118
194
|
sender.className = 'sender';
|
|
119
|
-
sender.textContent = role === 'user' ?
|
|
195
|
+
sender.textContent = role === 'user' ? userProfileName : 'DAEDALUS';
|
|
120
196
|
header.appendChild(sender);
|
|
121
197
|
|
|
122
198
|
if (roleBadge) {
|
|
@@ -174,93 +250,143 @@ function addChatMessage(role, text, roleBadge = null, imageBase64 = null, timest
|
|
|
174
250
|
|
|
175
251
|
msgEl.appendChild(header);
|
|
176
252
|
msgEl.appendChild(body);
|
|
253
|
+
|
|
254
|
+
if (role === 'assistant' && meta) {
|
|
255
|
+
attachCliFooter(msgEl, meta.model, meta.toolCount, meta.durationMs, meta.tokenCount);
|
|
256
|
+
}
|
|
257
|
+
|
|
177
258
|
chatMessages.appendChild(msgEl);
|
|
178
259
|
chatMessages.scrollTop = chatMessages.scrollHeight;
|
|
260
|
+
|
|
261
|
+
if (role === 'assistant') {
|
|
262
|
+
activeAssistantMsgEl = msgEl;
|
|
263
|
+
}
|
|
179
264
|
return body;
|
|
180
265
|
}
|
|
181
266
|
|
|
182
|
-
let activeAssistantBody = null;
|
|
183
|
-
let thinkingEl = null;
|
|
184
|
-
let currentRunningToolEl = null;
|
|
185
|
-
|
|
186
267
|
function renderToolStart(toolName) {
|
|
187
268
|
if (!chatMessages) return null;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
269
|
+
|
|
270
|
+
if (!currentTurnExecutedTools.includes(toolName)) {
|
|
271
|
+
currentTurnExecutedTools.push(toolName);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (!currentToolTreeEl) {
|
|
275
|
+
const tree = document.createElement('div');
|
|
276
|
+
tree.className = 'tool-execution-tree running';
|
|
277
|
+
|
|
278
|
+
const header = document.createElement('div');
|
|
279
|
+
header.className = 'tool-tree-header';
|
|
280
|
+
|
|
281
|
+
const left = document.createElement('div');
|
|
282
|
+
left.className = 'tool-tree-left';
|
|
283
|
+
|
|
284
|
+
const rail = document.createElement('span');
|
|
285
|
+
rail.className = 'tool-tree-rail';
|
|
286
|
+
rail.textContent = '┊';
|
|
287
|
+
|
|
288
|
+
const icon = document.createElement('span');
|
|
289
|
+
icon.className = 'tool-tree-icon';
|
|
290
|
+
icon.textContent = '⚡';
|
|
291
|
+
|
|
292
|
+
const label = document.createElement('span');
|
|
293
|
+
label.className = 'tool-tree-label';
|
|
294
|
+
label.textContent = `Running: ${toolName}...`;
|
|
295
|
+
|
|
296
|
+
left.appendChild(rail);
|
|
297
|
+
left.appendChild(icon);
|
|
298
|
+
left.appendChild(label);
|
|
299
|
+
|
|
300
|
+
const right = document.createElement('div');
|
|
301
|
+
right.className = 'tool-tree-right';
|
|
302
|
+
|
|
303
|
+
const badge = document.createElement('span');
|
|
304
|
+
badge.className = 'tool-tree-badge running';
|
|
305
|
+
badge.textContent = 'RUNNING';
|
|
306
|
+
|
|
307
|
+
const count = document.createElement('span');
|
|
308
|
+
count.className = 'tool-tree-count';
|
|
309
|
+
count.textContent = '1 tool';
|
|
310
|
+
|
|
311
|
+
const chevron = document.createElement('span');
|
|
312
|
+
chevron.className = 'tool-tree-chevron';
|
|
313
|
+
chevron.textContent = '▶';
|
|
314
|
+
|
|
315
|
+
right.appendChild(badge);
|
|
316
|
+
right.appendChild(count);
|
|
317
|
+
right.appendChild(chevron);
|
|
318
|
+
|
|
319
|
+
header.appendChild(left);
|
|
320
|
+
header.appendChild(right);
|
|
321
|
+
|
|
322
|
+
const details = document.createElement('div');
|
|
323
|
+
details.className = 'tool-tree-details hidden';
|
|
324
|
+
|
|
325
|
+
header.addEventListener('click', () => {
|
|
326
|
+
tree.classList.toggle('open');
|
|
327
|
+
details.classList.toggle('hidden');
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
tree.appendChild(header);
|
|
331
|
+
tree.appendChild(details);
|
|
332
|
+
chatMessages.appendChild(tree);
|
|
333
|
+
chatMessages.scrollTop = chatMessages.scrollHeight;
|
|
334
|
+
|
|
335
|
+
currentToolTreeEl = tree;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const label = currentToolTreeEl.querySelector('.tool-tree-label');
|
|
339
|
+
if (label) label.textContent = `Running: ${toolName}...`;
|
|
340
|
+
|
|
341
|
+
const count = currentToolTreeEl.querySelector('.tool-tree-count');
|
|
342
|
+
if (count) count.textContent = `${currentTurnExecutedTools.length} tool(s)`;
|
|
343
|
+
|
|
344
|
+
return currentToolTreeEl;
|
|
241
345
|
}
|
|
242
346
|
|
|
243
347
|
function renderToolResult(toolName, resultSummary) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
accordion = renderToolStart(toolName);
|
|
348
|
+
if (!currentToolTreeEl) {
|
|
349
|
+
renderToolStart(toolName);
|
|
247
350
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
351
|
+
|
|
352
|
+
if (currentToolTreeEl) {
|
|
353
|
+
const details = currentToolTreeEl.querySelector('.tool-tree-details');
|
|
354
|
+
if (details) {
|
|
355
|
+
const item = document.createElement('div');
|
|
356
|
+
item.className = 'tool-tree-item';
|
|
357
|
+
|
|
358
|
+
const rail = document.createElement('span');
|
|
359
|
+
rail.className = 'tool-tree-item-rail';
|
|
360
|
+
rail.textContent = '┊ └─';
|
|
361
|
+
|
|
362
|
+
const name = document.createElement('span');
|
|
363
|
+
name.className = 'tool-tree-item-name';
|
|
364
|
+
name.textContent = toolName;
|
|
365
|
+
|
|
366
|
+
const summary = document.createElement('span');
|
|
367
|
+
summary.className = 'tool-tree-item-summary';
|
|
368
|
+
summary.textContent = resultSummary ? `(${resultSummary})` : '✔ completed';
|
|
369
|
+
|
|
370
|
+
item.appendChild(rail);
|
|
371
|
+
item.appendChild(name);
|
|
372
|
+
item.appendChild(summary);
|
|
373
|
+
details.appendChild(item);
|
|
256
374
|
}
|
|
257
|
-
|
|
258
|
-
const
|
|
259
|
-
if (
|
|
260
|
-
|
|
375
|
+
|
|
376
|
+
const label = currentToolTreeEl.querySelector('.tool-tree-label');
|
|
377
|
+
if (label) {
|
|
378
|
+
label.textContent = `Executed tools: ${currentTurnExecutedTools.join(', ')}`;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const badge = currentToolTreeEl.querySelector('.tool-tree-badge');
|
|
382
|
+
if (badge) {
|
|
383
|
+
badge.className = 'tool-tree-badge completed';
|
|
384
|
+
badge.textContent = '✔ DONE';
|
|
261
385
|
}
|
|
386
|
+
|
|
387
|
+
currentToolTreeEl.classList.remove('running');
|
|
388
|
+
currentToolTreeEl.classList.add('completed');
|
|
262
389
|
}
|
|
263
|
-
currentRunningToolEl = null;
|
|
264
390
|
}
|
|
265
391
|
|
|
266
392
|
function showThinkingSpinner() {
|
|
@@ -483,8 +609,14 @@ if (chatForm && chatInput) {
|
|
|
483
609
|
chatInput.style.height = 'auto';
|
|
484
610
|
if (chatStatusBadge) chatStatusBadge.textContent = 'THINKING...';
|
|
485
611
|
|
|
486
|
-
|
|
612
|
+
turnStartTime = Date.now();
|
|
613
|
+
currentTurnExecutedTools = [];
|
|
614
|
+
currentTurnTokenCount = 0;
|
|
615
|
+
currentToolTreeEl = null;
|
|
487
616
|
activeAssistantBody = null;
|
|
617
|
+
activeAssistantMsgEl = null;
|
|
618
|
+
|
|
619
|
+
addChatMessage('user', effectiveText || 'Attached image', null, imageBase64);
|
|
488
620
|
showThinkingSpinner();
|
|
489
621
|
|
|
490
622
|
try {
|
|
@@ -709,7 +841,14 @@ async function loadChatHistory() {
|
|
|
709
841
|
if (validHistory.length > 0) {
|
|
710
842
|
chatMessages.innerHTML = '';
|
|
711
843
|
validHistory.forEach(item => {
|
|
712
|
-
addChatMessage(
|
|
844
|
+
addChatMessage(
|
|
845
|
+
item.role === 'assistant' ? 'assistant' : 'user',
|
|
846
|
+
item.text,
|
|
847
|
+
null,
|
|
848
|
+
null,
|
|
849
|
+
item.timestamp,
|
|
850
|
+
item.role === 'assistant' ? { model: 'daedalus' } : null
|
|
851
|
+
);
|
|
713
852
|
});
|
|
714
853
|
}
|
|
715
854
|
}
|
|
@@ -748,8 +887,12 @@ function connectSSE() {
|
|
|
748
887
|
// already added locally or by another client
|
|
749
888
|
} else {
|
|
750
889
|
removeThinkingSpinner();
|
|
890
|
+
currentTurnTokenCount += (data.text || '').split(/\s+/).filter(Boolean).length;
|
|
751
891
|
if (!activeAssistantBody) {
|
|
752
892
|
activeAssistantBody = addChatMessage('assistant', data.text || '', 'STREAM', null, data.timestamp);
|
|
893
|
+
if (activeAssistantBody) {
|
|
894
|
+
activeAssistantMsgEl = activeAssistantBody.closest('.chat-msg');
|
|
895
|
+
}
|
|
753
896
|
} else if (data.text) {
|
|
754
897
|
const raw = (activeAssistantBody.dataset.raw || '') + data.text;
|
|
755
898
|
activeAssistantBody.dataset.raw = raw;
|
|
@@ -781,7 +924,14 @@ function connectSSE() {
|
|
|
781
924
|
if (activeAssistantBody && activeAssistantBody.dataset.raw) {
|
|
782
925
|
activeAssistantBody.innerHTML = renderMarkdown(activeAssistantBody.dataset.raw);
|
|
783
926
|
}
|
|
927
|
+
if (activeAssistantMsgEl) {
|
|
928
|
+
const duration = data.durationMs || (turnStartTime ? Date.now() - turnStartTime : 0);
|
|
929
|
+
const activeModelName = data.model || (modelLabel ? modelLabel.textContent.replace('MODEL: ', '').toLowerCase() : 'auto');
|
|
930
|
+
attachCliFooter(activeAssistantMsgEl, activeModelName, currentTurnExecutedTools.length, duration, currentTurnTokenCount);
|
|
931
|
+
}
|
|
784
932
|
activeAssistantBody = null;
|
|
933
|
+
activeAssistantMsgEl = null;
|
|
934
|
+
currentToolTreeEl = null;
|
|
785
935
|
if (chatStatusBadge) chatStatusBadge.textContent = 'READY';
|
|
786
936
|
addLog('Chat completion finished.');
|
|
787
937
|
return;
|
|
@@ -1067,8 +1217,23 @@ if (modelModal) {
|
|
|
1067
1217
|
});
|
|
1068
1218
|
}
|
|
1069
1219
|
|
|
1220
|
+
async function loadUserProfile() {
|
|
1221
|
+
try {
|
|
1222
|
+
const res = await fetch('/api/profile');
|
|
1223
|
+
if (!res.ok) return;
|
|
1224
|
+
const data = await res.json();
|
|
1225
|
+
if (data.name && data.name.trim()) {
|
|
1226
|
+
userProfileName = data.name.trim().toUpperCase();
|
|
1227
|
+
document.querySelectorAll('.chat-msg.user .sender').forEach(el => {
|
|
1228
|
+
el.textContent = userProfileName;
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
} catch {}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1070
1234
|
connectSSE();
|
|
1071
1235
|
loadModels();
|
|
1236
|
+
loadUserProfile();
|
|
1072
1237
|
|
|
1073
1238
|
setInterval(() => {
|
|
1074
1239
|
if (lastUpdateEl) {
|