diff --git a/apps/api/src/services/openclaw.py b/apps/api/src/services/openclaw.py index ff78140a..d3176469 100644 --- a/apps/api/src/services/openclaw.py +++ b/apps/api/src/services/openclaw.py @@ -1557,6 +1557,28 @@ Focus on: proposal["nemotron_tool_model"] = nemotron_result.get("tool_model", "") proposal["nemotron_tool_backend"] = nemotron_result.get("tool_backend", "") + # 2026-04-09 Claude Sonnet 4.6: 將 Nemotron tool call 回填為 kubectl_command + # 根本問題修復:approval_records.action 需要可執行指令才能被 parse_operation_from_action 解析 + _tools = proposal["nemotron_tools"] + if _tools: + _t = _tools[0] + _tool_name = _t.get("tool", "") + _args = _t.get("args", {}) + _ns = _args.get("namespace", proposal.get("namespace", "awoooi-prod")) + if _tool_name == "restart_deployment": + _deploy = _args.get("deployment_name", proposal.get("target_resource", "")) + if _deploy: + proposal["kubectl_command"] = f"kubectl rollout restart deployment/{_deploy} -n {_ns}" + elif _tool_name == "delete_pod": + _pod = _args.get("pod_name", "") + if _pod: + proposal["kubectl_command"] = f"kubectl delete pod {_pod} -n {_ns}" + elif _tool_name == "scale_deployment": + _deploy = _args.get("deployment_name", "") + _replicas = _args.get("replicas", 2) + if _deploy: + proposal["kubectl_command"] = f"kubectl scale deployment/{_deploy} --replicas={_replicas} -n {_ns}" + logger.info( "nemotron_collaboration_complete", incident_id=incident_id, @@ -1605,6 +1627,27 @@ Focus on: proposal["nemotron_tool_model"] = "gemini-fallback" proposal["nemotron_tool_backend"] = "Gemini 雲端" + # 2026-04-09 Claude Sonnet 4.6: Gemini fallback 同樣回填 kubectl_command + _fb_tools = proposal["nemotron_tools"] + if _fb_tools: + _t = _fb_tools[0] + _tool_name = _t.get("tool", "") + _args = _t.get("args", {}) + _ns = _args.get("namespace", proposal.get("namespace", "awoooi-prod")) + if _tool_name == "restart_deployment": + _deploy = _args.get("deployment_name", proposal.get("target_resource", "")) + if _deploy: + proposal["kubectl_command"] = f"kubectl rollout restart deployment/{_deploy} -n {_ns}" + elif _tool_name == "delete_pod": + _pod = _args.get("pod_name", "") + if _pod: + proposal["kubectl_command"] = f"kubectl delete pod {_pod} -n {_ns}" + elif _tool_name == "scale_deployment": + _deploy = _args.get("deployment_name", "") + _replicas = _args.get("replicas", 2) + if _deploy: + proposal["kubectl_command"] = f"kubectl scale deployment/{_deploy} --replicas={_replicas} -n {_ns}" + return proposal, provider, True async def _call_nemotron_tools(