mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:20:43 +00:00
fix(plugins): align provider auth metadata
This commit is contained in:
@@ -23,6 +23,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Providers/Google: honor the private-network SSRF opt-in for Gemini image generation requests, so trusted proxy setups that resolve Google API hosts to private addresses can use `image_generate`. Fixes #67216.
|
||||
- Agents/transport: stop embedded runs from lowering the process-wide undici stream timeouts, so slow Gemini image generation and other long-running provider requests no longer inherit short run-attempt headers timeouts. Fixes #70423. Thanks @giangthb.
|
||||
- Providers/OpenRouter: send image-understanding prompts as user text before image parts, restoring non-empty vision responses for OpenRouter multimodal models. Fixes #70410.
|
||||
- Plugins/providers: mirror runtime auth choices in bundled provider manifests and detect `KIMI_API_KEY` for Moonshot/Kimi web search before plugin runtime loads. Thanks @vincentkoc.
|
||||
- Memory/QMD: recreate stale managed QMD collections when startup repair finds the collection name already exists, so root memory narrows back to `MEMORY.md` instead of staying on broad workspace markdown indexing.
|
||||
- Agents/OpenAI: surface selected-model capacity failures from PI, Codex, and auto-reply harness paths with a model-switch hint instead of the generic empty-response error. Thanks @vincentkoc.
|
||||
- Providers/OpenAI: route `openai/gpt-image-2` through configured Codex OAuth directly when an `openai-codex` profile is active, instead of probing `OPENAI_API_KEY` first.
|
||||
|
||||
@@ -23,6 +23,17 @@
|
||||
"groupLabel": "Anthropic",
|
||||
"groupHint": "Claude CLI + API key"
|
||||
},
|
||||
{
|
||||
"provider": "anthropic",
|
||||
"method": "setup-token",
|
||||
"choiceId": "setup-token",
|
||||
"choiceLabel": "Anthropic setup-token",
|
||||
"choiceHint": "Manual token path",
|
||||
"assistantPriority": 40,
|
||||
"groupId": "anthropic",
|
||||
"groupLabel": "Anthropic",
|
||||
"groupHint": "Claude CLI + API key + token"
|
||||
},
|
||||
{
|
||||
"provider": "anthropic",
|
||||
"method": "api-key",
|
||||
|
||||
41
extensions/comfy/index.test.ts
Normal file
41
extensions/comfy/index.test.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import fs from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveProviderPluginChoice } from "../../src/plugins/provider-auth-choice.runtime.js";
|
||||
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
|
||||
import plugin from "./index.js";
|
||||
|
||||
type ComfyManifest = {
|
||||
providerAuthChoices?: Array<{ choiceId?: string; method?: string; provider?: string }>;
|
||||
};
|
||||
|
||||
function readManifest(): ComfyManifest {
|
||||
return JSON.parse(
|
||||
fs.readFileSync(new URL("./openclaw.plugin.json", import.meta.url), "utf8"),
|
||||
) as ComfyManifest;
|
||||
}
|
||||
|
||||
describe("comfy provider plugin", () => {
|
||||
it("registers cloud API-key auth metadata", async () => {
|
||||
const provider = await registerSingleProviderPlugin(plugin);
|
||||
|
||||
expect(provider.id).toBe("comfy");
|
||||
expect(provider.envVars).toEqual(["COMFY_API_KEY", "COMFY_CLOUD_API_KEY"]);
|
||||
expect(provider.auth?.map((method) => method.id)).toEqual(["cloud-api-key"]);
|
||||
|
||||
const choice = resolveProviderPluginChoice({
|
||||
providers: [provider],
|
||||
choice: "comfy-cloud-api-key",
|
||||
});
|
||||
expect(choice?.provider.id).toBe("comfy");
|
||||
expect(choice?.method.id).toBe("cloud-api-key");
|
||||
expect(readManifest().providerAuthChoices).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
provider: "comfy",
|
||||
method: "cloud-api-key",
|
||||
choiceId: "comfy-cloud-api-key",
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth-api-key";
|
||||
import { buildComfyImageGenerationProvider } from "./image-generation-provider.js";
|
||||
import { buildComfyMusicGenerationProvider } from "./music-generation-provider.js";
|
||||
import { buildComfyVideoGenerationProvider } from "./video-generation-provider.js";
|
||||
@@ -15,7 +16,27 @@ export default definePluginEntry({
|
||||
label: "ComfyUI",
|
||||
docsPath: "/providers/comfy",
|
||||
envVars: ["COMFY_API_KEY", "COMFY_CLOUD_API_KEY"],
|
||||
auth: [],
|
||||
auth: [
|
||||
createProviderApiKeyAuthMethod({
|
||||
providerId: PROVIDER_ID,
|
||||
methodId: "cloud-api-key",
|
||||
label: "Comfy Cloud API key",
|
||||
hint: "API key for Comfy Cloud workflow runs",
|
||||
optionKey: "comfyApiKey",
|
||||
flagName: "--comfy-api-key",
|
||||
envVar: "COMFY_API_KEY",
|
||||
promptMessage: "Enter Comfy Cloud API key",
|
||||
wizard: {
|
||||
choiceId: "comfy-cloud-api-key",
|
||||
choiceLabel: "Comfy Cloud API key",
|
||||
choiceHint: "Required for cloud workflows",
|
||||
groupId: "comfy",
|
||||
groupLabel: "ComfyUI",
|
||||
groupHint: "Local or cloud workflows",
|
||||
onboardingScopes: ["image-generation"],
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
api.registerImageGenerationProvider(buildComfyImageGenerationProvider());
|
||||
api.registerMusicGenerationProvider(buildComfyMusicGenerationProvider());
|
||||
|
||||
@@ -5,6 +5,23 @@
|
||||
"providerAuthEnvVars": {
|
||||
"comfy": ["COMFY_API_KEY", "COMFY_CLOUD_API_KEY"]
|
||||
},
|
||||
"providerAuthChoices": [
|
||||
{
|
||||
"provider": "comfy",
|
||||
"method": "cloud-api-key",
|
||||
"choiceId": "comfy-cloud-api-key",
|
||||
"choiceLabel": "Comfy Cloud API key",
|
||||
"choiceHint": "Required for cloud workflows",
|
||||
"groupId": "comfy",
|
||||
"groupLabel": "ComfyUI",
|
||||
"groupHint": "Local or cloud workflows",
|
||||
"optionKey": "comfyApiKey",
|
||||
"cliFlag": "--comfy-api-key",
|
||||
"cliOption": "--comfy-api-key <key>",
|
||||
"cliDescription": "Comfy Cloud API key",
|
||||
"onboardingScopes": ["image-generation"]
|
||||
}
|
||||
],
|
||||
"contracts": {
|
||||
"imageGenerationProviders": ["comfy"],
|
||||
"musicGenerationProviders": ["comfy"],
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
import fs from "node:fs";
|
||||
import type { Context, Model } from "@mariozechner/pi-ai";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
|
||||
import { createCapturedThinkingConfigStream } from "../../test/helpers/plugins/stream-hooks.js";
|
||||
import plugin from "./index.js";
|
||||
import { createKimiWebSearchProvider } from "./src/kimi-web-search-provider.js";
|
||||
|
||||
type MoonshotManifest = {
|
||||
providerAuthEnvVars?: Record<string, string[]>;
|
||||
};
|
||||
|
||||
function readManifest(): MoonshotManifest {
|
||||
return JSON.parse(
|
||||
fs.readFileSync(new URL("./openclaw.plugin.json", import.meta.url), "utf8"),
|
||||
) as MoonshotManifest;
|
||||
}
|
||||
|
||||
describe("moonshot provider plugin", () => {
|
||||
it("mirrors Kimi web-search env credentials in manifest metadata", () => {
|
||||
const manifestEnvVars = readManifest().providerAuthEnvVars?.moonshot ?? [];
|
||||
|
||||
expect(manifestEnvVars).toEqual(expect.arrayContaining(createKimiWebSearchProvider().envVars));
|
||||
});
|
||||
|
||||
it("owns replay policy for OpenAI-compatible Moonshot transports without mangling native Kimi tool_call IDs", async () => {
|
||||
const provider = await registerSingleProviderPlugin(plugin);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"enabledByDefault": true,
|
||||
"providers": ["moonshot"],
|
||||
"providerAuthEnvVars": {
|
||||
"moonshot": ["MOONSHOT_API_KEY"]
|
||||
"moonshot": ["MOONSHOT_API_KEY", "KIMI_API_KEY"]
|
||||
},
|
||||
"providerAuthChoices": [
|
||||
{
|
||||
|
||||
41
extensions/nvidia/index.test.ts
Normal file
41
extensions/nvidia/index.test.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import fs from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveProviderPluginChoice } from "../../src/plugins/provider-auth-choice.runtime.js";
|
||||
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
|
||||
import plugin from "./index.js";
|
||||
|
||||
type NvidiaManifest = {
|
||||
providerAuthChoices?: Array<{ choiceId?: string; method?: string; provider?: string }>;
|
||||
};
|
||||
|
||||
function readManifest(): NvidiaManifest {
|
||||
return JSON.parse(
|
||||
fs.readFileSync(new URL("./openclaw.plugin.json", import.meta.url), "utf8"),
|
||||
) as NvidiaManifest;
|
||||
}
|
||||
|
||||
describe("nvidia provider plugin", () => {
|
||||
it("registers API-key auth metadata", async () => {
|
||||
const provider = await registerSingleProviderPlugin(plugin);
|
||||
|
||||
expect(provider.id).toBe("nvidia");
|
||||
expect(provider.envVars).toEqual(["NVIDIA_API_KEY"]);
|
||||
expect(provider.auth?.map((method) => method.id)).toEqual(["api-key"]);
|
||||
|
||||
const choice = resolveProviderPluginChoice({
|
||||
providers: [provider],
|
||||
choice: "nvidia-api-key",
|
||||
});
|
||||
expect(choice?.provider.id).toBe("nvidia");
|
||||
expect(choice?.method.id).toBe("api-key");
|
||||
expect(readManifest().providerAuthChoices).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
provider: "nvidia",
|
||||
method: "api-key",
|
||||
choiceId: "nvidia-api-key",
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -11,7 +11,24 @@ export default defineSingleProviderPluginEntry({
|
||||
label: "NVIDIA",
|
||||
docsPath: "/providers/nvidia",
|
||||
envVars: ["NVIDIA_API_KEY"],
|
||||
auth: [],
|
||||
auth: [
|
||||
{
|
||||
methodId: "api-key",
|
||||
label: "NVIDIA API key",
|
||||
hint: "API key",
|
||||
optionKey: "nvidiaApiKey",
|
||||
flagName: "--nvidia-api-key",
|
||||
envVar: "NVIDIA_API_KEY",
|
||||
promptMessage: "Enter NVIDIA API key",
|
||||
wizard: {
|
||||
choiceId: "nvidia-api-key",
|
||||
choiceLabel: "NVIDIA API key",
|
||||
groupId: "nvidia",
|
||||
groupLabel: "NVIDIA",
|
||||
groupHint: "API key",
|
||||
},
|
||||
},
|
||||
],
|
||||
catalog: {
|
||||
buildProvider: buildNvidiaProvider,
|
||||
},
|
||||
|
||||
@@ -5,6 +5,21 @@
|
||||
"providerAuthEnvVars": {
|
||||
"nvidia": ["NVIDIA_API_KEY"]
|
||||
},
|
||||
"providerAuthChoices": [
|
||||
{
|
||||
"provider": "nvidia",
|
||||
"method": "api-key",
|
||||
"choiceId": "nvidia-api-key",
|
||||
"choiceLabel": "NVIDIA API key",
|
||||
"groupId": "nvidia",
|
||||
"groupLabel": "NVIDIA",
|
||||
"groupHint": "API key",
|
||||
"optionKey": "nvidiaApiKey",
|
||||
"cliFlag": "--nvidia-api-key",
|
||||
"cliOption": "--nvidia-api-key <key>",
|
||||
"cliDescription": "NVIDIA API key"
|
||||
}
|
||||
],
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
Reference in New Issue
Block a user