caarleexx commited on
Commit
b13d2b2
Β·
verified Β·
1 Parent(s): 8907ec6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +152 -225
app.py CHANGED
@@ -1,6 +1,6 @@
1
  # ╔════════════════════════════════════════════════════════════════════════════╗
2
- # β•‘ PIPELINE v29: PLANEJADOR AUTO-AGENTE | SUPERA PARADOXO MEHON β•‘
3
- # β•‘ 1ΒΊ: PLANEJA β†’ 2ΒΊ-N: EXECUTA β†’ N+1: CONVERGE COM HISTΓ“RICO β•‘
4
  # β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
5
 
6
  import os
@@ -11,324 +11,251 @@ from datetime import datetime
11
  import gradio as gr
12
  import google.generativeai as genai
13
 
14
- # ==================== 1. CONFIGURAÇÃO GLOBAL ====================
15
- api_key = os.getenv("GOOGLE_API_KEY")
16
  if api_key:
17
  genai.configure(api_key=api_key)
18
  model_flash = genai.GenerativeModel("gemini-flash-latest")
19
  model_pro = genai.GenerativeModel("gemini-pro-latest")
20
  else:
21
  model_flash = model_pro = None
22
- print("⚠️ GOOGLE_API_KEY não encontrada. Configure via export GOOGLE_API_KEY=...")
23
 
24
- ARQUIVO_HISTORY = "history_v29.json"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- # ==================== 2. UTILIDADES DE PERSISTÊNCIA ====================
27
  def carregar_history():
28
- """Carrega histΓ³rico persistente"""
29
  try:
30
  with open(ARQUIVO_HISTORY, "r", encoding="utf-8") as f:
31
  return json.load(f)
32
- except:
33
  return []
34
 
35
  def salvar_history(history):
36
- """Salva histΓ³rico automaticamente"""
37
  try:
38
  with open(ARQUIVO_HISTORY, "w", encoding="utf-8") as f:
39
  json.dump(history, f, ensure_ascii=False, indent=2)
40
  return True
41
- except:
42
  return False
43
 
44
  def ler_anexo(arquivo):
45
- """Processa arquivos anexados"""
46
- if not arquivo: return ""
47
  try:
48
  with open(arquivo.name, "r", encoding="utf-8") as f:
49
- nome = os.path.basename(arquivo.name)
50
- return f"\n\nπŸ“Ž ANEXO: {nome}\n{f.read()}\n[FIM ANEXO]\n"
51
- except:
52
- return "❌ Erro lendo anexo"
53
-
54
- def exportar_chat(history):
55
- """Gera TXT para download"""
56
- if not history: return ""
57
- timestamp = datetime.now().strftime('%Y-%m-%d_%H%M%S')
58
- chat_txt = f"MEHON v29 EXPORT - {timestamp}\n\n"
59
- for i, msg in enumerate(history, 1):
60
- role = "πŸ‘€ USUÁRIO" if i % 2 == 1 else "πŸ€– MEHON"
61
- chat_txt += f"{role}:\n{msg}\n\n{'-'*80}\n\n"
62
- return chat_txt
63
 
64
- # ==================== 3. AGENTE PLANEJADOR (SUPERA MEHON) ====================
65
- def gerar_plano_auto(input_completo, history_contexto):
66
- """AGENTE 1: CRIA PLANO DINΓ‚MICO baseando-se em histΓ³rico + input"""
67
  if not model_pro:
68
  return None, "❌ Sem API_KEY"
69
 
70
- # Compacta histΓ³rico (ΓΊltimas 5 trocas, 200 chars cada)
71
- history_resumo = ""
72
- if len(history_contexto) >= 2:
73
- history_resumo = "\n".join([
74
- f"πŸ‘€: {h[0][:200]}... | πŸ€–: {h[1][:200]}..."
75
- for h in history_contexto[-5:]
76
- ])
77
 
