trustgraph-cli 2.2.10__tar.gz → 2.2.12__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/PKG-INFO +1 -1
  2. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/dump_queues.py +54 -30
  3. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_agent.py +45 -1
  4. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/monitor_prompts.py +1 -1
  5. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_explain_trace.py +132 -50
  6. trustgraph_cli-2.2.12/trustgraph/cli_version.py +1 -0
  7. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph_cli.egg-info/PKG-INFO +1 -1
  8. trustgraph_cli-2.2.10/trustgraph/cli_version.py +0 -1
  9. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/README.md +0 -0
  10. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/pyproject.toml +0 -0
  11. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/setup.cfg +0 -0
  12. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/__init__.py +0 -0
  13. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/add_library_document.py +0 -0
  14. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/delete_collection.py +0 -0
  15. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/delete_config_item.py +0 -0
  16. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/delete_flow_blueprint.py +0 -0
  17. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/delete_kg_core.py +0 -0
  18. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/delete_mcp_tool.py +0 -0
  19. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/delete_tool.py +0 -0
  20. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/dump_msgpack.py +0 -0
  21. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/get_config_item.py +0 -0
  22. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/get_document_content.py +0 -0
  23. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/get_flow_blueprint.py +0 -0
  24. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/get_kg_core.py +0 -0
  25. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/graph_to_turtle.py +0 -0
  26. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/init_pulsar_manager.py +0 -0
  27. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/init_trustgraph.py +0 -0
  28. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_document_embeddings.py +0 -0
  29. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_document_rag.py +0 -0
  30. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_embeddings.py +0 -0
  31. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_graph_embeddings.py +0 -0
  32. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_graph_rag.py +0 -0
  33. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_llm.py +0 -0
  34. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_mcp_tool.py +0 -0
  35. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_nlp_query.py +0 -0
  36. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_prompt.py +0 -0
  37. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_row_embeddings.py +0 -0
  38. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_rows_query.py +0 -0
  39. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/invoke_structured_query.py +0 -0
  40. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/list_collections.py +0 -0
  41. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/list_config_items.py +0 -0
  42. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/list_explain_traces.py +0 -0
  43. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/load_doc_embeds.py +0 -0
  44. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/load_kg_core.py +0 -0
  45. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/load_knowledge.py +0 -0
  46. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/load_sample_documents.py +0 -0
  47. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/load_structured_data.py +0 -0
  48. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/load_turtle.py +0 -0
  49. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/put_config_item.py +0 -0
  50. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/put_flow_blueprint.py +0 -0
  51. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/put_kg_core.py +0 -0
  52. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/query_graph.py +0 -0
  53. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/remove_library_document.py +0 -0
  54. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/save_doc_embeds.py +0 -0
  55. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/set_collection.py +0 -0
  56. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/set_mcp_tool.py +0 -0
  57. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/set_prompt.py +0 -0
  58. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/set_token_costs.py +0 -0
  59. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/set_tool.py +0 -0
  60. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_config.py +0 -0
  61. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_extraction_provenance.py +0 -0
  62. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_flow_blueprints.py +0 -0
  63. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_flow_state.py +0 -0
  64. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_flows.py +0 -0
  65. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_graph.py +0 -0
  66. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_kg_cores.py +0 -0
  67. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_library_documents.py +0 -0
  68. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_library_processing.py +0 -0
  69. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_mcp_tools.py +0 -0
  70. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_parameter_types.py +0 -0
  71. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_processor_state.py +0 -0
  72. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_prompts.py +0 -0
  73. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_token_costs.py +0 -0
  74. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_token_rate.py +0 -0
  75. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/show_tools.py +0 -0
  76. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/start_flow.py +0 -0
  77. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/start_library_processing.py +0 -0
  78. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/stop_flow.py +0 -0
  79. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/stop_library_processing.py +0 -0
  80. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/unload_kg_core.py +0 -0
  81. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph/cli/verify_system_status.py +0 -0
  82. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph_cli.egg-info/SOURCES.txt +0 -0
  83. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph_cli.egg-info/dependency_links.txt +0 -0
  84. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph_cli.egg-info/entry_points.txt +0 -0
  85. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph_cli.egg-info/requires.txt +0 -0
  86. {trustgraph_cli-2.2.10 → trustgraph_cli-2.2.12}/trustgraph_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trustgraph-cli
