release/v2.4 -> master (#844)

This commit is contained in:
cybermaggedon 2026-04-22 15:19:57 +01:00 committed by GitHub
parent a24df8e990
commit 89cabee1b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
386 changed files with 7202 additions and 5741 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>=2.3,<2.4",
"trustgraph-base>=2.4,<2.5",
"requests",
"pulsar-client",
"aiohttp",
@ -95,6 +95,8 @@ 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-export-workspace-config = "trustgraph.cli.export_workspace_config:main"
tg-import-workspace-config = "trustgraph.cli.import_workspace_config: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"

View file

@ -15,17 +15,17 @@ from trustgraph.knowledge import Organization, PublicationEvent
from trustgraph.knowledge import DigitalDocument
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
class Loader:
def __init__(
self, id, url, user, metadata, title, comments, kind, tags
):
self, id, url, metadata, title, comments, kind, tags
, token=None, workspace="default"):
self.api = Api(url).library()
self.api = Api(url, token=token, workspace=workspace).library()
self.user = user
self.metadata = metadata
self.title = title
self.comments = comments
@ -55,13 +55,13 @@ class Loader:
else:
id = hash(data)
id = to_uri(PREF_DOC, id)
self.metadata.id = id
self.api.add_document(
document=data, id=id, metadata=self.metadata,
user=self.user, kind=self.kind, title=self.title,
document=data, id=id, metadata=self.metadata,
kind=self.kind, title=self.title,
comments=self.comments, tags=self.tags
)
@ -83,11 +83,16 @@ def main():
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -186,12 +191,13 @@ def main():
p = Loader(
id=args.identifier,
url=args.url,
user=args.user,
metadata=document,
title=args.name,
comments=args.description,
kind=args.kind,
tags=args.tags,
token=args.token,
workspace=args.workspace,
)
p.load(args.files)

View file

