Release 1.4 -> master (#524)

Catch up
This commit is contained in:
cybermaggedon 2025-09-20 16:00:37 +01:00 committed by GitHub
parent a8e437fc7f
commit 6c7af8789d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
216 changed files with 31360 additions and 1611 deletions

View file

@ -10,7 +10,7 @@ description = "TrustGraph provides a means to run a pipeline of flexible AI proc
readme = "README.md"
requires-python = ">=3.8"
dependencies = [
"trustgraph-base>=1.2,<1.3",
"trustgraph-base>=1.4,<1.5",
"requests",
"pulsar-client",
"aiohttp",
@ -43,7 +43,10 @@ tg-invoke-document-rag = "trustgraph.cli.invoke_document_rag:main"
tg-invoke-graph-rag = "trustgraph.cli.invoke_graph_rag:main"
tg-invoke-llm = "trustgraph.cli.invoke_llm:main"
tg-invoke-mcp-tool = "trustgraph.cli.invoke_mcp_tool:main"
tg-invoke-nlp-query = "trustgraph.cli.invoke_nlp_query:main"
tg-invoke-objects-query = "trustgraph.cli.invoke_objects_query:main"
tg-invoke-prompt = "trustgraph.cli.invoke_prompt:main"
tg-invoke-structured-query = "trustgraph.cli.invoke_structured_query:main"
tg-load-doc-embeds = "trustgraph.cli.load_doc_embeds:main"
tg-load-kg-core = "trustgraph.cli.load_kg_core:main"
tg-load-pdf = "trustgraph.cli.load_pdf:main"
@ -51,6 +54,7 @@ tg-load-sample-documents = "trustgraph.cli.load_sample_documents:main"
tg-load-text = "trustgraph.cli.load_text:main"
tg-load-turtle = "trustgraph.cli.load_turtle:main"
tg-load-knowledge = "trustgraph.cli.load_knowledge:main"
tg-load-structured-data = "trustgraph.cli.load_structured_data:main"
tg-put-flow-class = "trustgraph.cli.put_flow_class:main"
tg-put-kg-core = "trustgraph.cli.put_kg_core:main"
tg-remove-library-document = "trustgraph.cli.remove_library_document:main"
@ -82,6 +86,9 @@ tg-list-config-items = "trustgraph.cli.list_config_items:main"
tg-get-config-item = "trustgraph.cli.get_config_item:main"
tg-put-config-item = "trustgraph.cli.put_config_item:main"
tg-delete-config-item = "trustgraph.cli.delete_config_item:main"
tg-list-collections = "trustgraph.cli.list_collections:main"
tg-set-collection = "trustgraph.cli.set_collection:main"
tg-delete-collection = "trustgraph.cli.delete_collection:main"
[tool.setuptools.packages.find]
include = ["trustgraph*"]

View file

@ -0,0 +1,72 @@
"""
Delete a collection and all its data
"""
import argparse
import os
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = "trustgraph"
def delete_collection(url, user, collection, confirm):
if not confirm:
response = input(f"Are you sure you want to delete collection '{collection}' and all its data? (y/N): ")
if response.lower() not in ['y', 'yes']:
print("Operation cancelled.")
return
api = Api(url).collection()
api.delete_collection(user=user, collection=collection)
print(f"Collection '{collection}' deleted successfully.")
def main():
parser = argparse.ArgumentParser(
prog='tg-delete-collection',
description=__doc__,
)
parser.add_argument(
'collection',
help='Collection ID to delete'
)
parser.add_argument(
'-u', '--api-url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-y', '--yes',
action='store_true',
help='Skip confirmation prompt'
)
args = parser.parse_args()
try:
delete_collection(
url = args.api_url,
user = args.user,
collection = args.collection,
confirm = args.yes
)
except Exception as e:
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()

View file

@ -19,7 +19,7 @@ def delete_kg_core(url, user, id):
def main():
parser = argparse.ArgumentParser(
prog='tg-delete-flow-class',
prog='tg-delete-kg-core',
description=__doc__,
)
@ -56,4 +56,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -29,7 +29,7 @@ def output(text, prefix="> ", width=78):
async def question(
url, question, flow_id, user, collection,
plan=None, state=None, verbose=False
plan=None, state=None, group=None, verbose=False
):
if not url.endswith("/"):
@ -55,15 +55,24 @@ async def question(
async with connect(url) as ws:
req = json.dumps({
req = {
"id": mid,
"service": "agent",
"flow": flow_id,
"request": {
"question": question,
"user": user,
"history": []
}
}
# Only add optional fields if they have values
if state is not None:
req["request"]["state"] = state
if group is not None:
req["request"]["group"] = group
})
req = json.dumps(req)
await ws.send(req)
@ -140,6 +149,12 @@ def main():
help=f'Agent initial state (default: unspecified)'
)
parser.add_argument(
'-g', '--group',
nargs='+',
help='Agent tool groups (can specify multiple)'
)
parser.add_argument(
'-v', '--verbose',
action="store_true",
@ -159,6 +174,7 @@ def main():
collection = args.collection,
plan = args.plan,
state = args.state,
group = args.group,
verbose = args.verbose,
)
)

View file

@ -0,0 +1,111 @@
"""
Uses the NLP Query service to convert natural language questions to GraphQL queries
"""
import argparse
import os
import json
import sys
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
def nlp_query(url, flow_id, question, max_results, output_format='json'):
api = Api(url).flow().id(flow_id)
resp = api.nlp_query(
question=question,
max_results=max_results
)
# Check for errors
if "error" in resp and resp["error"]:
print("Error:", resp["error"].get("message", "Unknown error"), file=sys.stderr)
sys.exit(1)
# Format output based on requested format
if output_format == 'json':
print(json.dumps(resp, indent=2))
elif output_format == 'graphql':
# Just print the GraphQL query
if "graphql_query" in resp:
print(resp["graphql_query"])
else:
print("No GraphQL query generated", file=sys.stderr)
sys.exit(1)
elif output_format == 'summary':
# Print a human-readable summary
if "graphql_query" in resp:
print(f"Generated GraphQL Query:")
print("-" * 40)
print(resp["graphql_query"])
print("-" * 40)
if "detected_schemas" in resp and resp["detected_schemas"]:
print(f"Detected Schemas: {', '.join(resp['detected_schemas'])}")
if "confidence" in resp:
print(f"Confidence: {resp['confidence']:.2%}")
if "variables" in resp and resp["variables"]:
print(f"Variables: {json.dumps(resp['variables'], indent=2)}")
else:
print("No GraphQL query generated", file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(
prog='tg-invoke-nlp-query',
description=__doc__,
)
parser.add_argument(
'-u', '--url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
)
parser.add_argument(
'-q', '--question',
required=True,
help='Natural language question to convert to GraphQL',
)
parser.add_argument(
'-m', '--max-results',
type=int,
default=100,
help='Maximum number of results (default: 100)'
)
parser.add_argument(
'--format',
choices=['json', 'graphql', 'summary'],
default='summary',
help='Output format (default: summary)'
)
args = parser.parse_args()
try:
nlp_query(
url=args.url,
flow_id=args.flow_id,
question=args.question,
max_results=args.max_results,
output_format=args.format,
)
except Exception as e:
print("Exception:", e, flush=True, file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,201 @@
"""
Uses the ObjectsQuery service to execute GraphQL queries against structured data
"""
import argparse
import os
import json
import sys
import csv
import io
from trustgraph.api import Api
from tabulate import tabulate
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_collection = 'default'
def format_output(data, output_format):
"""Format GraphQL response data in the specified format"""
if not data:
return "No data returned"
# Handle case where data contains multiple query results
if len(data) == 1:
# Single query result - extract the list
query_name, result_list = next(iter(data.items()))
if isinstance(result_list, list):
return format_table_data(result_list, query_name, output_format)
# Multiple queries or non-list data - use JSON format
if output_format == 'json':
return json.dumps(data, indent=2)
else:
return json.dumps(data, indent=2) # Fallback to JSON
def format_table_data(rows, table_name, output_format):
"""Format a list of rows in the specified format"""
if not rows:
return f"No {table_name} found"
if output_format == 'json':
return json.dumps({table_name: rows}, indent=2)
elif output_format == 'csv':
# Get field names in order from first row, then add any missing ones
fieldnames = list(rows[0].keys()) if rows else []
# Add any additional fields from other rows that might be missing
all_fields = set(fieldnames)
for row in rows:
for field in row.keys():
if field not in all_fields:
fieldnames.append(field)
all_fields.add(field)
# Create CSV string
output = io.StringIO()
writer = csv.DictWriter(output, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
return output.getvalue().rstrip()
elif output_format == 'table':
# Get field names in order from first row, then add any missing ones
fieldnames = list(rows[0].keys()) if rows else []
# Add any additional fields from other rows that might be missing
all_fields = set(fieldnames)
for row in rows:
for field in row.keys():
if field not in all_fields:
fieldnames.append(field)
all_fields.add(field)
# Create table data
table_data = []
for row in rows:
table_row = [row.get(field, '') for field in fieldnames]
table_data.append(table_row)
return tabulate(table_data, headers=fieldnames, tablefmt='pretty')
else:
return json.dumps({table_name: rows}, indent=2)
def objects_query(
url, flow_id, query, user, collection, variables, operation_name, output_format='table'
):
api = Api(url).flow().id(flow_id)
# Parse variables if provided as JSON string
parsed_variables = {}
if variables:
try:
parsed_variables = json.loads(variables)
except json.JSONDecodeError as e:
print(f"Error parsing variables JSON: {e}", file=sys.stderr)
sys.exit(1)
resp = api.objects_query(
query=query,
user=user,
collection=collection,
variables=parsed_variables if parsed_variables else None,
operation_name=operation_name
)
# Check for GraphQL errors
if "errors" in resp and resp["errors"]:
print("GraphQL Errors:", file=sys.stderr)
for error in resp["errors"]:
print(f" - {error.get('message', 'Unknown error')}", file=sys.stderr)
if "path" in error and error["path"]:
print(f" Path: {error['path']}", file=sys.stderr)
# Still print data if available
if "data" in resp and resp["data"]:
print(format_output(resp["data"], output_format))
sys.exit(1)
# Print the data
if "data" in resp:
print(format_output(resp["data"], output_format))
else:
print("No data returned", file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(
prog='tg-invoke-objects-query',
description=__doc__,
)
parser.add_argument(
'-u', '--url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
)
parser.add_argument(
'-q', '--query',
required=True,
help='GraphQL query to execute',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
help=f'Collection ID (default: {default_collection})'
)
parser.add_argument(
'-v', '--variables',
help='GraphQL variables as JSON string (e.g., \'{"limit": 5}\')'
)
parser.add_argument(
'-o', '--operation-name',
help='Operation name for multi-operation GraphQL documents'
)
parser.add_argument(
'--format',
choices=['table', 'json', 'csv'],
default='table',
help='Output format (default: table)'
)
args = parser.parse_args()
try:
objects_query(
url=args.url,
flow_id=args.flow_id,
query=args.query,
user=args.user,
collection=args.collection,
variables=args.variables,
operation_name=args.operation_name,
output_format=args.format,
)
except Exception as e:
print("Exception:", e, flush=True, file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,173 @@
"""
Uses the Structured Query service to execute natural language questions against structured data
"""
import argparse
import os
import json
import sys
import csv
import io
from trustgraph.api import Api
from tabulate import tabulate
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
def format_output(data, output_format):
"""Format structured query response data in the specified format"""
if not data:
return "No data returned"
# Handle case where data contains multiple query results
if isinstance(data, dict) and len(data) == 1:
# Single query result - extract the list
query_name, result_list = next(iter(data.items()))
if isinstance(result_list, list):
return format_table_data(result_list, query_name, output_format)
# Multiple queries or non-list data - use JSON format
if output_format == 'json':
return json.dumps(data, indent=2)
else:
return json.dumps(data, indent=2) # Fallback to JSON
def format_table_data(rows, table_name, output_format):
"""Format a list of rows in the specified format"""
if not rows:
return f"No {table_name} found"
if output_format == 'json':
return json.dumps({table_name: rows}, indent=2)
elif output_format == 'csv':
# Get field names in order from first row, then add any missing ones
fieldnames = list(rows[0].keys()) if rows else []
# Add any additional fields from other rows that might be missing
all_fields = set(fieldnames)
for row in rows:
for field in row.keys():
if field not in all_fields:
fieldnames.append(field)
all_fields.add(field)
# Create CSV string
output = io.StringIO()
writer = csv.DictWriter(output, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
return output.getvalue().rstrip()
elif output_format == 'table':
# Get field names in order from first row, then add any missing ones
fieldnames = list(rows[0].keys()) if rows else []
# Add any additional fields from other rows that might be missing
all_fields = set(fieldnames)
for row in rows:
for field in row.keys():
if field not in all_fields:
fieldnames.append(field)
all_fields.add(field)
# Create table data
table_data = []
for row in rows:
table_row = [row.get(field, '') for field in fieldnames]
table_data.append(table_row)
return tabulate(table_data, headers=fieldnames, tablefmt='pretty')
else:
return json.dumps({table_name: rows}, indent=2)
def structured_query(url, flow_id, question, user='trustgraph', collection='default', output_format='table'):
api = Api(url).flow().id(flow_id)
resp = api.structured_query(question=question, user=user, collection=collection)
# Check for errors
if "error" in resp and resp["error"]:
print("Error:", resp["error"].get("message", "Unknown error"), file=sys.stderr)
sys.exit(1)
# Check for query errors
if "errors" in resp and resp["errors"]:
print("Query Errors:", file=sys.stderr)
for error in resp["errors"]:
print(f" - {error}", file=sys.stderr)
# Still print data if available
if "data" in resp and resp["data"]:
print(format_output(resp["data"], output_format))
sys.exit(1)
# Print the data
if "data" in resp:
print(format_output(resp["data"], output_format))
else:
print("No data returned", file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(
prog='tg-invoke-structured-query',
description=__doc__,
)
parser.add_argument(
'-u', '--url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
)
parser.add_argument(
'-q', '--question',
required=True,
help='Natural language question to execute',
)
parser.add_argument(
'--user',
default='trustgraph',
help='Cassandra keyspace identifier (default: trustgraph)'
)
parser.add_argument(
'--collection',
default='default',
help='Data collection identifier (default: default)'
)
parser.add_argument(
'--format',
choices=['table', 'json', 'csv'],
default='table',
help='Output format (default: table)'
)
args = parser.parse_args()
try:
structured_query(
url=args.url,
flow_id=args.flow_id,
question=args.question,
user=args.user,
collection=args.collection,
output_format=args.format,
)
except Exception as e:
print("Exception:", e, flush=True, file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,86 @@
"""
List collections for a user
"""
import argparse
import os
import tabulate
from trustgraph.api import Api
import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = "trustgraph"
def list_collections(url, user, tag_filter):
api = Api(url).collection()
collections = api.list_collections(user=user, tag_filter=tag_filter)
# Handle None or empty collections
if not collections or len(collections) == 0:
print("No collections found.")
return
table = []
for collection in collections:
table.append([
collection.collection,
collection.name,
collection.description,
", ".join(collection.tags),
collection.created_at,
collection.updated_at
])
headers = ["Collection", "Name", "Description", "Tags", "Created", "Updated"]
print(tabulate.tabulate(
table,
headers=headers,
tablefmt="pretty",
stralign="left",
maxcolwidths=[20, 30, 50, 30, 19, 19],
))
def main():
parser = argparse.ArgumentParser(
prog='tg-list-collections',
description=__doc__,
)
parser.add_argument(
'-u', '--api-url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-t', '--tag-filter',
action='append',
help='Filter by tags (can be specified multiple times)'
)
args = parser.parse_args()
try:
list_collections(
url = args.api_url,
user = args.user,
tag_filter = args.tag_filter
)
except Exception as e:
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()

View file

@ -24,7 +24,7 @@ def load_kg_core(url, user, id, flow, collection):
def main():
parser = argparse.ArgumentParser(
prog='tg-delete-flow-class',
prog='tg-load-kg-core',
description=__doc__,
)
@ -53,7 +53,7 @@ def main():
)
parser.add_argument(
'-c', '--collection',
'-C', '--collection',
default=default_collection,
help=f'Collection ID (default: {default_collection}',
)
@ -75,4 +75,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,103 @@
"""
Set collection metadata (creates if doesn't exist)
"""
import argparse
import os
import tabulate
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = "trustgraph"
def set_collection(url, user, collection, name, description, tags):
api = Api(url).collection()
result = api.update_collection(
user=user,
collection=collection,
name=name,
description=description,
tags=tags
)
if result:
print(f"Collection '{collection}' set successfully.")
table = []
table.append(("Collection", result.collection))
table.append(("Name", result.name))
table.append(("Description", result.description))
table.append(("Tags", ", ".join(result.tags)))
table.append(("Updated", result.updated_at))
print(tabulate.tabulate(
table,
tablefmt="pretty",
stralign="left",
maxcolwidths=[None, 67],
))
else:
print(f"Failed to set collection '{collection}'.")
def main():
parser = argparse.ArgumentParser(
prog='tg-set-collection',
description=__doc__,
)
parser.add_argument(
'collection',
help='Collection ID to set'
)
parser.add_argument(
'-u', '--api-url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-n', '--name',
help='Collection name'
)
parser.add_argument(
'-d', '--description',
help='Collection description'
)
parser.add_argument(
'-t', '--tag',
action='append',
dest='tags',
help='Collection tags (can be specified multiple times)'
)
args = parser.parse_args()
try:
set_collection(
url = args.api_url,
user = args.user,
collection = args.collection,
name = args.name,
description = args.description,
tags = args.tags
)
except Exception as e:
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()

View file

@ -3,6 +3,7 @@ Configures and registers tools in the TrustGraph system.
This script allows you to define agent tools with various types including:
- knowledge-query: Query knowledge bases
- structured-query: Query structured data using natural language
- text-completion: Text generation
- mcp-tool: Reference to MCP (Model Context Protocol) tools
- prompt: Prompt template execution
@ -63,6 +64,9 @@ def set_tool(
collection : str,
template : str,
arguments : List[Argument],
group : List[str],
state : str,
applicable_states : List[str],
):
api = Api(url).config()
@ -93,6 +97,12 @@ def set_tool(
for a in arguments
]
if group is not None: object["group"] = group
if state: object["state"] = state
if applicable_states is not None: object["applicable-states"] = applicable_states
values = api.put([
ConfigValue(
type="tool", key=f"{id}", value=json.dumps(object)
@ -108,21 +118,29 @@ def main():
description=__doc__,
epilog=textwrap.dedent('''
Valid tool types:
knowledge-query - Query knowledge bases
text-completion - Text completion/generation
mcp-tool - Model Control Protocol tool
prompt - Prompt template query
knowledge-query - Query knowledge bases (fixed args)
structured-query - Query structured data using natural language (fixed args)
text-completion - Text completion/generation (fixed args)
mcp-tool - Model Control Protocol tool (configurable args)
prompt - Prompt template query (configurable args)
Note: Tools marked "(fixed args)" have predefined arguments and don't need
--argument specified. Tools marked "(configurable args)" require --argument.
Valid argument types:
string - String/text parameter
string - String/text parameter
number - Numeric parameter
Examples:
%(prog)s --id weather_tool --name get_weather \\
--type knowledge-query \\
--description "Get weather information for a location" \\
--argument location:string:"Location to query" \\
--argument units:string:"Temperature units (C/F)"
--collection weather_data
%(prog)s --id data_query_tool --name query_data \\
--type structured-query \\
--description "Query structured data using natural language" \\
--collection sales_data
%(prog)s --id calc_tool --name calculate --type mcp-tool \\
--description "Perform mathematical calculations" \\
@ -155,7 +173,7 @@ def main():
parser.add_argument(
'--type',
help=f'Tool type, one of: knowledge-query, text-completion, mcp-tool, prompt',
help=f'Tool type, one of: knowledge-query, structured-query, text-completion, mcp-tool, prompt',
)
parser.add_argument(
@ -165,7 +183,7 @@ def main():
parser.add_argument(
'--collection',
help=f'For knowledge-query type: collection to query',
help=f'For knowledge-query and structured-query types: collection to query',
)
parser.add_argument(
@ -179,12 +197,29 @@ def main():
help=f'Tool arguments in the form: name:type:description (can specify multiple)',
)
parser.add_argument(
'--group',
nargs="*",
help=f'Tool groups (e.g., read-only, knowledge, admin)',
)
parser.add_argument(
'--state',
help=f'State to transition to after successful execution',
)
parser.add_argument(
'--applicable-states',
nargs="*",
help=f'States in which this tool is available',
)
args = parser.parse_args()
try:
valid_types = [
"knowledge-query", "text-completion", "mcp-tool", "prompt"
"knowledge-query", "structured-query", "text-completion", "mcp-tool", "prompt"
]
if args.id is None:
@ -219,6 +254,9 @@ def main():
collection=args.collection,
template=args.template,
arguments=arguments,
group=args.group,
state=args.state,
applicable_states=args.applicable_states,
)
except Exception as e:

View file

@ -3,6 +3,7 @@ Displays the current agent tool configurations
Shows all configured tools including their types:
- knowledge-query: Tools that query knowledge bases
- structured-query: Tools that query structured data using natural language
- text-completion: Tools for text generation
- mcp-tool: References to MCP (Model Context Protocol) tools
- prompt: Tools that execute prompt templates
@ -40,8 +41,9 @@ def show_config(url):
if tp == "mcp-tool":
table.append(("mcp-tool", data["mcp-tool"]))
if tp == "knowledge-query":
table.append(("collection", data["collection"]))
if tp == "knowledge-query" or tp == "structured-query":
if "collection" in data:
table.append(("collection", data["collection"]))
if tp == "prompt":
table.append(("template", data["template"]))
@ -50,6 +52,29 @@ def show_config(url):
f"arg {n}",
f"{arg['name']}: {arg['type']}\n{arg['description']}"
))
# Display group information
if "group" in data:
groups = data["group"]
if groups:
table.append(("groups", ", ".join(groups)))
else:
table.append(("groups", "(empty - no groups)"))
# Display state transition information
if "state" in data:
table.append(("next state", data["state"]))
# Display applicable states
if "applicable-states" in data:
states = data["applicable-states"]
if states:
if "*" in states:
table.append(("available in", "all states"))
else:
table.append(("available in", ", ".join(states)))
else:
table.append(("available in", "(empty - never available)"))
print()

View file

@ -23,7 +23,7 @@ def unload_kg_core(url, user, id, flow):
def main():
parser = argparse.ArgumentParser(
prog='tg-delete-flow-class',
prog='tg-unload-kg-core',
description=__doc__,
)
@ -67,4 +67,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()