Feature: Enhanced Branch and Checkpoint Naming (#4993)

* Add customizable name builder and max tries to getUniqueName utility

- Add optional `nameBuilder` parameter to allow custom name formatting
- Add `maxTries` parameter to client-side version to prevent infinite loops
- Update JSDoc with new optional parameters
- Use nullish coalescing to set default name builder function
- Default name builder maintains existing "${baseName} (${i})" format

* Add startIndex option to getUniqueName utility for flexible name generation

* Enhance branch creation to use current chat name and ensure unique names

- Import `getCurrentChatDetails` from script.js
- Replace hardcoded branch name format with current chat name as base
- Add custom `buildBranchName` function to format branch names with suffix
- Strip existing " - Branch #N" suffixes before generating new branch name
- Use `getUniqueName` utility with `nameBuilder` to ensure unique branch names
- Remove unused `mainChat` variable and replace with `mainChatName`

* Enhance checkpoint creation to use current chat name and suggest unique names

- Import `getCurrentChatDetails` from script.js to get current chat name
- Add custom `buildCheckpointName` function to format checkpoint names with suffix
- Strip existing " - Checkpoint #N" suffixes before generating new checkpoint name
- Use `getUniqueName` utility with `nameBuilder` to ensure unique checkpoint names
- Pass `suggestedName` to template and popup input for better UX
- Replace manual loop with `getUniqueName`

* Remove automatic timestamp suffix from bookmark names

* Fix getUniqueName utility to correctly handle maxTries and return null on failure

* shut up copilot

* Strip legacy bookmark and branch name prefixes when generating unique names

- Add removal of old "Checkpoint #N - " prefix format in `buildCheckpointName`
- Add removal of old "Branch #N - " prefix format in `buildBranchName`
- Change `cleanName` from const to let to allow multiple replacements
- Ensures clean base names regardless of legacy or current naming format
This commit is contained in:
Wolfsblvt
2026-01-12 00:07:51 +01:00
committed by GitHub
parent 2d1a96f91d
commit 491f2a3afd
3 changed files with 69 additions and 29 deletions
+33 -13
View File
@@ -12,6 +12,7 @@ import {
saveChatConditional,
saveItemizedPrompts,
setActiveGroup,
getCurrentChatDetails,
} from '../script.js';
import { humanizedDateTime } from './RossAscends-mods.js';
import {
@@ -81,24 +82,29 @@ async function getExistingChatNames() {
}
async function getBookmarkName({ isReplace = false, forceName = null } = {}) {
const chatNames = await getExistingChatNames();
const mainChatName = (getCurrentChatDetails()).sessionName;
const body = await renderTemplateAsync('createCheckpoint', { isReplace: isReplace });
let name = forceName ?? await Popup.show.input('Create Checkpoint', body);
function buildCheckpointName(name, i) {
// Strip off existing suffixes, then build new name
let cleanName = name.replace(new RegExp(` - ${bookmarkNameToken}\\d+$`), '');
// Strip off legacy old name prefix too
cleanName = name.replace(new RegExp(`^${bookmarkNameToken}\\d+ - `), '');
return `${cleanName} - ${bookmarkNameToken}${i}`;
}
const existingChats = await getExistingChatNames();
const suggestedName = getUniqueName(mainChatName, (x) => existingChats.includes(x), { nameBuilder: buildCheckpointName });
const body = await renderTemplateAsync('createCheckpoint', { isReplace: isReplace, suggestedName: suggestedName });
let name = forceName ?? await Popup.show.input('Create Checkpoint', body, suggestedName);
// Special handling for confirmed empty input (=> auto-generate name)
if (name === '') {
for (let i = chatNames.length; i < 1000; i++) {
name = bookmarkNameToken + i;
if (!chatNames.includes(name)) {
break;
}
}
name = suggestedName;
}
if (!name) {
return null;
}
return `${name} - ${humanizedDateTime()}`;
return name;
}
function getMainChatName() {
@@ -170,9 +176,23 @@ export async function createBranch(mesId) {
}
const lastMes = chat[mesId];
const mainChat = selected_group ? groups?.find(x => x.id == selected_group)?.chat_id : characters[this_chid].chat;
const newMetadata = { main_chat: mainChat };
let name = `Branch #${mesId} - ${humanizedDateTime()}`;
const mainChatName = (getCurrentChatDetails()).sessionName;
const newMetadata = { main_chat: mainChatName };
function buildBranchName(name, i) {
// Strip off existing suffixes, then build new name
let cleanName = name.replace(/ - Branch #\d+$/, '');
// Strip off legacy old name prefix too
cleanName = name.replace(/^Branch #\d+ - /, '');
return `${cleanName} - Branch #${i}`;
}
const existingChats = await getExistingChatNames();
const name = getUniqueName(mainChatName, (x) => existingChats.includes(x), { nameBuilder: buildBranchName });
if (!name) {
console.error('Could not generate a unique branch name.');
toastr.error('Could not generate a unique branch name.', 'Branch creation failed');
return;
}
if (selected_group) {
await saveGroupBookmarkChat(selected_group, name, newMetadata, mesId);