@ -7,9 +7,11 @@ import os
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = "trustgraph"
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def delete_collection(url, user, collection, confirm):
def delete_collection(url, collection, confirm, token=None, workspace="default"):
if not confirm:
response = input(f"Are you sure you want to delete collection '{collection}' and all its data? (y/N): ")
@ -17,9 +19,9 @@ def delete_collection(url, user, collection, confirm):
print("Operation cancelled.")
return
api = Api(url).collection()
api = Api(url, token=token, workspace=workspace).collection()
api.delete_collection(user=user, collection=collection)
api.delete_collection(collection=collection)
print(f"Collection '{collection}' deleted successfully.")
@ -41,27 +43,34 @@ def main():
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'
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
delete_collection(
url = args.api_url,
user = args.user,
collection = args.collection,
confirm = args.yes
confirm = args.yes,
token = args.token,
workspace = args.workspace,
)
except Exception as e:
@ -69,4 +78,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -9,10 +9,11 @@ from trustgraph.api.types import ConfigKey
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def delete_config_item(url, config_type, key, token=None):
def delete_config_item(url, config_type, key, token=None, workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
config_key = ConfigKey(type=config_type, key=key)
api.delete([config_key])
@ -50,6 +51,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -59,6 +66,8 @@ def main():
config_type=args.type,
key=args.key,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,10 +9,13 @@ from trustgraph.api import Api
import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def delete_flow_blueprint(url, blueprint_name):
def delete_flow_blueprint(url, blueprint_name, token=None,
workspace="default"):
api = Api(url).flow()
api = Api(url, token=token, workspace=workspace).flow()
blueprint_names = api.delete_blueprint(blueprint_name)
@ -29,6 +32,18 @@ def main():
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-n', '--blueprint-name',
help=f'Flow blueprint name',
@ -41,6 +56,8 @@ def main():
delete_flow_blueprint(
url=args.api_url,
blueprint_name=args.blueprint_name,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -1,20 +1,20 @@
"""
Deletes a flow class
Deletes a knowledge core
"""
import argparse
import os
import tabulate
from trustgraph.api import Api
import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def delete_kg_core(url, user, id):
def delete_kg_core(url, id, token=None, workspace="default"):
api = Api(url).knowledge()
api = Api(url, token=token, workspace=workspace).knowledge()
class_names = api.delete_kg_core(user = user, id = id)
api.delete_kg_core(id=id)
def main():
@ -29,26 +29,33 @@ def main():
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-U', '--user',
default="trustgraph",
help='API URL (default: trustgraph)',
)
parser.add_argument(
'--id', '--identifier',
required=True,
help=f'Knowledge core ID',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
delete_kg_core(
url=args.api_url,
user=args.user,
id=args.id,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -10,12 +10,16 @@ import textwrap
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def delete_mcp_tool(
url : str,
id : str,
token=None,
workspace="default",
):
api = Api(url).config()
api = Api(url, token=token, workspace=workspace).config()
# Check if the tool exists first
try:
@ -73,6 +77,18 @@ def main():
help='MCP tool ID to delete',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -81,8 +97,10 @@ def main():
raise RuntimeError("Must specify --id for MCP tool to delete")
delete_mcp_tool(
url=args.api_url,
id=args.id
url=args.api_url,
id=args.id,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -12,12 +12,16 @@ import textwrap
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def delete_tool(
url : str,
id : str,
token=None,
workspace="default",
):
api = Api(url).config()
api = Api(url, token=token, workspace=workspace).config()
# Check if the tool configuration exists
try:
@ -78,6 +82,18 @@ def main():
help='Tool ID to delete',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -86,8 +102,10 @@ def main():
raise RuntimeError("Must specify --id for tool to delete")
delete_tool(
url=args.api_url,
id=args.id
url=args.api_url,
id=args.id,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -0,0 +1,114 @@
"""
Exports a curated subset of a workspace's configuration to a JSON file
for later reload into another workspace (useful for cloning test setups).
The subset covers the config types that define workspace behaviour:
mcp-tool, tool, flow-blueprint, token-cost, agent-pattern,
agent-task-type, parameter-type, interface-description, prompt.
"""
import argparse
import os
import json
import sys
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
EXPORT_TYPES = [
"mcp-tool",
"tool",
"flow-blueprint",
"token-cost",
"agent-pattern",
"agent-task-type",
"parameter-type",
"interface-description",
"prompt",
]
def export_workspace_config(url, workspace, output, token=None):
api = Api(url, token=token, workspace=workspace).config()
config, version = api.all()
subset = {}
for t in EXPORT_TYPES:
if t in config:
subset[t] = config[t]
payload = {
"source_workspace": workspace,
"source_version": version,
"config": subset,
}
if output == "-":
json.dump(payload, sys.stdout, indent=2)
sys.stdout.write("\n")
else:
with open(output, "w") as f:
json.dump(payload, f, indent=2)
total = sum(len(v) for v in subset.values())
print(
f"Exported {total} items across {len(subset)} types "
f"from workspace '{workspace}' (version {version}).",
file=sys.stderr,
)
def main():
parser = argparse.ArgumentParser(
prog='tg-export-workspace-config',
description=__doc__,
)
parser.add_argument(
'-u', '--api-url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Source workspace (default: {default_workspace})',
)
parser.add_argument(
'-o', '--output',
required=True,
help='Output JSON file path (use "-" for stdout)',
)
args = parser.parse_args()
try:
export_workspace_config(
url=args.api_url,
workspace=args.workspace,
output=args.output,
token=args.token,
)
except Exception as e:
print("Exception:", e, flush=True)
sys.exit(1)
if __name__ == "__main__":
main()

View file

@ -10,10 +10,12 @@ from trustgraph.api.types import ConfigKey
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def get_config_item(url, config_type, key, format_type, token=None):
def get_config_item(url, config_type, key, format_type, token=None,
workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
config_key = ConfigKey(type=config_type, key=key)
values = api.get([config_key])
@ -66,6 +68,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -76,6 +84,7 @@ def main():
key=args.key,
format_type=args.format,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,21 +9,19 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = "trustgraph"
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def get_content(url, user, document_id, output_file, token=None):
def get_content(url, document_id, output_file, token=None, workspace="default"):
api = Api(url, token=token).library()
api = Api(url, token=token, workspace=workspace).library()
content = api.get_document_content(user=user, id=document_id)
content = api.get_document_content(id=document_id)
if output_file:
with open(output_file, 'wb') as f:
f.write(content)
print(f"Written {len(content)} bytes to {output_file}")
else:
# Write to stdout
# Try to decode as text, fall back to binary info
try:
text = content.decode('utf-8')
print(text)
@ -51,9 +49,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -73,10 +71,10 @@ def main():
get_content(
url=args.api_url,
user=args.user,
document_id=args.document_id,
output_file=args.output,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,10 +9,12 @@ from trustgraph.api import Api
import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def get_flow_blueprint(url, blueprint_name):
def get_flow_blueprint(url, blueprint_name, token=None, workspace="default"):
api = Api(url).flow()
api = Api(url, token=token, workspace=workspace).flow()
cls = api.get_blueprint(blueprint_name)
@ -31,6 +33,18 @@ def main():
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-n', '--blueprint-name',
required=True,
@ -44,6 +58,8 @@ def main():
get_flow_blueprint(
url=args.api_url,
blueprint_name=args.blueprint_name,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -5,7 +5,6 @@ to a local file in msgpack format.
import argparse
import os
import textwrap
import uuid
import asyncio
import json
@ -13,17 +12,16 @@ from websockets.asyncio.client import connect
import msgpack
default_url = os.getenv("TRUSTGRAPH_URL", 'ws://localhost:8088/')
default_user = 'trustgraph'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def write_triple(f, data):
msg = (
"t",
{
"m": {
"i": data["metadata"]["id"],
"i": data["metadata"]["id"],
"m": data["metadata"]["metadata"],
"u": data["metadata"]["user"],
"c": data["metadata"]["collection"],
},
"t": data["triples"],
@ -36,9 +34,8 @@ def write_ge(f, data):
"ge",
{
"m": {
"i": data["metadata"]["id"],
"i": data["metadata"]["id"],
"m": data["metadata"]["metadata"],
"u": data["metadata"]["user"],
"c": data["metadata"]["collection"],
},
"e": [
@ -52,7 +49,7 @@ def write_ge(f, data):
)
f.write(msgpack.packb(msg, use_bin_type=True))
async def fetch(url, user, id, output, token=None):
async def fetch(url, workspace, id, output, token=None):
if not url.endswith("/"):
url += "/"
@ -68,10 +65,11 @@ async def fetch(url, user, id, output, token=None):
req = json.dumps({
"id": mid,
"workspace": workspace,
"service": "knowledge",
"request": {
"operation": "get-kg-core",
"user": user,
"workspace": workspace,
"id": id,
}
})
@ -124,10 +122,11 @@ def main():
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})'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -154,11 +153,11 @@ def main():
asyncio.run(
fetch(
url = args.url,
user = args.user,
id = args.id,
output = args.output,
token = args.token,
url=args.url,
workspace=args.workspace,
id=args.id,
output=args.output,
token=args.token,
)
)
@ -167,4 +166,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -13,9 +13,9 @@ import os
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_collection = 'default'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def term_to_rdflib(term):
@ -58,9 +58,10 @@ def term_to_rdflib(term):
return rdflib.term.Literal(str(term))
def show_graph(url, flow_id, user, collection, limit, batch_size, token=None):
def show_graph(url, flow_id, collection, limit, batch_size,
token=None, workspace="default"):
socket = Api(url, token=token).socket()
socket = Api(url, token=token, workspace=workspace).socket()
flow = socket.flow(flow_id)
g = rdflib.Graph()
@ -68,7 +69,7 @@ def show_graph(url, flow_id, user, collection, limit, batch_size, token=None):
try:
for batch in flow.triples_query_stream(
s=None, p=None, o=None,
user=user, collection=collection,
collection=collection,
limit=limit,
batch_size=batch_size,
):
@ -108,12 +109,6 @@ def main():
help=f'Flow ID (default: default)'
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
@ -126,6 +121,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-l', '--limit',
type=int,
@ -147,11 +148,11 @@ def main():
show_graph(
url = args.api_url,
flow_id = args.flow_id,
user = args.user,
collection = args.collection,
limit = args.limit,
batch_size = args.batch_size,
token = args.token,
workspace = args.workspace,
)
except Exception as e:

View file

@ -0,0 +1,143 @@
"""
Imports a workspace-config dump produced by tg-export-workspace-config
into a target workspace. Writes mcp-tool, tool, flow-blueprint,
token-cost, agent-pattern, agent-task-type, parameter-type,
interface-description and prompt items verbatim.
Existing items with the same (type, key) are overwritten.
"""
import argparse
import os
import json
import sys
from trustgraph.api import Api
from trustgraph.api.types import ConfigValue
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
IMPORT_TYPES = {
"mcp-tool",
"tool",
"flow-blueprint",
"token-cost",
"agent-pattern",
"agent-task-type",
"parameter-type",
"interface-description",
"prompt",
}
def import_workspace_config(url, workspace, input_path, token=None,
dry_run=False):
if input_path == "-":
payload = json.load(sys.stdin)
else:
with open(input_path, "r") as f:
payload = json.load(f)
# Accept both the wrapped export format and a bare {type: {key: value}}
# dict, so hand-written files are also loadable.
if isinstance(payload, dict) and "config" in payload \
and isinstance(payload["config"], dict):
config = payload["config"]
source = payload.get("source_workspace")
else:
config = payload
source = None
skipped_types = set(config.keys()) - IMPORT_TYPES
if skipped_types:
print(
f"Ignoring unsupported types: {sorted(skipped_types)}",
file=sys.stderr,
)
values = []
for t in IMPORT_TYPES:
items = config.get(t, {})
for key, value in items.items():
values.append(ConfigValue(type=t, key=key, value=value))
if not values:
print("Nothing to import.", file=sys.stderr)
return
if dry_run:
print(
f"[dry-run] would import {len(values)} items into "
f"workspace '{workspace}'"
+ (f" (from '{source}')" if source else "")
)
return
api = Api(url, token=token, workspace=workspace).config()
api.put(values)
print(
f"Imported {len(values)} items into workspace '{workspace}'"
+ (f" (from '{source}')." if source else "."),
)
def main():
parser = argparse.ArgumentParser(
prog='tg-import-workspace-config',
description=__doc__,
)
parser.add_argument(
'-u', '--api-url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Target workspace (default: {default_workspace})',
)
parser.add_argument(
'-i', '--input',
required=True,
help='Input JSON file path (use "-" for stdin)',
)
parser.add_argument(
'--dry-run',
action='store_true',
help='Parse and validate the input without writing anything',
)
args = parser.parse_args()
try:
import_workspace_config(
url=args.api_url,
workspace=args.workspace,
input_path=args.input,
token=args.token,
dry_run=args.dry_run,
)
except Exception as e:
print("Exception:", e, flush=True)
sys.exit(1)
if __name__ == "__main__":
main()

View file

@ -69,10 +69,11 @@ def ensure_namespace(url, tenant, namespace, config):
print(f"Namespace {tenant}/{namespace} created.", flush=True)
def ensure_config(config, **pubsub_config):
def ensure_config(config, workspace="default", **pubsub_config):
cli = ConfigClient(
subscriber=subscriber,
workspace=workspace,
**pubsub_config,
)
@ -147,7 +148,8 @@ def init_pulsar(pulsar_admin_url, tenant):
})
def push_config(config_json, config_file, **pubsub_config):
def push_config(config_json, config_file, workspace="default",
**pubsub_config):
"""Push initial config if provided."""
if config_json is not None:
@ -160,7 +162,7 @@ def push_config(config_json, config_file, **pubsub_config):
print("Exception:", e, flush=True)
raise e
ensure_config(dec, **pubsub_config)
ensure_config(dec, workspace=workspace, **pubsub_config)
elif config_file is not None:
@ -172,7 +174,7 @@ def push_config(config_json, config_file, **pubsub_config):
print("Exception:", e, flush=True)
raise e
ensure_config(dec, **pubsub_config)
ensure_config(dec, workspace=workspace, **pubsub_config)
else:
print("No config to update.", flush=True)
@ -207,6 +209,12 @@ def main():
help=f'Tenant (default: tg)',
)
parser.add_argument(
'-w', '--workspace',
default="default",
help=f'Workspace (default: default)',
)
add_pubsub_args(parser)
args = parser.parse_args()
@ -216,7 +224,10 @@ def main():
# Extract pubsub config from args
pubsub_config = {
k: v for k, v in vars(args).items()
if k not in ('pulsar_admin_url', 'config', 'config_file', 'tenant')
if k not in (
'pulsar_admin_url', 'config', 'config_file', 'tenant',
'workspace',
)
}
while True:
@ -241,6 +252,7 @@ def main():
# Push config (works with any backend)
push_config(
args.config, args.config_file,
workspace=args.workspace,
**pubsub_config,
)

View file

@ -26,7 +26,7 @@ from trustgraph.api import (
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = 'trustgraph'
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
class Outputter:
@ -115,11 +115,12 @@ def output(text, prefix="> ", width=78):
print(out)
def question_explainable(
url, question_text, flow_id, user, collection,
state=None, group=None, verbose=False, token=None, debug=False
url, question_text, flow_id, collection,
state=None, group=None, verbose=False, token=None, debug=False,
workspace="default",
):
"""Execute agent with explainability - shows provenance events inline."""
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
explain_client = ExplainabilityClient(flow, retry_delay=0.2, max_retries=10)
@ -132,7 +133,6 @@ def question_explainable(
# Stream agent with explainability - process events as they arrive
for item in flow.agent_explain(
question=question_text,
user=user,
collection=collection,
state=state,
group=group,
@ -191,7 +191,6 @@ def question_explainable(
entity = explain_client.fetch_entity(
prov_id,
graph=explain_graph,
user=user,
collection=collection
)
@ -269,11 +268,11 @@ def question_explainable(
def question(
url, question, flow_id, user, collection,
url, question, flow_id, collection,
plan=None, state=None, group=None, pattern=None,
verbose=False, streaming=True,
token=None, explainable=False, debug=False,
show_usage=False
show_usage=False, workspace="default",
):
# Explainable mode uses the API to capture and process provenance events
if explainable:
@ -281,13 +280,13 @@ def question(
url=url,
question_text=question,
flow_id=flow_id,
user=user,
collection=collection,
state=state,
group=group,
verbose=verbose,
token=token,
debug=debug
debug=debug,
workspace=workspace,
)
return
@ -296,14 +295,13 @@ def question(
print()
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
# Prepare request parameters
request_params = {
"question": question,
"user": user,
"streaming": streaming,
}
@ -418,6 +416,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
@ -430,12 +434,6 @@ def main():
help=f'Question to answer',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
@ -502,7 +500,6 @@ def main():
url = args.url,
flow_id = args.flow_id,
question = args.question,
user = args.user,
collection = args.collection,
plan = args.plan,
state = args.state,
@ -514,6 +511,7 @@ def main():
explainable = args.explainable,
debug = args.debug,
show_usage = args.show_usage,
workspace = args.workspace,
)
except Exception as e:

View file

@ -9,11 +9,12 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def query(url, flow_id, query_text, user, collection, limit, token=None):
def query(url, flow_id, query_text, collection, limit, token=None, workspace="default"):
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
@ -21,7 +22,6 @@ def query(url, flow_id, query_text, user, collection, limit, token=None):
# Call document embeddings query service
result = flow.document_embeddings_query(
text=query_text,
user=user,
collection=collection,
limit=limit
)
@ -59,15 +59,15 @@ def main():
)
parser.add_argument(
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-U', '--user',
default="trustgraph",
help='User/keyspace (default: trustgraph)',
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
)
parser.add_argument(
@ -97,10 +97,10 @@ def main():
url=args.url,
flow_id=args.flow_id,
query_text=args.query[0],
user=args.user,
collection=args.collection,
limit=args.limit,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -18,16 +18,17 @@ from trustgraph.api import (
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = 'trustgraph'
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
default_doc_limit = 10
def question_explainable(
url, flow_id, question_text, user, collection, doc_limit, token=None, debug=False
url, flow_id, question_text, collection, doc_limit, token=None, debug=False,
workspace="default",
):
"""Execute document RAG with explainability - shows provenance events inline."""
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
explain_client = ExplainabilityClient(flow, retry_delay=0.2, max_retries=10)
@ -36,8 +37,7 @@ def question_explainable(
# Stream DocumentRAG with explainability - process events as they arrive
for item in flow.document_rag_explain(
query=question_text,
user=user,
collection=collection,
collection=collection,
doc_limit=doc_limit,
):
if isinstance(item, RAGChunk):
@ -54,8 +54,7 @@ def question_explainable(
entity = explain_client.fetch_entity(
prov_id,
graph=explain_graph,
user=user,
collection=collection
collection=collection
)
if entity is None:
@ -98,9 +97,9 @@ def question_explainable(
def question(
url, flow_id, question_text, user, collection, doc_limit,
url, flow_id, question_text, collection, doc_limit,
streaming=True, token=None, explainable=False, debug=False,
show_usage=False
show_usage=False, workspace="default",
):
# Explainable mode uses the API to capture and process provenance events
if explainable:
@ -108,16 +107,16 @@ def question(
url=url,
flow_id=flow_id,
question_text=question_text,
user=user,
collection=collection,
collection=collection,
doc_limit=doc_limit,
token=token,
debug=debug
debug=debug,
workspace=workspace,
)
return
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
if streaming:
# Use socket client for streaming
@ -127,8 +126,7 @@ def question(
try:
response = flow.document_rag(
query=question_text,
user=user,
collection=collection,
collection=collection,
doc_limit=doc_limit,
streaming=True
)
@ -155,8 +153,7 @@ def question(
flow = api.flow().id(flow_id)
result = flow.document_rag(
query=question_text,
user=user,
collection=collection,
collection=collection,
doc_limit=doc_limit,
)
print(result.text)
@ -189,6 +186,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
@ -201,12 +204,6 @@ def main():
help=f'Question to answer',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
@ -252,7 +249,6 @@ def main():
url=args.url,
flow_id=args.flow_id,
question_text=args.question,
user=args.user,
collection=args.collection,
doc_limit=args.doc_limit,
streaming=not args.no_streaming,
@ -260,6 +256,7 @@ def main():
explainable=args.explainable,
debug=args.debug,
show_usage=args.show_usage,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,11 +9,12 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def query(url, flow_id, texts, token=None):
def query(url, flow_id, texts, token=None, workspace="default"):
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
@ -51,6 +52,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
@ -72,6 +79,8 @@ def main():
flow_id=args.flow_id,
texts=args.texts,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,11 +9,12 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def query(url, flow_id, query_text, user, collection, limit, token=None):
def query(url, flow_id, query_text, collection, limit, token=None, workspace="default"):
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
@ -21,7 +22,6 @@ def query(url, flow_id, query_text, user, collection, limit, token=None):
# Call graph embeddings query service
result = flow.graph_embeddings_query(
text=query_text,
user=user,
collection=collection,
limit=limit
)
@ -69,15 +69,15 @@ def main():
)
parser.add_argument(
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-U', '--user',
default="trustgraph",
help='User/keyspace (default: trustgraph)',
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
)
parser.add_argument(
@ -107,10 +107,10 @@ def main():
url=args.url,
flow_id=args.flow_id,
query_text=args.query[0],
user=args.user,
collection=args.collection,
limit=args.limit,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -22,7 +22,7 @@ from trustgraph.api import (
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = 'trustgraph'
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
default_entity_limit = 50
default_triple_limit = 30
@ -108,7 +108,7 @@ def _format_provenance_details(event_type, triples):
return lines
async def _query_triples_once(ws_url, flow_id, prov_id, user, collection, graph=None, debug=False):
async def _query_triples_once(ws_url, flow_id, prov_id, collection, graph=None, debug=False):
"""Query triples for a provenance node (single attempt)"""
request = {
"id": "triples-request",
@ -116,7 +116,6 @@ async def _query_triples_once(ws_url, flow_id, prov_id, user, collection, graph=
"flow": flow_id,
"request": {
"s": {"t": "i", "i": prov_id},
"user": user,
"collection": collection,
"limit": 100
}
@ -182,10 +181,10 @@ async def _query_triples_once(ws_url, flow_id, prov_id, user, collection, graph=
return triples
async def _query_triples(ws_url, flow_id, prov_id, user, collection, graph=None, max_retries=5, retry_delay=0.2, debug=False):
async def _query_triples(ws_url, flow_id, prov_id, collection, graph=None, max_retries=5, retry_delay=0.2, debug=False):
"""Query triples for a provenance node with retries for race condition"""
for attempt in range(max_retries):
triples = await _query_triples_once(ws_url, flow_id, prov_id, user, collection, graph=graph, debug=debug)
triples = await _query_triples_once(ws_url, flow_id, prov_id, collection, graph=graph, debug=debug)
if triples:
return triples
# Wait before retry if empty (triples may not be stored yet)
@ -196,7 +195,7 @@ async def _query_triples(ws_url, flow_id, prov_id, user, collection, graph=None,
return []
async def _query_edge_provenance(ws_url, flow_id, edge_s, edge_p, edge_o, user, collection, debug=False):
async def _query_edge_provenance(ws_url, flow_id, edge_s, edge_p, edge_o, collection, debug=False):
"""
Query for provenance of an edge (s, p, o) in the knowledge graph.
@ -220,7 +219,6 @@ async def _query_edge_provenance(ws_url, flow_id, edge_s, edge_p, edge_o, user,
"o": {"t": "i", "i": edge_o} if edge_o.startswith("http") or edge_o.startswith("urn:") else {"t": "l", "v": edge_o},
}
},
"user": user,
"collection": collection,
"limit": 10
}
@ -273,7 +271,6 @@ async def _query_edge_provenance(ws_url, flow_id, edge_s, edge_p, edge_o, user,
"request": {
"s": {"t": "i", "i": stmt_uri},
"p": {"t": "i", "i": PROV_WAS_DERIVED_FROM},
"user": user,
"collection": collection,
"limit": 10
}
@ -312,7 +309,7 @@ async def _query_edge_provenance(ws_url, flow_id, edge_s, edge_p, edge_o, user,
return sources
async def _query_derived_from(ws_url, flow_id, uri, user, collection, debug=False):
async def _query_derived_from(ws_url, flow_id, uri, collection, debug=False):
"""Query for the prov:wasDerivedFrom parent of a URI. Returns None if no parent."""
request = {
"id": "parent-request",
@ -321,7 +318,6 @@ async def _query_derived_from(ws_url, flow_id, uri, user, collection, debug=Fals
"request": {
"s": {"t": "i", "i": uri},
"p": {"t": "i", "i": PROV_WAS_DERIVED_FROM},
"user": user,
"collection": collection,
"limit": 1
}
@ -355,7 +351,7 @@ async def _query_derived_from(ws_url, flow_id, uri, user, collection, debug=Fals
return None
async def _trace_provenance_chain(ws_url, flow_id, source_uri, user, collection, label_cache, debug=False):
async def _trace_provenance_chain(ws_url, flow_id, source_uri, collection, label_cache, debug=False):
"""
Trace the full provenance chain from a source URI up to the root document.
Returns a list of (uri, label) tuples from leaf to root.
@ -369,11 +365,11 @@ async def _trace_provenance_chain(ws_url, flow_id, source_uri, user, collection,
break
# Get label for current entity
label = await _query_label(ws_url, flow_id, current, user, collection, label_cache, debug)
label = await _query_label(ws_url, flow_id, current, collection, label_cache, debug)
chain.append((current, label))
# Get parent
parent = await _query_derived_from(ws_url, flow_id, current, user, collection, debug)
parent = await _query_derived_from(ws_url, flow_id, current, collection, debug)
if not parent or parent == current:
break
current = parent
@ -401,7 +397,7 @@ def _is_iri(value):
return value.startswith("http://") or value.startswith("https://") or value.startswith("urn:")
async def _query_label(ws_url, flow_id, iri, user, collection, label_cache, debug=False):
async def _query_label(ws_url, flow_id, iri, collection, label_cache, debug=False):
"""
Query for the rdfs:label of an IRI.
Uses label_cache to avoid repeated queries.
@ -421,7 +417,6 @@ async def _query_label(ws_url, flow_id, iri, user, collection, label_cache, debu
"request": {
"s": {"t": "i", "i": iri},
"p": {"t": "i", "i": RDFS_LABEL},
"user": user,
"collection": collection,
"limit": 1
}
@ -460,7 +455,7 @@ async def _query_label(ws_url, flow_id, iri, user, collection, label_cache, debu
return label
async def _resolve_edge_labels(ws_url, flow_id, edge_triple, user, collection, label_cache, debug=False):
async def _resolve_edge_labels(ws_url, flow_id, edge_triple, collection, label_cache, debug=False):
"""
Resolve labels for all IRI components of an edge triple.
Returns (s_label, p_label, o_label).
@ -469,15 +464,15 @@ async def _resolve_edge_labels(ws_url, flow_id, edge_triple, user, collection, l
p = edge_triple.get("p", "?")
o = edge_triple.get("o", "?")
s_label = await _query_label(ws_url, flow_id, s, user, collection, label_cache, debug)
p_label = await _query_label(ws_url, flow_id, p, user, collection, label_cache, debug)
o_label = await _query_label(ws_url, flow_id, o, user, collection, label_cache, debug)
s_label = await _query_label(ws_url, flow_id, s, collection, label_cache, debug)
p_label = await _query_label(ws_url, flow_id, p, collection, label_cache, debug)
o_label = await _query_label(ws_url, flow_id, o, collection, label_cache, debug)
return s_label, p_label, o_label
async def _question_explainable(
url, flow_id, question, user, collection, entity_limit, triple_limit,
url, flow_id, question, collection, entity_limit, triple_limit,
max_subgraph_size, max_path_length, token=None, debug=False
):
"""Execute graph RAG with explainability - shows provenance events with details"""
@ -502,7 +497,6 @@ async def _question_explainable(
"flow": flow_id,
"request": {
"query": question,
"user": user,
"collection": collection,
"entity-limit": entity_limit,
"triple-limit": triple_limit,
@ -549,7 +543,7 @@ async def _question_explainable(
# Query triples for this explain node (using named graph filter)
triples = await _query_triples(
ws_url, flow_id, explain_id, user, collection, graph=explain_graph, debug=debug
ws_url, flow_id, explain_id, collection, graph=explain_graph, debug=debug
)
# Format and display details
@ -564,7 +558,7 @@ async def _question_explainable(
print(f" Seed entities: {len(entity_iris)}", file=sys.stderr)
for iri in entity_iris:
label = await _query_label(
ws_url, flow_id, iri, user, collection,
ws_url, flow_id, iri, collection,
label_cache, debug=debug
)
print(f" - {label}", file=sys.stderr)
@ -579,7 +573,7 @@ async def _question_explainable(
print(f" [debug] querying edge selection: {o}", file=sys.stderr)
# Query the edge selection entity (using named graph filter)
edge_triples = await _query_triples(
ws_url, flow_id, o, user, collection, graph=explain_graph, debug=debug
ws_url, flow_id, o, collection, graph=explain_graph, debug=debug
)
if debug:
print(f" [debug] got {len(edge_triples)} edge triples", file=sys.stderr)
@ -597,7 +591,7 @@ async def _question_explainable(
if edge_triple:
# Resolve labels for edge components
s_label, p_label, o_label = await _resolve_edge_labels(
ws_url, flow_id, edge_triple, user, collection,
ws_url, flow_id, edge_triple, collection,
label_cache, debug=debug
)
print(f" Edge: ({s_label}, {p_label}, {o_label})", file=sys.stderr)
@ -605,21 +599,21 @@ async def _question_explainable(
r_short = reasoning[:100] + "..." if len(reasoning) > 100 else reasoning
print(f" Reason: {r_short}", file=sys.stderr)
# Trace edge provenance in the user's collection (not explainability)
# Trace edge provenance in the workspace collection (not explainability)
if edge_triple:
sources = await _query_edge_provenance(
ws_url, flow_id,
edge_triple.get("s", ""),
edge_triple.get("p", ""),
edge_triple.get("o", ""),
user, collection, # Use the query collection, not explainability
collection, # Use the query collection, not explainability
debug=debug
)
if sources:
for src in sources:
# Trace full chain from source to root document
chain = await _trace_provenance_chain(
ws_url, flow_id, src, user, collection,
ws_url, flow_id, src, collection,
label_cache, debug=debug
)
chain_str = _format_provenance_chain(chain)
@ -639,12 +633,12 @@ async def _question_explainable(
def _question_explainable_api(
url, flow_id, question_text, user, collection, entity_limit, triple_limit,
url, flow_id, question_text, collection, entity_limit, triple_limit,
max_subgraph_size, max_path_length, edge_score_limit=30,
edge_limit=25, token=None, debug=False
edge_limit=25, token=None, debug=False, workspace="default",
):
"""Execute graph RAG with explainability using the new API classes."""
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
explain_client = ExplainabilityClient(flow, retry_delay=0.2, max_retries=10)
@ -653,8 +647,7 @@ def _question_explainable_api(
# Stream GraphRAG with explainability - process events as they arrive
for item in flow.graph_rag_explain(
query=question_text,
user=user,
collection=collection,
collection=collection,
entity_limit=entity_limit,
triple_limit=triple_limit,
max_subgraph_size=max_subgraph_size,
@ -676,8 +669,7 @@ def _question_explainable_api(
entity = explain_client.fetch_entity(
prov_id,
graph=explain_graph,
user=user,
collection=collection
collection=collection
)
if entity is None:
@ -707,7 +699,7 @@ def _question_explainable_api(
if entity.entities:
print(f" Seed entities: {len(entity.entities)}", file=sys.stderr)
for ent in entity.entities:
label = explain_client.resolve_label(ent, user, collection)
label = explain_client.resolve_label(ent, collection)
print(f" - {label}", file=sys.stderr)
elif isinstance(entity, Focus):
@ -719,15 +711,14 @@ def _question_explainable_api(
focus_full = explain_client.fetch_focus_with_edges(
prov_id,
graph=explain_graph,
user=user,
collection=collection
collection=collection
)
if focus_full and focus_full.edge_selections:
for edge_sel in focus_full.edge_selections:
if edge_sel.edge:
# Resolve labels for edge components
s_label, p_label, o_label = explain_client.resolve_edge_labels(
edge_sel.edge, user, collection
edge_sel.edge, collection
)
print(f" Edge: ({s_label}, {p_label}, {o_label})", file=sys.stderr)
if edge_sel.reasoning:
@ -750,10 +741,11 @@ def _question_explainable_api(
def question(
url, flow_id, question, user, collection, entity_limit, triple_limit,
url, flow_id, question, collection, entity_limit, triple_limit,
max_subgraph_size, max_path_length, edge_score_limit=50,
edge_limit=25, streaming=True, token=None,
explainable=False, debug=False, show_usage=False
explainable=False, debug=False, show_usage=False,
workspace="default",
):
# Explainable mode uses the API to capture and process provenance events
@ -762,8 +754,7 @@ def question(
url=url,
flow_id=flow_id,
question_text=question,
user=user,
collection=collection,
collection=collection,
entity_limit=entity_limit,
triple_limit=triple_limit,
max_subgraph_size=max_subgraph_size,
@ -771,12 +762,13 @@ def question(
edge_score_limit=edge_score_limit,
edge_limit=edge_limit,
token=token,
debug=debug
debug=debug,
workspace=workspace,
)
return
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
if streaming:
# Use socket client for streaming
@ -786,8 +778,7 @@ def question(
try:
response = flow.graph_rag(
query=question,
user=user,
collection=collection,
collection=collection,
entity_limit=entity_limit,
triple_limit=triple_limit,
max_subgraph_size=max_subgraph_size,
@ -819,8 +810,7 @@ def question(
flow = api.flow().id(flow_id)
result = flow.graph_rag(
query=question,
user=user,
collection=collection,
collection=collection,
entity_limit=entity_limit,
triple_limit=triple_limit,
max_subgraph_size=max_subgraph_size,
@ -857,6 +847,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
@ -869,12 +865,6 @@ def main():
help=f'Question to answer',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
@ -955,7 +945,6 @@ def main():
url=args.url,
flow_id=args.flow_id,
question=args.question,
user=args.user,
collection=args.collection,
entity_limit=args.entity_limit,
triple_limit=args.triple_limit,
@ -968,6 +957,7 @@ def main():
explainable=args.explainable,
debug=args.debug,
show_usage=args.show_usage,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,12 +9,13 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def query(url, flow_id, system, prompt, streaming=True, token=None,
show_usage=False):
show_usage=False, workspace="default"):
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
@ -74,6 +75,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'system',
nargs=1,
@ -116,6 +123,7 @@ def main():
streaming=not args.no_streaming,
token=args.token,
show_usage=args.show_usage,
workspace=args.workspace,
)
except Exception as e:

View file

@ -11,10 +11,12 @@ import json
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def query(url, flow_id, name, parameters):
def query(url, flow_id, name, parameters, token=None, workspace="default"):
api = Api(url).flow().id(flow_id)
api = Api(url, token=token, workspace=workspace).flow().id(flow_id)
resp = api.mcp_tool(name=name, parameters=parameters)
@ -36,6 +38,18 @@ def main():
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
@ -68,6 +82,8 @@ def main():
flow_id = args.flow_id,
name = args.name,
parameters = parameters,
token = args.token,
workspace = args.workspace,
)
except Exception as e:

View file

@ -10,9 +10,11 @@ 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'):
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def nlp_query(url, flow_id, question, max_results, output_format='json', token=None, workspace="default"):
api = Api(url).flow().id(flow_id)
api = Api(url, token=token, workspace=workspace).flow().id(flow_id)
resp = api.nlp_query(
question=question,
@ -63,6 +65,17 @@ def main():
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
@ -100,6 +113,11 @@ def main():
question=args.question,
max_results=args.max_results,
output_format=args.format,
token = args.token,
workspace = args.workspace,
)
except Exception as e:

View file

@ -14,12 +14,13 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def query(url, flow_id, template_id, variables, streaming=True, token=None,
show_usage=False):
show_usage=False, workspace="default"):
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
@ -80,6 +81,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
default="default",
@ -135,6 +142,7 @@ specified multiple times''',
streaming=not args.no_streaming,
token=args.token,
show_usage=args.show_usage,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,11 +9,12 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def query(url, flow_id, query_text, schema_name, user, collection, index_name, limit, token=None):
def query(url, flow_id, query_text, schema_name, collection, index_name, limit, token=None, workspace="default"):
# Create API client
api = Api(url=url, token=token)
api = Api(url=url, token=token, workspace=workspace)
socket = api.socket()
flow = socket.flow(flow_id)
@ -22,7 +23,6 @@ def query(url, flow_id, query_text, schema_name, user, collection, index_name, l
result = flow.row_embeddings_query(
text=query_text,
schema_name=schema_name,
user=user,
collection=collection,
index_name=index_name,
limit=limit
@ -60,15 +60,15 @@ def main():
)
parser.add_argument(
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-U', '--user',
default="trustgraph",
help='User/keyspace (default: trustgraph)',
'-f', '--flow-id',
default="default",
help=f'Flow ID (default: default)'
)
parser.add_argument(
@ -111,11 +111,11 @@ def main():
flow_id=args.flow_id,
query_text=args.query[0],
schema_name=args.schema_name,
user=args.user,
collection=args.collection,
index_name=args.index_name,
limit=args.limit,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -12,10 +12,11 @@ from trustgraph.api import Api
from tabulate import tabulate
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
def format_output(data, output_format):
def format_output(data, output_format, token=None, workspace="default"):
"""Format GraphQL response data in the specified format"""
if not data:
return "No data returned"
@ -82,10 +83,10 @@ def format_table_data(rows, table_name, output_format):
return json.dumps({table_name: rows}, indent=2)
def rows_query(
url, flow_id, query, user, collection, variables, operation_name, output_format='table'
url, flow_id, query, collection, variables, operation_name, output_format='table', token=None, workspace="default"
):
api = Api(url).flow().id(flow_id)
api = Api(url, token=token, workspace=workspace).flow().id(flow_id)
# Parse variables if provided as JSON string
parsed_variables = {}
@ -98,7 +99,6 @@ def rows_query(
resp = api.rows_query(
query=query,
user=user,
collection=collection,
variables=parsed_variables if parsed_variables else None,
operation_name=operation_name
@ -135,6 +135,17 @@ def main():
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
@ -148,12 +159,6 @@ def main():
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,
@ -185,11 +190,13 @@ def main():
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,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,7 +9,8 @@ import sys
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
@ -44,10 +45,10 @@ def _term_str(val):
return str(val)
def sparql_query(url, token, flow_id, query, user, collection, limit,
batch_size, output_format):
def sparql_query(url, token, flow_id, query, collection, limit,
batch_size, output_format, workspace="default"):
socket = Api(url=url, token=token).socket()
socket = Api(url=url, token=token, workspace=workspace).socket()
flow = socket.flow(flow_id)
variables = None
@ -57,7 +58,6 @@ def sparql_query(url, token, flow_id, query, user, collection, limit,
for response in flow.sparql_query_stream(
query=query,
user=user,
collection=collection,
limit=limit,
batch_size=batch_size,
@ -154,8 +154,14 @@ def main():
parser.add_argument(
'-t', '--token',
default=os.getenv("TRUSTGRAPH_TOKEN"),
help='API bearer token (default: TRUSTGRAPH_TOKEN env var)',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -174,12 +180,6 @@ def main():
help='Read SPARQL query from file (use - for stdin)',
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})',
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
@ -228,11 +228,11 @@ def main():
token=args.token,
flow_id=args.flow_id,
query=query,
user=args.user,
collection=args.collection,
limit=args.limit,
batch_size=args.batch_size,
output_format=args.format,
workspace=args.workspace,
)
except Exception as e:

View file

@ -13,7 +13,9 @@ from tabulate import tabulate
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
def format_output(data, output_format):
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def format_output(data, output_format, token=None, workspace="default"):
"""Format structured query response data in the specified format"""
if not data:
return "No data returned"
@ -79,11 +81,11 @@ def format_table_data(rows, table_name, output_format):
else:
return json.dumps({table_name: rows}, indent=2)
def structured_query(url, flow_id, question, user='trustgraph', collection='default', output_format='table'):
def structured_query(url, flow_id, question, collection='default', output_format='table', token=None, workspace="default"):
api = Api(url).flow().id(flow_id)
api = Api(url, token=token, workspace=workspace).flow().id(flow_id)
resp = api.structured_query(question=question, user=user, collection=collection)
resp = api.structured_query(question=question, collection=collection)
# Check for errors
if "error" in resp and resp["error"]:
@ -119,6 +121,17 @@ def main():
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-f', '--flow-id',
@ -132,12 +145,6 @@ def main():
help='Natural language question to execute',
)
parser.add_argument(
'--user',
default='trustgraph',
help='Cassandra keyspace identifier (default: trustgraph)'
)
parser.add_argument(
'--collection',
default='default',
@ -159,9 +166,12 @@ def main():
url=args.url,
flow_id=args.flow_id,
question=args.question,
user=args.user,
collection=args.collection,
output_format=args.format,
token=args.token,
workspace = args.workspace,
)
except Exception as e:

View file

@ -1,23 +1,22 @@
"""
List collections for a user
List collections in a workspace
"""
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"
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def list_collections(url, user, tag_filter):
def list_collections(url, tag_filter, token=None, workspace="default"):
api = Api(url).collection()
api = Api(url, token=token, workspace=workspace).collection()
collections = api.list_collections(user=user, tag_filter=tag_filter)
collections = api.list_collections(tag_filter=tag_filter)
# Handle None or empty collections
if not collections or len(collections) == 0:
print("No collections found.")
return
@ -54,26 +53,33 @@ def main():
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)'
)
parser.add_argument(
'--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
list_collections(
url = args.api_url,
user = args.user,
tag_filter = args.tag_filter
tag_filter = args.tag_filter,
token = args.token,
workspace = args.workspace,
)
except Exception as e:
@ -81,4 +87,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -9,10 +9,12 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def list_config_items(url, config_type, format_type, token=None):
def list_config_items(url, config_type, format_type, token=None,
workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
keys = api.list(config_type)
@ -54,6 +56,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -63,6 +71,7 @@ def main():
config_type=args.type,
format_type=args.format,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -18,7 +18,7 @@ from trustgraph.api import Api, ExplainabilityClient
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = 'trustgraph'
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
# Retrieval graph
@ -86,9 +86,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})',
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -120,7 +120,7 @@ def main():
args = parser.parse_args()
try:
api = Api(args.api_url, token=args.token)
api = Api(args.api_url, token=args.token, workspace=args.workspace)
socket = api.socket()
flow = socket.flow(args.flow_id)
explain_client = ExplainabilityClient(flow)
@ -129,7 +129,6 @@ def main():
# List all sessions — uses persistent websocket via SocketClient
questions = explain_client.list_sessions(
graph=RETRIEVAL_GRAPH,
user=args.user,
collection=args.collection,
limit=args.limit,
)
@ -141,7 +140,6 @@ def main():
session_type = explain_client.detect_session_type(
q.uri,
graph=RETRIEVAL_GRAPH,
user=args.user,
collection=args.collection
)

View file

@ -46,7 +46,6 @@ async def load_de(running, queue, url):
"metadata": {
"id": msg["m"]["i"],
"metadata": msg["m"]["m"],
"user": msg["m"]["u"],
"collection": msg["m"]["c"],
},
"chunks": [
@ -77,7 +76,7 @@ async def stats(running):
f"Graph embeddings: {de_counts:10d}"
)
async def loader(running, de_queue, path, format, user, collection):
async def loader(running, de_queue, path, format, collection):
if format == "json":
@ -96,9 +95,6 @@ async def loader(running, de_queue, path, format, user, collection):
except:
break
if user:
unpacked["metadata"]["user"] = user
if collection:
unpacked["metadata"]["collection"] = collection
@ -148,9 +144,9 @@ async def run(running, **args):
running=running,
de_queue=de_q,
path=args["input_file"], format=args["format"],
user=args["user"], collection=args["collection"],
collection=args["collection"],
)
)
de_task = asyncio.create_task(
@ -178,7 +174,6 @@ async def main(running):
)
default_url = os.getenv("TRUSTGRAPH_API", "http://localhost:8088/")
default_user = "trustgraph"
collection = "default"
parser.add_argument(
@ -207,11 +202,6 @@ async def main(running):
help=f'Output format (default: msgpack)',
)
parser.add_argument(
'--user',
help=f'User ID to load as (default: from input)'
)
parser.add_argument(
'--collection',
help=f'Collection ID to load as (default: from input)'

View file

@ -6,20 +6,19 @@ run this utility.
import argparse
import os
import tabulate
from trustgraph.api import Api
import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_flow = "default"
default_collection = "default"
def load_kg_core(url, user, id, flow, collection):
def load_kg_core(url, id, flow, collection, token=None, workspace="default"):
api = Api(url).knowledge()
api = Api(url, token=token, workspace=workspace).knowledge()
class_names = api.load_kg_core(user = user, id = id, flow=flow,
collection=collection)
api.load_kg_core(id=id, flow=flow, collection=collection)
def main():
@ -34,12 +33,6 @@ def main():
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'-U', '--user',
default="trustgraph",
help='API URL (default: trustgraph)',
)
parser.add_argument(
'--id', '--identifier',
required=True,
@ -49,13 +42,25 @@ def main():
parser.add_argument(
'-f', '--flow-id',
default=default_flow,
help=f'Flow ID (default: {default_flow}',
help=f'Flow ID (default: {default_flow})',
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
help=f'Collection ID (default: {default_collection}',
help=f'Collection ID (default: {default_collection})',
)
parser.add_argument(
'-t', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
@ -64,10 +69,11 @@ def main():
load_kg_core(
url=args.api_url,
user=args.user,
id=args.id,
flow=args.flow_id,
collection=args.collection,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -13,7 +13,7 @@ from trustgraph.log_level import LogLevel
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = 'trustgraph'
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
class KnowledgeLoader:
@ -22,19 +22,18 @@ class KnowledgeLoader:
self,
files,
flow,
user,
collection,
document_id,
url=default_url,
token=None,
token=None, workspace="default",
):
self.files = files
self.flow = flow
self.user = user
self.collection = collection
self.document_id = document_id
self.url = url
self.token = token
self.workspace = workspace
def load_triples_from_file(self, file) -> Iterator[Triple]:
"""Generator that yields Triple objects from a Turtle file"""
@ -43,11 +42,9 @@ class KnowledgeLoader:
g.parse(file, format="turtle")
for e in g:
# Extract subject, predicate, object
s_value = str(e[0])
p_value = str(e[1])
# Check if object is a URI or literal
if isinstance(e[2], rdflib.term.URIRef):
o_value = str(e[2])
o_is_uri = True
@ -55,9 +52,6 @@ class KnowledgeLoader:
o_value = str(e[2])
o_is_uri = False
# Create Triple object
# Note: The Triple dataclass has 's', 'p', 'o' fields as strings
# The API will handle the metadata wrapping
yield Triple(s=s_value, p=p_value, o=o_value)
def load_entity_contexts_from_file(self, file) -> Iterator[Tuple[str, str]]:
@ -67,11 +61,9 @@ class KnowledgeLoader:
g.parse(file, format="turtle")
for s, p, o in g:
# If object is a URI, skip (we only want literal contexts)
if isinstance(o, rdflib.term.URIRef):
continue
# If object is a literal, create entity context for subject
s_str = str(s)
o_str = str(o)
@ -81,11 +73,9 @@ class KnowledgeLoader:
"""Load triples and entity contexts using Python API"""
try:
# Create API client
api = Api(url=self.url, token=self.token)
api = Api(url=self.url, token=self.token, workspace=self.workspace)
bulk = api.bulk()
# Load triples from all files
print("Loading triples...")
total_triples = 0
for file in self.files:
@ -104,7 +94,6 @@ class KnowledgeLoader:
metadata={
"id": self.document_id,
"metadata": [],
"user": self.user,
"collection": self.collection
}
)
@ -113,20 +102,16 @@ class KnowledgeLoader:
print(f"Triples loaded. Total: {total_triples}")
# Load entity contexts from all files
print("Loading entity contexts...")
total_contexts = 0
for file in self.files:
print(f" Processing {file}...")
count = 0
# Convert tuples to the format expected by import_entity_contexts
# Entity must be in Term format: {"t": "i", "i": uri} for IRI
def entity_context_generator():
nonlocal count
for entity, context in self.load_entity_contexts_from_file(file):
count += 1
# Entities from RDF are URIs, use IRI term format
yield {
"entity": {"t": "i", "i": entity},
"context": context
@ -138,7 +123,6 @@ class KnowledgeLoader:
metadata={
"id": self.document_id,
"metadata": [],
"user": self.user,
"collection": self.collection
}
)
@ -170,6 +154,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-i', '--document-id',
required=True,
@ -182,12 +172,6 @@ def main():
help=f'Flow ID (default: default)'
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
@ -210,8 +194,8 @@ def main():
token=args.token,
flow=args.flow_id,
files=args.files,
user=args.user,
collection=args.collection,
workspace=args.workspace,
)
loader.run()

View file

@ -12,8 +12,8 @@ from trustgraph.api import Api
from trustgraph.api.types import hash, Uri, Literal, Triple
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
from requests.adapters import HTTPAdapter
@ -656,11 +656,10 @@ documents = [
class Loader:
def __init__(
self, url, user, token=None
self, url, token=None, workspace="default",
):
self.api = Api(url, token=token).library()
self.user = user
self.api = Api(url, token=token, workspace=workspace).library()
def load(self, documents):
@ -689,10 +688,10 @@ class Loader:
print(" adding...")
self.api.add_document(
id = doc["id"], metadata = doc["metadata"],
user = self.user, kind = doc["kind"], title = doc["title"],
comments = doc["comments"], tags = doc["tags"],
document = content
id=doc["id"], metadata=doc["metadata"],
kind=doc["kind"], title=doc["title"],
comments=doc["comments"], tags=doc["tags"],
document=content,
)
print(" successful.")
@ -714,26 +713,26 @@ def main():
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', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
p = Loader(
url=args.url,
user=args.user,
token=args.token,
workspace=args.workspace,
)
p.load(documents)

View file

@ -23,6 +23,7 @@ logger = logging.getLogger(__name__)
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def load_structured_data(
@ -39,11 +40,11 @@ def load_structured_data(
sample_chars: int = 500,
schema_name: str = None,
flow: str = 'default',
user: str = 'trustgraph',
collection: str = 'default',
dry_run: bool = False,
verbose: bool = False,
token: str = None
token: str = None,
workspace: str = "default",
):
"""
Load structured data using a descriptor configuration.
@ -62,7 +63,6 @@ def load_structured_data(
sample_chars: Maximum characters to read for sampling
schema_name: Target schema name for generation
flow: TrustGraph flow name to use for prompts
user: User name for metadata (default: trustgraph)
collection: Collection name for metadata (default: default)
dry_run: If True, validate but don't import data
verbose: Enable verbose logging
@ -78,7 +78,7 @@ def load_structured_data(
logger.info("Step 1: Analyzing data to discover best matching schema...")
# Step 1: Auto-discover schema (reuse discover_schema logic)
discovered_schema = _auto_discover_schema(api_url, input_file, sample_chars, flow, logger)
discovered_schema = _auto_discover_schema(api_url, input_file, sample_chars, flow, logger, workspace=workspace)
if not discovered_schema:
logger.error("Failed to discover suitable schema automatically")
print("❌ Could not automatically determine the best schema for your data.")
@ -90,7 +90,7 @@ def load_structured_data(
# Step 2: Auto-generate descriptor
logger.info("Step 2: Generating descriptor configuration...")
auto_descriptor = _auto_generate_descriptor(api_url, input_file, discovered_schema, sample_chars, flow, logger)
auto_descriptor = _auto_generate_descriptor(api_url, input_file, discovered_schema, sample_chars, flow, logger, workspace=workspace)
if not auto_descriptor:
logger.error("Failed to generate descriptor automatically")
print("❌ Could not automatically generate descriptor configuration.")
@ -110,7 +110,7 @@ def load_structured_data(
try:
# Use shared pipeline for preview (small sample)
preview_objects, _ = _process_data_pipeline(input_file, temp_descriptor.name, user, collection, sample_size=5)
preview_objects, _ = _process_data_pipeline(input_file, temp_descriptor.name, collection, sample_size=5)
# Show preview
print("📊 Data Preview (first few records):")
@ -131,13 +131,13 @@ def load_structured_data(
print("🚀 Importing data to TrustGraph...")
# Use shared pipeline for full processing (no sample limit)
output_objects, descriptor = _process_data_pipeline(input_file, temp_descriptor.name, user, collection)
output_objects, descriptor = _process_data_pipeline(input_file, temp_descriptor.name, collection)
# Get batch size from descriptor
batch_size = descriptor.get('output', {}).get('options', {}).get('batch_size', 1000)
# Send to TrustGraph using shared function
imported_count = _send_to_trustgraph(output_objects, api_url, flow, batch_size, token=token)
imported_count = _send_to_trustgraph(output_objects, api_url, flow, batch_size, token=token, workspace=workspace)
# Summary
format_info = descriptor.get('format', {})
@ -172,7 +172,7 @@ def load_structured_data(
logger.info(f"Sample chars: {sample_chars} characters")
# Use the helper function to discover schema (get raw response for display)
response = _auto_discover_schema(api_url, input_file, sample_chars, flow, logger, return_raw_response=True)
response = _auto_discover_schema(api_url, input_file, sample_chars, flow, logger, return_raw_response=True, workspace=workspace)
if response:
# Debug: print response type and content
@ -203,7 +203,7 @@ def load_structured_data(
# If no schema specified, discover it first
if not schema_name:
logger.info("No schema specified, auto-discovering...")
schema_name = _auto_discover_schema(api_url, input_file, sample_chars, flow, logger)
schema_name = _auto_discover_schema(api_url, input_file, sample_chars, flow, logger, workspace=workspace)
if not schema_name:
print("Error: Could not determine schema automatically.")
print("Please specify a schema using --schema-name or run --discover-schema first.")
@ -213,7 +213,7 @@ def load_structured_data(
logger.info(f"Target schema: {schema_name}")
# Generate descriptor using helper function
descriptor = _auto_generate_descriptor(api_url, input_file, schema_name, sample_chars, flow, logger)
descriptor = _auto_generate_descriptor(api_url, input_file, schema_name, sample_chars, flow, logger, workspace=workspace)
if descriptor:
# Output the generated descriptor
@ -242,7 +242,7 @@ def load_structured_data(
logger.info(f"Parsing {input_file} with descriptor {descriptor_file}...")
# Use shared pipeline
output_records, descriptor = _process_data_pipeline(input_file, descriptor_file, user, collection, sample_size)
output_records, descriptor = _process_data_pipeline(input_file, descriptor_file, collection, sample_size)
# Output results
if output_file:
@ -286,7 +286,7 @@ def load_structured_data(
logger.info(f"Loading {input_file} to TrustGraph using descriptor {descriptor_file}...")
# Use shared pipeline (no sample_size limit for full load)
output_records, descriptor = _process_data_pipeline(input_file, descriptor_file, user, collection)
output_records, descriptor = _process_data_pipeline(input_file, descriptor_file, collection)
# Get batch size from descriptor or use default
batch_size = descriptor.get('output', {}).get('options', {}).get('batch_size', 1000)
@ -527,18 +527,17 @@ def _apply_transformations(records, mappings):
return processed_records
def _format_extracted_objects(processed_records, descriptor, user, collection):
def _format_extracted_objects(processed_records, descriptor, collection):
"""Convert to TrustGraph ExtractedObject format"""
output_records = []
schema_name = descriptor.get('output', {}).get('schema_name', 'default')
confidence = descriptor.get('output', {}).get('options', {}).get('confidence', 0.9)
for record in processed_records:
output_record = {
"metadata": {
"id": f"parsed-{len(output_records)+1}",
"metadata": [], # Empty metadata triples
"user": user,
"collection": collection
},
"schema_name": schema_name,
@ -551,7 +550,7 @@ def _format_extracted_objects(processed_records, descriptor, user, collection):
return output_records
def _process_data_pipeline(input_file, descriptor_file, user, collection, sample_size=None):
def _process_data_pipeline(input_file, descriptor_file, collection, sample_size=None):
"""Shared pipeline: load descriptor → read → parse → transform → format"""
# Load descriptor configuration
descriptor = _load_descriptor(descriptor_file)
@ -568,12 +567,12 @@ def _process_data_pipeline(input_file, descriptor_file, user, collection, sample
processed_records = _apply_transformations(parsed_records, mappings)
# Format output for TrustGraph ExtractedObject structure
output_records = _format_extracted_objects(processed_records, descriptor, user, collection)
output_records = _format_extracted_objects(processed_records, descriptor, collection)
return output_records, descriptor
def _send_to_trustgraph(rows, api_url, flow, batch_size=1000, token=None):
def _send_to_trustgraph(rows, api_url, flow, batch_size=1000, token=None, workspace="default"):
"""Send ExtractedObject records to TrustGraph using Python API"""
from trustgraph.api import Api
@ -582,7 +581,7 @@ def _send_to_trustgraph(rows, api_url, flow, batch_size=1000, token=None):
logger.info(f"Importing {total_records} records to TrustGraph...")
# Use Python API bulk import
api = Api(api_url, token=token)
api = Api(api_url, token=token, workspace=workspace)
bulk = api.bulk()
bulk.import_rows(flow=flow, rows=iter(rows))
@ -604,7 +603,7 @@ def _send_to_trustgraph(rows, api_url, flow, batch_size=1000, token=None):
# Helper functions for auto mode
def _auto_discover_schema(api_url, input_file, sample_chars, flow, logger, return_raw_response=False):
def _auto_discover_schema(api_url, input_file, sample_chars, flow, logger, return_raw_response=False, workspace="default"):
"""Auto-discover the best matching schema for the input data
Args:
@ -627,7 +626,7 @@ def _auto_discover_schema(api_url, input_file, sample_chars, flow, logger, retur
# Import API modules
from trustgraph.api import Api
from trustgraph.api.types import ConfigKey
api = Api(api_url)
api = Api(api_url, workspace=workspace)
config_api = api.config()
# Get available schemas
@ -708,7 +707,7 @@ def _auto_discover_schema(api_url, input_file, sample_chars, flow, logger, retur
return None
def _auto_generate_descriptor(api_url, input_file, schema_name, sample_chars, flow, logger):
def _auto_generate_descriptor(api_url, input_file, schema_name, sample_chars, flow, logger, workspace="default"):
"""Auto-generate descriptor configuration for the discovered schema"""
try:
# Read sample data
@ -718,7 +717,7 @@ def _auto_generate_descriptor(api_url, input_file, schema_name, sample_chars, fl
# Import API modules
from trustgraph.api import Api
from trustgraph.api.types import ConfigKey
api = Api(api_url)
api = Api(api_url, workspace=workspace)
config_api = api.config()
# Get schema definition
@ -885,12 +884,6 @@ For more information on the descriptor format, see:
help='TrustGraph flow name to use for prompts and import (default: default)'
)
parser.add_argument(
'--user',
default='trustgraph',
help='User name for metadata (default: trustgraph)'
)
parser.add_argument(
'--collection',
default='default',
@ -997,6 +990,12 @@ For more information on the descriptor format, see:
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
# Input validation
@ -1046,11 +1045,11 @@ For more information on the descriptor format, see:
sample_chars=args.sample_chars,
schema_name=args.schema_name,
flow=args.flow,
user=args.user,
collection=args.collection,
dry_run=args.dry_run,
verbose=args.verbose,
token=args.token
token=args.token,
workspace=args.workspace,
)
except FileNotFoundError as e:
print(f"Error: File not found - {e}", file=sys.stderr)

View file

@ -13,7 +13,7 @@ from trustgraph.log_level import LogLevel
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = 'trustgraph'
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
class Loader:
@ -22,15 +22,14 @@ class Loader:
self,
files,
flow,
user,
collection,
document_id,
url=default_url,
token=None,
token=None, workspace="default",
):
self.files = files
self.flow = flow
self.user = user
self.workspace = workspace
self.collection = collection
self.document_id = document_id
self.url = url
@ -43,28 +42,23 @@ class Loader:
g.parse(file, format="turtle")
for e in g:
# Extract subject, predicate, object
s_value = str(e[0])
p_value = str(e[1])
# Check if object is a URI or literal
if isinstance(e[2], rdflib.term.URIRef):
o_value = str(e[2])
else:
o_value = str(e[2])
# Create Triple object
yield Triple(s=s_value, p=p_value, o=o_value)
def run(self):
"""Load triples using Python API"""
try:
# Create API client
api = Api(url=self.url, token=self.token)
api = Api(url=self.url, token=self.token, workspace=self.workspace)
bulk = api.bulk()
# Load triples from all files
print("Loading triples...")
for file in self.files:
print(f" Processing {file}...")
@ -76,7 +70,6 @@ class Loader:
metadata={
"id": self.document_id,
"metadata": [],
"user": self.user,
"collection": self.collection
}
)
@ -106,6 +99,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-i', '--document-id',
required=True,
@ -118,12 +117,6 @@ def main():
help=f'Flow ID (default: default)'
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
@ -146,8 +139,8 @@ def main():
token=args.token,
flow=args.flow_id,
files=args.files,
user=args.user,
collection=args.collection,
workspace=args.workspace,
)
loader.run()

View file

@ -10,10 +10,12 @@ from trustgraph.api.types import ConfigValue
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def put_config_item(url, config_type, key, value, token=None):
def put_config_item(url, config_type, key, value, token=None,
workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
config_value = ConfigValue(type=config_type, key=key, value=value)
api.put([config_value])
@ -63,6 +65,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -78,6 +86,7 @@ def main():
key=args.key,
value=value,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -10,10 +10,12 @@ import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def put_flow_blueprint(url, blueprint_name, config, token=None):
def put_flow_blueprint(url, blueprint_name, config, token=None,
workspace="default"):
api = Api(url, token=token)
api = Api(url, token=token, workspace=workspace)
blueprint_names = api.flow().put_blueprint(blueprint_name, config)
@ -36,6 +38,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-n', '--blueprint-name',
help=f'Flow blueprint name',
@ -55,6 +63,7 @@ def main():
blueprint_name=args.blueprint_name,
config=json.loads(args.config),
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -1,10 +1,9 @@
"""
Uses the agent service to answer a question
Puts a knowledge core into the knowledge manager via the API socket.
"""
import argparse
import os
import textwrap
import uuid
import asyncio
import json
@ -12,18 +11,17 @@ from websockets.asyncio.client import connect
import msgpack
default_url = os.getenv("TRUSTGRAPH_URL", 'ws://localhost:8088/')
default_user = 'trustgraph'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def read_message(unpacked, id):
def read_message(unpacked, id, user):
if unpacked[0] == "ge":
msg = unpacked[1]
return "ge", {
"metadata": {
"id": id,
"metadata": msg["m"]["m"],
"user": user,
"collection": "default", # Not used?
},
"entities": [
@ -40,7 +38,6 @@ def read_message(unpacked, id, user):
"metadata": {
"id": id,
"metadata": msg["m"]["m"],
"user": user,
"collection": "default", # Not used by receiver?
},
"triples": msg["t"],
@ -48,7 +45,7 @@ def read_message(unpacked, id, user):
else:
raise RuntimeError("Unpacked unexpected messsage type", unpacked[0])
async def put(url, user, id, input, token=None):
async def put(url, workspace, id, input, token=None):
if not url.endswith("/"):
url += "/"
@ -60,7 +57,6 @@ async def put(url, user, id, input, token=None):
async with connect(url) as ws:
ge = 0
t = 0
@ -75,7 +71,7 @@ async def put(url, user, id, input, token=None):
except:
break
kind, msg = read_message(unpacked, id, user)
kind, msg = read_message(unpacked, id)
mid = str(uuid.uuid4())
@ -85,10 +81,11 @@ async def put(url, user, id, input, token=None):
req = json.dumps({
"id": mid,
"workspace": workspace,
"service": "knowledge",
"request": {
"operation": "put-kg-core",
"user": user,
"workspace": workspace,
"id": id,
"graph-embeddings": msg
}
@ -100,10 +97,11 @@ async def put(url, user, id, input, token=None):
req = json.dumps({
"id": mid,
"workspace": workspace,
"service": "knowledge",
"request": {
"operation": "put-kg-core",
"user": user,
"workspace": workspace,
"id": id,
"triples": msg
}
@ -117,7 +115,7 @@ async def put(url, user, id, input, token=None):
# Retry loop, wait for right response to come back
while True:
msg = await ws.recv()
msg = json.loads(msg)
@ -146,10 +144,11 @@ def main():
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})'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -176,11 +175,11 @@ def main():
asyncio.run(
put(
url = args.url,
user = args.user,
id = args.id,
input = args.input,
token = args.token,
url=args.url,
workspace=args.workspace,
id=args.id,
input=args.input,
token=args.token,
)
)
@ -189,4 +188,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -23,9 +23,9 @@ import sys
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_collection = 'default'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def parse_inline_quoted_triple(value):
@ -285,15 +285,16 @@ def output_jsonl(triples):
def query_graph(
url, flow_id, user, collection, limit, batch_size,
url, flow_id, collection, limit, batch_size,
subject=None, predicate=None, obj=None, graph=None,
output_format="space", headers=False, token=None
output_format="space", headers=False, token=None,
workspace="default",
):
"""Query the triple store with pattern matching.
Uses the API's triples_query_stream for efficient streaming delivery.
"""
socket = Api(url, token=token).socket()
socket = Api(url, token=token, workspace=workspace).socket()
flow = socket.flow(flow_id)
all_triples = []
@ -305,7 +306,6 @@ def query_graph(
p=predicate,
o=obj,
g=graph,
user=user,
collection=collection,
limit=limit,
batch_size=batch_size,
@ -456,13 +456,6 @@ def main():
help='Flow ID (default: default)'
)
std_group.add_argument(
'-U', '--user',
default=default_user,
metavar='USER',
help=f'User/keyspace (default: {default_user})'
)
std_group.add_argument(
'-C', '--collection',
default=default_collection,
@ -477,6 +470,12 @@ def main():
help='Auth token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
std_group.add_argument(
'-l', '--limit',
type=int,
@ -550,7 +549,6 @@ def main():
query_graph(
url=args.api_url,
flow_id=args.flow_id,
user=args.user,
collection=args.collection,
limit=args.limit,
batch_size=args.batch_size,
@ -561,6 +559,8 @@ def main():
output_format=args.format,
headers=args.headers,
token=args.token,
workspace=args.workspace,
)
except json.JSONDecodeError as e:

View file

@ -4,20 +4,19 @@ Remove a document from the library
import argparse
import os
import uuid
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def remove_doc(url, user, id, token=None):
def remove_doc(url, id, token=None, workspace="default"):
api = Api(url, token=token).library()
api = Api(url, token=token, workspace=workspace).library()
api.remove_document(user=user, id=id)
api.remove_document(id=id)
def main():
@ -32,12 +31,6 @@ def main():
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(
'--identifier', '--id',
required=True,
@ -50,15 +43,24 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
remove_doc(args.url, args.user, args.identifier, token=args.token)
remove_doc(
args.url, args.identifier,
token=args.token, workspace=args.workspace,
)
except Exception as e:
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -21,7 +21,7 @@ class Running:
def get(self): return self.running
def stop(self): self.running = False
async def fetch_de(running, queue, user, collection, url):
async def fetch_de(running, queue, collection, url):
async with aiohttp.ClientSession() as session:
@ -38,10 +38,6 @@ async def fetch_de(running, queue, user, collection, url):
data = msg.json()
if user:
if data["metadata"]["user"] != user:
continue
if collection:
if data["metadata"]["collection"] != collection:
continue
@ -52,7 +48,6 @@ async def fetch_de(running, queue, user, collection, url):
"m": {
"i": data["metadata"]["id"],
"m": data["metadata"]["metadata"],
"u": data["metadata"]["user"],
"c": data["metadata"]["collection"],
},
"c": [
@ -119,7 +114,7 @@ async def run(running, **args):
de_task = asyncio.create_task(
fetch_de(
running=running,
queue=q, user=args["user"], collection=args["collection"],
queue=q, collection=args["collection"],
url = f"{url}api/v1/flow/{flow_id}/export/document-embeddings"
)
)
@ -148,7 +143,6 @@ async def main(running):
)
default_url = os.getenv("TRUSTGRAPH_API", "http://localhost:8088/")
default_user = "trustgraph"
collection = "default"
parser.add_argument(
@ -177,11 +171,6 @@ async def main(running):
help=f'Output format (default: msgpack)',
)
parser.add_argument(
'--user',
help=f'User ID to filter on (default: no filter)'
)
parser.add_argument(
'--collection',
help=f'Collection ID to filter on (default: no filter)'

View file

@ -8,15 +8,14 @@ import tabulate
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = "trustgraph"
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def set_collection(url, user, collection, name, description, tags, token=None):
def set_collection(url, collection, name, description, tags, token=None, workspace="default"):
api = Api(url, token=token).collection()
api = Api(url, token=token, workspace=workspace).collection()
result = api.update_collection(
user=user,
collection=collection,
name=name,
description=description,
@ -59,12 +58,6 @@ def main():
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'
@ -88,18 +81,24 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
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,
token = args.token
token = args.token,
workspace=args.workspace,
)
except Exception as e:
@ -107,4 +106,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -21,6 +21,7 @@ import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def set_mcp_tool(
url : str,
@ -29,9 +30,10 @@ def set_mcp_tool(
tool_url : str,
auth_token : str = None,
token : str = None,
workspace : str = "default",
):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
# Build the MCP tool configuration
config = {
@ -80,6 +82,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-i', '--id',
required=True,
@ -126,6 +134,8 @@ def main():
tool_url=args.tool_url,
auth_token=args.auth_token,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -11,10 +11,11 @@ import textwrap
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def set_system(url, system, token=None):
def set_system(url, system, token=None, workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
api.put([
ConfigValue(type="prompt", key="system", value=json.dumps(system))
@ -22,9 +23,9 @@ def set_system(url, system, token=None):
print("System prompt set.")
def set_prompt(url, id, prompt, response, schema, token=None):
def set_prompt(url, id, prompt, response, schema, token=None, workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
values = api.get([
ConfigKey(type="prompt", key="template-index")
@ -78,6 +79,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'--id',
help=f'Prompt ID',

View file

@ -11,10 +11,11 @@ import textwrap
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def set_costs(api_url, model, input_costs, output_costs, token=None):
def set_costs(api_url, model, input_costs, output_costs, token=None, workspace="default"):
api = Api(api_url, token=token).config()
api = Api(api_url, token=token, workspace=workspace).config()
api.put([
ConfigValue(
@ -26,9 +27,9 @@ def set_costs(api_url, model, input_costs, output_costs, token=None):
),
])
def set_prompt(url, id, prompt, response, schema):
def set_prompt(url, id, prompt, response, schema, workspace="default"):
api = Api(url)
api = Api(url, workspace=workspace)
values = api.config_get([
ConfigKey(type="prompt", key="template-index")
@ -102,6 +103,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:

View file

@ -28,6 +28,7 @@ import dataclasses
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
@dataclasses.dataclass
class Argument:
@ -73,9 +74,10 @@ def set_tool(
state : str,
applicable_states : List[str],
token : str = None,
workspace : str = "default",
):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
values = api.get([
ConfigKey(type="agent", key="tool-index")
@ -181,6 +183,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'--id',
help=f'Unique tool identifier',
@ -303,6 +311,8 @@ def main():
state=args.state,
applicable_states=args.applicable_states,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -9,10 +9,11 @@ import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def show_config(url, token=None):
def show_config(url, token=None, workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
config, version = api.all()
@ -38,6 +39,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -45,6 +52,7 @@ def main():
show_config(
url=args.api_url,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -36,7 +36,7 @@ from trustgraph.api import (
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = 'trustgraph'
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
# Graphs
@ -50,13 +50,12 @@ PROV = "http://www.w3.org/ns/prov#"
PROV_WAS_DERIVED_FROM = PROV + "wasDerivedFrom"
def trace_edge_provenance(flow, user, collection, edge, label_cache, explain_client):
def trace_edge_provenance(flow, collection, edge, label_cache, explain_client):
"""
Trace an edge back to its source document via reification.
Args:
flow: SocketFlowInstance
user: User identifier
collection: Collection identifier
edge: Dict with s, p, o keys
label_cache: Dict for caching labels
@ -90,7 +89,6 @@ def trace_edge_provenance(flow, user, collection, edge, label_cache, explain_cli
p=TG_CONTAINS,
o=quoted_triple,
g=SOURCE_GRAPH,
user=user,
collection=collection,
limit=10
)
@ -108,14 +106,14 @@ def trace_edge_provenance(flow, user, collection, edge, label_cache, explain_cli
# For each statement, trace wasDerivedFrom chain
provenance_chains = []
for stmt_uri in stmt_uris:
chain = trace_provenance_chain(flow, user, collection, stmt_uri, label_cache, explain_client)
chain = trace_provenance_chain(flow, collection, stmt_uri, label_cache, explain_client)
if chain:
provenance_chains.append(chain)
return provenance_chains
def trace_provenance_chain(flow, user, collection, start_uri, label_cache, explain_client, max_depth=10):
def trace_provenance_chain(flow, collection, start_uri, label_cache, explain_client, max_depth=10):
"""Trace prov:wasDerivedFrom chain from start_uri to root."""
chain = []
current = start_uri
@ -128,7 +126,7 @@ def trace_provenance_chain(flow, user, collection, start_uri, label_cache, expla
if current in label_cache:
label = label_cache[current]
else:
label = explain_client.resolve_label(current, user, collection)
label = explain_client.resolve_label(current, collection)
label_cache[current] = label
chain.append({"uri": current, "label": label})
@ -139,7 +137,6 @@ def trace_provenance_chain(flow, user, collection, start_uri, label_cache, expla
s=current,
p=PROV_WAS_DERIVED_FROM,
g=SOURCE_GRAPH,
user=user,
collection=collection,
limit=1
)
@ -167,7 +164,7 @@ def format_provenance_chain(chain):
return " -> ".join(labels)
def print_graphrag_text(trace, explain_client, flow, user, collection, api=None, show_provenance=False):
def print_graphrag_text(trace, explain_client, flow, collection, api=None, show_provenance=False):
"""Print GraphRAG trace in text format."""
question = trace.get("question")
@ -202,7 +199,7 @@ def print_graphrag_text(trace, explain_client, flow, user, collection, api=None,
for i, edge_sel in enumerate(edges, 1):
if edge_sel.edge:
s_label, p_label, o_label = explain_client.resolve_edge_labels(
edge_sel.edge, user, collection
edge_sel.edge, collection
)
print(f" {i}. ({s_label}, {p_label}, {o_label})")
@ -212,7 +209,7 @@ def print_graphrag_text(trace, explain_client, flow, user, collection, api=None,
if show_provenance and edge_sel.edge:
provenance = trace_edge_provenance(
flow, user, collection, edge_sel.edge,
flow, collection, edge_sel.edge,
label_cache, explain_client
)
for chain in provenance:
@ -238,7 +235,7 @@ def print_graphrag_text(trace, explain_client, flow, user, collection, api=None,
content = ""
if synthesis.document and api:
content = explain_client.fetch_document_content(
synthesis.document, api, user
synthesis.document, api
)
if content:
print("Answer:")
@ -252,7 +249,7 @@ def print_graphrag_text(trace, explain_client, flow, user, collection, api=None,
print("No synthesis data found")
def print_docrag_text(trace, explain_client, api, user):
def print_docrag_text(trace, explain_client, api):
"""Print DocRAG trace in text format."""
question = trace.get("question")
@ -288,7 +285,7 @@ def print_docrag_text(trace, explain_client, api, user):
content = ""
if synthesis.document and api:
content = explain_client.fetch_document_content(
synthesis.document, api, user
synthesis.document, api
)
if content:
print("Answer:")
@ -302,14 +299,14 @@ def print_docrag_text(trace, explain_client, api, user):
print("No synthesis data found")
def _print_document_content(explain_client, api, user, document_uri, label="Answer"):
def _print_document_content(explain_client, api, document_uri, label="Answer"):
"""Fetch and print document content, or fall back to URI."""
if not document_uri:
return
content = ""
if api:
content = explain_client.fetch_document_content(
document_uri, api, user
document_uri, api
)
if content:
print(f"{label}:")
@ -319,7 +316,7 @@ def _print_document_content(explain_client, api, user, document_uri, label="Answ
print(f"Document: {document_uri}")
def print_agent_text(trace, explain_client, api, user):
def print_agent_text(trace, explain_client, api):
"""Print Agent trace in text format."""
question = trace.get("question")
@ -348,7 +345,7 @@ def print_agent_text(trace, explain_client, api, user):
print("--- Finding ---")
print(f"Goal: {step.goal}")
_print_document_content(
explain_client, api, user, step.document, "Result",
explain_client, api, step.document, "Result",
)
print()
@ -363,7 +360,7 @@ def print_agent_text(trace, explain_client, api, user):
print("--- Step Result ---")
print(f"Step: {step.step}")
_print_document_content(
explain_client, api, user, step.document, "Result",
explain_client, api, step.document, "Result",
)
print()
@ -385,21 +382,21 @@ def print_agent_text(trace, explain_client, api, user):
elif isinstance(step, Observation):
print("--- Observation ---")
_print_document_content(
explain_client, api, user, step.document, "Content",
explain_client, api, step.document, "Content",
)
print()
elif isinstance(step, Synthesis):
print("--- Synthesis ---")
_print_document_content(
explain_client, api, user, step.document, "Answer",
explain_client, api, step.document, "Answer",
)
print()
elif isinstance(step, Conclusion):
print("--- Conclusion ---")
_print_document_content(
explain_client, api, user, step.document, "Answer",
explain_client, api, step.document, "Answer",
)
print()
@ -559,9 +556,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})',
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -599,7 +596,7 @@ def main():
args = parser.parse_args()
try:
api = Api(args.api_url, token=args.token)
api = Api(args.api_url, token=args.token, workspace=args.workspace)
socket = api.socket()
flow = socket.flow(args.flow_id)
explain_client = ExplainabilityClient(flow)
@ -609,7 +606,6 @@ def main():
trace_type = explain_client.detect_session_type(
args.question_id,
graph=RETRIEVAL_GRAPH,
user=args.user,
collection=args.collection,
)
@ -618,7 +614,6 @@ def main():
trace = explain_client.fetch_agent_trace(
args.question_id,
graph=RETRIEVAL_GRAPH,
user=args.user,
collection=args.collection,
api=api,
max_content=args.max_answer,
@ -627,14 +622,13 @@ def main():
if args.format == 'json':
print(json.dumps(trace_to_dict(trace, "agent"), indent=2))
else:
print_agent_text(trace, explain_client, api, args.user)
print_agent_text(trace, explain_client, api)
elif trace_type == "docrag":
# Fetch and display DocRAG trace
trace = explain_client.fetch_docrag_trace(
args.question_id,
graph=RETRIEVAL_GRAPH,
user=args.user,
collection=args.collection,
api=api,
max_content=args.max_answer,
@ -643,14 +637,13 @@ def main():
if args.format == 'json':
print(json.dumps(trace_to_dict(trace, "docrag"), indent=2))
else:
print_docrag_text(trace, explain_client, api, args.user)
print_docrag_text(trace, explain_client, api)
else:
# Fetch and display GraphRAG trace
trace = explain_client.fetch_graphrag_trace(
args.question_id,
graph=RETRIEVAL_GRAPH,
user=args.user,
collection=args.collection,
api=api,
max_content=args.max_answer,
@ -661,7 +654,7 @@ def main():
else:
print_graphrag_text(
trace, explain_client, flow,
args.user, args.collection,
args.collection,
api=api,
show_provenance=args.show_provenance
)

View file

@ -17,7 +17,7 @@ from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = 'trustgraph'
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_collection = 'default'
# Predicates
@ -45,10 +45,9 @@ TYPE_MAP = {
SOURCE_GRAPH = "urn:graph:source"
def query_triples(socket, flow_id, user, collection, s=None, p=None, o=None, g=None, limit=1000):
def query_triples(socket, flow_id, collection, s=None, p=None, o=None, g=None, limit=1000):
"""Query triples using the socket API."""
request = {
"user": user,
"collection": collection,
"limit": limit,
"streaming": False,
@ -120,9 +119,9 @@ def extract_value(term):
return str(term)
def get_node_metadata(socket, flow_id, user, collection, node_uri):
def get_node_metadata(socket, flow_id, collection, node_uri):
"""Get metadata for a node (label, types, title, format)."""
triples = query_triples(socket, flow_id, user, collection, s=node_uri, g=SOURCE_GRAPH)
triples = query_triples(socket, flow_id, collection, s=node_uri, g=SOURCE_GRAPH)
metadata = {"uri": node_uri, "types": []}
for s, p, o in triples:
@ -146,20 +145,20 @@ def classify_node(metadata):
return "unknown"
def get_children(socket, flow_id, user, collection, parent_uri):
def get_children(socket, flow_id, collection, parent_uri):
"""Get children of a node via prov:wasDerivedFrom."""
triples = query_triples(
socket, flow_id, user, collection,
socket, flow_id, collection,
p=PROV_WAS_DERIVED_FROM, o=parent_uri, g=SOURCE_GRAPH
)
return [s for s, p, o in triples]
def get_document_content(api, user, doc_id, max_content):
def get_document_content(api, doc_id, max_content):
"""Fetch document content from librarian API."""
try:
library = api.library()
content = library.get_document_content(user=user, id=doc_id)
content = library.get_document_content(id=doc_id)
# Try to decode as text
try:
@ -173,7 +172,7 @@ def get_document_content(api, user, doc_id, max_content):
return f"[Error fetching content: {e}]"
def build_hierarchy(socket, flow_id, user, collection, root_uri, api=None, show_content=False, max_content=200, visited=None):
def build_hierarchy(socket, flow_id, collection, root_uri, api=None, show_content=False, max_content=200, visited=None):
"""Build document hierarchy tree recursively."""
if visited is None:
visited = set()
@ -182,7 +181,7 @@ def build_hierarchy(socket, flow_id, user, collection, root_uri, api=None, show_
return None
visited.add(root_uri)
metadata = get_node_metadata(socket, flow_id, user, collection, root_uri)
metadata = get_node_metadata(socket, flow_id, collection, root_uri)
node_type = classify_node(metadata)
node = {
@ -195,21 +194,21 @@ def build_hierarchy(socket, flow_id, user, collection, root_uri, api=None, show_
# Fetch content if requested
if show_content and api:
content = get_document_content(api, user, root_uri, max_content)
content = get_document_content(api, root_uri, max_content)
if content:
node["content"] = content
# Get children
children_uris = get_children(socket, flow_id, user, collection, root_uri)
children_uris = get_children(socket, flow_id, collection, root_uri)
for child_uri in children_uris:
child_metadata = get_node_metadata(socket, flow_id, user, collection, child_uri)
child_metadata = get_node_metadata(socket, flow_id, collection, child_uri)
child_type = classify_node(child_metadata)
if child_type == "subgraph":
# Subgraphs contain extracted edges — inline them
contains_triples = query_triples(
socket, flow_id, user, collection,
socket, flow_id, collection,
s=child_uri, p=TG_CONTAINS, g=SOURCE_GRAPH
)
for _, _, edge in contains_triples:
@ -218,7 +217,7 @@ def build_hierarchy(socket, flow_id, user, collection, root_uri, api=None, show_
else:
# Recurse into pages, chunks, etc.
child_node = build_hierarchy(
socket, flow_id, user, collection, child_uri,
socket, flow_id, collection, child_uri,
api=api, show_content=show_content, max_content=max_content,
visited=visited
)
@ -331,9 +330,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})',
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -371,14 +370,13 @@ def main():
args = parser.parse_args()
try:
api = Api(args.api_url, token=args.token)
api = Api(args.api_url, token=args.token, workspace=args.workspace)
socket = api.socket()
try:
hierarchy = build_hierarchy(
socket=socket,
flow_id=args.flow_id,
user=args.user,
collection=args.collection,
root_uri=args.document_id,
api=api if args.show_content else None,

View file

@ -11,6 +11,7 @@ import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def format_parameters(params_metadata, param_type_defs):
"""
@ -44,12 +45,13 @@ def format_parameters(params_metadata, param_type_defs):
return "\n".join(param_list)
async def fetch_data(client):
async def fetch_data(client, workspace):
"""Fetch all data needed for show_flow_blueprints concurrently."""
# Round 1: list blueprints
resp = await client._send_request("flow", None, {
"operation": "list-blueprints",
"workspace": workspace,
})
blueprint_names = resp.get("blueprint-names", [])
@ -60,6 +62,7 @@ async def fetch_data(client):
blueprint_tasks = [
client._send_request("flow", None, {
"operation": "get-blueprint",
"workspace": workspace,
"blueprint-name": name,
})
for name in blueprint_names
@ -84,6 +87,7 @@ async def fetch_data(client):
param_type_tasks = [
client._send_request("config", None, {
"operation": "get",
"workspace": workspace,
"keys": [{"type": "parameter-type", "key": pt}],
})
for pt in param_types_needed
@ -100,14 +104,16 @@ async def fetch_data(client):
return blueprint_names, blueprints, param_type_defs
async def _show_flow_blueprints_async(url, token=None):
async def _show_flow_blueprints_async(url, token=None, workspace="default"):
async with AsyncSocketClient(url, timeout=60, token=token) as client:
return await fetch_data(client)
return await fetch_data(client, workspace)
def show_flow_blueprints(url, token=None):
def show_flow_blueprints(url, token=None, workspace="default"):
blueprint_names, blueprints, param_type_defs = asyncio.run(
_show_flow_blueprints_async(url, token=token)
_show_flow_blueprints_async(
url, token=token, workspace=workspace,
)
)
if not blueprint_names:
@ -156,6 +162,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -163,6 +175,7 @@ def main():
show_flow_blueprints(
url=args.api_url,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -10,10 +10,12 @@ import os
default_metrics_url = "http://localhost:8088/api/metrics"
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def dump_status(metrics_url, api_url, flow_id, token=None):
def dump_status(metrics_url, api_url, flow_id, token=None,
workspace="default"):
api = Api(api_url, token=token).flow()
api = Api(api_url, token=token, workspace=workspace).flow()
flow = api.get(flow_id)
blueprint_name = flow["blueprint-name"]
@ -84,11 +86,20 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
dump_status(args.metrics_url, args.api_url, args.flow_id, token=args.token)
dump_status(
args.metrics_url, args.api_url, args.flow_id,
token=args.token, workspace=args.workspace,
)
except Exception as e:

View file

@ -11,6 +11,7 @@ import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def describe_interfaces(intdefs, flow):
@ -97,17 +98,19 @@ def format_parameters(flow_params, blueprint_params_metadata, param_type_defs):
return "\n".join(param_list) if param_list else "None"
async def fetch_show_flows(client):
async def fetch_show_flows(client, workspace):
"""Fetch all data needed for show_flows concurrently."""
# Round 1: list interfaces and list flows in parallel
interface_names_resp, flow_ids_resp = await asyncio.gather(
client._send_request("config", None, {
"operation": "list",
"workspace": workspace,
"type": "interface-description",
}),
client._send_request("flow", None, {
"operation": "list-flows",
"workspace": workspace,
}),
)
@ -115,12 +118,13 @@ async def fetch_show_flows(client):
flow_ids = flow_ids_resp.get("flow-ids", [])
if not flow_ids:
return {}, [], {}, {}
return {}, [], {}, {}, {}
# Round 2: get all interfaces + all flows in parallel
interface_tasks = [
client._send_request("config", None, {
"operation": "get",
"workspace": workspace,
"keys": [{"type": "interface-description", "key": name}],
})
for name in interface_names
@ -129,6 +133,7 @@ async def fetch_show_flows(client):
flow_tasks = [
client._send_request("flow", None, {
"operation": "get-flow",
"workspace": workspace,
"flow-id": fid,
})
for fid in flow_ids
@ -163,6 +168,7 @@ async def fetch_show_flows(client):
blueprint_tasks = [
client._send_request("flow", None, {
"operation": "get-blueprint",
"workspace": workspace,
"blueprint-name": bp_name,
})
for bp_name in blueprint_names
@ -186,6 +192,7 @@ async def fetch_show_flows(client):
param_type_tasks = [
client._send_request("config", None, {
"operation": "get",
"workspace": workspace,
"keys": [{"type": "parameter-type", "key": pt}],
})
for pt in param_types_needed
@ -204,14 +211,16 @@ async def fetch_show_flows(client):
return interface_defs, flow_ids, flows, blueprints, param_type_defs
async def _show_flows_async(url, token=None):
async def _show_flows_async(url, token=None, workspace="default"):
async with AsyncSocketClient(url, timeout=60, token=token) as client:
return await fetch_show_flows(client)
return await fetch_show_flows(client, workspace)
def show_flows(url, token=None):
def show_flows(url, token=None, workspace="default"):
result = asyncio.run(_show_flows_async(url, token=token))
result = asyncio.run(_show_flows_async(
url, token=token, workspace=workspace,
))
interface_defs, flow_ids, flows, blueprints, param_type_defs = result
@ -269,6 +278,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -276,6 +291,7 @@ def main():
show_flows(
url=args.api_url,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -13,9 +13,9 @@ import os
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = 'trustgraph'
default_collection = 'default'
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
# Named graph constants for convenience
GRAPH_DEFAULT = ""
@ -23,14 +23,13 @@ GRAPH_SOURCE = "urn:graph:source"
GRAPH_RETRIEVAL = "urn:graph:retrieval"
def show_graph(url, flow_id, user, collection, limit, batch_size, graph=None, show_graph_column=False, token=None):
def show_graph(url, flow_id, collection, limit, batch_size, graph=None, show_graph_column=False, token=None, workspace="default"):
socket = Api(url, token=token).socket()
socket = Api(url, token=token, workspace=workspace).socket()
flow = socket.flow(flow_id)
try:
for batch in flow.triples_query_stream(
user=user,
collection=collection,
s=None, p=None, o=None,
g=graph, # Filter by named graph (None = all graphs)
@ -73,12 +72,6 @@ def main():
help=f'Flow ID (default: default)'
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
)
parser.add_argument(
'-C', '--collection',
default=default_collection,
@ -91,6 +84,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-l', '--limit',
type=int,
@ -129,13 +128,13 @@ def main():
show_graph(
url = args.api_url,
flow_id = args.flow_id,
user = args.user,
collection = args.collection,
limit = args.limit,
batch_size = args.batch_size,
graph = graph,
show_graph_column = args.show_graph,
token = args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -4,16 +4,15 @@ Shows knowledge cores
import argparse
import os
import tabulate
from trustgraph.api import Api, ConfigKey
import json
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def show_cores(url, user, token=None):
def show_cores(url, token=None, workspace="default"):
api = Api(url, token=token).knowledge()
api = Api(url, token=token, workspace=workspace).knowledge()
ids = api.list_kg_cores()
@ -26,7 +25,7 @@ def show_cores(url, user, token=None):
def main():
parser = argparse.ArgumentParser(
prog='tg-show-flows',
prog='tg-show-kg-cores',
description=__doc__,
)
@ -43,9 +42,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default="trustgraph",
help='API URL (default: trustgraph)',
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
@ -54,8 +53,8 @@ def main():
show_cores(
url=args.api_url,
user=args.user,
token=args.token,
workspace=args.workspace,
)
except Exception as e:
@ -63,4 +62,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -10,13 +10,13 @@ import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = "trustgraph"
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def show_docs(url, user, token=None):
def show_docs(url, token=None, workspace="default"):
api = Api(url, token=token).library()
api = Api(url, token=token, workspace=workspace).library()
docs = api.get_documents(user=user)
docs = api.get_documents()
if len(docs) == 0:
print("No documents.")
@ -60,9 +60,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
@ -71,8 +71,8 @@ def main():
show_docs(
url = args.api_url,
user = args.user,
token = args.token,
workspace = args.workspace,
)
except Exception as e:

View file

@ -4,18 +4,17 @@
import argparse
import os
import tabulate
from trustgraph.api import Api, ConfigKey
import json
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_user = "trustgraph"
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def show_procs(url, user, token=None):
def show_procs(url, token=None, workspace="default"):
api = Api(url, token=token).library()
api = Api(url, token=token, workspace=workspace).library()
procs = api.get_processings(user = user)
procs = api.get_processings()
if len(procs) == 0:
print("No processing objects.")
@ -52,24 +51,26 @@ def main():
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', '--token',
default=default_token,
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
show_procs(
url = args.api_url, user = args.user, token = args.token
url=args.api_url,
token=args.token,
workspace=args.workspace,
)
except Exception as e:
@ -77,4 +78,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -11,10 +11,11 @@ import textwrap
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def show_config(url, token=None):
def show_config(url, token=None, workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
values = api.get_values(type="mcp")
@ -64,6 +65,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -71,6 +78,8 @@ def main():
show_config(
url=args.api_url,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -11,10 +11,11 @@ import textwrap
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def show_config(url, token=None):
def show_config(url, token=None, workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
values = api.get([
ConfigKey(type="prompt", key="system"),
@ -85,6 +86,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -92,6 +99,8 @@ def main():
show_config(
url=args.api_url,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -13,10 +13,11 @@ tabulate.PRESERVE_WHITESPACE = True
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def show_config(url, token=None):
def show_config(url, token=None, workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
models = api.list("token-cost")
@ -68,6 +69,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -75,6 +82,8 @@ def main():
show_config(
url=args.api_url,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -19,10 +19,11 @@ import textwrap
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def show_config(url, token=None):
def show_config(url, token=None, workspace="default"):
api = Api(url, token=token).config()
api = Api(url, token=token, workspace=workspace).config()
values = api.get_values(type="tool")
@ -116,6 +117,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
args = parser.parse_args()
try:
@ -123,6 +130,8 @@ def main():
show_config(
url=args.api_url,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -18,10 +18,12 @@ import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def start_flow(url, blueprint_name, flow_id, description, parameters=None, token=None):
def start_flow(url, blueprint_name, flow_id, description, parameters=None,
token=None, workspace="default"):
api = Api(url, token=token).flow()
api = Api(url, token=token, workspace=workspace).flow()
api.start(
blueprint_name = blueprint_name,
@ -49,6 +51,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-n', '--blueprint-name',
required=True,
@ -120,6 +128,7 @@ def main():
description = args.description,
parameters = parameters,
token = args.token,
workspace = args.workspace,
)
except Exception as e:

View file

@ -4,19 +4,18 @@ Submits a library document for processing
import argparse
import os
import tabulate
from trustgraph.api import Api, ConfigKey
import json
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = "trustgraph"
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def start_processing(
url, user, document_id, id, flow, collection, tags, token=None
url, document_id, id, flow, collection, tags,
token=None, workspace="default",
):
api = Api(url, token=token).library()
api = Api(url, token=token, workspace=workspace).library()
if tags:
tags = tags.split(",")
@ -27,9 +26,8 @@ def start_processing(
id = id,
document_id = document_id,
flow = flow,
user = user,
collection = collection,
tags = tags
tags = tags,
)
def main():
@ -52,9 +50,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -91,14 +89,14 @@ def main():
try:
start_processing(
url = args.api_url,
user = args.user,
document_id = args.document_id,
id = args.id,
flow = args.flow_id,
collection = args.collection,
tags = args.tags,
token = args.token,
url=args.api_url,
document_id=args.document_id,
id=args.id,
flow=args.flow_id,
collection=args.collection,
tags=args.tags,
token=args.token,
workspace=args.workspace,
)
except Exception as e:
@ -106,4 +104,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -10,10 +10,11 @@ import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def stop_flow(url, flow_id, token=None):
def stop_flow(url, flow_id, token=None, workspace="default"):
api = Api(url, token=token).flow()
api = Api(url, token=token, workspace=workspace).flow()
api.stop(id = flow_id)
@ -36,6 +37,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)',
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-i', '--flow-id',
required=True,
@ -50,6 +57,7 @@ def main():
url=args.api_url,
flow_id=args.flow_id,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -5,21 +5,17 @@ procesing, it doesn't stop in-flight processing at the moment.
import argparse
import os
import tabulate
from trustgraph.api import Api, ConfigKey
import json
from trustgraph.api import Api
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_user = "trustgraph"
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
def stop_processing(
url, user, id, token=None
):
def stop_processing(url, id, token=None, workspace="default"):
api = Api(url, token=token).library()
api = Api(url, token=token, workspace=workspace).library()
api.stop_processing(user = user, id = id)
api.stop_processing(id=id)
def main():
@ -41,9 +37,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default=default_user,
help=f'User ID (default: {default_user})'
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -57,10 +53,10 @@ def main():
try:
stop_processing(
url = args.api_url,
user = args.user,
id = args.id,
token = args.token,
url=args.api_url,
id=args.id,
token=args.token,
workspace=args.workspace,
)
except Exception as e:
@ -68,4 +64,4 @@ def main():
print("Exception:", e, flush=True)
if __name__ == "__main__":
main()
main()

View file

@ -1,25 +1,21 @@
"""
Starts a load operation on a knowledge core which is already stored by
the knowledge manager. You could load a core with tg-put-kg-core and then
run this utility.
Unloads a knowledge core from a flow.
"""
import argparse
import os
import tabulate
from trustgraph.api import Api
import json
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
default_flow = "default"
default_collection = "default"
def unload_kg_core(url, user, id, flow, token=None):
def unload_kg_core(url, id, flow, token=None, workspace="default"):
api = Api(url, token=token).knowledge()
api = Api(url, token=token, workspace=workspace).knowledge()
class_names = api.unload_kg_core(user = user, id = id, flow=flow)
api.unload_kg_core(id=id, flow=flow)
def main():
@ -41,9 +37,9 @@ def main():
)
parser.add_argument(
'-U', '--user',
default="trustgraph",
help='API URL (default: trustgraph)',
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
@ -55,7 +51,7 @@ def main():
parser.add_argument(
'-f', '--flow-id',
default=default_flow,
help=f'Flow ID (default: {default_flow}',
help=f'Flow ID (default: {default_flow})',
)
args = parser.parse_args()
@ -64,10 +60,10 @@ def main():
unload_kg_core(
url=args.api_url,
user=args.user,
id=args.id,
flow=args.flow_id,
token=args.token,
workspace=args.workspace,
)
except Exception as e:

View file

@ -25,6 +25,7 @@ default_pulsar_url = "http://localhost:8080"
default_api_url = os.getenv("TRUSTGRAPH_URL", "http://localhost:8088/")
default_ui_url = "http://localhost:8888"
default_token = os.getenv("TRUSTGRAPH_TOKEN", None)
default_workspace = os.getenv("TRUSTGRAPH_WORKSPACE", "default")
class HealthChecker:
@ -210,10 +211,10 @@ def check_processors(url: str, min_processors: int, timeout: int, tr, token: Opt
return False, tr.t("cli.verify_system_status.processors.error", error=str(e))
def check_flow_blueprints(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]:
def check_flow_blueprints(url: str, timeout: int, tr, token: Optional[str] = None, workspace: str = "default") -> Tuple[bool, str]:
"""Check if flow blueprints are loaded."""
try:
api = Api(url, token=token, timeout=timeout)
api = Api(url, token=token, timeout=timeout, workspace=workspace)
flow_api = api.flow()
blueprints = flow_api.list_blueprints()
@ -227,10 +228,10 @@ def check_flow_blueprints(url: str, timeout: int, tr, token: Optional[str] = Non
return False, tr.t("cli.verify_system_status.flow_blueprints.error", error=str(e))
def check_flows(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]:
def check_flows(url: str, timeout: int, tr, token: Optional[str] = None, workspace: str = "default") -> Tuple[bool, str]:
"""Check if flow manager is responding."""
try:
api = Api(url, token=token, timeout=timeout)
api = Api(url, token=token, timeout=timeout, workspace=workspace)
flow_api = api.flow()
flows = flow_api.list()
@ -242,10 +243,10 @@ def check_flows(url: str, timeout: int, tr, token: Optional[str] = None) -> Tupl
return False, tr.t("cli.verify_system_status.flows.error", error=str(e))
def check_prompts(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]:
def check_prompts(url: str, timeout: int, tr, token: Optional[str] = None, workspace: str = "default") -> Tuple[bool, str]:
"""Check if prompts are loaded."""
try:
api = Api(url, token=token, timeout=timeout)
api = Api(url, token=token, timeout=timeout, workspace=workspace)
config = api.config()
# Import ConfigKey here to avoid top-level import issues
@ -268,14 +269,14 @@ def check_prompts(url: str, timeout: int, tr, token: Optional[str] = None) -> Tu
return False, tr.t("cli.verify_system_status.prompts.error", error=str(e))
def check_library(url: str, timeout: int, tr, token: Optional[str] = None) -> Tuple[bool, str]:
def check_library(url: str, timeout: int, tr, token: Optional[str] = None, workspace: str = "default") -> Tuple[bool, str]:
"""Check if library service is responding."""
try:
api = Api(url, token=token, timeout=timeout)
api = Api(url, token=token, timeout=timeout, workspace=workspace)
library_api = api.library()
# Try to get documents (with default user)
docs = library_api.get_documents(user="trustgraph")
# Try to get documents
docs = library_api.get_documents()
# Success if we get a valid response (even if empty)
return True, tr.t("cli.verify_system_status.library.responding", count=len(docs))
@ -376,6 +377,12 @@ def main():
help='Authentication token (default: $TRUSTGRAPH_TOKEN)'
)
parser.add_argument(
'-w', '--workspace',
default=default_workspace,
help=f'Workspace (default: {default_workspace})',
)
parser.add_argument(
'-v', '--verbose',
action='store_true',
@ -438,6 +445,7 @@ def main():
args.check_timeout,
tr,
args.token,
args.workspace,
)
checker.run_check(
@ -447,6 +455,7 @@ def main():
args.check_timeout,
tr,
args.token,
args.workspace,
)
checker.run_check(
@ -456,6 +465,7 @@ def main():
args.check_timeout,
tr,
args.token,
args.workspace,
)
print()
@ -471,6 +481,7 @@ def main():
args.check_timeout,
tr,
args.token,
args.workspace,
)
print()