fix: Oracle Canvas JSON Component Generation planning and orchestration logic
This commit is contained in:
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user