coding-agent-tools 0.1.2__tar.gz → 0.1.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coding-agent-tools
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Session search and unified usage analytics for coding agents
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: rich>=13.0.0
@@ -1,3 +1,3 @@
1
1
  """CodingAgentTools package."""
2
2
 
3
- __version__ = "0.1.2"
3
+ __version__ = "0.1.3"
@@ -53,7 +53,7 @@ class ModelBucket:
53
53
 
54
54
  class PricingResolver:
55
55
  def __init__(self) -> None:
56
- self._prices = self._fetch_litellm_prices()
56
+ self._prices, self._fetch_error = self._fetch_litellm_prices()
57
57
  self._lookup_cache: dict[tuple[str, str], Optional[dict]] = {}
58
58
  self._model_aliases = {
59
59
  # Codex aliases
@@ -65,6 +65,23 @@ class PricingResolver:
65
65
  "antigravity-claude-opus-4-6-thinking": "claude-opus-4-1",
66
66
  }
67
67
 
68
+ def pricing_banner(self) -> str:
69
+ if self._prices:
70
+ return (
71
+ "💡 Pricing source: LiteLLM live registry "
72
+ f"({len(self._prices):,} model entries). "
73
+ "Unknown models fall back to observed/source-reported cost."
74
+ )
75
+ if self._fetch_error:
76
+ return (
77
+ "⚠ Pricing source: LiteLLM unavailable "
78
+ f"({self._fetch_error}). Using observed/source-reported cost only."
79
+ )
80
+ return (
81
+ "⚠ Pricing source: LiteLLM unavailable. "
82
+ "Using observed/source-reported cost only."
83
+ )
84
+
68
85
  def estimate_cost(
69
86
  self,
70
87
  model: str,
@@ -176,13 +193,15 @@ class PricingResolver:
176
193
  }
177
194
 
178
195
  @staticmethod
179
- def _fetch_litellm_prices() -> dict:
196
+ def _fetch_litellm_prices() -> tuple[dict, Optional[str]]:
180
197
  try:
181
198
  with urllib.request.urlopen(LITELLM_URL, timeout=15) as response:
182
199
  data = json.loads(response.read())
183
- return data if isinstance(data, dict) else {}
184
- except Exception:
185
- return {}
200
+ if isinstance(data, dict):
201
+ return data, None
202
+ return {}, "unexpected pricing payload"
203
+ except Exception as exc:
204
+ return {}, str(exc)
186
205
 
187
206
 
188
207
  def to_period(ts: datetime, mode: str) -> str:
@@ -386,7 +405,7 @@ def print_table(
386
405
  tw = max(len("Tokens"), max(len(e["total"]) for e in all_data))
387
406
  cow = max(len("(USD)"), max(len(e["cost"]) for e in all_data))
388
407
 
389
- use_color = sys.stdout.isatty() and not os.getenv("NO_COLOR")
408
+ use_color = not os.getenv("NO_COLOR")
390
409
  dim = "\033[90m" if use_color else ""
391
410
  cyan = "\033[36m" if use_color else ""
392
411
  reset = "\033[39m" if use_color else ""
@@ -1005,27 +1024,54 @@ Examples:
1005
1024
  def main() -> None:
1006
1025
  mode, breakdown, source_filter = parse_args(sys.argv[1:])
1007
1026
  pricing = PricingResolver()
1027
+ mode_title = mode.capitalize()
1028
+
1029
+ print(pricing.pricing_banner())
1008
1030
 
1009
1031
  if should_show("claude", source_filter):
1010
1032
  usage, totals = collect_claude(mode, pricing)
1011
- print_table("Claude Code Usage", usage, totals, mode, breakdown)
1033
+ print_table(
1034
+ f"📊 Claude Code Token Usage Report - {mode_title} (From JSONL Sessions)",
1035
+ usage,
1036
+ totals,
1037
+ mode,
1038
+ breakdown,
1039
+ )
1012
1040
 
1013
1041
  if should_show("codex", source_filter):
1014
1042
  usage, totals = collect_codex(mode, pricing)
1015
- print_table("Codex Usage", usage, totals, mode, breakdown)
1043
+ print_table(
1044
+ f"📊 Codex Token Usage Report - {mode_title} (From JSONL Sessions)",
1045
+ usage,
1046
+ totals,
1047
+ mode,
1048
+ breakdown,
1049
+ )
1016
1050
 
1017
1051
  if should_show("openclaw", source_filter):
1018
1052
  usage, totals = collect_openclaw(mode, pricing)
1019
- print_table("OpenClaw Usage", usage, totals, mode, breakdown)
1053
+ print_table(
1054
+ f"📊 OpenClaw Token Usage Report - {mode_title} (From JSONL Sessions)",
1055
+ usage,
1056
+ totals,
1057
+ mode,
1058
+ breakdown,
1059
+ )
1020
1060
 
1021
1061
  if should_show("opencode", source_filter):
1022
1062
  usage, totals = collect_opencode(mode, pricing)
1023
- print_table("OpenCode Usage", usage, totals, mode, breakdown)
1063
+ print_table(
1064
+ f"📊 OpenCode Token Usage Report - {mode_title} (From SQLite DB)",
1065
+ usage,
1066
+ totals,
1067
+ mode,
1068
+ breakdown,
1069
+ )
1024
1070
 
1025
1071
  if should_show("openwhispr", source_filter):
1026
1072
  usage, totals = collect_openwhispr(mode)
1027
1073
  print_table(
1028
- "OpenWhispr Usage",
1074
+ f"📊 OpenWhispr Token Usage Report - {mode_title} (From SQLite DB)",
1029
1075
  usage,
1030
1076
  totals,
1031
1077
  mode,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "coding-agent-tools"
3
- version = "0.1.2"
3
+ version = "0.1.3"
4
4
  description = "Session search and unified usage analytics for coding agents"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"