agentxchain 2.73.0 → 2.74.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.
@@ -55,6 +55,39 @@ function renderList(items, type) {
55
55
  .join('');
56
56
  }
57
57
 
58
+ function formatDuration(ms) {
59
+ if (ms == null || ms < 0 || !Number.isFinite(ms)) return null;
60
+ const totalSeconds = Math.floor(ms / 1000);
61
+ const hours = Math.floor(totalSeconds / 3600);
62
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
63
+ const seconds = totalSeconds % 60;
64
+ if (hours > 0) return `${hours}h ${minutes}m`;
65
+ if (minutes > 0) return `${minutes}m ${seconds}s`;
66
+ return `${seconds}s`;
67
+ }
68
+
69
+ function computeElapsed(startedAt) {
70
+ if (!startedAt) return null;
71
+ try {
72
+ const start = new Date(startedAt).getTime();
73
+ if (Number.isNaN(start)) return null;
74
+ return Math.max(0, Date.now() - start);
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+
80
+ function formatTimestamp(iso) {
81
+ if (!iso) return null;
82
+ try {
83
+ const d = new Date(iso);
84
+ if (Number.isNaN(d.getTime())) return null;
85
+ return d.toLocaleString();
86
+ } catch {
87
+ return null;
88
+ }
89
+ }
90
+
58
91
  function statusBadge(status) {
59
92
  const colors = {
60
93
  running: 'var(--green)',
@@ -230,6 +263,8 @@ function renderConnectorHealthPanel(connectorsPayload) {
230
263
  return html;
231
264
  }
232
265
 
266
+ export { formatDuration, computeElapsed, formatTimestamp };
267
+
233
268
  export function render({ state, continuity, history, annotations, audit, connectors }) {
234
269
  if (!state) {
235
270
  return `<div class="placeholder"><h2>No Run</h2><p>No governed run found. Start one with <code class="mono">agentxchain init --governed</code></p></div>`;
@@ -257,11 +292,14 @@ export function render({ state, continuity, history, annotations, audit, connect
257
292
  if (activeTurns.length > 0) {
258
293
  html += `<div class="section"><h3>Active Turns</h3><div class="turn-list">`;
259
294
  for (const turn of activeTurns) {
295
+ const elapsedMs = computeElapsed(turn.started_at);
296
+ const elapsedStr = formatDuration(elapsedMs);
260
297
  html += `<div class="turn-card active">
261
298
  <div class="turn-header">
262
299
  ${roleBadge(getRole(turn))}
263
300
  <span class="mono">${esc(turn.turn_id)}</span>
264
301
  <span class="turn-status">${esc(turn.status || 'assigned')}</span>
302
+ ${elapsedStr ? `<span class="turn-timing">Elapsed: ${esc(elapsedStr)}</span>` : ''}
265
303
  </div>
266
304
  </div>`;
267
305
  }
@@ -281,10 +319,14 @@ export function render({ state, continuity, history, annotations, audit, connect
281
319
  || entry.verification?.evidence_summary
282
320
  || null;
283
321
 
322
+ const durationStr = formatDuration(entry.duration_ms);
323
+ const acceptedStr = formatTimestamp(entry.accepted_at);
284
324
  html += `<div class="turn-card" data-turn-expand="${esc(entry.turn_id)}">
285
325
  <div class="turn-header">
286
326
  ${roleBadge(getRole(entry))}
287
327
  <span class="mono">${esc(entry.turn_id)}</span>
328
+ ${durationStr ? `<span class="turn-timing">${esc(durationStr)}</span>` : ''}
329
+ ${acceptedStr ? `<span class="turn-timestamp">${esc(acceptedStr)}</span>` : ''}
288
330
  </div>`;
289
331
 
290
332
  if (entry.summary) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentxchain",
3
- "version": "2.73.0",
3
+ "version": "2.74.0",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {