fix: add robust Z.AI config persistence with error handling and logging
Some checks failed
Release Binaries / release (push) Has been cancelled
Some checks failed
Release Binaries / release (push) Has been cancelled
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
import { z } from "zod"
|
||||
import { createHmac } from "crypto"
|
||||
|
||||
export const ZAIConfigSchema = z.object({
|
||||
apiKey: z.string().optional(),
|
||||
endpoint: z.string().default("https://api.z.ai/api/coding/paas/v4"),
|
||||
endpoint: z.string().default("https://api.z.ai/api"),
|
||||
enabled: z.boolean().default(false),
|
||||
timeout: z.number().default(300000)
|
||||
})
|
||||
@@ -142,7 +140,8 @@ export class ZAIClient {
|
||||
|
||||
constructor(config: ZAIConfig) {
|
||||
this.config = config
|
||||
this.baseUrl = config.endpoint.replace(/\/$/, "")
|
||||
const trimmed = config.endpoint.replace(/\/$/, "")
|
||||
this.baseUrl = trimmed.replace(/\/(?:api\/coding\/)?paas\/v4$/, "")
|
||||
}
|
||||
|
||||
async testConnection(): Promise<boolean> {
|
||||
@@ -151,7 +150,7 @@ export class ZAIClient {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
||||
const response = await fetch(`${this.baseUrl}/paas/v4/chat/completions`, {
|
||||
method: "POST",
|
||||
headers: this.getHeaders(),
|
||||
body: JSON.stringify({
|
||||
@@ -182,7 +181,7 @@ export class ZAIClient {
|
||||
throw new Error("Z.AI API key is required")
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
||||
const response = await fetch(`${this.baseUrl}/paas/v4/chat/completions`, {
|
||||
method: "POST",
|
||||
headers: this.getHeaders(),
|
||||
body: JSON.stringify({
|
||||
@@ -236,7 +235,7 @@ export class ZAIClient {
|
||||
throw new Error("Z.AI API key is required")
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
||||
const response = await fetch(`${this.baseUrl}/paas/v4/chat/completions`, {
|
||||
method: "POST",
|
||||
headers: this.getHeaders(),
|
||||
body: JSON.stringify({
|
||||
@@ -254,56 +253,13 @@ export class ZAIClient {
|
||||
}
|
||||
|
||||
private getHeaders(): Record<string, string> {
|
||||
const token = this.generateToken(this.config.apiKey!)
|
||||
return {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Bearer ${token}`
|
||||
}
|
||||
}
|
||||
|
||||
private generateToken(apiKey: string, expiresIn: number = 3600): string {
|
||||
try {
|
||||
const [id, secret] = apiKey.split(".")
|
||||
if (!id || !secret) return apiKey // Fallback or handle error
|
||||
|
||||
const now = Date.now()
|
||||
const payload = {
|
||||
api_key: id,
|
||||
exp: now + expiresIn * 1000,
|
||||
timestamp: now
|
||||
}
|
||||
|
||||
const header = {
|
||||
alg: "HS256",
|
||||
sign_type: "SIGN"
|
||||
}
|
||||
|
||||
const base64UrlEncode = (obj: any) => {
|
||||
return Buffer.from(JSON.stringify(obj))
|
||||
.toString('base64')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=+$/, '')
|
||||
}
|
||||
|
||||
const encodedHeader = base64UrlEncode(header)
|
||||
const encodedPayload = base64UrlEncode(payload)
|
||||
|
||||
const signature = createHmac("sha256", secret)
|
||||
.update(`${encodedHeader}.${encodedPayload}`)
|
||||
.digest("base64")
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=+$/, '')
|
||||
|
||||
return `${encodedHeader}.${encodedPayload}.${signature}`
|
||||
} catch (e) {
|
||||
console.warn("Failed to generate JWT, using raw key", e)
|
||||
return apiKey
|
||||
"Authorization": `Bearer ${this.config.apiKey!}`
|
||||
}
|
||||
}
|
||||
|
||||
static validateApiKey(apiKey: string): boolean {
|
||||
return typeof apiKey === "string" && apiKey.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user