3
- Version: 2.2.10
3
+ Version: 2.2.12
4
4
  Summary: TrustGraph provides a means to run a pipeline of flexible AI processing components in a flexible means to achieve a processing pipeline.
5
5
  Author-email: "trustgraph.ai" <security@trustgraph.ai>
6
6
  Project-URL: Homepage, https://github.com/trustgraph-ai/trustgraph
@@ -19,43 +19,67 @@ import argparse
19
19
  from trustgraph.base.subscriber import Subscriber
20
20
  from trustgraph.base.pubsub import get_pubsub
21
21
 
22
+ def decode_json_strings(obj):
23
+ """Recursively decode JSON-encoded string values within a dict/list."""
24
+ if isinstance(obj, dict):
25
+ return {k: decode_json_strings(v) for k, v in obj.items()}
26
+ if isinstance(obj, list):
27
+ return [decode_json_strings(v) for v in obj]
28
+ if isinstance(obj, str):
29
+ try:
30
+ parsed = json.loads(obj)
31
+ if isinstance(parsed, (dict, list)):
32
+ return decode_json_strings(parsed)
33
+ except (json.JSONDecodeError, TypeError):
34
+ pass
35
+ return obj
36
+
37
+
38
+ def to_dict(value):
39
+ """Recursively convert a value to a JSON-serialisable structure."""
40
+
41
+ if value is None or isinstance(value, (bool, int, float)):
42
+ return value
43
+
44
+ if isinstance(value, bytes):
45
+ value = value.decode('utf-8')
46
+
47
+ if isinstance(value, str):
48
+ try:
49
+ return json.loads(value)
50
+ except (json.JSONDecodeError, TypeError):
51
+ return value
52
+
53
+ if isinstance(value, dict):
54
+ return {k: to_dict(v) for k, v in value.items()}
55
+
56
+ if isinstance(value, (list, tuple)):
57
+ return [to_dict(v) for v in value]
58
+
59
+ # Pulsar schema objects expose fields via __dict__
60
+ if hasattr(value, '__dict__'):
61
+ return {
62
+ k: to_dict(v) for k, v in value.__dict__.items()
63
+ if not k.startswith('_')
64
+ }
65
+
66
+ return str(value)
67
+
68
+
22
69
  def format_message(queue_name, msg):
23
70
  """Format a message with timestamp and queue name."""
24
71
  timestamp = datetime.now().isoformat()
25
72
 
26
- # Try to parse as JSON and pretty-print
27
73
  try:
28
- # Handle both Message objects and raw bytes
29
- if hasattr(msg, 'value'):
30
- # Message object with .value() method
31
- value = msg.value()
32
- else:
33
- # Raw bytes from schema-less subscription
34
- value = msg
35
-
36
- # If it's bytes, decode it
37
- if isinstance(value, bytes):
38
- value = value.decode('utf-8')
74
+ value = msg.value() if hasattr(msg, 'value') else msg
75
+ parsed = to_dict(value)
39
76
 
40
- # If it's a string, try to parse as JSON
41
- if isinstance(value, str):
42
- try:
43
- parsed = json.loads(value)
44
- body = json.dumps(parsed, indent=2)
45
- except (json.JSONDecodeError, TypeError):
46
- body = value
77
+ # Unwrap nested JSON strings (e.g. terms values)
78
+ if isinstance(parsed, (dict, list)):
79
+ parsed = decode_json_strings(parsed)
80
+ body = json.dumps(parsed, indent=2, default=str)
47
81
  else:
48
- # Try to convert to dict for pretty printing
49
- try:
50
- # Pulsar schema objects have __dict__ or similar
51
- if hasattr(value, '__dict__'):
52
- parsed = {k: v for k, v in value.__dict__.items()
53
- if not k.startswith('_')}
54
- else:
55
- parsed = str(value)
56
- body = json.dumps(parsed, indent=2, default=str)
57
- except (TypeError, AttributeError):
58
- body = str(value)
82
+ body = str(parsed)
59
83
 
60
84
  except Exception as e:
