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,766 @@
|
|
|
1
|
+
/* Sidebar data management for WebView */
|
|
2
|
+
import { setText, fetchJSON, on, emit, sessionState, logger } from '/static/js/ui-utils.js?v=2';
|
|
3
|
+
|
|
4
|
+
// Refresh state tracking
|
|
5
|
+
const REFRESH_INTERVAL = 15000; // 15 seconds
|
|
6
|
+
let refreshTimer = null;
|
|
7
|
+
let isRefreshing = false;
|
|
8
|
+
let lastRefreshTime = {
|
|
9
|
+
session: 0,
|
|
10
|
+
task: 0,
|
|
11
|
+
agents: 0,
|
|
12
|
+
services: 0,
|
|
13
|
+
skills: 0
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Create debounce cache to prevent overlapping requests
|
|
17
|
+
const _inflightTokens = {
|
|
18
|
+
task: 0,
|
|
19
|
+
agents: 0,
|
|
20
|
+
services: 0,
|
|
21
|
+
session: 0,
|
|
22
|
+
skills: 0
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function _nextToken(kind) {
|
|
26
|
+
_inflightTokens[kind] = (_inflightTokens[kind] || 0) + 1;
|
|
27
|
+
return _inflightTokens[kind];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function _isLatest(kind, token) {
|
|
31
|
+
return token === _inflightTokens[kind];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Track in-flight requests
|
|
35
|
+
const _inflightRequests = {
|
|
36
|
+
agents: null,
|
|
37
|
+
services: null,
|
|
38
|
+
task: null,
|
|
39
|
+
session: null,
|
|
40
|
+
skills: null
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
44
|
+
// Initialize sidebar data once
|
|
45
|
+
refreshSidebar('all');
|
|
46
|
+
|
|
47
|
+
// Set up auto-refresh with a single timer that handles all updates
|
|
48
|
+
refreshTimer = setInterval(() => {
|
|
49
|
+
// Only refresh if page is visible and we're not already refreshing
|
|
50
|
+
if (document.visibilityState === 'visible' && !isRefreshing) {
|
|
51
|
+
refreshSidebar('all');
|
|
52
|
+
}
|
|
53
|
+
}, REFRESH_INTERVAL);
|
|
54
|
+
|
|
55
|
+
// Listen for specific refresh requests from other modules
|
|
56
|
+
on('sidebar:refreshRequest', (event) => {
|
|
57
|
+
const kind = event.detail?.kind || 'all';
|
|
58
|
+
refreshSidebar(kind);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Pause refreshes when page is hidden
|
|
62
|
+
document.addEventListener('visibilitychange', () => {
|
|
63
|
+
if (document.visibilityState === 'hidden') {
|
|
64
|
+
logger.debug('[Sidebar] Page hidden, pausing sidebar refreshes');
|
|
65
|
+
} else {
|
|
66
|
+
logger.debug('[Sidebar] Page visible, resuming sidebar refreshes');
|
|
67
|
+
// Refresh immediately when becoming visible again
|
|
68
|
+
refreshSidebar('all');
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Central refresh function that manages all sidebar data updates
|
|
75
|
+
* @param {string} kind - What to refresh: 'all', 'session', 'task', 'agents', or 'services'
|
|
76
|
+
* @param {boolean} force - Force refresh regardless of timing
|
|
77
|
+
*/
|
|
78
|
+
function refreshSidebar(kind = 'all', force = false) {
|
|
79
|
+
// Don't try to load data for new sessions (empty state)
|
|
80
|
+
const sessionId = sessionState.sessionId;
|
|
81
|
+
|
|
82
|
+
if (!sessionId || sessionState.isNew) {
|
|
83
|
+
logger.debug('[Sidebar] Skipping refresh - no active session yet');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (isRefreshing && !force) return;
|
|
88
|
+
|
|
89
|
+
logger.debug(`[Sidebar] Refreshing sidebar: ${kind}`);
|
|
90
|
+
isRefreshing = true;
|
|
91
|
+
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
const debounceTime = 2000; // 2 second debounce
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
if (kind === 'all' || kind === 'session') {
|
|
97
|
+
if (force || now - lastRefreshTime.session > debounceTime) {
|
|
98
|
+
updateSessionInfo();
|
|
99
|
+
lastRefreshTime.session = now;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (kind === 'all' || kind === 'task') {
|
|
104
|
+
if (force || now - lastRefreshTime.task > debounceTime) {
|
|
105
|
+
loadTask();
|
|
106
|
+
lastRefreshTime.task = now;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (kind === 'all' || kind === 'agents') {
|
|
111
|
+
if (force || now - lastRefreshTime.agents > debounceTime) {
|
|
112
|
+
loadAgents();
|
|
113
|
+
lastRefreshTime.agents = now;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (kind === 'all' || kind === 'services') {
|
|
118
|
+
if (force || now - lastRefreshTime.services > debounceTime) {
|
|
119
|
+
loadServices();
|
|
120
|
+
lastRefreshTime.services = now;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (kind === 'all' || kind === 'skills') {
|
|
125
|
+
if (force || now - lastRefreshTime.skills > debounceTime) {
|
|
126
|
+
loadSkills();
|
|
127
|
+
lastRefreshTime.skills = now;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} finally {
|
|
131
|
+
isRefreshing = false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Update session information in the sidebar
|
|
137
|
+
*/
|
|
138
|
+
function updateSessionInfo() {
|
|
139
|
+
const sessionId = sessionState.sessionId;
|
|
140
|
+
if (!sessionId) return;
|
|
141
|
+
|
|
142
|
+
const token = _nextToken('session');
|
|
143
|
+
logger.debug('[Sidebar] Updating session info for', sessionId);
|
|
144
|
+
|
|
145
|
+
// Don't start a new request if one is already in progress
|
|
146
|
+
if (_inflightRequests.session) {
|
|
147
|
+
logger.debug('[Sidebar] Session info request already in progress, skipping');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Update session ID (should already be in the template, but just in case)
|
|
152
|
+
const sessionIdEl = document.getElementById('session-id');
|
|
153
|
+
if (sessionIdEl) {
|
|
154
|
+
sessionIdEl.textContent = sessionId;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Get session status and update it
|
|
158
|
+
try {
|
|
159
|
+
// Set in-flight request
|
|
160
|
+
_inflightRequests.session = true;
|
|
161
|
+
|
|
162
|
+
// Use fetchJSON utility with proper error handling
|
|
163
|
+
fetchJSON(`/api/session/${sessionId}/status`)
|
|
164
|
+
.then(data => {
|
|
165
|
+
// Clear in-flight request
|
|
166
|
+
_inflightRequests.session = null;
|
|
167
|
+
|
|
168
|
+
// Guard against race
|
|
169
|
+
if (!_isLatest('session', token)) {
|
|
170
|
+
logger.debug('[Sidebar] Discarding stale session response');
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
logger.debug('[Sidebar] Session status response:', data);
|
|
175
|
+
const statusEl = document.getElementById('session-status');
|
|
176
|
+
if (statusEl) {
|
|
177
|
+
if (data && data.status) {
|
|
178
|
+
// Format the status: capitalize first letter
|
|
179
|
+
const formattedStatus = data.status.charAt(0).toUpperCase() + data.status.slice(1);
|
|
180
|
+
statusEl.textContent = formattedStatus;
|
|
181
|
+
logger.debug('[Sidebar] Updated session status to:', formattedStatus);
|
|
182
|
+
|
|
183
|
+
// Add status class for styling
|
|
184
|
+
statusEl.className = ''; // Clear existing classes
|
|
185
|
+
if (data.status === 'running' || data.status === 'active') {
|
|
186
|
+
statusEl.classList.add('status-running');
|
|
187
|
+
} else if (data.status === 'completed' || data.status === 'success') {
|
|
188
|
+
statusEl.classList.add('status-completed');
|
|
189
|
+
} else if (data.status === 'failed' || data.status === 'error') {
|
|
190
|
+
statusEl.classList.add('status-failed');
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
statusEl.textContent = 'Unknown';
|
|
194
|
+
logger.debug('[Sidebar] No status in response, setting to Unknown');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Also update session duration if available
|
|
199
|
+
if (data && data.created_at) {
|
|
200
|
+
updateSessionDuration(data.created_at);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Emit event that session info is updated
|
|
204
|
+
emit('sidebar:sessionUpdated', { status: data?.status });
|
|
205
|
+
})
|
|
206
|
+
.catch(err => {
|
|
207
|
+
// Clear in-flight request on error
|
|
208
|
+
_inflightRequests.session = null;
|
|
209
|
+
|
|
210
|
+
logger.warn('[Sidebar] Failed to fetch session status:', err);
|
|
211
|
+
// Set a fallback status on error
|
|
212
|
+
const statusEl = document.getElementById('session-status');
|
|
213
|
+
if (statusEl) {
|
|
214
|
+
statusEl.textContent = 'Unknown';
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
} catch (e) {
|
|
218
|
+
// Clear in-flight request
|
|
219
|
+
_inflightRequests.session = null;
|
|
220
|
+
logger.warn('[Sidebar] Error in updateSessionInfo:', e);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Update the session duration display
|
|
226
|
+
* @param {number} createdAt - Timestamp when session was created
|
|
227
|
+
*/
|
|
228
|
+
function updateSessionDuration(createdAt) {
|
|
229
|
+
const durationEl = document.getElementById('session-duration');
|
|
230
|
+
if (!durationEl || !createdAt) return;
|
|
231
|
+
|
|
232
|
+
// Calculate duration
|
|
233
|
+
const now = Date.now() / 1000;
|
|
234
|
+
const startTime = Number(createdAt);
|
|
235
|
+
const duration = now - startTime;
|
|
236
|
+
|
|
237
|
+
// Format duration
|
|
238
|
+
let formattedDuration = '';
|
|
239
|
+
if (duration < 60) {
|
|
240
|
+
formattedDuration = `${Math.floor(duration)}s`;
|
|
241
|
+
} else if (duration < 3600) {
|
|
242
|
+
const minutes = Math.floor(duration / 60);
|
|
243
|
+
const seconds = Math.floor(duration % 60);
|
|
244
|
+
formattedDuration = `${minutes}m ${seconds}s`;
|
|
245
|
+
} else {
|
|
246
|
+
const hours = Math.floor(duration / 3600);
|
|
247
|
+
const minutes = Math.floor((duration % 3600) / 60);
|
|
248
|
+
formattedDuration = `${hours}h ${minutes}m`;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
durationEl.textContent = formattedDuration;
|
|
252
|
+
logger.debug('[Sidebar] Updated session duration:', formattedDuration);
|
|
253
|
+
|
|
254
|
+
// Schedule next update in 1 second
|
|
255
|
+
setTimeout(() => updateSessionDuration(createdAt), 1000);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Load agents information for the session
|
|
260
|
+
*/
|
|
261
|
+
async function loadAgents() {
|
|
262
|
+
const sessionId = sessionState.sessionId;
|
|
263
|
+
if (!sessionId) return;
|
|
264
|
+
|
|
265
|
+
const token = _nextToken('agents');
|
|
266
|
+
const agentsContainer = document.getElementById('agents-container');
|
|
267
|
+
|
|
268
|
+
if (!agentsContainer) return;
|
|
269
|
+
|
|
270
|
+
// Don't start a new request if one is already in progress
|
|
271
|
+
if (_inflightRequests.agents) {
|
|
272
|
+
logger.debug('[Sidebar] Agents request already in progress, skipping');
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
try {
|
|
277
|
+
// Store current HTML before updating to avoid flicker
|
|
278
|
+
const currentContent = agentsContainer.innerHTML;
|
|
279
|
+
|
|
280
|
+
// Add cache-busting parameter to force a fresh load without caching
|
|
281
|
+
const timestamp = new Date().getTime();
|
|
282
|
+
const url = `/api/session/${sessionId}/agents?nocache=${timestamp}`;
|
|
283
|
+
|
|
284
|
+
// Set the in-flight request
|
|
285
|
+
_inflightRequests.agents = url;
|
|
286
|
+
|
|
287
|
+
// Fetch agents data using the utility function with the non-cached URL
|
|
288
|
+
const result = await fetchJSON(url);
|
|
289
|
+
|
|
290
|
+
// Clear in-flight request now that it's done
|
|
291
|
+
_inflightRequests.agents = null;
|
|
292
|
+
|
|
293
|
+
// Guard against race – if another call was triggered afterwards we
|
|
294
|
+
// ignore this stale result.
|
|
295
|
+
if (!_isLatest('agents', token)) {
|
|
296
|
+
logger.debug('[Sidebar] Discarding stale agents response');
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
logger.debug('[Sidebar] Agents data:', result);
|
|
301
|
+
|
|
302
|
+
// Update the agents container
|
|
303
|
+
if (result.agents && result.agents.length > 0) {
|
|
304
|
+
const agentsHtml = result.agents.map(agent => {
|
|
305
|
+
// Extract agent data using consistent field names
|
|
306
|
+
// Support both field naming conventions for compatibility
|
|
307
|
+
const agentId = agent.id || agent.agent_id || 'unknown';
|
|
308
|
+
const agentName = agent.name || agent.agent_name || '';
|
|
309
|
+
|
|
310
|
+
// Properly format agent type - ensure full agent type name
|
|
311
|
+
let agentType = agent.type || agent.agent_type || 'Unknown';
|
|
312
|
+
|
|
313
|
+
// Add "Agent" suffix if missing and not already containing "Agent"
|
|
314
|
+
if (!agentType.includes("Agent") && agentType !== "Unknown") {
|
|
315
|
+
// Special handling for common agent types
|
|
316
|
+
if (agentType.toLowerCase() === "planner") {
|
|
317
|
+
agentType = "PlannerAgent";
|
|
318
|
+
} else if (agentType.toLowerCase() === "executor") {
|
|
319
|
+
agentType = "ExecutorAgent";
|
|
320
|
+
} else if (agentType.toLowerCase() === "evaluator") {
|
|
321
|
+
agentType = "EvaluatorAgent";
|
|
322
|
+
} else if (agentType.toLowerCase() === "orchestrator") {
|
|
323
|
+
agentType = "SessionOrchestrator";
|
|
324
|
+
} else {
|
|
325
|
+
agentType = `${agentType}Agent`;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Get model name - check both field naming conventions
|
|
330
|
+
let agentModel = agent.model || agent.model_name || '';
|
|
331
|
+
|
|
332
|
+
// Clean up "Unknown" or empty values
|
|
333
|
+
if (!agentModel || agentModel === 'Unknown' || agentModel === 'None') {
|
|
334
|
+
agentModel = '';
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Log model information for debugging
|
|
338
|
+
logger.debug(`[Sidebar] Agent "${agentName}" model: "${agentModel}", type: ${agentType}`);
|
|
339
|
+
|
|
340
|
+
// Determine agent role/badge based on name or type - use generic approach
|
|
341
|
+
// Extract role from agent name - simply use agent name or type as badge
|
|
342
|
+
let role = '';
|
|
343
|
+
if (agentName) {
|
|
344
|
+
role = agentName.toLowerCase();
|
|
345
|
+
} else if (agentType && agentType !== 'Unknown') {
|
|
346
|
+
role = agentType.toLowerCase().replace('agent', '').replace('session', '');
|
|
347
|
+
} else {
|
|
348
|
+
role = 'agent';
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Use role name as the display title, properly formatted
|
|
352
|
+
let roleDisplay = role.charAt(0).toUpperCase() + role.slice(1);
|
|
353
|
+
|
|
354
|
+
// Properly clean up common agent roles for display
|
|
355
|
+
if (roleDisplay === "Executor") roleDisplay = "Executor";
|
|
356
|
+
if (roleDisplay === "Planner") roleDisplay = "Planner";
|
|
357
|
+
if (roleDisplay === "Evaluator") roleDisplay = "Evaluator";
|
|
358
|
+
if (roleDisplay === "Orchestrator") roleDisplay = "Orchestrator";
|
|
359
|
+
|
|
360
|
+
return `
|
|
361
|
+
<div class="agent-item">
|
|
362
|
+
<div class="agent-info-row">
|
|
363
|
+
<div class="agent-role">${roleDisplay}</div>
|
|
364
|
+
<div class="agent-type">${agentType}</div>
|
|
365
|
+
${agentModel ? `<div class="agent-model" title="${agentModel}">${agentModel}</div>` : ''}
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
`;
|
|
369
|
+
}).join('');
|
|
370
|
+
|
|
371
|
+
// Compare with existing content before updating to avoid DOM flicker
|
|
372
|
+
const newContent = agentsHtml;
|
|
373
|
+
if (newContent !== currentContent) {
|
|
374
|
+
agentsContainer.innerHTML = newContent;
|
|
375
|
+
}
|
|
376
|
+
} else {
|
|
377
|
+
// Only update if necessary
|
|
378
|
+
if (currentContent !== '<div class="empty-state">No agents available</div>') {
|
|
379
|
+
agentsContainer.innerHTML = '<div class="empty-state">No agents available</div>';
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Emit event that agents are updated
|
|
384
|
+
emit('sidebar:agentsUpdated');
|
|
385
|
+
} catch (error) {
|
|
386
|
+
// Clear in-flight request on error
|
|
387
|
+
_inflightRequests.agents = null;
|
|
388
|
+
|
|
389
|
+
logger.error('Error loading agents:', error);
|
|
390
|
+
// Only update with error if not already showing an error
|
|
391
|
+
if (!agentsContainer.innerHTML.includes('error-message')) {
|
|
392
|
+
agentsContainer.innerHTML = `<div class="error-message">Error loading agents: ${error.message}</div>`;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Load services information for the session
|
|
399
|
+
*/
|
|
400
|
+
async function loadServices() {
|
|
401
|
+
const sessionId = sessionState.sessionId;
|
|
402
|
+
if (!sessionId) return;
|
|
403
|
+
|
|
404
|
+
const token = _nextToken('services');
|
|
405
|
+
const servicesContainer = document.getElementById('services-container');
|
|
406
|
+
|
|
407
|
+
if (!servicesContainer) return;
|
|
408
|
+
|
|
409
|
+
// Don't start a new request if one is already in progress
|
|
410
|
+
if (_inflightRequests.services) {
|
|
411
|
+
logger.debug('[Sidebar] Services request already in progress, skipping');
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
try {
|
|
416
|
+
// Store current HTML before updating to avoid flicker
|
|
417
|
+
const currentContent = servicesContainer.innerHTML;
|
|
418
|
+
|
|
419
|
+
// Add cache-busting parameter to force a fresh load without caching
|
|
420
|
+
const timestamp = new Date().getTime();
|
|
421
|
+
const url = `/api/session/${sessionId}/services?nocache=${timestamp}`;
|
|
422
|
+
|
|
423
|
+
// Set the in-flight request
|
|
424
|
+
_inflightRequests.services = url;
|
|
425
|
+
|
|
426
|
+
// Fetch services data using the utility function with the non-cached URL
|
|
427
|
+
const result = await fetchJSON(url);
|
|
428
|
+
|
|
429
|
+
// Clear in-flight request now that it's done
|
|
430
|
+
_inflightRequests.services = null;
|
|
431
|
+
|
|
432
|
+
// Guard against race – if another call was triggered afterwards we
|
|
433
|
+
// ignore this stale result.
|
|
434
|
+
if (!_isLatest('services', token)) {
|
|
435
|
+
logger.debug('[Sidebar] Discarding stale services response');
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Update the services container
|
|
440
|
+
if (result.services && result.services.length > 0) {
|
|
441
|
+
// Sort services by name (safely)
|
|
442
|
+
const sortedServices = [...result.services].sort((a, b) => {
|
|
443
|
+
const nameA = (a.name || 'Unknown').toString();
|
|
444
|
+
const nameB = (b.name || 'Unknown').toString();
|
|
445
|
+
return nameA.localeCompare(nameB);
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
let servicesHtml = '';
|
|
449
|
+
|
|
450
|
+
// Create service tiles with name and description only (no action count)
|
|
451
|
+
for (const service of sortedServices) {
|
|
452
|
+
const serviceName = service.name || 'Unknown';
|
|
453
|
+
const rawDesc = service.description || '';
|
|
454
|
+
const hasCustomDesc = rawDesc && rawDesc.toLowerCase() !== 'no description available';
|
|
455
|
+
|
|
456
|
+
servicesHtml += `
|
|
457
|
+
<div class="service-tile sidebar-tile">
|
|
458
|
+
<div class="service-name">${serviceName}</div>
|
|
459
|
+
${hasCustomDesc ? `<div class="service-description">${rawDesc}</div>` : ''}
|
|
460
|
+
</div>
|
|
461
|
+
`;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Only update DOM if content has changed
|
|
465
|
+
if (servicesHtml !== currentContent) {
|
|
466
|
+
servicesContainer.innerHTML = servicesHtml;
|
|
467
|
+
}
|
|
468
|
+
} else {
|
|
469
|
+
// Only update if necessary
|
|
470
|
+
if (currentContent !== '<div class="empty-state">No services available</div>') {
|
|
471
|
+
servicesContainer.innerHTML = '<div class="empty-state">No services available</div>';
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Emit event that services are updated
|
|
476
|
+
emit('sidebar:servicesUpdated');
|
|
477
|
+
} catch (error) {
|
|
478
|
+
// Clear in-flight request on error
|
|
479
|
+
_inflightRequests.services = null;
|
|
480
|
+
|
|
481
|
+
logger.error('Error loading services:', error);
|
|
482
|
+
// Only update with error if not already showing an error
|
|
483
|
+
if (!servicesContainer.innerHTML.includes('error-message')) {
|
|
484
|
+
servicesContainer.innerHTML = `<div class="error-message">Error loading services: ${error.message}</div>`;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Load the task information
|
|
491
|
+
*/
|
|
492
|
+
async function loadTask() {
|
|
493
|
+
const sessionId = sessionState.sessionId;
|
|
494
|
+
if (!sessionId) return;
|
|
495
|
+
|
|
496
|
+
const token = _nextToken('task');
|
|
497
|
+
const taskDisplay = document.getElementById('task-display');
|
|
498
|
+
const currentTaskText = document.getElementById('current-task-text');
|
|
499
|
+
|
|
500
|
+
if (!taskDisplay) return;
|
|
501
|
+
|
|
502
|
+
// Don't start a new request if one is already in progress
|
|
503
|
+
if (_inflightRequests.task) {
|
|
504
|
+
logger.debug('[Sidebar] Task request already in progress, skipping');
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
try {
|
|
509
|
+
logger.debug(`[Sidebar] Fetching task data for session ${sessionId}`);
|
|
510
|
+
|
|
511
|
+
// Store current content to avoid flicker
|
|
512
|
+
const currentContent = taskDisplay.textContent;
|
|
513
|
+
|
|
514
|
+
// Set the in-flight request
|
|
515
|
+
_inflightRequests.task = true;
|
|
516
|
+
|
|
517
|
+
fetch('/api/session/' + sessionId + '/task')
|
|
518
|
+
.then(response => {
|
|
519
|
+
logger.debug(`[Sidebar] Direct fetch response:`, response);
|
|
520
|
+
if (!response.ok) {
|
|
521
|
+
logger.error(`[Sidebar] Task API returned error:`, response.status);
|
|
522
|
+
throw new Error(`Failed to fetch task: ${response.statusText}`);
|
|
523
|
+
}
|
|
524
|
+
return response.json();
|
|
525
|
+
})
|
|
526
|
+
.then(data => {
|
|
527
|
+
// Clear in-flight request
|
|
528
|
+
_inflightRequests.task = null;
|
|
529
|
+
|
|
530
|
+
// Guard against race – if another call was triggered afterwards we
|
|
531
|
+
// ignore this stale result.
|
|
532
|
+
if (!_isLatest('task', token)) {
|
|
533
|
+
logger.debug('[Sidebar] Discarding stale task response');
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
logger.debug(`[Sidebar] Task API response:`, data);
|
|
538
|
+
|
|
539
|
+
// Handle different response formats and statuses
|
|
540
|
+
if (data && data.status === "ok" && data.task) {
|
|
541
|
+
// We have a valid initial task
|
|
542
|
+
logger.debug(`[Sidebar] Task found: "${data.task}"`);
|
|
543
|
+
|
|
544
|
+
// Store the initial task once we retrieve it, to avoid showing dynamic task updates
|
|
545
|
+
if (!window.initialTaskSet) {
|
|
546
|
+
// Only update if the content has changed
|
|
547
|
+
if (taskDisplay.textContent !== data.task) {
|
|
548
|
+
taskDisplay.textContent = data.task;
|
|
549
|
+
|
|
550
|
+
// Update page title with task
|
|
551
|
+
document.title = `Session: ${sessionId} - ${data.task.substring(0, 30)}${data.task.length > 30 ? '...' : ''}`;
|
|
552
|
+
|
|
553
|
+
// Mark that we've set the initial task
|
|
554
|
+
window.initialTaskSet = true;
|
|
555
|
+
|
|
556
|
+
// Store task in localStorage to preserve between page refreshes
|
|
557
|
+
try {
|
|
558
|
+
localStorage.setItem(`task_${sessionId}`, data.task);
|
|
559
|
+
} catch (e) {
|
|
560
|
+
logger.error('[Sidebar] Error storing task in localStorage:', e);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
} else {
|
|
564
|
+
logger.debug('[Sidebar] Initial task already set, not updating with new task data');
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Always update the current task text (status) - this is independent of the task description
|
|
568
|
+
if (currentTaskText) {
|
|
569
|
+
// For the status, we can use either current_status if available, or status
|
|
570
|
+
const statusText = data.current_status || data.status || 'Running';
|
|
571
|
+
if (currentTaskText.textContent !== statusText) {
|
|
572
|
+
currentTaskText.textContent = statusText;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
else if (data && data.status === "not_found") {
|
|
577
|
+
// Check if we have a stored task first
|
|
578
|
+
const storedTask = localStorage.getItem(`task_${sessionId}`);
|
|
579
|
+
if (storedTask) {
|
|
580
|
+
logger.debug(`[Sidebar] Using stored task: "${storedTask}"`);
|
|
581
|
+
taskDisplay.textContent = storedTask;
|
|
582
|
+
window.initialTaskSet = true;
|
|
583
|
+
} else {
|
|
584
|
+
// No task found but response was valid
|
|
585
|
+
logger.debug(`[Sidebar] No task data available`);
|
|
586
|
+
if (taskDisplay.textContent !== 'No task specified') {
|
|
587
|
+
taskDisplay.textContent = 'No task specified';
|
|
588
|
+
|
|
589
|
+
// Update page title with just session ID
|
|
590
|
+
document.title = `Session: ${sessionId}`;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
else if (data && data.task === "") {
|
|
595
|
+
// Check if we have a stored task first
|
|
596
|
+
const storedTask = localStorage.getItem(`task_${sessionId}`);
|
|
597
|
+
if (storedTask) {
|
|
598
|
+
logger.debug(`[Sidebar] Using stored task: "${storedTask}"`);
|
|
599
|
+
taskDisplay.textContent = storedTask;
|
|
600
|
+
window.initialTaskSet = true;
|
|
601
|
+
} else {
|
|
602
|
+
// Empty task string
|
|
603
|
+
logger.debug(`[Sidebar] Empty task string received`);
|
|
604
|
+
if (taskDisplay.textContent !== 'No task specified') {
|
|
605
|
+
taskDisplay.textContent = 'No task specified';
|
|
606
|
+
|
|
607
|
+
// Update page title with just session ID
|
|
608
|
+
document.title = `Session: ${sessionId}`;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
// Check if we have a stored task first
|
|
614
|
+
const storedTask = localStorage.getItem(`task_${sessionId}`);
|
|
615
|
+
if (storedTask) {
|
|
616
|
+
logger.debug(`[Sidebar] Using stored task: "${storedTask}"`);
|
|
617
|
+
taskDisplay.textContent = storedTask;
|
|
618
|
+
window.initialTaskSet = true;
|
|
619
|
+
} else {
|
|
620
|
+
// Some other response format
|
|
621
|
+
logger.debug(`[Sidebar] Unexpected task response format`);
|
|
622
|
+
if (data && typeof data === "string" && data.trim().length > 0) {
|
|
623
|
+
// If data is a non-empty string, use it as the task
|
|
624
|
+
logger.debug(`[Sidebar] Task found: "${data}"`);
|
|
625
|
+
if (taskDisplay.textContent !== data) {
|
|
626
|
+
taskDisplay.textContent = data;
|
|
627
|
+
window.initialTaskSet = true;
|
|
628
|
+
|
|
629
|
+
// Store task in localStorage
|
|
630
|
+
try {
|
|
631
|
+
localStorage.setItem(`task_${sessionId}`, data);
|
|
632
|
+
} catch (e) {
|
|
633
|
+
logger.error('[Sidebar] Error storing task in localStorage:', e);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
} else {
|
|
637
|
+
if (taskDisplay.textContent !== 'No task specified') {
|
|
638
|
+
taskDisplay.textContent = 'No task specified';
|
|
639
|
+
|
|
640
|
+
// Update page title with just session ID
|
|
641
|
+
document.title = `Session: ${sessionId}`;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// Emit event that task is updated
|
|
648
|
+
emit('sidebar:taskUpdated');
|
|
649
|
+
})
|
|
650
|
+
.catch(error => {
|
|
651
|
+
// Clear in-flight request on error
|
|
652
|
+
_inflightRequests.task = null;
|
|
653
|
+
|
|
654
|
+
logger.error(`[Sidebar] Error fetching task:`, error);
|
|
655
|
+
// Check if we have a stored task
|
|
656
|
+
const storedTask = localStorage.getItem(`task_${sessionId}`);
|
|
657
|
+
if (storedTask) {
|
|
658
|
+
logger.debug(`[Sidebar] Using stored task on error: "${storedTask}"`);
|
|
659
|
+
taskDisplay.textContent = storedTask;
|
|
660
|
+
} else if (taskDisplay.textContent !== 'Error loading task information') {
|
|
661
|
+
taskDisplay.textContent = 'Error loading task information';
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
} catch (error) {
|
|
665
|
+
// Clear in-flight request on error
|
|
666
|
+
_inflightRequests.task = null;
|
|
667
|
+
|
|
668
|
+
logger.error('[Sidebar] Error loading task:', error);
|
|
669
|
+
// Check for stored task on error
|
|
670
|
+
const storedTask = localStorage.getItem(`task_${sessionId}`);
|
|
671
|
+
if (storedTask) {
|
|
672
|
+
logger.debug(`[Sidebar] Using stored task on error: "${storedTask}"`);
|
|
673
|
+
taskDisplay.textContent = storedTask;
|
|
674
|
+
} else if (taskDisplay.textContent !== 'Error loading task information') {
|
|
675
|
+
taskDisplay.textContent = 'Error loading task information';
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Load skills information for the session
|
|
682
|
+
*/
|
|
683
|
+
async function loadSkills() {
|
|
684
|
+
const sessionId = sessionState.sessionId;
|
|
685
|
+
if (!sessionId) return;
|
|
686
|
+
|
|
687
|
+
const token = _nextToken('skills');
|
|
688
|
+
const skillsContainer = document.getElementById('skills-container');
|
|
689
|
+
|
|
690
|
+
if (!skillsContainer) return;
|
|
691
|
+
|
|
692
|
+
// Don't start a new request if one is already in progress
|
|
693
|
+
if (_inflightRequests.skills) {
|
|
694
|
+
logger.debug('[Sidebar] Skills request already in progress, skipping');
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
try {
|
|
699
|
+
// Store current HTML before updating to avoid flicker
|
|
700
|
+
const currentContent = skillsContainer.innerHTML;
|
|
701
|
+
|
|
702
|
+
// Add cache-busting parameter to force a fresh load without caching
|
|
703
|
+
const timestamp = new Date().getTime();
|
|
704
|
+
const url = `/api/session/${sessionId}/skills?nocache=${timestamp}`;
|
|
705
|
+
|
|
706
|
+
// Set the in-flight request
|
|
707
|
+
_inflightRequests.skills = url;
|
|
708
|
+
|
|
709
|
+
// Fetch skills data
|
|
710
|
+
const result = await fetchJSON(url);
|
|
711
|
+
|
|
712
|
+
// Clear in-flight request now that it's done
|
|
713
|
+
_inflightRequests.skills = null;
|
|
714
|
+
|
|
715
|
+
// Guard against race
|
|
716
|
+
if (!_isLatest('skills', token)) {
|
|
717
|
+
logger.debug('[Sidebar] Discarding stale skills response');
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
logger.debug('[Sidebar] Skills data:', result);
|
|
722
|
+
|
|
723
|
+
// Update the skills container
|
|
724
|
+
if (result.skills && result.skills.length > 0) {
|
|
725
|
+
const skillsHtml = result.skills.map(skill => {
|
|
726
|
+
const skillId = skill.id || skill.skill_id || 'unknown';
|
|
727
|
+
const skillName = skill.name || skillId;
|
|
728
|
+
const isUserSkill = skill.type === 'user' || skill.is_user_skill;
|
|
729
|
+
|
|
730
|
+
return `
|
|
731
|
+
<div class="service-tile sidebar-tile">
|
|
732
|
+
<div class="service-name">
|
|
733
|
+
${skillName}
|
|
734
|
+
${isUserSkill ? '<span class="skill-badge custom">Custom</span>' : ''}
|
|
735
|
+
</div>
|
|
736
|
+
</div>
|
|
737
|
+
`;
|
|
738
|
+
}).join('');
|
|
739
|
+
|
|
740
|
+
// Only update DOM if content has changed
|
|
741
|
+
if (skillsHtml !== currentContent) {
|
|
742
|
+
skillsContainer.innerHTML = skillsHtml;
|
|
743
|
+
}
|
|
744
|
+
} else {
|
|
745
|
+
// Only update if necessary
|
|
746
|
+
if (currentContent !== '<div class="empty-state compact">No skills loaded</div>') {
|
|
747
|
+
skillsContainer.innerHTML = '<div class="empty-state compact">No skills loaded</div>';
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// Emit event that skills are updated
|
|
752
|
+
emit('sidebar:skillsUpdated');
|
|
753
|
+
} catch (error) {
|
|
754
|
+
// Clear in-flight request on error
|
|
755
|
+
_inflightRequests.skills = null;
|
|
756
|
+
|
|
757
|
+
// Skills endpoint may not exist yet, just show empty state
|
|
758
|
+
logger.debug('[Sidebar] Skills API not available:', error.message);
|
|
759
|
+
if (!skillsContainer.innerHTML.includes('No skills loaded')) {
|
|
760
|
+
skillsContainer.innerHTML = '<div class="empty-state compact">No skills loaded</div>';
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Export functions for use in other modules
|
|
766
|
+
export { refreshSidebar, updateSessionInfo, loadTask, loadAgents, loadServices, loadSkills };
|