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,532 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import sys
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from agents.task.agent.views import ActionResult, AgentBrain, AgentOutput, AgentStepInfo
|
|
8
|
+
from modules.llm.messages import (
|
|
9
|
+
AIMessage,
|
|
10
|
+
BaseMessage,
|
|
11
|
+
HumanMessage,
|
|
12
|
+
SystemMessage,
|
|
13
|
+
ToolMessage,
|
|
14
|
+
)
|
|
15
|
+
from modules.llm.adapters import BaseChatModel
|
|
16
|
+
|
|
17
|
+
# LLM module availability flag + token counters (mirrors service.py module-level setup)
|
|
18
|
+
try:
|
|
19
|
+
from modules.llm.model_registry import get_model_config
|
|
20
|
+
from modules.llm import count_tokens, count_messages_tokens
|
|
21
|
+
LLM_MODULE_AVAILABLE = True
|
|
22
|
+
except ImportError:
|
|
23
|
+
LLM_MODULE_AVAILABLE = False
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TokenCounterMixin:
|
|
29
|
+
# Empty slots so the composed MessageManager keeps its own __slots__ (no __dict__).
|
|
30
|
+
__slots__ = ()
|
|
31
|
+
|
|
32
|
+
def _calculate_token_limits(self, llm: BaseChatModel,
|
|
33
|
+
max_input_override: Optional[int]) -> tuple:
|
|
34
|
+
"""Calculate token limits from model config (SINGLE SOURCE OF TRUTH).
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
llm: Language model instance
|
|
38
|
+
max_input_override: Optional explicit limit (None = auto-calculate)
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
(max_input_tokens, safe_input_tokens, completion_reserve)
|
|
42
|
+
"""
|
|
43
|
+
from modules.llm.model_registry import get_model_config
|
|
44
|
+
from agents.task.robust_parse_config import RobustParseConfig
|
|
45
|
+
|
|
46
|
+
# Env override (operational knob): cap the effective input budget regardless of
|
|
47
|
+
# the model's native window. An explicit constructor override still wins.
|
|
48
|
+
if max_input_override is None:
|
|
49
|
+
import os
|
|
50
|
+
_env_cap = os.getenv("TASK_MAX_INPUT_TOKENS")
|
|
51
|
+
if _env_cap and _env_cap.strip().isdigit():
|
|
52
|
+
max_input_override = int(_env_cap)
|
|
53
|
+
self.logger.info(f"TASK_MAX_INPUT_TOKENS override: max_input={max_input_override}")
|
|
54
|
+
|
|
55
|
+
# Use override if provided
|
|
56
|
+
if max_input_override is not None:
|
|
57
|
+
max_input = max_input_override
|
|
58
|
+
safe_input = int(max_input * (1 - RobustParseConfig.SAFETY_MARGIN_PERCENT))
|
|
59
|
+
self.logger.info(f"Using explicit token limit: max={max_input}, safe={safe_input}")
|
|
60
|
+
return max_input, safe_input, 4096 # Default completion reserve
|
|
61
|
+
|
|
62
|
+
# Auto-calculate from model
|
|
63
|
+
model_name = self._model_name
|
|
64
|
+
model_config = get_model_config(model_name)
|
|
65
|
+
|
|
66
|
+
if model_config and model_config.context_window:
|
|
67
|
+
# 95% of context window minus completion reserve
|
|
68
|
+
context_95pct = int(model_config.context_window * 0.95)
|
|
69
|
+
completion_reserve = model_config.max_completion_tokens
|
|
70
|
+
max_input = max(1000, context_95pct - completion_reserve)
|
|
71
|
+
|
|
72
|
+
# Apply safety margin (default 5%)
|
|
73
|
+
safe_input = int(max_input * (1 - RobustParseConfig.SAFETY_MARGIN_PERCENT))
|
|
74
|
+
|
|
75
|
+
self.logger.info(
|
|
76
|
+
f"Calculated token limits for {model_name}: "
|
|
77
|
+
f"context={model_config.context_window}, "
|
|
78
|
+
f"max_input={max_input}, safe_input={safe_input}, "
|
|
79
|
+
f"completion_reserve={completion_reserve}"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return max_input, safe_input, completion_reserve
|
|
83
|
+
else:
|
|
84
|
+
# Fallback defaults
|
|
85
|
+
self.logger.warning(f"No model config found for {model_name}, using fallback limits")
|
|
86
|
+
max_input = 120000
|
|
87
|
+
safe_input = int(max_input * 0.95)
|
|
88
|
+
return max_input, safe_input, 4096
|
|
89
|
+
|
|
90
|
+
def _count_message_tokens(self, message: BaseMessage) -> int:
|
|
91
|
+
"""Count tokens for a single message using modules.llm.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
message: BaseMessage to count tokens for
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
Token count
|
|
98
|
+
"""
|
|
99
|
+
if not LLM_MODULE_AVAILABLE:
|
|
100
|
+
text = str(message.content if hasattr(message, 'content') else message)
|
|
101
|
+
return max(1, len(text) // 4) if text else 0
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
# Convert to dict format for modules.llm
|
|
105
|
+
message_dict = {
|
|
106
|
+
"role": message.type,
|
|
107
|
+
"content": message.content
|
|
108
|
+
}
|
|
109
|
+
# CX-H4: tool-call arguments are real prompt bytes — the downstream
|
|
110
|
+
# counter supports them; omitting them makes compaction fire late.
|
|
111
|
+
tool_calls = getattr(message, "tool_calls", None)
|
|
112
|
+
if tool_calls:
|
|
113
|
+
message_dict["tool_calls"] = tool_calls
|
|
114
|
+
return count_messages_tokens([message_dict], self.model_name)
|
|
115
|
+
except Exception as e:
|
|
116
|
+
self.logger.debug(f"Token counting failed: {e}, using fallback")
|
|
117
|
+
text = str(message.content if hasattr(message, 'content') else message)
|
|
118
|
+
fallback_len = len(text)
|
|
119
|
+
tool_calls = getattr(message, "tool_calls", None)
|
|
120
|
+
if tool_calls:
|
|
121
|
+
import json
|
|
122
|
+
fallback_len += len(json.dumps(tool_calls))
|
|
123
|
+
return max(1, fallback_len // 4) if fallback_len else 0
|
|
124
|
+
|
|
125
|
+
def _increment_token_count(self, delta: int) -> None:
|
|
126
|
+
"""Increment the total token count by delta.
|
|
127
|
+
|
|
128
|
+
This method provides efficient token counting without recalculation.
|
|
129
|
+
Token counts are now trusted from centralized modules.llm - no periodic recalibration needed.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
delta: The number of tokens to add (positive) or remove (negative)
|
|
133
|
+
"""
|
|
134
|
+
previous_count = self.history.total_tokens
|
|
135
|
+
self.history.total_tokens = max(0, self.history.total_tokens + delta)
|
|
136
|
+
|
|
137
|
+
if delta != 0:
|
|
138
|
+
self.logger.debug(
|
|
139
|
+
f"Token count incremented: {previous_count} → {self.history.total_tokens} (Δ{delta:+})"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Check if we need to trim after increment
|
|
143
|
+
if self.history.total_tokens > self.max_input_tokens:
|
|
144
|
+
self.logger.debug(
|
|
145
|
+
f"Token count {self.history.total_tokens} exceeds limit {self.max_input_tokens} "
|
|
146
|
+
f"(trimming disabled - using full context)"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def get_total_tokens(self) -> int:
|
|
150
|
+
"""Get total tokens including all foundation messages.
|
|
151
|
+
|
|
152
|
+
FIX #4: Single source of truth for total token count.
|
|
153
|
+
Includes system message, initial task, and conversation history.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Total token count across all message storage
|
|
157
|
+
"""
|
|
158
|
+
return (
|
|
159
|
+
self.history.total_tokens +
|
|
160
|
+
self._system_message_tokens +
|
|
161
|
+
self._initial_task_tokens +
|
|
162
|
+
getattr(self, '_skill_message_tokens', 0) +
|
|
163
|
+
getattr(self, '_self_context_tokens', 0) +
|
|
164
|
+
getattr(self, '_project_context_tokens', 0) +
|
|
165
|
+
getattr(self, '_runtime_identity_tokens', 0)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
def estimate_tokens(self, messages: List[BaseMessage]) -> int:
|
|
169
|
+
"""Estimate total tokens for a list of messages using modules.llm.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
messages: List of BaseMessage objects to count tokens for
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Total estimated token count for all messages
|
|
176
|
+
"""
|
|
177
|
+
if not LLM_MODULE_AVAILABLE:
|
|
178
|
+
# Fallback: estimate 4 chars per token
|
|
179
|
+
total_chars = sum(len(str(m.content)) for m in messages if hasattr(m, 'content'))
|
|
180
|
+
return max(1, total_chars // 4)
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
# Convert to message dicts for modules.llm
|
|
184
|
+
message_dicts = []
|
|
185
|
+
for msg in messages:
|
|
186
|
+
message_dict = {"role": msg.type, "content": msg.content}
|
|
187
|
+
# CX-H4: mirror _count_message_tokens — include tool-call args.
|
|
188
|
+
tool_calls = getattr(msg, "tool_calls", None)
|
|
189
|
+
if tool_calls:
|
|
190
|
+
message_dict["tool_calls"] = tool_calls
|
|
191
|
+
message_dicts.append(message_dict)
|
|
192
|
+
return count_messages_tokens(message_dicts, self.model_name)
|
|
193
|
+
except Exception as e:
|
|
194
|
+
self.logger.debug(f"Token counting failed: {e}, using fallback")
|
|
195
|
+
import json
|
|
196
|
+
total_chars = 0
|
|
197
|
+
for m in messages:
|
|
198
|
+
if hasattr(m, 'content'):
|
|
199
|
+
total_chars += len(str(m.content))
|
|
200
|
+
tool_calls = getattr(m, "tool_calls", None)
|
|
201
|
+
if tool_calls:
|
|
202
|
+
total_chars += len(json.dumps(tool_calls))
|
|
203
|
+
return max(1, total_chars // 4)
|
|
204
|
+
|
|
205
|
+
def _get_model_token_limits(self) -> tuple[int, int]:
|
|
206
|
+
"""Get token limits from model registry.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
Tuple of (context_window, max_completion_tokens)
|
|
210
|
+
"""
|
|
211
|
+
from modules.llm.model_registry import get_model_config
|
|
212
|
+
model_name = self.model_name
|
|
213
|
+
|
|
214
|
+
# Use centralized model registry
|
|
215
|
+
config = get_model_config(model_name)
|
|
216
|
+
if config:
|
|
217
|
+
context_window = config.context_window
|
|
218
|
+
completion_tokens = config.max_completion_tokens
|
|
219
|
+
else:
|
|
220
|
+
# Conservative fallback
|
|
221
|
+
context_window = 128000
|
|
222
|
+
completion_tokens = 16384
|
|
223
|
+
self.logger.info(f"Got limits for {model_name}: context={context_window}, completion={completion_tokens}")
|
|
224
|
+
return context_window, completion_tokens
|
|
225
|
+
|
|
226
|
+
def get_memory_usage_estimate(self) -> int:
|
|
227
|
+
"""Estimate memory usage of message history in bytes.
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
Estimated memory usage in bytes
|
|
231
|
+
"""
|
|
232
|
+
import sys
|
|
233
|
+
|
|
234
|
+
total_size = 0
|
|
235
|
+
for managed_msg in self.history.messages:
|
|
236
|
+
msg = managed_msg.message
|
|
237
|
+
|
|
238
|
+
# Estimate size of message content
|
|
239
|
+
if hasattr(msg, 'content') and msg.content:
|
|
240
|
+
total_size += sys.getsizeof(str(msg.content))
|
|
241
|
+
|
|
242
|
+
# Add size of metadata
|
|
243
|
+
if hasattr(managed_msg, 'metadata'):
|
|
244
|
+
total_size += sys.getsizeof(managed_msg.metadata)
|
|
245
|
+
|
|
246
|
+
# Add overhead for message object itself
|
|
247
|
+
total_size += sys.getsizeof(msg)
|
|
248
|
+
|
|
249
|
+
return total_size
|
|
250
|
+
|
|
251
|
+
def recalibrate_token_counts(self, force: bool = False) -> None:
|
|
252
|
+
"""Recalculate token counts using unified counting method.
|
|
253
|
+
|
|
254
|
+
This is now only called when explicitly requested or when model changes.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
force: If True, always recalibrate even if not necessary
|
|
258
|
+
"""
|
|
259
|
+
self.logger.info("Recalibrating token counts for all messages")
|
|
260
|
+
|
|
261
|
+
# Check if model limits have changed (e.g. a fallback to a smaller-context
|
|
262
|
+
# model). Recompute the input budget the SAME way _calculate_token_limits does
|
|
263
|
+
# — 95% of the window MINUS the completion reserve — instead of using the raw
|
|
264
|
+
# context window (which leaves zero room for the response). Update BOTH
|
|
265
|
+
# max_input_tokens AND safe_input_tokens so check_token_safety stays consistent.
|
|
266
|
+
context_window, completion_tokens = self._get_model_token_limits()
|
|
267
|
+
|
|
268
|
+
if context_window > 0:
|
|
269
|
+
from agents.task.robust_parse_config import RobustParseConfig
|
|
270
|
+
new_max_input = max(1000, int(context_window * 0.95) - completion_tokens)
|
|
271
|
+
if new_max_input < self.max_input_tokens:
|
|
272
|
+
old_limit = self.max_input_tokens
|
|
273
|
+
self.max_input_tokens = new_max_input
|
|
274
|
+
self.safe_input_tokens = int(new_max_input * (1 - RobustParseConfig.SAFETY_MARGIN_PERCENT))
|
|
275
|
+
self.logger.info(
|
|
276
|
+
f"Updated token limits after model change: max_input={new_max_input}, "
|
|
277
|
+
f"safe_input={self.safe_input_tokens} (was max_input={old_limit})"
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
# Store the original total
|
|
281
|
+
original_total = self.history.total_tokens
|
|
282
|
+
|
|
283
|
+
# Reset total
|
|
284
|
+
self.history.total_tokens = 0
|
|
285
|
+
|
|
286
|
+
# Recalculate for each message
|
|
287
|
+
for managed_msg in self.history.messages:
|
|
288
|
+
old_count = managed_msg.metadata.input_tokens
|
|
289
|
+
new_count = self._count_message_tokens(managed_msg.message)
|
|
290
|
+
managed_msg.metadata.input_tokens = new_count
|
|
291
|
+
self.history.total_tokens += new_count
|
|
292
|
+
|
|
293
|
+
# Log the change (only if significant to reduce spam)
|
|
294
|
+
diff = self.history.total_tokens - original_total
|
|
295
|
+
if abs(diff) > 100: # Only log if significant change
|
|
296
|
+
self.logger.info(f"Token count recalibration: {original_total} → {self.history.total_tokens} (Δ{diff:+})")
|
|
297
|
+
elif diff != 0:
|
|
298
|
+
self.logger.debug(f"Token count recalibration: {original_total} → {self.history.total_tokens} (Δ{diff:+})")
|
|
299
|
+
# else: no logging for unchanged recalibration
|
|
300
|
+
|
|
301
|
+
# Capture telemetry for token count changes if significant
|
|
302
|
+
if abs(diff) > 100: # Only capture if change is significant
|
|
303
|
+
try:
|
|
304
|
+
from agents.task import capture_llm_request
|
|
305
|
+
|
|
306
|
+
capture_llm_request(
|
|
307
|
+
component="MessageManager",
|
|
308
|
+
purpose="token_recalibration",
|
|
309
|
+
model_name=self.model_name,
|
|
310
|
+
duration_seconds=0.0, # No actual LLM call
|
|
311
|
+
success=True,
|
|
312
|
+
token_count=self.history.total_tokens,
|
|
313
|
+
session_id=self.session_id
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
self.logger.debug("Captured telemetry for token count recalibration")
|
|
317
|
+
|
|
318
|
+
except Exception as e:
|
|
319
|
+
self.logger.debug(f"Failed to capture telemetry for token recalibration: {e}")
|
|
320
|
+
|
|
321
|
+
# Log if token count exceeds max (trimming disabled)
|
|
322
|
+
if self.history.total_tokens > self.max_input_tokens:
|
|
323
|
+
self.logger.debug(f"Token count {self.history.total_tokens} exceeds limit {self.max_input_tokens} (trimming disabled)")
|
|
324
|
+
|
|
325
|
+
def get_token_count(self) -> int:
|
|
326
|
+
"""Get the current total token count including all separately stored messages.
|
|
327
|
+
|
|
328
|
+
NOTE: This does NOT include H-MEM or ephemeral messages.
|
|
329
|
+
Use get_actual_token_count() for the true count that will be sent to LLM.
|
|
330
|
+
"""
|
|
331
|
+
return (self.history.total_tokens + self._system_message_tokens
|
|
332
|
+
+ self._initial_task_tokens + getattr(self, '_skill_message_tokens', 0)
|
|
333
|
+
+ getattr(self, '_self_context_tokens', 0)
|
|
334
|
+
+ getattr(self, '_project_context_tokens', 0)
|
|
335
|
+
+ getattr(self, '_runtime_identity_tokens', 0))
|
|
336
|
+
|
|
337
|
+
def get_actual_token_count(self) -> int:
|
|
338
|
+
"""Get the ACTUAL token count including H-MEM and ephemeral messages.
|
|
339
|
+
|
|
340
|
+
This returns the true token count that will be sent to the LLM,
|
|
341
|
+
including dynamically injected hierarchical memory and ephemeral messages.
|
|
342
|
+
|
|
343
|
+
Use this for accurate context usage calculations before LLM calls.
|
|
344
|
+
|
|
345
|
+
NOTE: H-MEM tokens are cached per-step to avoid duplicate hierarchical searches.
|
|
346
|
+
Cache is invalidated when invalidate_hmem_cache() is called (typically at step start).
|
|
347
|
+
"""
|
|
348
|
+
# Start with base count (system + task + history)
|
|
349
|
+
base_count = self.get_token_count()
|
|
350
|
+
|
|
351
|
+
# Add ephemeral messages if any
|
|
352
|
+
ephemeral_tokens = 0
|
|
353
|
+
if hasattr(self, '_ephemeral_messages') and self._ephemeral_messages:
|
|
354
|
+
ephemeral_tokens = self.estimate_tokens(self._ephemeral_messages)
|
|
355
|
+
|
|
356
|
+
# Estimate H-MEM tokens if available
|
|
357
|
+
hmem_tokens = 0
|
|
358
|
+
if self.task_context_manager and self.session_id:
|
|
359
|
+
try:
|
|
360
|
+
context = self.task_context_manager.get_context_injection(self.session_id)
|
|
361
|
+
if context:
|
|
362
|
+
# Rough estimate: words * 1.3 tokens per word
|
|
363
|
+
hmem_tokens = int(len(context.split()) * 1.3)
|
|
364
|
+
except Exception:
|
|
365
|
+
pass
|
|
366
|
+
|
|
367
|
+
total = base_count + ephemeral_tokens + hmem_tokens
|
|
368
|
+
|
|
369
|
+
# Log if there's a significant difference from base count
|
|
370
|
+
if ephemeral_tokens + hmem_tokens > 1000:
|
|
371
|
+
self.logger.debug(
|
|
372
|
+
f"Token count: base={base_count}, ephemeral={ephemeral_tokens}, "
|
|
373
|
+
f"hmem={hmem_tokens}, total={total}"
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
return total
|
|
377
|
+
|
|
378
|
+
def get_estimated_context_usage(self) -> float:
|
|
379
|
+
"""Get estimated context usage as a ratio (0.0 to 1.0).
|
|
380
|
+
|
|
381
|
+
Uses actual token count including H-MEM and ephemeral messages.
|
|
382
|
+
"""
|
|
383
|
+
if self.max_input_tokens <= 0:
|
|
384
|
+
return 0.0
|
|
385
|
+
total_tokens = self.get_actual_token_count()
|
|
386
|
+
return min(1.0, total_tokens / self.max_input_tokens)
|
|
387
|
+
|
|
388
|
+
def check_token_safety(self,
|
|
389
|
+
additional_messages: Optional[List[BaseMessage]] = None,
|
|
390
|
+
raise_on_overflow: bool = False) -> Dict[str, Any]:
|
|
391
|
+
"""Check if current or projected token usage is safe.
|
|
392
|
+
|
|
393
|
+
Uses actual token count including H-MEM and ephemeral messages.
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
additional_messages: Optional messages to add (for projection)
|
|
397
|
+
raise_on_overflow: Raise LLMResponseError if unsafe
|
|
398
|
+
|
|
399
|
+
Returns:
|
|
400
|
+
{
|
|
401
|
+
'safe': bool,
|
|
402
|
+
'current_tokens': int,
|
|
403
|
+
'estimated_tokens': int,
|
|
404
|
+
'safe_limit': int,
|
|
405
|
+
'max_limit': int,
|
|
406
|
+
'would_overflow': bool,
|
|
407
|
+
'usage_percent': float
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
Raises:
|
|
411
|
+
LLMResponseError: If raise_on_overflow=True and unsafe
|
|
412
|
+
"""
|
|
413
|
+
from agents.task.robust_parse_config import RobustParseConfig
|
|
414
|
+
from core.exceptions import LLMResponseError
|
|
415
|
+
|
|
416
|
+
current = self.get_actual_token_count()
|
|
417
|
+
|
|
418
|
+
# Estimate with additional messages
|
|
419
|
+
if additional_messages:
|
|
420
|
+
additional_tokens = self.estimate_tokens(additional_messages)
|
|
421
|
+
estimated = current + additional_tokens
|
|
422
|
+
else:
|
|
423
|
+
estimated = current
|
|
424
|
+
|
|
425
|
+
# Check against safe limit
|
|
426
|
+
safe = estimated <= self.safe_input_tokens
|
|
427
|
+
|
|
428
|
+
# Check context overflow (hard limit)
|
|
429
|
+
would_overflow = RobustParseConfig.should_abort_context_overflow(
|
|
430
|
+
estimated,
|
|
431
|
+
self._model_name
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
if would_overflow:
|
|
435
|
+
safe = False
|
|
436
|
+
|
|
437
|
+
usage_percent = (estimated / self.max_input_tokens * 100) if self.max_input_tokens > 0 else 0
|
|
438
|
+
|
|
439
|
+
result = {
|
|
440
|
+
'safe': safe,
|
|
441
|
+
'current_tokens': current,
|
|
442
|
+
'estimated_tokens': estimated,
|
|
443
|
+
'safe_limit': self.safe_input_tokens,
|
|
444
|
+
'max_limit': self.max_input_tokens,
|
|
445
|
+
'would_overflow': would_overflow,
|
|
446
|
+
'usage_percent': usage_percent
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
# Optionally raise
|
|
450
|
+
if raise_on_overflow and not safe:
|
|
451
|
+
raise LLMResponseError(
|
|
452
|
+
f"Token overflow: {estimated} tokens exceeds safe limit {self.safe_input_tokens} "
|
|
453
|
+
f"({usage_percent:.1f}% of max {self.max_input_tokens})"
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
return result
|
|
457
|
+
|
|
458
|
+
def get_token_stats(self) -> Dict[str, Any]:
|
|
459
|
+
"""Get current token statistics.
|
|
460
|
+
|
|
461
|
+
Uses actual token count including H-MEM and ephemeral messages.
|
|
462
|
+
|
|
463
|
+
Returns:
|
|
464
|
+
{
|
|
465
|
+
'current': int,
|
|
466
|
+
'base': int (without H-MEM/ephemeral),
|
|
467
|
+
'max': int,
|
|
468
|
+
'safe': int,
|
|
469
|
+
'remaining': int,
|
|
470
|
+
'usage_percent': float
|
|
471
|
+
}
|
|
472
|
+
"""
|
|
473
|
+
base_count = (self.history.total_tokens + self._system_message_tokens
|
|
474
|
+
+ self._initial_task_tokens + getattr(self, '_skill_message_tokens', 0)
|
|
475
|
+
+ getattr(self, '_self_context_tokens', 0)
|
|
476
|
+
+ getattr(self, '_project_context_tokens', 0)
|
|
477
|
+
+ getattr(self, '_runtime_identity_tokens', 0))
|
|
478
|
+
current = self.get_actual_token_count()
|
|
479
|
+
remaining = self.safe_input_tokens - current
|
|
480
|
+
usage_percent = (current / self.max_input_tokens * 100) if self.max_input_tokens > 0 else 0
|
|
481
|
+
|
|
482
|
+
return {
|
|
483
|
+
'current': current,
|
|
484
|
+
'base': base_count,
|
|
485
|
+
'max': self.max_input_tokens,
|
|
486
|
+
'safe': self.safe_input_tokens,
|
|
487
|
+
'remaining': remaining,
|
|
488
|
+
'usage_percent': usage_percent
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
def _get_min_safe_tokens(self, model_name: str) -> int:
|
|
492
|
+
"""Get minimum safe token limit for a model.
|
|
493
|
+
|
|
494
|
+
This ensures we don't reduce tokens below a reasonable threshold for each model.
|
|
495
|
+
"""
|
|
496
|
+
# Try to get config from the centralized LLM module
|
|
497
|
+
if LLM_MODULE_AVAILABLE:
|
|
498
|
+
try:
|
|
499
|
+
config = get_model_config(model_name)
|
|
500
|
+
if config:
|
|
501
|
+
return config.min_safe_tokens
|
|
502
|
+
except Exception as e:
|
|
503
|
+
self.logger.debug(f"Error getting min safe tokens from LLM module: {e}")
|
|
504
|
+
|
|
505
|
+
# Fallback to hardcoded logic
|
|
506
|
+
# For high-context models, use a larger minimum
|
|
507
|
+
if any(name in model_name for name in ["gpt-4", "claude", "o1"]):
|
|
508
|
+
# These models work well with at least 16k tokens
|
|
509
|
+
return 16000
|
|
510
|
+
elif "gpt-3.5" in model_name:
|
|
511
|
+
# GPT-3.5 can handle at least 8k
|
|
512
|
+
return 8000
|
|
513
|
+
elif "llama" in model_name:
|
|
514
|
+
# Llama models typically have smaller contexts
|
|
515
|
+
return 4000
|
|
516
|
+
else:
|
|
517
|
+
# Conservative default for unknown models
|
|
518
|
+
return 4000
|
|
519
|
+
|
|
520
|
+
def get_context_usage_percent(self) -> float:
|
|
521
|
+
"""Get current context usage as a percentage.
|
|
522
|
+
|
|
523
|
+
Returns:
|
|
524
|
+
Percentage of context window used (0-100)
|
|
525
|
+
"""
|
|
526
|
+
if self.max_input_tokens <= 0:
|
|
527
|
+
return 0.0
|
|
528
|
+
|
|
529
|
+
# Use get_actual_token_count for complete picture including H-MEM
|
|
530
|
+
total_tokens = self.get_actual_token_count()
|
|
531
|
+
usage_pct = (total_tokens / self.max_input_tokens) * 100
|
|
532
|
+
return min(usage_pct, 100.0)
|