78
- prompt_planejador = f"""πŸš€ PLANEJADOR AUTO-AGENTE v29 - SUPERA PARADOXO MEHON
79
-
80
- CONTEXTO HISTΓ“RICO DO USUÁRIO:
81
  {history_resumo}
82
 
83
- INPUT ATUAL: {input_completo}
84
-
85
- ---
86
 
87
- CRIE PLANO ESTRUTURADO DE 3-6 AGENTES para resolver PERFEITAMENTE:
88
 
89
- πŸ“‹ FORMATO OBRIGATΓ“RIO (JSON VÁLIDO):
90
  [
91
- {{"nome": "NomeClaro", "missao": "InstruΓ§Γ£oPrecisade200palavras", "modelo": "flash", "tipo_saida": "texto"}},
92
- ...
93
  ]
94
 
95
- βœ… CRITΓ‰RIOS DO PLANO:
96
- β€’ DECOMPONHA: problema β†’ anΓ‘lise β†’ cenΓ‘rios β†’ validaΓ§Γ£o β†’ sΓ­ntese
97
- β€’ IDENTIFIQUE ambiguidades/possibilidades do input
98
- β€’ PERSONALIZE com histΓ³rico do usuΓ‘rio
99
- β€’ ÚLTIMO agente SEMPRE gera saΓ­da FINAL pro usuΓ‘rio
100
- β€’ Evite resposta direta - USE CADEIA DE PENSAMENTO
101
-
102
- EXEMPLO PLANO BOM:
103
- [
104
- {{"nome": "AnalisadorInput", "missao": "Identifique elementos principais, ambiguidades e contexto", "modelo": "flash", "tipo_saida": "json"}},
105
- {{"nome": "ExploradorCenΓ‘rios", "missao": "Liste 3-5 cenΓ‘rios possΓ­veis com probabilidades", "modelo": "pro", "tipo_saida": "json"}},
106
- {{"nome": "SintetizadorFinal", "missao": "Converja tudo em resposta ΓΊnica e acionΓ‘vel", "modelo": "pro", "tipo_saida": "texto"}}
107
- ]
108
-
109
- APENAS JSON VÁLIDO - SEM TEXTO EXTRA!"""
110
 
111
  try:
112
- resp = model_pro.generate_content(prompt_planejador, temperature=0.3)
113
- plano_raw = resp.text.strip().replace('``````','').replace('json','')
114
  plano = json.loads(plano_raw)
115
 
116
- # Valida estrutura mΓ­nima
117
- if not isinstance(plano, list) or len(plano) < 2:
118
- return None, "❌ Plano invÑlido (precisa 2+ agentes)"
119
-
120
- return plano, f"βœ… Plano: {len(plano)} agentes gerados"
121
- except Exception as e:
122
- return None, f"❌ Erro plano: {str(e)[:100]}"
123
 
124
- # ==================== 4. EXECUTOR DE AGENTES DINΓ‚MICOS ====================
125
- def executar_agente_especifico(timeline, agente_config, history_contexto):
126
- """Executa agente especΓ­fico do plano dinΓ’mico"""
127
- if not (model_flash or model_pro):
128
- return {"role": "system", "error": "Sem API"}, "(ERRO: API)", "Sem Google API Key"
129
-
130
- modelo = model_pro if agente_config.get("modelo") == "pro" else model_flash
131
 
132
- # Contexto: ΓΊltimos 8 passos da timeline + histΓ³rico
133
- contexto_timeline = json.dumps(timeline[-8:], ensure_ascii=False, indent=2)
134
- history_resumo = "\n".join([f"πŸ‘€: {h[0][:100]}... | πŸ€–: {h[1][:100]}..." for h in history_contexto[-3:]])
135
 
136
- prompt = f"""CONTEXTO DA CADEIA DE PENSAMENTO:
137
- {contexto_timeline}
138
-
139
- HISTΓ“RICO RECENTE:
140
- {history_resumo}
141
 
142
- AGENTE ATIVO: {agente_config['nome']}
143
- MISSΓƒO ESPECÍFICA: {agente_config['missao']}
144
-
145
- { 'JSON estruturado e vΓ‘lido' if agente_config['tipo_saida']=='json' else 'Resposta clara, completa e finalizada pro usuΓ‘rio' }:"""
146
-
147
- log = f"πŸ”Έ {agente_config['nome']} ({agente_config['modelo']})"
148
  try:
149
  inicio = time.time()
150
- resp = modelo.generate_content(prompt, temperature=0.1 if agente_config['tipo_saida']=='json' else 0.7)
151
- out = resp.text.strip()
152
 
