copy(desktop): the word "persona" leaves the UI (Phase 1B.4) (#1646)

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
Wes
2026-07-08 17:33:26 +00:00
committed by GitHub
co-authored by Brain
parent c145037aad
commit 41b187f936
26 changed files with 52 additions and 52 deletions
@@ -73,7 +73,7 @@ export function resolvePersonaRuntime(
return {
runtime: defaultRuntime,
warnings: [
`Persona is configured for runtime "${personaRuntimeId}" but it is not available. Using ${defaultRuntime.label} instead.`,
`This agent is configured for runtime "${personaRuntimeId}" but it is not available. Using ${defaultRuntime.label} instead.`,
],
isOverridden: true,
};
@@ -82,7 +82,7 @@ export function resolvePersonaRuntime(
return {
runtime: null,
warnings: [
`Persona is configured for runtime "${personaRuntimeId}" but it is not available, and no other runtimes were found.`,
`This agent is configured for runtime "${personaRuntimeId}" but it is not available, and no other runtimes were found.`,
],
isOverridden: false,
};
@@ -115,7 +115,7 @@ function provenanceSentence(
case "buzzExplicit":
return "Set in Buzz";
case "personaDefault":
return "Inherited from persona";
return "Inherited from template";
case "runtimeOverride":
return "Live override (this session only)";
case "harnessConstraint":
@@ -235,7 +235,7 @@ export function AgentInstanceEditDialog({
// The runtime id that will actually be active after submit. When inheriting,
// resolve from the LINKED PERSONA's runtime — that is what will run once the
// override is cleared. Deriving from agent.agentCommand here is wrong for a
// pinned agent that just toggled "Inherit runtime from persona": the override
// pinned agent that just toggled "Inherit runtime from template": the override
// (e.g. a Claude pin) is still present on the record, so it would resolve to
// the old pin instead of the persona's runtime, hiding required credentials.
// Fall back to the agent.agentCommand dual-match (command path, then id) only
@@ -131,7 +131,7 @@ export function BatchImportDialog({
<DialogContent className="max-w-2xl overflow-hidden p-0">
<div className="flex max-h-[85vh] flex-col">
<DialogHeader className="shrink-0 border-b border-border/60 px-6 py-5 pr-14">
<DialogTitle>Import Personas</DialogTitle>
<DialogTitle>Import Agents</DialogTitle>
<DialogDescription>
Found {personas.length} persona
{personas.length !== 1 ? "s" : ""} in {fileName || "archive"}.
@@ -828,7 +828,7 @@ export function CreateAgentDialog({
<EnvVarsEditor
disabled={createMutation.isPending}
fileSatisfiedKeys={fileSatisfiedEnvKeys}
helperText="Injected at spawn. Overrides the persona's env vars on collision."
helperText="Injected at spawn. Overrides the template's env vars on collision."
onChange={setEnvVars}
requiredKeys={requiredEnvKeys}
value={envVars}
@@ -70,7 +70,7 @@ export function EditAgentAdvancedFields({
}) {
return (
<div className="space-y-5 pt-2">
{/* Inherit runtime from persona */}
{/* Inherit runtime from template */}
{linkedPersona ? (
<div className="space-y-1.5">
<label
@@ -83,14 +83,14 @@ export function EditAgentAdvancedFields({
onChange={(event) => onInheritHarnessChange(event.target.checked)}
type="checkbox"
/>
Inherit runtime from persona
Inherit runtime from template
</label>
<p className="text-xs text-muted-foreground">
{inheritHarness
? `Uses the ${linkedPersona.displayName} persona's runtime${
? `Uses the ${linkedPersona.displayName} template's runtime${
linkedPersona.runtime ? ` (${linkedPersona.runtime})` : ""
}. Editing the persona and respawning propagates the new runtime.`
: "Pins this agent to a specific runtime command, overriding the persona's runtime."}
}. Editing the template and respawning propagates the new runtime.`
: "Pins this agent to a specific runtime command, overriding the template's runtime."}
</p>
</div>
) : null}
@@ -366,9 +366,9 @@ export function EditAgentAdvancedFields({
<EnvVarsEditor
disabled={disabled}
fileSatisfiedKeys={fileSatisfiedEnvKeys}
helperText="Per-agent env vars. Override the persona's vars on collision."
helperText="Per-agent env vars. Override the template's vars on collision."
inheritedFrom={inheritedEnvVars}
inheritedLabel="persona"
inheritedLabel="template"
onChange={onEnvVarsChange}
requiredKeys={requiredEnvKeys}
value={envVars}
@@ -424,7 +424,7 @@ export function EnvVarsEditor({
/**
* Render a masked preview of an inherited (persona) env value so the agent
* dialog can show "Overrides persona value •••• (last 4)" without exposing
* dialog can show "Overrides template value •••• (last 4)" without exposing
* the persona's actual secret to anyone viewing the agent UI. Empty values
* render as "(empty)" so the user can still tell the persona had a value
* set at all.
@@ -101,7 +101,7 @@ export function ModelPicker({
acpConfigOption: "from ACP config",
envVar: "from env",
configFile: "from config file",
personaDefault: "persona default",
personaDefault: "template default",
runtimeOverride: "live override",
};
return labels[origin] ?? null;
@@ -126,7 +126,7 @@ export function PersonaCatalogDetailsSheet({
<p className="text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground">
Type
</p>
<p className="mt-2 text-sm font-medium">Built-in persona</p>
<p className="mt-2 text-sm font-medium">Built-in agent</p>
</div>
<div className="rounded-xl border border-border/70 bg-card/70 p-4">
<p className="text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground">
@@ -282,7 +282,7 @@ function PersonaCatalogDetail({ persona }: { persona: AgentPersona }) {
items={[
{
label: "Type",
value: persona.isBuiltIn ? "Built-in persona" : "Custom persona",
value: persona.isBuiltIn ? "Built-in agent" : "Custom agent",
},
{
label: "Preferred model",
@@ -28,11 +28,11 @@ export function PersonaDeleteDialog({
<AlertDialog onOpenChange={onOpenChange} open={open}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete persona?</AlertDialogTitle>
<AlertDialogTitle>Delete agent?</AlertDialogTitle>
<AlertDialogDescription>
{persona
? `Delete ${persona.displayName}. Existing agents keep their copied settings, but this template will no longer be available for new deployments.`
: "Delete this persona."}
: "Delete this agent."}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
@@ -131,7 +131,7 @@ export function PersonaImportUpdateDialog({
<Dialog onOpenChange={onOpenChange} open={open}>
<DialogContent className="flex max-h-[85vh] max-w-3xl flex-col overflow-hidden p-0">
<DialogHeader className="shrink-0 space-y-1 border-b border-border/60 px-6 py-5 pr-14">
<DialogTitle>Import persona</DialogTitle>
<DialogTitle>Import agent</DialogTitle>
</DialogHeader>
<div className="min-h-0 flex-1 overflow-y-auto px-6 py-4">
@@ -363,7 +363,7 @@ export function TeamDialog({
</div>
<div className="space-y-2">
<span className="text-sm font-medium">Personas</span>
<span className="text-sm font-medium">Agents</span>
<p className="text-xs text-muted-foreground">
Select the personas to include in this team.
</p>
@@ -384,7 +384,7 @@ export function TeamDialog({
<div
className="max-h-60 space-y-1 overflow-y-auto rounded-lg border border-border/70 p-2"
role="listbox"
aria-label="Personas"
aria-label="Agents"
aria-multiselectable="true"
>
{orderedPersonas.map((persona) => {
@@ -148,7 +148,7 @@ export function TeamImportDialog({
</div>
<div className="space-y-1">
<p className="text-sm font-medium">Personas to import</p>
<p className="text-sm font-medium">Agents to import</p>
<p className="text-xs text-muted-foreground">
Each persona will be created, then grouped into a new team.
</p>
@@ -232,7 +232,7 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
agents={unknown}
collapsed={collapsed}
groupKey="__unknown__"
label="Unknown Persona"
label="Unknown Agent"
startingAgentPubkey={startingAgentPubkey}
onToggle={toggle}
onOpenAgentProfile={onOpenAgentProfile}
@@ -1,14 +1,14 @@
export const personaLibraryCopy = {
title: "My agents",
description:
"The personas you have chosen for this app. Use them to create teams and launch agents.",
"The agents you have chosen for this app. Use them to create teams and launch agents.",
chooseFromCatalog: "Choose from catalog",
createNew: "New agent",
customAgent: "Custom agent",
import: "Import",
emptyTitle: "No agents yet",
emptyDescription:
"Choose one from Agent Catalog, add your own persona, or import one to get started.",
"Choose one from Agent Catalog, create your own, or import one to get started.",
emptyImportHint:
"Or drop a .persona.md, .persona.json, .persona.png, or .zip file here to import.",
} as const;
@@ -30,14 +30,14 @@ export const personaCatalogCopy = {
availableState: "Available",
detailSelectedTitle: "Selected for My Agents",
detailSelectedDescription:
"Turn this off to remove the persona from teams and agent creation in this app.",
"Turn this off to remove the agent from teams and agent creation in this app.",
detailAvailableTitle: "Available in Agent Catalog",
detailAvailableDescription:
"Turn this on to make the persona available for teams and agent creation.",
"Turn this on to make the agent available for teams and agent creation.",
useAction: "Add agent",
addedAction: "Added to My Agents",
teamEmptyState:
"No personas in My Agents yet. Create one or choose one from Agent Catalog first.",
"No agents in My Agents yet. Create one or choose one from Agent Catalog first.",
} as const;
export function getPersonaCatalogSelectionActionCopy(isActive: boolean) {
@@ -119,7 +119,7 @@ export function hasMissingRequiredEnvKey(
* The ONE exception is the inherit-TRANSITION-from-a-harness-pin: a previously
* harness-pinned agent (e.g. Claude — `agent.agentCommandOverride != null` at
* dialog open) has its `provider` cleared and carries no persona credential,
* then the user checks "Inherit runtime from persona" for a provider-backed
* then the user checks "Inherit runtime from template" for a provider-backed
* persona (e.g. buzz-agent/Anthropic). Persisting the local (empty) provider +
* credential-less env would save an agent that fails readiness on next start.
* Only in that case — inheriting AND the local provider is empty AND the agent
@@ -232,7 +232,7 @@ export function usePersonaActions() {
return true;
} catch (error) {
setPersonaErrorMessage(
error instanceof Error ? error.message : "Failed to save persona.",
error instanceof Error ? error.message : "Failed to save agent.",
);
return false;
} finally {
@@ -248,7 +248,7 @@ export function usePersonaActions() {
setPersonaToDelete(null);
} catch (error) {
setPersonaErrorMessage(
error instanceof Error ? error.message : "Failed to delete persona.",
error instanceof Error ? error.message : "Failed to delete agent.",
);
}
}
@@ -271,8 +271,8 @@ export function usePersonaActions() {
error instanceof Error
? error.message
: active
? "Failed to select persona for My Agents."
: "Failed to deselect persona from My Agents.",
? "Failed to select agent for My Agents."
: "Failed to deselect agent from My Agents.",
);
}
}
@@ -291,11 +291,11 @@ export function usePersonaActions() {
setBatchImportResult(result);
setBatchImportFileName(fileName);
} else {
setPersonaErrorMessage("No valid personas found in file.");
setPersonaErrorMessage("No valid agents found in file.");
}
} catch (err) {
setPersonaErrorMessage(
err instanceof Error ? err.message : "Failed to parse persona file.",
err instanceof Error ? err.message : "Failed to parse agent file.",
);
}
}
@@ -310,7 +310,7 @@ export function usePersonaActions() {
},
onError: (error) => {
setPersonaErrorMessage(
error instanceof Error ? error.message : "Failed to export persona.",
error instanceof Error ? error.message : "Failed to export agent.",
);
},
});
@@ -48,7 +48,7 @@ export function usePersonaImportActions(
(candidate) => candidate.id === personaId,
);
if (!persona) {
const message = "Persona not found. Refresh and try again.";
const message = "Agent not found. Refresh and try again.";
feedback.setPersonaErrorMessage(message);
throw new Error(message);
}
@@ -56,7 +56,7 @@ export function usePersonaImportActions(
try {
const result = await parsePersonaFiles(fileBytes, fileName);
if (result.personas.length === 0) {
const message = "No valid personas found in file.";
const message = "No valid agents found in file.";
feedback.setPersonaErrorMessage(message);
throw new Error(message);
}
@@ -66,7 +66,7 @@ export function usePersonaImportActions(
feedback.setPersonaDialogState(null);
} catch (err) {
const message =
err instanceof Error ? err.message : "Failed to parse persona file.";
err instanceof Error ? err.message : "Failed to parse agent file.";
feedback.setPersonaErrorMessage(message);
throw err instanceof Error ? err : new Error(message);
}
@@ -158,7 +158,7 @@ export function useTeamActions(
actions.setActionErrorMessage(null);
setTeamDialogState({
title: "Create team",
description: "Group personas together for quick deployment to channels.",
description: "Group agents together for quick deployment to channels.",
submitLabel: "Create team",
initialValues: {
name: "",
@@ -433,7 +433,7 @@ export function AddChannelBotDialog({
? "Loading runtimes..."
: providers.length === 0
? "No runtimes found"
: (selectedRuntime?.label ?? "Use persona defaults");
: (selectedRuntime?.label ?? "Use agent defaults");
const addButtonLabel = createBotsMutation.isPending
? selectedCount > 1
? `Adding ${selectedCount}...`
@@ -447,7 +447,7 @@ export function AddChannelBotDialog({
<ChooserDialogContent
className="max-w-3xl"
data-testid="add-channel-bot-dialog"
description="Select any combination of saved personas, or turn on Generic for a one-off custom agent."
description="Select any combination of saved agents, or turn on Generic for a one-off custom agent."
footer={
<>
<Button
@@ -567,8 +567,8 @@ export function AddChannelBotDialog({
</DropdownMenu>
<p className="text-xs text-muted-foreground">
{isOverrideActive
? "All agents will use this runtime, overriding persona preferences."
: "Each persona uses its preferred runtime. Choose a runtime above to override all."}
? "All agents will use this runtime, overriding their configured preferences."
: "Each agent uses its preferred runtime. Choose a runtime above to override all."}
</p>
</div>
@@ -118,7 +118,7 @@ export function AddChannelBotPersonasSection({
<div className="space-y-3">
<div className="space-y-3">
<div>
<div className="text-sm font-medium">Personas</div>
<div className="text-sm font-medium">Agents</div>
<p className="text-xs text-muted-foreground">
Toggle as many as you want. Each selected persona is added as its
own agent. Hover a persona to preview its role.
@@ -215,7 +215,7 @@ export function AddChannelBotPersonasSection({
</TooltipProvider>
{isLoading ? (
<p className="text-xs text-muted-foreground">Loading personas...</p>
<p className="text-xs text-muted-foreground">Loading agents...</p>
) : null}
</div>
</div>
@@ -96,7 +96,7 @@ async function ensureWelcomeGuidePersonaActive() {
(persona) => persona.id === WELCOME_GUIDE_PERSONA_ID,
);
if (!guidePersona) {
throw new Error(`${WELCOME_GUIDE_AGENT_NAME} persona not found.`);
throw new Error(`${WELCOME_GUIDE_AGENT_NAME} agent not found.`);
}
if (!guidePersona.isActive) {
await setPersonaActive(WELCOME_GUIDE_PERSONA_ID, true);
+1 -1
View File
@@ -1445,7 +1445,7 @@ function buildMockConfigSurface(pubkey: string): {
// Mixed-provenance showcase — top-level rows carry different origins so the
// panel witnesses distinct provenance labels in one frame: "Set in Buzz",
// "Inherited from persona", "From config file (...)" and
// "Inherited from template", "From config file (...)" and
// "From environment variable (...)".
const multiOriginSurface = {
runtimeId: "goose",
+2 -2
View File
@@ -336,7 +336,7 @@ test("catalog detail pane shows the full persona details", async ({ page }) => {
"You are Fizz.",
);
await expect(page.getByTestId("persona-catalog-detail-pane")).toContainText(
"Built-in persona",
"Built-in agent",
);
await expect(page.getByTestId("persona-catalog-detail-pane")).toContainText(
"Preferred model",
@@ -409,7 +409,7 @@ test("custom personas can be shown in the agent catalog", async ({ page }) => {
).toContainText("Analyst");
await selectCatalogPersona(page, analystPersonaId);
await expect(page.getByTestId("persona-catalog-detail-pane")).toContainText(
"Custom persona",
"Custom agent",
);
await expect(
page.getByTestId(`persona-catalog-use-agent-target-${analystPersonaId}`),
@@ -210,7 +210,7 @@ test.describe("config bridge screenshots", () => {
// Multiple distinct provenance origins visible at once.
await expect(panel.getByText("Set in Buzz").first()).toBeVisible();
await expect(panel.getByText("Inherited from persona")).toBeVisible();
await expect(panel.getByText("Inherited from template")).toBeVisible();
await expect(
panel.getByText("From environment variable (GOOSE_MODE)"),
).toBeVisible();