61
85
  body = f"<Error formatting message: {e}>\n{str(msg)}"
@@ -13,6 +13,11 @@ from trustgraph.api import (
13
13
  Question,
14
14
  Analysis,
15
15
  Conclusion,
16
+ Decomposition,
17
+ Finding,
18
+ Plan,
19
+ StepResult,
20
+ Synthesis,
16
21
  AgentThought,
17
22
  AgentObservation,
18
23
  AgentAnswer,
@@ -209,6 +214,35 @@ def question_explainable(
209
214
  if entity.observation:
210
215
  print(f" Observation: {entity.observation}", file=sys.stderr)
211
216
 
217
+ elif isinstance(entity, Decomposition):
218
+ print(f"\n [decompose] {prov_id}", file=sys.stderr)
219
+ for i, goal in enumerate(entity.goals):
220
+ print(f" Thread {i}: {goal}", file=sys.stderr)
221
+
222
+ elif isinstance(entity, Finding):
223
+ print(f"\n [finding] {prov_id}", file=sys.stderr)
224
+ if entity.goal:
225
+ print(f" Goal: {entity.goal}", file=sys.stderr)
226
+ if entity.document:
227
+ print(f" Document: {entity.document}", file=sys.stderr)
228
+
229
+ elif isinstance(entity, Plan):
230
+ print(f"\n [plan] {prov_id}", file=sys.stderr)
231
+ for i, step in enumerate(entity.steps):
232
+ print(f" Step {i}: {step}", file=sys.stderr)
233
+
234
+ elif isinstance(entity, StepResult):
235
+ print(f"\n [step-result] {prov_id}", file=sys.stderr)
236
+ if entity.step:
237
+ print(f" Step: {entity.step}", file=sys.stderr)
238
+ if entity.document:
239
+ print(f" Document: {entity.document}", file=sys.stderr)
240
+
241
+ elif isinstance(entity, Synthesis):
242
+ print(f"\n [synthesis] {prov_id}", file=sys.stderr)
243
+ if entity.document:
244
+ print(f" Document: {entity.document}", file=sys.stderr)
245
+
212
246
  elif isinstance(entity, Conclusion):
213
247
  print(f"\n [conclusion] {prov_id}", file=sys.stderr)
214
248
  if entity.document:
@@ -233,7 +267,8 @@ def question_explainable(
233
267
 
234
268
  def question(
235
269
  url, question, flow_id, user, collection,
236
- plan=None, state=None, group=None, verbose=False, streaming=True,
270
+ plan=None, state=None, group=None, pattern=None,
271
+ verbose=False, streaming=True,
237
272
  token=None, explainable=False, debug=False
238
273
  ):
239
274
  # Explainable mode uses the API to capture and process provenance events
@@ -273,6 +308,8 @@ def question(
273
308
  request_params["state"] = state
274
309
  if group is not None:
275
310
  request_params["group"] = group
311
+ if pattern is not None:
312
+ request_params["pattern"] = pattern
276
313
 
277
314
  try:
278
315
  # Call agent
@@ -396,6 +433,12 @@ def main():
396
433
  help=f'Agent plan (default: unspecified)'
397
434
  )
398
435
 
436
+ parser.add_argument(
437
+ '-p', '--pattern',
438
+ choices=['react', 'plan-then-execute', 'supervisor'],
439
+ help='Force execution pattern (default: auto-selected by meta-router)'
440
+ )
441
+
399
442
  parser.add_argument(
400
443
  '-s', '--state',
401
444
  help=f'Agent initial state (default: unspecified)'
@@ -444,6 +487,7 @@ def main():
444
487
  plan = args.plan,
445
488
  state = args.state,
446
489
  group = args.group,
490
+ pattern = args.pattern,
447
491
  verbose = args.verbose,
448
492
  streaming = not args.no_streaming,
449
493
  token = args.token,
@@ -24,7 +24,7 @@ from pulsar.schema import BytesSchema
24
24
 
25
25
 
26
26
  default_flow = "default"
27
- default_queue_type = "prompt"
27
+ default_queue_type = "prompt-rag"
28
28
  default_max_lines = 3
29
29
  default_max_width = 80
30
30
 
@@ -27,6 +27,10 @@ from trustgraph.api import (
27
27
  Synthesis,
28
28
  Analysis,
29
29
  Conclusion,
30
+ Decomposition,
31
+ Finding,
32
+ Plan,
33
+ StepResult,
30
34
  )
31
35
 
32
36
  default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
@@ -297,6 +301,23 @@ def print_docrag_text(trace, explain_client, api, user):
297
301
  print("No synthesis data found")
298
302
 
299
303
 
304
+ def _print_document_content(explain_client, api, user, document_uri, label="Answer"):
305
+ """Fetch and print document content, or fall back to URI."""
306
+ if not document_uri:
307
+ return
308
+ content = ""
309
+ if api:
310
+ content = explain_client.fetch_document_content(
311
+ document_uri, api, user
312
+ )
313
+ if content:
314
+ print(f"{label}:")
315
+ for line in content.split("\n"):
316
+ print(f" {line}")
317
+ else:
318
+ print(f"Document: {document_uri}")
319
+
320
+
300
321
  def print_agent_text(trace, explain_client, api, user):
301
322
  """Print Agent trace in text format."""
302
323
  question = trace.get("question")
@@ -310,82 +331,143 @@ def print_agent_text(trace, explain_client, api, user):
310
331
  print(f"Time: {question.timestamp}")
311
332
  print()
312
333
 
313
- # Analysis steps
314
- print("--- Analysis ---")
315
- iterations = trace.get("iterations", [])
316
- if iterations:
317
- for i, analysis in enumerate(iterations, 1):
318
- print(f"Analysis {i}:")
319
- print(f" Thought: {analysis.thought or 'N/A'}")
320
- print(f" Action: {analysis.action or 'N/A'}")
334
+ # Walk the steps list which contains all entity types
335
+ steps = trace.get("steps", [])
336
+
337
+ for step in steps:
338
+
339
+ if isinstance(step, Decomposition):
340
+ print("--- Decomposition ---")
341
+ print(f"Decomposed into {len(step.goals)} research threads:")
342
+ for i, goal in enumerate(step.goals):
343
+ print(f" {i}: {goal}")
344
+ print()
345
+
346
+ elif isinstance(step, Finding):
347
+ print("--- Finding ---")
348
+ print(f"Goal: {step.goal}")
349
+ _print_document_content(
350
+ explain_client, api, user, step.document, "Result",
351
+ )
352
+ print()
353
+
354
+ elif isinstance(step, Plan):
355
+ print("--- Plan ---")
356
+ print(f"Plan with {len(step.steps)} steps:")
357
+ for i, s in enumerate(step.steps):
358
+ print(f" {i}: {s}")
359
+ print()
360
+
361
+ elif isinstance(step, StepResult):
362
+ print("--- Step Result ---")
363
+ print(f"Step: {step.step}")
364
+ _print_document_content(
365
+ explain_client, api, user, step.document, "Result",
366
+ )
367
+ print()
321
368
 
369
+ elif isinstance(step, Analysis):
370
+ print("--- Analysis ---")
371
+ print(f" Action: {step.action or 'N/A'}")
322
372
 
323
- if analysis.arguments:
324
- # Try to pretty-print JSON arguments
373
+ if step.arguments:
325
374
  try:
326
- args_obj = json.loads(analysis.arguments)
375
+ args_obj = json.loads(step.arguments)
327
376
  args_str = json.dumps(args_obj, indent=4)
328
377
  print(f" Arguments:")
329
378
  for line in args_str.split('\n'):
330
379
  print(f" {line}")
331
380
  except Exception:
332
- print(f" Arguments: {analysis.arguments}")
333
- else:
334
- print(f" Arguments: N/A")
381
+ print(f" Arguments: {step.arguments}")
335
382
 
336
- obs = analysis.observation or 'N/A'
383
+ obs = step.observation or 'N/A'
337
384
  if obs and len(obs) > 200:
338
385
  obs = obs[:200] + "... [truncated]"
339
386
  print(f" Observation: {obs}")
340
387
  print()
341
- else:
342
- print("No analysis steps recorded")
343
- print()
344
388
 
345
- # Conclusion
346
- print("--- Conclusion ---")
347
- conclusion = trace.get("conclusion")
348
- if conclusion:
349
- content = ""
350
- if conclusion.document and api:
351
- content = explain_client.fetch_document_content(
352
- conclusion.document, api, user
389
+ elif isinstance(step, Synthesis):
390
+ print("--- Synthesis ---")
391
+ _print_document_content(
392
+ explain_client, api, user, step.document, "Answer",
353
393
  )
354
- if content:
355
- print("Answer:")
356
- for line in content.split("\n"):
357
- print(f" {line}")
358
- elif conclusion.document:
359
- print(f"Document: {conclusion.document}")
360
- else:
361
- print("No conclusion recorded")
362
- else:
363
- print("No conclusion recorded")
394
+ print()
395
+
396
+ elif isinstance(step, Conclusion):
397
+ print("--- Conclusion ---")
398
+ _print_document_content(
399
+ explain_client, api, user, step.document, "Answer",
400
+ )
401
+ print()
402
+
403
+ if not steps:
404
+ print("No trace steps recorded")
405
+ print()
364
406
 
365
407
 
366
408
  def trace_to_dict(trace, trace_type):
367
409
  """Convert trace entities to JSON-serializable dict."""
368
410
  if trace_type == "agent":
369
411
  question = trace.get("question")
412
+
413
+ def _step_to_dict(step):
414
+ if isinstance(step, Decomposition):
415
+ return {
416
+ "type": "decomposition",
417
+ "id": step.uri,
418
+ "goals": step.goals,
419
+ }
420
+ elif isinstance(step, Finding):
421
+ return {
422
+ "type": "finding",
423
+ "id": step.uri,
424
+ "goal": step.goal,
425
+ "document": step.document,
426
+ }
427
+ elif isinstance(step, Plan):
428
+ return {
429
+ "type": "plan",
430
+ "id": step.uri,
431
+ "steps": step.steps,
432
+ }
433
+ elif isinstance(step, StepResult):
434
+ return {
435
+ "type": "step-result",
436
+ "id": step.uri,
437
+ "step": step.step,
438
+ "document": step.document,
439
+ }
440
+ elif isinstance(step, Analysis):
441
+ return {
442
+ "type": "analysis",
443
+ "id": step.uri,
444
+ "action": step.action,
445
+ "arguments": step.arguments,
446
+ "thought": step.thought,
447
+ "observation": step.observation,
448
+ }
449
+ elif isinstance(step, Synthesis):
450
+ return {
451
+ "type": "synthesis",
452
+ "id": step.uri,
453
+ "document": step.document,
454
+ }
455
+ elif isinstance(step, Conclusion):
456
+ return {
457
+ "type": "conclusion",
458
+ "id": step.uri,
459
+ "document": step.document,
460
+ }
461
+ return {"type": step.entity_type, "id": step.uri}
462
+
463
+ steps = trace.get("steps", [])
464
+
370
465
  return {
371
466
  "type": "agent",
372
467
  "session_id": question.uri if question else None,
373
468
  "question": question.query if question else None,
374
469
  "time": question.timestamp if question else None,
375
- "iterations": [
376
- {
377
- "id": a.uri,
378
- "thought": a.thought,
379
- "action": a.action,
380
- "arguments": a.arguments,
381
- "observation": a.observation,
382
- }
383
- for a in trace.get("iterations", [])
384
- ],
385
- "conclusion": {
386
- "id": trace["conclusion"].uri,
387
- "document": trace["conclusion"].document,
388
- } if trace.get("conclusion") else None,
470
+ "steps": [_step_to_dict(s) for s in steps],
389
471
  }
390
472
  elif trace_type == "docrag":
391
473
  question = trace.get("question")
@@ -0,0 +1 @@
1
+ __version__ = "2.2.12"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trustgraph-cli
3
- Version: 2.2.10
3
+ Version: 2.2.12
4
4
  Summary: TrustGraph provides a means to run a pipeline of flexible AI processing components in a flexible means to achieve a processing pipeline.
5
5
  Author-email: "trustgraph.ai" <security@trustgraph.ai>
6
6
  Project-URL: Homepage, https://github.com/trustgraph-ai/trustgraph
@@ -1 +0,0 @@
1
- __version__ = "2.2.10"