mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 06:29:42 +02:00
feat(ultracode): enrich live run tracking — real per-agent tokens/tools/state, readable title, blue connector line, click-to-open window
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8473,14 +8473,14 @@ kbd {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.ultracode-status.completed {
|
||||
background: var(--success);
|
||||
background: var(--green);
|
||||
}
|
||||
.ultracode-status.active {
|
||||
background: var(--warning);
|
||||
background: var(--yellow);
|
||||
color: black;
|
||||
}
|
||||
.ultracode-status.failed {
|
||||
background: var(--error, #b3261e);
|
||||
background: var(--red, #b3261e);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@@ -8531,6 +8531,16 @@ kbd {
|
||||
border-radius: 6px;
|
||||
padding: 0.4rem 0.5rem;
|
||||
margin-bottom: 0.35rem;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
/* At-a-glance agent state: yellow while working, green when done. */
|
||||
.ultracode-agent-card.uw-state-working {
|
||||
border-left-color: var(--yellow);
|
||||
background: color-mix(in srgb, var(--yellow) 9%, var(--bg-input));
|
||||
}
|
||||
.ultracode-agent-card.uw-state-done {
|
||||
border-left-color: var(--green);
|
||||
background: color-mix(in srgb, var(--green) 9%, var(--bg-input));
|
||||
}
|
||||
.ultracode-agent-card--clickable {
|
||||
cursor: pointer;
|
||||
@@ -8539,6 +8549,14 @@ kbd {
|
||||
.ultracode-agent-card--clickable:hover {
|
||||
background: var(--bg-card);
|
||||
}
|
||||
/* Keep the state tint on hover (equal specificity to the hover rule, so it must
|
||||
come after it) — a tad stronger so the hover still reads as interactive. */
|
||||
.ultracode-agent-card--clickable.uw-state-working:hover {
|
||||
background: color-mix(in srgb, var(--yellow) 16%, var(--bg-card));
|
||||
}
|
||||
.ultracode-agent-card--clickable.uw-state-done:hover {
|
||||
background: color-mix(in srgb, var(--green) 16%, var(--bg-card));
|
||||
}
|
||||
.ultracode-agent-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -8564,10 +8582,10 @@ kbd {
|
||||
color: white;
|
||||
}
|
||||
.ultracode-agent-state.completed {
|
||||
background: var(--success);
|
||||
background: var(--green);
|
||||
}
|
||||
.ultracode-agent-state.active {
|
||||
background: var(--warning);
|
||||
background: var(--yellow);
|
||||
color: black;
|
||||
}
|
||||
.ultracode-agent-state.idle {
|
||||
@@ -8707,14 +8725,15 @@ kbd {
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
/* Ultracode connector line — distinct purple to set it apart from blue subagent lines. */
|
||||
/* Ultracode connector line — the session-tab accent blue (dashed to stay distinct
|
||||
from the solid subagent lines, per the same-blue-as-the-tab request). */
|
||||
.connection-line.ultracode-connection {
|
||||
stroke: #a855f7;
|
||||
stroke: var(--accent);
|
||||
stroke-width: 3;
|
||||
stroke-dasharray: 6 3;
|
||||
filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.8))
|
||||
drop-shadow(0 0 5px rgba(168, 85, 247, 0.85))
|
||||
drop-shadow(0 0 10px rgba(168, 85, 247, 0.5));
|
||||
drop-shadow(0 0 5px rgba(var(--accent-rgb), 0.85))
|
||||
drop-shadow(0 0 10px rgba(var(--accent-rgb), 0.5));
|
||||
animation: ultracode-conn-pulse 1.4s ease-in-out infinite;
|
||||
}
|
||||
.connection-line.ultracode-connection:hover {
|
||||
|
||||
@@ -96,6 +96,10 @@ Object.assign(CodemanApp.prototype, {
|
||||
this.activeWorkflowPhaseIndex = null; // reset phase filter on run change
|
||||
this._fetchWorkflowRunDetail(runId);
|
||||
this.renderUltracodeAgentsPanel();
|
||||
// Clicking a run also pops its floating window (with connector line to the
|
||||
// session tab), like the auto-popped one — an explicit open, so it ignores the
|
||||
// floating-windows auto-pop toggle (ultracode-windows.js).
|
||||
if (typeof this.openUltracodeWindowForRun === 'function') this.openUltracodeWindowForRun(runId);
|
||||
},
|
||||
selectWorkflowPhase(phaseIndex) {
|
||||
this._ensureWorkflowState();
|
||||
@@ -105,6 +109,11 @@ Object.assign(CodemanApp.prototype, {
|
||||
},
|
||||
|
||||
async _fetchWorkflowRunDetail(runId) {
|
||||
// De-dupe concurrent fetches for the same run — selecting a run can trigger both
|
||||
// a panel refresh and a floating-window open, which would otherwise double-fetch.
|
||||
if (!this._wfDetailInFlight) this._wfDetailInFlight = new Set();
|
||||
if (this._wfDetailInFlight.has(runId)) return;
|
||||
this._wfDetailInFlight.add(runId);
|
||||
try {
|
||||
const res = await fetch(`/api/workflows/${encodeURIComponent(runId)}`);
|
||||
const env = await res.json();
|
||||
@@ -117,6 +126,8 @@ Object.assign(CodemanApp.prototype, {
|
||||
}
|
||||
} catch {
|
||||
/* transient — next update retries */
|
||||
} finally {
|
||||
this._wfDetailInFlight.delete(runId);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -274,10 +285,12 @@ Object.assign(CodemanApp.prototype, {
|
||||
// to the agent-<id>.jsonl stem already tracked by subagent-watcher). 'start' agents have
|
||||
// no agentId yet, so they stay non-clickable.
|
||||
const clickable = !!a.agentId;
|
||||
// At-a-glance state tint on the whole card: green when done, yellow while working.
|
||||
const cardStateCls = state === 'done' ? ' uw-state-done' : state === 'progress' ? ' uw-state-working' : '';
|
||||
const cardAttrs = clickable
|
||||
? ` class="ultracode-agent-card ultracode-agent-card--clickable" role="button" tabindex="0"` +
|
||||
? ` class="ultracode-agent-card ultracode-agent-card--clickable${cardStateCls}" role="button" tabindex="0"` +
|
||||
` title="View transcript" onclick="app.openWorkflowAgentTranscript('${escapeHtml(a.agentId)}')"`
|
||||
: ` class="ultracode-agent-card"`;
|
||||
: ` class="ultracode-agent-card${cardStateCls}"`;
|
||||
return (
|
||||
`<div${cardAttrs}>` +
|
||||
`<div class="ultracode-agent-top">` +
|
||||
|
||||
@@ -77,12 +77,14 @@ Object.assign(CodemanApp.prototype, {
|
||||
_syncUltracodeFloatingWindow(run, opts) {
|
||||
this._ensureUltracodeWindowState();
|
||||
if (!run || !run.runId) return;
|
||||
if (!this._ultracodeFloatingEnabled()) return;
|
||||
const runId = run.runId;
|
||||
const existing = this.ultracodeWindows.get(runId);
|
||||
// Auto-pop is gated on the floating-windows toggle, but an ALREADY-open window
|
||||
// (e.g. one opened by clicking the run in the dock) keeps refreshing regardless.
|
||||
if (!existing && !this._ultracodeFloatingEnabled()) return;
|
||||
if (this.ultracodeWindowsClosed.has(runId)) return; // respect explicit dismissal
|
||||
|
||||
const active = this._isWorkflowRunActive(run);
|
||||
const existing = this.ultracodeWindows.get(runId);
|
||||
|
||||
if (active) {
|
||||
// Run is alive — cancel any pending auto-close.
|
||||
@@ -120,6 +122,31 @@ Object.assign(CodemanApp.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Explicitly open (or focus) the floating window for a run — the click-through
|
||||
* from the dock panel's run list. Unlike auto-pop this ignores the floating-windows
|
||||
* toggle and clears any prior dismissal (it's a direct user action), then draws the
|
||||
* connector line from the run's session tab.
|
||||
*/
|
||||
openUltracodeWindowForRun(runId) {
|
||||
this._ensureUltracodeWindowState();
|
||||
if (!runId) return;
|
||||
const run = this.workflowRuns && this.workflowRuns.get(runId);
|
||||
if (!run) return;
|
||||
this.ultracodeWindowsClosed.delete(runId); // an explicit open overrides a past dismissal
|
||||
const existing = this.ultracodeWindows.get(runId);
|
||||
if (existing) {
|
||||
// Already open — bring to front, expand if collapsed, refresh.
|
||||
existing.element.style.zIndex = ++this.ultracodeWindowZIndex;
|
||||
if (existing.collapsed) this.toggleUltracodeWindowCollapse(runId);
|
||||
this.renderUltracodeWindowContent(runId);
|
||||
this._fetchWorkflowRunDetail(runId);
|
||||
this.updateConnectionLines();
|
||||
} else {
|
||||
this.createUltracodeWindow(run);
|
||||
}
|
||||
},
|
||||
|
||||
/** Build and mount a floating window for a run, positioned near its parent tab. */
|
||||
createUltracodeWindow(run) {
|
||||
this._ensureUltracodeWindowState();
|
||||
|
||||
Reference in New Issue
Block a user