Skip to content
Open
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
73 changes: 38 additions & 35 deletions desktop/src/features/profile/ui/UserProfilePanelFields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ export function buildOwnerFields({
relayAgent: RelayAgent | undefined;
}): ProfileField[] {
const fields: ProfileField[] = [];
const isProviderManaged = managedAgent?.backend.type === "provider";
const respondTo = managedAgent?.respondTo ?? relayAgent?.respondTo ?? null;
const respondToDisplayValue = respondTo
? respondTo === "owner-only" && ownerDisplayName
Expand Down Expand Up @@ -290,38 +291,40 @@ export function buildOwnerFields({
return fields;
}

if (managedAgent?.agentCommand) {
fields.push({
copyValue: managedAgent.agentCommand,
displayValue: runtimeLabel(managedAgent.agentCommand),
icon: Terminal,
label: "Runtime",
testId: "user-profile-runtime",
});
} else if (relayAgent?.agentType) {
fields.push({
copyValue: relayAgent.agentType,
displayValue: runtimeLabel(relayAgent.agentType),
icon: Terminal,
label: "Runtime",
testId: "user-profile-runtime",
});
} else if (persona?.runtime) {
fields.push({
copyValue: persona.runtime,
displayValue: runtimeLabel(persona.runtime),
icon: Terminal,
label: "Runtime",
testId: "user-profile-runtime",
});
} else if (ownerPubkey) {
fields.push({
copyValue: ownerPubkey,
displayValue: "Declared owner verified",
icon: UserRound,
label: "Agent profile",
testId: "user-profile-agent-profile",
});
if (!isProviderManaged) {
if (managedAgent?.agentCommand) {
fields.push({
copyValue: managedAgent.agentCommand,
displayValue: runtimeLabel(managedAgent.agentCommand),
icon: Terminal,
label: "Runtime",
testId: "user-profile-runtime",
});
} else if (relayAgent?.agentType) {
fields.push({
copyValue: relayAgent.agentType,
displayValue: runtimeLabel(relayAgent.agentType),
icon: Terminal,
label: "Runtime",
testId: "user-profile-runtime",
});
} else if (persona?.runtime) {
fields.push({
copyValue: persona.runtime,
displayValue: runtimeLabel(persona.runtime),
icon: Terminal,
label: "Runtime",
testId: "user-profile-runtime",
});
} else if (ownerPubkey) {
fields.push({
copyValue: ownerPubkey,
displayValue: "Declared owner verified",
icon: UserRound,
label: "Agent profile",
testId: "user-profile-agent-profile",
});
}
}

if (managedAgent) {
Expand All @@ -342,7 +345,7 @@ export function buildOwnerFields({
});
}

if (managedAgent?.acpCommand) {
if (managedAgent?.acpCommand && !isProviderManaged) {
fields.push({
copyValue: managedAgent.acpCommand,
displayValue: managedAgent.acpCommand,
Expand All @@ -352,7 +355,7 @@ export function buildOwnerFields({
});
}

if (managedAgent?.mcpCommand) {
if (managedAgent?.mcpCommand && !isProviderManaged) {
fields.push({
copyValue: managedAgent.mcpCommand,
displayValue: managedAgent.mcpCommand,
Expand All @@ -373,7 +376,7 @@ export function buildOwnerFields({
});
}

if (managedAgent) {
if (managedAgent && !isProviderManaged) {
fields.push({
displayValue: managedAgent.startOnAppLaunch ? "Yes" : "No",
icon: Server,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ export function ProfileSummaryView({
showDiagnosticsIngress={showDiagnosticsIngress}
showInstructionBlock={showInstructionBlock}
/>
{isOwner === true && managedAgent !== undefined ? (
{isOwner === true && managedAgent?.backend.type === "local" ? (
<div className="overflow-hidden rounded-2xl bg-muted/20">
<AgentConfigPanel
advancedMode="flat"
Expand Down
129 changes: 129 additions & 0 deletions desktop/tests/e2e/profile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,77 @@ async function addGenericAgent(
);
}

async function addProviderAgent(
page: Page,
channelName: string,
agentName: string,
): Promise<string> {
await page.getByTestId(`channel-${channelName}`).click();
await expect(page.getByTestId("chat-title")).toHaveText(channelName);
const channelId = await page
.getByTestId(`channel-${channelName}`)
.getAttribute("data-channel-id");
if (!channelId) {
throw new Error(`Channel ${channelName} is missing a data-channel-id.`);
}

return page.evaluate(
async ({ agentName, channelId }) => {
const invoke = (
window as Window & {
__BUZZ_E2E_INVOKE_MOCK_COMMAND__?: (
command: string,
payload?: Record<string, unknown>,
) => Promise<{ agent?: { pubkey: string } }>;
}
).__BUZZ_E2E_INVOKE_MOCK_COMMAND__;
if (!invoke) {
throw new Error("Mock bridge is not installed.");
}

const created = await invoke("create_managed_agent", {
input: {
name: agentName,
spawnAfterCreate: true,
systemPrompt: "Operate on the remote provider host.",
agentCommand: "claude-agent-acp",
acpCommand: "buzz-acp",
mcpCommand: "local-dev-mcp",
model: "local-fallback-model",
envVars: { PROVIDER_TEST_SECRET: "must-not-render" },
backend: {
type: "provider",
id: "remote-fleet",
config: {},
},
},
});
const pubkey = created.agent?.pubkey;
if (!pubkey) {
throw new Error(
"Mock provider agent creation did not return a pubkey.",
);
}

await invoke("add_channel_members", {
channelId,
pubkeys: [pubkey],
role: "bot",
});
await (
window as Window & {
__BUZZ_E2E_QUERY_CLIENT__?: {
invalidateQueries: () => Promise<void>;
};
}
).__BUZZ_E2E_QUERY_CLIENT__?.invalidateQueries();

return pubkey;
},
{ agentName, channelId },
);
}

async function waitForMockLiveSubscription(page: Page, channelName: string) {
await expect
.poll(async () => {
Expand Down Expand Up @@ -982,6 +1053,64 @@ test("restored Inbox deep link hides the back arrow", async ({ page }) => {
await expect(page.getByTestId("agent-session-thread-panel")).toHaveCount(0);
});

test("provider agent profile does not project local runtime configuration", async ({
page,
}) => {
await page.goto("/");
const agentPubkey = await addProviderAgent(
page,
"general",
"Remote Provider Agent",
);
await page.getByTestId("channel-general").click();
await waitForMockLiveSubscription(page, "general");

await page.evaluate(
({ pubkey }) => {
const emit = (
window as Window & {
__BUZZ_E2E_EMIT_MOCK_MESSAGE__?: (input: {
channelName: string;
content: string;
pubkey: string;
}) => unknown;
}
).__BUZZ_E2E_EMIT_MOCK_MESSAGE__;
if (!emit) {
throw new Error("Mock message emitter is unavailable.");
}
emit({
channelName: "general",
content: "Remote provider profile check",
pubkey,
});
},
{ pubkey: agentPubkey },
);

const messageRow = page
.getByTestId("message-row")
.filter({ hasText: "Remote provider profile check" });
await expect(messageRow).toBeVisible();
await messageRow.locator("button").first().click();

const panel = page.getByTestId("user-profile-panel");
await expect(panel).toBeVisible();
await expect(panel.getByTestId("user-profile-backend")).toContainText(
"remote-fleet",
);
await panel.getByRole("tab", { name: "Runtime" }).click();

await expect(panel.getByTestId("user-profile-runtime")).toHaveCount(0);
await expect(panel.getByTestId("user-profile-acp")).toHaveCount(0);
await expect(panel.getByTestId("user-profile-mcp")).toHaveCount(0);
await expect(panel.getByTestId("user-profile-start-on-launch")).toHaveCount(
0,
);
await expect(panel.getByText("local-fallback-model")).toHaveCount(0);
await expect(panel.getByText("must-not-render")).toHaveCount(0);
});

test("declared owner sees runtime tab for a remote relay agent", async ({
page,
}) => {
Expand Down