fix(gateway): keep agent image attachment checks accurate

This commit is contained in:
Vincent Koc
2026-05-03 00:20:58 -07:00
parent 74f243a0d0
commit 882ddc4665
3 changed files with 8 additions and 18 deletions

View File

@@ -37,6 +37,7 @@ Docs: https://docs.openclaw.ai
- Gateway/sessions: keep agent runtime metadata on lightweight `sessions.list` rows so model-only session patches do not make Control UI lose runtime identity. Thanks @vincentkoc.
- Gateway/sessions: keep bulk `sessions.list` rows lightweight by skipping per-row transcript usage fallback, display model inference, and plugin projection, avoiding event-loop stalls in large session stores. Thanks @Marvinthebored and @vincentkoc.
- Gateway/models: keep read-only `models.list` fallbacks on persisted/current metadata and configured rows while using static auth checks, so missing `models.json` files no longer runtime-load provider discovery or stall gateway after restart. Fixes #76382; refs #76360 and #75707. Thanks @trojy13, @RayWoo, @AnathemaOfficial, and @vincentkoc.
- Gateway/models: keep agent image attachment capability checks on the full catalog while preserving the read-only `models.list` path, so image sends are not rejected after static catalog fallback.
- CLI/plugins: reject missing plugin ids before config writes in `plugins enable` and `plugins disable` so a typo no longer persists a stale config entry. (#73554) Thanks @ai-hpc.
- Agents/sessions: preserve delivered trailing assistant replies during session-file repair so Telegram/WebChat history is not rewritten to drop already-delivered responses. Fixes #76329. Thanks @obviyus.
- Gateway/chat history: preserve oversized transcript turns as explicit omitted-message placeholders while avoiding large JSONL parse stalls. Thanks @Marvinthebored and @vincentkoc.

View File

@@ -518,7 +518,7 @@ describe("gateway server models + voicewake", () => {
);
});
test("models.list configured view includes auth-backed provider catalog entries", async () => {
test("models.list configured view does not run runtime discovery without a read-only catalog", async () => {
await withEnvAsync(
{
ANTHROPIC_API_KEY: undefined,
@@ -528,21 +528,11 @@ describe("gateway server models + voicewake", () => {
async () => {
await withModelsConfig({}, async () => {
await seedPiCatalog();
const discoverCallsBefore = piSdkMock.discoverCalls;
const res = await listModels({ view: "configured" });
expect(res.ok).toBe(true);
expect(res.payload?.models).toEqual([
{
id: "gpt-test-a",
name: "A-Model",
provider: "openai",
contextWindow: 8000,
},
{
id: "gpt-test-z",
name: "gpt-test-z",
provider: "openai",
},
]);
expect(res.payload?.models).toEqual([]);
expect(piSdkMock.discoverCalls).toBe(discoverCallsBefore);
});
},
);
@@ -654,9 +644,8 @@ describe("gateway server models + voicewake", () => {
expected: [
{
id: "claude-test-a",
name: "A-Model",
name: "claude-test-a",
provider: "anthropic",
contextWindow: 200_000,
},
{
id: "gpt-test-z",

View File

@@ -1257,7 +1257,7 @@ export function resolveSessionModelRef(
}
export async function resolveGatewayModelSupportsImages(params: {
loadGatewayModelCatalog: () => Promise<ModelCatalogEntry[]>;
loadGatewayModelCatalog: (params?: { readOnly?: boolean }) => Promise<ModelCatalogEntry[]>;
provider?: string;
model?: string;
}): Promise<boolean> {
@@ -1266,7 +1266,7 @@ export async function resolveGatewayModelSupportsImages(params: {
}
try {
const catalog = await params.loadGatewayModelCatalog();
const catalog = await params.loadGatewayModelCatalog({ readOnly: false });
const modelEntry = findModelCatalogEntry(catalog, {
provider: params.provider,
modelId: params.model,