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,1949 @@
|
|
|
1
|
+
"""Host API schemas — Pydantic models for the /v1/host surface.
|
|
2
|
+
|
|
3
|
+
Mirrors the TypeScript types in colony's src/types.ts.
|
|
4
|
+
The sidecar is the source of truth for these schemas.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os as _os
|
|
10
|
+
from typing import Any, Dict, List, Literal, Optional, Union
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
13
|
+
|
|
14
|
+
from apsimo.gate.communication_policy import CommunicationPolicyContextV1
|
|
15
|
+
from apsimo.gate.surface_policy import ResponseGuardSurfaceName
|
|
16
|
+
|
|
17
|
+
MAX_NAME_LEN = 256
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# --- Identity ---------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
class HostIdentity(BaseModel):
|
|
23
|
+
host_id: str
|
|
24
|
+
host_version: Optional[str] = None
|
|
25
|
+
plugin_version: Optional[str] = None
|
|
26
|
+
instance_id: Optional[str] = None
|
|
27
|
+
colony_id: Optional[str] = None
|
|
28
|
+
node_id: Optional[str] = None
|
|
29
|
+
node_cert_fingerprint: Optional[str] = None
|
|
30
|
+
trust_tier: Optional[Literal["REGULAR", "TRUSTED", "PRIVILEGED", "GENESIS"]] = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class HostTurnContext(BaseModel):
|
|
34
|
+
session_id: str
|
|
35
|
+
contact_id: str
|
|
36
|
+
channel_id: Optional[str] = None
|
|
37
|
+
turn_id: Optional[str] = None
|
|
38
|
+
locale: Optional[str] = None
|
|
39
|
+
timezone: Optional[str] = None # per-communication tz override (v0.21.0)
|
|
40
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# --- Messages ---------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
class HostMessage(BaseModel):
|
|
46
|
+
role: Literal["user", "assistant", "system", "tool"]
|
|
47
|
+
content: str
|
|
48
|
+
name: Optional[str] = None
|
|
49
|
+
tool_call_id: Optional[str] = None
|
|
50
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# --- Health -----------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
class TemporalMetrics(BaseModel):
|
|
56
|
+
started_at: Optional[str] = None
|
|
57
|
+
last_sync_at: Optional[str] = None
|
|
58
|
+
last_tick_at: Optional[str] = None
|
|
59
|
+
last_initiative_at: Optional[str] = None
|
|
60
|
+
last_prefetch_at: Optional[str] = None
|
|
61
|
+
silence_hours: Dict[str, Optional[float]] = Field(default_factory=dict)
|
|
62
|
+
stale_flags: List[str] = Field(default_factory=list)
|
|
63
|
+
#: "ok" normally; "unknown" when persisted telemetry could not be restored
|
|
64
|
+
state: Optional[str] = None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class HostHealthResponse(BaseModel):
|
|
68
|
+
status: Literal["ok", "degraded", "starting", "stopping"]
|
|
69
|
+
api_version: str = "1.0.0"
|
|
70
|
+
capabilities: List[str] = []
|
|
71
|
+
notes: Optional[Dict[str, str]] = None
|
|
72
|
+
temporal: Optional[TemporalMetrics] = None
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# --- Memory -----------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
class MemoryEntry(BaseModel):
|
|
78
|
+
id: str
|
|
79
|
+
content: str
|
|
80
|
+
type: Optional[str] = None
|
|
81
|
+
strength: Optional[float] = None
|
|
82
|
+
effective_confidence: Optional[float] = None
|
|
83
|
+
epistemic_state: Optional[str] = None
|
|
84
|
+
source_type: Optional[str] = None
|
|
85
|
+
source_uri: Optional[str] = None
|
|
86
|
+
source_version: Optional[str] = None
|
|
87
|
+
content_hash: Optional[str] = None
|
|
88
|
+
protected: Optional[bool] = None
|
|
89
|
+
person_id: Optional[str] = None
|
|
90
|
+
entities: Optional[List[str]] = None
|
|
91
|
+
tags: Optional[List[str]] = None
|
|
92
|
+
created_at: Optional[str] = None
|
|
93
|
+
score: Optional[float] = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class MemoryReadRequest(BaseModel):
|
|
97
|
+
identity: HostIdentity
|
|
98
|
+
memory_id: Optional[str] = None
|
|
99
|
+
person_id: Optional[str] = None
|
|
100
|
+
audience: Optional[Literal["viewer", "owner", "shared", "global"]] = None
|
|
101
|
+
limit: Optional[int] = None
|
|
102
|
+
source_id: Optional[str] = Field(default=None, min_length=1, max_length=256)
|
|
103
|
+
source_version: Optional[str] = Field(default=None, pattern='^[0-9a-f]{64}$')
|
|
104
|
+
session_id: Optional[str] = Field(default=None, min_length=1, max_length=256)
|
|
105
|
+
source_view: Literal['source', 'assertions', 'image', 'document', 'video'] = 'source'
|
|
106
|
+
asset_hash: Optional[str] = Field(default=None, pattern='^[0-9a-f]{64}$')
|
|
107
|
+
page: Optional[int] = Field(default=None, ge=1, strict=True)
|
|
108
|
+
requested_ms: Optional[int] = Field(default=None, ge=0, le=30000, strict=True)
|
|
109
|
+
claim_id: Optional[str] = Field(default=None, min_length=1, max_length=256)
|
|
110
|
+
offset: int = Field(default=0, ge=0, le=10000000)
|
|
111
|
+
read_revision: Optional[str] = Field(default=None, pattern='^[0-9a-f]{64}$')
|
|
112
|
+
|
|
113
|
+
@model_validator(mode='after')
|
|
114
|
+
def canonical_read_selector(self):
|
|
115
|
+
if self.source_id:
|
|
116
|
+
if not self.source_version or not self.session_id or self.memory_id:
|
|
117
|
+
raise ValueError('canonical reads require source version/session and no graph memory ID')
|
|
118
|
+
if (self.source_view == 'assertions') != bool(self.claim_id):
|
|
119
|
+
raise ValueError('assertion history requires its source claim ID')
|
|
120
|
+
if (self.source_view in {'image', 'document', 'video'}) != bool(self.asset_hash):
|
|
121
|
+
raise ValueError('image, document and video reads require an exact asset hash')
|
|
122
|
+
if self.source_view in {'image', 'video'} and self.offset:
|
|
123
|
+
raise ValueError('image and video reads take no page offset')
|
|
124
|
+
if (self.source_view == 'video') != (self.requested_ms is not None):
|
|
125
|
+
raise ValueError('video reads require a clip-relative requested_ms')
|
|
126
|
+
if (self.source_view == 'document') != (self.page is not None):
|
|
127
|
+
raise ValueError('document reads require an original page number')
|
|
128
|
+
if self.offset and not self.read_revision:
|
|
129
|
+
raise ValueError('continuation requires the preceding read revision')
|
|
130
|
+
elif self.source_version or self.claim_id or self.asset_hash or self.page is not None or self.requested_ms is not None or self.offset or self.read_revision or self.source_view != 'source':
|
|
131
|
+
raise ValueError('canonical read fields require a source ID')
|
|
132
|
+
return self
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class MemoryReadResponse(BaseModel):
|
|
136
|
+
entries: List[MemoryEntry] = []
|
|
137
|
+
source: Optional[Dict[str, Any]] = None
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class MemoryWriteRequest(BaseModel):
|
|
141
|
+
identity: HostIdentity
|
|
142
|
+
context: Optional[HostTurnContext] = None
|
|
143
|
+
content: str
|
|
144
|
+
type: Optional[str] = None
|
|
145
|
+
person_id: Optional[str] = None
|
|
146
|
+
audience: Optional[Literal["viewer", "owner", "shared", "global"]] = None
|
|
147
|
+
entities: Optional[List[str]] = None
|
|
148
|
+
tags: Optional[List[str]] = None
|
|
149
|
+
strength: Optional[float] = None
|
|
150
|
+
source_type: Optional[str] = "inference"
|
|
151
|
+
source_uri: Optional[str] = None
|
|
152
|
+
source_version: Optional[str] = None
|
|
153
|
+
content_hash: Optional[str] = None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class MemoryWriteResponse(BaseModel):
|
|
157
|
+
id: str
|
|
158
|
+
accepted: bool
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class MemorySearchRequest(BaseModel):
|
|
162
|
+
identity: HostIdentity
|
|
163
|
+
query: str
|
|
164
|
+
limit: Optional[int] = None
|
|
165
|
+
min_score: Optional[float] = None
|
|
166
|
+
min_confidence: Optional[float] = 0.1
|
|
167
|
+
person_id: Optional[str] = None
|
|
168
|
+
audience: Optional[Literal["viewer", "owner", "shared", "global"]] = None
|
|
169
|
+
types: Optional[List[str]] = None
|
|
170
|
+
tags: Optional[List[str]] = None
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class RerankRequest(BaseModel):
|
|
174
|
+
identity: HostIdentity
|
|
175
|
+
query: str
|
|
176
|
+
documents: List[str]
|
|
177
|
+
top_k: Optional[int] = 10
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class RerankResult(BaseModel):
|
|
181
|
+
index: int
|
|
182
|
+
score: float
|
|
183
|
+
text: str
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class RerankResponse(BaseModel):
|
|
187
|
+
results: List[RerankResult] = []
|
|
188
|
+
model: str = ""
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class MemorySearchResponse(BaseModel):
|
|
192
|
+
entries: List[MemoryEntry] = []
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class MemoryReconcileRequest(BaseModel):
|
|
196
|
+
identity: HostIdentity
|
|
197
|
+
dry_run: Optional[bool] = False
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class MemoryReconcileResponse(BaseModel):
|
|
201
|
+
files_checked: int = 0
|
|
202
|
+
memories_verified: int = 0
|
|
203
|
+
memories_staled: int = 0
|
|
204
|
+
memories_superseded: int = 0
|
|
205
|
+
errors: List[str] = []
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class MemoryConflictEntry(BaseModel):
|
|
209
|
+
memory_id_a: str
|
|
210
|
+
memory_id_b: str
|
|
211
|
+
entity_name: str
|
|
212
|
+
reason: str
|
|
213
|
+
detected_at: Optional[str] = None
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class MemoryConflictsResponse(BaseModel):
|
|
217
|
+
conflicts: List[MemoryConflictEntry] = []
|
|
218
|
+
total: int = 0
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class MemoryVerifyRequest(BaseModel):
|
|
222
|
+
identity: HostIdentity
|
|
223
|
+
memory_id: str
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class MemoryVerifyResponse(BaseModel):
|
|
227
|
+
memory_id: str
|
|
228
|
+
verified: bool
|
|
229
|
+
effective_confidence: float = 0.0
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class MemoryStatsResponse(BaseModel):
|
|
233
|
+
by_state: Dict[str, int] = Field(default_factory=dict)
|
|
234
|
+
by_source: Dict[str, int] = Field(default_factory=dict)
|
|
235
|
+
total_active: int = 0
|
|
236
|
+
total_archived: int = 0
|
|
237
|
+
protected_count: int = 0
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# --- Context ----------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
class ContextAssembleRequest(BaseModel):
|
|
243
|
+
identity: HostIdentity
|
|
244
|
+
context: HostTurnContext
|
|
245
|
+
audience: Optional[Literal["viewer", "owner", "shared", "global"]] = None
|
|
246
|
+
incoming_message: HostMessage
|
|
247
|
+
available_tools: Optional[List[str]] = None
|
|
248
|
+
citations_mode: Optional[Literal["off", "inline", "appendix"]] = None
|
|
249
|
+
include_initiatives: Optional[bool] = None # v0.13.0
|
|
250
|
+
projection_policy: Optional[
|
|
251
|
+
Literal["scoped_viewer_required"]
|
|
252
|
+
] = None
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class ContextSection(BaseModel):
|
|
256
|
+
id: str
|
|
257
|
+
title: Optional[str] = None
|
|
258
|
+
body: str
|
|
259
|
+
priority: Optional[int] = None
|
|
260
|
+
citations: Optional[List[Dict[str, Any]]] = None
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class ContextProjectionAttestation(BaseModel):
|
|
264
|
+
"""Server-sealed viewer/projection posture for one context response."""
|
|
265
|
+
|
|
266
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
267
|
+
schema_name: Literal["ContextProjectionAttestationV1"] = Field(
|
|
268
|
+
default="ContextProjectionAttestationV1",
|
|
269
|
+
alias="schema",
|
|
270
|
+
)
|
|
271
|
+
version: Literal[1] = 1
|
|
272
|
+
viewer_person_id: str = ""
|
|
273
|
+
viewer_attested: bool = False
|
|
274
|
+
viewer_is_owner: bool = False
|
|
275
|
+
p8_mode: Literal["off", "shadow", "live"] = "off"
|
|
276
|
+
projection_backend: Literal["unavailable", "p8", "canonical_sources"] = "unavailable"
|
|
277
|
+
scoped_projection_ready: bool = False
|
|
278
|
+
legacy_global_allowed: bool = False
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class ContextAssembleResponse(BaseModel):
|
|
282
|
+
sections: List[ContextSection] = []
|
|
283
|
+
notices: Optional[List[str]] = None
|
|
284
|
+
projection_attestation: Optional[ContextProjectionAttestation] = None
|
|
285
|
+
source_erasure_watermark: Optional[int] = None
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class MemoryFlushRequest(BaseModel):
|
|
289
|
+
identity: HostIdentity
|
|
290
|
+
reason: Optional[str] = None
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class MemoryFlushResponse(BaseModel):
|
|
294
|
+
accepted: bool
|
|
295
|
+
job_id: Optional[str] = None
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
class MemoryEmbedRequest(BaseModel):
|
|
299
|
+
identity: HostIdentity
|
|
300
|
+
inputs: List[str] # Kept for backward compat — use texts instead
|
|
301
|
+
texts: Optional[List[str]] = None # Preferred: list of texts to embed
|
|
302
|
+
model: Optional[str] = None
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class MemoryEmbedResponse(BaseModel):
|
|
306
|
+
model: str
|
|
307
|
+
vectors: List[List[float]]
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class EmbedHealthResponse(BaseModel):
|
|
311
|
+
provider: str = ""
|
|
312
|
+
model: str = ""
|
|
313
|
+
dims: int = 0
|
|
314
|
+
latency_ms: float = 0.0
|
|
315
|
+
status: str = "unknown"
|
|
316
|
+
error: Optional[str] = None
|
|
317
|
+
modalities: List[str] = ["text"]
|
|
318
|
+
multimodal_enabled: bool = False
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
class BackfillRequest(BaseModel):
|
|
322
|
+
identity: HostIdentity
|
|
323
|
+
collection: Optional[str] = None
|
|
324
|
+
batch_size: int = 64
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
class BackfillResponse(BaseModel):
|
|
328
|
+
task_id: str = ""
|
|
329
|
+
status: str = "started" # started | completed | failed
|
|
330
|
+
total: int = 0
|
|
331
|
+
processed: int = 0
|
|
332
|
+
failed: int = 0
|
|
333
|
+
skipped: int = 0
|
|
334
|
+
duration_s: float = 0.0
|
|
335
|
+
errors: List[str] = []
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
class MigrateRequest(BaseModel):
|
|
339
|
+
identity: HostIdentity
|
|
340
|
+
old_model_id: Optional[str] = None
|
|
341
|
+
batch_size: int = 64
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class MigrateResponse(BaseModel):
|
|
345
|
+
task_id: str = ""
|
|
346
|
+
status: str = "started" # started | completed | failed
|
|
347
|
+
collections_migrated: int = 0
|
|
348
|
+
vectors_migrated: int = 0
|
|
349
|
+
vectors_failed: int = 0
|
|
350
|
+
duration_s: float = 0.0
|
|
351
|
+
errors: List[str] = []
|
|
352
|
+
generation_id: str = ""
|
|
353
|
+
fingerprint: str = ""
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
class IndexRequest(BaseModel):
|
|
357
|
+
identity: HostIdentity
|
|
358
|
+
items: List[dict] # [{text, collection, id, metadata?}] or [{image, mime_type, caption, collection, id}]
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class IndexResponse(BaseModel):
|
|
362
|
+
indexed: int = 0
|
|
363
|
+
failed: int = 0
|
|
364
|
+
model: str = ""
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
class ImageEmbedRequest(BaseModel):
|
|
368
|
+
identity: HostIdentity
|
|
369
|
+
image: Optional[str] = None # Base64-encoded image
|
|
370
|
+
image_url: Optional[str] = None # URL to image
|
|
371
|
+
image_path: Optional[str] = None # Local file path
|
|
372
|
+
mime_type: Optional[str] = None
|
|
373
|
+
caption: Optional[str] = None
|
|
374
|
+
collection: Optional[str] = None
|
|
375
|
+
id: Optional[str] = None
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class ImageEmbedResponse(BaseModel):
|
|
379
|
+
model: str
|
|
380
|
+
vector: List[float]
|
|
381
|
+
image_hash: str = ""
|
|
382
|
+
image_ref: str = ""
|
|
383
|
+
thumbnail_ref: str = ""
|
|
384
|
+
caption: str = ""
|
|
385
|
+
width: int = 0
|
|
386
|
+
height: int = 0
|
|
387
|
+
modality: str = "image"
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
class ImageBatchEmbedRequest(BaseModel):
|
|
391
|
+
identity: HostIdentity
|
|
392
|
+
images: List[dict] # [{image, image_url, image_path, mime_type, caption}]
|
|
393
|
+
collection: Optional[str] = None
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
class ImageBatchEmbedResponse(BaseModel):
|
|
397
|
+
model: str
|
|
398
|
+
results: List[dict] # [{vector, image_hash, caption, ...}]
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
class MultimodalSearchRequest(BaseModel):
|
|
402
|
+
identity: HostIdentity
|
|
403
|
+
query: Optional[str] = None # Text query
|
|
404
|
+
query_image: Optional[str] = None # Base64 image for image-based search
|
|
405
|
+
collection: Optional[str] = None
|
|
406
|
+
filter_modality: Optional[str] = None # "text" or "image"
|
|
407
|
+
limit: int = 10
|
|
408
|
+
min_score: float = 0.0
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
class MultimodalSearchResponse(BaseModel):
|
|
412
|
+
results: List[dict]
|
|
413
|
+
model: str = ""
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
# --- Reasoning --------------------------------------------------------------
|
|
417
|
+
|
|
418
|
+
class ReasoningTurnRequest(BaseModel):
|
|
419
|
+
identity: HostIdentity
|
|
420
|
+
context: HostTurnContext
|
|
421
|
+
messages: List[HostMessage]
|
|
422
|
+
available_tools: List[str] = Field(default_factory=list)
|
|
423
|
+
model_override: Optional[str] = Field(None, max_length=MAX_NAME_LEN)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
class ReasoningToolCall(BaseModel):
|
|
427
|
+
id: str
|
|
428
|
+
name: str
|
|
429
|
+
arguments: Dict[str, Any] = Field(default_factory=dict)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
class ReasoningTurnResponse(BaseModel):
|
|
433
|
+
status: Literal["completed", "needs_tool", "error"]
|
|
434
|
+
message: Optional[HostMessage] = None
|
|
435
|
+
tool_calls: List[ReasoningToolCall] = Field(default_factory=list)
|
|
436
|
+
usage: Dict[str, Any] = Field(default_factory=dict)
|
|
437
|
+
error: Optional[str] = None
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
class ToolInvokeRequest(BaseModel):
|
|
441
|
+
identity: HostIdentity
|
|
442
|
+
name: str = Field(..., max_length=MAX_NAME_LEN)
|
|
443
|
+
arguments: Dict[str, Any] = Field(default_factory=dict)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
class ToolInvokeResponse(BaseModel):
|
|
447
|
+
result: str = ""
|
|
448
|
+
available: bool = True
|
|
449
|
+
error: Optional[str] = None
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
class SkillExecuteRequest(BaseModel):
|
|
453
|
+
identity: HostIdentity
|
|
454
|
+
arguments: Dict[str, Any] = Field(default_factory=dict)
|
|
455
|
+
context: Optional[HostTurnContext] = None
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
class SkillExecuteResponse(BaseModel):
|
|
459
|
+
status: Literal["success", "failed", "timeout", "violated"]
|
|
460
|
+
output: Optional[Any] = None
|
|
461
|
+
error: Optional[str] = None
|
|
462
|
+
execution_id: Optional[str] = None
|
|
463
|
+
duration_ms: Optional[int] = None
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
# --- Sender identity ---------------------------------------------------------
|
|
467
|
+
|
|
468
|
+
class HostSender(BaseModel):
|
|
469
|
+
"""WHO produced the user side of this turn (docs/RELATIONSHIPS.md).
|
|
470
|
+
|
|
471
|
+
Per-message sender identity so the sidecar attributes group traffic to
|
|
472
|
+
the real speaker server-side, independent of any client-side contact
|
|
473
|
+
caching. Optional and additive: hosts that cannot supply it keep the
|
|
474
|
+
legacy context.contact_id behavior."""
|
|
475
|
+
platform: str = Field(..., max_length=64)
|
|
476
|
+
user_id: str = Field(..., max_length=256)
|
|
477
|
+
display_name: str = Field(default="", max_length=256)
|
|
478
|
+
group_id: str = Field(default="", max_length=256)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
# --- Signals ----------------------------------------------------------------
|
|
482
|
+
|
|
483
|
+
class SignalIngestRequest(BaseModel):
|
|
484
|
+
identity: HostIdentity
|
|
485
|
+
context: HostTurnContext
|
|
486
|
+
sender: Optional[HostSender] = None
|
|
487
|
+
incoming_message: Optional[HostMessage] = None
|
|
488
|
+
outgoing_message: Optional[HostMessage] = None
|
|
489
|
+
tool_calls: List[ReasoningToolCall] = Field(default_factory=list)
|
|
490
|
+
correction: Optional[str] = None
|
|
491
|
+
signals: List[Dict[str, Any]] = Field(default_factory=list)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
class SignalIngestResponse(BaseModel):
|
|
495
|
+
accepted: bool
|
|
496
|
+
signals_recorded: int
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
# --- Turns ------------------------------------------------------------------
|
|
500
|
+
|
|
501
|
+
class CheckpointMessage(BaseModel):
|
|
502
|
+
"""Direct source content; injected API context is not part of this schema."""
|
|
503
|
+
model_config = ConfigDict(extra="forbid")
|
|
504
|
+
role: Literal["user", "assistant"]
|
|
505
|
+
content: Union[str, List[Dict[str, Any]]]
|
|
506
|
+
|
|
507
|
+
@model_validator(mode="after")
|
|
508
|
+
def nonempty_content(self):
|
|
509
|
+
if not self.content or isinstance(self.content, str) and not self.content.strip():
|
|
510
|
+
raise ValueError("checkpoint messages must contain source content")
|
|
511
|
+
return self
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
class TurnMessage(HostMessage):
|
|
515
|
+
"""Direct source blocks are retained; ordinary cognition receives text only."""
|
|
516
|
+
content: Union[str, List[Dict[str, Any]]]
|
|
517
|
+
|
|
518
|
+
def text_content(self) -> str:
|
|
519
|
+
if isinstance(self.content, str):
|
|
520
|
+
return self.content
|
|
521
|
+
return "\n".join(block["text"] for block in self.content
|
|
522
|
+
if block.get("type") in {"text", "input_text", "output_text"}
|
|
523
|
+
and isinstance(block.get("text"), str))
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class SourceReference(BaseModel):
|
|
527
|
+
"""A supplied canonical revision, not a generated citation or truth claim."""
|
|
528
|
+
model_config = ConfigDict(extra="forbid")
|
|
529
|
+
source_id: str = Field(min_length=1, max_length=256)
|
|
530
|
+
source_version: str = Field(pattern=r"^[0-9a-f]{64}$")
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
class SourceInputReference(BaseModel):
|
|
534
|
+
"""Exact admitted input before canonical media normalization."""
|
|
535
|
+
model_config = ConfigDict(extra="forbid")
|
|
536
|
+
source_id: str = Field(min_length=1, max_length=256)
|
|
537
|
+
input_message_hash: str = Field(pattern=r"^[0-9a-f]{64}$")
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
class TurnSyncRequest(BaseModel):
|
|
541
|
+
identity: HostIdentity
|
|
542
|
+
context: HostTurnContext
|
|
543
|
+
sender: Optional[HostSender] = None
|
|
544
|
+
topics: List[str] = Field(default_factory=list)
|
|
545
|
+
entities: List[str] = Field(default_factory=list)
|
|
546
|
+
pending_tasks: List[str] = Field(default_factory=list)
|
|
547
|
+
tools_used: List[str] = Field(default_factory=list)
|
|
548
|
+
summary: Optional[str] = None
|
|
549
|
+
# Raw message fields — populated by Hermes provider and MCP tools.
|
|
550
|
+
# When structured fields are empty but raw messages are present,
|
|
551
|
+
# the sidecar runs extraction from the raw messages.
|
|
552
|
+
user_message: Optional[Union[HostMessage, TurnMessage]] = None
|
|
553
|
+
assistant_message: Optional[Union[HostMessage, TurnMessage]] = None
|
|
554
|
+
assistant_source_refs: Optional[List[SourceReference]] = Field(default=None, min_length=1)
|
|
555
|
+
assistant_input_refs: Optional[List[SourceInputReference]] = Field(default=None, min_length=1)
|
|
556
|
+
source_only: Optional[Literal[True]] = None
|
|
557
|
+
# Model that produced the assistant side of this turn (optional, additive).
|
|
558
|
+
# Lets the mining layer detect provider escalations / cloud failovers from
|
|
559
|
+
# real per-turn metadata instead of guessing from text.
|
|
560
|
+
model: Optional[str] = None
|
|
561
|
+
# Evidence-only checkpoints never trigger ordinary turn/relationship effects.
|
|
562
|
+
checkpoint_messages: Optional[List[CheckpointMessage]] = Field(
|
|
563
|
+
default=None, min_length=1, max_length=20_000,
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
@model_validator(mode="after")
|
|
567
|
+
def bounded_checkpoint(self):
|
|
568
|
+
if len(self.model_dump_json().encode("utf-8")) > 8 * 1024 * 1024:
|
|
569
|
+
raise ValueError("turn exceeds the 8 MiB source limit")
|
|
570
|
+
if self.checkpoint_messages is not None:
|
|
571
|
+
if self.sender is not None or self.user_message is not None or self.assistant_message is not None:
|
|
572
|
+
raise ValueError("checkpoint cannot also represent an ordinary turn")
|
|
573
|
+
if not self.context.turn_id:
|
|
574
|
+
raise ValueError("checkpoint requires an idempotent turn id")
|
|
575
|
+
def nonempty(message):
|
|
576
|
+
return message is not None and bool(message.content.strip() if isinstance(message.content, str) else message.content)
|
|
577
|
+
if self.source_only and (self.checkpoint_messages is not None or not any(
|
|
578
|
+
nonempty(message) for message in (self.user_message, self.assistant_message))):
|
|
579
|
+
raise ValueError('source-only delivery requires nonempty direct source messages')
|
|
580
|
+
if (self.assistant_source_refs or self.assistant_input_refs) and not any(message is not None and message.role == 'assistant' and nonempty(message)
|
|
581
|
+
for message in [self.assistant_message, *(self.checkpoint_messages or [])]):
|
|
582
|
+
raise ValueError('source references require an assistant message')
|
|
583
|
+
if self.assistant_input_refs and (not self.context.turn_id or self.checkpoint_messages is not None):
|
|
584
|
+
raise ValueError('input parents require an identified direct assistant source')
|
|
585
|
+
return self
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
class TurnSyncResponse(BaseModel):
|
|
589
|
+
accepted: bool
|
|
590
|
+
continuity_updated: bool
|
|
591
|
+
skipped_reason: Optional[str] = None
|
|
592
|
+
errors: Optional[List[str]] = None
|
|
593
|
+
source_recorded: bool = False
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
# --- Safety -----------------------------------------------------------------
|
|
597
|
+
|
|
598
|
+
class SafetyCheckRequest(BaseModel):
|
|
599
|
+
identity: HostIdentity
|
|
600
|
+
context: HostTurnContext
|
|
601
|
+
response_text: str
|
|
602
|
+
incoming_message_text: Optional[str] = None
|
|
603
|
+
target_gateway: Optional[str] = None
|
|
604
|
+
trust_tier: Optional[str] = None
|
|
605
|
+
mentioned_entities: Optional[List[str]] = None
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
class SafetyCheckResponse(BaseModel):
|
|
609
|
+
# "unavailable" (with HTTP 503) = the gate did not evaluate; never
|
|
610
|
+
# reported as "pass".
|
|
611
|
+
decision: Literal["pass", "block", "pending", "unavailable"]
|
|
612
|
+
blocked: bool
|
|
613
|
+
blocking_layer: Optional[int] = None
|
|
614
|
+
reason: Optional[str] = None
|
|
615
|
+
flagged_excerpt: Optional[str] = None
|
|
616
|
+
layer_results: Optional[Dict[str, Any]] = None
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
# --- Events -----------------------------------------------------------------
|
|
620
|
+
|
|
621
|
+
class HostEvent(BaseModel):
|
|
622
|
+
type: str
|
|
623
|
+
occurred_at: str
|
|
624
|
+
payload: Dict[str, Any] = Field(default_factory=dict)
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
# --- Goals ------------------------------------------------------------------
|
|
628
|
+
|
|
629
|
+
class GoalCreateRequest(BaseModel):
|
|
630
|
+
identity: HostIdentity
|
|
631
|
+
context: Optional[HostTurnContext] = None
|
|
632
|
+
title: str
|
|
633
|
+
description: Optional[str] = None
|
|
634
|
+
priority: Optional[str] = "medium"
|
|
635
|
+
parent_goal_id: Optional[str] = None
|
|
636
|
+
person_id: Optional[str] = None
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
class GoalUpdateRequest(BaseModel):
|
|
640
|
+
identity: HostIdentity
|
|
641
|
+
status: Optional[str] = None
|
|
642
|
+
progress: Optional[float] = None
|
|
643
|
+
notes: Optional[str] = None
|
|
644
|
+
# When blocking: an external condition the autonomy loop polls; the goal
|
|
645
|
+
# auto-unblocks when it's met (email_reply | deployment_health |
|
|
646
|
+
# delivery_status | api_response | custom).
|
|
647
|
+
condition_type: Optional[str] = None
|
|
648
|
+
condition_params: Optional[Dict[str, Any]] = None
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
class GoalResponse(BaseModel):
|
|
652
|
+
id: str
|
|
653
|
+
title: str
|
|
654
|
+
description: Optional[str] = None
|
|
655
|
+
status: str = "active"
|
|
656
|
+
priority: str = "medium"
|
|
657
|
+
progress: float = 0.0
|
|
658
|
+
parent_goal_id: Optional[str] = None
|
|
659
|
+
person_id: Optional[str] = None
|
|
660
|
+
created_at: Optional[str] = None
|
|
661
|
+
updated_at: Optional[str] = None
|
|
662
|
+
dispatch_unavailable: Optional[str] = None
|
|
663
|
+
completion_basis: Optional[str] = None
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
class GoalListResponse(BaseModel):
|
|
667
|
+
goals: List[GoalResponse] = []
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
# --- Contacts ---------------------------------------------------------------
|
|
671
|
+
|
|
672
|
+
class ContactResponse(BaseModel):
|
|
673
|
+
contact_id: str
|
|
674
|
+
display_name: Optional[str] = None
|
|
675
|
+
given_name: Optional[str] = None
|
|
676
|
+
family_name: Optional[str] = None
|
|
677
|
+
organization: Optional[str] = None
|
|
678
|
+
relationship_score: float = 0.0
|
|
679
|
+
trust_tier: Optional[str] = None
|
|
680
|
+
interaction_allowed: bool = True
|
|
681
|
+
tags: List[str] = Field(default_factory=list)
|
|
682
|
+
privacy_level: Optional[str] = None
|
|
683
|
+
person_node_id: Optional[str] = None
|
|
684
|
+
notes: Optional[str] = None
|
|
685
|
+
import_source: Optional[str] = None
|
|
686
|
+
first_seen_at: Optional[str] = None
|
|
687
|
+
last_interaction_at: Optional[str] = None
|
|
688
|
+
interaction_count: int = 0
|
|
689
|
+
enrichment_source: List[str] = Field(default_factory=list)
|
|
690
|
+
enrichment_last_at: Optional[str] = None
|
|
691
|
+
deleted_at: Optional[str] = None
|
|
692
|
+
created_at: Optional[str] = None
|
|
693
|
+
updated_at: Optional[str] = None
|
|
694
|
+
timezone: Optional[str] = None # IANA tz for this contact (v0.21.0)
|
|
695
|
+
introduced_by: Optional[str] = None # contact_id of whoever introduced them
|
|
696
|
+
met_via: Optional[Dict[str, Any]] = None # {channel, scope_id, ...} provenance
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
class ContactListResponse(BaseModel):
|
|
700
|
+
contacts: List[ContactResponse] = []
|
|
701
|
+
source_filter: Optional[str] = None
|
|
702
|
+
total: int = 0
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
# --- Temporal awareness (v0.21.0) -------------------------------------------
|
|
706
|
+
|
|
707
|
+
class TemporalConfigRequest(BaseModel):
|
|
708
|
+
agent_timezone: Optional[str] = None # set the agent's home tz
|
|
709
|
+
default_contact_timezone: Optional[str] = None # fallback tz for contacts
|
|
710
|
+
clear_default_contact_timezone: bool = False # explicitly clear the fallback
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
class TemporalConfigResponse(BaseModel):
|
|
714
|
+
agent_timezone: str
|
|
715
|
+
default_contact_timezone: Optional[str] = None
|
|
716
|
+
now_utc: str
|
|
717
|
+
now_agent_local: str
|
|
718
|
+
agent_local_clock: str
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
class ContactTimezoneRequest(BaseModel):
|
|
722
|
+
timezone: Optional[str] = None # None clears it
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
class TimelineEvent(BaseModel):
|
|
726
|
+
seq: int
|
|
727
|
+
type: str
|
|
728
|
+
at: str # ISO timestamp the event was recorded
|
|
729
|
+
when: str # humanized, e.g. "3h ago"
|
|
730
|
+
bucket: str # coarse, e.g. "today"
|
|
731
|
+
summary: Optional[str] = None
|
|
732
|
+
contact_id: Optional[str] = None
|
|
733
|
+
data: Dict[str, Any] = Field(default_factory=dict)
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
class TimelineResponse(BaseModel):
|
|
737
|
+
since: str
|
|
738
|
+
count: int
|
|
739
|
+
digest: str # human-readable rollup for the agent
|
|
740
|
+
events: List[TimelineEvent] = Field(default_factory=list)
|
|
741
|
+
has_more: bool = False
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
class TemporalContact(BaseModel):
|
|
745
|
+
contact_id: str
|
|
746
|
+
name: str
|
|
747
|
+
timezone: Optional[str] = None
|
|
748
|
+
last_interaction_at: Optional[str] = None
|
|
749
|
+
days_since: float
|
|
750
|
+
cadence_days: float
|
|
751
|
+
overdue: bool
|
|
752
|
+
overdue_ratio: float
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
class TemporalContactsResponse(BaseModel):
|
|
756
|
+
now: str
|
|
757
|
+
count: int
|
|
758
|
+
contacts: List[TemporalContact] = Field(default_factory=list)
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
class ContactHandleIn(BaseModel):
|
|
762
|
+
gateway: str
|
|
763
|
+
address: str
|
|
764
|
+
is_primary: bool = False
|
|
765
|
+
verified: bool = False
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
class ContactCreateRequest(BaseModel):
|
|
769
|
+
display_name: str
|
|
770
|
+
given_name: Optional[str] = None
|
|
771
|
+
family_name: Optional[str] = None
|
|
772
|
+
organization: Optional[str] = None
|
|
773
|
+
trust_tier: str = "regular"
|
|
774
|
+
tags: Optional[List[str]] = None
|
|
775
|
+
notes: Optional[str] = None
|
|
776
|
+
handles: List[ContactHandleIn] = []
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
class ContactIntroRequest(BaseModel):
|
|
780
|
+
"""Capture an organic introduction: the agent met/learned of a new person.
|
|
781
|
+
|
|
782
|
+
Creates (or annotates) a PROVISIONAL contact with introduction provenance.
|
|
783
|
+
A provisional contact is inert by design — trust_tier defaults to 'unknown'
|
|
784
|
+
and interaction_allowed is forced false — so capturing an intro never grants
|
|
785
|
+
anyone outreach standing; promotion/merge reconciles them later.
|
|
786
|
+
"""
|
|
787
|
+
name: str
|
|
788
|
+
gateway: Optional[str] = None # optional handle to attach
|
|
789
|
+
address: Optional[str] = None
|
|
790
|
+
introduced_by: Optional[str] = None # contact_id of the introducer
|
|
791
|
+
met_via: Optional[Dict[str, Any]] = None # {channel, scope_id, ...}
|
|
792
|
+
note: Optional[str] = None
|
|
793
|
+
trust_tier: str = "unknown" # provisional; never grants 1:1 rights
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
class ContactIntroResponse(BaseModel):
|
|
797
|
+
contact: ContactResponse
|
|
798
|
+
created: bool # True if a new provisional contact was made; False if annotated existing
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
class ContactStyleRequest(BaseModel):
|
|
802
|
+
identity: HostIdentity
|
|
803
|
+
person_id: str
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
class ContactStyleResponse(BaseModel):
|
|
807
|
+
person_id: str
|
|
808
|
+
formality: Optional[str] = None
|
|
809
|
+
tone: Optional[str] = None
|
|
810
|
+
notes: Optional[Dict[str, Any]] = None
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
# --- Briefings --------------------------------------------------------------
|
|
814
|
+
|
|
815
|
+
class BriefingResponse(BaseModel):
|
|
816
|
+
id: str
|
|
817
|
+
title: Optional[str] = None
|
|
818
|
+
body: str
|
|
819
|
+
briefing_type: Optional[str] = None
|
|
820
|
+
created_at: Optional[str] = None
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
class BriefingListResponse(BaseModel):
|
|
824
|
+
briefings: List[BriefingResponse] = []
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
# --- World Model ------------------------------------------------------------
|
|
828
|
+
|
|
829
|
+
class EntityResponse(BaseModel):
|
|
830
|
+
id: str
|
|
831
|
+
entity_type: str
|
|
832
|
+
name: str
|
|
833
|
+
properties: Optional[Dict[str, Any]] = None
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
class EntityListResponse(BaseModel):
|
|
837
|
+
entities: List[EntityResponse] = []
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
class EntityQueryRequest(BaseModel):
|
|
841
|
+
identity: HostIdentity
|
|
842
|
+
query: str
|
|
843
|
+
entity_type: Optional[str] = None # None or "all" = every type
|
|
844
|
+
limit: Optional[int] = 10
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
class ExtractionRequest(BaseModel):
|
|
848
|
+
identity: HostIdentity
|
|
849
|
+
content: str # Base64-encoded document content
|
|
850
|
+
filename: Optional[str] = None
|
|
851
|
+
mime_type: Optional[str] = None
|
|
852
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
class ExtractedEntityResponse(BaseModel):
|
|
856
|
+
name: str
|
|
857
|
+
entity_type: str
|
|
858
|
+
attributes: Optional[Dict[str, Any]] = None
|
|
859
|
+
confidence: float = 1.0
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
class ExtractionResponse(BaseModel):
|
|
863
|
+
format_detected: str
|
|
864
|
+
entities: List[ExtractedEntityResponse] = []
|
|
865
|
+
text_length: int = 0
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
# --- Cognition --------------------------------------------------------------
|
|
869
|
+
|
|
870
|
+
class CognitionCycleRequest(BaseModel):
|
|
871
|
+
identity: HostIdentity
|
|
872
|
+
context: Optional[HostTurnContext] = None
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
class CognitivePerformanceIndex(BaseModel):
|
|
876
|
+
overall: float = 0.0
|
|
877
|
+
memory: float = 0.0
|
|
878
|
+
reasoning: float = 0.0
|
|
879
|
+
social: float = 0.0
|
|
880
|
+
autonomy: float = 0.0
|
|
881
|
+
domains: Optional[Dict[str, float]] = None
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
class CognitionGap(BaseModel):
|
|
885
|
+
gap_id: str
|
|
886
|
+
domain: str
|
|
887
|
+
severity: float
|
|
888
|
+
description: Optional[str] = None
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
class CognitionCycleResponse(BaseModel):
|
|
892
|
+
cpi: Optional[CognitivePerformanceIndex] = None
|
|
893
|
+
gaps: List[CognitionGap] = []
|
|
894
|
+
adjustments: List[Dict[str, Any]] = []
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
# --- Research ---------------------------------------------------------------
|
|
898
|
+
|
|
899
|
+
class ResearchStartRequest(BaseModel):
|
|
900
|
+
identity: HostIdentity
|
|
901
|
+
topic: str
|
|
902
|
+
depth: Optional[str] = "standard" # quick | standard | deep
|
|
903
|
+
person_id: Optional[str] = None
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
class ResearchRunResponse(BaseModel):
|
|
907
|
+
run_id: str
|
|
908
|
+
topic: str
|
|
909
|
+
status: str
|
|
910
|
+
stages_completed: List[str] = []
|
|
911
|
+
artifact: Optional[Dict[str, Any]] = None
|
|
912
|
+
created_at: Optional[str] = None
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
class ResearchListResponse(BaseModel):
|
|
916
|
+
runs: List[ResearchRunResponse] = []
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
# --- Delivery ---------------------------------------------------------------
|
|
920
|
+
|
|
921
|
+
class DeliveryListResponse(BaseModel):
|
|
922
|
+
pending: List[Dict[str, Any]] = []
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
class DeliveryMarkRequest(BaseModel):
|
|
926
|
+
identity: HostIdentity
|
|
927
|
+
delivery_id: str
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
# --- Synthesis --------------------------------------------------------------
|
|
931
|
+
|
|
932
|
+
class SynthesisDiscoverRequest(BaseModel):
|
|
933
|
+
identity: HostIdentity
|
|
934
|
+
context: Optional[HostTurnContext] = None
|
|
935
|
+
person_id: Optional[str] = None
|
|
936
|
+
min_novelty: Optional[float] = 0.3
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
class SynthesisConnection(BaseModel):
|
|
940
|
+
id: str
|
|
941
|
+
connection_type: str
|
|
942
|
+
entities: List[str] = []
|
|
943
|
+
novelty: float = 0.0
|
|
944
|
+
description: Optional[str] = None
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
class SynthesisDiscoverResponse(BaseModel):
|
|
948
|
+
connections: List[SynthesisConnection] = []
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
# --- Learning ---------------------------------------------------------------
|
|
952
|
+
|
|
953
|
+
class LearningCorrectionRequest(BaseModel):
|
|
954
|
+
identity: HostIdentity
|
|
955
|
+
context: HostTurnContext
|
|
956
|
+
original: str
|
|
957
|
+
correction: str
|
|
958
|
+
component: Optional[str] = None
|
|
959
|
+
correction_type: Literal[
|
|
960
|
+
"factual", "tone", "action", "preference"
|
|
961
|
+
] = "factual"
|
|
962
|
+
# Exact reference of the corrected outbound response. The benchmark
|
|
963
|
+
# later joins this to a receipt-backed CommsLog row; an absent or unknown
|
|
964
|
+
# reference remains useful learning feedback but is not causal evidence.
|
|
965
|
+
external_ref: Optional[str] = None
|
|
966
|
+
# Callers that retry can supply a stable id. FeedbackStore makes the
|
|
967
|
+
# resulting persistence idempotent across process restarts.
|
|
968
|
+
correction_id: Optional[str] = None
|
|
969
|
+
# Explicit owner control of one current agent judgment. Ordinary feedback
|
|
970
|
+
# retains its existing behavior when these fields are absent.
|
|
971
|
+
judgment_id: Optional[int] = Field(default=None, strict=True, gt=0)
|
|
972
|
+
judgment_action: Optional[Literal["withdraw", "reconsider"]] = None
|
|
973
|
+
source_id: Optional[str] = None
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
class LearningEngagementRequest(BaseModel):
|
|
977
|
+
identity: HostIdentity
|
|
978
|
+
briefing_id: str
|
|
979
|
+
action: str # opened | dismissed | clicked | saved
|
|
980
|
+
dwell_seconds: Optional[float] = None
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
class LearningWeightsResponse(BaseModel):
|
|
984
|
+
weights: Dict[str, float] = {}
|
|
985
|
+
stats: Dict[str, int] = {}
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
# --- Skills -----------------------------------------------------------------
|
|
989
|
+
|
|
990
|
+
class SkillSummary(BaseModel):
|
|
991
|
+
id: str
|
|
992
|
+
name: str
|
|
993
|
+
description: Optional[str] = None
|
|
994
|
+
version: Optional[str] = None
|
|
995
|
+
triggers: List[str] = []
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
class SkillDetailResponse(BaseModel):
|
|
999
|
+
id: str
|
|
1000
|
+
name: str
|
|
1001
|
+
description: Optional[str] = None
|
|
1002
|
+
version: Optional[str] = None
|
|
1003
|
+
triggers: List[str] = []
|
|
1004
|
+
input_schema: Optional[Dict[str, Any]] = None
|
|
1005
|
+
permissions: Optional[Dict[str, Any]] = None
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
class SkillsListResponse(BaseModel):
|
|
1009
|
+
skills: List[SkillSummary] = []
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
# --- Insights ---------------------------------------------------------------
|
|
1013
|
+
|
|
1014
|
+
class InsightResponse(BaseModel):
|
|
1015
|
+
id: str
|
|
1016
|
+
title: str
|
|
1017
|
+
body: str
|
|
1018
|
+
insight_type: Optional[str] = None
|
|
1019
|
+
novelty: float = 0.0
|
|
1020
|
+
entities: List[str] = []
|
|
1021
|
+
created_at: Optional[str] = None
|
|
1022
|
+
dismissed: bool = False
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
class InsightsListResponse(BaseModel):
|
|
1026
|
+
insights: List[InsightResponse] = []
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
# --- Enriched Context -------------------------------------------------------
|
|
1030
|
+
|
|
1031
|
+
class EnrichedContextRequest(BaseModel):
|
|
1032
|
+
identity: HostIdentity
|
|
1033
|
+
context: HostTurnContext
|
|
1034
|
+
audience: Optional[Literal["viewer", "owner", "shared", "global"]] = None
|
|
1035
|
+
message: str
|
|
1036
|
+
features: Optional[Dict[str, bool]] = None
|
|
1037
|
+
compression: Optional[Literal["off", "conservative", "balanced", "aggressive"]] = None
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
class EnrichedContextResponse(BaseModel):
|
|
1041
|
+
sections: List[ContextSection] = []
|
|
1042
|
+
contact_id: Optional[str] = None
|
|
1043
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
# --- Chain / Identity -------------------------------------------------------
|
|
1047
|
+
|
|
1048
|
+
class IdentityStatusResponse(BaseModel):
|
|
1049
|
+
colony_id: Optional[str] = None
|
|
1050
|
+
public_key: Optional[str] = None
|
|
1051
|
+
node_id: Optional[str] = None
|
|
1052
|
+
node_public_key: Optional[str] = None
|
|
1053
|
+
node_cert_fingerprint: Optional[str] = None
|
|
1054
|
+
initialized: bool = False
|
|
1055
|
+
keys_configured: bool = False
|
|
1056
|
+
is_genesis: bool = False
|
|
1057
|
+
trust_tier: Optional[Literal["REGULAR", "TRUSTED", "PRIVILEGED", "GENESIS"]] = None
|
|
1058
|
+
trust_anchor_verified: bool = False
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
class IdentityInitRequest(BaseModel):
|
|
1062
|
+
identity: HostIdentity
|
|
1063
|
+
force: bool = False
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
class ChainVerifyRequest(BaseModel):
|
|
1067
|
+
identity: HostIdentity
|
|
1068
|
+
data: str
|
|
1069
|
+
signature: Optional[str] = None
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
class ChainVerifyResponse(BaseModel):
|
|
1073
|
+
valid: bool
|
|
1074
|
+
colony_id: Optional[str] = None
|
|
1075
|
+
signed_attestation: Optional[str] = None
|
|
1076
|
+
attested_at: Optional[str] = None
|
|
1077
|
+
signer_public_key: Optional[str] = None
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
# --- Secrets ----------------------------------------------------------------
|
|
1081
|
+
|
|
1082
|
+
class SecretListRequest(BaseModel):
|
|
1083
|
+
identity: HostIdentity
|
|
1084
|
+
prefix: Optional[str] = None
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
class SecretListResponse(BaseModel):
|
|
1088
|
+
keys: List[str] = []
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
class SecretGetRequest(BaseModel):
|
|
1092
|
+
identity: HostIdentity
|
|
1093
|
+
key: str
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
class SecretGetResponse(BaseModel):
|
|
1097
|
+
key: str
|
|
1098
|
+
value: Optional[str] = None
|
|
1099
|
+
exists: bool = False
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
class SecretSetRequest(BaseModel):
|
|
1103
|
+
identity: HostIdentity
|
|
1104
|
+
key: str
|
|
1105
|
+
value: str
|
|
1106
|
+
secret_type: Optional[str] = None
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
class SecretSetResponse(BaseModel):
|
|
1110
|
+
key: str
|
|
1111
|
+
stored: bool
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
class SecretDeleteRequest(BaseModel):
|
|
1115
|
+
identity: HostIdentity
|
|
1116
|
+
key: str
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
class SecretDeleteResponse(BaseModel):
|
|
1120
|
+
key: str
|
|
1121
|
+
deleted: bool
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
# --- Autonomy ---------------------------------------------------------------
|
|
1125
|
+
|
|
1126
|
+
class AutonomyStatusResponse(BaseModel):
|
|
1127
|
+
running: bool = False
|
|
1128
|
+
mode: str = "reactive"
|
|
1129
|
+
timezone: str = "UTC"
|
|
1130
|
+
in_quiet_hours: bool = False
|
|
1131
|
+
ticks: int = 0
|
|
1132
|
+
events_processed: int = 0
|
|
1133
|
+
goals_checked: int = 0
|
|
1134
|
+
initiatives_generated: int = 0
|
|
1135
|
+
actions_executed: int = 0
|
|
1136
|
+
errors: int = 0
|
|
1137
|
+
phases_cancelled: int = 0
|
|
1138
|
+
last_cancelled_phase: Optional[str] = None
|
|
1139
|
+
# Per-phase wall-clock seconds (last run / worst run) and the phase
|
|
1140
|
+
# running right now, so a tick that overruns its budget is attributable.
|
|
1141
|
+
phases: Optional[Dict[str, Any]] = None
|
|
1142
|
+
config: Optional[Dict[str, Any]] = None
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
# --- Configure (Host LLM Config) -------------------------------------------
|
|
1147
|
+
|
|
1148
|
+
class LLMModelsConfig(BaseModel):
|
|
1149
|
+
# Each tier is either a bare model string or an object spec (per-tier
|
|
1150
|
+
# endpoint/priority/useful-context overrides — see build_tiers_from_host).
|
|
1151
|
+
small: Optional[Union[str, Dict[str, Any]]] = None
|
|
1152
|
+
medium: Optional[Union[str, Dict[str, Any]]] = None
|
|
1153
|
+
large: Optional[Union[str, Dict[str, Any]]] = None
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
class HostConfigureRequest(BaseModel):
|
|
1157
|
+
identity: HostIdentity
|
|
1158
|
+
llm: Optional[Dict[str, Any]] = Field(None, description="LLM provider config from host")
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
class HostConfigureResponse(BaseModel):
|
|
1162
|
+
configured: bool = True
|
|
1163
|
+
provider: Optional[str] = None
|
|
1164
|
+
# Values may be bare model strings or per-tier object specs, so the echo
|
|
1165
|
+
# must accept both (a str-only type 500s on multi-endpoint configs).
|
|
1166
|
+
models: Optional[Dict[str, Any]] = None
|
|
1167
|
+
routing: Optional[Dict[str, Any]] = None
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
# --- Models (local LLM discovery) -------------------------------------------
|
|
1171
|
+
|
|
1172
|
+
class ModelInfo(BaseModel):
|
|
1173
|
+
id: str
|
|
1174
|
+
provider: Optional[str] = None
|
|
1175
|
+
size: Optional[int] = None
|
|
1176
|
+
owned_by: Optional[str] = None
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
class ModelListResponse(BaseModel):
|
|
1180
|
+
provider: str = ""
|
|
1181
|
+
base_url: Optional[str] = None
|
|
1182
|
+
models: List[ModelInfo] = []
|
|
1183
|
+
discovered: bool = False
|
|
1184
|
+
error: Optional[str] = None
|
|
1185
|
+
routing: Optional[Dict[str, Any]] = None
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
# ---------------------------------------------------------------------------
|
|
1189
|
+
# Commitment Tracking
|
|
1190
|
+
# ---------------------------------------------------------------------------
|
|
1191
|
+
|
|
1192
|
+
class CommitmentCreateRequest(BaseModel):
|
|
1193
|
+
person_id: str = Field(..., min_length=1)
|
|
1194
|
+
description: str = Field(..., min_length=1, max_length=1000)
|
|
1195
|
+
due_at: Optional[str] = None
|
|
1196
|
+
priority: int = Field(default=50, ge=0, le=100)
|
|
1197
|
+
# "introspection": a same-interaction owed follow-up surfaced by the per-turn
|
|
1198
|
+
# introspection reflex (e.g. "text me the result"), as opposed to a durable
|
|
1199
|
+
# future promise ("cognition"). Such a commitment carries a deliverable tag in
|
|
1200
|
+
# `metadata`: {"kind": "deliverable", "content": <what to send>,
|
|
1201
|
+
# "channel_hint": "sms"|"dm"|..., "delivered": bool}. The autonomy loop turns an
|
|
1202
|
+
# undelivered deliverable into an agent_action so the host actually sends it.
|
|
1203
|
+
source_type: Literal["manual", "autonomy", "cognition", "introspection"] = "manual"
|
|
1204
|
+
source_context: Optional[str] = None
|
|
1205
|
+
# When true, an open commitment for the same person that already says the
|
|
1206
|
+
# same thing (normalized match) is returned instead of creating a twin.
|
|
1207
|
+
# Agent/tool callers should set this; the raw API default stays off.
|
|
1208
|
+
dedupe: bool = False
|
|
1209
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
class CommitmentUpdateRequest(BaseModel):
|
|
1213
|
+
status: Optional[Literal["fulfilled", "cancelled"]] = None
|
|
1214
|
+
fulfilled_at: Optional[str] = None
|
|
1215
|
+
description: Optional[str] = Field(None, min_length=1, max_length=1000)
|
|
1216
|
+
due_at: Optional[str] = None
|
|
1217
|
+
priority: Optional[int] = Field(None, ge=0, le=100)
|
|
1218
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1219
|
+
# Resolution semantics: WHY the item is being settled, so the system can
|
|
1220
|
+
# learn from it. When `outcome` is set, `status` may be omitted — it is
|
|
1221
|
+
# derived (done -> fulfilled, everything else -> cancelled) and the
|
|
1222
|
+
# resolution {outcome, note, by, at} is recorded in metadata.
|
|
1223
|
+
outcome: Optional[Literal["done", "invalid", "duplicate", "wont_do", "obsolete"]] = None
|
|
1224
|
+
reason: Optional[str] = Field(None, max_length=300)
|
|
1225
|
+
resolved_by: Optional[str] = Field(None, max_length=60)
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
class CommitmentResponse(BaseModel):
|
|
1229
|
+
id: str
|
|
1230
|
+
person_id: str
|
|
1231
|
+
description: str
|
|
1232
|
+
made_at: str
|
|
1233
|
+
due_at: Optional[str] = None
|
|
1234
|
+
fulfilled_at: Optional[str] = None
|
|
1235
|
+
status: str
|
|
1236
|
+
source_type: str
|
|
1237
|
+
source_context: Optional[str] = None
|
|
1238
|
+
priority: int
|
|
1239
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1240
|
+
# True when a dedupe-create returned an existing open item.
|
|
1241
|
+
deduped: bool = False
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
class CommitmentListResponse(BaseModel):
|
|
1245
|
+
commitments: List[CommitmentResponse] = []
|
|
1246
|
+
total: int
|
|
1247
|
+
limit: int
|
|
1248
|
+
offset: int
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
class ConcernResolveRequest(BaseModel):
|
|
1252
|
+
"""Owner/agent resolution of a workspace concern. `outcome` says why:
|
|
1253
|
+
done means handled, the rest are flavors of "stop tracking this".
|
|
1254
|
+
With cascade on (default), sources the concern was raised from (e.g. an
|
|
1255
|
+
overdue commitment) are settled too — otherwise the ingest loop re-raises
|
|
1256
|
+
the concern from the still-open source and the resolve is cosmetic."""
|
|
1257
|
+
note: str = Field("resolved by owner", max_length=300)
|
|
1258
|
+
outcome: Literal["done", "invalid", "duplicate", "wont_do", "obsolete"] = "done"
|
|
1259
|
+
cascade: bool = True
|
|
1260
|
+
resolved_by: str = Field("owner", max_length=60)
|
|
1261
|
+
|
|
1262
|
+
|
|
1263
|
+
# ---------------------------------------------------------------------------
|
|
1264
|
+
# Cognition Substrate
|
|
1265
|
+
# ---------------------------------------------------------------------------
|
|
1266
|
+
|
|
1267
|
+
class CognitionTriggerRequest(BaseModel):
|
|
1268
|
+
trigger_type: Literal["turn_sync", "signal_ingest", "anomaly", "manual"]
|
|
1269
|
+
context: Dict[str, Any]
|
|
1270
|
+
priority: Literal["high", "normal", "low"] = "normal"
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
class CognitionTriggerResponse(BaseModel):
|
|
1274
|
+
accepted: bool = True
|
|
1275
|
+
message: str = "Cognition trigger accepted"
|
|
1276
|
+
throttle_seconds: Optional[int] = None
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
# ---------------------------------------------------------------------------
|
|
1280
|
+
# Theory of Mind — Affect
|
|
1281
|
+
# ---------------------------------------------------------------------------
|
|
1282
|
+
|
|
1283
|
+
class AffectEventCreateRequest(BaseModel):
|
|
1284
|
+
contact_id: str
|
|
1285
|
+
valence: float = Field(..., ge=-1.0, le=1.0)
|
|
1286
|
+
arousal: float = Field(0.5, ge=0.0, le=1.0)
|
|
1287
|
+
source: Literal["explicit", "inferred", "signal"] = "explicit"
|
|
1288
|
+
trigger: Optional[str] = None
|
|
1289
|
+
session_id: Optional[str] = None
|
|
1290
|
+
|
|
1291
|
+
|
|
1292
|
+
class AffectEventResponse(BaseModel):
|
|
1293
|
+
id: str
|
|
1294
|
+
contact_id: str
|
|
1295
|
+
valence: float
|
|
1296
|
+
arousal: float
|
|
1297
|
+
source: str
|
|
1298
|
+
trigger: Optional[str] = None
|
|
1299
|
+
timestamp: str
|
|
1300
|
+
session_id: Optional[str] = None
|
|
1301
|
+
source_lineage: Optional[Dict[str, Any]] = None
|
|
1302
|
+
evidence_basis: str = "unlinked_observation"
|
|
1303
|
+
|
|
1304
|
+
|
|
1305
|
+
class AffectStateResponse(BaseModel):
|
|
1306
|
+
contact_id: str
|
|
1307
|
+
current_valence: float = 0.0
|
|
1308
|
+
current_arousal: float = 0.3
|
|
1309
|
+
trend: str = "stable"
|
|
1310
|
+
last_event_id: Optional[str] = None
|
|
1311
|
+
last_updated: Optional[str] = None
|
|
1312
|
+
event_count: int = 0
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
class AffectEventListResponse(BaseModel):
|
|
1316
|
+
events: List[AffectEventResponse] = []
|
|
1317
|
+
total: int
|
|
1318
|
+
limit: int
|
|
1319
|
+
offset: int
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
# ---------------------------------------------------------------------------
|
|
1323
|
+
# Theory of Mind — Shared Facts
|
|
1324
|
+
# ---------------------------------------------------------------------------
|
|
1325
|
+
|
|
1326
|
+
class SharedFactCreateRequest(BaseModel):
|
|
1327
|
+
contact_id: str
|
|
1328
|
+
fact: str
|
|
1329
|
+
source: Literal["told_by_contact", "told_to_contact", "shared_context", "inferred"] = "shared_context"
|
|
1330
|
+
confidence: float = Field(0.8, ge=0.0, le=1.0)
|
|
1331
|
+
expires_at: Optional[str] = None
|
|
1332
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
class SharedFactUpdateRequest(BaseModel):
|
|
1336
|
+
fact: Optional[str] = None
|
|
1337
|
+
confidence: Optional[float] = Field(None, ge=0.0, le=1.0)
|
|
1338
|
+
expires_at: Optional[str] = None
|
|
1339
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1340
|
+
|
|
1341
|
+
|
|
1342
|
+
class SharedFactResponse(BaseModel):
|
|
1343
|
+
id: str
|
|
1344
|
+
contact_id: str
|
|
1345
|
+
fact: str
|
|
1346
|
+
source: str
|
|
1347
|
+
confidence: float
|
|
1348
|
+
created_at: str
|
|
1349
|
+
expires_at: Optional[str] = None
|
|
1350
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
class SharedFactListResponse(BaseModel):
|
|
1354
|
+
facts: List[SharedFactResponse] = []
|
|
1355
|
+
total: int
|
|
1356
|
+
limit: int
|
|
1357
|
+
offset: int
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
# ---------------------------------------------------------------------------
|
|
1361
|
+
# Pattern Extraction
|
|
1362
|
+
# ---------------------------------------------------------------------------
|
|
1363
|
+
|
|
1364
|
+
class PatternCreateRequest(BaseModel):
|
|
1365
|
+
pattern_type: Literal["entity_cooccurrence", "relation_frequency", "temporal_sequence", "attribute_cluster"]
|
|
1366
|
+
description: str
|
|
1367
|
+
pattern_key: str
|
|
1368
|
+
frequency: int = 1
|
|
1369
|
+
confidence: float = Field(0.5, ge=0.0, le=1.0)
|
|
1370
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1371
|
+
source: Literal["extraction", "manual", "inferred"] = "extraction"
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
class PatternResponse(BaseModel):
|
|
1375
|
+
id: str
|
|
1376
|
+
pattern_type: str
|
|
1377
|
+
description: str
|
|
1378
|
+
pattern_key: str
|
|
1379
|
+
frequency: int
|
|
1380
|
+
last_seen: str
|
|
1381
|
+
first_seen: str
|
|
1382
|
+
confidence: float
|
|
1383
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1384
|
+
source: str
|
|
1385
|
+
active: bool = True
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
class PatternListResponse(BaseModel):
|
|
1389
|
+
patterns: List[PatternResponse] = []
|
|
1390
|
+
total: int
|
|
1391
|
+
limit: int
|
|
1392
|
+
offset: int
|
|
1393
|
+
|
|
1394
|
+
|
|
1395
|
+
class PatternUpdateRequest(BaseModel):
|
|
1396
|
+
description: Optional[str] = None
|
|
1397
|
+
confidence: Optional[float] = Field(None, ge=0.0, le=1.0)
|
|
1398
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
1399
|
+
active: Optional[bool] = None
|
|
1400
|
+
|
|
1401
|
+
|
|
1402
|
+
class PatternExtractResponse(BaseModel):
|
|
1403
|
+
new: int = 0
|
|
1404
|
+
updated: int = 0
|
|
1405
|
+
total: int = 0
|
|
1406
|
+
reason: Optional[str] = None
|
|
1407
|
+
|
|
1408
|
+
|
|
1409
|
+
# ---------------------------------------------------------------------------
|
|
1410
|
+
# Surprise Engine
|
|
1411
|
+
# ---------------------------------------------------------------------------
|
|
1412
|
+
|
|
1413
|
+
class SurpriseCreateRequest(BaseModel):
|
|
1414
|
+
observation: str
|
|
1415
|
+
expected: Optional[str] = None
|
|
1416
|
+
surprise_score: Optional[float] = Field(None, ge=0.0, le=1.0)
|
|
1417
|
+
pattern_id: Optional[str] = None
|
|
1418
|
+
context: Optional[Dict[str, Any]] = None
|
|
1419
|
+
auto_score: bool = False
|
|
1420
|
+
|
|
1421
|
+
|
|
1422
|
+
class SurpriseResponse(BaseModel):
|
|
1423
|
+
id: str
|
|
1424
|
+
observation: str
|
|
1425
|
+
expected: Optional[str] = None
|
|
1426
|
+
surprise_score: float
|
|
1427
|
+
pattern_id: Optional[str] = None
|
|
1428
|
+
context: Optional[Dict[str, Any]] = None
|
|
1429
|
+
timestamp: str
|
|
1430
|
+
resolved: bool = False
|
|
1431
|
+
resolution: Optional[str] = None
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
class SurpriseListResponse(BaseModel):
|
|
1435
|
+
surprises: List[SurpriseResponse] = []
|
|
1436
|
+
total: int
|
|
1437
|
+
limit: int
|
|
1438
|
+
offset: int
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
class SurpriseResolveRequest(BaseModel):
|
|
1442
|
+
resolution: Optional[str] = None
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
# ---------------------------------------------------------------------------
|
|
1446
|
+
# ToM LLM Extraction
|
|
1447
|
+
# ---------------------------------------------------------------------------
|
|
1448
|
+
|
|
1449
|
+
class TomExtractRequest(BaseModel):
|
|
1450
|
+
conversation_text: str
|
|
1451
|
+
contact_id: str
|
|
1452
|
+
session_id: Optional[str] = None
|
|
1453
|
+
extract_affect: bool = True
|
|
1454
|
+
extract_facts: bool = True
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
class TomExtractResponse(BaseModel):
|
|
1458
|
+
affect: Optional[Dict[str, Any]] = None
|
|
1459
|
+
facts: List[Dict[str, Any]] = []
|
|
1460
|
+
throttled: bool = False
|
|
1461
|
+
|
|
1462
|
+
|
|
1463
|
+
# ---------------------------------------------------------------------------
|
|
1464
|
+
# World Model — Entities
|
|
1465
|
+
# ---------------------------------------------------------------------------
|
|
1466
|
+
|
|
1467
|
+
class WorldEntityCreateRequest(BaseModel):
|
|
1468
|
+
name: str
|
|
1469
|
+
entity_type: str
|
|
1470
|
+
aliases: Optional[List[str]] = []
|
|
1471
|
+
external_ids: Optional[Dict[str, str]] = {}
|
|
1472
|
+
confidence: float = 0.5
|
|
1473
|
+
properties: Optional[Dict[str, Any]] = {}
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
class WorldEntityUpdateRequest(BaseModel):
|
|
1477
|
+
name: Optional[str] = None
|
|
1478
|
+
confidence: Optional[float] = None
|
|
1479
|
+
properties: Optional[Dict[str, Any]] = None
|
|
1480
|
+
aliases: Optional[List[str]] = None
|
|
1481
|
+
|
|
1482
|
+
|
|
1483
|
+
class WorldEntityDetailResponse(BaseModel):
|
|
1484
|
+
id: str
|
|
1485
|
+
name: str
|
|
1486
|
+
entity_type: str
|
|
1487
|
+
aliases: List[str] = []
|
|
1488
|
+
external_ids: Dict[str, str] = {}
|
|
1489
|
+
confidence: float = 0.5
|
|
1490
|
+
properties: Dict[str, Any] = {}
|
|
1491
|
+
first_seen: Optional[str] = None
|
|
1492
|
+
last_seen: Optional[str] = None
|
|
1493
|
+
created_at: Optional[str] = None
|
|
1494
|
+
updated_at: Optional[str] = None
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
class WorldEntityListResponse(BaseModel):
|
|
1498
|
+
entities: List[WorldEntityDetailResponse] = []
|
|
1499
|
+
total: int = 0
|
|
1500
|
+
|
|
1501
|
+
|
|
1502
|
+
# ---------------------------------------------------------------------------
|
|
1503
|
+
# World Model — Relationships
|
|
1504
|
+
# ---------------------------------------------------------------------------
|
|
1505
|
+
|
|
1506
|
+
class WorldRelationshipCreateRequest(BaseModel):
|
|
1507
|
+
source_id: str
|
|
1508
|
+
target_id: str
|
|
1509
|
+
relationship_type: str
|
|
1510
|
+
confidence: float = 0.5
|
|
1511
|
+
valid_from: Optional[str] = None
|
|
1512
|
+
properties: Optional[Dict[str, Any]] = {}
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
class WorldRelationshipUpdateRequest(BaseModel):
|
|
1516
|
+
confidence: Optional[float] = None
|
|
1517
|
+
valid_to: Optional[str] = None
|
|
1518
|
+
properties: Optional[Dict[str, Any]] = None
|
|
1519
|
+
|
|
1520
|
+
|
|
1521
|
+
class WorldRelationshipResponse(BaseModel):
|
|
1522
|
+
id: str
|
|
1523
|
+
source_id: str
|
|
1524
|
+
target_id: str
|
|
1525
|
+
relationship_type: str
|
|
1526
|
+
confidence: float = 0.5
|
|
1527
|
+
valid_from: Optional[str] = None
|
|
1528
|
+
valid_to: Optional[str] = None
|
|
1529
|
+
properties: Dict[str, Any] = {}
|
|
1530
|
+
is_active: bool = True
|
|
1531
|
+
created_at: Optional[str] = None
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
class WorldRelationshipListResponse(BaseModel):
|
|
1535
|
+
relationships: List[WorldRelationshipResponse] = []
|
|
1536
|
+
total: int = 0
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
# ---------------------------------------------------------------------------
|
|
1540
|
+
# World Model — Graph Traversal
|
|
1541
|
+
# ---------------------------------------------------------------------------
|
|
1542
|
+
|
|
1543
|
+
class WorldNeighborhoodResponse(BaseModel):
|
|
1544
|
+
center: Optional[WorldEntityDetailResponse] = None
|
|
1545
|
+
reachable: List[WorldEntityDetailResponse] = []
|
|
1546
|
+
edges: List[WorldRelationshipResponse] = []
|
|
1547
|
+
hop_counts: Dict[str, int] = {}
|
|
1548
|
+
truncated: bool = False
|
|
1549
|
+
|
|
1550
|
+
|
|
1551
|
+
class WorldPathResponse(BaseModel):
|
|
1552
|
+
source_id: str
|
|
1553
|
+
target_id: str
|
|
1554
|
+
path: Optional[List[WorldRelationshipResponse]] = None
|
|
1555
|
+
found: bool = False
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
class WorldStatsResponse(BaseModel):
|
|
1559
|
+
total_entities: int = 0
|
|
1560
|
+
entities_by_type: Dict[str, int] = {}
|
|
1561
|
+
total_relationships: int = 0
|
|
1562
|
+
active_relationships: int = 0
|
|
1563
|
+
total_observations: int = 0
|
|
1564
|
+
merge_proposals_pending: int = 0
|
|
1565
|
+
|
|
1566
|
+
|
|
1567
|
+
# ---------------------------------------------------------------------------
|
|
1568
|
+
# Multi-Agent — Agent Management (v0.7.0)
|
|
1569
|
+
# ---------------------------------------------------------------------------
|
|
1570
|
+
|
|
1571
|
+
class AgentInviteRequest(BaseModel):
|
|
1572
|
+
expires_in_seconds: int = Field(default=900, ge=60, le=86400)
|
|
1573
|
+
max_uses: int = Field(default=1, ge=1, le=100)
|
|
1574
|
+
granted_capabilities: List[str] = Field(default_factory=lambda: ["messaging"])
|
|
1575
|
+
granted_is_primary: bool = False
|
|
1576
|
+
granted_max_concurrent: int = Field(default=5, ge=1, le=100)
|
|
1577
|
+
label: Optional[str] = None
|
|
1578
|
+
|
|
1579
|
+
|
|
1580
|
+
class AgentInviteResponse(BaseModel):
|
|
1581
|
+
code: str
|
|
1582
|
+
expires_at: str
|
|
1583
|
+
max_uses: int
|
|
1584
|
+
setup_command: str
|
|
1585
|
+
|
|
1586
|
+
|
|
1587
|
+
class AgentConnectRequest(BaseModel):
|
|
1588
|
+
setup_code: str
|
|
1589
|
+
node_id: Optional[str] = None
|
|
1590
|
+
node_public_key: str
|
|
1591
|
+
name: str
|
|
1592
|
+
capabilities: List[str] = Field(default_factory=list)
|
|
1593
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
class AgentNodeCert(BaseModel):
|
|
1597
|
+
colony_id: str
|
|
1598
|
+
node_id: str
|
|
1599
|
+
public_key: str
|
|
1600
|
+
signature: str
|
|
1601
|
+
issued_at: str
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
class AgentConnectResponse(BaseModel):
|
|
1605
|
+
agent_id: str
|
|
1606
|
+
node_id: str
|
|
1607
|
+
colony_id: str
|
|
1608
|
+
node_cert: AgentNodeCert
|
|
1609
|
+
websocket_url: str
|
|
1610
|
+
capabilities: List[str]
|
|
1611
|
+
is_primary: bool
|
|
1612
|
+
max_concurrent: int
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
class AgentRegisterRequest(BaseModel):
|
|
1616
|
+
agent_id: Optional[str] = None
|
|
1617
|
+
node_id: Optional[str] = None
|
|
1618
|
+
name: str
|
|
1619
|
+
connection_mode: Literal["local", "remote"] = "local"
|
|
1620
|
+
gateway_url: Optional[str] = None
|
|
1621
|
+
capabilities: List[str] = Field(default_factory=list)
|
|
1622
|
+
is_primary: bool = False
|
|
1623
|
+
priority: int = Field(default=0, ge=0, le=100)
|
|
1624
|
+
max_concurrent: int = Field(default=5, ge=1, le=100)
|
|
1625
|
+
excluded_types: List[str] = Field(default_factory=list)
|
|
1626
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
class AgentRegisterResponse(BaseModel):
|
|
1630
|
+
agent_id: str
|
|
1631
|
+
node_id: str
|
|
1632
|
+
colony_id: str
|
|
1633
|
+
websocket_url: Optional[str] = None
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
class AgentHeartbeatRequest(BaseModel):
|
|
1637
|
+
status: Literal["online", "busy", "offline"] = "online"
|
|
1638
|
+
current_assignments: int = Field(default=0, ge=0)
|
|
1639
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
class AgentMetadataSchema(BaseModel):
|
|
1643
|
+
hostname: Optional[str] = None
|
|
1644
|
+
platform: Optional[str] = None
|
|
1645
|
+
version: Optional[str] = None
|
|
1646
|
+
harness: Optional[str] = None
|
|
1647
|
+
timezone: Optional[str] = None
|
|
1648
|
+
|
|
1649
|
+
|
|
1650
|
+
class AgentResponse(BaseModel):
|
|
1651
|
+
agent_id: str
|
|
1652
|
+
node_id: Optional[str] = None
|
|
1653
|
+
name: str
|
|
1654
|
+
colony_id: str
|
|
1655
|
+
connection_mode: Literal["local", "remote"]
|
|
1656
|
+
gateway_url: Optional[str] = None
|
|
1657
|
+
capabilities: List[str]
|
|
1658
|
+
is_primary: bool
|
|
1659
|
+
priority: int
|
|
1660
|
+
max_concurrent: int
|
|
1661
|
+
excluded_types: List[str]
|
|
1662
|
+
status: Literal["online", "busy", "offline", "suspended", "revoked"]
|
|
1663
|
+
current_assignments: int
|
|
1664
|
+
metadata: AgentMetadataSchema = AgentMetadataSchema()
|
|
1665
|
+
registered_at: str
|
|
1666
|
+
last_seen_at: Optional[str] = None
|
|
1667
|
+
|
|
1668
|
+
|
|
1669
|
+
class AgentListResponse(BaseModel):
|
|
1670
|
+
agents: List[AgentResponse]
|
|
1671
|
+
total: int
|
|
1672
|
+
|
|
1673
|
+
|
|
1674
|
+
class AgentHealthResponse(BaseModel):
|
|
1675
|
+
agents: List[Dict[str, Any]]
|
|
1676
|
+
websocket_endpoint: str
|
|
1677
|
+
|
|
1678
|
+
|
|
1679
|
+
class AgentUpdateRequest(BaseModel):
|
|
1680
|
+
name: Optional[str] = None
|
|
1681
|
+
capabilities: Optional[List[str]] = None
|
|
1682
|
+
is_primary: Optional[bool] = None
|
|
1683
|
+
priority: Optional[int] = None
|
|
1684
|
+
max_concurrent: Optional[int] = None
|
|
1685
|
+
excluded_types: Optional[List[str]] = None
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
# ---------------------------------------------------------------------------
|
|
1689
|
+
# Multi-Agent — Initiative Management (v0.7.0)
|
|
1690
|
+
# ---------------------------------------------------------------------------
|
|
1691
|
+
|
|
1692
|
+
class InitiativeCreateRequest(BaseModel):
|
|
1693
|
+
initiative_type: Literal[
|
|
1694
|
+
"PROACTIVE_MESSAGE", "CALENDAR_REMINDER", "TASK_SUGGESTION",
|
|
1695
|
+
"RESEARCH_DEEP_DIVE", "SKILL_EVICT", "CODING"
|
|
1696
|
+
]
|
|
1697
|
+
title: str
|
|
1698
|
+
description: str
|
|
1699
|
+
priority: int = Field(default=0, ge=0, le=100)
|
|
1700
|
+
timeout_seconds: int = Field(default=3600, ge=60, le=86400)
|
|
1701
|
+
context: Dict[str, Any] = Field(default_factory=dict)
|
|
1702
|
+
entity_id: Optional[str] = None
|
|
1703
|
+
target_agent_id: Optional[str] = None
|
|
1704
|
+
dedup_key: Optional[str] = None
|
|
1705
|
+
|
|
1706
|
+
|
|
1707
|
+
class InitiativeResponse(BaseModel):
|
|
1708
|
+
id: str
|
|
1709
|
+
initiative_type: str
|
|
1710
|
+
title: str
|
|
1711
|
+
description: str
|
|
1712
|
+
priority: int
|
|
1713
|
+
status: Literal[
|
|
1714
|
+
"pending", "assigned", "acknowledged", "in_progress",
|
|
1715
|
+
"completed", "failed", "cancelled",
|
|
1716
|
+
]
|
|
1717
|
+
timeout_seconds: int
|
|
1718
|
+
context: Dict[str, Any]
|
|
1719
|
+
# v0.16.0: durability contract for the context snapshot —
|
|
1720
|
+
# 'durable' (safe to act on as-is) or 'volatile' (check
|
|
1721
|
+
# context_captured_at against the type's freshness TTL first).
|
|
1722
|
+
context_durability: Optional[str] = None
|
|
1723
|
+
# The SUBJECT of the initiative (a person, a PR, a commitment) —
|
|
1724
|
+
# distinct from target/assigned agent (who EXECUTES it).
|
|
1725
|
+
entity_id: Optional[str] = None
|
|
1726
|
+
target_agent_id: Optional[str]
|
|
1727
|
+
assigned_agent_id: Optional[str]
|
|
1728
|
+
dedup_key: Optional[str]
|
|
1729
|
+
result: Optional[Dict[str, Any]]
|
|
1730
|
+
error_message: Optional[str]
|
|
1731
|
+
created_at: str
|
|
1732
|
+
acknowledged_at: Optional[str]
|
|
1733
|
+
completed_at: Optional[str]
|
|
1734
|
+
failed_at: Optional[str]
|
|
1735
|
+
expires_at: Optional[str]
|
|
1736
|
+
|
|
1737
|
+
|
|
1738
|
+
class InitiativeListResponse(BaseModel):
|
|
1739
|
+
initiatives: List[InitiativeResponse]
|
|
1740
|
+
total: int
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
class InitiativeClaimRequest(BaseModel):
|
|
1744
|
+
agent_id: str
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
class InitiativeCompleteRequest(BaseModel):
|
|
1748
|
+
agent_id: str
|
|
1749
|
+
result: Dict[str, Any] = Field(default_factory=dict)
|
|
1750
|
+
|
|
1751
|
+
|
|
1752
|
+
class InitiativeFailRequest(BaseModel):
|
|
1753
|
+
agent_id: str
|
|
1754
|
+
error_message: str
|
|
1755
|
+
|
|
1756
|
+
|
|
1757
|
+
class InitiativeDelegateRequest(BaseModel):
|
|
1758
|
+
target_agent_id: str
|
|
1759
|
+
reason: Optional[str] = None
|
|
1760
|
+
|
|
1761
|
+
|
|
1762
|
+
class InitiativePriorityRequest(BaseModel):
|
|
1763
|
+
priority: int = Field(ge=0, le=100)
|
|
1764
|
+
|
|
1765
|
+
|
|
1766
|
+
# --- Agent Snapshot ---------------------------------------------------------
|
|
1767
|
+
|
|
1768
|
+
class AgentSnapshotInitiative(BaseModel):
|
|
1769
|
+
id: str
|
|
1770
|
+
type: str
|
|
1771
|
+
description: str
|
|
1772
|
+
priority: float
|
|
1773
|
+
status: str
|
|
1774
|
+
rationale: Optional[str] = None
|
|
1775
|
+
action_hint: Optional[str] = None
|
|
1776
|
+
entity_id: Optional[str] = None
|
|
1777
|
+
dedup_key: Optional[str] = None
|
|
1778
|
+
created_at: str
|
|
1779
|
+
expires_at: Optional[str] = None
|
|
1780
|
+
assigned_agent_id: Optional[str] = None
|
|
1781
|
+
acknowledged_at: Optional[str] = None
|
|
1782
|
+
completed_at: Optional[str] = None
|
|
1783
|
+
failed_at: Optional[str] = None
|
|
1784
|
+
failed_reason: Optional[str] = None
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
class AgentSnapshotResponse(BaseModel):
|
|
1788
|
+
timestamp: str
|
|
1789
|
+
telemetry: Dict[str, Any]
|
|
1790
|
+
pending_initiatives: List[AgentSnapshotInitiative]
|
|
1791
|
+
pending_count: int
|
|
1792
|
+
assigned_count: int
|
|
1793
|
+
failed_count: int
|
|
1794
|
+
recently_completed: List[AgentSnapshotInitiative]
|
|
1795
|
+
autonomy_mode: str
|
|
1796
|
+
autonomy_running: bool
|
|
1797
|
+
last_tick_age_minutes: Optional[float] = None
|
|
1798
|
+
flags: List[str]
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
class RecordOutreachRequest(BaseModel):
|
|
1802
|
+
# Agent identity is deployment-specific — configure COLONY_AGENT_NAME
|
|
1803
|
+
# rather than relying on this generic fallback.
|
|
1804
|
+
agent_id: str = Field(
|
|
1805
|
+
default_factory=lambda: _os.environ.get("COLONY_AGENT_NAME", "agent")
|
|
1806
|
+
)
|
|
1807
|
+
channel: str = "whatsapp"
|
|
1808
|
+
contact_id: Optional[str] = None
|
|
1809
|
+
reason: Optional[str] = None
|
|
1810
|
+
|
|
1811
|
+
|
|
1812
|
+
class RecordOutreachResponse(BaseModel):
|
|
1813
|
+
recorded_at: str
|
|
1814
|
+
last_agent_outreach_at: str
|
|
1815
|
+
|
|
1816
|
+
|
|
1817
|
+
# --- Session Reports & Context Digest -----------------------------------------
|
|
1818
|
+
|
|
1819
|
+
class AgentSnapshotSystemState(BaseModel):
|
|
1820
|
+
"""Reusable system-state component for context digest."""
|
|
1821
|
+
|
|
1822
|
+
autonomy_running: bool
|
|
1823
|
+
mode: str
|
|
1824
|
+
last_tick_age_minutes: Optional[float] = None
|
|
1825
|
+
silence_hours: Dict[str, Any] = Field(default_factory=dict)
|
|
1826
|
+
stale_flags: List[str] = Field(default_factory=list)
|
|
1827
|
+
|
|
1828
|
+
|
|
1829
|
+
class SessionReportRequest(BaseModel):
|
|
1830
|
+
session_id: str
|
|
1831
|
+
contact_id: str
|
|
1832
|
+
started_at: str # ISO datetime
|
|
1833
|
+
ended_at: Optional[str] = None
|
|
1834
|
+
summary: str
|
|
1835
|
+
topics: List[str] = Field(default_factory=list)
|
|
1836
|
+
resolutions: List[str] = Field(default_factory=list)
|
|
1837
|
+
pending: List[str] = Field(default_factory=list)
|
|
1838
|
+
notified_user: bool = False
|
|
1839
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
1840
|
+
|
|
1841
|
+
|
|
1842
|
+
class SessionReportResponse(BaseModel):
|
|
1843
|
+
stored: bool
|
|
1844
|
+
report_id: str
|
|
1845
|
+
|
|
1846
|
+
|
|
1847
|
+
class ContextDigestSessionReport(BaseModel):
|
|
1848
|
+
report_id: str
|
|
1849
|
+
started_at: str
|
|
1850
|
+
ended_at: Optional[str] = None
|
|
1851
|
+
summary: str
|
|
1852
|
+
topics: List[str] = Field(default_factory=list)
|
|
1853
|
+
resolutions: List[str] = Field(default_factory=list)
|
|
1854
|
+
pending: List[str] = Field(default_factory=list)
|
|
1855
|
+
notified_user: bool = False
|
|
1856
|
+
|
|
1857
|
+
|
|
1858
|
+
class ContextDigestResponse(BaseModel):
|
|
1859
|
+
generated_at: str
|
|
1860
|
+
contact_id: Optional[str] = None
|
|
1861
|
+
session_reports: List[ContextDigestSessionReport] = Field(default_factory=list)
|
|
1862
|
+
pending_initiatives: List[AgentSnapshotInitiative] = Field(default_factory=list)
|
|
1863
|
+
system_state: AgentSnapshotSystemState
|
|
1864
|
+
last_outreach: Dict[str, Any] = Field(default_factory=dict)
|
|
1865
|
+
|
|
1866
|
+
|
|
1867
|
+
# ── Trust scopes (context-scoped authorization) ──────────────────────────────
|
|
1868
|
+
|
|
1869
|
+
class ScopeAuthzResponse(BaseModel):
|
|
1870
|
+
"""Whether a sender is authorized WITHIN a scope (group). Says nothing about 1:1."""
|
|
1871
|
+
authorized: bool
|
|
1872
|
+
scope_id: Optional[str] = None
|
|
1873
|
+
granted_tier: Optional[str] = None
|
|
1874
|
+
contact_id: Optional[str] = None
|
|
1875
|
+
active: bool = False
|
|
1876
|
+
|
|
1877
|
+
|
|
1878
|
+
class ScopeMemberIn(BaseModel):
|
|
1879
|
+
gateway: Optional[str] = None # handle gateway (resolve / auto-create a shadow)
|
|
1880
|
+
address: Optional[str] = None # handle address
|
|
1881
|
+
contact_id: Optional[str] = None # or a known contact directly
|
|
1882
|
+
name: Optional[str] = None # display name for an auto-created shadow
|
|
1883
|
+
role: str = "member"
|
|
1884
|
+
|
|
1885
|
+
|
|
1886
|
+
class ScopeCreateRequest(BaseModel):
|
|
1887
|
+
platform: str
|
|
1888
|
+
external_id: str # the group/conversation id on the platform
|
|
1889
|
+
label: Optional[str] = None
|
|
1890
|
+
scope_type: str = "group"
|
|
1891
|
+
granted_tier: str = "group_guest"
|
|
1892
|
+
created_by: str = "agent"
|
|
1893
|
+
members: List[ScopeMemberIn] = Field(default_factory=list)
|
|
1894
|
+
|
|
1895
|
+
|
|
1896
|
+
class ScopeResponse(BaseModel):
|
|
1897
|
+
scope_id: str
|
|
1898
|
+
scope_type: str
|
|
1899
|
+
platform: Optional[str] = None
|
|
1900
|
+
external_id: Optional[str] = None
|
|
1901
|
+
label: Optional[str] = None
|
|
1902
|
+
granted_tier: str
|
|
1903
|
+
active: bool
|
|
1904
|
+
members: List[str] = Field(default_factory=list) # contact_ids
|
|
1905
|
+
|
|
1906
|
+
|
|
1907
|
+
class ScopeDeactivateRequest(BaseModel):
|
|
1908
|
+
scope_id: Optional[str] = None
|
|
1909
|
+
platform: Optional[str] = None
|
|
1910
|
+
external_id: Optional[str] = None
|
|
1911
|
+
|
|
1912
|
+
|
|
1913
|
+
class ScopePromoteRequest(BaseModel):
|
|
1914
|
+
contact_id: str
|
|
1915
|
+
to_tier: str = "regular"
|
|
1916
|
+
|
|
1917
|
+
|
|
1918
|
+
class ResponseGuardCheckRequest(BaseModel):
|
|
1919
|
+
"""A host asks the gate to evaluate an outbound reply before sending it."""
|
|
1920
|
+
surface: ResponseGuardSurfaceName
|
|
1921
|
+
response_text: str
|
|
1922
|
+
incoming_message_text: Optional[str] = None
|
|
1923
|
+
trust_tier: Optional[str] = None
|
|
1924
|
+
target_contact_id: Optional[str] = None
|
|
1925
|
+
target_gateway: Optional[str] = None
|
|
1926
|
+
session_id: Optional[str] = None
|
|
1927
|
+
turn_id: Optional[str] = None
|
|
1928
|
+
conversation_key: Optional[str] = None
|
|
1929
|
+
mentioned_entities: Optional[List[str]] = None
|
|
1930
|
+
mode: Optional[Literal["shadow", "enforce"]] = None
|
|
1931
|
+
# Optional, exact host-owned purpose/disclosure binding. This narrows the
|
|
1932
|
+
# candidate's permitted use; its literal-false capability fields cannot
|
|
1933
|
+
# grant authority or select owner-private context.
|
|
1934
|
+
communication_policy: Optional[CommunicationPolicyContextV1] = None
|
|
1935
|
+
# A request may strengthen shadow to enforce. It cannot weaken a server
|
|
1936
|
+
# configured for enforce; ResponseGuardSurfacePolicyV1 resolves the mode.
|
|
1937
|
+
# Legacy compatibility input. The host API never treats a caller-declared
|
|
1938
|
+
# boolean as owner authority; trusted in-process paths derive that fact from
|
|
1939
|
+
# server-owned identity state.
|
|
1940
|
+
authorized: bool = False
|
|
1941
|
+
|
|
1942
|
+
@model_validator(mode="after")
|
|
1943
|
+
def _communication_policy_matches_target(self) -> "ResponseGuardCheckRequest":
|
|
1944
|
+
policy = self.communication_policy
|
|
1945
|
+
if policy is not None and self.target_contact_id != policy.target_contact_id:
|
|
1946
|
+
raise ValueError(
|
|
1947
|
+
"communication policy target must match target_contact_id"
|
|
1948
|
+
)
|
|
1949
|
+
return self
|