153
- # Parse output
154
- content = json.loads(out.replace('``````','')) if agente_config['tipo_saida']=='json' else out
155
  tempo = time.time() - inicio
 
156
 
157
- log += f" βœ“ {tempo:.1f}s"
158
- return {"role": "assistant", "agent": agente_config['nome'], "content": content}, log, out
159
-
160
  except Exception as e:
161
- log += f" βœ— {str(e)[:50]}"
162
- return {"role": "system", "error": str(e)}, log, str(e)
163
 
164
- # ==================== 5. ORQUESTRADOR PRINCIPAL (MEHON) ====================
165
- def pipeline_mehon_completo(texto, arquivo, history):
166
- """Pipeline completo: PLANEJA β†’ EXECUTA β†’ CONVERGE"""
167
-
168
- # Processa input
169
  anexo = ler_anexo(arquivo)
170
- full_input = f"{texto}{anexo}".strip()
171
 
172
  if not full_input:
173
- yield history, [], "ℹ️ Input vazio - digite algo!"
174
  return
175
 
176
- # Inicializa pipeline
177
- history = history + [[full_input, "🧠 Iniciando raciocínio MEHON..."]]
178
- timeline = [{"role": "user", "content": full_input, "timestamp": datetime.now().isoformat()}]
179
- logs = f"πŸš€ MEHON v29 | {datetime.now().strftime('%H:%M:%S')}\n"
180
-
181
- yield history, timeline, logs
182
 
183
- # PASSO 1: PLANEJADOR AUTO-GERA plano dinΓ’mico
184
- history[-1][1] = "🎯 Planejador criando agentes sob medida..."
185
  yield history, timeline, logs
186
 
187
- plano, log_plano = gerar_plano_auto(full_input, history)
 
188
  if not plano:
189
- history[-1][1] = f"❌ {log_plano}"
190
  yield history, timeline, logs
191
  return
192
 
193
  logs += f"{log_plano}\n"
194
- timeline.append({"role": "system", "plano_gerado": plano, "step": "PLANEJAMENTO"})
 
 
195
  yield history, timeline, logs
196
 
197
- # PASSO 2: EXECUTA plano dinΓ’mico sequencialmente
198
- resposta_acumulada = ""
199
- for i, agente in enumerate(plano):
200
- history[-1][1] = f"βš™οΈ [{i+1}/{len(plano)}] {agente['nome']} pensando..."
201
  yield history, timeline, logs
202
 
203
- resultado, log_add, raw = executar_agente_especifico(timeline, agente, history)
204
- timeline.append(resultado)
205
- logs += f" {log_add}\n"
206
 
207
- # Atualiza chat com output textual
208
- if agente.get('tipo_saida') == 'texto' and 'content' in resultado:
209
- resposta_acumulada = resultado['content']
210
- preview = resposta_acumulada[:900] + "..." if len(resposta_acumulada) > 900 else resposta_acumulada
211
- history[-1][1] = preview
212
  yield history, timeline, logs
213
 
214
- # Finaliza
215
- logs += f"\nβœ… Pipeline MEHON concluΓ­do | {len(plano)} agentes | {len(timeline)} passos"
216
- salvar_history(history) # Auto-save
217
-
218
  yield history, timeline, logs
219
 
220
- # ==================== 6. INTERFACE GRADIO COMPLETA ====================
221
- def criar_app_mehon_v29():
222
- """UI completa e funcional"""
223
  css = """
224
- footer { display: none !important; }
225
- .gradio-container { max-width: 1400px; }
226
- .mehon-title { font-size: 1.6em; font-weight: bold; color: #1e40af; text-align: center; }
227
- .status-bar { background: linear-gradient(90deg, #3b82f6, #1e40af); color: white; padding: 8px; border-radius: 8px; }
228
  """
229
 
230
- history_inicial = carregar_history()
 
231
 
232
- with gr.Blocks(title="πŸš€ PIPELINE MEHON v29", css=css, theme=gr.themes.Soft()) as app:
233
-
234
- # HEADER
235
- gr.Markdown("### 🧠 PIPELINE MEHON v29 - Raciocínio Estruturado AutomÑtico")
236
- gr.Markdown("*O modelo planeja β†’ executa β†’ converge. Supera respostas probabilΓ­sticas diretas.*")
237
-
238
  with gr.Tabs():
