Reduce machine max MCP response size
This commit is contained in:
@@ -157,7 +157,10 @@ Tool calling semantics:
|
||||
weight, and the domain returns the governing constraint(s), unrounded.
|
||||
Core and width incompatibility cannot be corrected by shortening and is
|
||||
returned structurally. No manufacturing increment, core/packaging/gross
|
||||
weight, or conditional production rule is applied in V1.1.
|
||||
weight, or conditional production rule is applied in V1.1. Its successful
|
||||
MCP response is a compact projection: machine identity, configured maximum
|
||||
diameter/material-weight limits, production maxima, material weights, and
|
||||
warnings. Flask and other domain consumers retain the full diagnostic result.
|
||||
- `calculate_product_length` calculates required roll length from a target outer
|
||||
diameter, core diameter, and material thickness. Its optional thickness
|
||||
stddev returns minimum/average/maximum length ranges; optional width and area
|
||||
|
||||
+31
-2
@@ -69,8 +69,8 @@ def calculate_machine_max_product_length_result(
|
||||
product_width_m: float | None = None,
|
||||
area_weight_g_m2: float | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Delegate machine-aware maximum product length to the shared domain."""
|
||||
return calculate_machine_max_product_length(
|
||||
"""Return the compact MCP view of the machine-aware domain calculation."""
|
||||
result = calculate_machine_max_product_length(
|
||||
machine=machine,
|
||||
core_diameter_mm=core_diameter_mm,
|
||||
thickness_mm=thickness_mm,
|
||||
@@ -78,6 +78,35 @@ def calculate_machine_max_product_length_result(
|
||||
product_width_m=product_width_m,
|
||||
area_weight_g_m2=area_weight_g_m2,
|
||||
)
|
||||
return project_machine_max_product_length_result(result)
|
||||
|
||||
|
||||
def project_machine_max_product_length_result(result: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Project successful maximum-length results for MCP without diagnostics.
|
||||
|
||||
The shared domain result deliberately contains detailed verification reports.
|
||||
They remain available to Flask and other consumers, but duplicate machine
|
||||
metadata and checks are unnecessary in the MCP response.
|
||||
"""
|
||||
if result.get("status") != "success":
|
||||
return result
|
||||
|
||||
machine = result["machine"]
|
||||
constraints = machine["constraints"]
|
||||
return {
|
||||
"status": result["status"],
|
||||
"machine": {"id": machine["id"], "name": machine["name"]},
|
||||
"weight_scope": result["weight_scope"],
|
||||
"machine_limits": {
|
||||
"maximum_roll_diameter_mm": constraints["roll_diameter_mm"]["maximum"]
|
||||
if constraints["roll_diameter_mm"] is not None else None,
|
||||
"maximum_material_roll_weight_kg": constraints["roll_weight_kg"]["maximum"]
|
||||
if constraints["roll_weight_kg"] is not None else None,
|
||||
},
|
||||
"production_maximums": result["production_maximums"],
|
||||
"material_weights_kg": result["material_weights_kg"],
|
||||
"warnings": result["warnings"],
|
||||
}
|
||||
|
||||
|
||||
def calculate_material_weight_result(
|
||||
|
||||
@@ -5,6 +5,7 @@ import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import app as rollcalc_app
|
||||
from machine_constraints import calculate_machine_max_product_length
|
||||
|
||||
|
||||
class CalculationApiTests(unittest.TestCase):
|
||||
@@ -140,21 +141,24 @@ class CalculationApiTests(unittest.TestCase):
|
||||
self.assertEqual(result["warning_constraints"], ["roll_diameter_mm"])
|
||||
|
||||
def test_machine_maximum_length_endpoint_is_authenticated_and_structured(self):
|
||||
payload = {
|
||||
"machine": "K7",
|
||||
"core_diameter_mm": 133,
|
||||
"thickness_mm": 4.311611,
|
||||
"thickness_stddev_mm": 0.249999,
|
||||
"product_width_m": 6,
|
||||
"area_weight_g_m2": 495.395833,
|
||||
}
|
||||
response = self.client.post(
|
||||
"/api/calculations/machine-max-product-length",
|
||||
json={
|
||||
"machine": "K7",
|
||||
"core_diameter_mm": 133,
|
||||
"thickness_mm": 4.311611,
|
||||
"thickness_stddev_mm": 0.249999,
|
||||
"product_width_m": 6,
|
||||
"area_weight_g_m2": 495.395833,
|
||||
},
|
||||
json=payload,
|
||||
headers=self.headers,
|
||||
)
|
||||
result = response.get_json()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(result["status"], "success")
|
||||
self.assertEqual(result, calculate_machine_max_product_length(**payload))
|
||||
self.assertIn("final_feasibility", result)
|
||||
self.assertEqual(
|
||||
result["production_maximums"]["nominal_governing_constraints"],
|
||||
["roll_diameter_nominal"],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import copy
|
||||
import inspect
|
||||
import sys
|
||||
import types
|
||||
@@ -21,6 +22,7 @@ from rollcalc_mcp_tools import (
|
||||
calculate_roll_diameter_result,
|
||||
get_article_result,
|
||||
get_machine_result,
|
||||
project_machine_max_product_length_result,
|
||||
search_articles_result,
|
||||
)
|
||||
from machine_constraints import (
|
||||
@@ -103,7 +105,7 @@ class McpAdapterTests(unittest.TestCase):
|
||||
"feasible_with_warnings",
|
||||
)
|
||||
|
||||
def test_machine_maximum_length_adapter_delegates_to_shared_domain(self):
|
||||
def test_machine_maximum_length_adapter_projects_success_without_mutating_domain(self):
|
||||
arguments = {
|
||||
"machine": "K7",
|
||||
"core_diameter_mm": 133.0,
|
||||
@@ -112,10 +114,79 @@ class McpAdapterTests(unittest.TestCase):
|
||||
"product_width_m": 6.0,
|
||||
"area_weight_g_m2": 495.395833,
|
||||
}
|
||||
domain_result = calculate_machine_max_product_length(**arguments)
|
||||
domain_before_projection = copy.deepcopy(domain_result)
|
||||
|
||||
result = project_machine_max_product_length_result(domain_result)
|
||||
|
||||
self.assertEqual(domain_result, domain_before_projection)
|
||||
self.assertIn("final_feasibility", domain_result)
|
||||
self.assertNotIn("final_feasibility", result)
|
||||
self.assertEqual(
|
||||
calculate_machine_max_product_length_result(**arguments),
|
||||
calculate_machine_max_product_length(**arguments),
|
||||
calculate_machine_max_product_length_result(**arguments), result
|
||||
)
|
||||
self.assertEqual(result["machine"], {"id": "k7", "name": "K7"})
|
||||
self.assertEqual(result["weight_scope"], "material_only")
|
||||
self.assertEqual(result["machine_limits"], {
|
||||
"maximum_roll_diameter_mm": 1100.0,
|
||||
"maximum_material_roll_weight_kg": 700.0,
|
||||
})
|
||||
self.assertEqual(result["production_maximums"], {
|
||||
"nominal_length_m": 217.1900177447768,
|
||||
"nominal_governing_constraints": ["roll_diameter_nominal"],
|
||||
"conservative_length_m": 194.62073281485985,
|
||||
"conservative_governing_constraints": ["roll_diameter_conservative"],
|
||||
})
|
||||
self.assertEqual(result["material_weights_kg"], {
|
||||
"at_nominal_production_maximum": 645.570178559751,
|
||||
"at_conservative_production_maximum": 578.4858003113276,
|
||||
})
|
||||
self.assertEqual(result["warnings"], {"nominal": ["roll_diameter_mm"]})
|
||||
|
||||
def test_machine_maximum_length_adapter_preserves_non_success_diagnostics(self):
|
||||
base = {
|
||||
"machine": "K7",
|
||||
"core_diameter_mm": 133.0,
|
||||
"thickness_mm": 4.311611,
|
||||
"thickness_stddev_mm": 0.249999,
|
||||
"product_width_m": 6.0,
|
||||
"area_weight_g_m2": 495.395833,
|
||||
}
|
||||
for changes, status in (
|
||||
({"core_diameter_mm": 194.0}, "incompatible"),
|
||||
({"product_width_m": 3.0}, "incompatible"),
|
||||
(
|
||||
{"product_width_m": None, "area_weight_g_m2": None},
|
||||
"needs_clarification",
|
||||
),
|
||||
({"thickness_mm": -1.0}, "invalid_parameter"),
|
||||
({"machine": "not configured"}, "machine_not_found"),
|
||||
):
|
||||
with self.subTest(changes=changes):
|
||||
arguments = {**base, **changes}
|
||||
domain_result = calculate_machine_max_product_length(**arguments)
|
||||
adapter_result = calculate_machine_max_product_length_result(**arguments)
|
||||
self.assertEqual(adapter_result, domain_result)
|
||||
self.assertEqual(adapter_result["status"], status)
|
||||
|
||||
missing = calculate_machine_max_product_length_result(
|
||||
**{**base, "product_width_m": None, "area_weight_g_m2": None}
|
||||
)
|
||||
self.assertEqual(
|
||||
missing["missing_required_inputs"],
|
||||
["product_width_m", "area_weight_g_m2"],
|
||||
)
|
||||
core = calculate_machine_max_product_length_result(
|
||||
**{**base, "core_diameter_mm": 194.0}
|
||||
)
|
||||
self.assertEqual(
|
||||
core["failed_compatibility_constraints"],
|
||||
["allowed_core_diameters_mm"],
|
||||
)
|
||||
width = calculate_machine_max_product_length_result(
|
||||
**{**base, "product_width_m": 3.0}
|
||||
)
|
||||
self.assertEqual(width["failed_compatibility_constraints"], ["product_width_m"])
|
||||
|
||||
def test_material_weight_adapter_delegates_without_a_core_diameter(self):
|
||||
arguments = {
|
||||
|
||||
Reference in New Issue
Block a user