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
agents/task/templates.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Agent templates — pre-built (toolset, autonomy, persona) bundles.
|
|
2
|
+
|
|
3
|
+
A template is a one-pick shortcut that drives the toolset, autonomy level,
|
|
4
|
+
and a short persona / voice hint written into ~/.polyrob/.env.
|
|
5
|
+
|
|
6
|
+
Design notes:
|
|
7
|
+
- Every ``toolset`` value MUST be a key in ``TOOLSETS`` (tool_defaults.py).
|
|
8
|
+
- No template enables ``code_execution`` or live trade execution.
|
|
9
|
+
- ``trading`` maps to the ``research`` toolset (polymarket/hyperliquid are in
|
|
10
|
+
VALID_TOOL_IDS, but adding a bespoke trading toolset would only add read-only
|
|
11
|
+
ids already covered by ``research``; simpler mapping chosen over scope creep).
|
|
12
|
+
- ``seeded_skills`` is populated for research, coding, social, and trading
|
|
13
|
+
templates; blank and general have no seeded skills.
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from dataclasses import dataclass, field
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class AgentTemplate:
|
|
22
|
+
"""Immutable bundle of defaults for a named agent persona."""
|
|
23
|
+
name: str
|
|
24
|
+
toolset: str
|
|
25
|
+
autonomy: str
|
|
26
|
+
persona: str
|
|
27
|
+
seeded_skills: list[str] = field(default_factory=list)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
# Built-in templates
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
TEMPLATES: dict[str, AgentTemplate] = {
|
|
35
|
+
"general": AgentTemplate(
|
|
36
|
+
name="general",
|
|
37
|
+
toolset="default",
|
|
38
|
+
autonomy="standard",
|
|
39
|
+
persona="Helpful, concise assistant. Strong generalist.",
|
|
40
|
+
),
|
|
41
|
+
"research": AgentTemplate(
|
|
42
|
+
name="research",
|
|
43
|
+
toolset="research",
|
|
44
|
+
autonomy="standard",
|
|
45
|
+
persona="Deep researcher. Thorough, cites sources, stays factual.",
|
|
46
|
+
seeded_skills=["web-research", "market-research-brief", "lead-research"],
|
|
47
|
+
),
|
|
48
|
+
"coding": AgentTemplate(
|
|
49
|
+
name="coding",
|
|
50
|
+
toolset="coding",
|
|
51
|
+
autonomy="standard",
|
|
52
|
+
persona="Expert software engineer. Writes clean, tested, production-quality code.",
|
|
53
|
+
seeded_skills=["coding-workflow", "skill-authoring"],
|
|
54
|
+
),
|
|
55
|
+
"social": AgentTemplate(
|
|
56
|
+
name="social",
|
|
57
|
+
toolset="social",
|
|
58
|
+
autonomy="standard",
|
|
59
|
+
persona="Social-media and content strategist. Engaging, on-brand voice.",
|
|
60
|
+
seeded_skills=["web-scraping", "lead-research"],
|
|
61
|
+
),
|
|
62
|
+
# trading → research toolset (reads-only; no code_execution/trade execution).
|
|
63
|
+
"trading": AgentTemplate(
|
|
64
|
+
name="trading",
|
|
65
|
+
toolset="research",
|
|
66
|
+
autonomy="standard",
|
|
67
|
+
persona="Markets researcher. Analyses price action and on-chain data. Never executes trades.",
|
|
68
|
+
seeded_skills=["market-research-brief"],
|
|
69
|
+
),
|
|
70
|
+
"blank": AgentTemplate(
|
|
71
|
+
name="blank",
|
|
72
|
+
toolset="minimal",
|
|
73
|
+
autonomy="off",
|
|
74
|
+
persona="",
|
|
75
|
+
),
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def resolve_template(name) -> AgentTemplate:
|
|
80
|
+
"""Return the template for *name*, or ``general`` for unknown names.
|
|
81
|
+
|
|
82
|
+
Never raises; accepts any input type.
|
|
83
|
+
"""
|
|
84
|
+
try:
|
|
85
|
+
key = str(name or "").strip().lower()
|
|
86
|
+
except Exception:
|
|
87
|
+
key = ""
|
|
88
|
+
return TEMPLATES.get(key, TEMPLATES["general"])
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def resolve_template_persona(name: str | None) -> str:
|
|
92
|
+
"""Persona text for *name* (``""`` for blank/empty)."""
|
|
93
|
+
return resolve_template(name).persona
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def seeded_skills_for(name: str | None) -> list[str]:
|
|
97
|
+
"""Seeded skill ids for *name* (empty list if none)."""
|
|
98
|
+
return list(resolve_template(name).seeded_skills)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Per-feature aux-model slots + per-task fallback chains (B5, Hermes parity).
|
|
2
|
+
|
|
3
|
+
resolve_aux_chain() wraps resolve_aux_model() to return an ORDERED list of
|
|
4
|
+
provider/model candidates for an aux task (compaction/judge/reflection),
|
|
5
|
+
instead of a single model string. Empty list => caller falls back to the
|
|
6
|
+
main model (unchanged runtime contract).
|
|
7
|
+
"""
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from agents.task.constants import resolve_aux_chain
|
|
11
|
+
|
|
12
|
+
# Every env var resolve_aux_chain / resolve_aux_model can read, across all 3 slots.
|
|
13
|
+
_ALL_AUX_ENV_KEYS = (
|
|
14
|
+
"AUX_AUTO",
|
|
15
|
+
"COMPACTION_AUTO_AUX",
|
|
16
|
+
"COMPACTION_MODEL",
|
|
17
|
+
"COMPACTION_PROVIDER",
|
|
18
|
+
"AUX_MODEL_JUDGE",
|
|
19
|
+
"AUX_PROVIDER",
|
|
20
|
+
"AUX_MODEL_COMPACTION",
|
|
21
|
+
"AUX_PROVIDER_COMPACTION",
|
|
22
|
+
"AUX_FALLBACK_COMPACTION",
|
|
23
|
+
"AUX_MODEL_JUDGE",
|
|
24
|
+
"AUX_PROVIDER_JUDGE",
|
|
25
|
+
"AUX_FALLBACK_JUDGE",
|
|
26
|
+
"AUX_MODEL_REFLECTION",
|
|
27
|
+
"AUX_PROVIDER_REFLECTION",
|
|
28
|
+
"AUX_FALLBACK_REFLECTION",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.fixture(autouse=True)
|
|
33
|
+
def _clean_aux_env(monkeypatch):
|
|
34
|
+
"""Isolate every test from whatever the dev/CI environment happens to set."""
|
|
35
|
+
for key in _ALL_AUX_ENV_KEYS:
|
|
36
|
+
monkeypatch.delenv(key, raising=False)
|
|
37
|
+
yield
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_primary_plus_fallbacks(monkeypatch):
|
|
41
|
+
monkeypatch.setenv("AUX_MODEL_JUDGE", "claude-haiku-4-5")
|
|
42
|
+
monkeypatch.setenv("AUX_PROVIDER_JUDGE", "anthropic")
|
|
43
|
+
monkeypatch.setenv("AUX_FALLBACK_JUDGE", "openai/gpt-5-mini,gemini/gemini-flash")
|
|
44
|
+
chain = resolve_aux_chain("judge", "openrouter")
|
|
45
|
+
assert chain[0] == {"model": "claude-haiku-4-5", "provider": "anthropic"}
|
|
46
|
+
assert chain[1] == {"model": "gpt-5-mini", "provider": "openai"}
|
|
47
|
+
assert chain[2] == {"model": "gemini-flash", "provider": "gemini"}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_legacy_compaction_env_still_works(monkeypatch):
|
|
51
|
+
monkeypatch.setenv("COMPACTION_MODEL", "gpt-5-mini")
|
|
52
|
+
assert resolve_aux_chain("compaction", "openai")[0]["model"] == "gpt-5-mini"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_empty_when_unset():
|
|
56
|
+
assert resolve_aux_chain("judge", "openrouter") == []
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_new_compaction_env_takes_precedence_over_legacy(monkeypatch):
|
|
60
|
+
monkeypatch.setenv("COMPACTION_MODEL", "gpt-5-mini")
|
|
61
|
+
monkeypatch.setenv("AUX_MODEL_COMPACTION", "claude-haiku-4-5")
|
|
62
|
+
assert resolve_aux_chain("compaction", "openai")[0]["model"] == "claude-haiku-4-5"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_bare_model_fallback_keeps_default_provider(monkeypatch):
|
|
66
|
+
# A fallback token with no "/" is a bare model name; it should NOT inherit the
|
|
67
|
+
# primary candidate's provider (default_provider=None per the sketch) so the
|
|
68
|
+
# factory auto-detects it from the model registry.
|
|
69
|
+
monkeypatch.setenv("AUX_MODEL_JUDGE", "claude-haiku-4-5")
|
|
70
|
+
monkeypatch.setenv("AUX_FALLBACK_JUDGE", "gpt-5-mini")
|
|
71
|
+
chain = resolve_aux_chain("judge", "openai")
|
|
72
|
+
assert chain[1] == {"model": "gpt-5-mini", "provider": None}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_reflection_inherits_compaction_model_and_provider_when_unset(monkeypatch):
|
|
76
|
+
monkeypatch.setenv("AUX_MODEL_COMPACTION", "claude-haiku-4-5")
|
|
77
|
+
monkeypatch.setenv("AUX_PROVIDER_COMPACTION", "anthropic")
|
|
78
|
+
chain = resolve_aux_chain("reflection", "openai")
|
|
79
|
+
assert chain[0] == {"model": "claude-haiku-4-5", "provider": "anthropic"}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_reflection_inherits_legacy_compaction_provider_when_model_inherited(monkeypatch):
|
|
83
|
+
# Legacy knobs only (no new AUX_MODEL_COMPACTION/AUX_PROVIDER_COMPACTION set):
|
|
84
|
+
# reflection must still inherit COMPACTION_MODEL + COMPACTION_PROVIDER together,
|
|
85
|
+
# not fall through to the generic AUX_PROVIDER.
|
|
86
|
+
monkeypatch.setenv("COMPACTION_MODEL", "gpt-5-mini")
|
|
87
|
+
monkeypatch.setenv("COMPACTION_PROVIDER", "openai")
|
|
88
|
+
monkeypatch.setenv("AUX_PROVIDER", "gemini") # decoy: must NOT win
|
|
89
|
+
chain = resolve_aux_chain("reflection", "anthropic")
|
|
90
|
+
assert chain[0] == {"model": "gpt-5-mini", "provider": "openai"}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_reflection_uses_own_env_when_set(monkeypatch):
|
|
94
|
+
# Reflection has its OWN model+provider+fallback configured: compaction's config
|
|
95
|
+
# (even if also set) must NOT be consulted at all.
|
|
96
|
+
monkeypatch.setenv("AUX_MODEL_COMPACTION", "gpt-5-mini")
|
|
97
|
+
monkeypatch.setenv("AUX_PROVIDER_COMPACTION", "openai")
|
|
98
|
+
monkeypatch.setenv("AUX_MODEL_REFLECTION", "claude-haiku-4-5")
|
|
99
|
+
monkeypatch.setenv("AUX_PROVIDER_REFLECTION", "anthropic")
|
|
100
|
+
monkeypatch.setenv("AUX_FALLBACK_REFLECTION", "gemini/gemini-flash")
|
|
101
|
+
chain = resolve_aux_chain("reflection", "openai")
|
|
102
|
+
assert chain[0] == {"model": "claude-haiku-4-5", "provider": "anthropic"}
|
|
103
|
+
assert chain[1] == {"model": "gemini-flash", "provider": "gemini"}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_reflection_own_model_set_own_provider_unset_does_not_leak_compaction_provider(monkeypatch):
|
|
107
|
+
# Reflection sets its OWN model but not its OWN provider, while compaction has a
|
|
108
|
+
# provider configured. Since the model did NOT come from compaction-inheritance,
|
|
109
|
+
# compaction's provider must NOT apply — falls through to the generic AUX_PROVIDER
|
|
110
|
+
# (or None).
|
|
111
|
+
monkeypatch.setenv("AUX_MODEL_COMPACTION", "gpt-5-mini")
|
|
112
|
+
monkeypatch.setenv("AUX_PROVIDER_COMPACTION", "openai")
|
|
113
|
+
monkeypatch.setenv("AUX_MODEL_REFLECTION", "claude-haiku-4-5")
|
|
114
|
+
chain = resolve_aux_chain("reflection", "anthropic")
|
|
115
|
+
assert chain[0] == {"model": "claude-haiku-4-5", "provider": None}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_reflection_fallback_inherits_compaction_fallback_when_unset(monkeypatch):
|
|
119
|
+
monkeypatch.setenv("AUX_MODEL_COMPACTION", "claude-haiku-4-5")
|
|
120
|
+
monkeypatch.setenv("AUX_FALLBACK_COMPACTION", "openai/gpt-5-mini")
|
|
121
|
+
chain = resolve_aux_chain("reflection", "anthropic")
|
|
122
|
+
assert len(chain) == 2
|
|
123
|
+
assert chain[1] == {"model": "gpt-5-mini", "provider": "openai"}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_reflection_aux_auto_pairs_legacy_compaction_provider(monkeypatch):
|
|
127
|
+
# Regression (B5 review): with all model envs unset, global AUX_AUTO=true and
|
|
128
|
+
# legacy COMPACTION_PROVIDER set, reflection must resolve via the COMPACTION
|
|
129
|
+
# inheritance branch (model from the cheap map + COMPACTION_PROVIDER paired) —
|
|
130
|
+
# matching pre-B5 behavior where reflection reused _provision_compaction_llm().
|
|
131
|
+
# The bug: resolve_aux_model("reflection") hit the global-AUX_AUTO early-exit
|
|
132
|
+
# first, so inherited_from_compaction stayed False and the provider was dropped.
|
|
133
|
+
monkeypatch.setenv("AUX_AUTO", "true")
|
|
134
|
+
monkeypatch.setenv("COMPACTION_PROVIDER", "anthropic")
|
|
135
|
+
chain = resolve_aux_chain("reflection", "openai")
|
|
136
|
+
assert chain[0] == {"model": "gpt-5-mini", "provider": "anthropic"}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def test_unknown_slot_returns_empty_chain(monkeypatch):
|
|
140
|
+
# The slot set is fixed at the 3 real aux call sites (_AUX_SLOTS); an unknown
|
|
141
|
+
# task never gets a chain — even under AUX_AUTO (dead-config trap guard).
|
|
142
|
+
monkeypatch.setenv("AUX_AUTO", "true")
|
|
143
|
+
assert resolve_aux_chain("planner", "anthropic") == []
|
|
144
|
+
assert resolve_aux_chain("vision", "anthropic") == []
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_compaction_and_judge_do_not_cross_inherit():
|
|
148
|
+
# Sanity: compaction/judge never inherit each other (only reflection inherits
|
|
149
|
+
# from compaction).
|
|
150
|
+
assert resolve_aux_chain("compaction", "openai") == []
|
|
151
|
+
assert resolve_aux_chain("judge", "openai") == []
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Per-task aux-model resolution: explicit env wins, then auto-map, else None."""
|
|
2
|
+
from agents.task.constants import resolve_aux_model, AUX_MODEL_MAP, _AUX_TASK_ENV
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_explicit_env_wins(monkeypatch):
|
|
6
|
+
monkeypatch.setenv("AUX_MODEL_JUDGE", "claude-haiku-4-5")
|
|
7
|
+
assert resolve_aux_model("judge", provider="openai") == "claude-haiku-4-5"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_auto_map_when_enabled(monkeypatch):
|
|
11
|
+
monkeypatch.delenv("AUX_MODEL_JUDGE", raising=False)
|
|
12
|
+
monkeypatch.setenv("AUX_AUTO", "true")
|
|
13
|
+
assert resolve_aux_model("judge", provider="anthropic") == AUX_MODEL_MAP["anthropic"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_none_when_unconfigured(monkeypatch):
|
|
17
|
+
monkeypatch.delenv("AUX_MODEL_JUDGE", raising=False)
|
|
18
|
+
monkeypatch.delenv("AUX_AUTO", raising=False)
|
|
19
|
+
assert resolve_aux_model("judge", provider="openai") is None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_planner_vision_rows_removed(monkeypatch):
|
|
23
|
+
# UP-10 2.1: planner/vision were dead config surface (no call sites) and were
|
|
24
|
+
# removed. With no env mapping they resolve to None regardless of AUX_AUTO.
|
|
25
|
+
assert "planner" not in _AUX_TASK_ENV
|
|
26
|
+
assert "vision" not in _AUX_TASK_ENV
|
|
27
|
+
monkeypatch.setenv("AUX_AUTO", "true")
|
|
28
|
+
monkeypatch.setenv("AUX_MODEL_PLANNER", "should-be-ignored")
|
|
29
|
+
monkeypatch.setenv("AUX_MODEL_VISION", "should-be-ignored")
|
|
30
|
+
assert resolve_aux_model("planner", provider="anthropic") == AUX_MODEL_MAP["anthropic"]
|
|
31
|
+
# ^ note: an unknown task with AUX_AUTO+provider still falls through to the auto-map;
|
|
32
|
+
# the point is the *explicit* AUX_MODEL_PLANNER/VISION envs are no longer consulted.
|
|
33
|
+
monkeypatch.delenv("AUX_AUTO", raising=False)
|
|
34
|
+
assert resolve_aux_model("planner", provider="anthropic") is None
|
|
35
|
+
assert resolve_aux_model("vision", provider="anthropic") is None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_compaction_back_compat(monkeypatch):
|
|
39
|
+
# COMPACTION_MODEL must still win for the compaction task (legacy knob).
|
|
40
|
+
monkeypatch.setenv("COMPACTION_MODEL", "gpt-5-mini")
|
|
41
|
+
assert resolve_aux_model("compaction", provider="openai") == "gpt-5-mini"
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test suite for parse robustness in the task agent.
|
|
3
|
+
|
|
4
|
+
Modernized 2026-06 against the current API. Three tests were REMOVED because they
|
|
5
|
+
asserted behavior that has since been deleted/changed by design:
|
|
6
|
+
- TestRetryLogic.test_get_next_action_retry_on_parse_error — mocked
|
|
7
|
+
`message_manager.extract_json_from_model_output` as a METHOD; it is now a free
|
|
8
|
+
function (`agents.task.utils_json.extract_json_from_model_output`), and the old
|
|
9
|
+
`with_structured_output` retry shape no longer matches the native-tools path.
|
|
10
|
+
- TestTokenManagement.test_cut_messages_called_before_llm — `MessageManager.cut_messages`
|
|
11
|
+
no longer exists (token management was reorganized into the messages mixins).
|
|
12
|
+
- TestExponentialBackoff.test_exponential_backoff_on_parse_error — asserted deterministic,
|
|
13
|
+
no-jitter delays capped at 60s; the current LLM backoff is jittered and capped at 120s,
|
|
14
|
+
and a plain ValueError is not on the LLM-backoff path at all.
|
|
15
|
+
|
|
16
|
+
This module now tests:
|
|
17
|
+
1. JSON extraction from various malformed outputs (the free function)
|
|
18
|
+
2. AgentOutput validation (now extra='forbid')
|
|
19
|
+
3. Tool-calling method selection per provider
|
|
20
|
+
"""
|
|
21
|
+
import pytest
|
|
22
|
+
from pydantic import ValidationError
|
|
23
|
+
|
|
24
|
+
from agents.task.agent.views import AgentOutput
|
|
25
|
+
from agents.task.utils_json import extract_json_from_model_output
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TestJSONExtraction:
|
|
29
|
+
"""JSON extraction robustness (utils_json.extract_json_from_model_output)."""
|
|
30
|
+
|
|
31
|
+
def test_extract_json_from_json_code_block(self):
|
|
32
|
+
content = '''Here's the response:
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"current_state": {
|
|
36
|
+
"page_summary": "Test page",
|
|
37
|
+
"evaluation_previous_goal": "Success",
|
|
38
|
+
"memory": "Test memory",
|
|
39
|
+
"next_goal": "Next test",
|
|
40
|
+
"reasoning": "Test reasoning"
|
|
41
|
+
},
|
|
42
|
+
"action": []
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
Some additional text'''
|
|
46
|
+
result = extract_json_from_model_output(content)
|
|
47
|
+
assert result['current_state']['page_summary'] == "Test page"
|
|
48
|
+
assert result['action'] == []
|
|
49
|
+
|
|
50
|
+
def test_extract_json_from_regular_code_block(self):
|
|
51
|
+
# A regular (non-"json"-tagged) ``` fence around the full object.
|
|
52
|
+
content = '''```
|
|
53
|
+
{
|
|
54
|
+
"current_state": {
|
|
55
|
+
"page_summary": "Test",
|
|
56
|
+
"evaluation_previous_goal": "Success",
|
|
57
|
+
"memory": "Memory",
|
|
58
|
+
"next_goal": "Goal",
|
|
59
|
+
"reasoning": "Reason"
|
|
60
|
+
},
|
|
61
|
+
"action": [{"test": {"param": "value"}}]
|
|
62
|
+
}
|
|
63
|
+
```'''
|
|
64
|
+
result = extract_json_from_model_output(content)
|
|
65
|
+
assert result['current_state']['page_summary'] == "Test"
|
|
66
|
+
assert len(result['action']) == 1
|
|
67
|
+
|
|
68
|
+
def test_extract_json_from_raw_content(self):
|
|
69
|
+
content = '''{
|
|
70
|
+
"current_state": {
|
|
71
|
+
"page_summary": "Raw test",
|
|
72
|
+
"evaluation_previous_goal": "Success",
|
|
73
|
+
"memory": "Raw memory",
|
|
74
|
+
"next_goal": "Raw goal",
|
|
75
|
+
"reasoning": "Raw reason"
|
|
76
|
+
},
|
|
77
|
+
"action": []
|
|
78
|
+
}'''
|
|
79
|
+
result = extract_json_from_model_output(content)
|
|
80
|
+
assert result['current_state']['page_summary'] == "Raw test"
|
|
81
|
+
|
|
82
|
+
def test_extract_json_with_extra_text(self):
|
|
83
|
+
content = '''Let me analyze the current state:
|
|
84
|
+
|
|
85
|
+
{
|
|
86
|
+
"current_state": {
|
|
87
|
+
"page_summary": "Embedded test",
|
|
88
|
+
"evaluation_previous_goal": "Success",
|
|
89
|
+
"memory": "Embedded memory",
|
|
90
|
+
"next_goal": "Embedded goal",
|
|
91
|
+
"reasoning": "Embedded reason"
|
|
92
|
+
},
|
|
93
|
+
"action": []
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
That's my analysis.'''
|
|
97
|
+
result = extract_json_from_model_output(content)
|
|
98
|
+
assert result['current_state']['page_summary'] == "Embedded test"
|
|
99
|
+
|
|
100
|
+
def test_extract_json_invalid_raises_error(self):
|
|
101
|
+
with pytest.raises(ValueError, match="Could not parse response"):
|
|
102
|
+
extract_json_from_model_output("This is not JSON at all")
|
|
103
|
+
|
|
104
|
+
def test_extract_json_empty_content_raises_error(self):
|
|
105
|
+
with pytest.raises(ValueError, match="Empty response from model"):
|
|
106
|
+
extract_json_from_model_output("")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class TestAgentOutputValidation:
|
|
110
|
+
"""AgentOutput model validation (now ConfigDict(extra='forbid'))."""
|
|
111
|
+
|
|
112
|
+
def test_agent_output_rejects_extra_fields(self):
|
|
113
|
+
"""AgentOutput now FORBIDS unknown fields (was: ignore). Extra => ValidationError."""
|
|
114
|
+
data = {
|
|
115
|
+
"current_state": {
|
|
116
|
+
"page_summary": "Test",
|
|
117
|
+
"evaluation_previous_goal": "Success",
|
|
118
|
+
"memory": "Memory",
|
|
119
|
+
"next_goal": "Goal",
|
|
120
|
+
"reasoning": "Reason"
|
|
121
|
+
},
|
|
122
|
+
"action": [],
|
|
123
|
+
"extra_field": "This should now be rejected",
|
|
124
|
+
"another_extra": {"nested": "data"}
|
|
125
|
+
}
|
|
126
|
+
with pytest.raises(ValidationError):
|
|
127
|
+
AgentOutput(**data)
|
|
128
|
+
|
|
129
|
+
def test_agent_output_requires_core_fields(self):
|
|
130
|
+
"""AgentOutput still requires its core fields."""
|
|
131
|
+
with pytest.raises(ValidationError):
|
|
132
|
+
AgentOutput(**{"extra_field": "This is not enough"})
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class TestToolCallingMethods:
|
|
136
|
+
"""Tool-calling method selection — all modern providers use native function_calling."""
|
|
137
|
+
|
|
138
|
+
def _host(self, library):
|
|
139
|
+
import logging
|
|
140
|
+
from agents.task.agent.core.llm_provisioning import LLMProvisioningMixin
|
|
141
|
+
|
|
142
|
+
host = LLMProvisioningMixin.__new__(LLMProvisioningMixin)
|
|
143
|
+
host.chat_model_library = library
|
|
144
|
+
host.logger = logging.getLogger("test_tool_calling")
|
|
145
|
+
return host
|
|
146
|
+
|
|
147
|
+
def test_tool_calling_enabled_for_all_providers(self):
|
|
148
|
+
# Current native-tools adapters (Llama/LangChain providers were removed) plus an
|
|
149
|
+
# unknown library, which must still default to function_calling.
|
|
150
|
+
providers = [
|
|
151
|
+
'ChatOpenAI',
|
|
152
|
+
'ChatAnthropic',
|
|
153
|
+
'ChatGoogleGenerativeAI',
|
|
154
|
+
'ChatDeepSeek',
|
|
155
|
+
'DeepSeekChatAdapter',
|
|
156
|
+
'UnknownProvider',
|
|
157
|
+
]
|
|
158
|
+
for provider in providers:
|
|
159
|
+
host = self._host(provider)
|
|
160
|
+
assert host.set_tool_calling_method('auto') == 'function_calling', (
|
|
161
|
+
f"Expected function_calling for {provider}"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
def test_explicit_method_passthrough(self):
|
|
165
|
+
host = self._host('ChatOpenAI')
|
|
166
|
+
assert host.set_tool_calling_method('json_mode') == 'json_mode'
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Single source of truth for per-surface default tool lists.
|
|
2
|
+
|
|
3
|
+
Three call sites historically hard-coded their own defaults and drifted. This
|
|
4
|
+
module is the one place that answers "what tools does a session get when the
|
|
5
|
+
caller didn't ask for a specific set?" — keyed by surface (server vs CLI/local).
|
|
6
|
+
|
|
7
|
+
Named toolsets (TOOLSETS) provide a stable vocabulary for choosing a pre-built
|
|
8
|
+
tool configuration. All ids are cross-checked against VALID_TOOL_IDS from
|
|
9
|
+
skill_manager — only valid ids appear in any set. ``code_execution`` is
|
|
10
|
+
intentionally absent from every set (unsafe by default).
|
|
11
|
+
|
|
12
|
+
Notes on ids that were considered but excluded:
|
|
13
|
+
- ``twitter``: not in VALID_TOOL_IDS → excluded from all sets (incl. ``social``).
|
|
14
|
+
- ``goal``, ``cronjob``: not in VALID_TOOL_IDS → excluded.
|
|
15
|
+
- ``knowledge``: not in VALID_TOOL_IDS → excluded.
|
|
16
|
+
- ``code_execution``: deliberately excluded (unsafe without a sandbox).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
# Named toolsets registry
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
# Every id listed here is a member of VALID_TOOL_IDS (skill_manager.py:26):
|
|
25
|
+
# {'browser', 'mcp', 'filesystem', 'perplexity', 'email', 'task',
|
|
26
|
+
# 'anysite', 'coding', 'code_execution', 'polymarket', 'hyperliquid'}
|
|
27
|
+
# code_execution is excluded from all named sets (unsafe by default).
|
|
28
|
+
|
|
29
|
+
TOOLSETS: dict[str, list[str]] = {
|
|
30
|
+
# Absolute minimum: file access + task management.
|
|
31
|
+
"minimal": ["filesystem", "task"],
|
|
32
|
+
# Equivalent to the safe/cli minimum.
|
|
33
|
+
"safe": ["filesystem", "task"],
|
|
34
|
+
# Matches the current cli_default_tools() base (without dynamic additions).
|
|
35
|
+
"default": ["filesystem", "task"],
|
|
36
|
+
# Research workflow: lightweight web read + search + any-site scraping + read-only
|
|
37
|
+
# crypto market data (no wallet).
|
|
38
|
+
"research": ["filesystem", "task", "perplexity", "anysite", "web_fetch",
|
|
39
|
+
"polymarket_data", "hyperliquid_data"],
|
|
40
|
+
# Trading research: research base focused on the crypto read tools (no trade tools).
|
|
41
|
+
"trading_research": ["filesystem", "task", "perplexity", "anysite", "web_fetch",
|
|
42
|
+
"polymarket_data", "hyperliquid_data"],
|
|
43
|
+
# Coding workflow: file editing + code runner tool.
|
|
44
|
+
"coding": ["filesystem", "task", "coding"],
|
|
45
|
+
# Development: coding + browser (e.g. to browse docs / test web UIs).
|
|
46
|
+
"development": ["filesystem", "task", "coding", "browser"],
|
|
47
|
+
# Browser-centric: just the browser on top of core.
|
|
48
|
+
"browser": ["filesystem", "task", "browser"],
|
|
49
|
+
# Social listening / research: any-site scraping + web search.
|
|
50
|
+
# NOTE: `twitter` is NOT in VALID_TOOL_IDS, so it is intentionally omitted;
|
|
51
|
+
# social-platform data is reached via `anysite` (which covers twitter/linkedin/etc).
|
|
52
|
+
"social": ["filesystem", "task", "anysite", "perplexity", "polymarket_data"],
|
|
53
|
+
# Full server stack (mirrors server_default_tools()).
|
|
54
|
+
"full": ["filesystem", "task", "web_fetch", "perplexity", "email", "mcp", "anysite"],
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def resolve_toolset(name: str) -> list[str]:
|
|
59
|
+
"""Return the tool list for *name*, or the ``default`` set for unknown names.
|
|
60
|
+
|
|
61
|
+
Never raises; always returns a non-empty list.
|
|
62
|
+
"""
|
|
63
|
+
key = (name or "").strip().lower()
|
|
64
|
+
return list(TOOLSETS.get(key, TOOLSETS["default"]))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# Per-surface defaults
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def server_default_tools() -> list[str]:
|
|
73
|
+
"""Comprehensive default for a server-container session (web read + MCP available).
|
|
74
|
+
|
|
75
|
+
Web reading defaults to the lightweight ``web_fetch`` tool; the heavyweight Playwright
|
|
76
|
+
``browser`` tool is opt-in (request ``tool_ids=['browser']`` or a browser-oriented toolset).
|
|
77
|
+
"""
|
|
78
|
+
return ['filesystem', 'task', 'web_fetch', 'perplexity', 'email', 'mcp', 'anysite']
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def cli_default_tools() -> list[str]:
|
|
82
|
+
"""Default for the lightweight CLI container.
|
|
83
|
+
|
|
84
|
+
When ``POLYROB_AGENT_TOOLSET`` is set, the tool list is driven by the named
|
|
85
|
+
toolset via ``resolve_toolset``; unset behaviour is BYTE-IDENTICAL to the
|
|
86
|
+
previous implementation.
|
|
87
|
+
|
|
88
|
+
Either way the final list is intersected through ``cli_unavailable_tools`` so
|
|
89
|
+
the agent is never advertised tools the CLI container can't register.
|
|
90
|
+
"""
|
|
91
|
+
from core.bootstrap import cli_unavailable_tools
|
|
92
|
+
|
|
93
|
+
toolset_name = os.environ.get("POLYROB_AGENT_TOOLSET", "").strip()
|
|
94
|
+
|
|
95
|
+
if toolset_name:
|
|
96
|
+
# Named-toolset path: drive the list from the registry.
|
|
97
|
+
tools = resolve_toolset(toolset_name)
|
|
98
|
+
else:
|
|
99
|
+
# Legacy path: byte-identical to the original implementation.
|
|
100
|
+
from tools.coding import coding_tools_enabled
|
|
101
|
+
from tools.anysite import anysite_cli_enabled
|
|
102
|
+
|
|
103
|
+
tools = ['filesystem', 'task', 'web_fetch']
|
|
104
|
+
if coding_tools_enabled():
|
|
105
|
+
tools.append('coding')
|
|
106
|
+
if anysite_cli_enabled():
|
|
107
|
+
tools.append('anysite')
|
|
108
|
+
|
|
109
|
+
unavailable = set(cli_unavailable_tools(tools))
|
|
110
|
+
return [t for t in tools if t not in unavailable]
|