fix(miroflow): fallback robusto para resultado do agente + modelo llama3.2:3b

- miroflow_service.py: extrai resposta de summary, final_boxed_answer,
  exceed_max_turn_summary ou último message_history do assistente
- Troca deepseek-r1:14b por llama3.2:3b nos agentes Statistician e Fiscal Auditor
- shared/schema.ts: adiciona tabelas OpenClaw (detectedPatterns, skillSuggestions)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jonas Pacheco 2026-03-26 16:26:43 -03:00
parent c73b9d6658
commit d4af26e59d
2 changed files with 79 additions and 3 deletions

View File

@ -25,8 +25,8 @@ OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
RESEARCHER_MODEL = os.getenv("MIROFLOW_RESEARCHER_MODEL", "llama3.1:8b")
AGENT_MODELS = {
"statistician": "deepseek-r1:14b",
"fiscal_auditor": "deepseek-r1:14b",
"statistician": "llama3.2:3b",
"fiscal_auditor": "llama3.2:3b",
"researcher": RESEARCHER_MODEL,
}
@ -75,7 +75,19 @@ async def run_agent(agent_type: str, task: str) -> tuple[str, str]:
initial_user_message=task,
)
result = await agent.run(ctx)
text = result.get("summary", str(result)) if isinstance(result, dict) else str(result)
if isinstance(result, dict):
text = (
result.get("summary")
or result.get("final_boxed_answer")
or result.get("exceed_max_turn_summary")
or next(
(m["content"] for m in reversed(result.get("message_history") or []) if m.get("role") == "assistant"),
None,
)
or str(result)
)
else:
text = str(result)
return text, cfg["llm"]["model_name"]

View File

@ -7525,3 +7525,67 @@ export type ArcadiaSkill = typeof arcadiaSkills.$inferSelect;
export type InsertArcadiaSkill = z.infer<typeof insertArcadiaSkillSchema>;
export type SkillExecution = typeof skillExecutions.$inferSelect;
export type InsertSkillExecution = z.infer<typeof insertSkillExecutionSchema>;
// ============================================================
// OpenClaw — Fase 4: Detecção de Padrões e Emergência de Skills
// ============================================================
export const detectedPatterns = pgTable("detected_patterns", {
id: uuid("id").primaryKey().defaultRandom(),
tenantId: integer("tenant_id").references(() => tenants.id),
userId: varchar("user_id").references(() => users.id),
// Padrão detectado
actionType: varchar("action_type", { length: 100 }).notNull(),
description: text("description"),
frequency: integer("frequency").notNull().default(0),
confidence: numeric("confidence", { precision: 4, scale: 3 }).notNull().default("0"),
// Janela de análise
firstSeenAt: timestamp("first_seen_at").default(sql`CURRENT_TIMESTAMP`).notNull(),
lastSeenAt: timestamp("last_seen_at").default(sql`CURRENT_TIMESTAMP`).notNull(),
// Metadados do padrão (contexto, módulos envolvidos, etc.)
metadata: jsonb("metadata").default({}),
// Estado do ciclo de vida
status: varchar("status", { length: 20 }).notNull().default("active"), // active | archived | converted
createdAt: timestamp("created_at").default(sql`CURRENT_TIMESTAMP`).notNull(),
updatedAt: timestamp("updated_at").default(sql`CURRENT_TIMESTAMP`).notNull(),
});
export const skillSuggestions = pgTable("skill_suggestions", {
id: uuid("id").primaryKey().defaultRandom(),
patternId: uuid("pattern_id").references(() => detectedPatterns.id, { onDelete: "cascade" }),
tenantId: integer("tenant_id").references(() => tenants.id),
userId: varchar("user_id").references(() => users.id),
// Skill sugerida
suggestedSkillName: varchar("suggested_skill_name", { length: 200 }).notNull(),
suggestedDescription: text("suggested_description"),
estimatedAutomation: text("estimated_automation"),
confidence: numeric("confidence", { precision: 4, scale: 3 }).notNull().default("0"),
// Skill gerada (após confirmação)
generatedSkillId: uuid("generated_skill_id").references(() => arcadiaSkills.id),
// Estado da sugestão
status: varchar("status", { length: 20 }).notNull().default("pending"), // pending | accepted | rejected | expired
// Rastreabilidade
source: varchar("source", { length: 50 }).notNull().default("openclaw"),
reviewedBy: varchar("reviewed_by").references(() => users.id),
reviewedAt: timestamp("reviewed_at"),
createdAt: timestamp("created_at").default(sql`CURRENT_TIMESTAMP`).notNull(),
updatedAt: timestamp("updated_at").default(sql`CURRENT_TIMESTAMP`).notNull(),
});
export const insertDetectedPatternSchema = createInsertSchema(detectedPatterns).omit({ id: true, createdAt: true, updatedAt: true });
export const insertSkillSuggestionSchema = createInsertSchema(skillSuggestions).omit({ id: true, createdAt: true, updatedAt: true });
export type DetectedPattern = typeof detectedPatterns.$inferSelect;
export type InsertDetectedPattern = z.infer<typeof insertDetectedPatternSchema>;
export type SkillSuggestionRecord = typeof skillSuggestions.$inferSelect;
export type InsertSkillSuggestion = z.infer<typeof insertSkillSuggestionSchema>;