polyrob 0.5.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.
- agents/README.md +453 -0
- agents/__init__.py +164 -0
- agents/base_agent.py +743 -0
- agents/personality/character.py +119 -0
- agents/personality/character_manager.py +309 -0
- agents/personality/characters/rob.character.json +56 -0
- agents/personality/characters/trump.character.json +63 -0
- agents/personality/persona_render.py +78 -0
- agents/personality/persona_resolver.py +115 -0
- agents/prompt/__init__.py +58 -0
- agents/prompt/base_prompt.py +92 -0
- agents/prompt/system.py +417 -0
- agents/task/README_PATH_MANAGEMENT.md +141 -0
- agents/task/__init__.py +162 -0
- agents/task/agent/__init__.py +70 -0
- agents/task/agent/agent_state.py +408 -0
- agents/task/agent/async_delegation.py +274 -0
- agents/task/agent/autonomy_state.py +275 -0
- agents/task/agent/conversation.py +75 -0
- agents/task/agent/core/__init__.py +6 -0
- agents/task/agent/core/aux_metering.py +61 -0
- agents/task/agent/core/background_review.py +157 -0
- agents/task/agent/core/construction.py +1179 -0
- agents/task/agent/core/conversational_exit.py +49 -0
- agents/task/agent/core/correspondent_gate.py +227 -0
- agents/task/agent/core/curator.py +246 -0
- agents/task/agent/core/episodic_digest.py +103 -0
- agents/task/agent/core/error_recovery.py +480 -0
- agents/task/agent/core/history_io.py +257 -0
- agents/task/agent/core/llm_provisioning.py +287 -0
- agents/task/agent/core/llm_runner.py +547 -0
- agents/task/agent/core/logging_io.py +276 -0
- agents/task/agent/core/loop_detection.py +262 -0
- agents/task/agent/core/memory_prefetch.py +325 -0
- agents/task/agent/core/memory_writer.py +667 -0
- agents/task/agent/core/model_introspection.py +82 -0
- agents/task/agent/core/model_swap.py +177 -0
- agents/task/agent/core/next_action_internal.py +1331 -0
- agents/task/agent/core/output_validation.py +303 -0
- agents/task/agent/core/project_context.py +272 -0
- agents/task/agent/core/resources.py +93 -0
- agents/task/agent/core/result_processing.py +389 -0
- agents/task/agent/core/run_loop.py +661 -0
- agents/task/agent/core/safety_lifecycle.py +228 -0
- agents/task/agent/core/secret_guard.py +293 -0
- agents/task/agent/core/self_wake.py +280 -0
- agents/task/agent/core/session_metadata.py +104 -0
- agents/task/agent/core/step.py +781 -0
- agents/task/agent/core/step_execution.py +398 -0
- agents/task/agent/core/step_telemetry.py +222 -0
- agents/task/agent/core/test_aux_metering.py +50 -0
- agents/task/agent/core/test_billing_failover.py +68 -0
- agents/task/agent/core/test_fatal_error_classifier.py +38 -0
- agents/task/agent/core/test_judge_validation.py +275 -0
- agents/task/agent/core/test_model_swap.py +190 -0
- agents/task/agent/core/test_reflection_offload.py +54 -0
- agents/task/agent/core/turn_input.py +8 -0
- agents/task/agent/core/untrusted_wrap.py +103 -0
- agents/task/agent/core/user_ingress.py +228 -0
- agents/task/agent/hitl_manager.py +396 -0
- agents/task/agent/log_sanitize.py +36 -0
- agents/task/agent/message_manager/config.py +97 -0
- agents/task/agent/message_manager/service.py +758 -0
- agents/task/agent/message_manager/tests.py +305 -0
- agents/task/agent/message_manager/tool_call_builder.py +539 -0
- agents/task/agent/message_manager/tool_message_repair.py +364 -0
- agents/task/agent/message_manager/views.py +143 -0
- agents/task/agent/messages/__init__.py +8 -0
- agents/task/agent/messages/builders.py +309 -0
- agents/task/agent/messages/compactor.py +611 -0
- agents/task/agent/messages/context_references.py +271 -0
- agents/task/agent/messages/filters.py +333 -0
- agents/task/agent/messages/guidance.py +328 -0
- agents/task/agent/messages/persistence.py +448 -0
- agents/task/agent/messages/retrieval.py +506 -0
- agents/task/agent/messages/sqlite_persistence.py +85 -0
- agents/task/agent/messages/test_compaction_upgrade.py +349 -0
- agents/task/agent/messages/test_persistence_subdir_fix.py +28 -0
- agents/task/agent/messages/test_sqlite_persistence.py +54 -0
- agents/task/agent/messages/token_counter.py +532 -0
- agents/task/agent/orchestrator.py +776 -0
- agents/task/agent/profile_manager.py +105 -0
- agents/task/agent/profile_registry.py +173 -0
- agents/task/agent/prompts.py +1090 -0
- agents/task/agent/scenario_registry.py +226 -0
- agents/task/agent/service.py +509 -0
- agents/task/agent/session.py +984 -0
- agents/task/agent/skill_discovery.py +110 -0
- agents/task/agent/skill_frontmatter.py +94 -0
- agents/task/agent/skill_manager.py +1201 -0
- agents/task/agent/skill_store.py +627 -0
- agents/task/agent/skill_validation.py +56 -0
- agents/task/agent/skill_writer.py +492 -0
- agents/task/agent/sub_agent_manager.py +1137 -0
- agents/task/agent/test_session_disk_recovery.py +34 -0
- agents/task/agent/tests.py +513 -0
- agents/task/agent/tool_call_tracker.py +511 -0
- agents/task/agent/views.py +469 -0
- agents/task/config.py +432 -0
- agents/task/constants.py +1384 -0
- agents/task/flag_defaults.py +63 -0
- agents/task/goals/__init__.py +1 -0
- agents/task/goals/autonomy_marker.py +28 -0
- agents/task/goals/board.py +690 -0
- agents/task/goals/completion_judge.py +247 -0
- agents/task/goals/context.py +62 -0
- agents/task/goals/dispatcher.py +848 -0
- agents/task/goals/escalation.py +102 -0
- agents/task/goals/planner.py +114 -0
- agents/task/logging_config.py +155 -0
- agents/task/path.py +991 -0
- agents/task/robust_parse_config.py +400 -0
- agents/task/runtime/__init__.py +0 -0
- agents/task/runtime/run_as_session.py +130 -0
- agents/task/runtime_safety.py +308 -0
- agents/task/session/__init__.py +5 -0
- agents/task/session/browser_pool.py +130 -0
- agents/task/session/cleanup.py +612 -0
- agents/task/session/execution.py +397 -0
- agents/task/session/feed.py +200 -0
- agents/task/session/hitl_ingress.py +201 -0
- agents/task/session/hooks.py +83 -0
- agents/task/session/multi_agent.py +243 -0
- agents/task/session/workspace.py +91 -0
- agents/task/session_registry.py +91 -0
- agents/task/session_route.py +35 -0
- agents/task/sqlite_session_registry.py +261 -0
- agents/task/surface_config.py +185 -0
- agents/task/telemetry/__init__.py +58 -0
- agents/task/telemetry/event_log.py +180 -0
- agents/task/telemetry/formatters.py +642 -0
- agents/task/telemetry/manager.py +571 -0
- agents/task/telemetry/memory_events.py +66 -0
- agents/task/telemetry/self_events.py +53 -0
- agents/task/telemetry/sequence.py +160 -0
- agents/task/telemetry/service.py +1265 -0
- agents/task/telemetry/views.py +882 -0
- agents/task/templates.py +98 -0
- agents/task/test_aux_chain.py +151 -0
- agents/task/test_aux_router.py +41 -0
- agents/task/tests/test_parse_robustness.py +170 -0
- agents/task/tool_defaults.py +110 -0
- agents/task/utils.py +762 -0
- agents/task/utils_json.py +768 -0
- agents/task/utils_webview.py +86 -0
- agents/task/workspace_context.py +229 -0
- agents/task_agent_lite.py +2398 -0
- api/README.md +683 -0
- api/TASK_API_DOCS.md +151 -0
- api/__init__.py +0 -0
- api/a2a/__init__.py +37 -0
- api/a2a/agent_card.py +337 -0
- api/a2a/client.py +657 -0
- api/a2a/endpoints.py +375 -0
- api/a2a/models.py +268 -0
- api/a2a/streaming.py +419 -0
- api/a2a/task_handler.py +929 -0
- api/admin_endpoints.py +1584 -0
- api/app.py +923 -0
- api/auth_constants.py +28 -0
- api/auth_endpoints.py +402 -0
- api/auth_state.py +36 -0
- api/chat_via_task.py +42 -0
- api/conversation_manager.py +231 -0
- api/dependencies.py +186 -0
- api/eip8004_endpoints.py +452 -0
- api/hyperliquid_models.py +174 -0
- api/hyperliquid_routes.py +450 -0
- api/interfaces.py +207 -0
- api/jwt_middleware.py +83 -0
- api/kb/__init__.py +1 -0
- api/kb/endpoints.py +314 -0
- api/mcp_models.py +279 -0
- api/mcp_routes.py +438 -0
- api/middleware.py +526 -0
- api/models.py +176 -0
- api/openai_compat/__init__.py +0 -0
- api/openai_compat/model_map.py +25 -0
- api/openai_compat/models.py +59 -0
- api/openai_compat/router.py +140 -0
- api/payment_endpoints.py +444 -0
- api/payment_verification.py +138 -0
- api/polymarket_models.py +155 -0
- api/polymarket_routes.py +501 -0
- api/pricing_endpoints.py +89 -0
- api/session_routing.py +54 -0
- api/skill_endpoints.py +453 -0
- api/task_http_api.py +1856 -0
- api/webhooks.py +52 -0
- api/x402_endpoints.py +280 -0
- avatar/README.md +44 -0
- avatar/__init__.py +1 -0
- avatar/config/rob.json +7 -0
- avatar/mindprint.js +395 -0
- avatar/renders/rob.meta.json +20 -0
- avatar/renders/rob.png +0 -0
- avatar/studio.html +373 -0
- avatar/webview/avatar-live.js +44 -0
- cli/README.md +89 -0
- cli/__init__.py +0 -0
- cli/cli_surface.py +67 -0
- cli/commands/__init__.py +0 -0
- cli/commands/_bootstrap.py +49 -0
- cli/commands/_errors.py +53 -0
- cli/commands/chat.py +973 -0
- cli/commands/config.py +100 -0
- cli/commands/dashboard.py +103 -0
- cli/commands/doctor.py +222 -0
- cli/commands/email.py +174 -0
- cli/commands/gateway.py +346 -0
- cli/commands/goals.py +509 -0
- cli/commands/init.py +276 -0
- cli/commands/journey.py +30 -0
- cli/commands/kb.py +280 -0
- cli/commands/model.py +107 -0
- cli/commands/owner.py +431 -0
- cli/commands/pfp.py +232 -0
- cli/commands/run.py +414 -0
- cli/commands/serve.py +41 -0
- cli/commands/session.py +684 -0
- cli/commands/skill_install.py +786 -0
- cli/commands/skills.py +128 -0
- cli/commands/subagents.py +100 -0
- cli/commands/surface.py +81 -0
- cli/commands/telegram.py +185 -0
- cli/commands/todos.py +209 -0
- cli/commands/tools.py +102 -0
- cli/commands/update.py +316 -0
- cli/commands/whatsapp.py +175 -0
- cli/config_store.py +276 -0
- cli/gitignore.py +43 -0
- cli/inventory.py +46 -0
- cli/keys.py +101 -0
- cli/persona.py +17 -0
- cli/polyrob.py +137 -0
- cli/ui/__init__.py +64 -0
- cli/ui/activity.py +141 -0
- cli/ui/app.py +538 -0
- cli/ui/banner.py +233 -0
- cli/ui/blocks.py +534 -0
- cli/ui/bootstrap_notice.py +47 -0
- cli/ui/commands/__init__.py +41 -0
- cli/ui/commands/h_cron.py +64 -0
- cli/ui/commands/h_journey.py +164 -0
- cli/ui/commands/h_kb.py +121 -0
- cli/ui/commands/h_learn.py +100 -0
- cli/ui/commands/h_mcp.py +215 -0
- cli/ui/commands/h_self.py +113 -0
- cli/ui/commands/h_skills.py +314 -0
- cli/ui/commands/handlers.py +1672 -0
- cli/ui/commands/registry.py +426 -0
- cli/ui/dialog.py +425 -0
- cli/ui/event_registry.py +110 -0
- cli/ui/event_specs.py +45 -0
- cli/ui/events.py +433 -0
- cli/ui/identity.py +15 -0
- cli/ui/lifecycle.py +159 -0
- cli/ui/live_hooks.py +43 -0
- cli/ui/model_selector.py +532 -0
- cli/ui/persistent_loop.py +181 -0
- cli/ui/pick.py +113 -0
- cli/ui/plain_renderer.py +351 -0
- cli/ui/renderer.py +384 -0
- cli/ui/rich_renderer.py +533 -0
- cli/ui/secrets.py +115 -0
- cli/ui/state.py +376 -0
- cli/ui/statusbar.py +231 -0
- cli/ui/streaming.py +254 -0
- cli/ui/terminal_render.py +105 -0
- cli/ui/theme.py +132 -0
- cli/update/__init__.py +6 -0
- cli/update/context.py +121 -0
- cli/update/detect.py +176 -0
- cli/update/engine.py +95 -0
- cli/update/migrate_guarded.py +55 -0
- cli/update/process_guard.py +215 -0
- cli/update/runners.py +78 -0
- cli/update/snapshot.py +270 -0
- cli/update/versions.py +205 -0
- core/README.md +377 -0
- core/__init__.py +174 -0
- core/assets.py +87 -0
- core/async_bridge.py +76 -0
- core/autonomy_runtime.py +259 -0
- core/base_component.py +302 -0
- core/bootstrap.py +681 -0
- core/bot.py +310 -0
- core/config.py +833 -0
- core/constants.py +126 -0
- core/container.py +462 -0
- core/db_manifest.py +101 -0
- core/embedding.py +57 -0
- core/env.py +39 -0
- core/exceptions.py +287 -0
- core/flags.py +144 -0
- core/flags_catalog.py +345 -0
- core/home_migration.py +62 -0
- core/identity.py +118 -0
- core/initialization.py +1004 -0
- core/instance.py +537 -0
- core/interactive_gate.py +96 -0
- core/logging.py +436 -0
- core/owner_doc_writer.py +176 -0
- core/pairing.py +193 -0
- core/path_safety.py +20 -0
- core/paths.py +27 -0
- core/payment_config.py +21 -0
- core/permissions.py +322 -0
- core/runtime_config.py +96 -0
- core/runtime_paths.py +135 -0
- core/seams.py +35 -0
- core/secret_scan.py +25 -0
- core/secret_scrub.py +71 -0
- core/secrets.py +35 -0
- core/security_logging_filter.py +148 -0
- core/self_context_writer.py +333 -0
- core/self_evolution.py +294 -0
- core/session_context.py +47 -0
- core/sqlite_util.py +59 -0
- core/surfaces/__init__.py +16 -0
- core/surfaces/access.py +118 -0
- core/surfaces/binding.py +88 -0
- core/surfaces/bootstrap.py +78 -0
- core/surfaces/circuit.py +168 -0
- core/surfaces/continuity.py +77 -0
- core/surfaces/correspondents.py +228 -0
- core/surfaces/dispatcher.py +216 -0
- core/surfaces/envelopes.py +75 -0
- core/surfaces/gc.py +30 -0
- core/surfaces/idempotency.py +57 -0
- core/surfaces/inbound_webhook.py +124 -0
- core/surfaces/media.py +32 -0
- core/surfaces/message_router.py +91 -0
- core/surfaces/outbound_allowlist.py +80 -0
- core/surfaces/outbound_dispatcher.py +110 -0
- core/surfaces/outbound_mirror.py +37 -0
- core/surfaces/outbound_queue.py +107 -0
- core/surfaces/outbound_target.py +12 -0
- core/surfaces/owner_admin.py +29 -0
- core/surfaces/proactive.py +78 -0
- core/surfaces/progress.py +108 -0
- core/surfaces/rate_bucket.py +21 -0
- core/surfaces/registry.py +51 -0
- core/surfaces/rendering.py +53 -0
- core/surfaces/send_policy.py +14 -0
- core/surfaces/serialize.py +24 -0
- core/surfaces/session_chat_registry.py +112 -0
- core/surfaces/session_policy.py +60 -0
- core/surfaces/surface.py +288 -0
- core/surfaces/transcription.py +88 -0
- core/surfaces/voice_echo.py +26 -0
- core/surfaces/voice_guard.py +23 -0
- core/tickers.py +174 -0
- core/tool_catalog.py +192 -0
- core/version.py +75 -0
- core/wallet/__init__.py +5 -0
- core/wallet/agent_wallet.py +59 -0
- core/wallet/audit_sink.py +61 -0
- core/wallet/config.py +70 -0
- core/wallet/factory.py +87 -0
- core/wallet/policy.py +104 -0
- core/wallet/signer.py +51 -0
- cron/README.md +65 -0
- cron/__init__.py +0 -0
- cron/delivery.py +277 -0
- cron/digest.py +124 -0
- cron/jobs.py +207 -0
- cron/runner.py +297 -0
- cron/schedule.py +194 -0
- cron/scheduler.py +201 -0
- cron/service.py +57 -0
- cron/wake_gate.py +223 -0
- data/__init__.py +1 -0
- data/prompts/autov2_prompts.json +87 -0
- data/prompts/skills/browser-automation/SKILL.md +43 -0
- data/prompts/skills/coding-workflow/SKILL.md +36 -0
- data/prompts/skills/crypto-trading-safety/SKILL.md +53 -0
- data/prompts/skills/document-writing/SKILL.md +33 -0
- data/prompts/skills/email-comms/SKILL.md +33 -0
- data/prompts/skills/file-data-ops/SKILL.md +35 -0
- data/prompts/skills/hyperliquid-account-review/SKILL.md +48 -0
- data/prompts/skills/hyperliquid-market-data/SKILL.md +52 -0
- data/prompts/skills/hyperliquid-trading/SKILL.md +59 -0
- data/prompts/skills/lead-research/SKILL.md +86 -0
- data/prompts/skills/market-research-brief/SKILL.md +104 -0
- data/prompts/skills/person-analyzer/SKILL.md +124 -0
- data/prompts/skills/polymarket-market-research/SKILL.md +54 -0
- data/prompts/skills/polymarket-portfolio-review/SKILL.md +50 -0
- data/prompts/skills/polymarket-trading/SKILL.md +55 -0
- data/prompts/skills/presentation-creator/SKILL.md +36 -0
- data/prompts/skills/project-analyzer/SKILL.md +169 -0
- data/prompts/skills/rules.json +268 -0
- data/prompts/skills/secret-handling/SKILL.md +20 -0
- data/prompts/skills/skill-authoring/SKILL.md +31 -0
- data/prompts/skills/skill-security-review/SKILL.md +27 -0
- data/prompts/skills/social-discovery/SKILL.md +57 -0
- data/prompts/skills/task-planning/SKILL.md +33 -0
- data/prompts/skills/web-research/SKILL.md +39 -0
- data/prompts/skills/web-scraping/SKILL.md +73 -0
- data/prompts/skills/x-engagement/SKILL.md +69 -0
- data/prompts/system_prompts.json +4 -0
- data/subscription_channels.json +5 -0
- modules/README.md +503 -0
- modules/__init__.py +124 -0
- modules/auth/__init__.py +13 -0
- modules/auth/api_key_manager.py +157 -0
- modules/auth/identity_mapper.py +380 -0
- modules/auth/siwe_auth.py +273 -0
- modules/auth/tier_manager.py +173 -0
- modules/base_module.py +190 -0
- modules/credits/__init__.py +29 -0
- modules/credits/balance_manager.py +237 -0
- modules/credits/cost_utils.py +129 -0
- modules/credits/pricing.py +139 -0
- modules/credits/unified_ledger.py +148 -0
- modules/credits/usage_meter.py +310 -0
- modules/credits/usage_tracker.py +674 -0
- modules/database/__init__.py +33 -0
- modules/database/audit_log.py +322 -0
- modules/database/auth_tables.py +276 -0
- modules/database/connection.py +644 -0
- modules/database/connection_pool.py +305 -0
- modules/database/conversation_contexts.py +446 -0
- modules/database/database_manager.py +237 -0
- modules/database/hyperliquid.py +375 -0
- modules/database/polymarket.py +574 -0
- modules/database/user_mcp_servers.py +728 -0
- modules/database/user_profiles.py +562 -0
- modules/database/utils.py +107 -0
- modules/database/x402_tables.py +92 -0
- modules/eip8004/README.md +1069 -0
- modules/eip8004/__init__.py +65 -0
- modules/eip8004/contracts.py +498 -0
- modules/eip8004/models.py +271 -0
- modules/eip8004/registration.py +148 -0
- modules/eip8004/reputation.py +367 -0
- modules/eip8004/validation.py +277 -0
- modules/llm/__init__.py +97 -0
- modules/llm/adapters.py +963 -0
- modules/llm/anthropic_client.py +831 -0
- modules/llm/available_models.py +106 -0
- modules/llm/brain_scrubber.py +137 -0
- modules/llm/cache_hints.py +162 -0
- modules/llm/deepseek_client.py +562 -0
- modules/llm/gemini_client.py +1367 -0
- modules/llm/llm_client.py +1139 -0
- modules/llm/llm_client_registry.py +188 -0
- modules/llm/llm_factory.py +237 -0
- modules/llm/llm_manager.py +1036 -0
- modules/llm/messages.py +374 -0
- modules/llm/model_registry.py +1935 -0
- modules/llm/nvidia_client.py +125 -0
- modules/llm/openai_client.py +800 -0
- modules/llm/openrouter_client.py +969 -0
- modules/llm/profiles.py +178 -0
- modules/llm/test_anthropic_cache_capture.py +35 -0
- modules/llm/test_cached_pricing_derivation.py +24 -0
- modules/llm/think_scrubber.py +444 -0
- modules/llm/token_counter.py +268 -0
- modules/memory/__init__.py +35 -0
- modules/memory/backend_factory.py +83 -0
- modules/memory/cache_manager.py +186 -0
- modules/memory/episodic.py +108 -0
- modules/memory/local_vector_memory_provider.py +552 -0
- modules/memory/memory_manager.py +225 -0
- modules/memory/models.py +312 -0
- modules/memory/provider.py +210 -0
- modules/memory/registry.py +205 -0
- modules/memory/sqlite_memory_provider.py +767 -0
- modules/memory/task/__init__.py +52 -0
- modules/memory/task/compaction_manager.py +157 -0
- modules/memory/task/context_retriever.py +809 -0
- modules/memory/task/hierarchical_memory.py +1002 -0
- modules/memory/task/lexical_retriever.py +71 -0
- modules/memory/task/null_context_manager.py +213 -0
- modules/memory/task/phase_manager.py +625 -0
- modules/memory/task/reflection_service.py +157 -0
- modules/memory/task/semantic_retriever.py +218 -0
- modules/memory/task/task_context_manager.py +1165 -0
- modules/memory/task/test_forgetting_engages.py +24 -0
- modules/memory/task/test_reflection_llm.py +39 -0
- modules/memory/task/test_threat_scan.py +53 -0
- modules/memory/task/threat_scan.py +90 -0
- modules/memory/test_sqlite_memory_provider.py +106 -0
- modules/memory/user_profile_manager.py +527 -0
- modules/payments/__init__.py +11 -0
- modules/payments/deposit_monitor.py +478 -0
- modules/payments/price_oracle.py +70 -0
- modules/payments/treasury_sweeper.py +401 -0
- modules/payments/wallet_generator.py +145 -0
- modules/pfp/__init__.py +1 -0
- modules/pfp/config.py +92 -0
- modules/pfp/mesh.py +565 -0
- modules/pfp/push.py +69 -0
- modules/pfp/renderer.py +85 -0
- modules/pfp/store.py +82 -0
- modules/skills/__init__.py +1 -0
- modules/skills/skill_usage.py +248 -0
- modules/transcription/__init__.py +24 -0
- modules/transcription/base.py +20 -0
- modules/transcription/faster_whisper_transcriber.py +55 -0
- modules/x402/README.md +249 -0
- modules/x402/__init__.py +22 -0
- modules/x402/invoicing.py +416 -0
- modules/x402/middleware.py +364 -0
- modules/x402/settlement_watcher.py +145 -0
- modules/x402/x402_integration.py +344 -0
- polyrob-0.5.0.dist-info/METADATA +482 -0
- polyrob-0.5.0.dist-info/RECORD +745 -0
- polyrob-0.5.0.dist-info/WHEEL +5 -0
- polyrob-0.5.0.dist-info/entry_points.txt +2 -0
- polyrob-0.5.0.dist-info/licenses/LICENSE +21 -0
- polyrob-0.5.0.dist-info/top_level.txt +12 -0
- surfaces/README.md +70 -0
- surfaces/__init__.py +0 -0
- surfaces/email/__init__.py +0 -0
- surfaces/email/dedup.py +44 -0
- surfaces/email/harness.py +187 -0
- surfaces/email/inbound.py +159 -0
- surfaces/email/seed.py +60 -0
- surfaces/email/surface.py +105 -0
- surfaces/telegram/__init__.py +0 -0
- surfaces/telegram/dedup.py +83 -0
- surfaces/telegram/harness.py +886 -0
- surfaces/telegram/inbound.py +145 -0
- surfaces/telegram/interactive_tools.py +49 -0
- surfaces/telegram/markdown.py +347 -0
- surfaces/telegram/rate_limit.py +167 -0
- surfaces/telegram/surface.py +187 -0
- surfaces/telegram/voice.py +52 -0
- surfaces/whatsapp/__init__.py +0 -0
- surfaces/whatsapp/client.py +51 -0
- surfaces/whatsapp/harness.py +62 -0
- surfaces/whatsapp/inbound.py +132 -0
- surfaces/whatsapp/surface.py +64 -0
- surfaces/whatsapp/window.py +34 -0
- tools/README.md +578 -0
- tools/__init__.py +424 -0
- tools/alchemy/__init__.py +5 -0
- tools/alchemy/alchemy_tool.py +389 -0
- tools/anysite/__init__.py +17 -0
- tools/anysite/client.py +88 -0
- tools/anysite/tool.py +89 -0
- tools/base_tool.py +468 -0
- tools/browser/__init__.py +22 -0
- tools/browser/actions.py +118 -0
- tools/browser/browser.py +1457 -0
- tools/browser/browser_manager.py +690 -0
- tools/browser/context.py +1748 -0
- tools/browser/playwright_utils.py +137 -0
- tools/browser/views.py +56 -0
- tools/code_exec/SANDBOX_SECURITY.md +144 -0
- tools/code_exec/__init__.py +178 -0
- tools/code_exec/backend.py +73 -0
- tools/code_exec/backends/__init__.py +1 -0
- tools/code_exec/backends/docker.py +779 -0
- tools/code_exec/backends/local_subprocess.py +154 -0
- tools/code_exec/env_policy.py +45 -0
- tools/code_exec/result.py +42 -0
- tools/code_exec/sandbox_guard.py +59 -0
- tools/code_exec/tool.py +227 -0
- tools/coding/__init__.py +50 -0
- tools/coding/edit.py +107 -0
- tools/coding/search.py +113 -0
- tools/coding/tool.py +353 -0
- tools/collabland/__init__.py +5 -0
- tools/collabland/collabland_tool.py +471 -0
- tools/controller/__init__.py +0 -0
- tools/controller/_helpers.py +165 -0
- tools/controller/action_registration.py +1765 -0
- tools/controller/approval.py +244 -0
- tools/controller/approval_interactive.py +90 -0
- tools/controller/delegation.py +195 -0
- tools/controller/execution.py +797 -0
- tools/controller/execution_context.py +141 -0
- tools/controller/hooks.py +135 -0
- tools/controller/introspection.py +344 -0
- tools/controller/mcp_registrar.py +190 -0
- tools/controller/message_send.py +31 -0
- tools/controller/registry/__init__.py +4 -0
- tools/controller/registry/schema_generators.py +395 -0
- tools/controller/registry/schema_sanitizer.py +406 -0
- tools/controller/registry/service.py +1266 -0
- tools/controller/registry/views.py +151 -0
- tools/controller/service.py +409 -0
- tools/controller/tool_management.py +334 -0
- tools/controller/types.py +28 -0
- tools/controller/views.py +450 -0
- tools/cronjob_tools.py +166 -0
- tools/crypto_trade_gate.py +59 -0
- tools/descriptors.py +452 -0
- tools/dom/__init__.py +0 -0
- tools/dom/history_tree_processor/service.py +244 -0
- tools/dom/history_tree_processor/view.py +99 -0
- tools/dom/service.py +471 -0
- tools/dom/views.py +346 -0
- tools/email_tool.py +403 -0
- tools/exceptions.py +169 -0
- tools/filesystem.py +1038 -0
- tools/filesystem_docproc.py +331 -0
- tools/filesystem_pdf.py +755 -0
- tools/git/__init__.py +42 -0
- tools/git/tool.py +258 -0
- tools/github/__init__.py +33 -0
- tools/github/client.py +94 -0
- tools/github/tool.py +237 -0
- tools/goal_tools.py +309 -0
- tools/hyperliquid/__init__.py +56 -0
- tools/hyperliquid/models.py +233 -0
- tools/hyperliquid/service.py +1680 -0
- tools/knowledge_ingest.py +950 -0
- tools/mcp/README.md +535 -0
- tools/mcp/__init__.py +52 -0
- tools/mcp/catalog.py +115 -0
- tools/mcp/config.py +337 -0
- tools/mcp/mcp_tool.py +1415 -0
- tools/mcp/param_coercion.py +289 -0
- tools/mcp/protocol.py +1520 -0
- tools/mcp/rate_limit.py +50 -0
- tools/mcp/security.py +424 -0
- tools/mcp/self_install.py +111 -0
- tools/mcp/server_manager.py +829 -0
- tools/mcp/subscriptions.py +72 -0
- tools/mcp/user_mcp_service.py +899 -0
- tools/mcp/validation_tracker.py +89 -0
- tools/mcp/views.py +346 -0
- tools/oauth/__init__.py +17 -0
- tools/oauth/manager.py +75 -0
- tools/oauth/provider.py +69 -0
- tools/oauth/providers/__init__.py +1 -0
- tools/oauth/providers/generic_oauth2.py +96 -0
- tools/perplexity_tool.py +280 -0
- tools/polymarket/__init__.py +41 -0
- tools/polymarket/clob_adapter.py +76 -0
- tools/polymarket/models.py +182 -0
- tools/polymarket/service.py +2082 -0
- tools/self_env/__init__.py +61 -0
- tools/self_env/tool.py +274 -0
- tools/shell/__init__.py +80 -0
- tools/shell/backend_pool.py +118 -0
- tools/shell/discipline.py +62 -0
- tools/shell/executor.py +157 -0
- tools/shell/loopback_allow.py +87 -0
- tools/shell/process_registry.py +113 -0
- tools/shell/process_tool.py +131 -0
- tools/shell/state.py +129 -0
- tools/shell/tool.py +151 -0
- tools/task_tool.py +637 -0
- tools/twitter_tool.py +2086 -0
- tools/user_directory.py +179 -0
- tools/web_fetch/__init__.py +3 -0
- tools/web_fetch/fetcher.py +144 -0
- tools/web_fetch/render.py +44 -0
- tools/web_fetch/tool.py +60 -0
- tools/x402/__init__.py +60 -0
- tools/x402/client.py +47 -0
- tools/x402/invoice_tool.py +143 -0
- tools/x402/real_client.py +250 -0
- tools/x402/service.py +131 -0
- utils/README.md +498 -0
- utils/__init__.py +46 -0
- utils/auth_utils.py +114 -0
- utils/bounded_collections.py +162 -0
- utils/circuit_breaker.py +389 -0
- utils/gif_utils.py +435 -0
- utils/markdown_utils.py +291 -0
- utils/message_utils.py +147 -0
- utils/metrics.py +36 -0
- utils/path_validator.py +227 -0
- utils/rate_limit_manager.py +399 -0
- utils/result_size.py +296 -0
- utils/time_utils.py +206 -0
- utils/user_utils.py +188 -0
- webview/README.md +111 -0
- webview/RENAME_AND_ALIGN_HANDOFF.md +200 -0
- webview/__init__.py +8 -0
- webview/activity.py +636 -0
- webview/owner_auth.py +108 -0
- webview/pages.py +448 -0
- webview/repair_sessions.py +399 -0
- webview/server.py +4323 -0
- webview/server_launcher.py +112 -0
- webview/static/css/activity.css +89 -0
- webview/static/css/chat.css +1772 -0
- webview/static/css/components.css +1190 -0
- webview/static/css/config-panel.css +651 -0
- webview/static/css/pages/admin.css +766 -0
- webview/static/css/pages/profile.css +231 -0
- webview/static/css/pages/settings.css +297 -0
- webview/static/css/pages/signin.css +316 -0
- webview/static/css/style.css +4250 -0
- webview/static/css/variables.css +147 -0
- webview/static/css/workspace-fullwidth-fix.css +109 -0
- webview/static/img/favicon.ico +0 -0
- webview/static/js/activity.js +394 -0
- webview/static/js/admin/activity.js +186 -0
- webview/static/js/admin/dashboard.js +163 -0
- webview/static/js/admin/user_detail.js +400 -0
- webview/static/js/admin/users.js +174 -0
- webview/static/js/admin/utils.js +214 -0
- webview/static/js/chat.js +3178 -0
- webview/static/js/config-panel.js +522 -0
- webview/static/js/constants.js +20 -0
- webview/static/js/error-handler.js +226 -0
- webview/static/js/ethers.min.js +1 -0
- webview/static/js/event-filter.js +137 -0
- webview/static/js/event-store.js +351 -0
- webview/static/js/file-attachments.js +374 -0
- webview/static/js/file-loader.js +163 -0
- webview/static/js/index.js +103 -0
- webview/static/js/performance-utils.js +196 -0
- webview/static/js/profile.js +396 -0
- webview/static/js/screenshot.js +386 -0
- webview/static/js/session.js +1527 -0
- webview/static/js/settings.js +1288 -0
- webview/static/js/sidebar-data.js +766 -0
- webview/static/js/sidebar-toggle.js +296 -0
- webview/static/js/socket.io.min.js +7 -0
- webview/static/js/stats.js +355 -0
- webview/static/js/ui-utils.js +420 -0
- webview/static/js/workspace.js +966 -0
- webview/stats_service.py +613 -0
- webview/templates/__init__.py +1 -0
- webview/templates/__pycache__/__init__.cpython-311.pyc +0 -0
- webview/templates/activity.html +36 -0
- webview/templates/admin/activity.html +122 -0
- webview/templates/admin/dashboard.html +112 -0
- webview/templates/admin/user_detail.html +228 -0
- webview/templates/admin/users.html +105 -0
- webview/templates/autonomy.html +60 -0
- webview/templates/error.html +133 -0
- webview/templates/finance.html +90 -0
- webview/templates/identity.html +73 -0
- webview/templates/index.html +42 -0
- webview/templates/layout.html +125 -0
- webview/templates/memory.html +59 -0
- webview/templates/owner_login.html +15 -0
- webview/templates/profile.html +121 -0
- webview/templates/session.html +312 -0
- webview/templates/settings.html +534 -0
- webview/templates/sidebar.html +112 -0
- webview/templates/signin.html +213 -0
- webview/templates/status.html +14 -0
- webview/templates/system.html +45 -0
- webview/webgate.py +196 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""One persona resolver for every surface (T1-07, 2026-07-06 structural review).
|
|
2
|
+
|
|
3
|
+
Before this module, two live persona SSOTs were split by surface: the chat_once
|
|
4
|
+
path rendered the default character JSON (via CharacterManager +
|
|
5
|
+
render_persona_block) while the CLI rendered the ``templates.py`` persona for
|
|
6
|
+
``POLYROB_PERSONA`` — same instance, contradictory voice, and template-only
|
|
7
|
+
guidance (e.g. trading's "Never executes trades") shipped on one surface only.
|
|
8
|
+
|
|
9
|
+
Single precedence, applied identically everywhere:
|
|
10
|
+
|
|
11
|
+
1. Gate: ``task_personality_block_enabled()`` off -> ``""``.
|
|
12
|
+
2. Explicit ``POLYROB_PERSONA``: a known template key renders that template's
|
|
13
|
+
persona; any other non-empty value is used as LITERAL free-form persona text.
|
|
14
|
+
3. The default character, rendered by the pure ``render_persona_block``:
|
|
15
|
+
- async path (:func:`resolve_persona`): the container's ``character_manager``;
|
|
16
|
+
- sync path (:func:`resolve_persona_sync`): the default character JSON read
|
|
17
|
+
directly, mirroring CharacterManager's directory precedence
|
|
18
|
+
(``<data_dir>/characters`` when it holds ``*.character.json``, else the
|
|
19
|
+
package ``agents/personality/characters``).
|
|
20
|
+
4. ``""`` — byte-identical off-path.
|
|
21
|
+
|
|
22
|
+
Note the pinned SELF-CONTEXT stays authoritative over any persona text
|
|
23
|
+
(<identity>/<source-precedence>, T1-08); persona only styles the voice.
|
|
24
|
+
"""
|
|
25
|
+
import json
|
|
26
|
+
import logging
|
|
27
|
+
import os
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Optional
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _gate_on() -> bool:
|
|
35
|
+
try:
|
|
36
|
+
from agents.task.constants import task_personality_block_enabled
|
|
37
|
+
return task_personality_block_enabled()
|
|
38
|
+
except Exception:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _explicit_persona() -> Optional[str]:
|
|
43
|
+
"""Tier 2: the operator-chosen POLYROB_PERSONA (template key or literal)."""
|
|
44
|
+
val = (os.environ.get("POLYROB_PERSONA") or "").strip()
|
|
45
|
+
if not val:
|
|
46
|
+
return None
|
|
47
|
+
try:
|
|
48
|
+
from agents.task.templates import TEMPLATES, resolve_template_persona
|
|
49
|
+
if val in TEMPLATES:
|
|
50
|
+
return resolve_template_persona(val)
|
|
51
|
+
except Exception:
|
|
52
|
+
pass
|
|
53
|
+
# A non-template value is LITERAL persona text (free-form), rather than
|
|
54
|
+
# silently degrading to the "general" template.
|
|
55
|
+
return val
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _characters_dir() -> Path:
|
|
59
|
+
"""Mirror CharacterManager's precedence without requiring the container."""
|
|
60
|
+
data_dir = (os.environ.get("POLYROB_DATA_DIR") or "data").strip() or "data"
|
|
61
|
+
data_chars = Path(data_dir) / "characters"
|
|
62
|
+
try:
|
|
63
|
+
if data_chars.exists() and list(data_chars.glob("*.character.json")):
|
|
64
|
+
return data_chars
|
|
65
|
+
except Exception:
|
|
66
|
+
pass
|
|
67
|
+
return Path(__file__).parent / "characters"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _default_character_dict() -> Optional[dict]:
|
|
71
|
+
"""Tier 3 (sync): read the default character JSON directly, fail-open."""
|
|
72
|
+
name = (os.environ.get("PERSONALITY_DEFAULT_CHARACTER") or "rob").strip() or "rob"
|
|
73
|
+
char_file = _characters_dir() / f"{name}.character.json"
|
|
74
|
+
try:
|
|
75
|
+
if not char_file.is_file():
|
|
76
|
+
return None
|
|
77
|
+
return json.loads(char_file.read_text(encoding="utf-8"))
|
|
78
|
+
except Exception as e:
|
|
79
|
+
logger.debug(f"default character read skipped: {e}")
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def resolve_persona_sync() -> str:
|
|
84
|
+
"""Persona text for surfaces without an initialized container (CLI/REPL)."""
|
|
85
|
+
if not _gate_on():
|
|
86
|
+
return ""
|
|
87
|
+
explicit = _explicit_persona()
|
|
88
|
+
if explicit is not None:
|
|
89
|
+
return explicit
|
|
90
|
+
from agents.personality.persona_render import render_persona_block
|
|
91
|
+
return render_persona_block(_default_character_dict())
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def resolve_persona(container=None) -> str:
|
|
95
|
+
"""Persona text for async surfaces (chat front door). Same precedence; the
|
|
96
|
+
character tier prefers the container's CharacterManager (honors config-driven
|
|
97
|
+
default-character selection), falling back to the direct file read."""
|
|
98
|
+
if not _gate_on():
|
|
99
|
+
return ""
|
|
100
|
+
explicit = _explicit_persona()
|
|
101
|
+
if explicit is not None:
|
|
102
|
+
return explicit
|
|
103
|
+
from agents.personality.persona_render import render_persona_block
|
|
104
|
+
char_dict = None
|
|
105
|
+
try:
|
|
106
|
+
cm = container.get_service("character_manager") if container else None
|
|
107
|
+
if cm is not None and hasattr(cm, "get_default_character"):
|
|
108
|
+
character = await cm.get_default_character()
|
|
109
|
+
if character:
|
|
110
|
+
char_dict = character.to_dict() if hasattr(character, "to_dict") else character
|
|
111
|
+
except Exception as e:
|
|
112
|
+
logger.debug(f"character_manager persona resolve skipped: {e}")
|
|
113
|
+
if char_dict is None:
|
|
114
|
+
char_dict = _default_character_dict()
|
|
115
|
+
return render_persona_block(char_dict)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Prompt management and composition system.
|
|
2
|
+
|
|
3
|
+
This module provides a comprehensive prompt management system including:
|
|
4
|
+
- Base prompt management functionality
|
|
5
|
+
- JSON-based prompt storage and retrieval
|
|
6
|
+
- Unified prompt composition for different LLM types
|
|
7
|
+
- System prompt management with character integration
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .base_prompt import BasePromptManager
|
|
11
|
+
from .system import SystemPromptManager
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
# H8: UnifiedPromptComposer + PromptPackage (agents/prompt/prompt_composer.py) were
|
|
15
|
+
# dead code — exported but never instantiated anywhere. Retired in the prompt-stack
|
|
16
|
+
# consolidation. The live prompt path is SystemPromptManager / the task agent's
|
|
17
|
+
# SystemPrompt builder.
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
'BasePromptManager',
|
|
21
|
+
'SystemPromptManager'
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
# Version info
|
|
25
|
+
from core.version import __version__ # noqa: F401 (project version SSOT)
|
|
26
|
+
|
|
27
|
+
# Default configuration
|
|
28
|
+
DEFAULT_CONFIG = {
|
|
29
|
+
'max_history_messages': 5,
|
|
30
|
+
'max_knowledge_tokens': 1500,
|
|
31
|
+
'min_relevance_score': 0.6,
|
|
32
|
+
'default_response_type': 'factual'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Response types supported by the system
|
|
36
|
+
RESPONSE_TYPES = {
|
|
37
|
+
'factual': 'Precise and factual responses with source citations',
|
|
38
|
+
'creative': 'Creative responses while maintaining factual accuracy',
|
|
39
|
+
'analysis': 'Detailed analysis with structured format',
|
|
40
|
+
'conversational': 'Natural, engaging dialogue while maintaining accuracy'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Agent types supported by the system
|
|
44
|
+
AGENT_TYPES = {
|
|
45
|
+
'chat_agent': 'Primary conversational agent',
|
|
46
|
+
'task_agent': 'Task automation agent'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# Model types supported by the system
|
|
50
|
+
MODEL_TYPES = {
|
|
51
|
+
'anthropic': 'Anthropic Claude models',
|
|
52
|
+
'openai': 'OpenAI GPT models',
|
|
53
|
+
'default': 'Default text completion models'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Default prompts directory — anchored to the install/repo root (this file is
|
|
57
|
+
# agents/prompt/__init__.py -> parents[2]), NOT the process CWD.
|
|
58
|
+
DEFAULT_PROMPTS_DIR = Path(__file__).resolve().parents[2] / "data" / "prompts"
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Base class for prompt management."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any, Dict, Optional, Union
|
|
5
|
+
from agents.personality.character import Character
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BasePromptManager(ABC):
|
|
9
|
+
"""Abstract base class for prompt management.
|
|
10
|
+
|
|
11
|
+
This class defines the interface for prompt management systems. All prompt managers
|
|
12
|
+
must implement these methods to ensure consistent behavior across the system.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
@abstractmethod
|
|
16
|
+
async def initialize(self) -> None:
|
|
17
|
+
"""Initialize the prompt manager.
|
|
18
|
+
|
|
19
|
+
This method should be called before any other operations.
|
|
20
|
+
It should handle loading prompts from storage and setting up any required resources.
|
|
21
|
+
"""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
async def cleanup(self) -> None:
|
|
26
|
+
"""Clean up resources.
|
|
27
|
+
|
|
28
|
+
This method should be called when the prompt manager is no longer needed.
|
|
29
|
+
It should handle saving prompts and cleaning up any resources.
|
|
30
|
+
"""
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
async def get_prompt(
|
|
35
|
+
self,
|
|
36
|
+
role: str,
|
|
37
|
+
model_type: Optional[str] = None,
|
|
38
|
+
character: Optional[Character] = None
|
|
39
|
+
) -> Union[str, Dict[str, Any]]:
|
|
40
|
+
"""Get a prompt formatted for the specified model type.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
role: The role/key identifying the prompt to retrieve
|
|
44
|
+
model_type: Optional model type to format the prompt for
|
|
45
|
+
character: Optional character to integrate into the prompt
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
The prompt string or a model-specific prompt structure
|
|
49
|
+
"""
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
async def set_prompt(self, role: str, prompt: str) -> None:
|
|
54
|
+
"""Set a prompt for a specific role.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
role: The role/key identifying where to store the prompt
|
|
58
|
+
prompt: The prompt text to store
|
|
59
|
+
"""
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
@abstractmethod
|
|
63
|
+
async def format_for_model(
|
|
64
|
+
self,
|
|
65
|
+
prompt: str,
|
|
66
|
+
model_type: str,
|
|
67
|
+
character: Optional[Character] = None
|
|
68
|
+
) -> Union[str, Dict[str, Any]]:
|
|
69
|
+
"""Format a prompt for a specific model type.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
prompt: The prompt text to format
|
|
73
|
+
model_type: The type of model to format for (e.g., "openai", "anthropic")
|
|
74
|
+
character: Optional character to integrate
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Formatted prompt structure for the specified model
|
|
78
|
+
"""
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
@abstractmethod
|
|
82
|
+
async def integrate_character(self, prompt: str, character: Character) -> str:
|
|
83
|
+
"""Integrate character information into a prompt.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
prompt: The base prompt to integrate the character into
|
|
87
|
+
character: The character information to integrate
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
The prompt with character information integrated
|
|
91
|
+
"""
|
|
92
|
+
pass
|
agents/prompt/system.py
ADDED
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
"""System prompt management with character integration."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
import asyncio
|
|
6
|
+
from typing import Optional, Dict, Any, Union, TYPE_CHECKING
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from core.config import BotConfig
|
|
9
|
+
from core.base_component import BaseComponent
|
|
10
|
+
from agents.personality.character import Character
|
|
11
|
+
from .base_prompt import BasePromptManager
|
|
12
|
+
from utils.message_utils import send_long_message
|
|
13
|
+
from utils.markdown_utils import escape_markdown
|
|
14
|
+
|
|
15
|
+
# aiogram (Telegram SDK) is heavy (~1.3s import) and used ONLY in the Telegram-only
|
|
16
|
+
# display_prompts() path. Keep it out of module load so importing this prompt system
|
|
17
|
+
# (every CLI invocation / server worker boot) does not pull aiogram.
|
|
18
|
+
# See docs/plans/2026-06-26-runtime-architecture-finalization-FUSION.md (P0a).
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from aiogram import types
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SystemPromptManager(BaseComponent, BasePromptManager):
|
|
24
|
+
"""Manages system prompts with character integration."""
|
|
25
|
+
|
|
26
|
+
def __init__(self, name: str, config: BotConfig, container=None, json_file_path: Optional[str] = None):
|
|
27
|
+
"""Initialize the system prompt manager."""
|
|
28
|
+
if not name:
|
|
29
|
+
raise ValueError("Name is required")
|
|
30
|
+
if not config:
|
|
31
|
+
raise ValueError("Config is required")
|
|
32
|
+
|
|
33
|
+
super().__init__(name=name, config=config, container=container)
|
|
34
|
+
self.config = config
|
|
35
|
+
|
|
36
|
+
# Determine the correct file path
|
|
37
|
+
if json_file_path:
|
|
38
|
+
self.json_file_path = Path(json_file_path)
|
|
39
|
+
elif config and hasattr(config, 'data_dir'):
|
|
40
|
+
self.json_file_path = Path(config.data_dir) / "prompts" / "system_prompts.json"
|
|
41
|
+
else:
|
|
42
|
+
self.json_file_path = (
|
|
43
|
+
Path(__file__).resolve().parents[2] / "data" / "prompts" / "system_prompts.json"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
self._prompts = {}
|
|
47
|
+
self._lock = asyncio.Lock()
|
|
48
|
+
|
|
49
|
+
# Log the file path being used
|
|
50
|
+
self.logger.info(f"Using prompts file path: {self.json_file_path}")
|
|
51
|
+
|
|
52
|
+
# Default prompts as fallback
|
|
53
|
+
self.default_prompts = {
|
|
54
|
+
"chat_agent": """You are an AI assistant focused on helpful and accurate responses.
|
|
55
|
+
|
|
56
|
+
Key Guidelines:
|
|
57
|
+
1. Provide clear and accurate information
|
|
58
|
+
2. Be helpful while maintaining appropriate boundaries
|
|
59
|
+
3. Acknowledge uncertainty when present
|
|
60
|
+
4. Stay focused on the user's needs
|
|
61
|
+
5. Maintain a professional and friendly tone"""
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async def _initialize(self) -> None:
|
|
65
|
+
"""Initialize the prompt manager."""
|
|
66
|
+
try:
|
|
67
|
+
# Ensure the prompts directory exists
|
|
68
|
+
self.json_file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
69
|
+
|
|
70
|
+
# Load prompts from JSON if file exists
|
|
71
|
+
if self.json_file_path.exists():
|
|
72
|
+
try:
|
|
73
|
+
self.logger.info(f"Loading prompts from: {self.json_file_path}")
|
|
74
|
+
with self.json_file_path.open('r', encoding='utf-8') as f:
|
|
75
|
+
loaded_prompts = json.load(f)
|
|
76
|
+
# Store loaded prompts
|
|
77
|
+
self._prompts = loaded_prompts
|
|
78
|
+
self.logger.info(f"Loaded {len(self._prompts)} prompts from {self.json_file_path}")
|
|
79
|
+
|
|
80
|
+
# Log loaded roles
|
|
81
|
+
for role in self._prompts:
|
|
82
|
+
self.logger.info(f"Loaded prompt for role: {role}")
|
|
83
|
+
except json.JSONDecodeError as e:
|
|
84
|
+
self.logger.error(f"Error parsing prompts file {self.json_file_path}: {e}")
|
|
85
|
+
self._prompts = {}
|
|
86
|
+
except Exception as e:
|
|
87
|
+
self.logger.error(f"Error loading prompts from {self.json_file_path}: {e}")
|
|
88
|
+
self._prompts = {}
|
|
89
|
+
else:
|
|
90
|
+
self.logger.warning(f"No prompts file found at {self.json_file_path}")
|
|
91
|
+
self._prompts = {}
|
|
92
|
+
|
|
93
|
+
except Exception as e:
|
|
94
|
+
self.logger.error(f"Failed to initialize system prompt manager: {e}")
|
|
95
|
+
raise
|
|
96
|
+
|
|
97
|
+
async def _cleanup(self) -> None:
|
|
98
|
+
"""Clean up resources."""
|
|
99
|
+
try:
|
|
100
|
+
# Save any pending changes
|
|
101
|
+
await self._save_prompts()
|
|
102
|
+
self._prompts.clear()
|
|
103
|
+
self.logger.info("System prompt manager cleaned up successfully")
|
|
104
|
+
except Exception as e:
|
|
105
|
+
self.logger.error(f"Error during cleanup: {e}")
|
|
106
|
+
raise
|
|
107
|
+
|
|
108
|
+
def _read_prompts_sync(self) -> Dict[str, str]:
|
|
109
|
+
"""Read prompts from JSON file synchronously."""
|
|
110
|
+
try:
|
|
111
|
+
if not self.json_file_path.exists():
|
|
112
|
+
return {}
|
|
113
|
+
|
|
114
|
+
with self.json_file_path.open('r', encoding='utf-8') as f:
|
|
115
|
+
return json.load(f)
|
|
116
|
+
except Exception as e:
|
|
117
|
+
self.logger.error(f"Error reading prompts: {e}")
|
|
118
|
+
return {}
|
|
119
|
+
|
|
120
|
+
async def _save_prompts(self) -> None:
|
|
121
|
+
"""Save prompts to JSON file."""
|
|
122
|
+
try:
|
|
123
|
+
async with self._lock:
|
|
124
|
+
with self.json_file_path.open('w', encoding='utf-8') as f:
|
|
125
|
+
json.dump(self._prompts, f, indent=2)
|
|
126
|
+
self.logger.debug(f"Saved prompts to {self.json_file_path}")
|
|
127
|
+
except Exception as e:
|
|
128
|
+
self.logger.error(f"Error saving prompts: {e}")
|
|
129
|
+
raise
|
|
130
|
+
|
|
131
|
+
async def get_prompt(
|
|
132
|
+
self,
|
|
133
|
+
role: str,
|
|
134
|
+
model_type: Optional[str] = None,
|
|
135
|
+
character: Optional[Character] = None,
|
|
136
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
137
|
+
) -> str:
|
|
138
|
+
"""Get system prompt with optional character integration."""
|
|
139
|
+
try:
|
|
140
|
+
if not self._initialized:
|
|
141
|
+
await self.initialize()
|
|
142
|
+
|
|
143
|
+
# First try to get prompt from JSON-loaded prompts
|
|
144
|
+
base_prompt = self._prompts.get(role)
|
|
145
|
+
|
|
146
|
+
# Log prompt source
|
|
147
|
+
if base_prompt:
|
|
148
|
+
self.logger.debug(f"Using JSON prompt for role: {role}")
|
|
149
|
+
else:
|
|
150
|
+
self.logger.warning(f"No JSON prompt found for role {role}, using default")
|
|
151
|
+
base_prompt = self.default_prompts.get(role, "")
|
|
152
|
+
|
|
153
|
+
if not base_prompt:
|
|
154
|
+
self.logger.warning(f"No prompt template found for role: {role}")
|
|
155
|
+
return ""
|
|
156
|
+
|
|
157
|
+
# Start building final prompt
|
|
158
|
+
prompt_parts = []
|
|
159
|
+
|
|
160
|
+
# Add system prompt if available
|
|
161
|
+
if base_prompt:
|
|
162
|
+
prompt_parts.append(base_prompt)
|
|
163
|
+
|
|
164
|
+
# Add character context if available
|
|
165
|
+
if character:
|
|
166
|
+
char_context = self._build_character_context(character)
|
|
167
|
+
if char_context:
|
|
168
|
+
prompt_parts.append(char_context)
|
|
169
|
+
self.logger.debug(f"Added character context for {character.name}")
|
|
170
|
+
|
|
171
|
+
# Add additional context from metadata if available
|
|
172
|
+
if metadata:
|
|
173
|
+
context = self._build_additional_context(metadata)
|
|
174
|
+
if context:
|
|
175
|
+
prompt_parts.append(context)
|
|
176
|
+
self.logger.debug("Added metadata context")
|
|
177
|
+
|
|
178
|
+
# Combine all parts with proper spacing
|
|
179
|
+
final_prompt = "\n\n".join(filter(None, prompt_parts))
|
|
180
|
+
|
|
181
|
+
# Log prompt statistics for troubleshooting
|
|
182
|
+
self.logger.debug(f"Built system prompt for {role}, length: {len(final_prompt)} chars, with character: {character.name if character else 'None'}")
|
|
183
|
+
|
|
184
|
+
return final_prompt
|
|
185
|
+
|
|
186
|
+
except Exception as e:
|
|
187
|
+
self.logger.error(f"Error building system prompt: {e}")
|
|
188
|
+
return self.default_prompts.get(role, "")
|
|
189
|
+
|
|
190
|
+
def _build_character_context(self, character: Character) -> str:
|
|
191
|
+
"""Build character context section."""
|
|
192
|
+
try:
|
|
193
|
+
sections = [
|
|
194
|
+
f"CHARACTER PROFILE:",
|
|
195
|
+
f"Name: {character.name}",
|
|
196
|
+
f"Background: {character.bio}"
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
if character.adjectives:
|
|
200
|
+
sections.append(f"Personality: {', '.join(character.adjectives)}")
|
|
201
|
+
|
|
202
|
+
if character.style.get('speaking'):
|
|
203
|
+
sections.append("Speaking Style:")
|
|
204
|
+
sections.extend(f"- {style}" for style in character.style['speaking'])
|
|
205
|
+
|
|
206
|
+
if character.knowledge:
|
|
207
|
+
sections.append("Knowledge & Expertise:")
|
|
208
|
+
sections.extend(f"- {k}" for k in character.knowledge)
|
|
209
|
+
|
|
210
|
+
if character.topics:
|
|
211
|
+
sections.append("Topics of Interest:")
|
|
212
|
+
sections.extend(f"- {t}" for t in character.topics)
|
|
213
|
+
|
|
214
|
+
return "\n".join(sections)
|
|
215
|
+
|
|
216
|
+
except Exception as e:
|
|
217
|
+
self.logger.error(f"Error building character context: {e}")
|
|
218
|
+
return ""
|
|
219
|
+
|
|
220
|
+
def _build_additional_context(self, metadata: Dict[str, Any]) -> str:
|
|
221
|
+
"""Build additional context section from metadata."""
|
|
222
|
+
try:
|
|
223
|
+
sections = []
|
|
224
|
+
|
|
225
|
+
# Add knowledge context if available
|
|
226
|
+
if metadata.get('knowledge_context'):
|
|
227
|
+
sections.append("RELEVANT KNOWLEDGE:")
|
|
228
|
+
sections.append(metadata['knowledge_context'])
|
|
229
|
+
|
|
230
|
+
# Add conversation mode if available
|
|
231
|
+
if metadata.get('conversation_mode'):
|
|
232
|
+
sections.append(f"Conversation Mode: {metadata['conversation_mode']}")
|
|
233
|
+
|
|
234
|
+
# Add any other relevant metadata
|
|
235
|
+
if metadata.get('additional_instructions'):
|
|
236
|
+
sections.append("Additional Instructions:")
|
|
237
|
+
sections.append(metadata['additional_instructions'])
|
|
238
|
+
|
|
239
|
+
return "\n\n".join(sections) if sections else ""
|
|
240
|
+
|
|
241
|
+
except Exception as e:
|
|
242
|
+
self.logger.error(f"Error building additional context: {e}")
|
|
243
|
+
return ""
|
|
244
|
+
|
|
245
|
+
async def set_prompt(self, role: str, prompt: str) -> None:
|
|
246
|
+
"""Set a prompt for a specific role."""
|
|
247
|
+
try:
|
|
248
|
+
if not self._initialized:
|
|
249
|
+
await self.initialize()
|
|
250
|
+
|
|
251
|
+
# First, reload any existing prompts from disk to avoid overwriting
|
|
252
|
+
try:
|
|
253
|
+
with self.json_file_path.open('r', encoding='utf-8') as f:
|
|
254
|
+
current_prompts = json.load(f)
|
|
255
|
+
# Update our in-memory prompts with latest from disk
|
|
256
|
+
self._prompts.update(current_prompts)
|
|
257
|
+
self.logger.info(f"Reloaded current prompts before update, found {len(current_prompts)} roles")
|
|
258
|
+
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
259
|
+
self.logger.warning(f"Could not reload existing prompts: {e}")
|
|
260
|
+
|
|
261
|
+
async with self._lock:
|
|
262
|
+
# Log previous value if available for debugging
|
|
263
|
+
previous = self._prompts.get(role, "")
|
|
264
|
+
self.logger.info(f"Updating prompt for role '{role}', previous length: {len(previous)}, new length: {len(prompt)}")
|
|
265
|
+
|
|
266
|
+
# Update prompt in memory
|
|
267
|
+
self._prompts[role] = prompt.strip()
|
|
268
|
+
|
|
269
|
+
# Save to file, ensuring directory exists
|
|
270
|
+
self.json_file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
271
|
+
|
|
272
|
+
# Log what we're about to save
|
|
273
|
+
self.logger.info(f"Saving {len(self._prompts)} prompts to {self.json_file_path}")
|
|
274
|
+
for r in self._prompts:
|
|
275
|
+
self.logger.debug(f"Saving prompt for role: {r}, length: {len(self._prompts[r])}")
|
|
276
|
+
|
|
277
|
+
# Save to file
|
|
278
|
+
with self.json_file_path.open('w', encoding='utf-8') as f:
|
|
279
|
+
json.dump(self._prompts, f, indent=2, ensure_ascii=False)
|
|
280
|
+
self.logger.info(f"Successfully saved prompt for role: {role}")
|
|
281
|
+
|
|
282
|
+
except Exception as e:
|
|
283
|
+
self.logger.error(f"Error setting prompt for role '{role}': {e}", exc_info=True)
|
|
284
|
+
raise
|
|
285
|
+
|
|
286
|
+
def _format_for_model_sync(
|
|
287
|
+
self,
|
|
288
|
+
prompt: str,
|
|
289
|
+
model_type: str
|
|
290
|
+
) -> Union[str, Dict[str, Any]]:
|
|
291
|
+
"""Format the prompt for specific model types synchronously."""
|
|
292
|
+
try:
|
|
293
|
+
if model_type == "anthropic":
|
|
294
|
+
return {
|
|
295
|
+
"system": prompt,
|
|
296
|
+
"messages": []
|
|
297
|
+
}
|
|
298
|
+
elif model_type == "openai":
|
|
299
|
+
return {
|
|
300
|
+
"messages": [
|
|
301
|
+
{"role": "system", "content": prompt}
|
|
302
|
+
]
|
|
303
|
+
}
|
|
304
|
+
else:
|
|
305
|
+
return prompt
|
|
306
|
+
|
|
307
|
+
except Exception as e:
|
|
308
|
+
self.logger.error(f"Error formatting prompt for model {model_type}: {e}")
|
|
309
|
+
return prompt
|
|
310
|
+
|
|
311
|
+
def _integrate_character_sync(self, prompt: str, character: Character) -> str:
|
|
312
|
+
"""Integrate character information into the prompt synchronously."""
|
|
313
|
+
try:
|
|
314
|
+
# Build character profile section
|
|
315
|
+
char_sections = [
|
|
316
|
+
"\nCHARACTER PROFILE:",
|
|
317
|
+
f"Name: {character.name}",
|
|
318
|
+
f"Background: {character.bio}",
|
|
319
|
+
f"Personality: {', '.join(character.adjectives)}",
|
|
320
|
+
"\nSPEAKING STYLE:",
|
|
321
|
+
*[f"- {style}" for style in character.style.get('speaking', [])],
|
|
322
|
+
"\nKNOWLEDGE & EXPERTISE:",
|
|
323
|
+
*[f"- {k}" for k in character.knowledge],
|
|
324
|
+
"\nTOPICS OF INTEREST:",
|
|
325
|
+
*[f"- {t}" for t in character.topics],
|
|
326
|
+
"\nEXAMPLE MESSAGES:",
|
|
327
|
+
*[f"- {ex}" for ex in character.messageExamples[:3]]
|
|
328
|
+
]
|
|
329
|
+
|
|
330
|
+
char_profile = "\n".join(char_sections)
|
|
331
|
+
|
|
332
|
+
# Add behavior guidelines
|
|
333
|
+
guidelines = [
|
|
334
|
+
"\nBEHAVIOR GUIDELINES:",
|
|
335
|
+
"1. Maintain this personality consistently",
|
|
336
|
+
"2. Use your expertise and knowledge naturally",
|
|
337
|
+
"3. Express yourself in your unique voice",
|
|
338
|
+
"4. Stay true to your character while being helpful",
|
|
339
|
+
"5. Keep your responses focused and relevant"
|
|
340
|
+
]
|
|
341
|
+
|
|
342
|
+
guidelines_text = "\n".join(guidelines)
|
|
343
|
+
|
|
344
|
+
# Combine all sections
|
|
345
|
+
return f"{prompt}\n\n{char_profile}\n\n{guidelines_text}"
|
|
346
|
+
|
|
347
|
+
except Exception as e:
|
|
348
|
+
self.logger.error(f"Error integrating character: {e}")
|
|
349
|
+
return prompt
|
|
350
|
+
|
|
351
|
+
# Keep these methods for backward compatibility
|
|
352
|
+
async def format_for_model(
|
|
353
|
+
self,
|
|
354
|
+
prompt: str,
|
|
355
|
+
model_type: str,
|
|
356
|
+
character: Optional[Character] = None
|
|
357
|
+
) -> Union[str, Dict[str, Any]]:
|
|
358
|
+
"""Format the prompt for specific model types."""
|
|
359
|
+
return self._format_for_model_sync(prompt, model_type)
|
|
360
|
+
|
|
361
|
+
async def integrate_character(self, prompt: str, character: Character) -> str:
|
|
362
|
+
"""Integrate character information into the prompt."""
|
|
363
|
+
return self._integrate_character_sync(prompt, character)
|
|
364
|
+
|
|
365
|
+
async def format_prompts_display(self) -> str:
|
|
366
|
+
"""Format current prompts for display with proper markdown."""
|
|
367
|
+
try:
|
|
368
|
+
if not self._initialized:
|
|
369
|
+
await self.initialize()
|
|
370
|
+
|
|
371
|
+
sections = ["*System Prompts Management*\n\n*Current Prompts:*\n"]
|
|
372
|
+
|
|
373
|
+
# Format main agent prompt
|
|
374
|
+
sections.append("*Main Agent:*")
|
|
375
|
+
main_prompt = self._prompts.get('chat_agent')
|
|
376
|
+
if main_prompt:
|
|
377
|
+
sections.append("```\n" + main_prompt + "\n```")
|
|
378
|
+
else:
|
|
379
|
+
sections.append("_Not set_")
|
|
380
|
+
|
|
381
|
+
# Format simulator agent prompt
|
|
382
|
+
sections.append("\n*Simulator Agent:*")
|
|
383
|
+
sim_prompt = self._prompts.get('simulator_agent')
|
|
384
|
+
if sim_prompt:
|
|
385
|
+
sections.append("```\n" + sim_prompt + "\n```")
|
|
386
|
+
else:
|
|
387
|
+
sections.append("_Not set_")
|
|
388
|
+
|
|
389
|
+
# Combine all sections with proper escaping
|
|
390
|
+
formatted_text = "\n".join(sections)
|
|
391
|
+
return escape_markdown(formatted_text)
|
|
392
|
+
|
|
393
|
+
except Exception as e:
|
|
394
|
+
self.logger.error(f"Error formatting prompts display: {e}")
|
|
395
|
+
return "❌ Error formatting prompts display"
|
|
396
|
+
|
|
397
|
+
async def display_prompts(self, message: "types.Message") -> None:
|
|
398
|
+
"""Display current prompts using message utils for proper formatting."""
|
|
399
|
+
from aiogram import types
|
|
400
|
+
from aiogram.enums import ParseMode
|
|
401
|
+
try:
|
|
402
|
+
formatted_text = await self.format_prompts_display()
|
|
403
|
+
|
|
404
|
+
# Use send_long_message to handle long prompts
|
|
405
|
+
await send_long_message(
|
|
406
|
+
message=message,
|
|
407
|
+
text=formatted_text,
|
|
408
|
+
parse_mode=ParseMode.MARKDOWN_V2,
|
|
409
|
+
link_preview_options=types.LinkPreviewOptions(is_disabled=True)
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
except Exception as e:
|
|
413
|
+
self.logger.error(f"Error displaying prompts: {e}")
|
|
414
|
+
await message.answer(
|
|
415
|
+
"❌ Error displaying prompts",
|
|
416
|
+
link_preview_options=types.LinkPreviewOptions(is_disabled=True)
|
|
417
|
+
)
|