(null)
@@ -472,7 +476,7 @@ function CreateProfileDialog({
}
setName('')
- setCloneFromDefault(true)
+ setCloneFrom('default')
setError(null)
setSaving(false)
}, [open])
@@ -493,7 +497,7 @@ function CreateProfileDialog({
setError(null)
try {
- await onCreate(trimmed, cloneFromDefault)
+ await onCreate(trimmed, cloneFrom)
onClose()
} catch (err) {
setError(err instanceof Error ? err.message : p.failedCreate)
@@ -528,18 +532,25 @@ function CreateProfileDialog({
-
+
+
+
+
{p.cloneFromDesc}
+
{error && (
diff --git a/apps/desktop/src/i18n/en.ts b/apps/desktop/src/i18n/en.ts
index 2ab95b3e61f..dc8dfc72777 100644
--- a/apps/desktop/src/i18n/en.ts
+++ b/apps/desktop/src/i18n/en.ts
@@ -903,6 +903,9 @@ export const en: Translations = {
deleting: 'Deleting...',
createDesc: 'Profiles are independent Hermes environments: separate config, skills, and SOUL.md.',
nameLabel: 'Name',
+ cloneFrom: 'Clone from',
+ cloneFromNone: 'None (blank)',
+ cloneFromDesc: 'Copies config, skills, and SOUL.md from the selected source profile.',
cloneFromDefault: 'Clone from default',
cloneFromDefaultDesc: 'Copy config, skills, and SOUL.md from your default profile.',
invalidName: hint => `Invalid name. ${hint}`,
diff --git a/apps/desktop/src/i18n/ja.ts b/apps/desktop/src/i18n/ja.ts
index a44019045fe..cae9539bccc 100644
--- a/apps/desktop/src/i18n/ja.ts
+++ b/apps/desktop/src/i18n/ja.ts
@@ -1041,6 +1041,9 @@ export const ja = defineLocale({
deleting: '削除中...',
createDesc: 'プロファイルは独立した Hermes 環境です:設定、スキル、SOUL.md が別々になります。',
nameLabel: '名前',
+ cloneFrom: '複製元',
+ cloneFromNone: 'なし(空)',
+ cloneFromDesc: '選択したプロファイルから設定、スキル、SOUL.md をコピーします。',
cloneFromDefault: 'デフォルトプロファイルから設定を複製',
cloneFromDefaultDesc: 'デフォルトプロファイルから設定、スキル、SOUL.md をコピーします。',
invalidName: hint => `無効なプロファイル名。${hint}`,
diff --git a/apps/desktop/src/i18n/types.ts b/apps/desktop/src/i18n/types.ts
index 1f65dc57287..44e03e87a97 100644
--- a/apps/desktop/src/i18n/types.ts
+++ b/apps/desktop/src/i18n/types.ts
@@ -695,6 +695,9 @@ export interface Translations {
deleting: string
createDesc: string
nameLabel: string
+ cloneFrom: string
+ cloneFromNone: string
+ cloneFromDesc: string
cloneFromDefault: string
cloneFromDefaultDesc: string
invalidName: (hint: string) => string
diff --git a/apps/desktop/src/i18n/zh-hant.ts b/apps/desktop/src/i18n/zh-hant.ts
index c7bdf3ba6da..e28091a9d93 100644
--- a/apps/desktop/src/i18n/zh-hant.ts
+++ b/apps/desktop/src/i18n/zh-hant.ts
@@ -999,6 +999,9 @@ export const zhHant = defineLocale({
deleting: '刪除中…',
createDesc: '設定檔是獨立的 Hermes 環境:各自擁有獨立的設定、技能和 SOUL.md。',
nameLabel: '名稱',
+ cloneFrom: '複製來源',
+ cloneFromNone: '無(空白)',
+ cloneFromDesc: '從選取的來源設定檔複製設定、技能和 SOUL.md。',
cloneFromDefault: '從預設設定檔複製設定',
cloneFromDefaultDesc: '從您的預設設定檔複製設定、技能和 SOUL.md。',
invalidName: hint => `設定檔名稱無效。${hint}`,
diff --git a/apps/desktop/src/i18n/zh.ts b/apps/desktop/src/i18n/zh.ts
index a047c0d44cd..0c073ba1e77 100644
--- a/apps/desktop/src/i18n/zh.ts
+++ b/apps/desktop/src/i18n/zh.ts
@@ -1092,6 +1092,9 @@ export const zh: Translations = {
deleting: '删除中…',
createDesc: '配置档案是相互独立的 Hermes 环境:各自拥有独立的配置、技能和 SOUL.md。',
nameLabel: '名称',
+ cloneFrom: '克隆来源',
+ cloneFromNone: '无(空白)',
+ cloneFromDesc: '从选中的来源配置档案复制配置、技能和 SOUL.md。',
cloneFromDefault: '从默认档案克隆',
cloneFromDefaultDesc: '从你的默认配置档案复制配置、技能和 SOUL.md。',
invalidName: hint => `名称无效。${hint}`,
diff --git a/apps/desktop/src/types/hermes.ts b/apps/desktop/src/types/hermes.ts
index f90e31c53bb..86dc41862db 100644
--- a/apps/desktop/src/types/hermes.ts
+++ b/apps/desktop/src/types/hermes.ts
@@ -470,7 +470,7 @@ export interface CronJobUpdates {
export interface ProfileCreatePayload {
clone_all?: boolean
- clone_from?: string
+ clone_from?: null | string
clone_from_default?: boolean
name: string
no_skills?: boolean
diff --git a/hermes_cli/web_server.py b/hermes_cli/web_server.py
index 527aae07cf2..78a327a4767 100644
--- a/hermes_cli/web_server.py
+++ b/hermes_cli/web_server.py
@@ -8518,15 +8518,13 @@ async def scan_skill_hub(identifier: str = ""):
class ProfileCreate(BaseModel):
name: str
+ clone_from: Optional[str] = None
+ # Backward compatibility for older dashboard/desktop clients. New clients
+ # send clone_from="default" (or another profile name) explicitly.
clone_from_default: bool = False
clone_all: bool = False
no_skills: bool = False
description: Optional[str] = None
- # Explicit source profile to clone from (e.g. duplicating an existing
- # profile). When set, it takes precedence over ``clone_from_default``,
- # which always sources from "default". ``clone_all`` still selects a full
- # state copytree vs. a config/skills/SOUL copy.
- clone_from: Optional[str] = None
provider: Optional[str] = None
model: Optional[str] = None
# Profile-builder additions — all optional, all applied best-effort AFTER
@@ -8798,10 +8796,16 @@ async def create_profile_endpoint(body: ProfileCreate):
clone = True
clone_from = explicit_source
clone_config = not body.clone_all
+ elif body.clone_all:
+ # Preserve the dashboard's historical clone-all behavior: a full-copy
+ # request with no explicit dropdown source copies from default.
+ clone = True
+ clone_from = "default"
+ clone_config = False
else:
- clone = body.clone_from_default or body.clone_all
+ clone = body.clone_from_default
clone_from = "default" if clone else None
- clone_config = body.clone_from_default and not body.clone_all
+ clone_config = clone
try:
path = profiles_mod.create_profile(
name=body.name,
diff --git a/tests/hermes_cli/test_web_server.py b/tests/hermes_cli/test_web_server.py
index 73d5a1a667f..01a76b92816 100644
--- a/tests/hermes_cli/test_web_server.py
+++ b/tests/hermes_cli/test_web_server.py
@@ -2633,7 +2633,7 @@ class TestNewEndpoints:
resp = self.client.post(
"/api/profiles",
- json={"name": "writer", "clone_from_default": False},
+ json={"name": "writer", "clone_from": None},
)
assert resp.status_code == 200
@@ -2641,7 +2641,7 @@ class TestNewEndpoints:
assert wrapper_path.exists()
assert wrapper_path.read_text() == '#!/bin/sh\nexec hermes -p writer "$@"\n'
- def test_profiles_create_with_clone_from_default_copies_default_skills(self, monkeypatch):
+ def test_profiles_create_with_clone_from_copies_source_skills(self, monkeypatch):
from hermes_constants import get_hermes_home
import hermes_cli.profiles as profiles_mod
@@ -2652,7 +2652,7 @@ class TestNewEndpoints:
resp = self.client.post(
"/api/profiles",
- json={"name": "cloned", "clone_from_default": True},
+ json={"name": "cloned", "clone_from": "default"},
)
assert resp.status_code == 200
@@ -2685,6 +2685,28 @@ class TestNewEndpoints:
)
assert cloned_skill.exists()
+ def test_profiles_create_clone_all_from_named_source(self, monkeypatch):
+ from hermes_constants import get_hermes_home
+ import hermes_cli.profiles as profiles_mod
+
+ monkeypatch.setattr(profiles_mod, "create_wrapper_script", lambda name: None)
+
+ assert self.client.post("/api/profiles", json={"name": "full-src"}).status_code == 200
+ source_dir = get_hermes_home() / "profiles" / "full-src"
+ (source_dir / "config.yaml").write_text("model:\n provider: source-only\n", encoding="utf-8")
+ (source_dir / "workspace" / "artifact.txt").parent.mkdir(parents=True, exist_ok=True)
+ (source_dir / "workspace" / "artifact.txt").write_text("copied", encoding="utf-8")
+
+ resp = self.client.post(
+ "/api/profiles",
+ json={"name": "full-copy", "clone_from": "full-src", "clone_all": True},
+ )
+
+ assert resp.status_code == 200
+ target_dir = get_hermes_home() / "profiles" / "full-copy"
+ assert (target_dir / "config.yaml").read_text(encoding="utf-8") == "model:\n provider: source-only\n"
+ assert (target_dir / "workspace" / "artifact.txt").read_text(encoding="utf-8") == "copied"
+
def test_profiles_create_without_clone_seeds_bundled_skills(self, monkeypatch):
from hermes_constants import get_hermes_home
import hermes_cli.profiles as profiles_mod
@@ -2701,7 +2723,7 @@ class TestNewEndpoints:
resp = self.client.post(
"/api/profiles",
- json={"name": "fresh", "clone_from_default": False},
+ json={"name": "fresh", "clone_from": None},
)
assert resp.status_code == 200
diff --git a/web/src/i18n/af.ts b/web/src/i18n/af.ts
index 5d5dc004222..2a8af6f0843 100644
--- a/web/src/i18n/af.ts
+++ b/web/src/i18n/af.ts
@@ -286,8 +286,8 @@ export const af: Translations = {
nameRequired: "Naam word vereis",
nameRule:
"Slegs kleinletters, syfers, _ en -; moet met 'n letter of syfer begin; tot 64 karakters.",
- invalidName: "Ongeldige profielnaam",
- cloneFromDefault: "Kloon konfigurasie vanaf verstekprofiel",
+ invalidName: "Ongeldige profielnaam", cloneFrom: "Kloon konfigurasie vanaf profiel",
+ cloneFromNone: "Geen (leeg)",
allProfiles: "Profiele",
noProfiles: "Geen profiele gevind nie.",
defaultBadge: "verstek",
diff --git a/web/src/i18n/de.ts b/web/src/i18n/de.ts
index e2eb1429c09..11b4a095cb6 100644
--- a/web/src/i18n/de.ts
+++ b/web/src/i18n/de.ts
@@ -286,8 +286,8 @@ export const de: Translations = {
nameRequired: "Name ist erforderlich",
nameRule:
"Nur Kleinbuchstaben, Ziffern, _ und -; muss mit einem Buchstaben oder einer Ziffer beginnen; maximal 64 Zeichen.",
- invalidName: "Ungültiger Profilname",
- cloneFromDefault: "Konfiguration vom Standardprofil klonen",
+ invalidName: "Ungültiger Profilname", cloneFrom: "Konfiguration klonen von",
+ cloneFromNone: "Keine (leer)",
allProfiles: "Profile",
noProfiles: "Keine Profile gefunden.",
defaultBadge: "Standard",
diff --git a/web/src/i18n/en.ts b/web/src/i18n/en.ts
index 853eeb4a9c1..10fd8df4300 100644
--- a/web/src/i18n/en.ts
+++ b/web/src/i18n/en.ts
@@ -297,7 +297,8 @@ export const en: Translations = {
nameRule:
"Lowercase letters, digits, _ and - only; must start with a letter or digit; up to 64 characters.",
invalidName: "Invalid profile name",
- cloneFromDefault: "Clone config from default profile",
+ cloneFrom: "Clone config from",
+ cloneFromNone: "None (blank)",
allProfiles: "Profiles",
noProfiles: "No profiles found.",
defaultBadge: "default",
diff --git a/web/src/i18n/es.ts b/web/src/i18n/es.ts
index 421837007ca..598e0a3ad24 100644
--- a/web/src/i18n/es.ts
+++ b/web/src/i18n/es.ts
@@ -287,7 +287,8 @@ export const es: Translations = {
nameRule:
"Solo letras minúsculas, dígitos, _ y -; debe comenzar con una letra o dígito; hasta 64 caracteres.",
invalidName: "Nombre de perfil no válido",
- cloneFromDefault: "Clonar configuración del perfil predeterminado",
+ cloneFrom: "Clonar desde el perfil",
+ cloneFromNone: "Ninguno (vacío)",
allProfiles: "Perfiles",
noProfiles: "No se encontraron perfiles.",
defaultBadge: "predeterminado",
diff --git a/web/src/i18n/fr.ts b/web/src/i18n/fr.ts
index 4887dc9c07e..659700a5864 100644
--- a/web/src/i18n/fr.ts
+++ b/web/src/i18n/fr.ts
@@ -287,7 +287,8 @@ export const fr: Translations = {
nameRule:
"Lettres minuscules, chiffres, _ et - uniquement ; doit commencer par une lettre ou un chiffre ; jusqu'à 64 caractères.",
invalidName: "Nom de profil invalide",
- cloneFromDefault: "Cloner la configuration du profil par défaut",
+ cloneFrom: "Cloner depuis le profil",
+ cloneFromNone: "Aucun (vide)",
allProfiles: "Profils",
noProfiles: "Aucun profil trouvé.",
defaultBadge: "défaut",
diff --git a/web/src/i18n/ga.ts b/web/src/i18n/ga.ts
index 6f71635b3cb..214d69373a1 100644
--- a/web/src/i18n/ga.ts
+++ b/web/src/i18n/ga.ts
@@ -294,8 +294,8 @@ export const ga: Translations = {
nameRequired: "Tá ainm riachtanach",
nameRule:
"Litreacha cás íochtair, digití, _ agus - amháin; caithfidh tús a chur le litir nó digit; suas le 64 carachtar.",
- invalidName: "Ainm próifíle neamhbhailí",
- cloneFromDefault: "Clónáil cumraíocht ón bpróifíl réamhshocraithe",
+ invalidName: "Ainm próifíle neamhbhailí", cloneFrom: "Clónáil cumraíocht ón bpróifíl",
+ cloneFromNone: "Dada (folamh)",
allProfiles: "Próifílí",
noProfiles: "Níor aimsíodh próifílí.",
defaultBadge: "réamhshocraithe",
diff --git a/web/src/i18n/hu.ts b/web/src/i18n/hu.ts
index a413820744e..cf9d121a06a 100644
--- a/web/src/i18n/hu.ts
+++ b/web/src/i18n/hu.ts
@@ -286,8 +286,8 @@ export const hu: Translations = {
nameRequired: "A név kötelező",
nameRule:
"Csak kisbetűk, számjegyek, _ és - karakterek; betűvel vagy számjeggyel kell kezdődnie; legfeljebb 64 karakter.",
- invalidName: "Érvénytelen profilnév",
- cloneFromDefault: "Konfiguráció klónozása az alapértelmezett profilból",
+ invalidName: "Érvénytelen profilnév", cloneFrom: "Konfiguráció klónozása ebből a profilból",
+ cloneFromNone: "Nincs (üres)",
allProfiles: "Profilok",
noProfiles: "Nem található profil.",
defaultBadge: "alapértelmezett",
diff --git a/web/src/i18n/it.ts b/web/src/i18n/it.ts
index 61ca8b7bb8e..777f913075d 100644
--- a/web/src/i18n/it.ts
+++ b/web/src/i18n/it.ts
@@ -286,8 +286,8 @@ export const it: Translations = {
nameRequired: "Il nome è obbligatorio",
nameRule:
"Solo lettere minuscole, cifre, _ e -; deve iniziare con una lettera o cifra; fino a 64 caratteri.",
- invalidName: "Nome del profilo non valido",
- cloneFromDefault: "Clona la configurazione dal profilo predefinito",
+ invalidName: "Nome del profilo non valido", cloneFrom: "Clona configurazione dal profilo",
+ cloneFromNone: "Nessuno (vuoto)",
allProfiles: "Profili",
noProfiles: "Nessun profilo trovato.",
defaultBadge: "predefinito",
diff --git a/web/src/i18n/ja.ts b/web/src/i18n/ja.ts
index e3db6b9a257..eb0f237a86c 100644
--- a/web/src/i18n/ja.ts
+++ b/web/src/i18n/ja.ts
@@ -285,8 +285,8 @@ export const ja: Translations = {
nameRequired: "名前は必須です",
nameRule:
"小文字、数字、_ および - のみ使用可能。最初は文字または数字で始める必要があります。最大 64 文字。",
- invalidName: "無効なプロファイル名",
- cloneFromDefault: "デフォルトプロファイルから設定を複製",
+ invalidName: "無効なプロファイル名", cloneFrom: "プロファイルから複製",
+ cloneFromNone: "なし(空)",
allProfiles: "プロファイル",
noProfiles: "プロファイルが見つかりません。",
defaultBadge: "デフォルト",
diff --git a/web/src/i18n/ko.ts b/web/src/i18n/ko.ts
index b624938f8df..44f689aa5f2 100644
--- a/web/src/i18n/ko.ts
+++ b/web/src/i18n/ko.ts
@@ -285,8 +285,8 @@ export const ko: Translations = {
nameRequired: "이름은 필수입니다",
nameRule:
"소문자, 숫자, _ 및 - 만 사용 가능합니다. 문자나 숫자로 시작해야 하며 최대 64자입니다.",
- invalidName: "잘못된 프로필 이름입니다",
- cloneFromDefault: "기본 프로필에서 설정 복제",
+ invalidName: "잘못된 프로필 이름입니다", cloneFrom: "프로필에서 복제",
+ cloneFromNone: "없음 (빈 상태)",
allProfiles: "프로필",
noProfiles: "프로필을 찾을 수 없습니다.",
defaultBadge: "기본",
diff --git a/web/src/i18n/pt.ts b/web/src/i18n/pt.ts
index 109027bc775..7ad8f15b9ca 100644
--- a/web/src/i18n/pt.ts
+++ b/web/src/i18n/pt.ts
@@ -287,7 +287,8 @@ export const pt: Translations = {
nameRule:
"Apenas letras minúsculas, dígitos, _ e -; deve começar com letra ou dígito; até 64 caracteres.",
invalidName: "Nome de perfil inválido",
- cloneFromDefault: "Clonar configuração do perfil predefinido",
+ cloneFrom: "Clonar a partir do perfil",
+ cloneFromNone: "Nenhum (vazio)",
allProfiles: "Perfis",
noProfiles: "Não foram encontrados perfis.",
defaultBadge: "predefinido",
diff --git a/web/src/i18n/ru.ts b/web/src/i18n/ru.ts
index 51eaf774c54..8f7fcab6126 100644
--- a/web/src/i18n/ru.ts
+++ b/web/src/i18n/ru.ts
@@ -286,8 +286,8 @@ export const ru: Translations = {
nameRequired: "Имя обязательно",
nameRule:
"Только строчные буквы, цифры, _ и -; должно начинаться с буквы или цифры; до 64 символов.",
- invalidName: "Недопустимое имя профиля",
- cloneFromDefault: "Клонировать конфигурацию из профиля по умолчанию",
+ invalidName: "Недопустимое имя профиля", cloneFrom: "Клонировать конфигурацию из профиля",
+ cloneFromNone: "Нет (пусто)",
allProfiles: "Профили",
noProfiles: "Профили не найдены.",
defaultBadge: "по умолчанию",
diff --git a/web/src/i18n/tr.ts b/web/src/i18n/tr.ts
index 85910c88e4a..c597e3d6852 100644
--- a/web/src/i18n/tr.ts
+++ b/web/src/i18n/tr.ts
@@ -286,8 +286,8 @@ export const tr: Translations = {
nameRequired: "Ad gereklidir",
nameRule:
"Yalnızca küçük harfler, rakamlar, _ ve - kullanılabilir; harf veya rakamla başlamalı; en fazla 64 karakter.",
- invalidName: "Geçersiz profil adı",
- cloneFromDefault: "Varsayılan profilden yapılandırmayı klonla",
+ invalidName: "Geçersiz profil adı", cloneFrom: "Profilden yapılandırmayı klonla",
+ cloneFromNone: "Hiçbiri (boş)",
allProfiles: "Profiller",
noProfiles: "Profil bulunamadı.",
defaultBadge: "varsayılan",
diff --git a/web/src/i18n/types.ts b/web/src/i18n/types.ts
index aecb863544e..68a5c569377 100644
--- a/web/src/i18n/types.ts
+++ b/web/src/i18n/types.ts
@@ -354,7 +354,8 @@ export interface Translations {
nameRequired: string;
nameRule: string;
invalidName: string;
- cloneFromDefault: string;
+ cloneFrom: string;
+ cloneFromNone: string;
allProfiles: string;
noProfiles: string;
defaultBadge: string;
diff --git a/web/src/i18n/uk.ts b/web/src/i18n/uk.ts
index ce1a4babfec..1382c1b2bf1 100644
--- a/web/src/i18n/uk.ts
+++ b/web/src/i18n/uk.ts
@@ -287,7 +287,8 @@ export const uk: Translations = {
nameRule:
"Лише малі літери, цифри, _ та -; має починатися з літери або цифри; до 64 символів.",
invalidName: "Недопустима назва профілю",
- cloneFromDefault: "Клонувати конфігурацію з профілю за замовчуванням",
+ cloneFrom: "Клонувати з профілю",
+ cloneFromNone: "Жоден (порожній)",
allProfiles: "Профілі",
noProfiles: "Профілів не знайдено.",
defaultBadge: "за замовчуванням",
diff --git a/web/src/i18n/zh-hant.ts b/web/src/i18n/zh-hant.ts
index e2c4ff7252f..09f611bb558 100644
--- a/web/src/i18n/zh-hant.ts
+++ b/web/src/i18n/zh-hant.ts
@@ -285,8 +285,8 @@ export const zhHant: Translations = {
nameRequired: "名稱為必填",
nameRule:
"僅允許小寫字母、數字、底線及連字號;首字必須為字母或數字;最多 64 個字元。",
- invalidName: "設定檔名稱無效",
- cloneFromDefault: "從預設設定檔複製設定",
+ invalidName: "設定檔名稱無效", cloneFrom: "從設定檔複製",
+ cloneFromNone: "無(空白)",
allProfiles: "設定檔",
noProfiles: "找不到設定檔。",
defaultBadge: "預設",
diff --git a/web/src/i18n/zh.ts b/web/src/i18n/zh.ts
index d60dea816e5..2bac16c3dec 100644
--- a/web/src/i18n/zh.ts
+++ b/web/src/i18n/zh.ts
@@ -282,8 +282,8 @@ export const zh: Translations = {
nameRequired: "名称必填",
nameRule:
"仅允许小写字母、数字、下划线和短横线;首字符必须是字母或数字;最多 64 个字符。",
- invalidName: "多Agent配置名称非法",
- cloneFromDefault: "从默认多Agent配置克隆配置",
+ invalidName: "多Agent配置名称非法", cloneFrom: "从配置文件克隆",
+ cloneFromNone: "无(空白)",
allProfiles: "多Agent配置列表",
noProfiles: "暂无多Agent配置。",
defaultBadge: "默认",
diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts
index b4390b80729..fab64b64c84 100644
--- a/web/src/lib/api.ts
+++ b/web/src/lib/api.ts
@@ -552,7 +552,8 @@ export const api = {
}),
createProfile: (body: {
name: string;
- clone_from_default: boolean;
+ clone_from?: string | null;
+ clone_from_default?: boolean;
clone_all?: boolean;
no_skills?: boolean;
description?: string;
diff --git a/web/src/pages/ProfileBuilderPage.tsx b/web/src/pages/ProfileBuilderPage.tsx
index 4747878be8e..6aedb8dc147 100644
--- a/web/src/pages/ProfileBuilderPage.tsx
+++ b/web/src/pages/ProfileBuilderPage.tsx
@@ -220,7 +220,7 @@ export default function ProfileBuilderPage() {
try {
const res = await api.createProfile({
name: n,
- clone_from_default: false,
+ clone_from: null,
description: description.trim() || undefined,
provider: pickedModel?.provider,
model: pickedModel?.model,
diff --git a/web/src/pages/ProfilesPage.tsx b/web/src/pages/ProfilesPage.tsx
index 29220ea9639..fdf89fa4a41 100644
--- a/web/src/pages/ProfilesPage.tsx
+++ b/web/src/pages/ProfilesPage.tsx
@@ -35,11 +35,11 @@ import { Badge } from "@nous-research/ui/ui/components/badge";
import { Button } from "@nous-research/ui/ui/components/button";
import { Input } from "@nous-research/ui/ui/components/input";
import { Label } from "@nous-research/ui/ui/components/label";
-import { Checkbox } from "@nous-research/ui/ui/components/checkbox";
import {
Select,
SelectOption,
} from "@nous-research/ui/ui/components/select";
+import { Checkbox } from "@nous-research/ui/ui/components/checkbox";
import { useI18n } from "@/i18n";
import { usePageHeader } from "@/contexts/usePageHeader";
import { cn, themedBody } from "@/lib/utils";
@@ -312,7 +312,7 @@ export default function ProfilesPage() {
// Create modal
const [createModalOpen, setCreateModalOpen] = useState(false);
const [newName, setNewName] = useState("");
- const [cloneFromDefault, setCloneFromDefault] = useState(true);
+ const [cloneFrom, setCloneFrom] = useState("default");
const [cloneAll, setCloneAll] = useState(false);
const [noSkills, setNoSkills] = useState(false);
const [newDescription, setNewDescription] = useState("");
@@ -429,7 +429,7 @@ export default function ProfilesPage() {
}
setCreating(true);
try {
- const cloning = cloneAll || cloneFromDefault;
+ const cloning = cloneFrom !== null;
const picked = modelChoice
? modelChoices?.find(
(c) => `${c.provider}\u0000${c.model}` === modelChoice,
@@ -437,8 +437,8 @@ export default function ProfilesPage() {
: undefined;
const res = await api.createProfile({
name,
- clone_from_default: cloneAll ? false : cloneFromDefault,
- clone_all: cloneAll,
+ clone_from: cloneFrom,
+ clone_all: cloning && cloneAll,
no_skills: cloning ? false : noSkills,
description: newDescription.trim() || undefined,
provider: picked?.provider,
@@ -455,7 +455,7 @@ export default function ProfilesPage() {
setNewDescription("");
setNoSkills(false);
setCloneAll(false);
- setCloneFromDefault(true);
+ setCloneFrom("default");
setModelChoice("");
setCreateModalOpen(false);
load();
@@ -772,7 +772,7 @@ export default function ProfilesPage() {
};
}, [setEnd, t.common.create, loading, navigate]);
- const cloning = cloneAll || cloneFromDefault;
+ const cloning = cloneFrom !== null;
if (loading) {
return (
@@ -862,6 +862,26 @@ export default function ProfilesPage() {
+
+
+
+
+