Rename Character copy to Persona

Issue #234: the "Character" tab and its "Style of response" label made it
unclear that this is where a system prompt is set. Rename the user-facing
labels for clarity:

- "Character" tab + section heading -> "Persona"
- "Style of response" -> "System prompt"
- supporting strings: select placeholder, name placeholder, button/title
  text, toasts, confirm/notice text, the chat-bar indicator tooltip, the
  settings visibility toggle, and the assistant personality picker
  ("Characters" optgroup -> "Personas").

Used "Persona" rather than the issue's suggested "Preset" because the app
already has a distinct, user-facing "Presets" concept (built-in presets
like Code Analyze/Brainstorm/Reason, shown as their own group in the
assistant picker). "Persona" matches what this tab actually creates -- a
named persona with its own memories -- without colliding with that term.

Internal identifiers (element IDs, data-chartab attributes, function names)
and the character_name backend field are intentionally left unchanged so
existing saved presets and JS wiring keep working.
This commit is contained in:
Zeus-Deus
2026-06-02 05:42:15 +02:00
committed by GitHub
parent c90a7a19a5
commit 19a4f823a4
3 changed files with 20 additions and 20 deletions

View File

@@ -1084,7 +1084,7 @@
</button>
<input type="checkbox" id="group-toggle" style="display:none;">
<!-- Character indicator (hidden until active) -->
<button type="button" class="input-icon-btn tool-indicator" title="Character active — click to deactivate" id="character-indicator-btn" style="display:none;">
<button type="button" class="input-icon-btn tool-indicator" title="Persona active — click to deactivate" id="character-indicator-btn" style="display:none;">
<svg id="char-indicator-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span id="character-indicator-name" style="font-size:11px;margin-left:2px;max-width:80px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"></span>
<svg class="tool-indicator-x" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
@@ -1124,7 +1124,7 @@
<div id="char-fields-wrap">
<div class="preset-tabs">
<button class="preset-tab active" data-chartab="inject"><svg class="preset-tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 2 4 4"/><path d="m17 7 3-3"/><path d="M19 9 8.7 19.3c-1 1-2.5 1-3.4 0l-.6-.6c-1-1-1-2.5 0-3.4L15 5"/><path d="m9 11 4 4"/><path d="m5 19-3 3"/><path d="m14 4 6 6"/></svg><span>Inject</span></button>
<button class="preset-tab" data-chartab="character"><svg class="preset-tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Character</span></button>
<button class="preset-tab" data-chartab="character"><svg class="preset-tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Persona</span></button>
<button class="preset-tab" data-chartab="group"><svg class="preset-tab-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg><span>Group</span></button>
</div>
<!-- Inject tab (also holds model tuning: temperature + max tokens) -->
@@ -1151,25 +1151,25 @@
</div>
<!-- Prompt (character/persona) tab -->
<div class="preset-chartab" data-chartab-panel="character" style="display:none">
<label>Character</label>
<label>Persona</label>
<div class="char-name-combo">
<select id="char-template-select" class="char-template-select">
<option value="">Select character...</option>
<option value="">Select persona...</option>
</select>
<button type="button" id="char-new-btn" class="char-action-btn" title="Create a new character">+ New</button>
<button type="button" id="char-new-btn" class="char-action-btn" title="Create a new persona">+ New</button>
</div>
<div id="char-name-row">
<label for="custom-character-name">Name</label>
<div class="char-name-combo">
<input type="text" id="custom-character-name" maxlength="50" placeholder="Give your character a name..." autocomplete="off" style="flex:1">
<button type="button" id="char-delete-template-btn" class="char-action-btn" title="Delete this character and its memories" style="display:none;margin-top:-6px !important"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>Delete</button>
<input type="text" id="custom-character-name" maxlength="50" placeholder="Give your persona a name..." autocomplete="off" style="flex:1">
<button type="button" id="char-delete-template-btn" class="char-action-btn" title="Delete this persona and its memories" style="display:none;margin-top:-6px !important"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>Delete</button>
<button type="button" id="reset-character-btn" class="char-action-btn" title="Reset to default" style="margin-top:-6px !important">&#x21BA; Reset</button>
</div>
</div>
<label for="custom-system-prompt">Style of response</label>
<label for="custom-system-prompt">System prompt</label>
<div class="char-prompt-wrap">
<textarea id="custom-system-prompt" rows="4" placeholder="Write rough notes and click Expand, or leave empty"></textarea>
<button type="button" id="char-expand-btn" class="char-expand-btn" title="AI expand — turn your notes into a full character prompt">
<button type="button" id="char-expand-btn" class="char-expand-btn" title="AI expand — turn your notes into a full system prompt">
<svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor" style="vertical-align:-1px;margin-right:2px;"><path d="M12 0L14.59 8.41L23 12L14.59 15.59L12 24L9.41 15.59L1 12L9.41 8.41Z"/></svg>
Expand
</button>
@@ -1808,7 +1808,7 @@
</label>
<label class="vis-row">
<span class="vis-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></span>
<span class="vis-label">Characters <span class="vis-hint">Persona picker &amp; system prompt</span></span>
<span class="vis-label">Personas <span class="vis-hint">Persona picker &amp; system prompt</span></span>
<input type="checkbox" checked data-ui-key="preset-mini-btn"><span class="vis-switch"></span>
</label>
</div>

