chore: switch mergemaster to opus and add cargo fmt guidance
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,10 +3,10 @@
|
||||
/// Provides:
|
||||
/// - An "Add Agent" button that generates a one-time join token.
|
||||
/// - Instructions for running a build agent with the token.
|
||||
/// - A list of connected agents with per-agent "Remove" buttons.
|
||||
/// - A list of connected agents with per-agent project assignment and "Remove" buttons.
|
||||
|
||||
import * as React from "react";
|
||||
import { gatewayApi, type JoinedAgent } from "../api/gateway";
|
||||
import { gatewayApi, type JoinedAgent, type GatewayProject } from "../api/gateway";
|
||||
|
||||
const { useCallback, useEffect, useState } = React;
|
||||
|
||||
@@ -90,12 +90,17 @@ function TokenDisplay({ token }: { token: string }) {
|
||||
|
||||
function AgentRow({
|
||||
agent,
|
||||
projects,
|
||||
onRemove,
|
||||
onAssign,
|
||||
}: {
|
||||
agent: JoinedAgent;
|
||||
projects: GatewayProject[];
|
||||
onRemove: (id: string) => void;
|
||||
onAssign: (id: string, project: string | null) => void;
|
||||
}) {
|
||||
const registeredAt = new Date(agent.registered_at * 1000).toLocaleString();
|
||||
const isAssigned = Boolean(agent.assigned_project);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -116,9 +121,10 @@ function AgentRow({
|
||||
width: "8px",
|
||||
height: "8px",
|
||||
borderRadius: "50%",
|
||||
background: "#3fb950",
|
||||
background: isAssigned ? "#3fb950" : "#6e7681",
|
||||
flexShrink: 0,
|
||||
}}
|
||||
title={isAssigned ? "Assigned" : "Idle (unassigned)"}
|
||||
/>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{ fontWeight: 600, color: "#e6edf3" }}>{agent.label}</div>
|
||||
@@ -129,6 +135,29 @@ function AgentRow({
|
||||
Registered {registeredAt}
|
||||
</div>
|
||||
</div>
|
||||
<select
|
||||
data-testid={`assign-agent-${agent.id}`}
|
||||
value={agent.assigned_project ?? ""}
|
||||
onChange={(e) =>
|
||||
onAssign(agent.id, e.target.value === "" ? null : e.target.value)
|
||||
}
|
||||
style={{
|
||||
fontSize: "0.8em",
|
||||
padding: "4px 8px",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid #30363d",
|
||||
background: "#0d1117",
|
||||
color: "#e6edf3",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<option value="">— unassigned —</option>
|
||||
{projects.map((p) => (
|
||||
<option key={p.name} value={p.name}>
|
||||
{p.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
data-testid={`remove-agent-${agent.id}`}
|
||||
@@ -152,6 +181,7 @@ function AgentRow({
|
||||
/// Gateway management panel — rendered when running in `--gateway` mode.
|
||||
export function GatewayPanel() {
|
||||
const [agents, setAgents] = useState<JoinedAgent[]>([]);
|
||||
const [projects, setProjects] = useState<GatewayProject[]>([]);
|
||||
const [token, setToken] = useState<string | null>(null);
|
||||
const [generating, setGenerating] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -161,6 +191,10 @@ export function GatewayPanel() {
|
||||
.listAgents()
|
||||
.then(setAgents)
|
||||
.catch(() => setAgents([]));
|
||||
gatewayApi
|
||||
.getGatewayInfo()
|
||||
.then((info) => setProjects(info.projects))
|
||||
.catch(() => setProjects([]));
|
||||
}, []);
|
||||
|
||||
const handleAddAgent = useCallback(async () => {
|
||||
@@ -186,6 +220,20 @@ export function GatewayPanel() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleAssignAgent = useCallback(
|
||||
async (id: string, project: string | null) => {
|
||||
try {
|
||||
const updated = await gatewayApi.assignAgent(id, project);
|
||||
setAgents((prev) =>
|
||||
prev.map((a) => (a.id === updated.id ? updated : a)),
|
||||
);
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : String(e));
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -273,7 +321,9 @@ export function GatewayPanel() {
|
||||
<AgentRow
|
||||
key={agent.id}
|
||||
agent={agent}
|
||||
projects={projects}
|
||||
onRemove={handleRemoveAgent}
|
||||
onAssign={handleAssignAgent}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user