atualizacoes codex
This commit is contained in:
+18
-5
@@ -135,21 +135,34 @@ class AreasService {
|
||||
throw new Error("ID da área é obrigatório");
|
||||
}
|
||||
|
||||
const idEnc = encodeURIComponent(id.trim());
|
||||
const body: EditarAreaBody = {
|
||||
nome: nome.trim(),
|
||||
descricao: (descricao ?? "").trim(),
|
||||
};
|
||||
|
||||
const response = await apiService.put<EditarAreaSuccessResponse | EditarAreaErrorResponse>(
|
||||
`https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/codex/parecer/area/${id}`,
|
||||
/** Mesmo prefixo de webhook que o fluxo n8n (UUID) usado nos endpoints de "parecer/areas". */
|
||||
const url = `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/parecer/area/${idEnc}`;
|
||||
|
||||
const response = await apiService.put<
|
||||
EditarAreaSuccessResponse | EditarAreaErrorResponse | (EditarAreaSuccessResponse | EditarAreaErrorResponse)[]
|
||||
>(
|
||||
url,
|
||||
body
|
||||
);
|
||||
|
||||
if (response.data.success === false) {
|
||||
throw new Error((response.data as EditarAreaErrorResponse).message ?? "Erro ao editar área");
|
||||
const raw = response.data;
|
||||
const data = Array.isArray(raw) ? raw[0] : raw;
|
||||
|
||||
if (!data || typeof data !== "object" || !("success" in data)) {
|
||||
throw new Error("Resposta inválida ao editar área");
|
||||
}
|
||||
|
||||
return response.data as EditarAreaSuccessResponse;
|
||||
if (data.success === false) {
|
||||
throw new Error((data as EditarAreaErrorResponse).message ?? "Erro ao editar área");
|
||||
}
|
||||
|
||||
return data as EditarAreaSuccessResponse;
|
||||
}
|
||||
|
||||
async deletar(id: string): Promise<DeletarAreaSuccessResponse> {
|
||||
|
||||
@@ -180,6 +180,89 @@ class AudioGenerationService {
|
||||
this.toApiError(error, 'Erro ao deletar áudio');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Baixa o arquivo no navegador (sem navegar para a URL).
|
||||
* Usa blob local + <a download> — necessário porque links cross-origin ignoram `download` e abrem a URL.
|
||||
*/
|
||||
async downloadAudioFile(audioUrl: string, filename?: string): Promise<void> {
|
||||
const urlTrim = audioUrl?.trim();
|
||||
if (!urlTrim) {
|
||||
throw new Error('URL do áudio inválida');
|
||||
}
|
||||
|
||||
const safeName = (filename || `audio_${Date.now()}.mp3`).replace(/[/\\?%*:|"<>]/g, '_');
|
||||
|
||||
let sameOrigin = false;
|
||||
try {
|
||||
const u = new URL(urlTrim, typeof window !== 'undefined' ? window.location.href : undefined);
|
||||
sameOrigin = typeof window !== 'undefined' && u.origin === window.location.origin;
|
||||
} catch {
|
||||
sameOrigin = false;
|
||||
}
|
||||
|
||||
const fetchBlob = async (): Promise<Blob> => {
|
||||
const response = await fetch(urlTrim, {
|
||||
mode: 'cors',
|
||||
credentials: sameOrigin ? 'include' : 'omit',
|
||||
cache: 'no-store',
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Falha ao baixar (HTTP ${response.status})`);
|
||||
}
|
||||
return response.blob();
|
||||
};
|
||||
|
||||
const xhrBlob = (): Promise<Blob> =>
|
||||
new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', urlTrim, true);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.onload = () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject(new Error(`Falha ao baixar (HTTP ${xhr.status})`));
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => reject(new Error('Falha de rede ao baixar o áudio'));
|
||||
xhr.send();
|
||||
});
|
||||
|
||||
let blob: Blob;
|
||||
try {
|
||||
blob = await fetchBlob();
|
||||
} catch (e1) {
|
||||
try {
|
||||
blob = await xhrBlob();
|
||||
} catch (e2) {
|
||||
console.error('downloadAudioFile:', e1, e2);
|
||||
throw new Error(
|
||||
'Não foi possível baixar o áudio. Se o arquivo estiver em outro domínio, é preciso CORS liberando GET para esta origem.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const needsMimeFix =
|
||||
!blob.type ||
|
||||
blob.type === 'application/octet-stream' ||
|
||||
blob.type === 'text/html';
|
||||
const typedBlob = needsMimeFix ? new Blob([blob], { type: 'audio/mpeg' }) : blob;
|
||||
|
||||
const objectUrl = URL.createObjectURL(typedBlob);
|
||||
try {
|
||||
const a = document.createElement('a');
|
||||
a.href = objectUrl;
|
||||
a.download = safeName.endsWith('.mp3') ? safeName : `${safeName}.mp3`;
|
||||
a.style.display = 'none';
|
||||
a.rel = 'noopener';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
} finally {
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const audioGenerationService = new AudioGenerationService();
|
||||
|
||||
+22
-12
@@ -151,25 +151,35 @@ class PromptsService {
|
||||
throw new Error("ID do prompt é obrigatório");
|
||||
}
|
||||
|
||||
const response = await apiService.put<EditarPromptSuccessResponse | EditarPromptErrorResponse>(
|
||||
`https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/codex/parecer/prompt/editar/${id}`,
|
||||
{
|
||||
titulo: (body.titulo ?? "").trim(),
|
||||
descricao: (body.descricao ?? "").trim(),
|
||||
area_id: body.area_id.trim(),
|
||||
conteudo: (body.conteudo ?? "").trim(),
|
||||
}
|
||||
);
|
||||
const idEnc = encodeURIComponent(id.trim());
|
||||
/** Mesmo prefixo de webhook n8n usado em edição de área (`areas.editar`). */
|
||||
const url = `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/parecer/prompt/${idEnc}`;
|
||||
|
||||
if (response.data.success === false) {
|
||||
const err = response.data as EditarPromptErrorResponse;
|
||||
const response = await apiService.put<
|
||||
EditarPromptSuccessResponse | EditarPromptErrorResponse | (EditarPromptSuccessResponse | EditarPromptErrorResponse)[]
|
||||
>(url, {
|
||||
titulo: (body.titulo ?? "").trim(),
|
||||
descricao: (body.descricao ?? "").trim(),
|
||||
area_id: body.area_id.trim(),
|
||||
conteudo: (body.conteudo ?? "").trim(),
|
||||
});
|
||||
|
||||
const raw = response.data;
|
||||
const data = Array.isArray(raw) ? raw[0] : raw;
|
||||
|
||||
if (!data || typeof data !== "object" || !("success" in data)) {
|
||||
throw new Error("Resposta inválida ao editar prompt");
|
||||
}
|
||||
|
||||
if (data.success === false) {
|
||||
const err = data as EditarPromptErrorResponse;
|
||||
const msg = err.missing_fields?.length
|
||||
? `Preencha: ${err.missing_fields.join(", ")}`
|
||||
: "Erro ao editar prompt.";
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
return response.data as EditarPromptSuccessResponse;
|
||||
return data as EditarPromptSuccessResponse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user