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
522 changes: 39 additions & 483 deletions desktop/src-tauri/src/managed_agents/config_bridge/reader.rs

Large diffs are not rendered by default.

497 changes: 497 additions & 0 deletions desktop/src-tauri/src/managed_agents/config_bridge/reader_tests.rs

Large diffs are not rendered by default.

309 changes: 251 additions & 58 deletions desktop/src/features/agents/ui/AgentConfigPanel.tsx

Large diffs are not rendered by default.

7 changes: 2 additions & 5 deletions desktop/src/features/agents/ui/CopyButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Copy } from "lucide-react";
import { toast } from "sonner";

import { copyTextToClipboard } from "@/shared/lib/clipboard";
import { Button, type ButtonProps } from "@/shared/ui/button";

export function CopyButton({
Expand All @@ -23,10 +23,7 @@ export function CopyButton({
return (
<Button
className={className}
onClick={async () => {
await navigator.clipboard.writeText(value);
toast.success("Copied to clipboard");
}}
onClick={() => copyTextToClipboard(value)}
size={size}
type="button"
variant={variant}
Expand Down
20 changes: 6 additions & 14 deletions desktop/src/features/messages/ui/MessageActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
Trash2,
} from "lucide-react";
import * as React from "react";
import { toast } from "sonner";

import { buildMessageLink } from "@/features/messages/lib/messageLink";
import { EmojiPicker } from "@/features/custom-emoji/ui/EmojiPicker";
Expand All @@ -29,6 +28,7 @@ import {
} from "@/features/messages/ui/useQuickReactionEmojis";
import { reactionEmojiUrl } from "@/shared/api/customEmoji";
import { cn } from "@/shared/lib/cn";
import { copyTextToClipboard } from "@/shared/lib/clipboard";
import { emojiDisplayName } from "@/shared/lib/emojiName";
import { rewriteRelayUrl } from "@/shared/lib/mediaUrl";
import { KIND_HUDDLE_STARTED } from "@/shared/constants/kinds";
Expand Down Expand Up @@ -57,17 +57,6 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip";
const ACTION_BUTTON_CLASS = "h-8 w-8 rounded-full p-0";
const ACTION_ICON_CLASS = "!h-4 !w-4";

function copyToClipboard(text: string, successMessage: string) {
void navigator.clipboard
.writeText(text)
.then(() => {
toast.success(successMessage);
})
.catch(() => {
toast.error("Failed to copy to clipboard");
});
}

function MoreActionsMenu({
channelId,
message,
Expand Down Expand Up @@ -199,7 +188,10 @@ function MoreActionsMenu({
{hasCopyActions ? (
<DropdownMenuItem
onClick={() => {
copyToClipboard(message.body, "Message copied to clipboard");
copyTextToClipboard(
message.body,
"Message copied to clipboard",
);
}}
>
<Copy className="h-4 w-4" />
Expand Down Expand Up @@ -228,7 +220,7 @@ function MoreActionsMenu({
messageId: message.id,
threadRootId: rootId,
});
copyToClipboard(link, "Link copied to clipboard");
copyTextToClipboard(link, "Link copied to clipboard");
}}
>
<Link2 className="h-4 w-4" />
Expand Down
47 changes: 19 additions & 28 deletions desktop/src/features/profile/ui/UserProfilePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -768,28 +768,24 @@ export function UserProfilePanel({
viewerIsOwner={viewerIsOwner}
/>
);
const {
agentInfoFields,
agentSettingsFields,
diagnosticsFields,
modelLabel,
} = useProfileFieldBuckets({
isBot,
isOwner,
managedAgent,
onOpenProfile,
ownerAvatarUrl: ownerAvatarProfile?.avatarUrl ?? null,
ownerDisplayName,
ownerHandle,
ownerProfilePubkey,
ownerPubkey,
persona: resolvedPersona,
presenceLoaded: presenceQuery.isSuccess,
presenceStatus,
profile,
pubkey: effectivePubkey,
relayAgent,
});
const { agentInfoFields, agentSettingsFields, diagnosticsFields } =
useProfileFieldBuckets({
isBot,
isOwner: viewerIsOwner,
managedAgent,
onOpenProfile,
ownerAvatarUrl: ownerAvatarProfile?.avatarUrl ?? null,
ownerDisplayName,
ownerHandle,
ownerProfilePubkey,
ownerPubkey,
persona: resolvedPersona,
presenceLoaded: presenceQuery.isSuccess,
presenceStatus,
profile,
pubkey: effectivePubkey,
relayAgent,
});
const isDiagnosticsLikeView = view === "diagnostics" || view === "logs";
const managedAgentLogContent = managedAgentLogQuery.data?.content ?? null;
const logHeaderSubtitle =
Expand Down Expand Up @@ -846,7 +842,6 @@ export function UserProfilePanel({
managedAgent={managedAgent}
memoriesLoading={memoryQuery.isLoading}
memoryCount={memoryCount}
modelLabel={modelLabel}
agentInfoFields={agentInfoFields}
agentSettingsFields={agentSettingsFields}
diagnosticsFields={diagnosticsFields}
Expand Down Expand Up @@ -876,11 +871,7 @@ export function UserProfilePanel({
<AgentInfoFocusedView metadataFields={agentInfoFields} />
) : null}
{view === "configuration" ? (
<AgentConfigurationFocusedView
fields={agentSettingsFields}
managedAgent={managedAgent}
modelLabel={modelLabel}
/>
<AgentConfigurationFocusedView fields={agentSettingsFields} />
) : null}
{view === "instructions" ? (
<AgentInstructionsFocusedView instruction={agentInstruction} />
Expand Down
68 changes: 3 additions & 65 deletions desktop/src/features/profile/ui/UserProfilePanelAgentDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ChevronRight, Cpu, MessageSquare } from "lucide-react";
import { ChevronRight, MessageSquare } from "lucide-react";

import type { ManagedAgent } from "@/shared/api/types";
import { Markdown } from "@/shared/ui/markdown";
import {
type ProfileField,
Expand All @@ -15,51 +14,33 @@ export const AGENT_DETAILS_FIELD_LABELS = new Set([

export function AgentConfigurationFocusedView({
fields,
managedAgent,
modelLabel,
}: {
fields: ProfileField[];
managedAgent: ManagedAgent | undefined;
modelLabel: string;
}) {
const runtimeConfigurationFields = fields.filter((field) =>
AGENT_DETAILS_FIELD_LABELS.has(field.label),
);

return (
<div className="pt-4">
<AgentConfigurationRows
fields={runtimeConfigurationFields}
managedAgent={managedAgent}
modelLabel={modelLabel}
showModel={true}
/>
<AgentConfigurationRows fields={runtimeConfigurationFields} />
</div>
);
}

function AgentConfigurationRows({
fields,
instruction,
managedAgent,
modelLabel,
showInstructionPlaceholder,
showModel,
}: {
fields: ProfileField[];
instruction?: string | null;
managedAgent: ManagedAgent | undefined;
modelLabel: string;
showInstructionPlaceholder?: boolean;
showModel: boolean;
}) {
const hasRows = hasAgentConfigurationRows({
fields,
instruction,
managedAgent,
modelLabel,
showInstructionPlaceholder,
showModel,
});

if (!hasRows) {
Expand All @@ -71,10 +52,7 @@ function AgentConfigurationRows({
<AgentDetailsRows
fields={fields}
instruction={instruction}
managedAgent={managedAgent}
modelLabel={modelLabel}
showInstructionPlaceholder={showInstructionPlaceholder}
showModel={showModel}
/>
</div>
);
Expand All @@ -83,26 +61,17 @@ function AgentConfigurationRows({
export function AgentDetailsRows({
fields,
instruction,
managedAgent,
modelLabel,
showInstructionPlaceholder,
showModel = false,
}: {
fields: ProfileField[];
instruction?: string | null;
managedAgent?: ManagedAgent | undefined;
modelLabel?: string;
showInstructionPlaceholder?: boolean;
showModel?: boolean;
}) {
const trimmedInstruction = instruction?.trim() ?? "";
const showInstructions =
trimmedInstruction.length > 0 || showInstructionPlaceholder === true;
const showModelRow =
showModel === true &&
(managedAgent !== undefined || (modelLabel?.trim().length ?? 0) > 0);

if (!showInstructions && !showModelRow && fields.length === 0) {
if (!showInstructions && fields.length === 0) {
return null;
}

Expand All @@ -112,10 +81,6 @@ export function AgentDetailsRows({
<AgentInstructionRow instruction={instruction ?? null} />
) : null}

{showModelRow ? (
<AgentModelRow modelLabel={modelLabel ?? "Auto"} />
) : null}

{fields.length > 0 ? <ProfileFieldRows fields={fields} /> : null}
</>
);
Expand All @@ -124,25 +89,17 @@ export function AgentDetailsRows({
function hasAgentConfigurationRows({
fields,
instruction,
managedAgent,
modelLabel,
showInstructionPlaceholder,
showModel,
}: {
fields: ProfileField[];
instruction?: string | null;
managedAgent: ManagedAgent | undefined;
modelLabel: string;
showInstructionPlaceholder?: boolean;
showModel: boolean;
}) {
const trimmedInstruction = instruction?.trim() ?? "";

return (
trimmedInstruction.length > 0 ||
showInstructionPlaceholder === true ||
(showModel === true &&
(managedAgent !== undefined || modelLabel.trim().length > 0)) ||
fields.length > 0
);
}
Expand Down Expand Up @@ -243,22 +200,3 @@ export function AgentInstructionsFocusedView({
</div>
);
}

function AgentModelRow({ modelLabel }: { modelLabel: string }) {
return (
<div
className="flex items-center gap-3 px-4 py-3"
data-testid="user-profile-model"
>
<span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-muted/60">
<Cpu className="h-4 w-4 text-muted-foreground" />
</span>
<span className="min-w-0 flex-1">
<span className="block text-xs font-medium text-foreground">Model</span>
<span className="mt-0.5 block truncate text-sm text-muted-foreground">
{modelLabel}
</span>
</span>
</div>
);
}
Loading
Loading