Fix realtime queued task counts
This commit is contained in:
@@ -120,6 +120,7 @@ export function PlaygroundPage(props: {
|
||||
const [mediaRuns, setMediaRuns] = useState<MediaGenerationRun[]>(readStoredMediaRuns);
|
||||
const [mediaMessage, setMediaMessage] = useState('');
|
||||
const isMountedRef = useRef(false);
|
||||
const pendingMediaModelRef = useRef('');
|
||||
const resumedTaskIdsRef = useRef(new Set<string>());
|
||||
const activeMode = useMemo(() => modeOptions.find((item) => item.value === props.mode) ?? modeOptions[0], [props.mode]);
|
||||
const modelOptions = useMemo(
|
||||
@@ -139,7 +140,17 @@ export function PlaygroundPage(props: {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedModel((current) => modelOptions.some((item) => item.value === current) ? current : modelOptions[0]?.value ?? '');
|
||||
setSelectedModel((current) => {
|
||||
const pendingModel = pendingMediaModelRef.current;
|
||||
if (pendingModel) {
|
||||
const resolvedPending = resolveModelOptionValue(pendingModel, modelOptions);
|
||||
if (resolvedPending) {
|
||||
pendingMediaModelRef.current = '';
|
||||
return resolvedPending;
|
||||
}
|
||||
}
|
||||
return modelOptions.some((item) => item.value === current) ? current : modelOptions[0]?.value ?? '';
|
||||
});
|
||||
}, [modelOptions]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -186,6 +197,7 @@ export function PlaygroundPage(props: {
|
||||
}, [activeApiKeySecret, mediaRuns, props.token]);
|
||||
|
||||
async function submitMediaTask(overrides?: {
|
||||
model?: string;
|
||||
mode?: Exclude<PlaygroundMode, 'chat'>;
|
||||
prompt?: string;
|
||||
settings?: MediaGenerationSettings;
|
||||
@@ -204,7 +216,8 @@ export function PlaygroundPage(props: {
|
||||
setMediaMessage('请选择可用于测试的 API Key;如果列表为空,请先创建一个 Key。');
|
||||
return;
|
||||
}
|
||||
if (!selectedModel) {
|
||||
const runModel = overrides?.model ?? selectedModel;
|
||||
if (!runModel) {
|
||||
setMediaMessage('当前没有可用模型,请确认用户组权限或平台模型配置。');
|
||||
return;
|
||||
}
|
||||
@@ -214,12 +227,13 @@ export function PlaygroundPage(props: {
|
||||
}
|
||||
|
||||
const localId = newLocalId();
|
||||
const modelLabel = modelOptions.find((item) => item.value === selectedModel)?.label ?? selectedModel;
|
||||
const modelLabel = modelOptions.find((item) => item.value === runModel)?.label ?? runModel;
|
||||
const run: MediaGenerationRun = {
|
||||
createdAt: new Date().toISOString(),
|
||||
localId,
|
||||
mode: runMode,
|
||||
modelLabel,
|
||||
modelValue: runModel,
|
||||
prompt: trimmedPrompt,
|
||||
settings: runSettings,
|
||||
status: 'submitting',
|
||||
@@ -229,7 +243,7 @@ export function PlaygroundPage(props: {
|
||||
setMediaMessage('');
|
||||
try {
|
||||
const requestPayload = {
|
||||
model: selectedModel,
|
||||
model: runModel,
|
||||
prompt: trimmedPrompt,
|
||||
...mediaRequestPayload(runSettings, runMode),
|
||||
};
|
||||
@@ -268,24 +282,38 @@ export function PlaygroundPage(props: {
|
||||
}));
|
||||
}
|
||||
|
||||
function selectMediaRunModel(run: MediaGenerationRun) {
|
||||
const runModel = resolveMediaRunModelValue(run, modelOptions);
|
||||
if (runModel) {
|
||||
pendingMediaModelRef.current = '';
|
||||
setSelectedModel(runModel);
|
||||
return runModel;
|
||||
}
|
||||
const fallbackModel = firstString(run.modelValue, run.task?.requestedModel, taskRequestModel(run.task), run.task?.model, run.task?.resolvedModel);
|
||||
pendingMediaModelRef.current = fallbackModel;
|
||||
return fallbackModel;
|
||||
}
|
||||
|
||||
function editMediaRun(run: MediaGenerationRun) {
|
||||
setPrompt(run.prompt);
|
||||
setMediaSettings(run.settings);
|
||||
selectMediaRunModel(run);
|
||||
if (props.mode !== run.mode) {
|
||||
props.onModeChange(run.mode);
|
||||
}
|
||||
setMediaMessage('已带入这条任务的提示词和参数,可调整后再次生成。');
|
||||
setMediaMessage('已带入这条任务的模型、提示词和参数,可调整后再次生成。');
|
||||
}
|
||||
|
||||
function rerunMediaRun(run: MediaGenerationRun) {
|
||||
setPrompt(run.prompt);
|
||||
setMediaSettings(run.settings);
|
||||
const runModel = selectMediaRunModel(run);
|
||||
if (props.mode !== run.mode) {
|
||||
props.onModeChange(run.mode);
|
||||
setMediaMessage('已切换到对应模式并带入参数,请确认模型后再次生成。');
|
||||
setMediaMessage('已切换到对应模式并带入模型和参数,请确认后再次生成。');
|
||||
return;
|
||||
}
|
||||
void submitMediaTask({ mode: run.mode, prompt: run.prompt, settings: run.settings });
|
||||
void submitMediaTask({ mode: run.mode, model: runModel, prompt: run.prompt, settings: run.settings });
|
||||
}
|
||||
|
||||
const mediaComposer = props.mode === 'chat' ? null : (
|
||||
@@ -1043,6 +1071,46 @@ function modelOptionLabel(option: ModelOption) {
|
||||
return `${option.label}${provider}${count}`;
|
||||
}
|
||||
|
||||
function resolveMediaRunModelValue(run: MediaGenerationRun, modelOptions: ModelOption[]) {
|
||||
const candidates = [
|
||||
run.modelValue,
|
||||
run.task?.requestedModel,
|
||||
taskRequestModel(run.task),
|
||||
run.task?.model,
|
||||
run.task?.resolvedModel,
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
const value = resolveModelOptionValue(candidate, modelOptions);
|
||||
if (value) return value;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function resolveModelOptionValue(value: unknown, modelOptions: ModelOption[]) {
|
||||
const raw = stringFromUnknown(value);
|
||||
if (!raw) return '';
|
||||
const direct = modelOptions.find((item) => item.value === raw);
|
||||
if (direct) return direct.value;
|
||||
const matched = modelOptions.find((item) => item.models.some((model) => (
|
||||
model.modelAlias === raw
|
||||
|| model.modelName === raw
|
||||
|| model.displayName === raw
|
||||
)));
|
||||
return matched?.value ?? '';
|
||||
}
|
||||
|
||||
function taskRequestModel(task: GatewayTask | undefined) {
|
||||
return stringFromUnknown(task?.request?.model);
|
||||
}
|
||||
|
||||
function firstString(...values: unknown[]) {
|
||||
for (const value of values) {
|
||||
const text = stringFromUnknown(value);
|
||||
if (text) return text;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function updateMediaRun(runs: MediaGenerationRun[], localId: string, patch: Partial<MediaGenerationRun>) {
|
||||
return runs.map((run) => run.localId === localId ? { ...run, ...patch } : run);
|
||||
}
|
||||
@@ -1091,7 +1159,8 @@ function mediaRunFromStorage(value: unknown, index: number): MediaGenerationRun
|
||||
const task = taskFromStorage(record.task);
|
||||
const createdAt = dateStringFromUnknown(record.createdAt) ?? new Date().toISOString();
|
||||
const localId = stringFromUnknown(record.localId) || task?.id || `stored-${index}-${createdAt}`;
|
||||
const modelLabel = stringFromUnknown(record.modelLabel) || task?.model || '未知模型';
|
||||
const modelValue = stringFromUnknown(record.modelValue) || task?.requestedModel || taskRequestModel(task) || task?.model || '';
|
||||
const modelLabel = stringFromUnknown(record.modelLabel) || modelValue || '未知模型';
|
||||
let status: MediaGenerationRun['status'] = stringFromUnknown(record.status) || task?.status || 'failed';
|
||||
let error = stringFromUnknown(record.error);
|
||||
if (status === 'submitting' && !task?.id) {
|
||||
@@ -1104,6 +1173,7 @@ function mediaRunFromStorage(value: unknown, index: number): MediaGenerationRun
|
||||
localId,
|
||||
mode,
|
||||
modelLabel,
|
||||
modelValue,
|
||||
prompt,
|
||||
settings: mediaSettingsFromStorage(record.settings),
|
||||
status,
|
||||
|
||||
@@ -41,6 +41,7 @@ export interface MediaGenerationRun {
|
||||
localId: string;
|
||||
mode: Exclude<PlaygroundMode, 'chat'>;
|
||||
modelLabel: string;
|
||||
modelValue?: string;
|
||||
prompt: string;
|
||||
settings: MediaGenerationSettings;
|
||||
status: GatewayTask['status'] | 'submitting';
|
||||
|
||||
Reference in New Issue
Block a user