changes shopping
This commit is contained in:
1 parent
62ab5b2608
commit
f4bc93bc8a
17 files changed
+2290
-1025
No files matched your search
@@ -0,0 +1,145 @@
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
|
||||
interface PromptContext {
|
||||
name: string;
|
||||
description: string;
|
||||
scope: "global" | "server";
|
||||
server?: string | null;
|
||||
categories: string[];
|
||||
servers: string[];
|
||||
}
|
||||
|
||||
let schemaSummaryCache: string | null = null;
|
||||
|
||||
async function loadSchemaSummary(): Promise<string> {
|
||||
if (schemaSummaryCache) {
|
||||
return schemaSummaryCache;
|
||||
}
|
||||
|
||||
const schemaPath = path.join(process.cwd(), "prisma", "schema.prisma");
|
||||
let file: string;
|
||||
try {
|
||||
file = await fs.readFile(schemaPath, "utf-8");
|
||||
} catch (error) {
|
||||
console.warn("[item-prompt] Não foi possível ler schema.prisma:", error);
|
||||
schemaSummaryCache = "Schema indisponível.";
|
||||
return schemaSummaryCache;
|
||||
}
|
||||
|
||||
const modelRegex = /model\s+(\w+)\s*{([^}]*)}/g;
|
||||
const blocks: string[] = [];
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
while ((match = modelRegex.exec(file)) !== null) {
|
||||
const modelName = match[1];
|
||||
const body = match[2]
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line && !line.startsWith("//") && !line.startsWith("@@"))
|
||||
.join("\n");
|
||||
|
||||
blocks.push(`Model ${modelName} {\n${body}\n}`);
|
||||
}
|
||||
|
||||
schemaSummaryCache = blocks.join("\n\n");
|
||||
return schemaSummaryCache;
|
||||
}
|
||||
|
||||
const FORM_FIELD_SUMMARY = `
|
||||
Front-end fields (AdminItemForm):
|
||||
- name: string
|
||||
- category: string (utiliza categorias pré-carregadas)
|
||||
- rarity: string opcional
|
||||
- imageUrl / imageLocalPath: caminhos de imagem
|
||||
- level, weight, slots: numéricos opcionais
|
||||
- skill: string opcional
|
||||
- servers: lista de servidores (separados por vírgula)
|
||||
- tags: lista de tags (texto)
|
||||
- description: texto longo
|
||||
- dynamic metadata: campos variáveis definidos por categoria (servidores, atributos, etc)
|
||||
`.trim();
|
||||
|
||||
export async function buildItemPrompt(context: PromptContext, extraInstructions?: string) {
|
||||
const schemaSummary = await loadSchemaSummary();
|
||||
|
||||
const categoriesText =
|
||||
context.categories.length > 0
|
||||
? context.categories.map((category) => `- ${category}`).join("\n")
|
||||
: "- Nenhuma categoria cadastrada";
|
||||
|
||||
const serversText =
|
||||
context.servers.length > 0
|
||||
? context.servers.map((server) => `- ${server}`).join("\n")
|
||||
: "- Nenhum servidor cadastrado";
|
||||
|
||||
return `
|
||||
Você é um assistente que prepara payloads JSON para cadastro de itens no banco de dados do Tibia Trade.
|
||||
|
||||
INSTRUÇÕES IMPORTANTES:
|
||||
- Responda SOMENTE com JSON válido. Nenhum texto fora do JSON.
|
||||
- Se não tiver certeza, retorne null nos campos desconhecidos.
|
||||
- Utilize ao máximo a estrutura de tabelas e campos informada abaixo.
|
||||
|
||||
Contexto fornecido pelo usuário:
|
||||
- Nome: ${context.name}
|
||||
- Escopo: ${context.scope === "server" ? `servidor específico (${context.server ?? "não informado"})` : "global"}
|
||||
- Descrição original:
|
||||
"""
|
||||
${context.description}
|
||||
"""
|
||||
- Categorias disponíveis no painel:
|
||||
${categoriesText}
|
||||
- Servidores disponíveis no painel:
|
||||
${serversText}
|
||||
|
||||
Schema do banco (Prisma):
|
||||
${schemaSummary}
|
||||
|
||||
Campos principais do formulário no front:
|
||||
${FORM_FIELD_SUMMARY}
|
||||
|
||||
Formato obrigatório da resposta:
|
||||
{
|
||||
"table": "nome_da_tabela",
|
||||
"columns": {
|
||||
"name": "...",
|
||||
"description": "...",
|
||||
"rarity": "...",
|
||||
"metadata": {...},
|
||||
"outros_campos": ...
|
||||
}
|
||||
}
|
||||
|
||||
Consistência:
|
||||
- Escolha a tabela coerente com o escopo. Para global, use "items" ou equivalente.
|
||||
- Inclua sempre os campos básicos: name, description.
|
||||
- Aplique outros campos conforme a descrição (ex.: atributos, requisitos, bônus).
|
||||
- Se houver informações que encaixem em metadados dinâmicos, use um objeto "metadata".
|
||||
|
||||
${extraInstructions ?? ""}
|
||||
`.trim();
|
||||
}
|
||||
|
||||
export interface InlineImageData {
|
||||
mimeType: string;
|
||||
base64Data: string;
|
||||
}
|
||||
|
||||
export async function buildGeminiParts(prompt: string, images: InlineImageData[] = []) {
|
||||
const parts: Array<{ text?: string; inlineData?: { mimeType: string; data: string } }> = [
|
||||
{ text: prompt },
|
||||
];
|
||||
|
||||
images.slice(0, 2).forEach((image) => {
|
||||
parts.push({
|
||||
inlineData: {
|
||||
mimeType: image.mimeType,
|
||||
data: image.base64Data,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user