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,469 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import traceback
|
|
5
|
+
from collections import deque
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Dict, List, Optional, Type, Union
|
|
9
|
+
|
|
10
|
+
from core.exceptions import RateLimitError
|
|
11
|
+
from pydantic import BaseModel, ConfigDict, Field, ValidationError, create_model, model_validator
|
|
12
|
+
|
|
13
|
+
from tools.browser.views import BrowserState, BrowserStateHistory, TabInfo
|
|
14
|
+
from tools.controller.registry.views import ActionModel
|
|
15
|
+
from tools.controller.types import ActionResult # Canonical location for ActionResult
|
|
16
|
+
from tools.dom.history_tree_processor.service import (
|
|
17
|
+
DOMElementNode,
|
|
18
|
+
DOMHistoryElement,
|
|
19
|
+
HistoryTreeProcessor,
|
|
20
|
+
)
|
|
21
|
+
from tools.dom.views import SelectorMap
|
|
22
|
+
from agents.task.path import pm
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class AgentStepInfo:
|
|
27
|
+
step_number: int
|
|
28
|
+
max_steps: int
|
|
29
|
+
|
|
30
|
+
__slots__ = ('step_number', 'max_steps')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AgentBrain(BaseModel):
|
|
34
|
+
"""Current state of the agent with enhanced tracking"""
|
|
35
|
+
|
|
36
|
+
page_summary: str = "" # Optional with default - not requested in native tools JSON format
|
|
37
|
+
evaluation_previous_goal: str
|
|
38
|
+
memory: str
|
|
39
|
+
next_goal: str
|
|
40
|
+
reasoning: Optional[str] = ""
|
|
41
|
+
thinking: Optional[str] = None # OPTIMIZATION: For chain-of-thought models (Task 5 - Nov 14, 2025)
|
|
42
|
+
|
|
43
|
+
# Enhanced tracking fields for intelligent completion
|
|
44
|
+
acceptance_criteria: Optional[List[str]] = None # What must be done to complete the task
|
|
45
|
+
working_memory: Optional[Dict[str, Any]] = None # Key-value pairs to track
|
|
46
|
+
confidence_level: Optional[float] = None # 0-1 confidence in current approach
|
|
47
|
+
blockers: Optional[List[str]] = None # Current blockers or issues
|
|
48
|
+
# Minimal hierarchical reasoning (keep lightweight)
|
|
49
|
+
phase: Optional[str] = None # discovery | collection | processing | documentation
|
|
50
|
+
macro_goal: Optional[str] = None # short description of overarching goal
|
|
51
|
+
subgoal: Optional[str] = None # immediate subgoal derived from macro
|
|
52
|
+
immediate_step: Optional[str] = None # the next concrete step
|
|
53
|
+
|
|
54
|
+
model_config = ConfigDict(slots=True)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class AgentOutput(BaseModel):
|
|
58
|
+
"""Output model for agent"""
|
|
59
|
+
|
|
60
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, extra='forbid', slots=True)
|
|
61
|
+
|
|
62
|
+
current_state: AgentBrain
|
|
63
|
+
# CRITICAL: Accept dicts OR ActionModel instances (including MCP subclasses)
|
|
64
|
+
# Don't force validation to ActionModel - it breaks MCP tool dicts
|
|
65
|
+
action: list[Union[Dict[str, Any], ActionModel]]
|
|
66
|
+
|
|
67
|
+
@model_validator(mode='before')
|
|
68
|
+
@classmethod
|
|
69
|
+
def handle_thinking_wrapper(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
|
70
|
+
"""Handle LLM responses that wrap content in '_thinking' field.
|
|
71
|
+
|
|
72
|
+
Some LLMs return: {"_thinking": "{...}", "action": []}
|
|
73
|
+
We need to extract the actual content from _thinking and merge it with the outer structure.
|
|
74
|
+
|
|
75
|
+
This fixes the native tool calling validation failure where the LLM puts current_state
|
|
76
|
+
inside a _thinking string instead of at the top level.
|
|
77
|
+
|
|
78
|
+
Also filters out None values from action list to prevent validation failures.
|
|
79
|
+
"""
|
|
80
|
+
import logging
|
|
81
|
+
logger = logging.getLogger(__name__)
|
|
82
|
+
|
|
83
|
+
if isinstance(values, dict):
|
|
84
|
+
# Handle _thinking wrapper
|
|
85
|
+
if '_thinking' in values:
|
|
86
|
+
import json
|
|
87
|
+
try:
|
|
88
|
+
# Parse the JSON string inside _thinking
|
|
89
|
+
thinking_content = values['_thinking']
|
|
90
|
+
if isinstance(thinking_content, str):
|
|
91
|
+
parsed = json.loads(thinking_content)
|
|
92
|
+
# Merge parsed content into values
|
|
93
|
+
# Keep action from outer level if present, use inner if not
|
|
94
|
+
if 'action' not in values and 'action' in parsed:
|
|
95
|
+
values['action'] = parsed['action']
|
|
96
|
+
# Always prefer inner current_state if present
|
|
97
|
+
if 'current_state' in parsed:
|
|
98
|
+
values['current_state'] = parsed['current_state']
|
|
99
|
+
# Remove the _thinking wrapper
|
|
100
|
+
del values['_thinking']
|
|
101
|
+
logger.debug("Unwrapped _thinking field successfully")
|
|
102
|
+
except (json.JSONDecodeError, TypeError) as e:
|
|
103
|
+
logger.warning(f"Failed to parse _thinking field: {e}")
|
|
104
|
+
# Keep original values if parsing fails
|
|
105
|
+
|
|
106
|
+
# FIXED: Filter out None values from action list
|
|
107
|
+
# This prevents validation failures when tool_calls_to_actions skips invalid actions
|
|
108
|
+
if 'action' in values and isinstance(values['action'], list):
|
|
109
|
+
original_len = len(values['action'])
|
|
110
|
+
values['action'] = [a for a in values['action'] if a is not None]
|
|
111
|
+
filtered_count = original_len - len(values['action'])
|
|
112
|
+
if filtered_count > 0:
|
|
113
|
+
logger.warning(
|
|
114
|
+
f"⚠️ Filtered out {filtered_count} None values from action list "
|
|
115
|
+
f"(likely from failed tool call validations)"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
return values
|
|
119
|
+
|
|
120
|
+
@staticmethod
|
|
121
|
+
def type_with_custom_actions(custom_actions: Type[ActionModel]) -> Type['AgentOutput']:
|
|
122
|
+
"""Extend actions with custom actions"""
|
|
123
|
+
model_ = create_model(
|
|
124
|
+
'AgentOutput',
|
|
125
|
+
__base__=AgentOutput,
|
|
126
|
+
action=(list[custom_actions], Field(...)), # Properly annotated field with no default
|
|
127
|
+
__module__=AgentOutput.__module__,
|
|
128
|
+
)
|
|
129
|
+
model_.__doc__ = "AgentOutput model"
|
|
130
|
+
|
|
131
|
+
# FIXED: Explicitly set model_config to ensure extra='forbid' is inherited
|
|
132
|
+
# This prevents the "additionalProperties is required to be supplied and to be false" error
|
|
133
|
+
model_.model_config = ConfigDict(arbitrary_types_allowed=True, extra='forbid', slots=True)
|
|
134
|
+
|
|
135
|
+
# CRITICAL FIX: Ensure the dynamically created model inherits our schema method
|
|
136
|
+
model_.get_openai_schema = classmethod(AgentOutput.get_openai_schema.__func__)
|
|
137
|
+
|
|
138
|
+
return model_
|
|
139
|
+
|
|
140
|
+
@classmethod
|
|
141
|
+
def get_openai_schema(cls) -> Dict[str, Any]:
|
|
142
|
+
"""Get OpenAI-compatible schema with explicit additionalProperties control."""
|
|
143
|
+
try:
|
|
144
|
+
# Use centralized schema fix utility
|
|
145
|
+
from agents.task.utils import fix_openai_schema
|
|
146
|
+
schema = cls.model_json_schema()
|
|
147
|
+
return fix_openai_schema(schema)
|
|
148
|
+
|
|
149
|
+
except Exception as e:
|
|
150
|
+
# ULTRA-SAFE FALLBACK: If all else fails, return a minimal working schema
|
|
151
|
+
return {
|
|
152
|
+
"type": "object",
|
|
153
|
+
"properties": {
|
|
154
|
+
"current_state": {
|
|
155
|
+
"type": "object",
|
|
156
|
+
"properties": {
|
|
157
|
+
"page_summary": {"type": "string"},
|
|
158
|
+
"evaluation_previous_goal": {"type": "string"},
|
|
159
|
+
"memory": {"type": "string"},
|
|
160
|
+
"next_goal": {"type": "string"},
|
|
161
|
+
"reasoning": {"type": "string"}
|
|
162
|
+
},
|
|
163
|
+
"required": ["page_summary", "evaluation_previous_goal", "memory", "next_goal"],
|
|
164
|
+
"additionalProperties": False
|
|
165
|
+
},
|
|
166
|
+
"action": {
|
|
167
|
+
"type": "array",
|
|
168
|
+
"items": {
|
|
169
|
+
"type": "object",
|
|
170
|
+
"additionalProperties": False
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"required": ["current_state", "action"],
|
|
175
|
+
"additionalProperties": False
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class AgentHistory(BaseModel):
|
|
180
|
+
"""History item for agent actions"""
|
|
181
|
+
|
|
182
|
+
model_output: AgentOutput | None
|
|
183
|
+
result: list[ActionResult]
|
|
184
|
+
state: BrowserStateHistory
|
|
185
|
+
|
|
186
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, protected_namespaces=(), slots=True)
|
|
187
|
+
|
|
188
|
+
@staticmethod
|
|
189
|
+
def get_interacted_element(model_output: AgentOutput, selector_map: SelectorMap) -> list[DOMHistoryElement | None]:
|
|
190
|
+
"""Get the elements interacted with from model output.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
model_output: The output from the model containing actions
|
|
194
|
+
selector_map: Mapping of element indices to DOM elements
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
List of DOM history elements that were interacted with, aligned with actions
|
|
198
|
+
"""
|
|
199
|
+
elements = []
|
|
200
|
+
for action in model_output.action:
|
|
201
|
+
index = action.get_index()
|
|
202
|
+
if index is not None and index in selector_map:
|
|
203
|
+
el: DOMElementNode = selector_map[index]
|
|
204
|
+
elements.append(HistoryTreeProcessor.convert_dom_element_to_history_element(el))
|
|
205
|
+
else:
|
|
206
|
+
elements.append(None)
|
|
207
|
+
return elements
|
|
208
|
+
|
|
209
|
+
def model_dump(self, **kwargs) -> Dict[str, Any]:
|
|
210
|
+
"""Custom serialization handling circular references"""
|
|
211
|
+
|
|
212
|
+
# Handle action serialization
|
|
213
|
+
model_output_dump = None
|
|
214
|
+
if self.model_output:
|
|
215
|
+
action_dump = [action.model_dump(exclude_none=True) for action in self.model_output.action]
|
|
216
|
+
model_output_dump = {
|
|
217
|
+
'current_state': self.model_output.current_state.model_dump(),
|
|
218
|
+
'action': action_dump, # This preserves the actual action data
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
'model_output': model_output_dump,
|
|
223
|
+
'result': [r.model_dump(exclude_none=True) for r in self.result],
|
|
224
|
+
'state': self.state.to_dict(),
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class AgentHistoryList(BaseModel):
|
|
229
|
+
"""List of agent history items"""
|
|
230
|
+
|
|
231
|
+
history: list[AgentHistory]
|
|
232
|
+
|
|
233
|
+
model_config = ConfigDict(slots=True)
|
|
234
|
+
|
|
235
|
+
def __str__(self) -> str:
|
|
236
|
+
"""Representation of the AgentHistoryList object"""
|
|
237
|
+
return f'AgentHistoryList(all_results={self.action_results()}, all_model_outputs={self.model_actions()})'
|
|
238
|
+
|
|
239
|
+
def __repr__(self) -> str:
|
|
240
|
+
"""Representation of the AgentHistoryList object"""
|
|
241
|
+
return self.__str__()
|
|
242
|
+
|
|
243
|
+
def save_to_file(self, filepath: str | Path, session_id: Optional[str] = None) -> None:
|
|
244
|
+
"""Save history to JSON file with proper serialization.
|
|
245
|
+
|
|
246
|
+
This method ensures proper path handling for session-specific files.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
filepath: Path to save history file
|
|
250
|
+
session_id: Optional session ID for path normalization
|
|
251
|
+
"""
|
|
252
|
+
try:
|
|
253
|
+
# If session_id explicitly provided, use it for normalization
|
|
254
|
+
if session_id:
|
|
255
|
+
clean_id = pm().clean_session_id(session_id)
|
|
256
|
+
filepath = pm().normalize_path(str(filepath), clean_id)
|
|
257
|
+
else:
|
|
258
|
+
# Try to extract session ID from path for backward compatibility
|
|
259
|
+
import re
|
|
260
|
+
filepath_str = str(filepath)
|
|
261
|
+
uuid_pattern = r'([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})'
|
|
262
|
+
uuid_match = re.search(uuid_pattern, filepath_str)
|
|
263
|
+
|
|
264
|
+
if uuid_match:
|
|
265
|
+
# Path contains a session ID, normalize it
|
|
266
|
+
session_id = uuid_match.group(1)
|
|
267
|
+
clean_id = pm().clean_session_id(session_id)
|
|
268
|
+
filepath = pm().normalize_path(filepath_str, clean_id)
|
|
269
|
+
|
|
270
|
+
# Create parent directory if needed
|
|
271
|
+
Path(filepath).parent.mkdir(parents=True, exist_ok=True)
|
|
272
|
+
|
|
273
|
+
# Serialize and save
|
|
274
|
+
data = self.model_dump()
|
|
275
|
+
with open(filepath, 'w', encoding='utf-8') as f:
|
|
276
|
+
json.dump(data, f, indent=2)
|
|
277
|
+
except Exception as e:
|
|
278
|
+
raise e
|
|
279
|
+
|
|
280
|
+
def model_dump(self, **kwargs) -> Dict[str, Any]:
|
|
281
|
+
"""Custom serialization that properly uses AgentHistory's model_dump"""
|
|
282
|
+
return {
|
|
283
|
+
'history': [h.model_dump(**kwargs) for h in self.history],
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@classmethod
|
|
287
|
+
def load_from_file(cls, filepath: str | Path, output_model: Type[AgentOutput], session_id: Optional[str] = None) -> 'AgentHistoryList':
|
|
288
|
+
"""Load history from JSON file.
|
|
289
|
+
|
|
290
|
+
This method handles normalizing paths and validating session data.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
filepath: Path to the history file
|
|
294
|
+
output_model: Model type for agent output validation
|
|
295
|
+
session_id: Optional session ID for path normalization
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
Loaded AgentHistoryList instance
|
|
299
|
+
"""
|
|
300
|
+
# Normalize path with explicit session_id if provided
|
|
301
|
+
try:
|
|
302
|
+
if session_id:
|
|
303
|
+
clean_id = pm().clean_session_id(session_id)
|
|
304
|
+
filepath = pm().normalize_path(str(filepath), clean_id)
|
|
305
|
+
else:
|
|
306
|
+
# Try to extract session ID from path for backward compatibility
|
|
307
|
+
import re
|
|
308
|
+
|
|
309
|
+
filepath_str = str(filepath)
|
|
310
|
+
uuid_pattern = r'([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})'
|
|
311
|
+
uuid_match = re.search(uuid_pattern, filepath_str)
|
|
312
|
+
|
|
313
|
+
if uuid_match:
|
|
314
|
+
# Path contains a session ID, normalize it
|
|
315
|
+
session_id = uuid_match.group(1)
|
|
316
|
+
clean_id = pm().clean_session_id(session_id)
|
|
317
|
+
filepath = pm().normalize_path(filepath_str, clean_id)
|
|
318
|
+
except ImportError:
|
|
319
|
+
# Continue with original path if path module not available
|
|
320
|
+
pass
|
|
321
|
+
|
|
322
|
+
with open(filepath, 'r', encoding='utf-8') as f:
|
|
323
|
+
data = json.load(f)
|
|
324
|
+
|
|
325
|
+
# Validate and enrich data
|
|
326
|
+
if 'history' not in data:
|
|
327
|
+
raise ValueError(f"Invalid history file format: {filepath}")
|
|
328
|
+
|
|
329
|
+
# Process each history entry
|
|
330
|
+
for h in data['history']:
|
|
331
|
+
# Handle model output if present
|
|
332
|
+
if h['model_output']:
|
|
333
|
+
if isinstance(h['model_output'], dict):
|
|
334
|
+
try:
|
|
335
|
+
h['model_output'] = output_model.model_validate(h['model_output'])
|
|
336
|
+
except Exception:
|
|
337
|
+
# If validation fails, set to None rather than breaking
|
|
338
|
+
h['model_output'] = None
|
|
339
|
+
else:
|
|
340
|
+
h['model_output'] = None
|
|
341
|
+
|
|
342
|
+
# Ensure state has interacted_element field
|
|
343
|
+
if 'state' in h and 'interacted_element' not in h['state']:
|
|
344
|
+
h['state']['interacted_element'] = None
|
|
345
|
+
|
|
346
|
+
history = cls.model_validate(data)
|
|
347
|
+
return history
|
|
348
|
+
|
|
349
|
+
def last_action(self) -> None | dict:
|
|
350
|
+
"""Last action in history"""
|
|
351
|
+
if self.history and self.history[-1].model_output and self.history[-1].model_output.action:
|
|
352
|
+
actions = self.history[-1].model_output.action
|
|
353
|
+
if actions and len(actions) > 0:
|
|
354
|
+
return actions[-1].model_dump(exclude_none=True)
|
|
355
|
+
return None
|
|
356
|
+
|
|
357
|
+
def errors(self) -> list[str]:
|
|
358
|
+
"""Get all errors from history"""
|
|
359
|
+
errors = []
|
|
360
|
+
for h in self.history:
|
|
361
|
+
errors.extend([r.error for r in h.result if r.error])
|
|
362
|
+
return errors
|
|
363
|
+
|
|
364
|
+
def final_result(self) -> None | str:
|
|
365
|
+
"""Final result from history"""
|
|
366
|
+
if self.history and self.history[-1].result[-1].extracted_content:
|
|
367
|
+
return self.history[-1].result[-1].extracted_content
|
|
368
|
+
return None
|
|
369
|
+
|
|
370
|
+
def is_done(self) -> bool:
|
|
371
|
+
"""Check if the agent is done"""
|
|
372
|
+
if self.history and len(self.history[-1].result) > 0 and self.history[-1].result[-1].is_done:
|
|
373
|
+
return self.history[-1].result[-1].is_done
|
|
374
|
+
return False
|
|
375
|
+
|
|
376
|
+
def has_errors(self) -> bool:
|
|
377
|
+
"""Check if the agent has any errors"""
|
|
378
|
+
return len(self.errors()) > 0
|
|
379
|
+
|
|
380
|
+
def urls(self) -> list[str]:
|
|
381
|
+
"""Get all unique URLs from history"""
|
|
382
|
+
return [h.state.url for h in self.history if h.state.url]
|
|
383
|
+
|
|
384
|
+
def screenshots(self) -> list[str]:
|
|
385
|
+
"""Get all screenshots from history"""
|
|
386
|
+
return [h.state.screenshot for h in self.history if h.state.screenshot]
|
|
387
|
+
|
|
388
|
+
def action_names(self) -> list[str]:
|
|
389
|
+
"""Get all action names from history"""
|
|
390
|
+
action_names = []
|
|
391
|
+
for action in self.model_actions():
|
|
392
|
+
actions = list(action.keys())
|
|
393
|
+
if actions:
|
|
394
|
+
action_names.append(actions[0])
|
|
395
|
+
return action_names
|
|
396
|
+
|
|
397
|
+
def model_thoughts(self) -> list[AgentBrain]:
|
|
398
|
+
"""Get all thoughts from history"""
|
|
399
|
+
return [h.model_output.current_state for h in self.history if h.model_output]
|
|
400
|
+
|
|
401
|
+
def model_outputs(self) -> list[AgentOutput]:
|
|
402
|
+
"""Get all model outputs from history"""
|
|
403
|
+
return [h.model_output for h in self.history if h.model_output]
|
|
404
|
+
|
|
405
|
+
def model_actions(self) -> list[dict]:
|
|
406
|
+
"""Get all actions from history"""
|
|
407
|
+
outputs = []
|
|
408
|
+
|
|
409
|
+
for h in self.history:
|
|
410
|
+
if h.model_output and h.model_output.action:
|
|
411
|
+
# FIX: Safe iteration with proper length handling
|
|
412
|
+
actions = h.model_output.action
|
|
413
|
+
interacted_elements = h.state.interacted_element if h.state.interacted_element else []
|
|
414
|
+
|
|
415
|
+
for i, action in enumerate(actions):
|
|
416
|
+
if action is None:
|
|
417
|
+
continue
|
|
418
|
+
|
|
419
|
+
output = action.model_dump(exclude_none=True)
|
|
420
|
+
# Safely get interacted element if available
|
|
421
|
+
if i < len(interacted_elements):
|
|
422
|
+
output['interacted_element'] = interacted_elements[i]
|
|
423
|
+
else:
|
|
424
|
+
output['interacted_element'] = None
|
|
425
|
+
outputs.append(output)
|
|
426
|
+
return outputs
|
|
427
|
+
|
|
428
|
+
def action_results(self) -> list[ActionResult]:
|
|
429
|
+
"""Get all results from history"""
|
|
430
|
+
results = []
|
|
431
|
+
for h in self.history:
|
|
432
|
+
results.extend([r for r in h.result if r])
|
|
433
|
+
return results
|
|
434
|
+
|
|
435
|
+
def extracted_content(self) -> list[str]:
|
|
436
|
+
"""Get all extracted content from history"""
|
|
437
|
+
content = []
|
|
438
|
+
for h in self.history:
|
|
439
|
+
content.extend([r.extracted_content for r in h.result if r.extracted_content])
|
|
440
|
+
return content
|
|
441
|
+
|
|
442
|
+
def model_actions_filtered(self, include: list[str] = []) -> list[dict]:
|
|
443
|
+
"""Get all model actions from history as JSON"""
|
|
444
|
+
outputs = self.model_actions()
|
|
445
|
+
result = []
|
|
446
|
+
for o in outputs:
|
|
447
|
+
for i in include:
|
|
448
|
+
if i == list(o.keys())[0]:
|
|
449
|
+
result.append(o)
|
|
450
|
+
return result
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
class AgentError:
|
|
454
|
+
"""Container for agent error handling"""
|
|
455
|
+
|
|
456
|
+
VALIDATION_ERROR = 'Invalid model output format. Please follow the correct schema.'
|
|
457
|
+
RATE_LIMIT_ERROR = 'Rate limit reached. Waiting before retry.'
|
|
458
|
+
NO_VALID_ACTION = 'No valid action found'
|
|
459
|
+
|
|
460
|
+
@staticmethod
|
|
461
|
+
def format_error(error: Exception, include_trace: bool = False) -> str:
|
|
462
|
+
"""Format error message based on error type and optionally include trace"""
|
|
463
|
+
if isinstance(error, ValidationError):
|
|
464
|
+
return f'{AgentError.VALIDATION_ERROR}\nDetails: {str(error)}'
|
|
465
|
+
if isinstance(error, RateLimitError):
|
|
466
|
+
return AgentError.RATE_LIMIT_ERROR
|
|
467
|
+
if include_trace:
|
|
468
|
+
return f'{str(error)}\nStacktrace:\n{traceback.format_exc()}'
|
|
469
|
+
return f'{str(error)}'
|