239
-
240
- # ABA 1: EXECUÇÃO PRINCIPAL
241
- with gr.Tab("πŸ’­ RaciocΓ­nio MEHON", icon="🧠"):
242
  chatbot = gr.Chatbot(
243
- value=history_inicial,
244
- height=550,
245
- show_copy_button=True,
246
  show_label=False,
 
 
247
  render_markdown=True
248
  )
249
 
250
  with gr.Row():
251
- with gr.Column(scale=8):
252
- txt_input = gr.Textbox(
253
- placeholder="""Qualquer pergunta complexa...
254
- O modelo CRIARÁ seu plano de agentes e executarÑ em cadeia!""",
255
- lines=4,
 
256
  container=False
257
  )
258
- with gr.Column(scale=1):
259
- file_input = gr.File(
260
- label="πŸ“Ž Anexo",
261
- file_types=[".txt", ".py", ".json", ".md", ".yaml", ".csv"]
 
262
  )
263
- with gr.Column(scale=1):
264
- btn_executar = gr.Button("πŸš€ EXECUTAR PLANO", variant="primary")
265
 
266
- status_atual = gr.Markdown("Status: Pronto", visible=True)
 
267
 
268
- # ABA 2: DEBUG COMPLETO
269
- with gr.Tab("πŸ” Plano & ExecuΓ§Γ£o", icon="πŸ”¬"):
270
  with gr.Row():
271
- with gr.Column(scale=1):
272
- gr.Markdown("### πŸ“‹ Plano Gerado")
273
- json_plano = gr.JSON(label="Agentes DinΓ’micos", lines=15)
274
- with gr.Column(scale=1):
275
- gr.Markdown("### πŸ“Š Timeline Completa")
276
- timeline_json = gr.JSON(label="Cadeia de Pensamento", lines=15)
277
-
278
- gr.Markdown("### πŸ“ˆ Logs de ExecuΓ§Γ£o")
279
- logs_execucao = gr.Textbox(label="Runtime Logs", lines=12)
280
 
281
- # ABA 3: GERENCIAMENTO
282
- with gr.Tab("πŸ“ HistΓ³rico & Export", icon="πŸ’Ύ"):
283
- gr.Markdown("**HistΓ³rico persistente em `history_v29.json`**")
284
  with gr.Row():
285
- btn_limpar_chat = gr.Button("πŸ—‘οΈ Limpar Chat", variant="stop")
286
- btn_export_txt = gr.Button("πŸ“₯ Download TXT", variant="secondary")
287
- btn_salvar_manual = gr.Button("πŸ’Ύ Salvar Manual", variant="secondary")
288
 
289
- export_content = gr.Textbox(label="ConteΓΊdo para Download", lines=20, max_lines=30)
290
- status_ops = gr.Label("Status: OK", visible=True)
291
-
292
- # ==================== EVENTOS ====================
293
- def executar_pipeline_completo(txt, file, hist):
294
- """Wrapper para generator do pipeline"""
295
- for resultado in pipeline_mehon_completo(txt, file, hist):
296
- yield resultado # [chatbot, timeline, logs]
297
-
298
- # Trigger principal
299
- btn_executar.click(
300
- executar_pipeline_completo,
301
- inputs=[txt_input, file_input, chatbot],
302
- outputs=[chatbot, timeline_json, logs_execucao]
303
- ).then(
304
- lambda: gr.update(value=""),
305
- outputs=[txt_input]
306
- )
307
-
308
- txt_input.submit(
309
- executar_pipeline_completo,
310
- inputs=[txt_input, file_input, chatbot],
311
- outputs=[chatbot, timeline_json, logs_execucao]
312
- )
313
 
314
- # Controles
315
- btn_limpar_chat.click(lambda: [], chatbot)
316
- btn_export_txt.click(exportar_chat, chatbot, export_content)
317
- btn_salvar_manual.click(lambda h: salvar_history(h) or "Salvo!", chatbot, status_ops)
 
 
 
 
 
 
 
318
 
