Add custom agent creator, Zread MCP, fix model change context continuity
Features added: - Custom Agent Creator dialog with AI generation support (up to 30k chars) - Plus button next to agent selector to create new agents - Zread MCP Server from Z.AI in marketplace (remote HTTP config) - Extended MCP config types to support remote/http/sse servers Bug fixes: - Filter SDK Z.AI/GLM providers to ensure our custom routing with full message history - This fixes the issue where changing models mid-chat lost conversationcontext
This commit is contained in:
327
packages/ui/src/components/agent-creator-dialog.tsx
Normal file
327
packages/ui/src/components/agent-creator-dialog.tsx
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
import { Dialog } from "@kobalte/core/dialog"
|
||||||
|
import { Bot, Loader2, Sparkles, X } from "lucide-solid"
|
||||||
|
import { Component, Show, createSignal } from "solid-js"
|
||||||
|
import { Portal } from "solid-js/web"
|
||||||
|
import { updateInstanceConfig } from "../stores/instance-config"
|
||||||
|
import { fetchAgents } from "../stores/sessions"
|
||||||
|
import { showToastNotification } from "../lib/notifications"
|
||||||
|
import { getLogger } from "../lib/logger"
|
||||||
|
|
||||||
|
const log = getLogger("agent-creator")
|
||||||
|
|
||||||
|
const MAX_PROMPT_LENGTH = 30000
|
||||||
|
|
||||||
|
interface AgentCreatorDialogProps {
|
||||||
|
instanceId: string
|
||||||
|
open: boolean
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const AgentCreatorDialog: Component<AgentCreatorDialogProps> = (props) => {
|
||||||
|
const [name, setName] = createSignal("")
|
||||||
|
const [description, setDescription] = createSignal("")
|
||||||
|
const [prompt, setPrompt] = createSignal("")
|
||||||
|
const [isGenerating, setIsGenerating] = createSignal(false)
|
||||||
|
const [isSaving, setIsSaving] = createSignal(false)
|
||||||
|
const [useAiGeneration, setUseAiGeneration] = createSignal(true)
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
setName("")
|
||||||
|
setDescription("")
|
||||||
|
setPrompt("")
|
||||||
|
setIsGenerating(false)
|
||||||
|
setUseAiGeneration(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
resetForm()
|
||||||
|
props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
const generatePromptWithAI = async () => {
|
||||||
|
if (!name().trim() || !description().trim()) {
|
||||||
|
showToastNotification({
|
||||||
|
title: "Missing Information",
|
||||||
|
message: "Please provide both name and description to generate an agent prompt.",
|
||||||
|
variant: "warning",
|
||||||
|
duration: 5000,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsGenerating(true)
|
||||||
|
try {
|
||||||
|
// Use Z.AI or another endpoint to generate the prompt
|
||||||
|
const response = await fetch("/api/zai/chat", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: "glm-4.5-flash",
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content: `You are an expert AI agent prompt designer. Generate a comprehensive, detailed system prompt for an AI coding assistant agent based on the user's requirements. The prompt should:
|
||||||
|
1. Define the agent's role and expertise
|
||||||
|
2. Specify its capabilities and limitations
|
||||||
|
3. Include guidelines for code style and best practices
|
||||||
|
4. Define how it should interact with users
|
||||||
|
5. Include any domain-specific knowledge relevant to the description
|
||||||
|
|
||||||
|
Output ONLY the agent system prompt, no explanations or markdown formatting.`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: `Create a system prompt for an AI coding agent with the following details:
|
||||||
|
|
||||||
|
Name: ${name()}
|
||||||
|
Purpose: ${description()}
|
||||||
|
|
||||||
|
Generate a comprehensive system prompt that will make this agent effective at its purpose.`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stream: false,
|
||||||
|
max_tokens: 4096,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Generation failed: ${response.status}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
const generatedPrompt = data?.choices?.[0]?.message?.content || data?.message?.content || ""
|
||||||
|
|
||||||
|
if (generatedPrompt) {
|
||||||
|
setPrompt(generatedPrompt)
|
||||||
|
showToastNotification({
|
||||||
|
title: "Prompt Generated",
|
||||||
|
message: "AI has generated a system prompt for your agent. Review and edit as needed.",
|
||||||
|
variant: "success",
|
||||||
|
duration: 5000,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw new Error("No prompt content in response")
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error("Failed to generate agent prompt", error)
|
||||||
|
showToastNotification({
|
||||||
|
title: "Generation Failed",
|
||||||
|
message: "Could not generate prompt. Please write one manually or check your Z.AI configuration.",
|
||||||
|
variant: "error",
|
||||||
|
duration: 8000,
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
setIsGenerating(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (!name().trim()) {
|
||||||
|
showToastNotification({
|
||||||
|
title: "Name Required",
|
||||||
|
message: "Please provide a name for the agent.",
|
||||||
|
variant: "warning",
|
||||||
|
duration: 5000,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prompt().trim()) {
|
||||||
|
showToastNotification({
|
||||||
|
title: "Prompt Required",
|
||||||
|
message: "Please provide a system prompt for the agent.",
|
||||||
|
variant: "warning",
|
||||||
|
duration: 5000,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsSaving(true)
|
||||||
|
try {
|
||||||
|
await updateInstanceConfig(props.instanceId, (draft) => {
|
||||||
|
if (!draft.customAgents) {
|
||||||
|
draft.customAgents = []
|
||||||
|
}
|
||||||
|
// Check for duplicate names
|
||||||
|
const existing = draft.customAgents.findIndex((a) => a.name.toLowerCase() === name().toLowerCase())
|
||||||
|
if (existing >= 0) {
|
||||||
|
// Update existing
|
||||||
|
draft.customAgents[existing] = {
|
||||||
|
name: name().trim(),
|
||||||
|
description: description().trim() || undefined,
|
||||||
|
prompt: prompt().trim(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Add new
|
||||||
|
draft.customAgents.push({
|
||||||
|
name: name().trim(),
|
||||||
|
description: description().trim() || undefined,
|
||||||
|
prompt: prompt().trim(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Refresh agents list
|
||||||
|
await fetchAgents(props.instanceId)
|
||||||
|
|
||||||
|
showToastNotification({
|
||||||
|
title: "Agent Created",
|
||||||
|
message: `Custom agent "${name()}" has been saved and is ready to use.`,
|
||||||
|
variant: "success",
|
||||||
|
duration: 5000,
|
||||||
|
})
|
||||||
|
|
||||||
|
handleClose()
|
||||||
|
} catch (error) {
|
||||||
|
log.error("Failed to save custom agent", error)
|
||||||
|
showToastNotification({
|
||||||
|
title: "Save Failed",
|
||||||
|
message: "Could not save the agent. Please try again.",
|
||||||
|
variant: "error",
|
||||||
|
duration: 8000,
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={props.open} onOpenChange={(open) => !open && handleClose()}>
|
||||||
|
<Portal>
|
||||||
|
<Dialog.Overlay class="fixed inset-0 bg-black/60 backdrop-blur-sm z-[9998]" />
|
||||||
|
<div class="fixed inset-0 flex items-center justify-center z-[9999] p-4">
|
||||||
|
<Dialog.Content class="bg-zinc-900 border border-zinc-700 rounded-2xl shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-hidden flex flex-col">
|
||||||
|
{/* Header */}
|
||||||
|
<div class="flex items-center justify-between p-4 border-b border-zinc-700/50">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="p-2 bg-indigo-500/20 rounded-lg">
|
||||||
|
<Bot size={20} class="text-indigo-400" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Dialog.Title class="text-lg font-semibold text-white">Create Custom Agent</Dialog.Title>
|
||||||
|
<Dialog.Description class="text-xs text-zinc-400">
|
||||||
|
Define a new AI agent with custom behavior and expertise
|
||||||
|
</Dialog.Description>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={handleClose}
|
||||||
|
class="p-1.5 text-zinc-400 hover:text-white hover:bg-zinc-700/50 rounded-lg transition-colors"
|
||||||
|
>
|
||||||
|
<X size={18} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div class="flex-1 overflow-y-auto p-4 space-y-4">
|
||||||
|
{/* Name Input */}
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<label class="text-xs font-medium text-zinc-300">Agent Name *</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={name()}
|
||||||
|
onInput={(e) => setName(e.currentTarget.value)}
|
||||||
|
placeholder="e.g., React Specialist, Python Expert, Code Reviewer..."
|
||||||
|
class="w-full px-3 py-2 bg-zinc-800 border border-zinc-600 rounded-lg text-white placeholder:text-zinc-500 focus:outline-none focus:border-indigo-500 transition-colors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Description Input */}
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<label class="text-xs font-medium text-zinc-300">Brief Description</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={description()}
|
||||||
|
onInput={(e) => setDescription(e.currentTarget.value)}
|
||||||
|
placeholder="A few words about what this agent specializes in..."
|
||||||
|
class="w-full px-3 py-2 bg-zinc-800 border border-zinc-600 rounded-lg text-white placeholder:text-zinc-500 focus:outline-none focus:border-indigo-500 transition-colors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Generation Mode Toggle */}
|
||||||
|
<div class="flex items-center gap-4 p-3 bg-zinc-800/50 rounded-lg border border-zinc-700/50">
|
||||||
|
<button
|
||||||
|
onClick={() => setUseAiGeneration(true)}
|
||||||
|
class={`flex-1 py-2 px-3 rounded-lg text-sm font-medium transition-all ${useAiGeneration()
|
||||||
|
? "bg-indigo-500 text-white"
|
||||||
|
: "text-zinc-400 hover:text-white hover:bg-zinc-700/50"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Sparkles size={14} class="inline-block mr-1.5" />
|
||||||
|
AI Generate
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setUseAiGeneration(false)}
|
||||||
|
class={`flex-1 py-2 px-3 rounded-lg text-sm font-medium transition-all ${!useAiGeneration()
|
||||||
|
? "bg-indigo-500 text-white"
|
||||||
|
: "text-zinc-400 hover:text-white hover:bg-zinc-700/50"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Write Manually
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* AI Generation Button */}
|
||||||
|
<Show when={useAiGeneration()}>
|
||||||
|
<button
|
||||||
|
onClick={generatePromptWithAI}
|
||||||
|
disabled={isGenerating() || !name().trim() || !description().trim()}
|
||||||
|
class="w-full py-2.5 px-4 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 text-white rounded-lg font-medium text-sm transition-all disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
|
||||||
|
>
|
||||||
|
<Show when={isGenerating()} fallback={<><Sparkles size={16} /> Generate Agent Prompt with AI</>}>
|
||||||
|
<Loader2 size={16} class="animate-spin" />
|
||||||
|
Generating...
|
||||||
|
</Show>
|
||||||
|
</button>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
{/* Prompt Textarea */}
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<label class="text-xs font-medium text-zinc-300">System Prompt *</label>
|
||||||
|
<span class="text-xs text-zinc-500">
|
||||||
|
{prompt().length.toLocaleString()} / {MAX_PROMPT_LENGTH.toLocaleString()}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<textarea
|
||||||
|
value={prompt()}
|
||||||
|
onInput={(e) => {
|
||||||
|
const value = e.currentTarget.value
|
||||||
|
if (value.length <= MAX_PROMPT_LENGTH) {
|
||||||
|
setPrompt(value)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
placeholder="Enter the system prompt that defines this agent's behavior, expertise, and guidelines..."
|
||||||
|
rows={12}
|
||||||
|
class="w-full px-3 py-2 bg-zinc-800 border border-zinc-600 rounded-lg text-white placeholder:text-zinc-500 focus:outline-none focus:border-indigo-500 transition-colors resize-none font-mono text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<div class="flex items-center justify-end gap-3 p-4 border-t border-zinc-700/50 bg-zinc-800/30">
|
||||||
|
<button
|
||||||
|
onClick={handleClose}
|
||||||
|
class="px-4 py-2 text-zinc-400 hover:text-white hover:bg-zinc-700/50 rounded-lg text-sm font-medium transition-colors"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={isSaving() || !name().trim() || !prompt().trim()}
|
||||||
|
class="px-4 py-2 bg-indigo-500 hover:bg-indigo-400 text-white rounded-lg text-sm font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<Show when={isSaving()} fallback={<>Save Agent</>}>
|
||||||
|
<Loader2 size={14} class="animate-spin" />
|
||||||
|
Saving...
|
||||||
|
</Show>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Dialog.Content>
|
||||||
|
</div>
|
||||||
|
</Portal>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AgentCreatorDialog
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Select } from "@kobalte/core/select"
|
import { Select } from "@kobalte/core/select"
|
||||||
import { For, Show, createEffect, createMemo } from "solid-js"
|
import { For, Show, createEffect, createMemo, createSignal } from "solid-js"
|
||||||
import { agents, fetchAgents, sessions } from "../stores/sessions"
|
import { agents, fetchAgents, sessions } from "../stores/sessions"
|
||||||
import { ChevronDown } from "lucide-solid"
|
import { ChevronDown, Plus } from "lucide-solid"
|
||||||
import type { Agent } from "../types/session"
|
import type { Agent } from "../types/session"
|
||||||
import { getLogger } from "../lib/logger"
|
import { getLogger } from "../lib/logger"
|
||||||
|
import AgentCreatorDialog from "./agent-creator-dialog"
|
||||||
|
|
||||||
const log = getLogger("session")
|
const log = getLogger("session")
|
||||||
|
|
||||||
|
|
||||||
@@ -16,6 +18,7 @@ interface AgentSelectorProps {
|
|||||||
|
|
||||||
export default function AgentSelector(props: AgentSelectorProps) {
|
export default function AgentSelector(props: AgentSelectorProps) {
|
||||||
const instanceAgents = () => agents().get(props.instanceId) || []
|
const instanceAgents = () => agents().get(props.instanceId) || []
|
||||||
|
const [showCreator, setShowCreator] = createSignal(false)
|
||||||
|
|
||||||
const session = createMemo(() => {
|
const session = createMemo(() => {
|
||||||
const instanceSessions = sessions().get(props.instanceId)
|
const instanceSessions = sessions().get(props.instanceId)
|
||||||
@@ -64,7 +67,8 @@ export default function AgentSelector(props: AgentSelectorProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="sidebar-selector">
|
<>
|
||||||
|
<div class="sidebar-selector flex items-center gap-1">
|
||||||
<Select
|
<Select
|
||||||
value={availableAgents().find((a) => a.name === props.currentAgent)}
|
value={availableAgents().find((a) => a.name === props.currentAgent)}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
@@ -83,6 +87,9 @@ export default function AgentSelector(props: AgentSelectorProps) {
|
|||||||
<Show when={itemProps.item.rawValue.mode === "subagent"}>
|
<Show when={itemProps.item.rawValue.mode === "subagent"}>
|
||||||
<span class="neutral-badge">subagent</span>
|
<span class="neutral-badge">subagent</span>
|
||||||
</Show>
|
</Show>
|
||||||
|
<Show when={itemProps.item.rawValue.mode === "custom"}>
|
||||||
|
<span class="text-[9px] px-1.5 py-0.5 bg-indigo-500/20 text-indigo-400 rounded-full font-medium">custom</span>
|
||||||
|
</Show>
|
||||||
</Select.ItemLabel>
|
</Select.ItemLabel>
|
||||||
<Show when={itemProps.item.rawValue.description}>
|
<Show when={itemProps.item.rawValue.description}>
|
||||||
<Select.ItemDescription class="selector-option-description">
|
<Select.ItemDescription class="selector-option-description">
|
||||||
@@ -119,6 +126,23 @@ export default function AgentSelector(props: AgentSelectorProps) {
|
|||||||
</Select.Content>
|
</Select.Content>
|
||||||
</Select.Portal>
|
</Select.Portal>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
|
{/* Add Agent Button */}
|
||||||
|
<button
|
||||||
|
onClick={() => setShowCreator(true)}
|
||||||
|
class="p-1.5 text-zinc-500 hover:text-indigo-400 hover:bg-indigo-500/10 rounded-lg transition-all shrink-0"
|
||||||
|
title="Create custom agent"
|
||||||
|
>
|
||||||
|
<Plus size={14} />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Agent Creator Dialog */}
|
||||||
|
<AgentCreatorDialog
|
||||||
|
instanceId={props.instanceId}
|
||||||
|
open={showCreator()}
|
||||||
|
onClose={() => setShowCreator(false)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ type McpServerConfig = {
|
|||||||
command?: string
|
command?: string
|
||||||
args?: string[]
|
args?: string[]
|
||||||
env?: Record<string, string>
|
env?: Record<string, string>
|
||||||
|
// Remote MCP server support
|
||||||
|
type?: "remote" | "http" | "sse" | "streamable-http"
|
||||||
|
url?: string
|
||||||
|
headers?: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
type McpConfig = {
|
type McpConfig = {
|
||||||
@@ -23,8 +27,10 @@ type McpMarketplaceEntry = {
|
|||||||
config: McpServerConfig
|
config: McpServerConfig
|
||||||
tags?: string[]
|
tags?: string[]
|
||||||
source?: string
|
source?: string
|
||||||
|
requiresApiKey?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface McpManagerProps {
|
interface McpManagerProps {
|
||||||
instanceId: string
|
instanceId: string
|
||||||
}
|
}
|
||||||
@@ -34,6 +40,19 @@ const log = getLogger("mcp-manager")
|
|||||||
const MCP_LINKER_RELEASES = "https://github.com/milisp/mcp-linker/releases"
|
const MCP_LINKER_RELEASES = "https://github.com/milisp/mcp-linker/releases"
|
||||||
const MCP_LINKER_MARKET = "https://github.com/milisp/mcp-linker"
|
const MCP_LINKER_MARKET = "https://github.com/milisp/mcp-linker"
|
||||||
const MARKETPLACE_ENTRIES: McpMarketplaceEntry[] = [
|
const MARKETPLACE_ENTRIES: McpMarketplaceEntry[] = [
|
||||||
|
{
|
||||||
|
id: "zread",
|
||||||
|
name: "Zread (Z.AI)",
|
||||||
|
description: "Search GitHub repos, read code, analyze structure. Powered by Z.AI - requires API key from z.ai/manage-apikey.",
|
||||||
|
config: {
|
||||||
|
type: "remote",
|
||||||
|
url: "https://api.z.ai/api/mcp/zread/mcp",
|
||||||
|
headers: { "Authorization": "Bearer YOUR_ZAI_API_KEY" }
|
||||||
|
},
|
||||||
|
tags: ["github", "code", "search", "z.ai"],
|
||||||
|
source: "z.ai",
|
||||||
|
requiresApiKey: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "sequential-thinking",
|
id: "sequential-thinking",
|
||||||
name: "Sequential Thinking",
|
name: "Sequential Thinking",
|
||||||
@@ -76,6 +95,7 @@ const MARKETPLACE_ENTRIES: McpMarketplaceEntry[] = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
const McpManager: Component<McpManagerProps> = (props) => {
|
const McpManager: Component<McpManagerProps> = (props) => {
|
||||||
const [config, setConfig] = createSignal<McpConfig>({ mcpServers: {} })
|
const [config, setConfig] = createSignal<McpConfig>({ mcpServers: {} })
|
||||||
const [isLoading, setIsLoading] = createSignal(false)
|
const [isLoading, setIsLoading] = createSignal(false)
|
||||||
|
|||||||
@@ -746,7 +746,12 @@ async function fetchProviders(instanceId: string): Promise<void> {
|
|||||||
})),
|
})),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const filteredBaseProviders = providerList.filter((provider) => provider.id !== "zai")
|
// Filter out Z.AI providers from SDK to use our custom routing with full message history
|
||||||
|
const filteredBaseProviders = providerList.filter((provider) =>
|
||||||
|
!provider.id.toLowerCase().includes("zai") &&
|
||||||
|
!provider.id.toLowerCase().includes("z.ai") &&
|
||||||
|
!provider.id.toLowerCase().includes("glm")
|
||||||
|
)
|
||||||
|
|
||||||
const extraProviders = await fetchExtraProviders()
|
const extraProviders = await fetchExtraProviders()
|
||||||
const baseProviders = removeDuplicateProviders(filteredBaseProviders, extraProviders)
|
const baseProviders = removeDuplicateProviders(filteredBaseProviders, extraProviders)
|
||||||
|
|||||||
Reference in New Issue
Block a user