Ship Assistent 0.15.3: user-owned Generate, SwarmUI aspects, HF import UX.
Chips and quick patches apply params without auto-Generate; aspect sizes match Swarm Side Length 1024. HF import shows drafts after switching filter from approved-only; training status and job polling improved. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { describe, it } from 'node:test';
|
||||
import {
|
||||
DEFAULT_ASPECT_TABLE,
|
||||
buildDefaultAspectTable,
|
||||
swarmSizeFromRef,
|
||||
} from '../src/aspect.js';
|
||||
|
||||
describe('aspect.js (SwarmUI side 1024)', () => {
|
||||
it('16:9 and 9:16 match Swarm Resolution dropdown', () => {
|
||||
assert.deepEqual(swarmSizeFromRef('16:9'), [1344, 768]);
|
||||
assert.deepEqual(swarmSizeFromRef('9:16'), [768, 1344]);
|
||||
});
|
||||
|
||||
it('default table uses Swarm formula for landscape/portrait chips', () => {
|
||||
assert.deepEqual(DEFAULT_ASPECT_TABLE['16:9'], [1344, 768]);
|
||||
assert.deepEqual(DEFAULT_ASPECT_TABLE['9:16'], [768, 1344]);
|
||||
assert.deepEqual(DEFAULT_ASPECT_TABLE['2:3'], [832, 1216]);
|
||||
assert.deepEqual(DEFAULT_ASPECT_TABLE['1:1'], [1024, 1024]);
|
||||
});
|
||||
|
||||
it('2.35:1 aliases 21:9', () => {
|
||||
assert.deepEqual(DEFAULT_ASPECT_TABLE['2.35:1'], DEFAULT_ASPECT_TABLE['21:9']);
|
||||
assert.deepEqual(DEFAULT_ASPECT_TABLE['21:9'], [1536, 640]);
|
||||
});
|
||||
|
||||
it('scales with side length', () => {
|
||||
const t = buildDefaultAspectTable(512);
|
||||
assert.deepEqual(t['16:9'], [672, 384]);
|
||||
});
|
||||
});
|
||||
+18
-1
@@ -23,11 +23,13 @@ describe('intent.js', () => {
|
||||
it('userAsksGenerate detects сгенерируй', () => {
|
||||
assert.equal(userAsksGenerate('сгенерируй'), true);
|
||||
assert.equal(userAsksGenerate('нарисуй лису'), true);
|
||||
assert.equal(userAsksGenerate('Давай сделаем изображение красивой рыжеволосой девушки'), true);
|
||||
assert.equal(userAsksGenerate('а ты знаешь какие то промпты с civitai'), false);
|
||||
assert.equal(userAsksGenerate('что ты умеешь'), false);
|
||||
assert.equal(userAsksGenerate('не генерируй'), false);
|
||||
});
|
||||
|
||||
it('resolveTurnIntent uses model generate + user generate ask + veto', () => {
|
||||
it('resolveTurnIntent uses user generate ask + veto, not model flag alone', () => {
|
||||
const lookOnly = resolveTurnIntent({ look_at: ['generate'] }, 'что не так с кадром?', {});
|
||||
assert.equal(lookOnly.generate, false);
|
||||
assert.equal(lookOnly.look, true);
|
||||
@@ -44,6 +46,21 @@ describe('intent.js', () => {
|
||||
|
||||
const chatOnly = resolveTurnIntent({ prompt: 'fox' }, 'что ты умеешь про генерацию?', {});
|
||||
assert.equal(chatOnly.generate, false);
|
||||
|
||||
const falseDump = resolveTurnIntent(
|
||||
{ prompt: 'civitai example', generate: true },
|
||||
'а ты знаешь какие то промпты с civitai',
|
||||
{},
|
||||
);
|
||||
assert.equal(falseDump.generate, false);
|
||||
assert.equal(falseDump.modelAsked, true);
|
||||
|
||||
const sdelаем = resolveTurnIntent(
|
||||
{ prompt: 'A 19-year-old redhead', generate: true },
|
||||
'Давай сделаем изображение красивой рыжеволосой девушки',
|
||||
{},
|
||||
);
|
||||
assert.equal(sdelаем.generate, true);
|
||||
});
|
||||
|
||||
it('packWantsVision for critique pack', () => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
isPatchObject,
|
||||
normalizePatch,
|
||||
setPatchKeys,
|
||||
visibleProse,
|
||||
} from '../src/patch.js';
|
||||
import {
|
||||
mergeDelta,
|
||||
@@ -56,6 +57,12 @@ describe('patch.js', () => {
|
||||
assert.equal(raw.prose, 'done');
|
||||
});
|
||||
|
||||
it('visibleProse hides the JSON fence when chat text is empty', () => {
|
||||
assert.equal(visibleProse('```json\n{"prompt":"fox","generate":true}\n```'), '');
|
||||
assert.equal(visibleProse('Ок, держи\n```json\n{"prompt":"fox"}\n```'), 'Ок, держи');
|
||||
assert.equal(visibleProse('просто чат без патча'), 'просто чат без патча');
|
||||
});
|
||||
|
||||
it('scheduler-only patch is detected with full key list', () => {
|
||||
setPatchKeys(['prompt', 'scheduler', 'generate', 'ask']);
|
||||
assert.equal(isPatchObject({ scheduler: 'euler' }), true);
|
||||
@@ -112,6 +119,16 @@ describe('session.js', () => {
|
||||
assert.equal(patchWantsGenerate({ generate: true }), true);
|
||||
});
|
||||
|
||||
it('resolveTurnIntent ignores model generate:true on a knowledge question', () => {
|
||||
const intent = resolveTurnIntent(
|
||||
{ prompt: 'civitai example prompt', generate: true },
|
||||
'а ты знаешь какие то промпты с civitai',
|
||||
{ askGenerateFn: (t) => /сгенер|нарисуй/i.test(t) },
|
||||
);
|
||||
assert.equal(intent.generate, false);
|
||||
assert.equal(intent.modelAsked, true);
|
||||
});
|
||||
|
||||
it('mergeExactParamsForGenerate fills turbo profile when LLM omits steps/cfg', () => {
|
||||
const exact = {
|
||||
generation: { profile: 'turbo', steps: 8, cfg: 1, sigma_shift: 1.15 },
|
||||
|
||||
Reference in New Issue
Block a user