openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
298 lines (297 loc) • 10.8 kB
JavaScript
import { a as normalizeLowercaseStringOrEmpty } from "../../string-coerce-mnp54Vah.js";
import { t as normalizeOptionalSecretInput } from "../../normalize-secret-input-OwRUfByL.js";
import { s as upsertAuthProfileWithLock } from "../../profiles-BMWtmBgj.js";
import { b as createToolStreamWrapper, l as defaultToolStreamExtraParams, o as createPayloadPatchStreamWrapper } from "../../provider-stream-shared-BIV_zuwB.js";
import { a as normalizeModelCompat } from "../../provider-model-compat-DhKi-Qv5.js";
import "../../string-coerce-runtime-CEGJWkQ_.js";
import { t as definePluginEntry } from "../../plugin-entry-C7DUzV0e.js";
import { a as buildProviderReplayFamilyHooks } from "../../provider-model-shared-D-lyTLvb.js";
import { i as normalizeApiKeyInput, n as ensureApiKeyFromOptionEnvOrPrompt, s as validateApiKeyInput } from "../../provider-auth-input-CjZ71i7e.js";
import { n as buildApiKeyCredential, t as applyAuthProfileConfig } from "../../provider-auth-helpers-BgLOn-Ws.js";
import "../../provider-auth-api-key-nSdfYNnB.js";
import { t as fetchZaiUsage } from "../../provider-usage-CoC__69_.js";
import { l as buildZaiModelDefinition } from "../../model-definitions-Ce_dJREx.js";
import { t as detectZaiEndpoint } from "../../detect-CIqxxfKB.js";
import { t as zaiMediaUnderstandingProvider } from "../../media-understanding-provider-ieH5zKf2.js";
import { n as applyZaiConfig, r as applyZaiProviderConfig, t as ZAI_DEFAULT_MODEL_REF } from "../../onboard-B6J0gBXD.js";
import fs from "node:fs";
import path from "node:path";
import os from "node:os";
//#region extensions/zai/index.ts
const PROVIDER_ID = "zai";
const GLM5_TEMPLATE_MODEL_ID = "glm-4.7";
const PROFILE_ID = "zai:default";
function resolveDeprecatedPiAgentAuthPath(env) {
const home = env.HOME?.trim() || env.USERPROFILE?.trim() || os.homedir();
return path.join(home, ".pi", "agent", "auth.json");
}
function resolveDeprecatedPiAgentAccessToken(env, providerIds) {
try {
const authPath = resolveDeprecatedPiAgentAuthPath(env);
if (!fs.existsSync(authPath)) return;
const parsed = JSON.parse(fs.readFileSync(authPath, "utf-8"));
for (const providerId of providerIds) {
const token = parsed[providerId]?.access;
if (typeof token === "string" && token.trim()) return token;
}
} catch {}
}
async function upsertAuthProfileWithLockOrThrow(params) {
if (!await upsertAuthProfileWithLock(params)) throw new Error("Failed to update auth profile store; the auth store lock may be busy. Wait a moment and retry.");
}
function resolveGlm5ForwardCompatModel(ctx) {
const trimmedModelId = ctx.modelId.trim();
if (!normalizeLowercaseStringOrEmpty(trimmedModelId).startsWith("glm-5")) return;
const existing = ctx.modelRegistry.find(PROVIDER_ID, trimmedModelId);
if (existing) return existing;
const def = buildZaiModelDefinition({ id: trimmedModelId });
return normalizeModelCompat({
...ctx.modelRegistry.find(PROVIDER_ID, GLM5_TEMPLATE_MODEL_ID),
id: def.id,
name: def.name,
api: "openai-completions",
provider: PROVIDER_ID,
reasoning: def.reasoning,
input: def.input,
cost: def.cost,
contextWindow: def.contextWindow,
maxTokens: def.maxTokens
});
}
function resolveZaiDefaultModel(modelIdOverride) {
return modelIdOverride ? `zai/${modelIdOverride}` : ZAI_DEFAULT_MODEL_REF;
}
function isTrueParam(value) {
return value === true;
}
function shouldPreserveZaiThinking(extraParams) {
return isTrueParam(extraParams?.preserveThinking) || isTrueParam(extraParams?.preserve_thinking);
}
function isDisabledThinkingLevel(thinkingLevel) {
return thinkingLevel === "off";
}
function wrapZaiStreamFn(ctx) {
let streamFn = createToolStreamWrapper(ctx.streamFn, ctx.extraParams?.tool_stream !== false);
const preserveThinking = shouldPreserveZaiThinking(ctx.extraParams);
if (!isDisabledThinkingLevel(ctx.thinkingLevel) && !preserveThinking) return streamFn;
streamFn = createPayloadPatchStreamWrapper(streamFn, ({ payload, model }) => {
if (model.api !== "openai-completions" || model.provider !== PROVIDER_ID) return;
if (isDisabledThinkingLevel(ctx.thinkingLevel)) {
payload.thinking = { type: "disabled" };
return;
}
if (preserveThinking) payload.thinking = {
type: "enabled",
clear_thinking: false
};
});
return streamFn;
}
async function promptForZaiEndpoint(ctx) {
return await ctx.prompter.select({
message: "Select Z.AI endpoint",
initialValue: "global",
options: [
{
value: "global",
label: "Global",
hint: "Z.AI Global (api.z.ai)"
},
{
value: "cn",
label: "CN",
hint: "Z.AI CN (open.bigmodel.cn)"
},
{
value: "coding-global",
label: "Coding-Plan-Global",
hint: "GLM Coding Plan Global (api.z.ai)"
},
{
value: "coding-cn",
label: "Coding-Plan-CN",
hint: "GLM Coding Plan CN (open.bigmodel.cn)"
}
]
});
}
async function runZaiApiKeyAuth(ctx, endpoint) {
let capturedSecretInput;
let capturedCredential = false;
let capturedMode;
const apiKey = await ensureApiKeyFromOptionEnvOrPrompt({
token: normalizeOptionalSecretInput(ctx.opts?.zaiApiKey) ?? normalizeOptionalSecretInput(ctx.opts?.token),
tokenProvider: normalizeOptionalSecretInput(ctx.opts?.zaiApiKey) ? PROVIDER_ID : normalizeOptionalSecretInput(ctx.opts?.tokenProvider),
secretInputMode: ctx.allowSecretRefPrompt === false ? ctx.secretInputMode ?? "plaintext" : ctx.secretInputMode,
config: ctx.config,
expectedProviders: [PROVIDER_ID, "z-ai"],
provider: PROVIDER_ID,
envLabel: "ZAI_API_KEY",
promptMessage: "Enter Z.AI API key",
normalize: normalizeApiKeyInput,
validate: validateApiKeyInput,
prompter: ctx.prompter,
setCredential: async (key, mode) => {
capturedSecretInput = key;
capturedCredential = true;
capturedMode = mode;
}
});
if (!capturedCredential) throw new Error("Missing Z.AI API key.");
const credentialInput = capturedSecretInput ?? "";
const detected = await detectZaiEndpoint({
apiKey,
...endpoint ? { endpoint } : {}
});
const modelIdOverride = detected?.modelId;
const nextEndpoint = detected?.endpoint ?? endpoint ?? await promptForZaiEndpoint(ctx);
return {
profiles: [{
profileId: PROFILE_ID,
credential: buildApiKeyCredential(PROVIDER_ID, credentialInput, void 0, capturedMode ? { secretInputMode: capturedMode } : void 0)
}],
configPatch: applyZaiProviderConfig(ctx.config, {
...nextEndpoint ? { endpoint: nextEndpoint } : {},
...modelIdOverride ? { modelId: modelIdOverride } : {}
}),
defaultModel: resolveZaiDefaultModel(modelIdOverride),
...detected?.note ? { notes: [detected.note] } : {}
};
}
async function runZaiApiKeyAuthNonInteractive(ctx, endpoint) {
const resolved = await ctx.resolveApiKey({
provider: PROVIDER_ID,
flagValue: normalizeOptionalSecretInput(ctx.opts.zaiApiKey),
flagName: "--zai-api-key",
envVar: "ZAI_API_KEY"
});
if (!resolved) return null;
const detected = await detectZaiEndpoint({
apiKey: resolved.key,
...endpoint ? { endpoint } : {}
});
const modelIdOverride = detected?.modelId;
const nextEndpoint = detected?.endpoint ?? endpoint;
if (resolved.source !== "profile") {
const credential = ctx.toApiKeyCredential({
provider: PROVIDER_ID,
resolved
});
if (!credential) return null;
await upsertAuthProfileWithLockOrThrow({
profileId: PROFILE_ID,
credential,
agentDir: ctx.agentDir
});
}
return applyZaiConfig(applyAuthProfileConfig(ctx.config, {
profileId: PROFILE_ID,
provider: PROVIDER_ID,
mode: "api_key"
}), {
...nextEndpoint ? { endpoint: nextEndpoint } : {},
...modelIdOverride ? { modelId: modelIdOverride } : {}
});
}
function buildZaiApiKeyMethod(params) {
return {
id: params.id,
label: params.choiceLabel,
hint: params.choiceHint,
kind: "api_key",
wizard: {
choiceId: params.choiceId,
choiceLabel: params.choiceLabel,
...params.choiceHint ? { choiceHint: params.choiceHint } : {},
groupId: "zai",
groupLabel: "Z.AI",
groupHint: "GLM Coding Plan / Global / CN"
},
run: async (ctx) => await runZaiApiKeyAuth(ctx, params.endpoint),
runNonInteractive: async (ctx) => await runZaiApiKeyAuthNonInteractive(ctx, params.endpoint)
};
}
var zai_default = definePluginEntry({
id: PROVIDER_ID,
name: "Z.AI Provider",
description: "Bundled Z.AI provider plugin",
register(api) {
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: [
buildZaiApiKeyMethod({
id: "api-key",
choiceId: "zai-api-key",
choiceLabel: "Z.AI API key"
}),
buildZaiApiKeyMethod({
id: "coding-global",
choiceId: "zai-coding-global",
choiceLabel: "Coding-Plan-Global",
choiceHint: "GLM Coding Plan Global (api.z.ai)",
endpoint: "coding-global"
}),
buildZaiApiKeyMethod({
id: "coding-cn",
choiceId: "zai-coding-cn",
choiceLabel: "Coding-Plan-CN",
choiceHint: "GLM Coding Plan CN (open.bigmodel.cn)",
endpoint: "coding-cn"
}),
buildZaiApiKeyMethod({
id: "global",
choiceId: "zai-global",
choiceLabel: "Global",
choiceHint: "Z.AI Global (api.z.ai)",
endpoint: "global"
}),
buildZaiApiKeyMethod({
id: "cn",
choiceId: "zai-cn",
choiceLabel: "CN",
choiceHint: "Z.AI CN (open.bigmodel.cn)",
endpoint: "cn"
})
],
resolveDynamicModel: (ctx) => resolveGlm5ForwardCompatModel(ctx),
...buildProviderReplayFamilyHooks({
family: "openai-compatible",
dropReasoningFromHistory: false
}),
prepareExtraParams: (ctx) => defaultToolStreamExtraParams(ctx.extraParams),
wrapStreamFn: (ctx) => wrapZaiStreamFn(ctx),
resolveThinkingProfile: () => ({
levels: [{
id: "off",
label: "off"
}, {
id: "low",
label: "on"
}],
defaultLevel: "off"
}),
isModernModelRef: ({ modelId }) => {
const lower = normalizeLowercaseStringOrEmpty(modelId);
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 = resolveDeprecatedPiAgentAccessToken(ctx.env, ["z-ai", PROVIDER_ID]);
return legacyToken ? { token: legacyToken } : null;
},
fetchUsageSnapshot: async (ctx) => await fetchZaiUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn),
isCacheTtlEligible: () => true
});
api.registerMediaUnderstandingProvider(zaiMediaUnderstandingProvider);
}
});
//#endregion
export { zai_default as default };