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
agents/transcriber.py ADDED
@@ -0,0 +1,341 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Assistant Audio/Video Transcription — Transcribe calls, meetings, videos.
4
+ Uses OpenAI Whisper API or local whisper.cpp.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import json
10
+ import subprocess
11
+ import tempfile
12
+ from pathlib import Path
13
+ from datetime import datetime
14
+ from typing import Optional, Dict, List
15
+ import httpx
16
+
17
+ # Use user's ~/.hyperclaw directory, not package location
18
+ HYPERCLAW_ROOT = Path(os.environ.get("HYPERCLAW_ROOT", Path.home() / ".hyperclaw"))
19
+ TRANSCRIPTS_DIR = HYPERCLAW_ROOT / "workspace" / "transcripts"
20
+ TRANSCRIPTS_DIR.mkdir(parents=True, exist_ok=True)
21
+
22
+
23
+ def load_env():
24
+ """Load environment from .env file."""
25
+ env_file = HYPERCLAW_ROOT / ".env"
26
+ if env_file.exists():
27
+ for line in env_file.read_text().splitlines():
28
+ if "=" in line and not line.startswith("#"):
29
+ key, val = line.split("=", 1)
30
+ os.environ.setdefault(key.strip(), val.strip().strip('"'))
31
+
32
+
33
+ load_env()
34
+
35
+
36
+ def get_openai_key():
37
+ return os.environ.get("OPENAI_API_KEY", "")
38
+
39
+
40
+ def transcribe_audio(
41
+ audio_path: str,
42
+ language: str = None,
43
+ prompt: str = None,
44
+ output_format: str = "text"
45
+ ) -> Dict:
46
+ """Transcribe audio file using OpenAI Whisper API."""
47
+ api_key = get_openai_key()
48
+ if not api_key:
49
+ return {"error": "OPENAI_API_KEY not set"}
50
+
51
+ path = Path(audio_path).expanduser()
52
+ if not path.exists():
53
+ return {"error": f"File not found: {audio_path}"}
54
+
55
+ # Check file size (max 25MB for Whisper API)
56
+ file_size = path.stat().st_size
57
+ if file_size > 25 * 1024 * 1024:
58
+ return {"error": f"File too large ({file_size / 1024 / 1024:.1f}MB). Max 25MB. Use split_audio first."}
59
+
60
+ try:
61
+ with open(path, "rb") as f:
62
+ files = {"file": (path.name, f, "audio/mpeg")}
63
+ data = {"model": "whisper-1"}
64
+
65
+ if language:
66
+ data["language"] = language
67
+ if prompt:
68
+ data["prompt"] = prompt
69
+ if output_format in ["json", "verbose_json", "srt", "vtt"]:
70
+ data["response_format"] = output_format
71
+
72
+ with httpx.Client(timeout=300) as client: # 5 min timeout for long files
73
+ resp = client.post(
74
+ "https://api.openai.com/v1/audio/transcriptions",
75
+ headers={"Authorization": f"Bearer {api_key}"},
76
+ files=files,
77
+ data=data
78
+ )
79
+
80
+ if resp.status_code == 200:
81
+ if output_format in ["json", "verbose_json"]:
82
+ result = resp.json()
83
+ else:
84
+ result = {"text": resp.text}
85
+
86
+ # Save transcript
87
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
88
+ transcript_path = TRANSCRIPTS_DIR / f"{path.stem}_{timestamp}.txt"
89
+ transcript_path.write_text(result.get("text", str(result)))
90
+
91
+ result["saved_to"] = str(transcript_path)
92
+ return result
93
+
94
+ return {"error": f"API error: {resp.status_code} - {resp.text}"}
95
+
96
+ except Exception as e:
97
+ return {"error": str(e)}
98
+
99
+
100
+ def transcribe_video(video_path: str, **kwargs) -> Dict:
101
+ """Transcribe video by extracting audio first."""
102
+ path = Path(video_path).expanduser()
103
+ if not path.exists():
104
+ return {"error": f"File not found: {video_path}"}
105
+
106
+ # Extract audio using ffmpeg
107
+ try:
108
+ with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmp:
109
+ tmp_path = tmp.name
110
+
111
+ result = subprocess.run([
112
+ "ffmpeg", "-i", str(path),
113
+ "-vn", "-acodec", "libmp3lame", "-q:a", "4",
114
+ "-y", tmp_path
115
+ ], capture_output=True, text=True, timeout=300)
116
+
117
+ if result.returncode != 0:
118
+ return {"error": f"ffmpeg failed: {result.stderr}"}
119
+
120
+ # Transcribe the extracted audio
121
+ transcript = transcribe_audio(tmp_path, **kwargs)
122
+
123
+ # Clean up
124
+ Path(tmp_path).unlink()
125
+
126
+ return transcript
127
+
128
+ except FileNotFoundError:
129
+ return {"error": "ffmpeg not installed. Install with: brew install ffmpeg"}
130
+ except Exception as e:
131
+ return {"error": str(e)}
132
+
133
+
134
+ def record_audio(duration: int = 30, output_path: str = None) -> Dict:
135
+ """Record audio from microphone."""
136
+ if not output_path:
137
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
138
+ output_path = str(TRANSCRIPTS_DIR / f"recording_{timestamp}.wav")
139
+
140
+ try:
141
+ # Use macOS sox or ffmpeg to record
142
+ result = subprocess.run([
143
+ "sox", "-d", "-r", "16000", "-c", "1", output_path,
144
+ "trim", "0", str(duration)
145
+ ], capture_output=True, text=True, timeout=duration + 10)
146
+
147
+ if result.returncode == 0:
148
+ return {"recorded": output_path, "duration": duration}
149
+
150
+ # Fallback to ffmpeg
151
+ result = subprocess.run([
152
+ "ffmpeg", "-f", "avfoundation", "-i", ":0",
153
+ "-t", str(duration), "-y", output_path
154
+ ], capture_output=True, text=True, timeout=duration + 10)
155
+
156
+ if result.returncode == 0:
157
+ return {"recorded": output_path, "duration": duration}
158
+
159
+ return {"error": "Recording failed. Install sox: brew install sox"}
160
+
161
+ except Exception as e:
162
+ return {"error": str(e)}
163
+
164
+
165
+ def record_and_transcribe(duration: int = 30) -> Dict:
166
+ """Record audio and transcribe it."""
167
+ # Record
168
+ record_result = record_audio(duration)
169
+ if "error" in record_result:
170
+ return record_result
171
+
172
+ # Transcribe
173
+ transcript = transcribe_audio(record_result["recorded"])
174
+
175
+ return {
176
+ "recorded": record_result["recorded"],
177
+ "duration": duration,
178
+ "transcript": transcript.get("text", ""),
179
+ "saved_to": transcript.get("saved_to")
180
+ }
181
+
182
+
183
+ def split_audio(audio_path: str, chunk_minutes: int = 10) -> List[str]:
184
+ """Split large audio file into chunks for transcription."""
185
+ path = Path(audio_path).expanduser()
186
+ if not path.exists():
187
+ return []
188
+
189
+ try:
190
+ chunks = []
191
+ chunk_dir = TRANSCRIPTS_DIR / f"chunks_{path.stem}"
192
+ chunk_dir.mkdir(exist_ok=True)
193
+
194
+ # Get duration
195
+ result = subprocess.run([
196
+ "ffprobe", "-v", "error", "-show_entries", "format=duration",
197
+ "-of", "default=noprint_wrappers=1:nokey=1", str(path)
198
+ ], capture_output=True, text=True)
199
+
200
+ duration = float(result.stdout.strip())
201
+ chunk_seconds = chunk_minutes * 60
202
+
203
+ for i, start in enumerate(range(0, int(duration), chunk_seconds)):
204
+ chunk_path = chunk_dir / f"chunk_{i:03d}.mp3"
205
+ subprocess.run([
206
+ "ffmpeg", "-i", str(path),
207
+ "-ss", str(start), "-t", str(chunk_seconds),
208
+ "-acodec", "libmp3lame", "-q:a", "4",
209
+ "-y", str(chunk_path)
210
+ ], capture_output=True, timeout=120)
211
+
212
+ if chunk_path.exists():
213
+ chunks.append(str(chunk_path))
214
+
215
+ return chunks
216
+
217
+ except Exception as e:
218
+ return []
219
+
220
+
221
+ def transcribe_long_audio(audio_path: str, chunk_minutes: int = 10) -> Dict:
222
+ """Transcribe long audio by splitting into chunks."""
223
+ chunks = split_audio(audio_path, chunk_minutes)
224
+ if not chunks:
225
+ return {"error": "Failed to split audio"}
226
+
227
+ full_transcript = []
228
+ for i, chunk in enumerate(chunks):
229
+ print(f"Transcribing chunk {i+1}/{len(chunks)}...")
230
+ result = transcribe_audio(chunk)
231
+ if "text" in result:
232
+ full_transcript.append(result["text"])
233
+
234
+ # Combine and save
235
+ combined_text = "\n\n".join(full_transcript)
236
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
237
+ output_path = TRANSCRIPTS_DIR / f"{Path(audio_path).stem}_full_{timestamp}.txt"
238
+ output_path.write_text(combined_text)
239
+
240
+ return {
241
+ "text": combined_text,
242
+ "chunks": len(chunks),
243
+ "saved_to": str(output_path)
244
+ }
245
+
246
+
247
+ def list_transcripts() -> List[Dict]:
248
+ """List all saved transcripts."""
249
+ transcripts = []
250
+ for path in TRANSCRIPTS_DIR.glob("*.txt"):
251
+ transcripts.append({
252
+ "name": path.name,
253
+ "path": str(path),
254
+ "size": path.stat().st_size,
255
+ "created": datetime.fromtimestamp(path.stat().st_ctime).isoformat()
256
+ })
257
+ return sorted(transcripts, key=lambda x: x["created"], reverse=True)
258
+
259
+
260
+ def get_transcript(name: str) -> str:
261
+ """Get a transcript by name."""
262
+ path = TRANSCRIPTS_DIR / name
263
+ if path.exists():
264
+ return path.read_text()
265
+
266
+ # Try partial match
267
+ for p in TRANSCRIPTS_DIR.glob(f"*{name}*.txt"):
268
+ return p.read_text()
269
+
270
+ return "Transcript not found"
271
+
272
+
273
+ def summarize_transcript(transcript_text: str) -> str:
274
+ """Summarize a transcript using Claude (placeholder)."""
275
+ # This would call Claude API to summarize
276
+ # For now, return word count
277
+ words = len(transcript_text.split())
278
+ return f"Transcript has {words} words. Full summarization requires Claude API call."
279
+
280
+
281
+ # CLI functions for TUI integration
282
+ def audio_transcribe(path: str, language: str = None) -> Dict:
283
+ """Transcribe an audio file."""
284
+ return transcribe_audio(path, language=language)
285
+
286
+
287
+ def video_transcribe(path: str, language: str = None) -> Dict:
288
+ """Transcribe a video file."""
289
+ return transcribe_video(path, language=language)
290
+
291
+
292
+ def audio_record(duration: int = 30) -> Dict:
293
+ """Record audio from microphone."""
294
+ return record_audio(duration)
295
+
296
+
297
+ def audio_record_transcribe(duration: int = 30) -> Dict:
298
+ """Record and transcribe."""
299
+ return record_and_transcribe(duration)
300
+
301
+
302
+ def transcripts_list() -> List[Dict]:
303
+ """List all transcripts."""
304
+ return list_transcripts()
305
+
306
+
307
+ def transcript_get(name: str) -> str:
308
+ """Get a specific transcript."""
309
+ return get_transcript(name)
310
+
311
+
312
+ if __name__ == "__main__":
313
+ import sys
314
+
315
+ if len(sys.argv) < 2:
316
+ print("Usage: transcriber.py <transcribe|record|list> [args]")
317
+ sys.exit(1)
318
+
319
+ cmd = sys.argv[1]
320
+
321
+ if cmd == "transcribe":
322
+ path = sys.argv[2] if len(sys.argv) > 2 else ""
323
+ result = transcribe_audio(path)
324
+ print(json.dumps(result, indent=2))
325
+
326
+ elif cmd == "video":
327
+ path = sys.argv[2] if len(sys.argv) > 2 else ""
328
+ result = transcribe_video(path)
329
+ print(json.dumps(result, indent=2))
330
+
331
+ elif cmd == "record":
332
+ duration = int(sys.argv[2]) if len(sys.argv) > 2 else 30
333
+ result = record_and_transcribe(duration)
334
+ print(json.dumps(result, indent=2))
335
+
336
+ elif cmd == "list":
337
+ for t in list_transcripts():
338
+ print(f"{t['name']} ({t['size']} bytes)")
339
+
340
+ else:
341
+ print(f"Unknown command: {cmd}")
@@ -0,0 +1,51 @@
1
+ """
2
+ Civilization Knowledge Layer — organizational knowledge graph for HyperClaw.
3
+ Stores SOPs, job descriptions, org charts, workflows, runbooks, and more.
4
+ """
5
+ from .schema import (
6
+ NodeType,
7
+ NodeStatus,
8
+ CivilizationNode,
9
+ SOP,
10
+ SOPStep,
11
+ JobDescription,
12
+ Role,
13
+ Person,
14
+ Checklist,
15
+ ChecklistItem,
16
+ Runbook,
17
+ RunbookStep,
18
+ Workflow,
19
+ WorkflowNode,
20
+ WorkflowEdge,
21
+ OrgChart,
22
+ OrgUnit,
23
+ ClientProfile,
24
+ PersonalRoutine,
25
+ RoutineBlock,
26
+ )
27
+ from .store import CivilizationStore
28
+
29
+ __all__ = [
30
+ "NodeType",
31
+ "NodeStatus",
32
+ "CivilizationNode",
33
+ "SOP",
34
+ "SOPStep",
35
+ "JobDescription",
36
+ "Role",
37
+ "Person",
38
+ "Checklist",
39
+ "ChecklistItem",
40
+ "Runbook",
41
+ "RunbookStep",
42
+ "Workflow",
43
+ "WorkflowNode",
44
+ "WorkflowEdge",
45
+ "OrgChart",
46
+ "OrgUnit",
47
+ "ClientProfile",
48
+ "PersonalRoutine",
49
+ "RoutineBlock",
50
+ "CivilizationStore",
51
+ ]
@@ -0,0 +1,7 @@
1
+ """
2
+ API module for Civilization Knowledge Layer.
3
+ Provides a unified interface for all civilization operations.
4
+ """
5
+ from .civilization_api import CivilizationAPI
6
+
7
+ __all__ = ["CivilizationAPI"]