Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions src/Highbyte.Wrighty.Web/Assets/wrighty.css
Original file line number Diff line number Diff line change
Expand Up @@ -431,24 +431,23 @@ input::placeholder, textarea::placeholder { color: var(--muted); }
.agent-table th, .agent-table td { text-align: left; }
.agent-table-header { color: var(--muted); font-size: .66rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; }
.agent-table-header th { padding: .15rem .6rem; }
.agent-table-row > th, .agent-table-row > td { height: 3rem; padding: .35rem .6rem; background: color-mix(in srgb, var(--surface) 76%, transparent); }
.agent-table-row > th, .agent-table-row > td { height: 3rem; padding: .35rem .6rem; background: color-mix(in srgb, var(--surface) 76%, transparent); vertical-align: middle; }
.agent-table-row > :first-child { border: 1px solid transparent; border-right: 0; border-radius: .45rem 0 0 .45rem; }
.agent-table-row > :last-child { border: 1px solid transparent; border-left: 0; border-radius: 0 .45rem .45rem 0; }
.agent-table-row.needs-attention > :first-child { border-color: color-mix(in srgb, #a36a00 42%, var(--line)); }
.agent-table-row.needs-attention > :last-child { border-color: color-mix(in srgb, #a36a00 42%, var(--line)); }
.agent-table-row form { margin: 0; }
.agent-name-cell { display: grid; min-width: 0; }
.agent-name-cell { min-width: 0; }
.agent-name-content { display: grid; min-width: 0; }
.agent-name-cell strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-name-cell small { color: var(--muted); font-size: .65rem; }
.agent-state { display: inline-flex; width: fit-content; padding: .08rem .4rem; border-radius: 999px; background: var(--surface-2); color: var(--muted); font-size: .68rem; font-weight: 700; white-space: nowrap; }
.agent-state.state-current { color: var(--success); }
.agent-state.state-warning { color: var(--warning); }
.agent-state.state-muted { color: var(--muted); }
.agent-capacity-cell { display: flex; align-items: center; gap: .35rem; }
.agent-capacity-content, .agent-action-content { display: flex; align-items: center; gap: .35rem; }
.button-link-compact { min-height: auto; padding: .1rem .2rem; border-color: transparent; background: transparent; color: var(--accent-text); font-size: .68rem; }
.agent-action-cell { align-items: center; gap: .35rem; }
.agent-action-cell > form, .agent-action-cell > button { margin-right: .35rem; }
.agent-action-cell form { display: flex; }
.agent-action-content form { display: flex; }
.agent-enable-switch { display: inline-flex; align-items: center; gap: .35rem; min-height: 1.65rem; padding: .15rem .35rem; border-color: transparent; background: transparent; color: var(--muted); font-size: .68rem; }
.agent-enable-switch > span:first-child { position: relative; width: 1.7rem; height: .9rem; border-radius: 999px; background: var(--line); }
.agent-enable-switch > span:first-child::after { position: absolute; top: .13rem; left: .13rem; width: .64rem; height: .64rem; border-radius: 50%; background: var(--muted); content: ""; transition: transform .12s ease; }
Expand Down
102 changes: 54 additions & 48 deletions src/Highbyte.Wrighty.Web/Pages/Shared/_Agents.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
<tr class="agent-table-row@(agent.NeedsAttention ? " needs-attention" : null)"
data-agent-id="@agent.Agent">
<th class="agent-name-cell" scope="row">
<strong>@agent.AgentLabel</strong>
<small>@agent.Agent</small>
<span class="agent-name-content">
<strong>@agent.AgentLabel</strong>
<small>@agent.Agent</small>
</span>
</th>
<td>
<form hx-post="/?handler=SetAgentEnabled"
Expand Down Expand Up @@ -196,59 +198,63 @@
</span>
</td>
<td class="agent-capacity-cell">
<span title="@agent.Capacity?.Reason"
class="agent-state @CapacityStateClass(agent)">@capacityLabel</span>
@if (agent.Capacity?.Simulated == true)
{
<small class="agent-capacity-source">Simulated</small>
}
@if (agent.Detected && agent.Capacity is not null)
{
<form hx-post="/?handler=ProbeProvider"
hx-target="#agents-region"
hx-swap="outerHTML"
hx-sync="this:drop"
hx-request='{"timeout":130000}'
hx-disabled-elt="find button"
data-agent-probe-request
data-confirm-title="Probe @agent.AgentLabel capacity?"
data-confirm-message="A real probe starts a small vendor request and may consume subscription usage. A configured repository simulation does not start the vendor CLI. Neither path claims a work item."
data-confirm-action="Probe @agent.AgentLabel">
@Html.AntiForgeryToken()
<input type="hidden" name="agent" value="@agent.Agent">
<input type="hidden" name="surface" value="agents">
<button type="submit"
id="agent-probe-@agent.Agent"
class="button-link-compact"
disabled="@(!agent.Enabled || agent.ProbeInProgress)">Probe</button>
</form>
}
<div class="agent-capacity-content">
<span title="@agent.Capacity?.Reason"
class="agent-state @CapacityStateClass(agent)">@capacityLabel</span>
@if (agent.Capacity?.Simulated == true)
{
<small class="agent-capacity-source">Simulated</small>
}
@if (agent.Detected && agent.Capacity is not null)
{
<form hx-post="/?handler=ProbeProvider"
hx-target="#agents-region"
hx-swap="outerHTML"
hx-sync="this:drop"
hx-request='{"timeout":130000}'
hx-disabled-elt="find button"
data-agent-probe-request
data-confirm-title="Probe @agent.AgentLabel capacity?"
data-confirm-message="A real probe starts a small vendor request and may consume subscription usage. A configured repository simulation does not start the vendor CLI. Neither path claims a work item."
data-confirm-action="Probe @agent.AgentLabel">
@Html.AntiForgeryToken()
<input type="hidden" name="agent" value="@agent.Agent">
<input type="hidden" name="surface" value="agents">
<button type="submit"
id="agent-probe-@agent.Agent"
class="button-link-compact"
disabled="@(!agent.Enabled || agent.ProbeInProgress)">Probe</button>
</form>
}
</div>
</td>
<td>
<span class="agent-state @SkillStateClass(skillLabel)">@skillLabel</span>
</td>
<td class="agent-action-cell">
@if (agent.Skill is not null)
{
@if (canUpdateSkill)
<div class="agent-action-content">
@if (agent.Skill is not null)
{
<form hx-post="/?handler=UpdateAgentSkill" hx-target="#agents-region" hx-swap="outerHTML" hx-disabled-elt="find button">
@Html.AntiForgeryToken()
<input type="hidden" name="agentSelection" value="@agent.Skill.AgentSelection">
<button type="submit"
id="agent-update-skill-@agent.Agent"
class="button-compact button-warning"
disabled="@(!agent.Enabled)">Update skill</button>
</form>
@if (canUpdateSkill)
{
<form hx-post="/?handler=UpdateAgentSkill" hx-target="#agents-region" hx-swap="outerHTML" hx-disabled-elt="find button">
@Html.AntiForgeryToken()
<input type="hidden" name="agentSelection" value="@agent.Skill.AgentSelection">
<button type="submit"
id="agent-update-skill-@agent.Agent"
class="button-compact button-warning"
disabled="@(!agent.Enabled)">Update skill</button>
</form>
}
<button type="button"
id="agent-manage-skill-@agent.Agent"
class="button-compact"
data-agent-details-toggle="@detailsId"
aria-expanded="false"
aria-controls="@detailsId"
disabled="@(!agent.Enabled)">Manage skill</button>
}
<button type="button"
id="agent-manage-skill-@agent.Agent"
class="button-compact"
data-agent-details-toggle="@detailsId"
aria-expanded="false"
aria-controls="@detailsId"
disabled="@(!agent.Enabled)">Manage skill</button>
}
</div>
</td>
</tr>
@if (agent.Skill is { } skill)
Expand Down
12 changes: 12 additions & 0 deletions tests/Highbyte.Wrighty.UnitTests/Web/WrightyWebServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ public async Task Agents_inventory_is_compact_expandable_and_persists_enablement
Assert.Contains("Agents on this computer", html);
Assert.Contains("hx-sync=\"#agents-region:replace\"", html);
Assert.Contains("<table class=\"agent-table\">", html);
Assert.Contains("class=\"agent-name-content\"", html);
Assert.Contains("class=\"agent-capacity-content\"", html);
Assert.Contains("class=\"agent-action-content\"", html);
Assert.Contains("data-agent-details-toggle=\"agent-details-codex\"", html);
Assert.Contains("aria-label=\"Disable Copilot\"", html);
Assert.Contains("name=\"enabled\" value=\"false\"", html);
Expand Down Expand Up @@ -5744,6 +5747,15 @@ public void Header_and_item_panel_layout_contracts_are_embedded()
Assert.Contains(".connection-tools { display: grid; justify-items: end;", stylesheet);
Assert.Contains(".access-link-button { min-height: 0; padding: 0; border: 0;", stylesheet);
Assert.Contains(".agents-menu.has-current > summary", stylesheet);
Assert.Contains(
".agent-table-row > th, .agent-table-row > td { height: 3rem; padding: .35rem .6rem; background: color-mix(in srgb, var(--surface) 76%, transparent); vertical-align: middle; }",
stylesheet);
Assert.Contains(".agent-name-content { display: grid; min-width: 0; }", stylesheet);
Assert.Contains(
".agent-capacity-content, .agent-action-content { display: flex; align-items: center; gap: .35rem; }",
stylesheet);
Assert.DoesNotContain(".agent-name-cell { display:", stylesheet);
Assert.DoesNotContain(".agent-capacity-cell { display:", stylesheet);
Assert.Contains(".board-filter-menu { position: relative; align-self: end; width: 7.25rem; }", stylesheet);
Assert.Contains(".board-filter-menu > summary { display: flex; align-items: center; justify-content: space-between;", stylesheet);
Assert.Contains(".board-filter-heading-actions { display: flex; align-items: center; gap: .25rem; }", stylesheet);
Expand Down