arbis 0.4.5__py3-none-any.whl

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 (95) hide show
  1. arbis/__init__.py +80 -0
  2. arbis/_agent_identity.py +59 -0
  3. arbis/_api.py +631 -0
  4. arbis/_capture_precedence.py +160 -0
  5. arbis/_collector.py +501 -0
  6. arbis/_config.py +25 -0
  7. arbis/_context.py +228 -0
  8. arbis/_data.py +297 -0
  9. arbis/_diff.py +69 -0
  10. arbis/_hooks.py +124 -0
  11. arbis/_http_config.py +59 -0
  12. arbis/_memory_profile.py +77 -0
  13. arbis/_policy.py +351 -0
  14. arbis/_provider_families.py +99 -0
  15. arbis/_span.py +119 -0
  16. arbis/_streaming_errors.py +32 -0
  17. arbis/_tracker.py +1339 -0
  18. arbis/_turn_messages.py +86 -0
  19. arbis/docs/README.md +242 -0
  20. arbis/docs/SKILL.md +1513 -0
  21. arbis/docs/architecture.md +323 -0
  22. arbis/docs/guide.md +811 -0
  23. arbis/docs/minted-identities.md +277 -0
  24. arbis/docs/overview.md +336 -0
  25. arbis/docs/streaming-runs.md +148 -0
  26. arbis/docs/viewer-guide.md +341 -0
  27. arbis/inference/__init__.py +22 -0
  28. arbis/inference/_agent_loops.py +128 -0
  29. arbis/inference/_builder.py +1825 -0
  30. arbis/inference/_data_lineage.py +254 -0
  31. arbis/inference/_fingerprint.py +112 -0
  32. arbis/inference/_graph.py +151 -0
  33. arbis/inference/_lineage.py +623 -0
  34. arbis/inference/_merge_lineage.py +284 -0
  35. arbis/inference/_patterns.py +1079 -0
  36. arbis/inference/_rename_detection.py +120 -0
  37. arbis/inference/_workflow_boundary.py +149 -0
  38. arbis/instrumentors/__init__.py +32 -0
  39. arbis/instrumentors/_anthropic.py +413 -0
  40. arbis/instrumentors/_autogen.py +280 -0
  41. arbis/instrumentors/_bedrock.py +544 -0
  42. arbis/instrumentors/_capture_precedence.py +3 -0
  43. arbis/instrumentors/_crewai.py +366 -0
  44. arbis/instrumentors/_delegation.py +47 -0
  45. arbis/instrumentors/_gemini.py +511 -0
  46. arbis/instrumentors/_httpx.py +312 -0
  47. arbis/instrumentors/_langchain.py +640 -0
  48. arbis/instrumentors/_litellm.py +222 -0
  49. arbis/instrumentors/_llamaindex.py +384 -0
  50. arbis/instrumentors/_llm_adapter.py +1032 -0
  51. arbis/instrumentors/_llm_contract.py +95 -0
  52. arbis/instrumentors/_llm_runtime.py +364 -0
  53. arbis/instrumentors/_openai.py +326 -0
  54. arbis/instrumentors/_openai_agents.py +212 -0
  55. arbis/instrumentors/_openrouter.py +352 -0
  56. arbis/instrumentors/_provider_families.py +3 -0
  57. arbis/instrumentors/_provider_oracle.py +359 -0
  58. arbis/instrumentors/_redaction.py +184 -0
  59. arbis/instrumentors/_requests.py +211 -0
  60. arbis/instrumentors/_transport_runtime.py +228 -0
  61. arbis/otel/__init__.py +9 -0
  62. arbis/otel/_attrs.py +64 -0
  63. arbis/otel/_bridge.py +223 -0
  64. arbis/otel/_metrics.py +73 -0
  65. arbis/otel/_span_builder.py +175 -0
  66. arbis/store/__init__.py +63 -0
  67. arbis/store/_backend.py +27 -0
  68. arbis/store/_http.py +218 -0
  69. arbis/store/_ingest_errors.py +194 -0
  70. arbis/store/_json_dir.py +70 -0
  71. arbis/store/_merkle.py +154 -0
  72. arbis/store/_postgres.py +1154 -0
  73. arbis/store/_postgres_schema.py +287 -0
  74. arbis/store/_segment.py +379 -0
  75. arbis/store/_serialize.py +119 -0
  76. arbis/store/_sqlite.py +90 -0
  77. arbis/store/_stream_client.py +332 -0
  78. arbis/store/_stream_emitter.py +337 -0
  79. arbis/store/_stream_identity.py +218 -0
  80. arbis/store/_workflow_artifact.py +23 -0
  81. arbis/viewer/__init__.py +0 -0
  82. arbis/viewer/__main__.py +4 -0
  83. arbis/viewer/_compliance_display.py +173 -0
  84. arbis/viewer/_compliance_pillars.py +44 -0
  85. arbis/viewer/_demo_data.py +1473 -0
  86. arbis/viewer/_diff_view.py +600 -0
  87. arbis/viewer/_event_detail.py +509 -0
  88. arbis/viewer/_markdown.py +89 -0
  89. arbis/viewer/_postgres_source.py +390 -0
  90. arbis/viewer/app.py +1341 -0
  91. arbis-0.4.5.dist-info/METADATA +318 -0
  92. arbis-0.4.5.dist-info/RECORD +95 -0
  93. arbis-0.4.5.dist-info/WHEEL +5 -0
  94. arbis-0.4.5.dist-info/licenses/LICENSE +21 -0
  95. arbis-0.4.5.dist-info/top_level.txt +1 -0
