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
@@ -0,0 +1,87 @@
1
+ """ZapierConnector — Zapier webhook integration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+
7
+ import httpx
8
+
9
+ from integrations.base import (
10
+ BaseConnector,
11
+ ConnectorCapability,
12
+ ConnectorInfo,
13
+ )
14
+
15
+ logger = logging.getLogger("hyperclaw.integrations.zapier")
16
+
17
+
18
+ class ZapierConnector(BaseConnector):
19
+ """
20
+ Zapier webhook connector for triggering Zaps.
21
+
22
+ Required config:
23
+ - webhook_url: Zapier webhook URL
24
+ """
25
+
26
+ def __init__(self, config: dict) -> None:
27
+ self.config = config
28
+ self.webhook_url = config.get("webhook_url", "")
29
+
30
+ if config.get("enabled", False) and not self.webhook_url:
31
+ raise ValueError("ZapierConnector requires webhook_url")
32
+
33
+ self._client: httpx.AsyncClient | None = None
34
+
35
+ @property
36
+ def info(self) -> ConnectorInfo:
37
+ return ConnectorInfo(
38
+ connector_id="zapier",
39
+ platform="zapier",
40
+ category="automation",
41
+ capabilities=frozenset(
42
+ [
43
+ ConnectorCapability.ACTION,
44
+ ConnectorCapability.WEBHOOKS,
45
+ ]
46
+ ),
47
+ auth_type="webhook_token",
48
+ rate_limit_per_minute=60,
49
+ )
50
+
51
+ async def _get_client(self) -> httpx.AsyncClient:
52
+ if self._client is None:
53
+ self._client = httpx.AsyncClient(
54
+ timeout=30.0,
55
+ headers={"Content-Type": "application/json"},
56
+ )
57
+ return self._client
58
+
59
+ async def health(self) -> bool:
60
+ """Zapier webhooks don't have a health endpoint."""
61
+ return True
62
+
63
+ async def trigger_zap(self, data: dict) -> dict:
64
+ """Trigger a Zap with the given data."""
65
+ client = await self._get_client()
66
+
67
+ response = await client.post(
68
+ self.webhook_url,
69
+ json=data,
70
+ )
71
+
72
+ # Zapier webhooks return various status codes
73
+ if response.status_code not in (200, 201, 202):
74
+ raise Exception(f"Zapier trigger_zap failed: {response.text}")
75
+
76
+ try:
77
+ return response.json()
78
+ except Exception:
79
+ return {"status": "triggered", "response": response.text}
80
+
81
+ async def _action_impl(self, action_name: str, params: dict) -> dict:
82
+ """Execute Zapier-specific actions."""
83
+ if action_name == "trigger" or action_name == "trigger_zap":
84
+ return await self.trigger_zap(params)
85
+
86
+ # Default: pass all params to trigger
87
+ return await self.trigger_zap(params)
integrations/base.py ADDED
@@ -0,0 +1,476 @@
1
+ """
2
+ BaseConnector — foundation for all HyperClaw platform connectors.
3
+ ConnectorRegistry — central registry for connector discovery and lookup.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import importlib
9
+ import logging
10
+ import os
11
+ from abc import ABC, abstractmethod
12
+ from dataclasses import dataclass, field
13
+ from datetime import datetime
14
+ from enum import Enum
15
+ from typing import Any, AsyncIterator
16
+
17
+ logger = logging.getLogger("hyperclaw.integrations")
18
+
19
+
20
+ class ConnectorCapability(str, Enum):
21
+ """Capabilities that a connector may support."""
22
+
23
+ SEND_MESSAGE = "send_message"
24
+ RECEIVE_MESSAGE = "receive_message"
25
+ READ_DATA = "read_data"
26
+ WRITE_DATA = "write_data"
27
+ DELETE_DATA = "delete_data"
28
+ LIST_DATA = "list_data"
29
+ STREAM = "stream"
30
+ FILE_UPLOAD = "file_upload"
31
+ FILE_DOWNLOAD = "file_download"
32
+ WEBHOOKS = "webhooks"
33
+ OAUTH = "oauth"
34
+ SEARCH = "search"
35
+ NOTIFY = "notify"
36
+ CALENDAR = "calendar"
37
+ ACTION = "action"
38
+
39
+
40
+ @dataclass
41
+ class InboundMessage:
42
+ """Message received from an external platform."""
43
+
44
+ message_id: str
45
+ platform: str
46
+ sender_id: str
47
+ sender_name: str
48
+ content: str
49
+ thread_id: str | None = None
50
+ channel_id: str | None = None
51
+ attachments: list[dict] = field(default_factory=list)
52
+ raw: dict = field(default_factory=dict)
53
+ received_at: datetime = field(default_factory=datetime.utcnow)
54
+
55
+
56
+ @dataclass
57
+ class OutboundMessage:
58
+ """Message to be sent to an external platform."""
59
+
60
+ content: str
61
+ platform: str
62
+ recipient_id: str
63
+ thread_id: str | None = None
64
+ channel_id: str | None = None
65
+ attachments: list[dict] = field(default_factory=list)
66
+ format: str = "text" # "text" | "markdown" | "html" | "blocks"
67
+
68
+
69
+ @dataclass
70
+ class ConnectorInfo:
71
+ """Metadata about a connector's capabilities and limits."""
72
+
73
+ connector_id: str
74
+ platform: str
75
+ category: str # "messaging" | "productivity" | "enterprise" | etc.
76
+ capabilities: frozenset
77
+ auth_type: str # "api_key" | "oauth2" | "webhook_token" | "bearer"
78
+ rate_limit_per_minute: int = 60
79
+ supports_threads: bool = False
80
+ supports_attachments: bool = False
81
+ supports_reactions: bool = False
82
+
83
+
84
+ class ConnectorAuthError(Exception):
85
+ """Authentication failed for connector."""
86
+
87
+ pass
88
+
89
+
90
+ class ConnectorRateLimitError(Exception):
91
+ """Rate limit exceeded for connector."""
92
+
93
+ pass
94
+
95
+
96
+ class ConnectorUnavailableError(Exception):
97
+ """Connector service is unavailable."""
98
+
99
+ pass
100
+
101
+
102
+ class CapabilityNotSupportedError(Exception):
103
+ """Requested capability is not supported by this connector."""
104
+
105
+ pass
106
+
107
+
108
+ class BaseConnector(ABC):
109
+ """
110
+ Abstract base class for all HyperClaw platform connectors.
111
+
112
+ Subclasses must implement:
113
+ - info property: returns ConnectorInfo
114
+ - health(): async check if connector is operational
115
+
116
+ Optional implementations depending on capabilities:
117
+ - _send_impl(): for SEND_MESSAGE
118
+ - _receive_impl(): for RECEIVE_MESSAGE
119
+ - _read_impl(): for READ_DATA
120
+ - _write_impl(): for WRITE_DATA
121
+ - _delete_impl(): for DELETE_DATA
122
+ - _list_impl(): for LIST_DATA
123
+ - _search_impl(): for SEARCH
124
+ - _action_impl(): for ACTION
125
+ """
126
+
127
+ # Optional HyperShield security context
128
+ hypershield_context: str | None = None
129
+
130
+ @property
131
+ @abstractmethod
132
+ def info(self) -> ConnectorInfo:
133
+ """Return connector metadata."""
134
+ ...
135
+
136
+ @property
137
+ def connector_id(self) -> str:
138
+ """Shorthand for info.connector_id."""
139
+ return self.info.connector_id
140
+
141
+ def _taint(self, value: Any) -> Any:
142
+ """What a connector read returns is connector content (hyperclaw.taint):
143
+ never memory, learning, training or evaluation data."""
144
+ from hyperclaw.taint import mark
145
+ info = self.info
146
+ return mark(value, str(info.platform or "connector").lower(), info.connector_id)
147
+
148
+ def supports(self, cap: ConnectorCapability) -> bool:
149
+ """Check if this connector supports a capability."""
150
+ return cap in self.info.capabilities
151
+
152
+ def require(self, cap: ConnectorCapability) -> None:
153
+ """Raise if capability not supported."""
154
+ if not self.supports(cap):
155
+ raise CapabilityNotSupportedError(
156
+ f"{self.connector_id} does not support {cap}"
157
+ )
158
+
159
+ @abstractmethod
160
+ async def health(self) -> bool:
161
+ """Check if connector is operational."""
162
+ ...
163
+
164
+ # ── Messaging ──────────────────────────────────────────────────────────
165
+
166
+ async def send(self, message: OutboundMessage) -> str:
167
+ """Send a message to the platform. Returns message ID."""
168
+ self.require(ConnectorCapability.SEND_MESSAGE)
169
+ return await self._send_impl(message)
170
+
171
+ async def _send_impl(self, message: OutboundMessage) -> str:
172
+ raise NotImplementedError
173
+
174
+ async def receive(self) -> AsyncIterator[InboundMessage]:
175
+ """Receive messages from the platform."""
176
+ self.require(ConnectorCapability.RECEIVE_MESSAGE)
177
+ async for msg in self._receive_impl():
178
+ msg.content = self._taint(msg.content)
179
+ yield msg
180
+
181
+ async def _receive_impl(self) -> AsyncIterator[InboundMessage]:
182
+ raise NotImplementedError
183
+ yield # make it an async generator
184
+
185
+ # ── Data Operations ────────────────────────────────────────────────────
186
+
187
+ async def read(self, resource_id: str, **kwargs) -> dict:
188
+ """Read a resource from the platform."""
189
+ self.require(ConnectorCapability.READ_DATA)
190
+ return self._taint(await self._read_impl(resource_id, **kwargs))
191
+
192
+ async def _read_impl(self, resource_id: str, **kwargs) -> dict:
193
+ raise NotImplementedError
194
+
195
+ async def write(self, resource_type: str, data: dict, **kwargs) -> dict:
196
+ """Write/create a resource on the platform."""
197
+ self.require(ConnectorCapability.WRITE_DATA)
198
+ return await self._write_impl(resource_type, data, **kwargs)
199
+
200
+ async def _write_impl(self, resource_type: str, data: dict, **kwargs) -> dict:
201
+ raise NotImplementedError
202
+
203
+ async def delete(self, resource_id: str, **kwargs) -> bool:
204
+ """Delete a resource from the platform."""
205
+ self.require(ConnectorCapability.DELETE_DATA)
206
+ return await self._delete_impl(resource_id, **kwargs)
207
+
208
+ async def _delete_impl(self, resource_id: str, **kwargs) -> bool:
209
+ raise NotImplementedError
210
+
211
+ async def list(
212
+ self, resource_type: str, filters: dict | None = None, **kwargs
213
+ ) -> list[dict]:
214
+ """List resources of a given type."""
215
+ self.require(ConnectorCapability.LIST_DATA)
216
+ return self._taint(await self._list_impl(resource_type, filters or {}, **kwargs))
217
+
218
+ async def _list_impl(
219
+ self, resource_type: str, filters: dict, **kwargs
220
+ ) -> list[dict]:
221
+ raise NotImplementedError
222
+
223
+ async def search(self, query: str, **kwargs) -> list[dict]:
224
+ """Search for resources."""
225
+ self.require(ConnectorCapability.SEARCH)
226
+ return self._taint(await self._search_impl(query, **kwargs))
227
+
228
+ async def _search_impl(self, query: str, **kwargs) -> list[dict]:
229
+ raise NotImplementedError
230
+
231
+ async def action(self, action_name: str, params: dict | None = None) -> dict:
232
+ """Execute a platform-specific action."""
233
+ self.require(ConnectorCapability.ACTION)
234
+ return await self._action_impl(action_name, params or {})
235
+
236
+ async def _action_impl(self, action_name: str, params: dict) -> dict:
237
+ raise NotImplementedError
238
+
239
+
240
+ class ConnectorRegistry:
241
+ """Central registry of all HyperClaw connectors."""
242
+
243
+ def __init__(self) -> None:
244
+ self._connectors: dict[str, BaseConnector] = {}
245
+
246
+ def register(self, connector: BaseConnector) -> None:
247
+ """Register a connector instance."""
248
+ self._connectors[connector.connector_id] = connector
249
+
250
+ def unregister(self, connector_id: str) -> None:
251
+ """Remove a connector from the registry."""
252
+ self._connectors.pop(connector_id, None)
253
+
254
+ def get(self, connector_id: str) -> BaseConnector:
255
+ """Get a connector by ID. Raises KeyError if not found."""
256
+ if connector_id not in self._connectors:
257
+ raise KeyError(f"Connector not found: {connector_id}")
258
+ return self._connectors[connector_id]
259
+
260
+ def has(self, connector_id: str) -> bool:
261
+ """Check if a connector is registered."""
262
+ return connector_id in self._connectors
263
+
264
+ def list_all(self) -> list[BaseConnector]:
265
+ """List all registered connectors."""
266
+ return list(self._connectors.values())
267
+
268
+ def list_by_category(self, category: str) -> list[BaseConnector]:
269
+ """List connectors in a specific category."""
270
+ return [c for c in self._connectors.values() if c.info.category == category]
271
+
272
+ def list_by_capability(self, cap: ConnectorCapability) -> list[BaseConnector]:
273
+ """List connectors that support a capability."""
274
+ return [c for c in self._connectors.values() if c.supports(cap)]
275
+
276
+ def get_messaging_connectors(self) -> list[BaseConnector]:
277
+ """Shorthand for messaging category."""
278
+ return self.list_by_category("messaging")
279
+
280
+ @classmethod
281
+ def build_from_config(cls, config_path: str) -> "ConnectorRegistry":
282
+ """
283
+ Reads integrations/config/integrations.yaml.
284
+ Instantiates and registers all enabled connectors.
285
+ Skips connectors with missing credentials without crashing.
286
+ """
287
+ import yaml
288
+
289
+ registry = cls()
290
+
291
+ try:
292
+ with open(config_path) as f:
293
+ config = yaml.safe_load(f)
294
+ except Exception as e:
295
+ logger.warning(f"Could not load integrations config: {e}")
296
+ return registry
297
+
298
+ if not config:
299
+ return registry
300
+
301
+ connector_map = _get_connector_map()
302
+
303
+ def _resolve_env(value: Any) -> Any:
304
+ """Resolve ${ENV_VAR} references."""
305
+ if isinstance(value, str) and value.startswith("${") and value.endswith("}"):
306
+ env_key = value[2:-1]
307
+ return os.environ.get(env_key, "")
308
+ return value
309
+
310
+ def _resolve_config(cfg: Any) -> Any:
311
+ """Recursively resolve env vars in config dict."""
312
+ if isinstance(cfg, dict):
313
+ return {k: _resolve_config(v) for k, v in cfg.items()}
314
+ elif isinstance(cfg, list):
315
+ return [_resolve_config(v) for v in cfg]
316
+ else:
317
+ return _resolve_env(cfg)
318
+
319
+ def _try_register(
320
+ connector_id: str, connector_class: type, connector_config: dict
321
+ ) -> None:
322
+ resolved = _resolve_config(connector_config)
323
+ try:
324
+ connector = connector_class(resolved)
325
+ registry.register(connector)
326
+ logger.info(f"Registered connector: {connector_id}")
327
+ except Exception as e:
328
+ logger.warning(f"Skipping connector {connector_id}: {e}")
329
+
330
+ _walk_config_and_register(config, connector_map, _try_register)
331
+
332
+ return registry
333
+
334
+
335
+ def _get_connector_map() -> dict[str, type]:
336
+ """Returns mapping of connector_id -> connector class."""
337
+ connectors: dict[str, type] = {}
338
+ _try_import_connectors(connectors)
339
+ return connectors
340
+
341
+
342
+ def _try_import_connectors(connectors: dict[str, type]) -> None:
343
+ """Try to import all connector classes, skip if import fails."""
344
+ imports = [
345
+ # Messaging
346
+ ("telegram", "integrations.messaging.telegram", "TelegramConnector"),
347
+ ("slack", "integrations.messaging.slack", "SlackConnector"),
348
+ ("discord", "integrations.messaging.discord", "DiscordConnector"),
349
+ ("whatsapp", "integrations.messaging.whatsapp", "WhatsAppConnector"),
350
+ ("teams", "integrations.messaging.teams", "TeamsConnector"),
351
+ ("signal", "integrations.messaging.signal", "SignalConnector"),
352
+ ("imessage", "integrations.messaging.imessage", "iMessageConnector"),
353
+ ("sms", "integrations.messaging.sms", "SMSConnector"),
354
+ ("email", "integrations.messaging.email", "EmailConnector"),
355
+ # Google Workspace
356
+ ("gmail", "integrations.productivity.google.gmail", "GmailConnector"),
357
+ (
358
+ "google_calendar",
359
+ "integrations.productivity.google.calendar",
360
+ "GoogleCalendarConnector",
361
+ ),
362
+ (
363
+ "google_drive",
364
+ "integrations.productivity.google.drive",
365
+ "GoogleDriveConnector",
366
+ ),
367
+ (
368
+ "google_docs",
369
+ "integrations.productivity.google.docs",
370
+ "GoogleDocsConnector",
371
+ ),
372
+ (
373
+ "google_sheets",
374
+ "integrations.productivity.google.sheets",
375
+ "GoogleSheetsConnector",
376
+ ),
377
+ (
378
+ "google_meet",
379
+ "integrations.productivity.google.meet",
380
+ "GoogleMeetConnector",
381
+ ),
382
+ (
383
+ "google_tasks",
384
+ "integrations.productivity.google.tasks",
385
+ "GoogleTasksConnector",
386
+ ),
387
+ # Microsoft 365
388
+ ("outlook", "integrations.productivity.microsoft.outlook", "OutlookConnector"),
389
+ (
390
+ "onedrive",
391
+ "integrations.productivity.microsoft.onedrive",
392
+ "OneDriveConnector",
393
+ ),
394
+ (
395
+ "sharepoint",
396
+ "integrations.productivity.microsoft.sharepoint",
397
+ "SharePointConnector",
398
+ ),
399
+ (
400
+ "microsoft_calendar",
401
+ "integrations.productivity.microsoft.calendar",
402
+ "MicrosoftCalendarConnector",
403
+ ),
404
+ # Productivity
405
+ ("notion", "integrations.productivity.notion", "NotionConnector"),
406
+ ("airtable", "integrations.productivity.airtable", "AirtableConnector"),
407
+ ("trello", "integrations.productivity.trello", "TrelloConnector"),
408
+ ("asana", "integrations.productivity.asana", "AsanaConnector"),
409
+ ("linear", "integrations.productivity.linear", "LinearConnector"),
410
+ ("todoist", "integrations.productivity.todoist", "TodoistConnector"),
411
+ # Enterprise
412
+ ("salesforce", "integrations.enterprise.salesforce", "SalesforceConnector"),
413
+ ("hubspot", "integrations.enterprise.hubspot", "HubSpotConnector"),
414
+ ("jira", "integrations.enterprise.jira", "JiraConnector"),
415
+ ("confluence", "integrations.enterprise.confluence", "ConfluenceConnector"),
416
+ # Developer
417
+ ("github", "integrations.developer.github", "GitHubConnector"),
418
+ ("gitlab", "integrations.developer.gitlab", "GitLabConnector"),
419
+ # Storage
420
+ ("box", "integrations.storage.box", "BoxConnector"),
421
+ ("dropbox", "integrations.storage.dropbox", "DropboxConnector"),
422
+ # Finance
423
+ ("stripe", "integrations.finance.stripe", "StripeConnector"),
424
+ ("quickbooks", "integrations.finance.quickbooks", "QuickBooksConnector"),
425
+ # Communication
426
+ ("zoom", "integrations.communication.zoom", "ZoomConnector"),
427
+ ("twilio", "integrations.communication.twilio", "TwilioConnector"),
428
+ # Automation
429
+ ("zapier", "integrations.automation.zapier", "ZapierConnector"),
430
+ ("make", "integrations.automation.make", "MakeConnector"),
431
+ # Data
432
+ ("supabase", "integrations.data.supabase_connector", "SupabaseConnector"),
433
+ ("postgres", "integrations.data.postgres", "PostgresConnector"),
434
+ (
435
+ "google_analytics",
436
+ "integrations.data.google_analytics",
437
+ "GoogleAnalyticsConnector",
438
+ ),
439
+ ]
440
+
441
+ for connector_id, module_path, class_name in imports:
442
+ try:
443
+ mod = importlib.import_module(module_path)
444
+ connectors[connector_id] = getattr(mod, class_name)
445
+ except Exception as e:
446
+ logger.debug(f"Could not import {connector_id}: {e}")
447
+
448
+
449
+ def _walk_config_and_register(
450
+ config: dict,
451
+ connector_map: dict[str, type],
452
+ register_fn: callable,
453
+ ) -> None:
454
+ """Walk nested config dict, find enabled connectors, register them."""
455
+ for section_key, section_val in config.items():
456
+ if not isinstance(section_val, dict):
457
+ continue
458
+
459
+ for connector_id, connector_cfg in section_val.items():
460
+ if not isinstance(connector_cfg, dict):
461
+ continue
462
+
463
+ # Direct connector config
464
+ if connector_cfg.get("enabled", False) and connector_id in connector_map:
465
+ register_fn(connector_id, connector_map[connector_id], connector_cfg)
466
+ # Handle nested sections (e.g. google.gmail, microsoft.outlook)
467
+ elif isinstance(connector_cfg, dict):
468
+ for sub_id, sub_cfg in connector_cfg.items():
469
+ if isinstance(sub_cfg, dict) and sub_cfg.get("enabled", False):
470
+ # Try sub_id first (e.g., "gmail"), then full path
471
+ full_id = f"{connector_id}_{sub_id}"
472
+ cls = connector_map.get(sub_id) or connector_map.get(full_id)
473
+ if cls:
474
+ # Merge parent config with sub config
475
+ merged = {**connector_cfg, **sub_cfg}
476
+ register_fn(sub_id, cls, merged)
@@ -0,0 +1 @@
1
+ # Communication integrations