319
  return app
320
 
321
- # ==================== LAUNCH ====================
322
  if __name__ == "__main__":
323
- print("πŸš€ Iniciando PIPELINE MEHON v29...")
324
- print("πŸ’‘ Configure GOOGLE_API_KEY para uso completo")
325
- print("πŸ“ History salvo em history_v29.json")
326
-
327
- app = criar_app_mehon_v29()
328
- app.launch(
329
- server_name="0.0.0.0",
330
- server_port=7861,
331
- share=False,
332
- show_error=True,
333
- quiet=False
334
- )
 
1
  # ╔════════════════════════════════════════════════════════════════════════════╗
2
+ # β•‘ PIPELINE v30: AUTO-PLAN | MESMA UI v27 | COMPATÍVEL HF SPACES β•‘
3
+ # β•‘ 1ΒΊ: MODELO CRIA PLANO β†’ ITERA PELO PRΓ“PRIO PLANO | SEM 'icon' β•‘
4
  # β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
5
 
6
  import os
 
11
  import gradio as gr
12
  import google.generativeai as genai
13
 
14
+ # ==================== 1. CONFIGURAÇÃO ====================
15
+ api_key = os.getenv("GOOGLE_API_KEY", "SUA_API_KEY_AQUI")
16
  if api_key:
17
  genai.configure(api_key=api_key)
18
  model_flash = genai.GenerativeModel("gemini-flash-latest")
19
  model_pro = genai.GenerativeModel("gemini-pro-latest")
20
  else:
21
  model_flash = model_pro = None
 
22
 
23
+ ARQUIVO_CONFIG = "protocolo.json"
24
+ ARQUIVO_HISTORY = "history_v30.json"
25
+
26
+ # ==================== 2. UTILIDADES (IDÊNTICAS AO v27) ====================
27
+ def carregar_protocolo():
28
+ try:
29
+ with open(ARQUIVO_CONFIG, "r", encoding="utf-8") as f:
30
+ return f.read()
31
+ except:
32
+ return "[]"
33
+
34
+ def salvar_protocolo(conteudo):
35
+ try:
36
+ json.loads(conteudo)
37
+ with open(ARQUIVO_CONFIG, "w", encoding="utf-8") as f:
38
+ f.write(conteudo)
39
+ return "βœ… Salvo"
40
+ except:
41
+ return "❌ Erro JSON"
42
 
 
43
  def carregar_history():
 
44
  try:
45
  with open(ARQUIVO_HISTORY, "r", encoding="utf-8") as f:
46
  return json.load(f)
47
+ except:
48
  return []
49
 
50
  def salvar_history(history):
 
51
  try:
52
  with open(ARQUIVO_HISTORY, "w", encoding="utf-8") as f:
53
  json.dump(history, f, ensure_ascii=False, indent=2)
54
  return True
55
+ except:
56
  return False
57
 
58
  def ler_anexo(arquivo):
59
+ if arquivo is None: return ""
 
60
  try:
61
  with open(arquivo.name, "r", encoding="utf-8") as f:
62
+ return f"\n\n[ANEXO: {os.path.basename(arquivo.name)}]\n{f.read()}\n[FIM ANEXO]\n"
63
+ except: return ""
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ # ==================== 3. PLANEJADOR AUTO (1Βͺ AÇÃO) ====================
66
+ def criar_plano_auto(full_input, history_contexto):
67
+ """MODELO CRIA SEU PRΓ“PRIO PLANO dinamicamente"""
68
  if not model_pro:
69
  return None, "❌ Sem API_KEY"
70
 
71
+ history_resumo = "\n".join([
72
+ f"πŸ‘€: {h[0][:150]}... | πŸ€–: {h[1][:150]}..."
73
+ for h in history_contexto[-3:]
74
+ ][:300]) if history_contexto else ""
 
 
 
75
 