View File

@@ -180,7 +180,7 @@ function _renderSettingsBody(body, data, tzList) {
<div class="assistant-field">
<span style="display:flex;align-items:center;gap:8px;">Personality
<select id="assistant-character-pick" style="font-size:11px;padding:1px 6px;border:1px solid var(--border);border-radius:3px;background:var(--bg);color:var(--fg);max-width:180px;">
<option value="">-- pick from character --</option>
<option value="">-- pick from persona --</option>
</select>
</span>
<textarea id="assistant-personality" rows="6" placeholder="Describe the assistant's personality, tone, and behavior...">${_esc(crew.personality || '')}</textarea>
@@ -293,7 +293,7 @@ function _renderSettingsBody(body, data, tzList) {
allPresets.push(...presetsRaw);
}
const allTemplates = Array.isArray(templates) ? templates : [];
let opts = '<option value="">-- pick from character --</option>';
let opts = '<option value="">-- pick from persona --</option>';
if (allPresets.length) {
opts += '<optgroup label="Presets">';
for (const p of allPresets) {
@@ -304,7 +304,7 @@ function _renderSettingsBody(body, data, tzList) {
opts += '</optgroup>';
}
if (allTemplates.length) {
opts += '<optgroup label="Characters">';
opts += '<optgroup label="Personas">';
for (const t of allTemplates) {
if (!t.system_prompt && !t.personality) continue;
const name = t.character_name || t.name || 'Unnamed';

View File

@@ -220,7 +220,7 @@ function initNameDropdown() {
if (!charName || charName === '__default__') return;
const match = userTemplates.find(t => t.name === charName);
const isBuiltin = PROMPT_TEMPLATES.some(t => t.name === charName);
if (!await window.styledConfirm(`Delete "${charName}"?\n\nThis will remove the character and all its memories.`, { confirmText: 'Delete', danger: true })) return;
if (!await window.styledConfirm(`Delete "${charName}"?\n\nThis will remove the persona and all its memories.`, { confirmText: 'Delete', danger: true })) return;
try {
// Delete saved template if exists
if (match) {
@@ -296,7 +296,7 @@ function _populateCharSelect() {
const select = document.getElementById('char-template-select');
if (!select) return;
const currentVal = select.value;
select.innerHTML = '<option value="__default__">Default (no character)</option>';
select.innerHTML = '<option value="__default__">Default (no persona)</option>';
const savedNames = new Set(userTemplates.map(t => t.name));
if (userTemplates.length) {
@@ -437,7 +437,7 @@ function initSaveAsTemplate() {
let name = nameInput ? nameInput.value.trim() : '';
if (!name) {
name = prompt('Enter a name for this character:');
name = prompt('Enter a name for this persona:');
if (!name || !name.trim()) return;
name = name.trim();
if (nameInput) nameInput.value = name;
@@ -616,7 +616,7 @@ export function openCustomPresetModal() {
} else {
// Character/persona tab. "Save & " prefix when the user edited a template,
// so it's clear the edit is being saved on start.
label = changed ? 'Save & Start Character' : 'Start Character';
label = changed ? 'Save & Start Persona' : 'Start Persona';
}
btn.textContent = label;
// Show a "Cancel" button next to Start when the active tab's feature is
@@ -708,7 +708,7 @@ export function openCustomPresetModal() {
const notice = document.createElement('div');
notice.id = 'char-lock-notice';
notice.style.cssText = 'font-size:11px;color:var(--color-muted);text-align:center;padding:6px;margin-bottom:8px;border:1px dashed var(--border);border-radius:6px;';
notice.textContent = 'Persistent chat — character is locked. Style, temperature, and memory can still be changed.';
notice.textContent = 'Persistent chat — persona is locked. Style, temperature, and memory can still be changed.';
modal.querySelector('.modal-body').prepend(notice);
}
} else {
@@ -825,7 +825,7 @@ export async function saveCustomPreset(showToast, showError) {
if (showToast) {
// The Inject tab is a plain tuned "prompt" chat, not a persona — say so.
showToast(_isInjectStart ? 'Prompt saved' : 'Character saved');
showToast(_isInjectStart ? 'Prompt saved' : 'Persona saved');
}
const modal = document.getElementById('custom-preset-modal');
if (modal) {
@@ -962,7 +962,7 @@ function _syncCharIndicator() {
if (hasChar) {
if (iconEl) iconEl.innerHTML = _AVATAR;
if (nameSpan) nameSpan.textContent = custom.character_name;
btn.title = `Character: ${custom.character_name} — click to configure`;
btn.title = `Persona: ${custom.character_name} — click to configure`;
} else {
// Inject/tuning chat — syringe tag labeled "Prompt" to match the
// window identity, no persona name.