feat(codex-link): persist direct subscription and AITURK connection modes
Server CI and Windows package / verify (push) Successful in 2m54s
Server CI and Windows package / windows-package (push) Successful in 7m17s

This commit is contained in:
yilsem committed 2026-10-13 19:56:40 +03:00
1 parent 049c4d1338
commit 8f53b090f7
11 files changed
+188 -17

No files matched your search

@@ -12,6 +12,7 @@ vi.mock('@/store/notifications', () => ({ notifyError }))
const RUNNING: CodexLinkStatus = {
enabled: true,
mod: 'aiturk',
codexFound: true,
venvReady: true,
foreign: false,
@@ -198,3 +199,18 @@ describe('Codex Link settings', () => {
expect(get).not.toHaveBeenCalled()
})
})
describe('connection mode controls', () => {
it('sends the mode and renders the saved direct preference', async () => {
get.mockResolvedValue({ ...RUNNING, mod: 'dogrudan' })
set.mockResolvedValue({ ...RUNNING, mod: 'aiturk' })
renderPage()
const direct = await screen.findByRole('radio', { name: 'Doğrudan (önerilen): abonelik modelleri köprüden bağımsız' })
await waitFor(() => expect((direct as HTMLInputElement).checked).toBe(true))
fireEvent.click(screen.getByRole('radio', { name: 'AITURK: combolar Codex listesinde, tüm modeller köprüden' }))
await waitFor(() => expect(set).toHaveBeenCalledWith({ mod: 'aiturk' }))
await waitFor(() => expect((direct as HTMLInputElement).checked).toBe(false))
expect(screen.getByText("Codex'i yeniden başlatın")).toBeTruthy()
})
})
@@ -57,7 +57,7 @@ export function codexLinkStatusLines(status: CodexLinkStatus, copy: CodexLinkCop
if (status.ideDurum === 'anahtar-yok') {
lines.push({ id: 'ide', text: copy.signIn, tone: 'warn' })
} else if (status.ideDurum === 'tamam' && status.ideModel !== null) {
} else if (status.mod === 'aiturk' && status.ideDurum === 'tamam' && status.ideModel !== null) {
lines.push({ id: 'ide', text: copy.models(status.ideModel), tone: 'ok' })
}
@@ -170,6 +170,27 @@ export function CodexLinkSettings() {
title={copy.title}
/>
<ListRow
title={copy.modeTitle}
below={
<fieldset disabled={!status || busy !== null} className="grid gap-2 py-2">
{(['dogrudan', 'aiturk'] as const).map(mod => (
<label key={mod} className="flex min-h-11 cursor-pointer items-center gap-2">
<input
type="radio"
name="codex-link-mode"
value={mod}
checked={(status?.mod ?? 'dogrudan') === mod}
onChange={() => void change({ mod }, 'toggle')}
/>
<span>{mod === 'dogrudan' ? copy.directMode : copy.aiturkMode}</span>
</label>
))}
<p className="text-(--ui-text-tertiary)">{copy.modeRestartNote}</p>
</fieldset>
}
/>
{!status && !loadFailed && <ListRowSkeleton wide />}
{loadFailed && !status && (