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
hyperclaw/setup.py
ADDED
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HyperClaw Setup & Initialization
|
|
3
|
+
Production-ready first-run setup, workspace scaffolding, and connection management.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import asyncio
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
# Configure logging
|
|
16
|
+
logging.basicConfig(
|
|
17
|
+
level=logging.INFO,
|
|
18
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
19
|
+
)
|
|
20
|
+
logger = logging.getLogger("hyperclaw.setup")
|
|
21
|
+
|
|
22
|
+
# ============================================================================
|
|
23
|
+
# CONFIGURATION
|
|
24
|
+
# ============================================================================
|
|
25
|
+
|
|
26
|
+
# Default paths - can be overridden by HYPERCLAW_ROOT env var
|
|
27
|
+
HYPERCLAW_ROOT = Path(os.environ.get("HYPERCLAW_ROOT", Path.home() / ".hyperclaw"))
|
|
28
|
+
WORKSPACE_PATH = HYPERCLAW_ROOT / "workspace"
|
|
29
|
+
MEMORY_PATH = HYPERCLAW_ROOT / "memory"
|
|
30
|
+
SECRETS_PATH = WORKSPACE_PATH / "secrets"
|
|
31
|
+
LOGS_PATH = HYPERCLAW_ROOT / "logs"
|
|
32
|
+
CONFIG_PATH = HYPERCLAW_ROOT / "config"
|
|
33
|
+
|
|
34
|
+
# Required directories
|
|
35
|
+
REQUIRED_DIRS = [
|
|
36
|
+
HYPERCLAW_ROOT,
|
|
37
|
+
WORKSPACE_PATH,
|
|
38
|
+
MEMORY_PATH,
|
|
39
|
+
SECRETS_PATH,
|
|
40
|
+
LOGS_PATH,
|
|
41
|
+
CONFIG_PATH,
|
|
42
|
+
WORKSPACE_PATH / "context",
|
|
43
|
+
MEMORY_PATH / "daily",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# ============================================================================
|
|
48
|
+
# WORKSPACE TEMPLATES
|
|
49
|
+
# ============================================================================
|
|
50
|
+
|
|
51
|
+
SOUL_MD_TEMPLATE = """# SOUL.md - AI Assistant Core Identity
|
|
52
|
+
|
|
53
|
+
## Who I Am
|
|
54
|
+
I am an AI Executive Assistant - a sophisticated multi-agent system designed to augment human capability.
|
|
55
|
+
|
|
56
|
+
## Core Values
|
|
57
|
+
- **Proactive**: Execute tasks without being asked when appropriate
|
|
58
|
+
- **Resourceful**: Try multiple approaches before asking for help
|
|
59
|
+
- **Precise**: Be accurate and thorough in all work
|
|
60
|
+
- **Respectful**: Respect user privacy and preferences
|
|
61
|
+
- **Honest**: Be transparent about capabilities and limitations
|
|
62
|
+
|
|
63
|
+
## Behavioral Guidelines
|
|
64
|
+
- Execute routine tasks autonomously
|
|
65
|
+
- Ask for clarification only when truly needed
|
|
66
|
+
- Provide status updates on long-running tasks
|
|
67
|
+
- Surface relevant information proactively
|
|
68
|
+
- Maintain context across conversations
|
|
69
|
+
- Learn from feedback and corrections
|
|
70
|
+
|
|
71
|
+
## Communication Style
|
|
72
|
+
- Concise and direct
|
|
73
|
+
- No filler phrases ("I'd be happy to help", "Great question")
|
|
74
|
+
- Technical when appropriate, accessible when needed
|
|
75
|
+
- Status-oriented for task updates
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
IDENTITY_MD_TEMPLATE = """# IDENTITY.md - Assistant Configuration
|
|
79
|
+
|
|
80
|
+
## Name
|
|
81
|
+
Assistant
|
|
82
|
+
|
|
83
|
+
## Role
|
|
84
|
+
AI Executive Assistant
|
|
85
|
+
|
|
86
|
+
## Platform
|
|
87
|
+
HyperClaw v1.0
|
|
88
|
+
|
|
89
|
+
## Capabilities
|
|
90
|
+
- Email management and drafting
|
|
91
|
+
- Calendar scheduling and reminders
|
|
92
|
+
- Task management and prioritization
|
|
93
|
+
- Research and information synthesis
|
|
94
|
+
- Code assistance and review
|
|
95
|
+
- Document creation and editing
|
|
96
|
+
- Communication across channels
|
|
97
|
+
|
|
98
|
+
## Active Integrations
|
|
99
|
+
Configure integrations in the HyperClaw settings or via CLI.
|
|
100
|
+
|
|
101
|
+
## Preferences
|
|
102
|
+
- Response format: Markdown
|
|
103
|
+
- Verbosity: Balanced
|
|
104
|
+
- Proactivity: High
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
USER_MD_TEMPLATE = """# USER.md - User Profile
|
|
108
|
+
|
|
109
|
+
## About
|
|
110
|
+
[Add information about yourself here]
|
|
111
|
+
|
|
112
|
+
## Preferences
|
|
113
|
+
- Communication style: [Direct/Detailed/Casual]
|
|
114
|
+
- Response length: [Brief/Moderate/Comprehensive]
|
|
115
|
+
- Proactivity level: [Low/Medium/High]
|
|
116
|
+
|
|
117
|
+
## Work Context
|
|
118
|
+
- Role: [Your role]
|
|
119
|
+
- Industry: [Your industry]
|
|
120
|
+
- Key responsibilities: [List here]
|
|
121
|
+
|
|
122
|
+
## Communication Channels
|
|
123
|
+
- Primary: [Email/Slack/Telegram/etc.]
|
|
124
|
+
- Preferred contact times: [Your availability]
|
|
125
|
+
|
|
126
|
+
## Important Contacts
|
|
127
|
+
[Add key contacts the assistant should know about]
|
|
128
|
+
|
|
129
|
+
## Notes
|
|
130
|
+
[Any other relevant information]
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
MEMORY_MD_TEMPLATE = """# MEMORY.md - Working Memory
|
|
134
|
+
|
|
135
|
+
## Active Context
|
|
136
|
+
*Updated automatically during conversations*
|
|
137
|
+
|
|
138
|
+
## Recent Decisions
|
|
139
|
+
*Key decisions and their rationale*
|
|
140
|
+
|
|
141
|
+
## Pending Tasks
|
|
142
|
+
*Tasks in progress or waiting*
|
|
143
|
+
|
|
144
|
+
## Important Notes
|
|
145
|
+
*Information to remember across sessions*
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
*Last updated: {timestamp}*
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
INSTINCTS_MD_TEMPLATE = """# instincts.md - Behavioral Reflexes
|
|
152
|
+
|
|
153
|
+
## Communication
|
|
154
|
+
- Always acknowledge receipt of important information
|
|
155
|
+
- Confirm understanding before executing complex tasks
|
|
156
|
+
- Provide progress updates on tasks taking longer than expected
|
|
157
|
+
|
|
158
|
+
## Safety
|
|
159
|
+
- Never execute destructive operations without confirmation
|
|
160
|
+
- Always verify before sending external communications
|
|
161
|
+
- Double-check financial or legal information
|
|
162
|
+
|
|
163
|
+
## Efficiency
|
|
164
|
+
- Batch similar tasks when possible
|
|
165
|
+
- Prioritize time-sensitive items
|
|
166
|
+
- Cache frequently accessed information
|
|
167
|
+
|
|
168
|
+
## Learning
|
|
169
|
+
- Note corrections and adjust behavior
|
|
170
|
+
- Track successful approaches for reuse
|
|
171
|
+
- Identify patterns in user preferences
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
CORE_EPISODES_MD_TEMPLATE = """# core-episodes.md - Permanent Memories
|
|
175
|
+
|
|
176
|
+
## Key Events
|
|
177
|
+
*Important events and decisions that should never be forgotten*
|
|
178
|
+
|
|
179
|
+
## Learned Facts
|
|
180
|
+
*Critical information learned about user, projects, or domain*
|
|
181
|
+
|
|
182
|
+
## Policy Decisions
|
|
183
|
+
*Standing instructions and preferences*
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
*Core memories are never pruned during consolidation*
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
ENV_TEMPLATE = """# HyperClaw Environment Configuration
|
|
190
|
+
# Copy this to .env and fill in your values
|
|
191
|
+
|
|
192
|
+
# =============================================================================
|
|
193
|
+
# REQUIRED - AI Provider
|
|
194
|
+
# =============================================================================
|
|
195
|
+
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
|
196
|
+
|
|
197
|
+
# =============================================================================
|
|
198
|
+
# REQUIRED - Database (Supabase recommended)
|
|
199
|
+
# =============================================================================
|
|
200
|
+
DATABASE_URL=postgresql://postgres:password@localhost:5432/hyperclaw
|
|
201
|
+
# Or for Supabase:
|
|
202
|
+
# DATABASE_URL=postgresql://postgres:password@db.xxxxx.supabase.co:5432/postgres
|
|
203
|
+
SUPABASE_URL=https://xxxxx.supabase.co
|
|
204
|
+
SUPABASE_ANON_KEY=your_anon_key
|
|
205
|
+
SUPABASE_SERVICE_KEY=your_service_key
|
|
206
|
+
|
|
207
|
+
# =============================================================================
|
|
208
|
+
# OPTIONAL - Messaging Integrations
|
|
209
|
+
# =============================================================================
|
|
210
|
+
# Telegram
|
|
211
|
+
TELEGRAM_BOT_TOKEN=
|
|
212
|
+
TELEGRAM_CHAT_ID=
|
|
213
|
+
|
|
214
|
+
# Email (Gmail)
|
|
215
|
+
GMAIL_CLIENT_ID=
|
|
216
|
+
GMAIL_CLIENT_SECRET=
|
|
217
|
+
GMAIL_REFRESH_TOKEN=
|
|
218
|
+
|
|
219
|
+
# Slack
|
|
220
|
+
SLACK_BOT_TOKEN=
|
|
221
|
+
SLACK_SIGNING_SECRET=
|
|
222
|
+
|
|
223
|
+
# =============================================================================
|
|
224
|
+
# OPTIONAL - Voice
|
|
225
|
+
# =============================================================================
|
|
226
|
+
ELEVENLABS_API_KEY=
|
|
227
|
+
ELEVENLABS_VOICE_ID=
|
|
228
|
+
|
|
229
|
+
# =============================================================================
|
|
230
|
+
# OPTIONAL - Additional AI Providers
|
|
231
|
+
# =============================================================================
|
|
232
|
+
OPENAI_API_KEY=
|
|
233
|
+
GOOGLE_API_KEY=
|
|
234
|
+
|
|
235
|
+
# =============================================================================
|
|
236
|
+
# SYSTEM
|
|
237
|
+
# =============================================================================
|
|
238
|
+
HYPERCLAW_ROOT={hyperclaw_root}
|
|
239
|
+
LOG_LEVEL=INFO
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
# ============================================================================
|
|
244
|
+
# SETUP FUNCTIONS
|
|
245
|
+
# ============================================================================
|
|
246
|
+
|
|
247
|
+
def create_directories() -> bool:
|
|
248
|
+
"""Create all required directories."""
|
|
249
|
+
logger.info("Creating directory structure...")
|
|
250
|
+
try:
|
|
251
|
+
for dir_path in REQUIRED_DIRS:
|
|
252
|
+
dir_path.mkdir(parents=True, exist_ok=True)
|
|
253
|
+
logger.debug(f" Created: {dir_path}")
|
|
254
|
+
logger.info(f"Directory structure created at {HYPERCLAW_ROOT}")
|
|
255
|
+
return True
|
|
256
|
+
except Exception as e:
|
|
257
|
+
logger.error(f"Failed to create directories: {e}")
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def create_workspace_files(overwrite: bool = False) -> bool:
|
|
262
|
+
"""Create workspace context files."""
|
|
263
|
+
logger.info("Creating workspace files...")
|
|
264
|
+
|
|
265
|
+
files = {
|
|
266
|
+
WORKSPACE_PATH / "SOUL.md": SOUL_MD_TEMPLATE,
|
|
267
|
+
WORKSPACE_PATH / "IDENTITY.md": IDENTITY_MD_TEMPLATE,
|
|
268
|
+
WORKSPACE_PATH / "USER.md": USER_MD_TEMPLATE,
|
|
269
|
+
WORKSPACE_PATH / "MEMORY.md": MEMORY_MD_TEMPLATE.format(
|
|
270
|
+
timestamp=datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
271
|
+
),
|
|
272
|
+
MEMORY_PATH / "instincts.md": INSTINCTS_MD_TEMPLATE,
|
|
273
|
+
MEMORY_PATH / "core-episodes.md": CORE_EPISODES_MD_TEMPLATE,
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
created = 0
|
|
277
|
+
skipped = 0
|
|
278
|
+
|
|
279
|
+
for filepath, content in files.items():
|
|
280
|
+
if filepath.exists() and not overwrite:
|
|
281
|
+
logger.debug(f" Skipped (exists): {filepath.name}")
|
|
282
|
+
skipped += 1
|
|
283
|
+
else:
|
|
284
|
+
try:
|
|
285
|
+
filepath.write_text(content, encoding="utf-8")
|
|
286
|
+
logger.debug(f" Created: {filepath.name}")
|
|
287
|
+
created += 1
|
|
288
|
+
except Exception as e:
|
|
289
|
+
logger.error(f" Failed to create {filepath.name}: {e}")
|
|
290
|
+
return False
|
|
291
|
+
|
|
292
|
+
logger.info(f"Workspace files: {created} created, {skipped} skipped")
|
|
293
|
+
return True
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def create_env_file(overwrite: bool = False) -> bool:
|
|
297
|
+
"""Create .env template file."""
|
|
298
|
+
env_path = SECRETS_PATH / ".env"
|
|
299
|
+
|
|
300
|
+
if env_path.exists() and not overwrite:
|
|
301
|
+
logger.info(".env file already exists, skipping")
|
|
302
|
+
return True
|
|
303
|
+
|
|
304
|
+
try:
|
|
305
|
+
content = ENV_TEMPLATE.format(hyperclaw_root=str(HYPERCLAW_ROOT))
|
|
306
|
+
env_path.write_text(content, encoding="utf-8")
|
|
307
|
+
logger.info(f"Created .env template at {env_path}")
|
|
308
|
+
return True
|
|
309
|
+
except Exception as e:
|
|
310
|
+
logger.error(f"Failed to create .env file: {e}")
|
|
311
|
+
return False
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def load_env() -> bool:
|
|
315
|
+
"""Load environment variables from .env file."""
|
|
316
|
+
env_path = SECRETS_PATH / ".env"
|
|
317
|
+
|
|
318
|
+
if not env_path.exists():
|
|
319
|
+
logger.warning(f".env file not found at {env_path}")
|
|
320
|
+
return False
|
|
321
|
+
|
|
322
|
+
try:
|
|
323
|
+
with open(env_path, 'r') as f:
|
|
324
|
+
for line in f:
|
|
325
|
+
line = line.strip()
|
|
326
|
+
if line and not line.startswith('#') and '=' in line:
|
|
327
|
+
key, _, value = line.partition('=')
|
|
328
|
+
key = key.strip()
|
|
329
|
+
value = value.strip()
|
|
330
|
+
if value and not value.startswith('your_'):
|
|
331
|
+
os.environ.setdefault(key, value)
|
|
332
|
+
logger.info("Environment variables loaded")
|
|
333
|
+
return True
|
|
334
|
+
except Exception as e:
|
|
335
|
+
logger.error(f"Failed to load .env file: {e}")
|
|
336
|
+
return False
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def check_api_keys() -> dict:
|
|
340
|
+
"""Check which API keys are configured."""
|
|
341
|
+
keys = {
|
|
342
|
+
"anthropic": bool(os.environ.get("ANTHROPIC_API_KEY")),
|
|
343
|
+
"database": bool(os.environ.get("DATABASE_URL")),
|
|
344
|
+
"telegram": bool(os.environ.get("TELEGRAM_BOT_TOKEN")),
|
|
345
|
+
"gmail": bool(os.environ.get("GMAIL_REFRESH_TOKEN")),
|
|
346
|
+
"elevenlabs": bool(os.environ.get("ELEVENLABS_API_KEY")),
|
|
347
|
+
"openai": bool(os.environ.get("OPENAI_API_KEY")),
|
|
348
|
+
}
|
|
349
|
+
return keys
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
async def check_database_connection() -> bool:
|
|
353
|
+
"""Test database connectivity."""
|
|
354
|
+
db_url = os.environ.get("DATABASE_URL")
|
|
355
|
+
if not db_url:
|
|
356
|
+
logger.warning("DATABASE_URL not configured")
|
|
357
|
+
return False
|
|
358
|
+
|
|
359
|
+
try:
|
|
360
|
+
import asyncpg
|
|
361
|
+
conn = await asyncpg.connect(db_url)
|
|
362
|
+
await conn.execute("SELECT 1")
|
|
363
|
+
await conn.close()
|
|
364
|
+
logger.info("Database connection successful")
|
|
365
|
+
return True
|
|
366
|
+
except ImportError:
|
|
367
|
+
logger.warning("asyncpg not installed - run: pip install asyncpg")
|
|
368
|
+
return False
|
|
369
|
+
except Exception as e:
|
|
370
|
+
logger.error(f"Database connection failed: {e}")
|
|
371
|
+
return False
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
async def initialize_database() -> bool:
|
|
375
|
+
"""Run database initialization schema."""
|
|
376
|
+
db_url = os.environ.get("DATABASE_URL")
|
|
377
|
+
if not db_url:
|
|
378
|
+
logger.error("DATABASE_URL not configured")
|
|
379
|
+
return False
|
|
380
|
+
|
|
381
|
+
# Find schema file
|
|
382
|
+
schema_paths = [
|
|
383
|
+
Path(__file__).parent.parent / "schema" / "init.sql",
|
|
384
|
+
HYPERCLAW_ROOT / "schema" / "init.sql",
|
|
385
|
+
]
|
|
386
|
+
|
|
387
|
+
schema_path = None
|
|
388
|
+
for path in schema_paths:
|
|
389
|
+
if path.exists():
|
|
390
|
+
schema_path = path
|
|
391
|
+
break
|
|
392
|
+
|
|
393
|
+
if not schema_path:
|
|
394
|
+
logger.error("Schema file not found")
|
|
395
|
+
return False
|
|
396
|
+
|
|
397
|
+
try:
|
|
398
|
+
import asyncpg
|
|
399
|
+
conn = await asyncpg.connect(db_url)
|
|
400
|
+
|
|
401
|
+
# Read and execute schema
|
|
402
|
+
schema_sql = schema_path.read_text(encoding="utf-8")
|
|
403
|
+
|
|
404
|
+
# Execute in transaction
|
|
405
|
+
async with conn.transaction():
|
|
406
|
+
await conn.execute(schema_sql)
|
|
407
|
+
|
|
408
|
+
await conn.close()
|
|
409
|
+
logger.info("Database schema initialized successfully")
|
|
410
|
+
return True
|
|
411
|
+
|
|
412
|
+
except Exception as e:
|
|
413
|
+
logger.error(f"Database initialization failed: {e}")
|
|
414
|
+
return False
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def create_default_config() -> bool:
|
|
418
|
+
"""Create default configuration files."""
|
|
419
|
+
config_file = CONFIG_PATH / "hyperclaw.yaml"
|
|
420
|
+
|
|
421
|
+
if config_file.exists():
|
|
422
|
+
logger.info("Config file already exists")
|
|
423
|
+
return True
|
|
424
|
+
|
|
425
|
+
default_config = {
|
|
426
|
+
"version": "1.0.0",
|
|
427
|
+
"server": {
|
|
428
|
+
"host": "0.0.0.0",
|
|
429
|
+
"port": 8001,
|
|
430
|
+
},
|
|
431
|
+
"models": {
|
|
432
|
+
"default": "claude-sonnet-4-6",
|
|
433
|
+
"fast": "claude-haiku-4-5-20251001",
|
|
434
|
+
"max_tokens": 4096,
|
|
435
|
+
},
|
|
436
|
+
"swarm": {
|
|
437
|
+
"max_agents": 50,
|
|
438
|
+
"default_domain": "business",
|
|
439
|
+
"task_timeout": 300,
|
|
440
|
+
},
|
|
441
|
+
"memory": {
|
|
442
|
+
"consolidation_hour": 3,
|
|
443
|
+
"max_history": 100,
|
|
444
|
+
"embedding_model": "text-embedding-3-small",
|
|
445
|
+
},
|
|
446
|
+
"security": {
|
|
447
|
+
"audit_log": True,
|
|
448
|
+
"rate_limit": 100,
|
|
449
|
+
},
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
try:
|
|
453
|
+
import yaml
|
|
454
|
+
CONFIG_PATH.mkdir(parents=True, exist_ok=True)
|
|
455
|
+
with open(config_file, 'w') as f:
|
|
456
|
+
yaml.dump(default_config, f, default_flow_style=False)
|
|
457
|
+
logger.info(f"Created default config at {config_file}")
|
|
458
|
+
return True
|
|
459
|
+
except ImportError:
|
|
460
|
+
# Fallback to JSON if yaml not available
|
|
461
|
+
config_file = CONFIG_PATH / "hyperclaw.json"
|
|
462
|
+
with open(config_file, 'w') as f:
|
|
463
|
+
json.dump(default_config, f, indent=2)
|
|
464
|
+
logger.info(f"Created default config at {config_file}")
|
|
465
|
+
return True
|
|
466
|
+
except Exception as e:
|
|
467
|
+
logger.error(f"Failed to create config: {e}")
|
|
468
|
+
return False
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
# ============================================================================
|
|
472
|
+
# MAIN SETUP RUNNER
|
|
473
|
+
# ============================================================================
|
|
474
|
+
|
|
475
|
+
class SetupResult:
|
|
476
|
+
"""Result of setup operation."""
|
|
477
|
+
def __init__(self):
|
|
478
|
+
self.success = True
|
|
479
|
+
self.steps = {}
|
|
480
|
+
self.warnings = []
|
|
481
|
+
self.errors = []
|
|
482
|
+
|
|
483
|
+
def add_step(self, name: str, success: bool, message: str = ""):
|
|
484
|
+
self.steps[name] = {"success": success, "message": message}
|
|
485
|
+
if not success:
|
|
486
|
+
self.success = False
|
|
487
|
+
|
|
488
|
+
def to_dict(self) -> dict:
|
|
489
|
+
return {
|
|
490
|
+
"success": self.success,
|
|
491
|
+
"steps": self.steps,
|
|
492
|
+
"warnings": self.warnings,
|
|
493
|
+
"errors": self.errors,
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
async def run_setup(
|
|
498
|
+
init_db: bool = False,
|
|
499
|
+
overwrite: bool = False,
|
|
500
|
+
verbose: bool = False
|
|
501
|
+
) -> SetupResult:
|
|
502
|
+
"""
|
|
503
|
+
Run full HyperClaw setup.
|
|
504
|
+
|
|
505
|
+
Args:
|
|
506
|
+
init_db: Initialize database schema
|
|
507
|
+
overwrite: Overwrite existing files
|
|
508
|
+
verbose: Enable verbose logging
|
|
509
|
+
|
|
510
|
+
Returns:
|
|
511
|
+
SetupResult with status of each step
|
|
512
|
+
"""
|
|
513
|
+
if verbose:
|
|
514
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
|
515
|
+
|
|
516
|
+
result = SetupResult()
|
|
517
|
+
|
|
518
|
+
print("\n" + "="*60)
|
|
519
|
+
print(" HyperClaw Setup")
|
|
520
|
+
print("="*60 + "\n")
|
|
521
|
+
|
|
522
|
+
# Step 1: Create directories
|
|
523
|
+
print("[1/6] Creating directories...")
|
|
524
|
+
success = create_directories()
|
|
525
|
+
result.add_step("directories", success)
|
|
526
|
+
print(f" {'OK' if success else 'FAILED'}\n")
|
|
527
|
+
|
|
528
|
+
# Step 2: Create workspace files
|
|
529
|
+
print("[2/6] Creating workspace files...")
|
|
530
|
+
success = create_workspace_files(overwrite)
|
|
531
|
+
result.add_step("workspace_files", success)
|
|
532
|
+
print(f" {'OK' if success else 'FAILED'}\n")
|
|
533
|
+
|
|
534
|
+
# Step 3: Create .env template
|
|
535
|
+
print("[3/6] Creating environment template...")
|
|
536
|
+
success = create_env_file(overwrite)
|
|
537
|
+
result.add_step("env_file", success)
|
|
538
|
+
print(f" {'OK' if success else 'FAILED'}\n")
|
|
539
|
+
|
|
540
|
+
# Step 4: Load environment
|
|
541
|
+
print("[4/6] Loading environment...")
|
|
542
|
+
success = load_env()
|
|
543
|
+
result.add_step("load_env", success)
|
|
544
|
+
if not success:
|
|
545
|
+
result.warnings.append("Environment not loaded - configure .env file")
|
|
546
|
+
print(f" {'OK' if success else 'SKIPPED'}\n")
|
|
547
|
+
|
|
548
|
+
# Step 5: Check API keys
|
|
549
|
+
print("[5/6] Checking API keys...")
|
|
550
|
+
keys = check_api_keys()
|
|
551
|
+
configured = [k for k, v in keys.items() if v]
|
|
552
|
+
missing = [k for k, v in keys.items() if not v]
|
|
553
|
+
result.add_step("api_keys", len(configured) > 0, f"Configured: {configured}")
|
|
554
|
+
if missing:
|
|
555
|
+
result.warnings.append(f"Missing API keys: {missing}")
|
|
556
|
+
print(f" Configured: {', '.join(configured) or 'None'}")
|
|
557
|
+
print(f" Missing: {', '.join(missing) or 'None'}\n")
|
|
558
|
+
|
|
559
|
+
# Step 6: Database
|
|
560
|
+
print("[6/6] Database setup...")
|
|
561
|
+
if init_db and keys.get("database"):
|
|
562
|
+
db_success = await initialize_database()
|
|
563
|
+
result.add_step("database", db_success)
|
|
564
|
+
print(f" {'Initialized' if db_success else 'FAILED'}\n")
|
|
565
|
+
elif keys.get("database"):
|
|
566
|
+
db_success = await check_database_connection()
|
|
567
|
+
result.add_step("database", db_success, "Connection test only")
|
|
568
|
+
print(f" {'Connected' if db_success else 'FAILED'}\n")
|
|
569
|
+
else:
|
|
570
|
+
result.add_step("database", False, "Not configured")
|
|
571
|
+
result.warnings.append("Database not configured")
|
|
572
|
+
print(" SKIPPED (no DATABASE_URL)\n")
|
|
573
|
+
|
|
574
|
+
# Summary
|
|
575
|
+
print("="*60)
|
|
576
|
+
if result.success:
|
|
577
|
+
print(" Setup completed successfully!")
|
|
578
|
+
else:
|
|
579
|
+
print(" Setup completed with issues.")
|
|
580
|
+
|
|
581
|
+
if result.warnings:
|
|
582
|
+
print("\n Warnings:")
|
|
583
|
+
for w in result.warnings:
|
|
584
|
+
print(f" - {w}")
|
|
585
|
+
|
|
586
|
+
print("\n Next steps:")
|
|
587
|
+
print(f" 1. Configure API keys in: {SECRETS_PATH / '.env'}")
|
|
588
|
+
print(f" 2. Customize workspace files in: {WORKSPACE_PATH}")
|
|
589
|
+
if not keys.get("database"):
|
|
590
|
+
print(" 3. Set DATABASE_URL and run: hyperclaw setup --init-db")
|
|
591
|
+
print(" 4. Start the server: hyperclaw server")
|
|
592
|
+
print("="*60 + "\n")
|
|
593
|
+
|
|
594
|
+
return result
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def setup_sync(init_db: bool = False, overwrite: bool = False, verbose: bool = False) -> SetupResult:
|
|
598
|
+
"""Synchronous wrapper for setup."""
|
|
599
|
+
return asyncio.run(run_setup(init_db, overwrite, verbose))
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
# ============================================================================
|
|
603
|
+
# CLI ENTRY POINT
|
|
604
|
+
# ============================================================================
|
|
605
|
+
|
|
606
|
+
def main():
|
|
607
|
+
"""CLI entry point for setup."""
|
|
608
|
+
import argparse
|
|
609
|
+
|
|
610
|
+
parser = argparse.ArgumentParser(description="HyperClaw Setup")
|
|
611
|
+
parser.add_argument("--init-db", action="store_true", help="Initialize database schema")
|
|
612
|
+
parser.add_argument("--overwrite", action="store_true", help="Overwrite existing files")
|
|
613
|
+
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
|
|
614
|
+
|
|
615
|
+
args = parser.parse_args()
|
|
616
|
+
|
|
617
|
+
result = setup_sync(
|
|
618
|
+
init_db=args.init_db,
|
|
619
|
+
overwrite=args.overwrite,
|
|
620
|
+
verbose=args.verbose
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
sys.exit(0 if result.success else 1)
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
if __name__ == "__main__":
|
|
627
|
+
main()
|