fix: Oracle Canvas JSON Component Generation planning and orchestration logic

This commit is contained in:
Sagnik
2026-04-24 05:14:11 +05:30
parent 9f27e6a017
commit cf602822b0
6 changed files with 1555 additions and 115 deletions

View File

@@ -175,6 +175,27 @@ def _infer_chart_axes(rows: list[dict[str, Any]], columns: list[str]) -> tuple[s
return x_axis, y_axis
def _canonical_plan_type(plan_type: str) -> str:
normalized = str(plan_type or "").strip()
mapping = {
"pipeline_board": "pipeline_board",
"pipelineBoard": "pipeline_board",
"bar_chart": "bar_chart",
"barChart": "bar_chart",
"geo_map": "geo_map",
"geoMap": "geo_map",
"table": "table",
"line_chart": "line_chart",
"lineChart": "line_chart",
"kpi_tile": "kpi_tile",
"kpiTile": "kpi_tile",
"activity_stream": "activity_stream",
"activityStream": "activity_stream",
"timeline": "activity_stream",
}
return mapping.get(normalized, normalized or "table")
_DATASET_MAP: dict[str, str] = {
"pipeline_board": "crm_opportunity_pipeline",
"bar_chart": "oracle_property_interest_rollup",
@@ -794,35 +815,35 @@ class PromptOrchestrator:
) -> dict[str, Any]:
rows = result.get("rows") or []
columns = result.get("columns") or (list(rows[0].keys()) if rows else [])
ctype = str(result.get("componentType") or "table")
mapped_type = self._map_type(ctype)
ctype_raw = str(result.get("componentType") or "table")
ctype = _canonical_plan_type(ctype_raw)
mapped_type = self._map_type(ctype_raw)
dataset = "oracle_natural_sql"
component_id = str(uuid.uuid4())
viz_decision = result.get("visualizationDecision") or {}
x_axis, y_axis = _infer_chart_axes(rows, columns)
bindings = self._default_bindings(ctype)
bindings = dict(viz_decision.get("dataBindings") or self._default_bindings(ctype))
viz_params = {
**self._default_viz_params(ctype, dataset, rows),
**dict(viz_decision.get("vizParams") or {}),
"columns": columns,
"sqlSummary": result.get("summary"),
"sourceTables": result.get("sourceTables", []),
"rowCount": result.get("rowCount", len(rows)),
}
if ctype == "bar_chart":
if x_axis:
if mapped_type in {"barChart", "lineChart"}:
if not viz_params.get("xAxis") and x_axis:
viz_params["xAxis"] = x_axis
bindings["dimensions"] = [x_axis]
if y_axis:
if not viz_params.get("yAxis") and y_axis:
viz_params["yAxis"] = y_axis
bindings["measures"] = [y_axis]
elif ctype == "line_chart":
if x_axis:
if not bindings.get("dimensions") and x_axis:
bindings["dimensions"] = [x_axis]
if y_axis:
if not bindings.get("measures") and y_axis:
bindings["measures"] = [y_axis]
comp: dict[str, Any] = {
"componentId": component_id,
"type": mapped_type,
"title": result.get("title") or self._generate_title(prompt, ctype),
"title": result.get("title") or self._generate_title(prompt, ctype_raw),
"description": f"SQL-backed Oracle result from: \"{prompt[:96]}\"",
"dataSourceDescriptor": {
"descriptorId": str(uuid.uuid4()),
@@ -849,12 +870,22 @@ class PromptOrchestrator:
"sourceTables": result.get("sourceTables", []),
"sqlSummary": result.get("summary"),
},
"renderingHints": self._rendering_hints(ctype),
"renderingHints": {
**self._rendering_hints(ctype),
**(
{
"estimatedHeightPx": int(viz_decision.get("minHeightPx", 0) or 0),
"skeletonVariant": str(viz_decision.get("skeletonVariant") or ""),
}
if viz_decision
else {}
),
},
"layout": {
"orderIndex": base_order + 100,
"sectionId": section_id,
"widthMode": "full" if mapped_type in ("table", "pipelineBoard", "timeline", "activityStream") else "half",
"minHeightPx": 320,
"widthMode": str(viz_decision.get("widthMode") or ("full" if mapped_type in ("table", "pipelineBoard", "timeline", "activityStream") else "half")),
"minHeightPx": int(viz_decision.get("minHeightPx") or 320),
"stickyHeader": False,
},
"accessControls": {
@@ -975,6 +1006,7 @@ class PromptOrchestrator:
@staticmethod
def _map_type(plan_type: str) -> str:
plan_type = _canonical_plan_type(plan_type)
mapping = {
"pipeline_board": "pipelineBoard",
"bar_chart": "barChart",
@@ -988,6 +1020,7 @@ class PromptOrchestrator:
@staticmethod
def _generate_title(prompt: str, comp_type: str) -> str:
comp_type = _canonical_plan_type(comp_type)
labels = {
"pipeline_board": "Pipeline View",
"bar_chart": "Comparative Analysis",
@@ -1001,6 +1034,7 @@ class PromptOrchestrator:
@staticmethod
def _default_viz_params(comp_type: str, dataset: str, rows: list[dict[str, Any]]) -> dict[str, Any]:
comp_type = _canonical_plan_type(comp_type)
first_row = rows[0] if rows else {}
inferred_columns = [key for key in first_row.keys() if key not in {"avatar"}] or ["name", "status"]
table_columns_by_dataset: dict[str, list[str]] = {
@@ -1038,10 +1072,12 @@ class PromptOrchestrator:
@staticmethod
def _default_bindings(comp_type: str) -> dict[str, Any]:
del comp_type
return {"dimensions": [], "measures": [], "series": [], "filters": []}
@staticmethod
def _rendering_hints(comp_type: str) -> dict[str, Any]:
comp_type = _canonical_plan_type(comp_type)
priority_map = {
"pipeline_board": ("pipeline", 9), "bar_chart": ("chart", 8),
"geo_map": ("map", 9), "table": ("table", 7),