feat(aiturk): one-click sign-in for AITURK IDE (1.0.0-beta.14)
The onboarding and provider settings get a Sign in button: the IDE shows a short code, opens the turkservis.online approval page, and after approval saves the TurkServis provider itself and hands a separate member key to the AITURK CLI over stdin (aiturk login --key-stdin --keep-other-account). Keys never reach the renderer, logs, process arguments or URLs. Pasting an API key remains as the fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B8ppceaR5s6cvMnm7uGRnf
This commit is contained in:
1 parent
fe0a45a84f
commit
25d8c18c10
13 files changed
+1938
-15
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { AiturkLogin } from '@/components/aiturk-login'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
import { Input } from '@/components/ui/input'
|
||||
@@ -80,7 +81,10 @@ function toPayload(form: EndpointForm, models?: string[]): CustomEndpointUpdate
|
||||
|
||||
export function CustomEndpointsSettings({ onConfigSaved, onMainModelChanged }: CustomEndpointsSettingsProps) {
|
||||
const { t } = useI18n()
|
||||
const c = useAiturkCopy().custom
|
||||
const aiturkCopy = useAiturkCopy()
|
||||
const c = aiturkCopy.custom
|
||||
const loginCopy = aiturkCopy.login
|
||||
const loginLabel = loginCopy.settingsSignIn
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [testing, setTesting] = useState(false)
|
||||
@@ -129,6 +133,31 @@ export function CustomEndpointsSettings({ onConfigSaved, onMainModelChanged }: C
|
||||
}
|
||||
}, [])
|
||||
|
||||
// One-click sign-in saved the TurkServis provider in the main process:
|
||||
// reload the list and tell the app its default model changed.
|
||||
async function handleAiturkConnected() {
|
||||
try {
|
||||
const data = await getCustomEndpoints()
|
||||
setEndpoints(data.endpoints)
|
||||
const current = data.endpoints.find(endpoint => endpoint.id === 'turkservis')
|
||||
|
||||
if (current) {
|
||||
setForm(formFromEndpoint(current))
|
||||
setDiscoveredModels(current.models)
|
||||
|
||||
if (current.is_current) {
|
||||
onMainModelChanged?.(current.id, current.model)
|
||||
}
|
||||
}
|
||||
|
||||
triggerHaptic('success')
|
||||
onConfigSaved?.()
|
||||
notify({ kind: 'success', message: loginCopy.connected })
|
||||
} catch (err) {
|
||||
notifyError(err, c.loadFailed)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
try {
|
||||
setSaving(true)
|
||||
@@ -298,10 +327,13 @@ export function CustomEndpointsSettings({ onConfigSaved, onMainModelChanged }: C
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<Button className="mb-3" onClick={() => {
|
||||
setForm({ ...EMPTY_FORM, name: 'TurkServis · AITURK', baseUrl: AITURK_API_BASE_URL })
|
||||
setDiscoveredModels([])
|
||||
}} variant="outline">{c.preset}</Button>
|
||||
<div className="mb-3 flex flex-wrap items-start gap-2">
|
||||
<AiturkLogin label={loginLabel} onConnected={handleAiturkConnected} />
|
||||
<Button onClick={() => {
|
||||
setForm({ ...EMPTY_FORM, name: 'TurkServis · AITURK', baseUrl: AITURK_API_BASE_URL })
|
||||
setDiscoveredModels([])
|
||||
}} variant="outline">{c.preset}</Button>
|
||||
</div>
|
||||
<SectionHeading icon={Plus} title={form.id ? c.edit : c.add} />
|
||||
<div className="grid gap-3 rounded-md border border-border/50 p-3">
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
|
||||
Reference in new issue
Block a user