feat(codex-link): persist direct subscription and AITURK connection modes
This commit is contained in:
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 && (
|
||||
|
||||
@@ -6,6 +6,10 @@ import { useI18n } from './context'
|
||||
// AITURK-distribution strings (see ./aiturk): Turkish for `tr`, English for
|
||||
// every other locale.
|
||||
const en = {
|
||||
modeTitle: 'Connection mode',
|
||||
directMode: 'Direct (recommended): subscription models independent of the bridge',
|
||||
aiturkMode: 'AITURK: combos in the Codex list, all models through the bridge',
|
||||
modeRestartNote: 'Restart Codex.',
|
||||
nav: 'Codex Link',
|
||||
title: 'Codex Link',
|
||||
description:
|
||||
@@ -39,6 +43,10 @@ const en = {
|
||||
}
|
||||
|
||||
const tr: typeof en = {
|
||||
modeTitle: 'Bağlantı modu',
|
||||
directMode: 'Doğrudan (önerilen): abonelik modelleri köprüden bağımsız',
|
||||
aiturkMode: 'AITURK: combolar Codex listesinde, tüm modeller köprüden',
|
||||
modeRestartNote: "Codex'i yeniden başlatın",
|
||||
nav: 'Codex Bağlama',
|
||||
title: 'Codex Bağlama',
|
||||
description:
|
||||
@@ -71,10 +79,45 @@ const tr: typeof en = {
|
||||
restartNote: "Codex'te yeni modelleri görmek için Codex'i yeniden açın."
|
||||
}
|
||||
|
||||
const modeTranslations = {
|
||||
zh: {
|
||||
modeTitle: '连接模式',
|
||||
directMode: '直接(推荐):订阅模型独立于桥接',
|
||||
aiturkMode: 'AITURK:组合显示在 Codex 列表中,所有模型通过桥接',
|
||||
modeRestartNote: '请重启 Codex。'
|
||||
},
|
||||
'zh-hant': {
|
||||
modeTitle: '連線模式',
|
||||
directMode: '直接(建議):訂閱模型獨立於橋接',
|
||||
aiturkMode: 'AITURK:組合顯示在 Codex 清單中,所有模型透過橋接',
|
||||
modeRestartNote: '請重新啟動 Codex。'
|
||||
},
|
||||
ja: {
|
||||
modeTitle: '接続モード',
|
||||
directMode: '直接(推奨):サブスクリプションモデルはブリッジから独立',
|
||||
aiturkMode: 'AITURK:Codex の一覧にコンボを表示、すべてのモデルはブリッジ経由',
|
||||
modeRestartNote: 'Codex を再起動してください。'
|
||||
},
|
||||
ar: {
|
||||
modeTitle: 'وضع الاتصال',
|
||||
directMode: 'مباشر (موصى به): نماذج الاشتراك مستقلة عن الجسر',
|
||||
aiturkMode: 'AITURK: مجموعات النماذج في قائمة Codex، وجميع النماذج عبر الجسر',
|
||||
modeRestartNote: 'أعد تشغيل Codex.'
|
||||
},
|
||||
ru: {
|
||||
modeTitle: 'Режим подключения',
|
||||
directMode: 'Напрямую (рекомендуется): модели подписки независимы от моста',
|
||||
aiturkMode: 'AITURK: комбинации в списке Codex, все модели через мост',
|
||||
modeRestartNote: 'Перезапустите Codex.'
|
||||
}
|
||||
}
|
||||
|
||||
export type CodexLinkCopy = typeof en
|
||||
|
||||
export function useCodexLinkCopy(): CodexLinkCopy {
|
||||
const { locale } = useI18n()
|
||||
|
||||
return locale === 'tr' ? tr : en
|
||||
if (locale === 'tr') return tr
|
||||
if (locale === 'en') return en
|
||||
return { ...en, ...modeTranslations[locale] }
|
||||
}
|
||||
Reference in new issue
Block a user