Skip to content

Commit 167ef73

Browse files
improv: types, ux
1 parent 4d05022 commit 167ef73

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

core/control-plane/client.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,9 @@ export class ControlPlaneClient {
608608
* @param agentSessionId - The ID of the agent session
609609
* @returns The agent session view including metadata and status
610610
*/
611-
public async getAgentSession(agentSessionId: string): Promise<any | null> {
611+
public async getAgentSession(
612+
agentSessionId: string,
613+
): Promise<AgentSessionView | null> {
612614
if (!(await this.isSignedIn())) {
613615
return null;
614616
}
@@ -621,7 +623,7 @@ export class ControlPlaneClient {
621623
},
622624
);
623625

624-
return await resp.json();
626+
return (await resp.json()) as AgentSessionView;
625627
} catch (e) {
626628
Logger.error(e, {
627629
context: "control_plane_get_agent_session",

gui/src/components/BackgroundMode/AgentsList.tsx

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,20 @@ interface AgentsListProps {
2222
isCreatingAgent?: boolean;
2323
}
2424

25+
interface WorkspaceInfo {
26+
repoUrl: string;
27+
workspaceDir: string;
28+
workspaceName: string;
29+
}
30+
2531
export function AgentsList({ isCreatingAgent = false }: AgentsListProps) {
2632
const { session } = useAuth();
2733
const ideMessenger = useContext(IdeMessengerContext);
2834
const currentOrg = useAppSelector(selectCurrentOrg);
2935
const [agents, setAgents] = useState<Agent[] | null>(null);
3036
const [totalCount, setTotalCount] = useState<number>(0);
3137
const [error, setError] = useState<string | null>(null);
32-
const [workspaceRepoUrls, setWorkspaceRepoUrls] = useState<string[]>([]);
38+
const [workspaces, setWorkspaces] = useState<WorkspaceInfo[]>([]);
3339

3440
// Fetch workspace repo URLs once on mount
3541
useEffect(() => {
@@ -40,19 +46,25 @@ export function AgentsList({ isCreatingAgent = false }: AgentsListProps) {
4046
undefined,
4147
);
4248
if (workspaceDirs.status === "success" && workspaceDirs.content) {
43-
const repoUrls: string[] = [];
49+
const workspaceInfos: WorkspaceInfo[] = [];
4450
for (const dir of workspaceDirs.content) {
4551
const repoNameResult = await ideMessenger.request("getRepoName", {
4652
dir,
4753
});
4854
if (repoNameResult.status === "success" && repoNameResult.content) {
4955
const normalizedUrl = normalizeRepoUrl(repoNameResult.content);
5056
if (normalizedUrl) {
51-
repoUrls.push(normalizedUrl);
57+
// Extract workspace name from directory path (last segment)
58+
const workspaceName = dir.split("/").pop() || dir;
59+
workspaceInfos.push({
60+
repoUrl: normalizedUrl,
61+
workspaceDir: dir,
62+
workspaceName,
63+
});
5264
}
5365
}
5466
}
55-
setWorkspaceRepoUrls(repoUrls);
67+
setWorkspaces(workspaceInfos);
5668
}
5769
} catch (err) {
5870
console.error("Failed to fetch workspace repos:", err);
@@ -120,11 +132,30 @@ export function AgentsList({ isCreatingAgent = false }: AgentsListProps) {
120132
.filter((url) => url !== "");
121133

122134
// Check if any of the agent URLs match any workspace URL
123-
return workspaceRepoUrls.some((workspaceUrl) =>
124-
agentUrls.some((agentUrl) => agentUrl === workspaceUrl),
135+
return workspaces.some((workspace) =>
136+
agentUrls.some((agentUrl) => agentUrl === workspace.repoUrl),
125137
);
126138
};
127139

140+
// Helper function to get the agent's repository name (for display in tooltips)
141+
const getAgentRepoName = (agent: Agent): string | null => {
142+
// Try to extract repo name from the agent's repository URL
143+
// Handles URLs like: https://github.com/org/repo or git@github.com:org/repo.git
144+
const repoUrl = agent.metadata?.github_repo || agent.repoUrl;
145+
if (!repoUrl) return null;
146+
147+
try {
148+
// Remove .git suffix if present
149+
const cleanUrl = repoUrl.replace(/\.git$/, "");
150+
// Extract the last path segment (repo name)
151+
const parts = cleanUrl.split("/");
152+
const repoName = parts[parts.length - 1];
153+
return repoName || null;
154+
} catch {
155+
return null;
156+
}
157+
};
158+
128159
const handleOpenLocally = (agent: Agent, e: React.MouseEvent) => {
129160
e.stopPropagation(); // Prevent opening the agent detail page
130161
ideMessenger.post("openAgentLocally", { agentSessionId: agent.id });
@@ -163,6 +194,7 @@ export function AgentsList({ isCreatingAgent = false }: AgentsListProps) {
163194
{agents.map((agent) => {
164195
const isInWorkspace = isAgentInCurrentWorkspace(agent);
165196
const canOpenLocally = isInWorkspace;
197+
const agentRepoName = getAgentRepoName(agent);
166198

167199
return (
168200
<div
@@ -197,7 +229,9 @@ export function AgentsList({ isCreatingAgent = false }: AgentsListProps) {
197229
title={
198230
canOpenLocally
199231
? "Open this agent workflow locally"
200-
: "This agent is for a different repository. Open the correct workspace to take over this workflow."
232+
: agentRepoName
233+
? `This agent is for a different repository (${agentRepoName}). Open that workspace to take over this workflow.`
234+
: "This agent is for a different repository. Open the correct workspace to take over this workflow."
201235
}
202236
>
203237
<PlayIcon className="h-3 w-3" />

0 commit comments

Comments
 (0)