Keep bot jobs and harness calls from hanging
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import HarnessError from "../../harness-error";
|
||||
import type { HarnessAdapter, HarnessImageOutput } from "../../types";
|
||||
import grabProviderPreset from "../grab-provider-preset";
|
||||
@@ -54,7 +55,12 @@ const generateImage: HarnessAdapter["generateImage"] = async ({
|
||||
media_type: item.media_type || "image/png",
|
||||
});
|
||||
} else if (typeof item?.url == "string") {
|
||||
const download = await fetch(item.url, { signal });
|
||||
const download = await fetch(item.url, {
|
||||
signal: AbortSignal.any([
|
||||
signal,
|
||||
AbortSignal.timeout(AppData.HarnessRequestTimeoutMs),
|
||||
]),
|
||||
});
|
||||
|
||||
if (download.ok) {
|
||||
images.push({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import guessModelModalities from "../../catalog/guess-model-modalities";
|
||||
import HarnessError from "../../harness-error";
|
||||
import type { HarnessAdapter, HarnessCatalogModel } from "../../types";
|
||||
import grabProviderPreset from "../grab-provider-preset";
|
||||
import openRouterModelToCatalog, {
|
||||
@@ -27,6 +28,18 @@ const listModels: HarnessAdapter["listModels"] = async ({
|
||||
});
|
||||
|
||||
const json = await res.json().catch(() => null);
|
||||
|
||||
/**
|
||||
* An unreadable list is a failed sync, not an empty catalog: keeping
|
||||
* the models already known beats marking them all unavailable.
|
||||
*/
|
||||
if (json === null) {
|
||||
throw new HarnessError({
|
||||
message: `${provider.name || preset.title} returned an unreadable model list.`,
|
||||
retryable: true,
|
||||
});
|
||||
}
|
||||
|
||||
const items: any[] = Array.isArray(json?.data)
|
||||
? json.data
|
||||
: Array.isArray(json?.models)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import HarnessError from "../../harness-error";
|
||||
import type { HarnessAdapter } from "../../types";
|
||||
import providerRequest from "./provider-request";
|
||||
|
||||
@@ -36,6 +37,19 @@ const transcribe: HarnessAdapter["transcribe"] = async ({
|
||||
|
||||
const json = await res.json().catch(() => null);
|
||||
|
||||
/**
|
||||
* A cut-off or malformed answer is a failed call, not silence: saying
|
||||
* it failed lets the harness try the next model instead of handing the
|
||||
* user an empty transcript.
|
||||
*/
|
||||
if (json === null) {
|
||||
throw new HarnessError({
|
||||
message: `${candidate.provider.name || "The provider"} returned an unreadable transcript.`,
|
||||
retryable: true,
|
||||
candidate_key: candidate.key,
|
||||
});
|
||||
}
|
||||
|
||||
return { text: String(json?.text || "").trim() };
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { z } from "zod";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import TaskTimeoutError from "@/src/utils/task-timeout-error";
|
||||
import withTimeout from "@/src/utils/with-timeout";
|
||||
import HarnessError from "../harness-error";
|
||||
import type { HarnessTool, HarnessToolCall } from "../types";
|
||||
|
||||
@@ -40,14 +42,27 @@ export default async function runToolCall({ call, tools, signal }: Params) {
|
||||
}
|
||||
|
||||
try {
|
||||
return truncate({
|
||||
text: await tool.run({ args: parsed ? parsed.data : raw, signal }),
|
||||
const text = await withTimeout({
|
||||
timeout_ms: AppData.HarnessToolTimeoutMs,
|
||||
signal,
|
||||
message: `${call.name} took too long and was stopped.`,
|
||||
task: (tool_signal) =>
|
||||
tool.run({
|
||||
args: parsed ? parsed.data : raw,
|
||||
signal: tool_signal,
|
||||
}),
|
||||
});
|
||||
|
||||
return truncate({ text });
|
||||
} catch (error: unknown) {
|
||||
if (signal.aborted) {
|
||||
throw new HarnessError({ message: `Cancelled.`, code: "aborted" });
|
||||
}
|
||||
|
||||
if (error instanceof TaskTimeoutError) {
|
||||
return `Error: ${error.message}`;
|
||||
}
|
||||
|
||||
return `Error: ${error instanceof Error ? error.message : String(error)}`;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user