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,397 @@
|
|
|
1
|
+
"""Agent-creation + session-execution mixin (roadmap P9; code-motion from orchestrator.py).
|
|
2
|
+
|
|
3
|
+
create_agent (build + register an Agent) and execute_session (run the session loop),
|
|
4
|
+
extracted as whole methods so orchestrator.py drops under 700L. SessionOrchestrator
|
|
5
|
+
composes SessionExecutionMixin; callers (task_agent_lite, sub_agent_manager) use
|
|
6
|
+
orchestrator.create_agent / execute_session unchanged via MRO.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
import json
|
|
12
|
+
import time
|
|
13
|
+
from typing import Any, Dict, List, Optional
|
|
14
|
+
|
|
15
|
+
# Module-level Agent import (no cycle: service does not import orchestrator, and
|
|
16
|
+
# service is loaded before this module during orchestrator import).
|
|
17
|
+
from agents.task.agent.service import Agent
|
|
18
|
+
from core.exceptions import LLMError, LLMPermanentError, LLMProviderExhaustedError
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _result_session_status(result) -> str:
|
|
22
|
+
"""Map an agent.run() result (AgentHistoryList) to a session status.
|
|
23
|
+
|
|
24
|
+
Live-test F7b: a permanent LLM/billing error halts the loop *inside* the agent
|
|
25
|
+
(error_recovery sets a final ActionResult with .error and is_done=True), so
|
|
26
|
+
agent.run() returns a truthy history and the old `"completed" if result` logic
|
|
27
|
+
mislabeled the halt as a success. A terminal result carrying .error is an
|
|
28
|
+
'error', not 'completed'. A genuine done() has error=None, so success is
|
|
29
|
+
unaffected. Falsy result → 'failed' (unchanged).
|
|
30
|
+
"""
|
|
31
|
+
if not result:
|
|
32
|
+
return "failed"
|
|
33
|
+
try:
|
|
34
|
+
last = result.history[-1].result[-1]
|
|
35
|
+
if getattr(last, "error", None):
|
|
36
|
+
return "error"
|
|
37
|
+
except (AttributeError, IndexError, TypeError):
|
|
38
|
+
pass
|
|
39
|
+
return "completed"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SessionExecutionMixin:
|
|
43
|
+
"""Agent creation + session execution for SessionOrchestrator."""
|
|
44
|
+
|
|
45
|
+
async def create_agent(self,
|
|
46
|
+
task: str,
|
|
47
|
+
llm: Any = None,
|
|
48
|
+
agent_name: str = "agent",
|
|
49
|
+
profile_id: Optional[str] = None,
|
|
50
|
+
profile_overrides: Optional[Dict[str, Any]] = None,
|
|
51
|
+
share_controller: bool = True,
|
|
52
|
+
**kwargs) -> Any:
|
|
53
|
+
"""Create an agent for this session.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
task: Task description for the agent
|
|
57
|
+
llm: Language model to use
|
|
58
|
+
agent_name: Name for the agent
|
|
59
|
+
profile_id: Optional profile ID to use
|
|
60
|
+
profile_overrides: Optional overrides for the profile
|
|
61
|
+
share_controller: Whether to share the controller with other agents
|
|
62
|
+
**kwargs: Additional agent configuration
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Configured Agent instance
|
|
66
|
+
"""
|
|
67
|
+
from agents.task.agent.service import Agent
|
|
68
|
+
|
|
69
|
+
self.logger.info(f"Creating agent '{agent_name}' for session {self.session_id}")
|
|
70
|
+
|
|
71
|
+
# CRITICAL FIX: If no LLM provided, get default from LLMManager
|
|
72
|
+
# This ensures sub-agents created via SubAgentManager get a valid LLM
|
|
73
|
+
if llm is None:
|
|
74
|
+
self.logger.info(f"No LLM provided for agent '{agent_name}', getting default from LLMManager")
|
|
75
|
+
try:
|
|
76
|
+
if self.container:
|
|
77
|
+
llm_manager = self.container.get_service('llm')
|
|
78
|
+
if llm_manager:
|
|
79
|
+
# Get default LLM using the primary provider
|
|
80
|
+
# Use fallback method to get any available provider
|
|
81
|
+
llm = await llm_manager.get_fallback_chat_model(
|
|
82
|
+
exclude_providers=[], # Don't exclude any providers
|
|
83
|
+
temperature=0.0
|
|
84
|
+
)
|
|
85
|
+
if llm:
|
|
86
|
+
self.logger.info(f"✅ Got default LLM for agent '{agent_name}': {getattr(llm, 'model_name', 'unknown')}")
|
|
87
|
+
else:
|
|
88
|
+
self.logger.error(f"❌ LLMManager returned no available LLM for agent '{agent_name}'")
|
|
89
|
+
raise RuntimeError(f"No LLM available for agent '{agent_name}'. Check your API keys.")
|
|
90
|
+
else:
|
|
91
|
+
self.logger.error(f"❌ LLMManager not found in container for agent '{agent_name}'")
|
|
92
|
+
raise RuntimeError(f"LLMManager not available in container for agent '{agent_name}'")
|
|
93
|
+
else:
|
|
94
|
+
self.logger.error(f"❌ No container available to get LLM for agent '{agent_name}'")
|
|
95
|
+
raise RuntimeError(f"No container available to get LLM for agent '{agent_name}'")
|
|
96
|
+
except Exception as e:
|
|
97
|
+
self.logger.error(f"Failed to get default LLM for agent '{agent_name}': {e}", exc_info=True)
|
|
98
|
+
raise RuntimeError(f"Cannot create agent '{agent_name}' without LLM: {e}")
|
|
99
|
+
|
|
100
|
+
# Generate unique agent ID (matches what Agent class will set)
|
|
101
|
+
agent_id = f"{agent_name}_{self.session_id}"
|
|
102
|
+
|
|
103
|
+
# Prepare agent configuration with all required parameters
|
|
104
|
+
# NOTE: Browser context obtained on-demand via orchestrator.get_browser_context()
|
|
105
|
+
agent_config = {
|
|
106
|
+
"agent_name": agent_name,
|
|
107
|
+
"task": task,
|
|
108
|
+
"llm": llm,
|
|
109
|
+
"orchestrator": self, # Orchestrator provides session_id and user_id (single source of truth)
|
|
110
|
+
**kwargs
|
|
111
|
+
}
|
|
112
|
+
# session_id and user_id removed - Agent gets them from orchestrator
|
|
113
|
+
|
|
114
|
+
# Note: Controller is accessed via self.orchestrator.controller in Agent.__init__
|
|
115
|
+
# No need to pass it explicitly as a parameter
|
|
116
|
+
|
|
117
|
+
# Add session_config if available
|
|
118
|
+
if hasattr(self, 'session_config') and self.session_config:
|
|
119
|
+
agent_config["session_config"] = self.session_config
|
|
120
|
+
|
|
121
|
+
# S1/S2 (chat consolidation): forward the chat-mode persona block set on
|
|
122
|
+
# the orchestrator (by TaskAgent.chat_once) into AgentConfig so the agent's
|
|
123
|
+
# SystemPrompt <identity> carries the character. None => byte-identical.
|
|
124
|
+
_persona = getattr(self, '_persona_block', None)
|
|
125
|
+
if _persona:
|
|
126
|
+
agent_config["persona_block"] = _persona
|
|
127
|
+
|
|
128
|
+
# Use profile if specified
|
|
129
|
+
if profile_id:
|
|
130
|
+
agent_config["profile_id"] = profile_id
|
|
131
|
+
if profile_overrides:
|
|
132
|
+
agent_config["profile_overrides"] = profile_overrides
|
|
133
|
+
|
|
134
|
+
# Create the agent
|
|
135
|
+
try:
|
|
136
|
+
agent = Agent.from_params(**agent_config)
|
|
137
|
+
|
|
138
|
+
# Validate requested tools are available
|
|
139
|
+
if hasattr(self, 'session_config') and self.session_config and isinstance(self.session_config, dict):
|
|
140
|
+
requested_tools = self.session_config.get('tools', [])
|
|
141
|
+
if requested_tools:
|
|
142
|
+
available_tools = self.controller.list_tools()
|
|
143
|
+
missing_tools = [t for t in requested_tools if t not in available_tools]
|
|
144
|
+
if missing_tools:
|
|
145
|
+
self.logger.warning(f"Agent '{agent_name}' missing requested tools: {missing_tools}")
|
|
146
|
+
|
|
147
|
+
# Track the agent
|
|
148
|
+
self.agents[agent_id] = agent
|
|
149
|
+
self.agent_types[agent_id] = profile_id or "executor"
|
|
150
|
+
self.agent_names[agent_id] = agent_name
|
|
151
|
+
import time
|
|
152
|
+
self.agent_creation_times[agent_id] = time.time()
|
|
153
|
+
# Store model name using agent property (after agent is created)
|
|
154
|
+
self.agent_models[agent_id] = agent.model_name
|
|
155
|
+
|
|
156
|
+
# Register agent with SessionManager (centralized registration)
|
|
157
|
+
# Skip for sub-agents - they're ephemeral and shouldn't pollute session registry
|
|
158
|
+
is_sub_agent = kwargs.get('is_sub_agent', False)
|
|
159
|
+
if self.session_manager and not is_sub_agent:
|
|
160
|
+
try:
|
|
161
|
+
self.session_manager.register_agent(
|
|
162
|
+
session_id=self.session_id,
|
|
163
|
+
agent_name=agent_name,
|
|
164
|
+
agent_id=agent_id,
|
|
165
|
+
agent_type=type(agent).__name__,
|
|
166
|
+
model_name=agent.model_name, # Use agent property (delegates to MessageManager)
|
|
167
|
+
user_id=self.user_id,
|
|
168
|
+
role="executor"
|
|
169
|
+
)
|
|
170
|
+
self.logger.debug(f"Registered agent '{agent_name}' with SessionManager")
|
|
171
|
+
|
|
172
|
+
# Emit telemetry for agent creation using TelemetryManager
|
|
173
|
+
try:
|
|
174
|
+
self.telemetry_manager.capture_agent_registration(
|
|
175
|
+
agent_id=agent_id,
|
|
176
|
+
agent_name=agent_name,
|
|
177
|
+
agent_type=type(agent).__name__,
|
|
178
|
+
model_name=agent.model_name, # Use agent property (delegates to MessageManager)
|
|
179
|
+
task=task
|
|
180
|
+
)
|
|
181
|
+
except Exception as te:
|
|
182
|
+
self.logger.debug(f"Failed to emit agent registration telemetry: {te}")
|
|
183
|
+
except Exception as e:
|
|
184
|
+
self.logger.warning(f"Failed to register agent with SessionManager: {e}")
|
|
185
|
+
elif is_sub_agent:
|
|
186
|
+
self.logger.debug(f"Skipped SessionManager registration for sub-agent '{agent_name}'")
|
|
187
|
+
|
|
188
|
+
# Register streaming callback if one was supplied (server layer
|
|
189
|
+
# provides the transport; core mode leaves _on_stream_chunk None).
|
|
190
|
+
if self._on_stream_chunk is not None:
|
|
191
|
+
await self._register_stream_callback(agent)
|
|
192
|
+
|
|
193
|
+
# CRITICAL FIX: Flush pending messages to newly created agent
|
|
194
|
+
# This ensures messages queued before agent existed are delivered
|
|
195
|
+
# SECURITY FIX: Use lock to prevent race with submit_user_message
|
|
196
|
+
async with self._pending_messages_lock:
|
|
197
|
+
if self._pending_messages and hasattr(agent, 'hitl_manager') and agent.hitl_manager:
|
|
198
|
+
pending_count = len(self._pending_messages)
|
|
199
|
+
image_count = sum(
|
|
200
|
+
1 for _, _, meta in self._pending_messages
|
|
201
|
+
if meta and meta.get('image_attachments')
|
|
202
|
+
)
|
|
203
|
+
self.logger.info(
|
|
204
|
+
f"📦 Flushing {pending_count} pending message(s) to agent {agent_id} "
|
|
205
|
+
f"({image_count} with images)"
|
|
206
|
+
)
|
|
207
|
+
for text, kind, metadata in self._pending_messages:
|
|
208
|
+
await agent.hitl_manager.queue_user_message(text, kind, metadata)
|
|
209
|
+
has_images = bool(metadata and metadata.get('image_attachments'))
|
|
210
|
+
self.logger.debug(f" → Delivered pending message (has_images={has_images})")
|
|
211
|
+
self._pending_messages.clear()
|
|
212
|
+
self.logger.info(f"✅ All pending messages delivered to agent")
|
|
213
|
+
|
|
214
|
+
self.logger.info(f"✅ Created agent '{agent_name}' with ID {agent_id}")
|
|
215
|
+
return agent
|
|
216
|
+
|
|
217
|
+
except Exception as e:
|
|
218
|
+
self.logger.error(f"Failed to create agent '{agent_name}': {e}")
|
|
219
|
+
raise
|
|
220
|
+
|
|
221
|
+
async def execute_session(self,
|
|
222
|
+
agent_sequence: List[str],
|
|
223
|
+
max_steps_per_agent: Optional[Dict[str, int]] = None,
|
|
224
|
+
shared_context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
225
|
+
"""Execute a session with the given agent sequence.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
agent_sequence: List of agent IDs to execute in sequence
|
|
229
|
+
max_steps_per_agent: Maximum steps per agent
|
|
230
|
+
shared_context: Shared context data
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
Results from the session execution
|
|
234
|
+
"""
|
|
235
|
+
self.logger.info(f"Executing session with {len(agent_sequence)} agents: {agent_sequence}")
|
|
236
|
+
|
|
237
|
+
# C-N1: fire on_session_start once (fail-open; no-op unless hooks registered).
|
|
238
|
+
if not getattr(self, "_session_start_fired", False):
|
|
239
|
+
self._session_start_fired = True
|
|
240
|
+
run_hooks = getattr(self, "_run_session_start_hooks", None)
|
|
241
|
+
if run_hooks is not None:
|
|
242
|
+
await run_hooks(session_id=self.session_id, user_id=getattr(self, "user_id", None))
|
|
243
|
+
|
|
244
|
+
results = {}
|
|
245
|
+
max_steps_per_agent = max_steps_per_agent or {}
|
|
246
|
+
|
|
247
|
+
try:
|
|
248
|
+
for agent_id in agent_sequence:
|
|
249
|
+
if agent_id not in self.agents:
|
|
250
|
+
self.logger.error(f"Agent {agent_id} not found in session")
|
|
251
|
+
continue
|
|
252
|
+
|
|
253
|
+
agent = self.agents[agent_id]
|
|
254
|
+
max_steps = max_steps_per_agent.get(agent_id, 50)
|
|
255
|
+
|
|
256
|
+
self.logger.info(f"Running agent {agent_id} with max {max_steps} steps")
|
|
257
|
+
|
|
258
|
+
# Track agent execution
|
|
259
|
+
import time
|
|
260
|
+
start_time = time.time()
|
|
261
|
+
|
|
262
|
+
try:
|
|
263
|
+
# Run the agent
|
|
264
|
+
result = await agent.run(max_steps=max_steps)
|
|
265
|
+
end_time = time.time()
|
|
266
|
+
|
|
267
|
+
# Track execution - include agent_type parameter
|
|
268
|
+
agent_type = type(agent).__name__
|
|
269
|
+
self.track_agent_execution(agent_id, agent_type, start_time, end_time)
|
|
270
|
+
|
|
271
|
+
# Store result
|
|
272
|
+
results[agent_id] = {
|
|
273
|
+
"status": _result_session_status(result),
|
|
274
|
+
"result": result,
|
|
275
|
+
"execution_time": end_time - start_time
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
self.logger.info(f"Agent {agent_id} completed with status: {results[agent_id]['status']}")
|
|
279
|
+
|
|
280
|
+
except LLMProviderExhaustedError as e:
|
|
281
|
+
# All LLM providers have been tried and failed - don't retry
|
|
282
|
+
end_time = time.time()
|
|
283
|
+
providers = getattr(e, 'providers_tried', [])
|
|
284
|
+
self.logger.error(f"❌ Agent {agent_id} exhausted all LLM providers: {providers}")
|
|
285
|
+
results[agent_id] = {
|
|
286
|
+
"status": "error",
|
|
287
|
+
"error": f"All LLM providers exhausted: {providers}",
|
|
288
|
+
"execution_time": end_time - start_time,
|
|
289
|
+
"providers_tried": providers
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
except LLMPermanentError as e:
|
|
293
|
+
# Permanent error (auth, billing) - don't retry
|
|
294
|
+
end_time = time.time()
|
|
295
|
+
self.logger.error(f"❌ Agent {agent_id} hit permanent LLM error: {e}")
|
|
296
|
+
results[agent_id] = {
|
|
297
|
+
"status": "error",
|
|
298
|
+
"error": f"Permanent LLM error: {str(e)[:300]}",
|
|
299
|
+
"execution_time": end_time - start_time,
|
|
300
|
+
"is_permanent": True
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
except InterruptedError as e:
|
|
304
|
+
# CRITICAL FIX (Dec 2025): Handle pause/stop gracefully
|
|
305
|
+
# InterruptedError is raised when agent is stopped (not paused - pause now waits)
|
|
306
|
+
end_time = time.time()
|
|
307
|
+
error_str = str(e).lower()
|
|
308
|
+
|
|
309
|
+
if "paused" in error_str:
|
|
310
|
+
# Agent was paused - this is a graceful interruption, not an error
|
|
311
|
+
self.logger.info(f"⏸️ Agent {agent_id} paused by user")
|
|
312
|
+
results[agent_id] = {
|
|
313
|
+
"status": "paused",
|
|
314
|
+
"execution_time": end_time - start_time
|
|
315
|
+
}
|
|
316
|
+
else:
|
|
317
|
+
# Agent was stopped
|
|
318
|
+
self.logger.info(f"⏹️ Agent {agent_id} stopped: {e}")
|
|
319
|
+
results[agent_id] = {
|
|
320
|
+
"status": "stopped",
|
|
321
|
+
"execution_time": end_time - start_time
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
except Exception as e:
|
|
325
|
+
end_time = time.time()
|
|
326
|
+
error_str = str(e).lower()
|
|
327
|
+
|
|
328
|
+
# UPGRADE (Dec 2025): Check if this is an LLM error that might benefit from fallback
|
|
329
|
+
is_llm_error = (
|
|
330
|
+
isinstance(e, LLMError) or
|
|
331
|
+
any(x in error_str for x in [
|
|
332
|
+
'llm', 'rate_limit', 'rate limit', '429', 'authentication',
|
|
333
|
+
'connection', 'timeout', 'quota'
|
|
334
|
+
])
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
if is_llm_error and hasattr(agent, 'state') and not agent.state.should_halt_for_llm_error():
|
|
338
|
+
self.logger.warning(f"Agent {agent_id} failed with LLM error, checking for fallback...")
|
|
339
|
+
|
|
340
|
+
# Try to get fallback LLM from container
|
|
341
|
+
try:
|
|
342
|
+
if self.container:
|
|
343
|
+
llm_manager = self.container.get_service('llm')
|
|
344
|
+
if llm_manager and hasattr(llm_manager, 'get_fallback_chat_model'):
|
|
345
|
+
fallback_llm = await llm_manager.get_fallback_chat_model(
|
|
346
|
+
exclude_providers=getattr(agent.state, 'llm_providers_failed', [])
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
if fallback_llm:
|
|
350
|
+
self.logger.info(f"🔄 Retrying agent {agent_id} with fallback LLM")
|
|
351
|
+
agent.llm = fallback_llm
|
|
352
|
+
agent.model_name = getattr(fallback_llm, 'model_name', 'fallback')
|
|
353
|
+
|
|
354
|
+
# Retry execution
|
|
355
|
+
retry_start = time.time()
|
|
356
|
+
result = await agent.run(max_steps=max_steps)
|
|
357
|
+
retry_end = time.time()
|
|
358
|
+
|
|
359
|
+
results[agent_id] = {
|
|
360
|
+
"status": _result_session_status(result),
|
|
361
|
+
"result": result,
|
|
362
|
+
"execution_time": retry_end - start_time,
|
|
363
|
+
"fallback_used": True
|
|
364
|
+
}
|
|
365
|
+
self.logger.info(f"✅ Agent {agent_id} succeeded with fallback LLM")
|
|
366
|
+
continue # Skip to next agent
|
|
367
|
+
except LLMProviderExhaustedError:
|
|
368
|
+
self.logger.error(f"Fallback retry exhausted all providers for {agent_id}")
|
|
369
|
+
except Exception as fallback_error:
|
|
370
|
+
self.logger.error(f"Fallback retry failed for {agent_id}: {fallback_error}")
|
|
371
|
+
|
|
372
|
+
self.logger.error(f"Agent {agent_id} failed: {e}")
|
|
373
|
+
results[agent_id] = {
|
|
374
|
+
"status": "error",
|
|
375
|
+
"error": str(e),
|
|
376
|
+
"execution_time": end_time - start_time
|
|
377
|
+
}
|
|
378
|
+
finally:
|
|
379
|
+
# Release browser context immediately after agent completes
|
|
380
|
+
if self.browser_manager:
|
|
381
|
+
try:
|
|
382
|
+
await self.browser_manager.release_context(agent_id, close=True)
|
|
383
|
+
self.logger.debug(f"Released browser context for completed agent {agent_id}")
|
|
384
|
+
except Exception as release_error:
|
|
385
|
+
self.logger.warning(f"Error releasing context for {agent_id}: {release_error}")
|
|
386
|
+
|
|
387
|
+
# NOTE: Status updates removed - task_agent_lite owns session status lifecycle
|
|
388
|
+
# Orchestrator only executes agents, it doesn't manage session status
|
|
389
|
+
self.logger.info(f"Session execution completed. Results: {list(results.keys())}")
|
|
390
|
+
return results
|
|
391
|
+
|
|
392
|
+
except Exception as e:
|
|
393
|
+
self.logger.error(f"Session execution failed: {e}")
|
|
394
|
+
# NOTE: Don't update status here - let caller (task_agent_lite) handle it
|
|
395
|
+
raise
|
|
396
|
+
|
|
397
|
+
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import time
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Any, Awaitable, Callable, Optional
|
|
7
|
+
|
|
8
|
+
_logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def build_stream_publish(
|
|
12
|
+
router: Any, session_key: Optional[str]
|
|
13
|
+
) -> Callable[..., Awaitable[None]]:
|
|
14
|
+
"""Return an async ``(chunk, step) -> None`` that mirrors a streamed chunk into
|
|
15
|
+
the unified outbound seam (``MessageRouter.publish``) as a partial OutboundMessage.
|
|
16
|
+
|
|
17
|
+
P1a outbound-collapse: additive and gated on ``SINGULAR_CHAT_ENABLED``. When the
|
|
18
|
+
flag is OFF, or there is no router / session_key, the returned fn is a no-op so
|
|
19
|
+
the legacy stream callback path stays byte-identical. Fail-open — a publish error
|
|
20
|
+
never propagates into the run loop.
|
|
21
|
+
"""
|
|
22
|
+
async def _publish(chunk: str, step: int = 0) -> None:
|
|
23
|
+
from agents.task.surface_config import SurfaceConfig
|
|
24
|
+
|
|
25
|
+
if not SurfaceConfig.singular_chat_enabled():
|
|
26
|
+
return
|
|
27
|
+
if router is None or not session_key:
|
|
28
|
+
return
|
|
29
|
+
try:
|
|
30
|
+
from core.surfaces.envelopes import OutboundMessage
|
|
31
|
+
|
|
32
|
+
await router.publish(OutboundMessage(
|
|
33
|
+
session_key=session_key,
|
|
34
|
+
text=chunk,
|
|
35
|
+
partial=True,
|
|
36
|
+
# Stable per-TURN stream_id (the session_key, NOT per-step): all of a
|
|
37
|
+
# turn's deltas edit ONE live message under incremental streaming, and the
|
|
38
|
+
# turn's discrete reply finalizes that same stream (see Surface
|
|
39
|
+
# _finalize_live_on_send). A per-step id would open a new bubble each step
|
|
40
|
+
# and never finalize. `step` is retained for callers but no longer keys.
|
|
41
|
+
stream_id=session_key,
|
|
42
|
+
))
|
|
43
|
+
except Exception as e: # fail-open: streaming mirror is non-critical
|
|
44
|
+
_logger.debug("stream publish mirror failed: %s", e)
|
|
45
|
+
|
|
46
|
+
return _publish
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class FeedMixin:
|
|
50
|
+
"""Feed metadata processing and stream-callback wiring for SessionOrchestrator."""
|
|
51
|
+
|
|
52
|
+
def _process_feed_metadata(self, clean_id, feed_entries: list) -> None:
|
|
53
|
+
"""Extract and store metadata from feed entries.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
clean_id: Cleaned session ID
|
|
57
|
+
feed_entries: List of feed entry data objects
|
|
58
|
+
"""
|
|
59
|
+
if not feed_entries:
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
# Initialize metadata update
|
|
64
|
+
metadata_update = {
|
|
65
|
+
"feed": {
|
|
66
|
+
"processed_entries": len(feed_entries),
|
|
67
|
+
"last_processed": datetime.now().isoformat(),
|
|
68
|
+
"entries": []
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Process each entry and extract key information
|
|
73
|
+
for entry in feed_entries:
|
|
74
|
+
# Skip entries without proper type
|
|
75
|
+
if not isinstance(entry, dict) or "type" not in entry:
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
entry_type = entry.get("type", "unknown")
|
|
79
|
+
timestamp = entry.get("timestamp", time.time())
|
|
80
|
+
|
|
81
|
+
# Create basic entry metadata
|
|
82
|
+
entry_meta = {
|
|
83
|
+
"type": entry_type,
|
|
84
|
+
"timestamp": timestamp
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# Extract specific data based on entry type
|
|
88
|
+
if entry_type == "step" and "data" in entry:
|
|
89
|
+
# Step data - extract actions and progress
|
|
90
|
+
data = entry.get("data", {})
|
|
91
|
+
step_num = entry.get("step", 0)
|
|
92
|
+
|
|
93
|
+
# Add step-specific metadata
|
|
94
|
+
entry_meta.update({
|
|
95
|
+
"step": step_num,
|
|
96
|
+
"actions": [action.get("name", action.get("action_type", "unknown"))
|
|
97
|
+
for action in data.get("actions", [])],
|
|
98
|
+
"has_errors": bool(data.get("errors")),
|
|
99
|
+
"task_progress": data.get("task_progress", "")
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
elif entry_type == "planner" and "data" in entry:
|
|
103
|
+
# Planner data
|
|
104
|
+
data = entry.get("data", {})
|
|
105
|
+
step_num = entry.get("step", 0)
|
|
106
|
+
|
|
107
|
+
# Add planner-specific metadata
|
|
108
|
+
entry_meta.update({
|
|
109
|
+
"step": step_num,
|
|
110
|
+
"model": data.get("model_name", "unknown"),
|
|
111
|
+
"components": data.get("components", {})
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
elif entry_type == "evaluation" and "data" in entry:
|
|
115
|
+
# Evaluation data
|
|
116
|
+
data = entry.get("data", {})
|
|
117
|
+
step_num = entry.get("step", 0)
|
|
118
|
+
|
|
119
|
+
# Add evaluation-specific metadata
|
|
120
|
+
entry_meta.update({
|
|
121
|
+
"step": step_num,
|
|
122
|
+
"model": data.get("model_name", "unknown"),
|
|
123
|
+
"assessment": data.get("assessment", ""),
|
|
124
|
+
"has_strengths": bool(data.get("strengths")),
|
|
125
|
+
"has_weaknesses": bool(data.get("weaknesses")),
|
|
126
|
+
"has_suggestions": bool(data.get("suggestions"))
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
elif entry_type == "multi_agent_relationship" and "data" in entry:
|
|
130
|
+
# Relationship data
|
|
131
|
+
data = entry.get("data", {})
|
|
132
|
+
|
|
133
|
+
# Add relationship-specific metadata
|
|
134
|
+
entry_meta.update({
|
|
135
|
+
"agent_count": len(data.get("agent_ids", [])),
|
|
136
|
+
"agent_types": data.get("agent_types", {}),
|
|
137
|
+
"has_sequence": bool(data.get("agent_sequence"))
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
# Add the entry metadata to the list
|
|
141
|
+
metadata_update["feed"]["entries"].append(entry_meta)
|
|
142
|
+
|
|
143
|
+
# Update session metadata with the feed information
|
|
144
|
+
if self.session_manager:
|
|
145
|
+
self.session_manager.update_session_metadata(clean_id, metadata_update)
|
|
146
|
+
self.logger.debug(f"Updated session metadata with {len(feed_entries)} feed entries")
|
|
147
|
+
|
|
148
|
+
except Exception as e:
|
|
149
|
+
self.logger.warning(f"Error processing feed metadata: {e}", exc_info=True)
|
|
150
|
+
|
|
151
|
+
async def _register_stream_callback(self, agent: Any) -> None:
|
|
152
|
+
"""Wire the injected stream callback into the agent's HITL manager.
|
|
153
|
+
|
|
154
|
+
The callback transport (httpx → webview, websocket, in-memory queue,
|
|
155
|
+
etc.) is supplied by whoever constructed the orchestrator. Core code
|
|
156
|
+
never knows the destination; it only forwards each LLM output chunk
|
|
157
|
+
with metadata.
|
|
158
|
+
"""
|
|
159
|
+
callback = self._on_stream_chunk
|
|
160
|
+
# P1a outbound-collapse: mirror chunks into the unified MessageRouter seam when
|
|
161
|
+
# a router + chat session_key have been bound (later phases). No-op otherwise,
|
|
162
|
+
# so the legacy callback path stays byte-identical until then.
|
|
163
|
+
_mirror = build_stream_publish(
|
|
164
|
+
getattr(self, "_message_router", None),
|
|
165
|
+
getattr(self, "_chat_session_key", None),
|
|
166
|
+
)
|
|
167
|
+
if callback is None:
|
|
168
|
+
# Even with no legacy callback, the unified mirror may be active.
|
|
169
|
+
async def stream_wrapper(chunk: str) -> None:
|
|
170
|
+
await _mirror(chunk, getattr(agent, 'n_steps', 0))
|
|
171
|
+
try:
|
|
172
|
+
agent.hitl_manager.register_output_callback(stream_wrapper)
|
|
173
|
+
except Exception as e:
|
|
174
|
+
self.logger.warning(f"Failed to register stream callback: {e}")
|
|
175
|
+
return
|
|
176
|
+
|
|
177
|
+
async def stream_wrapper(chunk: str) -> None:
|
|
178
|
+
try:
|
|
179
|
+
await callback(
|
|
180
|
+
self.session_id,
|
|
181
|
+
agent.agent_id,
|
|
182
|
+
chunk,
|
|
183
|
+
getattr(agent, 'n_steps', 0),
|
|
184
|
+
)
|
|
185
|
+
except Exception as e:
|
|
186
|
+
# Streaming is non-critical; never fail the run for transport errors.
|
|
187
|
+
self.logger.debug(f"Stream callback error: {e}")
|
|
188
|
+
await _mirror(chunk, getattr(agent, 'n_steps', 0))
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
agent.hitl_manager.register_output_callback(stream_wrapper)
|
|
192
|
+
self.logger.info(f"✅ Stream callback registered for {agent.agent_id}")
|
|
193
|
+
except Exception as e:
|
|
194
|
+
self.logger.warning(f"Failed to register stream callback: {e}")
|
|
195
|
+
|
|
196
|
+
async def add_to_feed(self, agent_id: str, entry_type: str, data: dict) -> None:
|
|
197
|
+
if self.session_manager:
|
|
198
|
+
await self.session_manager.add_to_feed(
|
|
199
|
+
self.session_id, agent_id, entry_type, data
|
|
200
|
+
)
|