mirror of
https://github.com/melgarafael/DeskcommCRM.git
synced 2026-10-02 09:34:46 +08:00
fix(kit): a chave de IA deixa de ser obrigatória — instala e cadastra depois pela tela
`docs/deploy-selfhost` promete, na lista de campos do `.env`: "deixe vazio e
cadastre a chave depois em /app/ai/credentials — fica cifrada no banco". O
runtime concorda: em `lib/env.ts` as três chaves são
`z.string().optional().default("")`, e faltar todas gera apenas um `warn`, não
erro. O instalador, não — exigia uma chave que PASSASSE numa chamada real ao
provedor, e sem ela a instalação morria na Fase 2/4. Na prática, não havia
caminho para subir o produto sem antes abrir conta num provedor de IA, mesmo o
produto subindo perfeitamente sem ela (issue #670).
O campo do provedor ESCOLHIDO passa a ser `opcional` — o mesmo mecanismo que o
`CAMPO_OPENAI_EXTRA` (áudio e base de conhecimento) já usava. Quem digita uma
chave continua com a validação na hora, chamada real incluída; o que mudou é
que pular deixou de ser erro.
E pular não pode terminar em silêncio: a tela final ganha `pendencia_da_ia`,
que nomeia o provedor escolhido e o caminho exato de cadastro (IA ›
Credenciais, cifrado no banco) — na tela que a pessoa lê inteira, não no meio
de um log de dez minutos. A pendência só aparece quando NENHUMA credencial de
ambiente existe (nem o AI Gateway, que tem precedência na resolução do chat):
quem já tem a chave não vê aviso nenhum.
═══ O TESTE ═══
`hostgator-setup-kit/test-validators.sh` ganha um cenário que roda o
`install.sh --yes` REAL (VPS dublê) com um `.env` sem NENHUMA chave de IA e
exige a tela final, o `.env` inteiro e o aviso com o caminho de volta. O
controle oposto, com a chave presente, exige que o aviso NÃO apareça — sem ele,
um `pendencia_da_ia` que imprimisse sempre passaria e viraria ruído em toda
instalação. Com o `opcional` removido do campo, o instalador morre em "Falta
ANTHROPIC_API_KEY (modo --yes exige .env preenchido)" e é a primeira asserção
do cenário que fica vermelha.
Ref: #670
This commit is contained in:
@@ -109,8 +109,9 @@ Se precisar do modo sem perguntas (`--yes` com `.env` pronto), duas armadilhas m
|
||||
- escreva `SENTRY_DSN=off` se a pessoa **não** quer enviar relatórios de erro. Com o `.env` copiado
|
||||
do exemplo, a pergunta de telemetria não aparece e a instalação sai enviando (issue #668).
|
||||
|
||||
Também medido (issue #670): o instalador **exige** uma chave de IA válida, mesmo que a documentação
|
||||
diga que dá para deixar vazia e cadastrar depois. Enquanto isso não muda, peça a chave antes.
|
||||
A chave de IA é **opcional** (issue #670, resolvida): dá para instalar sem conta em provedor de IA
|
||||
e cadastrar depois em IA › Credenciais — a tela final da instalação lembra quem pulou, com o
|
||||
caminho. Se a pessoa já tiver a chave em mãos, ótimo: ela é validada na hora.
|
||||
|
||||
### 6. Depois do "Instalação concluída!"
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ a do provedor escolhido. No modo `--yes`, sem escolha, o padrão é Anthropic.
|
||||
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | anon key (Settings › API) | lê o papel dentro da chave e testa |
|
||||
| `SUPABASE_SERVICE_ROLE_KEY` | service_role key — **secreta** | idem, contra a admin API |
|
||||
| `SUPABASE_DB_URL` | connection string **Session pooler, modo URI** (Settings › Database) — secreta | recusa `[YOUR-PASSWORD]`, recusa host `db.<ref>.supabase.co` (Direct, só IPv6), confere que é o mesmo projeto da URL, e **abre uma conexão de verdade** |
|
||||
| chave do provedor de IA | `ANTHROPIC_API_KEY` (`sk-ant-`), `OPENROUTER_API_KEY` (`sk-or-`) ou `OPENAI_API_KEY` (`sk-`) | prefixo + chamada real ao provedor (uma chave sem crédito passa; "recusada" é 401) |
|
||||
| `OWNER_EMAIL` | e-mail do primeiro admin (o dono) | formato |
|
||||
| `OWNER_PASSWORD` | senha do dono — secreta | mínimo 8 caracteres |
|
||||
|
||||
@@ -33,6 +32,7 @@ projeto** e preenche as quatro sozinho (`hostgator-setup-kit/supabase-provision.
|
||||
| campo | se pular |
|
||||
|---|---|
|
||||
| `SUPABASE_ACCESS_TOKEN` (token pessoal, **não fica salvo**) | projeto criado à mão (4 cópias); os e-mails de acesso saem no modelo em inglês do Supabase e o **Site URL fica `localhost:3000`** — "esqueci minha senha", confirmação de cadastro e aceite de convite chegam com link quebrado até alguém configurar Authentication › URL Configuration (`Site URL = https://DOMÍNIO`, `Redirect = https://DOMÍNIO/auth/confirm`). O instalador imprime essa pendência no fim; `hostgator-setup-kit/marca-emails.sh` resolve depois, com o token |
|
||||
| **chave do provedor escolhido** (`ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY` ou `OPENAI_API_KEY`) | o agente **não responde** até alguém cadastrar a chave em **IA › Credenciais** — cifrada no banco, sem mexer no `.env` e sem reiniciar. A tela final da instalação lembra o caminho. Quem digita uma chave tem ela validada na hora (prefixo + chamada real ao provedor: uma chave sem crédito passa; "recusada" é 401) |
|
||||
| `OPENAI_API_KEY` extra (quando a IA não é OpenAI) | o agente **não ouve áudio** nem indexa/consulta a base de conhecimento até alguém cadastrar a chave da OpenAI em IA › Credenciais (não precisa mexer no `.env`) |
|
||||
| `APP_NAME` (padrão `DeskcommCRM`) | é a **semente** do nome; depois muda em Configurações › Marca |
|
||||
| `APP_LOCALE` (1 = Português, 2 = Español) | grava o idioma da organização |
|
||||
|
||||
@@ -109,9 +109,11 @@ o baseline de hoje deduplica sozinho ao atualizar (`update.sh`), depois reinicie
|
||||
|
||||
## Instalação e atualização
|
||||
|
||||
**Instalador exige chave de IA "válida" e para** (issue #670): a documentação diz que dá para
|
||||
deixar vazia e cadastrar depois, mas o instalador não aceita. Enquanto isso não muda, consiga a
|
||||
chave antes (OpenRouter é o caminho mais rápido de criar).
|
||||
**Instalador exigia chave de IA "válida" e parava** (issue #670, **resolvida**): a documentação
|
||||
dizia que dava para deixar vazia e cadastrar depois, mas o instalador não aceitava — era preciso
|
||||
conseguir a chave antes (OpenRouter é o caminho mais rápido de criar). Agora a chave é opcional:
|
||||
dá para instalar sem ela e cadastrar depois em IA › Credenciais; a tela final lembra quem pulou.
|
||||
Vale para quem atualizar para a versão seguinte.
|
||||
|
||||
**Telemetria ligada sem ninguém escolher** (issue #668): acontece quando o `.env` foi copiado do
|
||||
exemplo. Para desligar: `SENTRY_DSN=off` no `.env` e `docker compose -f docker-compose.prod.yml up -d`.
|
||||
|
||||
@@ -5,7 +5,7 @@ Todos vivem em `hostgator-setup-kit/` e rodam **de dentro da VPS**, a partir da
|
||||
|
||||
| script | quando a pessoa diz | o que faz | como ler a saída |
|
||||
|---|---|---|---|
|
||||
| `install.sh` | "instala", "troca a configuração", "coloquei um dado errado" | instala do zero **ou** re-roda sobre o que existe (idempotente): retoma respostas, corrige pelo número da conferência, re-aplica o schema, sobe tudo | termina em "Instalação concluída!" com a pendência de e-mails (se sem token). `--yes` = sem perguntas, exige `.env` completo |
|
||||
| `install.sh` | "instala", "troca a configuração", "coloquei um dado errado" | instala do zero **ou** re-roda sobre o que existe (idempotente): retoma respostas, corrige pelo número da conferência, re-aplica o schema, sobe tudo | termina em "Instalação concluída!" com a pendência de e-mails (se sem token). `--yes` = sem perguntas, exige `.env` preenchido — a chave de IA pode ficar vazia |
|
||||
| `healthcheck.sh` | "está tudo no ar?", "o site caiu?" | lista os contêineres, chama `/api/v1/health` **de dentro** do contêiner do app, confere o cron do agente e o log dele | `✓ app saudável` se o JSON traz `"status":"ok"`; `⚠` nomeia o subsistema (supabase/redis/waha) degradado |
|
||||
| `diagnostico.sh` | "o agente parou de melhorar", "a versão está solta", "atualizei e nada mudou" | **só lê** (nada de escrever, puxar ou reiniciar): diz se a instalação foi afetada pelo worker que nunca era atualizado. Roda até avulso: `curl -fsSL https://raw.githubusercontent.com/melgarafael/DeskcommCRM/main/hostgator-setup-kit/diagnostico.sh \| bash` | código de saída 1 = afetada; explica o conserto |
|
||||
| `update.sh` | "atualiza", "tem versão nova?" | confere se há versão nova (senão sai na hora), **faz backup antes**, puxa o código, re-aplica o `baseline.sql` (idempotente e auto-curativo; muitos "já existe" são esperados), puxa as imagens da tag, confere a saúde | código 3 = recusou e **nada foi tocado** (ex.: sem internet para confirmar o que é mais novo, ou a versão pedida é anterior). `--force` volta no tempo de propósito; `--to <tag>` fixa uma versão; `--skip-backup` não recomendado |
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
impacto: nada_mudou
|
||||
secao: corrigido
|
||||
titulo: A instalação deixa de exigir chave de IA — dá para cadastrar depois pela tela
|
||||
---
|
||||
|
||||
O instalador exigia uma chave de IA que **passasse numa chamada real** ao
|
||||
provedor: sem ela, a instalação morria na Fase 2/4. Só que a documentação
|
||||
(`docs/deploy-selfhost`) sempre prometeu outra coisa — *"deixe vazio e cadastre
|
||||
a chave depois"* —, e o próprio sistema concorda com a doc: faltar todas as
|
||||
chaves é um aviso, não um erro.
|
||||
|
||||
Agora o campo é opcional de verdade: dá para instalar sem abrir conta em
|
||||
provedor de IA e cadastrar a chave depois pela tela, em **IA › Credenciais**,
|
||||
onde ela fica cifrada no banco. A tela final da instalação lembra quem pulou o
|
||||
passo, com o caminho exato.
|
||||
|
||||
Quem digita uma chave continua com ela validada na hora — o que mudou é que
|
||||
pular deixou de ser erro.
|
||||
@@ -109,8 +109,9 @@ Se precisar do modo sem perguntas (`--yes` com `.env` pronto), duas armadilhas m
|
||||
- escreva `SENTRY_DSN=off` se a pessoa **não** quer enviar relatórios de erro. Com o `.env` copiado
|
||||
do exemplo, a pergunta de telemetria não aparece e a instalação sai enviando (issue #668).
|
||||
|
||||
Também medido (issue #670): o instalador **exige** uma chave de IA válida, mesmo que a documentação
|
||||
diga que dá para deixar vazia e cadastrar depois. Enquanto isso não muda, peça a chave antes.
|
||||
A chave de IA é **opcional** (issue #670, resolvida): dá para instalar sem conta em provedor de IA
|
||||
e cadastrar depois em IA › Credenciais — a tela final da instalação lembra quem pulou, com o
|
||||
caminho. Se a pessoa já tiver a chave em mãos, ótimo: ela é validada na hora.
|
||||
|
||||
### 6. Depois do "Instalação concluída!"
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ a do provedor escolhido. No modo `--yes`, sem escolha, o padrão é Anthropic.
|
||||
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | anon key (Settings › API) | lê o papel dentro da chave e testa |
|
||||
| `SUPABASE_SERVICE_ROLE_KEY` | service_role key — **secreta** | idem, contra a admin API |
|
||||
| `SUPABASE_DB_URL` | connection string **Session pooler, modo URI** (Settings › Database) — secreta | recusa `[YOUR-PASSWORD]`, recusa host `db.<ref>.supabase.co` (Direct, só IPv6), confere que é o mesmo projeto da URL, e **abre uma conexão de verdade** |
|
||||
| chave do provedor de IA | `ANTHROPIC_API_KEY` (`sk-ant-`), `OPENROUTER_API_KEY` (`sk-or-`) ou `OPENAI_API_KEY` (`sk-`) | prefixo + chamada real ao provedor (uma chave sem crédito passa; "recusada" é 401) |
|
||||
| `OWNER_EMAIL` | e-mail do primeiro admin (o dono) | formato |
|
||||
| `OWNER_PASSWORD` | senha do dono — secreta | mínimo 8 caracteres |
|
||||
|
||||
@@ -33,6 +32,7 @@ projeto** e preenche as quatro sozinho (`hostgator-setup-kit/supabase-provision.
|
||||
| campo | se pular |
|
||||
|---|---|
|
||||
| `SUPABASE_ACCESS_TOKEN` (token pessoal, **não fica salvo**) | projeto criado à mão (4 cópias); os e-mails de acesso saem no modelo em inglês do Supabase e o **Site URL fica `localhost:3000`** — "esqueci minha senha", confirmação de cadastro e aceite de convite chegam com link quebrado até alguém configurar Authentication › URL Configuration (`Site URL = https://DOMÍNIO`, `Redirect = https://DOMÍNIO/auth/confirm`). O instalador imprime essa pendência no fim; `hostgator-setup-kit/marca-emails.sh` resolve depois, com o token |
|
||||
| **chave do provedor escolhido** (`ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY` ou `OPENAI_API_KEY`) | o agente **não responde** até alguém cadastrar a chave em **IA › Credenciais** — cifrada no banco, sem mexer no `.env` e sem reiniciar. A tela final da instalação lembra o caminho. Quem digita uma chave tem ela validada na hora (prefixo + chamada real ao provedor: uma chave sem crédito passa; "recusada" é 401) |
|
||||
| `OPENAI_API_KEY` extra (quando a IA não é OpenAI) | o agente **não ouve áudio** nem indexa/consulta a base de conhecimento até alguém cadastrar a chave da OpenAI em IA › Credenciais (não precisa mexer no `.env`) |
|
||||
| `APP_NAME` (padrão `DeskcommCRM`) | é a **semente** do nome; depois muda em Configurações › Marca |
|
||||
| `APP_LOCALE` (1 = Português, 2 = Español) | grava o idioma da organização |
|
||||
|
||||
@@ -109,9 +109,11 @@ o baseline de hoje deduplica sozinho ao atualizar (`update.sh`), depois reinicie
|
||||
|
||||
## Instalação e atualização
|
||||
|
||||
**Instalador exige chave de IA "válida" e para** (issue #670): a documentação diz que dá para
|
||||
deixar vazia e cadastrar depois, mas o instalador não aceita. Enquanto isso não muda, consiga a
|
||||
chave antes (OpenRouter é o caminho mais rápido de criar).
|
||||
**Instalador exigia chave de IA "válida" e parava** (issue #670, **resolvida**): a documentação
|
||||
dizia que dava para deixar vazia e cadastrar depois, mas o instalador não aceitava — era preciso
|
||||
conseguir a chave antes (OpenRouter é o caminho mais rápido de criar). Agora a chave é opcional:
|
||||
dá para instalar sem ela e cadastrar depois em IA › Credenciais; a tela final lembra quem pulou.
|
||||
Vale para quem atualizar para a versão seguinte.
|
||||
|
||||
**Telemetria ligada sem ninguém escolher** (issue #668): acontece quando o `.env` foi copiado do
|
||||
exemplo. Para desligar: `SENTRY_DSN=off` no `.env` e `docker compose -f docker-compose.prod.yml up -d`.
|
||||
|
||||
@@ -5,7 +5,7 @@ Todos vivem em `hostgator-setup-kit/` e rodam **de dentro da VPS**, a partir da
|
||||
|
||||
| script | quando a pessoa diz | o que faz | como ler a saída |
|
||||
|---|---|---|---|
|
||||
| `install.sh` | "instala", "troca a configuração", "coloquei um dado errado" | instala do zero **ou** re-roda sobre o que existe (idempotente): retoma respostas, corrige pelo número da conferência, re-aplica o schema, sobe tudo | termina em "Instalação concluída!" com a pendência de e-mails (se sem token). `--yes` = sem perguntas, exige `.env` completo |
|
||||
| `install.sh` | "instala", "troca a configuração", "coloquei um dado errado" | instala do zero **ou** re-roda sobre o que existe (idempotente): retoma respostas, corrige pelo número da conferência, re-aplica o schema, sobe tudo | termina em "Instalação concluída!" com a pendência de e-mails (se sem token). `--yes` = sem perguntas, exige `.env` preenchido — a chave de IA pode ficar vazia |
|
||||
| `healthcheck.sh` | "está tudo no ar?", "o site caiu?" | lista os contêineres, chama `/api/v1/health` **de dentro** do contêiner do app, confere o cron do agente e o log dele | `✓ app saudável` se o JSON traz `"status":"ok"`; `⚠` nomeia o subsistema (supabase/redis/waha) degradado |
|
||||
| `diagnostico.sh` | "o agente parou de melhorar", "a versão está solta", "atualizei e nada mudou" | **só lê** (nada de escrever, puxar ou reiniciar): diz se a instalação foi afetada pelo worker que nunca era atualizado. Roda até avulso: `curl -fsSL https://raw.githubusercontent.com/melgarafael/DeskcommCRM/main/hostgator-setup-kit/diagnostico.sh \| bash` | código de saída 1 = afetada; explica o conserto |
|
||||
| `update.sh` | "atualiza", "tem versão nova?" | confere se há versão nova (senão sai na hora), **faz backup antes**, puxa o código, re-aplica o `baseline.sql` (idempotente e auto-curativo; muitos "já existe" são esperados), puxa as imagens da tag, confere a saúde | código 3 = recusou e **nada foi tocado** (ex.: sem internet para confirmar o que é mais novo, ou a versão pedida é anterior). `--force` volta no tempo de propósito; `--to <tag>` fixa uma versão; `--skip-backup` não recomendado |
|
||||
|
||||
@@ -135,7 +135,9 @@ NEXT_PUBLIC_ADMIN_URL=https://crm.seudominio.com.br
|
||||
# -----------------------------------------------------------------------------
|
||||
# 4) IA (Anthropic via AI Gateway) — paga por uso, chave sua
|
||||
# -----------------------------------------------------------------------------
|
||||
# ou ANTHROPIC_API_KEY abaixo
|
||||
# ou ANTHROPIC_API_KEY abaixo. As chaves de IA são OPCIONAIS: o CRM sobe sem
|
||||
# nenhuma delas e você cadastra a sua depois pela tela, em IA › Credenciais
|
||||
# (fica cifrada no banco). Sem chave, o agente de IA não responde.
|
||||
AI_GATEWAY_API_KEY=
|
||||
ANTHROPIC_API_KEY=
|
||||
|
||||
|
||||
@@ -47,7 +47,8 @@ discordarem, vale o guia; quando o guia e `install.sh` discordarem, vale o insta
|
||||
- **Qual IA vai atender** — o instalador pergunta antes das chaves: OpenRouter (uma chave, muitos
|
||||
modelos, o mais simples), Anthropic (Claude, padrão do Enter) ou OpenAI. Se não for OpenAI, ele
|
||||
pede a chave da OpenAI à parte e **opcional** (áudio e base de conhecimento — dá para cadastrar
|
||||
depois pela tela).
|
||||
depois pela tela). A chave do provedor principal **também é opcional**: dá para instalar sem ela
|
||||
e cadastrar depois pela tela (IA › Credenciais).
|
||||
- O **e-mail e a senha** que ela quer para entrar no CRM (o primeiro admin).
|
||||
|
||||
## Passo a passo que você conduz
|
||||
|
||||
@@ -42,8 +42,8 @@ bash install.sh
|
||||
> contrato desse modo. Se preferir instalar por conta própria, responda `n` e rode
|
||||
> `curl -fsSL https://get.docker.com | sh` antes.
|
||||
|
||||
O instalador pergunta o que precisa (domínio, chaves do Supabase e da Anthropic,
|
||||
e-mail/senha do admin), gera o resto e sobe tudo.
|
||||
O instalador pergunta o que precisa (domínio, chaves do Supabase, provedor de IA
|
||||
— a chave pode ficar para depois —, e-mail/senha do admin), gera o resto e sobe tudo.
|
||||
|
||||
> Modo não-interativo: copie `.env.hostgator.example` (do repositório) para `.env`,
|
||||
> preencha, e rode `bash install.sh --yes`.
|
||||
@@ -85,7 +85,7 @@ Owner/Admin. Não dá para hospedar vários clientes numa conta só.
|
||||
| VPS (Docker) | HostGator — VPS com Docker (n8n/OpenClaw/GatorClaw). Outras hospedagens com Docker também servem — se a sua já tiver proxy próprio nas portas 80/443, [veja aqui](#vps-que-já-vem-com-proxy-próprio-hostinger-coolify-dokploy) |
|
||||
| Domínio | Registro de domínio (aponte um A-record pro IP do VPS) |
|
||||
| Banco de dados | Conta grátis no [supabase.com](https://supabase.com) (3 chaves + connection string) |
|
||||
| IA | Chave da [Anthropic](https://console.anthropic.com) |
|
||||
| IA | Chave da [Anthropic](https://console.anthropic.com) — opcional: dá para instalar sem ela e cadastrar depois pela tela (IA › Credenciais) |
|
||||
| WhatsApp | Seu número — conectado por QR code no onboarding |
|
||||
| Token do Supabase (opcional) | [supabase.com/dashboard/account/tokens](https://supabase.com/dashboard/account/tokens) — com ele o instalador configura sozinho os links dos e-mails de acesso. **Ele não fica salvo:** é usado uma vez e some com o processo |
|
||||
|
||||
|
||||
@@ -1161,10 +1161,19 @@ escolher_provedor
|
||||
|
||||
# O campo da chave do provedor ESCOLHIDO — e só dele. Pedir as três faria a
|
||||
# pessoa achar que precisa das três.
|
||||
#
|
||||
# O campo é `opcional` (issue #670). `docs/deploy-selfhost` promete que dá para
|
||||
# "deixar vazio e cadastrar a chave depois", e o runtime concorda (`lib/env.ts`
|
||||
# trata as três chaves como opcionais; faltar todas é `warn`, não erro) — mas o
|
||||
# instalador exigia uma chave que PASSASSE numa chamada real, e não havia
|
||||
# caminho para subir o produto sem antes abrir conta num provedor de IA. Quem
|
||||
# pula instala, e o caminho de volta sai na tela final (`pendencia_da_ia`, no
|
||||
# fecho). O validador continua valendo para quem digita uma chave — o que
|
||||
# mudou é que pular deixou de ser erro.
|
||||
case "$AI_PROVIDER" in
|
||||
openrouter) CAMPO_IA="OPENROUTER_API_KEY|Chave da OpenRouter — a IA que atende (openrouter.ai/keys)||v_openrouter|secret|";;
|
||||
openai) CAMPO_IA="OPENAI_API_KEY|Chave da OpenAI — a IA que atende (platform.openai.com/api-keys)||v_openai|secret|";;
|
||||
*) CAMPO_IA="ANTHROPIC_API_KEY|Chave da Anthropic — a IA que atende (console.anthropic.com)||v_anthropic|secret|";;
|
||||
openrouter) CAMPO_IA="OPENROUTER_API_KEY|Chave da OpenRouter — a IA que atende (openrouter.ai/keys; Enter pula: dá para cadastrar depois pela tela, em IA › Credenciais)||v_openrouter|secret|opcional";;
|
||||
openai) CAMPO_IA="OPENAI_API_KEY|Chave da OpenAI — a IA que atende (platform.openai.com/api-keys; Enter pula: dá para cadastrar depois pela tela, em IA › Credenciais)||v_openai|secret|opcional";;
|
||||
*) CAMPO_IA="ANTHROPIC_API_KEY|Chave da Anthropic — a IA que atende (console.anthropic.com; Enter pula: dá para cadastrar depois pela tela, em IA › Credenciais)||v_anthropic|secret|opcional";;
|
||||
esac
|
||||
|
||||
# A chave da OpenAI é pedida À PARTE quando ela NÃO é o provedor de conversa,
|
||||
@@ -1927,6 +1936,42 @@ $(sed 's/^/ /' "$PENDENCIA_EMAIL")
|
||||
PEND
|
||||
}
|
||||
|
||||
# ── A pendência da IA, quando a chave ficou para depois ─────────────────────
|
||||
# A #670 tornou o campo da chave `opcional`: antes o instalador morria sem uma
|
||||
# chave que passasse numa chamada real, contra a doc e contra o runtime.
|
||||
# Instalar sem chave é legítimo; o que não pode é a pessoa terminar sem saber
|
||||
# que a IA ainda não atende e ONDE cadastrar depois. Este bloco repete o
|
||||
# caminho na TELA FINAL, que é a única tela que a pessoa lê inteira.
|
||||
#
|
||||
# Critério: nenhuma credencial DE AMBIENTE preenchida — nem a do provedor
|
||||
# escolhido, nem o AI Gateway (que tem precedência na resolução do chat, ver
|
||||
# `.env.hostgator.example`). Credencial cadastrada pela tela (banco) não dá
|
||||
# para ver daqui; quem já cadastrou reconhece o aviso e ignora.
|
||||
pendencia_da_ia() {
|
||||
local chave="" rotulo=""
|
||||
case "${AI_PROVIDER:-anthropic}" in
|
||||
openrouter) chave="${OPENROUTER_API_KEY:-}"; rotulo="OpenRouter" ;;
|
||||
openai) chave="${OPENAI_API_KEY:-}"; rotulo="OpenAI" ;;
|
||||
*) chave="${ANTHROPIC_API_KEY:-}"; rotulo="Anthropic" ;;
|
||||
esac
|
||||
[ -n "$chave" ] && return 0
|
||||
[ -n "${AI_GATEWAY_API_KEY:-}" ] && return 0
|
||||
|
||||
cat <<PEND
|
||||
|
||||
$(c_ylw " ─── A IA ainda não atende — falta cadastrar a chave ───")
|
||||
|
||||
Você deixou a chave de IA para depois, e o CRM está no ar sem ela. O que
|
||||
ainda não funciona é o agente: ele responde quando uma credencial existir.
|
||||
|
||||
Quando tiver a chave da ${rotulo}, cadastre em:
|
||||
|
||||
IA › Credenciais
|
||||
|
||||
A chave fica CIFRADA no banco — não precisa mexer no .env nem reiniciar nada.
|
||||
PEND
|
||||
}
|
||||
|
||||
PENDENCIA_EMAIL="$(mktemp)"
|
||||
PENDENCIA_ARQUIVO="$PENDENCIA_EMAIL" \
|
||||
SUPABASE_ACCESS_TOKEN="${SUPABASE_ACCESS_TOKEN:-}" \
|
||||
@@ -2139,6 +2184,7 @@ $(c_grn " Instalação concluída!")
|
||||
$(c_grn "═══════════════════════════════════════════════════════")
|
||||
|
||||
$(pendencia_dos_emails)
|
||||
$(pendencia_da_ia)
|
||||
1. Acesse: https://${DOMAIN}
|
||||
(o SSL leva ~1min pra emitir no primeiro acesso)
|
||||
|
||||
|
||||
@@ -1912,6 +1912,106 @@ provedor_ok "OpenAI: instala e o .env sai inteiro" OPENAI_API_KEY sk-te
|
||||
provedor_ok "Anthropic: instala e o .env sai inteiro" ANTHROPIC_API_KEY sk-ant-teste anthropic
|
||||
|
||||
|
||||
echo "integração: instalar SEM chave de IA — o caminho que a documentação prometia (issue #670)"
|
||||
# A issue #670: `docs/deploy-selfhost` promete "deixe vazio e cadastre a chave
|
||||
# depois em IA › Credenciais", e o runtime concorda — `lib/env.ts` trata as três
|
||||
# chaves como opcionais, e faltar todas é `warn`, não erro. O instalador, não:
|
||||
# exigia uma chave que PASSASSE numa chamada real ao provedor, e a instalação
|
||||
# inteira parava sem ela. Não havia caminho para subir o produto sem antes abrir
|
||||
# conta num provedor de IA.
|
||||
#
|
||||
# O que este cenário mede é o caminho inteiro, com o .env de quem não tem conta
|
||||
# em provedor nenhum: BASE_ENV sem as três chaves e sem o AI Gateway (que tem
|
||||
# precedência na resolução do chat). Com o campo de volta a obrigatório, o
|
||||
# `ask_one` morre em "Falta ANTHROPIC_API_KEY (modo --yes exige .env
|
||||
# preenchido)" na coleta de configuração, e é a PRIMEIRA asserção que fica
|
||||
# vermelha.
|
||||
TMP_SEM_IA="$(mktemp -d)"
|
||||
(
|
||||
montar_vps "$TMP_SEM_IA" "crmsemia" <<'STUB'
|
||||
#!/usr/bin/env bash
|
||||
printf '%s\n' "$*" >> "$DOCKER_LOG"
|
||||
case "$1" in
|
||||
compose) case "$*" in *" exec "*) printf 'healthy\n{"data":{"status":"healthy"}}\n' ;; esac; exit 0 ;;
|
||||
esac
|
||||
exit 0
|
||||
STUB
|
||||
mkdir -p "$VPS_PROJ/supabase"; : > "$VPS_PROJ/supabase/baseline.sql"
|
||||
|
||||
# O .env da entrevista pulada: BASE_ENV sem NENHUMA chave de IA.
|
||||
printf '%s\n' "$BASE_ENV" \
|
||||
| grep -vE '^(ANTHROPIC|OPENROUTER|OPENAI)_API_KEY=|^AI_GATEWAY_API_KEY=' > "$VPS_PROJ/.env"
|
||||
|
||||
rodar_sem_ia() {
|
||||
: > "$VPS_LOG"
|
||||
(cd "$VPS_PROJ" && env PATH="$VPS_RAIZ/bin:$PATH" DOCKER_LOG="$VPS_LOG" \
|
||||
CRONTAB_SANDBOX="$CRONTAB_SANDBOX" SUPABASE_ACCESS_TOKEN= \
|
||||
bash "$VPS_RAIZ/install.sh" --yes 2>&1 || true) | sed -E 's/\x1b\[[0-9;]*m//g'
|
||||
}
|
||||
|
||||
saida="$(rodar_sem_ia)"
|
||||
|
||||
# A marca do defeito: com o campo obrigatório, o instalador morre aqui.
|
||||
if printf '%s' "$saida" | grep -q 'exige .env preenchido'; then
|
||||
printf ' ✗ o instalador ainda morre sem chave de IA — o campo do provedor não é `opcional`\n'
|
||||
printf ' %s\n' "$(printf '%s' "$saida" | grep -m1 'exige .env preenchido')"
|
||||
exit 1
|
||||
fi
|
||||
# CONTROLE POSITIVO: "não morreu" só significa alguma coisa se a instalação
|
||||
# chegou ao fim; sem esta âncora, um install que parasse antes passaria.
|
||||
if ! printf '%s' "$saida" | grep -q 'Instalação concluída'; then
|
||||
printf ' ✗ a instalação sem chave de IA não chegou à tela final — cenário inconclusivo, não verde\n'
|
||||
printf ' última linha: %s\n' "$(printf '%s' "$saida" | grep -v '^$' | tail -1)"
|
||||
exit 1
|
||||
fi
|
||||
# O .env sai INTEIRO: sem chave, a última linha do bloco continua presente —
|
||||
# a mesma régua dos cenários de provedor acima.
|
||||
if ! grep -qE '^OWNER_PASSWORD="' "$VPS_PROJ/.env"; then
|
||||
printf ' ✗ o .env saiu pela metade na instalação sem chave de IA\n'
|
||||
printf ' últimas chaves gravadas: %s\n' \
|
||||
"$(grep -oE '^[A-Z_]+=' "$VPS_PROJ/.env" | tail -3 | tr '\n' ' ')"
|
||||
exit 1
|
||||
fi
|
||||
# A chave que ninguém respondeu sai DECLARADA e vazia — a mesma distinção
|
||||
# entre ausente e declarada-e-vazia que o caso do APP_ACCENT_HEX guarda.
|
||||
if ! grep -qE '^ANTHROPIC_API_KEY=' "$VPS_PROJ/.env"; then
|
||||
printf ' ✗ ANTHROPIC_API_KEY nem apareceu no .env (esperado: declarada e vazia)\n'; exit 1
|
||||
fi
|
||||
if [ -n "$(valor_no_env "$VPS_PROJ/.env" ANTHROPIC_API_KEY)" ]; then
|
||||
printf ' ✗ ANTHROPIC_API_KEY veio com valor [%s] — ninguém digitou nada\n' \
|
||||
"$(valor_no_env "$VPS_PROJ/.env" ANTHROPIC_API_KEY)"; exit 1
|
||||
fi
|
||||
# A TELA FINAL lembra o caminho de volta. A medição é no RABO (depois de
|
||||
# "Instalação concluída"), como no caso do Site URL: é a única tela que a
|
||||
# pessoa lê inteira, e um aviso no meio do log de dez minutos não conta.
|
||||
rabo="${saida##*Instalação concluída}"
|
||||
if ! printf '%s' "$rabo" | grep -q 'A IA ainda não atende'; then
|
||||
printf ' ✗ a tela final não avisa que a IA ainda não atende\n'; exit 1
|
||||
fi
|
||||
if ! printf '%s' "$rabo" | grep -q 'IA › Credenciais'; then
|
||||
printf ' ✗ o aviso da tela final não diz ONDE cadastrar a chave (IA › Credenciais)\n'; exit 1
|
||||
fi
|
||||
printf ' ✓ sem chave de IA: instala, .env inteiro, e a tela final dá o caminho de volta\n'
|
||||
|
||||
# ── O outro lado: com a chave, o aviso NÃO aparece ────────────────────────
|
||||
# Sem isto, um `pendencia_da_ia` que imprimisse sempre passaria no caso acima
|
||||
# e viraria ruído em toda instalação que já tem chave — inclusive nas rodadas
|
||||
# de `provedor_ok` logo acima.
|
||||
printf '%s\n' "$BASE_ENV" > "$VPS_PROJ/.env"
|
||||
saida="$(rodar_sem_ia)"
|
||||
if ! printf '%s' "$saida" | grep -q 'Instalação concluída'; then
|
||||
printf ' ✗ (controle) a segunda rodada, com chave, não chegou à tela final — cenário inconclusivo\n'
|
||||
exit 1
|
||||
fi
|
||||
rabo="${saida##*Instalação concluída}"
|
||||
if printf '%s' "$rabo" | grep -q 'A IA ainda não atende'; then
|
||||
printf ' ✗ com a chave presente, a tela final avisou que falta chave de IA\n'; exit 1
|
||||
fi
|
||||
printf ' ✓ com a chave presente, o lembrete não aparece (o aviso não é ruído permanente)\n'
|
||||
) || fail=1
|
||||
rm -rf "$TMP_SEM_IA"
|
||||
|
||||
|
||||
echo "integração: instalação NOVA numa VPS com Traefik em modo host"
|
||||
# O install.sh roda contra um `docker` dublê que imita a Hostinger: 80/443
|
||||
# ocupadas, NINGUÉM publicando, um Traefik em `--network host`, e a rede do
|
||||
|
||||
Reference in New Issue
Block a user