arbis/__init__.py ADDED
@@ -0,0 +1,80 @@
1
+ """
2
+ arbis: runtime workflow observation for agent systems.
3
+
4
+ Instruments known SDK boundaries, collects execution events,
5
+ and infers workflow graphs from observed behavior.
6
+ """
7
+ from ._tracker import Tracker, discover
8
+ from ._diff import diff
9
+ from ._policy import (
10
+ PolicyEvaluationError,
11
+ PolicyEvalResult,
12
+ SemanticEvalResult,
13
+ SemanticExplainability,
14
+ SemanticRuleResult,
15
+ )
16
+ from ._streaming_errors import StreamingRequiredError
17
+ from ._api import (
18
+ agent,
19
+ begin_agent,
20
+ begin_subagent,
21
+ begin_workflow,
22
+ branch,
23
+ end_agent,
24
+ end_subagent,
25
+ end_workflow,
26
+ evaluate_policy,
27
+ evaluate_rules,
28
+ event,
29
+ human_input,
30
+ route,
31
+ route_decision,
32
+ session,
33
+ step,
34
+ subagent,
35
+ tool,
36
+ wait,
37
+ workflow,
38
+ )
39
+
40
+ def __getattr__(name: str):
41
+ # Lazy so that ``import arbis`` never imports opentelemetry.
42
+ if name == "enable_otel":
43
+ from .otel import enable_otel
44
+
45
+ return enable_otel
46
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
47
+
48
+
49
+ __all__ = [
50
+ "discover",
51
+ "Tracker",
52
+ "diff",
53
+ "enable_otel",
54
+ "session",
55
+ "workflow",
56
+ "tool",
57
+ "wait",
58
+ "StreamingRequiredError",
59
+ "agent",
60
+ "subagent",
61
+ "branch",
62
+ "begin_workflow",
63
+ "end_workflow",
64
+ "begin_agent",
65
+ "end_agent",
66
+ "begin_subagent",
67
+ "end_subagent",
68
+ "human_input",
69
+ "event",
70
+ "step",
71
+ "evaluate_policy",
72
+ "evaluate_rules",
73
+ "PolicyEvalResult",
74
+ "PolicyEvaluationError",
75
+ "SemanticEvalResult",
76
+ "SemanticExplainability",
77
+ "SemanticRuleResult",
78
+ "route",
79
+ "route_decision",
80
+ ]
@@ -0,0 +1,59 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import json
5
+ from typing import Any, Dict, Optional
6
+
7
+ from ._turn_messages import normalize_turn_messages
8
+
9
+
10
+ def stable_hash(value: Any) -> str:
11
+ payload = json.dumps(value, sort_keys=True, default=str)
12
+ return hashlib.sha256(payload.encode()).hexdigest()[:16]
13
+
14
+
15
+ def tools_hash(input_data: Optional[Dict[str, Any]]) -> str:
16
+ if not input_data or not input_data.get("tools"):
17
+ return ""
18
+ names = []
19
+ for tool in input_data.get("tools", []):
20
+ if not isinstance(tool, dict):
21
+ continue
22
+ fn = tool.get("function") or {}
23
+ if isinstance(fn, dict) and fn.get("name"):
24
+ names.append(str(fn["name"]))
25
+ return stable_hash(sorted(names)) if names else stable_hash(input_data.get("tools"))
26
+
27
+
28
+ def system_prompt_hash(input_data: Optional[Dict[str, Any]]) -> str:
29
+ if not input_data:
30
+ return ""
31
+ for msg in normalize_turn_messages(input_data):
32
+ if msg.get("role") == "system":
33
+ return stable_hash(msg.get("content"))
34
+ if input_data.get("system") is not None:
35
+ return stable_hash(input_data.get("system"))
36
+ if input_data.get("instructions") is not None:
37
+ return stable_hash(input_data.get("instructions"))
38
+ return ""
39
+
40
+
41
+ def developer_prompt_hash(input_data: Optional[Dict[str, Any]]) -> str:
42
+ if not input_data:
43
+ return ""
44
+ for msg in normalize_turn_messages(input_data):
45
+ if msg.get("role") == "developer":
46
+ return stable_hash(msg.get("content"))
47
+ return ""
48
+
49
+
50
+ def agent_type_hash(input_data: Optional[Dict[str, Any]]) -> Optional[str]:
51
+ if not input_data:
52
+ return None
53
+ return stable_hash(
54
+ (
55
+ system_prompt_hash(input_data),
56
+ developer_prompt_hash(input_data),
57
+ tools_hash(input_data),
58
+ )
59
+ )