spanforge 2.0.0__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 (101) hide show
  1. spanforge/__init__.py +695 -0
  2. spanforge/_batch_exporter.py +322 -0
  3. spanforge/_cli.py +3081 -0
  4. spanforge/_hooks.py +340 -0
  5. spanforge/_server.py +953 -0
  6. spanforge/_span.py +1015 -0
  7. spanforge/_store.py +287 -0
  8. spanforge/_stream.py +654 -0
  9. spanforge/_trace.py +334 -0
  10. spanforge/_tracer.py +253 -0
  11. spanforge/actor.py +141 -0
  12. spanforge/alerts.py +464 -0
  13. spanforge/auto.py +181 -0
  14. spanforge/baseline.py +336 -0
  15. spanforge/config.py +460 -0
  16. spanforge/consent.py +227 -0
  17. spanforge/consumer.py +379 -0
  18. spanforge/core/__init__.py +5 -0
  19. spanforge/core/compliance_mapping.py +1060 -0
  20. spanforge/cost.py +597 -0
  21. spanforge/debug.py +514 -0
  22. spanforge/drift.py +488 -0
  23. spanforge/egress.py +63 -0
  24. spanforge/eval.py +575 -0
  25. spanforge/event.py +1052 -0
  26. spanforge/exceptions.py +246 -0
  27. spanforge/explain.py +181 -0
  28. spanforge/export/__init__.py +50 -0
  29. spanforge/export/append_only.py +342 -0
  30. spanforge/export/cloud.py +349 -0
  31. spanforge/export/datadog.py +495 -0
  32. spanforge/export/grafana.py +331 -0
  33. spanforge/export/jsonl.py +198 -0
  34. spanforge/export/otel_bridge.py +291 -0
  35. spanforge/export/otlp.py +817 -0
  36. spanforge/export/otlp_bridge.py +231 -0
  37. spanforge/export/redis_backend.py +282 -0
  38. spanforge/export/webhook.py +302 -0
  39. spanforge/exporters/__init__.py +29 -0
  40. spanforge/exporters/console.py +271 -0
  41. spanforge/exporters/jsonl.py +144 -0
  42. spanforge/hitl.py +297 -0
  43. spanforge/inspect.py +429 -0
  44. spanforge/integrations/__init__.py +39 -0
  45. spanforge/integrations/_pricing.py +277 -0
  46. spanforge/integrations/anthropic.py +388 -0
  47. spanforge/integrations/bedrock.py +306 -0
  48. spanforge/integrations/crewai.py +251 -0
  49. spanforge/integrations/gemini.py +349 -0
  50. spanforge/integrations/groq.py +444 -0
  51. spanforge/integrations/langchain.py +349 -0
  52. spanforge/integrations/llamaindex.py +370 -0
  53. spanforge/integrations/ollama.py +286 -0
  54. spanforge/integrations/openai.py +370 -0
  55. spanforge/integrations/together.py +485 -0
  56. spanforge/metrics.py +393 -0
  57. spanforge/metrics_export.py +342 -0
  58. spanforge/migrate.py +278 -0
  59. spanforge/model_registry.py +282 -0
  60. spanforge/models.py +407 -0
  61. spanforge/namespaces/__init__.py +215 -0
  62. spanforge/namespaces/audit.py +253 -0
  63. spanforge/namespaces/cache.py +209 -0
  64. spanforge/namespaces/chain.py +74 -0
  65. spanforge/namespaces/confidence.py +69 -0
  66. spanforge/namespaces/consent.py +85 -0
  67. spanforge/namespaces/cost.py +175 -0
  68. spanforge/namespaces/decision.py +135 -0
  69. spanforge/namespaces/diff.py +146 -0
  70. spanforge/namespaces/drift.py +79 -0
  71. spanforge/namespaces/eval_.py +232 -0
  72. spanforge/namespaces/fence.py +180 -0
  73. spanforge/namespaces/guard.py +104 -0
  74. spanforge/namespaces/hitl.py +92 -0
  75. spanforge/namespaces/latency.py +69 -0
  76. spanforge/namespaces/prompt.py +185 -0
  77. spanforge/namespaces/redact.py +172 -0
  78. spanforge/namespaces/template.py +197 -0
  79. spanforge/namespaces/tool_call.py +76 -0
  80. spanforge/namespaces/trace.py +1006 -0
  81. spanforge/normalizer.py +183 -0
  82. spanforge/presidio_backend.py +149 -0
  83. spanforge/processor.py +258 -0
  84. spanforge/prompt_registry.py +415 -0
  85. spanforge/py.typed +0 -0
  86. spanforge/redact.py +780 -0
  87. spanforge/sampling.py +500 -0
  88. spanforge/schemas/v1.0/schema.json +170 -0
  89. spanforge/schemas/v2.0/schema.json +536 -0
  90. spanforge/signing.py +1152 -0
  91. spanforge/stream.py +559 -0
  92. spanforge/testing.py +376 -0
  93. spanforge/trace.py +199 -0
  94. spanforge/types.py +696 -0
  95. spanforge/ulid.py +304 -0
  96. spanforge/validate.py +383 -0
  97. spanforge-2.0.0.dist-info/METADATA +1777 -0
  98. spanforge-2.0.0.dist-info/RECORD +101 -0
  99. spanforge-2.0.0.dist-info/WHEEL +4 -0
  100. spanforge-2.0.0.dist-info/entry_points.txt +5 -0
  101. spanforge-2.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,76 @@
1
+ """spanforge.namespaces.tool_call \u2014 Tool call namespace payload types (RFC-0001 SPANFORGE).
2
+
3
+ Classes
4
+ -------
5
+ ToolCallPayload tool_call.invoked / tool_call.completed / tool_call.failed
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass, field
10
+ from typing import Any, Literal
11
+
12
+ __all__ = ["ToolCallPayload"]
13
+
14
+ _VALID_STATUSES = frozenset({"success", "failure", "timeout"})
15
+
16
+
17
+ @dataclass
18
+ class ToolCallPayload:
19
+ """RFC-0001 SPANFORGE \u2014 payload for tool_call.* events.
20
+
21
+ Captures all external tool invocations with inputs, outputs, latency, and
22
+ consent-check status (U \u2014 User Rights).
23
+ """
24
+
25
+ call_id: str
26
+ tool_name: str
27
+ latency_ms: float
28
+ status: Literal["success", "failure", "timeout"]
29
+ consent_checked: bool
30
+ tool_version: str | None = None
31
+ inputs: dict[str, Any] = field(default_factory=dict)
32
+ outputs: dict[str, Any] | None = None
33
+ error_message: str | None = None
34
+
35
+ def __post_init__(self) -> None:
36
+ if not self.call_id:
37
+ raise ValueError("ToolCallPayload.call_id must be non-empty")
38
+ if not self.tool_name:
39
+ raise ValueError("ToolCallPayload.tool_name must be non-empty")
40
+ if self.status not in _VALID_STATUSES:
41
+ raise ValueError(
42
+ f"ToolCallPayload.status must be one of {sorted(_VALID_STATUSES)}"
43
+ )
44
+ if self.latency_ms < 0:
45
+ raise ValueError("ToolCallPayload.latency_ms must be >= 0")
46
+
47
+ def to_dict(self) -> dict[str, Any]:
48
+ d: dict[str, Any] = {
49
+ "call_id": self.call_id,
50
+ "tool_name": self.tool_name,
51
+ "latency_ms": self.latency_ms,
52
+ "status": self.status,
53
+ "consent_checked": self.consent_checked,
54
+ "inputs": self.inputs,
55
+ }
56
+ if self.tool_version is not None:
57
+ d["tool_version"] = self.tool_version
58
+ if self.outputs is not None:
59
+ d["outputs"] = self.outputs
60
+ if self.error_message is not None:
61
+ d["error_message"] = self.error_message
62
+ return d
63
+
64
+ @classmethod
65
+ def from_dict(cls, data: dict[str, Any]) -> ToolCallPayload:
66
+ return cls(
67
+ call_id=data["call_id"],
68
+ tool_name=data["tool_name"],
69
+ latency_ms=float(data["latency_ms"]),
70
+ status=data["status"],
71
+ consent_checked=bool(data["consent_checked"]),
72
+ tool_version=data.get("tool_version"),
73
+ inputs=dict(data.get("inputs", {})),
74
+ outputs=data.get("outputs"),
75
+ error_message=data.get("error_message"),
76
+ )