From ac6fb750b5604ce818d70168e4af849363c77b22 Mon Sep 17 00:00:00 2001 From: richarddancin Date: Wed, 5 Aug 2026 18:06:52 +0800 Subject: [PATCH 1/8] feat(studio): add BytePlus provider support --- frontend/src/App.tsx | 100 ++- frontend/src/adk/client.ts | 11 +- frontend/src/adk/cloudProvider.ts | 57 ++ frontend/src/adk/connections.ts | 3 + frontend/src/assets/byteplus.svg | 1 + frontend/src/create/CodePackageCreate.tsx | 9 +- frontend/src/create/CustomCreate.css | 9 +- frontend/src/create/CustomCreate.tsx | 162 ++++- frontend/src/create/SkillSpacePicker.tsx | 41 +- frontend/src/create/TemplateCreate.tsx | 58 +- frontend/src/create/WorkflowCreate.tsx | 41 +- frontend/src/create/a2aSpaces.ts | 6 +- frontend/src/create/skills/skillspace.ts | 13 +- frontend/src/create/types.ts | 13 +- frontend/src/create/veadkCatalog.ts | 13 +- frontend/src/create/vikingKnowledgebases.ts | 22 +- frontend/src/ui/LoginPage.tsx | 21 +- frontend/src/ui/ManageAgents.tsx | 25 +- frontend/src/ui/MyAgents.tsx | 26 +- frontend/src/ui/ProjectPreview.css | 11 +- frontend/src/ui/ProjectPreview.tsx | 42 +- frontend/src/ui/Sidebar.tsx | 6 +- frontend/src/ui/SkillCenter.tsx | 46 +- frontend/tests/generatedAgentPlanner.test.mjs | 2 +- .../tests/manageAgentsConnection.test.mjs | 8 +- frontend/tests/markdownPromptEditor.test.mjs | 4 +- frontend/tests/myAgents.test.mjs | 11 +- frontend/tests/siteBranding.test.mjs | 10 +- frontend/tests/skillCenter.test.mjs | 5 +- tests/cli/test_frontend_runtime_proxy.py | 89 +++ ...enerated_agent_backend_codegen_extended.py | 12 +- tests/cli/test_studio_deploy_target.py | 299 +++++++++ tests/test_cloud.py | 76 +++ tests/test_vikingdb_knowledge_backend.py | 87 +++ veadk/cli/cli_frontend.py | 596 +++++++++++++++--- veadk/cli/generated_agent_catalog.py | 8 +- veadk/cli/generated_agent_planner.py | 20 +- veadk/cli/studio_package.py | 15 +- veadk/cloud/cloud_agent_engine.py | 5 + veadk/consts.py | 6 +- veadk/integrations/ve_apig/ve_apig.py | 14 +- .../ve_code_pipeline/ve_code_pipeline.py | 21 +- veadk/integrations/ve_faas/ve_faas.py | 82 ++- veadk/integrations/ve_faas/ve_faas_utils.py | 18 +- .../ve_identity/identity_client.py | 65 +- .../ve_viking_db_memory.py | 21 +- .../backends/vikingdb_knowledge_backend.py | 121 +++- .../vikingdb_memory_backend.py | 38 +- .../builtin_tools/parallel_web_search.py | 7 + veadk/tools/skills_tools/skills_tool.py | 12 +- veadk/tools/vanna_tools/vanna_trainer.py | 4 +- .../vanna_tools/vikingdb_agent_memory.py | 49 +- veadk/utils/cloud_provider.py | 79 +++ veadk/webui/assets/CodeEditor-DAoMDHSt.js | 4 + .../assets/MarkdownPromptEditor-B_kJIU0E.js | 4 + ...{index-DSQDAE_a.css => index-CnirOJOU.css} | 2 +- 56 files changed, 2165 insertions(+), 365 deletions(-) create mode 100644 frontend/src/adk/cloudProvider.ts create mode 100644 frontend/src/assets/byteplus.svg create mode 100644 tests/test_vikingdb_knowledge_backend.py create mode 100644 veadk/utils/cloud_provider.py rename veadk/webui/assets/{index-DSQDAE_a.css => index-CnirOJOU.css} (67%) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3033d0209..a75546f3c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -58,6 +58,7 @@ import { type SiteBranding, type SessionCapabilities, type StudioAccess, + type UiConfig, type UiFeatures, } from "./adk/client"; import { @@ -100,6 +101,7 @@ import { type AgentEntry, type RemoteConnection, } from "./adk/connections"; +import { defaultCloudRegion, formatCloudRegion } from "./adk/cloudProvider"; import { Blocks, ThinkingPlaceholder } from "./ui/Blocks"; import { Composer } from "./ui/Composer"; import { InvocationChips } from "./ui/InvocationChips"; @@ -165,6 +167,7 @@ import { SandboxAgentWorkspace } from "./ui/SandboxAgentWorkspace"; import { SandboxComposer } from "./ui/SandboxComposer"; import { sandboxSnapshotTurns } from "./ui/sandboxCommands"; import { useSandboxCodexCommands } from "./ui/useSandboxCodexCommands"; +import byteplusLogo from "./assets/byteplus.svg"; import defaultSiteLogo from "./assets/logo.svg"; import { FeedbackDownIcon, @@ -945,6 +948,8 @@ export default function App() { }); const [agentsSource, setAgentsSource] = useState<"local" | "cloud">("cloud"); const [siteBranding, setSiteBranding] = useState(DEFAULT_SITE_BRANDING); + const [cloudProvider, setCloudProvider] = + useState("volcengine"); const [version, setVersion] = useState(""); const [uiConfigLoaded, setUiConfigLoaded] = useState(false); const [localMode, setLocalMode] = useState(false); @@ -1135,7 +1140,7 @@ export default function App() { return next; }); }, []); - // Whether the server has Volcengine AK/SK. The agent-creation workbench needs + // Whether the server has cloud AK/SK. The agent-creation workbench needs // them; assume present until the runtime-config check says otherwise (avoids // flashing the notice in the common, configured case). const [hasCreds, setHasCreds] = useState(true); @@ -1198,7 +1203,9 @@ export default function App() { appName?: string; currentVersion?: number | null; } | null>(null); - const [newRuntimeRegion, setNewRuntimeRegion] = useState("cn-beijing"); + const [newRuntimeRegion, setNewRuntimeRegion] = useState( + defaultCloudRegion(cloudProvider), + ); const [focusedDeploymentTaskId, setFocusedDeploymentTaskId] = useState(""); const [focusedWorkspaceAgentId, setFocusedWorkspaceAgentId] = useState(""); const [agentDetailTarget, setAgentDetailTarget] = @@ -1849,6 +1856,7 @@ export default function App() { trackStudioLoaded({ agentsSource: cfg.agentsSource }); setFeatures(cfg.features); setAgentsSource(cfg.agentsSource); + setCloudProvider(cfg.provider); setSiteBranding(cfg.branding); setVersion(cfg.version); setUiConfigLoaded(true); @@ -1864,6 +1872,20 @@ export default function App() { }); }, [access, authStatus, localMode, userInfo]); + useEffect(() => { + setNewRuntimeRegion((region) => { + const providerDefault = defaultCloudRegion(cloudProvider); + if (!region) return providerDefault; + if (cloudProvider === "byteplus" && region.startsWith("cn-")) { + return providerDefault; + } + if (cloudProvider === "volcengine" && region.startsWith("ap-")) { + return providerDefault; + } + return region; + }); + }, [cloudProvider]); + useEffect(() => { if (!access) return; if (!access.capabilities.createAgents) { @@ -1898,10 +1920,11 @@ export default function App() { document.head.appendChild(favicon); } favicon.removeAttribute("type"); - favicon.href = siteBranding.logoUrl || defaultSiteLogo; - }, [siteBranding]); + favicon.href = siteBranding.logoUrl + || (cloudProvider === "byteplus" ? byteplusLogo : defaultSiteLogo); + }, [cloudProvider, siteBranding]); - // Check whether the server has Volcengine AK/SK (needed by the workbench). + // Check whether the server has cloud AK/SK (needed by the workbench). useEffect(() => { fetch("/web/runtime-config", { signal: AbortSignal.timeout(10_000) }) .then((r) => (r.ok ? r.json() : null)) @@ -3686,7 +3709,13 @@ export default function App() { return
; // resolving identity } if (authStatus === "unauthenticated") { - return ; + return ( + + ); } if (!access) { return
; @@ -3842,7 +3871,7 @@ export default function App() { if (currentConn?.runtimeId && currentRuntimeAppName) { upsertCachedAgentFeedbackCase({ runtimeId: currentConn.runtimeId, - region: currentConn.region ?? "cn-beijing", + region: currentConn.region ?? defaultCloudRegion(cloudProvider), appName: currentRuntimeAppName, userId, sessionId: sid, @@ -3887,7 +3916,7 @@ export default function App() { if (currentConn?.runtimeId && currentRuntimeAppName) { upsertCachedAgentFeedbackCase({ runtimeId: currentConn.runtimeId, - region: currentConn.region ?? "cn-beijing", + region: currentConn.region ?? defaultCloudRegion(cloudProvider), appName: currentRuntimeAppName, userId, sessionId: sid, @@ -3902,7 +3931,7 @@ export default function App() { }); refreshAgentFeedbackCases({ runtimeId: currentConn.runtimeId, - region: currentConn.region ?? "cn-beijing", + region: currentConn.region ?? defaultCloudRegion(cloudProvider), appName: currentRuntimeAppName, pageSize: 100, }); @@ -3918,7 +3947,7 @@ export default function App() { if (currentConn?.runtimeId && currentRuntimeAppName) { upsertCachedAgentFeedbackCase({ runtimeId: currentConn.runtimeId, - region: currentConn.region ?? "cn-beijing", + region: currentConn.region ?? defaultCloudRegion(cloudProvider), appName: currentRuntimeAppName, userId, sessionId: sid, @@ -4110,7 +4139,7 @@ export default function App() { const agentId = await connectRuntime( agent.runtimeId, agent.label, - agent.region ?? "cn-beijing", + agent.region ?? defaultCloudRegion(cloudProvider), agent.currentVersion, ); trackAgentConnectSucceeded({ @@ -4170,6 +4199,7 @@ export default function App() {
) : myAgents ? ( setAddAgent(false)} /> ) : skillCenter ? ( - + ) : visibleCreateView !== null && !hasCreds ? (
- 需要配置火山引擎 AK/SK + 需要配置{cloudProvider === "byteplus" ? "BytePlus" : "火山引擎"} AK/SK
- 智能体工作台需要 Volcengine 凭据才能使用。请在运行环境中设置 - {" "} - VOLCENGINE_ACCESS_KEY 与{" "} - VOLCENGINE_SECRET_KEY 后重试。 + 智能体工作台需要 + {cloudProvider === "byteplus" ? " BytePlus " : " Volcengine "} + 凭据才能使用。请在运行环境中设置{" "} + + {cloudProvider === "byteplus" + ? "BYTEPLUS_ACCESS_KEY" + : "VOLCENGINE_ACCESS_KEY"} + {" "} + 与{" "} + + {cloudProvider === "byteplus" + ? "BYTEPLUS_SECRET_KEY" + : "VOLCENGINE_SECRET_KEY"} + {" "} + 后重试。
) : visibleCreateView === "menu" ? ( @@ -4848,6 +4892,7 @@ export default function App() { ) : visibleCreateView === "custom" ? ( setCreateView("menu")} onCreate={onCreate} @@ -4886,11 +4931,20 @@ export default function App() { onDeploymentComplete={finishDeployment} /> ) : visibleCreateView === "template" ? ( - setCreateView("menu")} onCreate={onCreate} /> + setCreateView("menu")} + onCreate={onCreate} + /> ) : visibleCreateView === "workflow" ? ( - setCreateView("menu")} onCreate={onCreate} /> + setCreateView("menu")} + onCreate={onCreate} + /> ) : visibleCreateView === "package" ? ( { setCreateView(null); setAddMenu(true); diff --git a/frontend/src/adk/client.ts b/frontend/src/adk/client.ts index 5aed9cfc3..3c8d75512 100644 --- a/frontend/src/adk/client.ts +++ b/frontend/src/adk/client.ts @@ -20,6 +20,7 @@ import { import type { AgentProject } from "../create/project"; import type { AgentDraft, NetworkConfig } from "../create/types"; import type { IssueFeedbackReport } from "./issueFeedback"; +import { VOLCENGINE_DEFAULT_REGION } from "./cloudProvider"; /** An ADK event as serialised over `/run_sse` (camelCase, by_alias=True). */ export interface AdkUsage { @@ -516,7 +517,10 @@ function runtimeAppsCacheKey(runtimeId: string, region: string): string { } function runtimeRegionCandidates(region?: string): string[] { - const primary = region || "cn-beijing"; + const primary = region || VOLCENGINE_DEFAULT_REGION; + if (!RUNTIME_REGION_FALLBACKS.includes(primary as (typeof RUNTIME_REGION_FALLBACKS)[number])) { + return [primary]; + } return [ primary, ...RUNTIME_REGION_FALLBACKS.filter((candidate) => candidate !== primary), @@ -2053,7 +2057,7 @@ export interface ManagedRuntime { /** List AgentKit runtimes the server authorizes this user to manage. */ export async function getMyRuntimes( - region = "cn-beijing", + region = VOLCENGINE_DEFAULT_REGION, ): Promise { const res = await apiFetch(`/web/my-runtimes?region=${encodeURIComponent(region)}`); if (!res.ok) throw new Error(`加载失败 (${res.status})`); @@ -2107,6 +2111,7 @@ export interface StudioTelemetryConfig { export interface UiConfig { studio: boolean; version: string; + provider: "volcengine" | "byteplus"; branding: SiteBranding; features: UiFeatures; defaultView: "chat" | "addAgent"; @@ -2128,6 +2133,7 @@ const DISABLED_STUDIO_TELEMETRY: StudioTelemetryConfig = { const DEFAULT_UI_CONFIG: UiConfig = { studio: false, version: "", + provider: "volcengine", branding: DEFAULT_SITE_BRANDING, features: { newChat: true, @@ -2204,6 +2210,7 @@ export async function getUiConfig(): Promise { return { studio: d.studio ?? false, version: typeof d.version === "string" ? d.version : "", + provider: d.provider === "byteplus" ? "byteplus" : "volcengine", branding: { title: typeof d.branding?.title === "string" ? d.branding.title diff --git a/frontend/src/adk/cloudProvider.ts b/frontend/src/adk/cloudProvider.ts new file mode 100644 index 000000000..106d188ed --- /dev/null +++ b/frontend/src/adk/cloudProvider.ts @@ -0,0 +1,57 @@ +export type CloudProvider = "volcengine" | "byteplus"; + +export interface CloudRegionOption { + value: string; + label: string; +} + +export const BYTEPLUS_DEFAULT_REGION = "ap-southeast-1"; +export const VOLCENGINE_DEFAULT_REGION = "cn-beijing"; +export const BYTEPLUS_MODELARK_BASE_URL = "https://ark.ap-southeast.bytepluses.com/api/v3"; +export const VOLCENGINE_MODELARK_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3/"; +export const BYTEPLUS_DEFAULT_MODEL_NAME = "seed-2-0-lite-260228"; +export const VOLCENGINE_DEFAULT_MODEL_NAME = "doubao-seed-2-1-pro-260628"; +export const BYTEPLUS_PLANNER_MODEL_NAME = "seed-2-0-lite-260228"; +export const VOLCENGINE_PLANNER_MODEL_NAME = "doubao-seed-2-0-lite-260428"; + +const VOLCENGINE_REGIONS: CloudRegionOption[] = [ + { value: "cn-beijing", label: "华北 2(北京)" }, + { value: "cn-shanghai", label: "华东 2(上海)" }, +]; + +const BYTEPLUS_REGIONS: CloudRegionOption[] = [ + { value: BYTEPLUS_DEFAULT_REGION, label: "ap-southeast-1 (Singapore)" }, +]; + +export function cloudRegionOptions(provider: CloudProvider): CloudRegionOption[] { + return provider === "byteplus" ? BYTEPLUS_REGIONS : VOLCENGINE_REGIONS; +} + +export function defaultCloudRegion(provider: CloudProvider): string { + return cloudRegionOptions(provider)[0]?.value || VOLCENGINE_DEFAULT_REGION; +} + +export function formatCloudRegion(region: string, provider?: CloudProvider): string { + const options = provider + ? cloudRegionOptions(provider) + : [...VOLCENGINE_REGIONS, ...BYTEPLUS_REGIONS]; + return options.find((option) => option.value === region)?.label || region || "-"; +} + +export function defaultModelName(provider: CloudProvider): string { + return provider === "byteplus" + ? BYTEPLUS_DEFAULT_MODEL_NAME + : VOLCENGINE_DEFAULT_MODEL_NAME; +} + +export function defaultModelApiBase(provider: CloudProvider): string { + return provider === "byteplus" + ? BYTEPLUS_MODELARK_BASE_URL + : VOLCENGINE_MODELARK_BASE_URL; +} + +export function plannerModelName(provider: CloudProvider): string { + return provider === "byteplus" + ? BYTEPLUS_PLANNER_MODEL_NAME + : VOLCENGINE_PLANNER_MODEL_NAME; +} diff --git a/frontend/src/adk/connections.ts b/frontend/src/adk/connections.ts index db0373a34..8b939123d 100644 --- a/frontend/src/adk/connections.ts +++ b/frontend/src/adk/connections.ts @@ -47,6 +47,9 @@ const RUNTIME_REGION_FALLBACKS = ["cn-beijing", "cn-shanghai"] as const; function runtimeRegionCandidates(region: string): string[] { const primary = region || "cn-beijing"; + if (!RUNTIME_REGION_FALLBACKS.includes(primary as (typeof RUNTIME_REGION_FALLBACKS)[number])) { + return [primary]; + } return [ primary, ...RUNTIME_REGION_FALLBACKS.filter((candidate) => candidate !== primary), diff --git a/frontend/src/assets/byteplus.svg b/frontend/src/assets/byteplus.svg new file mode 100644 index 000000000..ba91ef998 --- /dev/null +++ b/frontend/src/assets/byteplus.svg @@ -0,0 +1 @@ + diff --git a/frontend/src/create/CodePackageCreate.tsx b/frontend/src/create/CodePackageCreate.tsx index 9b76b1413..d7649eb18 100644 --- a/frontend/src/create/CodePackageCreate.tsx +++ b/frontend/src/create/CodePackageCreate.tsx @@ -6,6 +6,10 @@ import { type DragEvent, } from "react"; import { deployAgentkitProject, type DeployStage } from "../adk/client"; +import { + defaultCloudRegion, + type CloudProvider, +} from "../adk/cloudProvider"; import { ProjectPreview, type DeployResult, @@ -28,6 +32,7 @@ interface CodePackageCreateProps { onDeploymentStarted?: (task: DeploymentTaskUpdate) => void; onDeploymentComplete?: (result: DeployResult) => void | Promise; initialDeployRegion?: string; + cloudProvider?: CloudProvider; } function packageProjectName(fileName: string): string { @@ -88,7 +93,8 @@ export function CodePackageCreate({ onDeploymentTaskChange, onDeploymentStarted, onDeploymentComplete, - initialDeployRegion = "cn-beijing", + cloudProvider = "volcengine", + initialDeployRegion = defaultCloudRegion(cloudProvider), }: CodePackageCreateProps) { const inputRef = useRef(null); const loadRunRef = useRef(0); @@ -178,6 +184,7 @@ export function CodePackageCreate({ return (
+
@@ -933,6 +964,14 @@ function VikingKnowledgebaseSelect({ {filteredItems.map((item) => { const optionLabel = vikingKnowledgebaseDisplayName(item); const selected = item.id === value; + const optionIds = [ + item.id, + item.resourceId, + item.agentkitKnowledgeId, + item.providerKnowledgeId, + ] + .filter(Boolean) + .join(" / "); return ( @@ -1226,9 +1265,11 @@ const SKILL_SOURCES: { function SkillsSourceTabs({ selected, onChange, + cloudProvider, }: { selected: SelectedSkill[]; onChange: (next: SelectedSkill[]) => void; + cloudProvider: CloudProvider; }) { const [active, setActive] = useState("local"); const [open, setOpen] = useState(false); @@ -1355,7 +1396,11 @@ function SkillsSourceTabs({ )} {active === "skillspace" && ( - + )}
@@ -1445,10 +1490,14 @@ function updateNode( return { ...root, subAgents }; } -function addChild(root: AgentDraft, path: NodePath): AgentDraft { +function addChild( + root: AgentDraft, + path: NodePath, + cloudProvider: CloudProvider = "volcengine", +): AgentDraft { return updateNode(root, path, (n) => ({ ...n, - subAgents: [...n.subAgents, emptyDraft()], + subAgents: [...n.subAgents, emptyDraft(cloudProvider)], })); } @@ -1456,10 +1505,11 @@ function insertChild( root: AgentDraft, parentPath: NodePath, index: number, + cloudProvider: CloudProvider = "volcengine", ): AgentDraft { return updateNode(root, parentPath, (n) => { const subAgents = n.subAgents.slice(); - subAgents.splice(index, 0, emptyDraft()); + subAgents.splice(index, 0, emptyDraft(cloudProvider)); return { ...n, subAgents }; }); } @@ -2490,6 +2540,8 @@ interface CustomCreateProps extends CreateModeProps { }; /** Region selected before entering the create flow. */ initialDeployRegion?: string; + /** Cloud provider selected by the Studio shell. */ + cloudProvider?: CloudProvider; /** Called after an existing Runtime has been updated and released. */ onDeploymentComplete?: (result: DeployResult) => void | Promise; /** Called once the persistent deployment task has been created. */ @@ -2509,7 +2561,8 @@ export function CustomCreate({ onDeploymentTaskChange, createMode = "custom", deploymentTarget, - initialDeployRegion = "cn-beijing", + cloudProvider = "volcengine", + initialDeployRegion = defaultCloudRegion(cloudProvider), onDeploymentComplete, onDeploymentStarted, onDraftChange, @@ -2519,8 +2572,37 @@ export function CustomCreate({ void onBack; // no footer nav in the single-scroll layout; back lives in app chrome void onDiscard; // the discard action is intentionally hidden in this flow const [draft, setDraft] = useState( - () => initialDraft ?? emptyDraft(), + () => initialDraft ?? emptyDraft(cloudProvider), ); + useEffect(() => { + const otherProviderModel = cloudProvider === "byteplus" + ? VOLCENGINE_DEFAULT_MODEL_NAME + : BYTEPLUS_DEFAULT_MODEL_NAME; + const otherProviderBase = cloudProvider === "byteplus" + ? VOLCENGINE_MODELARK_BASE_URL + : BYTEPLUS_MODELARK_BASE_URL; + setDraft((current) => { + const nextModelName = + current.modelName?.trim() === otherProviderModel + ? defaultModelName(cloudProvider) + : current.modelName; + const nextModelApiBase = + current.modelApiBase?.trim() === otherProviderBase + ? defaultModelApiBase(cloudProvider) + : current.modelApiBase; + if ( + nextModelName === current.modelName && + nextModelApiBase === current.modelApiBase + ) { + return current; + } + return { + ...current, + modelName: nextModelName, + modelApiBase: nextModelApiBase, + }; + }); + }, [cloudProvider]); const [aiRequirement, setAiRequirement] = useState(""); const [aiGenerating, setAiGenerating] = useState(false); const [aiGenerated, setAiGenerated] = useState(false); @@ -2561,9 +2643,9 @@ export function CustomCreate({ { id: "baseline", name: "基准组", - modelName: defaultDebugModelName(initialDraft ?? emptyDraft()), - description: (initialDraft ?? emptyDraft()).description, - instruction: (initialDraft ?? emptyDraft()).instruction, + modelName: defaultDebugModelName(initialDraft ?? emptyDraft(cloudProvider)), + description: (initialDraft ?? emptyDraft(cloudProvider)).description, + instruction: (initialDraft ?? emptyDraft(cloudProvider)).instruction, optimizations: [], configOpen: false, phase: "idle", @@ -2779,7 +2861,7 @@ export function CustomCreate({ const addCanvasStep = (path: NodePath) => { const parent = getNode(draft, path); if (!nodeAcceptsChildren(parent) || path.length >= MAX_TREE_DEPTH) return; - const next = addChild(draft, path); + const next = addChild(draft, path, cloudProvider); const childIndex = getNode(next, path).subAgents.length - 1; applyTree(next, [...path, childIndex]); }; @@ -2793,7 +2875,7 @@ export function CustomCreate({ return; } const safeIndex = Math.max(0, Math.min(index, parent.subAgents.length)); - const next = insertChild(draft, parentPath, safeIndex); + const next = insertChild(draft, parentPath, safeIndex, cloudProvider); applyTree(next, [...parentPath, safeIndex]); }; @@ -2803,7 +2885,7 @@ export function CustomCreate({ ) { return; } - setDraft(emptyDraft()); + setDraft(emptyDraft(cloudProvider)); setSelectedPath([]); setShowErrors(false); }; @@ -3399,7 +3481,7 @@ export function CustomCreate({ value={aiRequirement} maxLength={8000} disabled={aiGenerating} - placeholder="描述目标,使用 doubao-seed-2-0-lite-260428 模型一键生成配置" + placeholder={`描述目标,使用 ${plannerModelName(cloudProvider)} 模型一键生成配置`} aria-invalid={Boolean(aiRequirementError)} aria-describedby={ aiRequirementError ? "ai-requirement-error" : undefined @@ -3735,7 +3817,7 @@ export function CustomCreate({ patch({ modelName: e.target.value }) } @@ -3786,7 +3868,7 @@ export function CustomCreate({ patch({ modelApiBase: e.target.value }) } @@ -3862,6 +3944,7 @@ export function CustomCreate({ patch({ selectedSkills: next })} + cloudProvider={cloudProvider} />
@@ -3897,9 +3980,33 @@ export function CustomCreate({ - patch({ knowledgebaseIndex }) - } + onChange={(knowledgebase) => { + patch({ + knowledgebaseIndex: knowledgebase.id, + }); + if (knowledgebase.projectName) { + patchDeploymentEnv( + "DATABASE_VIKING_PROJECT", + knowledgebase.projectName, + ); + } + if (knowledgebase.region) { + patchDeploymentEnv( + "DATABASE_VIKING_REGION", + knowledgebase.region, + ); + } + if (knowledgebase.sourceKind) { + patchDeploymentEnv( + "DATABASE_VIKING_COLLECTION_KIND", + knowledgebase.sourceKind, + ); + } + patchDeploymentEnv( + "DATABASE_VIKING_RESOURCE_ID", + knowledgebase.resourceId ?? "", + ); + }} />
)} @@ -4067,6 +4174,7 @@ export function CustomCreate({ {project ? ( void; + cloudProvider?: CloudProvider; }) { const [spaces, setSpaces] = useState([]); const [skills, setSkills] = useState([]); @@ -85,6 +85,9 @@ export function SkillSpacePicker({ }, [spaceId, spaces]); const selectedSpace = spaces.find((s) => s.id === spaceId); + const consoleUrl = selectedSpace + ? getSkillSpaceConsoleUrl(selectedSpace.id, selectedSpace.region, cloudProvider) + : ""; const isSelected = (skillId: string, ver: string) => selected.some( @@ -161,19 +164,21 @@ export function SkillSpacePicker({ className="cw-skillspace-region-label" title={selectedSpace.region} > - {regionLabel(selectedSpace.region)} + {formatCloudRegion(selectedSpace.region, cloudProvider)} )} - - - + {consoleUrl && ( + + + + )} )}
diff --git a/frontend/src/create/TemplateCreate.tsx b/frontend/src/create/TemplateCreate.tsx index 4e90570ac..1ddf7ec2d 100644 --- a/frontend/src/create/TemplateCreate.tsx +++ b/frontend/src/create/TemplateCreate.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useMemo, useState } from "react"; import { motion } from "motion/react"; import { ArrowLeft, @@ -18,6 +18,13 @@ import { } from "lucide-react"; import { type CreateModeProps, type AgentDraft, emptyDraft } from "./types"; import { displayDescription } from "./displayText"; +import { + defaultModelApiBase, + defaultModelName, + VOLCENGINE_DEFAULT_MODEL_NAME, + VOLCENGINE_MODELARK_BASE_URL, + type CloudProvider, +} from "../adk/cloudProvider"; import "./TemplateCreate.css"; /** A gallery preset: an AgentDraft plus presentation metadata. */ @@ -154,6 +161,29 @@ const TEMPLATES: Template[] = [ }, ]; +function providerTemplateDraft( + draft: AgentDraft, + cloudProvider: CloudProvider, +): AgentDraft { + if (cloudProvider !== "byteplus") return draft; + const byteplusModelName = defaultModelName(cloudProvider); + return { + ...draft, + model: draft.model === "doubao-1.5-pro-32k" ? byteplusModelName : draft.model, + modelName: + draft.modelName === VOLCENGINE_DEFAULT_MODEL_NAME + ? byteplusModelName + : draft.modelName, + modelApiBase: + !draft.modelApiBase || draft.modelApiBase === VOLCENGINE_MODELARK_BASE_URL + ? defaultModelApiBase(cloudProvider) + : draft.modelApiBase, + subAgents: draft.subAgents.map((child) => + providerTemplateDraft(child, cloudProvider), + ), + }; +} + /** Which built-in components a draft uses → tags on the card. */ function components(d: AgentDraft) { const out: { icon: LucideIcon; label: string }[] = []; @@ -165,8 +195,20 @@ function components(d: AgentDraft) { return out; } -export function TemplateCreate({ onBack, onCreate }: CreateModeProps) { +export function TemplateCreate({ + cloudProvider = "volcengine", + onBack, + onCreate, +}: CreateModeProps) { const [selected, setSelected] = useState