Merge branch 'main' into val/plugin-runtime-dist-symlink-and-config-ui

This commit is contained in:
Val Alexander
2026-03-18 00:16:13 -05:00
committed by GitHub
6 changed files with 45 additions and 16 deletions

View File

@@ -141,6 +141,7 @@ Docs: https://docs.openclaw.ai
- Secrets/exec refs: require explicit `--allow-exec` for `secrets apply` write plans that contain exec SecretRefs/providers, and align audit/configure/apply dry-run behavior to skip exec checks unless opted in to prevent unexpected command side effects. (#49417) Thanks @restriction and @joshavant.
- Tools/image generation: add bundled fal image generation support so `image_generate` can target `fal/*` models with `FAL_KEY`, including single-image edit flows via FLUX image-to-image. Thanks @vincentkoc.
- xAI/web search: add missing Grok credential metadata so the bundled provider registration type-checks again. (#49472) thanks @scoootscooob.
- Signal/runtime API: re-export `SignalAccountConfig` so Signal account resolution type-checks again. (#49470) Thanks @scoootscooob.
### Breaking

View File

@@ -1 +1,2 @@
export * from "./src/index.js";
export type { SignalAccountConfig } from "../../src/config/types.signal.js";

View File

@@ -4,7 +4,7 @@ import {
resolveAccountEntry,
type OpenClawConfig,
} from "openclaw/plugin-sdk/account-resolution";
import type { SignalAccountConfig } from "../runtime-api.js";
import type { SignalAccountConfig } from "../../../src/config/types.signal.js";
export type ResolvedSignalAccount = {
accountId: string;

View File

@@ -14,6 +14,7 @@ import {
wrapWebContent,
writeCache,
} from "openclaw/plugin-sdk/provider-web-search";
import type { WebSearchProviderPlugin } from "../../src/plugins/types.js";
const XAI_WEB_SEARCH_ENDPOINT = "https://api.x.ai/v1/responses";
const XAI_DEFAULT_WEB_SEARCH_MODEL = "grok-4-1-fast";
@@ -200,7 +201,7 @@ async function runXaiWebSearch(params: {
return payload;
}
export function createXaiWebSearchProvider() {
export function createXaiWebSearchProvider(): WebSearchProviderPlugin {
return {
id: "grok",
label: "Grok (xAI)",
@@ -210,8 +211,8 @@ export function createXaiWebSearchProvider() {
signupUrl: "https://console.x.ai/",
docsUrl: "https://docs.openclaw.ai/tools/web",
autoDetectOrder: 30,
credentialPath: "tools.web.search.grok.apiKey",
inactiveSecretPaths: ["tools.web.search.grok.apiKey"],
credentialPath: "plugins.entries.xai.config.webSearch.apiKey",
inactiveSecretPaths: ["plugins.entries.xai.config.webSearch.apiKey"],
getCredentialValue: (searchConfig?: Record<string, unknown>) =>
getScopedCredentialValue(searchConfig, "grok"),
setCredentialValue: (searchConfigTarget: Record<string, unknown>, value: unknown) =>

View File

@@ -1,3 +1,4 @@
import type { OpenAICompletionsCompat } from "@mariozechner/pi-ai";
import type { SecretInput } from "./types.secrets.js";
export const MODEL_APIS = [
@@ -13,21 +14,25 @@ export const MODEL_APIS = [
export type ModelApi = (typeof MODEL_APIS)[number];
export type ModelCompatConfig = {
supportsStore?: boolean;
supportsDeveloperRole?: boolean;
supportsReasoningEffort?: boolean;
supportsUsageInStreaming?: boolean;
type SupportedOpenAICompatFields = Pick<
OpenAICompletionsCompat,
| "supportsStore"
| "supportsDeveloperRole"
| "supportsReasoningEffort"
| "supportsUsageInStreaming"
| "supportsStrictMode"
| "maxTokensField"
| "thinkingFormat"
| "requiresToolResultName"
| "requiresAssistantAfterToolResult"
| "requiresThinkingAsText"
>;
export type ModelCompatConfig = SupportedOpenAICompatFields & {
supportsTools?: boolean;
supportsStrictMode?: boolean;
toolSchemaProfile?: "xai";
nativeWebSearchTool?: boolean;
toolCallArgumentsEncoding?: "html-entities";
maxTokensField?: "max_completion_tokens" | "max_tokens";
thinkingFormat?: "openai" | "zai" | "qwen";
requiresToolResultName?: boolean;
requiresAssistantAfterToolResult?: boolean;
requiresThinkingAsText?: boolean;
requiresMistralToolIds?: boolean;
requiresOpenAiAnthropicToolPayload?: boolean;
};

View File

@@ -6,6 +6,7 @@ import {
isValidExecSecretRefId,
isValidFileSecretRefId,
} from "../secrets/ref-contract.js";
import type { ModelCompatConfig } from "./types.models.js";
import { MODEL_APIS } from "./types.models.js";
import { createAllowDenyChannelRulesSchema } from "./zod-schema.allowdeny.js";
import { sensitive } from "./zod-schema.sensitive.js";
@@ -191,16 +192,36 @@ export const ModelCompatSchema = z
maxTokensField: z
.union([z.literal("max_completion_tokens"), z.literal("max_tokens")])
.optional(),
thinkingFormat: z.union([z.literal("openai"), z.literal("zai"), z.literal("qwen")]).optional(),
thinkingFormat: z
.union([
z.literal("openai"),
z.literal("zai"),
z.literal("qwen"),
z.literal("qwen-chat-template"),
])
.optional(),
requiresToolResultName: z.boolean().optional(),
requiresAssistantAfterToolResult: z.boolean().optional(),
requiresThinkingAsText: z.boolean().optional(),
toolSchemaProfile: z.literal("xai").optional(),
nativeWebSearchTool: z.boolean().optional(),
toolCallArgumentsEncoding: z.literal("html-entities").optional(),
requiresMistralToolIds: z.boolean().optional(),
requiresOpenAiAnthropicToolPayload: z.boolean().optional(),
})
.strict()
.optional();
type AssertAssignable<_T extends U, U> = true;
type _ModelCompatSchemaAssignableToType = AssertAssignable<
z.infer<typeof ModelCompatSchema>,
ModelCompatConfig | undefined
>;
type _ModelCompatTypeAssignableToSchema = AssertAssignable<
ModelCompatConfig | undefined,
z.infer<typeof ModelCompatSchema>
>;
export const ModelDefinitionSchema = z
.object({
id: z.string().min(1),