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.
- agents/__init__.py +31 -0
- agents/background_monitor.py +453 -0
- agents/learning.py +460 -0
- agents/planner.py +421 -0
- agents/transcriber.py +341 -0
- civilization/__init__.py +51 -0
- civilization/api/__init__.py +7 -0
- civilization/api/civilization_api.py +361 -0
- civilization/graph/__init__.py +19 -0
- civilization/graph/knowledge_linker.py +348 -0
- civilization/graph/org_graph.py +348 -0
- civilization/graph/process_graph.py +386 -0
- civilization/ingestion/__init__.py +20 -0
- civilization/ingestion/chunker.py +273 -0
- civilization/ingestion/document_ingestor.py +358 -0
- civilization/ingestion/embedder.py +262 -0
- civilization/ingestion/extractor.py +224 -0
- civilization/interview/__init__.py +19 -0
- civilization/interview/gap_detector.py +380 -0
- civilization/interview/interviewer.py +323 -0
- civilization/interview/questioner.py +363 -0
- civilization/retrieval/__init__.py +17 -0
- civilization/retrieval/civilization_rag.py +316 -0
- civilization/retrieval/context_injector.py +342 -0
- civilization/retrieval/relevance_ranker.py +287 -0
- civilization/schema.py +299 -0
- civilization/store.py +177 -0
- civilization/sync/__init__.py +16 -0
- civilization/sync/confluence_sync.py +317 -0
- civilization/sync/gdrive_sync.py +262 -0
- civilization/sync/notion_sync.py +237 -0
- civilization/versioning/__init__.py +19 -0
- civilization/versioning/diff_engine.py +351 -0
- civilization/versioning/staleness_detector.py +303 -0
- civilization/versioning/version_manager.py +293 -0
- cli/__init__.py +1 -0
- cli/doctor.py +334 -0
- cli/hyperclaw.py +1357 -0
- cli/onboarding.py +469 -0
- core/__init__.py +1 -0
- core/connectors/__init__.py +119 -0
- core/connectors/infrastructure.py +772 -0
- core/connectors/messaging.py +586 -0
- core/connectors/productivity.py +764 -0
- core/connectors/smarthome.py +528 -0
- core/connectors/social.py +730 -0
- core/hyperrouter/__init__.py +23 -0
- core/hyperrouter/bandit.py +218 -0
- core/hyperrouter/fast_loop.py +68 -0
- core/hyperrouter/slow_loop.py +143 -0
- core/hyperstate/__init__.py +24 -0
- core/hyperstate/certifier.py +154 -0
- core/hyperstate/schema.py +160 -0
- core/hyperstate/state_manager.py +103 -0
- core/hyperstate/store.py +163 -0
- core/providers/__init__.py +121 -0
- core/providers/embeddings.py +389 -0
- core/providers/image.py +534 -0
- core/providers/llm.py +1935 -0
- core/providers/search.py +608 -0
- core/providers/voice.py +474 -0
- hyperagents-1.2.3rc5.post3.dist-info/METADATA +469 -0
- hyperagents-1.2.3rc5.post3.dist-info/RECORD +361 -0
- hyperagents-1.2.3rc5.post3.dist-info/WHEEL +5 -0
- hyperagents-1.2.3rc5.post3.dist-info/entry_points.txt +6 -0
- hyperagents-1.2.3rc5.post3.dist-info/licenses/LICENSE +21 -0
- hyperagents-1.2.3rc5.post3.dist-info/top_level.txt +13 -0
- hyperclaw/__init__.py +67 -0
- hyperclaw/__main__.py +220 -0
- hyperclaw/agent.py +775 -0
- hyperclaw/agent_coordinator.py +577 -0
- hyperclaw/anthropic_params.py +225 -0
- hyperclaw/api_utils.py +85 -0
- hyperclaw/approval_telegram.py +209 -0
- hyperclaw/approval_terminal.py +80 -0
- hyperclaw/attachments.py +177 -0
- hyperclaw/branding.py +55 -0
- hyperclaw/brief/__init__.py +11 -0
- hyperclaw/brief/cli.py +204 -0
- hyperclaw/brief/collect.py +146 -0
- hyperclaw/brief/compose.py +333 -0
- hyperclaw/brief/diff.py +110 -0
- hyperclaw/brief/errors.py +99 -0
- hyperclaw/brief/google.py +269 -0
- hyperclaw/brief/google_auth.py +294 -0
- hyperclaw/brief/links.py +124 -0
- hyperclaw/brief/service.py +424 -0
- hyperclaw/brief/store.py +205 -0
- hyperclaw/brief/tasks.py +200 -0
- hyperclaw/chat_scope.py +115 -0
- hyperclaw/cli_tui.py +497 -0
- hyperclaw/client_guard.py +717 -0
- hyperclaw/connection_check.py +113 -0
- hyperclaw/cost_guard.py +1728 -0
- hyperclaw/default_config/agents.yaml +534 -0
- hyperclaw/default_config/hyperclaw.yaml +27 -0
- hyperclaw/default_config/models.yaml +161 -0
- hyperclaw/deployment.py +39 -0
- hyperclaw/digest/__init__.py +9 -0
- hyperclaw/digest/cli.py +117 -0
- hyperclaw/digest/errors.py +100 -0
- hyperclaw/digest/gitlab.py +187 -0
- hyperclaw/digest/http.py +113 -0
- hyperclaw/digest/redact.py +32 -0
- hyperclaw/digest/service.py +271 -0
- hyperclaw/digest/slack.py +223 -0
- hyperclaw/digest/state.py +124 -0
- hyperclaw/digest/summarize.py +198 -0
- hyperclaw/digest/tokens.py +143 -0
- hyperclaw/distribution.py +46 -0
- hyperclaw/documents.py +351 -0
- hyperclaw/feeds.py +339 -0
- hyperclaw/google_workspace/__init__.py +5 -0
- hyperclaw/google_workspace/api.py +151 -0
- hyperclaw/google_workspace/auth.py +397 -0
- hyperclaw/google_workspace/calendar.py +157 -0
- hyperclaw/google_workspace/cli.py +72 -0
- hyperclaw/google_workspace/drive.py +236 -0
- hyperclaw/google_workspace/errors.py +58 -0
- hyperclaw/google_workspace/gmail.py +295 -0
- hyperclaw/google_workspace/meet.py +122 -0
- hyperclaw/google_workspace/tools.py +319 -0
- hyperclaw/hyperspeed.py +57 -0
- hyperclaw/integrations_layer.py +1427 -0
- hyperclaw/live_state.py +188 -0
- hyperclaw/managed_config.py +245 -0
- hyperclaw/media_hub.py +179 -0
- hyperclaw/memory_manager.py +584 -0
- hyperclaw/model_catalog.py +551 -0
- hyperclaw/model_policy.py +211 -0
- hyperclaw/model_router.py +595 -0
- hyperclaw/model_selector.py +72 -0
- hyperclaw/naming.py +284 -0
- hyperclaw/notices.py +65 -0
- hyperclaw/oai_stream.py +106 -0
- hyperclaw/orchestrator.py +591 -0
- hyperclaw/outbox.py +82 -0
- hyperclaw/persona.py +367 -0
- hyperclaw/prometheus.py +219 -0
- hyperclaw/prompt_assembly.py +157 -0
- hyperclaw/provider_setup.py +146 -0
- hyperclaw/providers.py +340 -0
- hyperclaw/qualification.py +341 -0
- hyperclaw/qualification_keys/hyper-d292fd127cef5a3e.pub +1 -0
- hyperclaw/qualification_records/anthropic--claude-sonnet-5-5.json +14 -0
- hyperclaw/reasoning_display.py +35 -0
- hyperclaw/scheduler.py +454 -0
- hyperclaw/server.py +847 -0
- hyperclaw/setup.py +627 -0
- hyperclaw/skills.py +717 -0
- hyperclaw/solomon.py +442 -0
- hyperclaw/swarm.py +533 -0
- hyperclaw/taint.py +832 -0
- hyperclaw/team/__init__.py +28 -0
- hyperclaw/team/dispatcher.py +431 -0
- hyperclaw/team/genesis.py +106 -0
- hyperclaw/team/lead.py +110 -0
- hyperclaw/team/model.py +135 -0
- hyperclaw/team/morning.py +238 -0
- hyperclaw/team/repos.py +66 -0
- hyperclaw/team/roster.py +264 -0
- hyperclaw/team/specialist.py +235 -0
- hyperclaw/team/status.py +163 -0
- hyperclaw/team/watchers.py +112 -0
- hyperclaw/teamsetup/__init__.py +17 -0
- hyperclaw/teamsetup/checks.py +208 -0
- hyperclaw/teamsetup/item.py +391 -0
- hyperclaw/teamsetup/oauth_loopback.py +84 -0
- hyperclaw/teamsetup/onboard.py +550 -0
- hyperclaw/teamsetup/profile.py +82 -0
- hyperclaw/teamsetup/secrets.py +313 -0
- hyperclaw/teamsetup/selfcheck.py +295 -0
- hyperclaw/teamsetup/service.py +495 -0
- hyperclaw/teamsetup/slack_oauth.py +442 -0
- hyperclaw/teamsetup/tty.py +62 -0
- hyperclaw/telegram_bot.py +1106 -0
- hyperclaw/telegram_intake.py +126 -0
- hyperclaw/telegram_pairing.py +360 -0
- hyperclaw/terminal_provider.py +323 -0
- hyperclaw/tools/__init__.py +1 -0
- hyperclaw/tools/approval.py +949 -0
- hyperclaw/tools/args.py +212 -0
- hyperclaw/tools/catalog.py +244 -0
- hyperclaw/tools/classify.py +266 -0
- hyperclaw/tools/effects.py +724 -0
- hyperclaw/tools/egress.py +210 -0
- hyperclaw/tools/envelope.py +188 -0
- hyperclaw/tools/guard.py +367 -0
- hyperclaw/tools/ledger.py +339 -0
- hyperclaw/tools/receipts.py +70 -0
- hyperclaw/tools/registry.py +318 -0
- hyperclaw/tools/service_guard.py +151 -0
- hyperclaw/tools/surfaces.py +54 -0
- hyperclaw/tools/workspace.py +87 -0
- hyperclaw/trading/__init__.py +77 -0
- hyperclaw/truth_guard.py +791 -0
- hyperclaw/tts.py +124 -0
- hyperclaw/tui.py +4255 -0
- hyperclaw/tui_bridge.py +938 -0
- hyperclaw/unattended.py +60 -0
- hyperclaw/updates/__init__.py +54 -0
- hyperclaw/updates/check.py +131 -0
- hyperclaw/updates/index.py +178 -0
- hyperclaw/updates/install.py +110 -0
- hyperclaw/updates/managed.py +161 -0
- hyperclaw/updates/manifest.py +138 -0
- hyperclaw/updates/notices.py +86 -0
- hyperclaw/updates/paths.py +53 -0
- hyperclaw/updates/release.py +146 -0
- hyperclaw/updates/upgrade.py +253 -0
- hyperclaw/updates/versioning.py +104 -0
- hyperclaw/userconfig.py +119 -0
- hyperclaw/xai.py +83 -0
- integrations/__init__.py +31 -0
- integrations/automation/__init__.py +1 -0
- integrations/automation/make.py +87 -0
- integrations/automation/zapier.py +87 -0
- integrations/base.py +476 -0
- integrations/communication/__init__.py +1 -0
- integrations/communication/twilio.py +279 -0
- integrations/communication/zoom.py +290 -0
- integrations/data/__init__.py +1 -0
- integrations/data/google_analytics.py +135 -0
- integrations/data/postgres.py +182 -0
- integrations/data/supabase_connector.py +202 -0
- integrations/data/weather_feeds.py +450 -0
- integrations/developer/__init__.py +9 -0
- integrations/developer/github.py +406 -0
- integrations/developer/gitlab.py +298 -0
- integrations/enterprise/__init__.py +13 -0
- integrations/enterprise/confluence.py +266 -0
- integrations/enterprise/hubspot.py +293 -0
- integrations/enterprise/jira.py +314 -0
- integrations/enterprise/salesforce.py +286 -0
- integrations/finance/__init__.py +1 -0
- integrations/finance/polymarket_client.py +247 -0
- integrations/finance/quickbooks.py +281 -0
- integrations/finance/stripe.py +261 -0
- integrations/gateway.py +238 -0
- integrations/messaging/__init__.py +32 -0
- integrations/messaging/discord.py +159 -0
- integrations/messaging/email.py +401 -0
- integrations/messaging/imessage.py +443 -0
- integrations/messaging/signal.py +175 -0
- integrations/messaging/slack.py +217 -0
- integrations/messaging/sms.py +175 -0
- integrations/messaging/teams.py +208 -0
- integrations/messaging/telegram.py +260 -0
- integrations/messaging/whatsapp.py +203 -0
- integrations/productivity/__init__.py +17 -0
- integrations/productivity/airtable.py +217 -0
- integrations/productivity/asana.py +248 -0
- integrations/productivity/google/__init__.py +19 -0
- integrations/productivity/google/base.py +89 -0
- integrations/productivity/google/calendar.py +272 -0
- integrations/productivity/google/docs.py +202 -0
- integrations/productivity/google/drive.py +268 -0
- integrations/productivity/google/gmail.py +279 -0
- integrations/productivity/google/meet.py +218 -0
- integrations/productivity/google/sheets.py +222 -0
- integrations/productivity/google/tasks.py +199 -0
- integrations/productivity/linear.py +279 -0
- integrations/productivity/microsoft/__init__.py +13 -0
- integrations/productivity/microsoft/base.py +93 -0
- integrations/productivity/microsoft/calendar.py +207 -0
- integrations/productivity/microsoft/onedrive.py +222 -0
- integrations/productivity/microsoft/outlook.py +241 -0
- integrations/productivity/microsoft/sharepoint.py +211 -0
- integrations/productivity/notion.py +243 -0
- integrations/productivity/todoist.py +250 -0
- integrations/productivity/trello.py +244 -0
- integrations/storage/__init__.py +1 -0
- integrations/storage/box.py +279 -0
- integrations/storage/dropbox.py +215 -0
- integrations/telegram_inbound.py +179 -0
- integrations/telegram_poller.py +151 -0
- memory/__init__.py +1 -0
- memory/causal_graph.py +125 -0
- memory/impact_tracker.py +88 -0
- memory/vector_memory.py +436 -0
- models/__init__.py +12 -0
- models/chatjimmy_client.py +210 -0
- models/claude_client.py +235 -0
- models/claude_code_subagent.py +192 -0
- models/openai_client.py +120 -0
- models/router.py +162 -0
- recursive/discovery_loop.py +118 -0
- recursive/optimization_loop.py +135 -0
- recursive/validation_loop.py +38 -0
- security/__init__.py +1 -0
- security/audit_logger.py +106 -0
- security/filesystem_guard.py +100 -0
- security/hypershield.py +99 -0
- security/network_guard.py +97 -0
- security/policy_engine.py +198 -0
- swarm/__init__.py +1 -0
- swarm/agents/__init__.py +0 -0
- swarm/agents/base.py +230 -0
- swarm/agents/business/__init__.py +0 -0
- swarm/agents/business/counsel.py +31 -0
- swarm/agents/business/herald.py +32 -0
- swarm/agents/business/ledger.py +26 -0
- swarm/agents/business/nexus.py +30 -0
- swarm/agents/business/ops.py +30 -0
- swarm/agents/business/pipeline.py +28 -0
- swarm/agents/business/revenue.py +30 -0
- swarm/agents/business/sovereign.py +31 -0
- swarm/agents/business/strategos.py +27 -0
- swarm/agents/business/talent.py +27 -0
- swarm/agents/business/venture.py +32 -0
- swarm/agents/comms/__init__.py +1 -0
- swarm/agents/comms/cipher.py +32 -0
- swarm/agents/comms/echo_comms.py +31 -0
- swarm/agents/comms/envoy.py +31 -0
- swarm/agents/comms/herald_scheduler.py +33 -0
- swarm/agents/comms/pulse.py +29 -0
- swarm/agents/creative/__init__.py +0 -0
- swarm/agents/creative/author.py +27 -0
- swarm/agents/creative/lens.py +25 -0
- swarm/agents/executive/__init__.py +1 -0
- swarm/agents/intelligence/__init__.py +1 -0
- swarm/agents/intelligence/arbiter.py +30 -0
- swarm/agents/intelligence/sentinel.py +30 -0
- swarm/agents/media/__init__.py +0 -0
- swarm/agents/personal/__init__.py +0 -0
- swarm/agents/personal/atlas.py +27 -0
- swarm/agents/personal/hearth.py +26 -0
- swarm/agents/personal/midas.py +27 -0
- swarm/agents/personal/navigator.py +27 -0
- swarm/agents/personal/nourish.py +31 -0
- swarm/agents/personal/vitals.py +33 -0
- swarm/agents/recursive/__init__.py +0 -0
- swarm/agents/recursive/alchemist.py +73 -0
- swarm/agents/recursive/calibrator.py +45 -0
- swarm/agents/recursive/scout.py +97 -0
- swarm/agents/scientific/__init__.py +0 -0
- swarm/agents/scientific/cosmos.py +36 -0
- swarm/agents/scientific/gaia.py +26 -0
- swarm/agents/scientific/medicus.py +33 -0
- swarm/agents/scientific/oracle_agent.py +39 -0
- swarm/agents/scientific/scribe.py +39 -0
- swarm/agents/talent/__init__.py +0 -0
- swarm/agents/talent/deal.py +28 -0
- swarm/agents/talent/roster.py +29 -0
- swarm/agents/talent/scout.py +29 -0
- swarm/agents/talent/stage.py +27 -0
- swarm/agents/tech/__init__.py +0 -0
- swarm/agents/tech/aegis.py +28 -0
- swarm/agents/tech/bridge.py +28 -0
- swarm/agents/tech/forge.py +28 -0
- swarm/agents/trading/__init__.py +1 -0
- swarm/agents/trading/global_prediction_engine.py +611 -0
- swarm/agents/trading/polymarket_trader.py +165 -0
- swarm/agents/trading/prediction_strategist.py +218 -0
- swarm/autogen_bridge.py +68 -0
- swarm/bid_protocol.py +196 -0
- swarm/dispatcher.py +527 -0
- swarm/nexus.py +181 -0
- swarm/registry.py +112 -0
- telegram_listener.py +403 -0
- ui/tui/app.py +214 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""Polymarket API Client — Interface for prediction market data and trading."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import asyncio
|
|
4
|
+
import httpx
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Dict, List, Optional, Any
|
|
7
|
+
from web3 import Web3
|
|
8
|
+
from eth_account import Account
|
|
9
|
+
import json
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger("polymarket_client")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PolymarketClient:
|
|
16
|
+
"""Client for Polymarket API interactions."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, private_key: str = None):
|
|
19
|
+
self.base_url = "https://clob.polymarket.com"
|
|
20
|
+
self.data_url = "https://gamma-api.polymarket.com"
|
|
21
|
+
self.private_key = private_key
|
|
22
|
+
self.address = None
|
|
23
|
+
|
|
24
|
+
if private_key:
|
|
25
|
+
account = Account.from_key(private_key)
|
|
26
|
+
self.address = account.address
|
|
27
|
+
|
|
28
|
+
self.session = None
|
|
29
|
+
|
|
30
|
+
async def __aenter__(self):
|
|
31
|
+
self.session = httpx.AsyncClient(timeout=30.0)
|
|
32
|
+
return self
|
|
33
|
+
|
|
34
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
35
|
+
if self.session:
|
|
36
|
+
await self.session.aclose()
|
|
37
|
+
|
|
38
|
+
async def get_markets(self, limit: int = 50, active: bool = True) -> List[Dict]:
|
|
39
|
+
"""Fetch active prediction markets."""
|
|
40
|
+
try:
|
|
41
|
+
params = {
|
|
42
|
+
"limit": limit,
|
|
43
|
+
"active": str(active).lower(),
|
|
44
|
+
"order": "volume24hr",
|
|
45
|
+
"order_direction": "desc"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
response = await self.session.get(
|
|
49
|
+
f"{self.data_url}/markets",
|
|
50
|
+
params=params
|
|
51
|
+
)
|
|
52
|
+
response.raise_for_status()
|
|
53
|
+
|
|
54
|
+
data = response.json()
|
|
55
|
+
return data.get("data", [])
|
|
56
|
+
|
|
57
|
+
except Exception as e:
|
|
58
|
+
logger.error(f"Error fetching markets: {e}")
|
|
59
|
+
return []
|
|
60
|
+
|
|
61
|
+
async def get_market_data(self, condition_id: str) -> Optional[Dict]:
|
|
62
|
+
"""Get detailed data for a specific market."""
|
|
63
|
+
try:
|
|
64
|
+
response = await self.session.get(
|
|
65
|
+
f"{self.data_url}/markets/{condition_id}"
|
|
66
|
+
)
|
|
67
|
+
response.raise_for_status()
|
|
68
|
+
return response.json()
|
|
69
|
+
|
|
70
|
+
except Exception as e:
|
|
71
|
+
logger.error(f"Error fetching market {condition_id}: {e}")
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
async def get_market_orderbook(self, token_id: str) -> Optional[Dict]:
|
|
75
|
+
"""Get order book for a market token."""
|
|
76
|
+
try:
|
|
77
|
+
response = await self.session.get(
|
|
78
|
+
f"{self.base_url}/book",
|
|
79
|
+
params={"token_id": token_id}
|
|
80
|
+
)
|
|
81
|
+
response.raise_for_status()
|
|
82
|
+
return response.json()
|
|
83
|
+
|
|
84
|
+
except Exception as e:
|
|
85
|
+
logger.error(f"Error fetching orderbook for {token_id}: {e}")
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
async def get_market_trades(self, condition_id: str, limit: int = 100) -> List[Dict]:
|
|
89
|
+
"""Get recent trades for a market."""
|
|
90
|
+
try:
|
|
91
|
+
params = {
|
|
92
|
+
"condition_id": condition_id,
|
|
93
|
+
"limit": limit
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
response = await self.session.get(
|
|
97
|
+
f"{self.data_url}/trades",
|
|
98
|
+
params=params
|
|
99
|
+
)
|
|
100
|
+
response.raise_for_status()
|
|
101
|
+
|
|
102
|
+
data = response.json()
|
|
103
|
+
return data.get("data", [])
|
|
104
|
+
|
|
105
|
+
except Exception as e:
|
|
106
|
+
logger.error(f"Error fetching trades for {condition_id}: {e}")
|
|
107
|
+
return []
|
|
108
|
+
|
|
109
|
+
def analyze_market_opportunity(self, market: Dict) -> Dict:
|
|
110
|
+
"""Analyze a market for trading opportunities."""
|
|
111
|
+
try:
|
|
112
|
+
title = market.get("question", "").lower()
|
|
113
|
+
volume_24h = float(market.get("volume24hr", 0))
|
|
114
|
+
|
|
115
|
+
# Calculate basic metrics
|
|
116
|
+
outcomes = market.get("outcomes", [])
|
|
117
|
+
if len(outcomes) >= 2:
|
|
118
|
+
yes_price = float(outcomes[0].get("price", 0.5))
|
|
119
|
+
no_price = float(outcomes[1].get("price", 0.5))
|
|
120
|
+
|
|
121
|
+
implied_prob = yes_price
|
|
122
|
+
liquidity_score = min(volume_24h / 1000, 10) # Scale 0-10
|
|
123
|
+
|
|
124
|
+
# Category classification for advantage assessment
|
|
125
|
+
category = self._classify_market(title)
|
|
126
|
+
advantage_score = self._assess_advantage(category)
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
"condition_id": market.get("condition_id"),
|
|
130
|
+
"title": market.get("question"),
|
|
131
|
+
"category": category,
|
|
132
|
+
"implied_probability": implied_prob,
|
|
133
|
+
"volume_24h": volume_24h,
|
|
134
|
+
"liquidity_score": liquidity_score,
|
|
135
|
+
"advantage_score": advantage_score,
|
|
136
|
+
"opportunity_score": (liquidity_score * advantage_score) / 10,
|
|
137
|
+
"analysis_time": datetime.utcnow().isoformat(),
|
|
138
|
+
"recommendation": self._generate_recommendation(
|
|
139
|
+
category, advantage_score, liquidity_score, implied_prob
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
logger.error(f"Error analyzing market: {e}")
|
|
145
|
+
return {}
|
|
146
|
+
|
|
147
|
+
def _classify_market(self, title: str) -> str:
|
|
148
|
+
"""Classify market by category."""
|
|
149
|
+
title = title.lower()
|
|
150
|
+
|
|
151
|
+
categories = {
|
|
152
|
+
"hospitality": ["hotel", "travel", "tourism", "marriott", "hilton", "hyatt", "airbnb"],
|
|
153
|
+
"ai_tech": ["ai", "artificial intelligence", "openai", "chatgpt", "machine learning", "llm"],
|
|
154
|
+
"economics": ["fed", "interest rate", "inflation", "recession", "gdp", "unemployment"],
|
|
155
|
+
"politics": ["election", "biden", "trump", "congress", "senate", "vote"],
|
|
156
|
+
"crypto": ["bitcoin", "ethereum", "crypto", "btc", "eth", "blockchain"],
|
|
157
|
+
"business": ["apple", "microsoft", "tesla", "meta", "google", "amazon"],
|
|
158
|
+
"geopolitics": ["war", "ukraine", "russia", "china", "nato", "sanctions"],
|
|
159
|
+
"weather": ["hurricane", "drought", "flood", "climate", "temperature"],
|
|
160
|
+
"sports": ["nfl", "nba", "mlb", "olympics", "world cup", "super bowl"]
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
for category, keywords in categories.items():
|
|
164
|
+
if any(keyword in title for keyword in keywords):
|
|
165
|
+
return category
|
|
166
|
+
|
|
167
|
+
return "other"
|
|
168
|
+
|
|
169
|
+
def _assess_advantage(self, category: str) -> float:
|
|
170
|
+
"""Assess our information advantage for this category (0-10)."""
|
|
171
|
+
advantages = {
|
|
172
|
+
"hospitality": 9.5, # the user's direct expertise
|
|
173
|
+
"ai_tech": 9.0, # the organization development insights
|
|
174
|
+
"business": 8.0, # B2B SaaS experience
|
|
175
|
+
"economics": 7.0, # Impact on all ventures
|
|
176
|
+
"crypto": 7.5, # Trading experience
|
|
177
|
+
"politics": 6.0, # General analysis
|
|
178
|
+
"geopolitics": 6.5, # Global intelligence feeds
|
|
179
|
+
"weather": 8.0, # Data integration advantage
|
|
180
|
+
"sports": 5.0, # Limited advantage
|
|
181
|
+
"other": 4.0 # Baseline
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return advantages.get(category, 4.0)
|
|
185
|
+
|
|
186
|
+
def _generate_recommendation(self, category: str, advantage: float,
|
|
187
|
+
liquidity: float, prob: float) -> str:
|
|
188
|
+
"""Generate trading recommendation."""
|
|
189
|
+
if advantage < 6.0:
|
|
190
|
+
return "SKIP - Limited information advantage"
|
|
191
|
+
|
|
192
|
+
if liquidity < 3.0:
|
|
193
|
+
return "SKIP - Insufficient liquidity"
|
|
194
|
+
|
|
195
|
+
if advantage >= 8.0 and liquidity >= 5.0:
|
|
196
|
+
return "HIGH - Strong advantage and liquidity"
|
|
197
|
+
elif advantage >= 7.0 and liquidity >= 3.0:
|
|
198
|
+
return "MEDIUM - Good opportunity for analysis"
|
|
199
|
+
else:
|
|
200
|
+
return "LOW - Monitor for better entry"
|
|
201
|
+
|
|
202
|
+
async def get_portfolio_summary(self) -> Dict:
|
|
203
|
+
"""Get current portfolio summary."""
|
|
204
|
+
if not self.address:
|
|
205
|
+
return {"error": "No wallet address configured"}
|
|
206
|
+
|
|
207
|
+
try:
|
|
208
|
+
response = await self.session.get(
|
|
209
|
+
f"{self.data_url}/positions",
|
|
210
|
+
params={"user": self.address}
|
|
211
|
+
)
|
|
212
|
+
response.raise_for_status()
|
|
213
|
+
|
|
214
|
+
data = response.json()
|
|
215
|
+
positions = data.get("data", [])
|
|
216
|
+
|
|
217
|
+
total_value = sum(float(p.get("size", 0)) * float(p.get("price", 0)) for p in positions)
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
"address": self.address,
|
|
221
|
+
"active_positions": len(positions),
|
|
222
|
+
"total_portfolio_value": total_value,
|
|
223
|
+
"positions": positions,
|
|
224
|
+
"last_updated": datetime.utcnow().isoformat()
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
except Exception as e:
|
|
228
|
+
logger.error(f"Error fetching portfolio: {e}")
|
|
229
|
+
return {"error": str(e)}
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
async def test_polymarket_connection():
|
|
233
|
+
"""Test Polymarket API connection."""
|
|
234
|
+
async with PolymarketClient() as client:
|
|
235
|
+
markets = await client.get_markets(limit=5)
|
|
236
|
+
|
|
237
|
+
print(f"Fetched {len(markets)} markets")
|
|
238
|
+
for market in markets[:3]:
|
|
239
|
+
analysis = client.analyze_market_opportunity(market)
|
|
240
|
+
print(f"\nMarket: {analysis.get('title', 'Unknown')}")
|
|
241
|
+
print(f"Category: {analysis.get('category')}")
|
|
242
|
+
print(f"Advantage Score: {analysis.get('advantage_score'):.1f}/10")
|
|
243
|
+
print(f"Recommendation: {analysis.get('recommendation')}")
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
if __name__ == "__main__":
|
|
247
|
+
asyncio.run(test_polymarket_connection())
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""QuickBooksConnector — QuickBooks Online integration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from urllib.parse import quote
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
|
|
10
|
+
from integrations.base import (
|
|
11
|
+
BaseConnector,
|
|
12
|
+
ConnectorCapability,
|
|
13
|
+
ConnectorInfo,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger("hyperclaw.integrations.quickbooks")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class QuickBooksConnector(BaseConnector):
|
|
20
|
+
"""
|
|
21
|
+
QuickBooks Online connector.
|
|
22
|
+
|
|
23
|
+
Required config:
|
|
24
|
+
- client_id: OAuth2 client ID
|
|
25
|
+
- client_secret: OAuth2 client secret
|
|
26
|
+
- realm_id: Company ID (optional - can be set after OAuth flow)
|
|
27
|
+
- access_token: OAuth2 access token (set after auth flow)
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
BASE_URL = "https://quickbooks.api.intuit.com/v3/company"
|
|
31
|
+
|
|
32
|
+
# HyperShield context for financial data
|
|
33
|
+
hypershield_context = "financial_data"
|
|
34
|
+
|
|
35
|
+
def __init__(self, config: dict) -> None:
|
|
36
|
+
self.config = config
|
|
37
|
+
self.client_id = config.get("client_id", "")
|
|
38
|
+
self.client_secret = config.get("client_secret", "")
|
|
39
|
+
self.realm_id = config.get("realm_id", "")
|
|
40
|
+
self.access_token = config.get("access_token", "")
|
|
41
|
+
|
|
42
|
+
if config.get("enabled", False):
|
|
43
|
+
if not self.client_id or not self.client_secret:
|
|
44
|
+
raise ValueError(
|
|
45
|
+
"QuickBooksConnector requires client_id and client_secret"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
self._client: httpx.AsyncClient | None = None
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def info(self) -> ConnectorInfo:
|
|
52
|
+
return ConnectorInfo(
|
|
53
|
+
connector_id="quickbooks",
|
|
54
|
+
platform="quickbooks",
|
|
55
|
+
category="finance",
|
|
56
|
+
capabilities=frozenset(
|
|
57
|
+
[
|
|
58
|
+
ConnectorCapability.READ_DATA,
|
|
59
|
+
ConnectorCapability.WRITE_DATA,
|
|
60
|
+
ConnectorCapability.LIST_DATA,
|
|
61
|
+
ConnectorCapability.SEARCH,
|
|
62
|
+
]
|
|
63
|
+
),
|
|
64
|
+
auth_type="oauth2",
|
|
65
|
+
rate_limit_per_minute=60,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
async def _get_client(self) -> httpx.AsyncClient:
|
|
69
|
+
if self._client is None:
|
|
70
|
+
self._client = httpx.AsyncClient(
|
|
71
|
+
timeout=30.0,
|
|
72
|
+
headers={
|
|
73
|
+
"Authorization": f"Bearer {self.access_token}",
|
|
74
|
+
"Accept": "application/json",
|
|
75
|
+
"Content-Type": "application/json",
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
return self._client
|
|
79
|
+
|
|
80
|
+
def _api_url(self, endpoint: str) -> str:
|
|
81
|
+
"""Build API URL with realm_id."""
|
|
82
|
+
return f"{self.BASE_URL}/{self.realm_id}/{endpoint}"
|
|
83
|
+
|
|
84
|
+
async def health(self) -> bool:
|
|
85
|
+
"""Check if QuickBooks API is accessible."""
|
|
86
|
+
# In production, OAuth2 flow required before API calls
|
|
87
|
+
# Return True to indicate connector is configured
|
|
88
|
+
return bool(self.client_id and self.client_secret)
|
|
89
|
+
|
|
90
|
+
async def list_invoices(self, limit: int = 20) -> dict:
|
|
91
|
+
"""List invoices."""
|
|
92
|
+
client = await self._get_client()
|
|
93
|
+
|
|
94
|
+
query = quote(f"SELECT * FROM Invoice MAXRESULTS {limit}")
|
|
95
|
+
response = await client.get(self._api_url(f"query?query={query}"))
|
|
96
|
+
|
|
97
|
+
if response.status_code != 200:
|
|
98
|
+
raise Exception(f"QuickBooks list_invoices failed: {response.text}")
|
|
99
|
+
|
|
100
|
+
return response.json()
|
|
101
|
+
|
|
102
|
+
async def create_invoice(
|
|
103
|
+
self, customer_ref: dict, line_items: list[dict]
|
|
104
|
+
) -> dict:
|
|
105
|
+
"""Create an invoice."""
|
|
106
|
+
client = await self._get_client()
|
|
107
|
+
|
|
108
|
+
payload = {
|
|
109
|
+
"CustomerRef": customer_ref,
|
|
110
|
+
"Line": line_items,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
response = await client.post(
|
|
114
|
+
self._api_url("invoice"),
|
|
115
|
+
json=payload,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
if response.status_code not in (200, 201):
|
|
119
|
+
raise Exception(f"QuickBooks create_invoice failed: {response.text}")
|
|
120
|
+
|
|
121
|
+
return response.json()
|
|
122
|
+
|
|
123
|
+
async def list_expenses(self, limit: int = 20) -> dict:
|
|
124
|
+
"""List expenses (purchases)."""
|
|
125
|
+
client = await self._get_client()
|
|
126
|
+
|
|
127
|
+
query = quote(f"SELECT * FROM Purchase MAXRESULTS {limit}")
|
|
128
|
+
response = await client.get(self._api_url(f"query?query={query}"))
|
|
129
|
+
|
|
130
|
+
if response.status_code != 200:
|
|
131
|
+
raise Exception(f"QuickBooks list_expenses failed: {response.text}")
|
|
132
|
+
|
|
133
|
+
return response.json()
|
|
134
|
+
|
|
135
|
+
async def create_expense(
|
|
136
|
+
self, vendor_ref: dict, amount: float, description: str
|
|
137
|
+
) -> dict:
|
|
138
|
+
"""Create an expense (purchase)."""
|
|
139
|
+
client = await self._get_client()
|
|
140
|
+
|
|
141
|
+
payload = {
|
|
142
|
+
"AccountRef": vendor_ref,
|
|
143
|
+
"PaymentType": "Cash",
|
|
144
|
+
"Line": [
|
|
145
|
+
{
|
|
146
|
+
"Amount": amount,
|
|
147
|
+
"Description": description,
|
|
148
|
+
"DetailType": "AccountBasedExpenseLineDetail",
|
|
149
|
+
"AccountBasedExpenseLineDetail": {
|
|
150
|
+
"AccountRef": vendor_ref,
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
response = await client.post(
|
|
157
|
+
self._api_url("purchase"),
|
|
158
|
+
json=payload,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
if response.status_code not in (200, 201):
|
|
162
|
+
raise Exception(f"QuickBooks create_expense failed: {response.text}")
|
|
163
|
+
|
|
164
|
+
return response.json()
|
|
165
|
+
|
|
166
|
+
async def get_profit_loss_report(
|
|
167
|
+
self, start_date: str, end_date: str
|
|
168
|
+
) -> dict:
|
|
169
|
+
"""Get Profit and Loss report."""
|
|
170
|
+
client = await self._get_client()
|
|
171
|
+
|
|
172
|
+
response = await client.get(
|
|
173
|
+
self._api_url("reports/ProfitAndLoss"),
|
|
174
|
+
params={
|
|
175
|
+
"start_date": start_date,
|
|
176
|
+
"end_date": end_date,
|
|
177
|
+
},
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
if response.status_code != 200:
|
|
181
|
+
raise Exception(
|
|
182
|
+
f"QuickBooks get_profit_loss_report failed: {response.text}"
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
return response.json()
|
|
186
|
+
|
|
187
|
+
async def list_customers(self, limit: int = 20) -> dict:
|
|
188
|
+
"""List customers."""
|
|
189
|
+
client = await self._get_client()
|
|
190
|
+
|
|
191
|
+
query = quote(f"SELECT * FROM Customer MAXRESULTS {limit}")
|
|
192
|
+
response = await client.get(self._api_url(f"query?query={query}"))
|
|
193
|
+
|
|
194
|
+
if response.status_code != 200:
|
|
195
|
+
raise Exception(f"QuickBooks list_customers failed: {response.text}")
|
|
196
|
+
|
|
197
|
+
return response.json()
|
|
198
|
+
|
|
199
|
+
async def list_vendors(self, limit: int = 20) -> dict:
|
|
200
|
+
"""List vendors."""
|
|
201
|
+
client = await self._get_client()
|
|
202
|
+
|
|
203
|
+
query = quote(f"SELECT * FROM Vendor MAXRESULTS {limit}")
|
|
204
|
+
response = await client.get(self._api_url(f"query?query={query}"))
|
|
205
|
+
|
|
206
|
+
if response.status_code != 200:
|
|
207
|
+
raise Exception(f"QuickBooks list_vendors failed: {response.text}")
|
|
208
|
+
|
|
209
|
+
return response.json()
|
|
210
|
+
|
|
211
|
+
async def get_balance_sheet(self, as_of_date: str) -> dict:
|
|
212
|
+
"""Get Balance Sheet report."""
|
|
213
|
+
client = await self._get_client()
|
|
214
|
+
|
|
215
|
+
response = await client.get(
|
|
216
|
+
self._api_url("reports/BalanceSheet"),
|
|
217
|
+
params={"date": as_of_date},
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
if response.status_code != 200:
|
|
221
|
+
raise Exception(f"QuickBooks get_balance_sheet failed: {response.text}")
|
|
222
|
+
|
|
223
|
+
return response.json()
|
|
224
|
+
|
|
225
|
+
async def _read_impl(self, resource_id: str, **kwargs) -> dict:
|
|
226
|
+
"""Read an entity."""
|
|
227
|
+
entity_type = kwargs.get("entity_type", "invoice")
|
|
228
|
+
client = await self._get_client()
|
|
229
|
+
|
|
230
|
+
response = await client.get(self._api_url(f"{entity_type}/{resource_id}"))
|
|
231
|
+
|
|
232
|
+
if response.status_code != 200:
|
|
233
|
+
raise Exception(f"QuickBooks read failed: {response.text}")
|
|
234
|
+
|
|
235
|
+
return response.json()
|
|
236
|
+
|
|
237
|
+
async def _write_impl(self, resource_type: str, data: dict, **kwargs) -> dict:
|
|
238
|
+
"""Create an entity."""
|
|
239
|
+
if resource_type == "invoice":
|
|
240
|
+
return await self.create_invoice(
|
|
241
|
+
customer_ref=data.get("customer_ref"),
|
|
242
|
+
line_items=data.get("line_items", []),
|
|
243
|
+
)
|
|
244
|
+
elif resource_type == "expense":
|
|
245
|
+
return await self.create_expense(
|
|
246
|
+
vendor_ref=data.get("vendor_ref"),
|
|
247
|
+
amount=data.get("amount", 0),
|
|
248
|
+
description=data.get("description", ""),
|
|
249
|
+
)
|
|
250
|
+
raise ValueError(f"Unknown resource type: {resource_type}")
|
|
251
|
+
|
|
252
|
+
async def _list_impl(
|
|
253
|
+
self, resource_type: str, filters: dict, **kwargs
|
|
254
|
+
) -> list[dict]:
|
|
255
|
+
"""List entities."""
|
|
256
|
+
limit = filters.get("limit", 20)
|
|
257
|
+
if resource_type == "invoices":
|
|
258
|
+
result = await self.list_invoices(limit)
|
|
259
|
+
return result.get("QueryResponse", {}).get("Invoice", [])
|
|
260
|
+
elif resource_type == "expenses":
|
|
261
|
+
result = await self.list_expenses(limit)
|
|
262
|
+
return result.get("QueryResponse", {}).get("Purchase", [])
|
|
263
|
+
elif resource_type == "customers":
|
|
264
|
+
result = await self.list_customers(limit)
|
|
265
|
+
return result.get("QueryResponse", {}).get("Customer", [])
|
|
266
|
+
elif resource_type == "vendors":
|
|
267
|
+
result = await self.list_vendors(limit)
|
|
268
|
+
return result.get("QueryResponse", {}).get("Vendor", [])
|
|
269
|
+
return []
|
|
270
|
+
|
|
271
|
+
async def _search_impl(self, query: str, **kwargs) -> list[dict]:
|
|
272
|
+
"""Execute a QuickBooks query."""
|
|
273
|
+
client = await self._get_client()
|
|
274
|
+
|
|
275
|
+
encoded_query = quote(query)
|
|
276
|
+
response = await client.get(self._api_url(f"query?query={encoded_query}"))
|
|
277
|
+
|
|
278
|
+
if response.status_code != 200:
|
|
279
|
+
raise Exception(f"QuickBooks search failed: {response.text}")
|
|
280
|
+
|
|
281
|
+
return response.json().get("QueryResponse", {})
|