mirror of https://github.com/openclaw/openclaw.git
129 lines
3.9 KiB
TypeScript
129 lines
3.9 KiB
TypeScript
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import {
|
|
emptyPluginConfigSchema,
|
|
type OpenClawPluginApi,
|
|
type ProviderResolveDynamicModelContext,
|
|
type ProviderRuntimeModel,
|
|
} from "openclaw/plugin-sdk/core";
|
|
import { DEFAULT_CONTEXT_TOKENS } from "../../src/agents/defaults.js";
|
|
import { normalizeModelCompat } from "../../src/agents/model-compat.js";
|
|
import { createZaiToolStreamWrapper } from "../../src/agents/pi-embedded-runner/zai-stream-wrappers.js";
|
|
import { resolveRequiredHomeDir } from "../../src/infra/home-dir.js";
|
|
import { fetchZaiUsage } from "../../src/infra/provider-usage.fetch.js";
|
|
|
|
const PROVIDER_ID = "zai";
|
|
const GLM5_MODEL_ID = "glm-5";
|
|
const GLM5_TEMPLATE_MODEL_ID = "glm-4.7";
|
|
|
|
function resolveGlm5ForwardCompatModel(
|
|
ctx: ProviderResolveDynamicModelContext,
|
|
): ProviderRuntimeModel | undefined {
|
|
const trimmedModelId = ctx.modelId.trim();
|
|
const lower = trimmedModelId.toLowerCase();
|
|
if (lower !== GLM5_MODEL_ID && !lower.startsWith(`${GLM5_MODEL_ID}-`)) {
|
|
return undefined;
|
|
}
|
|
|
|
const template = ctx.modelRegistry.find(
|
|
PROVIDER_ID,
|
|
GLM5_TEMPLATE_MODEL_ID,
|
|
) as ProviderRuntimeModel | null;
|
|
if (template) {
|
|
return normalizeModelCompat({
|
|
...template,
|
|
id: trimmedModelId,
|
|
name: trimmedModelId,
|
|
reasoning: true,
|
|
} as ProviderRuntimeModel);
|
|
}
|
|
|
|
return normalizeModelCompat({
|
|
id: trimmedModelId,
|
|
name: trimmedModelId,
|
|
api: "openai-completions",
|
|
provider: PROVIDER_ID,
|
|
reasoning: true,
|
|
input: ["text"],
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
contextWindow: DEFAULT_CONTEXT_TOKENS,
|
|
maxTokens: DEFAULT_CONTEXT_TOKENS,
|
|
} as ProviderRuntimeModel);
|
|
}
|
|
|
|
function resolveLegacyZaiUsageToken(env: NodeJS.ProcessEnv): string | undefined {
|
|
try {
|
|
const authPath = path.join(
|
|
resolveRequiredHomeDir(env, os.homedir),
|
|
".pi",
|
|
"agent",
|
|
"auth.json",
|
|
);
|
|
if (!fs.existsSync(authPath)) {
|
|
return undefined;
|
|
}
|
|
const parsed = JSON.parse(fs.readFileSync(authPath, "utf8")) as Record<
|
|
string,
|
|
{ access?: string }
|
|
>;
|
|
return parsed["z-ai"]?.access || parsed.zai?.access;
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
const zaiPlugin = {
|
|
id: PROVIDER_ID,
|
|
name: "Z.AI Provider",
|
|
description: "Bundled Z.AI provider plugin",
|
|
configSchema: emptyPluginConfigSchema(),
|
|
register(api: OpenClawPluginApi) {
|
|
api.registerProvider({
|
|
id: PROVIDER_ID,
|
|
label: "Z.AI",
|
|
aliases: ["z-ai", "z.ai"],
|
|
docsPath: "/providers/models",
|
|
envVars: ["ZAI_API_KEY", "Z_AI_API_KEY"],
|
|
auth: [],
|
|
resolveDynamicModel: (ctx) => resolveGlm5ForwardCompatModel(ctx),
|
|
prepareExtraParams: (ctx) => {
|
|
if (ctx.extraParams?.tool_stream !== undefined) {
|
|
return ctx.extraParams;
|
|
}
|
|
return {
|
|
...ctx.extraParams,
|
|
tool_stream: true,
|
|
};
|
|
},
|
|
wrapStreamFn: (ctx) =>
|
|
createZaiToolStreamWrapper(ctx.streamFn, ctx.extraParams?.tool_stream !== false),
|
|
isBinaryThinking: () => true,
|
|
isModernModelRef: ({ modelId }) => {
|
|
const lower = modelId.trim().toLowerCase();
|
|
return (
|
|
lower.startsWith("glm-5") ||
|
|
lower.startsWith("glm-4.7") ||
|
|
lower.startsWith("glm-4.7-flash") ||
|
|
lower.startsWith("glm-4.7-flashx")
|
|
);
|
|
},
|
|
resolveUsageAuth: async (ctx) => {
|
|
const apiKey = ctx.resolveApiKeyFromConfigAndStore({
|
|
providerIds: [PROVIDER_ID, "z-ai"],
|
|
envDirect: [ctx.env.ZAI_API_KEY, ctx.env.Z_AI_API_KEY],
|
|
});
|
|
if (apiKey) {
|
|
return { token: apiKey };
|
|
}
|
|
const legacyToken = resolveLegacyZaiUsageToken(ctx.env);
|
|
return legacyToken ? { token: legacyToken } : null;
|
|
},
|
|
fetchUsageSnapshot: async (ctx) => await fetchZaiUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn),
|
|
isCacheTtlEligible: () => true,
|
|
});
|
|
},
|
|
};
|
|
|
|
export default zaiPlugin;
|