fix(captain/hermes-builder): namespace controller correto + botao iniciar
Bug: controller estava em enterprise/api/v1/accounts/captain/ com namespace Enterprise:: — convencao Chatwoot eh enterprise/app/controllers/api/v1/... direto, classe Api::V1::Accounts::Captain::HermesBuilderController. Sem namespace Enterprise::. 404 acontecia porque rotas registravam Captain:: sem prefixo Enterprise::. Move controller pro path correto. Remove diretorios vazios criados. UX: adiciona endpoint POST /start que envia comando-gatilho oculto pro Construtor comecar fluxo socratico — admin nao precisa digitar primeira mensagem. Vue mostra empty state com botao "Iniciar criacao" em vez de exigir mensagem inicial. i18n keys novas: START + EMPTY_STATE atualizado em pt_BR + en. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bfa06597f2
commit
041766b427
@ -14,6 +14,10 @@ class HermesBuilder extends ApiClient {
|
||||
return axios.post(this.url, { text });
|
||||
}
|
||||
|
||||
start() {
|
||||
return axios.post(`${this.url}/start`);
|
||||
}
|
||||
|
||||
reset() {
|
||||
return axios.delete(`${this.url}/reset`);
|
||||
}
|
||||
|
||||
@ -899,11 +899,12 @@
|
||||
"HEADER_DESCRIPTION": "Chat with the Builder to create a new Hermes agent. It asks questions and saves the spec as JSON for review at the end.",
|
||||
"RESET": "Clear conversation",
|
||||
"RESET_CONFIRM": "Clear current conversation with the Builder?",
|
||||
"EMPTY_STATE": "Type \"hello\" to start. The Builder will guide you.",
|
||||
"EMPTY_STATE": "Ready to create a new Hermes agent? Click \"Start creation\" and the Builder will guide you.",
|
||||
"PLACEHOLDER": "Type and press Enter to send (Shift+Enter for new line)",
|
||||
"SEND": "Send",
|
||||
"SESSION_LABEL": "Session:",
|
||||
"SEND_FAILED": "Send failed: {message}",
|
||||
"RESET_FAILED": "Failed to clear session."
|
||||
"RESET_FAILED": "Failed to clear session.",
|
||||
"START": "Start creation"
|
||||
}
|
||||
}
|
||||
@ -900,11 +900,12 @@
|
||||
"HEADER_DESCRIPTION": "Converse com o Construtor pra criar um novo agente Hermes. Ele faz perguntas e ao final salva a especificação em JSON pra revisão.",
|
||||
"RESET": "Limpar conversa",
|
||||
"RESET_CONFIRM": "Limpar conversa atual com o Construtor?",
|
||||
"EMPTY_STATE": "Mande \"olá\" pra começar. O Construtor vai te guiar.",
|
||||
"EMPTY_STATE": "Pronto pra criar um novo agente Hermes? Clica em \"Iniciar criação\" e o Construtor te guia.",
|
||||
"PLACEHOLDER": "Escreva e Enter pra enviar (Shift+Enter pula linha)",
|
||||
"SEND": "Enviar",
|
||||
"SESSION_LABEL": "Sessão:",
|
||||
"SEND_FAILED": "Erro ao enviar: {message}",
|
||||
"RESET_FAILED": "Falha ao limpar sessão."
|
||||
"RESET_FAILED": "Falha ao limpar sessão.",
|
||||
"START": "Iniciar criação"
|
||||
}
|
||||
}
|
||||
@ -88,6 +88,24 @@ const resetSession = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const startSession = async () => {
|
||||
if (sending.value) return;
|
||||
sending.value = true;
|
||||
try {
|
||||
await hermesBuilderApi.start();
|
||||
// Construtor vai responder com primeira pergunta via callback async
|
||||
// — polling pega em ~2s
|
||||
} catch (e) {
|
||||
useAlert(
|
||||
t('CAPTAIN_HERMES_BUILDER.SEND_FAILED', {
|
||||
message: e.response?.data?.error || e.message || 'unknown',
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
sending.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const formatTime = iso => {
|
||||
if (!iso) return '';
|
||||
const d = new Date(iso);
|
||||
@ -124,7 +142,10 @@ watch(messages, () => nextTick().then(scrollToBottom), { deep: true });
|
||||
|
||||
<section ref="scrollContainer" class="messages">
|
||||
<div v-if="!messages.length" class="empty-state">
|
||||
{{ t('CAPTAIN_HERMES_BUILDER.EMPTY_STATE') }}
|
||||
<p>{{ t('CAPTAIN_HERMES_BUILDER.EMPTY_STATE') }}</p>
|
||||
<Button variant="primary" :disabled="sending" @click="startSession">
|
||||
{{ t('CAPTAIN_HERMES_BUILDER.START') }}
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
v-for="(msg, idx) in messages"
|
||||
@ -216,6 +237,14 @@ watch(messages, () => nextTick().then(scrollToBottom), { deep: true });
|
||||
color: var(--color-text-light, #9ca3af);
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.msg {
|
||||
|
||||
@ -60,6 +60,7 @@ Rails.application.routes.draw do
|
||||
namespace :captain do
|
||||
resources :hermes_builder, only: [:index, :create] do
|
||||
collection do
|
||||
post :start
|
||||
delete :reset
|
||||
end
|
||||
end
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
# 5. UI faz GET /messages a cada 2s (polling) e renderiza
|
||||
#
|
||||
# Sessão é por account+user (1 admin → 1 sessão de builder por vez).
|
||||
class Enterprise::Api::V1::Accounts::Captain::HermesBuilderController < Api::V1::Accounts::BaseController
|
||||
class Api::V1::Accounts::Captain::HermesBuilderController < Api::V1::Accounts::BaseController
|
||||
before_action :authorize_admin
|
||||
|
||||
def index
|
||||
@ -29,6 +29,21 @@ class Enterprise::Api::V1::Accounts::Captain::HermesBuilderController < Api::V1:
|
||||
render json: { error: "Falha ao contatar Construtor: #{e.message}" }, status: :bad_gateway
|
||||
end
|
||||
|
||||
# Inicia sessão limpa enviando comando-gatilho oculto pro Construtor pra
|
||||
# ele começar o fluxo socrático de criação. UI chama este endpoint
|
||||
# quando admin clica "Iniciar" — sem ter que digitar primeira msg.
|
||||
def start
|
||||
HermesBuilder::Storage.clear(session_key)
|
||||
HermesBuilder::Dispatcher.send_to_construtor(
|
||||
session_id: session_id,
|
||||
message: '__START__ Inicie o fluxo de criação de novo agente Hermes. Comece pela primeira pergunta do Bloco 1 (nome do agente).'
|
||||
)
|
||||
render json: { ok: true, session_id: session_id }, status: :accepted
|
||||
rescue HermesBuilder::Dispatcher::DispatchError => e
|
||||
Rails.logger.error("[HermesBuilder#start] dispatch failed: #{e.message}")
|
||||
render json: { error: "Falha ao contatar Construtor: #{e.message}" }, status: :bad_gateway
|
||||
end
|
||||
|
||||
def reset
|
||||
HermesBuilder::Storage.clear(session_key)
|
||||
render json: { ok: true }
|
||||
Loading…
Reference in New Issue
Block a user