hyperagents 1.2.3rc5.post3__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 (361) hide show
  1. agents/__init__.py +31 -0
  2. agents/background_monitor.py +453 -0
  3. agents/learning.py +460 -0
  4. agents/planner.py +421 -0
  5. agents/transcriber.py +341 -0
  6. civilization/__init__.py +51 -0
  7. civilization/api/__init__.py +7 -0
  8. civilization/api/civilization_api.py +361 -0
  9. civilization/graph/__init__.py +19 -0
  10. civilization/graph/knowledge_linker.py +348 -0
  11. civilization/graph/org_graph.py +348 -0
  12. civilization/graph/process_graph.py +386 -0
  13. civilization/ingestion/__init__.py +20 -0
  14. civilization/ingestion/chunker.py +273 -0
  15. civilization/ingestion/document_ingestor.py +358 -0
  16. civilization/ingestion/embedder.py +262 -0
  17. civilization/ingestion/extractor.py +224 -0
  18. civilization/interview/__init__.py +19 -0
  19. civilization/interview/gap_detector.py +380 -0
  20. civilization/interview/interviewer.py +323 -0
  21. civilization/interview/questioner.py +363 -0
  22. civilization/retrieval/__init__.py +17 -0
  23. civilization/retrieval/civilization_rag.py +316 -0
  24. civilization/retrieval/context_injector.py +342 -0
  25. civilization/retrieval/relevance_ranker.py +287 -0
  26. civilization/schema.py +299 -0
  27. civilization/store.py +177 -0
  28. civilization/sync/__init__.py +16 -0
  29. civilization/sync/confluence_sync.py +317 -0
  30. civilization/sync/gdrive_sync.py +262 -0
  31. civilization/sync/notion_sync.py +237 -0
  32. civilization/versioning/__init__.py +19 -0
  33. civilization/versioning/diff_engine.py +351 -0
  34. civilization/versioning/staleness_detector.py +303 -0
  35. civilization/versioning/version_manager.py +293 -0
  36. cli/__init__.py +1 -0
  37. cli/doctor.py +334 -0
  38. cli/hyperclaw.py +1357 -0
  39. cli/onboarding.py +469 -0
  40. core/__init__.py +1 -0
  41. core/connectors/__init__.py +119 -0
  42. core/connectors/infrastructure.py +772 -0
  43. core/connectors/messaging.py +586 -0
  44. core/connectors/productivity.py +764 -0
  45. core/connectors/smarthome.py +528 -0
  46. core/connectors/social.py +730 -0
  47. core/hyperrouter/__init__.py +23 -0
  48. core/hyperrouter/bandit.py +218 -0
  49. core/hyperrouter/fast_loop.py +68 -0
  50. core/hyperrouter/slow_loop.py +143 -0
  51. core/hyperstate/__init__.py +24 -0
  52. core/hyperstate/certifier.py +154 -0
  53. core/hyperstate/schema.py +160 -0
  54. core/hyperstate/state_manager.py +103 -0
  55. core/hyperstate/store.py +163 -0
  56. core/providers/__init__.py +121 -0
  57. core/providers/embeddings.py +389 -0
  58. core/providers/image.py +534 -0
  59. core/providers/llm.py +1935 -0
  60. core/providers/search.py +608 -0
  61. core/providers/voice.py +474 -0
  62. hyperagents-1.2.3rc5.post3.dist-info/METADATA +469 -0
  63. hyperagents-1.2.3rc5.post3.dist-info/RECORD +361 -0
  64. hyperagents-1.2.3rc5.post3.dist-info/WHEEL +5 -0
  65. hyperagents-1.2.3rc5.post3.dist-info/entry_points.txt +6 -0
  66. hyperagents-1.2.3rc5.post3.dist-info/licenses/LICENSE +21 -0
  67. hyperagents-1.2.3rc5.post3.dist-info/top_level.txt +13 -0
  68. hyperclaw/__init__.py +67 -0
  69. hyperclaw/__main__.py +220 -0
  70. hyperclaw/agent.py +775 -0
  71. hyperclaw/agent_coordinator.py +577 -0
  72. hyperclaw/anthropic_params.py +225 -0
  73. hyperclaw/api_utils.py +85 -0
  74. hyperclaw/approval_telegram.py +209 -0
  75. hyperclaw/approval_terminal.py +80 -0
  76. hyperclaw/attachments.py +177 -0
  77. hyperclaw/branding.py +55 -0
  78. hyperclaw/brief/__init__.py +11 -0
  79. hyperclaw/brief/cli.py +204 -0
  80. hyperclaw/brief/collect.py +146 -0
  81. hyperclaw/brief/compose.py +333 -0
  82. hyperclaw/brief/diff.py +110 -0
  83. hyperclaw/brief/errors.py +99 -0
  84. hyperclaw/brief/google.py +269 -0
  85. hyperclaw/brief/google_auth.py +294 -0
  86. hyperclaw/brief/links.py +124 -0
  87. hyperclaw/brief/service.py +424 -0
  88. hyperclaw/brief/store.py +205 -0
  89. hyperclaw/brief/tasks.py +200 -0
  90. hyperclaw/chat_scope.py +115 -0
  91. hyperclaw/cli_tui.py +497 -0
  92. hyperclaw/client_guard.py +717 -0
  93. hyperclaw/connection_check.py +113 -0
  94. hyperclaw/cost_guard.py +1728 -0
  95. hyperclaw/default_config/agents.yaml +534 -0
  96. hyperclaw/default_config/hyperclaw.yaml +27 -0
  97. hyperclaw/default_config/models.yaml +161 -0
  98. hyperclaw/deployment.py +39 -0
  99. hyperclaw/digest/__init__.py +9 -0
  100. hyperclaw/digest/cli.py +117 -0
  101. hyperclaw/digest/errors.py +100 -0
  102. hyperclaw/digest/gitlab.py +187 -0
  103. hyperclaw/digest/http.py +113 -0
  104. hyperclaw/digest/redact.py +32 -0
  105. hyperclaw/digest/service.py +271 -0
  106. hyperclaw/digest/slack.py +223 -0
  107. hyperclaw/digest/state.py +124 -0
  108. hyperclaw/digest/summarize.py +198 -0
  109. hyperclaw/digest/tokens.py +143 -0
  110. hyperclaw/distribution.py +46 -0
  111. hyperclaw/documents.py +351 -0
  112. hyperclaw/feeds.py +339 -0
  113. hyperclaw/google_workspace/__init__.py +5 -0
  114. hyperclaw/google_workspace/api.py +151 -0
  115. hyperclaw/google_workspace/auth.py +397 -0
  116. hyperclaw/google_workspace/calendar.py +157 -0
  117. hyperclaw/google_workspace/cli.py +72 -0
  118. hyperclaw/google_workspace/drive.py +236 -0
  119. hyperclaw/google_workspace/errors.py +58 -0
  120. hyperclaw/google_workspace/gmail.py +295 -0
  121. hyperclaw/google_workspace/meet.py +122 -0
  122. hyperclaw/google_workspace/tools.py +319 -0
  123. hyperclaw/hyperspeed.py +57 -0
  124. hyperclaw/integrations_layer.py +1427 -0
  125. hyperclaw/live_state.py +188 -0
  126. hyperclaw/managed_config.py +245 -0
  127. hyperclaw/media_hub.py +179 -0
  128. hyperclaw/memory_manager.py +584 -0
  129. hyperclaw/model_catalog.py +551 -0
  130. hyperclaw/model_policy.py +211 -0
  131. hyperclaw/model_router.py +595 -0
  132. hyperclaw/model_selector.py +72 -0
  133. hyperclaw/naming.py +284 -0
  134. hyperclaw/notices.py +65 -0
  135. hyperclaw/oai_stream.py +106 -0
  136. hyperclaw/orchestrator.py +591 -0
  137. hyperclaw/outbox.py +82 -0
  138. hyperclaw/persona.py +367 -0
  139. hyperclaw/prometheus.py +219 -0
  140. hyperclaw/prompt_assembly.py +157 -0
  141. hyperclaw/provider_setup.py +146 -0
  142. hyperclaw/providers.py +340 -0
  143. hyperclaw/qualification.py +341 -0
  144. hyperclaw/qualification_keys/hyper-d292fd127cef5a3e.pub +1 -0
  145. hyperclaw/qualification_records/anthropic--claude-sonnet-5-5.json +14 -0
  146. hyperclaw/reasoning_display.py +35 -0
  147. hyperclaw/scheduler.py +454 -0
  148. hyperclaw/server.py +847 -0
  149. hyperclaw/setup.py +627 -0
  150. hyperclaw/skills.py +717 -0
  151. hyperclaw/solomon.py +442 -0
  152. hyperclaw/swarm.py +533 -0
  153. hyperclaw/taint.py +832 -0
  154. hyperclaw/team/__init__.py +28 -0
  155. hyperclaw/team/dispatcher.py +431 -0
  156. hyperclaw/team/genesis.py +106 -0
  157. hyperclaw/team/lead.py +110 -0
  158. hyperclaw/team/model.py +135 -0
  159. hyperclaw/team/morning.py +238 -0
  160. hyperclaw/team/repos.py +66 -0
  161. hyperclaw/team/roster.py +264 -0
  162. hyperclaw/team/specialist.py +235 -0
  163. hyperclaw/team/status.py +163 -0
  164. hyperclaw/team/watchers.py +112 -0
  165. hyperclaw/teamsetup/__init__.py +17 -0
  166. hyperclaw/teamsetup/checks.py +208 -0
  167. hyperclaw/teamsetup/item.py +391 -0
  168. hyperclaw/teamsetup/oauth_loopback.py +84 -0
  169. hyperclaw/teamsetup/onboard.py +550 -0
  170. hyperclaw/teamsetup/profile.py +82 -0
  171. hyperclaw/teamsetup/secrets.py +313 -0
  172. hyperclaw/teamsetup/selfcheck.py +295 -0
  173. hyperclaw/teamsetup/service.py +495 -0
  174. hyperclaw/teamsetup/slack_oauth.py +442 -0
  175. hyperclaw/teamsetup/tty.py +62 -0
  176. hyperclaw/telegram_bot.py +1106 -0
  177. hyperclaw/telegram_intake.py +126 -0
  178. hyperclaw/telegram_pairing.py +360 -0
  179. hyperclaw/terminal_provider.py +323 -0
  180. hyperclaw/tools/__init__.py +1 -0
  181. hyperclaw/tools/approval.py +949 -0
  182. hyperclaw/tools/args.py +212 -0
  183. hyperclaw/tools/catalog.py +244 -0
  184. hyperclaw/tools/classify.py +266 -0
  185. hyperclaw/tools/effects.py +724 -0
  186. hyperclaw/tools/egress.py +210 -0
  187. hyperclaw/tools/envelope.py +188 -0
  188. hyperclaw/tools/guard.py +367 -0
  189. hyperclaw/tools/ledger.py +339 -0
  190. hyperclaw/tools/receipts.py +70 -0
  191. hyperclaw/tools/registry.py +318 -0
  192. hyperclaw/tools/service_guard.py +151 -0
  193. hyperclaw/tools/surfaces.py +54 -0
  194. hyperclaw/tools/workspace.py +87 -0
  195. hyperclaw/trading/__init__.py +77 -0
  196. hyperclaw/truth_guard.py +791 -0
  197. hyperclaw/tts.py +124 -0
  198. hyperclaw/tui.py +4255 -0
  199. hyperclaw/tui_bridge.py +938 -0
  200. hyperclaw/unattended.py +60 -0
  201. hyperclaw/updates/__init__.py +54 -0
  202. hyperclaw/updates/check.py +131 -0
  203. hyperclaw/updates/index.py +178 -0
  204. hyperclaw/updates/install.py +110 -0
  205. hyperclaw/updates/managed.py +161 -0
  206. hyperclaw/updates/manifest.py +138 -0
  207. hyperclaw/updates/notices.py +86 -0
  208. hyperclaw/updates/paths.py +53 -0
  209. hyperclaw/updates/release.py +146 -0
  210. hyperclaw/updates/upgrade.py +253 -0
  211. hyperclaw/updates/versioning.py +104 -0
  212. hyperclaw/userconfig.py +119 -0
  213. hyperclaw/xai.py +83 -0
  214. integrations/__init__.py +31 -0
  215. integrations/automation/__init__.py +1 -0
  216. integrations/automation/make.py +87 -0
  217. integrations/automation/zapier.py +87 -0
  218. integrations/base.py +476 -0
  219. integrations/communication/__init__.py +1 -0
  220. integrations/communication/twilio.py +279 -0
  221. integrations/communication/zoom.py +290 -0
  222. integrations/data/__init__.py +1 -0
  223. integrations/data/google_analytics.py +135 -0
  224. integrations/data/postgres.py +182 -0
  225. integrations/data/supabase_connector.py +202 -0
  226. integrations/data/weather_feeds.py +450 -0
  227. integrations/developer/__init__.py +9 -0
  228. integrations/developer/github.py +406 -0
  229. integrations/developer/gitlab.py +298 -0
  230. integrations/enterprise/__init__.py +13 -0
  231. integrations/enterprise/confluence.py +266 -0
  232. integrations/enterprise/hubspot.py +293 -0
  233. integrations/enterprise/jira.py +314 -0
  234. integrations/enterprise/salesforce.py +286 -0
  235. integrations/finance/__init__.py +1 -0
  236. integrations/finance/polymarket_client.py +247 -0
  237. integrations/finance/quickbooks.py +281 -0
  238. integrations/finance/stripe.py +261 -0
  239. integrations/gateway.py +238 -0
  240. integrations/messaging/__init__.py +32 -0
  241. integrations/messaging/discord.py +159 -0
  242. integrations/messaging/email.py +401 -0
  243. integrations/messaging/imessage.py +443 -0
  244. integrations/messaging/signal.py +175 -0
  245. integrations/messaging/slack.py +217 -0
  246. integrations/messaging/sms.py +175 -0
  247. integrations/messaging/teams.py +208 -0
  248. integrations/messaging/telegram.py +260 -0
  249. integrations/messaging/whatsapp.py +203 -0
  250. integrations/productivity/__init__.py +17 -0
  251. integrations/productivity/airtable.py +217 -0
  252. integrations/productivity/asana.py +248 -0
  253. integrations/productivity/google/__init__.py +19 -0
  254. integrations/productivity/google/base.py +89 -0
  255. integrations/productivity/google/calendar.py +272 -0
  256. integrations/productivity/google/docs.py +202 -0
  257. integrations/productivity/google/drive.py +268 -0
  258. integrations/productivity/google/gmail.py +279 -0
  259. integrations/productivity/google/meet.py +218 -0
  260. integrations/productivity/google/sheets.py +222 -0
  261. integrations/productivity/google/tasks.py +199 -0
  262. integrations/productivity/linear.py +279 -0
  263. integrations/productivity/microsoft/__init__.py +13 -0
  264. integrations/productivity/microsoft/base.py +93 -0
  265. integrations/productivity/microsoft/calendar.py +207 -0
  266. integrations/productivity/microsoft/onedrive.py +222 -0
  267. integrations/productivity/microsoft/outlook.py +241 -0
  268. integrations/productivity/microsoft/sharepoint.py +211 -0
  269. integrations/productivity/notion.py +243 -0
  270. integrations/productivity/todoist.py +250 -0
  271. integrations/productivity/trello.py +244 -0
  272. integrations/storage/__init__.py +1 -0
  273. integrations/storage/box.py +279 -0
  274. integrations/storage/dropbox.py +215 -0
  275. integrations/telegram_inbound.py +179 -0
  276. integrations/telegram_poller.py +151 -0
  277. memory/__init__.py +1 -0
  278. memory/causal_graph.py +125 -0
  279. memory/impact_tracker.py +88 -0
  280. memory/vector_memory.py +436 -0
  281. models/__init__.py +12 -0
  282. models/chatjimmy_client.py +210 -0
  283. models/claude_client.py +235 -0
  284. models/claude_code_subagent.py +192 -0
  285. models/openai_client.py +120 -0
  286. models/router.py +162 -0
  287. recursive/discovery_loop.py +118 -0
  288. recursive/optimization_loop.py +135 -0
  289. recursive/validation_loop.py +38 -0
  290. security/__init__.py +1 -0
  291. security/audit_logger.py +106 -0
  292. security/filesystem_guard.py +100 -0
  293. security/hypershield.py +99 -0
  294. security/network_guard.py +97 -0
  295. security/policy_engine.py +198 -0
  296. swarm/__init__.py +1 -0
  297. swarm/agents/__init__.py +0 -0
  298. swarm/agents/base.py +230 -0
  299. swarm/agents/business/__init__.py +0 -0
  300. swarm/agents/business/counsel.py +31 -0
  301. swarm/agents/business/herald.py +32 -0
  302. swarm/agents/business/ledger.py +26 -0
  303. swarm/agents/business/nexus.py +30 -0
  304. swarm/agents/business/ops.py +30 -0
  305. swarm/agents/business/pipeline.py +28 -0
  306. swarm/agents/business/revenue.py +30 -0
  307. swarm/agents/business/sovereign.py +31 -0
  308. swarm/agents/business/strategos.py +27 -0
  309. swarm/agents/business/talent.py +27 -0
  310. swarm/agents/business/venture.py +32 -0
  311. swarm/agents/comms/__init__.py +1 -0
  312. swarm/agents/comms/cipher.py +32 -0
  313. swarm/agents/comms/echo_comms.py +31 -0
  314. swarm/agents/comms/envoy.py +31 -0
  315. swarm/agents/comms/herald_scheduler.py +33 -0
  316. swarm/agents/comms/pulse.py +29 -0
  317. swarm/agents/creative/__init__.py +0 -0
  318. swarm/agents/creative/author.py +27 -0
  319. swarm/agents/creative/lens.py +25 -0
  320. swarm/agents/executive/__init__.py +1 -0
  321. swarm/agents/intelligence/__init__.py +1 -0
  322. swarm/agents/intelligence/arbiter.py +30 -0
  323. swarm/agents/intelligence/sentinel.py +30 -0
  324. swarm/agents/media/__init__.py +0 -0
  325. swarm/agents/personal/__init__.py +0 -0
  326. swarm/agents/personal/atlas.py +27 -0
  327. swarm/agents/personal/hearth.py +26 -0
  328. swarm/agents/personal/midas.py +27 -0
  329. swarm/agents/personal/navigator.py +27 -0
  330. swarm/agents/personal/nourish.py +31 -0
  331. swarm/agents/personal/vitals.py +33 -0
  332. swarm/agents/recursive/__init__.py +0 -0
  333. swarm/agents/recursive/alchemist.py +73 -0
  334. swarm/agents/recursive/calibrator.py +45 -0
  335. swarm/agents/recursive/scout.py +97 -0
  336. swarm/agents/scientific/__init__.py +0 -0
  337. swarm/agents/scientific/cosmos.py +36 -0
  338. swarm/agents/scientific/gaia.py +26 -0
  339. swarm/agents/scientific/medicus.py +33 -0
  340. swarm/agents/scientific/oracle_agent.py +39 -0
  341. swarm/agents/scientific/scribe.py +39 -0
  342. swarm/agents/talent/__init__.py +0 -0
  343. swarm/agents/talent/deal.py +28 -0
  344. swarm/agents/talent/roster.py +29 -0
  345. swarm/agents/talent/scout.py +29 -0
  346. swarm/agents/talent/stage.py +27 -0
  347. swarm/agents/tech/__init__.py +0 -0
  348. swarm/agents/tech/aegis.py +28 -0
  349. swarm/agents/tech/bridge.py +28 -0
  350. swarm/agents/tech/forge.py +28 -0
  351. swarm/agents/trading/__init__.py +1 -0
  352. swarm/agents/trading/global_prediction_engine.py +611 -0
  353. swarm/agents/trading/polymarket_trader.py +165 -0
  354. swarm/agents/trading/prediction_strategist.py +218 -0
  355. swarm/autogen_bridge.py +68 -0
  356. swarm/bid_protocol.py +196 -0
  357. swarm/dispatcher.py +527 -0
  358. swarm/nexus.py +181 -0
  359. swarm/registry.py +112 -0
  360. telegram_listener.py +403 -0
  361. ui/tui/app.py +214 -0
