Ship 0.15.0: installable persona packs and slimmer bundled set.

Load Assistent/extensions packs between bundled and overlay, keep neutral/aggressive/dreamer, drop cinema/lewd/private shelves, and make horny slash commands schema-driven.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-23 08:28:31 +03:00
co-authored by Cursor
parent e2d48b4bf9
commit 47d352a7af
42 changed files with 353 additions and 429 deletions
+30 -26
View File
@@ -6014,9 +6014,9 @@ ${patch.prompt}`;
return {
id,
title: known && known.title || ({
neutral: "\u041D\u0435\u0439\u0442\u0440\u0430\u043B\u044C\u043D\u044B\u0439",
lewd: "\u041F\u043E\u0448\u043B\u044F\u043A",
aggressive: "\u0410\u0433\u0440\u0435\u0441\u0441\u0438\u0432\u043D\u044B\u0439"
neutral: "\u041D\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u044B\u0439",
aggressive: "\u0410\u0433\u0440\u0435\u0441\u0441\u0438\u0432\u043D\u044B\u0439",
dreamer: "\u041C\u0435\u0447\u0442\u0430\u0442\u0435\u043B\u044C"
}[id] || id)
};
}
@@ -6753,13 +6753,16 @@ ${data.ui.help_extra}`.trim();
renderPersonaControls(data.controls || {}, controlValues);
syncPersonaDeleteButton(data.persona_source || data.personas?.find((p) => p.id === (data.persona || $2("sa_persona")?.value))?.source);
}
function isDeletablePersonaSource(source) {
const src = String(source || "");
return src === "overlay" || src === "overlay+bundled" || src === "overlay+pack";
}
function syncPersonaDeleteButton(source) {
const btn = $2("sa_persona_delete");
if (!btn) {
return;
}
const src = String(source || "");
const canDelete = src === "overlay" || src === "overlay+bundled";
const canDelete = isDeletablePersonaSource(source);
btn.hidden = !canDelete;
btn.disabled = !canDelete;
}
@@ -6878,17 +6881,12 @@ ${data.ui.help_extra}`.trim();
return Number.isFinite(n) ? n : fallback;
}
function coolDownHorny() {
const persona = $2("sa_persona")?.value || "";
if (persona !== "leonid") {
setStatus("/\u043E\u0441\u0442\u044B\u043D\u044C \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F Leonid");
const schema = state.config?.controls || {};
if (!schema.horny) {
setStatus("/\u043E\u0441\u0442\u044B\u043D\u044C: \u0443 \u044D\u0442\u043E\u0439 \u043B\u0438\u0447\u043D\u043E\u0441\u0442\u0438 \u043D\u0435\u0442 \u0441\u043B\u0430\u0439\u0434\u0435\u0440\u0430 \u0425\u043E\u0440\u043D\u0438");
return;
}
state.lastUserControlIntent = true;
const schema = state.config?.controls || {};
if (!schema.horny) {
setStatus("\u0423 \u044D\u0442\u043E\u0439 \u043B\u0438\u0447\u043D\u043E\u0441\u0442\u0438 \u043D\u0435\u0442 \u0441\u043B\u0430\u0439\u0434\u0435\u0440\u0430 \u0425\u043E\u0440\u043D\u0438");
return;
}
const min = Number(schema.horny.min ?? 0);
const max = Number(schema.horny.max ?? 100);
const cur = getControlValue("horny", Number(schema.horny.default ?? 35));
@@ -6909,12 +6907,12 @@ ${data.ui.help_extra}`.trim();
setStatus(`/\u043E\u0441\u0442\u044B\u043D\u044C \u2192 ${Math.round(next)}%`);
}
async function startHornyGame() {
const persona = $2("sa_persona")?.value || "";
if (persona !== "leonid") {
setStatus("/horny-game \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F Leonid");
const schema = state.config?.controls || {};
if (!schema.horny) {
setStatus("/horny-game: \u0443 \u044D\u0442\u043E\u0439 \u043B\u0438\u0447\u043D\u043E\u0441\u0442\u0438 \u043D\u0435\u0442 \u0441\u043B\u0430\u0439\u0434\u0435\u0440\u0430 \u0425\u043E\u0440\u043D\u0438");
return;
}
const cur = getControlValue("horny", 35);
const cur = getControlValue("horny", Number(schema.horny.default ?? 35));
state.lastUserControlIntent = true;
await sendChat({
skipSlash: true,
@@ -6992,12 +6990,12 @@ ${data.ui.help_extra}`.trim();
const meta = (state.personas || []).find((p) => p.id === id);
const title = meta?.title || id;
const src = meta?.source || state.config?.persona_source || "";
if (src !== "overlay" && src !== "overlay+bundled") {
setStatus("Bundled personas cannot be deleted");
if (src !== "overlay" && src !== "overlay+bundled" && src !== "overlay+pack") {
setStatus("\u041C\u043E\u0436\u043D\u043E \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0442\u043E\u043B\u044C\u043A\u043E overlay-\u0441\u043B\u043E\u0439 (bundled/pack \u043D\u0435 \u0442\u0440\u043E\u0433\u0430\u044E\u0442\u0441\u044F)");
return;
}
if (!window.confirm(`\u0423\u0434\u0430\u043B\u0438\u0442\u044C \xAB${title}\xBB?
\u041F\u043E\u0441\u0442\u0430\u0432\u043A\u0430 (bundled) \u043D\u0435 \u0442\u0440\u043E\u0433\u0430\u0435\u0442\u0441\u044F.`)) {
\u041F\u043E\u0441\u0442\u0430\u0432\u043A\u0430 (bundled/pack) \u043D\u0435 \u0442\u0440\u043E\u0433\u0430\u0435\u0442\u0441\u044F.`)) {
return;
}
await new Promise((resolve) => {
@@ -7644,6 +7642,12 @@ ${data.ui.help_extra}`.trim();
if (source === "overlay+bundled") {
return "\u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043E+\u043F\u0440\u0430\u0432\u043A\u0430";
}
if (source === "overlay+pack") {
return "\u043F\u0430\u043A+\u043F\u0440\u0430\u0432\u043A\u0430";
}
if (source === "pack") {
return "\u043F\u0430\u043A";
}
return "\u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043E";
}
function renderPersonaSettingsList() {
@@ -7676,7 +7680,7 @@ ${data.ui.help_extra}`.trim();
function syncPersonaPanelActions() {
const id = state.settingsPersonaId;
const p = (state.personas || []).find((x) => x.id === id);
const canDelete = p && (p.source === "overlay" || p.source === "overlay+bundled");
const canDelete = p && isDeletablePersonaSource(p.source);
const del = $2("sa_btn_persona_delete_panel");
if (del) {
del.disabled = !canDelete;
@@ -7745,8 +7749,8 @@ ${summary || "(\u043F\u0443\u0441\u0442\u043E)"}`;
return;
}
let newId = pack?.id || "";
if ((state.personas || []).some((p) => p.id === newId && (p.source === "bundled" || p.source === "overlay+bundled"))) {
newId = window.prompt("Id \u0437\u0430\u043D\u044F\u0442 bundled \u2014 \u043D\u043E\u0432\u044B\u0439 id:", `${newId}_import`) || "";
if ((state.personas || []).some((p) => p.id === newId && (p.source === "bundled" || p.source === "pack" || p.source === "overlay+bundled" || p.source === "overlay+pack"))) {
newId = window.prompt("Id \u0437\u0430\u043D\u044F\u0442 bundled/pack \u2014 \u043D\u043E\u0432\u044B\u0439 id:", `${newId}_import`) || "";
}
genericRequest(
"AssistentImportPersona",
@@ -7794,7 +7798,7 @@ ${summary || "(\u043F\u0443\u0441\u0442\u043E)"}`;
function deleteSelectedOverlayPersona() {
const id = state.settingsPersonaId;
const p = (state.personas || []).find((x) => x.id === id);
if (!p || p.source !== "overlay" && p.source !== "overlay+bundled") {
if (!p || !isDeletablePersonaSource(p.source)) {
setStatus("\u041C\u043E\u0436\u043D\u043E \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0442\u043E\u043B\u044C\u043A\u043E overlay");
return;
}
@@ -8488,8 +8492,8 @@ ${summary || "(\u043F\u0443\u0441\u0442\u043E)"}`;
why.push("session_exact \u043F\u0443\u0441\u0442 \u2014 params \u0438\u0437 Exact + \u043F\u0440\u043E\u0444\u0438\u043B\u044C \u0447\u0435\u043A\u043F\u043E\u0438\u043D\u0442\u0430");
}
why.push(`\u043F\u0440\u043E\u0444\u0438\u043B\u044C \u0447\u0435\u043A\u043F\u043E\u0438\u043D\u0442\u0430: ${profile} (\u0438\u043C\u044F/title \u2192 turbo|raw)`);
if (persona === "cinema" || state.exact?.generation?.aspect) {
why.push(`persona/exact aspect: ${state.exact?.generation?.aspect || exactGen.aspect || "\u2014"}`);
if (state.exact?.generation?.aspect) {
why.push(`persona/exact aspect: ${state.exact.generation.aspect || exactGen.aspect || "\u2014"}`);
}
if (state.lastPatch) {
const keys = Object.keys(state.lastPatch).filter((k) => state.lastPatch[k] != null && k !== "notes");