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
cli/commands/skills.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""polyrob skills commands (P3 cli/commands split)."""
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_skill_manager():
|
|
8
|
+
"""Lazy accessor (kept module-level so it stays cheap to import and patchable)."""
|
|
9
|
+
from agents.task.agent.skill_manager import get_skill_manager as _gsm
|
|
10
|
+
return _gsm()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group()
|
|
14
|
+
def skills():
|
|
15
|
+
"""List and validate agent skills."""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@skills.command("list")
|
|
20
|
+
def skills_list():
|
|
21
|
+
"""List registered skill IDs."""
|
|
22
|
+
try:
|
|
23
|
+
mgr = get_skill_manager()
|
|
24
|
+
except Exception as e:
|
|
25
|
+
click.echo(click.style("[polyrob] ERROR: ", fg="red") + f"skill manager unavailable: {e}")
|
|
26
|
+
raise SystemExit(1)
|
|
27
|
+
if hasattr(mgr, "_ensure_rules_loaded"):
|
|
28
|
+
mgr._ensure_rules_loaded()
|
|
29
|
+
skill_ids = sorted(getattr(mgr, "skill_rules", {}).keys())
|
|
30
|
+
if not skill_ids:
|
|
31
|
+
click.echo("No skills registered.")
|
|
32
|
+
return
|
|
33
|
+
click.echo(f"Registered skills ({len(skill_ids)}):")
|
|
34
|
+
for sid in skill_ids:
|
|
35
|
+
click.echo(f" - {sid}")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@skills.command("validate")
|
|
39
|
+
@click.argument("skill_id", required=False)
|
|
40
|
+
def skills_validate(skill_id: Optional[str]):
|
|
41
|
+
"""Validate one skill (by id) or the whole authored library.
|
|
42
|
+
|
|
43
|
+
With SKILL_ID: the legacy per-skill check (rules.json wiring + content shape).
|
|
44
|
+
With no argument: the strict agentskills.io frontmatter compliance check
|
|
45
|
+
(``SkillManager.validate_all_authored``) run across every shipped skill —
|
|
46
|
+
the same gate `polyrob doctor` and CI's library-invariant test use.
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
mgr = get_skill_manager()
|
|
50
|
+
except Exception as e:
|
|
51
|
+
click.echo(click.style("[polyrob] ERROR: ", fg="red") + f"skill manager unavailable: {e}")
|
|
52
|
+
raise SystemExit(1)
|
|
53
|
+
if skill_id:
|
|
54
|
+
# F7: an unknown skill id should fail clearly, not crash with a raw
|
|
55
|
+
# KeyError/traceback. Validate against the known ids first.
|
|
56
|
+
if hasattr(mgr, "_ensure_rules_loaded"):
|
|
57
|
+
try:
|
|
58
|
+
mgr._ensure_rules_loaded()
|
|
59
|
+
except Exception:
|
|
60
|
+
pass
|
|
61
|
+
known = getattr(mgr, "skill_rules", {}) or {}
|
|
62
|
+
if known and skill_id not in known:
|
|
63
|
+
click.echo(
|
|
64
|
+
click.style("[polyrob] ERROR: ", fg="red")
|
|
65
|
+
+ f"no such skill: {skill_id!r} (try `polyrob skills list`)"
|
|
66
|
+
)
|
|
67
|
+
raise SystemExit(1)
|
|
68
|
+
try:
|
|
69
|
+
result = mgr.validate_skill(skill_id)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
click.echo(
|
|
72
|
+
click.style("[polyrob] ERROR: ", fg="red")
|
|
73
|
+
+ f"no such skill: {skill_id!r} ({e})"
|
|
74
|
+
)
|
|
75
|
+
raise SystemExit(1)
|
|
76
|
+
status = click.style("valid", fg="green") if result.is_valid else click.style("INVALID", fg="red")
|
|
77
|
+
click.echo(f"{result.skill_id:<24} {status}")
|
|
78
|
+
for err in getattr(result, "errors", []) or []:
|
|
79
|
+
click.echo(f" error: {err}")
|
|
80
|
+
for warn in getattr(result, "warnings", []) or []:
|
|
81
|
+
click.echo(f" warn: {warn}")
|
|
82
|
+
if not result.is_valid:
|
|
83
|
+
raise SystemExit(1)
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
# No skill_id: strict library-wide compliance check (Task 4).
|
|
87
|
+
issues_by_skill = mgr.validate_all_authored()
|
|
88
|
+
error_count = 0
|
|
89
|
+
for sid in sorted(issues_by_skill):
|
|
90
|
+
click.echo(f"{sid}:")
|
|
91
|
+
for issue in issues_by_skill[sid]:
|
|
92
|
+
if issue.level == "error":
|
|
93
|
+
error_count += 1
|
|
94
|
+
click.echo(f" {issue.level}: {issue.code} — {issue.msg}")
|
|
95
|
+
if not issues_by_skill:
|
|
96
|
+
click.echo(click.style("All authored skills are compliant.", fg="green"))
|
|
97
|
+
else:
|
|
98
|
+
click.echo(
|
|
99
|
+
f"\n{len(issues_by_skill)} skill(s) with issues ({error_count} error(s))"
|
|
100
|
+
)
|
|
101
|
+
if error_count:
|
|
102
|
+
raise SystemExit(1)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@skills.command("export")
|
|
106
|
+
@click.argument("skill_id")
|
|
107
|
+
@click.option("--to", "dest", default=None, help="Target dir (default: ~/.agents/skills)")
|
|
108
|
+
def skills_export(skill_id: str, dest: Optional[str]):
|
|
109
|
+
"""Copy a skill folder (SKILL.md + resources) to a portable location.
|
|
110
|
+
|
|
111
|
+
Defaults to ``~/.agents/skills/<skill_id>`` (agentskills.io-style layout);
|
|
112
|
+
``--to DIR`` targets ``DIR/<skill_id>`` instead. Refuses to clobber an
|
|
113
|
+
existing target directory.
|
|
114
|
+
"""
|
|
115
|
+
import shutil
|
|
116
|
+
from pathlib import Path
|
|
117
|
+
|
|
118
|
+
mgr = get_skill_manager()
|
|
119
|
+
src = mgr.resolve_skill_dir(skill_id)
|
|
120
|
+
if not src or not (src / "SKILL.md").exists():
|
|
121
|
+
raise click.ClickException(f"no such skill: {skill_id!r} (try `polyrob skills list`)")
|
|
122
|
+
target_root = Path(dest) if dest else (Path.home() / ".agents" / "skills")
|
|
123
|
+
out = target_root / skill_id
|
|
124
|
+
if out.exists():
|
|
125
|
+
raise click.ClickException(f"already exists: {out} (remove it first)")
|
|
126
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
127
|
+
shutil.copytree(src, out)
|
|
128
|
+
click.echo(f"exported {skill_id} -> {out}")
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""POLYROB subagents commands — inspect background delegations.
|
|
2
|
+
|
|
3
|
+
Delegations are session-scoped and in-memory. This command can show:
|
|
4
|
+
- General delegation capability info
|
|
5
|
+
- Active delegations for a live session (if attached/queried)
|
|
6
|
+
- Static info about limits and configuration
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
|
|
15
|
+
from agents.task.constants import TimeoutConfig
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.group("subagents")
|
|
19
|
+
def subagents():
|
|
20
|
+
"""Inspect agent delegation and subagent activity."""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@subagents.command("info")
|
|
25
|
+
@click.option("--json", "as_json", is_flag=True, help="Print machine-readable JSON.")
|
|
26
|
+
def subagents_info(as_json: bool):
|
|
27
|
+
"""Show delegation capability and limits."""
|
|
28
|
+
# Lazy import to avoid heavy tools import chain
|
|
29
|
+
try:
|
|
30
|
+
from tools.controller.delegation import get_blocked_child_tools
|
|
31
|
+
blocked_tools = sorted(get_blocked_child_tools())
|
|
32
|
+
except Exception:
|
|
33
|
+
# Fallback if tools import fails
|
|
34
|
+
blocked_tools = []
|
|
35
|
+
|
|
36
|
+
info = {
|
|
37
|
+
"delegation_enabled": TimeoutConfig.get_sub_agents_enabled(),
|
|
38
|
+
"max_concurrent": TimeoutConfig.get_max_concurrent_sub_agents(),
|
|
39
|
+
"max_depth": TimeoutConfig.get_max_sub_agent_depth(),
|
|
40
|
+
"max_async": TimeoutConfig.get_max_async_sub_agents(),
|
|
41
|
+
"sync_timeout": TimeoutConfig.get_sub_agent_timeout(),
|
|
42
|
+
# The parallel/async (background) delegation path uses its own longer
|
|
43
|
+
# timeout, not the sync one — report the real value.
|
|
44
|
+
"async_timeout": TimeoutConfig.get_parallel_subtasks_timeout(),
|
|
45
|
+
"blocked_tools": blocked_tools,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if as_json:
|
|
49
|
+
click.echo(json.dumps(info, indent=2))
|
|
50
|
+
else:
|
|
51
|
+
click.echo("Delegation Capability:")
|
|
52
|
+
click.echo(f" Enabled: {info['delegation_enabled']}")
|
|
53
|
+
click.echo(f" Max concurrent: {info['max_concurrent']}")
|
|
54
|
+
click.echo(f" Max depth: {info['max_depth']}")
|
|
55
|
+
click.echo(f" Max background: {info['max_async']}")
|
|
56
|
+
click.echo(f" Sync timeout: {info['sync_timeout']}s")
|
|
57
|
+
click.echo(f" Async timeout: {info['async_timeout']}s")
|
|
58
|
+
if info['blocked_tools']:
|
|
59
|
+
click.echo(f" Blocked tools: {', '.join(info['blocked_tools'])}")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@subagents.command("list")
|
|
63
|
+
@click.option("--session-id", help="Session to inspect (requires live session or persisted data).")
|
|
64
|
+
@click.option("--json", "as_json", is_flag=True, help="Print machine-readable JSON.")
|
|
65
|
+
def subagents_list(session_id: Optional[str], as_json: bool):
|
|
66
|
+
"""List subagents/delegations.
|
|
67
|
+
|
|
68
|
+
Note: Delegations are currently in-memory and session-scoped. Without a live
|
|
69
|
+
session connection, this can only show persisted records (future work).
|
|
70
|
+
"""
|
|
71
|
+
if as_json:
|
|
72
|
+
click.echo(json.dumps({
|
|
73
|
+
"supported": False, "delegations": [],
|
|
74
|
+
"reason": "CLI delegation introspection is not yet persisted; "
|
|
75
|
+
"use /subagents in a live REPL session.",
|
|
76
|
+
}, indent=2))
|
|
77
|
+
return
|
|
78
|
+
if session_id:
|
|
79
|
+
click.echo(click.style("[polyrob] ", fg="yellow") +
|
|
80
|
+
"Live session introspection requires API/WebView connection")
|
|
81
|
+
click.echo("CLI will support persisted delegation records in a future update")
|
|
82
|
+
else:
|
|
83
|
+
click.echo("Use /subagents in an active REPL session, or specify --session-id for persisted records")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@subagents.command("show")
|
|
87
|
+
@click.argument("delegation_id")
|
|
88
|
+
@click.option("--json", "as_json", is_flag=True, help="Print machine-readable JSON.")
|
|
89
|
+
def subagents_show(delegation_id: str, as_json: bool):
|
|
90
|
+
"""Show details for a specific delegation."""
|
|
91
|
+
if as_json:
|
|
92
|
+
click.echo(json.dumps({
|
|
93
|
+
"supported": False, "delegation_id": delegation_id,
|
|
94
|
+
"reason": "CLI delegation introspection is not yet persisted; "
|
|
95
|
+
"use /subagents in a live REPL session.",
|
|
96
|
+
}, indent=2))
|
|
97
|
+
return
|
|
98
|
+
click.echo(click.style("[polyrob] ", fg="yellow") +
|
|
99
|
+
"Live delegation introspection requires API/WebView connection")
|
|
100
|
+
click.echo("CLI will support persisted delegation records in a future update")
|
cli/commands/surface.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""polyrob surface — operator controls for per-surface circuit breakers.
|
|
2
|
+
|
|
3
|
+
The worker process owns an in-memory SurfaceCircuitBreaker that auto-opens after
|
|
4
|
+
K consecutive failures. The CLI process is SEPARATE, so pause/resume are persisted
|
|
5
|
+
to a tiny SQLite table (data/surface_state.db) that the worker reads on each
|
|
6
|
+
is_open() call (when its breaker is built with a CircuitStore attached).
|
|
7
|
+
|
|
8
|
+
Commands:
|
|
9
|
+
polyrob surface list Show all known surfaces and their paused state.
|
|
10
|
+
polyrob surface pause <id> Pause a surface (writes to the store).
|
|
11
|
+
polyrob surface resume <id> Resume a surface (clears the stored flag).
|
|
12
|
+
"""
|
|
13
|
+
import os
|
|
14
|
+
|
|
15
|
+
import click
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _data_dir() -> str:
|
|
19
|
+
# Match the worker's data home (build_cli_container's _resolve_cli_data_home =
|
|
20
|
+
# <cwd>/.polyrob by default) so pause/resume write the SAME surface_state.db the
|
|
21
|
+
# worker reads — 'POLYROB_DATA_DIR or data' pointed the CLI at a divergent ./data.
|
|
22
|
+
from core.bootstrap import _resolve_cli_data_home
|
|
23
|
+
data_home, _, _ = _resolve_cli_data_home()
|
|
24
|
+
return str(data_home)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _store():
|
|
28
|
+
from core.surfaces.circuit import CircuitStore
|
|
29
|
+
return CircuitStore(os.path.join(_data_dir(), "surface_state.db"))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _warn_if_breaker_inert() -> None:
|
|
33
|
+
"""pause/resume only bite if the worker built a CircuitStore-backed breaker, which
|
|
34
|
+
it does ONLY when OUTBOUND_QUEUE_ENABLED is on. Warn so the operator isn't misled
|
|
35
|
+
by a 'paused' that has no effect."""
|
|
36
|
+
from agents.task.surface_config import SurfaceConfig
|
|
37
|
+
if not SurfaceConfig.outbound_queue_enabled():
|
|
38
|
+
click.echo(click.style(
|
|
39
|
+
"note: OUTBOUND_QUEUE_ENABLED is off — the worker builds no circuit breaker, "
|
|
40
|
+
"so this is recorded but has NO effect until you enable it.", fg="yellow"))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@click.group()
|
|
44
|
+
def surface():
|
|
45
|
+
"""Inspect and control per-surface circuit breakers."""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@surface.command("list")
|
|
49
|
+
def list_surfaces():
|
|
50
|
+
"""List surfaces and their persisted paused state."""
|
|
51
|
+
rows = _store().list_all()
|
|
52
|
+
if not rows:
|
|
53
|
+
click.echo(click.style("no surface state entries", dim=True))
|
|
54
|
+
click.echo(click.style("(surfaces are auto-registered when first paused)", dim=True))
|
|
55
|
+
return
|
|
56
|
+
for r in rows:
|
|
57
|
+
status = (
|
|
58
|
+
click.style("PAUSED", fg="red", bold=True)
|
|
59
|
+
if r["paused"]
|
|
60
|
+
else click.style("active", fg="green")
|
|
61
|
+
)
|
|
62
|
+
click.echo(f" {r['surface_id']:<20} {status}")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@surface.command("pause")
|
|
66
|
+
@click.argument("surface_id")
|
|
67
|
+
def pause_surface(surface_id: str):
|
|
68
|
+
"""Pause a surface — the worker will skip it until resumed."""
|
|
69
|
+
_store().pause(surface_id)
|
|
70
|
+
click.echo(click.style(f"paused: {surface_id}", fg="yellow"))
|
|
71
|
+
click.echo(click.style("worker will defer outbound messages for this surface", dim=True))
|
|
72
|
+
_warn_if_breaker_inert()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@surface.command("resume")
|
|
76
|
+
@click.argument("surface_id")
|
|
77
|
+
def resume_surface(surface_id: str):
|
|
78
|
+
"""Resume a paused surface — the worker will start delivering again."""
|
|
79
|
+
_store().resume(surface_id)
|
|
80
|
+
click.echo(click.style(f"resumed: {surface_id}", fg="green"))
|
|
81
|
+
_warn_if_breaker_inert()
|
cli/commands/telegram.py
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""polyrob telegram — chat with the agent over Telegram via local long-polling.
|
|
2
|
+
|
|
3
|
+
No webhook / public URL / SSL needed: this long-polls getUpdates on your machine and
|
|
4
|
+
runs the full Task agent (same front door as the API webhook path). Owner-locked via
|
|
5
|
+
ALLOWED_TELEGRAM_USER_IDS (raw Telegram numeric ids); with no allowlist set the bot
|
|
6
|
+
replies with your id so you can lock it.
|
|
7
|
+
|
|
8
|
+
Token: --token or TELEGRAM_BOT_TOKEN (process env or ./.polyrob/.env). Nothing is committed.
|
|
9
|
+
"""
|
|
10
|
+
import asyncio
|
|
11
|
+
import os
|
|
12
|
+
import signal
|
|
13
|
+
import sys
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
import click
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TelegramTokenError(click.ClickException):
|
|
20
|
+
"""No Telegram bot token available."""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def resolve_telegram_token(token_opt: Optional[str]) -> str:
|
|
24
|
+
"""--token wins, else TELEGRAM_BOT_TOKEN env; raise a clear error if absent."""
|
|
25
|
+
tok = (token_opt or os.environ.get("TELEGRAM_BOT_TOKEN") or "").strip()
|
|
26
|
+
if not tok:
|
|
27
|
+
raise TelegramTokenError(
|
|
28
|
+
"No Telegram bot token. Pass --token, or set TELEGRAM_BOT_TOKEN "
|
|
29
|
+
"(process env or ./.polyrob/.env). Create a bot via @BotFather to get one."
|
|
30
|
+
)
|
|
31
|
+
return tok
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@click.command()
|
|
35
|
+
@click.option("--token", default=None, help="Telegram bot token (else TELEGRAM_BOT_TOKEN env)")
|
|
36
|
+
@click.option("--verbose", "-v", is_flag=True, help="Show debug logging")
|
|
37
|
+
def telegram(token: Optional[str], verbose: bool):
|
|
38
|
+
"""Run the agent as a Telegram bot (local long-polling)."""
|
|
39
|
+
asyncio.run(_run_telegram(token, verbose))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
async def _run_telegram(token_opt: Optional[str], verbose: bool):
|
|
43
|
+
import logging as _logging
|
|
44
|
+
|
|
45
|
+
from core.bootstrap import build_cli_container, setup_project_path, setup_sqlite_compat
|
|
46
|
+
|
|
47
|
+
# The outbound bus + binding are gated on SINGULAR_CHAT_ENABLED; the surface gate
|
|
48
|
+
# is TELEGRAM_SURFACE_ENABLED. Default them ON for this command (explicit env wins),
|
|
49
|
+
# BEFORE the container build so the bus installs during TaskAgent construction too.
|
|
50
|
+
os.environ.setdefault("SINGULAR_CHAT_ENABLED", "true")
|
|
51
|
+
os.environ.setdefault("TELEGRAM_SURFACE_ENABLED", "true")
|
|
52
|
+
|
|
53
|
+
setup_project_path()
|
|
54
|
+
setup_sqlite_compat()
|
|
55
|
+
|
|
56
|
+
# No usable provider key → clean canonical message + exit (a daemon must not block
|
|
57
|
+
# on an interactive wizard). Loads env layers internally.
|
|
58
|
+
from cli.keys import preflight_or_onboard
|
|
59
|
+
if not preflight_or_onboard(interactive=False):
|
|
60
|
+
sys.exit(1)
|
|
61
|
+
|
|
62
|
+
# Resolve the bot token NOW — preflight_or_onboard already loaded the env layers
|
|
63
|
+
# (./.polyrob/.env etc.), so fail fast on a missing token (a clean ClickException)
|
|
64
|
+
# instead of paying a full container build first.
|
|
65
|
+
token = resolve_telegram_token(token_opt)
|
|
66
|
+
|
|
67
|
+
# A headless run (systemd: stderr is the journal, not a TTY) MUST log — a server
|
|
68
|
+
# with no logs is unoperable. An interactive run keeps the console clean. `-v` always
|
|
69
|
+
# gives DEBUG. So: verbose->DEBUG; headless->INFO to the journal; interactive->quiet.
|
|
70
|
+
headless = not sys.stderr.isatty()
|
|
71
|
+
if verbose:
|
|
72
|
+
log_level = "DEBUG"
|
|
73
|
+
elif headless:
|
|
74
|
+
log_level = "INFO"
|
|
75
|
+
else:
|
|
76
|
+
log_level = "ERROR"
|
|
77
|
+
quiet = (not verbose) and (not headless)
|
|
78
|
+
if quiet:
|
|
79
|
+
_logging.disable(_logging.CRITICAL)
|
|
80
|
+
os.environ["GRPC_VERBOSITY"] = "ERROR"
|
|
81
|
+
os.environ["GLOG_minloglevel"] = "3"
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
container = await build_cli_container(log_level=log_level)
|
|
85
|
+
except Exception as e:
|
|
86
|
+
click.echo(click.style("[polyrob] ERROR: ", fg="red") + f"failed to start: {e}")
|
|
87
|
+
sys.exit(1)
|
|
88
|
+
if quiet:
|
|
89
|
+
_logging.disable(_logging.ERROR)
|
|
90
|
+
elif not verbose:
|
|
91
|
+
# Headless service: app logs at INFO in the journal, but silence the noisy
|
|
92
|
+
# transport libraries (long-poll getUpdates, aiogram dispatcher, asyncio).
|
|
93
|
+
for _noisy in ("httpx", "httpcore", "aiogram.event", "asyncio", "hpack"):
|
|
94
|
+
_logging.getLogger(_noisy).setLevel(_logging.WARNING)
|
|
95
|
+
|
|
96
|
+
task_agent = container.get_agent("task_agent")
|
|
97
|
+
if not task_agent:
|
|
98
|
+
click.echo(click.style("[polyrob] ERROR: ", fg="red") + "TaskAgent not available in container")
|
|
99
|
+
sys.exit(1)
|
|
100
|
+
|
|
101
|
+
# Install the outbound bus (idempotent; gated on SINGULAR_CHAT_ENABLED) so agent
|
|
102
|
+
# replies can route out to the Telegram surface.
|
|
103
|
+
from core.surfaces.bootstrap import install_surface_bus
|
|
104
|
+
install_surface_bus(container) # db_path defaults to container.config.data_dir
|
|
105
|
+
|
|
106
|
+
dispatcher = container.get_service("outbound_dispatcher")
|
|
107
|
+
if dispatcher is not None:
|
|
108
|
+
dispatcher.start()
|
|
109
|
+
|
|
110
|
+
from surfaces.telegram.harness import build_telegram_harness
|
|
111
|
+
# Pin harness state DBs (dedup / user directory) to the container's data_dir so
|
|
112
|
+
# per-instance isolation holds under POLYROB_DATA_DIR (else they land in ./data).
|
|
113
|
+
_data_dir = getattr(getattr(container, "config", None), "data_dir", "data") or "data"
|
|
114
|
+
harness = build_telegram_harness(container, task_agent, token=token, webhook_base=None,
|
|
115
|
+
data_dir=_data_dir)
|
|
116
|
+
|
|
117
|
+
# start() registers + subscribes the surface and clears any stale webhook.
|
|
118
|
+
await harness.start()
|
|
119
|
+
|
|
120
|
+
# Start the autonomy background loops under the local profile — the SAME shared
|
|
121
|
+
# runtime the REPL + API lifespan use. Crucially this is what runs the #6 surface-GC
|
|
122
|
+
# ticker that prunes stale chat<->session bindings; without it GC would be dead on
|
|
123
|
+
# the primary Telegram surface (the one that mints those bindings). Fail-open.
|
|
124
|
+
autonomy_handles = None
|
|
125
|
+
try:
|
|
126
|
+
from agents.task.constants import local_mode_enabled
|
|
127
|
+
if local_mode_enabled():
|
|
128
|
+
from core.autonomy_runtime import start_autonomy
|
|
129
|
+
_data_dir = getattr(getattr(container, "config", None), "data_dir", "data")
|
|
130
|
+
autonomy_handles = start_autonomy(task_agent=task_agent, data_dir=_data_dir)
|
|
131
|
+
except Exception:
|
|
132
|
+
autonomy_handles = None
|
|
133
|
+
|
|
134
|
+
# Greet: confirm which bot we're driving + the owner-lock state.
|
|
135
|
+
try:
|
|
136
|
+
me = await harness.bot.get_me()
|
|
137
|
+
username = getattr(me, "username", None)
|
|
138
|
+
except Exception:
|
|
139
|
+
username = None
|
|
140
|
+
allow = (os.environ.get("ALLOWED_TELEGRAM_USER_IDS") or "").strip()
|
|
141
|
+
click.echo(click.style("telegram bot online", fg="green")
|
|
142
|
+
+ (f": @{username}" if username else ""))
|
|
143
|
+
if allow:
|
|
144
|
+
click.echo(click.style(f"owner-locked to user id(s): {allow}", dim=True))
|
|
145
|
+
else:
|
|
146
|
+
click.echo(click.style(
|
|
147
|
+
"no allowlist set — message the bot once and it will reply with your id, "
|
|
148
|
+
"then set ALLOWED_TELEGRAM_USER_IDS and restart.", fg="yellow"))
|
|
149
|
+
click.echo(click.style("polling… (Ctrl-C to stop)", dim=True))
|
|
150
|
+
|
|
151
|
+
# Clean shutdown on Ctrl-C: stop the loop, then close the bot session.
|
|
152
|
+
loop = asyncio.get_running_loop()
|
|
153
|
+
poll_task = asyncio.ensure_future(harness.run_polling())
|
|
154
|
+
|
|
155
|
+
def _stop(*_a):
|
|
156
|
+
harness._running = False
|
|
157
|
+
poll_task.cancel()
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
loop.add_signal_handler(signal.SIGINT, _stop)
|
|
161
|
+
loop.add_signal_handler(signal.SIGTERM, _stop)
|
|
162
|
+
except (NotImplementedError, RuntimeError):
|
|
163
|
+
for _sig in (signal.SIGINT, signal.SIGTERM):
|
|
164
|
+
try:
|
|
165
|
+
signal.signal(_sig, lambda *_a: _stop())
|
|
166
|
+
except (ValueError, OSError, AttributeError):
|
|
167
|
+
pass # SIGTERM may be unavailable on some platforms/threads
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
await poll_task
|
|
171
|
+
except asyncio.CancelledError:
|
|
172
|
+
pass
|
|
173
|
+
finally:
|
|
174
|
+
click.echo("\n" + click.style("stopping telegram bot…", dim=True))
|
|
175
|
+
if autonomy_handles is not None:
|
|
176
|
+
try:
|
|
177
|
+
await autonomy_handles.stop()
|
|
178
|
+
except Exception:
|
|
179
|
+
pass
|
|
180
|
+
if dispatcher is not None:
|
|
181
|
+
try:
|
|
182
|
+
await dispatcher.stop()
|
|
183
|
+
except Exception:
|
|
184
|
+
pass
|
|
185
|
+
await harness.stop()
|