Ship Assistent 0.14.1: Exact generate params and cheap park/warm.

Client always merges Exact turbo|raw steps/cfg/sigma before Generate so sparse LLM omissions and leftover SD 20/7 cannot stick; Ollama park/warm skip no-op /api/ps round-trips when the chat model is already unloaded or resident.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-23 06:50:08 +03:00
co-authored by Cursor
parent 9d2cbca8f2
commit 5f33130381
17 changed files with 1005 additions and 50 deletions
+250 -15
View File
@@ -571,6 +571,8 @@
}
}
let lastExactForceCkpt = null;
function updateGate() {
const ok = isKreaSelected();
const gate = $('sa_gate');
@@ -595,6 +597,21 @@
if (layout) {
layout.classList.toggle('sa-disabled', !ok);
}
// On Krea checkpoint change: align Swarm leftovers to Exact profile once.
try {
const ckptName = resolveCurrentCheckpoint()?.name || null;
if (ok && ckptName && ckptName !== lastExactForceCkpt) {
const defs = typeof exactProfileDefaults === 'function'
? exactProfileDefaults(detectKreaProfileName())
: null;
if (defs && defs.steps != null && defs.cfg != null) {
lastExactForceCkpt = ckptName;
forceExactParamsForGenerate({});
}
} else if (!ok) {
lastExactForceCkpt = null;
}
} catch (e) { /* ignore */ }
return ok;
}
@@ -923,7 +940,10 @@
if (/\b(steps?|cfg|seed|sigma|aspect|resolution|batch|turbo|raw)\b/i.test(t)) {
return true;
}
return cyrTokenRe('размер|ширин[а-яё]*|высот[а-яё]*|соотношен[а-яё]*|турбо|портрет|вертикал[а-яё]*').test(t);
return cyrTokenRe(
'размер|ширин[а-яё]*|высот[а-яё]*|соотношен[а-яё]*|турбо|портрет|вертикал[а-яё]*|'
+ 'шаг|шагом|шагами|шагов|шага',
).test(t);
}
function replyMissingJsonPatch(reply) {
@@ -1252,21 +1272,123 @@
}
function detectKreaProfileName() {
const KP = window.SA?.kreaProfile;
try {
const model = resolveCurrentCheckpoint();
const blob = `${model?.name || ''} ${model?.title || ''}`.toLowerCase();
const hasRaw = /\braw\b/.test(blob);
const hasTurbo = /\bturbo\b/.test(blob);
return hasRaw && !hasTurbo ? 'raw' : 'turbo';
const blob = `${model?.name || ''} ${model?.title || ''}`;
const exactProfile = state.exact?.generation?.profile;
if (KP?.detectKreaProfileName) {
return KP.detectKreaProfileName(blob, exactProfile);
}
const lower = blob.toLowerCase();
if (/turbo/.test(lower)) {
return 'turbo';
}
if (/\braw\b|_raw\b|-raw\b/.test(lower)) {
return 'raw';
}
// Unlabeled ckpt (e.g. realismByStableYogi) — never invent turbo.
return 'raw';
} catch (e) {
return (state.exact?.generation?.profile) || 'turbo';
return (state.exact?.generation?.profile) || 'raw';
}
}
/** Exact turbo/raw numbers only (no session overlay) — used to force stale SD leftovers. */
function exactProfileDefaults(profileName) {
const { exact, profiles } = resolveExactBundle();
const profile = profileName || detectKreaProfileName();
const KP = window.SA?.kreaProfile;
if (KP?.profileParamDefaults) {
return KP.profileParamDefaults(profiles, profile, exact.generation);
}
const gen = exact.generation && typeof exact.generation === 'object' ? exact.generation : {};
const fromProfile = profiles[profile] && typeof profiles[profile] === 'object' ? profiles[profile] : {};
return {
profile,
steps: fromProfile.steps ?? gen.steps ?? null,
cfg: fromProfile.cfg ?? gen.cfg ?? null,
sigma_shift: fromProfile.sigma_shift ?? gen.sigma_shift ?? null,
};
}
function readLiveStepsCfgSigma() {
return {
steps: parseInt(val('input_steps') || '', 10) || null,
cfg: parseFloat(val('input_cfgscale') || val('input_cfg') || '') || null,
sigma_shift: parseFloat(val('input_sigmashift') || '') || null,
};
}
function setCfgVal(n) {
if (document.getElementById('input_cfgscale')) {
setVal('input_cfgscale', String(n));
} else if (document.getElementById('input_cfg')) {
setVal('input_cfg', String(n));
}
}
/**
* P0: before Generate, overwrite foreign SD-like leftovers (e.g. 20/7) with Exact
* turbo 8/1/σ1.15 or raw 28/4.5. Always honors explicit patch keys; sessionExact
* only when the user asked for params this turn.
*/
function forceExactParamsForGenerate({ patch = null, profileName = null } = {}) {
if (typeof isKreaSelected === 'function' && !isKreaSelected()) {
return false;
}
const profile = profileName || detectKreaProfileName();
const defaults = exactProfileDefaults(profile);
const live = readLiveStepsCfgSigma();
const KP = window.SA?.kreaProfile;
const userIntent = !!state.lastUserParamIntent;
const keys = KP?.exactKeysToForce
? KP.exactKeysToForce(live, defaults, {
patch,
sessionExact: state.sessionExact,
userParamIntent: userIntent,
})
: ['steps', 'cfg', 'sigma_shift'].filter((k) => {
const want = defaults[k];
if (want == null) {
return false;
}
if (patch?.[k] != null && String(patch[k]) !== String(want)) {
return false;
}
if (userIntent && state.sessionExact?.[k] != null) {
return false;
}
return live[k] == null || String(live[k]) !== String(want);
});
if (!keys.length) {
return false;
}
for (const key of keys) {
const want = defaults[key];
if (key === 'steps') {
setVal('input_steps', String(want));
} else if (key === 'cfg') {
setCfgVal(want);
} else if (key === 'sigma_shift') {
setVal('input_sigmashift', String(want));
}
if (state.sessionExact && state.sessionExact[key] != null
&& String(state.sessionExact[key]) !== String(want)) {
delete state.sessionExact[key];
}
if (state.chatSession?.gen) {
state.chatSession.gen[key] = want;
}
}
syncLiveParamsBar();
return true;
}
function mergedGenerationDefaults(profileName) {
const { exact, profiles } = resolveExactBundle();
const gen = exact.generation && typeof exact.generation === 'object' ? { ...exact.generation } : {};
const profile = profileName || gen.profile || detectKreaProfileName();
const profile = profileName || detectKreaProfileName();
const fromProfile = profiles[profile] && typeof profiles[profile] === 'object' ? { ...profiles[profile] } : {};
const session = state.sessionExact && typeof state.sessionExact === 'object' ? { ...state.sessionExact } : {};
// Profile (turbo/raw) overrides generation defaults; session overrides both.
@@ -1313,6 +1435,42 @@
return String(value) !== String(exactVal);
}
/**
* Client-authoritative Exact fill for Generate: inject turbo/raw steps/cfg/sigma
* when the sparse patch omitted them, and drop stale sessionExact that would
* block applyPatch (e.g. leftover SD-like 20/7 after a turbo checkpoint).
*/
function ensureExactParamsForGenerate(patch) {
const S = window.SA && window.SA.session;
if (!patch || !S || typeof S.mergeExactParamsForGenerate !== 'function') {
return patch;
}
if (!S.patchWantsGenerate(patch)) {
return patch;
}
const { exact, profiles } = resolveExactBundle();
const { patch: next, clearSessionKeys } = S.mergeExactParamsForGenerate(patch, {
exact,
profiles,
profileName: detectKreaProfileName(),
sessionExact: state.sessionExact,
userParamIntent: !!state.lastUserParamIntent,
});
for (const key of clearSessionKeys || []) {
if (state.sessionExact && state.sessionExact[key] != null) {
delete state.sessionExact[key];
}
}
if (state.chatSession && state.chatSession.gen) {
for (const key of S.EXACT_GENERATE_PARAM_KEYS || ['steps', 'cfg', 'sigma_shift']) {
if (next[key] != null) {
state.chatSession.gen[key] = next[key];
}
}
}
return next;
}
function fillEmptyParamsFromExact() {
const defaults = mergedGenerationDefaults();
if (isEmptyParamField(val('input_steps'), { treatZeroEmpty: true }) && defaults.steps != null) {
@@ -3831,6 +3989,8 @@
const S = window.SA && window.SA.session;
let initCtx = {};
try { if (typeof readInitContext === 'function') initCtx = readInitContext(); } catch (e) { /* ignore */ }
const kreaProfile = detectKreaProfileName();
const exactDefs = exactProfileDefaults(kreaProfile);
const extra = {
prompt_image_count: typeof countPromptImages === 'function' ? countPromptImages() : 0,
has_vision_image: typeof visionReadySlots === 'function' ? visionReadySlots().length > 0 : false,
@@ -3838,6 +3998,12 @@
attached_slot_ids: typeof attachableSlots === 'function' ? attachableSlots().map((s) => s.id) : [],
auto_apply: !!$('sa_auto_apply')?.checked,
auto_generate: !false /* auto_generate ignored 0.14 */,
krea_profile: kreaProfile,
recommended_params: {
steps: exactDefs.steps,
cfg: exactDefs.cfg,
sigma_shift: exactDefs.sigma_shift,
},
...initCtx,
};
if (S && typeof S.compactContext === 'function') {
@@ -3853,7 +4019,7 @@
return ctx;
}
const g = (state.chatSession && state.chatSession.gen) || {};
return { session: true, prompt: g.prompt || '', negative: g.negative || '', ...extra };
return { session: true, prompt: g.prompt || '', negative: g.negative || '', krea_profile: kreaProfile, ...extra };
}
function slimInventoryLoras(list, limit) {
const selected = new Set();
@@ -4188,6 +4354,11 @@
if (!patch) {
return;
}
const S = window.SA && window.SA.session;
const wantsGen = S && typeof S.patchWantsGenerate === 'function' && S.patchWantsGenerate(patch);
if (wantsGen) {
patch = ensureExactParamsForGenerate(patch);
}
const doPrompt = !which || which === 'all' || which === 'prompt';
const doLoras = !which || which === 'all' || which === 'loras';
const doParams = !which || which === 'all' || which === 'size' || which === 'params';
@@ -4372,6 +4543,12 @@
setVal(batchId, String(defBatch));
}
}
// Generate: force Exact profile numbers when live still has foreign leftovers (20/7).
const Sgen = window.SA && window.SA.session;
if (Sgen?.patchWantsGenerate?.(patch) || patch.generate === true
|| (Array.isArray(patch.actions) && patch.actions.map(String).includes('generate'))) {
forceExactParamsForGenerate({ patch });
}
}
if (doInit) {
@@ -4795,17 +4972,53 @@
}
async function runGenerateFromPatch(patch, opts = {}) {
// Capture the model/user delta before live UI pollutes Exact keys.
const deltaBeforeLive = patch && typeof patch === 'object' ? { ...patch } : {};
const S = window.SA && window.SA.session;
const exactKeys = (S && S.EXACT_GENERATE_PARAM_KEYS) || ['steps', 'cfg', 'sigma_shift'];
// 0.14: session is source of truth for Generate
if (typeof pullLiveIntoSession === 'function') pullLiveIntoSession();
if (state.chatSession && state.chatSession.gen && (opts.fromSession || opts.force)) {
const fromSess = { ...state.chatSession.gen, generate: true, actions: ['generate'] };
if (patch && typeof patch === 'object') {
for (const k of Object.keys(patch)) {
if (patch[k] != null) fromSess[k] = patch[k];
// Live UI often still holds SD-like leftovers (steps 20 / cfg 7). Drop those
// Exact keys from the session unless this delta or the user explicitly set them.
if (state.chatSession && state.chatSession.gen) {
for (const key of exactKeys) {
const fromDelta = deltaBeforeLive[key] != null;
const fromUser = !!state.lastUserParamIntent && state.sessionExact?.[key] != null;
if (!fromDelta && !fromUser) {
state.chatSession.gen[key] = null;
}
}
patch = fromSess;
}
let working = {
...deltaBeforeLive,
generate: true,
actions: Array.isArray(deltaBeforeLive.actions)
&& deltaBeforeLive.actions.map(String).includes('generate')
? deltaBeforeLive.actions
: [...(Array.isArray(deltaBeforeLive.actions) ? deltaBeforeLive.actions : []), 'generate'],
};
working = ensureExactParamsForGenerate(working);
if (state.chatSession && state.chatSession.gen && (opts.fromSession || opts.force)) {
const fromSess = { ...state.chatSession.gen, generate: true, actions: ['generate'] };
for (const k of Object.keys(working)) {
if (working[k] != null) fromSess[k] = working[k];
}
// Re-clear Exact keys that still came only from stale live snapshot.
for (const key of exactKeys) {
const fromDelta = deltaBeforeLive[key] != null;
const fromUser = !!state.lastUserParamIntent && state.sessionExact?.[key] != null;
if (!fromDelta && !fromUser && working[key] != null) {
fromSess[key] = working[key];
}
}
patch = ensureExactParamsForGenerate(fromSess);
if (typeof pushSessionToSwarm === 'function') await pushSessionToSwarm(state.chatSession);
} else {
patch = working;
}
const force = !!opts.force;
@@ -4871,6 +5084,11 @@
syncLiveParamsBar();
}
ensureNegativeForGenerate(job.patch);
// P0: never Generate with leftover 20/7 under a turbo/raw Exact profile.
forceExactParamsForGenerate({ patch: job.patch });
if (typeof pullLiveIntoSession === 'function') {
pullLiveIntoSession();
}
if (epoch !== state.chatEpoch) {
break;
@@ -5817,7 +6035,12 @@ if (!(meta && meta.historical)) {
fillKnobsFromConfig(data);
updateCtxChip();
if (applyDefaults || data.exact) {
lastExactForceCkpt = null;
fillEmptyParamsFromExact();
if (typeof isKreaSelected === 'function' && isKreaSelected()) {
forceExactParamsForGenerate({});
lastExactForceCkpt = resolveCurrentCheckpoint()?.name || null;
}
}
const nextPersona = data.persona || $('sa_persona')?.value || '';
let controlValues = data.control_values || data.exact?.controls || {};
@@ -7531,6 +7754,15 @@ if (!(meta && meta.historical)) {
status: intent.vetoed ? 'skip' : 'running',
});
if (typeof startBusyUi === 'function') startBusyUi('silent_gen');
if (effective) {
effective = ensureExactParamsForGenerate({
...effective,
generate: true,
actions: Array.isArray(effective.actions) && effective.actions.map(String).includes('generate')
? effective.actions
: [...(Array.isArray(effective.actions) ? effective.actions : []), 'generate'],
});
}
if (S && effective) state.chatSession = S.mergeDelta(state.chatSession || S.emptySession(), effective);
await pushSessionToSwarm(state.chatSession);
if (typeof syncLiveParamsBar === 'function') syncLiveParamsBar();
@@ -7554,13 +7786,16 @@ if (!(meta && meta.historical)) {
state.pendingSilentGen = false;
}
async function applyQuickPatch(patch, note) {
const withActions = { ...patch };
let withActions = { ...patch };
if (!Array.isArray(withActions.actions) && patchHasGenTrigger(withActions)) {
withActions.actions = ['generate'];
}
const prevIntent = state.lastUserParamIntent;
state.lastUserParamIntent = true;
const S = window.SA && window.SA.session;
if (S && S.patchWantsGenerate && S.patchWantsGenerate(withActions)) {
withActions = ensureExactParamsForGenerate(withActions);
}
if (S) {
state.chatSession = S.mergeDelta(state.chatSession || S.emptySession(), withActions);
}
+108
View File
@@ -0,0 +1,108 @@
/**
* Krea turbo/raw profile detection + Exact param alignment helpers (pure).
* Prevents labeling ambiguous checkpoints as turbo while Swarm still has SD-like 20/7.
*/
export function numClose(a, b, eps = 0.051) {
const x = Number(a);
const y = Number(b);
if (!Number.isFinite(x) || !Number.isFinite(y)) {
return false;
}
return Math.abs(x - y) <= eps;
}
/**
* Detect turbo|raw from checkpoint name/title.
* Names without turbo/raw (e.g. realismByStableYogi) must NOT invent "turbo".
* Note: INT8Turbo has no word-boundary before "turbo" — use substring match.
*/
export function detectKreaProfileName(modelBlob, exactProfile) {
const blob = String(modelBlob || '').toLowerCase();
const hasTurbo = /turbo/.test(blob);
const hasRaw = /\braw\b|_raw\b|-raw\b|\/raw\b/.test(blob);
if (hasTurbo) {
return 'turbo';
}
if (hasRaw) {
return 'raw';
}
// Unlabeled ckpt — Exact generation.profile alone must not invent turbo.
void exactProfile;
return 'raw';
}
/** Profile-only defaults (no session overlay). */
export function profileParamDefaults(profiles, profileName, generation = {}) {
const profile = String(profileName || 'raw');
const fromProfile = profiles && typeof profiles[profile] === 'object' ? profiles[profile] : {};
const gen = generation && typeof generation === 'object' ? generation : {};
return {
profile,
steps: fromProfile.steps ?? gen.steps ?? null,
cfg: fromProfile.cfg ?? gen.cfg ?? null,
sigma_shift: fromProfile.sigma_shift ?? gen.sigma_shift ?? null,
};
}
/**
* Whether live Swarm numbers already match the Exact profile (steps/cfg/σ).
*/
export function liveMatchesExactProfile(live, defaults) {
if (!defaults || defaults.steps == null || defaults.cfg == null) {
return true;
}
const stepsOk = live?.steps == null || numClose(live.steps, defaults.steps, 0.5);
const cfgOk = live?.cfg == null || numClose(live.cfg, defaults.cfg);
const sigmaOk = defaults.sigma_shift == null
|| live?.sigma_shift == null
|| numClose(live.sigma_shift, defaults.sigma_shift);
return stepsOk && cfgOk && sigmaOk;
}
/**
* Keys that should be forced from Exact onto live before Generate.
* - Always rewrite live when it disagrees with Exact profile defaults.
* - Skip only when the patch sets a *different* intentional value, or
* sessionExact holds an override and userParamIntent is true.
* - Stale sessionExact leftovers (SD 20/7) must NOT block Exact.
*/
export function exactKeysToForce(live, defaults, {
patch = null,
sessionExact = null,
userParamIntent = false,
} = {}) {
if (!defaults) {
return [];
}
const out = [];
for (const key of ['steps', 'cfg', 'sigma_shift']) {
const want = defaults[key];
if (want == null) {
continue;
}
const eps = key === 'steps' ? 0.5 : 0.051;
// Patch asked for a non-Exact number — honor it.
if (patch && patch[key] != null && !numClose(patch[key], want, eps)) {
continue;
}
if (userParamIntent && sessionExact && sessionExact[key] != null) {
continue;
}
const have = live?.[key];
if (have == null || !numClose(have, want, eps)) {
out.push(key);
}
}
return out;
}
export function attachKreaProfile(SA) {
SA.kreaProfile = {
numClose,
detectKreaProfileName,
profileParamDefaults,
liveMatchesExactProfile,
exactKeysToForce,
};
}
+2
View File
@@ -4,6 +4,7 @@ import { attachPersist } from './persist.js';
import { attachSession } from './session.js';
import { attachContext } from './context.js';
import { attachActivity } from './activity.js';
import { attachKreaProfile } from './kreaProfile.js';
window.SA = window.SA || {};
attachApi(window.SA);
@@ -12,6 +13,7 @@ attachPersist(window.SA);
attachSession(window.SA);
attachContext(window.SA);
attachActivity(window.SA);
attachKreaProfile(window.SA);
/** Called from app after AssistentGetConfig — single source: Config/_base/patch-keys.json */
window.SA.applyConfigPatchKeys = function (config) {
+61
View File
@@ -350,6 +350,64 @@ export function resolveTurnIntent(patch, userText, { vetoFn } = {}) {
return { generate, look, vetoed, ask };
}
/** Params the client fills from Exact on Generate when the LLM omits them (sparse contract). */
export const EXACT_GENERATE_PARAM_KEYS = ['steps', 'cfg', 'sigma_shift'];
/**
* Turbo/RAW profile numbers from Exact — no sessionExact overlay.
* profileName should already reflect the live checkpoint (turbo vs raw).
*/
export function resolveExactProfileDefaults({ exact, profiles, profileName } = {}) {
const gen = exact?.generation && typeof exact.generation === 'object' ? exact.generation : {};
const profile = profileName || gen.profile || 'turbo';
const fromProfile = profiles?.[profile] && typeof profiles[profile] === 'object'
? profiles[profile]
: {};
return {
profile,
steps: fromProfile.steps ?? gen.steps ?? null,
cfg: fromProfile.cfg ?? gen.cfg ?? null,
sigma_shift: fromProfile.sigma_shift ?? gen.sigma_shift ?? null,
};
}
/**
* On generate, inject Exact profile steps/cfg/sigma when the patch omitted them.
* Client is authoritative so sparse LLM deltas are safe. Honors explicit patch values
* and sessionExact when the user asked for params this turn.
* Returns clearSessionKeys so the UI apply path is not blocked by stale sessionExact.
*/
export function mergeExactParamsForGenerate(patch, {
exact,
profiles,
profileName,
sessionExact,
userParamIntent,
} = {}) {
if (!patchWantsGenerate(patch)) {
return { patch, clearSessionKeys: [], profile: null };
}
const defaults = resolveExactProfileDefaults({ exact, profiles, profileName });
const out = { ...patch };
const clearSessionKeys = [];
for (const key of EXACT_GENERATE_PARAM_KEYS) {
if (out[key] != null) {
continue;
}
if (userParamIntent && sessionExact?.[key] != null) {
out[key] = sessionExact[key];
continue;
}
if (defaults[key] != null) {
out[key] = defaults[key];
if (sessionExact?.[key] != null && String(sessionExact[key]) !== String(defaults[key])) {
clearSessionKeys.push(key);
}
}
}
return { patch: out, clearSessionKeys, profile: defaults.profile };
}
export function attachSession(SA) {
SA.session = {
emptySession,
@@ -363,6 +421,9 @@ export function attachSession(SA) {
compactContext,
fullSettingsDump,
resolveTurnIntent,
resolveExactProfileDefaults,
mergeExactParamsForGenerate,
EXACT_GENERATE_PARAM_KEYS,
GEN_KEYS,
};
}