}}
-}}
-
-Then return:
-{{ "result": "✅ Creation of resource is Done." }}
-
-⚠️ JSON must be strictly valid (RFC8259).
-No markdown, no comments, no truncation, no null placeholders.
+### STEP 5 — Output contract
+- Respond ONLY with one valid JSON object.
+- Never output markdown, comments, or explanations.
+- Never put literal parameters in "candidates".
+- Never leave literal parameters null if present in text.
+- Always use snake_case for Schema A and camelCase for Schema B.
"""
prompt = ChatPromptTemplate.from_messages([
@@ -252,13 +375,24 @@ def index():
@app.route("/send", methods=["POST"])
def send():
user_message = request.form["message"]
+
+ if user_message.strip().lower() in ["reset", "newvm"]:
+ reset_state()
+ return Markup(
+ f"You: {user_message}
"
+ f"Assistant: Status reset. You can start a new request.
"
+ )
+
memory_state.messages.append(HumanMessage(content=user_message))
user_html = f"You: {user_message}
"
try:
- # injeta estado atual na conversa
- params_json = json.dumps({"parameters": memory_state.parameters}, indent=2)
- context_message = AIMessage(content=f"Current known parameters:\n{params_json}")
+ state_block = json.dumps({
+ "parameters": memory_state.parameters,
+ "candidates": memory_state.candidates
+ }, ensure_ascii=False)
+
+ context_message = AIMessage(content=f"Current known state:\n{state_block}")
result = asyncio.run(agent_executor.ainvoke({
"messages": memory_state.messages + [context_message]
@@ -280,46 +414,50 @@ def send():
parsed = sanitize_json(assistant_reply)
if parsed and "parameters" in parsed:
- # atualiza parâmetros
+ # 🔹 Smart merge: only overwrites if a non-null value came in
for k, v in parsed["parameters"].items():
- if v is not None:
+ if v not in (None, "null", ""):
memory_state.parameters[k] = v
+
print("📌 Current status:", memory_state.parameters)
missing = validate_payload(memory_state.parameters)
- if not missing:
- print("✅ All parameters filled in. The agent should now create the VM..")
- else:
- print("⚠️ Faltando parâmetros:", missing)
if not missing:
debug_info += "\n✅ All parameters filled in. The agent should now create the VM.."
else:
debug_info += f"\n⚠️ Missing parameters: {missing}"
if missing:
- auto_followup = f"Please resolve the following missing parameters: {missing}"
- memory_state.messages.append(HumanMessage(content=auto_followup))
+ # injeta um comando estruturado pedindo resolução
+ cmd = json.dumps({
+ "type": "resolve",
+ "missing": missing,
+ "hint": "Return Schema A JSON only."
+ })
+ memory_state.messages.append(HumanMessage(content=cmd))
- # adiciona debug_info na resposta enviada ao navegador
+ # adiciona debug_info à resposta
assistant_reply += "\n\n" + debug_info
- # se vieram candidatos
+ # 🔹 Se vieram candidatos
if parsed and "candidates" in parsed and parsed["candidates"]:
memory_state.candidates = parsed["candidates"]
print("🔍 Candidates found:", memory_state.candidates)
- # monta bloco HTML de candidatos
candidates_html = ""
for param, items in memory_state.candidates.items():
candidates_html += f"Options for {param}:
"
for c in items:
- line = f"{c.get('index')}. {c.get('name')} — {c.get('ocid')} — v{c.get('version')} — score {c.get('score')}"
+ line = f"{c.get('index')}. {c.get('name')} — {c.get('ocid')} — v{c.get('version', '')} — score {c.get('score', '')}"
candidates_html += line + "
"
ask_text = parsed.get("ask", "Choose an index or provide the OCID.")
- assistant_reply = f"{json.dumps({'parameters': memory_state.parameters}, ensure_ascii=False)}
{candidates_html}{ask_text}"
-
+ assistant_reply = (
+ f"{json.dumps({'parameters': memory_state.parameters}, ensure_ascii=False)}"
+ f"
{candidates_html}{ask_text}"
+ )
else:
+ # 🔹 Se não houver candidatos, zera
memory_state.candidates = {}
else: