tokenjam 0.2.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 (86) hide show
  1. tokenjam/__init__.py +1 -0
  2. tokenjam/api/__init__.py +0 -0
  3. tokenjam/api/app.py +104 -0
  4. tokenjam/api/deps.py +18 -0
  5. tokenjam/api/middleware.py +28 -0
  6. tokenjam/api/routes/__init__.py +0 -0
  7. tokenjam/api/routes/agents.py +33 -0
  8. tokenjam/api/routes/alerts.py +77 -0
  9. tokenjam/api/routes/budget.py +96 -0
  10. tokenjam/api/routes/cost.py +43 -0
  11. tokenjam/api/routes/drift.py +63 -0
  12. tokenjam/api/routes/logs.py +511 -0
  13. tokenjam/api/routes/metrics.py +81 -0
  14. tokenjam/api/routes/otlp.py +63 -0
  15. tokenjam/api/routes/spans.py +202 -0
  16. tokenjam/api/routes/status.py +84 -0
  17. tokenjam/api/routes/tools.py +22 -0
  18. tokenjam/api/routes/traces.py +92 -0
  19. tokenjam/cli/__init__.py +0 -0
  20. tokenjam/cli/cmd_alerts.py +94 -0
  21. tokenjam/cli/cmd_budget.py +119 -0
  22. tokenjam/cli/cmd_cost.py +90 -0
  23. tokenjam/cli/cmd_demo.py +82 -0
  24. tokenjam/cli/cmd_doctor.py +173 -0
  25. tokenjam/cli/cmd_drift.py +238 -0
  26. tokenjam/cli/cmd_export.py +200 -0
  27. tokenjam/cli/cmd_mcp.py +78 -0
  28. tokenjam/cli/cmd_onboard.py +779 -0
  29. tokenjam/cli/cmd_serve.py +85 -0
  30. tokenjam/cli/cmd_status.py +153 -0
  31. tokenjam/cli/cmd_stop.py +87 -0
  32. tokenjam/cli/cmd_tools.py +45 -0
  33. tokenjam/cli/cmd_traces.py +161 -0
  34. tokenjam/cli/cmd_uninstall.py +159 -0
  35. tokenjam/cli/main.py +110 -0
  36. tokenjam/core/__init__.py +0 -0
  37. tokenjam/core/alerts.py +619 -0
  38. tokenjam/core/api_backend.py +235 -0
  39. tokenjam/core/config.py +360 -0
  40. tokenjam/core/cost.py +102 -0
  41. tokenjam/core/db.py +718 -0
  42. tokenjam/core/drift.py +256 -0
  43. tokenjam/core/ingest.py +265 -0
  44. tokenjam/core/models.py +225 -0
  45. tokenjam/core/pricing.py +54 -0
  46. tokenjam/core/retention.py +21 -0
  47. tokenjam/core/schema_validator.py +156 -0
  48. tokenjam/demo/__init__.py +0 -0
  49. tokenjam/demo/env.py +96 -0
  50. tokenjam/mcp/__init__.py +0 -0
  51. tokenjam/mcp/server.py +1067 -0
  52. tokenjam/otel/__init__.py +0 -0
  53. tokenjam/otel/exporters.py +26 -0
  54. tokenjam/otel/provider.py +207 -0
  55. tokenjam/otel/semconv.py +144 -0
  56. tokenjam/pricing/models.toml +70 -0
  57. tokenjam/py.typed +0 -0
  58. tokenjam/sdk/__init__.py +21 -0
  59. tokenjam/sdk/agent.py +206 -0
  60. tokenjam/sdk/bootstrap.py +120 -0
  61. tokenjam/sdk/http_exporter.py +109 -0
  62. tokenjam/sdk/integrations/__init__.py +0 -0
  63. tokenjam/sdk/integrations/anthropic.py +200 -0
  64. tokenjam/sdk/integrations/autogen.py +97 -0
  65. tokenjam/sdk/integrations/base.py +27 -0
  66. tokenjam/sdk/integrations/bedrock.py +103 -0
  67. tokenjam/sdk/integrations/crewai.py +96 -0
  68. tokenjam/sdk/integrations/gemini.py +131 -0
  69. tokenjam/sdk/integrations/langchain.py +156 -0
  70. tokenjam/sdk/integrations/langgraph.py +101 -0
  71. tokenjam/sdk/integrations/litellm.py +323 -0
  72. tokenjam/sdk/integrations/llamaindex.py +52 -0
  73. tokenjam/sdk/integrations/nemoclaw.py +139 -0
  74. tokenjam/sdk/integrations/openai.py +159 -0
  75. tokenjam/sdk/integrations/openai_agents_sdk.py +47 -0
  76. tokenjam/sdk/transport.py +98 -0
  77. tokenjam/ui/index.html +1213 -0
  78. tokenjam/utils/__init__.py +0 -0
  79. tokenjam/utils/formatting.py +43 -0
  80. tokenjam/utils/ids.py +15 -0
  81. tokenjam/utils/time_parse.py +54 -0
  82. tokenjam-0.2.0.dist-info/METADATA +622 -0
  83. tokenjam-0.2.0.dist-info/RECORD +86 -0
  84. tokenjam-0.2.0.dist-info/WHEEL +4 -0
  85. tokenjam-0.2.0.dist-info/entry_points.txt +2 -0
  86. tokenjam-0.2.0.dist-info/licenses/LICENSE +21 -0
File without changes
@@ -0,0 +1,43 @@
1
+ from rich.console import Console
2
+ from rich.table import Table
3
+ from rich import box
4
+
5
+ console = Console()
6
+ err_console = Console(stderr=True)
7
+
8
+
9
+ def severity_colour(severity: str) -> str:
10
+ return {"critical": "red", "warning": "yellow", "info": "blue"}.get(severity, "white")
11
+
12
+
13
+ def status_icon(status: str) -> str:
14
+ return {
15
+ "ok": "\u2713",
16
+ "error": "\u2717",
17
+ "active": "\u25cf",
18
+ "idle": "\u25cb",
19
+ "completed": "\u25cf",
20
+ "stale": "\u25cb",
21
+ }.get(status, "?")
22
+
23
+
24
+ def format_cost(usd: float) -> str:
25
+ if usd < 0.001:
26
+ return f"${usd:.6f}"
27
+ return f"${usd:.4f}"
28
+
29
+
30
+ def format_tokens(n: int) -> str:
31
+ if n >= 1_000_000:
32
+ return f"{n/1_000_000:.1f}M"
33
+ if n >= 1_000:
34
+ return f"{n/1_000:.1f}k"
35
+ return str(n)
36
+
37
+
38
+ def make_table(*headers: str, box_style=box.SIMPLE) -> Table:
39
+ """Create a pre-styled Rich table."""
40
+ t = Table(box=box_style, show_header=True, header_style="bold dim")
41
+ for h in headers:
42
+ t.add_column(h)
43
+ return t
tokenjam/utils/ids.py ADDED
@@ -0,0 +1,15 @@
1
+ import uuid
2
+
3
+
4
+ def new_uuid() -> str:
5
+ return str(uuid.uuid4())
6
+
7
+
8
+ def new_trace_id() -> str:
9
+ """Generate a 32-char hex trace ID (OTel format)."""
10
+ return uuid.uuid4().hex
11
+
12
+
13
+ def new_span_id() -> str:
14
+ """Generate a 16-char hex span ID (OTel format)."""
15
+ return uuid.uuid4().hex[:16]
@@ -0,0 +1,54 @@
1
+ from datetime import datetime, timedelta, timezone
2
+ import re
3
+
4
+
5
+ _RELATIVE_PATTERN = re.compile(r"^(\d+)([mhd])$")
6
+
7
+
8
+ def parse_since(value: str) -> datetime:
9
+ """
10
+ Parse a --since value and return the corresponding UTC datetime.
11
+ Raises ValueError with a descriptive message for unrecognised formats.
12
+
13
+ Supported formats:
14
+ - 30m, 1h, 12h, 1d, 7d (relative)
15
+ - 2026-03-01 (date, treated as start of day UTC)
16
+ - 2026-03-01T10:00:00Z (ISO datetime)
17
+ """
18
+ value = value.strip()
19
+
20
+ match = _RELATIVE_PATTERN.match(value)
21
+ if match:
22
+ amount = int(match.group(1))
23
+ unit = match.group(2)
24
+ if amount == 0:
25
+ raise ValueError(f"Invalid --since value: {value!r} (amount must be > 0)")
26
+ delta_map = {"m": "minutes", "h": "hours", "d": "days"}
27
+ delta = timedelta(**{delta_map[unit]: amount})
28
+ return utcnow() - delta
29
+
30
+ # Try ISO datetime with timezone
31
+ try:
32
+ dt = datetime.fromisoformat(value)
33
+ if dt.tzinfo is None:
34
+ dt = dt.replace(tzinfo=timezone.utc)
35
+ return dt
36
+ except ValueError:
37
+ pass
38
+
39
+ # Try date-only format
40
+ try:
41
+ dt = datetime.strptime(value, "%Y-%m-%d")
42
+ return dt.replace(tzinfo=timezone.utc)
43
+ except ValueError:
44
+ pass
45
+
46
+ raise ValueError(
47
+ f"Unrecognised --since format: {value!r}. "
48
+ f"Expected: 30m, 1h, 7d, 2026-03-01, or 2026-03-01T10:00:00Z"
49
+ )
50
+
51
+
52
+ def utcnow() -> datetime:
53
+ """Return current UTC time, timezone-aware."""
54
+ return datetime.now(tz=timezone.utc)