76
+ prompt_planejador = f"""CONTEXTO HISTΓ“RICO:
 
 
77
  {history_resumo}
78
 
79
+ INPUT ATUAL: {full_input}
 
 
80
 
81
+ CRIE PLANO OTIMIZADO de 3-5 agentes:
82
 
83
+ FORMATO JSON VÁLIDO:
84
  [
85
+ {{"nome": "AnalisadorInput", "missao": "Identifique elementos principais", "modelo": "flash", "tipo_saida": "json"}},
86
+ {{"nome": "ExecutorFinal", "missao": "Produza resposta final completa", "modelo": "pro", "tipo_saida": "texto"}}
87
  ]
88
 
89
+ βœ… ÚLTIMO agente = saΓ­da FINAL pro usuΓ‘rio"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
  try:
92
+ resp = model_pro.generate_content(prompt_planejador, temperature=0.2)
93
+ plano_raw = resp.text.strip().replace('``````','')
94
  plano = json.loads(plano_raw)
95
 
96
+ if isinstance(plano, list) and len(plano) >= 2:
97
+ return plano, f"βœ… Plano: {len(plano)} agentes"
98
+ return None, "❌ Plano invÑlido"
99
+ except:
100
+ return None, "❌ Erro plano"
 
 
101
 
102
+ # ==================== 4. ENGINE EXECUÇÃO (ORIGINAL v27) ====================
103
+ def executar_no(timeline, config):
104
+ if not (model_flash or model_pro):
105
+ return {"role": "system", "error": "Sem API"}, "(ERRO: API)", "Sem key"
 
 
 
106
 
107
+ modelo = model_pro if config.get("modelo") == "pro" else model_flash
108
+ contexto = json.dumps(timeline[-10:], ensure_ascii=False, indent=2)
 
109
 
110
+ prompt = f"""--- TIMELINE ---
111
+ {contexto}
112
+ ----------------
113
+ AGENTE: {config['nome']}
114
+ MISSÃO: {config['missao']}"""
115
 
116
+ log = f"\nπŸ”Έ {config['nome']}..."
 
 
 
 
 
117
  try:
118
  inicio = time.time()
119
+ resp = modelo.generate_content(prompt)
120
+ out = resp.text
121
 
 
 
122
  tempo = time.time() - inicio
123
+ content = json.loads(out.strip().replace('``````','')) if config['tipo_saida']=='json' else out
124
 
125
+ log += f" (OK - {tempo:.2f}s)"
126
+ return {"role": "assistant", "agent": config['nome'], "content": content}, log, out
 
127
  except Exception as e:
128
+ return {"role": "system", "error": str(e)}, f" (ERRO: {e})", str(e)
 
129
 
130
+ # ==================== 5. ORQUESTRADOR v30 (PLANO AUTO) ====================
131
+ def orquestrador(texto, arquivo, history, json_config):
132
+ # 1. Input Check (IDÊNTICO v27)
 
 
133
  anexo = ler_anexo(arquivo)
134
+ full_input = f"{texto}\n{anexo}".strip()
135
 
136
  if not full_input:
137
+ yield history, {}, "Sem input."
138
  return
139
 
140
+ # 2. Setup (IDÊNTICO v27)
141
+ history = history + [[texto + (" πŸ“Ž" if arquivo else ""), None]]
142
+ timeline = [{"role": "user", "content": full_input}]
143
+ logs = f"πŸš€ AUTO-PLAN v30: {datetime.now().strftime('%H:%M:%S')}\n"
 
 
144
 
145
+ history[-1][1] = "🎯 Criando plano dinÒmico..."
 
146
  yield history, timeline, logs
147
 
148
+ # 3. 1Βͺ AÇÃO: CRIA PLANO
149
+ plano, log_plano = criar_plano_auto(full_input, history)
150
  if not plano:
151
+ history[-1][1] = log_plano
152
  yield history, timeline, logs
153
  return
154
 
155
  logs += f"{log_plano}\n"
156
+ timeline.append({"role": "system", "plano_auto": plano})
157
+
158
+ history[-1][1] = f"βœ… Plano criado: {len(plano)} agentes"
159
  yield history, timeline, logs
160
 
161
+ # 4. ITERA PELO PLANO (IDÊNTICO v27)
162
+ final_response = ""
163
+ for i, cfg in enumerate(plano):
164
+ history[-1][1] = f"βš™οΈ [{i+1}/{len(plano)}] {cfg['nome']}..."
165
  yield history, timeline, logs
166
 
167
+ res, log_add, raw = executar_no(timeline, cfg)
168
+ timeline.append(res)
169
+ logs += log_add + "\n"
170
 
171
+ if cfg['tipo_saida'] == 'texto':
172
+ final_response = res['content']
173
+ history[-1][1] = final_response[:800] + "..." if len(final_response) > 800 else final_response
 
 
174
  yield history, timeline, logs
175
 
176
+ logs += "βœ… AUTO-PLAN concluΓ­do."
177
+ salvar_history(history)
 
 
178
  yield history, timeline, logs
179
 
180
+ # ==================== 6. UI LIMPA v27 (SEM 'icon') ====================
181
+ def ui_clean():
 
182
  css = """
