Add Image v2 as a sibling of Image edit, with separate Klein graphs.
Keep the v1 Image tab on its dual-branch template. The host agent follows Desktop's live port so Coolify stays on :8198. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import type { LoraStackItem } from '~/utils/loras'
|
||||
import type { VideoWorkflowId } from '~/utils/videoModels'
|
||||
import type { ImageV2PresetSettings } from '~/utils/imageV2'
|
||||
|
||||
export type GenerationPresetKind = 'video' | 'image'
|
||||
export type GenerationPresetKind = 'video' | 'image' | 'imagev2'
|
||||
|
||||
export type VideoPresetSettings = {
|
||||
workflow?: VideoWorkflowId
|
||||
@@ -75,11 +76,13 @@ export type GenerationPreset = {
|
||||
createdAt: number
|
||||
updatedAt: number
|
||||
loraStack: LoraStackItem[]
|
||||
settings: VideoPresetSettings | ImagePresetSettings
|
||||
settings: VideoPresetSettings | ImagePresetSettings | ImageV2PresetSettings
|
||||
}
|
||||
|
||||
export function parseGenerationPresetKind(raw: unknown): GenerationPresetKind {
|
||||
return raw === 'image' ? 'image' : 'video'
|
||||
if (raw === 'image') return 'image'
|
||||
if (raw === 'imagev2') return 'imagev2'
|
||||
return 'video'
|
||||
}
|
||||
|
||||
export function normalizePresetName(raw: unknown) {
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
export const IMAGE_V2_MODES = ['edit', 'compose'] as const
|
||||
export const IMAGE_V2_TASKS = ['scene', 'identity', 'outfit', 'face_lock'] as const
|
||||
|
||||
export type ImageV2Mode = (typeof IMAGE_V2_MODES)[number]
|
||||
export type ImageV2Task = (typeof IMAGE_V2_TASKS)[number]
|
||||
|
||||
export const IMAGE_V2_STEPS_DEFAULT = 24
|
||||
export const IMAGE_V2_CFG_DEFAULT = 4
|
||||
export const IMAGE_V2_TURBO_STEPS = 8
|
||||
export const IMAGE_V2_TURBO_CFG = 1
|
||||
export const IMAGE_V2_SNOFS_MODEL = 0.65
|
||||
export const IMAGE_V2_SNOFS_CLIP = 0.35
|
||||
export const IMAGE_V2_CONSISTENCY_MODEL = 0.7
|
||||
export const IMAGE_V2_CONSISTENCY_CLIP = 0.7
|
||||
export const IMAGE_V2_STRENGTH_MIN = 0
|
||||
export const IMAGE_V2_STRENGTH_MAX = 2
|
||||
export const IMAGE_V2_STRENGTH_STEP = 0.05
|
||||
|
||||
export const IMAGE_V2_SNOFS_LORA = 'klein_snofs_v1_4.safetensors'
|
||||
export const IMAGE_V2_CONSISTENCY_LORA = 'Flux2-Klein-9B-consistency-V2.safetensors'
|
||||
|
||||
export const IMAGE_V2_ROLE_HEADERS: Record<Exclude<ImageV2Task, 'scene'>, string> = {
|
||||
outfit: 'Person, face, body, pose, and background from image 1. Clothing only from image 2. Fit the outfit from image 2 to the body in image 1. Do not copy image 2’s face, body shape, or pose.',
|
||||
face_lock: 'Body, pose, and scene from image 1. Exact face from image 2.',
|
||||
identity: 'Same person as image 1. Use image 2 only to reinforce the face. Follow the user’s pose/scene prompt.'
|
||||
}
|
||||
|
||||
export function parseImageV2Mode(raw: unknown): ImageV2Mode | null {
|
||||
const value = String(raw || '').trim().toLowerCase()
|
||||
return IMAGE_V2_MODES.includes(value as ImageV2Mode) ? value as ImageV2Mode : null
|
||||
}
|
||||
|
||||
export function parseImageV2Task(raw: unknown, fallback: ImageV2Task = 'scene'): ImageV2Task {
|
||||
const value = String(raw || '').trim().toLowerCase()
|
||||
return IMAGE_V2_TASKS.includes(value as ImageV2Task) ? value as ImageV2Task : fallback
|
||||
}
|
||||
|
||||
export function clampImageV2Strength(raw: unknown, fallback: number) {
|
||||
const value = Number(raw)
|
||||
if (!Number.isFinite(value)) return fallback
|
||||
const snapped = Math.round(value / IMAGE_V2_STRENGTH_STEP) * IMAGE_V2_STRENGTH_STEP
|
||||
return Math.min(IMAGE_V2_STRENGTH_MAX, Math.max(IMAGE_V2_STRENGTH_MIN, Math.round(snapped * 100) / 100))
|
||||
}
|
||||
|
||||
export function composeImageV2Prompt(mode: ImageV2Mode, task: ImageV2Task, prompt: string) {
|
||||
const body = String(prompt || '').trim()
|
||||
if (mode !== 'compose' || task === 'scene') return body
|
||||
const header = IMAGE_V2_ROLE_HEADERS[task]
|
||||
return header ? `${header}\n\n${body}` : body
|
||||
}
|
||||
|
||||
export type ImageV2PresetSettings = {
|
||||
mode?: ImageV2Mode
|
||||
task?: ImageV2Task
|
||||
negative?: string
|
||||
snofsModel?: number
|
||||
snofsClip?: number
|
||||
consistencyModel?: number
|
||||
consistencyClip?: number
|
||||
steps?: number
|
||||
cfg?: number
|
||||
megapixels?: number
|
||||
turbo?: boolean
|
||||
}
|
||||
Reference in New Issue
Block a user