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,389 @@
|
|
|
1
|
+
"""Action result-processing mixin (roadmap P9; code-motion from step.py).
|
|
2
|
+
|
|
3
|
+
Post-execution handling: turning action results into tool messages and processing
|
|
4
|
+
them into the next-step brain/memory. Split out of StepMixin so step.py trends
|
|
5
|
+
toward the step-phase skeleton. Agent composes ResultProcessingMixin; the step
|
|
6
|
+
loop calls these via MRO.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import logging
|
|
12
|
+
from typing import Any, Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
from agents.task.agent.views import ActionResult, AgentBrain
|
|
15
|
+
from agents.task.agent.core.untrusted_wrap import maybe_wrap
|
|
16
|
+
from modules.llm.messages import AIMessage, ToolMessage
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _pair_results_to_calls(result, tool_calls_to_pass, source_for=None):
|
|
22
|
+
"""Map each tool_call id -> (content, had_error) by identity.
|
|
23
|
+
|
|
24
|
+
Prefers ActionResult.tool_call_id (set by multi_act). Falls back to
|
|
25
|
+
positional pairing only when ids are absent (legacy / non-native path).
|
|
26
|
+
|
|
27
|
+
UP-06: when ``source_for`` is provided (a callable ``tool_call_id ->
|
|
28
|
+
(action_name, tool)``), the string ``extracted_content`` of an untrusted
|
|
29
|
+
tool result (mcp/browser/web/perplexity) is framed in
|
|
30
|
+
``<untrusted_tool_result>`` delimiters. ``source_for=None`` (default) skips
|
|
31
|
+
wrapping entirely — preserving the legacy 2-arg call sites/tests byte-for-byte.
|
|
32
|
+
Only the returned string is wrapped; the ``ActionResult`` object is never
|
|
33
|
+
mutated, so memory previews / telemetry stay clean.
|
|
34
|
+
"""
|
|
35
|
+
def _entry(ar, tc_id=None):
|
|
36
|
+
if ar.error:
|
|
37
|
+
# UP-06: an untrusted tool can control its own error string, so the error
|
|
38
|
+
# branch must go through the same wrap as extracted_content — otherwise
|
|
39
|
+
# injected instructions in a tool's error reach the model unframed.
|
|
40
|
+
content = f"Error: {ar.error}"
|
|
41
|
+
if source_for is not None and tc_id is not None:
|
|
42
|
+
action_name, tool = source_for(tc_id)
|
|
43
|
+
content = maybe_wrap(action_name, tool, content)
|
|
44
|
+
return (content, True)
|
|
45
|
+
if ar.extracted_content:
|
|
46
|
+
content = str(ar.extracted_content)
|
|
47
|
+
if source_for is not None and tc_id is not None:
|
|
48
|
+
action_name, tool = source_for(tc_id)
|
|
49
|
+
content = maybe_wrap(action_name, tool, content)
|
|
50
|
+
return (content, False)
|
|
51
|
+
if ar.is_done:
|
|
52
|
+
return ("Task marked as complete", False)
|
|
53
|
+
return ("Action completed successfully", False)
|
|
54
|
+
|
|
55
|
+
results = result or []
|
|
56
|
+
have_ids = len(results) > 0 and all(getattr(r, "tool_call_id", None) for r in results)
|
|
57
|
+
# P0-2 tripwire: identity pairing is the correct path. Positional pairing with
|
|
58
|
+
# >1 result misattributes outputs whenever the executor skips/reorders/truncates
|
|
59
|
+
# actions. If ids are missing on a multi-result step, the _tool_call_id re-stamp
|
|
60
|
+
# in next_action_internal regressed — surface it loudly instead of dying silent.
|
|
61
|
+
if not have_ids and len(results) > 1:
|
|
62
|
+
logger.warning(
|
|
63
|
+
"[pair] no tool_call_id on a %d-result step; falling back to POSITIONAL "
|
|
64
|
+
"pairing (results may be misattributed if the executor skipped/reordered "
|
|
65
|
+
"actions). Check the P0-2 tool_call_id re-stamp.",
|
|
66
|
+
len(results),
|
|
67
|
+
)
|
|
68
|
+
paired = {}
|
|
69
|
+
if have_ids:
|
|
70
|
+
ids = [ar.tool_call_id for ar in results]
|
|
71
|
+
if len(set(ids)) == len(ids):
|
|
72
|
+
return {ar.tool_call_id: _entry(ar, ar.tool_call_id) for ar in results}
|
|
73
|
+
# Duplicate tool_call_id in one step: identity pairing would silently drop a
|
|
74
|
+
# result (both dups collapse to one dict key). Fall back to POSITION-keyed
|
|
75
|
+
# pairing — (tool_call_id, index) — so every result surfaces; the consumer
|
|
76
|
+
# looks up by (id, i) first, then by id. Keeps the unique early-return above
|
|
77
|
+
# (keyed by id) unchanged.
|
|
78
|
+
logger.warning(
|
|
79
|
+
"[pair] duplicate tool_call_id detected (%s); falling back to positional pairing",
|
|
80
|
+
ids,
|
|
81
|
+
)
|
|
82
|
+
for i, tc in enumerate(tool_calls_to_pass):
|
|
83
|
+
if i < len(results):
|
|
84
|
+
tc_id = tc.get("id")
|
|
85
|
+
paired[(tc_id, i)] = _entry(results[i], tc_id)
|
|
86
|
+
return paired
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class ResultProcessingMixin:
|
|
90
|
+
"""Tool-message construction + action-result processing for Agent."""
|
|
91
|
+
|
|
92
|
+
async def _add_tool_messages(self, result, model_output, tool_calls_to_pass) -> bool:
|
|
93
|
+
"""Add AIMessage + ToolMessages for the step's tool calls.
|
|
94
|
+
|
|
95
|
+
Returns True on success (continue the step) and False on the corrupted-state
|
|
96
|
+
path (atomic mismatch), which signals the caller to abort the step.
|
|
97
|
+
"""
|
|
98
|
+
# Atomic message addition: AIMessage + all ToolMessages added together
|
|
99
|
+
if self.use_native_tools and tool_calls_to_pass:
|
|
100
|
+
self.logger.info(f"[ATOMIC] Preparing atomic addition for {len(tool_calls_to_pass)} tool calls")
|
|
101
|
+
|
|
102
|
+
# FIXED: Get validation errors from controller for tool calls that failed validation
|
|
103
|
+
validation_errors = {}
|
|
104
|
+
if self.controller:
|
|
105
|
+
validation_errors = self.controller.get_last_validation_errors()
|
|
106
|
+
if validation_errors:
|
|
107
|
+
self.logger.warning(f"[ATOMIC] {len(validation_errors)} tool calls had validation errors")
|
|
108
|
+
|
|
109
|
+
# Step 1: Build all tool responses from action results
|
|
110
|
+
# Pair results to calls by IDENTITY (tool_call_id), not list position —
|
|
111
|
+
# the executor reorders/truncates actions, so positional pairing misaligns.
|
|
112
|
+
tool_responses = []
|
|
113
|
+
# UP-06: resolve each tool call's (action_name, tool namespace) so untrusted
|
|
114
|
+
# results (mcp/browser/web/perplexity) get framed as DATA before entering
|
|
115
|
+
# history. Gated on the flag; source_for=None => no wrapping (legacy).
|
|
116
|
+
source_for = None
|
|
117
|
+
from agents.task.constants import UNTRUSTED_TOOL_RESULT_WRAP
|
|
118
|
+
if UNTRUSTED_TOOL_RESULT_WRAP:
|
|
119
|
+
name_by_id = {tc.get('id'): tc.get('name') for tc in tool_calls_to_pass if tc.get('id')}
|
|
120
|
+
|
|
121
|
+
def _source_for(tc_id, _name_by_id=name_by_id):
|
|
122
|
+
name = _name_by_id.get(tc_id)
|
|
123
|
+
tool = None
|
|
124
|
+
if name and self.controller:
|
|
125
|
+
# NOTE: get_action() returns the callable; get_action_details()
|
|
126
|
+
# returns the RegisteredAction carrying the .tool namespace.
|
|
127
|
+
ra = self.controller.get_action_details(name)
|
|
128
|
+
tool = getattr(ra, 'tool', None) if ra else None
|
|
129
|
+
return (name, tool)
|
|
130
|
+
|
|
131
|
+
source_for = _source_for
|
|
132
|
+
paired = _pair_results_to_calls(result, tool_calls_to_pass, source_for=source_for)
|
|
133
|
+
|
|
134
|
+
for i, tc in enumerate(tool_calls_to_pass):
|
|
135
|
+
tc_id = tc.get('id')
|
|
136
|
+
tc_name = tc.get('name', 'unknown')
|
|
137
|
+
|
|
138
|
+
if not tc_id:
|
|
139
|
+
self.logger.error(f"Tool call at index {i} missing ID, skipping")
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
# FIXED: Check validation errors FIRST - these tool calls were never executed
|
|
143
|
+
if tc_id in validation_errors:
|
|
144
|
+
error_msg = validation_errors[tc_id]
|
|
145
|
+
self.logger.warning(f"Tool call '{tc_name}' (id={tc_id}) failed validation: {error_msg[:100]}")
|
|
146
|
+
tool_responses.append((tc_id, f"Error: {error_msg}"))
|
|
147
|
+
|
|
148
|
+
if self.tool_call_tracker:
|
|
149
|
+
self.tool_call_tracker.mark_failed(tc_id, f"Validation failed: {error_msg[:100]}")
|
|
150
|
+
# This call was never executed (no result to pair)
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
# This tool call passed validation - pair its result. Try the
|
|
154
|
+
# position-keyed entry first (duplicate-id fallback), then the
|
|
155
|
+
# identity entry (the normal unique-id path).
|
|
156
|
+
entry = paired.get((tc_id, i))
|
|
157
|
+
if entry is None:
|
|
158
|
+
entry = paired.get(tc_id)
|
|
159
|
+
if entry is not None:
|
|
160
|
+
content, had_error = entry
|
|
161
|
+
tool_responses.append((tc_id, content))
|
|
162
|
+
if self.tool_call_tracker:
|
|
163
|
+
if had_error:
|
|
164
|
+
self.tool_call_tracker.mark_failed(tc_id, content)
|
|
165
|
+
else:
|
|
166
|
+
self.tool_call_tracker.mark_completed(tc_id, content[:200])
|
|
167
|
+
else:
|
|
168
|
+
error_msg = (
|
|
169
|
+
f"Action '{tc_name}' was NOT executed this step "
|
|
170
|
+
f"(deferred, truncated, or a prior action stopped execution). "
|
|
171
|
+
f"Retry it next step if still needed."
|
|
172
|
+
)
|
|
173
|
+
tool_responses.append((tc_id, f"Error: {error_msg}"))
|
|
174
|
+
if self.tool_call_tracker:
|
|
175
|
+
self.tool_call_tracker.mark_failed(tc_id, "Not executed this step")
|
|
176
|
+
|
|
177
|
+
# Step 2: Extract AI content from model_output (reuse existing pattern from line 2057)
|
|
178
|
+
try:
|
|
179
|
+
if model_output and hasattr(model_output, 'current_state'):
|
|
180
|
+
_mem = getattr(model_output.current_state, 'memory', '') or ''
|
|
181
|
+
if _mem.startswith("Synthesis pending"):
|
|
182
|
+
# P2-16: this is the pre-synthesis PLACEHOLDER brain (a native step
|
|
183
|
+
# with tool calls but no parseable brain JSON). The synthesis that
|
|
184
|
+
# replaces it runs AFTER this atomic add, so serializing it here
|
|
185
|
+
# persisted "Synthesis pending - will be generated..." verbatim into
|
|
186
|
+
# provider-visible history. Store neutral content instead — the
|
|
187
|
+
# tool_calls carry the turn, and the real (synthesized) brain is
|
|
188
|
+
# recorded to memory downstream by _process_action_results.
|
|
189
|
+
ai_content = "Processing actions"
|
|
190
|
+
else:
|
|
191
|
+
brain_dict = model_output.current_state.model_dump(exclude_unset=True)
|
|
192
|
+
ai_content = json.dumps(brain_dict, separators=(',', ':')) # Compact JSON
|
|
193
|
+
else:
|
|
194
|
+
ai_content = "Processing actions"
|
|
195
|
+
except Exception as e:
|
|
196
|
+
self.logger.warning(f"Failed to serialize brain state: {e}")
|
|
197
|
+
ai_content = "Brain state extraction failed"
|
|
198
|
+
|
|
199
|
+
# Step 3: Atomic addition - all or nothing
|
|
200
|
+
try:
|
|
201
|
+
self.message_manager.add_tool_call_pair_atomic(
|
|
202
|
+
ai_content=ai_content,
|
|
203
|
+
tool_calls=tool_calls_to_pass,
|
|
204
|
+
tool_responses=tool_responses
|
|
205
|
+
)
|
|
206
|
+
self.logger.info(f"[ATOMIC] ✅ Added AIMessage + {len(tool_responses)} ToolMessages atomically")
|
|
207
|
+
|
|
208
|
+
# Complete the step in tracker
|
|
209
|
+
if self.tool_call_tracker:
|
|
210
|
+
self.tool_call_tracker.complete_step()
|
|
211
|
+
|
|
212
|
+
except ValueError as e:
|
|
213
|
+
# FIX: Fail fast on mismatch - don't use degraded fallback
|
|
214
|
+
# The atomic method already rolled back, so we're in a clean state
|
|
215
|
+
# Adding separately would create inconsistent message state
|
|
216
|
+
self.logger.error(
|
|
217
|
+
f"[ATOMIC] Failed atomic addition (mismatch): {e}. "
|
|
218
|
+
f"Expected {len(tool_calls_to_pass)} tool_calls, got {len(tool_responses)} responses. "
|
|
219
|
+
f"Tool call IDs: {[tc.get('id') for tc in tool_calls_to_pass]}"
|
|
220
|
+
)
|
|
221
|
+
# Mark step as failed in tracker
|
|
222
|
+
if self.tool_call_tracker:
|
|
223
|
+
self.tool_call_tracker.complete_step()
|
|
224
|
+
# Set error result so next step can retry
|
|
225
|
+
self._last_result = [ActionResult(
|
|
226
|
+
error=f"Tool response mismatch: {e}. Actions executed but responses couldn't be recorded atomically.",
|
|
227
|
+
include_in_memory=True
|
|
228
|
+
)]
|
|
229
|
+
return False # Don't continue with corrupted state
|
|
230
|
+
except Exception as e:
|
|
231
|
+
# Other error during atomic addition
|
|
232
|
+
self.logger.error(f"[ATOMIC] Failed atomic addition: {e}")
|
|
233
|
+
# History already rolled back by atomic method
|
|
234
|
+
raise
|
|
235
|
+
|
|
236
|
+
elif tool_calls_to_pass:
|
|
237
|
+
self.logger.debug("Using non-atomic pattern (non-native tools)")
|
|
238
|
+
tool_call_id = self.message_manager.add_model_output(model_output, tool_calls=tool_calls_to_pass)
|
|
239
|
+
|
|
240
|
+
return True
|
|
241
|
+
|
|
242
|
+
async def _process_action_results(self, result, model_output, tool_calls_to_pass):
|
|
243
|
+
"""Phase 3b: record action results into context (large-result handling + atomic tool-message pairing). Returns the result list, or None to abort on corrupted state."""
|
|
244
|
+
if model_output and hasattr(model_output, 'action') and model_output.action:
|
|
245
|
+
# OPTIMIZATION: Log tool outputs (Task 1 - Nov 14, 2025)
|
|
246
|
+
self._log_tool_outputs(model_output.action, result, self.state.n_steps)
|
|
247
|
+
|
|
248
|
+
# CRITICAL: Handle large action results BEFORE adding to context
|
|
249
|
+
# This offloads content >10K to files, preventing context overflow
|
|
250
|
+
# Must happen BEFORE tool responses are added to message history
|
|
251
|
+
self._handle_large_action_results(result)
|
|
252
|
+
|
|
253
|
+
# Atomic message addition: AIMessage + all ToolMessages added together
|
|
254
|
+
if not await self._add_tool_messages(result, model_output, tool_calls_to_pass):
|
|
255
|
+
return None # Don't continue with corrupted state
|
|
256
|
+
|
|
257
|
+
# Build intelligent brain state from previous state + action results
|
|
258
|
+
if model_output and hasattr(model_output, 'action') and model_output.action and result:
|
|
259
|
+
# Start with previous brain state for continuity
|
|
260
|
+
previous_brain = None
|
|
261
|
+
if hasattr(self, '_last_model_output') and self._last_model_output and hasattr(self._last_model_output, 'current_state'):
|
|
262
|
+
previous_brain = self._last_model_output.current_state
|
|
263
|
+
|
|
264
|
+
# Build specific action summaries with actual results
|
|
265
|
+
action_summaries = []
|
|
266
|
+
has_errors = False
|
|
267
|
+
has_completion = False
|
|
268
|
+
|
|
269
|
+
for i, res in enumerate(result):
|
|
270
|
+
if i >= len(model_output.action):
|
|
271
|
+
break
|
|
272
|
+
|
|
273
|
+
# Safe extraction with validation (matching pattern from _log_response)
|
|
274
|
+
action_dump = model_output.action[i].model_dump(exclude_unset=True)
|
|
275
|
+
if not action_dump:
|
|
276
|
+
self.logger.warning(f"Action {i} has empty model_dump, skipping")
|
|
277
|
+
continue
|
|
278
|
+
|
|
279
|
+
action_keys = list(action_dump.keys())
|
|
280
|
+
if not action_keys:
|
|
281
|
+
self.logger.warning(f"Action {i} has no keys in model_dump, skipping")
|
|
282
|
+
continue
|
|
283
|
+
|
|
284
|
+
action_name = action_keys[0]
|
|
285
|
+
action_params = action_dump[action_name]
|
|
286
|
+
|
|
287
|
+
# Build specific description with params and results
|
|
288
|
+
param_str = ""
|
|
289
|
+
if isinstance(action_params, dict) and action_params:
|
|
290
|
+
# Show key params (not all)
|
|
291
|
+
key_params = []
|
|
292
|
+
for k, v in list(action_params.items())[:2]: # First 2 params only
|
|
293
|
+
if isinstance(v, str):
|
|
294
|
+
key_params.append(f"{k}={v[:30]}")
|
|
295
|
+
else:
|
|
296
|
+
key_params.append(f"{k}={v}")
|
|
297
|
+
param_str = f"({', '.join(key_params)})" if key_params else ""
|
|
298
|
+
|
|
299
|
+
if res.error:
|
|
300
|
+
action_summaries.append(f"{action_name}{param_str}→ERROR:{res.error[:50]}")
|
|
301
|
+
has_errors = True
|
|
302
|
+
elif res.is_done:
|
|
303
|
+
action_summaries.append(f"{action_name}{param_str}→DONE")
|
|
304
|
+
has_completion = True
|
|
305
|
+
elif res.extracted_content:
|
|
306
|
+
# Show actual extracted content
|
|
307
|
+
content_preview = res.extracted_content[:80].replace('\n', ' ')
|
|
308
|
+
action_summaries.append(f"{action_name}{param_str}→{content_preview}")
|
|
309
|
+
else:
|
|
310
|
+
action_summaries.append(f"{action_name}{param_str}→OK")
|
|
311
|
+
|
|
312
|
+
# Extract previous memory and progress for continuity
|
|
313
|
+
previous_memory = None
|
|
314
|
+
previous_progress = None
|
|
315
|
+
if previous_brain and hasattr(previous_brain, 'memory'):
|
|
316
|
+
previous_memory = previous_brain.memory
|
|
317
|
+
previous_progress = self._extract_progress_from_memory(previous_memory)
|
|
318
|
+
|
|
319
|
+
# Build memory that preserves previous context
|
|
320
|
+
new_memory = self._build_memory_from_actions(
|
|
321
|
+
step_number=self.state.n_steps,
|
|
322
|
+
action_summaries=action_summaries,
|
|
323
|
+
previous_memory=previous_memory,
|
|
324
|
+
previous_progress=previous_progress
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
# Build evaluation
|
|
328
|
+
if has_completion:
|
|
329
|
+
evaluation = f"Success - Task marked complete at step {self.state.n_steps}"
|
|
330
|
+
elif has_errors:
|
|
331
|
+
evaluation = f"Partial - {sum(1 for r in result if not r.error)}/{len(result)} actions succeeded"
|
|
332
|
+
else:
|
|
333
|
+
evaluation = f"Success - All {len(result)} actions completed"
|
|
334
|
+
|
|
335
|
+
# Keep previous goal if it existed, otherwise create continuation goal
|
|
336
|
+
if previous_brain and hasattr(previous_brain, 'next_goal') and previous_brain.next_goal and 'Continue' not in previous_brain.next_goal:
|
|
337
|
+
next_goal = previous_brain.next_goal # Preserve specific goal
|
|
338
|
+
else:
|
|
339
|
+
# Create new goal based on what we just did
|
|
340
|
+
next_goal = f"Continue based on results from step {self.state.n_steps}"
|
|
341
|
+
|
|
342
|
+
# Build reasoning from action sequence
|
|
343
|
+
reasoning = f"Executed: {' → '.join([a.split('→')[0] for a in action_summaries[:3]])}"
|
|
344
|
+
|
|
345
|
+
# ✅ FIX #3: Enhanced brain state synthesis
|
|
346
|
+
# Synthesis happens AFTER actions execute, so it can use actual results
|
|
347
|
+
# Also detect placeholder brain state and replace it
|
|
348
|
+
needs_synthesis = (
|
|
349
|
+
not model_output.current_state
|
|
350
|
+
or not model_output.current_state.memory
|
|
351
|
+
or "Synthesis pending" in model_output.current_state.memory
|
|
352
|
+
or model_output.current_state.evaluation_previous_goal == "Pending"
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
# FIX #3: Detect hallucinated brain state
|
|
356
|
+
# If LLM says it "created/wrote/generated" but actual actions were only "read", force synthesis
|
|
357
|
+
if not needs_synthesis and model_output.current_state and model_output.current_state.memory:
|
|
358
|
+
llm_memory = model_output.current_state.memory.lower()
|
|
359
|
+
actual_action_names = [a.split('→')[0].split('(')[0].lower() for a in action_summaries]
|
|
360
|
+
|
|
361
|
+
# Check for hallucination: LLM claims write actions but only read actions occurred
|
|
362
|
+
write_claims = any(word in llm_memory for word in ['created', 'wrote', 'generated', 'saved', 'writing'])
|
|
363
|
+
actual_reads_only = all('read' in a for a in actual_action_names)
|
|
364
|
+
|
|
365
|
+
if write_claims and actual_reads_only and len(actual_action_names) > 0:
|
|
366
|
+
self.logger.warning(
|
|
367
|
+
f"🚨 Detected hallucinated brain state: LLM claims write actions "
|
|
368
|
+
f"but actual actions were [{', '.join(actual_action_names)}]. Forcing synthesis."
|
|
369
|
+
)
|
|
370
|
+
needs_synthesis = True
|
|
371
|
+
|
|
372
|
+
if needs_synthesis:
|
|
373
|
+
# LLM failed to provide brain state OR used placeholder OR hallucinated
|
|
374
|
+
model_output.current_state = AgentBrain(
|
|
375
|
+
page_summary="",
|
|
376
|
+
memory=new_memory[:500],
|
|
377
|
+
evaluation_previous_goal=evaluation,
|
|
378
|
+
next_goal=next_goal,
|
|
379
|
+
reasoning=reasoning[:200]
|
|
380
|
+
)
|
|
381
|
+
self.logger.info(f"✅ Synthesized brain state from action results: {new_memory[:120]}")
|
|
382
|
+
# CO-F8: write the synthesized brain back to _last_brain_state so the
|
|
383
|
+
# next memory-prefetch recall query is enriched instead of degrading
|
|
384
|
+
# to the static task string (no-text-content / tool-calls-only steps).
|
|
385
|
+
self._last_brain_state = model_output.current_state
|
|
386
|
+
# ✅ FIX: Removed enhancement logic - don't corrupt LLM-provided brain state
|
|
387
|
+
|
|
388
|
+
return result
|
|
389
|
+
|