183
+ footer {display: none !important;}
184
+ .contain {border: none !important;}
 
 
185
  """
186
 
187
+ config_init = carregar_protocolo()
188
+ history_init = carregar_history()
189
 
190
+ with gr.Blocks(title="PIPELINE v30 - AUTO-PLAN", css=css, theme=gr.themes.Soft()) as app:
 
 
 
 
 
191
  with gr.Tabs():
192
+ # === ABA 1: CHAT (EXATA v27) ===
193
+ with gr.Tab("πŸ’¬ Pipeline"):
 
194
  chatbot = gr.Chatbot(
195
+ value=history_init,
196
+ label="",
 
197
  show_label=False,
198
+ height=600,
199
+ show_copy_button=True,
200
  render_markdown=True
201
  )
202
 
203
  with gr.Row():
204
+ with gr.Column(scale=10):
205
+ txt_in = gr.Textbox(
206
+ show_label=False,
207
+ placeholder="Digite input... Modelo criarΓ‘ plano automaticamente!",
208
+ lines=1,
209
+ max_lines=5,
210
  container=False
211
  )
212
+ with gr.Column(scale=1, min_width=50):
213
+ file_in = gr.UploadButton(
214
+ "πŸ“Ž",
215
+ file_types=[".txt", ".md", ".csv", ".json", ".py", ".yaml"],
216
+ size="sm"
217
  )
218
+ with gr.Column(scale=1, min_width=80):
219
+ btn_send = gr.Button("Enviar", variant="primary", size="sm")
220
 
221
+ file_status = gr.Markdown("", visible=True)
222
+ file_in.upload(lambda x: f"πŸ“Ž Anexo: {os.path.basename(x.name)}", file_in, file_status)
223
 
224
+ # === ABA 2: DEPURAÇÃO (EXATA v27) ===
225
+ with gr.Tab("πŸ•΅οΈ DepuraΓ§Γ£o"):
226
  with gr.Row():
227
+ out_dna = gr.JSON(label="DNA (Timeline)")
228
+ out_logs = gr.Textbox(label="Logs do Sistema", lines=20)
 
 
 
 
 
 
 
229
 
230
+ # === ABA 3: CONFIG (EXATA v27) ===
231
+ with gr.Tab("βš™οΈ Config"):
 
232
  with gr.Row():
233
+ btn_save = gr.Button("Salvar Config")
234
+ lbl_save = gr.Label(show_label=False)
 
235
 
236
+ code_json = gr.Code(
237
+ value=config_init,
238
+ language="json",
239
+ label="protocolo.json (placeholder - usa auto-plan)"
240
+ )
241
+ btn_save.click(salvar_protocolo, code_json, lbl_save)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
+ # === TRIGGERS (EXATOS v27) ===
244
+ triggers = [btn_send.click, txt_in.submit]
245
+ for trig in triggers:
246
+ trig(
247
+ orquestrador,
248
+ inputs=[txt_in, file_in, chatbot, code_json],
249
+ outputs=[chatbot, out_dna, out_logs]
250
+ ).then(
251
+ lambda: (None, ""),
252
+ outputs=[txt_in, file_status]
253
+ )
254
 
255
  return app
256
 
 
257
  if __name__ == "__main__":
258
+ print("πŸš€ PIPELINE v30 - AUTO-PLAN (HF Spaces compatΓ­vel)")
259
+ print("πŸ’‘ Sem 'icon' | History persistente | Mesmo UI v27")
260
+ app = ui_clean()
261
+ app.launch(server_name="0.0.0.0", server_port=7860, share=False)