diff --git a/src/grist_mcp/logging.py b/src/grist_mcp/logging.py index 42fb090..a8f1b0c 100644 --- a/src/grist_mcp/logging.py +++ b/src/grist_mcp/logging.py @@ -1,6 +1,50 @@ """Logging configuration and utilities.""" +def extract_stats(tool_name: str, arguments: dict, result: dict) -> str: + """Extract meaningful stats from tool call based on tool type.""" + if tool_name == "list_documents": + count = len(result.get("documents", [])) + return f"{count} docs" + + if tool_name == "list_tables": + count = len(result.get("tables", [])) + return f"{count} tables" + + if tool_name == "describe_table": + count = len(result.get("columns", [])) + return f"{count} columns" + + if tool_name == "get_records": + count = len(result.get("records", [])) + return f"{count} records" + + if tool_name == "sql_query": + count = len(result.get("records", [])) + return f"{count} rows" + + if tool_name == "add_records": + count = len(arguments.get("records", [])) + return f"{count} records" + + if tool_name == "update_records": + count = len(arguments.get("records", [])) + return f"{count} records" + + if tool_name == "delete_records": + count = len(arguments.get("record_ids", [])) + return f"{count} records" + + if tool_name == "create_table": + count = len(arguments.get("columns", [])) + return f"{count} columns" + + if tool_name in ("add_column", "modify_column", "delete_column"): + return "1 column" + + return "-" + + def truncate_token(token: str) -> str: """Truncate token to show first 3 and last 3 chars. diff --git a/tests/unit/test_logging.py b/tests/unit/test_logging.py index fbc5e55..c750936 100644 --- a/tests/unit/test_logging.py +++ b/tests/unit/test_logging.py @@ -1,6 +1,6 @@ """Unit tests for logging module.""" -from grist_mcp.logging import truncate_token +from grist_mcp.logging import truncate_token, extract_stats class TestTruncateToken: @@ -22,3 +22,52 @@ class TestTruncateToken: def test_boundary_token_shows_prefix_suffix(self): token = "abcdefghi" # 9 chars - first to show truncation assert truncate_token(token) == "abc...ghi" + + +class TestExtractStats: + def test_list_documents(self): + result = {"documents": [{"name": "a"}, {"name": "b"}, {"name": "c"}]} + assert extract_stats("list_documents", {}, result) == "3 docs" + + def test_list_tables(self): + result = {"tables": ["Orders", "Products"]} + assert extract_stats("list_tables", {}, result) == "2 tables" + + def test_describe_table(self): + result = {"columns": [{"id": "A"}, {"id": "B"}]} + assert extract_stats("describe_table", {}, result) == "2 columns" + + def test_get_records(self): + result = {"records": [{"id": 1}, {"id": 2}]} + assert extract_stats("get_records", {}, result) == "2 records" + + def test_sql_query(self): + result = {"records": [{"a": 1}, {"a": 2}, {"a": 3}]} + assert extract_stats("sql_query", {}, result) == "3 rows" + + def test_add_records_from_args(self): + args = {"records": [{"a": 1}, {"a": 2}]} + assert extract_stats("add_records", args, {"ids": [1, 2]}) == "2 records" + + def test_update_records_from_args(self): + args = {"records": [{"id": 1, "fields": {}}, {"id": 2, "fields": {}}]} + assert extract_stats("update_records", args, {}) == "2 records" + + def test_delete_records_from_args(self): + args = {"record_ids": [1, 2, 3]} + assert extract_stats("delete_records", args, {}) == "3 records" + + def test_create_table(self): + args = {"columns": [{"id": "A"}, {"id": "B"}]} + assert extract_stats("create_table", args, {}) == "2 columns" + + def test_single_column_ops(self): + assert extract_stats("add_column", {}, {}) == "1 column" + assert extract_stats("modify_column", {}, {}) == "1 column" + assert extract_stats("delete_column", {}, {}) == "1 column" + + def test_empty_result_returns_zero(self): + assert extract_stats("list_documents", {}, {"documents": []}) == "0 docs" + + def test_unknown_tool(self): + assert extract_stats("unknown_tool", {}, {}) == "-"