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/mining/models.py
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""Mining models: escalation records + verbatim turn capture.
|
|
2
|
+
|
|
3
|
+
Concept provenance: inspired by external scaffolding work (drowzeys
|
|
4
|
+
Keys-Setup) on turning cloud/escalation corrections into local supervision
|
|
5
|
+
and serving logs into training data. Concepts only; no code adopted
|
|
6
|
+
(unlicensed + immature upstream).
|
|
7
|
+
|
|
8
|
+
Env flags
|
|
9
|
+
---------
|
|
10
|
+
COLONY_ESCALATION_MINING = off | shadow | live (default shadow)
|
|
11
|
+
off: no capture, no detection.
|
|
12
|
+
shadow: capture verbatim turns + bank/journal escalation records.
|
|
13
|
+
live: shadow + feed banked escalations into skills-memory distillation.
|
|
14
|
+
COLONY_ESCALATION_CONSULT_REGEX
|
|
15
|
+
Pattern that marks a turn as a build-agent consultation (the agent
|
|
16
|
+
shelled out to a coding agent). Deployment-tunable.
|
|
17
|
+
COLONY_ESCALATION_HEAVY_RE
|
|
18
|
+
Pattern over the per-turn model name that marks a provider escalation
|
|
19
|
+
(heavy-model or cloud-failover turn). Empty (default) disables the
|
|
20
|
+
provider detector; deployments list their heavy/cloud models.
|
|
21
|
+
COLONY_MINING_TURN_CAP
|
|
22
|
+
Per-side verbatim capture cap in chars (default 8000).
|
|
23
|
+
COLONY_CORPUS_EXPORT_ENABLED
|
|
24
|
+
Gate for the corpus exporter endpoint (default true; exports only run
|
|
25
|
+
on explicit request and never leave the state dir).
|
|
26
|
+
"""
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
import json
|
|
30
|
+
import os
|
|
31
|
+
import time
|
|
32
|
+
import uuid
|
|
33
|
+
from dataclasses import dataclass, field
|
|
34
|
+
from typing import Any, Dict, List, Optional
|
|
35
|
+
|
|
36
|
+
ESCALATION_KINDS = ("consultation", "provider_escalation")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def mining_mode() -> str:
|
|
40
|
+
from apsimo.util.autonomy_preset import resolve
|
|
41
|
+
return resolve("COLONY_ESCALATION_MINING",
|
|
42
|
+
("off", "shadow", "live"), "shadow")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def corpus_export_enabled() -> bool:
|
|
46
|
+
return os.environ.get(
|
|
47
|
+
"COLONY_CORPUS_EXPORT_ENABLED", "true"
|
|
48
|
+
).strip().lower() not in ("false", "0", "no", "off")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def consult_regex() -> str:
|
|
52
|
+
return os.environ.get(
|
|
53
|
+
"COLONY_ESCALATION_CONSULT_REGEX",
|
|
54
|
+
r"claude\s+-p|claude[-_ ]code|\bcode agent\b",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def heavy_model_regex() -> str:
|
|
59
|
+
return os.environ.get("COLONY_ESCALATION_HEAVY_RE", "")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def turn_cap() -> int:
|
|
63
|
+
try:
|
|
64
|
+
return max(500, int(os.environ.get("COLONY_MINING_TURN_CAP", "8000")))
|
|
65
|
+
except ValueError:
|
|
66
|
+
return 8000
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass
|
|
70
|
+
class MinedTurn:
|
|
71
|
+
"""One verbatim conversation exchange, banked for corpus export."""
|
|
72
|
+
|
|
73
|
+
id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
|
74
|
+
session_id: str = ""
|
|
75
|
+
contact_id: str = ""
|
|
76
|
+
channel_id: str = ""
|
|
77
|
+
user_text: str = ""
|
|
78
|
+
assistant_text: str = ""
|
|
79
|
+
summary: str = ""
|
|
80
|
+
tools_used: List[str] = field(default_factory=list)
|
|
81
|
+
model: str = ""
|
|
82
|
+
ts: float = field(default_factory=time.time)
|
|
83
|
+
|
|
84
|
+
def to_row(self) -> Dict[str, Any]:
|
|
85
|
+
return {
|
|
86
|
+
"id": self.id,
|
|
87
|
+
"session_id": self.session_id,
|
|
88
|
+
"contact_id": self.contact_id,
|
|
89
|
+
"channel_id": self.channel_id,
|
|
90
|
+
"user_text": self.user_text,
|
|
91
|
+
"assistant_text": self.assistant_text,
|
|
92
|
+
"summary": self.summary,
|
|
93
|
+
"tools_used": json.dumps(self.tools_used),
|
|
94
|
+
"model": self.model,
|
|
95
|
+
"ts": self.ts,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def from_row(cls, row: Dict[str, Any]) -> "MinedTurn":
|
|
100
|
+
return cls(
|
|
101
|
+
id=row["id"],
|
|
102
|
+
session_id=row.get("session_id") or "",
|
|
103
|
+
contact_id=row.get("contact_id") or "",
|
|
104
|
+
channel_id=row.get("channel_id") or "",
|
|
105
|
+
user_text=row.get("user_text") or "",
|
|
106
|
+
assistant_text=row.get("assistant_text") or "",
|
|
107
|
+
summary=row.get("summary") or "",
|
|
108
|
+
tools_used=json.loads(row.get("tools_used") or "[]"),
|
|
109
|
+
model=row.get("model") or "",
|
|
110
|
+
ts=float(row.get("ts") or 0.0),
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass
|
|
115
|
+
class EscalationRecord:
|
|
116
|
+
"""A turn where the agent escalated: consulted a build agent, or the
|
|
117
|
+
turn ran on a heavy/cloud model. High-value supervision material."""
|
|
118
|
+
|
|
119
|
+
id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
|
120
|
+
kind: str = "consultation" # one of ESCALATION_KINDS
|
|
121
|
+
session_id: str = ""
|
|
122
|
+
contact_id: str = ""
|
|
123
|
+
channel_id: str = ""
|
|
124
|
+
task_context: str = "" # what was being asked/attempted
|
|
125
|
+
local_attempt: str = "" # prior local answer in-session, if any
|
|
126
|
+
escalated_answer: str = "" # the answer produced with escalation
|
|
127
|
+
model: str = ""
|
|
128
|
+
matched: str = "" # which signature matched (audit)
|
|
129
|
+
outcome: str = "unknown" # unknown | followed_up
|
|
130
|
+
outcome_note: str = "" # next user message excerpt
|
|
131
|
+
distilled: int = 0 # fed to skills distillation (live mode)
|
|
132
|
+
ts: float = field(default_factory=time.time)
|
|
133
|
+
|
|
134
|
+
def to_row(self) -> Dict[str, Any]:
|
|
135
|
+
return {
|
|
136
|
+
"id": self.id,
|
|
137
|
+
"kind": self.kind,
|
|
138
|
+
"session_id": self.session_id,
|
|
139
|
+
"contact_id": self.contact_id,
|
|
140
|
+
"channel_id": self.channel_id,
|
|
141
|
+
"task_context": self.task_context,
|
|
142
|
+
"local_attempt": self.local_attempt,
|
|
143
|
+
"escalated_answer": self.escalated_answer,
|
|
144
|
+
"model": self.model,
|
|
145
|
+
"matched": self.matched,
|
|
146
|
+
"outcome": self.outcome,
|
|
147
|
+
"outcome_note": self.outcome_note,
|
|
148
|
+
"distilled": self.distilled,
|
|
149
|
+
"ts": self.ts,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@classmethod
|
|
153
|
+
def from_row(cls, row: Dict[str, Any]) -> "EscalationRecord":
|
|
154
|
+
return cls(
|
|
155
|
+
id=row["id"],
|
|
156
|
+
kind=row.get("kind") or "consultation",
|
|
157
|
+
session_id=row.get("session_id") or "",
|
|
158
|
+
contact_id=row.get("contact_id") or "",
|
|
159
|
+
channel_id=row.get("channel_id") or "",
|
|
160
|
+
task_context=row.get("task_context") or "",
|
|
161
|
+
local_attempt=row.get("local_attempt") or "",
|
|
162
|
+
escalated_answer=row.get("escalated_answer") or "",
|
|
163
|
+
model=row.get("model") or "",
|
|
164
|
+
matched=row.get("matched") or "",
|
|
165
|
+
outcome=row.get("outcome") or "unknown",
|
|
166
|
+
outcome_note=row.get("outcome_note") or "",
|
|
167
|
+
distilled=int(row.get("distilled") or 0),
|
|
168
|
+
ts=float(row.get("ts") or 0.0),
|
|
169
|
+
)
|
apsimo/mining/store.py
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""MiningStore: SQLite persistence for verbatim turns + escalation records.
|
|
2
|
+
|
|
3
|
+
The rest of the sidecar keeps salience-gated summaries (memory graph, comms
|
|
4
|
+
ledger, rolling journal); none of those is a durable verbatim corpus. This
|
|
5
|
+
store is: every accepted turn is banked verbatim (capped per side), queryable
|
|
6
|
+
by channel / contact / date range, feeding the escalation miner and the
|
|
7
|
+
training-corpus exporter. Data never leaves COLONY_STATE_DIR.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import sqlite3
|
|
12
|
+
import threading
|
|
13
|
+
import time
|
|
14
|
+
from typing import Any, List, Optional
|
|
15
|
+
|
|
16
|
+
from apsimo.mining.models import EscalationRecord, MinedTurn
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MiningStore:
|
|
20
|
+
def __init__(self, db_path: Optional[str] = None) -> None:
|
|
21
|
+
self._lock = threading.RLock()
|
|
22
|
+
self._conn = sqlite3.connect(
|
|
23
|
+
str(db_path) if db_path else ":memory:", check_same_thread=False
|
|
24
|
+
)
|
|
25
|
+
self._conn.row_factory = sqlite3.Row
|
|
26
|
+
with self._lock:
|
|
27
|
+
self._conn.execute(
|
|
28
|
+
"""CREATE TABLE IF NOT EXISTS mined_turns (
|
|
29
|
+
id TEXT PRIMARY KEY,
|
|
30
|
+
session_id TEXT,
|
|
31
|
+
contact_id TEXT,
|
|
32
|
+
channel_id TEXT,
|
|
33
|
+
user_text TEXT,
|
|
34
|
+
assistant_text TEXT,
|
|
35
|
+
summary TEXT,
|
|
36
|
+
tools_used TEXT,
|
|
37
|
+
model TEXT,
|
|
38
|
+
ts REAL
|
|
39
|
+
)"""
|
|
40
|
+
)
|
|
41
|
+
self._conn.execute(
|
|
42
|
+
"""CREATE TABLE IF NOT EXISTS escalations (
|
|
43
|
+
id TEXT PRIMARY KEY,
|
|
44
|
+
kind TEXT,
|
|
45
|
+
session_id TEXT,
|
|
46
|
+
contact_id TEXT,
|
|
47
|
+
channel_id TEXT,
|
|
48
|
+
task_context TEXT,
|
|
49
|
+
local_attempt TEXT,
|
|
50
|
+
escalated_answer TEXT,
|
|
51
|
+
model TEXT,
|
|
52
|
+
matched TEXT,
|
|
53
|
+
outcome TEXT,
|
|
54
|
+
outcome_note TEXT,
|
|
55
|
+
distilled INTEGER DEFAULT 0,
|
|
56
|
+
ts REAL
|
|
57
|
+
)"""
|
|
58
|
+
)
|
|
59
|
+
self._conn.execute(
|
|
60
|
+
"CREATE INDEX IF NOT EXISTS idx_turns_session ON mined_turns(session_id, ts)"
|
|
61
|
+
)
|
|
62
|
+
self._conn.execute(
|
|
63
|
+
"CREATE INDEX IF NOT EXISTS idx_turns_ts ON mined_turns(ts)"
|
|
64
|
+
)
|
|
65
|
+
self._conn.execute(
|
|
66
|
+
"CREATE INDEX IF NOT EXISTS idx_esc_session ON escalations(session_id, ts)"
|
|
67
|
+
)
|
|
68
|
+
self._conn.commit()
|
|
69
|
+
|
|
70
|
+
# -- turns ---------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
def add_turn(self, t: MinedTurn) -> MinedTurn:
|
|
73
|
+
row = t.to_row()
|
|
74
|
+
with self._lock:
|
|
75
|
+
cols = ", ".join(row)
|
|
76
|
+
ph = ", ".join(["?"] * len(row))
|
|
77
|
+
self._conn.execute(
|
|
78
|
+
f"INSERT OR REPLACE INTO mined_turns ({cols}) VALUES ({ph})",
|
|
79
|
+
list(row.values()),
|
|
80
|
+
)
|
|
81
|
+
self._conn.commit()
|
|
82
|
+
return t
|
|
83
|
+
|
|
84
|
+
def last_turn_in_session(self, session_id: str) -> Optional[MinedTurn]:
|
|
85
|
+
with self._lock:
|
|
86
|
+
r = self._conn.execute(
|
|
87
|
+
"SELECT * FROM mined_turns WHERE session_id=? ORDER BY ts DESC LIMIT 1",
|
|
88
|
+
(session_id,),
|
|
89
|
+
).fetchone()
|
|
90
|
+
return MinedTurn.from_row(dict(r)) if r else None
|
|
91
|
+
|
|
92
|
+
def list_turns(
|
|
93
|
+
self,
|
|
94
|
+
*,
|
|
95
|
+
contact_id: Optional[str] = None,
|
|
96
|
+
channels: Optional[List[str]] = None,
|
|
97
|
+
since_ts: Optional[float] = None,
|
|
98
|
+
until_ts: Optional[float] = None,
|
|
99
|
+
limit: int = 5000,
|
|
100
|
+
) -> List[MinedTurn]:
|
|
101
|
+
q = "SELECT * FROM mined_turns WHERE 1=1"
|
|
102
|
+
params: List[Any] = []
|
|
103
|
+
if contact_id and contact_id != "*":
|
|
104
|
+
q += " AND contact_id=?"
|
|
105
|
+
params.append(contact_id)
|
|
106
|
+
if channels:
|
|
107
|
+
q += f" AND channel_id IN ({','.join(['?'] * len(channels))})"
|
|
108
|
+
params.extend(channels)
|
|
109
|
+
if since_ts is not None:
|
|
110
|
+
q += " AND ts >= ?"
|
|
111
|
+
params.append(since_ts)
|
|
112
|
+
if until_ts is not None:
|
|
113
|
+
q += " AND ts <= ?"
|
|
114
|
+
params.append(until_ts)
|
|
115
|
+
q += " ORDER BY session_id, ts ASC LIMIT ?"
|
|
116
|
+
params.append(limit)
|
|
117
|
+
with self._lock:
|
|
118
|
+
rows = self._conn.execute(q, params).fetchall()
|
|
119
|
+
return [MinedTurn.from_row(dict(r)) for r in rows]
|
|
120
|
+
|
|
121
|
+
def turn_count(self) -> int:
|
|
122
|
+
with self._lock:
|
|
123
|
+
r = self._conn.execute("SELECT COUNT(*) AS n FROM mined_turns").fetchone()
|
|
124
|
+
return int(r["n"])
|
|
125
|
+
|
|
126
|
+
def prune_turns(self, *, retention_days: int = 0,
|
|
127
|
+
max_turns: int = 0) -> dict:
|
|
128
|
+
"""Prune banked turns by age and/or count (newest kept).
|
|
129
|
+
|
|
130
|
+
Both knobs default to 0 = keep everything: the verbatim corpus is
|
|
131
|
+
unbounded by design unless a deployment opts into retention via
|
|
132
|
+
COLONY_MINING_RETENTION_DAYS / COLONY_MINING_MAX_TURNS. Escalation
|
|
133
|
+
records are never pruned here — they are the distilled, high-value
|
|
134
|
+
output the turn bank exists to produce.
|
|
135
|
+
"""
|
|
136
|
+
deleted_by_age = deleted_by_count = 0
|
|
137
|
+
with self._lock:
|
|
138
|
+
if retention_days > 0:
|
|
139
|
+
cutoff = time.time() - retention_days * 86400
|
|
140
|
+
cur = self._conn.execute(
|
|
141
|
+
"DELETE FROM mined_turns WHERE ts < ?", (cutoff,))
|
|
142
|
+
deleted_by_age = cur.rowcount
|
|
143
|
+
if max_turns > 0:
|
|
144
|
+
cur = self._conn.execute(
|
|
145
|
+
"DELETE FROM mined_turns WHERE id NOT IN ("
|
|
146
|
+
"SELECT id FROM mined_turns ORDER BY ts DESC LIMIT ?)",
|
|
147
|
+
(max_turns,))
|
|
148
|
+
deleted_by_count = cur.rowcount
|
|
149
|
+
if deleted_by_age or deleted_by_count:
|
|
150
|
+
self._conn.commit()
|
|
151
|
+
return {"deleted_by_age": deleted_by_age,
|
|
152
|
+
"deleted_by_count": deleted_by_count,
|
|
153
|
+
"remaining": self.turn_count()}
|
|
154
|
+
|
|
155
|
+
# -- escalations -----------------------------------------------------------
|
|
156
|
+
|
|
157
|
+
def add_escalation(self, e: EscalationRecord) -> EscalationRecord:
|
|
158
|
+
row = e.to_row()
|
|
159
|
+
with self._lock:
|
|
160
|
+
cols = ", ".join(row)
|
|
161
|
+
ph = ", ".join(["?"] * len(row))
|
|
162
|
+
self._conn.execute(
|
|
163
|
+
f"INSERT OR REPLACE INTO escalations ({cols}) VALUES ({ph})",
|
|
164
|
+
list(row.values()),
|
|
165
|
+
)
|
|
166
|
+
self._conn.commit()
|
|
167
|
+
return e
|
|
168
|
+
|
|
169
|
+
def update_escalation(self, e: EscalationRecord) -> EscalationRecord:
|
|
170
|
+
return self.add_escalation(e)
|
|
171
|
+
|
|
172
|
+
def latest_open_escalation(self, session_id: str) -> Optional[EscalationRecord]:
|
|
173
|
+
with self._lock:
|
|
174
|
+
r = self._conn.execute(
|
|
175
|
+
"SELECT * FROM escalations WHERE session_id=? AND outcome='unknown' "
|
|
176
|
+
"ORDER BY ts DESC LIMIT 1",
|
|
177
|
+
(session_id,),
|
|
178
|
+
).fetchone()
|
|
179
|
+
return EscalationRecord.from_row(dict(r)) if r else None
|
|
180
|
+
|
|
181
|
+
def list_escalations(
|
|
182
|
+
self, *, kind: Optional[str] = None, limit: int = 50
|
|
183
|
+
) -> List[EscalationRecord]:
|
|
184
|
+
q = "SELECT * FROM escalations"
|
|
185
|
+
params: List[Any] = []
|
|
186
|
+
if kind:
|
|
187
|
+
q += " WHERE kind=?"
|
|
188
|
+
params.append(kind)
|
|
189
|
+
q += " ORDER BY ts DESC LIMIT ?"
|
|
190
|
+
params.append(limit)
|
|
191
|
+
with self._lock:
|
|
192
|
+
rows = self._conn.execute(q, params).fetchall()
|
|
193
|
+
return [EscalationRecord.from_row(dict(r)) for r in rows]
|
|
194
|
+
|
|
195
|
+
def escalation_stats(self) -> dict:
|
|
196
|
+
with self._lock:
|
|
197
|
+
rows = self._conn.execute(
|
|
198
|
+
"SELECT kind, outcome, COUNT(*) AS n, SUM(distilled) AS d "
|
|
199
|
+
"FROM escalations GROUP BY kind, outcome"
|
|
200
|
+
).fetchall()
|
|
201
|
+
total = self._conn.execute(
|
|
202
|
+
"SELECT COUNT(*) AS n FROM escalations"
|
|
203
|
+
).fetchone()
|
|
204
|
+
by_bucket = [
|
|
205
|
+
{"kind": r["kind"], "outcome": r["outcome"], "count": int(r["n"]),
|
|
206
|
+
"distilled": int(r["d"] or 0)}
|
|
207
|
+
for r in rows
|
|
208
|
+
]
|
|
209
|
+
return {"total": int(total["n"]), "buckets": by_bucket,
|
|
210
|
+
"turns_banked": self.turn_count()}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Colony foundation data models.
|
|
2
|
+
|
|
3
|
+
Core dataclasses for people, signals, memories, and mesh nodes.
|
|
4
|
+
These models are the shared vocabulary across all Colony subsystems.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .memory import Memory, MemoryStrength, MemoryType
|
|
8
|
+
from .mesh import MeshNode, NodeRole, NodeStatus
|
|
9
|
+
from .person import ContactInfo, ContactType, Person, RelationshipTier
|
|
10
|
+
from .signal import Signal, SignalStrength, SignalType
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
# Person & relationships
|
|
14
|
+
"Person",
|
|
15
|
+
"ContactInfo",
|
|
16
|
+
"ContactType",
|
|
17
|
+
"RelationshipTier",
|
|
18
|
+
# Behavioral signals
|
|
19
|
+
"Signal",
|
|
20
|
+
"SignalType",
|
|
21
|
+
"SignalStrength",
|
|
22
|
+
# Memory
|
|
23
|
+
"Memory",
|
|
24
|
+
"MemoryType",
|
|
25
|
+
"MemoryStrength",
|
|
26
|
+
# Mesh
|
|
27
|
+
"MeshNode",
|
|
28
|
+
"NodeRole",
|
|
29
|
+
"NodeStatus",
|
|
30
|
+
]
|
apsimo/models/memory.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Memory storage models.
|
|
2
|
+
|
|
3
|
+
Colony's memory system stores three types of knowledge:
|
|
4
|
+
- Episodic: Events and conversations (what happened)
|
|
5
|
+
- Semantic: Facts and preferences (what is known)
|
|
6
|
+
- Procedural: Workflows and processes (how to do things)
|
|
7
|
+
|
|
8
|
+
Memories support semantic search via embeddings and decay/reinforce
|
|
9
|
+
based on access patterns.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from enum import Enum
|
|
15
|
+
from typing import Any, Dict, List, Optional
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MemoryType(str, Enum):
|
|
19
|
+
"""Classification of memory content.
|
|
20
|
+
|
|
21
|
+
EPISODIC: Events, conversations, interactions
|
|
22
|
+
SEMANTIC: Facts, preferences, knowledge
|
|
23
|
+
PROCEDURAL: How-to knowledge, workflows, processes
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
EPISODIC = "episodic"
|
|
27
|
+
SEMANTIC = "semantic"
|
|
28
|
+
PROCEDURAL = "procedural"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class MemoryStrength(str, Enum):
|
|
32
|
+
"""How strongly a memory is retained.
|
|
33
|
+
|
|
34
|
+
LOW: Weak retention, score < 0.3. Candidate for decay.
|
|
35
|
+
MEDIUM: Normal retention, score 0.3-0.7.
|
|
36
|
+
HIGH: Strong retention, score > 0.7. Frequently accessed or important.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
LOW = "low"
|
|
40
|
+
MEDIUM = "medium"
|
|
41
|
+
HIGH = "high"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class Memory:
|
|
46
|
+
"""A single memory unit in Colony's long-term store.
|
|
47
|
+
|
|
48
|
+
Memories are created from interactions, observations, and explicit input.
|
|
49
|
+
They support vector similarity search via the embedding field and have
|
|
50
|
+
strength/importance scores that evolve with access patterns.
|
|
51
|
+
|
|
52
|
+
Attributes:
|
|
53
|
+
id: Unique identifier
|
|
54
|
+
type: Category of memory (episodic, semantic, procedural)
|
|
55
|
+
content: The actual memory content as text
|
|
56
|
+
person_id: Related person, if the memory is about someone specific
|
|
57
|
+
strength: Retention strength 0-1, decays without access
|
|
58
|
+
importance: How important this memory is 0-1
|
|
59
|
+
tags: Categorization tags for filtering
|
|
60
|
+
embedding: Vector embedding for semantic search
|
|
61
|
+
source: Where this memory originated (channel, file, etc.)
|
|
62
|
+
created_at: When the memory was first stored
|
|
63
|
+
last_accessed: Most recent retrieval timestamp
|
|
64
|
+
access_count: How many times this memory has been retrieved
|
|
65
|
+
metadata: Additional structured data
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
id: str
|
|
69
|
+
type: MemoryType
|
|
70
|
+
content: str
|
|
71
|
+
person_id: Optional[str] = None
|
|
72
|
+
strength: float = 0.5
|
|
73
|
+
importance: float = 0.5
|
|
74
|
+
tags: List[str] = field(default_factory=list)
|
|
75
|
+
embedding: Optional[List[float]] = None
|
|
76
|
+
source: Optional[str] = None
|
|
77
|
+
created_at: Optional[datetime] = None
|
|
78
|
+
last_accessed: Optional[datetime] = None
|
|
79
|
+
access_count: int = 0
|
|
80
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
apsimo/models/mesh.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Mesh node data models.
|
|
2
|
+
|
|
3
|
+
Colony runs as a distributed mesh where nodes take on different roles.
|
|
4
|
+
The Sovereign node is the primary brain, Regents are backup brains,
|
|
5
|
+
and Vassals are worker nodes that handle specific tasks.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from typing import Any, Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NodeRole(str, Enum):
|
|
15
|
+
"""Role a node plays in the Colony mesh.
|
|
16
|
+
|
|
17
|
+
SOVEREIGN: The queen node with full brain capabilities.
|
|
18
|
+
REGENT: Backup brain, can assume sovereignty if needed.
|
|
19
|
+
VASSAL: Worker node, handles delegated tasks.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
SOVEREIGN = "sovereign"
|
|
23
|
+
REGENT = "regent"
|
|
24
|
+
VASSAL = "vassal"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class NodeStatus(str, Enum):
|
|
28
|
+
"""Current operational status of a mesh node.
|
|
29
|
+
|
|
30
|
+
ONLINE: Node is healthy and responsive.
|
|
31
|
+
OFFLINE: Node is unreachable.
|
|
32
|
+
DEGRADED: Node is up but not fully functional.
|
|
33
|
+
SYNCING: Node is catching up on state.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
ONLINE = "online"
|
|
37
|
+
OFFLINE = "offline"
|
|
38
|
+
DEGRADED = "degraded"
|
|
39
|
+
SYNCING = "syncing"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class MeshNode:
|
|
44
|
+
"""A node in the Colony mesh network.
|
|
45
|
+
|
|
46
|
+
Each node has a role, capabilities, and resource score that determines
|
|
47
|
+
what work gets routed to it. Nodes communicate via encrypted channels
|
|
48
|
+
using their public keys.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
id: Unique node identifier
|
|
52
|
+
role: What role this node serves (sovereign, regent, vassal)
|
|
53
|
+
status: Current operational status
|
|
54
|
+
capabilities: What this node can do ("gpu", "neo4j", "llm", etc.)
|
|
55
|
+
resource_score: Relative compute power score (higher = more capable)
|
|
56
|
+
endpoint: URL for the node's API
|
|
57
|
+
public_key: Encryption key for secure mesh communication
|
|
58
|
+
last_seen: Most recent heartbeat timestamp
|
|
59
|
+
registered_at: When the node joined the mesh
|
|
60
|
+
metadata: Additional node-specific data
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
id: str
|
|
64
|
+
role: NodeRole
|
|
65
|
+
status: NodeStatus = NodeStatus.OFFLINE
|
|
66
|
+
capabilities: List[str] = field(default_factory=list)
|
|
67
|
+
resource_score: int = 0
|
|
68
|
+
endpoint: Optional[str] = None
|
|
69
|
+
public_key: Optional[bytes] = None
|
|
70
|
+
last_seen: Optional[datetime] = None
|
|
71
|
+
registered_at: Optional[datetime] = None
|
|
72
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
apsimo/models/person.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Person and relationship data models.
|
|
2
|
+
|
|
3
|
+
Core identity and relationship tracking for Colony's social graph.
|
|
4
|
+
Each person has a tier (computed from behavioral signals) and contact info
|
|
5
|
+
across multiple channels.
|
|
6
|
+
|
|
7
|
+
Two-layer model
|
|
8
|
+
---------------
|
|
9
|
+
Colony maintains two distinct layers of relationship data:
|
|
10
|
+
|
|
11
|
+
- **Colony layer** (``score``, ``tier``): Colony's own evidence-based assessment,
|
|
12
|
+
derived from interaction signals observed across connected gateways. A score
|
|
13
|
+
of 80 means Colony has observed strong, consistent engagement — not that the
|
|
14
|
+
owner designated this person as important.
|
|
15
|
+
|
|
16
|
+
- **Owner layer** (``notes``, manual tier overrides in TrustTierManager): explicit
|
|
17
|
+
guidance the owner provides to inform Colony's initial orientation. Owner input
|
|
18
|
+
carries weight but does not override Colony's evidence once sufficient history
|
|
19
|
+
exists. The ``notes`` field is an owner-layer input: free-form context the
|
|
20
|
+
owner wants Colony to keep in mind.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from dataclasses import dataclass, field
|
|
24
|
+
from datetime import datetime
|
|
25
|
+
from enum import Enum
|
|
26
|
+
from typing import List, Optional
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class RelationshipTier(str, Enum):
|
|
30
|
+
"""Relationship tier based on interaction score.
|
|
31
|
+
|
|
32
|
+
Score ranges:
|
|
33
|
+
INNER_CIRCLE: 80-100 — closest relationships
|
|
34
|
+
TRUSTED: 60-79 — reliable, frequent contact
|
|
35
|
+
REGULAR: 30-59 — normal interaction level
|
|
36
|
+
PERIPHERAL: 10-29 — infrequent or new contacts
|
|
37
|
+
SILENCED: manual — explicitly muted by user
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
INNER_CIRCLE = "inner_circle"
|
|
41
|
+
TRUSTED = "trusted"
|
|
42
|
+
REGULAR = "regular"
|
|
43
|
+
PERIPHERAL = "peripheral"
|
|
44
|
+
SILENCED = "silenced"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ContactType(str, Enum):
|
|
48
|
+
"""Supported communication channels."""
|
|
49
|
+
|
|
50
|
+
PHONE = "phone"
|
|
51
|
+
EMAIL = "email"
|
|
52
|
+
TELEGRAM = "telegram"
|
|
53
|
+
DISCORD = "discord"
|
|
54
|
+
WHATSAPP = "whatsapp"
|
|
55
|
+
SIGNAL = "signal"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class ContactInfo:
|
|
60
|
+
"""A single contact method for a person.
|
|
61
|
+
|
|
62
|
+
Attributes:
|
|
63
|
+
type: Communication channel (phone, email, etc.)
|
|
64
|
+
value: The actual contact identifier (number, address, handle)
|
|
65
|
+
label: Optional label like "personal", "work"
|
|
66
|
+
last_used: When this contact method was last used
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
type: ContactType
|
|
70
|
+
value: str
|
|
71
|
+
label: Optional[str] = None
|
|
72
|
+
last_used: Optional[datetime] = None
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass
|
|
76
|
+
class Person:
|
|
77
|
+
"""A person in Colony's social graph.
|
|
78
|
+
|
|
79
|
+
Represents anyone the Colony owner interacts with. The owner themselves
|
|
80
|
+
is represented with is_user=True.
|
|
81
|
+
|
|
82
|
+
Attributes:
|
|
83
|
+
id: Unique identifier
|
|
84
|
+
name: Display name
|
|
85
|
+
tier: Relationship tier (computed from score or manually set)
|
|
86
|
+
score: Relationship score 0-100, drives tier computation
|
|
87
|
+
aliases: Alternative names or handles
|
|
88
|
+
contacts: List of contact methods
|
|
89
|
+
first_seen: When this person first appeared in the system
|
|
90
|
+
last_interaction: Most recent interaction timestamp
|
|
91
|
+
notes: Free-form notes about the person
|
|
92
|
+
is_user: True if this represents the Colony owner
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
id: str
|
|
96
|
+
name: str
|
|
97
|
+
tier: RelationshipTier = RelationshipTier.PERIPHERAL
|
|
98
|
+
score: float = 0.0 # Colony's evidence-based assessment (0–100); not owner-assigned
|
|
99
|
+
aliases: List[str] = field(default_factory=list)
|
|
100
|
+
contacts: List[ContactInfo] = field(default_factory=list)
|
|
101
|
+
first_seen: Optional[datetime] = None
|
|
102
|
+
last_interaction: Optional[datetime] = None
|
|
103
|
+
notes: Optional[str] = None # Owner-layer input: context the owner wants Colony to know
|
|
104
|
+
is_user: bool = False
|