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
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Strict, digest-bound receipt attestation for generic Action Plane work."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import asdict, dataclass
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
import hashlib
|
|
8
|
+
import json
|
|
9
|
+
import re
|
|
10
|
+
from typing import Any, Mapping, Tuple
|
|
11
|
+
|
|
12
|
+
from apsimo.execution_results import bounded_refs
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
ACTION_RECEIPT_SCHEMA = "ActionReceiptAttestationV1"
|
|
16
|
+
ACTION_RECEIPT_VERSION = 1
|
|
17
|
+
ACTION_EFFECT_CLASSES = frozenset({"mutation", "disclosure"})
|
|
18
|
+
_SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
|
|
19
|
+
_FIELDS = frozenset({
|
|
20
|
+
"schema", "version", "job_id", "action_digest", "claim_attempt_id",
|
|
21
|
+
"effect_class", "terminal_outcome", "receipt_refs", "observed_at",
|
|
22
|
+
"summary",
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ActionReceiptError(ValueError):
|
|
27
|
+
"""The verifier supplied a malformed or unbound attestation."""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _bounded(value: object, field: str, maximum: int, *, required=True) -> str:
|
|
31
|
+
text = str(value or "").strip()
|
|
32
|
+
if (required and not text) or len(text) > maximum:
|
|
33
|
+
qualifier = f"1..{maximum}" if required else f"0..{maximum}"
|
|
34
|
+
raise ActionReceiptError(f"{field} must be {qualifier} characters")
|
|
35
|
+
return text
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class ActionReceiptAttestationV1:
|
|
40
|
+
"""One verifier assertion bound to an exact action and claim attempt."""
|
|
41
|
+
|
|
42
|
+
job_id: str
|
|
43
|
+
action_digest: str
|
|
44
|
+
claim_attempt_id: str
|
|
45
|
+
effect_class: str
|
|
46
|
+
terminal_outcome: str
|
|
47
|
+
receipt_refs: Tuple[str, ...]
|
|
48
|
+
observed_at: str
|
|
49
|
+
summary: str = ""
|
|
50
|
+
schema: str = ACTION_RECEIPT_SCHEMA
|
|
51
|
+
version: int = ACTION_RECEIPT_VERSION
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def from_payload(cls, value: object) -> "ActionReceiptAttestationV1":
|
|
55
|
+
if not isinstance(value, Mapping):
|
|
56
|
+
raise ActionReceiptError("action receipt must be an object")
|
|
57
|
+
raw = dict(value)
|
|
58
|
+
unknown = set(raw) - _FIELDS
|
|
59
|
+
missing = _FIELDS - set(raw)
|
|
60
|
+
if unknown or missing:
|
|
61
|
+
raise ActionReceiptError(
|
|
62
|
+
"action receipt fields do not match V1 contract"
|
|
63
|
+
)
|
|
64
|
+
if raw.get("schema") != ACTION_RECEIPT_SCHEMA:
|
|
65
|
+
raise ActionReceiptError("action receipt schema is unsupported")
|
|
66
|
+
if (
|
|
67
|
+
type(raw.get("version")) is not int
|
|
68
|
+
or raw["version"] != ACTION_RECEIPT_VERSION
|
|
69
|
+
):
|
|
70
|
+
raise ActionReceiptError("action receipt version is unsupported")
|
|
71
|
+
for field in (
|
|
72
|
+
"job_id", "action_digest", "claim_attempt_id", "effect_class",
|
|
73
|
+
"terminal_outcome", "observed_at", "summary",
|
|
74
|
+
):
|
|
75
|
+
if type(raw.get(field)) is not str:
|
|
76
|
+
raise ActionReceiptError(
|
|
77
|
+
f"action receipt {field} must be a string"
|
|
78
|
+
)
|
|
79
|
+
digest = str(raw.get("action_digest") or "").strip().lower()
|
|
80
|
+
if not _SHA256_RE.fullmatch(digest) or set(digest) == {"0"}:
|
|
81
|
+
raise ActionReceiptError(
|
|
82
|
+
"action_digest must be a non-null lowercase SHA-256"
|
|
83
|
+
)
|
|
84
|
+
effect_class = str(raw.get("effect_class") or "").strip().lower()
|
|
85
|
+
if effect_class not in ACTION_EFFECT_CLASSES:
|
|
86
|
+
raise ActionReceiptError(
|
|
87
|
+
"effect_class must be mutation or disclosure"
|
|
88
|
+
)
|
|
89
|
+
if raw.get("terminal_outcome") != "succeeded":
|
|
90
|
+
raise ActionReceiptError(
|
|
91
|
+
"success attestation terminal_outcome must be succeeded"
|
|
92
|
+
)
|
|
93
|
+
try:
|
|
94
|
+
observed = datetime.fromisoformat(
|
|
95
|
+
str(raw.get("observed_at") or "").replace("Z", "+00:00")
|
|
96
|
+
)
|
|
97
|
+
except ValueError as exc:
|
|
98
|
+
raise ActionReceiptError(
|
|
99
|
+
"observed_at must be an ISO-8601 timestamp"
|
|
100
|
+
) from exc
|
|
101
|
+
if observed.tzinfo is None:
|
|
102
|
+
raise ActionReceiptError("observed_at must include a timezone")
|
|
103
|
+
refs = bounded_refs(raw.get("receipt_refs"))
|
|
104
|
+
if not refs:
|
|
105
|
+
raise ActionReceiptError(
|
|
106
|
+
"verified action effect requires a receipt reference"
|
|
107
|
+
)
|
|
108
|
+
return cls(
|
|
109
|
+
job_id=_bounded(raw.get("job_id"), "job_id", 128),
|
|
110
|
+
action_digest=digest,
|
|
111
|
+
claim_attempt_id=_bounded(
|
|
112
|
+
raw.get("claim_attempt_id"), "claim_attempt_id", 128,
|
|
113
|
+
),
|
|
114
|
+
effect_class=effect_class,
|
|
115
|
+
terminal_outcome="succeeded",
|
|
116
|
+
receipt_refs=refs,
|
|
117
|
+
observed_at=observed.astimezone(timezone.utc).isoformat(),
|
|
118
|
+
summary=_bounded(
|
|
119
|
+
raw.get("summary"), "summary", 500, required=False,
|
|
120
|
+
),
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
def payload(self) -> dict[str, Any]:
|
|
124
|
+
payload = asdict(self)
|
|
125
|
+
payload["receipt_refs"] = list(self.receipt_refs)
|
|
126
|
+
return payload
|
|
127
|
+
|
|
128
|
+
def evidence_sha256(
|
|
129
|
+
self,
|
|
130
|
+
*,
|
|
131
|
+
verifier_identity: str,
|
|
132
|
+
verifier_type: str,
|
|
133
|
+
) -> str:
|
|
134
|
+
"""Digest the canonical assertion plus server-derived authority."""
|
|
135
|
+
|
|
136
|
+
document = {
|
|
137
|
+
**self.payload(),
|
|
138
|
+
"verifier_identity": _bounded(
|
|
139
|
+
verifier_identity, "verifier_identity", 256,
|
|
140
|
+
),
|
|
141
|
+
"verifier_type": _bounded(verifier_type, "verifier_type", 128),
|
|
142
|
+
}
|
|
143
|
+
return hashlib.sha256(json.dumps(
|
|
144
|
+
document,
|
|
145
|
+
sort_keys=True,
|
|
146
|
+
separators=(",", ":"),
|
|
147
|
+
ensure_ascii=True,
|
|
148
|
+
).encode("utf-8")).hexdigest()
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Server-owned, permanently inert approval-relay calibration job.
|
|
2
|
+
|
|
3
|
+
The canary exists only to prove Colony -> host owner transport -> Colony
|
|
4
|
+
decision relay before generic effects are enabled. It deliberately uses the
|
|
5
|
+
normal canonical approval ledger while having no executable terminal path.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import hashlib
|
|
11
|
+
import hmac
|
|
12
|
+
import re
|
|
13
|
+
from typing import Any, Mapping
|
|
14
|
+
|
|
15
|
+
from apsimo.task_queue.models import Job, JobPriority, JobStatus, JobType
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
SCHEMA = "ApprovalRelayCanaryV1"
|
|
19
|
+
VERSION = 1
|
|
20
|
+
ACTION_HINT = "approval_relay_canary"
|
|
21
|
+
JOB_ID_PREFIX = "approval-relay-canary:"
|
|
22
|
+
POSTED_BY = "colony:approval-relay-canary"
|
|
23
|
+
TERMINAL_POLICY = "record_decision_then_cancel_without_execution"
|
|
24
|
+
APPROVAL_TTL_SECONDS = 60 * 60
|
|
25
|
+
_SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def idempotency_digest(value: str) -> str:
|
|
29
|
+
"""Hash one bounded opaque token so caller material is never persisted."""
|
|
30
|
+
|
|
31
|
+
if not isinstance(value, str) or value != value.strip():
|
|
32
|
+
raise ValueError("approval relay canary idempotency key is invalid")
|
|
33
|
+
if not 16 <= len(value) <= 128 or any(character.isspace() for character in value):
|
|
34
|
+
raise ValueError("approval relay canary idempotency key is invalid")
|
|
35
|
+
return hashlib.sha256(value.encode("utf-8")).hexdigest()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def job_id_for_digest(digest: str) -> str:
|
|
39
|
+
if not isinstance(digest, str) or not _SHA256.fullmatch(digest):
|
|
40
|
+
raise ValueError("approval relay canary idempotency digest is invalid")
|
|
41
|
+
return JOB_ID_PREFIX + digest
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def payload_for_digest(digest: str) -> dict[str, Any]:
|
|
45
|
+
job_id_for_digest(digest)
|
|
46
|
+
return {
|
|
47
|
+
"schema": SCHEMA,
|
|
48
|
+
"version": VERSION,
|
|
49
|
+
"action_hint": ACTION_HINT,
|
|
50
|
+
"risk": "mutating",
|
|
51
|
+
"description": (
|
|
52
|
+
"Approval relay calibration only. No tool, worker, external "
|
|
53
|
+
"write, or outbound action will run for either decision."
|
|
54
|
+
),
|
|
55
|
+
"external_effect": False,
|
|
56
|
+
"reversible": True,
|
|
57
|
+
"terminal_policy": TERMINAL_POLICY,
|
|
58
|
+
"idempotency_digest": digest,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def build_job(digest: str) -> Job:
|
|
63
|
+
"""Build the only queue object accepted as this reserved canary."""
|
|
64
|
+
|
|
65
|
+
return Job(
|
|
66
|
+
job_id=job_id_for_digest(digest),
|
|
67
|
+
job_type=JobType.AGENT_ACTION,
|
|
68
|
+
payload=payload_for_digest(digest),
|
|
69
|
+
priority=JobPriority.NORMAL,
|
|
70
|
+
max_retries=0,
|
|
71
|
+
timeout_secs=60.0,
|
|
72
|
+
posted_by=POSTED_BY,
|
|
73
|
+
status=JobStatus.BLOCKED,
|
|
74
|
+
tags={
|
|
75
|
+
"hold_kind": "approval",
|
|
76
|
+
"blocked_reason": "awaiting_owner_approval",
|
|
77
|
+
"awaiting_owner_approval": "true",
|
|
78
|
+
"approval_relay_canary": "true",
|
|
79
|
+
"external_effect": "false",
|
|
80
|
+
"terminal_policy": TERMINAL_POLICY,
|
|
81
|
+
},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def is_exact_job(job: Job) -> bool:
|
|
86
|
+
"""Recognize only the complete server-derived object, never loose tags."""
|
|
87
|
+
|
|
88
|
+
payload: Mapping[str, Any] = job.payload if isinstance(job.payload, Mapping) else {}
|
|
89
|
+
digest = payload.get("idempotency_digest")
|
|
90
|
+
if not isinstance(digest, str) or not _SHA256.fullmatch(digest):
|
|
91
|
+
return False
|
|
92
|
+
expected_payload = payload_for_digest(digest)
|
|
93
|
+
return bool(
|
|
94
|
+
job.job_type is JobType.AGENT_ACTION
|
|
95
|
+
and hmac.compare_digest(job.job_id, job_id_for_digest(digest))
|
|
96
|
+
and job.posted_by == POSTED_BY
|
|
97
|
+
and job.max_retries == 0
|
|
98
|
+
and float(job.timeout_secs) == 60.0
|
|
99
|
+
and dict(payload) == expected_payload
|
|
100
|
+
and job.tags.get("approval_relay_canary") == "true"
|
|
101
|
+
and job.tags.get("external_effect") == "false"
|
|
102
|
+
and job.tags.get("terminal_policy") == TERMINAL_POLICY
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def assert_exact_job(job: Job) -> None:
|
|
107
|
+
if not is_exact_job(job):
|
|
108
|
+
raise ValueError("approval relay canary identity or inert contract drifted")
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Configuration for the Colony distributed task queue."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
import math
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
DEFAULT_WORKER_HEARTBEAT_TTL_SECS = 60.0
|
|
11
|
+
MIN_WORKER_HEARTBEAT_TTL_SECS = 1.0
|
|
12
|
+
MAX_WORKER_HEARTBEAT_TTL_SECS = 3600.0
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def validate_worker_heartbeat_ttl(value: object) -> float:
|
|
16
|
+
"""Return the one bounded worker-liveness TTL used by queue consumers."""
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
parsed = float(value)
|
|
20
|
+
except (TypeError, ValueError) as exc:
|
|
21
|
+
raise ValueError(
|
|
22
|
+
"worker_heartbeat_ttl_secs must be between "
|
|
23
|
+
f"{MIN_WORKER_HEARTBEAT_TTL_SECS:g} and "
|
|
24
|
+
f"{MAX_WORKER_HEARTBEAT_TTL_SECS:g}"
|
|
25
|
+
) from exc
|
|
26
|
+
if (
|
|
27
|
+
not math.isfinite(parsed)
|
|
28
|
+
or parsed < MIN_WORKER_HEARTBEAT_TTL_SECS
|
|
29
|
+
or parsed > MAX_WORKER_HEARTBEAT_TTL_SECS
|
|
30
|
+
):
|
|
31
|
+
raise ValueError(
|
|
32
|
+
"worker_heartbeat_ttl_secs must be between "
|
|
33
|
+
f"{MIN_WORKER_HEARTBEAT_TTL_SECS:g} and "
|
|
34
|
+
f"{MAX_WORKER_HEARTBEAT_TTL_SECS:g}"
|
|
35
|
+
)
|
|
36
|
+
return parsed
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class TaskQueueConfig:
|
|
41
|
+
"""Configuration for the distributed task queue.
|
|
42
|
+
|
|
43
|
+
All timeouts are in seconds unless otherwise stated.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
# Storage
|
|
47
|
+
db_path: Path = field(default_factory=lambda: Path("~/.colony/task_queue.db"))
|
|
48
|
+
|
|
49
|
+
# Scheduling
|
|
50
|
+
scheduler_tick_secs: float = 2.0
|
|
51
|
+
"""How often the scheduler runs its assignment loop."""
|
|
52
|
+
|
|
53
|
+
# Worker health
|
|
54
|
+
heartbeat_interval_secs: float = 15.0
|
|
55
|
+
"""How often workers send heartbeats."""
|
|
56
|
+
|
|
57
|
+
heartbeat_timeout_secs: float = DEFAULT_WORKER_HEARTBEAT_TTL_SECS
|
|
58
|
+
"""Time after which a silent worker's jobs are abandoned."""
|
|
59
|
+
|
|
60
|
+
claim_timeout_secs: float = 30.0
|
|
61
|
+
"""Time after which a CLAIMED but not yet RUNNING job is re-queued."""
|
|
62
|
+
|
|
63
|
+
# Deadlines
|
|
64
|
+
no_worker_warning_secs: float = 300.0
|
|
65
|
+
"""Emit warning when a job with a deadline within this window has no eligible worker."""
|
|
66
|
+
|
|
67
|
+
# Retries
|
|
68
|
+
default_max_retries: int = 3
|
|
69
|
+
"""Default retry limit for jobs that do not specify one."""
|
|
70
|
+
|
|
71
|
+
# History retention
|
|
72
|
+
completed_job_retention_days: int = 30
|
|
73
|
+
failed_job_retention_days: int = 7
|
|
74
|
+
|
|
75
|
+
# Capacity
|
|
76
|
+
default_worker_max_concurrent: int = 4
|
|
77
|
+
"""Default maximum concurrent jobs per worker if not specified."""
|
|
78
|
+
|
|
79
|
+
# Regent sync
|
|
80
|
+
regent_sync_interval_secs: float = 5.0
|
|
81
|
+
"""How often the Regent syncs queue state from the Sovereign."""
|
|
82
|
+
|
|
83
|
+
def resolved_db_path(self) -> Path:
|
|
84
|
+
"""Return the db_path with ~ expanded."""
|
|
85
|
+
return Path(self.db_path).expanduser()
|