claude-mpm 4.16.0__py3-none-any.whl → 4.25.10__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +272 -23
- claude_mpm/agents/OUTPUT_STYLE.md +3 -48
- claude_mpm/agents/PM_INSTRUCTIONS.md +1821 -32
- claude_mpm/agents/WORKFLOW.md +75 -2
- claude_mpm/agents/agent_loader.py +4 -4
- claude_mpm/agents/base_agent.json +6 -3
- claude_mpm/agents/frontmatter_validator.py +1 -1
- claude_mpm/agents/templates/api_qa.json +5 -2
- claude_mpm/agents/templates/circuit_breakers.md +108 -2
- claude_mpm/agents/templates/documentation.json +33 -6
- claude_mpm/agents/templates/engineer.json +5 -1
- claude_mpm/agents/templates/javascript_engineer_agent.json +380 -0
- claude_mpm/agents/templates/php-engineer.json +10 -4
- claude_mpm/agents/templates/pm_red_flags.md +89 -19
- claude_mpm/agents/templates/project_organizer.json +7 -3
- claude_mpm/agents/templates/python_engineer.json +8 -3
- claude_mpm/agents/templates/qa.json +2 -1
- claude_mpm/agents/templates/react_engineer.json +1 -0
- claude_mpm/agents/templates/research.json +82 -12
- claude_mpm/agents/templates/rust_engineer.json +12 -7
- claude_mpm/agents/templates/security.json +4 -4
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/tauri_engineer.json +274 -0
- claude_mpm/agents/templates/ticketing.json +10 -6
- claude_mpm/agents/templates/version_control.json +4 -2
- claude_mpm/agents/templates/web_qa.json +2 -1
- claude_mpm/cli/README.md +253 -0
- claude_mpm/cli/__init__.py +11 -1
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/analyze.py +3 -3
- claude_mpm/cli/commands/cleanup.py +1 -1
- claude_mpm/cli/commands/configure_agent_display.py +4 -4
- claude_mpm/cli/commands/debug.py +12 -12
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/mcp_install_commands.py +1 -1
- claude_mpm/cli/commands/mcp_install_commands.py.backup +284 -0
- claude_mpm/cli/commands/mpm_init/README.md +365 -0
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +573 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +67 -1
- claude_mpm/cli/commands/run.py +124 -128
- claude_mpm/cli/commands/skills.py +922 -0
- claude_mpm/cli/executor.py +58 -0
- claude_mpm/cli/interactive/agent_wizard.py +5 -5
- claude_mpm/cli/parsers/base_parser.py +35 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
- claude_mpm/cli/parsers/skills_parser.py +275 -0
- claude_mpm/cli/startup.py +168 -8
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/cli_module/commands.py +1 -1
- claude_mpm/cli_module/refactoring_guide.md +253 -0
- claude_mpm/commands/mpm-auto-configure.md +52 -0
- claude_mpm/commands/mpm-help.md +6 -0
- claude_mpm/commands/mpm-init.md +130 -8
- claude_mpm/commands/mpm-resume.md +372 -0
- claude_mpm/commands/mpm-tickets.md +56 -7
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +2 -0
- claude_mpm/config/agent_capabilities.yaml +658 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/config/async_logging_config.yaml +145 -0
- claude_mpm/constants.py +24 -0
- claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +34 -0
- claude_mpm/core/api_validator.py +1 -1
- claude_mpm/core/claude_runner.py +14 -1
- claude_mpm/core/config.py +50 -0
- claude_mpm/core/constants.py +1 -1
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/framework/processors/metadata_processor.py +1 -1
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +41 -2
- claude_mpm/core/interactive_session.py +48 -3
- claude_mpm/core/interfaces.py +56 -1
- claude_mpm/core/logger.py +3 -1
- claude_mpm/core/oneshot_session.py +39 -0
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/d2/.gitignore +22 -0
- claude_mpm/d2/ARCHITECTURE_COMPARISON.md +273 -0
- claude_mpm/d2/FLASK_INTEGRATION.md +156 -0
- claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +452 -0
- claude_mpm/d2/QUICKSTART.md +186 -0
- claude_mpm/d2/README.md +232 -0
- claude_mpm/d2/STORE_FIX_SUMMARY.md +167 -0
- claude_mpm/d2/SVELTE5_STORES_GUIDE.md +180 -0
- claude_mpm/d2/TESTING.md +288 -0
- claude_mpm/d2/index.html +118 -0
- claude_mpm/d2/package.json +19 -0
- claude_mpm/d2/src/App.svelte +110 -0
- claude_mpm/d2/src/components/Header.svelte +153 -0
- claude_mpm/d2/src/components/MainContent.svelte +74 -0
- claude_mpm/d2/src/components/Sidebar.svelte +85 -0
- claude_mpm/d2/src/components/tabs/EventsTab.svelte +326 -0
- claude_mpm/d2/src/lib/socketio.js +144 -0
- claude_mpm/d2/src/main.js +7 -0
- claude_mpm/d2/src/stores/events.js +114 -0
- claude_mpm/d2/src/stores/socket.js +108 -0
- claude_mpm/d2/src/stores/theme.js +65 -0
- claude_mpm/d2/svelte.config.js +12 -0
- claude_mpm/d2/vite.config.js +15 -0
- claude_mpm/dashboard/.claude-mpm/memories/README.md +36 -0
- claude_mpm/dashboard/BUILD_NUMBER +1 -0
- claude_mpm/dashboard/README.md +121 -0
- claude_mpm/dashboard/VERSION +1 -0
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +273 -0
- claude_mpm/dashboard/react/components/ErrorBoundary.tsx +75 -0
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +141 -0
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +36 -0
- claude_mpm/dashboard/react/components/shared/FilterBar.tsx +89 -0
- claude_mpm/dashboard/react/contexts/DashboardContext.tsx +215 -0
- claude_mpm/dashboard/react/entries/events.tsx +165 -0
- claude_mpm/dashboard/react/hooks/useEvents.ts +191 -0
- claude_mpm/dashboard/react/hooks/useSocket.ts +225 -0
- claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +170 -0
- claude_mpm/dashboard/static/built/components/activity-tree.js.map +1 -0
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +101 -101
- claude_mpm/dashboard/static/built/components/agent-inference.js.map +1 -0
- claude_mpm/dashboard/static/built/components/build-tracker.js +59 -59
- claude_mpm/dashboard/static/built/components/code-simple.js +107 -107
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +29 -29
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +24 -24
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +27 -27
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +25 -25
- claude_mpm/dashboard/static/built/components/code-tree.js.map +1 -0
- claude_mpm/dashboard/static/built/components/code-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/connection-debug.js +101 -101
- claude_mpm/dashboard/static/built/components/diff-viewer.js +113 -113
- claude_mpm/dashboard/static/built/components/event-processor.js.map +1 -0
- claude_mpm/dashboard/static/built/components/event-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/export-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +57 -57
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +74 -74
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js.map +1 -0
- claude_mpm/dashboard/static/built/components/file-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +1 -0
- claude_mpm/dashboard/static/built/components/hud-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/module-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/session-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/socket-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +1 -0
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +1 -0
- claude_mpm/dashboard/static/built/components/working-directory.js.map +1 -0
- claude_mpm/dashboard/static/built/connection-manager.js +76 -76
- claude_mpm/dashboard/static/built/dashboard.js.map +1 -0
- claude_mpm/dashboard/static/built/extension-error-handler.js +22 -22
- claude_mpm/dashboard/static/built/react/events.js.map +1 -0
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +9 -9
- claude_mpm/dashboard/static/built/shared/event-bus.js +5 -5
- claude_mpm/dashboard/static/built/shared/logger.js +16 -16
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +6 -6
- claude_mpm/dashboard/static/built/socket-client.js.map +1 -0
- claude_mpm/dashboard/static/css/activity.css +69 -69
- claude_mpm/dashboard/static/css/connection-status.css +10 -10
- claude_mpm/dashboard/static/css/dashboard.css +15 -15
- claude_mpm/dashboard/static/index.html +22 -22
- claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +170 -0
- claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
- claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
- claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
- claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
- claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
- claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
- claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
- claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
- claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
- claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
- claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
- claude_mpm/dashboard/static/js/connection-manager.js +76 -76
- claude_mpm/dashboard/static/js/dashboard.js +76 -58
- claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +9 -9
- claude_mpm/dashboard/static/js/shared/event-bus.js +5 -5
- claude_mpm/dashboard/static/js/shared/logger.js +16 -16
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +6 -6
- claude_mpm/dashboard/static/js/socket-client.js +138 -121
- claude_mpm/dashboard/static/navigation-test-results.md +118 -0
- claude_mpm/dashboard/static/production/main.html +21 -21
- claude_mpm/dashboard/static/test-archive/dashboard.html +22 -22
- claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +36 -0
- claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +39 -0
- claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +38 -0
- claude_mpm/dashboard/templates/code_simple.html +23 -23
- claude_mpm/dashboard/templates/index.html +18 -18
- claude_mpm/hooks/README.md +143 -0
- claude_mpm/hooks/__init__.py +8 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
- claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
- claude_mpm/hooks/claude_hooks/installer.py +45 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/hooks/templates/README.md +180 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/templates/settings.json.example +147 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/schemas/agent_schema.json +596 -0
- claude_mpm/schemas/frontmatter_schema.json +165 -0
- claude_mpm/scripts/claude-hook-handler.sh +3 -3
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/agents/auto_config_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +8 -8
- claude_mpm/services/agents/local_template_manager.py +4 -2
- claude_mpm/services/agents/recommender.py +47 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +87 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
- claude_mpm/services/core/base.py +26 -11
- claude_mpm/services/core/interfaces.py +56 -1
- claude_mpm/services/core/models/agent_config.py +3 -0
- claude_mpm/services/core/models/process.py +4 -0
- claude_mpm/services/core/path_resolver.py +1 -1
- claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
- claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
- claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
- claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
- claude_mpm/services/diagnostics/doctor_reporter.py +6 -4
- claude_mpm/services/diagnostics/models.py +21 -0
- claude_mpm/services/event_bus/README.md +244 -0
- claude_mpm/services/event_bus/direct_relay.py +3 -3
- claude_mpm/services/event_bus/event_bus.py +36 -3
- claude_mpm/services/event_bus/relay.py +23 -7
- claude_mpm/services/events/README.md +303 -0
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/framework_claude_md_generator/README.md +119 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +2 -0
- claude_mpm/services/local_ops/process_manager.py +1 -1
- claude_mpm/services/local_ops/resource_monitor.py +2 -2
- claude_mpm/services/mcp_config_manager.py +7 -131
- claude_mpm/services/mcp_gateway/README.md +185 -0
- claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
- claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
- claude_mpm/services/mcp_gateway/core/process_pool.py +19 -10
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
- claude_mpm/services/memory/failure_tracker.py +19 -4
- claude_mpm/services/memory/optimizer.py +1 -1
- claude_mpm/services/model/model_router.py +8 -9
- claude_mpm/services/monitor/daemon.py +1 -1
- claude_mpm/services/monitor/server.py +2 -2
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/port_manager.py +1 -1
- claude_mpm/services/project/documentation_manager.py +2 -1
- claude_mpm/services/project/toolchain_analyzer.py +3 -1
- claude_mpm/services/runner_configuration_service.py +1 -0
- claude_mpm/services/self_upgrade_service.py +165 -7
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +955 -0
- claude_mpm/services/socketio/handlers/connection.py +1 -1
- claude_mpm/services/socketio/handlers/connection.py.backup +217 -0
- claude_mpm/services/socketio/handlers/git.py +2 -2
- claude_mpm/services/socketio/handlers/hook.py.backup +154 -0
- claude_mpm/services/static/.gitkeep +2 -0
- claude_mpm/services/system_instructions_service.py +1 -3
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
- claude_mpm/services/unified/deployment_strategies/local.py +1 -1
- claude_mpm/services/version_control/VERSION +1 -0
- claude_mpm/services/version_control/conflict_resolution.py +6 -4
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/.gitkeep +2 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/find-polluter.sh +63 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +54 -0
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +322 -0
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/example_evaluation.xml +22 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +2 -0
- claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +573 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +158 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/LICENSE.txt +202 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +97 -9
- claude_mpm/skills/skills_registry.py +347 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/templates/questions/EXAMPLES.md +501 -0
- claude_mpm/templates/questions/__init__.py +43 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +314 -0
- claude_mpm/templates/questions/project_init.py +388 -0
- claude_mpm/templates/questions/ticket_mgmt.py +397 -0
- claude_mpm/tools/README_SOCKETIO_DEBUG.md +224 -0
- claude_mpm/tools/__main__.py +8 -8
- claude_mpm/tools/code_tree_analyzer/README.md +64 -0
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/utils/agent_dependency_loader.py +5 -5
- claude_mpm/utils/dependency_cache.py +3 -1
- claude_mpm/utils/gitignore.py +241 -0
- claude_mpm/utils/log_cleanup.py +3 -3
- claude_mpm/utils/robust_installer.py +3 -5
- claude_mpm/utils/structured_questions.py +619 -0
- claude_mpm-4.25.10.dist-info/METADATA +789 -0
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/RECORD +485 -240
- claude_mpm/agents/INSTRUCTIONS_OLD_DEPRECATED.md +0 -602
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
- claude_mpm/cli/commands/mpm_init.py +0 -2008
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
- claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
- claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
- claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
- claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
- claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
- claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/dist/dashboard.js +0 -2
- claude_mpm/dashboard/static/dist/react/events.js +0 -30
- claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
- claude_mpm/tools/code_tree_analyzer.py +0 -1825
- claude_mpm-4.16.0.dist-info/METADATA +0 -453
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/WHEEL +0 -0
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unified-data-viewer.js","sources":["../../js/components/unified-data-viewer.js"],"sourcesContent":["/**\n * Unified Data Viewer Component\n * \n * Consolidates all data formatting and display logic from event-driven tabs\n * (Activity, Events, Agents) into a single, reusable component.\n * \n * WHY: Eliminates code duplication across multiple components and provides\n * consistent data display formatting throughout the dashboard.\n * \n * DESIGN DECISION: Auto-detects data type and applies appropriate formatting,\n * while allowing manual type specification for edge cases.\n */\n\nclass UnifiedDataViewer {\n constructor(containerId = 'module-data-content') {\n this.container = document.getElementById(containerId);\n this.currentData = null;\n this.currentType = null;\n \n // Global JSON visibility state - synchronized with localStorage\n // This ensures all JSON sections maintain consistent state\n this.globalJsonExpanded = localStorage.getItem('dashboard-json-expanded') === 'true';\n \n // Separate state for \"Full Event Data\" sections - uses its own localStorage key\n // This allows independent control of Full Event Data visibility\n this.fullEventDataExpanded = localStorage.getItem('dashboard-full-event-expanded') === 'true';\n \n // Listen for global JSON toggle changes from other components\n document.addEventListener('jsonToggleChanged', (e) => {\n this.globalJsonExpanded = e.detail.expanded;\n this.updateAllJsonSections();\n });\n \n // Listen for full event data toggle changes\n document.addEventListener('fullEventToggleChanged', (e) => {\n this.fullEventDataExpanded = e.detail.expanded;\n this.updateAllFullEventSections();\n });\n }\n\n /**\n * Main display method - auto-detects type and renders data\n * @param {Object|Array} data - Data to display\n * @param {string|null} type - Optional type override\n */\n display(data, type = null) {\n if (!this.container) {\n console.warn('UnifiedDataViewer: Container not found');\n return;\n }\n\n // Store current data for reference\n this.currentData = data;\n this.currentType = type;\n\n // Auto-detect type if not provided\n if (!type) {\n type = this.detectType(data);\n }\n\n // Clear container\n this.container.innerHTML = '';\n\n // Display based on type\n switch(type) {\n case 'event':\n this.displayEvent(data);\n break;\n case 'agent':\n this.displayAgent(data);\n break;\n case 'tool':\n this.displayTool(data);\n break;\n case 'todo':\n this.displayTodo(data);\n break;\n case 'instruction':\n this.displayInstruction(data);\n break;\n case 'session':\n this.displaySession(data);\n break;\n case 'file_operation':\n // Convert file tool to file operation format if needed\n if (data.name && (data.params || data.tool_parameters)) {\n const convertedData = this.convertToolToFileOperation(data);\n this.displayFileOperation(convertedData);\n } else {\n this.displayFileOperation(data);\n }\n break;\n case 'hook':\n this.displayHook(data);\n break;\n default:\n this.displayGeneric(data);\n }\n }\n\n /**\n * Auto-detect data type based on object properties\n * @param {Object} data - Data to analyze\n * @returns {string} Detected type\n */\n detectType(data) {\n if (!data || typeof data !== 'object') return 'generic';\n\n // Event detection\n if (data.hook_event_name || data.event_type || (data.type && data.timestamp)) {\n return 'event';\n }\n\n // Agent detection \n if (data.agent_name || data.agentName || \n (data.name && (data.status === 'active' || data.status === 'completed'))) {\n return 'agent';\n }\n\n // Tool detection - PRIORITY: Check if it's a tool first\n // This includes TodoWrite tools which should always be displayed as tools, not todos\n if (data.tool_name || data.name === 'TodoWrite' || data.name === 'Read' || \n data.tool_parameters || (data.params && data.icon) || \n (data.name && data.type === 'tool')) {\n return 'tool';\n }\n\n // Todo detection - Only for standalone todo lists, not tool todos\n if (data.todos && !data.name && !data.params) {\n return 'todo';\n }\n\n // Single todo item detection\n if (data.content && data.activeForm && data.status && !data.name && !data.params) {\n return 'todo';\n }\n\n // Instruction detection\n if (data.text && data.preview && data.type === 'user_instruction') {\n return 'instruction';\n }\n\n // Session detection\n if (data.session_id && (data.startTime || data.lastActivity)) {\n return 'session';\n }\n\n // File operation detection\n if (data.file_path && (data.operations || data.operation)) {\n return 'file_operation';\n }\n\n // File tool detection - handle file tools as file operations when they have file_path\n if ((data.name === 'Read' || data.name === 'Write' || data.name === 'Edit' || \n data.name === 'MultiEdit' || data.name === 'Grep' || data.name === 'Glob') &&\n (data.params?.file_path || data.tool_parameters?.file_path)) {\n // Convert file tool to file operation format for better display\n return 'file_operation';\n }\n\n // Hook detection\n if (data.event_type && (data.hook_name || data.subtype)) {\n return 'hook';\n }\n\n return 'generic';\n }\n\n /**\n * Display event data with comprehensive formatting\n * PRIMARY: Event type, timestamp, and key details\n * SECONDARY: Full event data in collapsible JSON\n */\n displayEvent(data) {\n const eventType = this.formatEventType(data);\n const timestamp = this.formatTimestamp(data.timestamp);\n \n let html = `\n <div class=\"unified-viewer-header\">\n <h6>${eventType}</h6>\n <span class=\"unified-viewer-timestamp\">${timestamp}</span>\n </div>\n <div class=\"unified-viewer-content\">\n `;\n\n // PRIMARY DATA: Event-specific key details\n html += `<div class=\"primary-data\">`;\n html += this.formatEventDetails(data);\n \n // Show important tool parameters inline if present\n if (data.tool_name || data.data?.tool_name) {\n const toolName = data.tool_name || data.data.tool_name;\n html += `\n <div class=\"detail-row highlight\">\n <span class=\"detail-label\">Tool:</span>\n <span class=\"detail-value\">${this.getToolIcon(toolName)} ${toolName}</span>\n </div>\n `;\n \n // Show key parameters for specific tools\n const params = data.tool_parameters || data.data?.tool_parameters;\n if (params) {\n if (params.file_path) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">File:</span>\n <span class=\"detail-value code\">${params.file_path}</span>\n </div>\n `;\n }\n if (params.command) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Command:</span>\n <pre class=\"code-snippet\">${this.escapeHtml(params.command)}</pre>\n </div>\n `;\n }\n }\n }\n html += `</div>`;\n\n // SECONDARY DATA: Collapsible JSON viewer for full event data\n html += this.createCollapsibleJSON(data, 'Full Event Data');\n\n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display agent data with full details\n * PRIMARY: Agent status, active tools, and key info\n * SECONDARY: Full agent data in collapsible JSON\n */\n displayAgent(data) {\n const agentIcon = this.getAgentIcon(data.name || data.agentName);\n const agentName = data.name || data.agentName || 'Unknown Agent';\n const status = this.formatStatus(data.status);\n \n let html = `\n <div class=\"unified-viewer-header\">\n <h6>${agentIcon} ${agentName}</h6>\n <span class=\"unified-viewer-status\">${status}</span>\n </div>\n <div class=\"unified-viewer-content\">\n `;\n\n // PRIMARY DATA: Key agent information\n html += `<div class=\"primary-data\">`;\n \n // Status with visual indicator\n html += `\n <div class=\"detail-row highlight\">\n <span class=\"detail-label\">Status:</span>\n <span class=\"detail-value ${this.formatStatusClass(status)}\">${status}</span>\n </div>\n `;\n\n // Tools summary if present\n if (data.tools && data.tools.length > 0) {\n // Show active tools prominently\n const activeTools = data.tools.filter(t => t.status === 'in_progress');\n const completedTools = data.tools.filter(t => t.status === 'completed');\n \n if (activeTools.length > 0) {\n html += `\n <div class=\"active-tools-section\">\n <span class=\"section-label\">🔄 Active Tools:</span>\n <div class=\"tools-grid\">\n `;\n activeTools.forEach(tool => {\n html += `\n <div class=\"tool-chip active\">\n ${this.getToolIcon(tool.name)} ${tool.name}\n </div>\n `;\n });\n html += `</div></div>`;\n }\n \n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Tools Summary:</span>\n <span class=\"detail-value\">\n ${activeTools.length} active, ${completedTools.length} completed, ${data.tools.length} total\n </span>\n </div>\n `;\n }\n\n // Current task if available\n if (data.currentTask || data.description) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Current Task:</span>\n <span class=\"detail-value\">${data.currentTask || data.description}</span>\n </div>\n `;\n }\n \n html += `</div>`;\n\n // SECONDARY DATA: Collapsible JSON viewer\n html += this.createCollapsibleJSON(data, 'Full Agent Details');\n\n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display tool data with parameters and results\n * Special handling for TodoWrite to show todos prominently\n */\n displayTool(data) {\n const toolName = data.name || data.tool_name || 'Unknown Tool';\n const toolIcon = this.getToolIcon(toolName);\n const status = this.formatStatus(data.status);\n \n // Special handling for TodoWrite tool\n if (toolName === 'TodoWrite') {\n this.displayTodoWriteTool(data);\n return;\n }\n \n let html = `\n <div class=\"unified-viewer-header\">\n <h6>${toolIcon} ${toolName}</h6>\n <span class=\"unified-viewer-status\">${status}</span>\n </div>\n <div class=\"unified-viewer-content\">\n `;\n\n // PRIMARY DATA: Show important tool-specific information first\n const params = data.params || data.tool_parameters || {};\n \n // Tool-specific primary data display\n if (toolName === 'Read' || toolName === 'Edit' || toolName === 'Write') {\n // File tools - show file path prominently\n if (params.file_path) {\n html += `\n <div class=\"primary-data\">\n <div class=\"detail-row highlight\">\n <span class=\"detail-label\">📁 File:</span>\n <span class=\"detail-value code\">${params.file_path}</span>\n </div>\n `;\n if (params.old_string) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Old Text:</span>\n <pre class=\"code-snippet\">${this.escapeHtml(params.old_string.substring(0, 200))}${params.old_string.length > 200 ? '...' : ''}</pre>\n </div>\n `;\n }\n if (params.new_string) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">New Text:</span>\n <pre class=\"code-snippet\">${this.escapeHtml(params.new_string.substring(0, 200))}${params.new_string.length > 200 ? '...' : ''}</pre>\n </div>\n `;\n }\n html += '</div>';\n }\n } else if (toolName === 'Bash') {\n // Bash tool - show command prominently\n if (params.command) {\n html += `\n <div class=\"primary-data\">\n <div class=\"detail-row highlight\">\n <span class=\"detail-label\">💻 Command:</span>\n <pre class=\"code-snippet\">${this.escapeHtml(params.command)}</pre>\n </div>\n </div>\n `;\n }\n } else if (toolName === 'Grep' || toolName === 'Glob') {\n // Search tools - show pattern prominently\n if (params.pattern) {\n html += `\n <div class=\"primary-data\">\n <div class=\"detail-row highlight\">\n <span class=\"detail-label\">🔍 Pattern:</span>\n <span class=\"detail-value code\">${this.escapeHtml(params.pattern)}</span>\n </div>\n `;\n if (params.path) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Path:</span>\n <span class=\"detail-value\">${params.path}</span>\n </div>\n `;\n }\n html += '</div>';\n }\n } else if (toolName === 'Task') {\n // Task tool - show delegation info prominently\n if (params.subagent_type) {\n html += `\n <div class=\"primary-data\">\n <div class=\"detail-row highlight\">\n <span class=\"detail-label\">🤖 Delegating to:</span>\n <span class=\"detail-value\">${params.subagent_type} agent</span>\n </div>\n `;\n if (params.description) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Task:</span>\n <span class=\"detail-value\">${params.description}</span>\n </div>\n `;\n }\n html += '</div>';\n }\n }\n\n // Status and metadata\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Status:</span>\n <span class=\"detail-value\">${status}</span>\n </div>\n `;\n\n if (data.callCount) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Call Count:</span>\n <span class=\"detail-value\">${data.callCount}</span>\n </div>\n `;\n }\n\n // Collapsible JSON viewer for full details\n html += this.createCollapsibleJSON(data, 'Full Tool Details');\n \n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display TodoWrite tool with todos list prominently after title\n */\n displayTodoWriteTool(data) {\n const status = this.formatStatus(data.status);\n const params = data.params || data.tool_parameters || {};\n const todos = params.todos || [];\n \n let html = `\n <div class=\"unified-viewer-header\">\n <h6>📝 TodoWrite</h6>\n <span class=\"unified-viewer-status\">${status}</span>\n </div>\n <div class=\"unified-viewer-content\">\n `;\n\n // PRIMARY DATA: Todo list and status summary immediately after title\n if (todos.length > 0) {\n const statusCounts = this.getTodoStatusCounts(todos);\n \n // Status summary - horizontal single line format\n html += `\n <div class=\"todo-status-line\">\n <span class=\"status-inline\">✅ ${statusCounts.completed} Done</span>\n <span class=\"status-inline\">🔄 ${statusCounts.in_progress} Active</span>\n <span class=\"status-inline\">⏳ ${statusCounts.pending} Pending</span>\n </div>\n `;\n\n // Todo items list\n html += `\n <div class=\"todo-list-primary\">\n `;\n \n todos.forEach((todo, index) => {\n const statusIcon = this.getCheckboxIcon(todo.status);\n const displayText = todo.status === 'in_progress' ? \n (todo.activeForm || todo.content) : todo.content;\n const statusClass = this.formatStatusClass(todo.status);\n \n html += `\n <div class=\"todo-item ${todo.status}\">\n <span class=\"todo-icon ${statusClass}\">${statusIcon}</span>\n <span class=\"todo-text\">${this.escapeHtml(displayText)}</span>\n ${todo.status === 'in_progress' ? '<span class=\"todo-badge active\">ACTIVE</span>' : ''}\n </div>\n `;\n });\n \n html += `\n </div>\n `;\n } else {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-value\">No todos in list</span>\n </div>\n `;\n }\n\n // Metadata section\n if (data.callCount && data.callCount > 1) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Updates:</span>\n <span class=\"detail-value\">${data.callCount}</span>\n </div>\n `;\n }\n\n // Collapsible JSON viewer for full details\n html += this.createCollapsibleJSON(data, 'Full Details');\n \n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display todo data with checklist formatting (for standalone todos, not TodoWrite)\n */\n displayTodo(data) {\n // Handle different data structures for standalone todos\n let todos;\n let toolName = 'Todo List';\n \n if (data.todos && Array.isArray(data.todos)) {\n todos = data.todos;\n } else if (Array.isArray(data)) {\n todos = data;\n } else if (data.content && data.activeForm && data.status) {\n todos = [data];\n } else {\n todos = [];\n }\n \n let html = `\n <div class=\"unified-viewer-header\">\n <h6>📋 ${toolName}</h6>\n </div>\n <div class=\"unified-viewer-content\">\n `;\n\n if (todos.length > 0) {\n // Show todos immediately\n html += `\n <div class=\"todo-list-primary\">\n `;\n \n todos.forEach((todo) => {\n const statusIcon = this.getCheckboxIcon(todo.status);\n const displayText = todo.status === 'in_progress' ? \n (todo.activeForm || todo.content) : todo.content;\n const statusClass = this.formatStatusClass(todo.status);\n \n html += `\n <div class=\"todo-item ${todo.status}\">\n <span class=\"todo-icon ${statusClass}\">${statusIcon}</span>\n <span class=\"todo-text\">${this.escapeHtml(displayText)}</span>\n <span class=\"todo-status-text ${statusClass}\">${todo.status.replace('_', ' ')}</span>\n </div>\n `;\n });\n \n html += `\n </div>\n `;\n } else {\n html += `\n <div class=\"detail-section\">\n <div class=\"no-todos\">No todo items found</div>\n </div>\n `;\n }\n\n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display instruction data\n * PRIMARY: Instruction text prominently displayed\n * SECONDARY: Metadata in collapsible section\n */\n displayInstruction(data) {\n let html = `\n <div class=\"unified-viewer-header\">\n <h6>💬 User Instruction</h6>\n <span class=\"unified-viewer-timestamp\">${this.formatTimestamp(data.timestamp)}</span>\n </div>\n <div class=\"unified-viewer-content\">\n `;\n \n // PRIMARY DATA: The instruction text itself\n html += `\n <div class=\"primary-data\">\n <div class=\"instruction-content\">\n ${this.escapeHtml(data.text)}\n </div>\n <div class=\"instruction-meta\">\n <span class=\"meta-item\">📏 ${data.text.length} characters</span>\n <span class=\"meta-item\">🕐 ${this.formatTimestamp(data.timestamp)}</span>\n </div>\n </div>\n `;\n\n // SECONDARY DATA: Full instruction object if there's more data\n if (Object.keys(data).length > 3) {\n html += this.createCollapsibleJSON(data, 'Full Instruction Data');\n }\n \n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display session data\n */\n displaySession(data) {\n let html = `\n <div class=\"unified-viewer-header\">\n <h6>🎯 Session: ${data.session_id || data.id}</h6>\n <span class=\"unified-viewer-status\">${this.formatStatus(data.status || 'active')}</span>\n </div>\n <div class=\"unified-viewer-content\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Session ID:</span>\n <span class=\"detail-value\">${data.session_id || data.id}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Start Time:</span>\n <span class=\"detail-value\">${this.formatTimestamp(data.startTime || data.timestamp)}</span>\n </div>\n `;\n\n if (data.working_directory) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Working Directory:</span>\n <span class=\"detail-value\">${data.working_directory}</span>\n </div>\n `;\n }\n\n if (data.git_branch) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Git Branch:</span>\n <span class=\"detail-value\">${data.git_branch}</span>\n </div>\n `;\n }\n\n if (data.eventCount !== undefined) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Events:</span>\n <span class=\"detail-value\">${data.eventCount}</span>\n </div>\n `;\n }\n\n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display file operation data with enhanced file viewing capabilities\n */\n displayFileOperation(data) {\n const fileName = data.file_path ? data.file_path.split('/').pop() : 'Unknown File';\n const isSingleFile = this.isSingleFileOperation(data);\n const fileIcon = this.getFileIcon(data.file_path);\n const fileType = this.getFileType(data.file_path);\n \n let html = `\n <div class=\"unified-viewer-header ${isSingleFile ? 'single-file-header' : ''}\">\n <h6>${fileIcon} File: ${fileName}</h6>\n <span class=\"unified-viewer-count\">${data.operations ? data.operations.length : 1} operation${data.operations && data.operations.length !== 1 ? 's' : ''}</span>\n ${fileType ? `<span class=\"file-type-badge\">${fileType}</span>` : ''}\n </div>\n <div class=\"unified-viewer-content\">\n <div class=\"primary-data\">\n <div class=\"detail-row highlight\">\n <span class=\"detail-label\">📁 File Path:</span>\n <span class=\"detail-value code clickable-file-path\" \n onclick=\"window.showFileViewerModal && window.showFileViewerModal('${data.file_path}')\"\n title=\"Click to view file contents\\\\nKeyboard: Hover + V key or Ctrl/Cmd + Click\\\\nFile: ${data.file_path}\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Open file ${data.file_path} in viewer\"\n onkeypress=\"if(event.key==='Enter'||event.key===' '){window.showFileViewerModal && window.showFileViewerModal('${data.file_path}')}\">${data.file_path}</span>\n </div>\n `;\n\n // Enhanced file viewing for single file operations\n if (data.file_path) {\n const shouldShowPreview = this.shouldShowInlinePreview(data);\n \n html += `\n <div class=\"file-actions ${isSingleFile ? 'single-file-actions' : ''}\">\n <button class=\"file-action-btn view-file-btn ${isSingleFile ? 'primary-action' : ''}\" \n onclick=\"window.showFileViewerModal && window.showFileViewerModal('${data.file_path}')\"\n title=\"View file contents with syntax highlighting\">\n ${fileIcon} View File Contents\n </button>\n ${isSingleFile && this.isTextFile(data.file_path) ? `\n <button class=\"file-action-btn inline-preview-btn\" \n onclick=\"window.unifiedDataViewer && window.unifiedDataViewer.toggleInlinePreview('${data.file_path}', this)\"\n title=\"Toggle inline preview\">\n 📖 Quick Preview\n </button>\n ` : ''}\n </div>\n `;\n \n // Add inline preview container for single file operations\n if (isSingleFile && shouldShowPreview) {\n const previewId = this.generatePreviewId(data.file_path);\n html += `\n <div class=\"inline-preview-container\" id=\"preview-${previewId}\" style=\"display: none;\">\n <div class=\"inline-preview-loading\">Loading preview...</div>\n </div>\n `;\n }\n }\n\n html += `</div>`;\n\n if (data.operations && Array.isArray(data.operations)) {\n html += `\n <div class=\"detail-section\">\n <span class=\"detail-section-title\">Operations (${data.operations.length}):</span>\n <div class=\"operations-list\">\n ${data.operations.map((op, index) => `\n <div class=\"operation-item\">\n <div class=\"operation-header\">\n <span class=\"operation-type\">${this.getOperationIcon(op.operation)} ${op.operation}</span>\n <span class=\"operation-timestamp\">${this.formatTimestamp(op.timestamp)}</span>\n </div>\n <div class=\"operation-details\">\n <span class=\"operation-agent\">by ${op.agent || 'Unknown'}</span>\n ${op.workingDirectory ? `<span class=\"operation-dir\">in ${op.workingDirectory}</span>` : ''}\n </div>\n </div>\n `).join('')}\n </div>\n </div>\n `;\n }\n\n // Add collapsible JSON viewer for full file data\n html += this.createCollapsibleJSON(data, 'Full File Data');\n\n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display hook event data\n */\n displayHook(data) {\n const hookType = data.event_type || data.subtype || 'unknown';\n \n let html = `\n <div class=\"unified-viewer-header\">\n <h6>🔗 Hook: ${hookType}</h6>\n <span class=\"unified-viewer-timestamp\">${this.formatTimestamp(data.timestamp)}</span>\n </div>\n <div class=\"unified-viewer-content\">\n `;\n\n html += this.formatHookDetails(data);\n html += '</div>';\n this.container.innerHTML = html;\n }\n\n /**\n * Display generic data with fallback formatting\n */\n displayGeneric(data) {\n let html = `\n <div class=\"unified-viewer-header\">\n <h6>📊 Data Details</h6>\n ${data.timestamp ? `<span class=\"unified-viewer-timestamp\">${this.formatTimestamp(data.timestamp)}</span>` : ''}\n </div>\n <div class=\"unified-viewer-content\">\n `;\n\n if (typeof data === 'object' && data !== null) {\n // Display meaningful properties\n const meaningfulProps = ['id', 'name', 'type', 'status', 'timestamp', 'text', 'content', 'message'];\n \n for (let prop of meaningfulProps) {\n if (data[prop] !== undefined) {\n let value = data[prop];\n if (typeof value === 'string' && value.length > 200) {\n value = value.substring(0, 200) + '...';\n }\n \n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">${prop}:</span>\n <span class=\"detail-value\">${this.escapeHtml(String(value))}</span>\n </div>\n `;\n }\n }\n } else {\n html += `<div class=\"simple-value\">${this.escapeHtml(String(data))}</div>`;\n }\n\n html += '</div>';\n this.container.innerHTML = html;\n }\n\n // ==================== FORMATTING UTILITIES ====================\n\n /**\n * Format event type for display\n */\n formatEventType(event) {\n if (event.type && event.subtype) {\n if (event.type === event.subtype || event.subtype === 'generic') {\n return event.type;\n }\n return `${event.type}.${event.subtype}`;\n }\n if (event.type) return event.type;\n if (event.hook_event_name) return event.hook_event_name;\n return 'unknown';\n }\n\n /**\n * Format detailed event data based on type\n */\n formatEventDetails(event) {\n const data = event.data || {};\n \n switch (event.type) {\n case 'hook':\n return this.formatHookDetails(event);\n case 'agent':\n return this.formatAgentEventDetails(event);\n case 'todo':\n return this.formatTodoEventDetails(event);\n case 'session':\n return this.formatSessionEventDetails(event);\n default:\n return this.formatGenericEventDetails(event);\n }\n }\n\n /**\n * Format hook event details\n */\n formatHookDetails(event) {\n const data = event.data || {};\n const hookType = event.subtype || event.event_type || 'unknown';\n \n let html = `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Hook Type:</span>\n <span class=\"detail-value\">${hookType}</span>\n </div>\n `;\n\n switch (hookType) {\n case 'user_prompt':\n const prompt = data.prompt_text || data.prompt_preview || '';\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Prompt:</span>\n <div class=\"detail-value prompt-text\">${this.escapeHtml(prompt)}</div>\n </div>\n `;\n break;\n\n case 'pre_tool':\n case 'post_tool':\n const toolName = data.tool_name || 'Unknown tool';\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Tool:</span>\n <span class=\"detail-value\">${toolName}</span>\n </div>\n `;\n if (data.operation_type) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Operation:</span>\n <span class=\"detail-value\">${data.operation_type}</span>\n </div>\n `;\n }\n if (hookType === 'post_tool' && data.duration_ms) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Duration:</span>\n <span class=\"detail-value\">${data.duration_ms}ms</span>\n </div>\n `;\n }\n break;\n\n case 'subagent_start':\n case 'subagent_stop':\n const agentType = data.agent_type || data.agent || 'Unknown';\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Agent:</span>\n <span class=\"detail-value\">${agentType}</span>\n </div>\n `;\n if (hookType === 'subagent_start' && data.prompt) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Task:</span>\n <div class=\"detail-value\">${this.escapeHtml(data.prompt)}</div>\n </div>\n `;\n }\n if (hookType === 'subagent_stop' && data.reason) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Reason:</span>\n <span class=\"detail-value\">${data.reason}</span>\n </div>\n `;\n }\n break;\n }\n\n return html;\n }\n\n /**\n * Format agent event details\n */\n formatAgentEventDetails(event) {\n const data = event.data || {};\n let html = '';\n\n if (data.agent_type || data.name) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Agent Type:</span>\n <span class=\"detail-value\">${data.agent_type || data.name}</span>\n </div>\n `;\n }\n\n if (event.subtype) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Action:</span>\n <span class=\"detail-value\">${event.subtype}</span>\n </div>\n `;\n }\n\n return html;\n }\n\n /**\n * Format todo event details\n */\n formatTodoEventDetails(event) {\n const data = event.data || {};\n let html = '';\n\n if (data.todos && Array.isArray(data.todos)) {\n const statusCounts = this.getTodoStatusCounts(data.todos);\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Todo Items:</span>\n <span class=\"detail-value\">${data.todos.length} total</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Status:</span>\n <span class=\"detail-value\">${statusCounts.completed} completed, ${statusCounts.in_progress} in progress</span>\n </div>\n `;\n }\n\n return html;\n }\n\n /**\n * Format session event details\n */\n formatSessionEventDetails(event) {\n const data = event.data || {};\n let html = '';\n\n if (data.session_id) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Session ID:</span>\n <span class=\"detail-value\">${data.session_id}</span>\n </div>\n `;\n }\n\n if (event.subtype) {\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">Action:</span>\n <span class=\"detail-value\">${event.subtype}</span>\n </div>\n `;\n }\n\n return html;\n }\n\n /**\n * Format generic event details\n */\n formatGenericEventDetails(event) {\n const data = event.data || {};\n let html = '';\n\n // Show basic data properties\n const basicProps = ['message', 'description', 'value', 'result'];\n for (let prop of basicProps) {\n if (data[prop] !== undefined) {\n let value = data[prop];\n if (typeof value === 'string' && value.length > 200) {\n value = value.substring(0, 200) + '...';\n }\n html += `\n <div class=\"detail-row\">\n <span class=\"detail-label\">${prop}:</span>\n <span class=\"detail-value\">${this.escapeHtml(String(value))}</span>\n </div>\n `;\n }\n }\n\n return html;\n }\n\n /**\n * Format event data section\n */\n formatEventData(event) {\n const data = event.data;\n if (!data || Object.keys(data).length === 0) return '';\n \n return `\n <div class=\"detail-section\">\n <span class=\"detail-section-title\">Event Data:</span>\n <pre class=\"event-data-json\">${this.escapeHtml(JSON.stringify(data, null, 2))}</pre>\n </div>\n `;\n }\n\n /**\n * Format tool/event parameters\n */\n formatParameters(params, title = 'Parameters') {\n if (!params || Object.keys(params).length === 0) {\n return `\n <div class=\"detail-section\">\n <span class=\"detail-section-title\">${title}:</span>\n <div class=\"no-params\">No parameters</div>\n </div>\n `;\n }\n\n const paramKeys = Object.keys(params);\n return `\n <div class=\"detail-section\">\n <span class=\"detail-section-title\">${title} (${paramKeys.length}):</span>\n <div class=\"params-list\">\n ${paramKeys.map(key => {\n const value = params[key];\n const displayValue = this.formatParameterValue(value);\n return `\n <div class=\"param-item\">\n <div class=\"param-key\">${key}:</div>\n <div class=\"param-value\">${displayValue}</div>\n </div>\n `;\n }).join('')}\n </div>\n </div>\n `;\n }\n\n /**\n * Format parameter value with appropriate styling\n */\n formatParameterValue(value) {\n if (typeof value === 'string') {\n if (value.length > 500) {\n return `<pre class=\"param-text-long\">${this.escapeHtml(value.substring(0, 500) + '...\\n\\n[Content truncated - ' + value.length + ' total characters]')}</pre>`;\n } else if (value.length > 100) {\n return `<pre class=\"param-text\">${this.escapeHtml(value)}</pre>`;\n } else {\n return `<span class=\"param-text-short\">${this.escapeHtml(value)}</span>`;\n }\n } else if (typeof value === 'object' && value !== null) {\n // Special handling for todos array - display as formatted list instead of raw JSON\n if (Array.isArray(value) && value.length > 0 && \n value[0].hasOwnProperty('content') && value[0].hasOwnProperty('status')) {\n return this.formatTodosAsParameter(value);\n }\n \n try {\n return `<pre class=\"param-json\">${this.escapeHtml(JSON.stringify(value, null, 2))}</pre>`;\n } catch (e) {\n return `<span class=\"param-error\">Error displaying object</span>`;\n }\n } else {\n return `<span class=\"param-primitive\">${this.escapeHtml(String(value))}</span>`;\n }\n }\n\n /**\n * Format todos array as a parameter value\n */\n formatTodosAsParameter(todos) {\n const statusCounts = this.getTodoStatusCounts(todos);\n \n let html = `\n <div class=\"param-todos\">\n <div class=\"param-todos-header\">\n Array of todo objects (${todos.length} items)\n </div>\n <div class=\"param-todos-summary\">\n ${statusCounts.completed} completed • ${statusCounts.in_progress} in progress • ${statusCounts.pending} pending\n </div>\n <div class=\"param-todos-list\">\n `;\n \n todos.forEach((todo, index) => {\n const statusIcon = this.getCheckboxIcon(todo.status);\n const displayText = todo.status === 'in_progress' ? \n (todo.activeForm || todo.content) : todo.content;\n const statusClass = this.formatStatusClass(todo.status);\n \n html += `\n <div class=\"param-todo-item ${todo.status}\">\n <div class=\"param-todo-checkbox\">\n <span class=\"param-checkbox-icon ${statusClass}\">${statusIcon}</span>\n </div>\n <div class=\"param-todo-text\">\n <span class=\"param-todo-content\">${this.escapeHtml(displayText)}</span>\n <span class=\"param-todo-status-badge ${statusClass}\">${todo.status.replace('_', ' ')}</span>\n </div>\n </div>\n `;\n });\n \n html += `\n </div>\n </div>\n `;\n \n return html;\n }\n\n // ==================== FILE OPERATION UTILITIES ====================\n\n /**\n * Determine if this is a single file operation\n */\n isSingleFileOperation(data) {\n // Single file if no operations array or only one operation\n if (!data.operations) return true;\n return data.operations.length === 1;\n }\n\n /**\n * Get file icon based on file extension\n */\n getFileIcon(filePath) {\n if (!filePath) return '📄';\n \n const ext = filePath.split('.').pop()?.toLowerCase();\n const iconMap = {\n // Code files\n 'js': '🟨',\n 'jsx': '⚛️',\n 'ts': '🔷',\n 'tsx': '⚛️',\n 'py': '🐍',\n 'java': '☕',\n 'cpp': '⚡',\n 'c': '⚡',\n 'cs': '#️⃣',\n 'php': '🐘',\n 'rb': '💎',\n 'go': '🐹',\n 'rs': '🦀',\n 'swift': '🦉',\n 'kt': '🅺',\n 'scala': '🎯',\n \n // Web files\n 'html': '🌐',\n 'htm': '🌐',\n 'css': '🎨',\n 'scss': '🎨',\n 'sass': '🎨',\n 'less': '🎨',\n 'vue': '💚',\n \n // Config files\n 'json': '📋',\n 'xml': '📄',\n 'yaml': '⚙️',\n 'yml': '⚙️',\n 'toml': '⚙️',\n 'ini': '⚙️',\n 'conf': '⚙️',\n 'config': '⚙️',\n \n // Documentation\n 'md': '📝',\n 'txt': '📃',\n 'rtf': '📃',\n 'pdf': '📕',\n 'doc': '📘',\n 'docx': '📘',\n \n // Images\n 'jpg': '🖼️',\n 'jpeg': '🖼️',\n 'png': '🖼️',\n 'gif': '🖼️',\n 'svg': '🎨',\n 'webp': '🖼️',\n 'ico': '🖼️',\n \n // Archives\n 'zip': '🗜️',\n 'tar': '🗜️',\n 'gz': '🗜️',\n 'rar': '🗜️',\n '7z': '🗜️',\n \n // Other\n 'sql': '🗃️',\n 'db': '🗃️',\n 'log': '📊',\n 'env': '🔐',\n 'lock': '🔒'\n };\n \n return iconMap[ext] || '📄';\n }\n\n /**\n * Get file type description\n */\n getFileType(filePath) {\n if (!filePath) return null;\n \n const ext = filePath.split('.').pop()?.toLowerCase();\n const typeMap = {\n 'js': 'JavaScript',\n 'jsx': 'React JSX',\n 'ts': 'TypeScript',\n 'tsx': 'React TSX',\n 'py': 'Python',\n 'java': 'Java',\n 'cpp': 'C++',\n 'c': 'C',\n 'cs': 'C#',\n 'php': 'PHP',\n 'rb': 'Ruby',\n 'go': 'Go',\n 'rs': 'Rust',\n 'html': 'HTML',\n 'css': 'CSS',\n 'scss': 'SCSS',\n 'json': 'JSON',\n 'xml': 'XML',\n 'yaml': 'YAML',\n 'yml': 'YAML',\n 'md': 'Markdown',\n 'txt': 'Text',\n 'sql': 'SQL',\n 'log': 'Log File'\n };\n \n return typeMap[ext] || null;\n }\n\n /**\n * Check if file should show inline preview\n */\n shouldShowInlinePreview(data) {\n // Show preview for single file text operations\n return this.isSingleFileOperation(data) && this.isTextFile(data.file_path);\n }\n\n /**\n * Check if file is a text file suitable for preview\n */\n isTextFile(filePath) {\n if (!filePath) return false;\n \n const ext = filePath.split('.').pop()?.toLowerCase();\n const textExtensions = [\n 'txt', 'md', 'json', 'xml', 'yaml', 'yml', 'ini', 'conf', 'config',\n 'js', 'jsx', 'ts', 'tsx', 'py', 'java', 'cpp', 'c', 'cs', 'php', 'rb',\n 'go', 'rs', 'swift', 'kt', 'scala', 'html', 'htm', 'css', 'scss', 'sass',\n 'less', 'vue', 'sql', 'log', 'env', 'gitignore', 'dockerignore'\n ];\n \n return textExtensions.includes(ext);\n }\n\n /**\n * Toggle inline preview for a file\n */\n async toggleInlinePreview(filePath, buttonElement) {\n const containerId = `preview-${this.generatePreviewId(filePath)}`;\n const container = document.getElementById(containerId);\n \n if (!container) {\n console.warn('Preview container not found');\n return;\n }\n \n if (container.style.display === 'none') {\n // Show preview\n container.style.display = 'block';\n buttonElement.innerHTML = '📖 Hide Preview';\n await this.loadInlinePreview(filePath, container);\n } else {\n // Hide preview\n container.style.display = 'none';\n buttonElement.innerHTML = '📖 Quick Preview';\n }\n }\n\n /**\n * Load inline preview content\n */\n async loadInlinePreview(filePath, container) {\n try {\n // This would typically make an API call to get file contents\n // For now, show a placeholder\n container.innerHTML = `\n <div class=\"inline-preview-header\">\n <span class=\"preview-label\">Quick Preview:</span>\n <span class=\"preview-file\">${filePath}</span>\n </div>\n <div class=\"inline-preview-content\">\n <div class=\"preview-note\">\n 💡 Inline preview feature ready - API integration needed\n <br>Click \"View File Contents\" for full syntax-highlighted view\n </div>\n </div>\n `;\n } catch (error) {\n container.innerHTML = `\n <div class=\"inline-preview-error\">\n ❌ Could not load preview: ${error.message}\n </div>\n `;\n }\n }\n\n /**\n * Generate a unique ID for preview containers\n */\n generateId() {\n return Date.now().toString(36) + Math.random().toString(36).substr(2, 9);\n }\n\n /**\n * Generate preview ID based on file path\n */\n generatePreviewId(filePath) {\n return btoa(filePath).replace(/[^a-zA-Z0-9]/g, '');\n }\n\n // ==================== UTILITY METHODS ====================\n\n /**\n * Format timestamp for display\n */\n formatTimestamp(timestamp) {\n if (!timestamp) return 'Unknown time';\n \n try {\n const date = new Date(timestamp);\n if (isNaN(date.getTime())) return 'Invalid date';\n return date.toLocaleString();\n } catch (error) {\n return 'Invalid date';\n }\n }\n\n /**\n * Format status with appropriate styling\n */\n formatStatus(status) {\n if (!status) return 'unknown';\n \n const statusMap = {\n 'active': '🟢 Active',\n 'completed': '✅ Completed', \n 'in_progress': '🔄 In Progress',\n 'pending': '⏳ Pending',\n 'error': '❌ Error',\n 'failed': '❌ Failed'\n };\n \n return statusMap[status] || status;\n }\n\n /**\n * Get CSS class for status styling\n */\n formatStatusClass(status) {\n return `status-${status}`;\n }\n\n /**\n * Get icon for agent type\n */\n getAgentIcon(agentName) {\n const icons = {\n 'PM': '🎯',\n 'Engineer': '🔧',\n 'Engineer Agent': '🔧',\n 'Research': '🔍',\n 'Research Agent': '🔍',\n 'QA': '✅',\n 'QA Agent': '✅',\n 'Architect': '🏗️',\n 'Architect Agent': '🏗️',\n 'Ops': '⚙️',\n 'Ops Agent': '⚙️'\n };\n return icons[agentName] || '🤖';\n }\n\n /**\n * Get icon for tool type\n */\n getToolIcon(toolName) {\n const icons = {\n 'Read': '👁️',\n 'Write': '✍️', \n 'Edit': '✏️',\n 'MultiEdit': '📝',\n 'Bash': '💻',\n 'Grep': '🔍',\n 'Glob': '📂',\n 'LS': '📁',\n 'TodoWrite': '📝',\n 'Task': '📋',\n 'WebFetch': '🌐'\n };\n return icons[toolName] || '🔧';\n }\n\n /**\n * Get checkbox icon for todo status\n */\n getCheckboxIcon(status) {\n const icons = {\n 'pending': '⏳',\n 'in_progress': '🔄',\n 'completed': '✅'\n };\n return icons[status] || '❓';\n }\n\n /**\n * Get icon for file operation type\n */\n getOperationIcon(operation) {\n const icons = {\n 'read': '👁️',\n 'write': '✍️',\n 'edit': '✏️',\n 'delete': '🗑️',\n 'create': '📝',\n 'search': '🔍',\n 'list': '📂',\n 'copy': '📋',\n 'move': '📦',\n 'bash': '💻'\n };\n return icons[operation.toLowerCase()] || '📄';\n }\n\n /**\n * Convert tool data to file operation format for better display\n */\n convertToolToFileOperation(toolData) {\n const params = toolData.params || toolData.tool_parameters || {};\n const filePath = params.file_path || params.path || params.notebook_path;\n \n if (!filePath) {\n return toolData; // Return original if no file path\n }\n\n // Create file operation format\n const operation = {\n operation: toolData.name.toLowerCase(),\n timestamp: toolData.timestamp || new Date().toISOString(),\n agent: 'Activity Tool',\n sessionId: toolData.sessionId || 'unknown',\n details: {\n parameters: params,\n tool_name: toolData.name,\n status: toolData.status || 'completed'\n }\n };\n\n return {\n file_path: filePath,\n operations: [operation],\n lastOperation: operation.timestamp,\n // Preserve original tool data for reference\n originalTool: toolData\n };\n }\n\n /**\n * Get todo status counts\n */\n getTodoStatusCounts(todos) {\n const counts = { completed: 0, in_progress: 0, pending: 0 };\n \n todos.forEach(todo => {\n if (counts.hasOwnProperty(todo.status)) {\n counts[todo.status]++;\n }\n });\n \n return counts;\n }\n\n /**\n * Escape HTML for safe display\n */\n escapeHtml(text) {\n if (typeof text !== 'string') return '';\n \n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n \n /**\n * Toggle JSON section visibility and update global state\n * WHY: Maintains sticky state across all JSON sections for consistent behavior\n * @param {string} sectionId - ID of the specific section being toggled\n * @param {HTMLElement} button - The button element that was clicked\n */\n toggleJsonSection(sectionId, button) {\n // Toggle the global state\n this.globalJsonExpanded = !this.globalJsonExpanded;\n \n // Persist the preference to localStorage\n localStorage.setItem('dashboard-json-expanded', this.globalJsonExpanded.toString());\n \n // Update ALL JSON sections on the page\n this.updateAllJsonSections();\n \n // Dispatch event to notify other components (like module-viewer) of the change\n document.dispatchEvent(new CustomEvent('jsonToggleChanged', {\n detail: { expanded: this.globalJsonExpanded }\n }));\n }\n \n /**\n * Toggle Full Event Data section visibility and update state\n * WHY: Maintains separate sticky state for Full Event Data sections\n * @param {string} sectionId - ID of the specific section being toggled\n * @param {HTMLElement} button - The button element that was clicked\n */\n toggleFullEventSection(sectionId, button) {\n // Toggle the full event data state\n this.fullEventDataExpanded = !this.fullEventDataExpanded;\n \n // Persist the preference to localStorage\n localStorage.setItem('dashboard-full-event-expanded', this.fullEventDataExpanded.toString());\n \n // Update ALL Full Event sections on the page\n this.updateAllFullEventSections();\n \n // Dispatch event to notify other components of the change\n document.dispatchEvent(new CustomEvent('fullEventToggleChanged', {\n detail: { expanded: this.fullEventDataExpanded }\n }));\n }\n \n /**\n * Update all JSON sections on the page to match global state\n * WHY: Ensures all \"Structured Data\" sections maintain consistent visibility\n */\n updateAllJsonSections() {\n // Find all unified JSON sections (NOT full event sections)\n const allJsonContents = document.querySelectorAll('.unified-json-content');\n const allJsonButtons = document.querySelectorAll('.unified-json-toggle');\n \n // Update each JSON section\n allJsonContents.forEach(content => {\n if (this.globalJsonExpanded) {\n content.style.display = 'block';\n } else {\n content.style.display = 'none';\n }\n });\n \n // Update all button states\n allJsonButtons.forEach(button => {\n const title = button.textContent.substring(2); // Remove arrow\n if (this.globalJsonExpanded) {\n button.innerHTML = '▼ ' + title;\n button.classList.add('expanded');\n } else {\n button.innerHTML = '▶ ' + title;\n button.classList.remove('expanded');\n }\n });\n }\n \n /**\n * Update all Full Event Data sections on the page to match state\n * WHY: Ensures all \"Full Event Data\" sections maintain consistent visibility\n */\n updateAllFullEventSections() {\n // Find all full event sections\n const allFullEventContents = document.querySelectorAll('.full-event-content');\n const allFullEventButtons = document.querySelectorAll('.full-event-toggle');\n \n // Update each full event section\n allFullEventContents.forEach(content => {\n if (this.fullEventDataExpanded) {\n content.style.display = 'block';\n } else {\n content.style.display = 'none';\n }\n });\n \n // Update all button states\n allFullEventButtons.forEach(button => {\n const title = button.textContent.substring(2); // Remove arrow\n if (this.fullEventDataExpanded) {\n button.innerHTML = '▼ ' + title;\n button.classList.add('expanded');\n } else {\n button.innerHTML = '▶ ' + title;\n button.classList.remove('expanded');\n }\n });\n }\n\n /**\n * Create a collapsible JSON viewer for secondary details\n * Provides a clean way to show full data without cluttering the main view\n */\n createCollapsibleJSON(data, title = 'Full Details') {\n // Generate unique ID for this collapsible section\n const sectionId = `json-details-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n \n // Filter out sensitive or overly verbose properties\n const cleanData = this.cleanDataForDisplay(data);\n \n // Determine which state to use based on title\n // \"Full Event Data\" and similar titles use the fullEventDataExpanded state\n // Other titles use the global JSON state (for backward compatibility)\n const isFullEventData = title.includes('Full Event') || title.includes('Full Details') || \n title.includes('Full Agent') || title.includes('Full Tool');\n const isExpanded = isFullEventData ? this.fullEventDataExpanded : this.globalJsonExpanded;\n const display = isExpanded ? 'block' : 'none';\n const arrow = isExpanded ? '▼' : '▶';\n const expandedClass = isExpanded ? 'expanded' : '';\n \n // Use different toggle function based on section type\n const toggleFunction = isFullEventData ? 'toggleFullEventSection' : 'toggleJsonSection';\n \n return `\n <div class=\"collapsible-json-section\">\n <button class=\"collapsible-json-toggle ${isFullEventData ? 'full-event-toggle' : 'unified-json-toggle'} ${expandedClass}\" \n data-section-id=\"${sectionId}\"\n data-is-full-event=\"${isFullEventData}\"\n onclick=\"window.unifiedDataViewer.${toggleFunction}('${sectionId}', this)\">\n ${arrow} ${title}\n </button>\n <div id=\"${sectionId}\" class=\"collapsible-json-content ${isFullEventData ? 'full-event-content' : 'unified-json-content'}\" style=\"display: ${display};\">\n <pre class=\"json-viewer\">${this.escapeHtml(JSON.stringify(cleanData, null, 2))}</pre>\n </div>\n </div>\n `;\n }\n\n /**\n * Clean data for display in JSON viewer\n * Removes circular references and limits string lengths\n */\n cleanDataForDisplay(data) {\n const seen = new WeakSet();\n \n return JSON.parse(JSON.stringify(data, (key, value) => {\n // Handle circular references\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return '[Circular Reference]';\n }\n seen.add(value);\n }\n \n // Truncate very long strings\n if (typeof value === 'string' && value.length > 1000) {\n return value.substring(0, 1000) + '... [truncated]';\n }\n \n // Handle functions\n if (typeof value === 'function') {\n return '[Function]';\n }\n \n return value;\n }));\n }\n\n // ==================== PUBLIC API METHODS ====================\n\n /**\n * Clear the viewer\n */\n clear() {\n if (this.container) {\n this.container.innerHTML = '';\n }\n this.currentData = null;\n this.currentType = null;\n }\n\n /**\n * Get current displayed data\n */\n getCurrentData() {\n return this.currentData;\n }\n\n /**\n * Get current data type\n */\n getCurrentType() {\n return this.currentType;\n }\n\n /**\n * Check if viewer has data\n */\n hasData() {\n return this.currentData !== null;\n }\n}\n\n// Export for module use\nexport { UnifiedDataViewer };\nexport default UnifiedDataViewer;\n\n// Make globally available for non-module usage\nwindow.UnifiedDataViewer = UnifiedDataViewer;\n\n// Create a global instance immediately for inline onclick handlers\n// This ensures the instance is available when HTML is rendered dynamically\nif (typeof window !== 'undefined') {\n // Always create/update the global instance\n window.unifiedDataViewer = new UnifiedDataViewer();\n \n // Also expose the methods directly on window as a fallback\n window.toggleFullEventSection = function(sectionId, button) {\n if (window.unifiedDataViewer) {\n window.unifiedDataViewer.toggleFullEventSection(sectionId, button);\n }\n };\n \n window.toggleJsonSection = function(sectionId, button) {\n if (window.unifiedDataViewer) {\n window.unifiedDataViewer.toggleJsonSection(sectionId, button);\n }\n };\n}\n\n// Create a global instance for inline preview functionality\nif (typeof window !== 'undefined') {\n window.addEventListener('DOMContentLoaded', function() {\n // Create global instance if one doesn't exist\n if (!window.unifiedDataViewer) {\n window.unifiedDataViewer = new UnifiedDataViewer();\n }\n \n // Add keyboard shortcuts for file operations\n document.addEventListener('keydown', function(e) {\n // Ctrl/Cmd + Click on file paths to open file viewer\n if ((e.ctrlKey || e.metaKey) && e.target.classList.contains('clickable-file-path')) {\n e.preventDefault();\n const filePath = e.target.textContent.trim();\n if (window.showFileViewerModal) {\n window.showFileViewerModal(filePath);\n }\n }\n \n // 'V' key to open file viewer when hovering over clickable file paths\n if (e.key.toLowerCase() === 'v' && document.querySelector('.clickable-file-path:hover')) {\n const hoveredPath = document.querySelector('.clickable-file-path:hover');\n if (hoveredPath && window.showFileViewerModal) {\n e.preventDefault();\n const filePath = hoveredPath.textContent.trim();\n window.showFileViewerModal(filePath);\n }\n }\n });\n });\n}"],"names":["UnifiedDataViewer","constructor","containerId","this","container","document","getElementById","currentData","currentType","globalJsonExpanded","localStorage","getItem","fullEventDataExpanded","addEventListener","e","detail","expanded","updateAllJsonSections","updateAllFullEventSections","display","data","type","detectType","innerHTML","displayEvent","displayAgent","displayTool","displayTodo","displayInstruction","displaySession","name","params","tool_parameters","convertedData","convertToolToFileOperation","displayFileOperation","displayHook","displayGeneric","console","warn","hook_event_name","event_type","timestamp","agent_name","agentName","status","tool_name","icon","todos","content","activeForm","text","preview","session_id","startTime","lastActivity","file_path","operations","operation","hook_name","subtype","html","formatEventType","formatTimestamp","formatEventDetails","toolName","getToolIcon","command","escapeHtml","createCollapsibleJSON","agentIcon","getAgentIcon","formatStatus","formatStatusClass","tools","length","activeTools","filter","t","completedTools","forEach","tool","currentTask","description","toolIcon","displayTodoWriteTool","old_string","substring","new_string","pattern","path","subagent_type","callCount","statusCounts","getTodoStatusCounts","completed","in_progress","pending","todo","index","statusIcon","getCheckboxIcon","displayText","statusClass","Array","isArray","replace","Object","keys","id","working_directory","git_branch","eventCount","fileName","split","pop","isSingleFile","isSingleFileOperation","fileIcon","getFileIcon","fileType","getFileType","shouldShowPreview","shouldShowInlinePreview","isTextFile","generatePreviewId","map","op","getOperationIcon","agent","workingDirectory","join","formatHookDetails","meaningfulProps","prop","value","String","event","formatAgentEventDetails","formatTodoEventDetails","formatSessionEventDetails","formatGenericEventDetails","hookType","prompt","prompt_text","prompt_preview","operation_type","duration_ms","agent_type","reason","basicProps","formatEventData","JSON","stringify","formatParameters","title","paramKeys","key","formatParameterValue","hasOwnProperty","formatTodosAsParameter","filePath","ext","toLowerCase","js","jsx","ts","tsx","py","java","cpp","c","cs","php","rb","go","rs","swift","kt","scala","htm","css","scss","sass","less","vue","json","xml","yaml","yml","toml","ini","conf","config","md","txt","rtf","pdf","doc","docx","jpg","jpeg","png","gif","svg","webp","ico","zip","tar","gz","rar","sql","db","log","env","lock","includes","toggleInlinePreview","buttonElement","style","loadInlinePreview","error","message","generateId","Date","now","toString","Math","random","substr","btoa","date","isNaN","getTime","toLocaleString","active","failed","PM","Engineer","Research","QA","Architect","Ops","Read","Write","Edit","MultiEdit","Bash","Grep","Glob","LS","TodoWrite","Task","WebFetch","read","write","edit","delete","create","search","list","copy","move","bash","toolData","notebook_path","toISOString","sessionId","details","parameters","lastOperation","originalTool","counts","div","createElement","textContent","toggleJsonSection","sectionId","button","setItem","dispatchEvent","CustomEvent","toggleFullEventSection","allJsonContents","querySelectorAll","allJsonButtons","classList","add","remove","allFullEventContents","allFullEventButtons","cleanData","cleanDataForDisplay","isFullEventData","isExpanded","seen","WeakSet","parse","has","clear","getCurrentData","getCurrentType","hasData","window","unifiedDataViewer","ctrlKey","metaKey","target","contains","preventDefault","trim","showFileViewerModal","querySelector","hoveredPath"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-directory.js","sources":["../../js/components/working-directory.js"],"sourcesContent":["/**\n * Working Directory Module\n *\n * Manages working directory state, session-specific directory tracking,\n * and git branch monitoring for the dashboard.\n *\n * WHY: Extracted from main dashboard to isolate working directory management\n * logic that involves coordination between UI updates, local storage persistence,\n * and git integration. This provides better maintainability for directory state.\n *\n * DESIGN DECISION: Maintains per-session working directories with persistence\n * in localStorage, provides git branch integration, and coordinates with\n * footer directory display for consistent state management.\n */\nclass WorkingDirectoryManager {\n constructor(socketManager) {\n this.socketManager = socketManager;\n this.currentWorkingDir = null;\n this.footerDirObserver = null;\n this._updatingFooter = false;\n\n this.setupEventHandlers();\n this.initialize();\n\n console.log('Working directory manager initialized');\n }\n\n /**\n * Initialize working directory management\n */\n initialize() {\n this.initializeWorkingDirectory();\n this.watchFooterDirectory();\n }\n\n /**\n * Set up event handlers for working directory controls\n */\n setupEventHandlers() {\n const changeDirBtn = document.getElementById('change-dir-btn');\n const workingDirPath = document.getElementById('working-dir-path');\n\n if (changeDirBtn) {\n changeDirBtn.addEventListener('click', () => {\n this.showChangeDirDialog();\n });\n }\n\n if (workingDirPath) {\n workingDirPath.addEventListener('click', (e) => {\n // Check if Shift key is held for directory change, otherwise show file viewer\n if (e.shiftKey) {\n this.showChangeDirDialog();\n } else {\n this.showWorkingDirectoryViewer();\n }\n });\n }\n\n // Listen for session changes to update working directory\n document.addEventListener('sessionChanged', (e) => {\n const sessionId = e.detail.sessionId;\n console.log('[WORKING-DIR-DEBUG] sessionChanged event received, sessionId:', this.repr(sessionId));\n if (sessionId) {\n this.loadWorkingDirectoryForSession(sessionId);\n }\n });\n\n // Listen for git branch responses\n if (this.socketManager && this.socketManager.getSocket) {\n const socket = this.socketManager.getSocket();\n if (socket) {\n console.log('[WORKING-DIR-DEBUG] Setting up git_branch_response listener');\n socket.on('git_branch_response', (response) => {\n console.log('[GIT-BRANCH-DEBUG] Received git_branch_response:', response);\n this.handleGitBranchResponse(response);\n });\n }\n }\n }\n\n /**\n * Initialize working directory for current session\n */\n initializeWorkingDirectory() {\n // Set initial loading state to prevent early Git requests\n const pathElement = document.getElementById('working-dir-path');\n if (pathElement && !pathElement.textContent.trim()) {\n pathElement.textContent = 'Loading...';\n }\n\n // Check if there's a selected session\n const sessionSelect = document.getElementById('session-select');\n if (sessionSelect && sessionSelect.value && sessionSelect.value !== 'all') {\n // Load working directory for selected session\n this.loadWorkingDirectoryForSession(sessionSelect.value);\n } else {\n // Use default working directory\n this.setWorkingDirectory(this.getDefaultWorkingDir());\n }\n }\n\n /**\n * Watch footer directory for changes and sync working directory\n */\n watchFooterDirectory() {\n const footerDir = document.getElementById('footer-working-dir');\n if (!footerDir) return;\n\n // Store observer reference for later use\n this.footerDirObserver = new MutationObserver((mutations) => {\n // Skip if we're updating from setWorkingDirectory\n if (this._updatingFooter) return;\n\n mutations.forEach((mutation) => {\n if (mutation.type === 'childList' || mutation.type === 'characterData') {\n const newDir = footerDir.textContent.trim();\n console.log('Footer directory changed to:', newDir);\n\n // Only update if it's different from current\n if (newDir && newDir !== this.currentWorkingDir) {\n console.log('Syncing working directory from footer change');\n this.setWorkingDirectory(newDir);\n }\n }\n });\n });\n\n // Observe changes to footer directory\n this.footerDirObserver.observe(footerDir, {\n childList: true,\n characterData: true,\n subtree: true\n });\n\n console.log('Started watching footer directory for changes');\n }\n\n /**\n * Load working directory for a specific session\n * @param {string} sessionId - Session ID\n */\n loadWorkingDirectoryForSession(sessionId) {\n console.log('[WORKING-DIR-DEBUG] loadWorkingDirectoryForSession called with sessionId:', this.repr(sessionId));\n\n if (!sessionId || sessionId === 'all') {\n console.log('[WORKING-DIR-DEBUG] No sessionId or sessionId is \"all\", using default working dir');\n const defaultDir = this.getDefaultWorkingDir();\n console.log('[WORKING-DIR-DEBUG] Default working dir:', this.repr(defaultDir));\n this.setWorkingDirectory(defaultDir);\n return;\n }\n\n // Load from localStorage\n const sessionDirs = JSON.parse(localStorage.getItem('sessionWorkingDirs') || '{}');\n console.log('[WORKING-DIR-DEBUG] Session directories from localStorage:', sessionDirs);\n\n const sessionDir = sessionDirs[sessionId];\n const defaultDir = this.getDefaultWorkingDir();\n const dir = sessionDir || defaultDir;\n\n console.log('[WORKING-DIR-DEBUG] Directory selection:', {\n sessionId: sessionId,\n sessionDir: this.repr(sessionDir),\n defaultDir: this.repr(defaultDir),\n finalDir: this.repr(dir)\n });\n\n this.setWorkingDirectory(dir);\n }\n\n /**\n * Set the working directory for the current session\n * @param {string} dir - Directory path\n */\n setWorkingDirectory(dir) {\n console.log('[WORKING-DIR-DEBUG] setWorkingDirectory called with:', this.repr(dir));\n\n this.currentWorkingDir = dir;\n \n // Store in session storage for persistence during the session\n if (dir && this.validateDirectoryPath(dir)) {\n sessionStorage.setItem('currentWorkingDirectory', dir);\n console.log('[WORKING-DIR-DEBUG] Stored working directory in session storage:', dir);\n }\n\n // Update UI\n const pathElement = document.getElementById('working-dir-path');\n if (pathElement) {\n console.log('[WORKING-DIR-DEBUG] Updating UI path element to:', dir);\n pathElement.textContent = dir;\n } else {\n console.warn('[WORKING-DIR-DEBUG] working-dir-path element not found');\n }\n\n // Update footer directory (sync across components)\n const footerDir = document.getElementById('footer-working-dir');\n if (footerDir) {\n const currentFooterText = footerDir.textContent;\n console.log('[WORKING-DIR-DEBUG] Footer directory current text:', this.repr(currentFooterText), 'new text:', this.repr(dir));\n\n if (currentFooterText !== dir) {\n // Set flag to prevent observer from triggering\n this._updatingFooter = true;\n footerDir.textContent = dir;\n console.log('[WORKING-DIR-DEBUG] Updated footer directory to:', dir);\n\n // Clear flag after a short delay\n setTimeout(() => {\n this._updatingFooter = false;\n console.log('[WORKING-DIR-DEBUG] Cleared _updatingFooter flag');\n }, 100);\n } else {\n console.log('[WORKING-DIR-DEBUG] Footer directory already has correct text');\n }\n } else {\n console.warn('[WORKING-DIR-DEBUG] footer-working-dir element not found');\n }\n\n // Save to localStorage for session persistence\n const sessionSelect = document.getElementById('session-select');\n if (sessionSelect && sessionSelect.value && sessionSelect.value !== 'all') {\n const sessionId = sessionSelect.value;\n const sessionDirs = JSON.parse(localStorage.getItem('sessionWorkingDirs') || '{}');\n sessionDirs[sessionId] = dir;\n localStorage.setItem('sessionWorkingDirs', JSON.stringify(sessionDirs));\n console.log(`[WORKING-DIR-DEBUG] Saved working directory for session ${sessionId}:`, dir);\n } else {\n console.log('[WORKING-DIR-DEBUG] No session selected or session is \"all\", not saving to localStorage');\n }\n\n // Update git branch for new directory - only if it's a valid path\n console.log('[WORKING-DIR-DEBUG] About to call updateGitBranch with:', this.repr(dir));\n if (this.validateDirectoryPath(dir)) {\n this.updateGitBranch(dir);\n } else {\n console.log('[WORKING-DIR-DEBUG] Skipping git branch update for invalid directory:', this.repr(dir));\n }\n\n // Dispatch event for other modules\n document.dispatchEvent(new CustomEvent('workingDirectoryChanged', {\n detail: { directory: dir }\n }));\n\n console.log('[WORKING-DIR-DEBUG] Working directory set to:', dir);\n }\n\n /**\n * Update git branch display for current working directory\n * @param {string} dir - Working directory path\n */\n updateGitBranch(dir) {\n console.log('[GIT-BRANCH-DEBUG] updateGitBranch called with dir:', this.repr(dir), 'type:', typeof dir);\n\n if (!this.socketManager || !this.socketManager.isConnected()) {\n console.log('[GIT-BRANCH-DEBUG] Not connected to socket server');\n // Not connected, set to unknown\n const footerBranch = document.getElementById('footer-git-branch');\n if (footerBranch) {\n footerBranch.textContent = 'Not Connected';\n footerBranch.style.display = 'inline';\n }\n return;\n }\n\n // Enhanced validation with specific checks for common invalid states\n const isValidPath = this.validateDirectoryPath(dir);\n const isLoadingState = dir === 'Loading...' || dir === 'Loading';\n const isUnknown = dir === 'Unknown';\n const isEmptyOrWhitespace = !dir || (typeof dir === 'string' && dir.trim() === '');\n\n console.log('[GIT-BRANCH-DEBUG] Validation results:', {\n dir: dir,\n isValidPath: isValidPath,\n isLoadingState: isLoadingState,\n isUnknown: isUnknown,\n isEmptyOrWhitespace: isEmptyOrWhitespace,\n shouldReject: !isValidPath || isLoadingState || isUnknown || isEmptyOrWhitespace\n });\n\n // Validate directory before sending to server - reject common invalid states\n if (!isValidPath || isLoadingState || isUnknown || isEmptyOrWhitespace) {\n console.warn('[GIT-BRANCH-DEBUG] Invalid working directory for git branch request:', dir);\n const footerBranch = document.getElementById('footer-git-branch');\n if (footerBranch) {\n if (isLoadingState) {\n footerBranch.textContent = 'Loading...';\n } else if (isUnknown || isEmptyOrWhitespace) {\n footerBranch.textContent = 'No Directory';\n } else {\n footerBranch.textContent = 'Invalid Directory';\n }\n footerBranch.style.display = 'inline';\n }\n return;\n }\n\n // Request git branch from server\n const socket = this.socketManager.getSocket();\n if (socket) {\n console.log('[GIT-BRANCH-DEBUG] Requesting git branch for directory:', dir);\n console.log('[GIT-BRANCH-DEBUG] Socket state:', {\n connected: socket.connected,\n id: socket.id\n });\n // Server expects working_dir as a direct parameter, not as an object\n socket.emit('get_git_branch', dir);\n } else {\n console.error('[GIT-BRANCH-DEBUG] No socket available for git branch request');\n }\n }\n\n /**\n * Get default working directory\n * @returns {string} - Default directory path\n */\n getDefaultWorkingDir() {\n console.log('[WORKING-DIR-DEBUG] getDefaultWorkingDir called');\n \n // Try to get from the current working directory if set\n if (this.currentWorkingDir && this.validateDirectoryPath(this.currentWorkingDir)) {\n console.log('[WORKING-DIR-DEBUG] Using current working directory:', this.currentWorkingDir);\n return this.currentWorkingDir;\n }\n \n // Try to get from header display\n const headerWorkingDir = document.querySelector('.working-dir-text');\n if (headerWorkingDir?.textContent?.trim()) {\n const headerPath = headerWorkingDir.textContent.trim();\n if (headerPath !== 'Loading...' && headerPath !== 'Unknown' && this.validateDirectoryPath(headerPath)) {\n console.log('[WORKING-DIR-DEBUG] Using header working directory:', headerPath);\n return headerPath;\n }\n }\n\n // Try to get from footer\n const footerDir = document.getElementById('footer-working-dir');\n if (footerDir?.textContent?.trim()) {\n const footerPath = footerDir.textContent.trim();\n console.log('[WORKING-DIR-DEBUG] Footer path found:', this.repr(footerPath));\n\n // Don't use 'Unknown' as a valid directory\n const isUnknown = footerPath === 'Unknown';\n const isValid = this.validateDirectoryPath(footerPath);\n\n console.log('[WORKING-DIR-DEBUG] Footer path validation:', {\n footerPath: this.repr(footerPath),\n isUnknown: isUnknown,\n isValid: isValid,\n shouldUse: !isUnknown && isValid\n });\n\n if (!isUnknown && isValid) {\n console.log('[WORKING-DIR-DEBUG] Using footer path as default:', footerPath);\n return footerPath;\n }\n } else {\n console.log('[WORKING-DIR-DEBUG] No footer directory element or no text content');\n }\n\n // Fallback to a reasonable default - try to get the current project directory\n // This should be set when the dashboard initializes\n\n // Try getting from events that have a working directory\n if (window.socketClient && window.socketClient.events) {\n // Look for the most recent event with a working directory\n const eventsWithDir = window.socketClient.events\n .filter(e => e.data && (e.data.working_directory || e.data.cwd || e.data.working_dir))\n .reverse();\n \n if (eventsWithDir.length > 0) {\n const recentEvent = eventsWithDir[0];\n const dir = recentEvent.data.working_directory || \n recentEvent.data.cwd || \n recentEvent.data.working_dir;\n console.log('[WORKING-DIR-DEBUG] Using working directory from recent event:', dir);\n return dir;\n }\n }\n const workingDirPath = document.getElementById('working-dir-path');\n if (workingDirPath?.textContent?.trim()) {\n const pathText = workingDirPath.textContent.trim();\n console.log('[WORKING-DIR-DEBUG] Found working-dir-path element text:', this.repr(pathText));\n if (pathText !== 'Unknown' && this.validateDirectoryPath(pathText)) {\n console.log('[WORKING-DIR-DEBUG] Using working-dir-path as fallback:', pathText);\n return pathText;\n }\n }\n\n // Try to get from session storage or environment\n const sessionWorkingDir = sessionStorage.getItem('currentWorkingDirectory');\n if (sessionWorkingDir && this.validateDirectoryPath(sessionWorkingDir)) {\n console.log('[WORKING-DIR-DEBUG] Using session storage working directory:', this.repr(sessionWorkingDir));\n return sessionWorkingDir;\n }\n \n // Try to get the current working directory from environment/process\n // This should be the directory where claude-mpm was started from\n const processWorkingDir = window.processWorkingDirectory || process?.cwd?.() || null;\n if (processWorkingDir && this.validateDirectoryPath(processWorkingDir)) {\n console.log('[WORKING-DIR-DEBUG] Using process working directory:', this.repr(processWorkingDir));\n return processWorkingDir;\n }\n \n // Final fallback - use current working directory if available, otherwise home directory\n // Never default to root \"/\" as it's not a useful default for code viewing\n const homeDir = window.homeDirectory || process?.env?.HOME || process?.env?.USERPROFILE || null;\n const fallback = homeDir || process?.cwd?.() || os?.homedir?.() || '/Users/masa';\n console.log('[WORKING-DIR-DEBUG] Using fallback directory (home or cwd):', this.repr(fallback));\n return fallback;\n }\n\n /**\n * Show change directory dialog\n */\n showChangeDirDialog() {\n const newDir = prompt('Enter new working directory:', this.currentWorkingDir || '');\n if (newDir && newDir.trim() !== '') {\n this.setWorkingDirectory(newDir.trim());\n }\n }\n\n /**\n * Show working directory file viewer overlay\n * WHY: Provides quick file browsing from the header without opening a full modal\n * DESIGN DECISION: Uses overlay positioned below the blue bar for easy access\n */\n showWorkingDirectoryViewer() {\n // Create or show the directory viewer overlay\n this.createDirectoryViewerOverlay();\n }\n\n /**\n * Create directory viewer overlay positioned below the working directory display\n * WHY: Positions overlay near the trigger for intuitive user experience\n * without disrupting the main dashboard layout\n */\n createDirectoryViewerOverlay() {\n // Remove existing overlay if present\n this.removeDirectoryViewerOverlay();\n\n const workingDirDisplay = document.querySelector('.working-dir-display');\n if (!workingDirDisplay) return;\n\n // Create overlay element\n const overlay = document.createElement('div');\n overlay.id = 'directory-viewer-overlay';\n overlay.className = 'directory-viewer-overlay';\n\n // Create overlay content\n overlay.innerHTML = `\n <div class=\"directory-viewer-content\">\n <div class=\"directory-viewer-header\">\n <h3 class=\"directory-viewer-title\">\n 📁 ${this.currentWorkingDir || 'Working Directory'}\n </h3>\n <button class=\"close-btn\" onclick=\"workingDirectoryManager.removeDirectoryViewerOverlay()\">✕</button>\n </div>\n <div class=\"directory-viewer-body\">\n <div class=\"loading-indicator\">Loading directory contents...</div>\n </div>\n <div class=\"directory-viewer-footer\">\n <span class=\"directory-hint\">Click file to view • Shift+Click directory path to change</span>\n </div>\n </div>\n `;\n\n // Position overlay below the working directory display\n const rect = workingDirDisplay.getBoundingClientRect();\n overlay.style.cssText = `\n position: fixed;\n top: ${rect.bottom + 5}px;\n left: ${rect.left}px;\n min-width: 400px;\n max-width: 600px;\n max-height: 400px;\n z-index: 1001;\n background: white;\n border-radius: 8px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);\n border: 1px solid #e2e8f0;\n `;\n\n // Add to document\n document.body.appendChild(overlay);\n\n // Load directory contents\n this.loadDirectoryContents();\n\n // Add click outside to close\n setTimeout(() => {\n document.addEventListener('click', this.handleOutsideClick.bind(this), true);\n }, 100);\n }\n\n /**\n * Remove directory viewer overlay\n */\n removeDirectoryViewerOverlay() {\n const overlay = document.getElementById('directory-viewer-overlay');\n if (overlay) {\n overlay.remove();\n document.removeEventListener('click', this.handleOutsideClick.bind(this), true);\n }\n }\n\n /**\n * Handle clicks outside the overlay to close it\n * @param {Event} event - Click event\n */\n handleOutsideClick(event) {\n const overlay = document.getElementById('directory-viewer-overlay');\n const workingDirPath = document.getElementById('working-dir-path');\n\n if (overlay && !overlay.contains(event.target) && event.target !== workingDirPath) {\n this.removeDirectoryViewerOverlay();\n }\n }\n\n /**\n * Load directory contents using socket connection\n * WHY: Uses existing socket infrastructure to get directory listing\n * without requiring new endpoints\n */\n loadDirectoryContents() {\n if (!this.socketManager || !this.socketManager.isConnected()) {\n this.showDirectoryError('Not connected to server');\n return;\n }\n\n const socket = this.socketManager.getSocket();\n if (!socket) {\n this.showDirectoryError('No socket connection available');\n return;\n }\n\n // Request directory listing\n socket.emit('get_directory_listing', {\n directory: this.currentWorkingDir,\n limit: 50 // Reasonable limit for overlay display\n });\n\n // Listen for response\n const responseHandler = (data) => {\n socket.off('directory_listing_response', responseHandler);\n this.handleDirectoryListingResponse(data);\n };\n\n socket.on('directory_listing_response', responseHandler);\n\n // Timeout after 5 seconds\n setTimeout(() => {\n socket.off('directory_listing_response', responseHandler);\n const overlay = document.getElementById('directory-viewer-overlay');\n if (overlay && overlay.querySelector('.loading-indicator')) {\n this.showDirectoryError('Request timeout');\n }\n }, 5000);\n }\n\n /**\n * Handle directory listing response from server\n * @param {Object} data - Directory listing data\n */\n handleDirectoryListingResponse(data) {\n const bodyElement = document.querySelector('.directory-viewer-body');\n if (!bodyElement) return;\n\n if (!data.success) {\n this.showDirectoryError(data.error || 'Failed to load directory');\n return;\n }\n\n // Create file listing\n const files = data.files || [];\n const directories = data.directories || [];\n\n let html = '';\n\n // Add parent directory link if not root\n if (this.currentWorkingDir && this.currentWorkingDir !== '/') {\n const parentDir = this.currentWorkingDir.split('/').slice(0, -1).join('/') || '/';\n html += `\n <div class=\"file-item directory-item\" onclick=\"workingDirectoryManager.setWorkingDirectory('${parentDir}')\">\n <span class=\"file-icon\">📁</span>\n <span class=\"file-name\">..</span>\n <span class=\"file-type\">parent directory</span>\n </div>\n `;\n }\n\n // Add directories\n directories.forEach(dir => {\n const fullPath = `${this.currentWorkingDir}/${dir}`.replace(/\\/+/g, '/');\n html += `\n <div class=\"file-item directory-item\" onclick=\"workingDirectoryManager.setWorkingDirectory('${fullPath}')\">\n <span class=\"file-icon\">📁</span>\n <span class=\"file-name\">${dir}</span>\n <span class=\"file-type\">directory</span>\n </div>\n `;\n });\n\n // Add files\n files.forEach(file => {\n const filePath = `${this.currentWorkingDir}/${file}`.replace(/\\/+/g, '/');\n const fileExt = file.split('.').pop().toLowerCase();\n const fileIcon = this.getFileIcon(fileExt);\n\n html += `\n <div class=\"file-item\" onclick=\"workingDirectoryManager.viewFile('${filePath}')\">\n <span class=\"file-icon\">${fileIcon}</span>\n <span class=\"file-name\">${file}</span>\n <span class=\"file-type\">${fileExt}</span>\n </div>\n `;\n });\n\n if (html === '') {\n html = '<div class=\"no-files\">Empty directory</div>';\n }\n\n bodyElement.innerHTML = html;\n }\n\n /**\n * Show directory error in the overlay\n * @param {string} message - Error message\n */\n showDirectoryError(message) {\n const bodyElement = document.querySelector('.directory-viewer-body');\n if (bodyElement) {\n bodyElement.innerHTML = `\n <div class=\"directory-error\">\n <span class=\"error-icon\">⚠️</span>\n <span class=\"error-message\">${message}</span>\n </div>\n `;\n }\n }\n\n /**\n * Get file icon based on extension\n * @param {string} extension - File extension\n * @returns {string} - File icon emoji\n */\n getFileIcon(extension) {\n const iconMap = {\n 'js': '📄',\n 'py': '🐍',\n 'html': '🌐',\n 'css': '🎨',\n 'json': '📋',\n 'md': '📝',\n 'txt': '📝',\n 'yml': '⚙️',\n 'yaml': '⚙️',\n 'xml': '📄',\n 'pdf': '📕',\n 'png': '🖼️',\n 'jpg': '🖼️',\n 'jpeg': '🖼️',\n 'gif': '🖼️',\n 'svg': '🖼️',\n 'zip': '📦',\n 'tar': '📦',\n 'gz': '📦',\n 'sh': '🔧',\n 'bat': '🔧',\n 'exe': '⚙️',\n 'dll': '⚙️'\n };\n\n return iconMap[extension] || '📄';\n }\n\n /**\n * View a file using the existing file viewer modal\n * @param {string} filePath - Path to the file to view\n */\n viewFile(filePath) {\n // Close the directory viewer overlay\n this.removeDirectoryViewerOverlay();\n\n // Use the existing file viewer modal functionality\n if (window.showFileViewerModal) {\n window.showFileViewerModal(filePath);\n } else {\n console.warn('File viewer modal function not available');\n }\n }\n\n /**\n * Get current working directory\n * @returns {string} - Current working directory\n */\n getCurrentWorkingDir() {\n return this.currentWorkingDir;\n }\n\n /**\n * Get session working directories from localStorage\n * @returns {Object} - Session directories mapping\n */\n getSessionDirectories() {\n return JSON.parse(localStorage.getItem('sessionWorkingDirs') || '{}');\n }\n\n /**\n * Set working directory for a specific session\n * @param {string} sessionId - Session ID\n * @param {string} directory - Directory path\n */\n setSessionDirectory(sessionId, directory) {\n const sessionDirs = this.getSessionDirectories();\n sessionDirs[sessionId] = directory;\n localStorage.setItem('sessionWorkingDirs', JSON.stringify(sessionDirs));\n\n // If this is the current session, update the current directory\n const sessionSelect = document.getElementById('session-select');\n if (sessionSelect && sessionSelect.value === sessionId) {\n this.setWorkingDirectory(directory);\n }\n }\n\n /**\n * Remove session directory from storage\n * @param {string} sessionId - Session ID to remove\n */\n removeSessionDirectory(sessionId) {\n const sessionDirs = this.getSessionDirectories();\n delete sessionDirs[sessionId];\n localStorage.setItem('sessionWorkingDirs', JSON.stringify(sessionDirs));\n }\n\n /**\n * Clear all session directories from storage\n */\n clearAllSessionDirectories() {\n localStorage.removeItem('sessionWorkingDirs');\n }\n\n /**\n * Extract working directory from event pair\n * Used by file operations tracking\n * @param {Object} pair - Event pair object\n * @returns {string} - Working directory path\n */\n extractWorkingDirectoryFromPair(pair) {\n // Try different sources for working directory\n if (pair.pre?.working_dir) return pair.pre.working_dir;\n if (pair.post?.working_dir) return pair.post.working_dir;\n if (pair.pre?.data?.working_dir) return pair.pre.data.working_dir;\n if (pair.post?.data?.working_dir) return pair.post.data.working_dir;\n\n // Fallback to current working directory\n return this.currentWorkingDir || this.getDefaultWorkingDir();\n }\n\n /**\n * Validate directory path\n * @param {string} path - Directory path to validate\n * @returns {boolean} - True if path appears valid\n */\n validateDirectoryPath(path) {\n if (!path || typeof path !== 'string') return false;\n\n // Basic path validation\n const trimmed = path.trim();\n if (trimmed.length === 0) return false;\n\n // Check for obviously invalid paths\n if (trimmed.includes('\\0')) return false;\n\n // Check for common invalid placeholder states\n const invalidStates = [\n 'Loading...',\n 'Loading',\n 'Unknown',\n 'undefined',\n 'null',\n 'Not Connected',\n 'Invalid Directory',\n 'No Directory'\n ];\n\n if (invalidStates.includes(trimmed)) return false;\n\n // Basic path structure validation - should start with / or drive letter on Windows\n if (!trimmed.startsWith('/') && !(/^[A-Za-z]:/.test(trimmed))) {\n // Allow relative paths that look reasonable\n if (trimmed.startsWith('./') || trimmed.startsWith('../') ||\n /^[a-zA-Z0-9._-]+/.test(trimmed)) {\n return true;\n }\n return false;\n }\n\n return true;\n }\n\n /**\n * Handle git branch response from server\n * @param {Object} response - Git branch response\n */\n handleGitBranchResponse(response) {\n console.log('[GIT-BRANCH-DEBUG] handleGitBranchResponse called with:', response);\n\n const footerBranch = document.getElementById('footer-git-branch');\n if (!footerBranch) {\n console.warn('[GIT-BRANCH-DEBUG] footer-git-branch element not found');\n return;\n }\n\n if (response.success) {\n console.log('[GIT-BRANCH-DEBUG] Git branch request successful, branch:', response.branch);\n footerBranch.textContent = response.branch;\n footerBranch.style.display = 'inline';\n\n // Optional: Add a class to indicate successful git status\n footerBranch.classList.remove('git-error');\n footerBranch.classList.add('git-success');\n } else {\n // Handle different error types more gracefully\n let displayText = 'Git Error';\n const error = response.error || 'Unknown error';\n\n if (error.includes('Directory not found') || error.includes('does not exist')) {\n displayText = 'Dir Not Found';\n } else if (error.includes('Not a directory')) {\n displayText = 'Invalid Path';\n } else if (error.includes('Not a git repository')) {\n displayText = 'No Git Repo';\n } else if (error.includes('git')) {\n displayText = 'Git Error';\n } else {\n displayText = 'Unknown';\n }\n\n console.log('[GIT-BRANCH-DEBUG] Git branch request failed:', error, '- showing as:', displayText);\n footerBranch.textContent = displayText;\n footerBranch.style.display = 'inline';\n\n // Optional: Add a class to indicate error state\n footerBranch.classList.remove('git-success');\n footerBranch.classList.add('git-error');\n }\n\n // Log additional debug info from server\n if (response.original_working_dir) {\n console.log('[GIT-BRANCH-DEBUG] Server received original working_dir:', this.repr(response.original_working_dir));\n }\n if (response.working_dir) {\n console.log('[GIT-BRANCH-DEBUG] Server used working_dir:', this.repr(response.working_dir));\n }\n if (response.git_error) {\n console.log('[GIT-BRANCH-DEBUG] Git command stderr:', response.git_error);\n }\n }\n\n /**\n * Check if working directory is ready for Git operations\n * @returns {boolean} - True if directory is ready\n */\n isWorkingDirectoryReady() {\n const dir = this.getCurrentWorkingDir();\n return this.validateDirectoryPath(dir) && dir !== 'Loading...' && dir !== 'Unknown';\n }\n\n /**\n * Wait for working directory to be ready, then execute callback\n * @param {Function} callback - Function to call when directory is ready\n * @param {number} timeout - Maximum time to wait in milliseconds\n */\n whenDirectoryReady(callback, timeout = 5000) {\n const startTime = Date.now();\n\n const checkReady = () => {\n if (this.isWorkingDirectoryReady()) {\n callback();\n } else if (Date.now() - startTime < timeout) {\n setTimeout(checkReady, 100); // Check every 100ms\n } else {\n console.warn('[WORKING-DIR-DEBUG] Timeout waiting for directory to be ready');\n }\n };\n\n checkReady();\n }\n\n /**\n * Helper function for detailed logging\n * @param {*} value - Value to represent\n * @returns {string} - String representation\n */\n repr(value) {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'string') return `\"${value}\"`;\n return String(value);\n }\n\n /**\n * Cleanup resources\n */\n cleanup() {\n if (this.footerDirObserver) {\n this.footerDirObserver.disconnect();\n this.footerDirObserver = null;\n }\n\n console.log('Working directory manager cleaned up');\n }\n}\n// ES6 Module export\nexport { WorkingDirectoryManager };\nexport default WorkingDirectoryManager;\n\n// Make WorkingDirectoryManager globally available for dist/dashboard.js\nwindow.WorkingDirectoryManager = WorkingDirectoryManager;\n"],"names":["window","WorkingDirectoryManager","constructor","socketManager","this","currentWorkingDir","footerDirObserver","_updatingFooter","setupEventHandlers","initialize","console","log","initializeWorkingDirectory","watchFooterDirectory","changeDirBtn","document","getElementById","workingDirPath","addEventListener","showChangeDirDialog","e","shiftKey","showWorkingDirectoryViewer","sessionId","detail","repr","loadWorkingDirectoryForSession","getSocket","socket","on","response","handleGitBranchResponse","pathElement","textContent","trim","sessionSelect","value","setWorkingDirectory","getDefaultWorkingDir","footerDir","MutationObserver","mutations","forEach","mutation","type","newDir","observe","childList","characterData","subtree","defaultDir","sessionDirs","JSON","parse","localStorage","getItem","sessionDir","dir","finalDir","validateDirectoryPath","sessionStorage","setItem","warn","currentFooterText","setTimeout","stringify","updateGitBranch","dispatchEvent","CustomEvent","directory","isConnected","footerBranch","style","display","isValidPath","isLoadingState","isUnknown","isEmptyOrWhitespace","shouldReject","connected","id","emit","error","headerWorkingDir","querySelector","headerPath","footerPath","isValid","shouldUse","socketClient","events","eventsWithDir","filter","data","working_directory","cwd","working_dir","reverse","length","recentEvent","pathText","sessionWorkingDir","processWorkingDir","processWorkingDirectory","process","fallback","homeDirectory","env","HOME","USERPROFILE","os","homedir","prompt","createDirectoryViewerOverlay","removeDirectoryViewerOverlay","workingDirDisplay","overlay","createElement","className","innerHTML","rect","getBoundingClientRect","cssText","bottom","left","body","appendChild","loadDirectoryContents","handleOutsideClick","bind","remove","removeEventListener","event","contains","target","showDirectoryError","limit","responseHandler","off","handleDirectoryListingResponse","bodyElement","success","files","directories","html","parentDir","split","slice","join","fullPath","replace","file","filePath","fileExt","pop","toLowerCase","fileIcon","getFileIcon","message","extension","js","py","css","json","md","txt","yml","yaml","xml","pdf","png","jpg","jpeg","gif","svg","zip","tar","gz","sh","bat","exe","dll","viewFile","showFileViewerModal","getCurrentWorkingDir","getSessionDirectories","setSessionDirectory","removeSessionDirectory","clearAllSessionDirectories","removeItem","extractWorkingDirectoryFromPair","pair","pre","post","path","trimmed","includes","startsWith","test","branch","classList","add","displayText","original_working_dir","git_error","isWorkingDirectoryReady","whenDirectoryReady","callback","timeout","startTime","Date","now","checkReady","String","cleanup","disconnect"],"mappings":"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"}
|