costs.py
1 #!/usr/bin/env python3 2 """ 3 Sovereign OS - Cost & Value Tracking Display 4 ============================================= 5 6 Quick view of costs and value attribution in sats and USD. 7 Reads from FO-STATE.json, economics.yaml, and attention ledger. 8 9 Usage: 10 python3 scripts/costs.py # Show costs 11 python3 scripts/costs.py --value # Show value attribution report 12 python3 scripts/costs.py --session-hours 1.5 # Show session costs 13 python3 scripts/costs.py --record "Built feature" 0.75 45 # Record work item 14 """ 15 16 import json 17 import sys 18 from pathlib import Path 19 from datetime import datetime 20 21 # Paths 22 SOVEREIGN_OS = Path(__file__).parent.parent 23 FO_STATE = SOVEREIGN_OS / "sessions" / "FO-STATE.json" 24 ECONOMICS = Path.home() / ".sovereign" / "economics.yaml" 25 26 # Add parent to path for imports 27 sys.path.insert(0, str(SOVEREIGN_OS)) 28 29 30 def load_fo_state(): 31 """Load FO-STATE.json.""" 32 if not FO_STATE.exists(): 33 return None 34 with open(FO_STATE) as f: 35 return json.load(f) 36 37 38 def load_economics(): 39 """Load economics config.""" 40 if not ECONOMICS.exists(): 41 return None 42 try: 43 import yaml 44 with open(ECONOMICS) as f: 45 return yaml.safe_load(f) 46 except ImportError: 47 # Fallback: parse yaml manually for simple values 48 config = {} 49 with open(ECONOMICS) as f: 50 for line in f: 51 if "hourly_rate_usd:" in line: 52 config["hourly_rate_usd"] = float(line.split(":")[1].strip()) 53 elif "sats_per_hour:" in line: 54 config["sats_per_hour"] = int(line.split(":")[1].strip()) 55 elif "btc_price_usd:" in line: 56 config["btc_price_usd"] = float(line.split(":")[1].strip()) 57 return {"operator": config} 58 59 60 def sats_to_usd(sats: int, btc_price: float = 100000) -> float: 61 """Convert sats to USD.""" 62 return round(sats / 100_000_000 * btc_price, 2) 63 64 65 def format_sats(sats: int, btc_price: float = 100000) -> str: 66 """Format sats with USD equivalent.""" 67 usd = sats_to_usd(sats, btc_price) 68 return f"{sats:,} sats (${usd:,.2f})" 69 70 71 def display_costs(session_hours: float = None): 72 """Display current cost tracking.""" 73 fo_state = load_fo_state() 74 economics = load_economics() 75 76 btc_price = 100000 77 sats_per_hour = 172110 # Default 78 hourly_rate = 172.11 79 80 if economics and "operator" in economics: 81 op = economics["operator"] 82 btc_price = op.get("btc_price_usd", btc_price) 83 sats_per_hour = op.get("sats_per_hour", sats_per_hour) 84 hourly_rate = op.get("hourly_rate_usd", hourly_rate) 85 86 print() 87 print("╔══════════════════════════════════════════════════════════════════╗") 88 print("║ SOVEREIGN OS - COST TRACKING ║") 89 print("║ Bitcoin-Anchored Economy ║") 90 print("╚══════════════════════════════════════════════════════════════════╝") 91 print() 92 93 # Operator attention pricing 94 print("┌─────────────────────────────────────────────────────────────────┐") 95 print("│ OPERATOR ATTENTION │") 96 print("├─────────────────────────────────────────────────────────────────┤") 97 print(f"│ Hourly rate: ${hourly_rate:,.2f}/hr = {sats_per_hour:,} sats/hr") 98 print(f"│ Price source: historical_market (Meta W-2 2024)") 99 print(f"│ BTC price: ${btc_price:,}") 100 print("└─────────────────────────────────────────────────────────────────┘") 101 print() 102 103 # Session costs (if hours provided) 104 if session_hours: 105 attention_sats = int(session_hours * sats_per_hour) 106 claude_sats = 3333 # Approximate per-session allocation 107 total_sats = attention_sats + claude_sats 108 109 print("┌─────────────────────────────────────────────────────────────────┐") 110 print(f"│ THIS SESSION ({session_hours:.1f} hours) │") 111 print("├─────────────────────────────────────────────────────────────────┤") 112 print(f"│ Attention: {format_sats(attention_sats, btc_price)}") 113 print(f"│ Claude: {format_sats(claude_sats, btc_price)}") 114 print(f"│ TOTAL INVESTED: {format_sats(total_sats, btc_price)}") 115 print("└─────────────────────────────────────────────────────────────────┘") 116 print() 117 118 # Claude usage from FO-STATE 119 if fo_state and "costs" in fo_state: 120 costs = fo_state["costs"] 121 print("┌─────────────────────────────────────────────────────────────────┐") 122 print("│ CLAUDE USAGE (All Time) │") 123 print("├─────────────────────────────────────────────────────────────────┤") 124 125 if "tokens" in costs: 126 t = costs["tokens"] 127 print(f"│ Input tokens: {t.get('input', 0):,}") 128 print(f"│ Output tokens: {t.get('output', 0):,}") 129 print(f"│ Cache read: {t.get('cache_read', 0):,}") 130 print(f"│ Total tokens: {t.get('total', 0):,}") 131 132 print("├─────────────────────────────────────────────────────────────────┤") 133 134 if "sats" in costs and "usd" in costs: 135 s = costs["sats"] 136 u = costs["usd"] 137 print(f"│ Subscription: {s.get('subscription_sats', 0):,} sats (${u.get('subscription', 0):.2f})") 138 print(f"│ API equivalent: {s.get('api_sats', 0):,} sats (${u.get('api', 0):.2f})") 139 print(f"│ Infra value: {s.get('infra_sats', 0):,} sats (${u.get('infra', 0):.2f})") 140 141 if "savings" in costs: 142 sav = costs["savings"] 143 print("├─────────────────────────────────────────────────────────────────┤") 144 print(f"│ Savings vs API: {sav.get('vs_api_sats', 0):,} sats (${sav.get('vs_api_usd', 0):.2f})") 145 print(f"│ Savings vs Infra:{sav.get('vs_infra_sats', 0):,} sats (${sav.get('vs_infra_usd', 0):.2f})") 146 147 if "efficiency" in costs: 148 eff = costs["efficiency"] 149 print("├─────────────────────────────────────────────────────────────────┤") 150 print(f"│ Efficiency: {eff.get('api_efficiency', 0)}x vs API | {eff.get('infra_efficiency', 0)}x vs infra") 151 152 print(f"│ Last updated: {costs.get('updated', 'unknown')[:19]}") 153 print("└─────────────────────────────────────────────────────────────────┘") 154 155 print() 156 157 158 def display_value_report(): 159 """Display value attribution report.""" 160 try: 161 from core.attention.economics import AttentionEconomics 162 economics = AttentionEconomics() 163 print(economics.format_value_report()) 164 except ImportError as e: 165 print(f"Error: Could not import economics module: {e}") 166 print("Make sure you're running from the Sovereign_OS directory.") 167 except Exception as e: 168 print(f"Error generating value report: {e}") 169 170 171 def record_work_item(description: str, v_score: float, duration_minutes: float): 172 """Record a work item with V-score.""" 173 try: 174 from core.attention.economics import AttentionEconomics 175 economics = AttentionEconomics() 176 177 # Get or start a session for CLI usage 178 session_id = f"cli-{datetime.now().strftime('%Y%m%d')}" 179 ledger = economics.get_today_ledger() 180 181 if session_id not in ledger.sessions: 182 economics.start_session(session_id, context="cli") 183 184 economics.record_work_item( 185 session_id=session_id, 186 description=description, 187 v_score=v_score, 188 duration_minutes=duration_minutes 189 ) 190 191 # Calculate value created 192 sats_per_hour = economics._config.get('operator', {}).get('sats_per_hour', 172110) 193 value_sats = int((duration_minutes / 60) * sats_per_hour * v_score) 194 cost_sats = int((duration_minutes / 60) * sats_per_hour) 195 196 print() 197 print("┌─────────────────────────────────────────────────────────────────┐") 198 print("│ WORK ITEM RECORDED │") 199 print("├─────────────────────────────────────────────────────────────────┤") 200 print(f"│ Description: {description[:50]}") 201 print(f"│ V-Score: {v_score:.2f}") 202 print(f"│ Duration: {duration_minutes:.0f} minutes") 203 print("├─────────────────────────────────────────────────────────────────┤") 204 print(f"│ Cost: {cost_sats:,} sats (attention invested)") 205 print(f"│ Value: {value_sats:,} sats (V-weighted)") 206 print(f"│ ROI: {v_score * 100:.0f}% of potential captured") 207 print("└─────────────────────────────────────────────────────────────────┘") 208 print() 209 210 except ImportError as e: 211 print(f"Error: Could not import economics module: {e}") 212 except Exception as e: 213 print(f"Error recording work item: {e}") 214 215 216 if __name__ == "__main__": 217 session_hours = None 218 219 if len(sys.argv) > 1: 220 if sys.argv[1] == "--value": 221 display_value_report() 222 sys.exit(0) 223 224 elif sys.argv[1] == "--record" and len(sys.argv) >= 5: 225 # --record "description" v_score duration_minutes 226 description = sys.argv[2] 227 v_score = float(sys.argv[3]) 228 duration_minutes = float(sys.argv[4]) 229 record_work_item(description, v_score, duration_minutes) 230 sys.exit(0) 231 232 elif sys.argv[1] == "--session-hours" and len(sys.argv) > 2: 233 session_hours = float(sys.argv[2]) 234 235 elif sys.argv[1] == "--help" or sys.argv[1] == "-h": 236 print(__doc__) 237 sys.exit(0) 238 239 else: 240 try: 241 session_hours = float(sys.argv[1]) 242 except ValueError: 243 print(f"Unknown option: {sys.argv[1]}") 244 print(__doc__) 245 sys.exit(1) 246 247 display_costs(session_hours)