hyperagents 1.2.3rc5.post3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agents/__init__.py +31 -0
- agents/background_monitor.py +453 -0
- agents/learning.py +460 -0
- agents/planner.py +421 -0
- agents/transcriber.py +341 -0
- civilization/__init__.py +51 -0
- civilization/api/__init__.py +7 -0
- civilization/api/civilization_api.py +361 -0
- civilization/graph/__init__.py +19 -0
- civilization/graph/knowledge_linker.py +348 -0
- civilization/graph/org_graph.py +348 -0
- civilization/graph/process_graph.py +386 -0
- civilization/ingestion/__init__.py +20 -0
- civilization/ingestion/chunker.py +273 -0
- civilization/ingestion/document_ingestor.py +358 -0
- civilization/ingestion/embedder.py +262 -0
- civilization/ingestion/extractor.py +224 -0
- civilization/interview/__init__.py +19 -0
- civilization/interview/gap_detector.py +380 -0
- civilization/interview/interviewer.py +323 -0
- civilization/interview/questioner.py +363 -0
- civilization/retrieval/__init__.py +17 -0
- civilization/retrieval/civilization_rag.py +316 -0
- civilization/retrieval/context_injector.py +342 -0
- civilization/retrieval/relevance_ranker.py +287 -0
- civilization/schema.py +299 -0
- civilization/store.py +177 -0
- civilization/sync/__init__.py +16 -0
- civilization/sync/confluence_sync.py +317 -0
- civilization/sync/gdrive_sync.py +262 -0
- civilization/sync/notion_sync.py +237 -0
- civilization/versioning/__init__.py +19 -0
- civilization/versioning/diff_engine.py +351 -0
- civilization/versioning/staleness_detector.py +303 -0
- civilization/versioning/version_manager.py +293 -0
- cli/__init__.py +1 -0
- cli/doctor.py +334 -0
- cli/hyperclaw.py +1357 -0
- cli/onboarding.py +469 -0
- core/__init__.py +1 -0
- core/connectors/__init__.py +119 -0
- core/connectors/infrastructure.py +772 -0
- core/connectors/messaging.py +586 -0
- core/connectors/productivity.py +764 -0
- core/connectors/smarthome.py +528 -0
- core/connectors/social.py +730 -0
- core/hyperrouter/__init__.py +23 -0
- core/hyperrouter/bandit.py +218 -0
- core/hyperrouter/fast_loop.py +68 -0
- core/hyperrouter/slow_loop.py +143 -0
- core/hyperstate/__init__.py +24 -0
- core/hyperstate/certifier.py +154 -0
- core/hyperstate/schema.py +160 -0
- core/hyperstate/state_manager.py +103 -0
- core/hyperstate/store.py +163 -0
- core/providers/__init__.py +121 -0
- core/providers/embeddings.py +389 -0
- core/providers/image.py +534 -0
- core/providers/llm.py +1935 -0
- core/providers/search.py +608 -0
- core/providers/voice.py +474 -0
- hyperagents-1.2.3rc5.post3.dist-info/METADATA +469 -0
- hyperagents-1.2.3rc5.post3.dist-info/RECORD +361 -0
- hyperagents-1.2.3rc5.post3.dist-info/WHEEL +5 -0
- hyperagents-1.2.3rc5.post3.dist-info/entry_points.txt +6 -0
- hyperagents-1.2.3rc5.post3.dist-info/licenses/LICENSE +21 -0
- hyperagents-1.2.3rc5.post3.dist-info/top_level.txt +13 -0
- hyperclaw/__init__.py +67 -0
- hyperclaw/__main__.py +220 -0
- hyperclaw/agent.py +775 -0
- hyperclaw/agent_coordinator.py +577 -0
- hyperclaw/anthropic_params.py +225 -0
- hyperclaw/api_utils.py +85 -0
- hyperclaw/approval_telegram.py +209 -0
- hyperclaw/approval_terminal.py +80 -0
- hyperclaw/attachments.py +177 -0
- hyperclaw/branding.py +55 -0
- hyperclaw/brief/__init__.py +11 -0
- hyperclaw/brief/cli.py +204 -0
- hyperclaw/brief/collect.py +146 -0
- hyperclaw/brief/compose.py +333 -0
- hyperclaw/brief/diff.py +110 -0
- hyperclaw/brief/errors.py +99 -0
- hyperclaw/brief/google.py +269 -0
- hyperclaw/brief/google_auth.py +294 -0
- hyperclaw/brief/links.py +124 -0
- hyperclaw/brief/service.py +424 -0
- hyperclaw/brief/store.py +205 -0
- hyperclaw/brief/tasks.py +200 -0
- hyperclaw/chat_scope.py +115 -0
- hyperclaw/cli_tui.py +497 -0
- hyperclaw/client_guard.py +717 -0
- hyperclaw/connection_check.py +113 -0
- hyperclaw/cost_guard.py +1728 -0
- hyperclaw/default_config/agents.yaml +534 -0
- hyperclaw/default_config/hyperclaw.yaml +27 -0
- hyperclaw/default_config/models.yaml +161 -0
- hyperclaw/deployment.py +39 -0
- hyperclaw/digest/__init__.py +9 -0
- hyperclaw/digest/cli.py +117 -0
- hyperclaw/digest/errors.py +100 -0
- hyperclaw/digest/gitlab.py +187 -0
- hyperclaw/digest/http.py +113 -0
- hyperclaw/digest/redact.py +32 -0
- hyperclaw/digest/service.py +271 -0
- hyperclaw/digest/slack.py +223 -0
- hyperclaw/digest/state.py +124 -0
- hyperclaw/digest/summarize.py +198 -0
- hyperclaw/digest/tokens.py +143 -0
- hyperclaw/distribution.py +46 -0
- hyperclaw/documents.py +351 -0
- hyperclaw/feeds.py +339 -0
- hyperclaw/google_workspace/__init__.py +5 -0
- hyperclaw/google_workspace/api.py +151 -0
- hyperclaw/google_workspace/auth.py +397 -0
- hyperclaw/google_workspace/calendar.py +157 -0
- hyperclaw/google_workspace/cli.py +72 -0
- hyperclaw/google_workspace/drive.py +236 -0
- hyperclaw/google_workspace/errors.py +58 -0
- hyperclaw/google_workspace/gmail.py +295 -0
- hyperclaw/google_workspace/meet.py +122 -0
- hyperclaw/google_workspace/tools.py +319 -0
- hyperclaw/hyperspeed.py +57 -0
- hyperclaw/integrations_layer.py +1427 -0
- hyperclaw/live_state.py +188 -0
- hyperclaw/managed_config.py +245 -0
- hyperclaw/media_hub.py +179 -0
- hyperclaw/memory_manager.py +584 -0
- hyperclaw/model_catalog.py +551 -0
- hyperclaw/model_policy.py +211 -0
- hyperclaw/model_router.py +595 -0
- hyperclaw/model_selector.py +72 -0
- hyperclaw/naming.py +284 -0
- hyperclaw/notices.py +65 -0
- hyperclaw/oai_stream.py +106 -0
- hyperclaw/orchestrator.py +591 -0
- hyperclaw/outbox.py +82 -0
- hyperclaw/persona.py +367 -0
- hyperclaw/prometheus.py +219 -0
- hyperclaw/prompt_assembly.py +157 -0
- hyperclaw/provider_setup.py +146 -0
- hyperclaw/providers.py +340 -0
- hyperclaw/qualification.py +341 -0
- hyperclaw/qualification_keys/hyper-d292fd127cef5a3e.pub +1 -0
- hyperclaw/qualification_records/anthropic--claude-sonnet-5-5.json +14 -0
- hyperclaw/reasoning_display.py +35 -0
- hyperclaw/scheduler.py +454 -0
- hyperclaw/server.py +847 -0
- hyperclaw/setup.py +627 -0
- hyperclaw/skills.py +717 -0
- hyperclaw/solomon.py +442 -0
- hyperclaw/swarm.py +533 -0
- hyperclaw/taint.py +832 -0
- hyperclaw/team/__init__.py +28 -0
- hyperclaw/team/dispatcher.py +431 -0
- hyperclaw/team/genesis.py +106 -0
- hyperclaw/team/lead.py +110 -0
- hyperclaw/team/model.py +135 -0
- hyperclaw/team/morning.py +238 -0
- hyperclaw/team/repos.py +66 -0
- hyperclaw/team/roster.py +264 -0
- hyperclaw/team/specialist.py +235 -0
- hyperclaw/team/status.py +163 -0
- hyperclaw/team/watchers.py +112 -0
- hyperclaw/teamsetup/__init__.py +17 -0
- hyperclaw/teamsetup/checks.py +208 -0
- hyperclaw/teamsetup/item.py +391 -0
- hyperclaw/teamsetup/oauth_loopback.py +84 -0
- hyperclaw/teamsetup/onboard.py +550 -0
- hyperclaw/teamsetup/profile.py +82 -0
- hyperclaw/teamsetup/secrets.py +313 -0
- hyperclaw/teamsetup/selfcheck.py +295 -0
- hyperclaw/teamsetup/service.py +495 -0
- hyperclaw/teamsetup/slack_oauth.py +442 -0
- hyperclaw/teamsetup/tty.py +62 -0
- hyperclaw/telegram_bot.py +1106 -0
- hyperclaw/telegram_intake.py +126 -0
- hyperclaw/telegram_pairing.py +360 -0
- hyperclaw/terminal_provider.py +323 -0
- hyperclaw/tools/__init__.py +1 -0
- hyperclaw/tools/approval.py +949 -0
- hyperclaw/tools/args.py +212 -0
- hyperclaw/tools/catalog.py +244 -0
- hyperclaw/tools/classify.py +266 -0
- hyperclaw/tools/effects.py +724 -0
- hyperclaw/tools/egress.py +210 -0
- hyperclaw/tools/envelope.py +188 -0
- hyperclaw/tools/guard.py +367 -0
- hyperclaw/tools/ledger.py +339 -0
- hyperclaw/tools/receipts.py +70 -0
- hyperclaw/tools/registry.py +318 -0
- hyperclaw/tools/service_guard.py +151 -0
- hyperclaw/tools/surfaces.py +54 -0
- hyperclaw/tools/workspace.py +87 -0
- hyperclaw/trading/__init__.py +77 -0
- hyperclaw/truth_guard.py +791 -0
- hyperclaw/tts.py +124 -0
- hyperclaw/tui.py +4255 -0
- hyperclaw/tui_bridge.py +938 -0
- hyperclaw/unattended.py +60 -0
- hyperclaw/updates/__init__.py +54 -0
- hyperclaw/updates/check.py +131 -0
- hyperclaw/updates/index.py +178 -0
- hyperclaw/updates/install.py +110 -0
- hyperclaw/updates/managed.py +161 -0
- hyperclaw/updates/manifest.py +138 -0
- hyperclaw/updates/notices.py +86 -0
- hyperclaw/updates/paths.py +53 -0
- hyperclaw/updates/release.py +146 -0
- hyperclaw/updates/upgrade.py +253 -0
- hyperclaw/updates/versioning.py +104 -0
- hyperclaw/userconfig.py +119 -0
- hyperclaw/xai.py +83 -0
- integrations/__init__.py +31 -0
- integrations/automation/__init__.py +1 -0
- integrations/automation/make.py +87 -0
- integrations/automation/zapier.py +87 -0
- integrations/base.py +476 -0
- integrations/communication/__init__.py +1 -0
- integrations/communication/twilio.py +279 -0
- integrations/communication/zoom.py +290 -0
- integrations/data/__init__.py +1 -0
- integrations/data/google_analytics.py +135 -0
- integrations/data/postgres.py +182 -0
- integrations/data/supabase_connector.py +202 -0
- integrations/data/weather_feeds.py +450 -0
- integrations/developer/__init__.py +9 -0
- integrations/developer/github.py +406 -0
- integrations/developer/gitlab.py +298 -0
- integrations/enterprise/__init__.py +13 -0
- integrations/enterprise/confluence.py +266 -0
- integrations/enterprise/hubspot.py +293 -0
- integrations/enterprise/jira.py +314 -0
- integrations/enterprise/salesforce.py +286 -0
- integrations/finance/__init__.py +1 -0
- integrations/finance/polymarket_client.py +247 -0
- integrations/finance/quickbooks.py +281 -0
- integrations/finance/stripe.py +261 -0
- integrations/gateway.py +238 -0
- integrations/messaging/__init__.py +32 -0
- integrations/messaging/discord.py +159 -0
- integrations/messaging/email.py +401 -0
- integrations/messaging/imessage.py +443 -0
- integrations/messaging/signal.py +175 -0
- integrations/messaging/slack.py +217 -0
- integrations/messaging/sms.py +175 -0
- integrations/messaging/teams.py +208 -0
- integrations/messaging/telegram.py +260 -0
- integrations/messaging/whatsapp.py +203 -0
- integrations/productivity/__init__.py +17 -0
- integrations/productivity/airtable.py +217 -0
- integrations/productivity/asana.py +248 -0
- integrations/productivity/google/__init__.py +19 -0
- integrations/productivity/google/base.py +89 -0
- integrations/productivity/google/calendar.py +272 -0
- integrations/productivity/google/docs.py +202 -0
- integrations/productivity/google/drive.py +268 -0
- integrations/productivity/google/gmail.py +279 -0
- integrations/productivity/google/meet.py +218 -0
- integrations/productivity/google/sheets.py +222 -0
- integrations/productivity/google/tasks.py +199 -0
- integrations/productivity/linear.py +279 -0
- integrations/productivity/microsoft/__init__.py +13 -0
- integrations/productivity/microsoft/base.py +93 -0
- integrations/productivity/microsoft/calendar.py +207 -0
- integrations/productivity/microsoft/onedrive.py +222 -0
- integrations/productivity/microsoft/outlook.py +241 -0
- integrations/productivity/microsoft/sharepoint.py +211 -0
- integrations/productivity/notion.py +243 -0
- integrations/productivity/todoist.py +250 -0
- integrations/productivity/trello.py +244 -0
- integrations/storage/__init__.py +1 -0
- integrations/storage/box.py +279 -0
- integrations/storage/dropbox.py +215 -0
- integrations/telegram_inbound.py +179 -0
- integrations/telegram_poller.py +151 -0
- memory/__init__.py +1 -0
- memory/causal_graph.py +125 -0
- memory/impact_tracker.py +88 -0
- memory/vector_memory.py +436 -0
- models/__init__.py +12 -0
- models/chatjimmy_client.py +210 -0
- models/claude_client.py +235 -0
- models/claude_code_subagent.py +192 -0
- models/openai_client.py +120 -0
- models/router.py +162 -0
- recursive/discovery_loop.py +118 -0
- recursive/optimization_loop.py +135 -0
- recursive/validation_loop.py +38 -0
- security/__init__.py +1 -0
- security/audit_logger.py +106 -0
- security/filesystem_guard.py +100 -0
- security/hypershield.py +99 -0
- security/network_guard.py +97 -0
- security/policy_engine.py +198 -0
- swarm/__init__.py +1 -0
- swarm/agents/__init__.py +0 -0
- swarm/agents/base.py +230 -0
- swarm/agents/business/__init__.py +0 -0
- swarm/agents/business/counsel.py +31 -0
- swarm/agents/business/herald.py +32 -0
- swarm/agents/business/ledger.py +26 -0
- swarm/agents/business/nexus.py +30 -0
- swarm/agents/business/ops.py +30 -0
- swarm/agents/business/pipeline.py +28 -0
- swarm/agents/business/revenue.py +30 -0
- swarm/agents/business/sovereign.py +31 -0
- swarm/agents/business/strategos.py +27 -0
- swarm/agents/business/talent.py +27 -0
- swarm/agents/business/venture.py +32 -0
- swarm/agents/comms/__init__.py +1 -0
- swarm/agents/comms/cipher.py +32 -0
- swarm/agents/comms/echo_comms.py +31 -0
- swarm/agents/comms/envoy.py +31 -0
- swarm/agents/comms/herald_scheduler.py +33 -0
- swarm/agents/comms/pulse.py +29 -0
- swarm/agents/creative/__init__.py +0 -0
- swarm/agents/creative/author.py +27 -0
- swarm/agents/creative/lens.py +25 -0
- swarm/agents/executive/__init__.py +1 -0
- swarm/agents/intelligence/__init__.py +1 -0
- swarm/agents/intelligence/arbiter.py +30 -0
- swarm/agents/intelligence/sentinel.py +30 -0
- swarm/agents/media/__init__.py +0 -0
- swarm/agents/personal/__init__.py +0 -0
- swarm/agents/personal/atlas.py +27 -0
- swarm/agents/personal/hearth.py +26 -0
- swarm/agents/personal/midas.py +27 -0
- swarm/agents/personal/navigator.py +27 -0
- swarm/agents/personal/nourish.py +31 -0
- swarm/agents/personal/vitals.py +33 -0
- swarm/agents/recursive/__init__.py +0 -0
- swarm/agents/recursive/alchemist.py +73 -0
- swarm/agents/recursive/calibrator.py +45 -0
- swarm/agents/recursive/scout.py +97 -0
- swarm/agents/scientific/__init__.py +0 -0
- swarm/agents/scientific/cosmos.py +36 -0
- swarm/agents/scientific/gaia.py +26 -0
- swarm/agents/scientific/medicus.py +33 -0
- swarm/agents/scientific/oracle_agent.py +39 -0
- swarm/agents/scientific/scribe.py +39 -0
- swarm/agents/talent/__init__.py +0 -0
- swarm/agents/talent/deal.py +28 -0
- swarm/agents/talent/roster.py +29 -0
- swarm/agents/talent/scout.py +29 -0
- swarm/agents/talent/stage.py +27 -0
- swarm/agents/tech/__init__.py +0 -0
- swarm/agents/tech/aegis.py +28 -0
- swarm/agents/tech/bridge.py +28 -0
- swarm/agents/tech/forge.py +28 -0
- swarm/agents/trading/__init__.py +1 -0
- swarm/agents/trading/global_prediction_engine.py +611 -0
- swarm/agents/trading/polymarket_trader.py +165 -0
- swarm/agents/trading/prediction_strategist.py +218 -0
- swarm/autogen_bridge.py +68 -0
- swarm/bid_protocol.py +196 -0
- swarm/dispatcher.py +527 -0
- swarm/nexus.py +181 -0
- swarm/registry.py +112 -0
- telegram_listener.py +403 -0
- ui/tui/app.py +214 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HyperState Schema — Pydantic v2 data models for HyperClaw state management.
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import uuid
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from typing import Any, Literal
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# ── Enums ─────────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
Domain = Literal["personal", "business", "scientific", "creative", "recursive"]
|
|
16
|
+
|
|
17
|
+
TaskType = Literal[
|
|
18
|
+
"code", "research", "analysis", "synthesis",
|
|
19
|
+
"planning", "health", "finance", "scientific",
|
|
20
|
+
"routing", "classification", "quick_lookup",
|
|
21
|
+
"summarization", "draft", "triage", "status_check",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# ── Sub-models ─────────────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
class Task(BaseModel):
|
|
28
|
+
goal: str
|
|
29
|
+
constraints: list[str] = Field(default_factory=list)
|
|
30
|
+
priority: int = Field(default=5, ge=0, le=10)
|
|
31
|
+
task_type: TaskType = "research"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Hypothesis(BaseModel):
|
|
35
|
+
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
|
36
|
+
statement: str
|
|
37
|
+
confidence: float = Field(default=0.5, ge=0.0, le=1.0)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ExperimentEntry(BaseModel):
|
|
41
|
+
method: str
|
|
42
|
+
model_used: str
|
|
43
|
+
result: str = ""
|
|
44
|
+
certified: bool = False
|
|
45
|
+
test_trace: str = ""
|
|
46
|
+
cost_usd: float = 0.0
|
|
47
|
+
latency_ms: float = 0.0
|
|
48
|
+
timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class AgentScore(BaseModel):
|
|
52
|
+
attempts: int = 0
|
|
53
|
+
successes: int = 0
|
|
54
|
+
task_type: str = "general"
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def win_rate(self) -> float:
|
|
58
|
+
return self.successes / self.attempts if self.attempts > 0 else 0.0
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ModelScore(BaseModel):
|
|
62
|
+
attempts: int = 0
|
|
63
|
+
successes: int = 0
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def win_rate(self) -> float:
|
|
67
|
+
return self.successes / self.attempts if self.attempts > 0 else 0.0
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class CertifiedMethod(BaseModel):
|
|
71
|
+
method_id: str
|
|
72
|
+
validated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
|
73
|
+
performance: dict[str, Any] = Field(default_factory=dict)
|
|
74
|
+
model_used: str = ""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class RecursiveResearch(BaseModel):
|
|
78
|
+
active: bool = False
|
|
79
|
+
domains_monitored: list[str] = Field(default_factory=list)
|
|
80
|
+
last_sweep: datetime | None = None
|
|
81
|
+
discoveries_this_week: int = 0
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# ── HyperState ─────────────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
class HyperState(BaseModel):
|
|
87
|
+
state_id: uuid.UUID = Field(default_factory=uuid.uuid4)
|
|
88
|
+
domain: Domain = "business"
|
|
89
|
+
task: Task = Field(default_factory=lambda: Task(goal=""))
|
|
90
|
+
hypotheses: list[Hypothesis] = Field(default_factory=list)
|
|
91
|
+
experiment_log: list[ExperimentEntry] = Field(default_factory=list)
|
|
92
|
+
agent_scores: dict[str, AgentScore] = Field(default_factory=dict)
|
|
93
|
+
model_scores: dict[str, dict[str, ModelScore]] = Field(default_factory=dict)
|
|
94
|
+
certified_methods: list[CertifiedMethod] = Field(default_factory=list)
|
|
95
|
+
routing_weights: dict[str, float] = Field(default_factory=dict)
|
|
96
|
+
recursive_research: RecursiveResearch = Field(default_factory=RecursiveResearch)
|
|
97
|
+
state_version: int = 0
|
|
98
|
+
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
|
99
|
+
last_updated: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
|
100
|
+
|
|
101
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
102
|
+
|
|
103
|
+
def _bump_version(self) -> None:
|
|
104
|
+
self.state_version += 1
|
|
105
|
+
self.last_updated = datetime.now(timezone.utc)
|
|
106
|
+
|
|
107
|
+
def certify_method(
|
|
108
|
+
self,
|
|
109
|
+
method_id: str,
|
|
110
|
+
test_trace: str,
|
|
111
|
+
result: str,
|
|
112
|
+
model_used: str,
|
|
113
|
+
) -> CertifiedMethod:
|
|
114
|
+
"""
|
|
115
|
+
Certify a method if test_trace and result are non-empty.
|
|
116
|
+
Raises CertificationError if validation fails.
|
|
117
|
+
"""
|
|
118
|
+
# Import here to avoid circular at module level
|
|
119
|
+
from .certifier import CertificationError
|
|
120
|
+
|
|
121
|
+
if not test_trace or not test_trace.strip():
|
|
122
|
+
raise CertificationError(
|
|
123
|
+
f"Certification failed for '{method_id}': test_trace is empty. "
|
|
124
|
+
"A non-empty test trace is required for certification."
|
|
125
|
+
)
|
|
126
|
+
if not result or not result.strip():
|
|
127
|
+
raise CertificationError(
|
|
128
|
+
f"Certification failed for '{method_id}': result is empty. "
|
|
129
|
+
"A non-empty result is required for certification."
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
cm = CertifiedMethod(
|
|
133
|
+
method_id=method_id,
|
|
134
|
+
model_used=model_used,
|
|
135
|
+
performance={"test_trace_length": len(test_trace), "result_length": len(result)},
|
|
136
|
+
)
|
|
137
|
+
self.certified_methods.append(cm)
|
|
138
|
+
self._bump_version()
|
|
139
|
+
return cm
|
|
140
|
+
|
|
141
|
+
def get_best_model(self, task_type: str) -> str:
|
|
142
|
+
"""
|
|
143
|
+
Return the model_id with the highest successes/attempts ratio for
|
|
144
|
+
the given task_type. Returns 'claude-sonnet-5' if no data exists.
|
|
145
|
+
"""
|
|
146
|
+
best_model = "claude-sonnet-5"
|
|
147
|
+
best_rate = -1.0
|
|
148
|
+
|
|
149
|
+
for model_id, task_scores in self.model_scores.items():
|
|
150
|
+
score = task_scores.get(task_type)
|
|
151
|
+
if score is None:
|
|
152
|
+
continue
|
|
153
|
+
if score.attempts == 0:
|
|
154
|
+
continue
|
|
155
|
+
rate = score.successes / score.attempts
|
|
156
|
+
if rate > best_rate:
|
|
157
|
+
best_rate = rate
|
|
158
|
+
best_model = model_id
|
|
159
|
+
|
|
160
|
+
return best_model
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
StateManager — lifecycle management for HyperState objects.
|
|
3
|
+
Wraps store operations with business logic.
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
from uuid import UUID
|
|
10
|
+
|
|
11
|
+
from .certifier import Certifier
|
|
12
|
+
from .schema import (
|
|
13
|
+
Domain,
|
|
14
|
+
ExperimentEntry,
|
|
15
|
+
HyperState,
|
|
16
|
+
Task,
|
|
17
|
+
TaskType,
|
|
18
|
+
)
|
|
19
|
+
from .store import HyperStateStore
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class StateManager:
|
|
23
|
+
"""
|
|
24
|
+
High-level API for creating, updating, and managing HyperState lifecycles.
|
|
25
|
+
Uses asyncpg pool internally via HyperStateStore.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, store: HyperStateStore) -> None:
|
|
29
|
+
self._store = store
|
|
30
|
+
self._certifier = Certifier()
|
|
31
|
+
|
|
32
|
+
async def create_state(
|
|
33
|
+
self,
|
|
34
|
+
goal: str,
|
|
35
|
+
domain: Domain,
|
|
36
|
+
task_type: TaskType,
|
|
37
|
+
constraints: Optional[list[str]] = None,
|
|
38
|
+
) -> HyperState:
|
|
39
|
+
"""Create and persist a new HyperState."""
|
|
40
|
+
state = HyperState(
|
|
41
|
+
domain=domain,
|
|
42
|
+
task=Task(
|
|
43
|
+
goal=goal,
|
|
44
|
+
task_type=task_type,
|
|
45
|
+
constraints=constraints or [],
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
await self._store.save_state(state)
|
|
49
|
+
return state
|
|
50
|
+
|
|
51
|
+
async def update_state(
|
|
52
|
+
self,
|
|
53
|
+
state_id: UUID,
|
|
54
|
+
updates: dict[str, Any],
|
|
55
|
+
) -> HyperState:
|
|
56
|
+
"""Apply a dict of field updates to a HyperState and persist it."""
|
|
57
|
+
state = await self._store.load_state(state_id)
|
|
58
|
+
for key, value in updates.items():
|
|
59
|
+
if hasattr(state, key):
|
|
60
|
+
setattr(state, key, value)
|
|
61
|
+
state._bump_version()
|
|
62
|
+
await self._store.save_state(state)
|
|
63
|
+
return state
|
|
64
|
+
|
|
65
|
+
async def add_experiment(
|
|
66
|
+
self,
|
|
67
|
+
state_id: UUID,
|
|
68
|
+
entry: ExperimentEntry,
|
|
69
|
+
) -> HyperState:
|
|
70
|
+
"""Append an ExperimentEntry to a HyperState's experiment log."""
|
|
71
|
+
state = await self._store.load_state(state_id)
|
|
72
|
+
state.experiment_log.append(entry)
|
|
73
|
+
state._bump_version()
|
|
74
|
+
await self._store.save_state(state)
|
|
75
|
+
return state
|
|
76
|
+
|
|
77
|
+
async def certify_method(
|
|
78
|
+
self,
|
|
79
|
+
state_id: UUID,
|
|
80
|
+
method_id: str,
|
|
81
|
+
test_trace: str,
|
|
82
|
+
result: str,
|
|
83
|
+
model_used: str,
|
|
84
|
+
) -> HyperState:
|
|
85
|
+
"""
|
|
86
|
+
Certify a method on a HyperState. Validates via Certifier then
|
|
87
|
+
calls HyperState.certify_method() to record the CertifiedMethod.
|
|
88
|
+
Raises CertificationError if validation fails.
|
|
89
|
+
"""
|
|
90
|
+
state = await self._store.load_state(state_id)
|
|
91
|
+
# Will raise CertificationError if validation fails
|
|
92
|
+
state.certify_method(
|
|
93
|
+
method_id=method_id,
|
|
94
|
+
test_trace=test_trace,
|
|
95
|
+
result=result,
|
|
96
|
+
model_used=model_used,
|
|
97
|
+
)
|
|
98
|
+
await self._store.save_state(state)
|
|
99
|
+
return state
|
|
100
|
+
|
|
101
|
+
async def archive_state(self, state_id: UUID) -> None:
|
|
102
|
+
"""Archive a HyperState (soft delete)."""
|
|
103
|
+
await self._store.archive_state(state_id)
|
core/hyperstate/store.py
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HyperState Store — asyncpg-backed persistence for HyperState objects.
|
|
3
|
+
Connection string loaded from DATABASE_URL env var or config/hyperclaw.yaml.
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import os
|
|
9
|
+
from datetime import datetime, timezone
|
|
10
|
+
from typing import Optional
|
|
11
|
+
from uuid import UUID
|
|
12
|
+
|
|
13
|
+
import asyncpg
|
|
14
|
+
import yaml
|
|
15
|
+
|
|
16
|
+
from .schema import HyperState
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _load_db_url() -> str:
|
|
20
|
+
"""Load DATABASE_URL from env or config/hyperclaw.yaml."""
|
|
21
|
+
url = os.environ.get("DATABASE_URL")
|
|
22
|
+
if url:
|
|
23
|
+
return url
|
|
24
|
+
config_path = os.path.join(os.path.dirname(__file__), "../../../config/hyperclaw.yaml")
|
|
25
|
+
config_path = os.path.normpath(config_path)
|
|
26
|
+
if os.path.exists(config_path):
|
|
27
|
+
with open(config_path) as f:
|
|
28
|
+
cfg = yaml.safe_load(f) or {}
|
|
29
|
+
db_url = cfg.get("database", {}).get("url")
|
|
30
|
+
if db_url:
|
|
31
|
+
return db_url
|
|
32
|
+
return "postgresql://localhost/hyperclaw"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class HyperStateStore:
|
|
36
|
+
"""
|
|
37
|
+
Async persistence layer for HyperState. Uses asyncpg + PostgreSQL.
|
|
38
|
+
pgvector extension assumed available for future vector fields.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, db_url: str | None = None) -> None:
|
|
42
|
+
self._db_url = db_url or _load_db_url()
|
|
43
|
+
self._pool: asyncpg.Pool | None = None
|
|
44
|
+
|
|
45
|
+
async def connect(self) -> None:
|
|
46
|
+
self._pool = await asyncpg.create_pool(self._db_url, min_size=1, max_size=10)
|
|
47
|
+
|
|
48
|
+
async def close(self) -> None:
|
|
49
|
+
if self._pool:
|
|
50
|
+
await self._pool.close()
|
|
51
|
+
|
|
52
|
+
async def create_tables(self) -> None:
|
|
53
|
+
"""Create hyperstates and hyperstate_history tables if they don't exist."""
|
|
54
|
+
assert self._pool, "Call connect() first"
|
|
55
|
+
async with self._pool.acquire() as conn:
|
|
56
|
+
await conn.execute("""
|
|
57
|
+
CREATE TABLE IF NOT EXISTS hyperstates (
|
|
58
|
+
state_id UUID PRIMARY KEY,
|
|
59
|
+
domain TEXT NOT NULL,
|
|
60
|
+
data JSONB NOT NULL,
|
|
61
|
+
state_version INTEGER NOT NULL DEFAULT 0,
|
|
62
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
63
|
+
updated_at TIMESTAMPTZ NOT NULL,
|
|
64
|
+
archived_at TIMESTAMPTZ
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
CREATE TABLE IF NOT EXISTS hyperstate_history (
|
|
68
|
+
id BIGSERIAL PRIMARY KEY,
|
|
69
|
+
state_id UUID NOT NULL REFERENCES hyperstates(state_id),
|
|
70
|
+
state_version INTEGER NOT NULL,
|
|
71
|
+
data JSONB NOT NULL,
|
|
72
|
+
recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_hyperstates_domain
|
|
76
|
+
ON hyperstates(domain);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_hyperstate_history_state_id
|
|
78
|
+
ON hyperstate_history(state_id);
|
|
79
|
+
""")
|
|
80
|
+
|
|
81
|
+
async def save_state(self, state: HyperState) -> None:
|
|
82
|
+
"""Upsert a HyperState by state_id. Writes a history snapshot on each save."""
|
|
83
|
+
assert self._pool, "Call connect() first"
|
|
84
|
+
data = state.model_dump_json()
|
|
85
|
+
async with self._pool.acquire() as conn:
|
|
86
|
+
async with conn.transaction():
|
|
87
|
+
await conn.execute("""
|
|
88
|
+
INSERT INTO hyperstates (state_id, domain, data, state_version, created_at, updated_at)
|
|
89
|
+
VALUES ($1, $2, $3::jsonb, $4, $5, $6)
|
|
90
|
+
ON CONFLICT (state_id) DO UPDATE SET
|
|
91
|
+
domain = EXCLUDED.domain,
|
|
92
|
+
data = EXCLUDED.data,
|
|
93
|
+
state_version = EXCLUDED.state_version,
|
|
94
|
+
updated_at = EXCLUDED.updated_at
|
|
95
|
+
""",
|
|
96
|
+
state.state_id,
|
|
97
|
+
state.domain,
|
|
98
|
+
data,
|
|
99
|
+
state.state_version,
|
|
100
|
+
state.created_at,
|
|
101
|
+
state.last_updated,
|
|
102
|
+
)
|
|
103
|
+
await conn.execute("""
|
|
104
|
+
INSERT INTO hyperstate_history (state_id, state_version, snapshot)
|
|
105
|
+
VALUES ($1, $2, $3::jsonb)
|
|
106
|
+
""", state.state_id, state.state_version, data)
|
|
107
|
+
|
|
108
|
+
async def load_state(self, state_id: UUID) -> HyperState:
|
|
109
|
+
"""Load a HyperState by state_id. Raises KeyError if not found."""
|
|
110
|
+
assert self._pool, "Call connect() first"
|
|
111
|
+
async with self._pool.acquire() as conn:
|
|
112
|
+
row = await conn.fetchrow(
|
|
113
|
+
"SELECT data FROM hyperstates WHERE state_id = $1", state_id
|
|
114
|
+
)
|
|
115
|
+
if row is None:
|
|
116
|
+
raise KeyError(f"HyperState {state_id} not found")
|
|
117
|
+
return HyperState.model_validate_json(row["data"])
|
|
118
|
+
|
|
119
|
+
async def list_states(
|
|
120
|
+
self,
|
|
121
|
+
domain: Optional[str] = None,
|
|
122
|
+
limit: int = 50,
|
|
123
|
+
) -> list[HyperState]:
|
|
124
|
+
"""List active (non-archived) HyperStates, optionally filtered by domain."""
|
|
125
|
+
assert self._pool, "Call connect() first"
|
|
126
|
+
if domain:
|
|
127
|
+
rows = await self._pool.fetch(
|
|
128
|
+
"SELECT data FROM hyperstates WHERE domain = $1 AND archived_at IS NULL "
|
|
129
|
+
"ORDER BY updated_at DESC LIMIT $2",
|
|
130
|
+
domain, limit,
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
rows = await self._pool.fetch(
|
|
134
|
+
"SELECT data FROM hyperstates WHERE archived_at IS NULL "
|
|
135
|
+
"ORDER BY updated_at DESC LIMIT $1",
|
|
136
|
+
limit,
|
|
137
|
+
)
|
|
138
|
+
return [HyperState.model_validate_json(r["data"]) for r in rows]
|
|
139
|
+
|
|
140
|
+
async def archive_state(self, state_id: UUID) -> None:
|
|
141
|
+
"""Set archived_at timestamp on a HyperState."""
|
|
142
|
+
assert self._pool, "Call connect() first"
|
|
143
|
+
await self._pool.execute(
|
|
144
|
+
"UPDATE hyperstates SET archived_at = $1 WHERE state_id = $2",
|
|
145
|
+
datetime.now(timezone.utc), state_id,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
async def get_state_history(self, state_id: UUID) -> list[dict]:
|
|
149
|
+
"""Return all version snapshots for a HyperState."""
|
|
150
|
+
assert self._pool, "Call connect() first"
|
|
151
|
+
rows = await self._pool.fetch(
|
|
152
|
+
"SELECT state_version, snapshot, created_at as recorded_at FROM hyperstate_history "
|
|
153
|
+
"WHERE state_id = $1 ORDER BY state_version ASC",
|
|
154
|
+
state_id,
|
|
155
|
+
)
|
|
156
|
+
return [
|
|
157
|
+
{
|
|
158
|
+
"state_version": r["state_version"],
|
|
159
|
+
"recorded_at": r["recorded_at"].isoformat(),
|
|
160
|
+
"state_data": json.loads(r["snapshot"]),
|
|
161
|
+
}
|
|
162
|
+
for r in rows
|
|
163
|
+
]
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HyperClaw Provider Abstraction Layer.
|
|
3
|
+
Unified interfaces for AI/LLM, voice, image, search, and other providers.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .llm import (
|
|
7
|
+
LLMProvider,
|
|
8
|
+
AnthropicProvider,
|
|
9
|
+
OpenAIProvider,
|
|
10
|
+
GeminiProvider,
|
|
11
|
+
MistralProvider,
|
|
12
|
+
GroqProvider,
|
|
13
|
+
XAIProvider,
|
|
14
|
+
BedrockProvider,
|
|
15
|
+
OpenRouterProvider,
|
|
16
|
+
TogetherProvider,
|
|
17
|
+
PerplexityProvider,
|
|
18
|
+
DeepSeekProvider,
|
|
19
|
+
QwenProvider,
|
|
20
|
+
CerebrasProvider,
|
|
21
|
+
HuggingFaceProvider,
|
|
22
|
+
OllamaProvider,
|
|
23
|
+
VLLMProvider,
|
|
24
|
+
LiteLLMProvider,
|
|
25
|
+
get_llm_provider,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
from .voice import (
|
|
29
|
+
VoiceProvider,
|
|
30
|
+
STTProvider,
|
|
31
|
+
TTSProvider,
|
|
32
|
+
WhisperProvider,
|
|
33
|
+
DeepgramProvider,
|
|
34
|
+
AssemblyAIProvider,
|
|
35
|
+
ElevenLabsProvider,
|
|
36
|
+
GoogleTTSProvider,
|
|
37
|
+
OpenAITTSProvider,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
from .image import (
|
|
41
|
+
ImageProvider,
|
|
42
|
+
DALLEProvider,
|
|
43
|
+
StabilityProvider,
|
|
44
|
+
MidjourneyProvider,
|
|
45
|
+
ReplicateProvider,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
from .search import (
|
|
49
|
+
SearchProvider,
|
|
50
|
+
GoogleSearchProvider,
|
|
51
|
+
BingSearchProvider,
|
|
52
|
+
DuckDuckGoProvider,
|
|
53
|
+
SerpAPIProvider,
|
|
54
|
+
PerplexitySearchProvider,
|
|
55
|
+
ArxivProvider,
|
|
56
|
+
WikipediaProvider,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
from .embeddings import (
|
|
60
|
+
EmbeddingProvider,
|
|
61
|
+
OpenAIEmbedder,
|
|
62
|
+
VoyageEmbedder,
|
|
63
|
+
GeminiEmbedder,
|
|
64
|
+
MistralEmbedder,
|
|
65
|
+
CohereEmbedder,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
__all__ = [
|
|
69
|
+
# LLM
|
|
70
|
+
"LLMProvider",
|
|
71
|
+
"AnthropicProvider",
|
|
72
|
+
"OpenAIProvider",
|
|
73
|
+
"GeminiProvider",
|
|
74
|
+
"MistralProvider",
|
|
75
|
+
"GroqProvider",
|
|
76
|
+
"XAIProvider",
|
|
77
|
+
"BedrockProvider",
|
|
78
|
+
"OpenRouterProvider",
|
|
79
|
+
"TogetherProvider",
|
|
80
|
+
"PerplexityProvider",
|
|
81
|
+
"DeepSeekProvider",
|
|
82
|
+
"QwenProvider",
|
|
83
|
+
"CerebrasProvider",
|
|
84
|
+
"HuggingFaceProvider",
|
|
85
|
+
"OllamaProvider",
|
|
86
|
+
"VLLMProvider",
|
|
87
|
+
"LiteLLMProvider",
|
|
88
|
+
"get_llm_provider",
|
|
89
|
+
# Voice
|
|
90
|
+
"VoiceProvider",
|
|
91
|
+
"STTProvider",
|
|
92
|
+
"TTSProvider",
|
|
93
|
+
"WhisperProvider",
|
|
94
|
+
"DeepgramProvider",
|
|
95
|
+
"AssemblyAIProvider",
|
|
96
|
+
"ElevenLabsProvider",
|
|
97
|
+
"GoogleTTSProvider",
|
|
98
|
+
"OpenAITTSProvider",
|
|
99
|
+
# Image
|
|
100
|
+
"ImageProvider",
|
|
101
|
+
"DALLEProvider",
|
|
102
|
+
"StabilityProvider",
|
|
103
|
+
"MidjourneyProvider",
|
|
104
|
+
"ReplicateProvider",
|
|
105
|
+
# Search
|
|
106
|
+
"SearchProvider",
|
|
107
|
+
"GoogleSearchProvider",
|
|
108
|
+
"BingSearchProvider",
|
|
109
|
+
"DuckDuckGoProvider",
|
|
110
|
+
"SerpAPIProvider",
|
|
111
|
+
"PerplexitySearchProvider",
|
|
112
|
+
"ArxivProvider",
|
|
113
|
+
"WikipediaProvider",
|
|
114
|
+
# Embeddings
|
|
115
|
+
"EmbeddingProvider",
|
|
116
|
+
"OpenAIEmbedder",
|
|
117
|
+
"VoyageEmbedder",
|
|
118
|
+
"GeminiEmbedder",
|
|
119
|
+
"MistralEmbedder",
|
|
120
|
+
"CohereEmbedder",
|
|
121
|
+
]
|