apsimo 1.3.0__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.
- apsimo/__init__.py +38 -0
- apsimo/__main__.py +6 -0
- apsimo/agent/__init__.py +6 -0
- apsimo/agent/client.py +276 -0
- apsimo/agent/models.py +46 -0
- apsimo/agents/__init__.py +20 -0
- apsimo/agents/models.py +264 -0
- apsimo/agents/store.py +861 -0
- apsimo/agents/websocket.py +522 -0
- apsimo/api/__init__.py +1 -0
- apsimo/api/auth_telemetry.py +287 -0
- apsimo/api/authority.py +1203 -0
- apsimo/api/contact_grants.py +347 -0
- apsimo/api/middleware.py +483 -0
- apsimo/api/routers/__init__.py +1 -0
- apsimo/api/routers/commitment_work.py +265 -0
- apsimo/api/routers/context_gate.py +123 -0
- apsimo/api/routers/executions.py +140 -0
- apsimo/api/routers/followup_plans.py +147 -0
- apsimo/api/routers/governed_actions.py +162 -0
- apsimo/api/routers/host.py +14473 -0
- apsimo/api/routers/initiative_work.py +115 -0
- apsimo/api/routers/mining.py +104 -0
- apsimo/api/routers/observations.py +110 -0
- apsimo/api/routers/social_state.py +225 -0
- apsimo/api/routers/task_queue.py +2715 -0
- apsimo/api/routers/temporal_followups.py +251 -0
- apsimo/api/routers/transport.py +110 -0
- apsimo/api/routers/transport_ingress_api.py +240 -0
- apsimo/api/schemas/__init__.py +1 -0
- apsimo/api/schemas/host.py +1949 -0
- apsimo/autonomy/cli.py +110 -0
- apsimo/autonomy/condition_worker.py +437 -0
- apsimo/autonomy/config.py +424 -0
- apsimo/autonomy/loop.py +4316 -0
- apsimo/autonomy/registry.py +339 -0
- apsimo/autonomy/scheduler.py +1822 -0
- apsimo/autonomy/synthesis.py +449 -0
- apsimo/backup.py +962 -0
- apsimo/beliefs/__init__.py +23 -0
- apsimo/beliefs/contradictions.py +109 -0
- apsimo/beliefs/decay.py +61 -0
- apsimo/beliefs/engine.py +479 -0
- apsimo/beliefs/models.py +67 -0
- apsimo/beliefs/promotion.py +41 -0
- apsimo/beliefs/resolve.py +58 -0
- apsimo/beliefs/source_claims.py +690 -0
- apsimo/beliefs/source_projection.py +883 -0
- apsimo/beliefs/source_time.py +208 -0
- apsimo/beliefs/store.py +133 -0
- apsimo/briefings/aggregators.py +824 -0
- apsimo/briefings/composer.py +420 -0
- apsimo/briefings/config.py +55 -0
- apsimo/briefings/delivery.py +439 -0
- apsimo/briefings/engagement.py +97 -0
- apsimo/briefings/engine.py +274 -0
- apsimo/briefings/enhancer.py +99 -0
- apsimo/briefings/models.py +183 -0
- apsimo/briefings/scheduler.py +382 -0
- apsimo/briefings/store.py +435 -0
- apsimo/chain/__init__.py +48 -0
- apsimo/chain/block.py +100 -0
- apsimo/chain/cli.py +704 -0
- apsimo/chain/genesis.py +443 -0
- apsimo/chain/identity.py +416 -0
- apsimo/chain/keys.py +1025 -0
- apsimo/chain/local_keys.py +187 -0
- apsimo/chain/manager.py +290 -0
- apsimo/chain/node.py +163 -0
- apsimo/chain/plugin_transactions.py +371 -0
- apsimo/chain/protocol.py +220 -0
- apsimo/chain/state_machine.py +676 -0
- apsimo/chain/storage.py +503 -0
- apsimo/chain/transactions.py +250 -0
- apsimo/chain/validation.py +397 -0
- apsimo/channels/__init__.py +1 -0
- apsimo/channels/manifest.py +31 -0
- apsimo/channels/migrations/001_channels_schema.sql +12 -0
- apsimo/channels/phone_gateways.py +42 -0
- apsimo/channels/presence.py +188 -0
- apsimo/channels/router.py +235 -0
- apsimo/channels/store.py +231 -0
- apsimo/cli.py +2688 -0
- apsimo/cognition/__init__.py +11 -0
- apsimo/cognition/charter.py +398 -0
- apsimo/cognition/drive_governance.py +3530 -0
- apsimo/cognition/evidence_pipeline.py +1627 -0
- apsimo/cognition/external_events.py +932 -0
- apsimo/cognition/goal_spine.py +3488 -0
- apsimo/cognition/introspection.py +214 -0
- apsimo/cognition/prompt.py +150 -0
- apsimo/cognition/runtime.py +108 -0
- apsimo/cognition/trigger.py +154 -0
- apsimo/commitments/__init__.py +18 -0
- apsimo/commitments/local_work.py +355 -0
- apsimo/commitments/store.py +1052 -0
- apsimo/commitments/work.py +91 -0
- apsimo/compat.py +53 -0
- apsimo/compression/__init__.py +467 -0
- apsimo/connectors/__init__.py +21 -0
- apsimo/connectors/base.py +152 -0
- apsimo/connectors/caldav_calendar.py +125 -0
- apsimo/connectors/fs_documents.py +85 -0
- apsimo/connectors/imap_email.py +138 -0
- apsimo/connectors/manager.py +218 -0
- apsimo/connectors/webhook_pull.py +88 -0
- apsimo/contacts/__init__.py +33 -0
- apsimo/contacts/comms.py +357 -0
- apsimo/contacts/config.py +79 -0
- apsimo/contacts/exporters/__init__.py +1 -0
- apsimo/contacts/exporters/vcard.py +71 -0
- apsimo/contacts/identity_links.py +251 -0
- apsimo/contacts/importer.py +280 -0
- apsimo/contacts/importers/__init__.py +1 -0
- apsimo/contacts/importers/batch.py +43 -0
- apsimo/contacts/importers/macos_contacts.py +101 -0
- apsimo/contacts/migrations/001_contacts_schema.sql +141 -0
- apsimo/contacts/migrations/002_trust_scopes.sql +36 -0
- apsimo/contacts/migrations/003_open_gateway_enum.sql +32 -0
- apsimo/contacts/migrations/004_contact_provision_operations.sql +18 -0
- apsimo/contacts/migrations/005_identity_links.sql +27 -0
- apsimo/contacts/models.py +308 -0
- apsimo/contacts/scoring.py +16 -0
- apsimo/contacts/store.py +1623 -0
- apsimo/contacts/transport_ingress.py +252 -0
- apsimo/contacts/world_bridge.py +314 -0
- apsimo/contextgate/__init__.py +69 -0
- apsimo/contextgate/chunker.py +169 -0
- apsimo/contextgate/estimate.py +54 -0
- apsimo/contextgate/gate.py +313 -0
- apsimo/contextgate/retrieve.py +115 -0
- apsimo/delivery/__init__.py +16 -0
- apsimo/delivery/bridge.py +1260 -0
- apsimo/delivery/channels.py +526 -0
- apsimo/delivery/classification.py +50 -0
- apsimo/delivery/rate_limiter.py +268 -0
- apsimo/delivery/reachout_policy.py +206 -0
- apsimo/directed/__init__.py +22 -0
- apsimo/directed/audit.py +167 -0
- apsimo/directed/intake.py +95 -0
- apsimo/directed/models.py +191 -0
- apsimo/directed/service.py +509 -0
- apsimo/directives/__init__.py +25 -0
- apsimo/directives/evidence.py +87 -0
- apsimo/directives/extractor.py +188 -0
- apsimo/directives/guard.py +364 -0
- apsimo/directives/models.py +206 -0
- apsimo/directives/service.py +372 -0
- apsimo/directives/store.py +167 -0
- apsimo/doctor.py +2173 -0
- apsimo/environment.py +43 -0
- apsimo/events/__init__.py +33 -0
- apsimo/events/broadcaster.py +98 -0
- apsimo/events/bus.py +217 -0
- apsimo/events/journal.py +863 -0
- apsimo/events/stream.py +131 -0
- apsimo/events/types.py +150 -0
- apsimo/execution_results.py +357 -0
- apsimo/feedback/__init__.py +5 -0
- apsimo/feedback/store.py +76 -0
- apsimo/feeds/__init__.py +19 -0
- apsimo/feeds/cli.py +84 -0
- apsimo/feeds/engine.py +437 -0
- apsimo/feeds/example-feed.yaml +77 -0
- apsimo/feeds/hermes_cron.py +126 -0
- apsimo/feeds/manager.py +235 -0
- apsimo/feeds/spec.py +250 -0
- apsimo/feeds/template.py +202 -0
- apsimo/gate/__init__.py +18 -0
- apsimo/gate/audit.py +61 -0
- apsimo/gate/communication_policy.py +166 -0
- apsimo/gate/config.py +72 -0
- apsimo/gate/context_provenance.py +170 -0
- apsimo/gate/env_risk.py +226 -0
- apsimo/gate/guard_audit.py +353 -0
- apsimo/gate/layers/__init__.py +1 -0
- apsimo/gate/layers/base.py +15 -0
- apsimo/gate/layers/l1_recipient.py +66 -0
- apsimo/gate/layers/l2_pii.py +134 -0
- apsimo/gate/layers/l3_cross_context.py +50 -0
- apsimo/gate/layers/l4_trust_tier.py +78 -0
- apsimo/gate/layers/l5_injection.py +199 -0
- apsimo/gate/layers/l6_review.py +86 -0
- apsimo/gate/layers/l7_delay.py +100 -0
- apsimo/gate/layers/tom2_epistemic.py +185 -0
- apsimo/gate/models.py +64 -0
- apsimo/gate/pending_dispatch.py +5 -0
- apsimo/gate/pipeline.py +206 -0
- apsimo/gate/rejection.py +259 -0
- apsimo/gate/response_guard.py +700 -0
- apsimo/gate/rulesets/injection_v1.yaml +51 -0
- apsimo/gate/surface_policy.py +189 -0
- apsimo/gate/taint.py +226 -0
- apsimo/genesis.json +9 -0
- apsimo/goals/__init__.py +100 -0
- apsimo/goals/config.py +38 -0
- apsimo/goals/decomposer.py +421 -0
- apsimo/goals/engine.py +617 -0
- apsimo/goals/inference.py +354 -0
- apsimo/goals/models.py +302 -0
- apsimo/goals/priority.py +270 -0
- apsimo/goals/queue_bridge.py +149 -0
- apsimo/goals/replan.py +450 -0
- apsimo/goals/schema.sql +89 -0
- apsimo/goals/store.py +692 -0
- apsimo/governed_actions.py +1708 -0
- apsimo/harness_integration/__init__.py +45 -0
- apsimo/harness_integration/context.py +41 -0
- apsimo/harness_integration/skills.py +231 -0
- apsimo/identity/__init__.py +26 -0
- apsimo/identity/participants.py +181 -0
- apsimo/identity/resolver.py +329 -0
- apsimo/identity_bootstrap/__init__.py +5 -0
- apsimo/identity_bootstrap/builder.py +208 -0
- apsimo/identity_bootstrap/corpus.py +443 -0
- apsimo/identity_bootstrap/models.py +54 -0
- apsimo/identity_bootstrap/runner.py +353 -0
- apsimo/identity_bootstrap/seeders/__init__.py +25 -0
- apsimo/identity_bootstrap/seeders/briefings.py +109 -0
- apsimo/identity_bootstrap/seeders/chain.py +57 -0
- apsimo/identity_bootstrap/seeders/goals.py +128 -0
- apsimo/identity_bootstrap/seeders/memory.py +191 -0
- apsimo/identity_bootstrap/seeders/neo4j_cognition.py +79 -0
- apsimo/identity_bootstrap/seeders/relationship.py +152 -0
- apsimo/identity_bootstrap/seeders/sessions.py +67 -0
- apsimo/identity_bootstrap/seeders/skills.py +92 -0
- apsimo/identity_bootstrap/seeders/task_queue.py +72 -0
- apsimo/identity_bootstrap/seeders/world_model.py +143 -0
- apsimo/identity_bootstrap/self_query.py +92 -0
- apsimo/identity_bootstrap/self_reflection.py +155 -0
- apsimo/identity_bootstrap/skill.py +37 -0
- apsimo/identity_bootstrap/verifier.py +436 -0
- apsimo/initiatives/__init__.py +20 -0
- apsimo/initiatives/action_registry.py +454 -0
- apsimo/initiatives/approval_authority.py +2105 -0
- apsimo/initiatives/approval_policy.py +123 -0
- apsimo/initiatives/assignment.py +263 -0
- apsimo/initiatives/backup_evidence.py +100 -0
- apsimo/initiatives/context_freshness.py +103 -0
- apsimo/initiatives/models.py +318 -0
- apsimo/initiatives/native_work.py +270 -0
- apsimo/initiatives/standing_approvals.py +232 -0
- apsimo/initiatives/store.py +1081 -0
- apsimo/initiatives/temporal_followup.py +410 -0
- apsimo/intelligence/__init__.py +1 -0
- apsimo/intelligence/cognition/__init__.py +24 -0
- apsimo/intelligence/cognition/gap_detector.py +148 -0
- apsimo/intelligence/cognition/metalearner.py +547 -0
- apsimo/intelligence/cognition/metrics_collector.py +217 -0
- apsimo/intelligence/cognition/performance_index.py +299 -0
- apsimo/intelligence/cognition/registry.py +192 -0
- apsimo/intelligence/cognition/strategy_adjuster.py +222 -0
- apsimo/intelligence/cognition/types.py +16 -0
- apsimo/intelligence/components/__init__.py +66 -0
- apsimo/intelligence/components/anomaly_detector.py +413 -0
- apsimo/intelligence/components/initiative_engine.py +2643 -0
- apsimo/intelligence/components/preference_learner.py +521 -0
- apsimo/intelligence/components/research_orchestrator.py +358 -0
- apsimo/intelligence/components/self_directed_thinker.py +221 -0
- apsimo/intelligence/components/self_reflector.py +252 -0
- apsimo/intelligence/components/session_continuity.py +154 -0
- apsimo/intelligence/components/task_planner.py +320 -0
- apsimo/intelligence/components/tool_learner.py +217 -0
- apsimo/intelligence/graph/__init__.py +79 -0
- apsimo/intelligence/graph/client.py +2483 -0
- apsimo/intelligence/graph/consolidator.py +405 -0
- apsimo/intelligence/graph/distiller.py +312 -0
- apsimo/intelligence/graph/migrations.py +129 -0
- apsimo/intelligence/graph/queries.py +248 -0
- apsimo/intelligence/graph/recall.py +281 -0
- apsimo/intelligence/graph/reconciler.py +144 -0
- apsimo/intelligence/graph/schema.py +337 -0
- apsimo/intelligence/graph/selection.py +252 -0
- apsimo/intelligence/learning/__init__.py +17 -0
- apsimo/intelligence/learning/continuous_learner.py +245 -0
- apsimo/intelligence/learning/feedback_store.py +321 -0
- apsimo/intelligence/mind_model/__init__.py +1 -0
- apsimo/intelligence/mind_model/graph_baseline.py +136 -0
- apsimo/intelligence/mind_model/signal_collector.py +361 -0
- apsimo/intelligence/relationships/__init__.py +11 -0
- apsimo/intelligence/relationships/profiler.py +389 -0
- apsimo/intelligence/relationships/scorer.py +560 -0
- apsimo/intelligence/relationships/signal_floor.py +66 -0
- apsimo/intelligence/relationships/trust_tiers.py +300 -0
- apsimo/intelligence/synthesis/__init__.py +40 -0
- apsimo/intelligence/synthesis/connection_discoverer.py +379 -0
- apsimo/intelligence/synthesis/cross_domain_analyzer.py +287 -0
- apsimo/intelligence/synthesis/insight_deliverer.py +171 -0
- apsimo/intelligence/synthesis/insight_store.py +79 -0
- apsimo/intelligence/synthesis/insight_validator.py +183 -0
- apsimo/intelligence/synthesis/novelty_scorer.py +267 -0
- apsimo/intelligence/turn_middleware/__init__.py +15 -0
- apsimo/intelligence/turn_middleware/memory_sync.py +119 -0
- apsimo/mcp/__init__.py +41 -0
- apsimo/mcp/__main__.py +6 -0
- apsimo/mcp/config.py +287 -0
- apsimo/mcp/server.py +501 -0
- apsimo/migrations.py +187 -0
- apsimo/mining/__init__.py +27 -0
- apsimo/mining/corpus.py +239 -0
- apsimo/mining/escalations.py +289 -0
- apsimo/mining/models.py +169 -0
- apsimo/mining/store.py +210 -0
- apsimo/models/__init__.py +30 -0
- apsimo/models/memory.py +80 -0
- apsimo/models/mesh.py +72 -0
- apsimo/models/person.py +104 -0
- apsimo/models/signal.py +108 -0
- apsimo/observations/__init__.py +15 -0
- apsimo/observations/store.py +277 -0
- apsimo/patterns/__init__.py +6 -0
- apsimo/patterns/extract.py +187 -0
- apsimo/patterns/store.py +227 -0
- apsimo/persona/__init__.py +1 -0
- apsimo/persona/engine.py +611 -0
- apsimo/persona/manifest.py +140 -0
- apsimo/projects/__init__.py +28 -0
- apsimo/projects/engine.py +1681 -0
- apsimo/projects/event_outbox.py +188 -0
- apsimo/projects/models.py +216 -0
- apsimo/projects/planner.py +181 -0
- apsimo/projects/store.py +1446 -0
- apsimo/proposals/__init__.py +12 -0
- apsimo/proposals/engine.py +114 -0
- apsimo/proposals/models.py +207 -0
- apsimo/qualification/__init__.py +1 -0
- apsimo/qualification/cases.py +75 -0
- apsimo/qualification/cli.py +51 -0
- apsimo/qualification/memory_cases.py +209 -0
- apsimo/qualification/records.py +92 -0
- apsimo/qualification/report.py +87 -0
- apsimo/qualification/runner.py +311 -0
- apsimo/qualification/structured_cases.py +131 -0
- apsimo/reasoning/__init__.py +13 -0
- apsimo/reasoning/executor.py +506 -0
- apsimo/reasoning/loop.py +373 -0
- apsimo/reasoning/native_tools/__init__.py +16 -0
- apsimo/reasoning/native_tools/calculate.py +141 -0
- apsimo/reasoning/native_tools/file_ops.py +150 -0
- apsimo/reasoning/native_tools/web_search.py +49 -0
- apsimo/reasoning/tool_policy.py +182 -0
- apsimo/redact/__init__.py +176 -0
- apsimo/repos/__init__.py +5 -0
- apsimo/repos/mirrors.py +204 -0
- apsimo/research/__init__.py +41 -0
- apsimo/research/artifact.py +482 -0
- apsimo/research/gatherer.py +387 -0
- apsimo/research/pipeline.py +513 -0
- apsimo/research/search/__init__.py +7 -0
- apsimo/research/search/base.py +41 -0
- apsimo/research/search/brave.py +59 -0
- apsimo/research/search/cache.py +51 -0
- apsimo/research/search/duckduckgo.py +103 -0
- apsimo/research/search/orchestrator.py +119 -0
- apsimo/research/search/serpapi.py +59 -0
- apsimo/research/search/tavily.py +59 -0
- apsimo/research/synthesizer.py +309 -0
- apsimo/router/__init__.py +30 -0
- apsimo/router/complexity_scorer.py +148 -0
- apsimo/router/endpoints.py +153 -0
- apsimo/router/fallback.py +58 -0
- apsimo/router/functions.py +243 -0
- apsimo/router/native_policy.py +52 -0
- apsimo/router/router.py +762 -0
- apsimo/router/self_learning.py +174 -0
- apsimo/router/tiers.py +677 -0
- apsimo/sandbox/__init__.py +21 -0
- apsimo/sandbox/backend.py +195 -0
- apsimo/sandbox/manager.py +173 -0
- apsimo/scope_bounds.py +7 -0
- apsimo/secrets/__init__.py +6 -0
- apsimo/secrets/backends/__init__.py +8 -0
- apsimo/secrets/backends/base.py +42 -0
- apsimo/secrets/backends/env.py +110 -0
- apsimo/secrets/backends/keyring.py +72 -0
- apsimo/secrets/backends/onepassword.py +232 -0
- apsimo/secrets/cli.py +191 -0
- apsimo/secrets/manager.py +160 -0
- apsimo/secrets/migration.py +101 -0
- apsimo/secrets/types.py +98 -0
- apsimo/seed.py +41 -0
- apsimo/self_model/__init__.py +37 -0
- apsimo/self_model/appraisals.py +673 -0
- apsimo/self_model/benchmark.py +1314 -0
- apsimo/self_model/brief.py +40 -0
- apsimo/self_model/event_concerns.py +1128 -0
- apsimo/self_model/execution_forecasts.py +353 -0
- apsimo/self_model/expectations.py +1595 -0
- apsimo/self_model/experiments.py +1150 -0
- apsimo/self_model/journal.py +148 -0
- apsimo/self_model/judgments.py +705 -0
- apsimo/self_model/native_outcomes.py +55 -0
- apsimo/self_model/params.py +220 -0
- apsimo/self_model/perspective.py +246 -0
- apsimo/self_model/reconcile.py +183 -0
- apsimo/self_model/reply_forecasts.py +381 -0
- apsimo/self_model/runtime_forecasts.py +296 -0
- apsimo/self_model/runtime_models.py +67 -0
- apsimo/self_model/settlement.py +207 -0
- apsimo/self_model/situation.py +1731 -0
- apsimo/self_model/store.py +883 -0
- apsimo/self_model/supervised.py +137 -0
- apsimo/self_model/thinker.py +99 -0
- apsimo/self_model/trust.py +388 -0
- apsimo/self_model/workspace.py +2388 -0
- apsimo/server.py +4197 -0
- apsimo/services/__init__.py +1 -0
- apsimo/services/agent_bridge.py +474 -0
- apsimo/services/initiative_executor.py +914 -0
- apsimo/services/instance.py +297 -0
- apsimo/sessions/__init__.py +22 -0
- apsimo/sessions/config.py +13 -0
- apsimo/sessions/context_loader.py +88 -0
- apsimo/sessions/federation_session.py +75 -0
- apsimo/sessions/isolated_session.py +98 -0
- apsimo/sessions/reports.py +84 -0
- apsimo/sessions/store.py +148 -0
- apsimo/setup.py +2818 -0
- apsimo/setup_hermes.py +879 -0
- apsimo/setup_local_work.py +218 -0
- apsimo/setup_native_goals.py +134 -0
- apsimo/setup_native_reviews.py +115 -0
- apsimo/skills/__init__.py +10 -0
- apsimo/skills/base.py +108 -0
- apsimo/skills/budget.py +28 -0
- apsimo/skills/executor.py +493 -0
- apsimo/skills/executors/__init__.py +1 -0
- apsimo/skills/executors/behavioral_correction.py +75 -0
- apsimo/skills/executors/capability_gap.py +38 -0
- apsimo/skills/executors/data_quality.py +163 -0
- apsimo/skills/executors/knowledge_acquisition.py +41 -0
- apsimo/skills/executors/operational_hygiene.py +185 -0
- apsimo/skills/executors/subsystem_health.py +169 -0
- apsimo/skills/hermes_export.py +431 -0
- apsimo/skills/index.py +123 -0
- apsimo/skills/learning/__init__.py +21 -0
- apsimo/skills/learning/novelty_detector.py +206 -0
- apsimo/skills/learning/pattern_extractor.py +199 -0
- apsimo/skills/learning/triggers.py +159 -0
- apsimo/skills/loader.py +246 -0
- apsimo/skills/migrations/002_progressive_loading.sql +6 -0
- apsimo/skills/migrations/backfill_triggers.py +20 -0
- apsimo/skills/models.py +202 -0
- apsimo/skills/packager.py +128 -0
- apsimo/skills/protocols.py +70 -0
- apsimo/skills/registry.py +191 -0
- apsimo/skills/runtime.py +58 -0
- apsimo/skills/sandbox_runner.py +229 -0
- apsimo/skills/scheduler.py +129 -0
- apsimo/skills/schema.py +79 -0
- apsimo/skills/security/__init__.py +12 -0
- apsimo/skills/security/guards.py +53 -0
- apsimo/skills/security/scanner.py +223 -0
- apsimo/skills_memory/__init__.py +26 -0
- apsimo/skills_memory/distill.py +159 -0
- apsimo/skills_memory/models.py +85 -0
- apsimo/skills_memory/retrieve.py +62 -0
- apsimo/skills_memory/store.py +172 -0
- apsimo/surprise/__init__.py +6 -0
- apsimo/surprise/accumulation.py +57 -0
- apsimo/surprise/scorer.py +102 -0
- apsimo/surprise/store.py +203 -0
- apsimo/task_queue/__init__.py +69 -0
- apsimo/task_queue/action_receipts.py +148 -0
- apsimo/task_queue/approval_relay_canary.py +108 -0
- apsimo/task_queue/config.py +85 -0
- apsimo/task_queue/contract.py +361 -0
- apsimo/task_queue/events.py +130 -0
- apsimo/task_queue/governor.py +1031 -0
- apsimo/task_queue/handlers/__init__.py +16 -0
- apsimo/task_queue/handlers/base.py +37 -0
- apsimo/task_queue/handlers/inference.py +640 -0
- apsimo/task_queue/handlers/monitoring.py +116 -0
- apsimo/task_queue/handlers/registry.py +75 -0
- apsimo/task_queue/handlers/subtask_handler.py +173 -0
- apsimo/task_queue/handlers/system_maintenance.py +147 -0
- apsimo/task_queue/mesh_integration.py +111 -0
- apsimo/task_queue/models.py +317 -0
- apsimo/task_queue/queue_manager.py +8286 -0
- apsimo/task_queue/routing.py +287 -0
- apsimo/task_queue/scheduler.py +252 -0
- apsimo/task_queue/schema.sql +197 -0
- apsimo/task_queue/work_control.py +342 -0
- apsimo/task_queue/worker.py +993 -0
- apsimo/telemetry.py +145 -0
- apsimo/tom/__init__.py +6 -0
- apsimo/tom/affect.py +387 -0
- apsimo/tom/approvals.py +171 -0
- apsimo/tom/arcs.py +896 -0
- apsimo/tom/asymmetry.py +131 -0
- apsimo/tom/eligibility.py +248 -0
- apsimo/tom/engagement.py +214 -0
- apsimo/tom/exposure.py +214 -0
- apsimo/tom/extractor.py +306 -0
- apsimo/tom/fact_adapters.py +144 -0
- apsimo/tom/facts.py +326 -0
- apsimo/tom/integration.py +592 -0
- apsimo/tom/leveled.py +118 -0
- apsimo/tom/levels.py +247 -0
- apsimo/tom/recipient_audit.py +995 -0
- apsimo/tom/recipient_simulator.py +593 -0
- apsimo/tom/source_lineage.py +93 -0
- apsimo/tom/tom2.py +277 -0
- apsimo/tom/visibility.py +559 -0
- apsimo/tom/visibility_store.py +414 -0
- apsimo/tools/__init__.py +0 -0
- apsimo/tools/definitions.py +740 -0
- apsimo/tools/handlers.py +943 -0
- apsimo/toolsmith/__init__.py +26 -0
- apsimo/toolsmith/authority.py +166 -0
- apsimo/toolsmith/engine.py +559 -0
- apsimo/toolsmith/integrity.py +100 -0
- apsimo/toolsmith/miner.py +145 -0
- apsimo/toolsmith/policy.py +110 -0
- apsimo/toolsmith/registry.py +635 -0
- apsimo/turns/__init__.py +17 -0
- apsimo/turns/audio.py +134 -0
- apsimo/turns/documents.py +235 -0
- apsimo/turns/executions.py +486 -0
- apsimo/turns/hermes_history.py +245 -0
- apsimo/turns/hermes_kanban.py +268 -0
- apsimo/turns/hermes_work.py +96 -0
- apsimo/turns/idempotency.py +752 -0
- apsimo/turns/local_work.py +115 -0
- apsimo/turns/media.py +581 -0
- apsimo/turns/reported_workers.py +196 -0
- apsimo/turns/source_annotations.py +283 -0
- apsimo/turns/source_attribution.py +154 -0
- apsimo/turns/source_read.py +351 -0
- apsimo/turns/source_vectors.py +263 -0
- apsimo/turns/video.py +210 -0
- apsimo/util/autonomy_preset.py +220 -0
- apsimo/util/instance.py +92 -0
- apsimo/util/model_output.py +25 -0
- apsimo/util/quiet_hours.py +27 -0
- apsimo/util/session_safety.py +37 -0
- apsimo/util/temporal.py +343 -0
- apsimo/vector/__init__.py +75 -0
- apsimo/vector/backfill.py +171 -0
- apsimo/vector/caption.py +114 -0
- apsimo/vector/collections.py +51 -0
- apsimo/vector/config.py +102 -0
- apsimo/vector/embedder.py +670 -0
- apsimo/vector/image_preprocess.py +406 -0
- apsimo/vector/image_store.py +296 -0
- apsimo/vector/indexes.py +162 -0
- apsimo/vector/migrate.py +334 -0
- apsimo/vector/multimodal_provider.py +417 -0
- apsimo/vector/multimodal_types.py +87 -0
- apsimo/vector/openai_provider.py +119 -0
- apsimo/vector/query.py +49 -0
- apsimo/vector/reranker.py +565 -0
- apsimo/vector/safety_image.py +159 -0
- apsimo/vector/scanner.py +197 -0
- apsimo/vector/setup.py +289 -0
- apsimo/vector/store.py +533 -0
- apsimo/vector/tiers.py +263 -0
- apsimo/work_orders.py +925 -0
- apsimo/workers/__init__.py +21 -0
- apsimo/workers/agent_bridge.py +640 -0
- apsimo/workers/colony_worker.py +382 -0
- apsimo/workers/queue_worker.py +441 -0
- apsimo/workers/skills_sync.py +152 -0
- apsimo/world_model/__init__.py +71 -0
- apsimo/world_model/causal_maintenance.py +131 -0
- apsimo/world_model/causal_policy.py +43 -0
- apsimo/world_model/causal_query.py +125 -0
- apsimo/world_model/confidence.py +54 -0
- apsimo/world_model/config.py +64 -0
- apsimo/world_model/constants.py +97 -0
- apsimo/world_model/entities.py +145 -0
- apsimo/world_model/expectation_resolvers.py +177 -0
- apsimo/world_model/extraction/__init__.py +7 -0
- apsimo/world_model/extraction/base.py +62 -0
- apsimo/world_model/extraction/conversation_extractor.py +262 -0
- apsimo/world_model/extraction/detector.py +74 -0
- apsimo/world_model/extraction/document_extractor.py +78 -0
- apsimo/world_model/extraction/formats/__init__.py +24 -0
- apsimo/world_model/extraction/formats/csv_fmt.py +68 -0
- apsimo/world_model/extraction/formats/html_fmt.py +72 -0
- apsimo/world_model/extraction/formats/json_fmt.py +68 -0
- apsimo/world_model/extraction/formats/pdf.py +43 -0
- apsimo/world_model/extraction/formats/text.py +27 -0
- apsimo/world_model/extraction/llm_extractor.py +164 -0
- apsimo/world_model/extraction/pipeline.py +73 -0
- apsimo/world_model/integrations/__init__.py +5 -0
- apsimo/world_model/integrations/mind_model_bridge.py +115 -0
- apsimo/world_model/integrations/social_intel_bridge.py +120 -0
- apsimo/world_model/jobs/__init__.py +4 -0
- apsimo/world_model/jobs/extraction_job.py +168 -0
- apsimo/world_model/llm_extract.py +572 -0
- apsimo/world_model/neo4j/__init__.py +5 -0
- apsimo/world_model/neo4j/backend.py +654 -0
- apsimo/world_model/observations.py +155 -0
- apsimo/world_model/populator.py +307 -0
- apsimo/world_model/postgres/__init__.py +1 -0
- apsimo/world_model/postgres/backend.py +683 -0
- apsimo/world_model/relationships.py +25 -0
- apsimo/world_model/resolution/__init__.py +13 -0
- apsimo/world_model/resolution/entity_resolver.py +232 -0
- apsimo/world_model/resolution/merge_audit.py +16 -0
- apsimo/world_model/resolution/merge_workflow.py +117 -0
- apsimo/world_model/source_reports.py +121 -0
- apsimo/world_model/sqlite/__init__.py +4 -0
- apsimo/world_model/sqlite/backend.py +855 -0
- apsimo/world_model/sqlite/schema.sql +132 -0
- apsimo/world_model/store.py +545 -0
- apsimo-1.3.0.dist-info/METADATA +78 -0
- apsimo-1.3.0.dist-info/RECORD +614 -0
- apsimo-1.3.0.dist-info/WHEEL +5 -0
- apsimo-1.3.0.dist-info/entry_points.txt +11 -0
- apsimo-1.3.0.dist-info/licenses/LICENSE +21 -0
- apsimo-1.3.0.dist-info/top_level.txt +2 -0
- colony_sidecar/__init__.py +4 -0
apsimo/environment.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Normalize public environment names at process and instance load boundaries.
|
|
2
|
+
|
|
3
|
+
Stored configuration remains unchanged. Internal COLONY_* readers receive
|
|
4
|
+
explicit APSIMO_* values; conflicting explicit aliases are configuration errors.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from collections.abc import Mapping
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
_generated: dict[str, str] = {}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def normalize_environment(values: Mapping[str, str] | None = None) -> dict[str, str]:
|
|
15
|
+
"""Return a normalized copy, with no mutation or secret values in errors."""
|
|
16
|
+
result = dict(os.environ if values is None else values)
|
|
17
|
+
for name, value in tuple(result.items()):
|
|
18
|
+
if not name.startswith('APSIMO_'):
|
|
19
|
+
continue
|
|
20
|
+
legacy = 'COLONY_' + name[len('APSIMO_'):]
|
|
21
|
+
if legacy in result and result[legacy] != value:
|
|
22
|
+
raise ValueError(f'Conflicting environment names: {name} and {legacy}')
|
|
23
|
+
result[legacy] = value
|
|
24
|
+
return result
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def clear_environment_aliases() -> None:
|
|
28
|
+
"""Remove only aliases this module generated, before selecting an instance."""
|
|
29
|
+
for name, value in _generated.items():
|
|
30
|
+
if os.environ.get(name) == value:
|
|
31
|
+
os.environ.pop(name, None)
|
|
32
|
+
_generated.clear()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def apply_environment_aliases() -> None:
|
|
36
|
+
"""Refresh generated aliases; removed canonical keys cannot leave stale reads."""
|
|
37
|
+
clear_environment_aliases()
|
|
38
|
+
original = dict(os.environ)
|
|
39
|
+
normalized = normalize_environment(original)
|
|
40
|
+
for name, value in normalized.items():
|
|
41
|
+
if name not in original:
|
|
42
|
+
os.environ[name] = value
|
|
43
|
+
_generated[name] = value
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Colony event bus.
|
|
2
|
+
|
|
3
|
+
Typed event dispatch for inter-component communication.
|
|
4
|
+
Components emit events when state changes, and other components
|
|
5
|
+
subscribe to react. The bus provides type filtering, error isolation,
|
|
6
|
+
and bounded history.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .bus import EventBus, Subscription, TypedEventBus
|
|
10
|
+
from .types import (
|
|
11
|
+
CognitionEvent,
|
|
12
|
+
Event,
|
|
13
|
+
IntegrationEvent,
|
|
14
|
+
MemoryEvent,
|
|
15
|
+
MeshEvent,
|
|
16
|
+
PersonEvent,
|
|
17
|
+
SignalEvent,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
# Bus
|
|
22
|
+
"EventBus",
|
|
23
|
+
"TypedEventBus",
|
|
24
|
+
"Subscription",
|
|
25
|
+
# Event types
|
|
26
|
+
"Event",
|
|
27
|
+
"PersonEvent",
|
|
28
|
+
"SignalEvent",
|
|
29
|
+
"MemoryEvent",
|
|
30
|
+
"MeshEvent",
|
|
31
|
+
"CognitionEvent",
|
|
32
|
+
"IntegrationEvent",
|
|
33
|
+
]
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Shared lazy-broadcast helper for sidecar subsystems.
|
|
2
|
+
|
|
3
|
+
Subsystems (consolidator, goal store, briefing store, world-model store,
|
|
4
|
+
skills registry) call ``emit(type, payload)`` to push a typed event to
|
|
5
|
+
all connected WebSocket subscribers. The import of ``broadcast_event``
|
|
6
|
+
is lazy so modules that want to emit events don't take a hard dependency
|
|
7
|
+
on the API router.
|
|
8
|
+
|
|
9
|
+
Errors are swallowed — event emission must never break the subsystem
|
|
10
|
+
that triggers it.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
_broadcast_fn = None
|
|
22
|
+
|
|
23
|
+
# In-process consumers by event type. emit() used to reach only WebSocket
|
|
24
|
+
# subscribers, so an event with no client connected simply died; subsystems
|
|
25
|
+
# that need to REACT to an event (not just display it) register here.
|
|
26
|
+
_subscribers: Dict[str, List[Callable[[Dict[str, Any]], Any]]] = {}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def subscribe(event_type: str, fn: Callable[[Dict[str, Any]], Any]) -> None:
|
|
30
|
+
"""Register an in-process consumer for one event type.
|
|
31
|
+
|
|
32
|
+
Consumers are invoked synchronously from ``emit()`` with the full event
|
|
33
|
+
dict (``type``/``occurred_at``/``payload``); keep them cheap. A consumer
|
|
34
|
+
error is swallowed — emission must never break the emitting subsystem.
|
|
35
|
+
"""
|
|
36
|
+
_subscribers.setdefault(event_type, []).append(fn)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _resolve_broadcaster():
|
|
40
|
+
"""Lazy-import ``broadcast_event`` from the host router.
|
|
41
|
+
|
|
42
|
+
Returns a no-op lambda if the import fails (unit-test contexts,
|
|
43
|
+
circular-import edge cases, sidecar not yet booted).
|
|
44
|
+
"""
|
|
45
|
+
global _broadcast_fn
|
|
46
|
+
if _broadcast_fn is None:
|
|
47
|
+
try:
|
|
48
|
+
from apsimo.api.routers.host import broadcast_event
|
|
49
|
+
_broadcast_fn = broadcast_event
|
|
50
|
+
except ImportError:
|
|
51
|
+
# Do not cache startup/circular-import failure forever. A later
|
|
52
|
+
# emission can resolve the fully initialized host publisher.
|
|
53
|
+
return lambda _e: None
|
|
54
|
+
return _broadcast_fn
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def emit(event_type: str, payload: Optional[Dict[str, Any]] = None) -> None:
|
|
58
|
+
"""Send a typed event through the durable host event publisher.
|
|
59
|
+
|
|
60
|
+
The production host publisher journals and assigns a sequence before it
|
|
61
|
+
broadcasts. Test doubles may return ``None``; in-process consumers still
|
|
62
|
+
receive the source event in that case.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
event_type: One of the canonical ``HostEventType`` values —
|
|
66
|
+
``briefing``, ``anomaly``, ``goal_update``,
|
|
67
|
+
``memory_consolidated``, ``world_model_changed``,
|
|
68
|
+
``skill_draft_approved``, ``proactive_message``, etc.
|
|
69
|
+
payload: Arbitrary event-specific payload. Keep it small —
|
|
70
|
+
subscribers fetch full records via the REST API when they
|
|
71
|
+
need detail.
|
|
72
|
+
"""
|
|
73
|
+
try:
|
|
74
|
+
broadcaster = _resolve_broadcaster()
|
|
75
|
+
event = {
|
|
76
|
+
"type": event_type,
|
|
77
|
+
"occurred_at": datetime.now(timezone.utc).isoformat(),
|
|
78
|
+
"payload": payload or {},
|
|
79
|
+
}
|
|
80
|
+
published = broadcaster(event)
|
|
81
|
+
consumer_event = published if isinstance(published, dict) else event
|
|
82
|
+
|
|
83
|
+
# In-process consumers (best-effort, each isolated)
|
|
84
|
+
for fn in _subscribers.get(event_type, ()):
|
|
85
|
+
try:
|
|
86
|
+
fn(consumer_event)
|
|
87
|
+
except Exception:
|
|
88
|
+
logger.debug("in-process consumer failed for %s",
|
|
89
|
+
event_type, exc_info=True)
|
|
90
|
+
|
|
91
|
+
except Exception:
|
|
92
|
+
logger.debug("broadcast_event(%s) failed", event_type, exc_info=True)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def reset_broadcaster_for_tests(fn) -> None:
|
|
96
|
+
"""Inject a broadcaster for test doubles. Production code never calls this."""
|
|
97
|
+
global _broadcast_fn
|
|
98
|
+
_broadcast_fn = fn
|
apsimo/events/bus.py
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"""Event bus for Colony.
|
|
2
|
+
|
|
3
|
+
Provides typed, filtered event dispatch with error isolation.
|
|
4
|
+
Handlers subscribe to specific event types and receive only matching
|
|
5
|
+
events. Handler exceptions are caught and logged, never propagated
|
|
6
|
+
to other handlers or the emitter. Supports both sync and async emit.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import logging
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from typing import Any, Callable, List, Optional, Type, TypeVar
|
|
13
|
+
|
|
14
|
+
from apsimo.events.types import (
|
|
15
|
+
Event,
|
|
16
|
+
MemoryEvent,
|
|
17
|
+
MeshEvent,
|
|
18
|
+
PersonEvent,
|
|
19
|
+
)
|
|
20
|
+
from apsimo.models.memory import Memory
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
T = TypeVar("T", bound=Event)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Subscription:
|
|
29
|
+
"""Event subscription metadata.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
handler: Callback to invoke when a matching event is emitted
|
|
33
|
+
event_types: Which event types this subscription listens for
|
|
34
|
+
filter_fn: Optional predicate for additional filtering
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
handler: Callable[[Event], None]
|
|
38
|
+
event_types: List[Type[Event]]
|
|
39
|
+
filter_fn: Optional[Callable[[Event], bool]] = None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class EventBus:
|
|
43
|
+
"""Typed event bus for Colony.
|
|
44
|
+
|
|
45
|
+
Features:
|
|
46
|
+
- Type-safe subscriptions (subscribe to specific event types)
|
|
47
|
+
- Optional filtering (predicate function per subscription)
|
|
48
|
+
- Async support (awaitable emit)
|
|
49
|
+
- Error isolation (handler errors don't crash other handlers)
|
|
50
|
+
- Bounded history (capped at max_history entries)
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self, max_history: int = 1000):
|
|
54
|
+
self._subscribers: List[Subscription] = []
|
|
55
|
+
self._event_history: List[Event] = []
|
|
56
|
+
self._max_history = max_history
|
|
57
|
+
|
|
58
|
+
def subscribe(
|
|
59
|
+
self,
|
|
60
|
+
handler: Callable[[Event], None],
|
|
61
|
+
event_types: List[Type[Event]],
|
|
62
|
+
filter_fn: Optional[Callable[[Event], bool]] = None,
|
|
63
|
+
) -> Subscription:
|
|
64
|
+
"""Subscribe to events of specific types with optional filter.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
handler: Function called when a matching event is emitted
|
|
68
|
+
event_types: List of event classes to listen for
|
|
69
|
+
filter_fn: Optional predicate; handler only called if this returns True
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
The Subscription instance (pass to unsubscribe to remove)
|
|
73
|
+
"""
|
|
74
|
+
sub = Subscription(
|
|
75
|
+
handler=handler,
|
|
76
|
+
event_types=event_types,
|
|
77
|
+
filter_fn=filter_fn,
|
|
78
|
+
)
|
|
79
|
+
self._subscribers.append(sub)
|
|
80
|
+
return sub
|
|
81
|
+
|
|
82
|
+
def unsubscribe(self, subscription: Subscription) -> None:
|
|
83
|
+
"""Remove a subscription."""
|
|
84
|
+
if subscription in self._subscribers:
|
|
85
|
+
self._subscribers.remove(subscription)
|
|
86
|
+
|
|
87
|
+
def emit(self, event: Event) -> None:
|
|
88
|
+
"""Emit an event to all matching subscribers.
|
|
89
|
+
|
|
90
|
+
Handler errors are caught and logged, not propagated.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
event: The event to dispatch
|
|
94
|
+
"""
|
|
95
|
+
self._record(event)
|
|
96
|
+
|
|
97
|
+
for sub in self._subscribers:
|
|
98
|
+
if not self._matches(sub, event):
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
sub.handler(event)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.error(
|
|
105
|
+
"Event handler error: %s", e,
|
|
106
|
+
extra={"event_id": event.id, "handler": sub.handler.__name__},
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
async def emit_async(self, event: Event) -> None:
|
|
110
|
+
"""Async emit. Handlers can be sync or async callables.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
event: The event to dispatch
|
|
114
|
+
"""
|
|
115
|
+
self._record(event)
|
|
116
|
+
|
|
117
|
+
for sub in self._subscribers:
|
|
118
|
+
if not self._matches(sub, event):
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
result = sub.handler(event)
|
|
123
|
+
if asyncio.iscoroutine(result):
|
|
124
|
+
await result
|
|
125
|
+
except Exception as e:
|
|
126
|
+
logger.error(
|
|
127
|
+
"Async event handler error: %s", e,
|
|
128
|
+
extra={"event_id": event.id, "handler": sub.handler.__name__},
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def get_history(
|
|
132
|
+
self,
|
|
133
|
+
event_types: Optional[List[Type[Event]]] = None,
|
|
134
|
+
limit: int = 100,
|
|
135
|
+
) -> List[Event]:
|
|
136
|
+
"""Get recent events, optionally filtered by type.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
event_types: If provided, only return events matching these types
|
|
140
|
+
limit: Maximum number of events to return
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
List of recent events, most recent last
|
|
144
|
+
"""
|
|
145
|
+
events = self._event_history
|
|
146
|
+
if event_types:
|
|
147
|
+
events = [e for e in events if any(isinstance(e, et) for et in event_types)]
|
|
148
|
+
return events[-limit:]
|
|
149
|
+
|
|
150
|
+
def clear_history(self) -> None:
|
|
151
|
+
"""Clear event history."""
|
|
152
|
+
self._event_history.clear()
|
|
153
|
+
|
|
154
|
+
def _record(self, event: Event) -> None:
|
|
155
|
+
"""Append event to history, trimming if over capacity."""
|
|
156
|
+
self._event_history.append(event)
|
|
157
|
+
if len(self._event_history) > self._max_history:
|
|
158
|
+
self._event_history = self._event_history[-self._max_history :]
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def _matches(sub: Subscription, event: Event) -> bool:
|
|
162
|
+
"""Check if an event matches a subscription's type and filter."""
|
|
163
|
+
if not any(isinstance(event, et) for et in sub.event_types):
|
|
164
|
+
return False
|
|
165
|
+
if sub.filter_fn and not sub.filter_fn(event):
|
|
166
|
+
return False
|
|
167
|
+
return True
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class TypedEventBus(EventBus):
|
|
171
|
+
"""EventBus with typed emit helpers for common event types."""
|
|
172
|
+
|
|
173
|
+
def emit_person_event(
|
|
174
|
+
self,
|
|
175
|
+
person_id: str,
|
|
176
|
+
event_type: str,
|
|
177
|
+
old_value: Any = None,
|
|
178
|
+
new_value: Any = None,
|
|
179
|
+
**kwargs: Any,
|
|
180
|
+
) -> None:
|
|
181
|
+
"""Emit a PersonEvent with convenience parameters."""
|
|
182
|
+
self.emit(
|
|
183
|
+
PersonEvent(
|
|
184
|
+
id=f"person-{person_id}-{event_type}",
|
|
185
|
+
person_id=person_id,
|
|
186
|
+
event_type=event_type,
|
|
187
|
+
old_value=old_value,
|
|
188
|
+
new_value=new_value,
|
|
189
|
+
**kwargs,
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
def emit_memory_event(self, memory: Memory, event_type: str) -> None:
|
|
194
|
+
"""Emit a MemoryEvent for a specific memory."""
|
|
195
|
+
self.emit(
|
|
196
|
+
MemoryEvent(
|
|
197
|
+
id=f"memory-{memory.id}-{event_type}",
|
|
198
|
+
memory=memory,
|
|
199
|
+
event_type=event_type,
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def emit_mesh_event(
|
|
204
|
+
self,
|
|
205
|
+
node_id: str,
|
|
206
|
+
event_type: str,
|
|
207
|
+
**kwargs: Any,
|
|
208
|
+
) -> None:
|
|
209
|
+
"""Emit a MeshEvent for a specific node."""
|
|
210
|
+
self.emit(
|
|
211
|
+
MeshEvent(
|
|
212
|
+
id=f"mesh-{node_id}-{event_type}",
|
|
213
|
+
node_id=node_id,
|
|
214
|
+
event_type=event_type,
|
|
215
|
+
**kwargs,
|
|
216
|
+
)
|
|
217
|
+
)
|