mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-02 00:18:17 +00:00
select provider in frontend (#944)
This commit is contained in:
1 parent
5415109a35
commit
11bf5949fe
36 files changed
+258
-86
No files matched your search
+9
-4
@@ -277,8 +277,13 @@ pub async fn handle_request(
|
||||
}
|
||||
};
|
||||
|
||||
let mut success_event = match request.provider {
|
||||
None | Some(GenerationProvider::Artcraft) => {
|
||||
let provider = request.provider
|
||||
.unwrap_or(GenerationProvider::Artcraft);
|
||||
|
||||
info!("edit image with {:?} via provider {:?}", &model, &provider);
|
||||
|
||||
let mut success_event = match provider {
|
||||
GenerationProvider::Artcraft => {
|
||||
handle_image_edit_artcraft(
|
||||
model,
|
||||
request,
|
||||
@@ -288,7 +293,7 @@ pub async fn handle_request(
|
||||
storyteller_creds_manager,
|
||||
).await?
|
||||
}
|
||||
Some(GenerationProvider::Sora) => {
|
||||
GenerationProvider::Sora => {
|
||||
handle_image_edit_sora(
|
||||
model,
|
||||
request,
|
||||
@@ -301,7 +306,7 @@ pub async fn handle_request(
|
||||
}
|
||||
_ => {
|
||||
return Err(GenerateError::BadProviderForModel {
|
||||
provider: request.provider.unwrap_or(GenerationProvider::Artcraft),
|
||||
provider,
|
||||
model: image_edit_model_to_model_type(model),
|
||||
})
|
||||
}
|
||||
|
||||
+8
-3
@@ -234,8 +234,13 @@ pub async fn handle_request(
|
||||
}
|
||||
};
|
||||
|
||||
let success_event = match request.provider {
|
||||
None | Some(GenerationProvider::Artcraft) => {
|
||||
let provider = request.provider
|
||||
.unwrap_or(GenerationProvider::Artcraft);
|
||||
|
||||
info!("image inpaint with {:?} via provider {:?}", &model, &provider);
|
||||
|
||||
let success_event = match provider {
|
||||
GenerationProvider::Artcraft => {
|
||||
handle_inpaint_artcraft(
|
||||
model,
|
||||
request,
|
||||
@@ -245,7 +250,7 @@ pub async fn handle_request(
|
||||
storyteller_creds_manager,
|
||||
).await?
|
||||
}
|
||||
Some(provider) => {
|
||||
_ => {
|
||||
return Err(GenerateError::BadProviderForModel {
|
||||
provider,
|
||||
model: image_inpaint_model_to_model_type(model),
|
||||
|
||||
+23
-4
@@ -4,6 +4,7 @@ use crate::core::commands::enqueue::image_to_video::artcraft::handle_artcraft_vi
|
||||
use crate::core::commands::enqueue::image_to_video::grok::handle_grok_video::handle_grok_video;
|
||||
use crate::core::commands::enqueue::image_to_video::sora2::handle_sora_sora2::handle_sora_sora2;
|
||||
use crate::core::commands::enqueue::task_enqueue_success::TaskEnqueueSuccess;
|
||||
use crate::core::commands::enqueue::text_to_image::enqueue_text_to_image_command::TextToImageModel;
|
||||
use crate::core::commands::response::failure_response_wrapper::{CommandErrorResponseWrapper, CommandErrorStatus};
|
||||
use crate::core::commands::response::shorthand::Response;
|
||||
use crate::core::commands::response::success_response_wrapper::SerializeMarker;
|
||||
@@ -20,6 +21,7 @@ use crate::services::grok::state::grok_credential_manager::GrokCredentialManager
|
||||
use crate::services::sora::state::sora_credential_manager::SoraCredentialManager;
|
||||
use crate::services::sora::state::sora_task_queue::SoraTaskQueue;
|
||||
use crate::services::storyteller::state::storyteller_credential_manager::StorytellerCredentialManager;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::tauri::ux::tauri_command_caller::TauriCommandCaller;
|
||||
use log::{error, info, warn};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
@@ -76,6 +78,10 @@ pub enum VideoModel {
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct EnqueueImageToVideoRequest {
|
||||
/// The provider to use (defaults to Artcraft/Storyteller).
|
||||
/// Not all (provider, model) combinations are valid.
|
||||
pub provider: Option<GenerationProvider>,
|
||||
|
||||
/// REQUIRED.
|
||||
/// The model to use.
|
||||
pub model: Option<VideoModel>,
|
||||
@@ -263,8 +269,22 @@ pub async fn handle_request(
|
||||
storyteller_creds_manager: &StorytellerCredentialManager,
|
||||
) -> Result<TaskEnqueueSuccess, GenerateError> {
|
||||
|
||||
let result = match request.model {
|
||||
Some(VideoModel::GrokVideo) => {
|
||||
let model = match request.model {
|
||||
Some(model) => model,
|
||||
None => {
|
||||
return Err(GenerateError::no_model_specified())
|
||||
}
|
||||
};
|
||||
|
||||
let provider = match (model, request.provider) {
|
||||
(VideoModel::GrokVideo, _) => GenerationProvider::Grok,
|
||||
_ => request.provider.unwrap_or(GenerationProvider::Artcraft),
|
||||
};
|
||||
|
||||
info!("generate video with {:?} via provider {:?}", &model, &provider);
|
||||
|
||||
let result = match provider {
|
||||
GenerationProvider::Grok => {
|
||||
handle_grok_video(
|
||||
&request,
|
||||
app,
|
||||
@@ -273,8 +293,7 @@ pub async fn handle_request(
|
||||
grok_creds_manager,
|
||||
).await
|
||||
}
|
||||
Some(VideoModel::Sora2) => {
|
||||
// TODO: Route based on forthcoming provider parameter.
|
||||
GenerationProvider::Sora => {
|
||||
handle_sora_sora2(
|
||||
&request,
|
||||
app,
|
||||
|
||||
+2
@@ -333,6 +333,8 @@ pub async fn dispatch_request(
|
||||
_ => request.provider.unwrap_or(GenerationProvider::Artcraft),
|
||||
};
|
||||
|
||||
info!("generate image with {:?} via provider {:?}", &model, &provider);
|
||||
|
||||
match provider {
|
||||
GenerationProvider::Artcraft => {
|
||||
handle_text_to_image_artcraft(
|
||||
|
||||
@@ -19,9 +19,11 @@ import {
|
||||
//ProviderSelector,
|
||||
//PROVIDER_LOOKUP_BY_PAGE,
|
||||
useSelectedImageModel,
|
||||
useSelectedProviderForModel,
|
||||
} from "@storyteller/ui-model-selector";
|
||||
import { useCanvasBgRemovedEvent } from "@storyteller/tauri-api";
|
||||
import { TutorialModalButton } from "@storyteller/ui-tutorial-modal";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
const PAGE_ID: ModelPage = ModelPage.Canvas2D;
|
||||
|
||||
@@ -61,6 +63,9 @@ const PageDraw = () => {
|
||||
const selectedImageModel: ImageModel | undefined =
|
||||
useSelectedImageModel(PAGE_ID);
|
||||
|
||||
const selectedProvider : GenerationProvider | undefined =
|
||||
useSelectedProviderForModel(PAGE_ID, selectedImageModel?.id);
|
||||
|
||||
useDeleteHotkeys({ onDelete: store.deleteSelectedItems });
|
||||
useUndoRedoHotkeys({ undo: store.undo, redo: store.redo });
|
||||
useCopyPasteHotkeys({
|
||||
@@ -304,6 +309,7 @@ const PageDraw = () => {
|
||||
onFitPressed={onFitPressed}
|
||||
//selectedModelInfo={selectedModelInfo}
|
||||
selectedImageModel={selectedImageModel}
|
||||
selectedProvider={selectedProvider}
|
||||
/>
|
||||
</div>
|
||||
<SideToolbar
|
||||
|
||||
@@ -17,6 +17,7 @@ const PromptEditor: React.FC<PromptEditorProps> = ({
|
||||
onFitPressed,
|
||||
//selectedModelInfo,
|
||||
selectedImageModel,
|
||||
selectedProvider,
|
||||
}) => {
|
||||
const [images, setImages] = useState<ImageStyle[]>([]);
|
||||
|
||||
@@ -48,6 +49,7 @@ const PromptEditor: React.FC<PromptEditorProps> = ({
|
||||
onFitPressed={onFitPressed}
|
||||
//selectedModelInfo={selectedModelInfo}
|
||||
selectedImageModel={selectedImageModel}
|
||||
selectedProvider={selectedProvider}
|
||||
/>
|
||||
</JobProvider>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ImageModel } from "@storyteller/model-list";
|
||||
import { ModelInfo } from "@storyteller/model-list";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export interface PromptEditorProps {
|
||||
initialPrompt?: string;
|
||||
@@ -13,6 +14,7 @@ export interface PromptEditorProps {
|
||||
onFitPressed?: () => void;
|
||||
selectedModelInfo?: ModelInfo;
|
||||
selectedImageModel?: ImageModel;
|
||||
selectedProvider?: GenerationProvider;
|
||||
}
|
||||
|
||||
export type AspectRatio = "1:1" | "3:2" | "2:3";
|
||||
|
||||
@@ -5,6 +5,8 @@ import {
|
||||
EnqueueImageInpaint,
|
||||
EnqueueEditImageSize,
|
||||
EnqueueEditImageResolution,
|
||||
EnqueueEditImageRequest,
|
||||
EnqueueImageInpaintRequest,
|
||||
} from "@storyteller/tauri-api";
|
||||
import { PromptsApi } from "@storyteller/api";
|
||||
import { RefImage, usePromptEditStore } from "@storyteller/ui-promptbox";
|
||||
@@ -21,6 +23,7 @@ import MarkerToolControlBar from "./MarkerToolControlBar";
|
||||
import {
|
||||
ClassyModelSelector,
|
||||
useSelectedImageModel,
|
||||
useSelectedProviderForModel,
|
||||
IMAGE_EDITOR_PAGE_MODEL_LIST,
|
||||
ModelPage,
|
||||
//ProviderSelector,
|
||||
@@ -29,6 +32,8 @@ import {
|
||||
import { ImageModel } from "@storyteller/model-list";
|
||||
import { HistoryStack, ImageBundle } from "./HistoryStack";
|
||||
import { TutorialModalButton } from "@storyteller/ui-tutorial-modal";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
|
||||
const PAGE_ID: ModelPage = ModelPage.ImageEditor;
|
||||
|
||||
@@ -38,6 +43,9 @@ const PageEdit = () => {
|
||||
const selectedImageModel: ImageModel | undefined =
|
||||
useSelectedImageModel(PAGE_ID);
|
||||
|
||||
const selectedProvider : GenerationProvider | undefined =
|
||||
useSelectedProviderForModel(PAGE_ID, selectedImageModel?.id);
|
||||
|
||||
// State for canvas dimensions
|
||||
const canvasWidth = useRef<number>(1024);
|
||||
const canvasHeight = useRef<number>(1024);
|
||||
@@ -322,6 +330,7 @@ const PageEdit = () => {
|
||||
aspectRatio?: string;
|
||||
resolution?: string;
|
||||
images?: RefImage[];
|
||||
selectedProvider?: GenerationProvider;
|
||||
},
|
||||
) => {
|
||||
const editedImageToken = store.baseImageInfo?.mediaToken;
|
||||
@@ -374,7 +383,7 @@ const PageEdit = () => {
|
||||
|
||||
if (selectedImageModel?.editingIsInpainting) {
|
||||
const arrayBuffer = await getMaskArrayBuffer();
|
||||
result = await EnqueueImageInpaint({
|
||||
let request : EnqueueImageInpaintRequest = {
|
||||
model: selectedImageModel,
|
||||
image_media_token: editedImageToken,
|
||||
mask_image_raw_bytes: arrayBuffer,
|
||||
@@ -382,7 +391,11 @@ const PageEdit = () => {
|
||||
image_count: generationCount,
|
||||
frontend_caller: "image_editor",
|
||||
frontend_subscriber_id: subscriberId,
|
||||
});
|
||||
};
|
||||
if (!!options?.selectedProvider) {
|
||||
request.provider = options.selectedProvider;
|
||||
}
|
||||
result = await EnqueueImageInpaint(request);
|
||||
} else if (selectedImageModel?.isNanoBananaModel()) {
|
||||
const compositeFile = await getCompositeCanvasFile();
|
||||
if (!compositeFile) {
|
||||
@@ -398,7 +411,7 @@ const PageEdit = () => {
|
||||
return;
|
||||
}
|
||||
const imgs = options?.images || [];
|
||||
result = await EnqueueEditImage({
|
||||
let request: EnqueueEditImageRequest = {
|
||||
model: selectedImageModel,
|
||||
scene_image_media_token: snapshotResult.data,
|
||||
image_media_tokens: imgs
|
||||
@@ -410,10 +423,14 @@ const PageEdit = () => {
|
||||
frontend_subscriber_id: subscriberId,
|
||||
aspect_ratio: mapAspectRatio(options?.aspectRatio),
|
||||
image_resolution: mapResolution(options?.resolution),
|
||||
});
|
||||
};
|
||||
if (!!options?.selectedProvider) {
|
||||
request.provider = options.selectedProvider;
|
||||
}
|
||||
result = await EnqueueEditImage(request);
|
||||
} else {
|
||||
const imgs = options?.images || [];
|
||||
result = await EnqueueEditImage({
|
||||
let request : EnqueueEditImageRequest = {
|
||||
model: selectedImageModel,
|
||||
image_media_tokens: [
|
||||
editedImageToken,
|
||||
@@ -428,10 +445,14 @@ const PageEdit = () => {
|
||||
frontend_subscriber_id: subscriberId,
|
||||
aspect_ratio: mapAspectRatio(options?.aspectRatio),
|
||||
image_resolution: mapResolution(options?.resolution),
|
||||
});
|
||||
};
|
||||
if (!!options?.selectedProvider) {
|
||||
request.provider = options.selectedProvider;
|
||||
}
|
||||
result = await EnqueueEditImage(request);
|
||||
}
|
||||
|
||||
if (result.status === "success") {
|
||||
if (result?.status === "success") {
|
||||
setPendingGenerations((prev) => [
|
||||
...prev,
|
||||
{ id: subscriberId as string, count: generationCount },
|
||||
@@ -609,6 +630,7 @@ const PageEdit = () => {
|
||||
>
|
||||
<PromptEditor
|
||||
selectedImageModel={selectedImageModel}
|
||||
selectedProvider={selectedProvider}
|
||||
onModeChange={(mode: string) => {
|
||||
store.setActiveTool(mode as ActiveEditTool);
|
||||
}}
|
||||
|
||||
@@ -77,6 +77,7 @@ import {
|
||||
STAGE_3D_PAGE_MODEL_LIST,
|
||||
ModelPage,
|
||||
useSelectedImageModel,
|
||||
useSelectedProviderForModel,
|
||||
ClassyModelSelector,
|
||||
//ProviderSelector,
|
||||
//PROVIDER_LOOKUP_BY_PAGE,
|
||||
@@ -87,6 +88,7 @@ import { useTabStore } from "../Stores/TabState";
|
||||
import PageEdit from "../PageEdit/PageEdit";
|
||||
import { ImageModel } from "@storyteller/model-list";
|
||||
import { TutorialModalButton } from "@storyteller/ui-tutorial-modal";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
const PAGE_ID: ModelPage = ModelPage.Stage3D;
|
||||
|
||||
@@ -117,6 +119,9 @@ export const PageEditor = () => {
|
||||
const selectedImageModel: ImageModel | undefined =
|
||||
useSelectedImageModel(PAGE_ID);
|
||||
|
||||
const selectedProvider : GenerationProvider | undefined =
|
||||
useSelectedProviderForModel(PAGE_ID, selectedImageModel?.id);
|
||||
|
||||
const height =
|
||||
dndTimelineHeight.value > -1
|
||||
? pageHeight.value - dndTimelineHeight.value - 56
|
||||
@@ -530,6 +535,7 @@ export const PageEditor = () => {
|
||||
handleCameraFocalLengthChange={handleCameraFocalLengthChange}
|
||||
onAspectRatioSelect={onAspectRatioSelect}
|
||||
selectedImageModel={selectedImageModel}
|
||||
selectedProvider={selectedProvider}
|
||||
setEnginePrompt={(prompt) => {
|
||||
console.log("setEnginePrompt", prompt);
|
||||
if (!editorEngine) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
ModelPage,
|
||||
ClassyModelSelector,
|
||||
useSelectedImageModel,
|
||||
useSelectedProviderForModel,
|
||||
//ProviderSelector,
|
||||
//PROVIDER_LOOKUP_BY_PAGE,
|
||||
} from "@storyteller/ui-model-selector";
|
||||
@@ -27,6 +28,7 @@ import {
|
||||
import { Badge } from "@storyteller/ui-badge";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { TutorialModalButton } from "@storyteller/ui-tutorial-modal";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
const PAGE_ID: ModelPage = ModelPage.TextToImage;
|
||||
|
||||
@@ -43,6 +45,9 @@ const TextToImage = ({ imageMediaId, imageUrl }: TextToImageProps) => {
|
||||
const selectedImageModel: ImageModel | undefined =
|
||||
useSelectedImageModel(PAGE_ID);
|
||||
|
||||
const selectedProvider : GenerationProvider | undefined =
|
||||
useSelectedProviderForModel(PAGE_ID, selectedImageModel?.id);
|
||||
|
||||
const jobContext: JobContextType = {
|
||||
jobTokens: [],
|
||||
addJobToken: () => {},
|
||||
@@ -214,6 +219,7 @@ const TextToImage = ({ imageMediaId, imageUrl }: TextToImageProps) => {
|
||||
}}
|
||||
uploadImage={uploadImage}
|
||||
selectedModel={selectedImageModel}
|
||||
selectedProvider={selectedProvider}
|
||||
imageMediaId={imageMediaId}
|
||||
url={imageUrl ?? undefined}
|
||||
onImageRowVisibilityChange={setImageRowVisible}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
IMAGE_TO_VIDEO_PAGE_MODEL_LIST,
|
||||
ModelPage,
|
||||
useSelectedVideoModel,
|
||||
useSelectedProviderForModel,
|
||||
//ProviderSelector,
|
||||
//PROVIDER_LOOKUP_BY_PAGE,
|
||||
} from "@storyteller/ui-model-selector";
|
||||
@@ -21,6 +22,7 @@ import {
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { uploadImage } from "../../components/reusable/UploadModalMedia/uploadImage";
|
||||
import { TutorialModalButton } from "@storyteller/ui-tutorial-modal";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
const PAGE_ID: ModelPage = ModelPage.ImageToVideo;
|
||||
|
||||
@@ -42,6 +44,9 @@ const ImageToVideo = ({ imageMediaId, imageUrl }: ImageToVideoProps) => {
|
||||
const selectedVideoModel: VideoModel | undefined =
|
||||
useSelectedVideoModel(PAGE_ID);
|
||||
|
||||
const selectedProvider: GenerationProvider | undefined =
|
||||
useSelectedProviderForModel(PAGE_ID, selectedVideoModel?.id);
|
||||
|
||||
const jobContext: JobContextType = {
|
||||
jobTokens: [],
|
||||
addJobToken: () => {},
|
||||
@@ -186,6 +191,7 @@ const ImageToVideo = ({ imageMediaId, imageUrl }: ImageToVideoProps) => {
|
||||
<PromptBoxVideo
|
||||
useJobContext={() => jobContext}
|
||||
selectedModel={selectedVideoModel}
|
||||
selectedProvider={selectedProvider}
|
||||
imageMediaId={imageMediaId}
|
||||
url={imageUrl ?? undefined}
|
||||
onImageRowVisibilityChange={setImageRowVisible}
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
export enum GenerationProvider {
|
||||
Artcraft = "artcraft",
|
||||
Fal = "fal",
|
||||
Grok = "grok",
|
||||
Midjourney = "midjourney",
|
||||
Sora = "sora",
|
||||
WorldLabs = "world_labs",
|
||||
// NB: We should build our own open source Fal
|
||||
//Fal = "fal",
|
||||
}
|
||||
@@ -4,4 +4,3 @@ export * from "./lib/classy-model-selector";
|
||||
export * from "./lib/classy-model-selector-store";
|
||||
export * from "./lib/provider-selector";
|
||||
export * from "./lib/provider-icons";
|
||||
export * from "./lib/provider-lookup";
|
||||
@@ -1,16 +1,16 @@
|
||||
import { create } from "zustand";
|
||||
import { ModelPage } from "./model-pages";
|
||||
import { ImageModel, Model, VideoModel } from "@storyteller/model-list";
|
||||
import { Provider } from "@storyteller/tauri-api";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
interface ClassyModelSelectorState {
|
||||
selectedModels: { [page in ModelPage]?: Model };
|
||||
selectedProviders: { [page in ModelPage]?: { [modelId: string]: Provider } };
|
||||
selectedProviders: { [page in ModelPage]?: { [modelId: string]: GenerationProvider } };
|
||||
setSelectedModel: (page: ModelPage, model: Model) => void;
|
||||
setSelectedProvider: (
|
||||
page: ModelPage,
|
||||
modelId: string,
|
||||
provider: Provider
|
||||
provider: GenerationProvider
|
||||
) => void;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export const getSelectedVideoModel = (
|
||||
export const getSelectedProviderForModel = (
|
||||
page: ModelPage,
|
||||
modelId: string
|
||||
): Provider | undefined => {
|
||||
): GenerationProvider | undefined => {
|
||||
const { selectedProviders } = useClassyModelSelectorStore.getState();
|
||||
const byPage = selectedProviders[page];
|
||||
if (!byPage) return undefined;
|
||||
@@ -104,10 +104,11 @@ export const useSelectedVideoModel = (
|
||||
: undefined;
|
||||
};
|
||||
|
||||
// TODO: This shouldn't be on a per-page basis.
|
||||
export const useSelectedProviderForModel = (
|
||||
page: ModelPage,
|
||||
modelId: string | undefined
|
||||
): Provider | undefined =>
|
||||
): GenerationProvider | undefined =>
|
||||
useClassyModelSelectorStore((s) =>
|
||||
modelId ? s.selectedProviders[page]?.[modelId] : undefined
|
||||
);
|
||||
@@ -10,7 +10,7 @@ import { getProviderDisplayName, getProviderIcon } from "./provider-icons";
|
||||
import { Model } from "@storyteller/model-list";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCircleCheck, faChevronUp } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { PROVIDER_LOOKUP_BY_PAGE } from "./provider-lookup";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
interface ClassyModelSelectorProps {
|
||||
items: Omit<PopoverItem, "selected">[];
|
||||
@@ -26,7 +26,7 @@ interface ClassyModelSelectorProps {
|
||||
maxListHeight?: number | string;
|
||||
}
|
||||
|
||||
const DEFAULT_PROVIDER_OPTIONS: Provider[] = [Provider.ArtCraft];
|
||||
const DEFAULT_PROVIDER_OPTIONS: GenerationProvider[] = [GenerationProvider.Artcraft];
|
||||
|
||||
function ProviderTooltipContent({
|
||||
page,
|
||||
@@ -40,7 +40,7 @@ function ProviderTooltipContent({
|
||||
modelId?: string;
|
||||
model?: Model;
|
||||
modelLabel?: string;
|
||||
allowedProviders: Provider[];
|
||||
allowedProviders: GenerationProvider[];
|
||||
onFinished?: () => void;
|
||||
}) {
|
||||
const { setSelectedModel, setSelectedProvider } =
|
||||
@@ -126,10 +126,7 @@ export function ClassyModelSelector({
|
||||
const modelId = item.model?.id;
|
||||
if (!modelId) continue;
|
||||
if (selectedProvidersByModel[modelId]) continue;
|
||||
const allowed =
|
||||
providersByModel?.[modelId] ??
|
||||
PROVIDER_LOOKUP_BY_PAGE[page]?.[modelId] ??
|
||||
DEFAULT_PROVIDER_OPTIONS;
|
||||
const allowed = item.model?.getProviders() || DEFAULT_PROVIDER_OPTIONS;
|
||||
if (allowed.length > 0) {
|
||||
setSelectedProvider(page, modelId, allowed[0]);
|
||||
}
|
||||
@@ -146,11 +143,7 @@ export function ClassyModelSelector({
|
||||
() =>
|
||||
items.map((item) => {
|
||||
const modelId = item.model?.id;
|
||||
const allowedProviders: Provider[] = modelId
|
||||
? (providersByModel?.[modelId] ??
|
||||
PROVIDER_LOOKUP_BY_PAGE[page]?.[modelId] ??
|
||||
DEFAULT_PROVIDER_OPTIONS)
|
||||
: DEFAULT_PROVIDER_OPTIONS;
|
||||
const allowedProviders = item.model?.getProviders() || DEFAULT_PROVIDER_OPTIONS;
|
||||
|
||||
const hasMultipleProviders = allowedProviders.length >= 2;
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { getCreatorIcon, ModelCreator } from "@storyteller/model-list";
|
||||
import { IsDesktopApp } from "@storyteller/tauri-utils";
|
||||
import { Provider } from "@storyteller/tauri-api";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
const PROVIDER_TO_CREATOR: Partial<Record<Provider, ModelCreator>> = {
|
||||
[Provider.ArtCraft]: ModelCreator.ArtCraft,
|
||||
[Provider.Fal]: ModelCreator.Fal,
|
||||
[Provider.Sora]: ModelCreator.OpenAi,
|
||||
[Provider.Grok]: ModelCreator.Grok,
|
||||
[Provider.Midjourney]: ModelCreator.Midjourney,
|
||||
const GENERATION_PROVIDER_TO_CREATOR: Partial<Record<GenerationProvider, ModelCreator>> = {
|
||||
[GenerationProvider.Artcraft]: ModelCreator.ArtCraft,
|
||||
[GenerationProvider.Grok]: ModelCreator.Grok,
|
||||
[GenerationProvider.Midjourney]: ModelCreator.Midjourney,
|
||||
[GenerationProvider.Sora]: ModelCreator.OpenAi,
|
||||
[GenerationProvider.WorldLabs]: ModelCreator.WorldLabs,
|
||||
};
|
||||
|
||||
export const getProviderIcon = (
|
||||
provider: Provider,
|
||||
provider: GenerationProvider,
|
||||
className = "h-4 w-4 icon-auto-contrast"
|
||||
): ReactNode => {
|
||||
const creator = PROVIDER_TO_CREATOR[provider];
|
||||
const creator = GENERATION_PROVIDER_TO_CREATOR[provider];
|
||||
if (creator) return getCreatorIcon(creator, className);
|
||||
return (
|
||||
<img
|
||||
@@ -30,21 +30,19 @@ export const getProviderIcon = (
|
||||
);
|
||||
};
|
||||
|
||||
export const getProviderDisplayName = (provider: Provider | string): string => {
|
||||
export const getProviderDisplayName = (provider: GenerationProvider): string => {
|
||||
switch (provider) {
|
||||
case Provider.ArtCraft:
|
||||
case GenerationProvider.Artcraft:
|
||||
return "ArtCraft";
|
||||
case Provider.Fal:
|
||||
return "Fal";
|
||||
case Provider.Sora:
|
||||
return "Sora / ChatGPT";
|
||||
case Provider.Grok:
|
||||
case GenerationProvider.Grok:
|
||||
return "Grok";
|
||||
case Provider.Midjourney:
|
||||
case GenerationProvider.Midjourney:
|
||||
return "Midjourney";
|
||||
case "worldlabs":
|
||||
case GenerationProvider.Sora:
|
||||
return "Sora / ChatGPT";
|
||||
case GenerationProvider.WorldLabs:
|
||||
return "World Labs";
|
||||
default:
|
||||
return provider;
|
||||
return "Unknown Provider";
|
||||
}
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
import { ModelPage } from "./model-pages";
|
||||
import { Provider } from "@storyteller/tauri-api";
|
||||
|
||||
export type ProvidersByModel = Partial<Record<string, Provider[]>>;
|
||||
|
||||
// Centralized lookup: page (product/tab) → modelId → allowed providers
|
||||
export const PROVIDER_LOOKUP_BY_PAGE: Record<ModelPage, ProvidersByModel> = {
|
||||
[ModelPage.TextToImage]: {
|
||||
gpt_image_1: [Provider.ArtCraft, Provider.Sora],
|
||||
grok_image: [Provider.Grok],
|
||||
midjourney: [Provider.Midjourney],
|
||||
},
|
||||
[ModelPage.ImageToVideo]: {
|
||||
grok_video: [Provider.Grok],
|
||||
},
|
||||
[ModelPage.Canvas2D]: {
|
||||
gpt_image_1: [Provider.ArtCraft, Provider.Sora],
|
||||
},
|
||||
[ModelPage.Stage3D]: { gpt_image_1: [Provider.ArtCraft, Provider.Sora] },
|
||||
[ModelPage.ImageEditor]: {
|
||||
gpt_image_1: [Provider.ArtCraft, Provider.Sora],
|
||||
},
|
||||
};
|
||||
@@ -11,6 +11,9 @@
|
||||
{
|
||||
"path": "../../tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "../../api-enums"
|
||||
},
|
||||
{
|
||||
"path": "../../model-list"
|
||||
},
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../api-enums/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../model-list/tsconfig.lib.json"
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
EnqueueEditImage,
|
||||
EnqueueEditImageSize,
|
||||
EnqueueEditImageResolution,
|
||||
EnqueueEditImageRequest,
|
||||
} from "@storyteller/tauri-api";
|
||||
import { usePrompt2DStore } from "./promptStore";
|
||||
import { gtagEvent } from "@storyteller/google-analytics";
|
||||
@@ -39,6 +40,7 @@ import { getCapabilitiesForModel } from "@storyteller/model-list";
|
||||
import { ImageModel } from "@storyteller/model-list";
|
||||
import { ImagePromptRow } from "./ImagePromptRow";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export type AspectRatio = "wide" | "tall" | "square";
|
||||
|
||||
@@ -53,6 +55,7 @@ interface PromptBox2DProps {
|
||||
progressCallback: (newState: UploaderState) => void;
|
||||
}) => Promise<void>;
|
||||
selectedImageModel?: ImageModel;
|
||||
selectedProvider?: GenerationProvider;
|
||||
getCanvasRenderBitmap: () => MaybeCanvasRenderBitmapType;
|
||||
EncodeImageBitmapToBase64: (imageBitmap: ImageBitmap) => Promise<string>;
|
||||
useJobContext: () => JobContextType;
|
||||
@@ -69,6 +72,7 @@ export const PromptBox2D = ({
|
||||
onEnqueuePressed,
|
||||
onAspectRatioChange,
|
||||
selectedImageModel,
|
||||
selectedProvider,
|
||||
onFitPressed,
|
||||
}: PromptBox2DProps) => {
|
||||
useSignals();
|
||||
@@ -272,7 +276,7 @@ export const PromptBox2D = ({
|
||||
const aspectRatio = getCurrentAspectRatio();
|
||||
const resolution = getCurrentResolution();
|
||||
|
||||
const generateResponse = await EnqueueEditImage({
|
||||
let request : EnqueueEditImageRequest = {
|
||||
model: selectedImageModel,
|
||||
scene_image_media_token: snapshotMediaToken.data!,
|
||||
image_media_tokens: referenceImages
|
||||
@@ -283,7 +287,13 @@ export const PromptBox2D = ({
|
||||
image_count: generationCount,
|
||||
aspect_ratio: aspectRatio,
|
||||
image_resolution: resolution,
|
||||
});
|
||||
};
|
||||
|
||||
if (!!selectedProvider) {
|
||||
request.provider = selectedProvider;
|
||||
}
|
||||
|
||||
const generateResponse = await EnqueueEditImage(request);
|
||||
|
||||
console.log("generateResponse", generateResponse);
|
||||
};
|
||||
|
||||
@@ -42,10 +42,12 @@ import {
|
||||
EnqueueEditImage,
|
||||
EnqueueEditImageSize,
|
||||
EnqueueEditImageResolution,
|
||||
EnqueueEditImageRequest,
|
||||
} from "@storyteller/tauri-api";
|
||||
import { usePrompt3DStore } from "./promptStore";
|
||||
import { gtagEvent } from "@storyteller/google-analytics";
|
||||
import { ImageModel } from "@storyteller/model-list";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
import { ImagePromptRow } from "./ImagePromptRow";
|
||||
|
||||
interface PromptBox3DProps {
|
||||
@@ -67,6 +69,7 @@ interface PromptBox3DProps {
|
||||
onAspectRatioSelect: (newRatio: CameraAspectRatio) => void;
|
||||
setEnginePrompt: (prompt: string) => void;
|
||||
selectedImageModel?: ImageModel;
|
||||
selectedProvider?: GenerationProvider;
|
||||
snapshotCurrentFrame:
|
||||
| ((shouldDownload?: boolean) => {
|
||||
base64Snapshot: string;
|
||||
@@ -94,6 +97,7 @@ export const PromptBox3D = ({
|
||||
onAspectRatioSelect,
|
||||
setEnginePrompt,
|
||||
selectedImageModel,
|
||||
selectedProvider,
|
||||
snapshotCurrentFrame,
|
||||
}: PromptBox3DProps) => {
|
||||
useSignals();
|
||||
@@ -366,7 +370,7 @@ export const PromptBox3D = ({
|
||||
const aspectRatio = getCurrentAspectRatio();
|
||||
const resolution = getCurrentResolution();
|
||||
|
||||
const generateResponse = await EnqueueEditImage({
|
||||
let request: EnqueueEditImageRequest = {
|
||||
model: selectedImageModel,
|
||||
scene_image_media_token: snapshotResult.data!,
|
||||
image_media_tokens: referenceImages.map((image) => image.mediaToken),
|
||||
@@ -375,7 +379,13 @@ export const PromptBox3D = ({
|
||||
image_count: 1,
|
||||
aspect_ratio: aspectRatio,
|
||||
image_resolution: resolution,
|
||||
});
|
||||
};
|
||||
|
||||
if (!!selectedProvider) {
|
||||
request.provider = selectedProvider;
|
||||
}
|
||||
|
||||
const generateResponse = await EnqueueEditImage(request);
|
||||
|
||||
console.log("generateResponse", generateResponse);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import { ImageModel, getCapabilitiesForModel } from "@storyteller/model-list";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { ImagePromptRow, type UploadImageFn } from "./ImagePromptRow";
|
||||
import { RefImage, usePromptEditStore } from "./promptStore";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export interface PromptBoxEditProps {
|
||||
onModeChange?: (mode: string) => void;
|
||||
@@ -39,11 +40,13 @@ export interface PromptBoxEditProps {
|
||||
aspectRatio?: string;
|
||||
resolution?: string;
|
||||
images?: RefImage[];
|
||||
selectedProvider?: GenerationProvider;
|
||||
},
|
||||
) => void | Promise<void>;
|
||||
isDisabled?: boolean;
|
||||
onFitPressed?: () => void | Promise<void>;
|
||||
selectedImageModel?: ImageModel;
|
||||
selectedProvider?: GenerationProvider;
|
||||
generationCount?: number;
|
||||
onGenerationCountChange?: (count: number) => void;
|
||||
supportsMaskedInpainting?: boolean;
|
||||
@@ -62,6 +65,7 @@ export const PromptBoxEdit = ({
|
||||
isDisabled,
|
||||
onFitPressed,
|
||||
selectedImageModel,
|
||||
selectedProvider,
|
||||
generationCount: generationCountProp,
|
||||
onGenerationCountChange,
|
||||
supportsMaskedInpainting = false,
|
||||
@@ -277,6 +281,7 @@ export const PromptBoxEdit = ({
|
||||
aspectRatio,
|
||||
resolution,
|
||||
images: referenceImages,
|
||||
selectedProvider: selectedProvider,
|
||||
}),
|
||||
);
|
||||
} finally {
|
||||
|
||||
@@ -32,6 +32,7 @@ import { usePromptImageStore, RefImage } from "./promptStore";
|
||||
import { gtagEvent } from "@storyteller/google-analytics";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { ImagePromptRow } from "./ImagePromptRow";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
interface PromptBoxImageProps {
|
||||
useJobContext: () => JobContextType;
|
||||
@@ -50,6 +51,7 @@ interface PromptBoxImageProps {
|
||||
subscriberId: string,
|
||||
) => void | Promise<void>;
|
||||
selectedModel?: ImageModel;
|
||||
selectedProvider?: GenerationProvider;
|
||||
imageMediaId?: string;
|
||||
url?: string;
|
||||
onImageRowVisibilityChange?: (visible: boolean) => void;
|
||||
@@ -60,6 +62,7 @@ export const PromptBoxImage = ({
|
||||
uploadImage,
|
||||
onEnqueuePressed,
|
||||
selectedModel,
|
||||
selectedProvider,
|
||||
imageMediaId,
|
||||
url,
|
||||
onImageRowVisibilityChange,
|
||||
@@ -299,6 +302,10 @@ export const PromptBoxImage = ({
|
||||
frontend_subscriber_id: subscriberId,
|
||||
};
|
||||
|
||||
if (!!selectedProvider) {
|
||||
request.provider = selectedProvider;
|
||||
}
|
||||
|
||||
if (
|
||||
selectedModel?.canUseImagePrompt &&
|
||||
!!referenceImages &&
|
||||
|
||||
@@ -36,6 +36,7 @@ import { ImagePromptRow } from "./ImagePromptRow";
|
||||
import type { UploadImageFn } from "./ImagePromptRow";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { toast } from "@storyteller/ui-toaster";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
type GROK_ASPECT_RATIO = "landscape" | "portrait" | "square";
|
||||
|
||||
@@ -59,6 +60,7 @@ interface PromptBoxVideoProps {
|
||||
subscriberId: string,
|
||||
) => void | Promise<void>;
|
||||
selectedModel?: VideoModel;
|
||||
selectedProvider?: GenerationProvider;
|
||||
imageMediaId?: string;
|
||||
url?: string;
|
||||
onImageRowVisibilityChange?: (visible: boolean) => void;
|
||||
@@ -69,6 +71,7 @@ export const PromptBoxVideo = ({
|
||||
useJobContext,
|
||||
onEnqueuePressed,
|
||||
selectedModel,
|
||||
selectedProvider,
|
||||
imageMediaId,
|
||||
url,
|
||||
onImageRowVisibilityChange,
|
||||
@@ -285,6 +288,10 @@ export const PromptBoxVideo = ({
|
||||
frontend_subscriber_id: subscriberId,
|
||||
};
|
||||
|
||||
if (!!selectedProvider) {
|
||||
request.provider = selectedProvider;
|
||||
}
|
||||
|
||||
if (selectedModel.generateWithSound) {
|
||||
request.generate_audio = !!generateWithSound;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ModelCreator } from "src/index.js";
|
||||
import { Model, ModelKind } from "./Model.js";
|
||||
import { ModelCategory } from "../legacy/ModelConfig.js";
|
||||
import { ModelTag } from "./metadata/ModelTag.js";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export class ImageModel extends Model {
|
||||
// Typescript type discriminator property
|
||||
@@ -63,6 +64,7 @@ export class ImageModel extends Model {
|
||||
canChangeAspectRatio?: boolean;
|
||||
tags?: ModelTag[];
|
||||
progressBarTime?: number;
|
||||
providers?: GenerationProvider[];
|
||||
}) {
|
||||
if (args.maxGenerationCount < 1) {
|
||||
throw new Error("maxGenerationCount must be at least 1");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ModelCreator } from "./metadata/ModelCreator.js";
|
||||
import { ModelCategory, ModelConfig } from "../legacy/ModelConfig.js";
|
||||
import { ModelTag } from "./metadata/ModelTag.js";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export type ModelKind = "model" | "image_model" | "video_model" | "gaussian_model";
|
||||
|
||||
@@ -40,6 +41,9 @@ export class Model {
|
||||
// A list of filterable "capabilities" that can be used to filter models.
|
||||
readonly tags: ModelTag[];
|
||||
|
||||
// Use `getProviders()` to read the list.
|
||||
protected readonly providers?: GenerationProvider[];
|
||||
|
||||
// Optional provider preferences; two-to-many via page and providers.
|
||||
readonly preferredProvidersByPage?: Partial<Record<string, string[]>>;
|
||||
|
||||
@@ -56,6 +60,7 @@ export class Model {
|
||||
selectorDescription: string;
|
||||
selectorBadges: string[];
|
||||
tags?: ModelTag[];
|
||||
providers?: GenerationProvider[];
|
||||
preferredProvidersByPage?: Partial<Record<string, string[]>>;
|
||||
progressBarTime?: number;
|
||||
}) {
|
||||
@@ -68,10 +73,15 @@ export class Model {
|
||||
this.selectorDescription = args.selectorDescription;
|
||||
this.selectorBadges = args.selectorBadges;
|
||||
this.tags = args.tags ?? [];
|
||||
this.providers = args.providers;
|
||||
this.preferredProvidersByPage = args.preferredProvidersByPage;
|
||||
this.progressBarTime = args.progressBarTime ?? 20000;
|
||||
}
|
||||
|
||||
getProviders(): GenerationProvider[] {
|
||||
return this.providers ?? [GenerationProvider.Artcraft];
|
||||
}
|
||||
|
||||
toLegacyBadges(): { label: string }[] {
|
||||
return this.selectorBadges.map((b) => ({ label: b }));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Model, ModelKind } from "./Model.js";
|
||||
import { ModelCategory } from "../legacy/ModelConfig.js";
|
||||
import { ModelTag } from "./metadata/ModelTag.js";
|
||||
import { SizeOption } from "./metadata/SizeOption.js";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export class VideoModel extends Model {
|
||||
// Typescript type discriminator property
|
||||
@@ -41,6 +42,7 @@ export class VideoModel extends Model {
|
||||
sizeOptions?: SizeOption[];
|
||||
progressBarTime?: number;
|
||||
generateWithSound?: boolean;
|
||||
providers?: GenerationProvider[];
|
||||
}) {
|
||||
super(args);
|
||||
this.startFrame = args.startFrame;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
import { ImageModel } from "../classes/ImageModel.js";
|
||||
import { ModelCreator } from "../classes/metadata/ModelCreator.js";
|
||||
import { ModelTag } from "../classes/metadata/ModelTag.js";
|
||||
@@ -11,6 +12,9 @@ export const IMAGE_MODELS: ImageModel[] = [
|
||||
fullName: "Grok",
|
||||
category: "image",
|
||||
creator: ModelCreator.Grok,
|
||||
providers: [
|
||||
GenerationProvider.Grok,
|
||||
],
|
||||
selectorName: "Grok",
|
||||
selectorDescription: "Fast af",
|
||||
selectorBadges: ["10 sec."],
|
||||
@@ -27,6 +31,9 @@ export const IMAGE_MODELS: ImageModel[] = [
|
||||
fullName: "Midjourney",
|
||||
category: "image",
|
||||
creator: ModelCreator.Midjourney,
|
||||
providers: [
|
||||
GenerationProvider.Midjourney
|
||||
],
|
||||
selectorName: "Midjourney",
|
||||
selectorDescription: "Stunning style and quality",
|
||||
selectorBadges: ["45 sec."],
|
||||
@@ -147,6 +154,10 @@ export const IMAGE_MODELS: ImageModel[] = [
|
||||
fullName: "GPT Image 1 (GPT-4o)",
|
||||
category: "image",
|
||||
creator: ModelCreator.OpenAi,
|
||||
providers: [
|
||||
GenerationProvider.Artcraft,
|
||||
GenerationProvider.Sora
|
||||
],
|
||||
selectorName: "GPT Image 1 (GPT-4o)",
|
||||
selectorDescription: "Slow, but super smart",
|
||||
selectorBadges: ["60 sec."],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
import { VideoModel } from "../classes/VideoModel.js";
|
||||
import { ModelCreator } from "../classes/metadata/ModelCreator.js";
|
||||
import { SizeIconOption } from "../classes/metadata/SizeOption.js";
|
||||
@@ -9,6 +10,9 @@ export const VIDEO_MODELS: VideoModel[] = [
|
||||
fullName: "Grok Video",
|
||||
category: "video",
|
||||
creator: ModelCreator.Grok,
|
||||
providers: [
|
||||
GenerationProvider.Grok
|
||||
],
|
||||
selectorName: "Grok Video",
|
||||
selectorDescription: "Fastest video model",
|
||||
selectorBadges: ["20 sec."],
|
||||
@@ -129,6 +133,10 @@ export const VIDEO_MODELS: VideoModel[] = [
|
||||
fullName: "Sora 2",
|
||||
category: "video",
|
||||
creator: ModelCreator.OpenAi,
|
||||
providers: [
|
||||
GenerationProvider.Artcraft,
|
||||
GenerationProvider.Sora,
|
||||
],
|
||||
selectorName: "Sora 2",
|
||||
selectorDescription: "Smart video model",
|
||||
selectorBadges: ["2 min."],
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
{
|
||||
"path": "../tauri-utils"
|
||||
},
|
||||
{
|
||||
"path": "../api-enums"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
"references": [
|
||||
{
|
||||
"path": "../tauri-utils/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../api-enums/tsconfig.lib.json"
|
||||
}
|
||||
],
|
||||
"exclude": [
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { CommandResult } from "../common/CommandStatus";
|
||||
import { ImageModel } from "@storyteller/model-list";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export interface EnqueueEditImageRequest {
|
||||
|
||||
/// The model to use.
|
||||
model?: ImageModel | EnqueueEditImageModel;
|
||||
|
||||
// The provider to use.
|
||||
provider?: GenerationProvider;
|
||||
|
||||
/// If set, this is the first image in the contextual image set.
|
||||
/// This gets submitted along with `image_media_tokens` and will
|
||||
// be prompt engineered by Tauri.
|
||||
@@ -45,6 +48,7 @@ export interface EnqueueEditImageRequest {
|
||||
// (We do some transformations from the public-facing request object.)
|
||||
interface RawEnqueueEditImageRequest {
|
||||
model?: EnqueueEditImageModel | string;
|
||||
provider?: GenerationProvider;
|
||||
scene_image_media_token?: string;
|
||||
image_media_tokens?: string[];
|
||||
prompt?: string;
|
||||
@@ -126,6 +130,10 @@ export const EnqueueEditImage = async (request: EnqueueEditImageRequest) : Promi
|
||||
model: modelName,
|
||||
prompt: request.prompt,
|
||||
};
|
||||
|
||||
if (!!request.provider) {
|
||||
mutableRequest.provider = request.provider;
|
||||
}
|
||||
|
||||
if (!!request.scene_image_media_token) {
|
||||
mutableRequest.scene_image_media_token = request.scene_image_media_token;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { CommandResult } from "../common/CommandStatus";
|
||||
import { ImageModel, ModelInfo } from "@storyteller/model-list";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export interface EnqueueImageInpaintRequest {
|
||||
// The model to use.
|
||||
model?: ImageModel | ModelInfo | EnqueueImageInpaintModel;
|
||||
|
||||
// The provider to use.
|
||||
provider?: GenerationProvider;
|
||||
|
||||
// The image we're editing.
|
||||
image_media_token?: string;
|
||||
|
||||
@@ -30,6 +34,7 @@ export interface EnqueueImageInpaintRequest {
|
||||
// (We do some transformations from the public-facing request object.)
|
||||
interface RawEnqueueImageInpaintRequest {
|
||||
model?: EnqueueImageInpaintModel | string;
|
||||
provider?: GenerationProvider;
|
||||
image_media_token?: string;
|
||||
mask_image_raw_bytes?: Uint8Array;
|
||||
prompt?: string;
|
||||
@@ -89,6 +94,10 @@ export const EnqueueImageInpaint = async (request: EnqueueImageInpaintRequest) :
|
||||
model: modelName,
|
||||
prompt: request.prompt,
|
||||
};
|
||||
|
||||
if (!!request.provider) {
|
||||
mutableRequest.provider = request.provider;
|
||||
}
|
||||
|
||||
if (!!request.image_media_token) {
|
||||
mutableRequest.image_media_token = request.image_media_token;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { CommandResult } from "../common/CommandStatus";
|
||||
import { Model } from "@storyteller/model-list";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export enum EnqueueImageToVideoErrorType {
|
||||
/// Caller didn't specify a model
|
||||
@@ -17,6 +18,9 @@ export interface EnqueueImageToVideoRequest {
|
||||
// Required. The model to use.
|
||||
model?: Model;
|
||||
|
||||
// The provider to use.
|
||||
provider?: GenerationProvider;
|
||||
|
||||
// Required. Starting frame.
|
||||
image_media_token?: string;
|
||||
|
||||
@@ -44,6 +48,7 @@ export interface EnqueueImageToVideoRequest {
|
||||
|
||||
interface RawEnqueueImageToVideoRequest {
|
||||
model?: string;
|
||||
provider?: GenerationProvider;
|
||||
image_media_token?: string;
|
||||
end_frame_image_media_token?: string;
|
||||
prompt?: string;
|
||||
@@ -77,6 +82,10 @@ export const EnqueueImageToVideo = async (
|
||||
image_media_token: request.image_media_token,
|
||||
};
|
||||
|
||||
if (request.provider) {
|
||||
mutableRequest.provider = request.provider;
|
||||
}
|
||||
|
||||
if (request.prompt) {
|
||||
mutableRequest.prompt = request.prompt;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { CommandResult } from "../common/CommandStatus";
|
||||
import { Model } from "@storyteller/model-list";
|
||||
import { GenerationProvider } from "@storyteller/api-enums";
|
||||
|
||||
export enum EnqueueTextToImageErrorType {
|
||||
/// Caller didn't specify a model
|
||||
@@ -17,6 +18,9 @@ export interface EnqueueTextToImageRequest {
|
||||
// The model to use.
|
||||
model?: Model | EnqueueTextToImageModel;
|
||||
|
||||
// The provider to use.
|
||||
provider?: GenerationProvider;
|
||||
|
||||
// The text prompt.
|
||||
prompt?: string;
|
||||
|
||||
@@ -46,8 +50,9 @@ export interface EnqueueTextToImageRequest {
|
||||
// Shape of request sent to Tauri
|
||||
// (We do some transformations from the public-facing request object.)
|
||||
interface EnqueueTextToImageRawRequest {
|
||||
prompt?: string;
|
||||
model?: EnqueueTextToImageModel | string; // TODO: Shouldn't allow string
|
||||
provider?: GenerationProvider;
|
||||
prompt?: string;
|
||||
aspect_ratio?: EnqueueTextToImageSize;
|
||||
image_resolution?: EnqueueTextToImageResolution;
|
||||
number_images?: number;
|
||||
@@ -113,6 +118,10 @@ export const EnqueueTextToImage = async (request: EnqueueTextToImageRequest) : P
|
||||
prompt: request.prompt,
|
||||
};
|
||||
|
||||
if (!!request.provider) {
|
||||
mutableRequest.provider = request.provider;
|
||||
}
|
||||
|
||||
if (!!request.aspect_ratio) {
|
||||
mutableRequest.aspect_ratio = request.aspect_ratio;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
|
||||
// TODO: REMOVE THIS.
|
||||
// Deprecated in favor of @storyteller/api-enums - GenerationProvider
|
||||
export enum Provider {
|
||||
ArtCraft = "artcraft",
|
||||
Fal = "fal",
|
||||
Sora = "sora",
|
||||
Grok = "grok",
|
||||
Midjourney = "midjourney",
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user