Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
639 changes: 307 additions & 332 deletions skill_analytics/README.md

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions skill_analytics/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
WxA Analyzer CLI Module

This module provides command-line interface tools for analyzing watsonx Assistant instances.
"""

__version__ = "0.1.0"
126 changes: 126 additions & 0 deletions skill_analytics/cli/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""
Main CLI entry point for wxa-analyze.

This module provides a unified command-line interface for all analysis commands.
"""

import sys
from argparse import ArgumentParser


def main():
"""Main entry point for the wxa-analyze CLI."""
parser = ArgumentParser(
prog="wxa-analyze",
description="Analyze and search various aspects of a watsonx Assistant instance",
epilog="Use 'wxa-analyze <command> --help' for more information on a specific command."
)

subparsers = parser.add_subparsers(
title="Available commands",
dest="command",
help="Command to run",
required=True,
metavar="<command>"
)

# Define all available commands
commands = {
"action-metadata": {
"module": "cli.action_metadata",
"help": "Extract metadata for all actions in the assistant"
},
"assistant-metadata": {
"module": "cli.assistant_metadata",
"help": "Extract comprehensive metadata about the assistant"
},
"condition-usage": {
"module": "cli.condition_usage",
"help": "Report all conditions used in action steps"
},
"context-usage": {
"module": "cli.context_usage",
"help": "Report all context statements used in action steps"
},
"customer-response-settings": {
"module": "cli.customer_response_settings",
"help": "Extract customer response settings for action steps"
},
"entity-metadata": {
"module": "cli.entity_metadata",
"help": "Extract metadata for all entities defined in the assistant"
},
"entity-usage": {
"module": "cli.entity_usage",
"help": "Find where entities are used throughout the assistant"
},
"extension-usage": {
"module": "cli.extension_usage",
"help": "Find all custom extension calls in the assistant"
},
"intent-usage": {
"module": "cli.intent_usage",
"help": "Find where intents are used in action conditions and step handlers"
},
"response-usage": {
"module": "cli.response_usage",
"help": "Report all customer response types used in action steps"
},
"subaction-usage": {
"module": "cli.subaction_usage",
"help": "Find all subaction invocations in the assistant"
},
"validation-settings": {
"module": "cli.validation_settings",
"help": "Extract validation settings for action steps"
},
"variable-metadata": {
"module": "cli.variable_metadata",
"help": "Extract metadata for all variables defined in the assistant"
},
"variable-usage": {
"module": "cli.variable_usage",
"help": "Find where variables are used throughout the assistant"
},
}

# Add subparsers for each command
for cmd_name, cmd_info in commands.items():
subparsers.add_parser(
cmd_name,
help=cmd_info["help"],
add_help=False # Let the actual module handle help
)

# Parse only the command name first
args, remaining = parser.parse_known_args()

# Get the module for the selected command
if args.command in commands:
module_name = commands[args.command]["module"]

# Import and run the command's main function
try:
# Restore sys.argv to include the remaining arguments
sys.argv = [f"wxa-analyze {args.command}"] + remaining

# Import the module dynamically
import importlib
module = importlib.import_module(module_name)

# Run the main function
module.main()
except ImportError as e:
print(f"Error: Could not import module '{module_name}': {e}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Error running command '{args.command}': {e}", file=sys.stderr)
sys.exit(1)
else:
parser.print_help()
sys.exit(1)


if __name__ == "__main__":
main()
60 changes: 0 additions & 60 deletions skill_analytics/cli/action_contents.py

This file was deleted.

55 changes: 55 additions & 0 deletions skill_analytics/cli/action_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from argparse import ArgumentParser

from config.config import get_config
from src.analyzers import ActionAnalyzer
from src.models.assistant import Assistant

from .utils.file_path_helper import (
create_directory,
get_assistant_json,
get_output_save_path,
)


def main():
cfg = get_config()

parser = ArgumentParser(
description="Extract metadata for all actions in the assistant",
epilog="Example: python -m cli.action_metadata -i assistant.json -o ./reports"
)
parser.add_argument(
'-i', '--assistant_json_path',
required=False,
default=cfg["assistant_json_directory"],
type=str,
metavar='PATH',
help=f'Path to the watsonx Assistant JSON file. Default: {cfg["assistant_json_directory"]}'
)
parser.add_argument(
'-o', '--output_path',
required=False,
default=cfg["output_directory"],
type=str,
metavar='PATH',
help=f'Directory where the CSV output will be saved. Default: {cfg["output_directory"]}'
)
args = parser.parse_args()

assistant_dict = get_assistant_json(args.assistant_json_path)
assistant = Assistant.from_dict(assistant_dict)
action_analyzer = ActionAnalyzer(assistant)

action_metadata_df = action_analyzer.action_metadata(return_as="dataframe")

action_metadata_df = action_metadata_df.sort_values("action_id")

default_file_name = "action_metadata.csv"
create_directory(args.output_path)
output_path = get_output_save_path(args.output_path, default_file_name)
action_metadata_df.to_csv(output_path, index=False)

print(f"Action metadata saved to: {output_path}")

if __name__ == "__main__":
main()
31 changes: 0 additions & 31 deletions skill_analytics/cli/action_settings.py

This file was deleted.

61 changes: 61 additions & 0 deletions skill_analytics/cli/assistant_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import json
from argparse import ArgumentParser

from config.config import get_config
from src.analyzers import AssistantAnalyzer
from src.models.assistant import Assistant

from .utils.file_path_helper import (
create_directory,
get_assistant_json,
get_output_save_path,
)


def main():
cfg = get_config()

parser = ArgumentParser(
description="Extract comprehensive metadata about the assistant including IDs, settings, and aggregated statistics",
epilog="Example: python -m cli.assistant_metadata -i assistant.json -o ./reports"
)
parser.add_argument(
'-i', '--assistant_json_path',
required=False,
default=cfg["assistant_json_directory"],
type=str,
metavar='PATH',
help=f'Path to the watsonx Assistant JSON file. Default: {cfg["assistant_json_directory"]}'
)
parser.add_argument(
'-o', '--output_path',
required=False,
default=cfg["output_directory"],
type=str,
metavar='PATH',
help=f'Directory where the JSON output will be saved. Default: {cfg["output_directory"]}'
)
args = parser.parse_args()

assistant_dict = get_assistant_json(args.assistant_json_path)
assistant = Assistant.from_dict(assistant_dict)
assistant_analyzer = AssistantAnalyzer(assistant)

# Get metadata as Python dict (list with single dict)
assistant_metadata = assistant_analyzer.assistant_metadata(return_as="python")

# Since there's only one assistant, extract the single dict from the list
metadata_dict = assistant_metadata[0] if assistant_metadata else {}

default_file_name = "assistant_metadata.json"
create_directory(args.output_path)
output_path = get_output_save_path(args.output_path, default_file_name)

# Write as formatted JSON
with open(output_path, 'w') as f:
json.dump(metadata_dict, f, indent=2)

print(f"Assistant metadata saved to: {output_path}")

if __name__ == "__main__":
main()
Loading