fix(walkthrough): block unauthenticated providers with a friendly refusal

When the walkthrough small model resolves to a provider with no usable
login, readiness was still ready and generate returned a raw 500 message.
Refuse up front with no-provider-login and surface a blocker instead.

Closes openchamber/openchamber#2607

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-08-04 11:29:58 +00:00
co-authored by Serhii Dziupin
parent f47110c66f
commit abb396e080
22 changed files with 286 additions and 12 deletions
@@ -41,7 +41,8 @@ export const WalkthroughBlocker = ({
// Settings.
const canChooseModel = reason === 'context-too-small'
|| reason === 'structured-output-unsupported'
|| reason === 'output-exhausted';
|| reason === 'output-exhausted'
|| reason === 'no-provider-login';
useEffect(() => {
if (!canChooseModel || providers !== undefined) return;
@@ -100,6 +101,11 @@ export const WalkthroughBlocker = ({
const description = () => {
if (reason === 'no-model') return t('walkthrough.blocked.noModel.description');
if (reason === 'no-provider-login') {
return label
? t('walkthrough.blocked.noProviderLogin.description', { model: label })
: t('walkthrough.blocked.noProviderLogin.descriptionUnknownModel');
}
if (reason === 'empty-diff') return t('walkthrough.blocked.emptyDiff.description');
if (reason === 'only-generated') return t('walkthrough.blocked.onlyGenerated.description');
if (reason === 'output-exhausted') {
@@ -123,6 +129,7 @@ export const WalkthroughBlocker = ({
const title = () => {
if (reason === 'no-model') return t('walkthrough.blocked.noModel.title');
if (reason === 'no-provider-login') return t('walkthrough.blocked.noProviderLogin.title');
if (reason === 'empty-diff') return t('walkthrough.blocked.emptyDiff.title');
if (reason === 'only-generated') return t('walkthrough.blocked.onlyGenerated.title');
if (reason === 'output-exhausted') return t('walkthrough.blocked.outputExhausted.title');
@@ -406,6 +406,7 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
const blockedReason = entry.error?.code === 'context-too-small'
|| entry.error?.code === 'structured-output-unsupported'
|| entry.error?.code === 'no-model'
|| entry.error?.code === 'no-provider-login'
|| entry.error?.code === 'empty-diff'
|| entry.error?.code === 'only-generated'
|| entry.error?.code === 'output-exhausted'
+3
View File
@@ -2866,6 +2866,9 @@ export const dict = {
'walkthrough.importance.context': 'Kontext',
'walkthrough.blocked.noModel.title': 'Kein Modell ausgewählt',
'walkthrough.blocked.noModel.description': 'Wählen Sie zuerst ein Modell aus.',
'walkthrough.blocked.noProviderLogin.title': 'Dieser Anbieter ist nicht angemeldet',
'walkthrough.blocked.noProviderLogin.description': '{model} braucht eine Anmeldung bei seinem Anbieter. Melde dich an oder wähle ein Modell eines Anbieters, den du bereits nutzt.',
'walkthrough.blocked.noProviderLogin.descriptionUnknownModel': 'Das ausgewählte Modell braucht eine Anmeldung bei seinem Anbieter. Melde dich an oder wähle ein Modell eines Anbieters, den du bereits nutzt.',
'walkthrough.blocked.emptyDiff.title': 'Kein Diff vorhanden',
'walkthrough.blocked.emptyDiff.description': 'Es gibt keine Änderungen, die zusammengefasst werden können.',
'walkthrough.blocked.contextTooSmall.title': 'Kontext zu klein',
+3
View File
@@ -1147,6 +1147,9 @@ export const dict = {
'walkthrough.importance.context': 'Context',
'walkthrough.blocked.noModel.title': 'No small model available',
'walkthrough.blocked.noModel.description': 'Sign in to a model provider to generate a review.',
'walkthrough.blocked.noProviderLogin.title': 'This provider is not signed in',
'walkthrough.blocked.noProviderLogin.description': '{model} needs a login for its provider. Sign in, or choose a model from a provider you already use.',
'walkthrough.blocked.noProviderLogin.descriptionUnknownModel': 'The selected model needs a login for its provider. Sign in, or choose a model from a provider you already use.',
'walkthrough.blocked.emptyDiff.title': 'Nothing to review',
'walkthrough.blocked.emptyDiff.description': 'There are no changes in this scope yet.',
'walkthrough.blocked.contextTooSmall.title': 'This diff is too large for the current model',
+3
View File
@@ -1148,6 +1148,9 @@ export const dict: Record<I18nKey, string> = {
"walkthrough.importance.context": "Contexto",
"walkthrough.blocked.noModel.title": "No hay ningún modelo pequeño disponible",
"walkthrough.blocked.noModel.description": "Inicia sesión en un proveedor de modelos para generar una revisión.",
"walkthrough.blocked.noProviderLogin.title": "Este proveedor no tiene sesión iniciada",
"walkthrough.blocked.noProviderLogin.description": "{model} necesita un inicio de sesión en su proveedor. Inicia sesión o elige un modelo de un proveedor que ya uses.",
"walkthrough.blocked.noProviderLogin.descriptionUnknownModel": "El modelo seleccionado necesita un inicio de sesión en su proveedor. Inicia sesión o elige un modelo de un proveedor que ya uses.",
"walkthrough.blocked.emptyDiff.title": "Nada que revisar",
"walkthrough.blocked.emptyDiff.description": "Todavía no hay cambios en este ámbito.",
"walkthrough.blocked.contextTooSmall.title": "Este diff es demasiado grande para el modelo actual",
+3
View File
@@ -972,6 +972,9 @@ export const dict = {
'walkthrough.importance.context': 'Contexte',
'walkthrough.blocked.noModel.title': 'Aucun petit modèle disponible',
'walkthrough.blocked.noModel.description': 'Connectez-vous à un fournisseur de modèles pour générer une revue.',
'walkthrough.blocked.noProviderLogin.title': 'Ce fournisseur nest pas connecté',
'walkthrough.blocked.noProviderLogin.description': '{model} nécessite une connexion à son fournisseur. Connectez-vous, ou choisissez un modèle dun fournisseur que vous utilisez déjà.',
'walkthrough.blocked.noProviderLogin.descriptionUnknownModel': 'Le modèle sélectionné nécessite une connexion à son fournisseur. Connectez-vous, ou choisissez un modèle dun fournisseur que vous utilisez déjà.',
'walkthrough.blocked.emptyDiff.title': 'Rien à examiner',
'walkthrough.blocked.emptyDiff.description': 'Il ny a encore aucune modification dans cette portée.',
'walkthrough.blocked.contextTooSmall.title': 'Ce diff est trop volumineux pour le modèle actuel',
+3
View File
@@ -1144,6 +1144,9 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.importance.context': '補足',
'walkthrough.blocked.noModel.title': '利用できるスモールモデルがありません',
'walkthrough.blocked.noModel.description': 'レビューを生成するにはモデルプロバイダーにサインインしてください。',
'walkthrough.blocked.noProviderLogin.title': 'このプロバイダーにはサインインしていません',
'walkthrough.blocked.noProviderLogin.description': '{model} にはプロバイダーへのログインが必要です。サインインするか、すでに使っているプロバイダーのモデルを選んでください。',
'walkthrough.blocked.noProviderLogin.descriptionUnknownModel': '選択したモデルにはプロバイダーへのログインが必要です。サインインするか、すでに使っているプロバイダーのモデルを選んでください。',
'walkthrough.blocked.emptyDiff.title': 'レビュー対象がありません',
'walkthrough.blocked.emptyDiff.description': 'この範囲にはまだ変更がありません。',
'walkthrough.blocked.contextTooSmall.title': 'この差分は現在のモデルには大きすぎます',
+3
View File
@@ -1148,6 +1148,9 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.importance.context': '참고',
'walkthrough.blocked.noModel.title': '사용할 수 있는 스몰 모델이 없습니다',
'walkthrough.blocked.noModel.description': '리뷰를 생성하려면 모델 제공자에 로그인하세요.',
'walkthrough.blocked.noProviderLogin.title': '이 제공자에 로그인되어 있지 않습니다',
'walkthrough.blocked.noProviderLogin.description': '{model}을(를) 쓰려면 해당 제공자에 로그인해야 합니다. 로그인하거나, 이미 사용 중인 제공자의 모델을 선택하세요.',
'walkthrough.blocked.noProviderLogin.descriptionUnknownModel': '선택한 모델을 쓰려면 해당 제공자에 로그인해야 합니다. 로그인하거나, 이미 사용 중인 제공자의 모델을 선택하세요.',
'walkthrough.blocked.emptyDiff.title': '리뷰할 내용이 없습니다',
'walkthrough.blocked.emptyDiff.description': '이 범위에는 아직 변경 사항이 없습니다.',
'walkthrough.blocked.contextTooSmall.title': '이 diff는 현재 모델에 너무 큽니다',
+3
View File
@@ -1460,6 +1460,9 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.importance.context': 'Kontekst',
'walkthrough.blocked.noModel.title': 'Brak dostępnego małego modelu',
'walkthrough.blocked.noModel.description': 'Zaloguj się u dostawcy modeli, aby wygenerować przegląd.',
'walkthrough.blocked.noProviderLogin.title': 'Ten dostawca nie jest zalogowany',
'walkthrough.blocked.noProviderLogin.description': '{model} wymaga logowania u swojego dostawcy. Zaloguj się albo wybierz model u dostawcy, którego już używasz.',
'walkthrough.blocked.noProviderLogin.descriptionUnknownModel': 'Wybrany model wymaga logowania u swojego dostawcy. Zaloguj się albo wybierz model u dostawcy, którego już używasz.',
'walkthrough.blocked.emptyDiff.title': 'Nie ma czego przeglądać',
'walkthrough.blocked.emptyDiff.description': 'W tym zakresie nie ma jeszcze zmian.',
'walkthrough.blocked.contextTooSmall.title': 'Te różnice są za duże dla bieżącego modelu',
@@ -1148,6 +1148,9 @@ export const dict: Record<I18nKey, string> = {
"walkthrough.importance.context": "Contexto",
"walkthrough.blocked.noModel.title": "Nenhum modelo pequeno disponível",
"walkthrough.blocked.noModel.description": "Entre em um provedor de modelos para gerar uma revisão.",
"walkthrough.blocked.noProviderLogin.title": "Este provedor não está conectado",
"walkthrough.blocked.noProviderLogin.description": "{model} precisa de login no provedor. Entre na conta ou escolha um modelo de um provedor que você já usa.",
"walkthrough.blocked.noProviderLogin.descriptionUnknownModel": "O modelo selecionado precisa de login no provedor. Entre na conta ou escolha um modelo de um provedor que você já usa.",
"walkthrough.blocked.emptyDiff.title": "Nada para revisar",
"walkthrough.blocked.emptyDiff.description": "Ainda não há mudanças neste escopo.",
"walkthrough.blocked.contextTooSmall.title": "Este diff é grande demais para o modelo atual",
+3
View File
@@ -1148,6 +1148,9 @@ export const dict: Record<I18nKey, string> = {
"walkthrough.importance.context": "Контекст",
"walkthrough.blocked.noModel.title": "Немає доступної small model",
"walkthrough.blocked.noModel.description": "Увійдіть до провайдера моделей, щоб створити розбір.",
"walkthrough.blocked.noProviderLogin.title": "У цей провайдер не ввійшли",
"walkthrough.blocked.noProviderLogin.description": "{model} потребує входу в його провайдер. Увійдіть або виберіть модель у провайдера, яким ви вже користуєтесь.",
"walkthrough.blocked.noProviderLogin.descriptionUnknownModel": "Вибрана модель потребує входу в її провайдер. Увійдіть або виберіть модель у провайдера, яким ви вже користуєтесь.",
"walkthrough.blocked.emptyDiff.title": "Немає що оглядати",
"walkthrough.blocked.emptyDiff.description": "У цій області поки що немає змін.",
"walkthrough.blocked.contextTooSmall.title": "Цей diff завеликий для поточної моделі",
@@ -1148,6 +1148,9 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.importance.context': '背景',
'walkthrough.blocked.noModel.title': '没有可用的小模型',
'walkthrough.blocked.noModel.description': '请登录模型提供方后再生成评审。',
'walkthrough.blocked.noProviderLogin.title': '尚未登录此提供方',
'walkthrough.blocked.noProviderLogin.description': '{model} 需要登录其提供方。请先登录,或改选你已在使用的提供方中的模型。',
'walkthrough.blocked.noProviderLogin.descriptionUnknownModel': '所选模型需要登录其提供方。请先登录,或改选你已在使用的提供方中的模型。',
'walkthrough.blocked.emptyDiff.title': '没有可评审的内容',
'walkthrough.blocked.emptyDiff.description': '该范围内暂无改动。',
'walkthrough.blocked.contextTooSmall.title': '当前模型无法容纳这份差异',
@@ -1160,6 +1160,9 @@ export const dict: Record<I18nKey, string> = {
'walkthrough.importance.context': '背景',
'walkthrough.blocked.noModel.title': '沒有可用的小模型',
'walkthrough.blocked.noModel.description': '請先登入模型供應商再產生審閱。',
'walkthrough.blocked.noProviderLogin.title': '尚未登入此供應商',
'walkthrough.blocked.noProviderLogin.description': '{model} 需要登入其供應商。請先登入,或改選你已在使用的供應商中的模型。',
'walkthrough.blocked.noProviderLogin.descriptionUnknownModel': '所選模型需要登入其供應商。請先登入,或改選你已在使用的供應商中的模型。',
'walkthrough.blocked.emptyDiff.title': '沒有可審閱的內容',
'walkthrough.blocked.emptyDiff.description': '此範圍目前沒有變更。',
'walkthrough.blocked.contextTooSmall.title': '目前模型無法容納這份差異',
+1
View File
@@ -91,6 +91,7 @@ export type WalkthroughStage = 'collecting' | 'asking' | 'retrying' | 'assemblin
export type WalkthroughBlockedReason =
| 'no-model'
| 'no-provider-login'
| 'empty-diff'
| 'only-generated'
| 'context-too-small'