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,661 @@
|
|
|
1
|
+
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import asyncio
|
|
5
|
+
import base64
|
|
6
|
+
import http
|
|
7
|
+
import importlib
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
import subprocess
|
|
13
|
+
import traceback
|
|
14
|
+
import time
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from datetime import datetime
|
|
17
|
+
from io import BytesIO
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Any, Callable, Dict, List, Optional, Type, TypeVar, Union, Tuple
|
|
20
|
+
from collections import deque # ADDED: Import deque for bounded collections
|
|
21
|
+
from agents.task.agent.tool_call_tracker import ToolCallTracker # Robust tool call ID tracking
|
|
22
|
+
|
|
23
|
+
from dotenv import load_dotenv
|
|
24
|
+
|
|
25
|
+
# Import centralized constants
|
|
26
|
+
from agents.task.constants import (
|
|
27
|
+
IMG_TOKENS,
|
|
28
|
+
LoopDetectionConfig,
|
|
29
|
+
DEFAULT_USER_ID,
|
|
30
|
+
MemoryConfig,
|
|
31
|
+
MAX_MCP_PER_STEP
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Import POLYROB exceptions
|
|
35
|
+
from core.exceptions import (
|
|
36
|
+
AgentError,
|
|
37
|
+
ValidationError as ROBValidationError,
|
|
38
|
+
LLMResponseError,
|
|
39
|
+
ToolError
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Import billing exception for fail-fast handling
|
|
43
|
+
from core.exceptions import InsufficientCreditsError
|
|
44
|
+
|
|
45
|
+
# Import centralized utilities to avoid repeated inline imports
|
|
46
|
+
from agents.task.utils_json import normalize_action_schema
|
|
47
|
+
# Model limits now come from modules.llm.model_registry
|
|
48
|
+
|
|
49
|
+
# Native message types
|
|
50
|
+
from modules.llm.messages import (
|
|
51
|
+
AIMessage,
|
|
52
|
+
BaseMessage,
|
|
53
|
+
HumanMessage,
|
|
54
|
+
SystemMessage,
|
|
55
|
+
ToolMessage,
|
|
56
|
+
MessageOrigin,
|
|
57
|
+
make_control_message,
|
|
58
|
+
)
|
|
59
|
+
from modules.llm.adapters import BaseChatModel
|
|
60
|
+
from core.exceptions import (
|
|
61
|
+
RateLimitError,
|
|
62
|
+
LLMError,
|
|
63
|
+
LLMRateLimitError,
|
|
64
|
+
LLMAuthenticationError,
|
|
65
|
+
LLMConnectionError,
|
|
66
|
+
LLMContextLengthError,
|
|
67
|
+
LLMResponseError,
|
|
68
|
+
LLMPermanentError,
|
|
69
|
+
LLMProviderExhaustedError
|
|
70
|
+
)
|
|
71
|
+
# PIL Image imported locally in save_screenshot() method where needed
|
|
72
|
+
from pydantic import BaseModel, ConfigDict, ValidationError
|
|
73
|
+
|
|
74
|
+
from tools.browser.views import BrowserStateHistory, BrowserState
|
|
75
|
+
from agents.task.agent.message_manager.service import MessageManager
|
|
76
|
+
from agents.task.agent.core.llm_runner import LLMRunnerMixin
|
|
77
|
+
from agents.task.agent.core.memory_writer import MemoryWriterMixin
|
|
78
|
+
from agents.task.agent.core.step import StepMixin
|
|
79
|
+
from agents.task.agent.core.history_io import HistoryIOMixin
|
|
80
|
+
from agents.task.agent.core.logging_io import LoggingIOMixin
|
|
81
|
+
from agents.task.agent.core.safety_lifecycle import SafetyLifecycleMixin
|
|
82
|
+
from agents.task.agent.core.user_ingress import UserIngressMixin
|
|
83
|
+
from agents.task.agent.core.llm_provisioning import LLMProvisioningMixin
|
|
84
|
+
from agents.task.agent.core.model_introspection import ModelIntrospectionMixin
|
|
85
|
+
from agents.task.agent.core.loop_detection import LoopDetectionMixin
|
|
86
|
+
from agents.task.agent.core.resources import ResourceMixin
|
|
87
|
+
from agents.task.agent.core.session_metadata import SessionMetadataMixin
|
|
88
|
+
from agents.task.agent.core.error_recovery import ErrorRecoveryMixin
|
|
89
|
+
from agents.task.agent.core.step_telemetry import StepTelemetryMixin
|
|
90
|
+
from agents.task.agent.core.output_validation import OutputValidationMixin
|
|
91
|
+
from agents.task.agent.core.result_processing import ResultProcessingMixin
|
|
92
|
+
from agents.task.agent.core.next_action_internal import NextActionInternalMixin
|
|
93
|
+
from agents.task.agent.core.step_execution import StepExecutionMixin
|
|
94
|
+
from agents.task.agent.prompts import SystemPrompt, AgentMessagePrompt
|
|
95
|
+
from agents.task.agent.views import (
|
|
96
|
+
ActionModel,
|
|
97
|
+
AgentBrain,
|
|
98
|
+
AgentError,
|
|
99
|
+
AgentHistory,
|
|
100
|
+
AgentHistoryList,
|
|
101
|
+
AgentOutput,
|
|
102
|
+
AgentStepInfo,
|
|
103
|
+
ActionResult,
|
|
104
|
+
)
|
|
105
|
+
from tools.browser.context import BrowserContext
|
|
106
|
+
from tools.dom.views import DOMElementNode, SelectorMap
|
|
107
|
+
from agents.task.telemetry.views import (
|
|
108
|
+
HumanApprovalRequestedEvent,
|
|
109
|
+
HumanApprovalDecisionEvent,
|
|
110
|
+
TodoStatusEvent,
|
|
111
|
+
AgentRunTelemetryEvent,
|
|
112
|
+
AgentEndTelemetryEvent,
|
|
113
|
+
ProviderFailureEvent,
|
|
114
|
+
ProviderFallbackSuccessEvent,
|
|
115
|
+
)
|
|
116
|
+
# ProductTelemetry no longer directly used - accessed via TelemetryManager
|
|
117
|
+
from agents.task.utils import time_execution_async, detect_llm_provider, extract_token_usage
|
|
118
|
+
# Safely import Google API exceptions
|
|
119
|
+
try:
|
|
120
|
+
from google.api_core.exceptions import ResourceExhausted
|
|
121
|
+
except ImportError:
|
|
122
|
+
# Create a dummy exception class if google-api-core is not installed
|
|
123
|
+
class ResourceExhausted(Exception):
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
# Import from our own logging config
|
|
127
|
+
from agents.task.logging_config import get_task_logger
|
|
128
|
+
|
|
129
|
+
# Import centralized path management
|
|
130
|
+
from agents.task.path import pm
|
|
131
|
+
|
|
132
|
+
load_dotenv()
|
|
133
|
+
|
|
134
|
+
# Generic logger for the module itself (not instances)
|
|
135
|
+
logger = get_task_logger('agent')
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class RunLoopMixin:
|
|
139
|
+
"""The agent run loop (run), split whole out of Agent so service.py drops toward
|
|
140
|
+
its constructor core (P9). Agent composes RunLoopMixin; callers use agent.run()
|
|
141
|
+
unchanged via MRO. Imports above are service.py's (incl. module-level logger)."""
|
|
142
|
+
|
|
143
|
+
async def run(self, max_steps: int = 100, _continue_session: bool = False) -> AgentHistoryList:
|
|
144
|
+
"""Run agent for the task.
|
|
145
|
+
|
|
146
|
+
Runs the agent to complete the task set during initialization.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
max_steps: Maximum number of steps to take
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
List of history items
|
|
153
|
+
"""
|
|
154
|
+
# Log a truncated version of the task to avoid verbose logging
|
|
155
|
+
truncated_task = self.task[:50] + "..." if len(self.task) > 50 else self.task
|
|
156
|
+
self.logger.info(f'Running agent for task: {truncated_task}')
|
|
157
|
+
|
|
158
|
+
# Track start time for metrics
|
|
159
|
+
start_time = time.time()
|
|
160
|
+
|
|
161
|
+
# Initialize step counter - will be managed by step() method
|
|
162
|
+
self.state.n_steps = 0 # Start at 0, will be incremented by step() method
|
|
163
|
+
|
|
164
|
+
# Session-scoped setup (session-start telemetry + hierarchical memory)
|
|
165
|
+
# runs ONCE per session. Conversational turns (Conversation.respond with
|
|
166
|
+
# _continue_session=True) reuse the same agent and skip it to avoid
|
|
167
|
+
# telemetry spam + redundant H-MEM reloads. Tasks/HITL resume are unchanged.
|
|
168
|
+
if not _continue_session:
|
|
169
|
+
# Capture session start telemetry using TelemetryManager
|
|
170
|
+
try:
|
|
171
|
+
self.telemetry_manager.capture_session_start(
|
|
172
|
+
task=self.task,
|
|
173
|
+
model=self.model_name,
|
|
174
|
+
agent_type=self.__class__.__name__,
|
|
175
|
+
use_vision=self.use_vision,
|
|
176
|
+
internal_planning=False
|
|
177
|
+
)
|
|
178
|
+
except Exception as e:
|
|
179
|
+
self.logger.debug(f"Failed to capture session start telemetry: {e}")
|
|
180
|
+
|
|
181
|
+
# Initialize and create/load hierarchical memory session (MANDATORY)
|
|
182
|
+
try:
|
|
183
|
+
# Initialize TaskContextManager if we created it
|
|
184
|
+
if self._created_task_context_manager:
|
|
185
|
+
await self.task_context_manager._initialize()
|
|
186
|
+
self.logger.info("✅ Initialized dedicated TaskContextManager")
|
|
187
|
+
|
|
188
|
+
# Try to load existing session first
|
|
189
|
+
memory = self.task_context_manager.load_session(self.session_id, self.user_id)
|
|
190
|
+
|
|
191
|
+
if not memory:
|
|
192
|
+
# Create new session
|
|
193
|
+
memory = self.task_context_manager.create_session(
|
|
194
|
+
session_id=self.session_id,
|
|
195
|
+
task=self.task,
|
|
196
|
+
user_id=self.user_id
|
|
197
|
+
)
|
|
198
|
+
self.logger.info(f"📚 Created hierarchical memory session: {self.session_id}")
|
|
199
|
+
else:
|
|
200
|
+
self.logger.info(f"📚 Loaded hierarchical memory session: {self.session_id}")
|
|
201
|
+
|
|
202
|
+
except Exception as e:
|
|
203
|
+
# FAIL HARD - hierarchical memory is mandatory
|
|
204
|
+
error_msg = f"CRITICAL: Cannot initialize hierarchical memory: {e}"
|
|
205
|
+
self.logger.error(error_msg)
|
|
206
|
+
raise RuntimeError(error_msg)
|
|
207
|
+
|
|
208
|
+
try:
|
|
209
|
+
# Do initial actions if provided
|
|
210
|
+
if self.initial_actions:
|
|
211
|
+
try:
|
|
212
|
+
# Get fresh browser context for initial actions
|
|
213
|
+
browser_context = await self.get_browser_context()
|
|
214
|
+
result = await self.controller.multi_act(
|
|
215
|
+
self.initial_actions,
|
|
216
|
+
browser_context=browser_context,
|
|
217
|
+
_page_extraction_llm=self.page_extraction_llm
|
|
218
|
+
)
|
|
219
|
+
self._last_result = result
|
|
220
|
+
self.logger.info(f'Executed initial actions')
|
|
221
|
+
except Exception as e:
|
|
222
|
+
self.logger.error(f'Failed to execute initial actions: {str(e)}', exc_info=True)
|
|
223
|
+
|
|
224
|
+
# Create gif if required
|
|
225
|
+
if self.generate_gif:
|
|
226
|
+
if isinstance(self.generate_gif, str):
|
|
227
|
+
output_path = self.generate_gif
|
|
228
|
+
else:
|
|
229
|
+
if not self.save_conversation_path:
|
|
230
|
+
# Use proper path handling for conversation path
|
|
231
|
+
try:
|
|
232
|
+
# Create proper path in the results directory
|
|
233
|
+
from agents.task.path import pm
|
|
234
|
+
self.save_conversation_path = str(pm().create_file_path(
|
|
235
|
+
self.session_id,
|
|
236
|
+
"logs",
|
|
237
|
+
f"conversation_{str(time.time())}"
|
|
238
|
+
))
|
|
239
|
+
except Exception as e:
|
|
240
|
+
self.logger.warning(f"Failed to create conversation path: {e}")
|
|
241
|
+
|
|
242
|
+
# Fallback to direct utility functions
|
|
243
|
+
try:
|
|
244
|
+
from agents.task.path import pm
|
|
245
|
+
self.save_conversation_path = str(pm().create_file_path(
|
|
246
|
+
self.session_id,
|
|
247
|
+
"logs",
|
|
248
|
+
f"conversation_{str(time.time())}"
|
|
249
|
+
))
|
|
250
|
+
except ImportError:
|
|
251
|
+
# Last resort - still use central PathManager to avoid nested path issues
|
|
252
|
+
from agents.task.path import pm
|
|
253
|
+
self.save_conversation_path = str(pm().create_file_path(
|
|
254
|
+
self.session_id,
|
|
255
|
+
"logs",
|
|
256
|
+
f"conversation_{str(time.time())}"
|
|
257
|
+
))
|
|
258
|
+
else:
|
|
259
|
+
# Fallback path handling using centralized PathManager to avoid directory issues
|
|
260
|
+
from agents.task.path import pm
|
|
261
|
+
self.save_conversation_path = str(pm().create_file_path(
|
|
262
|
+
self.session_id,
|
|
263
|
+
"logs",
|
|
264
|
+
f"conversation_{str(time.time())}"
|
|
265
|
+
))
|
|
266
|
+
|
|
267
|
+
output_path = f'{self.save_conversation_path}.gif'
|
|
268
|
+
self.logger.debug(f'Will create gif at {output_path}')
|
|
269
|
+
|
|
270
|
+
# Loop until done or max steps reached
|
|
271
|
+
max_failures_reached = False
|
|
272
|
+
|
|
273
|
+
# Log the starting point
|
|
274
|
+
self.logger.info(f"Starting task execution with max {max_steps} steps")
|
|
275
|
+
|
|
276
|
+
# FIX 10: Add progress monitoring with heartbeat
|
|
277
|
+
last_progress_time = time.time()
|
|
278
|
+
PROGRESS_INTERVAL = 30 # Report progress every 30 seconds
|
|
279
|
+
last_activity_time = time.time()
|
|
280
|
+
# Use configurable stall timeout or default to 600 seconds
|
|
281
|
+
STALL_TIMEOUT = self.stall_timeout_seconds if self.stall_timeout_seconds else 600
|
|
282
|
+
|
|
283
|
+
# Import AgentStepInfo for proper step tracking
|
|
284
|
+
from agents.task.agent.views import AgentStepInfo
|
|
285
|
+
|
|
286
|
+
# Start stall monitor task
|
|
287
|
+
if self.stall_timeout_seconds:
|
|
288
|
+
self._stall_check_task = asyncio.create_task(self._stall_monitor_loop())
|
|
289
|
+
self.logger.debug("Started stall monitor task")
|
|
290
|
+
|
|
291
|
+
# Track task in orchestrator for proper cleanup
|
|
292
|
+
if hasattr(self, 'orchestrator') and self.orchestrator:
|
|
293
|
+
if hasattr(self.orchestrator, '_execution_tasks'):
|
|
294
|
+
self.orchestrator._execution_tasks.append(self._stall_check_task)
|
|
295
|
+
self.logger.debug("Registered stall monitor task with orchestrator for cleanup")
|
|
296
|
+
|
|
297
|
+
# CRITICAL: Check for queued messages BEFORE starting execution loop
|
|
298
|
+
# This enables continuous chat - when agent restarts after completion,
|
|
299
|
+
# it picks up messages that were queued while it was idle
|
|
300
|
+
initial_messages = await self._drain_user_messages()
|
|
301
|
+
self.logger.info(f"Checked for queued messages at start: found {len(initial_messages)} messages")
|
|
302
|
+
if initial_messages:
|
|
303
|
+
self.logger.info(f"Processing {len(initial_messages)} queued messages:")
|
|
304
|
+
for i, msg in enumerate(initial_messages):
|
|
305
|
+
msg_text = msg.get('text', '')[:100]
|
|
306
|
+
self.logger.info(f" Message {i+1}: {msg_text}...")
|
|
307
|
+
|
|
308
|
+
# ✅ FIX: Pass continuation context that was set by _drain_user_messages()
|
|
309
|
+
# This triggers the strong "PRIORITY INPUT" signal in inject_user_guidance()
|
|
310
|
+
session_context = getattr(self, '_session_continuation_context', None)
|
|
311
|
+
|
|
312
|
+
# Inject messages into history so LLM sees them
|
|
313
|
+
self.message_manager.inject_user_guidance(initial_messages, session_context=session_context)
|
|
314
|
+
|
|
315
|
+
self.logger.info(
|
|
316
|
+
f"✅ Injected {len(initial_messages)} messages with continuation context "
|
|
317
|
+
f"(continuation={session_context.get('continuation') if session_context else False})"
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
# R1: count consecutive reply-only steps. A turn ends after a run of
|
|
321
|
+
# them (see conversational_exit) so a chat answer doesn't loop and
|
|
322
|
+
# re-greet; any productive step resets the run, so a real task is never
|
|
323
|
+
# cut short. See agent/core/conversational_exit.py for the policy.
|
|
324
|
+
from agents.task.agent.core.conversational_exit import (
|
|
325
|
+
is_reply_only_step, should_conversational_exit,
|
|
326
|
+
)
|
|
327
|
+
consecutive_reply_steps = 0
|
|
328
|
+
|
|
329
|
+
for step_num in range(max_steps):
|
|
330
|
+
# Check for cancellation first
|
|
331
|
+
if self._cancelled:
|
|
332
|
+
self.logger.warning(f"❌ Agent execution cancelled at step {step_num}")
|
|
333
|
+
break
|
|
334
|
+
|
|
335
|
+
# Create step info with correct step number
|
|
336
|
+
step_info = AgentStepInfo(step_number=step_num, max_steps=max_steps)
|
|
337
|
+
|
|
338
|
+
# The agent's step() method will use this to update its internal counter
|
|
339
|
+
self.logger.debug(f"Starting step {step_num + 1}/{max_steps}")
|
|
340
|
+
|
|
341
|
+
# P6 session-registry heartbeat — refresh last_seen_at each step so the
|
|
342
|
+
# periodic reaper (SESSION_REGISTRY_BACKEND=sqlite) spares this live
|
|
343
|
+
# session. Best-effort / fail-open: a no-op for the in-process registry,
|
|
344
|
+
# and must never break the run loop. Resolves the TaskAgent through the
|
|
345
|
+
# existing container accessor (no new globals).
|
|
346
|
+
try:
|
|
347
|
+
from core.container import DependencyContainer
|
|
348
|
+
_task_agent = DependencyContainer.get_instance().get_agent("task_agent")
|
|
349
|
+
if _task_agent is not None and hasattr(_task_agent, "heartbeat_session"):
|
|
350
|
+
_task_agent.heartbeat_session(self.session_id)
|
|
351
|
+
except Exception:
|
|
352
|
+
pass # best-effort; never break the loop on heartbeat
|
|
353
|
+
|
|
354
|
+
# FIX 10: Periodic progress reporting
|
|
355
|
+
current_time = time.time()
|
|
356
|
+
if current_time - last_progress_time > PROGRESS_INTERVAL:
|
|
357
|
+
elapsed = current_time - start_time
|
|
358
|
+
progress_pct = (step_num / max_steps) * 100
|
|
359
|
+
self.logger.info(f"Progress: Step {step_num}/{max_steps} ({progress_pct:.1f}%), elapsed: {elapsed:.1f}s")
|
|
360
|
+
|
|
361
|
+
# Also emit telemetry for progress monitoring
|
|
362
|
+
if hasattr(self, 'session_data'):
|
|
363
|
+
self.session_data['last_progress_update'] = {
|
|
364
|
+
'timestamp': current_time,
|
|
365
|
+
'step': step_num,
|
|
366
|
+
'max_steps': max_steps,
|
|
367
|
+
'elapsed_seconds': elapsed
|
|
368
|
+
}
|
|
369
|
+
last_progress_time = current_time
|
|
370
|
+
|
|
371
|
+
# FIX 10: Check for stalled execution and take action
|
|
372
|
+
if current_time - last_activity_time > STALL_TIMEOUT:
|
|
373
|
+
self.logger.error(f"Agent appears stalled - no activity for {STALL_TIMEOUT} seconds", exc_info=True)
|
|
374
|
+
# Emit stall warning telemetry
|
|
375
|
+
if hasattr(self, 'session_data'):
|
|
376
|
+
if 'stall_warnings' not in self.session_data:
|
|
377
|
+
self.session_data['stall_warnings'] = []
|
|
378
|
+
self.session_data['stall_warnings'].append({
|
|
379
|
+
'timestamp': current_time,
|
|
380
|
+
'step': step_num,
|
|
381
|
+
'stall_duration': current_time - last_activity_time
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
# CRITICAL: Actually stop execution when stalled
|
|
385
|
+
self.logger.error("Breaking execution due to stall timeout", exc_info=True)
|
|
386
|
+
# Set error state before breaking
|
|
387
|
+
self.state.consecutive_failures = self.max_failures
|
|
388
|
+
# Mark as failed and break
|
|
389
|
+
break
|
|
390
|
+
|
|
391
|
+
if self._too_many_failures():
|
|
392
|
+
max_failures_reached = True
|
|
393
|
+
self.logger.warning(f"Too many consecutive failures ({self.state.consecutive_failures}/{self.max_failures})")
|
|
394
|
+
break
|
|
395
|
+
|
|
396
|
+
if await self._handle_control_flags():
|
|
397
|
+
self.logger.info("Agent execution stopped by control flags")
|
|
398
|
+
break
|
|
399
|
+
|
|
400
|
+
# Check for context overflow before executing step
|
|
401
|
+
if self._check_context_overflow():
|
|
402
|
+
self.logger.info("Context overflow detected and mitigated - continuing")
|
|
403
|
+
|
|
404
|
+
# Execute one step with the correct step info
|
|
405
|
+
try:
|
|
406
|
+
await self.step(step_info=step_info)
|
|
407
|
+
except asyncio.CancelledError:
|
|
408
|
+
self.logger.warning(f"❌ Step execution cancelled at step {step_num + 1}")
|
|
409
|
+
break
|
|
410
|
+
|
|
411
|
+
# FIX 10: Update last activity time after successful step
|
|
412
|
+
last_activity_time = time.time()
|
|
413
|
+
|
|
414
|
+
# UPGRADE (Dec 2025): Reset failure counter on successful step
|
|
415
|
+
# This prevents accumulated failures from previous steps from affecting new steps
|
|
416
|
+
if self._last_result and not any(r.error for r in self._last_result):
|
|
417
|
+
if self.state.consecutive_failures > 0:
|
|
418
|
+
self.logger.info(f"✅ Step succeeded, resetting failure counter (was {self.state.consecutive_failures})")
|
|
419
|
+
self.state.consecutive_failures = 0
|
|
420
|
+
self.state.reset_llm_errors()
|
|
421
|
+
|
|
422
|
+
# Log step completion
|
|
423
|
+
self.logger.debug(f"Completed step {step_num + 1}")
|
|
424
|
+
|
|
425
|
+
# Note: n_steps is now managed by the step() method using step_info
|
|
426
|
+
|
|
427
|
+
# Check for messages that arrived during step
|
|
428
|
+
user_messages = await self._drain_user_messages()
|
|
429
|
+
if user_messages:
|
|
430
|
+
self.logger.info(f"Received {len(user_messages)} messages during step - injecting immediately")
|
|
431
|
+
# Inject messages with context (set by _drain_user_messages)
|
|
432
|
+
session_context = getattr(self, '_session_continuation_context', None)
|
|
433
|
+
self.message_manager.inject_user_guidance(user_messages, session_context=session_context)
|
|
434
|
+
self.logger.info(f"✅ Injected {len(user_messages)} messages into conversation")
|
|
435
|
+
|
|
436
|
+
# R1: track consecutive reply-only steps. A reply-only step is one
|
|
437
|
+
# whose every result is a non-blocking user-facing reply (no tool
|
|
438
|
+
# ran); anything else (productive tool, planning turn, error, done)
|
|
439
|
+
# resets the run.
|
|
440
|
+
results = self._last_result or []
|
|
441
|
+
if is_reply_only_step(results):
|
|
442
|
+
consecutive_reply_steps += 1
|
|
443
|
+
else:
|
|
444
|
+
consecutive_reply_steps = 0
|
|
445
|
+
|
|
446
|
+
# Check if the agent is done
|
|
447
|
+
if results and any(result.is_done for result in results):
|
|
448
|
+
# CO-F1: judge the FINAL answer, not an intermediate step. This
|
|
449
|
+
# replaces the old top-of-loop check (which ran before step() on
|
|
450
|
+
# the previous step's result and could never see the true final
|
|
451
|
+
# answer, since a done() result broke the loop before that check
|
|
452
|
+
# ever re-ran). Gated by AgentConfig.validate_output (env
|
|
453
|
+
# VALIDATE_OUTPUT, default off) — off is byte-identical to legacy.
|
|
454
|
+
# Bound: `continue` re-enters the SAME `for step_num in
|
|
455
|
+
# range(max_steps)` loop, so a judge that always says "invalid"
|
|
456
|
+
# still terminates at max_steps (no unbounded retry loop); the
|
|
457
|
+
# consecutive_failures bump also lets `_too_many_failures()`
|
|
458
|
+
# (checked at the top of the loop) cut it short sooner.
|
|
459
|
+
if self.validate_output and not await self._validate_output():
|
|
460
|
+
self.logger.warning('❌ Final output failed judge validation - continuing task')
|
|
461
|
+
self.state.consecutive_failures += 1
|
|
462
|
+
continue
|
|
463
|
+
|
|
464
|
+
self.logger.info('✅ Task completed - agent called done()')
|
|
465
|
+
|
|
466
|
+
# W2-C: at the turn boundary, maybe fork a background reviewer to
|
|
467
|
+
# distil a durable skill from the run just completed. Productive =
|
|
468
|
+
# the run actually did work (the final step wasn't reply-only).
|
|
469
|
+
# Non-blocking + fail-open + gated BACKGROUND_REVIEW_ENABLED (off).
|
|
470
|
+
# E6 (deliberate scope): this fires ONLY on the done()-completion
|
|
471
|
+
# path — NOT on conversational-exit (reply-only = not productive,
|
|
472
|
+
# correctly skipped) nor max-steps exhaustion (a non-converging /
|
|
473
|
+
# incomplete run is poor skill material and would dilute the
|
|
474
|
+
# "every N productive turns" cadence with failures). The cadence is
|
|
475
|
+
# intentionally measured over COMPLETED productive runs only.
|
|
476
|
+
try:
|
|
477
|
+
self._maybe_spawn_background_review(
|
|
478
|
+
turn_was_productive=not is_reply_only_step(results)
|
|
479
|
+
)
|
|
480
|
+
except Exception:
|
|
481
|
+
pass
|
|
482
|
+
|
|
483
|
+
# CHAT MODE: Break immediately, let session finalize
|
|
484
|
+
# Continuous chat works via:
|
|
485
|
+
# 1. Session status → "completed"
|
|
486
|
+
# 2. User sends new message → queued in HITL manager
|
|
487
|
+
# 3. User initiates new run → agent picks up queued messages from step 3896
|
|
488
|
+
# 4. Agent continues with new task phase
|
|
489
|
+
#
|
|
490
|
+
# This eliminates race conditions from the old 1.5s wait pattern
|
|
491
|
+
break
|
|
492
|
+
|
|
493
|
+
# R1 conversational exit: the agent has produced a run of reply-only
|
|
494
|
+
# steps without calling done() — it's chatting, not working. End the
|
|
495
|
+
# turn so a greeting/chat answer doesn't loop and re-greet. A blocking
|
|
496
|
+
# send or done() already ended the turn via is_done above.
|
|
497
|
+
# T2-08: an autonomous (goal/cron) session is exempt — status
|
|
498
|
+
# narration during a mission is not a greeting loop. Fail-open False.
|
|
499
|
+
try:
|
|
500
|
+
from agents.task.goals.autonomy_marker import is_autonomous
|
|
501
|
+
_is_autonomous_run = is_autonomous(self.session_id)
|
|
502
|
+
except Exception:
|
|
503
|
+
_is_autonomous_run = False
|
|
504
|
+
if should_conversational_exit(
|
|
505
|
+
consecutive_reply_steps, getattr(self, '_is_sub_agent', False),
|
|
506
|
+
is_autonomous=_is_autonomous_run,
|
|
507
|
+
):
|
|
508
|
+
self.logger.info(
|
|
509
|
+
f'💬 {consecutive_reply_steps} consecutive reply-only steps — '
|
|
510
|
+
f'ending turn (R1 conversational exit)'
|
|
511
|
+
)
|
|
512
|
+
break
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
if max_failures_reached:
|
|
516
|
+
self.logger.warning(f'Too many consecutive failures')
|
|
517
|
+
|
|
518
|
+
# Create output gif (PIL decode + GIF assembly are blocking — off-loop)
|
|
519
|
+
if self.generate_gif and len(self.history.history) > 0:
|
|
520
|
+
try:
|
|
521
|
+
await asyncio.to_thread(self.create_history_gif, output_path)
|
|
522
|
+
except Exception as e:
|
|
523
|
+
self.logger.warning(f'Failed to create history gif: {str(e)}')
|
|
524
|
+
|
|
525
|
+
# Call done callback if provided
|
|
526
|
+
if self.register_done_callback:
|
|
527
|
+
if callable(self.register_done_callback):
|
|
528
|
+
self.register_done_callback(self.history)
|
|
529
|
+
else:
|
|
530
|
+
self.logger.warning("register_done_callback is set but not callable")
|
|
531
|
+
|
|
532
|
+
# RAM optimization: Final memory cleanup after session completion
|
|
533
|
+
try:
|
|
534
|
+
import gc
|
|
535
|
+
|
|
536
|
+
# Clean up telemetry buffers if available
|
|
537
|
+
self.telemetry_manager.flush_buffers()
|
|
538
|
+
|
|
539
|
+
# Force garbage collection after session completion
|
|
540
|
+
gc.collect()
|
|
541
|
+
|
|
542
|
+
self.logger.debug("Completed final memory cleanup")
|
|
543
|
+
except Exception as cleanup_error:
|
|
544
|
+
self.logger.debug(f"Error during final memory cleanup: {cleanup_error}")
|
|
545
|
+
|
|
546
|
+
# Capture session completion telemetry
|
|
547
|
+
try:
|
|
548
|
+
end_time = time.time()
|
|
549
|
+
duration = end_time - start_time
|
|
550
|
+
|
|
551
|
+
# Determine if the session was successful
|
|
552
|
+
success = False
|
|
553
|
+
if self._last_result and any(result.is_done for result in self._last_result):
|
|
554
|
+
success = True
|
|
555
|
+
|
|
556
|
+
# Extract metrics about the session
|
|
557
|
+
metrics = {
|
|
558
|
+
"steps_completed": self.state.n_steps - 1, # -1 because n_steps is incremented at the end of step
|
|
559
|
+
"consecutive_failures": self.state.consecutive_failures,
|
|
560
|
+
"max_failures_reached": max_failures_reached,
|
|
561
|
+
"token_count": self.message_manager.get_token_count() if hasattr(self.message_manager, "get_token_count") else None,
|
|
562
|
+
"model_name": self.model_name,
|
|
563
|
+
# Single agent handles everything
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
# Get error message if any
|
|
567
|
+
error_message = None
|
|
568
|
+
if self._last_result and any(result.error for result in self._last_result):
|
|
569
|
+
error_messages = [result.error for result in self._last_result if result.error]
|
|
570
|
+
if error_messages:
|
|
571
|
+
error_message = "; ".join(error_messages)
|
|
572
|
+
|
|
573
|
+
# Get final result content if successful
|
|
574
|
+
if success and self._last_result:
|
|
575
|
+
for result in self._last_result:
|
|
576
|
+
if result.is_done and result.extracted_content:
|
|
577
|
+
metrics["final_result"] = result.extracted_content
|
|
578
|
+
break
|
|
579
|
+
|
|
580
|
+
# Capture completion event using TelemetryManager
|
|
581
|
+
self.telemetry_manager.capture_session_end(
|
|
582
|
+
success=success,
|
|
583
|
+
steps=self.state.n_steps - 1,
|
|
584
|
+
duration=duration,
|
|
585
|
+
error_message=error_message,
|
|
586
|
+
metrics=metrics
|
|
587
|
+
)
|
|
588
|
+
except Exception as e:
|
|
589
|
+
self.logger.debug(f"Failed to capture session completion telemetry: {e}")
|
|
590
|
+
|
|
591
|
+
# Log final step count and result
|
|
592
|
+
if self._last_result and any(result.is_done for result in self._last_result):
|
|
593
|
+
self.logger.info(f"Task completed successfully in {self.state.n_steps-1} steps")
|
|
594
|
+
else:
|
|
595
|
+
self.logger.warning(f"Task not completed after {self.state.n_steps-1} steps")
|
|
596
|
+
|
|
597
|
+
# Save hierarchical memory session
|
|
598
|
+
if self.task_context_manager:
|
|
599
|
+
try:
|
|
600
|
+
self.task_context_manager.save_session(
|
|
601
|
+
session_id=self.session_id,
|
|
602
|
+
user_id=self.user_id
|
|
603
|
+
)
|
|
604
|
+
self.logger.info(f"💾 Saved hierarchical memory for session: {self.session_id}")
|
|
605
|
+
except Exception as e:
|
|
606
|
+
self.logger.warning(f"Failed to save hierarchical memory: {e}")
|
|
607
|
+
|
|
608
|
+
# Session cost tracking - credits already deducted per-call by usage_tracker
|
|
609
|
+
# (usage_meter, the pre-usage_tracker fallback, was retired in C5 — see
|
|
610
|
+
# docs/superpowers/plans/2026-07-02-polyrob-console-web-app-finalization-C-payments.md)
|
|
611
|
+
if self.user_id:
|
|
612
|
+
try:
|
|
613
|
+
if self.usage_tracker:
|
|
614
|
+
breakdown = await self.usage_tracker.get_session_breakdown(self.session_id)
|
|
615
|
+
self.logger.info(
|
|
616
|
+
f"💰 Session {self.session_id} summary: "
|
|
617
|
+
f"{breakdown['total_credits_charged']} credits charged, "
|
|
618
|
+
f"${breakdown['total_user_cost_usd']:.4f} user cost"
|
|
619
|
+
)
|
|
620
|
+
except Exception as e:
|
|
621
|
+
self.logger.error(f"Failed to get session cost summary: {e}")
|
|
622
|
+
|
|
623
|
+
# CO-F7: the once-per-SESSION bootstrap flag (episodic digest +
|
|
624
|
+
# continuity bridge, see memory_prefetch.py) is now set from inside
|
|
625
|
+
# step.py, right after the injectors are actually invoked on
|
|
626
|
+
# n_steps == 1 (see the call site there). It is deliberately NOT
|
|
627
|
+
# set here at the end of run() — a turn-1 run() that breaks BEFORE
|
|
628
|
+
# step() ever executes (cancellation, resumed-from-done/stopped,
|
|
629
|
+
# too-many-failures) must leave the flag False so a later real
|
|
630
|
+
# turn still gets its one shot at the digest + continuity bridge.
|
|
631
|
+
|
|
632
|
+
return self.history
|
|
633
|
+
finally:
|
|
634
|
+
# Clean up stall monitor task
|
|
635
|
+
if hasattr(self, '_stall_check_task') and self._stall_check_task:
|
|
636
|
+
self._stall_check_task.cancel()
|
|
637
|
+
try:
|
|
638
|
+
await self._stall_check_task
|
|
639
|
+
except asyncio.CancelledError:
|
|
640
|
+
pass
|
|
641
|
+
self.logger.debug("Cancelled stall monitor task")
|
|
642
|
+
|
|
643
|
+
# Release browser context for this agent
|
|
644
|
+
if self.orchestrator and self.orchestrator.browser_manager:
|
|
645
|
+
try:
|
|
646
|
+
await self.orchestrator.browser_manager.release_context(self.agent_id, close=True)
|
|
647
|
+
self.logger.info(f"Released browser context for {self.agent_id}")
|
|
648
|
+
except Exception as e:
|
|
649
|
+
self.logger.debug(f"Error releasing browser context: {e}")
|
|
650
|
+
|
|
651
|
+
self.telemetry_manager.capture_event(
|
|
652
|
+
AgentEndTelemetryEvent(
|
|
653
|
+
agent_id=self.agent_id,
|
|
654
|
+
success=self.history.is_done(),
|
|
655
|
+
steps=self.state.n_steps,
|
|
656
|
+
max_steps_reached=self.state.n_steps >= max_steps,
|
|
657
|
+
errors=self.history.errors(),
|
|
658
|
+
)
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
|