支持Codex CLI的官网订阅设置
This commit is contained in:
@@ -92,6 +92,7 @@ interface AgentDraft {
|
|||||||
googleCloudProject: string
|
googleCloudProject: string
|
||||||
googleCloudLocation: string
|
googleCloudLocation: string
|
||||||
googleApplicationCredentials: string
|
googleApplicationCredentials: string
|
||||||
|
codexAuthMode: CodexAuthMode
|
||||||
codexModelProvider: string
|
codexModelProvider: string
|
||||||
codexProviderOptions: string[]
|
codexProviderOptions: string[]
|
||||||
codexReasoningEffort: CodexReasoningEffort
|
codexReasoningEffort: CodexReasoningEffort
|
||||||
@@ -970,6 +971,10 @@ interface CodexImportantValues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CODEX_DEFAULT_MODEL_PROVIDER = "codeg"
|
const CODEX_DEFAULT_MODEL_PROVIDER = "codeg"
|
||||||
|
|
||||||
|
const CODEX_AUTH_MODES = ["api_key", "chatgpt_subscription"] as const
|
||||||
|
type CodexAuthMode = (typeof CODEX_AUTH_MODES)[number]
|
||||||
|
|
||||||
type CodexReasoningEffort = "low" | "medium" | "high" | "xhigh"
|
type CodexReasoningEffort = "low" | "medium" | "high" | "xhigh"
|
||||||
|
|
||||||
const CODEX_REASONING_EFFORT_OPTIONS: ReadonlyArray<{
|
const CODEX_REASONING_EFFORT_OPTIONS: ReadonlyArray<{
|
||||||
@@ -1283,6 +1288,21 @@ function parseCodexAuthJsonText(authJsonText: string): string | null {
|
|||||||
return parseCodexAuthJsonObject(authJsonText).error
|
return parseCodexAuthJsonObject(authJsonText).error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function inferCodexAuthMode(authJsonText: string): CodexAuthMode {
|
||||||
|
const { authObject } = parseCodexAuthJsonObject(authJsonText)
|
||||||
|
if (authObject) {
|
||||||
|
// 官网订阅:auth_mode 为 chatgpt,或没有 OPENAI_API_KEY,或值为 null
|
||||||
|
if (
|
||||||
|
authObject.auth_mode === "chatgpt" ||
|
||||||
|
!("OPENAI_API_KEY" in authObject) ||
|
||||||
|
authObject.OPENAI_API_KEY === null
|
||||||
|
) {
|
||||||
|
return "chatgpt_subscription"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "api_key"
|
||||||
|
}
|
||||||
|
|
||||||
function extractCodexImportantValues(
|
function extractCodexImportantValues(
|
||||||
authJsonText: string,
|
authJsonText: string,
|
||||||
configTomlText: string
|
configTomlText: string
|
||||||
@@ -1982,6 +2002,10 @@ function buildAgentDraft(agent: AcpAgentInfo): AgentDraft {
|
|||||||
googleCloudProject: geminiImportant.googleCloudProject,
|
googleCloudProject: geminiImportant.googleCloudProject,
|
||||||
googleCloudLocation: geminiImportant.googleCloudLocation,
|
googleCloudLocation: geminiImportant.googleCloudLocation,
|
||||||
googleApplicationCredentials: geminiImportant.googleApplicationCredentials,
|
googleApplicationCredentials: geminiImportant.googleApplicationCredentials,
|
||||||
|
codexAuthMode:
|
||||||
|
agent.agent_type === "codex"
|
||||||
|
? inferCodexAuthMode(codexAuthJsonText)
|
||||||
|
: "api_key",
|
||||||
codexModelProvider: codexImportant.modelProvider,
|
codexModelProvider: codexImportant.modelProvider,
|
||||||
codexProviderOptions: codexImportant.providerOptions,
|
codexProviderOptions: codexImportant.providerOptions,
|
||||||
codexReasoningEffort: codexImportant.reasoningEffort,
|
codexReasoningEffort: codexImportant.reasoningEffort,
|
||||||
@@ -3956,6 +3980,7 @@ export function AcpAgentSettings() {
|
|||||||
)
|
)
|
||||||
updateSelectedDraft((current) => ({
|
updateSelectedDraft((current) => ({
|
||||||
...current,
|
...current,
|
||||||
|
codexAuthMode: inferCodexAuthMode(nextText),
|
||||||
codexAuthJsonText: nextText,
|
codexAuthJsonText: nextText,
|
||||||
apiBaseUrl: important.apiBaseUrl,
|
apiBaseUrl: important.apiBaseUrl,
|
||||||
apiKey: important.apiKey ?? current.apiKey,
|
apiKey: important.apiKey ?? current.apiKey,
|
||||||
@@ -4027,6 +4052,58 @@ export function AcpAgentSettings() {
|
|||||||
[selectedAgent, selectedDraft, updateSelectedDraft]
|
[selectedAgent, selectedDraft, updateSelectedDraft]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const handleCodexAuthModeChange = useCallback(
|
||||||
|
(nextMode: CodexAuthMode) => {
|
||||||
|
if (
|
||||||
|
!selectedAgent ||
|
||||||
|
!selectedDraft ||
|
||||||
|
selectedAgent.agent_type !== "codex"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
const nextAuthJsonText =
|
||||||
|
nextMode === "chatgpt_subscription"
|
||||||
|
? "{}"
|
||||||
|
: JSON.stringify({ OPENAI_API_KEY: "" }, null, 2)
|
||||||
|
|
||||||
|
const nextConfigTomlText =
|
||||||
|
nextMode === "chatgpt_subscription"
|
||||||
|
? ""
|
||||||
|
: selectedDraft.codexConfigTomlText
|
||||||
|
|
||||||
|
const nextEnvText =
|
||||||
|
nextMode === "chatgpt_subscription"
|
||||||
|
? patchEnvText(selectedDraft.envText, {
|
||||||
|
OPENAI_API_KEY: "",
|
||||||
|
OPENAI_BASE_URL: "",
|
||||||
|
})
|
||||||
|
: selectedDraft.envText
|
||||||
|
|
||||||
|
const synced = extractCodexImportantValues(
|
||||||
|
nextAuthJsonText,
|
||||||
|
nextConfigTomlText
|
||||||
|
)
|
||||||
|
|
||||||
|
updateSelectedDraft((current) => ({
|
||||||
|
...current,
|
||||||
|
codexAuthMode: nextMode,
|
||||||
|
codexAuthJsonText: nextAuthJsonText,
|
||||||
|
codexConfigTomlText: nextConfigTomlText,
|
||||||
|
envText: nextEnvText,
|
||||||
|
apiBaseUrl:
|
||||||
|
nextMode === "chatgpt_subscription" ? "" : synced.apiBaseUrl,
|
||||||
|
apiKey:
|
||||||
|
nextMode === "chatgpt_subscription" ? "" : (synced.apiKey ?? ""),
|
||||||
|
model: synced.model,
|
||||||
|
codexModelProvider: synced.modelProvider,
|
||||||
|
codexProviderOptions: synced.providerOptions,
|
||||||
|
codexReasoningEffort: synced.reasoningEffort,
|
||||||
|
codexSupportsWebsockets: synced.supportsWebsockets,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
[selectedAgent, selectedDraft, updateSelectedDraft]
|
||||||
|
)
|
||||||
|
|
||||||
const handleCodexImportantConfigChange = useCallback(
|
const handleCodexImportantConfigChange = useCallback(
|
||||||
(
|
(
|
||||||
key: "apiBaseUrl" | "apiKey" | "model" | "reasoningEffort",
|
key: "apiBaseUrl" | "apiKey" | "model" | "reasoningEffort",
|
||||||
@@ -4482,6 +4559,41 @@ export function AcpAgentSettings() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
<label className="text-[11px] text-muted-foreground">
|
||||||
|
{t("codex.authMode")}
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={selectedDraft.codexAuthMode}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
if (
|
||||||
|
CODEX_AUTH_MODES.includes(value as CodexAuthMode)
|
||||||
|
) {
|
||||||
|
handleCodexAuthModeChange(value as CodexAuthMode)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-full">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent align="start">
|
||||||
|
{CODEX_AUTH_MODES.map((mode) => (
|
||||||
|
<SelectItem key={mode} value={mode}>
|
||||||
|
{mode === "chatgpt_subscription"
|
||||||
|
? t("codex.chatgptSubscription")
|
||||||
|
: "API Key"}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<p className="text-[11px] text-muted-foreground">
|
||||||
|
{selectedDraft.codexAuthMode === "chatgpt_subscription"
|
||||||
|
? t("codex.chatgptSubscriptionHint")
|
||||||
|
: t("codex.apiKeyHint")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{selectedDraft.codexAuthMode !== "chatgpt_subscription" && (
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<label className="text-[11px] text-muted-foreground">
|
<label className="text-[11px] text-muted-foreground">
|
||||||
Provider
|
Provider
|
||||||
@@ -4506,7 +4618,9 @@ export function AcpAgentSettings() {
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{selectedDraft.codexAuthMode !== "chatgpt_subscription" && (
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<label className="text-[11px] text-muted-foreground">
|
<label className="text-[11px] text-muted-foreground">
|
||||||
API URL
|
API URL
|
||||||
@@ -4522,7 +4636,9 @@ export function AcpAgentSettings() {
|
|||||||
placeholder="https://api.openai.com/v1"
|
placeholder="https://api.openai.com/v1"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{selectedDraft.codexAuthMode !== "chatgpt_subscription" && (
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<label className="text-[11px] text-muted-foreground">
|
<label className="text-[11px] text-muted-foreground">
|
||||||
API Key
|
API Key
|
||||||
@@ -4568,7 +4684,9 @@ export function AcpAgentSettings() {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{selectedDraft.codexAuthMode !== "chatgpt_subscription" && (
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<label className="text-[11px] text-muted-foreground">
|
<label className="text-[11px] text-muted-foreground">
|
||||||
{t("codex.modelName")}
|
{t("codex.modelName")}
|
||||||
@@ -4584,6 +4702,7 @@ export function AcpAgentSettings() {
|
|||||||
placeholder="gpt-5 / gpt-5-mini"
|
placeholder="gpt-5 / gpt-5-mini"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<label className="text-[11px] text-muted-foreground">
|
<label className="text-[11px] text-muted-foreground">
|
||||||
@@ -4679,10 +4798,18 @@ supports_websockets = true`}
|
|||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
const codexEnvText =
|
||||||
|
selectedDraft.codexAuthMode ===
|
||||||
|
"chatgpt_subscription"
|
||||||
|
? patchEnvText(selectedDraft.envText, {
|
||||||
|
OPENAI_API_KEY: "",
|
||||||
|
OPENAI_BASE_URL: "",
|
||||||
|
})
|
||||||
|
: selectedDraft.envText
|
||||||
persistPreferences(
|
persistPreferences(
|
||||||
selectedAgent.agent_type,
|
selectedAgent.agent_type,
|
||||||
selectedDraft.enabled,
|
selectedDraft.enabled,
|
||||||
selectedDraft.envText,
|
codexEnvText,
|
||||||
selectedDraft.configText,
|
selectedDraft.configText,
|
||||||
{
|
{
|
||||||
codexAuthJsonText:
|
codexAuthJsonText:
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "يدعم الإعداد السريع لعنوان API ومفتاح API واسم النموذج وجهد الاستدلال، مع المزامنة مع `auth.json` / `config.toml`.",
|
"configDescription": "يدعم الإعداد السريع لعنوان API ومفتاح API واسم النموذج وجهد الاستدلال، مع المزامنة مع `auth.json` / `config.toml`.",
|
||||||
|
"authMode": "طريقة المصادقة",
|
||||||
|
"chatgptSubscription": "اشتراك رسمي",
|
||||||
|
"chatgptSubscriptionHint": "تسجيل الدخول باشتراك ChatGPT الرسمي، لا حاجة لـ API Key",
|
||||||
|
"apiKeyHint": "الاتصال باستخدام API Key بخدمات OpenAI أو الخدمات المتوافقة",
|
||||||
"selectProvider": "اختر المزود",
|
"selectProvider": "اختر المزود",
|
||||||
"modelName": "اسم النموذج",
|
"modelName": "اسم النموذج",
|
||||||
"selectReasoningEffort": "اختر Reasoning Effort",
|
"selectReasoningEffort": "اختر Reasoning Effort",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "Unterstützt schnelle Konfiguration von API-URL, API-Key, Modellname und reasoning effort und synchronisiert mit `auth.json` / `config.toml`.",
|
"configDescription": "Unterstützt schnelle Konfiguration von API-URL, API-Key, Modellname und reasoning effort und synchronisiert mit `auth.json` / `config.toml`.",
|
||||||
|
"authMode": "Authentifizierungsmodus",
|
||||||
|
"chatgptSubscription": "Offizielles Abonnement",
|
||||||
|
"chatgptSubscriptionHint": "Mit offiziellem ChatGPT-Abonnement anmelden, kein API Key erforderlich",
|
||||||
|
"apiKeyHint": "Mit API Key zu OpenAI oder kompatiblen API-Diensten verbinden",
|
||||||
"selectProvider": "Provider auswählen",
|
"selectProvider": "Provider auswählen",
|
||||||
"modelName": "Modellname",
|
"modelName": "Modellname",
|
||||||
"selectReasoningEffort": "Reasoning Effort auswählen",
|
"selectReasoningEffort": "Reasoning Effort auswählen",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "Supports quick configuration for API URL, API Key, model name and reasoning effort, and syncs with `auth.json` / `config.toml`.",
|
"configDescription": "Supports quick configuration for API URL, API Key, model name and reasoning effort, and syncs with `auth.json` / `config.toml`.",
|
||||||
|
"authMode": "Auth Mode",
|
||||||
|
"chatgptSubscription": "Official Subscription",
|
||||||
|
"chatgptSubscriptionHint": "Log in with ChatGPT official subscription, no API Key required",
|
||||||
|
"apiKeyHint": "Connect using API Key to OpenAI or compatible API services",
|
||||||
"selectProvider": "Select Provider",
|
"selectProvider": "Select Provider",
|
||||||
"modelName": "Model Name",
|
"modelName": "Model Name",
|
||||||
"selectReasoningEffort": "Select Reasoning Effort",
|
"selectReasoningEffort": "Select Reasoning Effort",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "Admite configuración rápida de URL de API, API Key, nombre del modelo y reasoning effort, y sincroniza con `auth.json` / `config.toml`.",
|
"configDescription": "Admite configuración rápida de URL de API, API Key, nombre del modelo y reasoning effort, y sincroniza con `auth.json` / `config.toml`.",
|
||||||
|
"authMode": "Modo de Autenticación",
|
||||||
|
"chatgptSubscription": "Suscripción oficial",
|
||||||
|
"chatgptSubscriptionHint": "Iniciar sesión con suscripción oficial de ChatGPT, sin necesidad de API Key",
|
||||||
|
"apiKeyHint": "Conectar usando API Key a OpenAI o servicios API compatibles",
|
||||||
"selectProvider": "Seleccionar proveedor",
|
"selectProvider": "Seleccionar proveedor",
|
||||||
"modelName": "Nombre del modelo",
|
"modelName": "Nombre del modelo",
|
||||||
"selectReasoningEffort": "Seleccionar Reasoning Effort",
|
"selectReasoningEffort": "Seleccionar Reasoning Effort",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "Prend en charge la configuration rapide de l’URL API, de la clé API, du nom du modèle et du reasoning effort, avec synchronisation vers `auth.json` / `config.toml`.",
|
"configDescription": "Prend en charge la configuration rapide de l’URL API, de la clé API, du nom du modèle et du reasoning effort, avec synchronisation vers `auth.json` / `config.toml`.",
|
||||||
|
"authMode": "Mode d’authentification",
|
||||||
|
"chatgptSubscription": "Abonnement officiel",
|
||||||
|
"chatgptSubscriptionHint": "Connectez-vous avec l’abonnement officiel ChatGPT, pas besoin d’API Key",
|
||||||
|
"apiKeyHint": "Connectez-vous avec une API Key à OpenAI ou aux services API compatibles",
|
||||||
"selectProvider": "Sélectionner un provider",
|
"selectProvider": "Sélectionner un provider",
|
||||||
"modelName": "Nom du modèle",
|
"modelName": "Nom du modèle",
|
||||||
"selectReasoningEffort": "Sélectionner Reasoning Effort",
|
"selectReasoningEffort": "Sélectionner Reasoning Effort",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "API URL、API Key、モデル名、reasoning effort を素早く設定でき、`auth.json` / `config.toml` と同期します。",
|
"configDescription": "API URL、API Key、モデル名、reasoning effort を素早く設定でき、`auth.json` / `config.toml` と同期します。",
|
||||||
|
"authMode": "認証方式",
|
||||||
|
"chatgptSubscription": "公式サブスクリプション",
|
||||||
|
"chatgptSubscriptionHint": "ChatGPT 公式サブスクリプションでログイン、API Key 不要",
|
||||||
|
"apiKeyHint": "API Key で OpenAI または互換 API サービスに接続",
|
||||||
"selectProvider": "プロバイダーを選択",
|
"selectProvider": "プロバイダーを選択",
|
||||||
"modelName": "モデル名",
|
"modelName": "モデル名",
|
||||||
"selectReasoningEffort": "Reasoning Effort を選択",
|
"selectReasoningEffort": "Reasoning Effort を選択",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "API URL, API Key, 모델 이름, reasoning effort를 빠르게 설정하고 `auth.json` / `config.toml`과 동기화합니다.",
|
"configDescription": "API URL, API Key, 모델 이름, reasoning effort를 빠르게 설정하고 `auth.json` / `config.toml`과 동기화합니다.",
|
||||||
|
"authMode": "인증 방식",
|
||||||
|
"chatgptSubscription": "공식 구독",
|
||||||
|
"chatgptSubscriptionHint": "ChatGPT 공식 구독으로 로그인, API Key 불필요",
|
||||||
|
"apiKeyHint": "API Key로 OpenAI 또는 호환 API 서비스에 연결",
|
||||||
"selectProvider": "Provider 선택",
|
"selectProvider": "Provider 선택",
|
||||||
"modelName": "모델 이름",
|
"modelName": "모델 이름",
|
||||||
"selectReasoningEffort": "Reasoning Effort 선택",
|
"selectReasoningEffort": "Reasoning Effort 선택",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "Suporta configuração rápida de URL da API, API Key, nome do modelo e reasoning effort, com sincronização para `auth.json` / `config.toml`.",
|
"configDescription": "Suporta configuração rápida de URL da API, API Key, nome do modelo e reasoning effort, com sincronização para `auth.json` / `config.toml`.",
|
||||||
|
"authMode": "Modo de Autenticação",
|
||||||
|
"chatgptSubscription": "Assinatura oficial",
|
||||||
|
"chatgptSubscriptionHint": "Faça login com assinatura oficial do ChatGPT, sem necessidade de API Key",
|
||||||
|
"apiKeyHint": "Conecte-se usando API Key ao OpenAI ou serviços de API compatíveis",
|
||||||
"selectProvider": "Selecionar provedor",
|
"selectProvider": "Selecionar provedor",
|
||||||
"modelName": "Nome do modelo",
|
"modelName": "Nome do modelo",
|
||||||
"selectReasoningEffort": "Selecionar Reasoning Effort",
|
"selectReasoningEffort": "Selecionar Reasoning Effort",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "支持 API URL、API Key、模型名称、Reasoning Effort 快捷配置,并与 `auth.json` / `config.toml` 双向联动。",
|
"configDescription": "支持 API URL、API Key、模型名称、Reasoning Effort 快捷配置,并与 `auth.json` / `config.toml` 双向联动。",
|
||||||
|
"authMode": "认证方式",
|
||||||
|
"chatgptSubscription": "官网订阅",
|
||||||
|
"chatgptSubscriptionHint": "使用 ChatGPT 官网订阅登录,无需配置 API Key",
|
||||||
|
"apiKeyHint": "使用 API Key 连接 OpenAI 或兼容的 API 服务",
|
||||||
"selectProvider": "选择 Provider",
|
"selectProvider": "选择 Provider",
|
||||||
"modelName": "模型名称",
|
"modelName": "模型名称",
|
||||||
"selectReasoningEffort": "选择 Reasoning Effort",
|
"selectReasoningEffort": "选择 Reasoning Effort",
|
||||||
|
|||||||
@@ -406,6 +406,10 @@
|
|||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"configDescription": "支援 API URL、API Key、模型名稱、Reasoning Effort 快捷配置,並與 `auth.json` / `config.toml` 雙向聯動。",
|
"configDescription": "支援 API URL、API Key、模型名稱、Reasoning Effort 快捷配置,並與 `auth.json` / `config.toml` 雙向聯動。",
|
||||||
|
"authMode": "認證方式",
|
||||||
|
"chatgptSubscription": "官網訂閱",
|
||||||
|
"chatgptSubscriptionHint": "使用 ChatGPT 官網訂閱登入,無需配置 API Key",
|
||||||
|
"apiKeyHint": "使用 API Key 連接 OpenAI 或相容的 API 服務",
|
||||||
"selectProvider": "選擇 Provider",
|
"selectProvider": "選擇 Provider",
|
||||||
"modelName": "模型名稱",
|
"modelName": "模型名稱",
|
||||||
"selectReasoningEffort": "選擇 Reasoning Effort",
|
"selectReasoningEffort": "選擇 Reasoning Effort",
|
||||||
|
|||||||
Reference in New Issue
Block a user