From b450cc8dc713dc61faeb0edcb4ef006f19336ec4 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 9 Jul 2026 09:50:02 +0200 Subject: [PATCH] fix: expose gpt pika provider profile --- internal/cloud/code-agent-agentrun-profile.ts | 3 ++- internal/cloud/provider-profile-management.ts | 22 ++++++++++++------- tools/src/hwlab-cli-lib.ts | 9 ++++---- .../src/stores/provider-profiles-view.ts | 2 +- .../src/stores/workbench-session.ts | 3 ++- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/internal/cloud/code-agent-agentrun-profile.ts b/internal/cloud/code-agent-agentrun-profile.ts index 43b3ae5f..c698bf71 100644 --- a/internal/cloud/code-agent-agentrun-profile.ts +++ b/internal/cloud/code-agent-agentrun-profile.ts @@ -12,7 +12,7 @@ const AGENTRUN_RUNNER_KIND = "agentrun-v01-shared-runner"; const AGENTRUN_SESSION_MODE = "agentrun-v01-durable-session"; const AGENTRUN_IMPLEMENTATION_TYPE = "agentrun-v01-shared-execution-infra"; const AGENTRUN_PROVIDER_TRACE_PROTOCOL = "agentrun-v01-jsonrpc"; -const AGENTRUN_BACKEND_ALIASES = Object.freeze({ "codex-api": "codex", codex: "codex" }); +const AGENTRUN_BACKEND_ALIASES = Object.freeze({ "codex-api": "codex", codex: "codex", "gpt.pika": "gpt-pika" }); const AGENTRUN_BACKEND_PROFILE_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/u; export function resolveAgentRunBackendProfile(env = process.env, params = {}) { @@ -108,6 +108,7 @@ export function modelForBackendProfile(profile, env = process.env) { export function providerForBackendProfile(profile) { const resolved = resolveAgentRunBackendProfile({}, { providerProfile: profile }); if (resolved === "codex") return "codex-api"; + if (resolved === "gpt-pika") return "gpt.pika"; return resolved; } diff --git a/internal/cloud/provider-profile-management.ts b/internal/cloud/provider-profile-management.ts index d51e3391..77d37cb7 100644 --- a/internal/cloud/provider-profile-management.ts +++ b/internal/cloud/provider-profile-management.ts @@ -8,7 +8,10 @@ const AGENTRUN_MANAGER_HOST_PATTERN = /^agentrun-mgr\.[a-z0-9]([-a-z0-9]*[a-z0-9 const DEFAULT_TIMEOUT_MS = 30000; const PROVIDER_PROFILE_ALIASES = Object.freeze({ codex: "codex-api" }); -const PROVIDER_PROFILE_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/u; +const PROVIDER_PROFILE_BACKEND_ALIASES = Object.freeze({ "codex-api": "codex", "gpt.pika": "gpt-pika" }); +const PROVIDER_PROFILE_DISPLAY_ALIASES = Object.freeze({ codex: "codex-api", "gpt-pika": "gpt.pika" }); +const PROVIDER_PROFILE_ID_PATTERN = /^[a-z0-9][a-z0-9.-]{0,63}$/u; +const AGENTRUN_PROVIDER_PROFILE_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/u; const RESERVED_PROVIDER_PROFILES = new Set(["runtime-default"]); export async function handleProviderProfileCatalogHttp(request, response, options = {}) { @@ -174,14 +177,15 @@ function parseProviderProfileRoute(pathname, method) { function normalizeProfile(value) { const input = text(value).toLowerCase(); const publicProfile = PROVIDER_PROFILE_ALIASES[input] ?? input; - if (!publicProfile || RESERVED_PROVIDER_PROFILES.has(publicProfile) || !PROVIDER_PROFILE_ID_PATTERN.test(publicProfile)) { - throw routeError(400, "invalid_provider_profile", "Provider profile must be a lowercase slug such as deepseek, minimax-m3, dsflash-go, or codex-api", { + const agentRunProfile = PROVIDER_PROFILE_BACKEND_ALIASES[publicProfile] ?? publicProfile; + if (!publicProfile || RESERVED_PROVIDER_PROFILES.has(publicProfile) || !PROVIDER_PROFILE_ID_PATTERN.test(publicProfile) || !AGENTRUN_PROVIDER_PROFILE_ID_PATTERN.test(agentRunProfile)) { + throw routeError(400, "invalid_provider_profile", "Provider profile must be a lowercase id such as deepseek, minimax-m3, dsflash-go, codex-api, or gpt.pika", { profile: input, - alias: "codex -> codex-api", + alias: "codex -> codex-api, gpt.pika -> gpt-pika", pattern: String(PROVIDER_PROFILE_ID_PATTERN) }); } - return { publicProfile, agentRunProfile: publicProfile === "codex-api" ? "codex" : publicProfile }; + return { publicProfile, agentRunProfile }; } async function agentRunJson(fetchImpl, managerUrl, path, { method = "GET", body, requestId, timeoutMs, apiKey }) { @@ -270,9 +274,11 @@ function normalizeCatalogData(data) { function normalizeProfileData(item) { if (!item || typeof item !== "object") return item; const copy = redactObject(item); - if (copy.profile === "codex") { - copy.backendProfile = "codex"; - copy.profile = "codex-api"; + const backendProfile = text(copy.backendProfile ?? copy.profile); + const displayProfile = PROVIDER_PROFILE_DISPLAY_ALIASES[backendProfile] ?? copy.profile; + if (displayProfile && displayProfile !== copy.profile) { + copy.backendProfile = backendProfile; + copy.profile = displayProfile; } if (copy.profile === "deepseek") copy.bridge = deepseekBridgeSummary(); if (text(copy.configSummary?.model ?? copy.model) === "deepseek-v4-flash") copy.bridge = opencodeZenGoBridgeSummary(); diff --git a/tools/src/hwlab-cli-lib.ts b/tools/src/hwlab-cli-lib.ts index 857df170..7a323ce8 100644 --- a/tools/src/hwlab-cli-lib.ts +++ b/tools/src/hwlab-cli-lib.ts @@ -580,11 +580,12 @@ async function providerProfileAuthJsonFromStdin(context: any) { function normalizeProviderProfile(value: unknown) { const profile = text(value).toLowerCase(); const normalized = profile === "codex" ? "codex-api" : profile; - if (/^[a-z0-9][a-z0-9-]{0,63}$/u.test(normalized) && normalized !== "runtime-default") return normalized; - throw cliError("invalid_provider_profile", "provider profile must be a lowercase slug such as deepseek, minimax-m3, dsflash-go, or codex-api", { + const backendProfile = normalized === "gpt.pika" ? "gpt-pika" : normalized; + if (/^[a-z0-9][a-z0-9.-]{0,63}$/u.test(normalized) && /^[a-z0-9][a-z0-9-]{0,63}$/u.test(backendProfile) && normalized !== "runtime-default") return normalized; + throw cliError("invalid_provider_profile", "provider profile must be a lowercase id such as deepseek, minimax-m3, dsflash-go, codex-api, or gpt.pika", { profile, - alias: "codex -> codex-api", - pattern: "^[a-z0-9][a-z0-9-]{0,63}$" + alias: "codex -> codex-api, gpt.pika -> gpt-pika", + pattern: "public=^[a-z0-9][a-z0-9.-]{0,63}$ backend=^[a-z0-9][a-z0-9-]{0,63}$" }); } diff --git a/web/hwlab-cloud-web/src/stores/provider-profiles-view.ts b/web/hwlab-cloud-web/src/stores/provider-profiles-view.ts index f33f0224..a51d3ac8 100644 --- a/web/hwlab-cloud-web/src/stores/provider-profiles-view.ts +++ b/web/hwlab-cloud-web/src/stores/provider-profiles-view.ts @@ -92,7 +92,7 @@ export function mergeProviderRow(rows: ProviderProfileRow[], updated: ProviderPr } export function orderProviderProfiles(rows: ProviderProfileRow[]): ProviderProfileRow[] { - const preferred = ["deepseek", "dsflash-go", "codex-api", "minimax-m3"]; + const preferred = ["deepseek", "dsflash-go", "gpt.pika", "codex-api", "minimax-m3"]; return [...rows].sort((a, b) => { const ai = preferred.indexOf(a.profile); const bi = preferred.indexOf(b.profile); diff --git a/web/hwlab-cloud-web/src/stores/workbench-session.ts b/web/hwlab-cloud-web/src/stores/workbench-session.ts index 79f58bfd..2568f407 100644 --- a/web/hwlab-cloud-web/src/stores/workbench-session.ts +++ b/web/hwlab-cloud-web/src/stores/workbench-session.ts @@ -66,10 +66,11 @@ export const RECENT_DRAFTS_LIMIT = 8; const OBJECT_OBJECT_TEXT = "[object Object]"; const GENERIC_USER_TITLE_TEXT = "用户"; -const BUILTIN_PROVIDER_PROFILE_ORDER = Object.freeze(["deepseek", "dsflash-go", "codex-api", "minimax-m3"]); +const BUILTIN_PROVIDER_PROFILE_ORDER = Object.freeze(["deepseek", "dsflash-go", "gpt.pika", "codex-api", "minimax-m3"]); const BUILTIN_PROVIDER_PROFILE_LABELS: Readonly> = Object.freeze({ deepseek: "DeepSeek", "dsflash-go": "DeepSeek V4 Flash", + "gpt.pika": "gpt.pika", "codex-api": "Codex API", "minimax-m3": "MiniMax-M3" });