hyperclaw/feeds.py ADDED
@@ -0,0 +1,339 @@
1
+ """
2
+ HyperClaw Live Feeds — Markets, Intel, Polymarket
3
+ """
4
+
5
+ import asyncio
6
+ import logging
7
+ from datetime import datetime, timedelta
8
+ from typing import Optional
9
+ import httpx
10
+ import feedparser
11
+
12
+ logger = logging.getLogger("hyperclaw.feeds")
13
+
14
+ # ── Market Symbols ────────────────────────────────────────────────────────────
15
+ MARKET_SYMBOLS = {
16
+ # Crypto
17
+ "BTC-USD": "Bitcoin",
18
+ "ETH-USD": "Ethereum",
19
+ "SOL-USD": "Solana",
20
+ "AVAX-USD": "Avalanche",
21
+ "LINK-USD": "Chainlink",
22
+ "MATIC-USD": "Polygon",
23
+ "DOT-USD": "Polkadot",
24
+ "ATOM-USD": "Cosmos",
25
+ "UNI-USD": "Uniswap",
26
+ "AAVE-USD": "Aave",
27
+ # Major Indices
28
+ "^GSPC": "S&P 500",
29
+ "^DJI": "Dow Jones",
30
+ "^IXIC": "Nasdaq",
31
+ "^RUT": "Russell 2000",
32
+ "^VIX": "VIX",
33
+ # Mega Caps
34
+ "AAPL": "Apple",
35
+ "MSFT": "Microsoft",
36
+ "GOOGL": "Alphabet",
37
+ "AMZN": "Amazon",
38
+ "NVDA": "NVIDIA",
39
+ "META": "Meta",
40
+ "TSLA": "Tesla",
41
+ "BRK-B": "Berkshire",
42
+ # Tech
43
+ "AMD": "AMD",
44
+ "INTC": "Intel",
45
+ "CRM": "Salesforce",
46
+ "ORCL": "Oracle",
47
+ "ADBE": "Adobe",
48
+ "NFLX": "Netflix",
49
+ "PYPL": "PayPal",
50
+ "SQ": "Block",
51
+ "SHOP": "Shopify",
52
+ "SNOW": "Snowflake",
53
+ "PLTR": "Palantir",
54
+ "COIN": "Coinbase",
55
+ # Finance
56
+ "JPM": "JPMorgan",
57
+ "GS": "Goldman",
58
+ "MS": "Morgan Stanley",
59
+ "BAC": "Bank of America",
60
+ "V": "Visa",
61
+ "MA": "Mastercard",
62
+ # Healthcare
63
+ "UNH": "UnitedHealth",
64
+ "JNJ": "J&J",
65
+ "PFE": "Pfizer",
66
+ "MRNA": "Moderna",
67
+ "LLY": "Eli Lilly",
68
+ # Commodities
69
+ "GC=F": "Gold",
70
+ "SI=F": "Silver",
71
+ "CL=F": "Crude Oil",
72
+ "NG=F": "Natural Gas",
73
+ # Forex
74
+ "DX-Y.NYB": "USD Index",
75
+ "EURUSD=X": "EUR/USD",
76
+ "GBPUSD=X": "GBP/USD",
77
+ "USDJPY=X": "USD/JPY",
78
+ # ETFs
79
+ "SPY": "S&P 500 ETF",
80
+ "QQQ": "Nasdaq ETF",
81
+ "IWM": "Russell 2000 ETF",
82
+ "GLD": "Gold ETF",
83
+ "TLT": "Treasury ETF",
84
+ "XLF": "Financials ETF",
85
+ "XLE": "Energy ETF",
86
+ "ARKK": "ARK Innovation",
87
+ # Space & Defense
88
+ "LMT": "Lockheed",
89
+ "RTX": "Raytheon",
90
+ "BA": "Boeing",
91
+ "RKLB": "Rocket Lab",
92
+ # Travel & Hospitality
93
+ "MAR": "Marriott",
94
+ "HLT": "Hilton",
95
+ "H": "Hyatt",
96
+ "ABNB": "Airbnb",
97
+ "BKNG": "Booking",
98
+ "EXPE": "Expedia",
99
+ }
100
+
101
+ # ── Intel RSS Feeds (60+ sources) ─────────────────────────────────────────────
102
+ INTEL_FEEDS = [
103
+ # Tier 1 — Major Wire Services
104
+ ("Reuters", "https://feeds.reuters.com/reuters/topNews"),
105
+ ("AP News", "https://rsshub.app/apnews/topics/apf-topnews"),
106
+ # Tier 2 — Business/Finance
107
+ ("Bloomberg", "https://feeds.bloomberg.com/markets/news.rss"),
108
+ ("WSJ", "https://feeds.a]arstechnica.com/arstechnica/index"),
109
+ ("FT", "https://www.ft.com/rss/home"),
110
+ ("CNBC", "https://www.cnbc.com/id/100003114/device/rss/rss.html"),
111
+ ("MarketWatch", "https://feeds.marketwatch.com/marketwatch/topstories"),
112
+ ("Barron's", "https://www.barrons.com/feed"),
113
+ # Tier 3 — Tech
114
+ ("TechCrunch", "https://techcrunch.com/feed/"),
115
+ ("Ars Technica", "https://feeds.arstechnica.com/arstechnica/index"),
116
+ ("The Verge", "https://www.theverge.com/rss/index.xml"),
117
+ ("Wired", "https://www.wired.com/feed/rss"),
118
+ ("MIT Tech Review", "https://www.technologyreview.com/feed/"),
119
+ ("Hacker News", "https://news.ycombinator.com/rss"),
120
+ # Tier 4 — AI/ML
121
+ ("AI News", "https://www.artificialintelligence-news.com/feed/"),
122
+ ("OpenAI Blog", "https://openai.com/blog/rss/"),
123
+ ("DeepMind", "https://deepmind.com/blog/feed/basic/"),
124
+ # Tier 5 — Crypto
125
+ ("CoinDesk", "https://www.coindesk.com/arc/outboundfeeds/rss/"),
126
+ ("The Block", "https://www.theblock.co/rss.xml"),
127
+ ("Decrypt", "https://decrypt.co/feed"),
128
+ # Tier 6 — Science/Space
129
+ ("NASA", "https://www.nasa.gov/rss/dyn/breaking_news.rss"),
130
+ ("SpaceNews", "https://spacenews.com/feed/"),
131
+ ("Nature", "https://www.nature.com/nature.rss"),
132
+ ("Science Daily", "https://www.sciencedaily.com/rss/all.xml"),
133
+ # Tier 7 — Geopolitics
134
+ ("Foreign Affairs", "https://www.foreignaffairs.com/rss.xml"),
135
+ ("The Economist", "https://www.economist.com/international/rss.xml"),
136
+ ("Politico", "https://www.politico.com/rss/politicopicks.xml"),
137
+ ("Defense One", "https://www.defenseone.com/rss/all/"),
138
+ ]
139
+
140
+
141
+ YAHOO_HEADERS = {
142
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
143
+ "Accept": "application/json",
144
+ }
145
+
146
+
147
+ async def fetch_yahoo_quote(symbol: str, client: httpx.AsyncClient) -> Optional[dict]:
148
+ """Fetch a single quote from Yahoo Finance."""
149
+ try:
150
+ url = f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}"
151
+ params = {"interval": "1d", "range": "5d"}
152
+ resp = await client.get(url, params=params, headers=YAHOO_HEADERS, timeout=8.0)
153
+ if resp.status_code == 429:
154
+ # Rate limited - wait and retry once
155
+ await asyncio.sleep(1)
156
+ resp = await client.get(url, params=params, headers=YAHOO_HEADERS, timeout=8.0)
157
+ if resp.status_code != 200:
158
+ return None
159
+ data = resp.json()
160
+ result = data.get("chart", {}).get("result", [])
161
+ if not result:
162
+ return None
163
+ meta = result[0].get("meta", {})
164
+ price = meta.get("regularMarketPrice", 0)
165
+ prev_close = meta.get("chartPreviousClose") or meta.get("previousClose") or meta.get("regularMarketPreviousClose") or price
166
+ change_pct = ((price - prev_close) / prev_close * 100) if prev_close and prev_close != price else 0
167
+
168
+ # Get sparkline data
169
+ indicators = result[0].get("indicators", {}).get("quote", [{}])[0]
170
+ closes = indicators.get("close", [])
171
+ sparkline = [c for c in closes if c is not None][-20:] if closes else []
172
+
173
+ return {
174
+ "symbol": symbol.replace("-USD", "").replace("=F", "").replace("^", ""),
175
+ "name": MARKET_SYMBOLS.get(symbol, symbol),
176
+ "price": round(price, 2),
177
+ "change": round(change_pct, 2),
178
+ "sparkline": sparkline,
179
+ }
180
+ except Exception as e:
181
+ logger.debug(f"Yahoo quote error for {symbol}: {e}")
182
+ return None
183
+
184
+
185
+ async def get_markets(symbols: Optional[list] = None) -> list[dict]:
186
+ """Fetch live market data using parallel v8/chart API calls."""
187
+ if symbols is None:
188
+ symbols = list(MARKET_SYMBOLS.keys())[:25] # Top 25 for performance
189
+
190
+ async with httpx.AsyncClient() as client:
191
+ # Fire all requests concurrently with semaphore to avoid hammering
192
+ sem = asyncio.Semaphore(8)
193
+ async def fetch_one(sym):
194
+ async with sem:
195
+ return await fetch_yahoo_quote(sym, client)
196
+
197
+ results = await asyncio.gather(*[fetch_one(s) for s in symbols])
198
+ return [r for r in results if r is not None]
199
+
200
+
201
+ async def fetch_rss_feed(name: str, url: str, client: httpx.AsyncClient) -> list[dict]:
202
+ """Fetch and parse a single RSS feed."""
203
+ try:
204
+ resp = await client.get(url, timeout=8.0, follow_redirects=True)
205
+ if resp.status_code != 200:
206
+ return []
207
+ feed = feedparser.parse(resp.text)
208
+ items = []
209
+ for entry in feed.entries[:5]: # Top 5 per source
210
+ published = entry.get("published_parsed") or entry.get("updated_parsed")
211
+ if published:
212
+ pub_time = datetime(*published[:6])
213
+ delta = datetime.utcnow() - pub_time
214
+ if delta.days > 0:
215
+ time_str = f"{delta.days}D AGO"
216
+ elif delta.seconds >= 3600:
217
+ time_str = f"{delta.seconds // 3600}H AGO"
218
+ else:
219
+ time_str = f"{delta.seconds // 60}M AGO"
220
+ else:
221
+ time_str = "RECENT"
222
+
223
+ items.append({
224
+ "source": name.upper(),
225
+ "title": entry.get("title", "")[:120],
226
+ "summary": (entry.get("summary") or entry.get("description") or "")[:200].strip(),
227
+ "link": entry.get("link", ""),
228
+ "time": time_str,
229
+ "timestamp": pub_time.isoformat() if published else None,
230
+ })
231
+ return items
232
+ except Exception as e:
233
+ logger.debug(f"RSS error for {name}: {e}")
234
+ return []
235
+
236
+
237
+ async def get_intel(limit: int = 30) -> list[dict]:
238
+ """Aggregate intel from all RSS feeds."""
239
+ async with httpx.AsyncClient() as client:
240
+ tasks = [fetch_rss_feed(name, url, client) for name, url in INTEL_FEEDS]
241
+ results = await asyncio.gather(*tasks)
242
+
243
+ all_items = []
244
+ for items in results:
245
+ all_items.extend(items)
246
+
247
+ # Sort by timestamp (most recent first), filter out items without timestamps
248
+ with_ts = [i for i in all_items if i.get("timestamp")]
249
+ with_ts.sort(key=lambda x: x["timestamp"], reverse=True)
250
+
251
+ return with_ts[:limit]
252
+
253
+
254
+ async def get_polymarket(limit: int = 20) -> list[dict]:
255
+ """Fetch live Polymarket prediction markets."""
256
+ try:
257
+ async with httpx.AsyncClient() as client:
258
+ # Polymarket Gamma API (better for browsing markets)
259
+ url = "https://gamma-api.polymarket.com/markets"
260
+ params = {"limit": 100, "active": "true", "closed": "false", "order": "volume", "ascending": "false"}
261
+ resp = await client.get(url, params=params, timeout=10.0)
262
+ if resp.status_code != 200:
263
+ # Fallback to CLOB API
264
+ url = "https://clob.polymarket.com/markets"
265
+ params = {"limit": 50, "active": "true"}
266
+ resp = await client.get(url, params=params, timeout=10.0)
267
+ if resp.status_code != 200:
268
+ return []
269
+
270
+ raw = resp.json()
271
+ # Handle both API structures
272
+ data = raw.get("data", raw) if isinstance(raw, dict) else raw
273
+ if not isinstance(data, list):
274
+ data = [data] if data else []
275
+
276
+ markets = []
277
+ for m in data:
278
+ if m.get("closed") or m.get("archived"):
279
+ continue
280
+ question = m.get("question", "") or m.get("title", "")
281
+ if not question or len(question) < 10:
282
+ continue
283
+
284
+ # Get probability from various possible fields
285
+ prob = 50
286
+ if "outcomePrices" in m:
287
+ try:
288
+ prices = m["outcomePrices"]
289
+ if isinstance(prices, str):
290
+ import json
291
+ prices = json.loads(prices)
292
+ if prices and len(prices) > 0:
293
+ prob = int(float(prices[0]) * 100)
294
+ except:
295
+ pass
296
+ elif "tokens" in m and m["tokens"]:
297
+ try:
298
+ prob = int(float(m["tokens"][0].get("price", 0.5)) * 100)
299
+ except:
300
+ pass
301
+
302
+ vol = m.get("volume", 0) or m.get("volumeNum", 0) or 0
303
+ try:
304
+ vol = float(vol)
305
+ except:
306
+ vol = 0
307
+ vol_str = f"${vol/1e6:.1f}M" if vol >= 1e6 else f"${vol/1e3:.0f}K" if vol >= 1000 else f"${vol:.0f}"
308
+
309
+ markets.append({
310
+ "question": question[:150],
311
+ "prob": max(1, min(99, prob)),
312
+ "volume": vol_str,
313
+ "end_date": m.get("endDate") or m.get("end_date_iso"),
314
+ "slug": m.get("slug") or m.get("condition_id", ""),
315
+ })
316
+
317
+ # Sort by volume (already sorted but ensure)
318
+ markets.sort(key=lambda x: float(x["volume"].replace("$","").replace("M","000000").replace("K","000")), reverse=True)
319
+ return markets[:limit]
320
+ except Exception as e:
321
+ logger.error(f"Polymarket API error: {e}")
322
+ return []
323
+
324
+
325
+ # ── Summit Calendar ───────────────────────────────────────────────────────────
326
+ SUMMITS = [
327
+ {"month": "JUN", "day": "12", "name": "BILDERBERG 2026", "location": "Madrid, Spain", "date": "2026-06-12"},
328
+ {"month": "JUL", "day": "09", "name": "SUN VALLEY CONFERENCE", "location": "Sun Valley, Idaho", "date": "2026-07-09"},
329
+ {"month": "SEP", "day": "17", "name": "UN GENERAL ASSEMBLY", "location": "New York, NY", "date": "2026-09-17"},
330
+ {"month": "NOV", "day": "15", "name": "G20 SUMMIT", "location": "South Africa", "date": "2026-11-15"},
331
+ {"month": "JAN", "day": "20", "name": "WEF DAVOS 2027", "location": "Davos, Switzerland", "date": "2027-01-20"},
332
+ {"month": "FEB", "day": "17", "name": "MUNICH SECURITY CONF", "location": "Munich, Germany", "date": "2027-02-17"},
333
+ ]
334
+
335
+
336
+ def get_summits() -> list[dict]:
337
+ """Return upcoming summits."""
338
+ today = datetime.now().strftime("%Y-%m-%d")
339
+ return [s for s in SUMMITS if s["date"] >= today]
@@ -0,0 +1,5 @@
1
+ """Google Workspace for HyperAgents: Gmail and Calendar first, then Drive,
2
+ Docs, Sheets, Slides and Meet (read). One sign-in per person through the
3
+ team's internal Google app; per-install tokens; every non-read tool behind
4
+ the owner's approval; every read result tainted (Limited Use) and screened
5
+ by the restricted-client guard (hyperclaw/client_guard.py)."""
@@ -0,0 +1,151 @@
1
+ """HTTP to Google's Workspace APIs for one install's own account.
2
+
3
+ Reads are GET only. Writes (a Gmail draft, a Gmail send, a Calendar event)
4
+ use POST/PATCH and are reachable only from ask-tier tools, i.e. after the
5
+ owner pressed Send on the exact payload. Requests go only to Google's API
6
+ hosts below. No token, URL or response body is ever logged: reason codes only.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ import time
12
+ from typing import Any, Callable, Optional
13
+
14
+ import httpx
15
+
16
+ from .errors import GoogleError, Reason
17
+
18
+ log = logging.getLogger("hyperclaw.google")
19
+
20
+ BASES = {
21
+ "gmail": "https://gmail.googleapis.com/gmail/v1",
22
+ "calendar": "https://www.googleapis.com/calendar/v3",
23
+ "drive": "https://www.googleapis.com/drive/v3",
24
+ "docs": "https://docs.googleapis.com/v1",
25
+ "sheets": "https://sheets.googleapis.com/v4",
26
+ "slides": "https://slides.googleapis.com/v1",
27
+ "meet": "https://meet.googleapis.com/v2",
28
+ }
29
+ TIMEOUT = 30.0
30
+ MAX_RETRIES = 2
31
+ MAX_WAIT = 20.0
32
+
33
+
34
+ class GoogleApi:
35
+ """One install's Google client. ``token_fn(force_refresh=False)`` gives
36
+ the access token (auth.access_token by default): it is re-read from this
37
+ install's own store on every client, never shared between installs."""
38
+
39
+ def __init__(self, *, token_fn: Optional[Callable[..., str]] = None,
40
+ client: Optional[httpx.Client] = None,
41
+ sleep: Callable[[float], None] = time.sleep):
42
+ if token_fn is None:
43
+ from . import auth
44
+ token_fn = auth.access_token
45
+ self._token_fn = token_fn
46
+ self._token: Optional[str] = None
47
+ self.client = client or httpx.Client(timeout=TIMEOUT, follow_redirects=False)
48
+ self._own_client = client is None
49
+ self.sleep = sleep
50
+
51
+ def close(self) -> None:
52
+ if self._own_client:
53
+ try:
54
+ self.client.close()
55
+ except Exception:
56
+ pass
57
+
58
+ def __enter__(self):
59
+ return self
60
+
61
+ def __exit__(self, *a):
62
+ self.close()
63
+
64
+ def _headers(self, force: bool = False) -> dict:
65
+ if self._token is None or force:
66
+ try:
67
+ self._token = self._token_fn(force_refresh=force) if force else self._token_fn()
68
+ except TypeError:
69
+ self._token = self._token_fn()
70
+ return {"Authorization": f"Bearer {self._token}"}
71
+
72
+ # ── requests ──
73
+ def get(self, api: str, path: str, params: Any = None, *, raw: bool = False) -> Any:
74
+ return self._request("GET", api, path, params=params, raw=raw)
75
+
76
+ def post(self, api: str, path: str, body: dict) -> Any:
77
+ return self._request("POST", api, path, json=body)
78
+
79
+ def patch(self, api: str, path: str, body: dict) -> Any:
80
+ return self._request("PATCH", api, path, json=body)
81
+
82
+ def _request(self, method: str, api: str, path: str, *, params: Any = None,
83
+ json: Optional[dict] = None, raw: bool = False) -> Any:
84
+ url = f"{BASES[api]}/{path.lstrip('/')}"
85
+ refreshed = False
86
+ attempt = 0
87
+ while True:
88
+ try:
89
+ resp = self.client.request(method, url, params=params, json=json,
90
+ headers=self._headers())
91
+ except httpx.HTTPError as e:
92
+ # A write may have gone through: never retried.
93
+ if method != "GET" or attempt >= MAX_RETRIES:
94
+ raise GoogleError(Reason.UNREACHABLE, type(e).__name__)
95
+ attempt += 1
96
+ self.sleep(min(2 ** attempt, MAX_WAIT))
97
+ continue
98
+ code = resp.status_code
99
+ if code == 401 and not refreshed:
100
+ refreshed = True # reload/refresh this install's token once
101
+ self._headers(force=True)
102
+ continue
103
+ if code == 401:
104
+ raise GoogleError(Reason.EXPIRED, "401")
105
+ if code == 429 or code >= 500:
106
+ if method != "GET" or attempt >= MAX_RETRIES:
107
+ raise GoogleError(Reason.RATE_LIMITED if code == 429 else Reason.UNREACHABLE,
108
+ f"HTTP {code}")
109
+ attempt += 1
110
+ self.sleep(_retry_after(resp) if code == 429 else min(2 ** attempt, MAX_WAIT))
111
+ continue
112
+ if code == 403:
113
+ msg = _message(resp).lower()
114
+ if "scope" in msg or "insufficient" in msg:
115
+ raise GoogleError(Reason.MISSING_SCOPE, "403 scope")
116
+ raise GoogleError(Reason.NO_ACCESS, "403")
117
+ if code in (404, 410):
118
+ raise GoogleError(Reason.NOT_FOUND, str(code))
119
+ if code == 400:
120
+ raise GoogleError(Reason.BAD_REQUEST, "400")
121
+ if code < 200 or code >= 300:
122
+ raise GoogleError(Reason.UNREADABLE, f"HTTP {code}")
123
+ if raw:
124
+ return resp.content
125
+ if not resp.content:
126
+ return {}
127
+ try:
128
+ body = resp.json()
129
+ except Exception:
130
+ raise GoogleError(Reason.UNREADABLE, "not json")
131
+ if not isinstance(body, dict):
132
+ raise GoogleError(Reason.UNREADABLE, "not an object")
133
+ return body
134
+
135
+
136
+ def _retry_after(resp) -> float:
137
+ try:
138
+ return max(0.0, min(float(resp.headers.get("Retry-After", "1")), MAX_WAIT))
139
+ except ValueError:
140
+ return 1.0
141
+
142
+
143
+ def _message(resp) -> str:
144
+ try:
145
+ b = resp.json()
146
+ e = b.get("error") if isinstance(b, dict) else None
147
+ if isinstance(e, dict):
148
+ return str(e.get("message") or "") + " " + str(e.get("status") or "")
149
+ except Exception:
150
+ pass
151
+ return ""