From 0adaddacaaed028f97b7f45020b0ace906418000 Mon Sep 17 00:00:00 2001 From: Andy <119136210+AndyMik90@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:34:51 +0100 Subject: [PATCH] Feature/apps restructure v2.7.2 (#138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: restructure project to Apps/frontend and Apps/backend - Move auto-claude-ui to Apps/frontend with feature-based architecture - Move auto-claude to Apps/backend - Switch from pnpm to npm for frontend - Update Node.js requirement to v24.12.0 LTS - Add pre-commit hooks for lint, typecheck, and security audit - Add commit-msg hook for conventional commits - Fix CommonJS compatibility issues (postcss.config, postinstall scripts) - Update README with comprehensive setup and contribution guidelines - Configure ESLint to ignore .cjs files - 0 npm vulnerabilities Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * feat(refactor): clean code and move to npm * feat(refactor): clean code and move to npm * chore: update to v2.7.0, remove Docker deps (LadybugDB is embedded) * feat: v2.8.0 - update workflows and configs for Apps/ structure, npm * fix: resolve Python lint errors (F401, I001) * fix: update test paths for Apps/backend structure * fix: add missing facade files and update paths for Apps/backend structure - Fix ruff lint error I001 in auto_claude_tools.py - Create missing facade files to match upstream (agent, ci_discovery, critique, etc.) - Update test paths from auto-claude/ to Apps/backend/ - Update .pre-commit-config.yaml paths for Apps/ structure - Add pytest to pre-commit hooks (skip slow/integration/Windows-incompatible tests) - Fix Unicode encoding in test_agent_architecture.py for Windows Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * feat: improve readme * fix: new path * fix: correct release workflow and docs for Apps/ restructure - Fix ARM64 macOS build: pnpm → npm, auto-claude-ui → Apps/frontend - Fix artifact upload paths in release.yml - Update Node.js version to 24 for consistency - Update CLI-USAGE.md with Apps/backend paths - Update RELEASE.md with Apps/frontend/package.json paths 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * refactor: rename Apps/ to apps/ and fix backend path resolution - Rename Apps/ folder to apps/ for consistency with JS/Node conventions - Update all path references across CI/CD workflows, docs, and config files - Fix frontend Python path resolver to look for 'backend' instead of 'auto-claude' - Update path-resolver.ts to correctly find apps/backend in development mode This completes the Apps restructure from PR #122 and prepares for v2.8.0 release. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * fix(electron): correct preload script path from .js to .mjs electron-vite builds the preload script as ESM (index.mjs) but the main process was looking for CommonJS (index.js). This caused the preload to fail silently, making the app fall back to browser mock mode with fake data and non-functional IPC handlers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * - Introduced `dev:debug` script to enable debugging during development. - Added `dev:mcp` script for running the frontend in MCP mode. These enhancements streamline the development process for frontend developers. * refactor(memory): make Graphiti memory mandatory and remove Docker dependency Memory is now a core component of Auto Claude rather than optional: - Python 3.12+ is required for the backend (not just memory layer) - Graphiti is enabled by default in .env.example - Removed all FalkorDB/Docker references (migrated to embedded LadybugDB) - Deleted guides/DOCKER-SETUP.md and docker-handlers.ts - Updated onboarding UI to remove "optional" language - Updated all documentation to reflect LadybugDB architecture 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * feat: add cross-platform Windows support for npm scripts - Add scripts/install-backend.js for cross-platform Python venv setup - Auto-detects Python 3.12 (py -3.12 on Windows, python3.12 on Unix) - Handles platform-specific venv paths - Add scripts/test-backend.js for cross-platform pytest execution - Update package.json to use Node.js scripts instead of shell commands - Update CONTRIBUTING.md with correct paths and instructions: - apps/backend/ and apps/frontend/ paths - Python 3.12 requirement (memory system now required) - Platform-specific install commands (winget, brew, apt) - npm instead of pnpm - Quick Start section with npm run install:all 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * remove doc * fix(frontend): correct Ollama detector script path after apps restructure The Ollama status check was failing because memory-handlers.ts was looking for ollama_model_detector.py at auto-claude/ but the script is now at apps/backend/ after the directory restructure. This caused "Ollama not running" to display even when Ollama was actually running and accessible. * chore: bump version to 2.7.2 Downgrade version from 2.8.0 to 2.7.2 as the Apps/ restructure is better suited as a patch release rather than a minor release. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * chore: update package-lock.json for Windows compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * docs(contributing): add hotfix workflow and update paths for apps/ structure Add Git Flow hotfix workflow documentation with step-by-step guide and ASCII diagram showing the branching strategy. Update all paths from auto-claude/auto-claude-ui to apps/backend/apps/frontend and migrate package manager references from pnpm to npm to match the new project structure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * fix(ci): remove duplicate ARM64 build from Intel runner The Intel runner was building both x64 and arm64 architectures, while a separate ARM64 runner also builds arm64 natively. This caused duplicate ARM64 builds, wasting CI resources. Now each runner builds only its native architecture: - Intel runner: x64 only - ARM64 runner: arm64 only 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --------- Co-authored-by: Alex Madera Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 --- .github/ISSUE_TEMPLATE/bug_report.yml | 4 +- .github/ISSUE_TEMPLATE/feature_request.yml | 4 +- .github/workflows/build-prebuilds.yml | 19 +- .github/workflows/ci.yml | 57 +- .github/workflows/lint.yml | 23 +- .github/workflows/release.yml | 118 +- .github/workflows/test-on-tag.yml | 25 +- .github/workflows/validate-version.yml | 2 +- .gitignore | 147 +- .husky/commit-msg | 73 + .husky/pre-commit | 96 +- .pre-commit-config.yaml | 26 +- CLAUDE.md | 119 +- CONTRIBUTING.md | 210 +- README.md | 369 +- RELEASE.md | 6 +- {auto-claude => apps/backend}/.env.example | 8 +- {auto-claude => apps/backend}/.gitignore | 3 + apps/backend/README.md | 120 + apps/backend/__init__.py | 23 + {auto-claude => apps/backend}/agent.py | 0 .../backend}/agents/README.md | 0 apps/backend/agents/__init__.py | 92 + .../backend}/agents/auto_claude_tools.py | 0 {auto-claude => apps/backend}/agents/base.py | 0 {auto-claude => apps/backend}/agents/coder.py | 0 .../backend}/agents/memory_manager.py | 0 .../backend}/agents/planner.py | 0 .../backend}/agents/session.py | 0 .../backend}/agents/test_refactoring.py | 0 .../backend}/agents/tools_pkg/__init__.py | 0 .../backend}/agents/tools_pkg/models.py | 0 .../backend}/agents/tools_pkg/permissions.py | 0 .../backend}/agents/tools_pkg/registry.py | 0 .../agents/tools_pkg/tools/__init__.py | 0 .../backend}/agents/tools_pkg/tools/memory.py | 0 .../agents/tools_pkg/tools/progress.py | 0 .../backend}/agents/tools_pkg/tools/qa.py | 0 .../agents/tools_pkg/tools/subtask.py | 0 {auto-claude => apps/backend}/agents/utils.py | 0 .../backend}/analysis/__init__.py | 0 .../backend}/analysis/analyzer.py | 0 .../backend}/analysis/analyzers/__init__.py | 0 .../backend}/analysis/analyzers/base.py | 0 .../analysis/analyzers/context/__init__.py | 0 .../analyzers/context/api_docs_detector.py | 0 .../analyzers/context/auth_detector.py | 0 .../analyzers/context/env_detector.py | 0 .../analyzers/context/jobs_detector.py | 0 .../analyzers/context/migrations_detector.py | 0 .../analyzers/context/monitoring_detector.py | 0 .../analyzers/context/services_detector.py | 0 .../analysis/analyzers/context_analyzer.py | 0 .../analysis/analyzers/database_detector.py | 0 .../analysis/analyzers/framework_analyzer.py | 0 .../analysis/analyzers/port_detector.py | 0 .../analyzers/project_analyzer_module.py | 0 .../analysis/analyzers/route_detector.py | 0 .../analysis/analyzers/service_analyzer.py | 0 .../backend}/analysis/ci_discovery.py | 0 .../backend}/analysis/insight_extractor.py | 0 .../backend}/analysis/project_analyzer.py | 0 .../backend}/analysis/risk_classifier.py | 0 .../backend}/analysis/security_scanner.py | 0 .../backend}/analysis/test_discovery.py | 0 apps/backend/analyzer.py | 26 + apps/backend/auto_claude_tools.py | 36 + {auto-claude => apps/backend}/ci_discovery.py | 0 {auto-claude => apps/backend}/cli/__init__.py | 0 .../backend}/cli/build_commands.py | 0 .../backend}/cli/followup_commands.py | 0 .../backend}/cli/input_handlers.py | 0 {auto-claude => apps/backend}/cli/main.py | 0 .../backend}/cli/qa_commands.py | 0 .../backend}/cli/spec_commands.py | 70 +- {auto-claude => apps/backend}/cli/utils.py | 0 .../backend}/cli/workspace_commands.py | 0 apps/backend/client.py | 25 + .../backend}/commit_message.py | 0 .../backend}/context/__init__.py | 0 .../backend}/context/builder.py | 0 .../backend}/context/categorizer.py | 0 .../backend}/context/constants.py | 0 .../backend}/context/graphiti_integration.py | 0 .../backend}/context/keyword_extractor.py | 0 {auto-claude => apps/backend}/context/main.py | 0 .../backend}/context/models.py | 0 .../backend}/context/pattern_discovery.py | 0 .../backend}/context/search.py | 0 .../backend}/context/serialization.py | 0 .../backend}/context/service_matcher.py | 0 .../backend}/core/__init__.py | 0 {auto-claude => apps/backend}/core/agent.py | 0 {auto-claude => apps/backend}/core/auth.py | 0 {auto-claude => apps/backend}/core/client.py | 4 +- {auto-claude => apps/backend}/core/debug.py | 0 .../backend}/core/progress.py | 0 .../backend}/core/workspace.py | 0 .../backend}/core/workspace/README.md | 0 .../backend}/core/workspace/__init__.py | 0 .../backend}/core/workspace/display.py | 0 .../backend}/core/workspace/finalization.py | 0 .../backend}/core/workspace/git_utils.py | 0 .../backend}/core/workspace/models.py | 0 .../backend}/core/workspace/setup.py | 0 .../backend}/core/worktree.py | 0 {auto-claude => apps/backend}/critique.py | 0 apps/backend/debug.py | 40 + .../backend}/graphiti_config.py | 0 .../backend}/graphiti_providers.py | 0 .../backend}/ideation/__init__.py | 0 .../backend}/ideation/analyzer.py | 0 .../backend}/ideation/config.py | 0 .../backend}/ideation/formatter.py | 0 .../backend}/ideation/generator.py | 0 .../backend}/ideation/output_streamer.py | 0 .../backend}/ideation/phase_executor.py | 0 .../backend}/ideation/prioritizer.py | 0 .../backend}/ideation/project_index_phase.py | 0 .../backend}/ideation/runner.py | 0 .../backend}/ideation/script_runner.py | 0 .../backend}/ideation/types.py | 0 .../backend}/implementation_plan/__init__.py | 0 .../backend}/implementation_plan/enums.py | 0 .../backend}/implementation_plan/factories.py | 0 .../backend}/implementation_plan/main.py | 0 .../backend}/implementation_plan/phase.py | 0 .../backend}/implementation_plan/plan.py | 0 .../backend}/implementation_plan/subtask.py | 0 .../implementation_plan/verification.py | 0 {auto-claude => apps/backend}/init.py | 0 .../backend}/insight_extractor.py | 0 .../backend}/integrations/__init__.py | 0 .../integrations/graphiti/__init__.py | 0 .../backend}/integrations/graphiti/config.py | 0 .../backend}/integrations/graphiti/memory.py | 6 +- .../graphiti/migrate_embeddings.py | 0 .../integrations/graphiti/providers.py | 0 .../graphiti/providers_pkg/__init__.py | 0 .../graphiti/providers_pkg/cross_encoder.py | 0 .../embedder_providers/__init__.py | 0 .../azure_openai_embedder.py | 0 .../embedder_providers/google_embedder.py | 0 .../embedder_providers/ollama_embedder.py | 0 .../embedder_providers/openai_embedder.py | 0 .../embedder_providers/voyage_embedder.py | 0 .../graphiti/providers_pkg/exceptions.py | 0 .../graphiti/providers_pkg/factory.py | 0 .../providers_pkg/llm_providers/__init__.py | 0 .../llm_providers/anthropic_llm.py | 0 .../llm_providers/azure_openai_llm.py | 0 .../providers_pkg/llm_providers/google_llm.py | 0 .../providers_pkg/llm_providers/ollama_llm.py | 0 .../providers_pkg/llm_providers/openai_llm.py | 0 .../graphiti/providers_pkg/models.py | 0 .../graphiti/providers_pkg/utils.py | 0 .../graphiti/providers_pkg/validators.py | 0 .../graphiti/queries_pkg/__init__.py | 0 .../graphiti/queries_pkg/client.py | 0 .../graphiti/queries_pkg/graphiti.py | 0 .../queries_pkg/kuzu_driver_patched.py | 0 .../graphiti/queries_pkg/queries.py | 0 .../graphiti/queries_pkg/schema.py | 0 .../graphiti/queries_pkg/search.py | 0 .../graphiti/test_graphiti_memory.py | 0 .../graphiti/test_provider_naming.py | 0 .../backend}/integrations/linear/__init__.py | 0 .../backend}/integrations/linear/config.py | 0 .../integrations/linear/integration.py | 0 .../backend}/integrations/linear/updater.py | 0 .../backend}/linear_config.py | 0 apps/backend/linear_integration.py | 22 + apps/backend/linear_updater.py | 42 + .../backend}/memory/__init__.py | 2 +- .../backend}/memory/codebase_map.py | 0 .../backend}/memory/graphiti_helpers.py | 0 {auto-claude => apps/backend}/memory/main.py | 0 {auto-claude => apps/backend}/memory/paths.py | 0 .../backend}/memory/patterns.py | 0 .../backend}/memory/sessions.py | 0 .../backend}/memory/summary.py | 0 .../backend}/merge/__init__.py | 0 .../backend}/merge/ai_resolver.py | 0 .../backend}/merge/ai_resolver/README.md | 0 .../backend}/merge/ai_resolver/__init__.py | 0 .../merge/ai_resolver/claude_client.py | 0 .../backend}/merge/ai_resolver/context.py | 0 .../merge/ai_resolver/language_utils.py | 0 .../backend}/merge/ai_resolver/parsers.py | 0 .../backend}/merge/ai_resolver/prompts.py | 0 .../backend}/merge/ai_resolver/resolver.py | 0 .../backend}/merge/auto_merger.py | 0 .../backend}/merge/auto_merger/__init__.py | 0 .../backend}/merge/auto_merger/context.py | 0 .../backend}/merge/auto_merger/helpers.py | 0 .../backend}/merge/auto_merger/merger.py | 0 .../merge/auto_merger/strategies/__init__.py | 0 .../auto_merger/strategies/append_strategy.py | 0 .../auto_merger/strategies/base_strategy.py | 0 .../auto_merger/strategies/hooks_strategy.py | 0 .../auto_merger/strategies/import_strategy.py | 0 .../strategies/ordering_strategy.py | 0 .../auto_merger/strategies/props_strategy.py | 0 .../backend}/merge/compatibility_rules.py | 0 .../backend}/merge/conflict_analysis.py | 0 .../backend}/merge/conflict_detector.py | 0 .../backend}/merge/conflict_explanation.py | 0 .../backend}/merge/conflict_resolver.py | 0 .../backend}/merge/file_evolution.py | 0 .../backend}/merge/file_evolution/__init__.py | 0 .../merge/file_evolution/baseline_capture.py | 0 .../merge/file_evolution/evolution_queries.py | 0 .../file_evolution/modification_tracker.py | 0 .../backend}/merge/file_evolution/storage.py | 0 .../backend}/merge/file_evolution/tracker.py | 0 .../backend}/merge/file_merger.py | 0 .../backend}/merge/file_timeline.py | 0 .../backend}/merge/git_utils.py | 0 .../backend}/merge/hooks/post-commit | 0 .../backend}/merge/install_hook.py | 0 .../backend}/merge/merge_pipeline.py | 0 {auto-claude => apps/backend}/merge/models.py | 0 .../backend}/merge/orchestrator.py | 0 .../backend}/merge/prompts.py | 0 .../merge/semantic_analysis/__init__.py | 0 .../merge/semantic_analysis/comparison.py | 0 .../merge/semantic_analysis/js_analyzer.py | 0 .../merge/semantic_analysis/models.py | 0 .../semantic_analysis/python_analyzer.py | 0 .../merge/semantic_analysis/regex_analyzer.py | 0 .../backend}/merge/semantic_analyzer.py | 0 .../backend}/merge/timeline_git.py | 0 .../backend}/merge/timeline_models.py | 0 .../backend}/merge/timeline_persistence.py | 0 .../backend}/merge/timeline_tracker.py | 0 .../backend}/merge/tracker_cli.py | 0 {auto-claude => apps/backend}/merge/types.py | 0 .../backend}/ollama_model_detector.py | 0 {auto-claude => apps/backend}/phase_config.py | 0 .../backend}/planner_lib/__init__.py | 0 .../backend}/planner_lib/context.py | 0 .../backend}/planner_lib/generators.py | 0 .../backend}/planner_lib/main.py | 0 .../backend}/planner_lib/models.py | 0 .../backend}/planner_lib/utils.py | 0 .../backend}/prediction/__init__.py | 0 .../prediction/checklist_generator.py | 0 .../backend}/prediction/formatter.py | 0 .../backend}/prediction/main.py | 0 .../backend}/prediction/memory_loader.py | 0 .../backend}/prediction/models.py | 0 .../backend}/prediction/patterns.py | 0 .../backend}/prediction/predictor.py | 0 .../backend}/prediction/risk_analyzer.py | 0 apps/backend/progress.py | 36 + .../backend}/project/__init__.py | 0 .../backend}/project/analyzer.py | 0 .../backend}/project/command_registry.py | 0 .../project/command_registry/README.md | 0 .../project/command_registry/__init__.py | 0 .../backend}/project/command_registry/base.py | 0 .../project/command_registry/cloud.py | 0 .../project/command_registry/code_quality.py | 0 .../project/command_registry/databases.py | 0 .../project/command_registry/frameworks.py | 0 .../command_registry/infrastructure.py | 0 .../project/command_registry/languages.py | 0 .../command_registry/package_managers.py | 0 .../command_registry/version_managers.py | 0 .../backend}/project/config_parser.py | 0 .../backend}/project/framework_detector.py | 0 .../backend}/project/models.py | 0 .../backend}/project/stack_detector.py | 0 .../backend}/project/structure_analyzer.py | 0 .../backend}/project_analyzer.py | 0 .../backend}/prompt_generator.py | 0 {auto-claude => apps/backend}/prompts.py | 0 .../backend}/prompts/coder.md | 0 .../backend}/prompts/coder_recovery.md | 0 .../backend}/prompts/competitor_analysis.md | 0 .../backend}/prompts/complexity_assessor.md | 20 +- .../backend}/prompts/followup_planner.md | 0 .../prompts/ideation_code_improvements.md | 0 .../backend}/prompts/ideation_code_quality.md | 0 .../prompts/ideation_documentation.md | 0 .../backend}/prompts/ideation_performance.md | 0 .../backend}/prompts/ideation_security.md | 0 .../backend}/prompts/ideation_ui_ux.md | 0 .../backend}/prompts/insight_extractor.md | 0 .../prompts/mcp_tools/api_validation.md | 0 .../prompts/mcp_tools/database_validation.md | 0 .../prompts/mcp_tools/electron_validation.md | 0 .../prompts/mcp_tools/puppeteer_browser.md | 0 .../backend}/prompts/planner.md | 0 .../backend}/prompts/qa_fixer.md | 0 .../backend}/prompts/qa_reviewer.md | 0 .../backend}/prompts/roadmap_discovery.md | 0 .../backend}/prompts/roadmap_features.md | 0 .../backend}/prompts/spec_critic.md | 6 +- .../backend}/prompts/spec_gatherer.md | 0 .../backend}/prompts/spec_quick.md | 0 .../backend}/prompts/spec_researcher.md | 14 +- .../backend}/prompts/spec_writer.md | 0 .../backend}/prompts/validation_fixer.md | 0 .../backend}/prompts_pkg/__init__.py | 0 .../backend}/prompts_pkg/project_context.py | 0 .../backend}/prompts_pkg/prompt_generator.py | 0 .../backend}/prompts_pkg/prompts.py | 0 {auto-claude => apps/backend}/qa/__init__.py | 0 {auto-claude => apps/backend}/qa/criteria.py | 0 {auto-claude => apps/backend}/qa/fixer.py | 0 {auto-claude => apps/backend}/qa/loop.py | 0 {auto-claude => apps/backend}/qa/qa_loop.py | 0 {auto-claude => apps/backend}/qa/report.py | 0 {auto-claude => apps/backend}/qa/reviewer.py | 0 {auto-claude => apps/backend}/qa_loop.py | 17 +- {auto-claude => apps/backend}/query_memory.py | 0 {auto-claude => apps/backend}/recovery.py | 0 .../backend}/requirements.txt | 0 .../backend}/review/__init__.py | 0 .../backend}/review/diff_analyzer.py | 0 .../backend}/review/formatters.py | 0 {auto-claude => apps/backend}/review/main.py | 0 .../backend}/review/reviewer.py | 0 {auto-claude => apps/backend}/review/state.py | 0 .../backend}/risk_classifier.py | 0 {auto-claude => apps/backend}/run.py | 0 .../backend}/runners/__init__.py | 0 .../backend}/runners/ai_analyzer/EXAMPLES.md | 0 .../backend}/runners/ai_analyzer/README.md | 0 .../backend}/runners/ai_analyzer/__init__.py | 0 .../backend}/runners/ai_analyzer/analyzers.py | 0 .../runners/ai_analyzer/cache_manager.py | 0 .../runners/ai_analyzer/claude_client.py | 0 .../runners/ai_analyzer/cost_estimator.py | 0 .../backend}/runners/ai_analyzer/models.py | 0 .../runners/ai_analyzer/result_parser.py | 0 .../backend}/runners/ai_analyzer/runner.py | 0 .../runners/ai_analyzer/summary_printer.py | 0 .../backend}/runners/ai_analyzer_runner.py | 0 .../backend}/runners/ideation_runner.py | 0 .../backend}/runners/insights_runner.py | 0 .../backend}/runners/roadmap/__init__.py | 0 .../runners/roadmap/competitor_analyzer.py | 0 .../backend}/runners/roadmap/executor.py | 0 .../runners/roadmap/graph_integration.py | 0 .../backend}/runners/roadmap/models.py | 0 .../backend}/runners/roadmap/orchestrator.py | 0 .../backend}/runners/roadmap/phases.py | 0 .../runners/roadmap/project_index.json | 0 .../backend}/runners/roadmap_runner.py | 0 .../backend}/runners/spec_runner.py | 0 .../backend}/scan-for-secrets | 0 {auto-claude => apps/backend}/scan_secrets.py | 0 {auto-claude => apps/backend}/security.py | 0 .../backend}/security/__init__.py | 0 .../backend}/security/database_validators.py | 0 .../security/filesystem_validators.py | 0 .../backend}/security/git_validators.py | 0 .../backend}/security/hooks.py | 0 .../backend}/security/main.py | 0 .../backend}/security/parser.py | 0 .../backend}/security/process_validators.py | 0 .../backend}/security/profile.py | 0 .../backend}/security/scan_secrets.py | 0 .../backend}/security/validation_models.py | 0 .../backend}/security/validator.py | 0 .../backend}/security/validator_registry.py | 0 .../backend}/security_scanner.py | 0 .../backend}/service_orchestrator.py | 0 .../backend}/services/__init__.py | 0 .../backend}/services/context.py | 0 .../backend}/services/orchestrator.py | 0 .../backend}/services/recovery.py | 0 .../backend}/spec/__init__.py | 0 .../backend}/spec/compaction.py | 0 .../backend}/spec/complexity.py | 0 {auto-claude => apps/backend}/spec/context.py | 0 .../backend}/spec/critique.py | 0 .../backend}/spec/discovery.py | 0 {auto-claude => apps/backend}/spec/phases.py | 0 .../backend}/spec/phases/README.md | 0 .../backend}/spec/phases/__init__.py | 0 .../backend}/spec/phases/discovery_phases.py | 0 .../backend}/spec/phases/executor.py | 0 .../backend}/spec/phases/models.py | 0 .../backend}/spec/phases/planning_phases.py | 0 .../spec/phases/requirements_phases.py | 0 .../backend}/spec/phases/spec_phases.py | 0 .../backend}/spec/phases/utils.py | 0 .../backend}/spec/pipeline.py | 0 .../backend}/spec/pipeline/__init__.py | 0 .../backend}/spec/pipeline/agent_runner.py | 0 .../backend}/spec/pipeline/models.py | 0 .../backend}/spec/pipeline/orchestrator.py | 0 .../backend}/spec/requirements.py | 0 .../backend}/spec/validate_pkg/README.md | 0 .../backend}/spec/validate_pkg/__init__.py | 0 .../backend}/spec/validate_pkg/auto_fix.py | 0 .../backend}/spec/validate_pkg/models.py | 0 .../backend}/spec/validate_pkg/schemas.py | 0 .../spec/validate_pkg/spec_validator.py | 0 .../spec/validate_pkg/validators/__init__.py | 0 .../validators/context_validator.py | 0 .../implementation_plan_validator.py | 0 .../validators/prereqs_validator.py | 0 .../validators/spec_document_validator.py | 0 .../backend}/spec/validate_spec.py | 0 .../backend}/spec/validation_strategy.py | 0 .../backend}/spec/validator.py | 0 {auto-claude => apps/backend}/spec/writer.py | 0 .../backend}/spec_contract.json | 0 .../backend}/task_logger/README.md | 0 .../backend}/task_logger/__init__.py | 0 .../backend}/task_logger/capture.py | 0 .../backend}/task_logger/logger.py | 0 .../backend}/task_logger/main.py | 0 .../backend}/task_logger/models.py | 0 .../backend}/task_logger/storage.py | 0 .../backend}/task_logger/streaming.py | 0 .../backend}/task_logger/utils.py | 0 .../backend}/test_discovery.py | 0 {auto-claude => apps/backend}/ui/__init__.py | 0 {auto-claude => apps/backend}/ui/boxes.py | 0 .../backend}/ui/capabilities.py | 0 {auto-claude => apps/backend}/ui/colors.py | 0 .../backend}/ui/formatters.py | 0 {auto-claude => apps/backend}/ui/icons.py | 0 {auto-claude => apps/backend}/ui/main.py | 0 {auto-claude => apps/backend}/ui/menu.py | 0 {auto-claude => apps/backend}/ui/progress.py | 0 {auto-claude => apps/backend}/ui/spinner.py | 0 {auto-claude => apps/backend}/ui/status.py | 0 .../backend}/ui/statusline.py | 0 .../backend}/validation_strategy.py | 0 apps/backend/workspace.py | 72 + {auto-claude => apps/backend}/worktree.py | 14 +- .../frontend}/.env.example | 0 {auto-claude-ui => apps/frontend}/.gitignore | 16 +- apps/frontend/.husky/pre-commit | 32 + apps/frontend/CONTRIBUTING.md | 166 + apps/frontend/README.md | 221 + {auto-claude-ui => apps/frontend}/design.json | 0 .../frontend}/e2e/electron-helper.ts | 0 .../frontend}/e2e/flows.e2e.ts | 0 .../frontend}/e2e/playwright.config.ts | 0 .../frontend}/electron.vite.config.ts | 6 +- .../frontend}/eslint.config.mjs | 20 +- .../frontend}/package-lock.json | 372 +- .../frontend}/package.json | 30 +- .../frontend/postcss.config.cjs | 0 .../resources/entitlements.mac.plist | 0 .../frontend}/resources/icon-256.png | Bin .../frontend}/resources/icon.icns | Bin .../frontend}/resources/icon.ico | Bin .../frontend}/resources/icon.png | Bin .../frontend/scripts/download-prebuilds.cjs | 0 .../frontend/scripts/postinstall.cjs | 2 +- .../frontend}/src/__mocks__/electron.ts | 0 .../integration/file-watcher.test.ts | 0 .../__tests__/integration/ipc-bridge.test.ts | 0 .../integration/subprocess-spawn.test.ts | 0 .../frontend}/src/__tests__/setup.ts | 0 .../src/main/__tests__/ipc-handlers.test.ts | 0 .../src/main/__tests__/project-store.test.ts | 0 .../rate-limit-auto-recovery.test.ts | 0 .../__tests__/rate-limit-detector.test.ts | 0 .../frontend}/src/main/agent-manager.ts | 0 .../frontend}/src/main/agent/agent-events.ts | 0 .../frontend}/src/main/agent/agent-manager.ts | 0 .../frontend}/src/main/agent/agent-process.ts | 12 +- .../frontend}/src/main/agent/agent-queue.ts | 0 .../frontend}/src/main/agent/agent-state.ts | 0 .../frontend}/src/main/agent/index.ts | 0 .../frontend}/src/main/agent/types.ts | 0 .../src/main/api-validation-service.ts | 0 .../frontend}/src/main/app-updater.ts | 0 .../frontend}/src/main/auto-claude-updater.ts | 0 .../frontend}/src/main/changelog-service.ts | 0 .../frontend}/src/main/changelog/README.md | 0 .../src/main/changelog/changelog-service.ts | 0 .../frontend}/src/main/changelog/formatter.ts | 0 .../frontend}/src/main/changelog/generator.ts | 0 .../src/main/changelog/git-integration.ts | 0 .../frontend}/src/main/changelog/index.ts | 0 .../frontend}/src/main/changelog/parser.ts | 0 .../frontend}/src/main/changelog/types.ts | 0 .../src/main/changelog/version-suggester.ts | 0 .../src/main/claude-profile-manager.ts | 0 .../src/main/claude-profile/README.md | 0 .../src/main/claude-profile/index.ts | 0 .../src/main/claude-profile/profile-scorer.ts | 0 .../main/claude-profile/profile-storage.ts | 0 .../src/main/claude-profile/profile-utils.ts | 0 .../main/claude-profile/rate-limit-manager.ts | 0 .../main/claude-profile/token-encryption.ts | 0 .../src/main/claude-profile/types.ts | 0 .../src/main/claude-profile/usage-monitor.ts | 0 .../src/main/claude-profile/usage-parser.ts | 0 .../frontend}/src/main/file-watcher.ts | 0 .../frontend}/src/main/index.ts | 2 +- .../frontend}/src/main/insights-service.ts | 0 .../frontend}/src/main/insights/README.md | 0 .../src/main/insights/REFACTORING_NOTES.md | 0 .../frontend}/src/main/insights/config.ts | 0 .../frontend}/src/main/insights/index.ts | 0 .../src/main/insights/insights-executor.ts | 0 .../frontend}/src/main/insights/paths.ts | 0 .../src/main/insights/session-manager.ts | 0 .../src/main/insights/session-storage.ts | 0 .../frontend}/src/main/integrations/index.ts | 0 .../frontend}/src/main/integrations/types.ts | 0 .../frontend}/src/main/ipc-handlers/README.md | 0 .../ipc-handlers/agent-events-handlers.ts | 0 .../main/ipc-handlers/app-update-handlers.ts | 0 .../ipc-handlers/autobuild-source-handlers.ts | 0 .../main/ipc-handlers/changelog-handlers.ts | 0 .../ipc-handlers/changelog-handlers.ts.bk | 0 .../src/main/ipc-handlers/context-handlers.ts | 0 .../src/main/ipc-handlers/context/README.md | 18 +- .../src/main/ipc-handlers/context/index.ts | 0 .../context/memory-data-handlers.ts | 0 .../context/memory-status-handlers.ts | 0 .../context/project-context-handlers.ts | 0 .../src/main/ipc-handlers/context/utils.ts | 0 .../src/main/ipc-handlers/env-handlers.ts | 0 .../src/main/ipc-handlers/file-handlers.ts | 0 .../src/main/ipc-handlers/github-handlers.ts | 0 .../main/ipc-handlers/github/ARCHITECTURE.md | 0 .../src/main/ipc-handlers/github/README.md | 0 .../github/__tests__/oauth-handlers.spec.ts | 0 .../ipc-handlers/github/import-handlers.ts | 0 .../src/main/ipc-handlers/github/index.ts | 0 .../github/investigation-handlers.ts | 0 .../ipc-handlers/github/issue-handlers.ts | 0 .../ipc-handlers/github/oauth-handlers.ts | 0 .../ipc-handlers/github/release-handlers.ts | 0 .../github/repository-handlers.ts | 0 .../main/ipc-handlers/github/spec-utils.ts | 0 .../src/main/ipc-handlers/github/types.ts | 0 .../src/main/ipc-handlers/github/utils.ts | 0 .../main/ipc-handlers/ideation-handlers.ts | 0 .../main/ipc-handlers/ideation/file-utils.ts | 0 .../ideation/generation-handlers.ts | 0 .../ipc-handlers/ideation/idea-manager.ts | 0 .../src/main/ipc-handlers/ideation/index.ts | 0 .../ipc-handlers/ideation/session-manager.ts | 0 .../ipc-handlers/ideation/task-converter.ts | 0 .../ipc-handlers/ideation/transformers.ts | 0 .../src/main/ipc-handlers/ideation/types.ts | 0 .../frontend}/src/main/ipc-handlers/index.ts | 6 +- .../main/ipc-handlers/insights-handlers.ts | 0 .../src/main/ipc-handlers/linear-handlers.ts | 0 .../src/main/ipc-handlers/memory-handlers.ts | 5 +- .../src/main/ipc-handlers/project-handlers.ts | 0 .../src/main/ipc-handlers/roadmap-handlers.ts | 0 .../sections/context-roadmap-section.txt | 0 .../sections/context_extracted.txt | 0 .../sections/ideation-insights-section.txt | 0 .../sections/integration-section.txt | 2 +- .../sections/roadmap_extracted.txt | 0 .../ipc-handlers/sections/task-section.txt | 0 .../ipc-handlers/sections/task_extracted.txt | 0 .../sections/terminal-section.txt | 0 .../sections/terminal_extracted.txt | 0 .../main/ipc-handlers/settings-handlers.ts | 0 .../src/main/ipc-handlers/task-handlers.ts | 0 .../src/main/ipc-handlers/task/README.md | 0 .../ipc-handlers/task/REFACTORING_SUMMARY.md | 0 .../ipc-handlers/task/archive-handlers.ts | 0 .../main/ipc-handlers/task/crud-handlers.ts | 0 .../ipc-handlers/task/execution-handlers.ts | 0 .../src/main/ipc-handlers/task/index.ts | 0 .../main/ipc-handlers/task/logs-handlers.ts | 0 .../src/main/ipc-handlers/task/shared.ts | 0 .../ipc-handlers/task/worktree-handlers.ts | 0 .../main/ipc-handlers/terminal-handlers.ts | 0 .../frontend}/src/main/ipc-handlers/utils.ts | 0 .../frontend}/src/main/ipc-setup.ts | 0 .../frontend}/src/main/log-service.ts | 0 .../frontend}/src/main/memory-service.ts | 0 .../src/main/notification-service.ts | 0 .../frontend}/src/main/project-initializer.ts | 0 .../frontend}/src/main/project-store.ts | 0 .../frontend}/src/main/python-detector.ts | 0 .../frontend}/src/main/python-env-manager.ts | 0 .../frontend}/src/main/rate-limit-detector.ts | 0 .../frontend}/src/main/release-service.ts | 0 .../frontend}/src/main/task-log-service.ts | 0 .../frontend}/src/main/terminal-manager.ts | 0 .../src/main/terminal-name-generator.ts | 0 .../src/main/terminal-session-store.ts | 0 .../terminal/claude-integration-handler.ts | 0 .../frontend}/src/main/terminal/index.ts | 0 .../src/main/terminal/output-parser.ts | 0 .../src/main/terminal/pty-daemon-client.ts | 0 .../frontend}/src/main/terminal/pty-daemon.ts | 0 .../src/main/terminal/pty-manager.ts | 0 .../src/main/terminal/session-handler.ts | 0 .../src/main/terminal/session-persistence.ts | 0 .../main/terminal/terminal-event-handler.ts | 0 .../src/main/terminal/terminal-lifecycle.ts | 0 .../src/main/terminal/terminal-manager.ts | 0 .../frontend}/src/main/terminal/types.ts | 0 .../frontend}/src/main/title-generator.ts | 0 .../frontend}/src/main/updater/config.ts | 0 .../src/main/updater/file-operations.ts | 0 .../frontend}/src/main/updater/http-client.ts | 0 .../src/main/updater/path-resolver.ts | 23 +- .../frontend}/src/main/updater/types.ts | 0 .../src/main/updater/update-checker.ts | 0 .../src/main/updater/update-installer.ts | 0 .../src/main/updater/update-status.ts | 0 .../src/main/updater/version-manager.ts | 0 .../frontend}/src/preload/api/agent-api.ts | 0 .../src/preload/api/app-update-api.ts | 0 .../frontend}/src/preload/api/file-api.ts | 0 .../frontend}/src/preload/api/index.ts | 0 .../src/preload/api/modules/README.md | 0 .../src/preload/api/modules/autobuild-api.ts | 0 .../src/preload/api/modules/changelog-api.ts | 0 .../src/preload/api/modules/github-api.ts | 0 .../src/preload/api/modules/ideation-api.ts | 0 .../src/preload/api/modules/index.ts | 0 .../src/preload/api/modules/insights-api.ts | 0 .../src/preload/api/modules/ipc-utils.ts | 0 .../src/preload/api/modules/linear-api.ts | 0 .../src/preload/api/modules/roadmap-api.ts | 0 .../src/preload/api/modules/shell-api.ts | 0 .../frontend}/src/preload/api/project-api.ts | 0 .../frontend}/src/preload/api/settings-api.ts | 0 .../frontend}/src/preload/api/task-api.ts | 0 .../frontend}/src/preload/api/terminal-api.ts | 0 .../frontend}/src/preload/index.ts | 0 .../frontend}/src/renderer/App.tsx | 0 .../src/renderer/__tests__/OAuthStep.test.tsx | 0 .../renderer/__tests__/TaskEditDialog.test.ts | 0 .../__tests__/project-store-tabs.test.ts | 0 .../renderer/__tests__/roadmap-store.test.ts | 0 .../src/renderer/__tests__/task-store.test.ts | 0 .../renderer/components/AddFeatureDialog.tsx | 0 .../renderer/components/AddProjectModal.tsx | 0 .../components/AgentProfileSelector.tsx | 0 .../src/renderer/components/AgentProfiles.tsx | 0 .../src/renderer/components/AppSettings.tsx | 0 .../components/AppUpdateNotification.tsx | 0 .../src/renderer/components/Changelog.tsx | 0 .../components/ChatHistorySidebar.tsx | 0 .../components/CompetitorAnalysisDialog.tsx | 0 .../components/CompetitorAnalysisViewer.tsx | 0 .../src/renderer/components/Context.tsx | 0 .../renderer/components/CustomModelModal.tsx | 0 .../renderer/components/EnvConfigModal.tsx | 0 .../ExistingCompetitorAnalysisDialog.tsx | 0 .../renderer/components/FileAutocomplete.tsx | 0 .../renderer/components/FileExplorerPanel.tsx | 0 .../src/renderer/components/FileTree.tsx | 0 .../src/renderer/components/FileTreeItem.tsx | 0 .../src/renderer/components/GitHubIssues.tsx | 0 .../renderer/components/GitHubSetupModal.tsx | 0 .../src/renderer/components/GitSetupModal.tsx | 0 .../src/renderer/components/Ideation.tsx | 0 .../src/renderer/components/ImageUpload.tsx | 0 .../src/renderer/components/Insights.tsx | 0 .../components/InsightsModelSelector.tsx | 0 .../src/renderer/components/KanbanBoard.tsx | 0 .../components/LinearTaskImportModal.tsx | 0 .../components/PhaseProgressIndicator.tsx | 0 .../components/ProactiveSwapListener.tsx | 0 .../renderer/components/ProjectSettings.tsx | 0 .../src/renderer/components/ProjectTabBar.tsx | 0 .../components/RateLimitIndicator.tsx | 0 .../renderer/components/RateLimitModal.tsx | 0 .../components/ReferencedFilesSection.tsx | 0 .../src/renderer/components/Roadmap.tsx | 0 .../components/RoadmapGenerationProgress.tsx | 0 .../renderer/components/RoadmapKanbanView.tsx | 0 .../renderer/components/SDKRateLimitModal.tsx | 0 .../src/renderer/components/Sidebar.tsx | 0 .../components/SortableFeatureCard.tsx | 0 .../components/SortableProjectTab.tsx | 0 .../renderer/components/SortableTaskCard.tsx | 0 .../src/renderer/components/TaskCard.tsx | 0 .../components/TaskCreationWizard.tsx | 0 .../renderer/components/TaskDetailPanel.tsx | 0 .../renderer/components/TaskEditDialog.tsx | 0 .../components/TaskFileExplorerDrawer.tsx | 0 .../src/renderer/components/Terminal.tsx | 0 .../src/renderer/components/TerminalGrid.tsx | 0 .../renderer/components/UsageIndicator.tsx | 0 .../src/renderer/components/WelcomeScreen.tsx | 0 .../src/renderer/components/Worktrees.tsx | 0 .../__tests__/ProjectTabBar.test.tsx | 0 .../RoadmapGenerationProgress.test.tsx | 0 .../components/changelog/ArchiveTasksCard.tsx | 0 .../components/changelog/Changelog.tsx | 0 .../components/changelog/ChangelogDetails.tsx | 0 .../components/changelog/ChangelogEntry.tsx | 0 .../components/changelog/ChangelogFilters.tsx | 0 .../components/changelog/ChangelogHeader.tsx | 0 .../components/changelog/ChangelogList.tsx | 0 .../changelog/ConfigurationPanel.tsx | 0 .../changelog/GitHubReleaseCard.tsx | 0 .../components/changelog/PreviewPanel.tsx | 0 .../changelog/REFACTORING_SUMMARY.md | 0 .../changelog/Step3SuccessScreen.tsx | 0 .../changelog/hooks/useChangelog.ts | 0 .../changelog/hooks/useImageUpload.ts | 0 .../renderer/components/changelog/index.ts | 0 .../renderer/components/changelog/utils.ts | 0 .../renderer/components/context/Context.tsx | 0 .../renderer/components/context/InfoItem.tsx | 0 .../components/context/MemoriesTab.tsx | 0 .../components/context/MemoryCard.tsx | 0 .../components/context/ProjectIndexTab.tsx | 0 .../src/renderer/components/context/README.md | 0 .../components/context/ServiceCard.tsx | 0 .../renderer/components/context/constants.ts | 0 .../src/renderer/components/context/hooks.ts | 0 .../src/renderer/components/context/index.ts | 0 .../service-sections/APIRoutesSection.tsx | 0 .../service-sections/DatabaseSection.tsx | 0 .../service-sections/DependenciesSection.tsx | 0 .../service-sections/EnvironmentSection.tsx | 0 .../ExternalServicesSection.tsx | 0 .../service-sections/MonitoringSection.tsx | 0 .../context/service-sections/index.ts | 0 .../src/renderer/components/context/types.ts | 0 .../src/renderer/components/context/utils.ts | 0 .../components/github-issues/ARCHITECTURE.md | 0 .../components/github-issues/README.md | 0 .../github-issues/REFACTORING_SUMMARY.md | 0 .../github-issues/components/EmptyStates.tsx | 0 .../components/InvestigationDialog.tsx | 0 .../github-issues/components/IssueDetail.tsx | 0 .../github-issues/components/IssueList.tsx | 0 .../components/IssueListHeader.tsx | 0 .../components/IssueListItem.tsx | 0 .../github-issues/components/index.ts | 0 .../components/github-issues/hooks/index.ts | 0 .../hooks/useGitHubInvestigation.ts | 0 .../github-issues/hooks/useGitHubIssues.ts | 0 .../github-issues/hooks/useIssueFiltering.ts | 0 .../components/github-issues/index.ts | 0 .../components/github-issues/types/index.ts | 0 .../components/github-issues/utils/index.ts | 0 .../ideation/GenerationProgressScreen.tsx | 0 .../renderer/components/ideation/IdeaCard.tsx | 0 .../components/ideation/IdeaDetailPanel.tsx | 0 .../components/ideation/IdeaSkeletonCard.tsx | 0 .../renderer/components/ideation/Ideation.tsx | 0 .../components/ideation/IdeationDialogs.tsx | 0 .../ideation/IdeationEmptyState.tsx | 0 .../components/ideation/IdeationFilters.tsx | 0 .../components/ideation/IdeationHeader.tsx | 0 .../renderer/components/ideation/TypeIcon.tsx | 0 .../components/ideation/TypeStateIcon.tsx | 0 .../renderer/components/ideation/constants.ts | 0 .../details/CodeImprovementDetails.tsx | 0 .../ideation/details/CodeQualityDetails.tsx | 0 .../details/DocumentationGapDetails.tsx | 0 .../PerformanceOptimizationDetails.tsx | 0 .../details/SecurityHardeningDetails.tsx | 0 .../ideation/details/UIUXDetails.tsx | 0 .../components/ideation/hooks/useIdeation.ts | 0 .../src/renderer/components/ideation/index.ts | 0 .../components/ideation/type-guards.ts | 0 .../src/renderer/components/index.ts | 0 .../LinearTaskImportModalRefactored.tsx | 0 .../components/linear-import/README.md | 0 .../linear-import/REFACTORING_SUMMARY.md | 0 .../linear-import/components/ErrorBanner.tsx | 0 .../components/ImportSuccessBanner.tsx | 0 .../linear-import/components/IssueCard.tsx | 0 .../linear-import/components/IssueList.tsx | 0 .../components/SearchAndFilterBar.tsx | 0 .../components/SelectionControls.tsx | 0 .../components/TeamProjectSelector.tsx | 0 .../linear-import/components/index.ts | 0 .../components/linear-import/hooks/index.ts | 0 .../linear-import/hooks/useIssueFiltering.ts | 0 .../linear-import/hooks/useIssueSelection.ts | 0 .../linear-import/hooks/useLinearImport.ts | 0 .../hooks/useLinearImportModal.ts | 0 .../linear-import/hooks/useLinearIssues.ts | 0 .../linear-import/hooks/useLinearProjects.ts | 0 .../linear-import/hooks/useLinearTeams.ts | 0 .../components/linear-import/index.ts | 0 .../components/linear-import/types.ts | 0 .../components/onboarding/CompletionStep.tsx | 0 .../components/onboarding/FirstSpecStep.tsx | 0 .../components/onboarding/GraphitiStep.tsx | 5 +- .../components/onboarding/MemoryStep.tsx | 0 .../components/onboarding/OAuthStep.tsx | 0 .../onboarding/OllamaModelSelector.tsx | 0 .../onboarding/OnboardingWizard.tsx | 0 .../components/onboarding/WelcomeStep.tsx | 4 +- .../components/onboarding/WizardProgress.tsx | 0 .../renderer/components/onboarding/index.ts | 0 .../project-settings/AgentConfigSection.tsx | 0 .../project-settings/AutoBuildIntegration.tsx | 0 .../project-settings/ClaudeAuthSection.tsx | 0 .../project-settings/ClaudeOAuthFlow.tsx | 0 .../project-settings/CollapsibleSection.tsx | 0 .../project-settings/ConnectionStatus.tsx | 0 .../project-settings/EnvironmentSettings.tsx | 0 .../project-settings/GeneralSettings.tsx | 0 .../GitHubIntegrationSection.tsx | 0 .../project-settings/GitHubOAuthFlow.tsx | 0 .../project-settings/InfrastructureStatus.tsx | 0 .../project-settings/IntegrationSettings.tsx | 0 .../LinearIntegrationSection.tsx | 0 .../project-settings/MemoryBackendSection.tsx | 0 .../project-settings/NotificationsSection.tsx | 0 .../project-settings/PasswordInput.tsx | 0 .../project-settings/ProjectSettings.tsx | 0 .../components/project-settings/README.md | 14 +- .../project-settings/SecuritySettings.tsx | 0 .../project-settings/StatusBadge.tsx | 0 .../hooks/useProjectSettings.ts | 0 .../components/project-settings/index.ts | 0 .../components/roadmap/FeatureCard.tsx | 0 .../components/roadmap/FeatureDetailPanel.tsx | 0 .../renderer/components/roadmap/PhaseCard.tsx | 0 .../src/renderer/components/roadmap/README.md | 0 .../components/roadmap/RoadmapEmptyState.tsx | 0 .../components/roadmap/RoadmapHeader.tsx | 0 .../components/roadmap/RoadmapTabs.tsx | 0 .../src/renderer/components/roadmap/hooks.ts | 0 .../src/renderer/components/roadmap/index.ts | 0 .../src/renderer/components/roadmap/types.ts | 0 .../src/renderer/components/roadmap/utils.ts | 0 .../components/settings/AdvancedSettings.tsx | 0 .../settings/AgentProfileSettings.tsx | 0 .../components/settings/AppSettings.tsx | 0 .../components/settings/GeneralSettings.tsx | 0 .../settings/IntegrationSettings.tsx | 0 .../components/settings/ProjectSelector.tsx | 0 .../settings/ProjectSettingsContent.tsx | 0 .../renderer/components/settings/README.md | 0 .../settings/REFACTORING_SUMMARY.md | 0 .../components/settings/SettingsSection.tsx | 0 .../components/settings/ThemeSelector.tsx | 0 .../components/settings/ThemeSettings.tsx | 0 .../settings/common/EmptyProjectState.tsx | 0 .../settings/common/ErrorDisplay.tsx | 0 .../settings/common/InitializationGuard.tsx | 0 .../components/settings/common/index.ts | 0 .../components/settings/hooks/useSettings.ts | 0 .../src/renderer/components/settings/index.ts | 0 .../integrations/GitHubIntegration.tsx | 0 .../integrations/LinearIntegration.tsx | 0 .../components/settings/integrations/index.ts | 0 .../settings/sections/SectionRouter.tsx | 0 .../components/settings/sections/index.ts | 0 .../settings/utils/hookProxyFactory.ts | 0 .../components/settings/utils/index.ts | 0 .../renderer/components/task-detail/README.md | 0 .../components/task-detail/TaskActions.tsx | 0 .../task-detail/TaskDetailModal.tsx | 0 .../task-detail/TaskDetailPanel.tsx | 0 .../components/task-detail/TaskHeader.tsx | 0 .../components/task-detail/TaskLogs.tsx | 0 .../components/task-detail/TaskMetadata.tsx | 0 .../components/task-detail/TaskProgress.tsx | 0 .../components/task-detail/TaskReview.tsx | 0 .../components/task-detail/TaskSubtasks.tsx | 0 .../components/task-detail/TaskWarnings.tsx | 0 .../task-detail/hooks/useTaskDetail.ts | 0 .../renderer/components/task-detail/index.ts | 0 .../task-review/ConflictDetailsDialog.tsx | 0 .../task-review/DiffViewDialog.tsx | 0 .../task-detail/task-review/DiscardDialog.tsx | 0 .../task-review/MergePreviewSummary.tsx | 0 .../task-review/QAFeedbackSection.tsx | 0 .../task-detail/task-review/README.md | 0 .../task-review/StagedSuccessMessage.tsx | 0 .../task-review/WorkspaceMessages.tsx | 0 .../task-review/WorkspaceStatus.tsx | 0 .../task-detail/task-review/index.ts | 0 .../task-detail/task-review/utils.tsx | 0 .../renderer/components/terminal/README.md | 0 .../terminal/REFACTORING_SUMMARY.md | 0 .../components/terminal/TaskSelector.tsx | 0 .../components/terminal/TerminalHeader.tsx | 0 .../components/terminal/TerminalTitle.tsx | 0 .../src/renderer/components/terminal/index.ts | 0 .../src/renderer/components/terminal/types.ts | 0 .../components/terminal/useAutoNaming.ts | 0 .../components/terminal/usePtyProcess.ts | 0 .../components/terminal/useTerminalEvents.ts | 0 .../renderer/components/terminal/useXterm.ts | 0 .../renderer/components/ui/alert-dialog.tsx | 0 .../src/renderer/components/ui/badge.tsx | 0 .../src/renderer/components/ui/button.tsx | 0 .../src/renderer/components/ui/card.tsx | 0 .../src/renderer/components/ui/checkbox.tsx | 0 .../renderer/components/ui/collapsible.tsx | 0 .../src/renderer/components/ui/dialog.tsx | 0 .../renderer/components/ui/dropdown-menu.tsx | 0 .../components/ui/full-screen-dialog.tsx | 0 .../src/renderer/components/ui/index.ts | 0 .../src/renderer/components/ui/input.tsx | 0 .../src/renderer/components/ui/label.tsx | 0 .../src/renderer/components/ui/progress.tsx | 0 .../renderer/components/ui/radio-group.tsx | 0 .../renderer/components/ui/scroll-area.tsx | 0 .../src/renderer/components/ui/select.tsx | 0 .../src/renderer/components/ui/separator.tsx | 0 .../src/renderer/components/ui/switch.tsx | 0 .../src/renderer/components/ui/tabs.tsx | 0 .../src/renderer/components/ui/textarea.tsx | 0 .../src/renderer/components/ui/tooltip.tsx | 0 .../__tests__/useVirtualizedTree.test.ts | 0 .../frontend}/src/renderer/hooks/index.ts | 0 .../src/renderer/hooks/useClaudeAuth.ts | 0 .../renderer/hooks/useEnvironmentConfig.ts | 0 .../src/renderer/hooks/useGitHubConnection.ts | 0 .../renderer/hooks/useInfrastructureStatus.ts | 0 .../frontend}/src/renderer/hooks/useIpc.ts | 0 .../src/renderer/hooks/useLinearConnection.ts | 0 .../src/renderer/hooks/useProjectSettings.ts | 0 .../src/renderer/hooks/useVirtualizedTree.ts | 0 .../frontend}/src/renderer/index.html | 0 .../src/renderer/lib/browser-mock.ts | 0 .../src/renderer/lib/buffer-persistence.ts | 0 .../src/renderer/lib/flow-controller.ts | 0 .../frontend}/src/renderer/lib/icons.ts | 0 .../src/renderer/lib/mocks/README.md | 2 +- .../src/renderer/lib/mocks/changelog-mock.ts | 0 .../renderer/lib/mocks/claude-profile-mock.ts | 0 .../src/renderer/lib/mocks/context-mock.ts | 0 .../frontend}/src/renderer/lib/mocks/index.ts | 0 .../renderer/lib/mocks/infrastructure-mock.ts | 0 .../src/renderer/lib/mocks/insights-mock.ts | 0 .../renderer/lib/mocks/integration-mock.ts | 0 .../src/renderer/lib/mocks/mock-data.ts | 0 .../src/renderer/lib/mocks/project-mock.ts | 0 .../src/renderer/lib/mocks/roadmap-mock.ts | 0 .../src/renderer/lib/mocks/settings-mock.ts | 0 .../src/renderer/lib/mocks/task-mock.ts | 0 .../src/renderer/lib/mocks/terminal-mock.ts | 0 .../src/renderer/lib/mocks/workspace-mock.ts | 0 .../src/renderer/lib/scroll-controller.ts | 0 .../renderer/lib/terminal-buffer-manager.ts | 0 .../frontend}/src/renderer/lib/utils.ts | 0 .../src/renderer/lib/webgl-context-manager.ts | 0 .../frontend}/src/renderer/lib/webgl-utils.ts | 0 .../frontend}/src/renderer/main.tsx | 0 .../src/renderer/stores/changelog-store.ts | 0 .../renderer/stores/claude-profile-store.ts | 0 .../src/renderer/stores/context-store.ts | 0 .../renderer/stores/file-explorer-store.ts | 0 .../src/renderer/stores/github-store.ts | 0 .../src/renderer/stores/ideation-store.ts | 0 .../src/renderer/stores/insights-store.ts | 0 .../src/renderer/stores/project-store.ts | 0 .../src/renderer/stores/rate-limit-store.ts | 0 .../src/renderer/stores/release-store.ts | 0 .../src/renderer/stores/roadmap-store.ts | 0 .../src/renderer/stores/settings-store.ts | 0 .../src/renderer/stores/task-store.ts | 0 .../src/renderer/stores/terminal-store.ts | 0 .../frontend}/src/renderer/styles/globals.css | 0 .../src/shared/__tests__/progress.test.ts | 0 .../frontend}/src/shared/constants.ts | 0 .../src/shared/constants/changelog.ts | 0 .../frontend}/src/shared/constants/config.ts | 0 .../frontend}/src/shared/constants/github.ts | 0 .../src/shared/constants/ideation.ts | 0 .../frontend}/src/shared/constants/index.ts | 0 .../frontend}/src/shared/constants/ipc.ts | 0 .../frontend}/src/shared/constants/models.ts | 0 .../frontend}/src/shared/constants/roadmap.ts | 0 .../frontend}/src/shared/constants/task.ts | 0 .../frontend}/src/shared/constants/themes.ts | 0 .../frontend}/src/shared/progress.ts | 0 .../frontend}/src/shared/types.ts | 0 .../frontend}/src/shared/types/agent.ts | 0 .../frontend}/src/shared/types/app-update.ts | 0 .../frontend}/src/shared/types/changelog.ts | 0 .../frontend}/src/shared/types/common.ts | 0 .../frontend}/src/shared/types/index.ts | 0 .../frontend}/src/shared/types/insights.ts | 0 .../src/shared/types/integrations.ts | 0 .../frontend}/src/shared/types/ipc.ts | 0 .../frontend}/src/shared/types/project.ts | 0 .../frontend}/src/shared/types/roadmap.ts | 0 .../frontend}/src/shared/types/settings.ts | 0 .../frontend}/src/shared/types/task.ts | 0 .../src/shared/types/terminal-session.ts | 0 .../frontend}/src/shared/types/terminal.ts | 0 .../src/shared/utils/debug-logger.ts | 0 .../src/shared/utils/shell-escape.ts | 0 .../frontend}/tsconfig.json | 6 +- .../frontend}/vitest.config.ts | 0 auto-claude-ui/.husky/pre-commit | 1 - auto-claude-ui/.npmrc | 1 - auto-claude-ui/README.md | 131 - auto-claude-ui/pnpm-lock.yaml | 9588 ----------------- .../src/main/agent-manager.ts.backup | 1101 -- .../src/main/ipc-handlers.ts.backup | 6913 ------------ .../src/main/ipc-handlers/docker-handlers.ts | 20 - .../main/ipc-handlers/task-handlers.ts.backup | 1885 ---- .../project-settings/REFACTORING_SUMMARY.md | 325 - auto-claude/__init__.py | 23 - auto-claude/agents/__init__.py | 70 - auto-claude/analyzer.py | 7 - auto-claude/analyzers/__init__.py | 3 - auto-claude/auto_claude_tools.py | 13 - auto-claude/client.py | 17 - auto-claude/debug.py | 3 - auto-claude/implementation_plan.py | 4 - auto-claude/linear_integration.py | 3 - auto-claude/linear_updater.py | 3 - auto-claude/merge/ARCHITECTURE.md | 200 - auto-claude/merge/REFACTORING_DETAILS.md | 278 - auto-claude/merge/REFACTORING_SUMMARY.md | 182 - auto-claude/merge/auto_merger_old.py | 654 -- auto-claude/progress.py | 3 - .../prompts/_archived_ideation_high_value.md | 428 - .../_archived_ideation_low_hanging_fruit.md | 315 - .../runners/ai_analyzer/REFACTORING.md | 284 - auto-claude/spec/validate_pkg/MIGRATION.md | 198 - auto-claude/validate_spec/__init__.py | 45 - auto-claude/validate_spec/auto_fix.py | 39 - auto-claude/validate_spec/spec_validator.py | 41 - auto-claude/workspace.py | 45 - guides/CLI-USAGE.md | 13 +- guides/DOCKER-SETUP.md | 435 - package.json | 40 + pnpm-lock.yaml | 9 + scripts/bump-version.js | 29 +- scripts/install-backend.js | 104 + scripts/test-backend.js | 53 + tests/conftest.py | 4 +- tests/qa_report_helpers.py | 2 +- tests/review_fixtures.py | 2 +- tests/test_agent_architecture.py | 30 +- tests/test_analyzer_port_detection.py | 2 +- tests/test_ci_discovery.py | 2 +- tests/test_critique_integration.py | 2 +- tests/test_discovery.py | 2 +- tests/test_graphiti.py | 2 +- tests/test_merge_auto_merger.py | 2 +- tests/test_merge_conflict_detector.py | 2 +- tests/test_merge_file_tracker.py | 2 +- tests/test_merge_fixtures.py | 2 +- tests/test_merge_orchestrator.py | 2 +- tests/test_merge_parallel.py | 2 +- tests/test_merge_semantic_analyzer.py | 2 +- tests/test_merge_types.py | 2 +- tests/test_qa_criteria.py | 2 +- tests/test_qa_loop_enhancements.py | 2 +- tests/test_risk_classifier.py | 2 +- tests/test_security_scanner.py | 2 +- tests/test_service_orchestrator.py | 2 +- tests/test_spec_complexity.py | 2 +- tests/test_spec_pipeline.py | 2 +- tests/test_thinking_level_validation.py | 2 +- tests/test_validation_strategy.py | 2 +- 1061 files changed, 2322 insertions(+), 24226 deletions(-) create mode 100644 .husky/commit-msg rename {auto-claude => apps/backend}/.env.example (98%) rename {auto-claude => apps/backend}/.gitignore (94%) create mode 100644 apps/backend/README.md create mode 100644 apps/backend/__init__.py rename {auto-claude => apps/backend}/agent.py (100%) rename {auto-claude => apps/backend}/agents/README.md (100%) create mode 100644 apps/backend/agents/__init__.py rename {auto-claude => apps/backend}/agents/auto_claude_tools.py (100%) rename {auto-claude => apps/backend}/agents/base.py (100%) rename {auto-claude => apps/backend}/agents/coder.py (100%) rename {auto-claude => apps/backend}/agents/memory_manager.py (100%) rename {auto-claude => apps/backend}/agents/planner.py (100%) rename {auto-claude => apps/backend}/agents/session.py (100%) rename {auto-claude => apps/backend}/agents/test_refactoring.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/__init__.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/models.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/permissions.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/registry.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/tools/__init__.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/tools/memory.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/tools/progress.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/tools/qa.py (100%) rename {auto-claude => apps/backend}/agents/tools_pkg/tools/subtask.py (100%) rename {auto-claude => apps/backend}/agents/utils.py (100%) rename {auto-claude => apps/backend}/analysis/__init__.py (100%) rename {auto-claude => apps/backend}/analysis/analyzer.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/__init__.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/base.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context/__init__.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context/api_docs_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context/auth_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context/env_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context/jobs_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context/migrations_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context/monitoring_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context/services_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/context_analyzer.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/database_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/framework_analyzer.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/port_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/project_analyzer_module.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/route_detector.py (100%) rename {auto-claude => apps/backend}/analysis/analyzers/service_analyzer.py (100%) rename {auto-claude => apps/backend}/analysis/ci_discovery.py (100%) rename {auto-claude => apps/backend}/analysis/insight_extractor.py (100%) rename {auto-claude => apps/backend}/analysis/project_analyzer.py (100%) rename {auto-claude => apps/backend}/analysis/risk_classifier.py (100%) rename {auto-claude => apps/backend}/analysis/security_scanner.py (100%) rename {auto-claude => apps/backend}/analysis/test_discovery.py (100%) create mode 100644 apps/backend/analyzer.py create mode 100644 apps/backend/auto_claude_tools.py rename {auto-claude => apps/backend}/ci_discovery.py (100%) rename {auto-claude => apps/backend}/cli/__init__.py (100%) rename {auto-claude => apps/backend}/cli/build_commands.py (100%) rename {auto-claude => apps/backend}/cli/followup_commands.py (100%) rename {auto-claude => apps/backend}/cli/input_handlers.py (100%) rename {auto-claude => apps/backend}/cli/main.py (100%) rename {auto-claude => apps/backend}/cli/qa_commands.py (100%) rename {auto-claude => apps/backend}/cli/spec_commands.py (58%) rename {auto-claude => apps/backend}/cli/utils.py (100%) rename {auto-claude => apps/backend}/cli/workspace_commands.py (100%) create mode 100644 apps/backend/client.py rename {auto-claude => apps/backend}/commit_message.py (100%) rename {auto-claude => apps/backend}/context/__init__.py (100%) rename {auto-claude => apps/backend}/context/builder.py (100%) rename {auto-claude => apps/backend}/context/categorizer.py (100%) rename {auto-claude => apps/backend}/context/constants.py (100%) rename {auto-claude => apps/backend}/context/graphiti_integration.py (100%) rename {auto-claude => apps/backend}/context/keyword_extractor.py (100%) rename {auto-claude => apps/backend}/context/main.py (100%) rename {auto-claude => apps/backend}/context/models.py (100%) rename {auto-claude => apps/backend}/context/pattern_discovery.py (100%) rename {auto-claude => apps/backend}/context/search.py (100%) rename {auto-claude => apps/backend}/context/serialization.py (100%) rename {auto-claude => apps/backend}/context/service_matcher.py (100%) rename {auto-claude => apps/backend}/core/__init__.py (100%) rename {auto-claude => apps/backend}/core/agent.py (100%) rename {auto-claude => apps/backend}/core/auth.py (100%) rename {auto-claude => apps/backend}/core/client.py (98%) rename {auto-claude => apps/backend}/core/debug.py (100%) rename {auto-claude => apps/backend}/core/progress.py (100%) rename {auto-claude => apps/backend}/core/workspace.py (100%) rename {auto-claude => apps/backend}/core/workspace/README.md (100%) rename {auto-claude => apps/backend}/core/workspace/__init__.py (100%) rename {auto-claude => apps/backend}/core/workspace/display.py (100%) rename {auto-claude => apps/backend}/core/workspace/finalization.py (100%) rename {auto-claude => apps/backend}/core/workspace/git_utils.py (100%) rename {auto-claude => apps/backend}/core/workspace/models.py (100%) rename {auto-claude => apps/backend}/core/workspace/setup.py (100%) rename {auto-claude => apps/backend}/core/worktree.py (100%) rename {auto-claude => apps/backend}/critique.py (100%) create mode 100644 apps/backend/debug.py rename {auto-claude => apps/backend}/graphiti_config.py (100%) rename {auto-claude => apps/backend}/graphiti_providers.py (100%) rename {auto-claude => apps/backend}/ideation/__init__.py (100%) rename {auto-claude => apps/backend}/ideation/analyzer.py (100%) rename {auto-claude => apps/backend}/ideation/config.py (100%) rename {auto-claude => apps/backend}/ideation/formatter.py (100%) rename {auto-claude => apps/backend}/ideation/generator.py (100%) rename {auto-claude => apps/backend}/ideation/output_streamer.py (100%) rename {auto-claude => apps/backend}/ideation/phase_executor.py (100%) rename {auto-claude => apps/backend}/ideation/prioritizer.py (100%) rename {auto-claude => apps/backend}/ideation/project_index_phase.py (100%) rename {auto-claude => apps/backend}/ideation/runner.py (100%) rename {auto-claude => apps/backend}/ideation/script_runner.py (100%) rename {auto-claude => apps/backend}/ideation/types.py (100%) rename {auto-claude => apps/backend}/implementation_plan/__init__.py (100%) rename {auto-claude => apps/backend}/implementation_plan/enums.py (100%) rename {auto-claude => apps/backend}/implementation_plan/factories.py (100%) rename {auto-claude => apps/backend}/implementation_plan/main.py (100%) rename {auto-claude => apps/backend}/implementation_plan/phase.py (100%) rename {auto-claude => apps/backend}/implementation_plan/plan.py (100%) rename {auto-claude => apps/backend}/implementation_plan/subtask.py (100%) rename {auto-claude => apps/backend}/implementation_plan/verification.py (100%) rename {auto-claude => apps/backend}/init.py (100%) rename {auto-claude => apps/backend}/insight_extractor.py (100%) rename {auto-claude => apps/backend}/integrations/__init__.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/__init__.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/config.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/memory.py (96%) rename {auto-claude => apps/backend}/integrations/graphiti/migrate_embeddings.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/__init__.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/cross_encoder.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/embedder_providers/__init__.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/exceptions.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/factory.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/llm_providers/__init__.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/llm_providers/google_llm.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/models.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/utils.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/providers_pkg/validators.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/queries_pkg/__init__.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/queries_pkg/client.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/queries_pkg/graphiti.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/queries_pkg/kuzu_driver_patched.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/queries_pkg/queries.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/queries_pkg/schema.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/queries_pkg/search.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/test_graphiti_memory.py (100%) rename {auto-claude => apps/backend}/integrations/graphiti/test_provider_naming.py (100%) rename {auto-claude => apps/backend}/integrations/linear/__init__.py (100%) rename {auto-claude => apps/backend}/integrations/linear/config.py (100%) rename {auto-claude => apps/backend}/integrations/linear/integration.py (100%) rename {auto-claude => apps/backend}/integrations/linear/updater.py (100%) rename {auto-claude => apps/backend}/linear_config.py (100%) create mode 100644 apps/backend/linear_integration.py create mode 100644 apps/backend/linear_updater.py rename {auto-claude => apps/backend}/memory/__init__.py (97%) rename {auto-claude => apps/backend}/memory/codebase_map.py (100%) rename {auto-claude => apps/backend}/memory/graphiti_helpers.py (100%) rename {auto-claude => apps/backend}/memory/main.py (100%) mode change 100755 => 100644 rename {auto-claude => apps/backend}/memory/paths.py (100%) rename {auto-claude => apps/backend}/memory/patterns.py (100%) rename {auto-claude => apps/backend}/memory/sessions.py (100%) rename {auto-claude => apps/backend}/memory/summary.py (100%) rename {auto-claude => apps/backend}/merge/__init__.py (100%) rename {auto-claude => apps/backend}/merge/ai_resolver.py (100%) rename {auto-claude => apps/backend}/merge/ai_resolver/README.md (100%) rename {auto-claude => apps/backend}/merge/ai_resolver/__init__.py (100%) rename {auto-claude => apps/backend}/merge/ai_resolver/claude_client.py (100%) rename {auto-claude => apps/backend}/merge/ai_resolver/context.py (100%) rename {auto-claude => apps/backend}/merge/ai_resolver/language_utils.py (100%) rename {auto-claude => apps/backend}/merge/ai_resolver/parsers.py (100%) rename {auto-claude => apps/backend}/merge/ai_resolver/prompts.py (100%) rename {auto-claude => apps/backend}/merge/ai_resolver/resolver.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/__init__.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/context.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/helpers.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/merger.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/strategies/__init__.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/strategies/append_strategy.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/strategies/base_strategy.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/strategies/hooks_strategy.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/strategies/import_strategy.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/strategies/ordering_strategy.py (100%) rename {auto-claude => apps/backend}/merge/auto_merger/strategies/props_strategy.py (100%) rename {auto-claude => apps/backend}/merge/compatibility_rules.py (100%) rename {auto-claude => apps/backend}/merge/conflict_analysis.py (100%) rename {auto-claude => apps/backend}/merge/conflict_detector.py (100%) rename {auto-claude => apps/backend}/merge/conflict_explanation.py (100%) rename {auto-claude => apps/backend}/merge/conflict_resolver.py (100%) rename {auto-claude => apps/backend}/merge/file_evolution.py (100%) rename {auto-claude => apps/backend}/merge/file_evolution/__init__.py (100%) rename {auto-claude => apps/backend}/merge/file_evolution/baseline_capture.py (100%) rename {auto-claude => apps/backend}/merge/file_evolution/evolution_queries.py (100%) rename {auto-claude => apps/backend}/merge/file_evolution/modification_tracker.py (100%) rename {auto-claude => apps/backend}/merge/file_evolution/storage.py (100%) rename {auto-claude => apps/backend}/merge/file_evolution/tracker.py (100%) rename {auto-claude => apps/backend}/merge/file_merger.py (100%) rename {auto-claude => apps/backend}/merge/file_timeline.py (100%) rename {auto-claude => apps/backend}/merge/git_utils.py (100%) rename {auto-claude => apps/backend}/merge/hooks/post-commit (100%) mode change 100755 => 100644 rename {auto-claude => apps/backend}/merge/install_hook.py (100%) rename {auto-claude => apps/backend}/merge/merge_pipeline.py (100%) rename {auto-claude => apps/backend}/merge/models.py (100%) rename {auto-claude => apps/backend}/merge/orchestrator.py (100%) rename {auto-claude => apps/backend}/merge/prompts.py (100%) rename {auto-claude => apps/backend}/merge/semantic_analysis/__init__.py (100%) rename {auto-claude => apps/backend}/merge/semantic_analysis/comparison.py (100%) rename {auto-claude => apps/backend}/merge/semantic_analysis/js_analyzer.py (100%) rename {auto-claude => apps/backend}/merge/semantic_analysis/models.py (100%) rename {auto-claude => apps/backend}/merge/semantic_analysis/python_analyzer.py (100%) rename {auto-claude => apps/backend}/merge/semantic_analysis/regex_analyzer.py (100%) rename {auto-claude => apps/backend}/merge/semantic_analyzer.py (100%) rename {auto-claude => apps/backend}/merge/timeline_git.py (100%) rename {auto-claude => apps/backend}/merge/timeline_models.py (100%) rename {auto-claude => apps/backend}/merge/timeline_persistence.py (100%) rename {auto-claude => apps/backend}/merge/timeline_tracker.py (100%) rename {auto-claude => apps/backend}/merge/tracker_cli.py (100%) rename {auto-claude => apps/backend}/merge/types.py (100%) rename {auto-claude => apps/backend}/ollama_model_detector.py (100%) rename {auto-claude => apps/backend}/phase_config.py (100%) rename {auto-claude => apps/backend}/planner_lib/__init__.py (100%) rename {auto-claude => apps/backend}/planner_lib/context.py (100%) rename {auto-claude => apps/backend}/planner_lib/generators.py (100%) rename {auto-claude => apps/backend}/planner_lib/main.py (100%) rename {auto-claude => apps/backend}/planner_lib/models.py (100%) rename {auto-claude => apps/backend}/planner_lib/utils.py (100%) rename {auto-claude => apps/backend}/prediction/__init__.py (100%) rename {auto-claude => apps/backend}/prediction/checklist_generator.py (100%) rename {auto-claude => apps/backend}/prediction/formatter.py (100%) rename {auto-claude => apps/backend}/prediction/main.py (100%) rename {auto-claude => apps/backend}/prediction/memory_loader.py (100%) rename {auto-claude => apps/backend}/prediction/models.py (100%) rename {auto-claude => apps/backend}/prediction/patterns.py (100%) rename {auto-claude => apps/backend}/prediction/predictor.py (100%) rename {auto-claude => apps/backend}/prediction/risk_analyzer.py (100%) create mode 100644 apps/backend/progress.py rename {auto-claude => apps/backend}/project/__init__.py (100%) rename {auto-claude => apps/backend}/project/analyzer.py (100%) rename {auto-claude => apps/backend}/project/command_registry.py (100%) rename {auto-claude => apps/backend}/project/command_registry/README.md (100%) rename {auto-claude => apps/backend}/project/command_registry/__init__.py (100%) rename {auto-claude => apps/backend}/project/command_registry/base.py (100%) rename {auto-claude => apps/backend}/project/command_registry/cloud.py (100%) rename {auto-claude => apps/backend}/project/command_registry/code_quality.py (100%) rename {auto-claude => apps/backend}/project/command_registry/databases.py (100%) rename {auto-claude => apps/backend}/project/command_registry/frameworks.py (100%) rename {auto-claude => apps/backend}/project/command_registry/infrastructure.py (100%) rename {auto-claude => apps/backend}/project/command_registry/languages.py (100%) rename {auto-claude => apps/backend}/project/command_registry/package_managers.py (100%) rename {auto-claude => apps/backend}/project/command_registry/version_managers.py (100%) rename {auto-claude => apps/backend}/project/config_parser.py (100%) rename {auto-claude => apps/backend}/project/framework_detector.py (100%) rename {auto-claude => apps/backend}/project/models.py (100%) rename {auto-claude => apps/backend}/project/stack_detector.py (100%) rename {auto-claude => apps/backend}/project/structure_analyzer.py (100%) rename {auto-claude => apps/backend}/project_analyzer.py (100%) rename {auto-claude => apps/backend}/prompt_generator.py (100%) rename {auto-claude => apps/backend}/prompts.py (100%) rename {auto-claude => apps/backend}/prompts/coder.md (100%) rename {auto-claude => apps/backend}/prompts/coder_recovery.md (100%) rename {auto-claude => apps/backend}/prompts/competitor_analysis.md (100%) rename {auto-claude => apps/backend}/prompts/complexity_assessor.md (96%) rename {auto-claude => apps/backend}/prompts/followup_planner.md (100%) rename {auto-claude => apps/backend}/prompts/ideation_code_improvements.md (100%) rename {auto-claude => apps/backend}/prompts/ideation_code_quality.md (100%) rename {auto-claude => apps/backend}/prompts/ideation_documentation.md (100%) rename {auto-claude => apps/backend}/prompts/ideation_performance.md (100%) rename {auto-claude => apps/backend}/prompts/ideation_security.md (100%) rename {auto-claude => apps/backend}/prompts/ideation_ui_ux.md (100%) rename {auto-claude => apps/backend}/prompts/insight_extractor.md (100%) rename {auto-claude => apps/backend}/prompts/mcp_tools/api_validation.md (100%) rename {auto-claude => apps/backend}/prompts/mcp_tools/database_validation.md (100%) rename {auto-claude => apps/backend}/prompts/mcp_tools/electron_validation.md (100%) rename {auto-claude => apps/backend}/prompts/mcp_tools/puppeteer_browser.md (100%) rename {auto-claude => apps/backend}/prompts/planner.md (100%) rename {auto-claude => apps/backend}/prompts/qa_fixer.md (100%) rename {auto-claude => apps/backend}/prompts/qa_reviewer.md (100%) rename {auto-claude => apps/backend}/prompts/roadmap_discovery.md (100%) rename {auto-claude => apps/backend}/prompts/roadmap_features.md (100%) rename {auto-claude => apps/backend}/prompts/spec_critic.md (97%) rename {auto-claude => apps/backend}/prompts/spec_gatherer.md (100%) rename {auto-claude => apps/backend}/prompts/spec_quick.md (100%) rename {auto-claude => apps/backend}/prompts/spec_researcher.md (95%) rename {auto-claude => apps/backend}/prompts/spec_writer.md (100%) rename {auto-claude => apps/backend}/prompts/validation_fixer.md (100%) rename {auto-claude => apps/backend}/prompts_pkg/__init__.py (100%) rename {auto-claude => apps/backend}/prompts_pkg/project_context.py (100%) rename {auto-claude => apps/backend}/prompts_pkg/prompt_generator.py (100%) rename {auto-claude => apps/backend}/prompts_pkg/prompts.py (100%) rename {auto-claude => apps/backend}/qa/__init__.py (100%) rename {auto-claude => apps/backend}/qa/criteria.py (100%) rename {auto-claude => apps/backend}/qa/fixer.py (100%) rename {auto-claude => apps/backend}/qa/loop.py (100%) rename {auto-claude => apps/backend}/qa/qa_loop.py (100%) rename {auto-claude => apps/backend}/qa/report.py (100%) rename {auto-claude => apps/backend}/qa/reviewer.py (100%) rename {auto-claude => apps/backend}/qa_loop.py (84%) rename {auto-claude => apps/backend}/query_memory.py (100%) rename {auto-claude => apps/backend}/recovery.py (100%) rename {auto-claude => apps/backend}/requirements.txt (100%) rename {auto-claude => apps/backend}/review/__init__.py (100%) rename {auto-claude => apps/backend}/review/diff_analyzer.py (100%) rename {auto-claude => apps/backend}/review/formatters.py (100%) rename {auto-claude => apps/backend}/review/main.py (100%) rename {auto-claude => apps/backend}/review/reviewer.py (100%) rename {auto-claude => apps/backend}/review/state.py (100%) rename {auto-claude => apps/backend}/risk_classifier.py (100%) rename {auto-claude => apps/backend}/run.py (100%) rename {auto-claude => apps/backend}/runners/__init__.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/EXAMPLES.md (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/README.md (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/__init__.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/analyzers.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/cache_manager.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/claude_client.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/cost_estimator.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/models.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/result_parser.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/runner.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer/summary_printer.py (100%) rename {auto-claude => apps/backend}/runners/ai_analyzer_runner.py (100%) mode change 100755 => 100644 rename {auto-claude => apps/backend}/runners/ideation_runner.py (100%) rename {auto-claude => apps/backend}/runners/insights_runner.py (100%) rename {auto-claude => apps/backend}/runners/roadmap/__init__.py (100%) rename {auto-claude => apps/backend}/runners/roadmap/competitor_analyzer.py (100%) rename {auto-claude => apps/backend}/runners/roadmap/executor.py (100%) rename {auto-claude => apps/backend}/runners/roadmap/graph_integration.py (100%) rename {auto-claude => apps/backend}/runners/roadmap/models.py (100%) rename {auto-claude => apps/backend}/runners/roadmap/orchestrator.py (100%) rename {auto-claude => apps/backend}/runners/roadmap/phases.py (100%) rename {auto-claude => apps/backend}/runners/roadmap/project_index.json (100%) rename {auto-claude => apps/backend}/runners/roadmap_runner.py (100%) rename {auto-claude => apps/backend}/runners/spec_runner.py (100%) rename {auto-claude => apps/backend}/scan-for-secrets (100%) mode change 100755 => 100644 rename {auto-claude => apps/backend}/scan_secrets.py (100%) rename {auto-claude => apps/backend}/security.py (100%) rename {auto-claude => apps/backend}/security/__init__.py (100%) rename {auto-claude => apps/backend}/security/database_validators.py (100%) rename {auto-claude => apps/backend}/security/filesystem_validators.py (100%) rename {auto-claude => apps/backend}/security/git_validators.py (100%) rename {auto-claude => apps/backend}/security/hooks.py (100%) rename {auto-claude => apps/backend}/security/main.py (100%) rename {auto-claude => apps/backend}/security/parser.py (100%) rename {auto-claude => apps/backend}/security/process_validators.py (100%) rename {auto-claude => apps/backend}/security/profile.py (100%) rename {auto-claude => apps/backend}/security/scan_secrets.py (100%) rename {auto-claude => apps/backend}/security/validation_models.py (100%) rename {auto-claude => apps/backend}/security/validator.py (100%) rename {auto-claude => apps/backend}/security/validator_registry.py (100%) rename {auto-claude => apps/backend}/security_scanner.py (100%) rename {auto-claude => apps/backend}/service_orchestrator.py (100%) rename {auto-claude => apps/backend}/services/__init__.py (100%) rename {auto-claude => apps/backend}/services/context.py (100%) rename {auto-claude => apps/backend}/services/orchestrator.py (100%) rename {auto-claude => apps/backend}/services/recovery.py (100%) rename {auto-claude => apps/backend}/spec/__init__.py (100%) rename {auto-claude => apps/backend}/spec/compaction.py (100%) rename {auto-claude => apps/backend}/spec/complexity.py (100%) rename {auto-claude => apps/backend}/spec/context.py (100%) rename {auto-claude => apps/backend}/spec/critique.py (100%) rename {auto-claude => apps/backend}/spec/discovery.py (100%) rename {auto-claude => apps/backend}/spec/phases.py (100%) rename {auto-claude => apps/backend}/spec/phases/README.md (100%) rename {auto-claude => apps/backend}/spec/phases/__init__.py (100%) rename {auto-claude => apps/backend}/spec/phases/discovery_phases.py (100%) rename {auto-claude => apps/backend}/spec/phases/executor.py (100%) rename {auto-claude => apps/backend}/spec/phases/models.py (100%) rename {auto-claude => apps/backend}/spec/phases/planning_phases.py (100%) rename {auto-claude => apps/backend}/spec/phases/requirements_phases.py (100%) rename {auto-claude => apps/backend}/spec/phases/spec_phases.py (100%) rename {auto-claude => apps/backend}/spec/phases/utils.py (100%) rename {auto-claude => apps/backend}/spec/pipeline.py (100%) rename {auto-claude => apps/backend}/spec/pipeline/__init__.py (100%) rename {auto-claude => apps/backend}/spec/pipeline/agent_runner.py (100%) rename {auto-claude => apps/backend}/spec/pipeline/models.py (100%) rename {auto-claude => apps/backend}/spec/pipeline/orchestrator.py (100%) rename {auto-claude => apps/backend}/spec/requirements.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/README.md (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/__init__.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/auto_fix.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/models.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/schemas.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/spec_validator.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/validators/__init__.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/validators/context_validator.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/validators/implementation_plan_validator.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/validators/prereqs_validator.py (100%) rename {auto-claude => apps/backend}/spec/validate_pkg/validators/spec_document_validator.py (100%) rename {auto-claude => apps/backend}/spec/validate_spec.py (100%) rename {auto-claude => apps/backend}/spec/validation_strategy.py (100%) rename {auto-claude => apps/backend}/spec/validator.py (100%) rename {auto-claude => apps/backend}/spec/writer.py (100%) rename {auto-claude => apps/backend}/spec_contract.json (100%) rename {auto-claude => apps/backend}/task_logger/README.md (100%) rename {auto-claude => apps/backend}/task_logger/__init__.py (100%) rename {auto-claude => apps/backend}/task_logger/capture.py (100%) rename {auto-claude => apps/backend}/task_logger/logger.py (100%) rename {auto-claude => apps/backend}/task_logger/main.py (100%) rename {auto-claude => apps/backend}/task_logger/models.py (100%) rename {auto-claude => apps/backend}/task_logger/storage.py (100%) rename {auto-claude => apps/backend}/task_logger/streaming.py (100%) rename {auto-claude => apps/backend}/task_logger/utils.py (100%) rename {auto-claude => apps/backend}/test_discovery.py (100%) rename {auto-claude => apps/backend}/ui/__init__.py (100%) rename {auto-claude => apps/backend}/ui/boxes.py (100%) rename {auto-claude => apps/backend}/ui/capabilities.py (100%) rename {auto-claude => apps/backend}/ui/colors.py (100%) rename {auto-claude => apps/backend}/ui/formatters.py (100%) rename {auto-claude => apps/backend}/ui/icons.py (100%) rename {auto-claude => apps/backend}/ui/main.py (100%) rename {auto-claude => apps/backend}/ui/menu.py (100%) rename {auto-claude => apps/backend}/ui/progress.py (100%) rename {auto-claude => apps/backend}/ui/spinner.py (100%) rename {auto-claude => apps/backend}/ui/status.py (100%) rename {auto-claude => apps/backend}/ui/statusline.py (100%) rename {auto-claude => apps/backend}/validation_strategy.py (100%) create mode 100644 apps/backend/workspace.py rename {auto-claude => apps/backend}/worktree.py (77%) rename {auto-claude-ui => apps/frontend}/.env.example (100%) rename {auto-claude-ui => apps/frontend}/.gitignore (73%) create mode 100644 apps/frontend/.husky/pre-commit create mode 100644 apps/frontend/CONTRIBUTING.md create mode 100644 apps/frontend/README.md rename {auto-claude-ui => apps/frontend}/design.json (100%) rename {auto-claude-ui => apps/frontend}/e2e/electron-helper.ts (100%) rename {auto-claude-ui => apps/frontend}/e2e/flows.e2e.ts (100%) rename {auto-claude-ui => apps/frontend}/e2e/playwright.config.ts (100%) rename {auto-claude-ui => apps/frontend}/electron.vite.config.ts (84%) rename {auto-claude-ui => apps/frontend}/eslint.config.mjs (82%) rename {auto-claude-ui => apps/frontend}/package-lock.json (98%) rename {auto-claude-ui => apps/frontend}/package.json (90%) rename auto-claude-ui/postcss.config.js => apps/frontend/postcss.config.cjs (100%) rename {auto-claude-ui => apps/frontend}/resources/entitlements.mac.plist (100%) rename {auto-claude-ui => apps/frontend}/resources/icon-256.png (100%) rename {auto-claude-ui => apps/frontend}/resources/icon.icns (100%) rename {auto-claude-ui => apps/frontend}/resources/icon.ico (100%) rename {auto-claude-ui => apps/frontend}/resources/icon.png (100%) rename auto-claude-ui/scripts/download-prebuilds.js => apps/frontend/scripts/download-prebuilds.cjs (100%) rename auto-claude-ui/scripts/postinstall.js => apps/frontend/scripts/postinstall.cjs (99%) rename {auto-claude-ui => apps/frontend}/src/__mocks__/electron.ts (100%) rename {auto-claude-ui => apps/frontend}/src/__tests__/integration/file-watcher.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/__tests__/integration/ipc-bridge.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/__tests__/integration/subprocess-spawn.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/__tests__/setup.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/__tests__/ipc-handlers.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/__tests__/project-store.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/__tests__/rate-limit-auto-recovery.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/__tests__/rate-limit-detector.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/agent-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/agent/agent-events.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/agent/agent-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/agent/agent-process.ts (97%) rename {auto-claude-ui => apps/frontend}/src/main/agent/agent-queue.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/agent/agent-state.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/agent/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/agent/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/api-validation-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/app-updater.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/auto-claude-updater.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/changelog-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/formatter.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/generator.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/git-integration.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/parser.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/changelog/version-suggester.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/profile-scorer.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/profile-storage.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/profile-utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/rate-limit-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/token-encryption.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/usage-monitor.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/claude-profile/usage-parser.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/file-watcher.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/index.ts (99%) rename {auto-claude-ui => apps/frontend}/src/main/insights-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/insights/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/insights/REFACTORING_NOTES.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/insights/config.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/insights/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/insights/insights-executor.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/insights/paths.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/insights/session-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/insights/session-storage.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/integrations/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/integrations/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/agent-events-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/app-update-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/autobuild-source-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/changelog-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/changelog-handlers.ts.bk (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/context-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/context/README.md (89%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/context/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/context/memory-data-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/context/memory-status-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/context/project-context-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/context/utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/env-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/file-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/ARCHITECTURE.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/import-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/investigation-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/issue-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/oauth-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/release-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/repository-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/spec-utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/github/utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation/file-utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation/generation-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation/idea-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation/session-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation/task-converter.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation/transformers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/ideation/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/index.ts (97%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/insights-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/linear-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/memory-handlers.ts (98%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/project-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/roadmap-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/context-roadmap-section.txt (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/context_extracted.txt (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/ideation-insights-section.txt (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/integration-section.txt (99%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/roadmap_extracted.txt (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/task-section.txt (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/task_extracted.txt (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/terminal-section.txt (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/sections/terminal_extracted.txt (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/settings-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/archive-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/crud-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/execution-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/logs-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/shared.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/task/worktree-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/terminal-handlers.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-handlers/utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/ipc-setup.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/log-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/memory-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/notification-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/project-initializer.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/project-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/python-detector.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/python-env-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/rate-limit-detector.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/release-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/task-log-service.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal-name-generator.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal-session-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/claude-integration-handler.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/output-parser.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/pty-daemon-client.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/pty-daemon.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/pty-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/session-handler.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/session-persistence.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/terminal-event-handler.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/terminal-lifecycle.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/terminal-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/terminal/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/title-generator.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/updater/config.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/updater/file-operations.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/updater/http-client.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/updater/path-resolver.ts (63%) rename {auto-claude-ui => apps/frontend}/src/main/updater/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/updater/update-checker.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/updater/update-installer.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/updater/update-status.ts (100%) rename {auto-claude-ui => apps/frontend}/src/main/updater/version-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/agent-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/app-update-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/file-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/autobuild-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/changelog-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/github-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/ideation-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/insights-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/ipc-utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/linear-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/roadmap-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/modules/shell-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/project-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/settings-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/task-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/api/terminal-api.ts (100%) rename {auto-claude-ui => apps/frontend}/src/preload/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/App.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/__tests__/OAuthStep.test.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/__tests__/TaskEditDialog.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/__tests__/project-store-tabs.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/__tests__/roadmap-store.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/__tests__/task-store.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/AddFeatureDialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/AddProjectModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/AgentProfileSelector.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/AgentProfiles.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/AppSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/AppUpdateNotification.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/Changelog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ChatHistorySidebar.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/CompetitorAnalysisDialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/CompetitorAnalysisViewer.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/Context.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/CustomModelModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/EnvConfigModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/FileAutocomplete.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/FileExplorerPanel.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/FileTree.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/FileTreeItem.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/GitHubIssues.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/GitHubSetupModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/GitSetupModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/Ideation.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ImageUpload.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/Insights.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/InsightsModelSelector.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/KanbanBoard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/LinearTaskImportModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/PhaseProgressIndicator.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ProactiveSwapListener.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ProjectSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ProjectTabBar.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/RateLimitIndicator.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/RateLimitModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ReferencedFilesSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/Roadmap.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/RoadmapGenerationProgress.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/RoadmapKanbanView.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/SDKRateLimitModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/Sidebar.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/SortableFeatureCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/SortableProjectTab.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/SortableTaskCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/TaskCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/TaskCreationWizard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/TaskDetailPanel.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/TaskEditDialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/TaskFileExplorerDrawer.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/Terminal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/TerminalGrid.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/UsageIndicator.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/WelcomeScreen.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/Worktrees.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/__tests__/ProjectTabBar.test.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/ArchiveTasksCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/Changelog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/ChangelogDetails.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/ChangelogEntry.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/ChangelogFilters.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/ChangelogHeader.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/ChangelogList.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/ConfigurationPanel.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/GitHubReleaseCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/PreviewPanel.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/REFACTORING_SUMMARY.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/Step3SuccessScreen.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/hooks/useChangelog.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/hooks/useImageUpload.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/changelog/utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/Context.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/InfoItem.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/MemoriesTab.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/MemoryCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/ProjectIndexTab.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/ServiceCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/constants.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/hooks.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/service-sections/APIRoutesSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/service-sections/DatabaseSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/service-sections/DependenciesSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/service-sections/EnvironmentSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/service-sections/ExternalServicesSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/service-sections/MonitoringSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/service-sections/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/context/utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/ARCHITECTURE.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/REFACTORING_SUMMARY.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/components/EmptyStates.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/components/InvestigationDialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/components/IssueDetail.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/components/IssueList.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/components/IssueListHeader.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/components/IssueListItem.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/components/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/hooks/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/hooks/useGitHubIssues.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/hooks/useIssueFiltering.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/types/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/github-issues/utils/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/GenerationProgressScreen.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/IdeaCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/IdeaDetailPanel.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/IdeaSkeletonCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/Ideation.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/IdeationDialogs.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/IdeationEmptyState.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/IdeationFilters.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/IdeationHeader.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/TypeIcon.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/TypeStateIcon.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/constants.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/details/CodeImprovementDetails.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/details/CodeQualityDetails.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/details/DocumentationGapDetails.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/details/UIUXDetails.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/hooks/useIdeation.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ideation/type-guards.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/REFACTORING_SUMMARY.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/components/ErrorBanner.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/components/IssueCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/components/IssueList.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/components/SelectionControls.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/components/TeamProjectSelector.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/components/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/hooks/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/hooks/useIssueFiltering.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/hooks/useIssueSelection.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/hooks/useLinearImport.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/hooks/useLinearImportModal.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/hooks/useLinearIssues.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/hooks/useLinearProjects.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/hooks/useLinearTeams.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/linear-import/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/CompletionStep.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/FirstSpecStep.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/GraphitiStep.tsx (99%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/MemoryStep.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/OAuthStep.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/OllamaModelSelector.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/OnboardingWizard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/WelcomeStep.tsx (95%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/WizardProgress.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/onboarding/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/AgentConfigSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/AutoBuildIntegration.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/ClaudeAuthSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/CollapsibleSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/ConnectionStatus.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/EnvironmentSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/GeneralSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/GitHubIntegrationSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/GitHubOAuthFlow.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/InfrastructureStatus.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/IntegrationSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/LinearIntegrationSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/MemoryBackendSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/NotificationsSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/PasswordInput.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/ProjectSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/README.md (95%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/SecuritySettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/StatusBadge.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/hooks/useProjectSettings.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/project-settings/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/FeatureCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/FeatureDetailPanel.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/PhaseCard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/RoadmapEmptyState.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/RoadmapHeader.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/RoadmapTabs.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/hooks.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/roadmap/utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/AdvancedSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/AgentProfileSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/AppSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/GeneralSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/IntegrationSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/ProjectSelector.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/ProjectSettingsContent.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/REFACTORING_SUMMARY.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/SettingsSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/ThemeSelector.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/ThemeSettings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/common/EmptyProjectState.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/common/ErrorDisplay.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/common/InitializationGuard.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/common/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/hooks/useSettings.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/integrations/GitHubIntegration.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/integrations/LinearIntegration.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/integrations/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/sections/SectionRouter.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/sections/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/utils/hookProxyFactory.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/settings/utils/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskActions.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskDetailModal.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskDetailPanel.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskHeader.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskLogs.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskMetadata.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskProgress.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskReview.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskSubtasks.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/TaskWarnings.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/hooks/useTaskDetail.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/DiscardDialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/task-detail/task-review/utils.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/README.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/REFACTORING_SUMMARY.md (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/TaskSelector.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/TerminalHeader.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/TerminalTitle.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/useAutoNaming.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/usePtyProcess.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/useTerminalEvents.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/terminal/useXterm.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/alert-dialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/badge.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/button.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/card.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/checkbox.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/collapsible.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/dialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/dropdown-menu.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/full-screen-dialog.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/input.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/label.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/progress.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/radio-group.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/scroll-area.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/select.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/separator.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/switch.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/tabs.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/textarea.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/components/ui/tooltip.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/useClaudeAuth.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/useEnvironmentConfig.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/useGitHubConnection.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/useInfrastructureStatus.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/useIpc.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/useLinearConnection.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/useProjectSettings.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/hooks/useVirtualizedTree.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/index.html (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/browser-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/buffer-persistence.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/flow-controller.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/icons.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/README.md (97%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/changelog-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/claude-profile-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/context-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/infrastructure-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/insights-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/integration-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/mock-data.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/project-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/roadmap-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/settings-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/task-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/terminal-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/mocks/workspace-mock.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/scroll-controller.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/terminal-buffer-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/webgl-context-manager.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/lib/webgl-utils.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/main.tsx (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/changelog-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/claude-profile-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/context-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/file-explorer-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/github-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/ideation-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/insights-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/project-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/rate-limit-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/release-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/roadmap-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/settings-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/task-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/stores/terminal-store.ts (100%) rename {auto-claude-ui => apps/frontend}/src/renderer/styles/globals.css (100%) rename {auto-claude-ui => apps/frontend}/src/shared/__tests__/progress.test.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/changelog.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/config.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/github.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/ideation.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/ipc.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/models.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/roadmap.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/task.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/constants/themes.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/progress.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/agent.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/app-update.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/changelog.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/common.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/index.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/insights.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/integrations.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/ipc.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/project.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/roadmap.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/settings.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/task.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/terminal-session.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/types/terminal.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/utils/debug-logger.ts (100%) rename {auto-claude-ui => apps/frontend}/src/shared/utils/shell-escape.ts (100%) rename {auto-claude-ui => apps/frontend}/tsconfig.json (68%) rename {auto-claude-ui => apps/frontend}/vitest.config.ts (100%) delete mode 100644 auto-claude-ui/.husky/pre-commit delete mode 100644 auto-claude-ui/.npmrc delete mode 100644 auto-claude-ui/README.md delete mode 100644 auto-claude-ui/pnpm-lock.yaml delete mode 100644 auto-claude-ui/src/main/agent-manager.ts.backup delete mode 100644 auto-claude-ui/src/main/ipc-handlers.ts.backup delete mode 100644 auto-claude-ui/src/main/ipc-handlers/docker-handlers.ts delete mode 100644 auto-claude-ui/src/main/ipc-handlers/task-handlers.ts.backup delete mode 100644 auto-claude-ui/src/renderer/components/project-settings/REFACTORING_SUMMARY.md delete mode 100644 auto-claude/__init__.py delete mode 100644 auto-claude/agents/__init__.py delete mode 100644 auto-claude/analyzer.py delete mode 100644 auto-claude/analyzers/__init__.py delete mode 100644 auto-claude/auto_claude_tools.py delete mode 100644 auto-claude/client.py delete mode 100644 auto-claude/debug.py delete mode 100644 auto-claude/implementation_plan.py delete mode 100644 auto-claude/linear_integration.py delete mode 100644 auto-claude/linear_updater.py delete mode 100644 auto-claude/merge/ARCHITECTURE.md delete mode 100644 auto-claude/merge/REFACTORING_DETAILS.md delete mode 100644 auto-claude/merge/REFACTORING_SUMMARY.md delete mode 100644 auto-claude/merge/auto_merger_old.py delete mode 100644 auto-claude/progress.py delete mode 100644 auto-claude/prompts/_archived_ideation_high_value.md delete mode 100644 auto-claude/prompts/_archived_ideation_low_hanging_fruit.md delete mode 100644 auto-claude/runners/ai_analyzer/REFACTORING.md delete mode 100644 auto-claude/spec/validate_pkg/MIGRATION.md delete mode 100644 auto-claude/validate_spec/__init__.py delete mode 100644 auto-claude/validate_spec/auto_fix.py delete mode 100644 auto-claude/validate_spec/spec_validator.py delete mode 100644 auto-claude/workspace.py delete mode 100644 guides/DOCKER-SETUP.md create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 scripts/install-backend.js create mode 100644 scripts/test-backend.js diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index a60e63df..0e06e2ea 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -56,8 +56,8 @@ body: label: Component description: Which part of Auto Claude is affected? options: - - Python Backend (auto-claude/) - - Electron UI (auto-claude-ui/) + - Python Backend (apps/backend/) + - Electron UI (apps/frontend/) - Both - Not sure validations: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 1ab14837..2cb0f656 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -38,8 +38,8 @@ body: label: Component description: Which part of Auto Claude would this affect? options: - - Python Backend (auto-claude/) - - Electron UI (auto-claude-ui/) + - Python Backend (apps/backend/) + - Electron UI (apps/frontend/) - Both - New component - Not sure diff --git a/.github/workflows/build-prebuilds.yml b/.github/workflows/build-prebuilds.yml index 34765831..d3d4585a 100644 --- a/.github/workflows/build-prebuilds.yml +++ b/.github/workflows/build-prebuilds.yml @@ -32,22 +32,17 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 9 + node-version: '24' - name: Install Visual Studio Build Tools uses: microsoft/setup-msbuild@v2 - name: Install node-pty and rebuild for Electron - working-directory: auto-claude-ui + working-directory: apps/frontend shell: pwsh run: | # Install only node-pty - pnpm add node-pty@1.1.0-beta42 + npm install node-pty@1.1.0-beta42 # Get Electron ABI version $electronAbi = (npx electron-abi $env:ELECTRON_VERSION) @@ -57,7 +52,7 @@ jobs: npx @electron/rebuild --version $env:ELECTRON_VERSION --module-dir node_modules/node-pty --arch ${{ matrix.arch }} - name: Package prebuilt binaries - working-directory: auto-claude-ui + working-directory: apps/frontend shell: pwsh run: | $electronAbi = (npx electron-abi $env:ELECTRON_VERSION) @@ -83,7 +78,7 @@ jobs: Get-ChildItem $prebuildDir - name: Create archive - working-directory: auto-claude-ui + working-directory: apps/frontend shell: pwsh run: | $electronAbi = (npx electron-abi $env:ELECTRON_VERSION) @@ -98,14 +93,14 @@ jobs: uses: actions/upload-artifact@v4 with: name: node-pty-win32-${{ matrix.arch }} - path: auto-claude-ui/node-pty-*.zip + path: apps/frontend/node-pty-*.zip retention-days: 90 - name: Upload to release if: github.event_name == 'release' uses: softprops/action-gh-release@v1 with: - files: auto-claude-ui/node-pty-*.zip + files: apps/frontend/node-pty-*.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76b644a7..cb036c59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,30 +29,34 @@ jobs: version: "latest" - name: Install dependencies - working-directory: auto-claude + working-directory: apps/backend run: | uv venv uv pip install -r requirements.txt - uv pip install -r ../tests/requirements-test.txt + uv pip install -r ../../tests/requirements-test.txt - name: Run tests - working-directory: auto-claude + working-directory: apps/backend + env: + PYTHONPATH: ${{ github.workspace }}/apps/backend run: | source .venv/bin/activate - pytest ../tests/ -v --tb=short -x + pytest ../../tests/ -v --tb=short -x - name: Run tests with coverage if: matrix.python-version == '3.12' - working-directory: auto-claude + working-directory: apps/backend + env: + PYTHONPATH: ${{ github.workspace }}/apps/backend run: | source .venv/bin/activate - pytest ../tests/ -v --cov=. --cov-report=xml --cov-report=term-missing + pytest ../../tests/ -v --cov=. --cov-report=xml --cov-report=term-missing - name: Upload coverage reports if: matrix.python-version == '3.12' uses: codecov/codecov-action@v4 with: - file: ./auto-claude/coverage.xml + file: ./apps/backend/coverage.xml fail_ci_if_error: false env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -67,39 +71,34 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - - - name: Get pnpm store directory - id: pnpm-cache - run: echo "dir=$(pnpm store path)" >> "$GITHUB_OUTPUT" + - name: Get npm cache directory + id: npm-cache + run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT" - uses: actions/cache@v4 with: - path: ${{ steps.pnpm-cache.outputs.dir }} - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: ${{ runner.os }}-pnpm- + path: ${{ steps.npm-cache.outputs.dir }} + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-npm- - name: Install dependencies - working-directory: auto-claude-ui - run: pnpm install --frozen-lockfile --ignore-scripts + working-directory: apps/frontend + run: npm ci --ignore-scripts - name: Lint - working-directory: auto-claude-ui - run: pnpm run lint + working-directory: apps/frontend + run: npm run lint - name: Type check - working-directory: auto-claude-ui - run: pnpm run typecheck + working-directory: apps/frontend + run: npm run typecheck - name: Run tests - working-directory: auto-claude-ui - run: pnpm run test + working-directory: apps/frontend + run: npm run test - name: Build - working-directory: auto-claude-ui - run: pnpm run build + working-directory: apps/frontend + run: npm run build diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5a3b2581..76ad2e01 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,10 +23,10 @@ jobs: run: pip install ruff - name: Run ruff check - run: ruff check auto-claude/ --output-format=github + run: ruff check apps/backend/ --output-format=github - name: Run ruff format check - run: ruff format auto-claude/ --check --diff + run: ruff format apps/backend/ --check --diff # TypeScript/React linting frontend: @@ -38,21 +38,16 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 9 + node-version: '24' - name: Install dependencies - working-directory: auto-claude-ui - run: pnpm install --frozen-lockfile --ignore-scripts + working-directory: apps/frontend + run: npm ci --ignore-scripts - name: Run ESLint - working-directory: auto-claude-ui - run: pnpm lint + working-directory: apps/frontend + run: npm run lint - name: Run TypeScript check - working-directory: auto-claude-ui - run: pnpm typecheck + working-directory: apps/frontend + run: npm run typecheck diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c02d7c89..1a4fe504 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,31 +23,26 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - - - name: Get pnpm store directory - id: pnpm-cache - run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Get npm cache directory + id: npm-cache + run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - uses: actions/cache@v4 with: - path: ${{ steps.pnpm-cache.outputs.dir }} - key: ${{ runner.os }}-x64-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: ${{ runner.os }}-x64-pnpm- + path: ${{ steps.npm-cache.outputs.dir }} + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-npm- - name: Install dependencies - run: cd auto-claude-ui && pnpm install --frozen-lockfile + run: cd apps/frontend && npm ci - name: Build application - run: cd auto-claude-ui && pnpm run build + run: cd apps/frontend && npm run build - name: Package macOS (Intel) - run: cd auto-claude-ui && pnpm run package:mac -- --arch=x64 + run: cd apps/frontend && npm run package:mac -- --arch=x64 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} CSC_LINK: ${{ secrets.MAC_CERTIFICATE }} @@ -63,7 +58,7 @@ jobs: echo "Skipping notarization: APPLE_ID not configured" exit 0 fi - cd auto-claude-ui + cd apps/frontend for dmg in dist/*.dmg; do echo "Notarizing $dmg..." xcrun notarytool submit "$dmg" \ @@ -80,8 +75,8 @@ jobs: with: name: macos-intel-builds path: | - auto-claude-ui/dist/*.dmg - auto-claude-ui/dist/*.zip + apps/frontend/dist/*.dmg + apps/frontend/dist/*.zip # Apple Silicon build on ARM64 runner for native compilation build-macos-arm64: @@ -92,31 +87,26 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - - - name: Get pnpm store directory - id: pnpm-cache - run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Get npm cache directory + id: npm-cache + run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - uses: actions/cache@v4 with: - path: ${{ steps.pnpm-cache.outputs.dir }} - key: ${{ runner.os }}-arm64-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: ${{ runner.os }}-arm64-pnpm- + path: ${{ steps.npm-cache.outputs.dir }} + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-npm- - name: Install dependencies - run: cd auto-claude-ui && pnpm install --frozen-lockfile + run: cd apps/frontend && npm ci - name: Build application - run: cd auto-claude-ui && pnpm run build + run: cd apps/frontend && npm run build - name: Package macOS (Apple Silicon) - run: cd auto-claude-ui && pnpm run package:mac -- --arch=arm64 + run: cd apps/frontend && npm run package:mac -- --arch=arm64 env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} CSC_LINK: ${{ secrets.MAC_CERTIFICATE }} @@ -132,7 +122,7 @@ jobs: echo "Skipping notarization: APPLE_ID not configured" exit 0 fi - cd auto-claude-ui + cd apps/frontend for dmg in dist/*.dmg; do echo "Notarizing $dmg..." xcrun notarytool submit "$dmg" \ @@ -149,8 +139,8 @@ jobs: with: name: macos-arm64-builds path: | - auto-claude-ui/dist/*.dmg - auto-claude-ui/dist/*.zip + apps/frontend/dist/*.dmg + apps/frontend/dist/*.zip build-windows: runs-on: windows-latest @@ -160,32 +150,27 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - - - name: Get pnpm store directory - id: pnpm-cache + - name: Get npm cache directory + id: npm-cache shell: bash - run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT + run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - uses: actions/cache@v4 with: - path: ${{ steps.pnpm-cache.outputs.dir }} - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: ${{ runner.os }}-pnpm- + path: ${{ steps.npm-cache.outputs.dir }} + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-npm- - name: Install dependencies - run: cd auto-claude-ui && pnpm install --frozen-lockfile + run: cd apps/frontend && npm ci - name: Build application - run: cd auto-claude-ui && pnpm run build + run: cd apps/frontend && npm run build - name: Package Windows - run: cd auto-claude-ui && pnpm run package:win + run: cd apps/frontend && npm run package:win env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} CSC_LINK: ${{ secrets.WIN_CERTIFICATE }} @@ -196,7 +181,7 @@ jobs: with: name: windows-builds path: | - auto-claude-ui/dist/*.exe + apps/frontend/dist/*.exe build-linux: runs-on: ubuntu-latest @@ -206,31 +191,26 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - - - name: Get pnpm store directory - id: pnpm-cache - run: echo "dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Get npm cache directory + id: npm-cache + run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - uses: actions/cache@v4 with: - path: ${{ steps.pnpm-cache.outputs.dir }} - key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: ${{ runner.os }}-pnpm- + path: ${{ steps.npm-cache.outputs.dir }} + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: ${{ runner.os }}-npm- - name: Install dependencies - run: cd auto-claude-ui && pnpm install --frozen-lockfile + run: cd apps/frontend && npm ci - name: Build application - run: cd auto-claude-ui && pnpm run build + run: cd apps/frontend && npm run build - name: Package Linux - run: cd auto-claude-ui && pnpm run package:linux + run: cd apps/frontend && npm run package:linux env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -239,8 +219,8 @@ jobs: with: name: linux-builds path: | - auto-claude-ui/dist/*.AppImage - auto-claude-ui/dist/*.deb + apps/frontend/dist/*.AppImage + apps/frontend/dist/*.deb create-release: needs: [build-macos-intel, build-macos-arm64, build-windows, build-linux] diff --git a/.github/workflows/test-on-tag.yml b/.github/workflows/test-on-tag.yml index 078bd561..f633c868 100644 --- a/.github/workflows/test-on-tag.yml +++ b/.github/workflows/test-on-tag.yml @@ -28,17 +28,19 @@ jobs: version: "latest" - name: Install dependencies - working-directory: auto-claude + working-directory: apps/backend run: | uv venv uv pip install -r requirements.txt - uv pip install -r ../tests/requirements-test.txt + uv pip install -r ../../tests/requirements-test.txt - name: Run tests - working-directory: auto-claude + working-directory: apps/backend + env: + PYTHONPATH: ${{ github.workspace }}/apps/backend run: | source .venv/bin/activate - pytest ../tests/ -v --tb=short + pytest ../../tests/ -v --tb=short # Frontend tests test-frontend: @@ -50,17 +52,12 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' - - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 9 + node-version: '24' - name: Install dependencies - working-directory: auto-claude-ui - run: pnpm install --frozen-lockfile --ignore-scripts + working-directory: apps/frontend + run: npm ci --ignore-scripts - name: Run tests - working-directory: auto-claude-ui - run: pnpm test + working-directory: apps/frontend + run: npm run test diff --git a/.github/workflows/validate-version.yml b/.github/workflows/validate-version.yml index b97fe71e..a076114d 100644 --- a/.github/workflows/validate-version.yml +++ b/.github/workflows/validate-version.yml @@ -26,7 +26,7 @@ jobs: id: package_version run: | # Read version from package.json - PACKAGE_VERSION=$(node -p "require('./auto-claude-ui/package.json').version") + PACKAGE_VERSION=$(node -p "require('./apps/frontend/package.json').version") echo "version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT echo "Package.json version: $PACKAGE_VERSION" diff --git a/.gitignore b/.gitignore index 0781d8a0..7ba9c4ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,69 @@ -# OS +# =========================== +# OS Files +# =========================== .DS_Store +.DS_Store? +._* Thumbs.db +ehthumbs.db +Desktop.ini -# Environment files (contain API keys) +# =========================== +# Security - Environment & Secrets +# =========================== .env -.env.local +.env.* +!.env.example +*.pem +*.key +*.crt +*.p12 +*.pfx +.secrets +secrets/ +credentials/ -# Git worktrees (used by auto-build parallel mode) -.worktrees/ - -# IDE +# =========================== +# IDE & Editors +# =========================== .idea/ .vscode/ *.swp *.swo +*.sublime-workspace +*.sublime-project +.project +.classpath +.settings/ +# =========================== # Logs +# =========================== logs/ *.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* -# Personal notes -OPUS_ANALYSIS_AND_IDEAS.md +# =========================== +# Git Worktrees (parallel builds) +# =========================== +.worktrees/ -# Documentation -docs/ +# =========================== +# Auto Claude Generated +# =========================== +.auto-claude/ +.auto-build-security.json +.auto-claude-security.json +.auto-claude-status +.claude_settings.json +.update-metadata.json -# Python +# =========================== +# Python (apps/backend) +# =========================== __pycache__/ *.py[cod] *$py.class @@ -33,25 +71,19 @@ __pycache__/ .Python build/ develop-eggs/ -dist/ -downloads/ eggs/ .eggs/ -/lib/ -/lib64/ -parts/ -sdist/ -var/ -wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST # Virtual environments .venv/ venv/ ENV/ env/ +.conda/ # Testing .pytest_cache/ @@ -64,26 +96,69 @@ coverage.xml *.py,cover .hypothesis/ -# mypy +# Type checking .mypy_cache/ .dmypy.json dmypy.json +.pytype/ +.pyre/ -# Auto-build generated files -.auto-build-security.json -.auto-claude-security.json -.auto-claude-status -.claude_settings.json -.update-metadata.json +# =========================== +# Node.js (apps/frontend) +# =========================== +node_modules/ +.npm +.yarn/ +.pnp.* -# Development of Auto Build with Auto Build +# Build output +dist/ +out/ +*.tsbuildinfo + +# Cache +.cache/ +.parcel-cache/ +.turbo/ +.eslintcache +.prettiercache + +# =========================== +# Electron +# =========================== +apps/frontend/dist/ +apps/frontend/out/ +*.asar +*.blockmap +*.snap +*.deb +*.rpm +*.AppImage +*.dmg +*.exe +*.msi + +# =========================== +# Testing +# =========================== +coverage/ +.nyc_output/ +test-results/ +playwright-report/ +playwright/.cache/ + +# =========================== +# Misc +# =========================== +*.local +*.bak +*.tmp +*.temp + +# Development dev/ - -.auto-claude/ - +_bmad/ +_bmad-output/ +.claude/ /docs - -_bmad -_bmad-output - -.claude +OPUS_ANALYSIS_AND_IDEAS.md diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 00000000..53d141b8 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,73 @@ +#!/bin/sh + +# Commit message validation +# Enforces conventional commit format: type(scope): description +# +# Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert +# Examples: +# feat(tasks): add drag and drop support +# fix(terminal): resolve scroll position issue +# docs: update README with setup instructions +# chore: update dependencies + +commit_msg_file=$1 +commit_msg=$(cat "$commit_msg_file") + +# Regex for conventional commits +# Format: type(optional-scope): description +pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9-]+\))?: .{1,100}$" + +# Allow merge commits +if echo "$commit_msg" | grep -qE "^Merge "; then + exit 0 +fi + +# Allow revert commits +if echo "$commit_msg" | grep -qE "^Revert "; then + exit 0 +fi + +# Check first line against pattern +first_line=$(echo "$commit_msg" | head -n 1) + +if ! echo "$first_line" | grep -qE "$pattern"; then + echo "" + echo "ERROR: Invalid commit message format!" + echo "" + echo "Your message: $first_line" + echo "" + echo "Expected format: type(scope): description" + echo "" + echo "Valid types:" + echo " feat - A new feature" + echo " fix - A bug fix" + echo " docs - Documentation changes" + echo " style - Code style changes (formatting, semicolons, etc.)" + echo " refactor - Code refactoring (no feature/fix)" + echo " perf - Performance improvements" + echo " test - Adding or updating tests" + echo " build - Build system or dependencies" + echo " ci - CI/CD configuration" + echo " chore - Other changes (maintenance)" + echo " revert - Reverting a previous commit" + echo "" + echo "Examples:" + echo " feat(tasks): add drag and drop support" + echo " fix(terminal): resolve scroll position issue" + echo " docs: update README" + echo " chore: update dependencies" + echo "" + exit 1 +fi + +# Check description length (max 100 chars for first line) +if [ ${#first_line} -gt 100 ]; then + echo "" + echo "ERROR: Commit message first line is too long!" + echo "Maximum: 100 characters" + echo "Current: ${#first_line} characters" + echo "" + exit 1 +fi + +exit 0 diff --git a/.husky/pre-commit b/.husky/pre-commit index d3f678b6..e79978be 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,6 +1,96 @@ #!/bin/sh -# Run lint-staged in auto-claude-ui if there are staged files there -if git diff --cached --name-only | grep -q "^auto-claude-ui/"; then - cd auto-claude-ui && pnpm exec lint-staged +echo "Running pre-commit checks..." + +# ============================================================================= +# BACKEND CHECKS (Python) - Run first, before frontend +# ============================================================================= + +# Check if there are staged Python files in apps/backend +if git diff --cached --name-only | grep -q "^apps/backend/.*\.py$"; then + echo "Python changes detected, running backend checks..." + + # Run ruff linting + echo "Running ruff lint..." + ruff check apps/backend/ --fix + if [ $? -ne 0 ]; then + echo "Ruff lint failed. Please fix Python linting errors before committing." + exit 1 + fi + + # Run ruff format check + echo "Running ruff format check..." + ruff format apps/backend/ --check + if [ $? -ne 0 ]; then + echo "Ruff format check failed. Run 'ruff format apps/backend/' to fix." + exit 1 + fi + + # Run pytest (skip slow/integration tests and Windows-incompatible tests for pre-commit speed) + echo "Running Python tests..." + cd apps/backend + # Tests to skip: graphiti (external deps), merge_file_tracker/service_orchestrator/worktree/workspace (Windows path/git issues) + IGNORE_TESTS="--ignore=../../tests/test_graphiti.py --ignore=../../tests/test_merge_file_tracker.py --ignore=../../tests/test_service_orchestrator.py --ignore=../../tests/test_worktree.py --ignore=../../tests/test_workspace.py" + if [ -d ".venv" ]; then + # Use venv if it exists + if [ -f ".venv/bin/pytest" ]; then + PYTHONPATH=. .venv/bin/pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS + elif [ -f ".venv/Scripts/pytest.exe" ]; then + # Windows + PYTHONPATH=. .venv/Scripts/pytest.exe ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS + else + PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS + fi + else + PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" $IGNORE_TESTS + fi + if [ $? -ne 0 ]; then + echo "Python tests failed. Please fix failing tests before committing." + exit 1 + fi + cd ../.. + + echo "Backend checks passed!" fi + +# ============================================================================= +# FRONTEND CHECKS (TypeScript/React) +# ============================================================================= + +# Check if there are staged files in apps/frontend +if git diff --cached --name-only | grep -q "^apps/frontend/"; then + echo "Frontend changes detected, running frontend checks..." + cd apps/frontend + + # Run lint-staged (handles staged .ts/.tsx files) + npm exec lint-staged + + # Run TypeScript type check + echo "Running type check..." + npm run typecheck + if [ $? -ne 0 ]; then + echo "Type check failed. Please fix TypeScript errors before committing." + exit 1 + fi + + # Run linting + echo "Running lint..." + npm run lint + if [ $? -ne 0 ]; then + echo "Lint failed. Run 'npm run lint:fix' to auto-fix issues." + exit 1 + fi + + # Check for vulnerabilities (only high severity) + echo "Checking for vulnerabilities..." + npm audit --audit-level=high + if [ $? -ne 0 ]; then + echo "High severity vulnerabilities found. Run 'npm audit fix' to resolve." + exit 1 + fi + + cd ../.. + echo "Frontend checks passed!" +fi + +echo "All pre-commit checks passed!" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5ee8b74e..e167c1d6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,29 +1,39 @@ repos: - # Python linting (auto-claude/) + # Python linting (apps/backend/) - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.8.3 hooks: - id: ruff args: [--fix] - files: ^auto-claude/ + files: ^apps/backend/ - id: ruff-format - files: ^auto-claude/ + files: ^apps/backend/ - # Frontend linting (auto-claude-ui/) + # Python tests (apps/backend/) - skip slow/integration tests for pre-commit speed + - repo: local + hooks: + - id: pytest + name: Python Tests + entry: bash -c 'cd apps/backend && PYTHONPATH=. python -m pytest ../../tests/ -v --tb=short -x -m "not slow and not integration" --ignore=../../tests/test_graphiti.py' + language: system + files: ^(apps/backend/.*\.py$|tests/.*\.py$) + pass_filenames: false + + # Frontend linting (apps/frontend/) - repo: local hooks: - id: eslint name: ESLint - entry: bash -c 'cd auto-claude-ui && pnpm lint' + entry: bash -c 'cd apps/frontend && npm run lint' language: system - files: ^auto-claude-ui/.*\.(ts|tsx|js|jsx)$ + files: ^apps/frontend/.*\.(ts|tsx|js|jsx)$ pass_filenames: false - id: typecheck name: TypeScript Check - entry: bash -c 'cd auto-claude-ui && pnpm typecheck' + entry: bash -c 'cd apps/frontend && npm run typecheck' language: system - files: ^auto-claude-ui/.*\.(ts|tsx)$ + files: ^apps/frontend/.*\.(ts|tsx)$ pass_filenames: false # General checks diff --git a/CLAUDE.md b/CLAUDE.md index 67a50bca..58020759 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,89 +9,109 @@ Auto Claude is a multi-agent autonomous coding framework that builds software th ## Commands ### Setup + +**Requirements:** +- Python 3.12+ (required for backend) +- Node.js (for frontend) + ```bash -# Install dependencies (from auto-claude/) -uv venv && uv pip install -r requirements.txt -# Or: python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt +# Install all dependencies from root +npm run install:all + +# Or install separately: +# Backend (from apps/backend/) +cd apps/backend && uv venv && uv pip install -r requirements.txt + +# Frontend (from apps/frontend/) +cd apps/frontend && npm install # Set up OAuth token claude setup-token -# Add to auto-claude/.env: CLAUDE_CODE_OAUTH_TOKEN=your-token +# Add to apps/backend/.env: CLAUDE_CODE_OAUTH_TOKEN=your-token ``` ### Creating and Running Specs ```bash +cd apps/backend + # Create a spec interactively -python auto-claude/spec_runner.py --interactive +python spec_runner.py --interactive # Create spec from task description -python auto-claude/spec_runner.py --task "Add user authentication" +python spec_runner.py --task "Add user authentication" # Force complexity level (simple/standard/complex) -python auto-claude/spec_runner.py --task "Fix button" --complexity simple +python spec_runner.py --task "Fix button" --complexity simple # Run autonomous build -python auto-claude/run.py --spec 001 +python run.py --spec 001 # List all specs -python auto-claude/run.py --list +python run.py --list ``` ### Workspace Management ```bash +cd apps/backend + # Review changes in isolated worktree -python auto-claude/run.py --spec 001 --review +python run.py --spec 001 --review # Merge completed build into project -python auto-claude/run.py --spec 001 --merge +python run.py --spec 001 --merge # Discard build -python auto-claude/run.py --spec 001 --discard +python run.py --spec 001 --discard ``` ### QA Validation ```bash +cd apps/backend + # Run QA manually -python auto-claude/run.py --spec 001 --qa +python run.py --spec 001 --qa # Check QA status -python auto-claude/run.py --spec 001 --qa-status +python run.py --spec 001 --qa-status ``` ### Testing ```bash # Install test dependencies (required first time) -cd auto-claude && uv pip install -r ../tests/requirements-test.txt +cd apps/backend && uv pip install -r ../../tests/requirements-test.txt # Run all tests (use virtual environment pytest) -auto-claude/.venv/bin/pytest tests/ -v +apps/backend/.venv/bin/pytest tests/ -v # Run single test file -auto-claude/.venv/bin/pytest tests/test_security.py -v +apps/backend/.venv/bin/pytest tests/test_security.py -v # Run specific test -auto-claude/.venv/bin/pytest tests/test_security.py::test_bash_command_validation -v +apps/backend/.venv/bin/pytest tests/test_security.py::test_bash_command_validation -v # Skip slow tests -auto-claude/.venv/bin/pytest tests/ -m "not slow" +apps/backend/.venv/bin/pytest tests/ -m "not slow" + +# Or from root +npm run test:backend ``` ### Spec Validation ```bash -python auto-claude/validate_spec.py --spec-dir auto-claude/specs/001-feature --checkpoint all +python apps/backend/validate_spec.py --spec-dir apps/backend/specs/001-feature --checkpoint all ``` ### Releases ```bash # Automated version bump and release (recommended) -node scripts/bump-version.js patch # 2.5.5 -> 2.5.6 -node scripts/bump-version.js minor # 2.5.5 -> 2.6.0 -node scripts/bump-version.js major # 2.5.5 -> 3.0.0 -node scripts/bump-version.js 2.6.0 # Set specific version +node scripts/bump-version.js patch # 2.8.0 -> 2.8.1 +node scripts/bump-version.js minor # 2.8.0 -> 2.9.0 +node scripts/bump-version.js major # 2.8.0 -> 3.0.0 +node scripts/bump-version.js 2.9.0 # Set specific version # Then push to trigger GitHub release workflows git push origin main -git push origin v2.6.0 +git push origin v2.9.0 ``` See [RELEASE.md](RELEASE.md) for detailed release process documentation. @@ -111,18 +131,18 @@ See [RELEASE.md](RELEASE.md) for detailed release process documentation. 3. QA Reviewer validates acceptance criteria 4. QA Fixer resolves issues in a loop -### Key Components +### Key Components (apps/backend/) - **client.py** - Claude SDK client with security hooks and tool permissions - **security.py** + **project_analyzer.py** - Dynamic command allowlisting based on detected project stack - **worktree.py** - Git worktree isolation for safe feature development - **memory.py** - File-based session memory (primary, always-available storage) -- **graphiti_memory.py** - Optional graph-based cross-session memory with semantic search +- **graphiti_memory.py** - Graph-based cross-session memory with semantic search - **graphiti_providers.py** - Multi-provider factory for Graphiti (OpenAI, Anthropic, Azure, Ollama, Google AI) - **graphiti_config.py** - Configuration and validation for Graphiti integration - **linear_updater.py** - Optional Linear integration for progress tracking -### Agent Prompts (auto-claude/prompts/) +### Agent Prompts (apps/backend/prompts/) | Prompt | Purpose | |--------|---------| @@ -139,7 +159,7 @@ See [RELEASE.md](RELEASE.md) for detailed release process documentation. ### Spec Directory Structure -Each spec in `auto-claude/specs/XXX-name/` contains: +Each spec in `.auto-claude/specs/XXX-name/` contains: - `spec.md` - Feature specification - `requirements.json` - Structured user requirements - `context.json` - Discovered codebase context @@ -188,35 +208,36 @@ Dual-layer memory architecture: - Human-readable files in `specs/XXX/memory/` - Session insights, patterns, gotchas, codebase map -**Graphiti Memory (Optional Enhancement)** - `graphiti_memory.py` +**Graphiti Memory** - `graphiti_memory.py` - Graph database with semantic search (LadybugDB - embedded, no Docker) - Cross-session context retrieval -- Requires Python 3.12+ - Multi-provider support: - LLM: OpenAI, Anthropic, Azure OpenAI, Ollama, Google AI (Gemini) - Embedders: OpenAI, Voyage AI, Azure OpenAI, Ollama, Google AI - -```bash -# Setup (requires Python 3.12+) -pip install real_ladybug graphiti-core -``` - -Enable with: `GRAPHITI_ENABLED=true` + provider credentials. See `.env.example`. +- Configure with provider credentials in `.env.example` ## Project Structure -Auto Claude can be used in two ways: - -**As a standalone CLI tool** (original project): -```bash -python auto-claude/run.py --spec 001 +``` +auto-claude/ +├── apps/ +│ ├── backend/ # Python backend/CLI (the framework code) +│ └── frontend/ # Electron desktop UI +├── guides/ # Documentation +├── tests/ # Test suite +└── scripts/ # Build and utility scripts ``` -**With the optional Electron frontend** (`auto-claude-ui/`): -- Provides a GUI for task management and progress tracking -- Wraps the CLI commands - the backend works independently +**As a standalone CLI tool**: +```bash +cd apps/backend +python run.py --spec 001 +``` + +**With the Electron frontend**: +```bash +npm start # Build and run desktop app +npm run dev # Run in development mode +``` -**Directory layout:** -- `auto-claude/` - Python backend/CLI (the framework code) -- `auto-claude-ui/` - Optional Electron frontend - `.auto-claude/specs/` - Per-project data (specs, plans, QA reports) - gitignored diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef53d5f9..4b64cf42 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,6 +5,7 @@ Thank you for your interest in contributing to Auto Claude! This document provid ## Table of Contents - [Prerequisites](#prerequisites) +- [Quick Start](#quick-start) - [Development Setup](#development-setup) - [Python Backend](#python-backend) - [Electron Frontend](#electron-frontend) @@ -30,37 +31,77 @@ Thank you for your interest in contributing to Auto Claude! This document provid Before contributing, ensure you have the following installed: -- **Python 3.8+** - For the backend framework -- **Node.js 18+** - For the Electron frontend -- **pnpm** - Package manager for the frontend (`npm install -g pnpm`) +- **Python 3.12+** - For the backend framework +- **Node.js 24+** - For the Electron frontend +- **npm 10+** - Package manager for the frontend (comes with Node.js) - **uv** (recommended) or **pip** - Python package manager - **Git** - Version control +### Installing Python 3.12 + +**Windows:** +```bash +winget install Python.Python.3.12 +``` + +**macOS:** +```bash +brew install python@3.12 +``` + +**Linux (Ubuntu/Debian):** +```bash +sudo apt install python3.12 python3.12-venv +``` + +## Quick Start + +The fastest way to get started: + +```bash +# Clone the repository +git clone https://github.com/AndyMik90/Auto-Claude.git +cd Auto-Claude + +# Install all dependencies (cross-platform) +npm run install:all + +# Run in development mode +npm run dev + +# Or build and run production +npm start +``` + ## Development Setup The project consists of two main components: -1. **Python Backend** (`auto-claude/`) - The core autonomous coding framework -2. **Electron Frontend** (`auto-claude-ui/`) - Optional desktop UI +1. **Python Backend** (`apps/backend/`) - The core autonomous coding framework +2. **Electron Frontend** (`apps/frontend/`) - Optional desktop UI ### Python Backend +The recommended way is to use `npm run install:backend`, but you can also set up manually: + ```bash -# Navigate to the auto-claude directory -cd auto-claude +# Navigate to the backend directory +cd apps/backend -# Create virtual environment (using uv - recommended) -uv venv -source .venv/bin/activate # On Windows: .venv\Scripts\activate -uv pip install -r requirements.txt +# Create virtual environment +# Windows: +py -3.12 -m venv .venv +.venv\Scripts\activate -# Or using standard Python -python3 -m venv .venv +# macOS/Linux: +python3.12 -m venv .venv source .venv/bin/activate + +# Install dependencies pip install -r requirements.txt # Install test dependencies -pip install -r ../tests/requirements-test.txt +pip install -r ../../tests/requirements-test.txt # Set up environment cp .env.example .env @@ -70,31 +111,31 @@ cp .env.example .env ### Electron Frontend ```bash -# Navigate to the UI directory -cd auto-claude-ui +# Navigate to the frontend directory +cd apps/frontend # Install dependencies -pnpm install +npm install # Start development server -pnpm dev +npm run dev # Build for production -pnpm build +npm run build # Package for distribution -pnpm package +npm run package ``` ## Running from Source If you want to run Auto Claude from source (for development or testing unreleased features), follow these steps: -### Step 1: Clone and Set Up Python Backend +### Step 1: Clone and Set Up ```bash git clone https://github.com/AndyMik90/Auto-Claude.git -cd Auto-Claude/auto-claude +cd Auto-Claude/apps/backend # Using uv (recommended) uv venv && uv pip install -r requirements.txt @@ -105,6 +146,7 @@ source .venv/bin/activate # On Windows: .venv\Scripts\activate pip install -r requirements.txt # Set up environment +cd apps/backend cp .env.example .env # Edit .env and add your CLAUDE_CODE_OAUTH_TOKEN (get it via: claude setup-token) ``` @@ -112,16 +154,16 @@ cp .env.example .env ### Step 2: Run the Desktop UI ```bash -cd ../auto-claude-ui +cd ../frontend # Install dependencies -pnpm install +npm install # Development mode (hot reload) -pnpm dev +npm run dev # Or production build -pnpm run build && pnpm run start +npm run build && npm run start ```
@@ -132,7 +174,7 @@ Auto Claude automatically downloads prebuilt binaries for Windows. If prebuilts 1. Download [Visual Studio Build Tools 2022](https://visualstudio.microsoft.com/visual-cpp-build-tools/) 2. Select "Desktop development with C++" workload 3. In "Individual Components", add "MSVC v143 - VS 2022 C++ x64/x86 Spectre-mitigated libs" -4. Restart terminal and run `pnpm install` again +4. Restart terminal and run `npm install` again
@@ -158,10 +200,10 @@ When you commit, the following checks run automatically: | Check | Scope | Description | |-------|-------|-------------| -| **ruff** | `auto-claude/` | Python linter with auto-fix | -| **ruff-format** | `auto-claude/` | Python code formatter | -| **eslint** | `auto-claude-ui/` | TypeScript/React linter | -| **typecheck** | `auto-claude-ui/` | TypeScript type checking | +| **ruff** | `apps/backend/` | Python linter with auto-fix | +| **ruff-format** | `apps/backend/` | Python code formatter | +| **eslint** | `apps/frontend/` | TypeScript/React linter | +| **typecheck** | `apps/frontend/` | TypeScript type checking | | **trailing-whitespace** | All files | Removes trailing whitespace | | **end-of-file-fixer** | All files | Ensures files end with newline | | **check-yaml** | All files | Validates YAML syntax | @@ -218,7 +260,7 @@ def gnc(sd): ### TypeScript/React - Use TypeScript strict mode -- Follow the existing component patterns in `auto-claude-ui/src/` +- Follow the existing component patterns in `apps/frontend/src/` - Use functional components with hooks - Prefer named exports over default exports - Use the UI components from `src/renderer/components/ui/` @@ -248,20 +290,25 @@ export default function(props) { ### Python Tests ```bash -# Run all tests -pytest tests/ -v +# Run all tests (from repository root) +npm run test:backend + +# Or manually with pytest +cd apps/backend +.venv/Scripts/pytest.exe ../tests -v # Windows +.venv/bin/pytest ../tests -v # macOS/Linux # Run a specific test file -pytest tests/test_security.py -v +npm run test:backend -- tests/test_security.py -v # Run a specific test -pytest tests/test_security.py::test_bash_command_validation -v +npm run test:backend -- tests/test_security.py::test_bash_command_validation -v # Skip slow tests -pytest tests/ -m "not slow" +npm run test:backend -- -m "not slow" # Run with coverage -pytest tests/ --cov=auto-claude --cov-report=html +pytest tests/ --cov=apps/backend --cov-report=html ``` Test configuration is in `tests/pytest.ini`. @@ -269,26 +316,26 @@ Test configuration is in `tests/pytest.ini`. ### Frontend Tests ```bash -cd auto-claude-ui +cd apps/frontend # Run unit tests -pnpm test +npm test # Run tests in watch mode -pnpm test:watch +npm run test:watch # Run with coverage -pnpm test:coverage +npm run test:coverage # Run E2E tests (requires built app) -pnpm build -pnpm test:e2e +npm run build +npm run test:e2e # Run linting -pnpm lint +npm run lint # Run type checking -pnpm typecheck +npm run typecheck ``` ### Testing Requirements @@ -326,15 +373,15 @@ Before a PR can be merged: ```bash # Python tests -cd auto-claude +cd apps/backend source .venv/bin/activate -pytest ../tests/ -v +pytest ../../tests/ -v # Frontend tests -cd auto-claude-ui -pnpm test -pnpm lint -pnpm typecheck +cd apps/frontend +npm test +npm run lint +npm run typecheck ``` ## Git Workflow @@ -378,6 +425,7 @@ Use descriptive branch names with a prefix indicating the type of change: |--------|---------|---------| | `feature/` | New feature | `feature/add-dark-mode` | | `fix/` | Bug fix | `fix/memory-leak-in-worker` | +| `hotfix/` | Urgent production fix | `hotfix/critical-crash-fix` | | `docs/` | Documentation | `docs/update-readme` | | `refactor/` | Code refactoring | `refactor/simplify-auth-flow` | | `test/` | Test additions/fixes | `test/add-integration-tests` | @@ -443,6 +491,52 @@ git branch -d release/v2.8.0 git push origin --delete release/v2.8.0 ``` +### Hotfix Workflow + +For urgent production fixes that can't wait for the normal release cycle: + +**1. Create hotfix from main** + +```bash +git checkout main +git pull origin main +git checkout -b hotfix/150-critical-fix +``` + +**2. Fix the issue** + +```bash +# ... make changes ... +git commit -m "hotfix: fix critical crash on startup" +``` + +**3. Open PR to main (fast-track review)** + +```bash +gh pr create --base main --title "hotfix: fix critical crash on startup" +``` + +**4. After merge to main, sync to develop** + +```bash +git checkout develop +git pull origin develop +git merge main +git push origin develop +``` + +``` +main ─────●─────●─────●─────●───── (production) + ↑ ↑ ↑ ↑ +develop ──●─────●─────●─────●───── (integration) + ↑ ↑ ↑ +feature/123 ────● +feature/124 ──────────● +hotfix/125 ─────────────────●───── (from main, merge to both) +``` + +> **Note:** Hotfixes branch FROM `main` and merge TO `main` first, then sync back to `develop` to keep branches aligned. + ### Commit Messages Write clear, concise commit messages that explain the "why" behind changes: @@ -487,11 +581,11 @@ git commit -m "WIP" 3. **Test thoroughly**: ```bash - # Python - pytest tests/ -v + # Python (from repository root) + npm run test:backend # Frontend - cd auto-claude-ui && pnpm test && pnpm lint && pnpm typecheck + cd apps/frontend && npm test && npm run lint && npm run typecheck ``` 4. **Update documentation** if your changes affect: @@ -550,7 +644,7 @@ When requesting a feature: Auto Claude consists of two main parts: -### Python Backend (`auto-claude/`) +### Python Backend (`apps/backend/`) The core autonomous coding framework: @@ -560,9 +654,9 @@ The core autonomous coding framework: - **Memory**: `memory.py` (file-based), `graphiti_memory.py` (graph-based) - **QA**: `qa_loop.py`, `prompts/qa_*.md` -### Electron Frontend (`auto-claude-ui/`) +### Electron Frontend (`apps/frontend/`) -Optional desktop interface: +Desktop interface: - **Main Process**: `src/main/` - Electron main process, IPC handlers - **Renderer**: `src/renderer/` - React UI components diff --git a/README.md b/README.md index 7dbd0a46..b6ea25f9 100644 --- a/README.md +++ b/README.md @@ -1,269 +1,222 @@ # Auto Claude -Your AI coding companion. Build features, fix bugs, and ship faster — with autonomous agents that plan, code, and validate for you. +**Autonomous multi-agent coding framework that plans, builds, and validates software for you.** ![Auto Claude Kanban Board](.github/assets/Auto-Claude-Kanban.png) -[![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/KCXaPBr4Dj) +[![Version](https://img.shields.io/badge/version-2.8.0-blue?style=flat-square)](https://github.com/AndyMik90/Auto-Claude/releases/latest) +[![License](https://img.shields.io/badge/license-AGPL--3.0-green?style=flat-square)](./agpl-3.0.txt) +[![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/KCXaPBr4Dj) +[![CI](https://img.shields.io/github/actions/workflow/status/AndyMik90/Auto-Claude/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/AndyMik90/Auto-Claude/actions) -## What It Does ✨ +--- -**Auto Claude is a desktop app that supercharges your AI coding workflow.** Whether you're a vibe coder just getting started or an experienced developer, Auto Claude meets you where you are. +## Download -- **Autonomous Tasks** — Describe what you want to build, and agents handle planning, coding, and validation while you focus on other work -- **Agent Terminals** — Run Claude Code in up to 12 terminals with a clean layout, smart naming based on context, and one-click task context injection -- **Safe by Default** — All work happens in git worktrees, keeping your main branch undisturbed until you're ready to merge -- **Self-Validating** — Built-in QA agents check their own work before you review +Get the latest pre-built release for your platform: -**The result?** 10x your output while maintaining code quality. +| Platform | Download | Notes | +|----------|----------|-------| +| **Windows** | [Auto-Claude-2.8.0.exe](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Installer (NSIS) | +| **macOS (Apple Silicon)** | [Auto-Claude-2.8.0-arm64.dmg](https://github.com/AndyMik90/Auto-Claude/releases/latest) | M1/M2/M3 Macs | +| **macOS (Intel)** | [Auto-Claude-2.8.0-x64.dmg](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Intel Macs | +| **Linux** | [Auto-Claude-2.8.0.AppImage](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Universal | +| **Linux (Debian)** | [Auto-Claude-2.8.0.deb](https://github.com/AndyMik90/Auto-Claude/releases/latest) | Ubuntu/Debian | -## Key Features +> All releases include SHA256 checksums and VirusTotal scan results for security verification. -- **Parallel Agents**: Run multiple builds simultaneously while you focus on other work -- **Context Engineering**: Agents understand your codebase structure before writing code -- **Self-Validating**: Built-in QA loop catches issues before you review -- **Isolated Workspaces**: All work happens in git worktrees — your code stays safe -- **AI Merge Resolution**: Intelligent conflict resolution when merging back to main — no manual conflict fixing -- **Cross-Platform**: Desktop app runs on Mac, Windows, and Linux -- **Any Project Type**: Build web apps, APIs, CLIs — works with any software project +--- + +## Requirements + +- **Claude Pro/Max subscription** - [Get one here](https://claude.ai/upgrade) +- **Claude Code CLI** - `npm install -g @anthropic-ai/claude-code` +- **Git repository** - Your project must be initialized as a git repo +- **Python 3.12+** - Required for the backend and Memory Layer + +--- ## Quick Start -### Download Auto Claude - -Download the latest release for your platform from [GitHub Releases](https://github.com/AndyMik90/Auto-Claude/releases/latest): - -| Platform | Download | -|----------|----------| -| **macOS (Apple Silicon M1-M4)** | `*-arm64.dmg` | -| **macOS (Intel)** | `*-x64.dmg` | -| **Windows** | `*.exe` | -| **Linux** | `*.AppImage` or `*.deb` | - -> **Not sure which Mac?** Click the Apple menu () > "About This Mac". Look for "Chip" - M1/M2/M3/M4 = Apple Silicon, otherwise Intel. - -### Prerequisites - -Before using Auto Claude, you need: - -1. **Claude Subscription** - Requires [Claude Pro or Max](https://claude.ai/upgrade) for Claude Code access -2. **Claude Code CLI** - Install with: `npm install -g @anthropic-ai/claude-code` - -### Install and Run - -1. **Download** the installer for your platform from the table above -2. **Install**: - - **macOS**: Open the `.dmg`, drag Auto Claude to Applications - - **Windows**: Run the `.exe` installer (see note below about security warning) - - **Linux**: Make the AppImage executable (`chmod +x`) and run it, or install the `.deb` -3. **Launch** Auto Claude -4. **Add your project** and start building! - -
-Windows users: Security warning when installing - -The Windows installer is not yet code-signed, so you may see a "Windows protected your PC" warning from Microsoft Defender SmartScreen. - -**To proceed:** -1. Click "More info" -2. Click "Run anyway" - -This is safe — all releases are automatically scanned with VirusTotal before publishing. You can verify any installer by checking the **VirusTotal Scan Results** section in each [release's notes](https://github.com/AndyMik90/Auto-Claude/releases). - -We're working on obtaining a code signing certificate for future releases. - -
- -> **Want to build from source?** See [CONTRIBUTING.md](CONTRIBUTING.md#running-from-source) for development setup. +1. **Download and install** the app for your platform +2. **Open your project** - Select a git repository folder +3. **Connect Claude** - The app will guide you through OAuth setup +4. **Create a task** - Describe what you want to build +5. **Watch it work** - Agents plan, code, and validate autonomously --- -## 🎯 Features +## Features + +| Feature | Description | +|---------|-------------| +| **Autonomous Tasks** | Describe your goal; agents handle planning, implementation, and validation | +| **Parallel Execution** | Run multiple builds simultaneously with up to 12 agent terminals | +| **Isolated Workspaces** | All changes happen in git worktrees - your main branch stays safe | +| **Self-Validating QA** | Built-in quality assurance loop catches issues before you review | +| **AI-Powered Merge** | Automatic conflict resolution when integrating back to main | +| **Memory Layer** | Agents retain insights across sessions for smarter builds | +| **Cross-Platform** | Native desktop apps for Windows, macOS, and Linux | +| **Auto-Updates** | App updates automatically when new versions are released | + +--- + +## Interface ### Kanban Board - -Plan tasks and let AI handle the planning, coding, and validation — all in a visual interface. Track progress from "Planning" to "Done" while agents work autonomously. +Visual task management from planning through completion. Create tasks and monitor agent progress in real-time. ### Agent Terminals +AI-powered terminals with one-click task context injection. Spawn multiple agents for parallel work. -Spawn up to 12 AI-powered terminals for hands-on coding. Inject task context with a click, reference files from your project, and work rapidly across multiple sessions. - -**Power users:** Connect multiple Claude Code subscriptions to run even more agents in parallel — perfect for teams or heavy workloads. - -![Auto Claude Agent Terminals](.github/assets/Auto-Claude-Agents-terminals.png) - -### Insights - -Have a conversation about your project in a ChatGPT-style interface. Ask questions, get explanations, and explore your codebase through natural dialogue. +![Agent Terminals](.github/assets/Auto-Claude-Agents-terminals.png) ### Roadmap +AI-assisted feature planning with competitor analysis and audience targeting. -Based on your target audience, AI anticipates and plans the most impactful features you should focus on. Prioritize what matters most to your users. +![Roadmap](.github/assets/Auto-Claude-roadmap.png) -![Auto Claude Roadmap](.github/assets/Auto-Claude-roadmap.png) - -### Ideation - -Let AI help you create a project that shines. Rapidly understand your codebase and discover: -- Code improvements and refactoring opportunities -- Performance bottlenecks -- Security vulnerabilities -- Documentation gaps -- UI/UX enhancements -- Overall code quality issues - -### Changelog - -Write professional changelogs effortlessly. Generate release notes from completed Auto Claude tasks or integrate with GitHub to create masterclass changelogs automatically. - -### Context - -See exactly what Auto Claude understands about your project — the tech stack, file structure, patterns, and insights it uses to write better code. - -### AI Merge Resolution - -When your main branch evolves while a build is in progress, Auto Claude automatically resolves merge conflicts using AI — no manual `<<<<<<< HEAD` fixing required. - -**How it works:** -1. **Git Auto-Merge First** — Simple non-conflicting changes merge instantly without AI -2. **Conflict-Only AI** — For actual conflicts, AI receives only the specific conflict regions (not entire files), achieving ~98% prompt reduction -3. **Parallel Processing** — Multiple conflicting files resolve simultaneously for faster merges -4. **Syntax Validation** — Every merge is validated before being applied - -**The result:** A build that was 50+ commits behind main merges in seconds instead of requiring manual conflict resolution. +### Additional Features +- **Insights** - Chat interface for exploring your codebase +- **Ideation** - Discover improvements, performance issues, and vulnerabilities +- **Changelog** - Generate release notes from completed tasks --- -## CLI Usage (Terminal-Only) - -For terminal-based workflows, headless servers, or CI/CD integration, see **[guides/CLI-USAGE.md](guides/CLI-USAGE.md)**. - -## ⚙️ How It Works - -Auto Claude focuses on three core principles: **context engineering** (understanding your codebase before writing code), **good coding standards** (following best practices and patterns), and **validation logic** (ensuring code works before you see it). - -### The Agent Pipeline - -**Phase 1: Spec Creation** (3-8 phases based on complexity) - -Before any code is written, agents gather context and create a detailed specification: - -1. **Discovery** — Analyzes your project structure and tech stack -2. **Requirements** — Gathers what you want to build through interactive conversation -3. **Research** — Validates external integrations against real documentation -4. **Context Discovery** — Finds relevant files in your codebase -5. **Spec Writer** — Creates a comprehensive specification document -6. **Spec Critic** — Self-critiques using extended thinking to find issues early -7. **Planner** — Breaks work into subtasks with dependencies -8. **Validation** — Ensures all outputs are valid before proceeding - -**Phase 2: Implementation** - -With a validated spec, coding agents execute the plan: - -1. **Planner Agent** — Creates subtask-based implementation plan -2. **Coder Agent** — Implements subtasks one-by-one with verification -3. **QA Reviewer** — Validates all acceptance criteria -4. **QA Fixer** — Fixes issues in a self-healing loop (up to 50 iterations) - -Each session runs with a fresh context window. Progress is tracked via `implementation_plan.json` and Git commits. - -**Phase 3: Merge** - -When you're ready to merge, AI handles any conflicts that arose while you were working: - -1. **Conflict Detection** — Identifies files modified in both main and the build -2. **3-Tier Resolution** — Git auto-merge → Conflict-only AI → Full-file AI (fallback) -3. **Parallel Merge** — Multiple files resolve simultaneously -4. **Staged for Review** — Changes are staged but not committed, so you can review before finalizing - -### 🔒 Security Model - -Three-layer defense keeps your code safe: -- **OS Sandbox** — Bash commands run in isolation -- **Filesystem Restrictions** — Operations limited to project directory -- **Command Allowlist** — Only approved commands based on your project's stack - ## Project Structure ``` -your-project/ -├── .worktrees/ # Created during build (git-ignored) -│ └── auto-claude/ # Isolated workspace for AI coding -├── .auto-claude/ # Per-project data (specs, plans, QA reports) -│ ├── specs/ # Task specifications -│ ├── roadmap/ # Project roadmap -│ └── ideation/ # Ideas and planning -├── auto-claude/ # Python backend (framework code) -│ ├── run.py # Build entry point -│ ├── spec_runner.py # Spec creation orchestrator -│ ├── prompts/ # Agent prompt templates -│ └── ... -└── auto-claude-ui/ # Electron desktop application - └── ... +Auto-Claude/ +├── apps/ +│ ├── backend/ # Python agents, specs, QA pipeline +│ └── frontend/ # Electron desktop application +├── guides/ # Additional documentation +├── tests/ # Test suite +└── scripts/ # Build utilities ``` -### Understanding the Folders +--- -**You don't create these folders manually** - they serve different purposes: +## CLI Usage -- **`auto-claude/`** - The framework repository itself (clone this once from GitHub) -- **`.auto-claude/`** - Created automatically in YOUR project when you run Auto Claude (stores specs, plans, QA reports) -- **`.worktrees/`** - Temporary isolated workspaces created during builds (git-ignored, deleted after merge) +For headless operation, CI/CD integration, or terminal-only workflows: -**When using Auto Claude on your project:** ```bash -cd your-project/ # Your own project directory -python /path/to/auto-claude/run.py --spec 001 -# Auto Claude creates .auto-claude/ automatically in your-project/ +cd apps/backend + +# Create a spec interactively +python spec_runner.py --interactive + +# Run autonomous build +python run.py --spec 001 + +# Review and merge +python run.py --spec 001 --review +python run.py --spec 001 --merge ``` -**When developing Auto Claude itself:** +See [guides/CLI-USAGE.md](guides/CLI-USAGE.md) for complete CLI documentation. + +--- + +## Configuration + +Create `apps/backend/.env` from the example: + ```bash -git clone https://github.com/yourusername/auto-claude -cd auto-claude/ # You're working in the framework repo +cp apps/backend/.env.example apps/backend/.env ``` -The `.auto-claude/` directory is gitignored and project-specific - you'll have one per project you use Auto Claude on. - -## Environment Variables (CLI Only) - -> **Desktop UI users:** These are configured through the app settings — no manual setup needed. - | Variable | Required | Description | |----------|----------|-------------| | `CLAUDE_CODE_OAUTH_TOKEN` | Yes | OAuth token from `claude setup-token` | -| `AUTO_BUILD_MODEL` | No | Model override (default: claude-opus-4-5-20251101) | +| `GRAPHITI_ENABLED` | No | Enable Memory Layer for cross-session context | +| `AUTO_BUILD_MODEL` | No | Override the default Claude model | -See `auto-claude/.env.example` for complete configuration options. +--- -## 💬 Community +## Building from Source -Join our Discord to get help, share what you're building, and connect with other Auto Claude users: +For contributors and development: -[![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/KCXaPBr4Dj) +```bash +# Clone the repository +git clone https://github.com/AndyMik90/Auto-Claude.git +cd Auto-Claude -## 🤝 Contributing +# Install all dependencies +npm run install:all -We welcome contributions! Whether it's bug fixes, new features, or documentation improvements. +# Run in development mode +npm run dev -See **[CONTRIBUTING.md](CONTRIBUTING.md)** for guidelines on how to get started. +# Or build and run +npm start +``` -## Acknowledgments +**System requirements for building:** +- Node.js 24+ +- Python 3.12+ +- npm 10+ -This framework was inspired by Anthropic's [Autonomous Coding Agent](https://github.com/anthropics/claude-quickstarts/tree/main/autonomous-coding). Thank you to the Anthropic team for their innovative work on autonomous coding systems. +See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed development setup. + +--- + +## Security + +Auto Claude uses a three-layer security model: + +1. **OS Sandbox** - Bash commands run in isolation +2. **Filesystem Restrictions** - Operations limited to project directory +3. **Dynamic Command Allowlist** - Only approved commands based on detected project stack + +All releases are: +- Scanned with VirusTotal before publishing +- Include SHA256 checksums for verification +- Code-signed where applicable (macOS) + +--- + +## Available Scripts + +| Command | Description | +|---------|-------------| +| `npm run install:all` | Install backend and frontend dependencies | +| `npm start` | Build and run the desktop app | +| `npm run dev` | Run in development mode with hot reload | +| `npm run package` | Package for current platform | +| `npm run package:mac` | Package for macOS | +| `npm run package:win` | Package for Windows | +| `npm run package:linux` | Package for Linux | +| `npm run lint` | Run linter | +| `npm test` | Run frontend tests | +| `npm run test:backend` | Run backend tests | + +--- + +## Contributing + +We welcome contributions! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for: +- Development setup instructions +- Code style guidelines +- Testing requirements +- Pull request process + +--- + +## Community + +- **Discord** - [Join our community](https://discord.gg/KCXaPBr4Dj) +- **Issues** - [Report bugs or request features](https://github.com/AndyMik90/Auto-Claude/issues) +- **Discussions** - [Ask questions](https://github.com/AndyMik90/Auto-Claude/discussions) + +--- ## License **AGPL-3.0** - GNU Affero General Public License v3.0 -This software is licensed under AGPL-3.0, which means: +Auto Claude is free to use. If you modify and distribute it, or run it as a service, your code must also be open source under AGPL-3.0. -- **Attribution Required**: You must give appropriate credit, provide a link to the license, and indicate if changes were made. When using Auto Claude, please credit the project. -- **Open Source Required**: If you modify this software and distribute it or run it as a service, you must release your source code under AGPL-3.0. -- **Network Use (Copyleft)**: If you run this software as a network service (e.g., SaaS), users interacting with it over a network must be able to receive the source code. -- **No Closed-Source Usage**: You cannot use this software in proprietary/closed-source projects without open-sourcing your entire project under AGPL-3.0. - -**In simple terms**: You can use Auto Claude freely, but if you build on it, your code must also be open source under AGPL-3.0 and attribute this project. Closed-source commercial use requires a separate license. - -For commercial licensing inquiries (closed-source usage), please contact the maintainers. +Commercial licensing available for closed-source use cases. diff --git a/RELEASE.md b/RELEASE.md index 57914a06..3978b063 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -30,7 +30,7 @@ We provide an automated script that handles version bumping, git commits, and ta ``` This script will: - - ✅ Update `auto-claude-ui/package.json` with the new version + - ✅ Update `apps/frontend/package.json` with the new version - ✅ Create a git commit with the version change - ✅ Create a git tag (e.g., `v2.5.6`) - ⚠️ **NOT** push to remote (you control when to push) @@ -71,7 +71,7 @@ We provide an automated script that handles version bumping, git commits, and ta If you need to create a release manually, follow these steps **carefully** to avoid version mismatches: -1. **Update `auto-claude-ui/package.json`:** +1. **Update `apps/frontend/package.json`:** ```json { @@ -82,7 +82,7 @@ If you need to create a release manually, follow these steps **carefully** to av 2. **Commit the change:** ```bash - git add auto-claude-ui/package.json + git add apps/frontend/package.json git commit -m "chore: bump version to 2.5.6" ``` diff --git a/auto-claude/.env.example b/apps/backend/.env.example similarity index 98% rename from auto-claude/.env.example rename to apps/backend/.env.example index 8ce6af28..3d4233e2 100644 --- a/auto-claude/.env.example +++ b/apps/backend/.env.example @@ -117,9 +117,9 @@ # ELECTRON_DEBUG_PORT=9222 # ============================================================================= -# GRAPHITI MEMORY INTEGRATION (OPTIONAL) +# GRAPHITI MEMORY INTEGRATION (REQUIRED) # ============================================================================= -# Enable Graphiti-based persistent memory layer for cross-session context +# Graphiti-based persistent memory layer for cross-session context # retention. Uses LadybugDB as the embedded graph database. # # REQUIREMENTS: @@ -133,8 +133,8 @@ # - Ollama (local, fully offline) # - Google AI (Gemini) -# Enable Graphiti integration (default: false) -# GRAPHITI_ENABLED=true +# Graphiti is enabled by default. Set to false to disable memory features. +GRAPHITI_ENABLED=true # ============================================================================= # GRAPHITI: Database Settings diff --git a/auto-claude/.gitignore b/apps/backend/.gitignore similarity index 94% rename from auto-claude/.gitignore rename to apps/backend/.gitignore index 31e19add..ad10d960 100644 --- a/auto-claude/.gitignore +++ b/apps/backend/.gitignore @@ -61,3 +61,6 @@ Thumbs.db # Tests (development only) tests/ + +# Auto Claude data directory +.auto-claude/ diff --git a/apps/backend/README.md b/apps/backend/README.md new file mode 100644 index 00000000..30640f61 --- /dev/null +++ b/apps/backend/README.md @@ -0,0 +1,120 @@ +# Auto Claude Backend + +Autonomous coding framework powered by Claude AI. Builds software features through coordinated multi-agent sessions. + +## Getting Started + +### 1. Install + +```bash +cd apps/backend +python -m pip install -r requirements.txt +``` + +### 2. Configure + +```bash +cp .env.example .env +``` + +Set your Claude API token in `.env`: +``` +CLAUDE_CODE_OAUTH_TOKEN=your-token-here +``` + +Get your token by running: `claude setup-token` + +### 3. Run + +```bash +# List available specs +python run.py --list + +# Run a spec +python run.py --spec 001 +``` + +## Requirements + +- Python 3.10+ +- Claude API token + +## Commands + +| Command | Description | +|---------|-------------| +| `--list` | List all specs | +| `--spec 001` | Run spec 001 | +| `--spec 001 --isolated` | Run in isolated workspace | +| `--spec 001 --direct` | Run directly in repo | +| `--spec 001 --merge` | Merge completed build | +| `--spec 001 --review` | Review build changes | +| `--spec 001 --discard` | Discard build | +| `--spec 001 --qa` | Run QA validation | +| `--list-worktrees` | List all worktrees | +| `--help` | Show all options | + +## Configuration + +Optional `.env` settings: + +| Variable | Description | +|----------|-------------| +| `AUTO_BUILD_MODEL` | Override Claude model | +| `DEBUG=true` | Enable debug logging | +| `LINEAR_API_KEY` | Enable Linear integration | +| `GRAPHITI_ENABLED=true` | Enable memory system | + +## Troubleshooting + +**"tree-sitter not available"** - Safe to ignore, uses regex fallback. + +**Missing module errors** - Run `python -m pip install -r requirements.txt` + +**Debug mode** - Set `DEBUG=true DEBUG_LEVEL=2` before running. + +--- + +## For Developers + +### Project Structure + +``` +backend/ +├── agents/ # AI agent execution +├── analysis/ # Code analysis +├── cli/ # Command-line interface +├── core/ # Core utilities +├── integrations/ # External services (Linear, Graphiti) +├── merge/ # Git merge handling +├── project/ # Project detection +├── prompts/ # Prompt templates +├── qa/ # QA validation +├── spec/ # Spec management +└── ui/ # Terminal UI +``` + +### Design Principles + +- **SOLID** - Single responsibility, clean interfaces +- **DRY** - Shared utilities in `core/` +- **KISS** - Simple flat imports via facade modules + +### Import Convention + +```python +# Use facade modules for clean imports +from debug import debug, debug_error +from progress import count_subtasks +from workspace import setup_workspace +``` + +### Adding Features + +1. Create module in appropriate folder +2. Export API in `__init__.py` +3. Add facade module at root if commonly imported + +## License + +AGPL-3.0 diff --git a/apps/backend/__init__.py b/apps/backend/__init__.py new file mode 100644 index 00000000..b67bca87 --- /dev/null +++ b/apps/backend/__init__.py @@ -0,0 +1,23 @@ +""" +Auto Claude Backend - Autonomous Coding Framework +================================================== + +Multi-agent autonomous coding framework that builds software through +coordinated AI agent sessions. + +This package provides: +- Autonomous agent execution for building features from specs +- Workspace isolation via git worktrees +- QA validation loops +- Memory management (Graphiti + file-based) +- Linear integration for project management + +Quick Start: + python run.py --spec 001 # Run a spec + python run.py --list # List all specs + +See README.md for full documentation. +""" + +__version__ = "2.5.5" +__author__ = "Auto Claude Team" diff --git a/auto-claude/agent.py b/apps/backend/agent.py similarity index 100% rename from auto-claude/agent.py rename to apps/backend/agent.py diff --git a/auto-claude/agents/README.md b/apps/backend/agents/README.md similarity index 100% rename from auto-claude/agents/README.md rename to apps/backend/agents/README.md diff --git a/apps/backend/agents/__init__.py b/apps/backend/agents/__init__.py new file mode 100644 index 00000000..37dae174 --- /dev/null +++ b/apps/backend/agents/__init__.py @@ -0,0 +1,92 @@ +""" +Agents Module +============= + +Modular agent system for autonomous coding. + +This module provides: +- run_autonomous_agent: Main coder agent loop +- run_followup_planner: Follow-up planner for completed specs +- Memory management (Graphiti + file-based fallback) +- Session management and post-processing +- Utility functions for git and plan management + +Uses lazy imports to avoid circular dependencies. +""" + +__all__ = [ + # Main API + "run_autonomous_agent", + "run_followup_planner", + # Memory + "debug_memory_system_status", + "get_graphiti_context", + "save_session_memory", + "save_session_to_graphiti", + # Session + "run_agent_session", + "post_session_processing", + # Utils + "get_latest_commit", + "get_commit_count", + "load_implementation_plan", + "find_subtask_in_plan", + "find_phase_for_subtask", + "sync_plan_to_source", + # Constants + "AUTO_CONTINUE_DELAY_SECONDS", + "HUMAN_INTERVENTION_FILE", +] + + +def __getattr__(name): + """Lazy imports to avoid circular dependencies.""" + if name in ("AUTO_CONTINUE_DELAY_SECONDS", "HUMAN_INTERVENTION_FILE"): + from .base import AUTO_CONTINUE_DELAY_SECONDS, HUMAN_INTERVENTION_FILE + + return locals()[name] + elif name == "run_autonomous_agent": + from .coder import run_autonomous_agent + + return run_autonomous_agent + elif name in ( + "debug_memory_system_status", + "get_graphiti_context", + "save_session_memory", + "save_session_to_graphiti", + ): + from .memory_manager import ( + debug_memory_system_status, + get_graphiti_context, + save_session_memory, + save_session_to_graphiti, + ) + + return locals()[name] + elif name == "run_followup_planner": + from .planner import run_followup_planner + + return run_followup_planner + elif name in ("post_session_processing", "run_agent_session"): + from .session import post_session_processing, run_agent_session + + return locals()[name] + elif name in ( + "find_phase_for_subtask", + "find_subtask_in_plan", + "get_commit_count", + "get_latest_commit", + "load_implementation_plan", + "sync_plan_to_source", + ): + from .utils import ( + find_phase_for_subtask, + find_subtask_in_plan, + get_commit_count, + get_latest_commit, + load_implementation_plan, + sync_plan_to_source, + ) + + return locals()[name] + raise AttributeError(f"module 'agents' has no attribute '{name}'") diff --git a/auto-claude/agents/auto_claude_tools.py b/apps/backend/agents/auto_claude_tools.py similarity index 100% rename from auto-claude/agents/auto_claude_tools.py rename to apps/backend/agents/auto_claude_tools.py diff --git a/auto-claude/agents/base.py b/apps/backend/agents/base.py similarity index 100% rename from auto-claude/agents/base.py rename to apps/backend/agents/base.py diff --git a/auto-claude/agents/coder.py b/apps/backend/agents/coder.py similarity index 100% rename from auto-claude/agents/coder.py rename to apps/backend/agents/coder.py diff --git a/auto-claude/agents/memory_manager.py b/apps/backend/agents/memory_manager.py similarity index 100% rename from auto-claude/agents/memory_manager.py rename to apps/backend/agents/memory_manager.py diff --git a/auto-claude/agents/planner.py b/apps/backend/agents/planner.py similarity index 100% rename from auto-claude/agents/planner.py rename to apps/backend/agents/planner.py diff --git a/auto-claude/agents/session.py b/apps/backend/agents/session.py similarity index 100% rename from auto-claude/agents/session.py rename to apps/backend/agents/session.py diff --git a/auto-claude/agents/test_refactoring.py b/apps/backend/agents/test_refactoring.py similarity index 100% rename from auto-claude/agents/test_refactoring.py rename to apps/backend/agents/test_refactoring.py diff --git a/auto-claude/agents/tools_pkg/__init__.py b/apps/backend/agents/tools_pkg/__init__.py similarity index 100% rename from auto-claude/agents/tools_pkg/__init__.py rename to apps/backend/agents/tools_pkg/__init__.py diff --git a/auto-claude/agents/tools_pkg/models.py b/apps/backend/agents/tools_pkg/models.py similarity index 100% rename from auto-claude/agents/tools_pkg/models.py rename to apps/backend/agents/tools_pkg/models.py diff --git a/auto-claude/agents/tools_pkg/permissions.py b/apps/backend/agents/tools_pkg/permissions.py similarity index 100% rename from auto-claude/agents/tools_pkg/permissions.py rename to apps/backend/agents/tools_pkg/permissions.py diff --git a/auto-claude/agents/tools_pkg/registry.py b/apps/backend/agents/tools_pkg/registry.py similarity index 100% rename from auto-claude/agents/tools_pkg/registry.py rename to apps/backend/agents/tools_pkg/registry.py diff --git a/auto-claude/agents/tools_pkg/tools/__init__.py b/apps/backend/agents/tools_pkg/tools/__init__.py similarity index 100% rename from auto-claude/agents/tools_pkg/tools/__init__.py rename to apps/backend/agents/tools_pkg/tools/__init__.py diff --git a/auto-claude/agents/tools_pkg/tools/memory.py b/apps/backend/agents/tools_pkg/tools/memory.py similarity index 100% rename from auto-claude/agents/tools_pkg/tools/memory.py rename to apps/backend/agents/tools_pkg/tools/memory.py diff --git a/auto-claude/agents/tools_pkg/tools/progress.py b/apps/backend/agents/tools_pkg/tools/progress.py similarity index 100% rename from auto-claude/agents/tools_pkg/tools/progress.py rename to apps/backend/agents/tools_pkg/tools/progress.py diff --git a/auto-claude/agents/tools_pkg/tools/qa.py b/apps/backend/agents/tools_pkg/tools/qa.py similarity index 100% rename from auto-claude/agents/tools_pkg/tools/qa.py rename to apps/backend/agents/tools_pkg/tools/qa.py diff --git a/auto-claude/agents/tools_pkg/tools/subtask.py b/apps/backend/agents/tools_pkg/tools/subtask.py similarity index 100% rename from auto-claude/agents/tools_pkg/tools/subtask.py rename to apps/backend/agents/tools_pkg/tools/subtask.py diff --git a/auto-claude/agents/utils.py b/apps/backend/agents/utils.py similarity index 100% rename from auto-claude/agents/utils.py rename to apps/backend/agents/utils.py diff --git a/auto-claude/analysis/__init__.py b/apps/backend/analysis/__init__.py similarity index 100% rename from auto-claude/analysis/__init__.py rename to apps/backend/analysis/__init__.py diff --git a/auto-claude/analysis/analyzer.py b/apps/backend/analysis/analyzer.py similarity index 100% rename from auto-claude/analysis/analyzer.py rename to apps/backend/analysis/analyzer.py diff --git a/auto-claude/analysis/analyzers/__init__.py b/apps/backend/analysis/analyzers/__init__.py similarity index 100% rename from auto-claude/analysis/analyzers/__init__.py rename to apps/backend/analysis/analyzers/__init__.py diff --git a/auto-claude/analysis/analyzers/base.py b/apps/backend/analysis/analyzers/base.py similarity index 100% rename from auto-claude/analysis/analyzers/base.py rename to apps/backend/analysis/analyzers/base.py diff --git a/auto-claude/analysis/analyzers/context/__init__.py b/apps/backend/analysis/analyzers/context/__init__.py similarity index 100% rename from auto-claude/analysis/analyzers/context/__init__.py rename to apps/backend/analysis/analyzers/context/__init__.py diff --git a/auto-claude/analysis/analyzers/context/api_docs_detector.py b/apps/backend/analysis/analyzers/context/api_docs_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/context/api_docs_detector.py rename to apps/backend/analysis/analyzers/context/api_docs_detector.py diff --git a/auto-claude/analysis/analyzers/context/auth_detector.py b/apps/backend/analysis/analyzers/context/auth_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/context/auth_detector.py rename to apps/backend/analysis/analyzers/context/auth_detector.py diff --git a/auto-claude/analysis/analyzers/context/env_detector.py b/apps/backend/analysis/analyzers/context/env_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/context/env_detector.py rename to apps/backend/analysis/analyzers/context/env_detector.py diff --git a/auto-claude/analysis/analyzers/context/jobs_detector.py b/apps/backend/analysis/analyzers/context/jobs_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/context/jobs_detector.py rename to apps/backend/analysis/analyzers/context/jobs_detector.py diff --git a/auto-claude/analysis/analyzers/context/migrations_detector.py b/apps/backend/analysis/analyzers/context/migrations_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/context/migrations_detector.py rename to apps/backend/analysis/analyzers/context/migrations_detector.py diff --git a/auto-claude/analysis/analyzers/context/monitoring_detector.py b/apps/backend/analysis/analyzers/context/monitoring_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/context/monitoring_detector.py rename to apps/backend/analysis/analyzers/context/monitoring_detector.py diff --git a/auto-claude/analysis/analyzers/context/services_detector.py b/apps/backend/analysis/analyzers/context/services_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/context/services_detector.py rename to apps/backend/analysis/analyzers/context/services_detector.py diff --git a/auto-claude/analysis/analyzers/context_analyzer.py b/apps/backend/analysis/analyzers/context_analyzer.py similarity index 100% rename from auto-claude/analysis/analyzers/context_analyzer.py rename to apps/backend/analysis/analyzers/context_analyzer.py diff --git a/auto-claude/analysis/analyzers/database_detector.py b/apps/backend/analysis/analyzers/database_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/database_detector.py rename to apps/backend/analysis/analyzers/database_detector.py diff --git a/auto-claude/analysis/analyzers/framework_analyzer.py b/apps/backend/analysis/analyzers/framework_analyzer.py similarity index 100% rename from auto-claude/analysis/analyzers/framework_analyzer.py rename to apps/backend/analysis/analyzers/framework_analyzer.py diff --git a/auto-claude/analysis/analyzers/port_detector.py b/apps/backend/analysis/analyzers/port_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/port_detector.py rename to apps/backend/analysis/analyzers/port_detector.py diff --git a/auto-claude/analysis/analyzers/project_analyzer_module.py b/apps/backend/analysis/analyzers/project_analyzer_module.py similarity index 100% rename from auto-claude/analysis/analyzers/project_analyzer_module.py rename to apps/backend/analysis/analyzers/project_analyzer_module.py diff --git a/auto-claude/analysis/analyzers/route_detector.py b/apps/backend/analysis/analyzers/route_detector.py similarity index 100% rename from auto-claude/analysis/analyzers/route_detector.py rename to apps/backend/analysis/analyzers/route_detector.py diff --git a/auto-claude/analysis/analyzers/service_analyzer.py b/apps/backend/analysis/analyzers/service_analyzer.py similarity index 100% rename from auto-claude/analysis/analyzers/service_analyzer.py rename to apps/backend/analysis/analyzers/service_analyzer.py diff --git a/auto-claude/analysis/ci_discovery.py b/apps/backend/analysis/ci_discovery.py similarity index 100% rename from auto-claude/analysis/ci_discovery.py rename to apps/backend/analysis/ci_discovery.py diff --git a/auto-claude/analysis/insight_extractor.py b/apps/backend/analysis/insight_extractor.py similarity index 100% rename from auto-claude/analysis/insight_extractor.py rename to apps/backend/analysis/insight_extractor.py diff --git a/auto-claude/analysis/project_analyzer.py b/apps/backend/analysis/project_analyzer.py similarity index 100% rename from auto-claude/analysis/project_analyzer.py rename to apps/backend/analysis/project_analyzer.py diff --git a/auto-claude/analysis/risk_classifier.py b/apps/backend/analysis/risk_classifier.py similarity index 100% rename from auto-claude/analysis/risk_classifier.py rename to apps/backend/analysis/risk_classifier.py diff --git a/auto-claude/analysis/security_scanner.py b/apps/backend/analysis/security_scanner.py similarity index 100% rename from auto-claude/analysis/security_scanner.py rename to apps/backend/analysis/security_scanner.py diff --git a/auto-claude/analysis/test_discovery.py b/apps/backend/analysis/test_discovery.py similarity index 100% rename from auto-claude/analysis/test_discovery.py rename to apps/backend/analysis/test_discovery.py diff --git a/apps/backend/analyzer.py b/apps/backend/analyzer.py new file mode 100644 index 00000000..847eb400 --- /dev/null +++ b/apps/backend/analyzer.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +""" +Analyzer facade module. + +Provides backward compatibility for scripts that import from analyzer.py at the root. +Actual implementation is in analysis/analyzer.py. +""" + +from analysis.analyzer import ( + ProjectAnalyzer, + ServiceAnalyzer, + analyze_project, + analyze_service, + main, +) + +__all__ = [ + "ServiceAnalyzer", + "ProjectAnalyzer", + "analyze_project", + "analyze_service", + "main", +] + +if __name__ == "__main__": + main() diff --git a/apps/backend/auto_claude_tools.py b/apps/backend/auto_claude_tools.py new file mode 100644 index 00000000..d774c5cc --- /dev/null +++ b/apps/backend/auto_claude_tools.py @@ -0,0 +1,36 @@ +""" +Auto Claude tools module facade. + +Provides MCP tools for agent operations. +Re-exports from agents.tools_pkg for clean imports. +""" + +from agents.tools_pkg.models import ( # noqa: F401 + ELECTRON_TOOLS, + TOOL_GET_BUILD_PROGRESS, + TOOL_GET_SESSION_CONTEXT, + TOOL_RECORD_DISCOVERY, + TOOL_RECORD_GOTCHA, + TOOL_UPDATE_QA_STATUS, + TOOL_UPDATE_SUBTASK_STATUS, + is_electron_mcp_enabled, +) +from agents.tools_pkg.permissions import get_allowed_tools # noqa: F401 +from agents.tools_pkg.registry import ( # noqa: F401 + create_auto_claude_mcp_server, + is_tools_available, +) + +__all__ = [ + "create_auto_claude_mcp_server", + "get_allowed_tools", + "is_tools_available", + "TOOL_UPDATE_SUBTASK_STATUS", + "TOOL_GET_BUILD_PROGRESS", + "TOOL_RECORD_DISCOVERY", + "TOOL_RECORD_GOTCHA", + "TOOL_GET_SESSION_CONTEXT", + "TOOL_UPDATE_QA_STATUS", + "ELECTRON_TOOLS", + "is_electron_mcp_enabled", +] diff --git a/auto-claude/ci_discovery.py b/apps/backend/ci_discovery.py similarity index 100% rename from auto-claude/ci_discovery.py rename to apps/backend/ci_discovery.py diff --git a/auto-claude/cli/__init__.py b/apps/backend/cli/__init__.py similarity index 100% rename from auto-claude/cli/__init__.py rename to apps/backend/cli/__init__.py diff --git a/auto-claude/cli/build_commands.py b/apps/backend/cli/build_commands.py similarity index 100% rename from auto-claude/cli/build_commands.py rename to apps/backend/cli/build_commands.py diff --git a/auto-claude/cli/followup_commands.py b/apps/backend/cli/followup_commands.py similarity index 100% rename from auto-claude/cli/followup_commands.py rename to apps/backend/cli/followup_commands.py diff --git a/auto-claude/cli/input_handlers.py b/apps/backend/cli/input_handlers.py similarity index 100% rename from auto-claude/cli/input_handlers.py rename to apps/backend/cli/input_handlers.py diff --git a/auto-claude/cli/main.py b/apps/backend/cli/main.py similarity index 100% rename from auto-claude/cli/main.py rename to apps/backend/cli/main.py diff --git a/auto-claude/cli/qa_commands.py b/apps/backend/cli/qa_commands.py similarity index 100% rename from auto-claude/cli/qa_commands.py rename to apps/backend/cli/qa_commands.py diff --git a/auto-claude/cli/spec_commands.py b/apps/backend/cli/spec_commands.py similarity index 58% rename from auto-claude/cli/spec_commands.py rename to apps/backend/cli/spec_commands.py index c20c0914..2fa1d02c 100644 --- a/auto-claude/cli/spec_commands.py +++ b/apps/backend/cli/spec_commands.py @@ -93,14 +93,76 @@ def list_specs(project_dir: Path, dev_mode: bool = False) -> list[dict]: return specs -def print_specs_list(project_dir: Path, dev_mode: bool = False) -> None: - """Print a formatted list of all specs.""" +def print_specs_list( + project_dir: Path, dev_mode: bool = False, auto_create: bool = True +) -> None: + """Print a formatted list of all specs. + + Args: + project_dir: Project root directory + dev_mode: If True, use dev/auto-claude/specs/ + auto_create: If True and no specs exist, automatically launch spec creation + """ + import subprocess + specs = list_specs(project_dir, dev_mode) if not specs: print("\nNo specs found.") - print("\nCreate your first spec:") - print(" claude /spec") + + if auto_create: + # Get the backend directory and find spec_runner.py + backend_dir = Path(__file__).parent.parent + spec_runner = backend_dir / "runners" / "spec_runner.py" + + # Find Python executable - use current interpreter + python_path = sys.executable + + if spec_runner.exists() and python_path: + # Quick prompt for task description + print("\n" + "=" * 60) + print(" QUICK START") + print("=" * 60) + print("\nWhat do you want to build?") + print( + "(Enter a brief description, or press Enter for interactive mode)\n" + ) + + try: + task = input("> ").strip() + except (EOFError, KeyboardInterrupt): + print("\nCancelled.") + return + + if task: + # Direct mode: create spec and start building + print(f"\nStarting build for: {task}\n") + subprocess.run( + [ + python_path, + str(spec_runner), + "--task", + task, + "--complexity", + "simple", + "--auto-approve", + ], + cwd=project_dir, + ) + else: + # Interactive mode + print("\nLaunching interactive mode...\n") + subprocess.run( + [python_path, str(spec_runner), "--interactive"], + cwd=project_dir, + ) + return + else: + print("\nCreate your first spec:") + print(" python runners/spec_runner.py --interactive") + else: + print("\nCreate your first spec:") + print(" python runners/spec_runner.py --interactive") return print("\n" + "=" * 70) diff --git a/auto-claude/cli/utils.py b/apps/backend/cli/utils.py similarity index 100% rename from auto-claude/cli/utils.py rename to apps/backend/cli/utils.py diff --git a/auto-claude/cli/workspace_commands.py b/apps/backend/cli/workspace_commands.py similarity index 100% rename from auto-claude/cli/workspace_commands.py rename to apps/backend/cli/workspace_commands.py diff --git a/apps/backend/client.py b/apps/backend/client.py new file mode 100644 index 00000000..4b144f97 --- /dev/null +++ b/apps/backend/client.py @@ -0,0 +1,25 @@ +""" +Claude client module facade. + +Provides Claude API client utilities. +Uses lazy imports to avoid circular dependencies. +""" + + +def __getattr__(name): + """Lazy import to avoid circular imports with auto_claude_tools.""" + from core import client as _client + + return getattr(_client, name) + + +def create_client(*args, **kwargs): + """Create a Claude client instance.""" + from core.client import create_client as _create_client + + return _create_client(*args, **kwargs) + + +__all__ = [ + "create_client", +] diff --git a/auto-claude/commit_message.py b/apps/backend/commit_message.py similarity index 100% rename from auto-claude/commit_message.py rename to apps/backend/commit_message.py diff --git a/auto-claude/context/__init__.py b/apps/backend/context/__init__.py similarity index 100% rename from auto-claude/context/__init__.py rename to apps/backend/context/__init__.py diff --git a/auto-claude/context/builder.py b/apps/backend/context/builder.py similarity index 100% rename from auto-claude/context/builder.py rename to apps/backend/context/builder.py diff --git a/auto-claude/context/categorizer.py b/apps/backend/context/categorizer.py similarity index 100% rename from auto-claude/context/categorizer.py rename to apps/backend/context/categorizer.py diff --git a/auto-claude/context/constants.py b/apps/backend/context/constants.py similarity index 100% rename from auto-claude/context/constants.py rename to apps/backend/context/constants.py diff --git a/auto-claude/context/graphiti_integration.py b/apps/backend/context/graphiti_integration.py similarity index 100% rename from auto-claude/context/graphiti_integration.py rename to apps/backend/context/graphiti_integration.py diff --git a/auto-claude/context/keyword_extractor.py b/apps/backend/context/keyword_extractor.py similarity index 100% rename from auto-claude/context/keyword_extractor.py rename to apps/backend/context/keyword_extractor.py diff --git a/auto-claude/context/main.py b/apps/backend/context/main.py similarity index 100% rename from auto-claude/context/main.py rename to apps/backend/context/main.py diff --git a/auto-claude/context/models.py b/apps/backend/context/models.py similarity index 100% rename from auto-claude/context/models.py rename to apps/backend/context/models.py diff --git a/auto-claude/context/pattern_discovery.py b/apps/backend/context/pattern_discovery.py similarity index 100% rename from auto-claude/context/pattern_discovery.py rename to apps/backend/context/pattern_discovery.py diff --git a/auto-claude/context/search.py b/apps/backend/context/search.py similarity index 100% rename from auto-claude/context/search.py rename to apps/backend/context/search.py diff --git a/auto-claude/context/serialization.py b/apps/backend/context/serialization.py similarity index 100% rename from auto-claude/context/serialization.py rename to apps/backend/context/serialization.py diff --git a/auto-claude/context/service_matcher.py b/apps/backend/context/service_matcher.py similarity index 100% rename from auto-claude/context/service_matcher.py rename to apps/backend/context/service_matcher.py diff --git a/auto-claude/core/__init__.py b/apps/backend/core/__init__.py similarity index 100% rename from auto-claude/core/__init__.py rename to apps/backend/core/__init__.py diff --git a/auto-claude/core/agent.py b/apps/backend/core/agent.py similarity index 100% rename from auto-claude/core/agent.py rename to apps/backend/core/agent.py diff --git a/auto-claude/core/auth.py b/apps/backend/core/auth.py similarity index 100% rename from auto-claude/core/auth.py rename to apps/backend/core/auth.py diff --git a/auto-claude/core/client.py b/apps/backend/core/client.py similarity index 98% rename from auto-claude/core/client.py rename to apps/backend/core/client.py index a1d6ec64..48de8d87 100644 --- a/auto-claude/core/client.py +++ b/apps/backend/core/client.py @@ -96,7 +96,7 @@ CONTEXT7_TOOLS = [ ] # Graphiti MCP tools for knowledge graph memory (when GRAPHITI_MCP_ENABLED is set) -# See: https://docs.falkordb.com/agentic-memory/graphiti-mcp-server.html +# See: https://github.com/getzep/graphiti GRAPHITI_MCP_TOOLS = [ "mcp__graphiti-memory__search_nodes", # Search entity summaries "mcp__graphiti-memory__search_facts", # Search relationships between entities @@ -321,7 +321,7 @@ def create_client( } # Add Graphiti MCP server if enabled - # Requires running: docker run -d -p 8000:8000 falkordb/graphiti-knowledge-graph-mcp + # Graphiti MCP server for knowledge graph memory (uses embedded LadybugDB) if graphiti_mcp_enabled: mcp_servers["graphiti-memory"] = { "type": "http", diff --git a/auto-claude/core/debug.py b/apps/backend/core/debug.py similarity index 100% rename from auto-claude/core/debug.py rename to apps/backend/core/debug.py diff --git a/auto-claude/core/progress.py b/apps/backend/core/progress.py similarity index 100% rename from auto-claude/core/progress.py rename to apps/backend/core/progress.py diff --git a/auto-claude/core/workspace.py b/apps/backend/core/workspace.py similarity index 100% rename from auto-claude/core/workspace.py rename to apps/backend/core/workspace.py diff --git a/auto-claude/core/workspace/README.md b/apps/backend/core/workspace/README.md similarity index 100% rename from auto-claude/core/workspace/README.md rename to apps/backend/core/workspace/README.md diff --git a/auto-claude/core/workspace/__init__.py b/apps/backend/core/workspace/__init__.py similarity index 100% rename from auto-claude/core/workspace/__init__.py rename to apps/backend/core/workspace/__init__.py diff --git a/auto-claude/core/workspace/display.py b/apps/backend/core/workspace/display.py similarity index 100% rename from auto-claude/core/workspace/display.py rename to apps/backend/core/workspace/display.py diff --git a/auto-claude/core/workspace/finalization.py b/apps/backend/core/workspace/finalization.py similarity index 100% rename from auto-claude/core/workspace/finalization.py rename to apps/backend/core/workspace/finalization.py diff --git a/auto-claude/core/workspace/git_utils.py b/apps/backend/core/workspace/git_utils.py similarity index 100% rename from auto-claude/core/workspace/git_utils.py rename to apps/backend/core/workspace/git_utils.py diff --git a/auto-claude/core/workspace/models.py b/apps/backend/core/workspace/models.py similarity index 100% rename from auto-claude/core/workspace/models.py rename to apps/backend/core/workspace/models.py diff --git a/auto-claude/core/workspace/setup.py b/apps/backend/core/workspace/setup.py similarity index 100% rename from auto-claude/core/workspace/setup.py rename to apps/backend/core/workspace/setup.py diff --git a/auto-claude/core/worktree.py b/apps/backend/core/worktree.py similarity index 100% rename from auto-claude/core/worktree.py rename to apps/backend/core/worktree.py diff --git a/auto-claude/critique.py b/apps/backend/critique.py similarity index 100% rename from auto-claude/critique.py rename to apps/backend/critique.py diff --git a/apps/backend/debug.py b/apps/backend/debug.py new file mode 100644 index 00000000..14aae6f1 --- /dev/null +++ b/apps/backend/debug.py @@ -0,0 +1,40 @@ +""" +Debug module facade. + +Provides debug logging utilities for the Auto-Claude framework. +Re-exports from core.debug for clean imports. +""" + +from core.debug import ( + Colors, + debug, + debug_async_timer, + debug_detailed, + debug_env_status, + debug_error, + debug_info, + debug_section, + debug_success, + debug_timer, + debug_verbose, + debug_warning, + get_debug_level, + is_debug_enabled, +) + +__all__ = [ + "Colors", + "debug", + "debug_async_timer", + "debug_detailed", + "debug_env_status", + "debug_error", + "debug_info", + "debug_section", + "debug_success", + "debug_timer", + "debug_verbose", + "debug_warning", + "get_debug_level", + "is_debug_enabled", +] diff --git a/auto-claude/graphiti_config.py b/apps/backend/graphiti_config.py similarity index 100% rename from auto-claude/graphiti_config.py rename to apps/backend/graphiti_config.py diff --git a/auto-claude/graphiti_providers.py b/apps/backend/graphiti_providers.py similarity index 100% rename from auto-claude/graphiti_providers.py rename to apps/backend/graphiti_providers.py diff --git a/auto-claude/ideation/__init__.py b/apps/backend/ideation/__init__.py similarity index 100% rename from auto-claude/ideation/__init__.py rename to apps/backend/ideation/__init__.py diff --git a/auto-claude/ideation/analyzer.py b/apps/backend/ideation/analyzer.py similarity index 100% rename from auto-claude/ideation/analyzer.py rename to apps/backend/ideation/analyzer.py diff --git a/auto-claude/ideation/config.py b/apps/backend/ideation/config.py similarity index 100% rename from auto-claude/ideation/config.py rename to apps/backend/ideation/config.py diff --git a/auto-claude/ideation/formatter.py b/apps/backend/ideation/formatter.py similarity index 100% rename from auto-claude/ideation/formatter.py rename to apps/backend/ideation/formatter.py diff --git a/auto-claude/ideation/generator.py b/apps/backend/ideation/generator.py similarity index 100% rename from auto-claude/ideation/generator.py rename to apps/backend/ideation/generator.py diff --git a/auto-claude/ideation/output_streamer.py b/apps/backend/ideation/output_streamer.py similarity index 100% rename from auto-claude/ideation/output_streamer.py rename to apps/backend/ideation/output_streamer.py diff --git a/auto-claude/ideation/phase_executor.py b/apps/backend/ideation/phase_executor.py similarity index 100% rename from auto-claude/ideation/phase_executor.py rename to apps/backend/ideation/phase_executor.py diff --git a/auto-claude/ideation/prioritizer.py b/apps/backend/ideation/prioritizer.py similarity index 100% rename from auto-claude/ideation/prioritizer.py rename to apps/backend/ideation/prioritizer.py diff --git a/auto-claude/ideation/project_index_phase.py b/apps/backend/ideation/project_index_phase.py similarity index 100% rename from auto-claude/ideation/project_index_phase.py rename to apps/backend/ideation/project_index_phase.py diff --git a/auto-claude/ideation/runner.py b/apps/backend/ideation/runner.py similarity index 100% rename from auto-claude/ideation/runner.py rename to apps/backend/ideation/runner.py diff --git a/auto-claude/ideation/script_runner.py b/apps/backend/ideation/script_runner.py similarity index 100% rename from auto-claude/ideation/script_runner.py rename to apps/backend/ideation/script_runner.py diff --git a/auto-claude/ideation/types.py b/apps/backend/ideation/types.py similarity index 100% rename from auto-claude/ideation/types.py rename to apps/backend/ideation/types.py diff --git a/auto-claude/implementation_plan/__init__.py b/apps/backend/implementation_plan/__init__.py similarity index 100% rename from auto-claude/implementation_plan/__init__.py rename to apps/backend/implementation_plan/__init__.py diff --git a/auto-claude/implementation_plan/enums.py b/apps/backend/implementation_plan/enums.py similarity index 100% rename from auto-claude/implementation_plan/enums.py rename to apps/backend/implementation_plan/enums.py diff --git a/auto-claude/implementation_plan/factories.py b/apps/backend/implementation_plan/factories.py similarity index 100% rename from auto-claude/implementation_plan/factories.py rename to apps/backend/implementation_plan/factories.py diff --git a/auto-claude/implementation_plan/main.py b/apps/backend/implementation_plan/main.py similarity index 100% rename from auto-claude/implementation_plan/main.py rename to apps/backend/implementation_plan/main.py diff --git a/auto-claude/implementation_plan/phase.py b/apps/backend/implementation_plan/phase.py similarity index 100% rename from auto-claude/implementation_plan/phase.py rename to apps/backend/implementation_plan/phase.py diff --git a/auto-claude/implementation_plan/plan.py b/apps/backend/implementation_plan/plan.py similarity index 100% rename from auto-claude/implementation_plan/plan.py rename to apps/backend/implementation_plan/plan.py diff --git a/auto-claude/implementation_plan/subtask.py b/apps/backend/implementation_plan/subtask.py similarity index 100% rename from auto-claude/implementation_plan/subtask.py rename to apps/backend/implementation_plan/subtask.py diff --git a/auto-claude/implementation_plan/verification.py b/apps/backend/implementation_plan/verification.py similarity index 100% rename from auto-claude/implementation_plan/verification.py rename to apps/backend/implementation_plan/verification.py diff --git a/auto-claude/init.py b/apps/backend/init.py similarity index 100% rename from auto-claude/init.py rename to apps/backend/init.py diff --git a/auto-claude/insight_extractor.py b/apps/backend/insight_extractor.py similarity index 100% rename from auto-claude/insight_extractor.py rename to apps/backend/insight_extractor.py diff --git a/auto-claude/integrations/__init__.py b/apps/backend/integrations/__init__.py similarity index 100% rename from auto-claude/integrations/__init__.py rename to apps/backend/integrations/__init__.py diff --git a/auto-claude/integrations/graphiti/__init__.py b/apps/backend/integrations/graphiti/__init__.py similarity index 100% rename from auto-claude/integrations/graphiti/__init__.py rename to apps/backend/integrations/graphiti/__init__.py diff --git a/auto-claude/integrations/graphiti/config.py b/apps/backend/integrations/graphiti/config.py similarity index 100% rename from auto-claude/integrations/graphiti/config.py rename to apps/backend/integrations/graphiti/config.py diff --git a/auto-claude/integrations/graphiti/memory.py b/apps/backend/integrations/graphiti/memory.py similarity index 96% rename from auto-claude/integrations/graphiti/memory.py rename to apps/backend/integrations/graphiti/memory.py index 9739f34c..7b160c81 100644 --- a/auto-claude/integrations/graphiti/memory.py +++ b/apps/backend/integrations/graphiti/memory.py @@ -7,7 +7,7 @@ memory system from the auto-claude/graphiti/ package. The refactored code is now organized as: - graphiti/graphiti.py - Main GraphitiMemory class -- graphiti/client.py - FalkorDB client wrapper +- graphiti/client.py - LadybugDB client wrapper - graphiti/queries.py - Graph query operations - graphiti/search.py - Semantic search logic - graphiti/schema.py - Graph schema definitions @@ -70,7 +70,7 @@ def get_graphiti_memory( async def test_graphiti_connection() -> tuple[bool, str]: """ - Test if FalkorDB is available and Graphiti can connect. + Test if LadybugDB is available and Graphiti can connect. Returns: Tuple of (success: bool, message: str) @@ -116,7 +116,7 @@ async def test_graphiti_connection() -> tuple[bool, str]: await graphiti.close() return True, ( - f"Connected to FalkorDB at {config.falkordb_host}:{config.falkordb_port} " + f"Connected to LadybugDB at {config.falkordb_host}:{config.falkordb_port} " f"(providers: {config.get_provider_summary()})" ) diff --git a/auto-claude/integrations/graphiti/migrate_embeddings.py b/apps/backend/integrations/graphiti/migrate_embeddings.py similarity index 100% rename from auto-claude/integrations/graphiti/migrate_embeddings.py rename to apps/backend/integrations/graphiti/migrate_embeddings.py diff --git a/auto-claude/integrations/graphiti/providers.py b/apps/backend/integrations/graphiti/providers.py similarity index 100% rename from auto-claude/integrations/graphiti/providers.py rename to apps/backend/integrations/graphiti/providers.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/__init__.py b/apps/backend/integrations/graphiti/providers_pkg/__init__.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/__init__.py rename to apps/backend/integrations/graphiti/providers_pkg/__init__.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/cross_encoder.py b/apps/backend/integrations/graphiti/providers_pkg/cross_encoder.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/cross_encoder.py rename to apps/backend/integrations/graphiti/providers_pkg/cross_encoder.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/__init__.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/__init__.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/__init__.py rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/__init__.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/azure_openai_embedder.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/google_embedder.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/ollama_embedder.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/openai_embedder.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py b/apps/backend/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py rename to apps/backend/integrations/graphiti/providers_pkg/embedder_providers/voyage_embedder.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/exceptions.py b/apps/backend/integrations/graphiti/providers_pkg/exceptions.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/exceptions.py rename to apps/backend/integrations/graphiti/providers_pkg/exceptions.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/factory.py b/apps/backend/integrations/graphiti/providers_pkg/factory.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/factory.py rename to apps/backend/integrations/graphiti/providers_pkg/factory.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/__init__.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/__init__.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/__init__.py rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/__init__.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/anthropic_llm.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/azure_openai_llm.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/google_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/google_llm.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/google_llm.py rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/google_llm.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/ollama_llm.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py b/apps/backend/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py rename to apps/backend/integrations/graphiti/providers_pkg/llm_providers/openai_llm.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/models.py b/apps/backend/integrations/graphiti/providers_pkg/models.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/models.py rename to apps/backend/integrations/graphiti/providers_pkg/models.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/utils.py b/apps/backend/integrations/graphiti/providers_pkg/utils.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/utils.py rename to apps/backend/integrations/graphiti/providers_pkg/utils.py diff --git a/auto-claude/integrations/graphiti/providers_pkg/validators.py b/apps/backend/integrations/graphiti/providers_pkg/validators.py similarity index 100% rename from auto-claude/integrations/graphiti/providers_pkg/validators.py rename to apps/backend/integrations/graphiti/providers_pkg/validators.py diff --git a/auto-claude/integrations/graphiti/queries_pkg/__init__.py b/apps/backend/integrations/graphiti/queries_pkg/__init__.py similarity index 100% rename from auto-claude/integrations/graphiti/queries_pkg/__init__.py rename to apps/backend/integrations/graphiti/queries_pkg/__init__.py diff --git a/auto-claude/integrations/graphiti/queries_pkg/client.py b/apps/backend/integrations/graphiti/queries_pkg/client.py similarity index 100% rename from auto-claude/integrations/graphiti/queries_pkg/client.py rename to apps/backend/integrations/graphiti/queries_pkg/client.py diff --git a/auto-claude/integrations/graphiti/queries_pkg/graphiti.py b/apps/backend/integrations/graphiti/queries_pkg/graphiti.py similarity index 100% rename from auto-claude/integrations/graphiti/queries_pkg/graphiti.py rename to apps/backend/integrations/graphiti/queries_pkg/graphiti.py diff --git a/auto-claude/integrations/graphiti/queries_pkg/kuzu_driver_patched.py b/apps/backend/integrations/graphiti/queries_pkg/kuzu_driver_patched.py similarity index 100% rename from auto-claude/integrations/graphiti/queries_pkg/kuzu_driver_patched.py rename to apps/backend/integrations/graphiti/queries_pkg/kuzu_driver_patched.py diff --git a/auto-claude/integrations/graphiti/queries_pkg/queries.py b/apps/backend/integrations/graphiti/queries_pkg/queries.py similarity index 100% rename from auto-claude/integrations/graphiti/queries_pkg/queries.py rename to apps/backend/integrations/graphiti/queries_pkg/queries.py diff --git a/auto-claude/integrations/graphiti/queries_pkg/schema.py b/apps/backend/integrations/graphiti/queries_pkg/schema.py similarity index 100% rename from auto-claude/integrations/graphiti/queries_pkg/schema.py rename to apps/backend/integrations/graphiti/queries_pkg/schema.py diff --git a/auto-claude/integrations/graphiti/queries_pkg/search.py b/apps/backend/integrations/graphiti/queries_pkg/search.py similarity index 100% rename from auto-claude/integrations/graphiti/queries_pkg/search.py rename to apps/backend/integrations/graphiti/queries_pkg/search.py diff --git a/auto-claude/integrations/graphiti/test_graphiti_memory.py b/apps/backend/integrations/graphiti/test_graphiti_memory.py similarity index 100% rename from auto-claude/integrations/graphiti/test_graphiti_memory.py rename to apps/backend/integrations/graphiti/test_graphiti_memory.py diff --git a/auto-claude/integrations/graphiti/test_provider_naming.py b/apps/backend/integrations/graphiti/test_provider_naming.py similarity index 100% rename from auto-claude/integrations/graphiti/test_provider_naming.py rename to apps/backend/integrations/graphiti/test_provider_naming.py diff --git a/auto-claude/integrations/linear/__init__.py b/apps/backend/integrations/linear/__init__.py similarity index 100% rename from auto-claude/integrations/linear/__init__.py rename to apps/backend/integrations/linear/__init__.py diff --git a/auto-claude/integrations/linear/config.py b/apps/backend/integrations/linear/config.py similarity index 100% rename from auto-claude/integrations/linear/config.py rename to apps/backend/integrations/linear/config.py diff --git a/auto-claude/integrations/linear/integration.py b/apps/backend/integrations/linear/integration.py similarity index 100% rename from auto-claude/integrations/linear/integration.py rename to apps/backend/integrations/linear/integration.py diff --git a/auto-claude/integrations/linear/updater.py b/apps/backend/integrations/linear/updater.py similarity index 100% rename from auto-claude/integrations/linear/updater.py rename to apps/backend/integrations/linear/updater.py diff --git a/auto-claude/linear_config.py b/apps/backend/linear_config.py similarity index 100% rename from auto-claude/linear_config.py rename to apps/backend/linear_config.py diff --git a/apps/backend/linear_integration.py b/apps/backend/linear_integration.py new file mode 100644 index 00000000..5eff31ee --- /dev/null +++ b/apps/backend/linear_integration.py @@ -0,0 +1,22 @@ +""" +Linear integration module facade. + +Provides Linear project management integration. +Re-exports from integrations.linear.integration for clean imports. +""" + +from integrations.linear.integration import ( + LinearManager, + get_linear_manager, + is_linear_enabled, + prepare_coder_linear_instructions, + prepare_planner_linear_instructions, +) + +__all__ = [ + "LinearManager", + "get_linear_manager", + "is_linear_enabled", + "prepare_coder_linear_instructions", + "prepare_planner_linear_instructions", +] diff --git a/apps/backend/linear_updater.py b/apps/backend/linear_updater.py new file mode 100644 index 00000000..9496385e --- /dev/null +++ b/apps/backend/linear_updater.py @@ -0,0 +1,42 @@ +""" +Linear updater module facade. + +Provides Linear integration functionality. +Re-exports from integrations.linear.updater for clean imports. +""" + +from integrations.linear.updater import ( + LinearTaskState, + add_linear_comment, + create_linear_task, + get_linear_api_key, + is_linear_enabled, + linear_build_complete, + linear_qa_approved, + linear_qa_max_iterations, + linear_qa_rejected, + linear_qa_started, + linear_subtask_completed, + linear_subtask_failed, + linear_task_started, + linear_task_stuck, + update_linear_status, +) + +__all__ = [ + "LinearTaskState", + "add_linear_comment", + "create_linear_task", + "get_linear_api_key", + "is_linear_enabled", + "linear_build_complete", + "linear_qa_approved", + "linear_qa_max_iterations", + "linear_qa_rejected", + "linear_qa_started", + "linear_subtask_completed", + "linear_subtask_failed", + "linear_task_started", + "linear_task_stuck", + "update_linear_status", +] diff --git a/auto-claude/memory/__init__.py b/apps/backend/memory/__init__.py similarity index 97% rename from auto-claude/memory/__init__.py rename to apps/backend/memory/__init__.py index ea7b152c..76ecd672 100644 --- a/auto-claude/memory/__init__.py +++ b/apps/backend/memory/__init__.py @@ -10,7 +10,7 @@ Architecture Decision: Memory System Hierarchy: PRIMARY: Graphiti (when GRAPHITI_ENABLED=true) - - Graph-based knowledge storage with FalkorDB + - Graph-based knowledge storage with LadybugDB (embedded Kuzu database) - Semantic search across sessions - Cross-project context retrieval - Rich relationship modeling diff --git a/auto-claude/memory/codebase_map.py b/apps/backend/memory/codebase_map.py similarity index 100% rename from auto-claude/memory/codebase_map.py rename to apps/backend/memory/codebase_map.py diff --git a/auto-claude/memory/graphiti_helpers.py b/apps/backend/memory/graphiti_helpers.py similarity index 100% rename from auto-claude/memory/graphiti_helpers.py rename to apps/backend/memory/graphiti_helpers.py diff --git a/auto-claude/memory/main.py b/apps/backend/memory/main.py old mode 100755 new mode 100644 similarity index 100% rename from auto-claude/memory/main.py rename to apps/backend/memory/main.py diff --git a/auto-claude/memory/paths.py b/apps/backend/memory/paths.py similarity index 100% rename from auto-claude/memory/paths.py rename to apps/backend/memory/paths.py diff --git a/auto-claude/memory/patterns.py b/apps/backend/memory/patterns.py similarity index 100% rename from auto-claude/memory/patterns.py rename to apps/backend/memory/patterns.py diff --git a/auto-claude/memory/sessions.py b/apps/backend/memory/sessions.py similarity index 100% rename from auto-claude/memory/sessions.py rename to apps/backend/memory/sessions.py diff --git a/auto-claude/memory/summary.py b/apps/backend/memory/summary.py similarity index 100% rename from auto-claude/memory/summary.py rename to apps/backend/memory/summary.py diff --git a/auto-claude/merge/__init__.py b/apps/backend/merge/__init__.py similarity index 100% rename from auto-claude/merge/__init__.py rename to apps/backend/merge/__init__.py diff --git a/auto-claude/merge/ai_resolver.py b/apps/backend/merge/ai_resolver.py similarity index 100% rename from auto-claude/merge/ai_resolver.py rename to apps/backend/merge/ai_resolver.py diff --git a/auto-claude/merge/ai_resolver/README.md b/apps/backend/merge/ai_resolver/README.md similarity index 100% rename from auto-claude/merge/ai_resolver/README.md rename to apps/backend/merge/ai_resolver/README.md diff --git a/auto-claude/merge/ai_resolver/__init__.py b/apps/backend/merge/ai_resolver/__init__.py similarity index 100% rename from auto-claude/merge/ai_resolver/__init__.py rename to apps/backend/merge/ai_resolver/__init__.py diff --git a/auto-claude/merge/ai_resolver/claude_client.py b/apps/backend/merge/ai_resolver/claude_client.py similarity index 100% rename from auto-claude/merge/ai_resolver/claude_client.py rename to apps/backend/merge/ai_resolver/claude_client.py diff --git a/auto-claude/merge/ai_resolver/context.py b/apps/backend/merge/ai_resolver/context.py similarity index 100% rename from auto-claude/merge/ai_resolver/context.py rename to apps/backend/merge/ai_resolver/context.py diff --git a/auto-claude/merge/ai_resolver/language_utils.py b/apps/backend/merge/ai_resolver/language_utils.py similarity index 100% rename from auto-claude/merge/ai_resolver/language_utils.py rename to apps/backend/merge/ai_resolver/language_utils.py diff --git a/auto-claude/merge/ai_resolver/parsers.py b/apps/backend/merge/ai_resolver/parsers.py similarity index 100% rename from auto-claude/merge/ai_resolver/parsers.py rename to apps/backend/merge/ai_resolver/parsers.py diff --git a/auto-claude/merge/ai_resolver/prompts.py b/apps/backend/merge/ai_resolver/prompts.py similarity index 100% rename from auto-claude/merge/ai_resolver/prompts.py rename to apps/backend/merge/ai_resolver/prompts.py diff --git a/auto-claude/merge/ai_resolver/resolver.py b/apps/backend/merge/ai_resolver/resolver.py similarity index 100% rename from auto-claude/merge/ai_resolver/resolver.py rename to apps/backend/merge/ai_resolver/resolver.py diff --git a/auto-claude/merge/auto_merger.py b/apps/backend/merge/auto_merger.py similarity index 100% rename from auto-claude/merge/auto_merger.py rename to apps/backend/merge/auto_merger.py diff --git a/auto-claude/merge/auto_merger/__init__.py b/apps/backend/merge/auto_merger/__init__.py similarity index 100% rename from auto-claude/merge/auto_merger/__init__.py rename to apps/backend/merge/auto_merger/__init__.py diff --git a/auto-claude/merge/auto_merger/context.py b/apps/backend/merge/auto_merger/context.py similarity index 100% rename from auto-claude/merge/auto_merger/context.py rename to apps/backend/merge/auto_merger/context.py diff --git a/auto-claude/merge/auto_merger/helpers.py b/apps/backend/merge/auto_merger/helpers.py similarity index 100% rename from auto-claude/merge/auto_merger/helpers.py rename to apps/backend/merge/auto_merger/helpers.py diff --git a/auto-claude/merge/auto_merger/merger.py b/apps/backend/merge/auto_merger/merger.py similarity index 100% rename from auto-claude/merge/auto_merger/merger.py rename to apps/backend/merge/auto_merger/merger.py diff --git a/auto-claude/merge/auto_merger/strategies/__init__.py b/apps/backend/merge/auto_merger/strategies/__init__.py similarity index 100% rename from auto-claude/merge/auto_merger/strategies/__init__.py rename to apps/backend/merge/auto_merger/strategies/__init__.py diff --git a/auto-claude/merge/auto_merger/strategies/append_strategy.py b/apps/backend/merge/auto_merger/strategies/append_strategy.py similarity index 100% rename from auto-claude/merge/auto_merger/strategies/append_strategy.py rename to apps/backend/merge/auto_merger/strategies/append_strategy.py diff --git a/auto-claude/merge/auto_merger/strategies/base_strategy.py b/apps/backend/merge/auto_merger/strategies/base_strategy.py similarity index 100% rename from auto-claude/merge/auto_merger/strategies/base_strategy.py rename to apps/backend/merge/auto_merger/strategies/base_strategy.py diff --git a/auto-claude/merge/auto_merger/strategies/hooks_strategy.py b/apps/backend/merge/auto_merger/strategies/hooks_strategy.py similarity index 100% rename from auto-claude/merge/auto_merger/strategies/hooks_strategy.py rename to apps/backend/merge/auto_merger/strategies/hooks_strategy.py diff --git a/auto-claude/merge/auto_merger/strategies/import_strategy.py b/apps/backend/merge/auto_merger/strategies/import_strategy.py similarity index 100% rename from auto-claude/merge/auto_merger/strategies/import_strategy.py rename to apps/backend/merge/auto_merger/strategies/import_strategy.py diff --git a/auto-claude/merge/auto_merger/strategies/ordering_strategy.py b/apps/backend/merge/auto_merger/strategies/ordering_strategy.py similarity index 100% rename from auto-claude/merge/auto_merger/strategies/ordering_strategy.py rename to apps/backend/merge/auto_merger/strategies/ordering_strategy.py diff --git a/auto-claude/merge/auto_merger/strategies/props_strategy.py b/apps/backend/merge/auto_merger/strategies/props_strategy.py similarity index 100% rename from auto-claude/merge/auto_merger/strategies/props_strategy.py rename to apps/backend/merge/auto_merger/strategies/props_strategy.py diff --git a/auto-claude/merge/compatibility_rules.py b/apps/backend/merge/compatibility_rules.py similarity index 100% rename from auto-claude/merge/compatibility_rules.py rename to apps/backend/merge/compatibility_rules.py diff --git a/auto-claude/merge/conflict_analysis.py b/apps/backend/merge/conflict_analysis.py similarity index 100% rename from auto-claude/merge/conflict_analysis.py rename to apps/backend/merge/conflict_analysis.py diff --git a/auto-claude/merge/conflict_detector.py b/apps/backend/merge/conflict_detector.py similarity index 100% rename from auto-claude/merge/conflict_detector.py rename to apps/backend/merge/conflict_detector.py diff --git a/auto-claude/merge/conflict_explanation.py b/apps/backend/merge/conflict_explanation.py similarity index 100% rename from auto-claude/merge/conflict_explanation.py rename to apps/backend/merge/conflict_explanation.py diff --git a/auto-claude/merge/conflict_resolver.py b/apps/backend/merge/conflict_resolver.py similarity index 100% rename from auto-claude/merge/conflict_resolver.py rename to apps/backend/merge/conflict_resolver.py diff --git a/auto-claude/merge/file_evolution.py b/apps/backend/merge/file_evolution.py similarity index 100% rename from auto-claude/merge/file_evolution.py rename to apps/backend/merge/file_evolution.py diff --git a/auto-claude/merge/file_evolution/__init__.py b/apps/backend/merge/file_evolution/__init__.py similarity index 100% rename from auto-claude/merge/file_evolution/__init__.py rename to apps/backend/merge/file_evolution/__init__.py diff --git a/auto-claude/merge/file_evolution/baseline_capture.py b/apps/backend/merge/file_evolution/baseline_capture.py similarity index 100% rename from auto-claude/merge/file_evolution/baseline_capture.py rename to apps/backend/merge/file_evolution/baseline_capture.py diff --git a/auto-claude/merge/file_evolution/evolution_queries.py b/apps/backend/merge/file_evolution/evolution_queries.py similarity index 100% rename from auto-claude/merge/file_evolution/evolution_queries.py rename to apps/backend/merge/file_evolution/evolution_queries.py diff --git a/auto-claude/merge/file_evolution/modification_tracker.py b/apps/backend/merge/file_evolution/modification_tracker.py similarity index 100% rename from auto-claude/merge/file_evolution/modification_tracker.py rename to apps/backend/merge/file_evolution/modification_tracker.py diff --git a/auto-claude/merge/file_evolution/storage.py b/apps/backend/merge/file_evolution/storage.py similarity index 100% rename from auto-claude/merge/file_evolution/storage.py rename to apps/backend/merge/file_evolution/storage.py diff --git a/auto-claude/merge/file_evolution/tracker.py b/apps/backend/merge/file_evolution/tracker.py similarity index 100% rename from auto-claude/merge/file_evolution/tracker.py rename to apps/backend/merge/file_evolution/tracker.py diff --git a/auto-claude/merge/file_merger.py b/apps/backend/merge/file_merger.py similarity index 100% rename from auto-claude/merge/file_merger.py rename to apps/backend/merge/file_merger.py diff --git a/auto-claude/merge/file_timeline.py b/apps/backend/merge/file_timeline.py similarity index 100% rename from auto-claude/merge/file_timeline.py rename to apps/backend/merge/file_timeline.py diff --git a/auto-claude/merge/git_utils.py b/apps/backend/merge/git_utils.py similarity index 100% rename from auto-claude/merge/git_utils.py rename to apps/backend/merge/git_utils.py diff --git a/auto-claude/merge/hooks/post-commit b/apps/backend/merge/hooks/post-commit old mode 100755 new mode 100644 similarity index 100% rename from auto-claude/merge/hooks/post-commit rename to apps/backend/merge/hooks/post-commit diff --git a/auto-claude/merge/install_hook.py b/apps/backend/merge/install_hook.py similarity index 100% rename from auto-claude/merge/install_hook.py rename to apps/backend/merge/install_hook.py diff --git a/auto-claude/merge/merge_pipeline.py b/apps/backend/merge/merge_pipeline.py similarity index 100% rename from auto-claude/merge/merge_pipeline.py rename to apps/backend/merge/merge_pipeline.py diff --git a/auto-claude/merge/models.py b/apps/backend/merge/models.py similarity index 100% rename from auto-claude/merge/models.py rename to apps/backend/merge/models.py diff --git a/auto-claude/merge/orchestrator.py b/apps/backend/merge/orchestrator.py similarity index 100% rename from auto-claude/merge/orchestrator.py rename to apps/backend/merge/orchestrator.py diff --git a/auto-claude/merge/prompts.py b/apps/backend/merge/prompts.py similarity index 100% rename from auto-claude/merge/prompts.py rename to apps/backend/merge/prompts.py diff --git a/auto-claude/merge/semantic_analysis/__init__.py b/apps/backend/merge/semantic_analysis/__init__.py similarity index 100% rename from auto-claude/merge/semantic_analysis/__init__.py rename to apps/backend/merge/semantic_analysis/__init__.py diff --git a/auto-claude/merge/semantic_analysis/comparison.py b/apps/backend/merge/semantic_analysis/comparison.py similarity index 100% rename from auto-claude/merge/semantic_analysis/comparison.py rename to apps/backend/merge/semantic_analysis/comparison.py diff --git a/auto-claude/merge/semantic_analysis/js_analyzer.py b/apps/backend/merge/semantic_analysis/js_analyzer.py similarity index 100% rename from auto-claude/merge/semantic_analysis/js_analyzer.py rename to apps/backend/merge/semantic_analysis/js_analyzer.py diff --git a/auto-claude/merge/semantic_analysis/models.py b/apps/backend/merge/semantic_analysis/models.py similarity index 100% rename from auto-claude/merge/semantic_analysis/models.py rename to apps/backend/merge/semantic_analysis/models.py diff --git a/auto-claude/merge/semantic_analysis/python_analyzer.py b/apps/backend/merge/semantic_analysis/python_analyzer.py similarity index 100% rename from auto-claude/merge/semantic_analysis/python_analyzer.py rename to apps/backend/merge/semantic_analysis/python_analyzer.py diff --git a/auto-claude/merge/semantic_analysis/regex_analyzer.py b/apps/backend/merge/semantic_analysis/regex_analyzer.py similarity index 100% rename from auto-claude/merge/semantic_analysis/regex_analyzer.py rename to apps/backend/merge/semantic_analysis/regex_analyzer.py diff --git a/auto-claude/merge/semantic_analyzer.py b/apps/backend/merge/semantic_analyzer.py similarity index 100% rename from auto-claude/merge/semantic_analyzer.py rename to apps/backend/merge/semantic_analyzer.py diff --git a/auto-claude/merge/timeline_git.py b/apps/backend/merge/timeline_git.py similarity index 100% rename from auto-claude/merge/timeline_git.py rename to apps/backend/merge/timeline_git.py diff --git a/auto-claude/merge/timeline_models.py b/apps/backend/merge/timeline_models.py similarity index 100% rename from auto-claude/merge/timeline_models.py rename to apps/backend/merge/timeline_models.py diff --git a/auto-claude/merge/timeline_persistence.py b/apps/backend/merge/timeline_persistence.py similarity index 100% rename from auto-claude/merge/timeline_persistence.py rename to apps/backend/merge/timeline_persistence.py diff --git a/auto-claude/merge/timeline_tracker.py b/apps/backend/merge/timeline_tracker.py similarity index 100% rename from auto-claude/merge/timeline_tracker.py rename to apps/backend/merge/timeline_tracker.py diff --git a/auto-claude/merge/tracker_cli.py b/apps/backend/merge/tracker_cli.py similarity index 100% rename from auto-claude/merge/tracker_cli.py rename to apps/backend/merge/tracker_cli.py diff --git a/auto-claude/merge/types.py b/apps/backend/merge/types.py similarity index 100% rename from auto-claude/merge/types.py rename to apps/backend/merge/types.py diff --git a/auto-claude/ollama_model_detector.py b/apps/backend/ollama_model_detector.py similarity index 100% rename from auto-claude/ollama_model_detector.py rename to apps/backend/ollama_model_detector.py diff --git a/auto-claude/phase_config.py b/apps/backend/phase_config.py similarity index 100% rename from auto-claude/phase_config.py rename to apps/backend/phase_config.py diff --git a/auto-claude/planner_lib/__init__.py b/apps/backend/planner_lib/__init__.py similarity index 100% rename from auto-claude/planner_lib/__init__.py rename to apps/backend/planner_lib/__init__.py diff --git a/auto-claude/planner_lib/context.py b/apps/backend/planner_lib/context.py similarity index 100% rename from auto-claude/planner_lib/context.py rename to apps/backend/planner_lib/context.py diff --git a/auto-claude/planner_lib/generators.py b/apps/backend/planner_lib/generators.py similarity index 100% rename from auto-claude/planner_lib/generators.py rename to apps/backend/planner_lib/generators.py diff --git a/auto-claude/planner_lib/main.py b/apps/backend/planner_lib/main.py similarity index 100% rename from auto-claude/planner_lib/main.py rename to apps/backend/planner_lib/main.py diff --git a/auto-claude/planner_lib/models.py b/apps/backend/planner_lib/models.py similarity index 100% rename from auto-claude/planner_lib/models.py rename to apps/backend/planner_lib/models.py diff --git a/auto-claude/planner_lib/utils.py b/apps/backend/planner_lib/utils.py similarity index 100% rename from auto-claude/planner_lib/utils.py rename to apps/backend/planner_lib/utils.py diff --git a/auto-claude/prediction/__init__.py b/apps/backend/prediction/__init__.py similarity index 100% rename from auto-claude/prediction/__init__.py rename to apps/backend/prediction/__init__.py diff --git a/auto-claude/prediction/checklist_generator.py b/apps/backend/prediction/checklist_generator.py similarity index 100% rename from auto-claude/prediction/checklist_generator.py rename to apps/backend/prediction/checklist_generator.py diff --git a/auto-claude/prediction/formatter.py b/apps/backend/prediction/formatter.py similarity index 100% rename from auto-claude/prediction/formatter.py rename to apps/backend/prediction/formatter.py diff --git a/auto-claude/prediction/main.py b/apps/backend/prediction/main.py similarity index 100% rename from auto-claude/prediction/main.py rename to apps/backend/prediction/main.py diff --git a/auto-claude/prediction/memory_loader.py b/apps/backend/prediction/memory_loader.py similarity index 100% rename from auto-claude/prediction/memory_loader.py rename to apps/backend/prediction/memory_loader.py diff --git a/auto-claude/prediction/models.py b/apps/backend/prediction/models.py similarity index 100% rename from auto-claude/prediction/models.py rename to apps/backend/prediction/models.py diff --git a/auto-claude/prediction/patterns.py b/apps/backend/prediction/patterns.py similarity index 100% rename from auto-claude/prediction/patterns.py rename to apps/backend/prediction/patterns.py diff --git a/auto-claude/prediction/predictor.py b/apps/backend/prediction/predictor.py similarity index 100% rename from auto-claude/prediction/predictor.py rename to apps/backend/prediction/predictor.py diff --git a/auto-claude/prediction/risk_analyzer.py b/apps/backend/prediction/risk_analyzer.py similarity index 100% rename from auto-claude/prediction/risk_analyzer.py rename to apps/backend/prediction/risk_analyzer.py diff --git a/apps/backend/progress.py b/apps/backend/progress.py new file mode 100644 index 00000000..5cc2afea --- /dev/null +++ b/apps/backend/progress.py @@ -0,0 +1,36 @@ +""" +Progress tracking module facade. + +Provides progress tracking utilities for build execution. +Re-exports from core.progress for clean imports. +""" + +from core.progress import ( + count_subtasks, + count_subtasks_detailed, + format_duration, + get_current_phase, + get_next_subtask, + get_plan_summary, + get_progress_percentage, + is_build_complete, + print_build_complete_banner, + print_paused_banner, + print_progress_summary, + print_session_header, +) + +__all__ = [ + "count_subtasks", + "count_subtasks_detailed", + "format_duration", + "get_current_phase", + "get_next_subtask", + "get_plan_summary", + "get_progress_percentage", + "is_build_complete", + "print_build_complete_banner", + "print_paused_banner", + "print_progress_summary", + "print_session_header", +] diff --git a/auto-claude/project/__init__.py b/apps/backend/project/__init__.py similarity index 100% rename from auto-claude/project/__init__.py rename to apps/backend/project/__init__.py diff --git a/auto-claude/project/analyzer.py b/apps/backend/project/analyzer.py similarity index 100% rename from auto-claude/project/analyzer.py rename to apps/backend/project/analyzer.py diff --git a/auto-claude/project/command_registry.py b/apps/backend/project/command_registry.py similarity index 100% rename from auto-claude/project/command_registry.py rename to apps/backend/project/command_registry.py diff --git a/auto-claude/project/command_registry/README.md b/apps/backend/project/command_registry/README.md similarity index 100% rename from auto-claude/project/command_registry/README.md rename to apps/backend/project/command_registry/README.md diff --git a/auto-claude/project/command_registry/__init__.py b/apps/backend/project/command_registry/__init__.py similarity index 100% rename from auto-claude/project/command_registry/__init__.py rename to apps/backend/project/command_registry/__init__.py diff --git a/auto-claude/project/command_registry/base.py b/apps/backend/project/command_registry/base.py similarity index 100% rename from auto-claude/project/command_registry/base.py rename to apps/backend/project/command_registry/base.py diff --git a/auto-claude/project/command_registry/cloud.py b/apps/backend/project/command_registry/cloud.py similarity index 100% rename from auto-claude/project/command_registry/cloud.py rename to apps/backend/project/command_registry/cloud.py diff --git a/auto-claude/project/command_registry/code_quality.py b/apps/backend/project/command_registry/code_quality.py similarity index 100% rename from auto-claude/project/command_registry/code_quality.py rename to apps/backend/project/command_registry/code_quality.py diff --git a/auto-claude/project/command_registry/databases.py b/apps/backend/project/command_registry/databases.py similarity index 100% rename from auto-claude/project/command_registry/databases.py rename to apps/backend/project/command_registry/databases.py diff --git a/auto-claude/project/command_registry/frameworks.py b/apps/backend/project/command_registry/frameworks.py similarity index 100% rename from auto-claude/project/command_registry/frameworks.py rename to apps/backend/project/command_registry/frameworks.py diff --git a/auto-claude/project/command_registry/infrastructure.py b/apps/backend/project/command_registry/infrastructure.py similarity index 100% rename from auto-claude/project/command_registry/infrastructure.py rename to apps/backend/project/command_registry/infrastructure.py diff --git a/auto-claude/project/command_registry/languages.py b/apps/backend/project/command_registry/languages.py similarity index 100% rename from auto-claude/project/command_registry/languages.py rename to apps/backend/project/command_registry/languages.py diff --git a/auto-claude/project/command_registry/package_managers.py b/apps/backend/project/command_registry/package_managers.py similarity index 100% rename from auto-claude/project/command_registry/package_managers.py rename to apps/backend/project/command_registry/package_managers.py diff --git a/auto-claude/project/command_registry/version_managers.py b/apps/backend/project/command_registry/version_managers.py similarity index 100% rename from auto-claude/project/command_registry/version_managers.py rename to apps/backend/project/command_registry/version_managers.py diff --git a/auto-claude/project/config_parser.py b/apps/backend/project/config_parser.py similarity index 100% rename from auto-claude/project/config_parser.py rename to apps/backend/project/config_parser.py diff --git a/auto-claude/project/framework_detector.py b/apps/backend/project/framework_detector.py similarity index 100% rename from auto-claude/project/framework_detector.py rename to apps/backend/project/framework_detector.py diff --git a/auto-claude/project/models.py b/apps/backend/project/models.py similarity index 100% rename from auto-claude/project/models.py rename to apps/backend/project/models.py diff --git a/auto-claude/project/stack_detector.py b/apps/backend/project/stack_detector.py similarity index 100% rename from auto-claude/project/stack_detector.py rename to apps/backend/project/stack_detector.py diff --git a/auto-claude/project/structure_analyzer.py b/apps/backend/project/structure_analyzer.py similarity index 100% rename from auto-claude/project/structure_analyzer.py rename to apps/backend/project/structure_analyzer.py diff --git a/auto-claude/project_analyzer.py b/apps/backend/project_analyzer.py similarity index 100% rename from auto-claude/project_analyzer.py rename to apps/backend/project_analyzer.py diff --git a/auto-claude/prompt_generator.py b/apps/backend/prompt_generator.py similarity index 100% rename from auto-claude/prompt_generator.py rename to apps/backend/prompt_generator.py diff --git a/auto-claude/prompts.py b/apps/backend/prompts.py similarity index 100% rename from auto-claude/prompts.py rename to apps/backend/prompts.py diff --git a/auto-claude/prompts/coder.md b/apps/backend/prompts/coder.md similarity index 100% rename from auto-claude/prompts/coder.md rename to apps/backend/prompts/coder.md diff --git a/auto-claude/prompts/coder_recovery.md b/apps/backend/prompts/coder_recovery.md similarity index 100% rename from auto-claude/prompts/coder_recovery.md rename to apps/backend/prompts/coder_recovery.md diff --git a/auto-claude/prompts/competitor_analysis.md b/apps/backend/prompts/competitor_analysis.md similarity index 100% rename from auto-claude/prompts/competitor_analysis.md rename to apps/backend/prompts/competitor_analysis.md diff --git a/auto-claude/prompts/complexity_assessor.md b/apps/backend/prompts/complexity_assessor.md similarity index 96% rename from auto-claude/prompts/complexity_assessor.md rename to apps/backend/prompts/complexity_assessor.md index 5ff0f925..540534cf 100644 --- a/auto-claude/prompts/complexity_assessor.md +++ b/apps/backend/prompts/complexity_assessor.md @@ -588,7 +588,7 @@ START ### Example 5: Complex Feature Task -**Task**: "Add Graphiti Memory Integration with FalkorDB as an optional layer controlled by .env variables using Docker Compose" +**Task**: "Add Graphiti Memory Integration with LadybugDB (embedded database) as an optional layer controlled by .env variables" **Assessment**: ```json @@ -596,7 +596,7 @@ START "complexity": "complex", "workflow_type": "feature", "confidence": 0.90, - "reasoning": "Multiple integrations (Graphiti, FalkorDB), infrastructure changes (Docker Compose), and new architectural pattern (optional memory layer). Requires research for correct API usage and careful design.", + "reasoning": "Multiple integrations (Graphiti, LadybugDB), new architectural pattern (memory layer with embedded database). Requires research for correct API usage and careful design.", "analysis": { "scope": { "estimated_files": 12, @@ -605,21 +605,21 @@ START "notes": "Memory integration will likely touch multiple parts of the system" }, "integrations": { - "external_services": ["Graphiti", "FalkorDB"], - "new_dependencies": ["graphiti-core", "falkordb driver"], + "external_services": ["Graphiti", "LadybugDB"], + "new_dependencies": ["graphiti-core", "real_ladybug"], "research_needed": true, "notes": "Graphiti is a newer library, need to verify API patterns" }, "infrastructure": { - "docker_changes": true, + "docker_changes": false, "database_changes": true, "config_changes": true, - "notes": "FalkorDB requires Docker container, new env vars needed" + "notes": "LadybugDB is embedded, no Docker needed, new env vars required" }, "knowledge": { "patterns_exist": false, "research_required": true, - "unfamiliar_tech": ["graphiti-core", "FalkorDB"], + "unfamiliar_tech": ["graphiti-core", "LadybugDB"], "notes": "No existing graph database patterns in codebase" }, "risk": { @@ -632,7 +632,7 @@ START "flags": { "needs_research": true, "needs_self_critique": true, - "needs_infrastructure_setup": true + "needs_infrastructure_setup": false }, "validation_recommendations": { "risk_level": "high", @@ -640,8 +640,8 @@ START "minimal_mode": false, "test_types_required": ["unit", "integration", "e2e"], "security_scan_required": true, - "staging_deployment_required": true, - "reasoning": "Database integration with new dependencies requires full test coverage. Security scan for API key handling. Staging deployment to verify Docker container orchestration." + "staging_deployment_required": false, + "reasoning": "Database integration with new dependencies requires full test coverage. Security scan for API key handling. No staging deployment needed since embedded database doesn't require infrastructure setup." } } ``` diff --git a/auto-claude/prompts/followup_planner.md b/apps/backend/prompts/followup_planner.md similarity index 100% rename from auto-claude/prompts/followup_planner.md rename to apps/backend/prompts/followup_planner.md diff --git a/auto-claude/prompts/ideation_code_improvements.md b/apps/backend/prompts/ideation_code_improvements.md similarity index 100% rename from auto-claude/prompts/ideation_code_improvements.md rename to apps/backend/prompts/ideation_code_improvements.md diff --git a/auto-claude/prompts/ideation_code_quality.md b/apps/backend/prompts/ideation_code_quality.md similarity index 100% rename from auto-claude/prompts/ideation_code_quality.md rename to apps/backend/prompts/ideation_code_quality.md diff --git a/auto-claude/prompts/ideation_documentation.md b/apps/backend/prompts/ideation_documentation.md similarity index 100% rename from auto-claude/prompts/ideation_documentation.md rename to apps/backend/prompts/ideation_documentation.md diff --git a/auto-claude/prompts/ideation_performance.md b/apps/backend/prompts/ideation_performance.md similarity index 100% rename from auto-claude/prompts/ideation_performance.md rename to apps/backend/prompts/ideation_performance.md diff --git a/auto-claude/prompts/ideation_security.md b/apps/backend/prompts/ideation_security.md similarity index 100% rename from auto-claude/prompts/ideation_security.md rename to apps/backend/prompts/ideation_security.md diff --git a/auto-claude/prompts/ideation_ui_ux.md b/apps/backend/prompts/ideation_ui_ux.md similarity index 100% rename from auto-claude/prompts/ideation_ui_ux.md rename to apps/backend/prompts/ideation_ui_ux.md diff --git a/auto-claude/prompts/insight_extractor.md b/apps/backend/prompts/insight_extractor.md similarity index 100% rename from auto-claude/prompts/insight_extractor.md rename to apps/backend/prompts/insight_extractor.md diff --git a/auto-claude/prompts/mcp_tools/api_validation.md b/apps/backend/prompts/mcp_tools/api_validation.md similarity index 100% rename from auto-claude/prompts/mcp_tools/api_validation.md rename to apps/backend/prompts/mcp_tools/api_validation.md diff --git a/auto-claude/prompts/mcp_tools/database_validation.md b/apps/backend/prompts/mcp_tools/database_validation.md similarity index 100% rename from auto-claude/prompts/mcp_tools/database_validation.md rename to apps/backend/prompts/mcp_tools/database_validation.md diff --git a/auto-claude/prompts/mcp_tools/electron_validation.md b/apps/backend/prompts/mcp_tools/electron_validation.md similarity index 100% rename from auto-claude/prompts/mcp_tools/electron_validation.md rename to apps/backend/prompts/mcp_tools/electron_validation.md diff --git a/auto-claude/prompts/mcp_tools/puppeteer_browser.md b/apps/backend/prompts/mcp_tools/puppeteer_browser.md similarity index 100% rename from auto-claude/prompts/mcp_tools/puppeteer_browser.md rename to apps/backend/prompts/mcp_tools/puppeteer_browser.md diff --git a/auto-claude/prompts/planner.md b/apps/backend/prompts/planner.md similarity index 100% rename from auto-claude/prompts/planner.md rename to apps/backend/prompts/planner.md diff --git a/auto-claude/prompts/qa_fixer.md b/apps/backend/prompts/qa_fixer.md similarity index 100% rename from auto-claude/prompts/qa_fixer.md rename to apps/backend/prompts/qa_fixer.md diff --git a/auto-claude/prompts/qa_reviewer.md b/apps/backend/prompts/qa_reviewer.md similarity index 100% rename from auto-claude/prompts/qa_reviewer.md rename to apps/backend/prompts/qa_reviewer.md diff --git a/auto-claude/prompts/roadmap_discovery.md b/apps/backend/prompts/roadmap_discovery.md similarity index 100% rename from auto-claude/prompts/roadmap_discovery.md rename to apps/backend/prompts/roadmap_discovery.md diff --git a/auto-claude/prompts/roadmap_features.md b/apps/backend/prompts/roadmap_features.md similarity index 100% rename from auto-claude/prompts/roadmap_features.md rename to apps/backend/prompts/roadmap_features.md diff --git a/auto-claude/prompts/spec_critic.md b/apps/backend/prompts/spec_critic.md similarity index 97% rename from auto-claude/prompts/spec_critic.md rename to apps/backend/prompts/spec_critic.md index 2f5a1f3c..2f0f08fb 100644 --- a/auto-claude/prompts/spec_critic.md +++ b/apps/backend/prompts/spec_critic.md @@ -130,8 +130,8 @@ Create a list of all issues found: ISSUES FOUND: 1. [SEVERITY: HIGH] Package name incorrect - - Spec says: "graphiti-core[falkordb]" - - Research says: "graphiti-core-falkordb" + - Spec says: "graphiti-core real_ladybug" + - Research says: "graphiti-core" with separate "real_ladybug" dependency - Location: Line 45, Requirements section 2. [SEVERITY: MEDIUM] Missing edge case @@ -156,7 +156,7 @@ cat spec.md # Apply fixes using edit commands # Example: Fix package name -sed -i 's/graphiti-core\[falkordb\]/graphiti-core-falkordb/g' spec.md +sed -i 's/graphiti-core real_ladybug/graphiti-core\nreal_ladybug/g' spec.md # Or rewrite sections as needed ``` diff --git a/auto-claude/prompts/spec_gatherer.md b/apps/backend/prompts/spec_gatherer.md similarity index 100% rename from auto-claude/prompts/spec_gatherer.md rename to apps/backend/prompts/spec_gatherer.md diff --git a/auto-claude/prompts/spec_quick.md b/apps/backend/prompts/spec_quick.md similarity index 100% rename from auto-claude/prompts/spec_quick.md rename to apps/backend/prompts/spec_quick.md diff --git a/auto-claude/prompts/spec_researcher.md b/apps/backend/prompts/spec_researcher.md similarity index 95% rename from auto-claude/prompts/spec_researcher.md rename to apps/backend/prompts/spec_researcher.md index f9793e0a..9d3af8b1 100644 --- a/auto-claude/prompts/spec_researcher.md +++ b/apps/backend/prompts/spec_researcher.md @@ -290,7 +290,7 @@ Input: { "type": "library", "verified_package": { "name": "graphiti-core", - "install_command": "pip install graphiti-core[falkordb]", + "install_command": "pip install graphiti-core", "version": ">=0.5.0", "verified": true }, @@ -308,16 +308,16 @@ Input: { }, "configuration": { "env_vars": ["OPENAI_API_KEY"], - "dependencies": ["neo4j or falkordb driver"] + "dependencies": ["real_ladybug"] }, "infrastructure": { - "requires_docker": true, - "docker_image": "falkordb/falkordb:latest", - "ports": [6379, 3000] + "requires_docker": false, + "embedded_database": "LadybugDB" }, "gotchas": [ "Requires OpenAI API key for embeddings", - "Must call build_indices_and_constraints() before use" + "Must call build_indices_and_constraints() before use", + "LadybugDB is embedded - no separate database server needed" ], "research_sources": [ "Context7 MCP: /zep/graphiti", @@ -328,7 +328,7 @@ Input: { ], "unverified_claims": [], "recommendations": [ - "Consider FalkorDB over Neo4j for simpler local development" + "LadybugDB is embedded and requires no Docker or separate database setup" ], "context7_libraries_used": ["/zep/graphiti"], "created_at": "2024-12-10T12:00:00Z" diff --git a/auto-claude/prompts/spec_writer.md b/apps/backend/prompts/spec_writer.md similarity index 100% rename from auto-claude/prompts/spec_writer.md rename to apps/backend/prompts/spec_writer.md diff --git a/auto-claude/prompts/validation_fixer.md b/apps/backend/prompts/validation_fixer.md similarity index 100% rename from auto-claude/prompts/validation_fixer.md rename to apps/backend/prompts/validation_fixer.md diff --git a/auto-claude/prompts_pkg/__init__.py b/apps/backend/prompts_pkg/__init__.py similarity index 100% rename from auto-claude/prompts_pkg/__init__.py rename to apps/backend/prompts_pkg/__init__.py diff --git a/auto-claude/prompts_pkg/project_context.py b/apps/backend/prompts_pkg/project_context.py similarity index 100% rename from auto-claude/prompts_pkg/project_context.py rename to apps/backend/prompts_pkg/project_context.py diff --git a/auto-claude/prompts_pkg/prompt_generator.py b/apps/backend/prompts_pkg/prompt_generator.py similarity index 100% rename from auto-claude/prompts_pkg/prompt_generator.py rename to apps/backend/prompts_pkg/prompt_generator.py diff --git a/auto-claude/prompts_pkg/prompts.py b/apps/backend/prompts_pkg/prompts.py similarity index 100% rename from auto-claude/prompts_pkg/prompts.py rename to apps/backend/prompts_pkg/prompts.py diff --git a/auto-claude/qa/__init__.py b/apps/backend/qa/__init__.py similarity index 100% rename from auto-claude/qa/__init__.py rename to apps/backend/qa/__init__.py diff --git a/auto-claude/qa/criteria.py b/apps/backend/qa/criteria.py similarity index 100% rename from auto-claude/qa/criteria.py rename to apps/backend/qa/criteria.py diff --git a/auto-claude/qa/fixer.py b/apps/backend/qa/fixer.py similarity index 100% rename from auto-claude/qa/fixer.py rename to apps/backend/qa/fixer.py diff --git a/auto-claude/qa/loop.py b/apps/backend/qa/loop.py similarity index 100% rename from auto-claude/qa/loop.py rename to apps/backend/qa/loop.py diff --git a/auto-claude/qa/qa_loop.py b/apps/backend/qa/qa_loop.py similarity index 100% rename from auto-claude/qa/qa_loop.py rename to apps/backend/qa/qa_loop.py diff --git a/auto-claude/qa/report.py b/apps/backend/qa/report.py similarity index 100% rename from auto-claude/qa/report.py rename to apps/backend/qa/report.py diff --git a/auto-claude/qa/reviewer.py b/apps/backend/qa/reviewer.py similarity index 100% rename from auto-claude/qa/reviewer.py rename to apps/backend/qa/reviewer.py diff --git a/auto-claude/qa_loop.py b/apps/backend/qa_loop.py similarity index 84% rename from auto-claude/qa_loop.py rename to apps/backend/qa_loop.py index 2fe364c1..65100226 100644 --- a/auto-claude/qa_loop.py +++ b/apps/backend/qa_loop.py @@ -1,8 +1,12 @@ -"""Backward compatibility shim - import from qa package instead.""" +""" +QA loop module facade. + +Provides QA validation loop functionality. +Re-exports from qa package for clean imports. +""" from qa import ( ISSUE_SIMILARITY_THRESHOLD, - # Configuration MAX_QA_ITERATIONS, RECURRING_ISSUE_THRESHOLD, _issue_similarity, @@ -10,7 +14,6 @@ from qa import ( check_test_discovery, create_manual_test_plan, escalate_to_human, - # Report & tracking get_iteration_history, get_qa_iteration_count, get_qa_signoff_status, @@ -20,15 +23,12 @@ from qa import ( is_no_test_project, is_qa_approved, is_qa_rejected, - # Criteria & status load_implementation_plan, load_qa_fixer_prompt, - # Agent sessions print_qa_status, record_iteration, run_qa_agent_session, run_qa_fixer_session, - # Main loop run_qa_validation_loop, save_implementation_plan, should_run_fixes, @@ -36,13 +36,10 @@ from qa import ( ) __all__ = [ - # Configuration "MAX_QA_ITERATIONS", "RECURRING_ISSUE_THRESHOLD", "ISSUE_SIMILARITY_THRESHOLD", - # Main loop "run_qa_validation_loop", - # Criteria & status "load_implementation_plan", "save_implementation_plan", "get_qa_signoff_status", @@ -53,7 +50,6 @@ __all__ = [ "should_run_qa", "should_run_fixes", "print_qa_status", - # Report & tracking "get_iteration_history", "record_iteration", "has_recurring_issues", @@ -64,7 +60,6 @@ __all__ = [ "is_no_test_project", "_normalize_issue_key", "_issue_similarity", - # Agent sessions "run_qa_agent_session", "load_qa_fixer_prompt", "run_qa_fixer_session", diff --git a/auto-claude/query_memory.py b/apps/backend/query_memory.py similarity index 100% rename from auto-claude/query_memory.py rename to apps/backend/query_memory.py diff --git a/auto-claude/recovery.py b/apps/backend/recovery.py similarity index 100% rename from auto-claude/recovery.py rename to apps/backend/recovery.py diff --git a/auto-claude/requirements.txt b/apps/backend/requirements.txt similarity index 100% rename from auto-claude/requirements.txt rename to apps/backend/requirements.txt diff --git a/auto-claude/review/__init__.py b/apps/backend/review/__init__.py similarity index 100% rename from auto-claude/review/__init__.py rename to apps/backend/review/__init__.py diff --git a/auto-claude/review/diff_analyzer.py b/apps/backend/review/diff_analyzer.py similarity index 100% rename from auto-claude/review/diff_analyzer.py rename to apps/backend/review/diff_analyzer.py diff --git a/auto-claude/review/formatters.py b/apps/backend/review/formatters.py similarity index 100% rename from auto-claude/review/formatters.py rename to apps/backend/review/formatters.py diff --git a/auto-claude/review/main.py b/apps/backend/review/main.py similarity index 100% rename from auto-claude/review/main.py rename to apps/backend/review/main.py diff --git a/auto-claude/review/reviewer.py b/apps/backend/review/reviewer.py similarity index 100% rename from auto-claude/review/reviewer.py rename to apps/backend/review/reviewer.py diff --git a/auto-claude/review/state.py b/apps/backend/review/state.py similarity index 100% rename from auto-claude/review/state.py rename to apps/backend/review/state.py diff --git a/auto-claude/risk_classifier.py b/apps/backend/risk_classifier.py similarity index 100% rename from auto-claude/risk_classifier.py rename to apps/backend/risk_classifier.py diff --git a/auto-claude/run.py b/apps/backend/run.py similarity index 100% rename from auto-claude/run.py rename to apps/backend/run.py diff --git a/auto-claude/runners/__init__.py b/apps/backend/runners/__init__.py similarity index 100% rename from auto-claude/runners/__init__.py rename to apps/backend/runners/__init__.py diff --git a/auto-claude/runners/ai_analyzer/EXAMPLES.md b/apps/backend/runners/ai_analyzer/EXAMPLES.md similarity index 100% rename from auto-claude/runners/ai_analyzer/EXAMPLES.md rename to apps/backend/runners/ai_analyzer/EXAMPLES.md diff --git a/auto-claude/runners/ai_analyzer/README.md b/apps/backend/runners/ai_analyzer/README.md similarity index 100% rename from auto-claude/runners/ai_analyzer/README.md rename to apps/backend/runners/ai_analyzer/README.md diff --git a/auto-claude/runners/ai_analyzer/__init__.py b/apps/backend/runners/ai_analyzer/__init__.py similarity index 100% rename from auto-claude/runners/ai_analyzer/__init__.py rename to apps/backend/runners/ai_analyzer/__init__.py diff --git a/auto-claude/runners/ai_analyzer/analyzers.py b/apps/backend/runners/ai_analyzer/analyzers.py similarity index 100% rename from auto-claude/runners/ai_analyzer/analyzers.py rename to apps/backend/runners/ai_analyzer/analyzers.py diff --git a/auto-claude/runners/ai_analyzer/cache_manager.py b/apps/backend/runners/ai_analyzer/cache_manager.py similarity index 100% rename from auto-claude/runners/ai_analyzer/cache_manager.py rename to apps/backend/runners/ai_analyzer/cache_manager.py diff --git a/auto-claude/runners/ai_analyzer/claude_client.py b/apps/backend/runners/ai_analyzer/claude_client.py similarity index 100% rename from auto-claude/runners/ai_analyzer/claude_client.py rename to apps/backend/runners/ai_analyzer/claude_client.py diff --git a/auto-claude/runners/ai_analyzer/cost_estimator.py b/apps/backend/runners/ai_analyzer/cost_estimator.py similarity index 100% rename from auto-claude/runners/ai_analyzer/cost_estimator.py rename to apps/backend/runners/ai_analyzer/cost_estimator.py diff --git a/auto-claude/runners/ai_analyzer/models.py b/apps/backend/runners/ai_analyzer/models.py similarity index 100% rename from auto-claude/runners/ai_analyzer/models.py rename to apps/backend/runners/ai_analyzer/models.py diff --git a/auto-claude/runners/ai_analyzer/result_parser.py b/apps/backend/runners/ai_analyzer/result_parser.py similarity index 100% rename from auto-claude/runners/ai_analyzer/result_parser.py rename to apps/backend/runners/ai_analyzer/result_parser.py diff --git a/auto-claude/runners/ai_analyzer/runner.py b/apps/backend/runners/ai_analyzer/runner.py similarity index 100% rename from auto-claude/runners/ai_analyzer/runner.py rename to apps/backend/runners/ai_analyzer/runner.py diff --git a/auto-claude/runners/ai_analyzer/summary_printer.py b/apps/backend/runners/ai_analyzer/summary_printer.py similarity index 100% rename from auto-claude/runners/ai_analyzer/summary_printer.py rename to apps/backend/runners/ai_analyzer/summary_printer.py diff --git a/auto-claude/runners/ai_analyzer_runner.py b/apps/backend/runners/ai_analyzer_runner.py old mode 100755 new mode 100644 similarity index 100% rename from auto-claude/runners/ai_analyzer_runner.py rename to apps/backend/runners/ai_analyzer_runner.py diff --git a/auto-claude/runners/ideation_runner.py b/apps/backend/runners/ideation_runner.py similarity index 100% rename from auto-claude/runners/ideation_runner.py rename to apps/backend/runners/ideation_runner.py diff --git a/auto-claude/runners/insights_runner.py b/apps/backend/runners/insights_runner.py similarity index 100% rename from auto-claude/runners/insights_runner.py rename to apps/backend/runners/insights_runner.py diff --git a/auto-claude/runners/roadmap/__init__.py b/apps/backend/runners/roadmap/__init__.py similarity index 100% rename from auto-claude/runners/roadmap/__init__.py rename to apps/backend/runners/roadmap/__init__.py diff --git a/auto-claude/runners/roadmap/competitor_analyzer.py b/apps/backend/runners/roadmap/competitor_analyzer.py similarity index 100% rename from auto-claude/runners/roadmap/competitor_analyzer.py rename to apps/backend/runners/roadmap/competitor_analyzer.py diff --git a/auto-claude/runners/roadmap/executor.py b/apps/backend/runners/roadmap/executor.py similarity index 100% rename from auto-claude/runners/roadmap/executor.py rename to apps/backend/runners/roadmap/executor.py diff --git a/auto-claude/runners/roadmap/graph_integration.py b/apps/backend/runners/roadmap/graph_integration.py similarity index 100% rename from auto-claude/runners/roadmap/graph_integration.py rename to apps/backend/runners/roadmap/graph_integration.py diff --git a/auto-claude/runners/roadmap/models.py b/apps/backend/runners/roadmap/models.py similarity index 100% rename from auto-claude/runners/roadmap/models.py rename to apps/backend/runners/roadmap/models.py diff --git a/auto-claude/runners/roadmap/orchestrator.py b/apps/backend/runners/roadmap/orchestrator.py similarity index 100% rename from auto-claude/runners/roadmap/orchestrator.py rename to apps/backend/runners/roadmap/orchestrator.py diff --git a/auto-claude/runners/roadmap/phases.py b/apps/backend/runners/roadmap/phases.py similarity index 100% rename from auto-claude/runners/roadmap/phases.py rename to apps/backend/runners/roadmap/phases.py diff --git a/auto-claude/runners/roadmap/project_index.json b/apps/backend/runners/roadmap/project_index.json similarity index 100% rename from auto-claude/runners/roadmap/project_index.json rename to apps/backend/runners/roadmap/project_index.json diff --git a/auto-claude/runners/roadmap_runner.py b/apps/backend/runners/roadmap_runner.py similarity index 100% rename from auto-claude/runners/roadmap_runner.py rename to apps/backend/runners/roadmap_runner.py diff --git a/auto-claude/runners/spec_runner.py b/apps/backend/runners/spec_runner.py similarity index 100% rename from auto-claude/runners/spec_runner.py rename to apps/backend/runners/spec_runner.py diff --git a/auto-claude/scan-for-secrets b/apps/backend/scan-for-secrets old mode 100755 new mode 100644 similarity index 100% rename from auto-claude/scan-for-secrets rename to apps/backend/scan-for-secrets diff --git a/auto-claude/scan_secrets.py b/apps/backend/scan_secrets.py similarity index 100% rename from auto-claude/scan_secrets.py rename to apps/backend/scan_secrets.py diff --git a/auto-claude/security.py b/apps/backend/security.py similarity index 100% rename from auto-claude/security.py rename to apps/backend/security.py diff --git a/auto-claude/security/__init__.py b/apps/backend/security/__init__.py similarity index 100% rename from auto-claude/security/__init__.py rename to apps/backend/security/__init__.py diff --git a/auto-claude/security/database_validators.py b/apps/backend/security/database_validators.py similarity index 100% rename from auto-claude/security/database_validators.py rename to apps/backend/security/database_validators.py diff --git a/auto-claude/security/filesystem_validators.py b/apps/backend/security/filesystem_validators.py similarity index 100% rename from auto-claude/security/filesystem_validators.py rename to apps/backend/security/filesystem_validators.py diff --git a/auto-claude/security/git_validators.py b/apps/backend/security/git_validators.py similarity index 100% rename from auto-claude/security/git_validators.py rename to apps/backend/security/git_validators.py diff --git a/auto-claude/security/hooks.py b/apps/backend/security/hooks.py similarity index 100% rename from auto-claude/security/hooks.py rename to apps/backend/security/hooks.py diff --git a/auto-claude/security/main.py b/apps/backend/security/main.py similarity index 100% rename from auto-claude/security/main.py rename to apps/backend/security/main.py diff --git a/auto-claude/security/parser.py b/apps/backend/security/parser.py similarity index 100% rename from auto-claude/security/parser.py rename to apps/backend/security/parser.py diff --git a/auto-claude/security/process_validators.py b/apps/backend/security/process_validators.py similarity index 100% rename from auto-claude/security/process_validators.py rename to apps/backend/security/process_validators.py diff --git a/auto-claude/security/profile.py b/apps/backend/security/profile.py similarity index 100% rename from auto-claude/security/profile.py rename to apps/backend/security/profile.py diff --git a/auto-claude/security/scan_secrets.py b/apps/backend/security/scan_secrets.py similarity index 100% rename from auto-claude/security/scan_secrets.py rename to apps/backend/security/scan_secrets.py diff --git a/auto-claude/security/validation_models.py b/apps/backend/security/validation_models.py similarity index 100% rename from auto-claude/security/validation_models.py rename to apps/backend/security/validation_models.py diff --git a/auto-claude/security/validator.py b/apps/backend/security/validator.py similarity index 100% rename from auto-claude/security/validator.py rename to apps/backend/security/validator.py diff --git a/auto-claude/security/validator_registry.py b/apps/backend/security/validator_registry.py similarity index 100% rename from auto-claude/security/validator_registry.py rename to apps/backend/security/validator_registry.py diff --git a/auto-claude/security_scanner.py b/apps/backend/security_scanner.py similarity index 100% rename from auto-claude/security_scanner.py rename to apps/backend/security_scanner.py diff --git a/auto-claude/service_orchestrator.py b/apps/backend/service_orchestrator.py similarity index 100% rename from auto-claude/service_orchestrator.py rename to apps/backend/service_orchestrator.py diff --git a/auto-claude/services/__init__.py b/apps/backend/services/__init__.py similarity index 100% rename from auto-claude/services/__init__.py rename to apps/backend/services/__init__.py diff --git a/auto-claude/services/context.py b/apps/backend/services/context.py similarity index 100% rename from auto-claude/services/context.py rename to apps/backend/services/context.py diff --git a/auto-claude/services/orchestrator.py b/apps/backend/services/orchestrator.py similarity index 100% rename from auto-claude/services/orchestrator.py rename to apps/backend/services/orchestrator.py diff --git a/auto-claude/services/recovery.py b/apps/backend/services/recovery.py similarity index 100% rename from auto-claude/services/recovery.py rename to apps/backend/services/recovery.py diff --git a/auto-claude/spec/__init__.py b/apps/backend/spec/__init__.py similarity index 100% rename from auto-claude/spec/__init__.py rename to apps/backend/spec/__init__.py diff --git a/auto-claude/spec/compaction.py b/apps/backend/spec/compaction.py similarity index 100% rename from auto-claude/spec/compaction.py rename to apps/backend/spec/compaction.py diff --git a/auto-claude/spec/complexity.py b/apps/backend/spec/complexity.py similarity index 100% rename from auto-claude/spec/complexity.py rename to apps/backend/spec/complexity.py diff --git a/auto-claude/spec/context.py b/apps/backend/spec/context.py similarity index 100% rename from auto-claude/spec/context.py rename to apps/backend/spec/context.py diff --git a/auto-claude/spec/critique.py b/apps/backend/spec/critique.py similarity index 100% rename from auto-claude/spec/critique.py rename to apps/backend/spec/critique.py diff --git a/auto-claude/spec/discovery.py b/apps/backend/spec/discovery.py similarity index 100% rename from auto-claude/spec/discovery.py rename to apps/backend/spec/discovery.py diff --git a/auto-claude/spec/phases.py b/apps/backend/spec/phases.py similarity index 100% rename from auto-claude/spec/phases.py rename to apps/backend/spec/phases.py diff --git a/auto-claude/spec/phases/README.md b/apps/backend/spec/phases/README.md similarity index 100% rename from auto-claude/spec/phases/README.md rename to apps/backend/spec/phases/README.md diff --git a/auto-claude/spec/phases/__init__.py b/apps/backend/spec/phases/__init__.py similarity index 100% rename from auto-claude/spec/phases/__init__.py rename to apps/backend/spec/phases/__init__.py diff --git a/auto-claude/spec/phases/discovery_phases.py b/apps/backend/spec/phases/discovery_phases.py similarity index 100% rename from auto-claude/spec/phases/discovery_phases.py rename to apps/backend/spec/phases/discovery_phases.py diff --git a/auto-claude/spec/phases/executor.py b/apps/backend/spec/phases/executor.py similarity index 100% rename from auto-claude/spec/phases/executor.py rename to apps/backend/spec/phases/executor.py diff --git a/auto-claude/spec/phases/models.py b/apps/backend/spec/phases/models.py similarity index 100% rename from auto-claude/spec/phases/models.py rename to apps/backend/spec/phases/models.py diff --git a/auto-claude/spec/phases/planning_phases.py b/apps/backend/spec/phases/planning_phases.py similarity index 100% rename from auto-claude/spec/phases/planning_phases.py rename to apps/backend/spec/phases/planning_phases.py diff --git a/auto-claude/spec/phases/requirements_phases.py b/apps/backend/spec/phases/requirements_phases.py similarity index 100% rename from auto-claude/spec/phases/requirements_phases.py rename to apps/backend/spec/phases/requirements_phases.py diff --git a/auto-claude/spec/phases/spec_phases.py b/apps/backend/spec/phases/spec_phases.py similarity index 100% rename from auto-claude/spec/phases/spec_phases.py rename to apps/backend/spec/phases/spec_phases.py diff --git a/auto-claude/spec/phases/utils.py b/apps/backend/spec/phases/utils.py similarity index 100% rename from auto-claude/spec/phases/utils.py rename to apps/backend/spec/phases/utils.py diff --git a/auto-claude/spec/pipeline.py b/apps/backend/spec/pipeline.py similarity index 100% rename from auto-claude/spec/pipeline.py rename to apps/backend/spec/pipeline.py diff --git a/auto-claude/spec/pipeline/__init__.py b/apps/backend/spec/pipeline/__init__.py similarity index 100% rename from auto-claude/spec/pipeline/__init__.py rename to apps/backend/spec/pipeline/__init__.py diff --git a/auto-claude/spec/pipeline/agent_runner.py b/apps/backend/spec/pipeline/agent_runner.py similarity index 100% rename from auto-claude/spec/pipeline/agent_runner.py rename to apps/backend/spec/pipeline/agent_runner.py diff --git a/auto-claude/spec/pipeline/models.py b/apps/backend/spec/pipeline/models.py similarity index 100% rename from auto-claude/spec/pipeline/models.py rename to apps/backend/spec/pipeline/models.py diff --git a/auto-claude/spec/pipeline/orchestrator.py b/apps/backend/spec/pipeline/orchestrator.py similarity index 100% rename from auto-claude/spec/pipeline/orchestrator.py rename to apps/backend/spec/pipeline/orchestrator.py diff --git a/auto-claude/spec/requirements.py b/apps/backend/spec/requirements.py similarity index 100% rename from auto-claude/spec/requirements.py rename to apps/backend/spec/requirements.py diff --git a/auto-claude/spec/validate_pkg/README.md b/apps/backend/spec/validate_pkg/README.md similarity index 100% rename from auto-claude/spec/validate_pkg/README.md rename to apps/backend/spec/validate_pkg/README.md diff --git a/auto-claude/spec/validate_pkg/__init__.py b/apps/backend/spec/validate_pkg/__init__.py similarity index 100% rename from auto-claude/spec/validate_pkg/__init__.py rename to apps/backend/spec/validate_pkg/__init__.py diff --git a/auto-claude/spec/validate_pkg/auto_fix.py b/apps/backend/spec/validate_pkg/auto_fix.py similarity index 100% rename from auto-claude/spec/validate_pkg/auto_fix.py rename to apps/backend/spec/validate_pkg/auto_fix.py diff --git a/auto-claude/spec/validate_pkg/models.py b/apps/backend/spec/validate_pkg/models.py similarity index 100% rename from auto-claude/spec/validate_pkg/models.py rename to apps/backend/spec/validate_pkg/models.py diff --git a/auto-claude/spec/validate_pkg/schemas.py b/apps/backend/spec/validate_pkg/schemas.py similarity index 100% rename from auto-claude/spec/validate_pkg/schemas.py rename to apps/backend/spec/validate_pkg/schemas.py diff --git a/auto-claude/spec/validate_pkg/spec_validator.py b/apps/backend/spec/validate_pkg/spec_validator.py similarity index 100% rename from auto-claude/spec/validate_pkg/spec_validator.py rename to apps/backend/spec/validate_pkg/spec_validator.py diff --git a/auto-claude/spec/validate_pkg/validators/__init__.py b/apps/backend/spec/validate_pkg/validators/__init__.py similarity index 100% rename from auto-claude/spec/validate_pkg/validators/__init__.py rename to apps/backend/spec/validate_pkg/validators/__init__.py diff --git a/auto-claude/spec/validate_pkg/validators/context_validator.py b/apps/backend/spec/validate_pkg/validators/context_validator.py similarity index 100% rename from auto-claude/spec/validate_pkg/validators/context_validator.py rename to apps/backend/spec/validate_pkg/validators/context_validator.py diff --git a/auto-claude/spec/validate_pkg/validators/implementation_plan_validator.py b/apps/backend/spec/validate_pkg/validators/implementation_plan_validator.py similarity index 100% rename from auto-claude/spec/validate_pkg/validators/implementation_plan_validator.py rename to apps/backend/spec/validate_pkg/validators/implementation_plan_validator.py diff --git a/auto-claude/spec/validate_pkg/validators/prereqs_validator.py b/apps/backend/spec/validate_pkg/validators/prereqs_validator.py similarity index 100% rename from auto-claude/spec/validate_pkg/validators/prereqs_validator.py rename to apps/backend/spec/validate_pkg/validators/prereqs_validator.py diff --git a/auto-claude/spec/validate_pkg/validators/spec_document_validator.py b/apps/backend/spec/validate_pkg/validators/spec_document_validator.py similarity index 100% rename from auto-claude/spec/validate_pkg/validators/spec_document_validator.py rename to apps/backend/spec/validate_pkg/validators/spec_document_validator.py diff --git a/auto-claude/spec/validate_spec.py b/apps/backend/spec/validate_spec.py similarity index 100% rename from auto-claude/spec/validate_spec.py rename to apps/backend/spec/validate_spec.py diff --git a/auto-claude/spec/validation_strategy.py b/apps/backend/spec/validation_strategy.py similarity index 100% rename from auto-claude/spec/validation_strategy.py rename to apps/backend/spec/validation_strategy.py diff --git a/auto-claude/spec/validator.py b/apps/backend/spec/validator.py similarity index 100% rename from auto-claude/spec/validator.py rename to apps/backend/spec/validator.py diff --git a/auto-claude/spec/writer.py b/apps/backend/spec/writer.py similarity index 100% rename from auto-claude/spec/writer.py rename to apps/backend/spec/writer.py diff --git a/auto-claude/spec_contract.json b/apps/backend/spec_contract.json similarity index 100% rename from auto-claude/spec_contract.json rename to apps/backend/spec_contract.json diff --git a/auto-claude/task_logger/README.md b/apps/backend/task_logger/README.md similarity index 100% rename from auto-claude/task_logger/README.md rename to apps/backend/task_logger/README.md diff --git a/auto-claude/task_logger/__init__.py b/apps/backend/task_logger/__init__.py similarity index 100% rename from auto-claude/task_logger/__init__.py rename to apps/backend/task_logger/__init__.py diff --git a/auto-claude/task_logger/capture.py b/apps/backend/task_logger/capture.py similarity index 100% rename from auto-claude/task_logger/capture.py rename to apps/backend/task_logger/capture.py diff --git a/auto-claude/task_logger/logger.py b/apps/backend/task_logger/logger.py similarity index 100% rename from auto-claude/task_logger/logger.py rename to apps/backend/task_logger/logger.py diff --git a/auto-claude/task_logger/main.py b/apps/backend/task_logger/main.py similarity index 100% rename from auto-claude/task_logger/main.py rename to apps/backend/task_logger/main.py diff --git a/auto-claude/task_logger/models.py b/apps/backend/task_logger/models.py similarity index 100% rename from auto-claude/task_logger/models.py rename to apps/backend/task_logger/models.py diff --git a/auto-claude/task_logger/storage.py b/apps/backend/task_logger/storage.py similarity index 100% rename from auto-claude/task_logger/storage.py rename to apps/backend/task_logger/storage.py diff --git a/auto-claude/task_logger/streaming.py b/apps/backend/task_logger/streaming.py similarity index 100% rename from auto-claude/task_logger/streaming.py rename to apps/backend/task_logger/streaming.py diff --git a/auto-claude/task_logger/utils.py b/apps/backend/task_logger/utils.py similarity index 100% rename from auto-claude/task_logger/utils.py rename to apps/backend/task_logger/utils.py diff --git a/auto-claude/test_discovery.py b/apps/backend/test_discovery.py similarity index 100% rename from auto-claude/test_discovery.py rename to apps/backend/test_discovery.py diff --git a/auto-claude/ui/__init__.py b/apps/backend/ui/__init__.py similarity index 100% rename from auto-claude/ui/__init__.py rename to apps/backend/ui/__init__.py diff --git a/auto-claude/ui/boxes.py b/apps/backend/ui/boxes.py similarity index 100% rename from auto-claude/ui/boxes.py rename to apps/backend/ui/boxes.py diff --git a/auto-claude/ui/capabilities.py b/apps/backend/ui/capabilities.py similarity index 100% rename from auto-claude/ui/capabilities.py rename to apps/backend/ui/capabilities.py diff --git a/auto-claude/ui/colors.py b/apps/backend/ui/colors.py similarity index 100% rename from auto-claude/ui/colors.py rename to apps/backend/ui/colors.py diff --git a/auto-claude/ui/formatters.py b/apps/backend/ui/formatters.py similarity index 100% rename from auto-claude/ui/formatters.py rename to apps/backend/ui/formatters.py diff --git a/auto-claude/ui/icons.py b/apps/backend/ui/icons.py similarity index 100% rename from auto-claude/ui/icons.py rename to apps/backend/ui/icons.py diff --git a/auto-claude/ui/main.py b/apps/backend/ui/main.py similarity index 100% rename from auto-claude/ui/main.py rename to apps/backend/ui/main.py diff --git a/auto-claude/ui/menu.py b/apps/backend/ui/menu.py similarity index 100% rename from auto-claude/ui/menu.py rename to apps/backend/ui/menu.py diff --git a/auto-claude/ui/progress.py b/apps/backend/ui/progress.py similarity index 100% rename from auto-claude/ui/progress.py rename to apps/backend/ui/progress.py diff --git a/auto-claude/ui/spinner.py b/apps/backend/ui/spinner.py similarity index 100% rename from auto-claude/ui/spinner.py rename to apps/backend/ui/spinner.py diff --git a/auto-claude/ui/status.py b/apps/backend/ui/status.py similarity index 100% rename from auto-claude/ui/status.py rename to apps/backend/ui/status.py diff --git a/auto-claude/ui/statusline.py b/apps/backend/ui/statusline.py similarity index 100% rename from auto-claude/ui/statusline.py rename to apps/backend/ui/statusline.py diff --git a/auto-claude/validation_strategy.py b/apps/backend/validation_strategy.py similarity index 100% rename from auto-claude/validation_strategy.py rename to apps/backend/validation_strategy.py diff --git a/apps/backend/workspace.py b/apps/backend/workspace.py new file mode 100644 index 00000000..7aec54d2 --- /dev/null +++ b/apps/backend/workspace.py @@ -0,0 +1,72 @@ +""" +Workspace management module facade. + +Provides workspace setup and management utilities for isolated builds. +Re-exports from core.workspace for clean imports. +""" + +from core.workspace import ( + MergeLock, + MergeLockError, + ParallelMergeResult, + ParallelMergeTask, + WorkspaceChoice, + WorkspaceMode, + check_existing_build, + choose_workspace, + cleanup_all_worktrees, + copy_spec_to_worktree, + create_conflict_file_with_git, + discard_existing_build, + finalize_workspace, + get_changed_files_from_branch, + get_current_branch, + get_existing_build_worktree, + get_file_content_from_ref, + handle_workspace_choice, + has_uncommitted_changes, + is_binary_file, + is_process_running, + list_all_worktrees, + merge_existing_build, + print_conflict_info, + print_merge_success, + review_existing_build, + setup_workspace, + show_build_summary, + show_changed_files, + validate_merged_syntax, +) + +__all__ = [ + "MergeLock", + "MergeLockError", + "ParallelMergeResult", + "ParallelMergeTask", + "WorkspaceChoice", + "WorkspaceMode", + "check_existing_build", + "choose_workspace", + "cleanup_all_worktrees", + "copy_spec_to_worktree", + "create_conflict_file_with_git", + "discard_existing_build", + "finalize_workspace", + "get_changed_files_from_branch", + "get_current_branch", + "get_existing_build_worktree", + "get_file_content_from_ref", + "handle_workspace_choice", + "has_uncommitted_changes", + "is_binary_file", + "is_process_running", + "list_all_worktrees", + "merge_existing_build", + "print_conflict_info", + "print_merge_success", + "review_existing_build", + "setup_workspace", + "show_build_summary", + "show_changed_files", + "validate_merged_syntax", +] diff --git a/auto-claude/worktree.py b/apps/backend/worktree.py similarity index 77% rename from auto-claude/worktree.py rename to apps/backend/worktree.py index d8a030a1..bbd95476 100644 --- a/auto-claude/worktree.py +++ b/apps/backend/worktree.py @@ -19,20 +19,20 @@ import sys from pathlib import Path from types import ModuleType -# Ensure auto-claude is in sys.path -_auto_claude_dir = Path(__file__).parent -if str(_auto_claude_dir) not in sys.path: - sys.path.insert(0, str(_auto_claude_dir)) +# Ensure apps/backend is in sys.path +_backend_dir = Path(__file__).parent +if str(_backend_dir) not in sys.path: + sys.path.insert(0, str(_backend_dir)) # Create a minimal 'core' module if it doesn't exist (to avoid importing core/__init__.py) if "core" not in sys.modules: _core_module = ModuleType("core") - _core_module.__file__ = str(_auto_claude_dir / "core" / "__init__.py") - _core_module.__path__ = [str(_auto_claude_dir / "core")] + _core_module.__file__ = str(_backend_dir / "core" / "__init__.py") + _core_module.__path__ = [str(_backend_dir / "core")] sys.modules["core"] = _core_module # Now load core.worktree directly -_worktree_file = _auto_claude_dir / "core" / "worktree.py" +_worktree_file = _backend_dir / "core" / "worktree.py" _spec = importlib.util.spec_from_file_location("core.worktree", _worktree_file) _worktree_module = importlib.util.module_from_spec(_spec) sys.modules["core.worktree"] = _worktree_module diff --git a/auto-claude-ui/.env.example b/apps/frontend/.env.example similarity index 100% rename from auto-claude-ui/.env.example rename to apps/frontend/.env.example diff --git a/auto-claude-ui/.gitignore b/apps/frontend/.gitignore similarity index 73% rename from auto-claude-ui/.gitignore rename to apps/frontend/.gitignore index 52160aaa..e9729119 100644 --- a/auto-claude-ui/.gitignore +++ b/apps/frontend/.gitignore @@ -45,7 +45,15 @@ coverage/ *.temp .cache/ -# Package manager locks (keep one) -# package-lock.json -# yarn.lock -# pnpm-lock.yaml +# Package manager locks - using npm only +yarn.lock +pnpm-lock.yaml +bun.lock +bun.lockb + +# Backup files +*.backup + +# Test files in root +test-*.js +test-*.cjs diff --git a/apps/frontend/.husky/pre-commit b/apps/frontend/.husky/pre-commit new file mode 100644 index 00000000..b10ebb83 --- /dev/null +++ b/apps/frontend/.husky/pre-commit @@ -0,0 +1,32 @@ +#!/bin/sh + +echo "Running pre-commit checks..." + +# Run lint-staged (handles staged .ts/.tsx files) +npm exec lint-staged + +# Run TypeScript type check +echo "Running type check..." +npm run typecheck +if [ $? -ne 0 ]; then + echo "Type check failed. Please fix TypeScript errors before committing." + exit 1 +fi + +# Run linting +echo "Running lint..." +npm run lint +if [ $? -ne 0 ]; then + echo "Lint failed. Run 'npm run lint:fix' to auto-fix issues." + exit 1 +fi + +# Check for vulnerabilities +echo "Checking for vulnerabilities..." +npm audit --audit-level=high +if [ $? -ne 0 ]; then + echo "Security vulnerabilities found. Run 'npm audit fix' to resolve." + exit 1 +fi + +echo "All pre-commit checks passed!" diff --git a/apps/frontend/CONTRIBUTING.md b/apps/frontend/CONTRIBUTING.md new file mode 100644 index 00000000..30bf164a --- /dev/null +++ b/apps/frontend/CONTRIBUTING.md @@ -0,0 +1,166 @@ +# Contributing to Auto Claude UI + +Thank you for your interest in contributing! This document provides guidelines for contributing to the frontend application. + +## Prerequisites + +- **Node.js v24.12.0 LTS** - Download from https://nodejs.org +- **npm v10+** - Included with Node.js +- **Git** - For version control + +## Getting Started + +```bash +# Clone the repository +git clone https://github.com/AndyMik90/Auto-Claude.git +cd Auto-Claude/apps/frontend + +# Install dependencies +npm install + +# Start development server +npm run dev +``` + +## Code Style + +### Architecture Principles + +1. **Feature-based Organization**: Group related code in feature folders +2. **Single Responsibility**: Each file does one thing well +3. **DRY**: Extract common patterns into shared modules +4. **KISS**: Simple solutions over complex ones +5. **SOLID**: Follow object-oriented design principles + +### Feature Module Structure + +Each feature follows this structure: + +``` +features/[feature-name]/ +├── components/ # Feature-specific React components +├── hooks/ # Feature-specific hooks +├── store/ # Zustand store +└── index.ts # Public API exports +``` + +### File Naming + +| Type | Convention | Example | +|------|------------|---------| +| React Components | PascalCase | `TaskCard.tsx` | +| Hooks | camelCase with `use` | `useTaskStore.ts` | +| Stores | kebab-case | `task-store.ts` | +| Types | PascalCase | `Task.ts` | +| Constants | SCREAMING_SNAKE_CASE | `MAX_RETRIES` | + +### Import Order + +```typescript +// 1. External libraries +import { useState } from 'react'; +import { Settings2 } from 'lucide-react'; + +// 2. Shared components and utilities +import { Button } from '@components/button'; +import { cn } from '@lib/utils'; + +// 3. Feature imports +import { useTaskStore } from '../store/task-store'; + +// 4. Types (use 'import type') +import type { Task } from '@shared/types'; +``` + +### TypeScript Guidelines + +- **No implicit `any`**: Always type parameters and variables +- **Use `type` for objects**: Prefer `type` over `interface` +- **Export types separately**: Use `export type` for type-only exports + +```typescript +// Good +type TaskStatus = 'backlog' | 'in_progress' | 'done'; + +interface TaskCardProps { + task: Task; + onClick: () => void; +} + +// Bad +function processTask(data: any) { ... } +``` + +## Testing + +```bash +# Run unit tests +npm test + +# Watch mode +npm run test:watch + +# Coverage report +npm run test:coverage + +# E2E tests +npm run test:e2e +``` + +### Writing Tests + +```typescript +import { describe, it, expect, vi } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import { TaskCard } from './TaskCard'; + +describe('TaskCard', () => { + it('renders task title', () => { + const task = { id: '1', title: 'Test Task' }; + render(); + + expect(screen.getByText('Test Task')).toBeInTheDocument(); + }); +}); +``` + +## Before Submitting + +1. **Run linting**: + ```bash + npm run lint:fix + ``` + +2. **Check types**: + ```bash + npm run typecheck + ``` + +3. **Run tests**: + ```bash + npm test + ``` + +4. **Test the build**: + ```bash + npm run build + ``` + +## Pull Request Process + +1. Create a feature branch: `git checkout -b feature/my-feature` +2. Make your changes following the guidelines above +3. Commit with clear messages +4. Push and create a Pull Request +5. Address review feedback + +## Security + +- Never commit secrets, API keys, or tokens +- Use environment variables for sensitive data +- Validate all IPC data +- Use contextBridge for renderer-main communication + +## Questions? + +Open an issue or reach out to the maintainers. diff --git a/apps/frontend/README.md b/apps/frontend/README.md new file mode 100644 index 00000000..67812918 --- /dev/null +++ b/apps/frontend/README.md @@ -0,0 +1,221 @@ +# Auto Claude UI - Frontend + +A modern Electron + React desktop application for the Auto Claude autonomous coding framework. + +## Prerequisites + +### Node.js v24.12.0 LTS (Required) + +This project requires **Node.js v24.12.0 LTS** (Latest LTS version as of December 2024). + +**Download:** https://nodejs.org/en/download/ + +> **IMPORTANT:** When installing Node.js on Windows, make sure to check: +> - "Add to PATH" +> - "npm package manager" + +**Verify installation:** +```bash +node --version # Should output: v24.12.0 +npm --version # Should output: 11.x.x or higher +``` + +> **Note:** npm is included with Node.js. If `npm` is not found after installing Node.js, you need to reinstall Node.js properly. + +## Quick Start + +```bash +# Navigate to frontend directory +cd apps/frontend + +# Install dependencies (includes native module rebuild) +npm install + +# Start development server +npm run dev +``` + +## Security + +This project maintains **0 vulnerabilities**. Run `npm audit` to verify. + +```bash +npm audit +# Expected output: found 0 vulnerabilities +``` + +## Architecture + +This project follows a **feature-based architecture** for better maintainability and scalability. + +``` +src/ +├── main/ # Electron main process +│ ├── agent/ # Agent management +│ ├── changelog/ # Changelog generation +│ ├── claude-profile/ # Claude profile management +│ ├── insights/ # Code analysis +│ ├── ipc-handlers/ # IPC communication handlers +│ ├── terminal/ # PTY and terminal management +│ └── updater/ # App update service +│ +├── preload/ # Electron preload scripts +│ └── api/ # IPC API modules +│ +├── renderer/ # React frontend +│ ├── features/ # Feature modules (self-contained) +│ │ ├── tasks/ # Task management, kanban, creation +│ │ ├── terminals/ # Terminal emulation +│ │ ├── projects/ # Project management, file explorer +│ │ ├── settings/ # App and project settings +│ │ ├── roadmap/ # Roadmap generation +│ │ ├── ideation/ # AI-powered brainstorming +│ │ ├── insights/ # Code analysis +│ │ ├── changelog/ # Release management +│ │ ├── github/ # GitHub integration +│ │ ├── agents/ # Claude profile management +│ │ ├── worktrees/ # Git worktree management +│ │ └── onboarding/ # First-time setup wizard +│ │ +│ ├── shared/ # Shared resources +│ │ ├── components/ # Reusable UI components +│ │ ├── hooks/ # Shared React hooks +│ │ └── lib/ # Utilities and helpers +│ │ +│ └── hooks/ # App-level hooks +│ +└── shared/ # Shared between main/renderer + ├── types/ # TypeScript type definitions + ├── constants/ # Application constants + └── utils/ # Shared utilities +``` + +## Scripts + +| Command | Description | +|---------|-------------| +| `npm run dev` | Start development server with hot reload | +| `npm run build` | Build for production | +| `npm run package` | Build and package for current platform | +| `npm run package:win` | Package for Windows | +| `npm run package:mac` | Package for macOS | +| `npm run package:linux` | Package for Linux | +| `npm test` | Run unit tests | +| `npm run test:watch` | Run tests in watch mode | +| `npm run test:coverage` | Run tests with coverage | +| `npm run lint` | Check for lint errors | +| `npm run lint:fix` | Auto-fix lint errors | +| `npm run typecheck` | Type check TypeScript | +| `npm audit` | Check for security vulnerabilities | + +## Development Guidelines + +### Code Organization Principles + +1. **Feature-based Architecture**: Group related code by feature, not by type +2. **Single Responsibility**: Each component/hook/store does one thing well +3. **DRY (Don't Repeat Yourself)**: Extract reusable logic into shared modules +4. **KISS (Keep It Simple)**: Prefer simple solutions over complex ones +5. **SOLID Principles**: Apply object-oriented design principles + +### Naming Conventions + +| Type | Convention | Example | +|------|------------|---------| +| Components | PascalCase | `TaskCard.tsx` | +| Hooks | camelCase with `use` prefix | `useTaskStore.ts` | +| Stores | kebab-case with `-store` suffix | `task-store.ts` | +| Types | PascalCase | `Task`, `TaskStatus` | +| Constants | SCREAMING_SNAKE_CASE | `MAX_RETRIES` | + +### TypeScript Guidelines + +- **No implicit `any`**: Always type your variables and parameters +- **Use `type` for simple objects**: Prefer `type` over `interface` +- **Export types separately**: Use `export type` for type-only exports + +### Security Guidelines + +- **Never expose secrets**: API keys, tokens should stay in main process +- **Validate IPC data**: Always validate data coming through IPC +- **Use contextBridge**: Never expose Node.js APIs directly to renderer + +## Troubleshooting + +### npm not found + +If `npm` command is not recognized after installing Node.js: + +1. **Windows**: Reinstall Node.js from https://nodejs.org and ensure you check "Add to PATH" +2. **macOS/Linux**: Add to your shell profile: + ```bash + export PATH="/usr/local/bin:$PATH" + ``` +3. Restart your terminal + +### Native module errors + +If you get errors about native modules (node-pty, etc.): + +```bash +npm run rebuild +``` + +### Windows build tools required + +If electron-rebuild fails on Windows, install Visual Studio Build Tools: + +1. Download from https://visualstudio.microsoft.com/visual-cpp-build-tools/ +2. Select "Desktop development with C++" workload +3. Restart terminal and run `npm install` again + +## Git Hooks + +This project uses Husky for Git hooks that run automatically: + +### Pre-commit Hook + +Runs before each commit: +- **lint-staged**: Lints staged `.ts`/`.tsx` files +- **typecheck**: TypeScript type checking +- **lint**: ESLint checks +- **npm audit**: Security vulnerability check (high severity) + +### Commit Message Format + +We use [Conventional Commits](https://www.conventionalcommits.org/). Your commit messages must follow this format: + +``` +type(scope): description +``` + +**Valid types:** +| Type | Description | +|------|-------------| +| `feat` | A new feature | +| `fix` | A bug fix | +| `docs` | Documentation changes | +| `style` | Code style (formatting, semicolons, etc.) | +| `refactor` | Code refactoring (no feature/fix) | +| `perf` | Performance improvements | +| `test` | Adding or updating tests | +| `build` | Build system or dependencies | +| `ci` | CI/CD configuration | +| `chore` | Maintenance tasks | +| `revert` | Reverting a previous commit | + +**Examples:** +```bash +git commit -m "feat(tasks): add drag and drop support" +git commit -m "fix(terminal): resolve scroll position issue" +git commit -m "docs: update README with setup instructions" +git commit -m "chore: update dependencies" +``` + +## Package Manager + +This project uses **npm** (not pnpm or yarn). The lock files for other package managers are ignored. + +## License + +AGPL-3.0 diff --git a/auto-claude-ui/design.json b/apps/frontend/design.json similarity index 100% rename from auto-claude-ui/design.json rename to apps/frontend/design.json diff --git a/auto-claude-ui/e2e/electron-helper.ts b/apps/frontend/e2e/electron-helper.ts similarity index 100% rename from auto-claude-ui/e2e/electron-helper.ts rename to apps/frontend/e2e/electron-helper.ts diff --git a/auto-claude-ui/e2e/flows.e2e.ts b/apps/frontend/e2e/flows.e2e.ts similarity index 100% rename from auto-claude-ui/e2e/flows.e2e.ts rename to apps/frontend/e2e/flows.e2e.ts diff --git a/auto-claude-ui/e2e/playwright.config.ts b/apps/frontend/e2e/playwright.config.ts similarity index 100% rename from auto-claude-ui/e2e/playwright.config.ts rename to apps/frontend/e2e/playwright.config.ts diff --git a/auto-claude-ui/electron.vite.config.ts b/apps/frontend/electron.vite.config.ts similarity index 84% rename from auto-claude-ui/electron.vite.config.ts rename to apps/frontend/electron.vite.config.ts index 846638fc..5dcaaf9f 100644 --- a/auto-claude-ui/electron.vite.config.ts +++ b/apps/frontend/electron.vite.config.ts @@ -47,7 +47,11 @@ export default defineConfig({ resolve: { alias: { '@': resolve(__dirname, 'src/renderer'), - '@shared': resolve(__dirname, 'src/shared') + '@shared': resolve(__dirname, 'src/shared'), + '@features': resolve(__dirname, 'src/renderer/features'), + '@components': resolve(__dirname, 'src/renderer/shared/components'), + '@hooks': resolve(__dirname, 'src/renderer/shared/hooks'), + '@lib': resolve(__dirname, 'src/renderer/shared/lib') } }, server: { diff --git a/auto-claude-ui/eslint.config.mjs b/apps/frontend/eslint.config.mjs similarity index 82% rename from auto-claude-ui/eslint.config.mjs rename to apps/frontend/eslint.config.mjs index d90ae77f..908d7123 100644 --- a/auto-claude-ui/eslint.config.mjs +++ b/apps/frontend/eslint.config.mjs @@ -74,6 +74,24 @@ export default tseslint.config( } }, { - ignores: ['out/**', 'dist/**', '.eslintrc.cjs', 'eslint.config.mjs', 'node_modules/**'] + files: ['**/*.cjs'], + languageOptions: { + globals: { + ...globals.node, + module: 'readonly', + require: 'readonly', + __dirname: 'readonly', + process: 'readonly', + console: 'readonly' + }, + sourceType: 'commonjs' + }, + rules: { + '@typescript-eslint/no-require-imports': 'off', + 'no-undef': 'off' + } + }, + { + ignores: ['out/**', 'dist/**', '.eslintrc.cjs', 'eslint.config.mjs', 'node_modules/**', '**/*.cjs'] } ); diff --git a/auto-claude-ui/package-lock.json b/apps/frontend/package-lock.json similarity index 98% rename from auto-claude-ui/package-lock.json rename to apps/frontend/package-lock.json index 422a26cc..b3896dad 100644 --- a/auto-claude-ui/package-lock.json +++ b/apps/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "auto-claude-ui", - "version": "2.6.5", + "version": "2.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "auto-claude-ui", - "version": "2.6.5", + "version": "2.8.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { @@ -40,7 +40,6 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "electron-updater": "^6.6.2", - "kuzu": "^0.8.2", "lucide-react": "^0.560.0", "motion": "^12.23.26", "react": "^19.2.3", @@ -82,6 +81,10 @@ "typescript-eslint": "^8.49.0", "vite": "^7.2.7", "vitest": "^4.0.15" + }, + "engines": { + "node": ">=24.0.0", + "npm": ">=10.0.0" } }, "node_modules/@alloc/quick-lru": { @@ -149,6 +152,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -534,6 +538,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -557,6 +562,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -596,6 +602,7 @@ "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", "license": "MIT", + "peer": true, "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", @@ -990,7 +997,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", @@ -1012,7 +1018,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -4013,8 +4018,7 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -4201,6 +4205,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -4211,6 +4216,7 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -4302,6 +4308,7 @@ "integrity": "sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.49.0", "@typescript-eslint/types": "8.49.0", @@ -4701,7 +4708,8 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz", "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/7zip-bin": { "version": "5.2.0", @@ -4723,6 +4731,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4783,6 +4792,7 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4824,6 +4834,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4833,6 +4844,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -4929,26 +4941,6 @@ "node": ">=12.13.0" } }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "license": "ISC" - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4973,7 +4965,6 @@ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "dequal": "^2.0.3" } @@ -5179,6 +5170,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, "license": "MIT" }, "node_modules/at-least-node": { @@ -5244,17 +5236,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -5368,6 +5349,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -5565,6 +5547,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5718,6 +5701,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -5816,6 +5800,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -5858,50 +5843,11 @@ "node": ">=6" } }, - "node_modules/cmake-js": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-7.4.0.tgz", - "integrity": "sha512-Lw0JxEHrmk+qNj1n9W9d4IvkDdYTBn7l2BW6XmtLj7WPpIo2shvxUy+YokfjMxAAOELNonQwX3stkPhM5xSC2Q==", - "license": "MIT", - "dependencies": { - "axios": "^1.6.5", - "debug": "^4", - "fs-extra": "^11.2.0", - "memory-stream": "^1.0.0", - "node-api-headers": "^1.1.0", - "npmlog": "^6.0.2", - "rc": "^1.2.7", - "semver": "^7.5.4", - "tar": "^6.2.0", - "url-join": "^4.0.1", - "which": "^2.0.2", - "yargs": "^17.7.2" - }, - "bin": { - "cmake-js": "bin/cmake-js" - }, - "engines": { - "node": ">= 14.15.0" - } - }, - "node_modules/cmake-js/node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5914,17 +5860,9 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -5936,6 +5874,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -6049,12 +5988,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "license": "ISC" - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -6087,8 +6020,7 @@ "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -6271,15 +6203,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -6350,17 +6273,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT" - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -6437,6 +6355,7 @@ "integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "app-builder-lib": "26.0.12", "builder-util": "26.0.11", @@ -6494,8 +6413,7 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/dotenv": { "version": "16.6.1", @@ -6530,6 +6448,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -6570,6 +6489,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^22.7.7", @@ -6698,7 +6618,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", @@ -6719,7 +6638,6 @@ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -6735,7 +6653,6 @@ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "license": "MIT", - "peer": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -6746,7 +6663,6 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 4.0.0" } @@ -6772,6 +6688,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, "license": "MIT" }, "node_modules/encoding": { @@ -6925,6 +6842,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -6934,6 +6852,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -6978,6 +6897,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -6990,6 +6910,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -7086,6 +7007,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -7110,6 +7032,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -7575,26 +7498,6 @@ "dev": true, "license": "ISC" }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -7645,6 +7548,7 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -7716,6 +7620,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -7750,6 +7655,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7786,26 +7692,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/generator-function": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", @@ -7830,6 +7716,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -7852,6 +7739,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -7885,6 +7773,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -8038,6 +7927,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8134,6 +8024,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8146,6 +8037,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -8157,16 +8049,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "license": "ISC" - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -8485,12 +8372,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, "license": "ISC" }, "node_modules/inline-style-parser": { @@ -8736,6 +8618,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9055,6 +8938,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, "license": "ISC" }, "node_modules/iterator.prototype": { @@ -9144,6 +9028,7 @@ "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", @@ -9271,24 +9156,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/kuzu": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/kuzu/-/kuzu-0.8.2.tgz", - "integrity": "sha512-GdaDfutKf/MXZQYZwhpupnUJLODbLheplzNUWy0CgU4HW/Yk8AYij7K4/FP8G/zlNNvn8pNP/jj19bg0vCwcYw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "cmake-js": "^7.3.0", - "node-addon-api": "^6.0.0" - } - }, - "node_modules/kuzu/node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "license": "MIT" - }, "node_modules/lazy-val": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", @@ -10093,7 +9960,6 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -10216,6 +10082,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10503,15 +10370,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/memory-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz", - "integrity": "sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==", - "license": "MIT", - "dependencies": { - "readable-stream": "^3.4.0" - } - }, "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", @@ -11119,6 +10977,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -11128,6 +10987,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -11189,6 +11049,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11198,6 +11059,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -11280,12 +11142,14 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, "license": "ISC" }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, "license": "MIT", "dependencies": { "minipass": "^3.0.0", @@ -11299,12 +11163,14 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, "license": "ISC" }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -11430,12 +11296,6 @@ "license": "MIT", "optional": true }, - "node_modules/node-api-headers": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.7.0.tgz", - "integrity": "sha512-uJMGdkhVwu9+I3UsVvI3KW6ICAy/yDfsu5Br9rSnTtY3WpoaComXvKloiV5wtx0Md2rn0B9n29Ys2WMNwWxj9A==", - "license": "MIT" - }, "node_modules/node-api-version": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz", @@ -11482,22 +11342,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/nwsapi": { "version": "2.2.23", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", @@ -11939,6 +11783,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -12036,6 +11881,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -12072,7 +11918,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "commander": "^9.4.0" }, @@ -12090,7 +11935,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": "^12.20.0 || >=14" } @@ -12111,7 +11955,6 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -12127,7 +11970,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -12140,8 +11982,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/proc-log": { "version": "2.0.1", @@ -12206,12 +12047,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -12246,35 +12081,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react": { "version": "19.2.3", "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -12284,6 +12096,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -12431,6 +12244,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -12568,6 +12382,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12814,6 +12629,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -12944,12 +12760,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -13109,6 +12919,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, "license": "ISC" }, "node_modules/simple-update-notifier": { @@ -13298,6 +13109,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -13317,6 +13129,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -13459,6 +13272,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -13572,7 +13386,8 @@ "version": "4.1.18", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tapable": { "version": "2.3.0", @@ -13592,6 +13407,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, "license": "ISC", "dependencies": { "chownr": "^2.0.0", @@ -13609,6 +13425,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, "license": "ISC", "engines": { "node": ">=8" @@ -13618,6 +13435,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, "license": "ISC" }, "node_modules/temp": { @@ -13626,7 +13444,6 @@ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -13653,7 +13470,6 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -13675,7 +13491,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -13689,7 +13504,6 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -13704,7 +13518,6 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -14021,6 +13834,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -14242,12 +14056,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "license": "MIT" - }, "node_modules/use-callback-ref": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", @@ -14367,6 +14175,7 @@ "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -15087,6 +14896,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -15204,15 +15014,6 @@ "node": ">=8" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -15227,6 +15028,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -15319,6 +15121,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -15351,6 +15154,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -15369,6 +15173,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -15404,6 +15209,7 @@ "integrity": "sha512-Bd5fw9wlIhtqCCxotZgdTOMwGm1a0u75wARVEY9HMs1X17trvA/lMi4+MGK5EUfYkXVTbX8UDiDKW4OgzHVUZw==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/auto-claude-ui/package.json b/apps/frontend/package.json similarity index 90% rename from auto-claude-ui/package.json rename to apps/frontend/package.json index 73ea2fac..9c0d22c1 100644 --- a/auto-claude-ui/package.json +++ b/apps/frontend/package.json @@ -1,6 +1,7 @@ { "name": "auto-claude-ui", - "version": "2.7.1", + "version": "2.7.2", + "type": "module", "description": "Desktop UI for Auto Claude autonomous coding framework", "homepage": "https://github.com/AndyMik90/Auto-Claude", "repository": { @@ -13,14 +14,19 @@ "email": "119136210+AndyMik90@users.noreply.github.com" }, "license": "AGPL-3.0", + "engines": { + "node": ">=24.0.0", + "npm": ">=10.0.0" + }, "scripts": { - "postinstall": "node scripts/postinstall.js", + "postinstall": "node scripts/postinstall.cjs", "dev": "electron-vite dev", "dev:mcp": "electron-vite dev -- --remote-debugging-port=9222", "build": "electron-vite build", "start": "electron .", "start:mcp": "electron . --remote-debugging-port=9222", "preview": "electron-vite preview", + "rebuild": "electron-rebuild", "package": "electron-vite build && electron-builder", "package:mac": "electron-vite build && electron-builder --mac", "package:win": "electron-vite build && electron-builder --win", @@ -109,18 +115,9 @@ "vite": "^7.2.7", "vitest": "^4.0.15" }, - "pnpm": { - "overrides": { - "electron-builder-squirrel-windows": "^26.0.12", - "dmg-builder": "^26.0.12", - "node-pty": "npm:@lydell/node-pty@^1.1.0" - }, - "onlyBuiltDependencies": [ - "@lydell/node-pty", - "electron", - "electron-winstaller", - "esbuild" - ] + "overrides": { + "electron-builder-squirrel-windows": "^26.0.12", + "dmg-builder": "^26.0.12" }, "build": { "appId": "com.autoclaude.ui", @@ -151,7 +148,7 @@ "to": "icon.ico" }, { - "from": "../auto-claude", + "from": "../backend", "to": "auto-claude", "filter": [ "!**/.git", @@ -201,6 +198,5 @@ "*.{ts,tsx}": [ "eslint --fix" ] - }, - "packageManager": "pnpm@10.26.1+sha512.664074abc367d2c9324fdc18037097ce0a8f126034160f709928e9e9f95d98714347044e5c3164d65bd5da6c59c6be362b107546292a8eecb7999196e5ce58fa" + } } diff --git a/auto-claude-ui/postcss.config.js b/apps/frontend/postcss.config.cjs similarity index 100% rename from auto-claude-ui/postcss.config.js rename to apps/frontend/postcss.config.cjs diff --git a/auto-claude-ui/resources/entitlements.mac.plist b/apps/frontend/resources/entitlements.mac.plist similarity index 100% rename from auto-claude-ui/resources/entitlements.mac.plist rename to apps/frontend/resources/entitlements.mac.plist diff --git a/auto-claude-ui/resources/icon-256.png b/apps/frontend/resources/icon-256.png similarity index 100% rename from auto-claude-ui/resources/icon-256.png rename to apps/frontend/resources/icon-256.png diff --git a/auto-claude-ui/resources/icon.icns b/apps/frontend/resources/icon.icns similarity index 100% rename from auto-claude-ui/resources/icon.icns rename to apps/frontend/resources/icon.icns diff --git a/auto-claude-ui/resources/icon.ico b/apps/frontend/resources/icon.ico similarity index 100% rename from auto-claude-ui/resources/icon.ico rename to apps/frontend/resources/icon.ico diff --git a/auto-claude-ui/resources/icon.png b/apps/frontend/resources/icon.png similarity index 100% rename from auto-claude-ui/resources/icon.png rename to apps/frontend/resources/icon.png diff --git a/auto-claude-ui/scripts/download-prebuilds.js b/apps/frontend/scripts/download-prebuilds.cjs similarity index 100% rename from auto-claude-ui/scripts/download-prebuilds.js rename to apps/frontend/scripts/download-prebuilds.cjs diff --git a/auto-claude-ui/scripts/postinstall.js b/apps/frontend/scripts/postinstall.cjs similarity index 99% rename from auto-claude-ui/scripts/postinstall.js rename to apps/frontend/scripts/postinstall.cjs index b071cfd6..41a8ebe6 100644 --- a/auto-claude-ui/scripts/postinstall.js +++ b/apps/frontend/scripts/postinstall.cjs @@ -96,7 +96,7 @@ async function main() { try { // Dynamic import to handle case where the script doesn't exist yet - const { downloadPrebuilds } = require('./download-prebuilds.js'); + const { downloadPrebuilds } = require('./download-prebuilds.cjs'); const result = await downloadPrebuilds(); if (result.success) { diff --git a/auto-claude-ui/src/__mocks__/electron.ts b/apps/frontend/src/__mocks__/electron.ts similarity index 100% rename from auto-claude-ui/src/__mocks__/electron.ts rename to apps/frontend/src/__mocks__/electron.ts diff --git a/auto-claude-ui/src/__tests__/integration/file-watcher.test.ts b/apps/frontend/src/__tests__/integration/file-watcher.test.ts similarity index 100% rename from auto-claude-ui/src/__tests__/integration/file-watcher.test.ts rename to apps/frontend/src/__tests__/integration/file-watcher.test.ts diff --git a/auto-claude-ui/src/__tests__/integration/ipc-bridge.test.ts b/apps/frontend/src/__tests__/integration/ipc-bridge.test.ts similarity index 100% rename from auto-claude-ui/src/__tests__/integration/ipc-bridge.test.ts rename to apps/frontend/src/__tests__/integration/ipc-bridge.test.ts diff --git a/auto-claude-ui/src/__tests__/integration/subprocess-spawn.test.ts b/apps/frontend/src/__tests__/integration/subprocess-spawn.test.ts similarity index 100% rename from auto-claude-ui/src/__tests__/integration/subprocess-spawn.test.ts rename to apps/frontend/src/__tests__/integration/subprocess-spawn.test.ts diff --git a/auto-claude-ui/src/__tests__/setup.ts b/apps/frontend/src/__tests__/setup.ts similarity index 100% rename from auto-claude-ui/src/__tests__/setup.ts rename to apps/frontend/src/__tests__/setup.ts diff --git a/auto-claude-ui/src/main/__tests__/ipc-handlers.test.ts b/apps/frontend/src/main/__tests__/ipc-handlers.test.ts similarity index 100% rename from auto-claude-ui/src/main/__tests__/ipc-handlers.test.ts rename to apps/frontend/src/main/__tests__/ipc-handlers.test.ts diff --git a/auto-claude-ui/src/main/__tests__/project-store.test.ts b/apps/frontend/src/main/__tests__/project-store.test.ts similarity index 100% rename from auto-claude-ui/src/main/__tests__/project-store.test.ts rename to apps/frontend/src/main/__tests__/project-store.test.ts diff --git a/auto-claude-ui/src/main/__tests__/rate-limit-auto-recovery.test.ts b/apps/frontend/src/main/__tests__/rate-limit-auto-recovery.test.ts similarity index 100% rename from auto-claude-ui/src/main/__tests__/rate-limit-auto-recovery.test.ts rename to apps/frontend/src/main/__tests__/rate-limit-auto-recovery.test.ts diff --git a/auto-claude-ui/src/main/__tests__/rate-limit-detector.test.ts b/apps/frontend/src/main/__tests__/rate-limit-detector.test.ts similarity index 100% rename from auto-claude-ui/src/main/__tests__/rate-limit-detector.test.ts rename to apps/frontend/src/main/__tests__/rate-limit-detector.test.ts diff --git a/auto-claude-ui/src/main/agent-manager.ts b/apps/frontend/src/main/agent-manager.ts similarity index 100% rename from auto-claude-ui/src/main/agent-manager.ts rename to apps/frontend/src/main/agent-manager.ts diff --git a/auto-claude-ui/src/main/agent/agent-events.ts b/apps/frontend/src/main/agent/agent-events.ts similarity index 100% rename from auto-claude-ui/src/main/agent/agent-events.ts rename to apps/frontend/src/main/agent/agent-events.ts diff --git a/auto-claude-ui/src/main/agent/agent-manager.ts b/apps/frontend/src/main/agent/agent-manager.ts similarity index 100% rename from auto-claude-ui/src/main/agent/agent-manager.ts rename to apps/frontend/src/main/agent/agent-manager.ts diff --git a/auto-claude-ui/src/main/agent/agent-process.ts b/apps/frontend/src/main/agent/agent-process.ts similarity index 97% rename from auto-claude-ui/src/main/agent/agent-process.ts rename to apps/frontend/src/main/agent/agent-process.ts index c3351cc4..fb0edd63 100644 --- a/auto-claude-ui/src/main/agent/agent-process.ts +++ b/apps/frontend/src/main/agent/agent-process.ts @@ -58,11 +58,13 @@ export class AgentProcessManager { // Auto-detect from app location const possiblePaths = [ - // Dev mode: from dist/main -> ../../auto-claude (sibling to auto-claude-ui) - path.resolve(__dirname, '..', '..', '..', 'auto-claude'), - // Alternative: from app root - path.resolve(app.getAppPath(), '..', 'auto-claude'), - // If running from repo root + // Dev mode: from dist/main -> ../../backend (apps/frontend/out/main -> apps/backend) + path.resolve(__dirname, '..', '..', '..', 'backend'), + // Alternative: from app root -> apps/backend + path.resolve(app.getAppPath(), '..', 'backend'), + // If running from repo root with apps structure + path.resolve(process.cwd(), 'apps', 'backend'), + // Legacy: auto-claude folder (for backwards compatibility) path.resolve(process.cwd(), 'auto-claude') ]; diff --git a/auto-claude-ui/src/main/agent/agent-queue.ts b/apps/frontend/src/main/agent/agent-queue.ts similarity index 100% rename from auto-claude-ui/src/main/agent/agent-queue.ts rename to apps/frontend/src/main/agent/agent-queue.ts diff --git a/auto-claude-ui/src/main/agent/agent-state.ts b/apps/frontend/src/main/agent/agent-state.ts similarity index 100% rename from auto-claude-ui/src/main/agent/agent-state.ts rename to apps/frontend/src/main/agent/agent-state.ts diff --git a/auto-claude-ui/src/main/agent/index.ts b/apps/frontend/src/main/agent/index.ts similarity index 100% rename from auto-claude-ui/src/main/agent/index.ts rename to apps/frontend/src/main/agent/index.ts diff --git a/auto-claude-ui/src/main/agent/types.ts b/apps/frontend/src/main/agent/types.ts similarity index 100% rename from auto-claude-ui/src/main/agent/types.ts rename to apps/frontend/src/main/agent/types.ts diff --git a/auto-claude-ui/src/main/api-validation-service.ts b/apps/frontend/src/main/api-validation-service.ts similarity index 100% rename from auto-claude-ui/src/main/api-validation-service.ts rename to apps/frontend/src/main/api-validation-service.ts diff --git a/auto-claude-ui/src/main/app-updater.ts b/apps/frontend/src/main/app-updater.ts similarity index 100% rename from auto-claude-ui/src/main/app-updater.ts rename to apps/frontend/src/main/app-updater.ts diff --git a/auto-claude-ui/src/main/auto-claude-updater.ts b/apps/frontend/src/main/auto-claude-updater.ts similarity index 100% rename from auto-claude-ui/src/main/auto-claude-updater.ts rename to apps/frontend/src/main/auto-claude-updater.ts diff --git a/auto-claude-ui/src/main/changelog-service.ts b/apps/frontend/src/main/changelog-service.ts similarity index 100% rename from auto-claude-ui/src/main/changelog-service.ts rename to apps/frontend/src/main/changelog-service.ts diff --git a/auto-claude-ui/src/main/changelog/README.md b/apps/frontend/src/main/changelog/README.md similarity index 100% rename from auto-claude-ui/src/main/changelog/README.md rename to apps/frontend/src/main/changelog/README.md diff --git a/auto-claude-ui/src/main/changelog/changelog-service.ts b/apps/frontend/src/main/changelog/changelog-service.ts similarity index 100% rename from auto-claude-ui/src/main/changelog/changelog-service.ts rename to apps/frontend/src/main/changelog/changelog-service.ts diff --git a/auto-claude-ui/src/main/changelog/formatter.ts b/apps/frontend/src/main/changelog/formatter.ts similarity index 100% rename from auto-claude-ui/src/main/changelog/formatter.ts rename to apps/frontend/src/main/changelog/formatter.ts diff --git a/auto-claude-ui/src/main/changelog/generator.ts b/apps/frontend/src/main/changelog/generator.ts similarity index 100% rename from auto-claude-ui/src/main/changelog/generator.ts rename to apps/frontend/src/main/changelog/generator.ts diff --git a/auto-claude-ui/src/main/changelog/git-integration.ts b/apps/frontend/src/main/changelog/git-integration.ts similarity index 100% rename from auto-claude-ui/src/main/changelog/git-integration.ts rename to apps/frontend/src/main/changelog/git-integration.ts diff --git a/auto-claude-ui/src/main/changelog/index.ts b/apps/frontend/src/main/changelog/index.ts similarity index 100% rename from auto-claude-ui/src/main/changelog/index.ts rename to apps/frontend/src/main/changelog/index.ts diff --git a/auto-claude-ui/src/main/changelog/parser.ts b/apps/frontend/src/main/changelog/parser.ts similarity index 100% rename from auto-claude-ui/src/main/changelog/parser.ts rename to apps/frontend/src/main/changelog/parser.ts diff --git a/auto-claude-ui/src/main/changelog/types.ts b/apps/frontend/src/main/changelog/types.ts similarity index 100% rename from auto-claude-ui/src/main/changelog/types.ts rename to apps/frontend/src/main/changelog/types.ts diff --git a/auto-claude-ui/src/main/changelog/version-suggester.ts b/apps/frontend/src/main/changelog/version-suggester.ts similarity index 100% rename from auto-claude-ui/src/main/changelog/version-suggester.ts rename to apps/frontend/src/main/changelog/version-suggester.ts diff --git a/auto-claude-ui/src/main/claude-profile-manager.ts b/apps/frontend/src/main/claude-profile-manager.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile-manager.ts rename to apps/frontend/src/main/claude-profile-manager.ts diff --git a/auto-claude-ui/src/main/claude-profile/README.md b/apps/frontend/src/main/claude-profile/README.md similarity index 100% rename from auto-claude-ui/src/main/claude-profile/README.md rename to apps/frontend/src/main/claude-profile/README.md diff --git a/auto-claude-ui/src/main/claude-profile/index.ts b/apps/frontend/src/main/claude-profile/index.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/index.ts rename to apps/frontend/src/main/claude-profile/index.ts diff --git a/auto-claude-ui/src/main/claude-profile/profile-scorer.ts b/apps/frontend/src/main/claude-profile/profile-scorer.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/profile-scorer.ts rename to apps/frontend/src/main/claude-profile/profile-scorer.ts diff --git a/auto-claude-ui/src/main/claude-profile/profile-storage.ts b/apps/frontend/src/main/claude-profile/profile-storage.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/profile-storage.ts rename to apps/frontend/src/main/claude-profile/profile-storage.ts diff --git a/auto-claude-ui/src/main/claude-profile/profile-utils.ts b/apps/frontend/src/main/claude-profile/profile-utils.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/profile-utils.ts rename to apps/frontend/src/main/claude-profile/profile-utils.ts diff --git a/auto-claude-ui/src/main/claude-profile/rate-limit-manager.ts b/apps/frontend/src/main/claude-profile/rate-limit-manager.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/rate-limit-manager.ts rename to apps/frontend/src/main/claude-profile/rate-limit-manager.ts diff --git a/auto-claude-ui/src/main/claude-profile/token-encryption.ts b/apps/frontend/src/main/claude-profile/token-encryption.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/token-encryption.ts rename to apps/frontend/src/main/claude-profile/token-encryption.ts diff --git a/auto-claude-ui/src/main/claude-profile/types.ts b/apps/frontend/src/main/claude-profile/types.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/types.ts rename to apps/frontend/src/main/claude-profile/types.ts diff --git a/auto-claude-ui/src/main/claude-profile/usage-monitor.ts b/apps/frontend/src/main/claude-profile/usage-monitor.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/usage-monitor.ts rename to apps/frontend/src/main/claude-profile/usage-monitor.ts diff --git a/auto-claude-ui/src/main/claude-profile/usage-parser.ts b/apps/frontend/src/main/claude-profile/usage-parser.ts similarity index 100% rename from auto-claude-ui/src/main/claude-profile/usage-parser.ts rename to apps/frontend/src/main/claude-profile/usage-parser.ts diff --git a/auto-claude-ui/src/main/file-watcher.ts b/apps/frontend/src/main/file-watcher.ts similarity index 100% rename from auto-claude-ui/src/main/file-watcher.ts rename to apps/frontend/src/main/file-watcher.ts diff --git a/auto-claude-ui/src/main/index.ts b/apps/frontend/src/main/index.ts similarity index 99% rename from auto-claude-ui/src/main/index.ts rename to apps/frontend/src/main/index.ts index 2ba7f6d5..11cb39b4 100644 --- a/auto-claude-ui/src/main/index.ts +++ b/apps/frontend/src/main/index.ts @@ -49,7 +49,7 @@ function createWindow(): void { trafficLightPosition: { x: 15, y: 10 }, icon: getIconPath(), webPreferences: { - preload: join(__dirname, '../preload/index.js'), + preload: join(__dirname, '../preload/index.mjs'), sandbox: false, contextIsolation: true, nodeIntegration: false, diff --git a/auto-claude-ui/src/main/insights-service.ts b/apps/frontend/src/main/insights-service.ts similarity index 100% rename from auto-claude-ui/src/main/insights-service.ts rename to apps/frontend/src/main/insights-service.ts diff --git a/auto-claude-ui/src/main/insights/README.md b/apps/frontend/src/main/insights/README.md similarity index 100% rename from auto-claude-ui/src/main/insights/README.md rename to apps/frontend/src/main/insights/README.md diff --git a/auto-claude-ui/src/main/insights/REFACTORING_NOTES.md b/apps/frontend/src/main/insights/REFACTORING_NOTES.md similarity index 100% rename from auto-claude-ui/src/main/insights/REFACTORING_NOTES.md rename to apps/frontend/src/main/insights/REFACTORING_NOTES.md diff --git a/auto-claude-ui/src/main/insights/config.ts b/apps/frontend/src/main/insights/config.ts similarity index 100% rename from auto-claude-ui/src/main/insights/config.ts rename to apps/frontend/src/main/insights/config.ts diff --git a/auto-claude-ui/src/main/insights/index.ts b/apps/frontend/src/main/insights/index.ts similarity index 100% rename from auto-claude-ui/src/main/insights/index.ts rename to apps/frontend/src/main/insights/index.ts diff --git a/auto-claude-ui/src/main/insights/insights-executor.ts b/apps/frontend/src/main/insights/insights-executor.ts similarity index 100% rename from auto-claude-ui/src/main/insights/insights-executor.ts rename to apps/frontend/src/main/insights/insights-executor.ts diff --git a/auto-claude-ui/src/main/insights/paths.ts b/apps/frontend/src/main/insights/paths.ts similarity index 100% rename from auto-claude-ui/src/main/insights/paths.ts rename to apps/frontend/src/main/insights/paths.ts diff --git a/auto-claude-ui/src/main/insights/session-manager.ts b/apps/frontend/src/main/insights/session-manager.ts similarity index 100% rename from auto-claude-ui/src/main/insights/session-manager.ts rename to apps/frontend/src/main/insights/session-manager.ts diff --git a/auto-claude-ui/src/main/insights/session-storage.ts b/apps/frontend/src/main/insights/session-storage.ts similarity index 100% rename from auto-claude-ui/src/main/insights/session-storage.ts rename to apps/frontend/src/main/insights/session-storage.ts diff --git a/auto-claude-ui/src/main/integrations/index.ts b/apps/frontend/src/main/integrations/index.ts similarity index 100% rename from auto-claude-ui/src/main/integrations/index.ts rename to apps/frontend/src/main/integrations/index.ts diff --git a/auto-claude-ui/src/main/integrations/types.ts b/apps/frontend/src/main/integrations/types.ts similarity index 100% rename from auto-claude-ui/src/main/integrations/types.ts rename to apps/frontend/src/main/integrations/types.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/README.md b/apps/frontend/src/main/ipc-handlers/README.md similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/README.md rename to apps/frontend/src/main/ipc-handlers/README.md diff --git a/auto-claude-ui/src/main/ipc-handlers/agent-events-handlers.ts b/apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/agent-events-handlers.ts rename to apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/app-update-handlers.ts b/apps/frontend/src/main/ipc-handlers/app-update-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/app-update-handlers.ts rename to apps/frontend/src/main/ipc-handlers/app-update-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/autobuild-source-handlers.ts b/apps/frontend/src/main/ipc-handlers/autobuild-source-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/autobuild-source-handlers.ts rename to apps/frontend/src/main/ipc-handlers/autobuild-source-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/changelog-handlers.ts b/apps/frontend/src/main/ipc-handlers/changelog-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/changelog-handlers.ts rename to apps/frontend/src/main/ipc-handlers/changelog-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/changelog-handlers.ts.bk b/apps/frontend/src/main/ipc-handlers/changelog-handlers.ts.bk similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/changelog-handlers.ts.bk rename to apps/frontend/src/main/ipc-handlers/changelog-handlers.ts.bk diff --git a/auto-claude-ui/src/main/ipc-handlers/context-handlers.ts b/apps/frontend/src/main/ipc-handlers/context-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/context-handlers.ts rename to apps/frontend/src/main/ipc-handlers/context-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/context/README.md b/apps/frontend/src/main/ipc-handlers/context/README.md similarity index 89% rename from auto-claude-ui/src/main/ipc-handlers/context/README.md rename to apps/frontend/src/main/ipc-handlers/context/README.md index 0fc2269d..19de7f4a 100644 --- a/auto-claude-ui/src/main/ipc-handlers/context/README.md +++ b/apps/frontend/src/main/ipc-handlers/context/README.md @@ -1,6 +1,6 @@ # Context Handlers Module -This directory contains the refactored context-related IPC handlers for the Auto Claude UI application. The handlers manage project context, memory systems (both file-based and Graphiti/FalkorDB), and project index operations. +This directory contains the refactored context-related IPC handlers for the Auto Claude UI application. The handlers manage project context, memory systems (both file-based and Graphiti/LadybugDB), and project index operations. ## Architecture @@ -18,12 +18,12 @@ Shared utility functions for environment configuration and parsing. - `loadGlobalSettings()` - Load global application settings - `isGraphitiEnabled(projectEnvVars)` - Check if Graphiti memory system is enabled - `hasOpenAIKey(projectEnvVars, globalSettings)` - Check if OpenAI API key is available -- `getGraphitiConnectionDetails(projectEnvVars)` - Get FalkorDB connection configuration +- `getGraphitiConnectionDetails(projectEnvVars)` - Get LadybugDB connection configuration **Types:** - `EnvironmentVars` - Environment variable dictionary - `GlobalSettings` - Global application settings -- `GraphitiConnectionDetails` - FalkorDB connection details +- `GraphitiConnectionDetails` - LadybugDB connection details #### `memory-status-handlers.ts` (130 lines) Handlers for checking Graphiti/memory system configuration status. @@ -37,7 +37,7 @@ Handlers for checking Graphiti/memory system configuration status. - `CONTEXT_MEMORY_STATUS` - Get memory system status #### `memory-data-handlers.ts` (242 lines) -Handlers for retrieving and searching memories (both file-based and FalkorDB). +Handlers for retrieving and searching memories (both file-based and LadybugDB). **Exports:** - `loadFileBasedMemories(specsDir, limit)` - Load memories from spec files @@ -45,11 +45,11 @@ Handlers for retrieving and searching memories (both file-based and FalkorDB). - `registerMemoryDataHandlers(getMainWindow)` - Register IPC handlers **IPC Channels:** -- `CONTEXT_GET_MEMORIES` - Get recent memories (with FalkorDB fallback) +- `CONTEXT_GET_MEMORIES` - Get recent memories (with LadybugDB fallback) - `CONTEXT_SEARCH_MEMORIES` - Search memories by query **Features:** -- Dual-source memory loading (FalkorDB primary, file-based fallback) +- Dual-source memory loading (LadybugDB primary, file-based fallback) - Session insights extraction from spec directories - Codebase map integration - Semantic search support (when Graphiti is available) @@ -103,7 +103,7 @@ context/index.ts (aggregator) ↓ ├── utils.ts (no dependencies, pure utilities) ├── memory-status-handlers.ts (depends on: utils) - ├── memory-data-handlers.ts (depends on: utils, falkordb-service) + ├── memory-data-handlers.ts (depends on: utils, ladybug-service) └── project-context-handlers.ts (depends on: utils, memory-status-handlers, memory-data-handlers) ``` @@ -147,12 +147,12 @@ test('buildMemoryStatus returns correct status', () => { - Add TypeScript interface documentation for all data structures - Implement caching layer for frequently accessed context data - Add telemetry for memory system performance -- Support additional memory providers beyond FalkorDB +- Support additional memory providers beyond LadybugDB - Implement memory compression for large session insights ## Related Documentation - [Project Memory System](../../../../auto-claude/memory.py) - [Graphiti Memory Integration](../../../../auto-claude/graphiti_memory.py) -- [FalkorDB Service](../../falkordb-service.ts) +- [LadybugDB Integration](../../ladybug-service.ts) - [IPC Channels](../../../shared/constants.ts) diff --git a/auto-claude-ui/src/main/ipc-handlers/context/index.ts b/apps/frontend/src/main/ipc-handlers/context/index.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/context/index.ts rename to apps/frontend/src/main/ipc-handlers/context/index.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/context/memory-data-handlers.ts b/apps/frontend/src/main/ipc-handlers/context/memory-data-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/context/memory-data-handlers.ts rename to apps/frontend/src/main/ipc-handlers/context/memory-data-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/context/memory-status-handlers.ts b/apps/frontend/src/main/ipc-handlers/context/memory-status-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/context/memory-status-handlers.ts rename to apps/frontend/src/main/ipc-handlers/context/memory-status-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/context/project-context-handlers.ts b/apps/frontend/src/main/ipc-handlers/context/project-context-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/context/project-context-handlers.ts rename to apps/frontend/src/main/ipc-handlers/context/project-context-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/context/utils.ts b/apps/frontend/src/main/ipc-handlers/context/utils.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/context/utils.ts rename to apps/frontend/src/main/ipc-handlers/context/utils.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/env-handlers.ts b/apps/frontend/src/main/ipc-handlers/env-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/env-handlers.ts rename to apps/frontend/src/main/ipc-handlers/env-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/file-handlers.ts b/apps/frontend/src/main/ipc-handlers/file-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/file-handlers.ts rename to apps/frontend/src/main/ipc-handlers/file-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github-handlers.ts b/apps/frontend/src/main/ipc-handlers/github-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github-handlers.ts rename to apps/frontend/src/main/ipc-handlers/github-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/ARCHITECTURE.md b/apps/frontend/src/main/ipc-handlers/github/ARCHITECTURE.md similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/ARCHITECTURE.md rename to apps/frontend/src/main/ipc-handlers/github/ARCHITECTURE.md diff --git a/auto-claude-ui/src/main/ipc-handlers/github/README.md b/apps/frontend/src/main/ipc-handlers/github/README.md similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/README.md rename to apps/frontend/src/main/ipc-handlers/github/README.md diff --git a/auto-claude-ui/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts b/apps/frontend/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts rename to apps/frontend/src/main/ipc-handlers/github/__tests__/oauth-handlers.spec.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/import-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/import-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/import-handlers.ts rename to apps/frontend/src/main/ipc-handlers/github/import-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/index.ts b/apps/frontend/src/main/ipc-handlers/github/index.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/index.ts rename to apps/frontend/src/main/ipc-handlers/github/index.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/investigation-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/investigation-handlers.ts rename to apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/issue-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/issue-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/issue-handlers.ts rename to apps/frontend/src/main/ipc-handlers/github/issue-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/oauth-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/oauth-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/oauth-handlers.ts rename to apps/frontend/src/main/ipc-handlers/github/oauth-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/release-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/release-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/release-handlers.ts rename to apps/frontend/src/main/ipc-handlers/github/release-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/repository-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/repository-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/repository-handlers.ts rename to apps/frontend/src/main/ipc-handlers/github/repository-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/spec-utils.ts b/apps/frontend/src/main/ipc-handlers/github/spec-utils.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/spec-utils.ts rename to apps/frontend/src/main/ipc-handlers/github/spec-utils.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/types.ts b/apps/frontend/src/main/ipc-handlers/github/types.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/types.ts rename to apps/frontend/src/main/ipc-handlers/github/types.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/github/utils.ts b/apps/frontend/src/main/ipc-handlers/github/utils.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/github/utils.ts rename to apps/frontend/src/main/ipc-handlers/github/utils.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation-handlers.ts b/apps/frontend/src/main/ipc-handlers/ideation-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation-handlers.ts rename to apps/frontend/src/main/ipc-handlers/ideation-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/file-utils.ts b/apps/frontend/src/main/ipc-handlers/ideation/file-utils.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation/file-utils.ts rename to apps/frontend/src/main/ipc-handlers/ideation/file-utils.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/generation-handlers.ts b/apps/frontend/src/main/ipc-handlers/ideation/generation-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation/generation-handlers.ts rename to apps/frontend/src/main/ipc-handlers/ideation/generation-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/idea-manager.ts b/apps/frontend/src/main/ipc-handlers/ideation/idea-manager.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation/idea-manager.ts rename to apps/frontend/src/main/ipc-handlers/ideation/idea-manager.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/index.ts b/apps/frontend/src/main/ipc-handlers/ideation/index.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation/index.ts rename to apps/frontend/src/main/ipc-handlers/ideation/index.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/session-manager.ts b/apps/frontend/src/main/ipc-handlers/ideation/session-manager.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation/session-manager.ts rename to apps/frontend/src/main/ipc-handlers/ideation/session-manager.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/task-converter.ts b/apps/frontend/src/main/ipc-handlers/ideation/task-converter.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation/task-converter.ts rename to apps/frontend/src/main/ipc-handlers/ideation/task-converter.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/transformers.ts b/apps/frontend/src/main/ipc-handlers/ideation/transformers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation/transformers.ts rename to apps/frontend/src/main/ipc-handlers/ideation/transformers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/ideation/types.ts b/apps/frontend/src/main/ipc-handlers/ideation/types.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/ideation/types.ts rename to apps/frontend/src/main/ipc-handlers/ideation/types.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/index.ts b/apps/frontend/src/main/ipc-handlers/index.ts similarity index 97% rename from auto-claude-ui/src/main/ipc-handlers/index.ts rename to apps/frontend/src/main/ipc-handlers/index.ts index fbb2017f..c79971bb 100644 --- a/auto-claude-ui/src/main/ipc-handlers/index.ts +++ b/apps/frontend/src/main/ipc-handlers/index.ts @@ -26,7 +26,7 @@ import { registerAutobuildSourceHandlers } from './autobuild-source-handlers'; import { registerIdeationHandlers } from './ideation-handlers'; import { registerChangelogHandlers } from './changelog-handlers'; import { registerInsightsHandlers } from './insights-handlers'; -import { registerDockerHandlers } from './docker-handlers'; +import { registerMemoryHandlers } from './memory-handlers'; import { registerAppUpdateHandlers } from './app-update-handlers'; import { notificationService } from '../notification-service'; @@ -93,7 +93,7 @@ export function setupIpcHandlers( registerInsightsHandlers(getMainWindow); // Memory & infrastructure handlers (for Graphiti/LadybugDB) - registerDockerHandlers(); + registerMemoryHandlers(); // App auto-update handlers registerAppUpdateHandlers(); @@ -118,6 +118,6 @@ export { registerIdeationHandlers, registerChangelogHandlers, registerInsightsHandlers, - registerDockerHandlers, + registerMemoryHandlers, registerAppUpdateHandlers }; diff --git a/auto-claude-ui/src/main/ipc-handlers/insights-handlers.ts b/apps/frontend/src/main/ipc-handlers/insights-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/insights-handlers.ts rename to apps/frontend/src/main/ipc-handlers/insights-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/linear-handlers.ts b/apps/frontend/src/main/ipc-handlers/linear-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/linear-handlers.ts rename to apps/frontend/src/main/ipc-handlers/linear-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/memory-handlers.ts b/apps/frontend/src/main/ipc-handlers/memory-handlers.ts similarity index 98% rename from auto-claude-ui/src/main/ipc-handlers/memory-handlers.ts rename to apps/frontend/src/main/ipc-handlers/memory-handlers.ts index 344e4c65..b155b38d 100644 --- a/auto-claude-ui/src/main/ipc-handlers/memory-handlers.ts +++ b/apps/frontend/src/main/ipc-handlers/memory-handlers.ts @@ -79,9 +79,12 @@ async function executeOllamaDetector( // Find the ollama_model_detector.py script const possiblePaths = [ + // Development paths + path.resolve(__dirname, '..', '..', '..', '..', 'backend', 'ollama_model_detector.py'), + path.resolve(process.cwd(), 'apps', 'backend', 'ollama_model_detector.py'), + // Legacy paths (for backwards compatibility) path.resolve(__dirname, '..', '..', '..', 'auto-claude', 'ollama_model_detector.py'), path.resolve(process.cwd(), 'auto-claude', 'ollama_model_detector.py'), - path.resolve(process.cwd(), '..', 'auto-claude', 'ollama_model_detector.py'), ]; let scriptPath: string | null = null; diff --git a/auto-claude-ui/src/main/ipc-handlers/project-handlers.ts b/apps/frontend/src/main/ipc-handlers/project-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/project-handlers.ts rename to apps/frontend/src/main/ipc-handlers/project-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/roadmap-handlers.ts b/apps/frontend/src/main/ipc-handlers/roadmap-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/roadmap-handlers.ts rename to apps/frontend/src/main/ipc-handlers/roadmap-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/context-roadmap-section.txt b/apps/frontend/src/main/ipc-handlers/sections/context-roadmap-section.txt similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/sections/context-roadmap-section.txt rename to apps/frontend/src/main/ipc-handlers/sections/context-roadmap-section.txt diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/context_extracted.txt b/apps/frontend/src/main/ipc-handlers/sections/context_extracted.txt similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/sections/context_extracted.txt rename to apps/frontend/src/main/ipc-handlers/sections/context_extracted.txt diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/ideation-insights-section.txt b/apps/frontend/src/main/ipc-handlers/sections/ideation-insights-section.txt similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/sections/ideation-insights-section.txt rename to apps/frontend/src/main/ipc-handlers/sections/ideation-insights-section.txt diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/integration-section.txt b/apps/frontend/src/main/ipc-handlers/sections/integration-section.txt similarity index 99% rename from auto-claude-ui/src/main/ipc-handlers/sections/integration-section.txt rename to apps/frontend/src/main/ipc-handlers/sections/integration-section.txt index f137af7f..5432d011 100644 --- a/auto-claude-ui/src/main/ipc-handlers/sections/integration-section.txt +++ b/apps/frontend/src/main/ipc-handlers/sections/integration-section.txt @@ -121,7 +121,7 @@ ${existingVars['GITHUB_AUTO_SYNC'] !== undefined ? `GITHUB_AUTO_SYNC=${existingV ${existingVars['ENABLE_FANCY_UI'] !== undefined ? `ENABLE_FANCY_UI=${existingVars['ENABLE_FANCY_UI']}` : '# ENABLE_FANCY_UI=true'} # ============================================================================= -# GRAPHITI MEMORY INTEGRATION (OPTIONAL) +# GRAPHITI MEMORY INTEGRATION (REQUIRED) # ============================================================================= ${existingVars['GRAPHITI_ENABLED'] ? `GRAPHITI_ENABLED=${existingVars['GRAPHITI_ENABLED']}` : '# GRAPHITI_ENABLED=false'} ${existingVars['OPENAI_API_KEY'] ? `OPENAI_API_KEY=${existingVars['OPENAI_API_KEY']}` : '# OPENAI_API_KEY='} diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/roadmap_extracted.txt b/apps/frontend/src/main/ipc-handlers/sections/roadmap_extracted.txt similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/sections/roadmap_extracted.txt rename to apps/frontend/src/main/ipc-handlers/sections/roadmap_extracted.txt diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/task-section.txt b/apps/frontend/src/main/ipc-handlers/sections/task-section.txt similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/sections/task-section.txt rename to apps/frontend/src/main/ipc-handlers/sections/task-section.txt diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/task_extracted.txt b/apps/frontend/src/main/ipc-handlers/sections/task_extracted.txt similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/sections/task_extracted.txt rename to apps/frontend/src/main/ipc-handlers/sections/task_extracted.txt diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/terminal-section.txt b/apps/frontend/src/main/ipc-handlers/sections/terminal-section.txt similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/sections/terminal-section.txt rename to apps/frontend/src/main/ipc-handlers/sections/terminal-section.txt diff --git a/auto-claude-ui/src/main/ipc-handlers/sections/terminal_extracted.txt b/apps/frontend/src/main/ipc-handlers/sections/terminal_extracted.txt similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/sections/terminal_extracted.txt rename to apps/frontend/src/main/ipc-handlers/sections/terminal_extracted.txt diff --git a/auto-claude-ui/src/main/ipc-handlers/settings-handlers.ts b/apps/frontend/src/main/ipc-handlers/settings-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/settings-handlers.ts rename to apps/frontend/src/main/ipc-handlers/settings-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/task-handlers.ts b/apps/frontend/src/main/ipc-handlers/task-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task-handlers.ts rename to apps/frontend/src/main/ipc-handlers/task-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/task/README.md b/apps/frontend/src/main/ipc-handlers/task/README.md similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/README.md rename to apps/frontend/src/main/ipc-handlers/task/README.md diff --git a/auto-claude-ui/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md b/apps/frontend/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md rename to apps/frontend/src/main/ipc-handlers/task/REFACTORING_SUMMARY.md diff --git a/auto-claude-ui/src/main/ipc-handlers/task/archive-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/archive-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/archive-handlers.ts rename to apps/frontend/src/main/ipc-handlers/task/archive-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/task/crud-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/crud-handlers.ts rename to apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/task/execution-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/execution-handlers.ts rename to apps/frontend/src/main/ipc-handlers/task/execution-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/task/index.ts b/apps/frontend/src/main/ipc-handlers/task/index.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/index.ts rename to apps/frontend/src/main/ipc-handlers/task/index.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/task/logs-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/logs-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/logs-handlers.ts rename to apps/frontend/src/main/ipc-handlers/task/logs-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/task/shared.ts b/apps/frontend/src/main/ipc-handlers/task/shared.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/shared.ts rename to apps/frontend/src/main/ipc-handlers/task/shared.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/task/worktree-handlers.ts b/apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/task/worktree-handlers.ts rename to apps/frontend/src/main/ipc-handlers/task/worktree-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/terminal-handlers.ts b/apps/frontend/src/main/ipc-handlers/terminal-handlers.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/terminal-handlers.ts rename to apps/frontend/src/main/ipc-handlers/terminal-handlers.ts diff --git a/auto-claude-ui/src/main/ipc-handlers/utils.ts b/apps/frontend/src/main/ipc-handlers/utils.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-handlers/utils.ts rename to apps/frontend/src/main/ipc-handlers/utils.ts diff --git a/auto-claude-ui/src/main/ipc-setup.ts b/apps/frontend/src/main/ipc-setup.ts similarity index 100% rename from auto-claude-ui/src/main/ipc-setup.ts rename to apps/frontend/src/main/ipc-setup.ts diff --git a/auto-claude-ui/src/main/log-service.ts b/apps/frontend/src/main/log-service.ts similarity index 100% rename from auto-claude-ui/src/main/log-service.ts rename to apps/frontend/src/main/log-service.ts diff --git a/auto-claude-ui/src/main/memory-service.ts b/apps/frontend/src/main/memory-service.ts similarity index 100% rename from auto-claude-ui/src/main/memory-service.ts rename to apps/frontend/src/main/memory-service.ts diff --git a/auto-claude-ui/src/main/notification-service.ts b/apps/frontend/src/main/notification-service.ts similarity index 100% rename from auto-claude-ui/src/main/notification-service.ts rename to apps/frontend/src/main/notification-service.ts diff --git a/auto-claude-ui/src/main/project-initializer.ts b/apps/frontend/src/main/project-initializer.ts similarity index 100% rename from auto-claude-ui/src/main/project-initializer.ts rename to apps/frontend/src/main/project-initializer.ts diff --git a/auto-claude-ui/src/main/project-store.ts b/apps/frontend/src/main/project-store.ts similarity index 100% rename from auto-claude-ui/src/main/project-store.ts rename to apps/frontend/src/main/project-store.ts diff --git a/auto-claude-ui/src/main/python-detector.ts b/apps/frontend/src/main/python-detector.ts similarity index 100% rename from auto-claude-ui/src/main/python-detector.ts rename to apps/frontend/src/main/python-detector.ts diff --git a/auto-claude-ui/src/main/python-env-manager.ts b/apps/frontend/src/main/python-env-manager.ts similarity index 100% rename from auto-claude-ui/src/main/python-env-manager.ts rename to apps/frontend/src/main/python-env-manager.ts diff --git a/auto-claude-ui/src/main/rate-limit-detector.ts b/apps/frontend/src/main/rate-limit-detector.ts similarity index 100% rename from auto-claude-ui/src/main/rate-limit-detector.ts rename to apps/frontend/src/main/rate-limit-detector.ts diff --git a/auto-claude-ui/src/main/release-service.ts b/apps/frontend/src/main/release-service.ts similarity index 100% rename from auto-claude-ui/src/main/release-service.ts rename to apps/frontend/src/main/release-service.ts diff --git a/auto-claude-ui/src/main/task-log-service.ts b/apps/frontend/src/main/task-log-service.ts similarity index 100% rename from auto-claude-ui/src/main/task-log-service.ts rename to apps/frontend/src/main/task-log-service.ts diff --git a/auto-claude-ui/src/main/terminal-manager.ts b/apps/frontend/src/main/terminal-manager.ts similarity index 100% rename from auto-claude-ui/src/main/terminal-manager.ts rename to apps/frontend/src/main/terminal-manager.ts diff --git a/auto-claude-ui/src/main/terminal-name-generator.ts b/apps/frontend/src/main/terminal-name-generator.ts similarity index 100% rename from auto-claude-ui/src/main/terminal-name-generator.ts rename to apps/frontend/src/main/terminal-name-generator.ts diff --git a/auto-claude-ui/src/main/terminal-session-store.ts b/apps/frontend/src/main/terminal-session-store.ts similarity index 100% rename from auto-claude-ui/src/main/terminal-session-store.ts rename to apps/frontend/src/main/terminal-session-store.ts diff --git a/auto-claude-ui/src/main/terminal/claude-integration-handler.ts b/apps/frontend/src/main/terminal/claude-integration-handler.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/claude-integration-handler.ts rename to apps/frontend/src/main/terminal/claude-integration-handler.ts diff --git a/auto-claude-ui/src/main/terminal/index.ts b/apps/frontend/src/main/terminal/index.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/index.ts rename to apps/frontend/src/main/terminal/index.ts diff --git a/auto-claude-ui/src/main/terminal/output-parser.ts b/apps/frontend/src/main/terminal/output-parser.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/output-parser.ts rename to apps/frontend/src/main/terminal/output-parser.ts diff --git a/auto-claude-ui/src/main/terminal/pty-daemon-client.ts b/apps/frontend/src/main/terminal/pty-daemon-client.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/pty-daemon-client.ts rename to apps/frontend/src/main/terminal/pty-daemon-client.ts diff --git a/auto-claude-ui/src/main/terminal/pty-daemon.ts b/apps/frontend/src/main/terminal/pty-daemon.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/pty-daemon.ts rename to apps/frontend/src/main/terminal/pty-daemon.ts diff --git a/auto-claude-ui/src/main/terminal/pty-manager.ts b/apps/frontend/src/main/terminal/pty-manager.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/pty-manager.ts rename to apps/frontend/src/main/terminal/pty-manager.ts diff --git a/auto-claude-ui/src/main/terminal/session-handler.ts b/apps/frontend/src/main/terminal/session-handler.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/session-handler.ts rename to apps/frontend/src/main/terminal/session-handler.ts diff --git a/auto-claude-ui/src/main/terminal/session-persistence.ts b/apps/frontend/src/main/terminal/session-persistence.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/session-persistence.ts rename to apps/frontend/src/main/terminal/session-persistence.ts diff --git a/auto-claude-ui/src/main/terminal/terminal-event-handler.ts b/apps/frontend/src/main/terminal/terminal-event-handler.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/terminal-event-handler.ts rename to apps/frontend/src/main/terminal/terminal-event-handler.ts diff --git a/auto-claude-ui/src/main/terminal/terminal-lifecycle.ts b/apps/frontend/src/main/terminal/terminal-lifecycle.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/terminal-lifecycle.ts rename to apps/frontend/src/main/terminal/terminal-lifecycle.ts diff --git a/auto-claude-ui/src/main/terminal/terminal-manager.ts b/apps/frontend/src/main/terminal/terminal-manager.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/terminal-manager.ts rename to apps/frontend/src/main/terminal/terminal-manager.ts diff --git a/auto-claude-ui/src/main/terminal/types.ts b/apps/frontend/src/main/terminal/types.ts similarity index 100% rename from auto-claude-ui/src/main/terminal/types.ts rename to apps/frontend/src/main/terminal/types.ts diff --git a/auto-claude-ui/src/main/title-generator.ts b/apps/frontend/src/main/title-generator.ts similarity index 100% rename from auto-claude-ui/src/main/title-generator.ts rename to apps/frontend/src/main/title-generator.ts diff --git a/auto-claude-ui/src/main/updater/config.ts b/apps/frontend/src/main/updater/config.ts similarity index 100% rename from auto-claude-ui/src/main/updater/config.ts rename to apps/frontend/src/main/updater/config.ts diff --git a/auto-claude-ui/src/main/updater/file-operations.ts b/apps/frontend/src/main/updater/file-operations.ts similarity index 100% rename from auto-claude-ui/src/main/updater/file-operations.ts rename to apps/frontend/src/main/updater/file-operations.ts diff --git a/auto-claude-ui/src/main/updater/http-client.ts b/apps/frontend/src/main/updater/http-client.ts similarity index 100% rename from auto-claude-ui/src/main/updater/http-client.ts rename to apps/frontend/src/main/updater/http-client.ts diff --git a/auto-claude-ui/src/main/updater/path-resolver.ts b/apps/frontend/src/main/updater/path-resolver.ts similarity index 63% rename from auto-claude-ui/src/main/updater/path-resolver.ts rename to apps/frontend/src/main/updater/path-resolver.ts index 4a19ffcb..c9aecc79 100644 --- a/auto-claude-ui/src/main/updater/path-resolver.ts +++ b/apps/frontend/src/main/updater/path-resolver.ts @@ -7,21 +7,22 @@ import path from 'path'; import { app } from 'electron'; /** - * Get the path to the bundled auto-claude source + * Get the path to the bundled backend source */ export function getBundledSourcePath(): string { // In production, use app resources - // In development, use the repo's auto-claude folder + // In development, use the repo's apps/backend folder if (app.isPackaged) { - return path.join(process.resourcesPath, 'auto-claude'); + return path.join(process.resourcesPath, 'backend'); } - // Development mode - look for auto-claude in various locations + // Development mode - look for backend in various locations const possiblePaths = [ - path.join(app.getAppPath(), '..', 'auto-claude'), - path.join(app.getAppPath(), '..', '..', 'auto-claude'), - path.join(process.cwd(), 'auto-claude'), - path.join(process.cwd(), '..', 'auto-claude') + // New structure: apps/frontend -> apps/backend + path.join(app.getAppPath(), '..', 'backend'), + path.join(app.getAppPath(), '..', '..', 'apps', 'backend'), + path.join(process.cwd(), 'apps', 'backend'), + path.join(process.cwd(), '..', 'backend') ]; for (const p of possiblePaths) { @@ -31,7 +32,7 @@ export function getBundledSourcePath(): string { } // Fallback - return path.join(app.getAppPath(), '..', 'auto-claude'); + return path.join(app.getAppPath(), '..', 'backend'); } /** @@ -47,7 +48,7 @@ export function getUpdateCachePath(): string { export function getEffectiveSourcePath(): string { if (app.isPackaged) { // Check for user-updated source first - const overridePath = path.join(app.getPath('userData'), 'auto-claude-source'); + const overridePath = path.join(app.getPath('userData'), 'backend-source'); if (existsSync(overridePath)) { return overridePath; } @@ -62,7 +63,7 @@ export function getEffectiveSourcePath(): string { export function getUpdateTargetPath(): string { if (app.isPackaged) { // For packaged apps, store in userData as a source override - return path.join(app.getPath('userData'), 'auto-claude-source'); + return path.join(app.getPath('userData'), 'backend-source'); } else { // In development, update the actual source return getBundledSourcePath(); diff --git a/auto-claude-ui/src/main/updater/types.ts b/apps/frontend/src/main/updater/types.ts similarity index 100% rename from auto-claude-ui/src/main/updater/types.ts rename to apps/frontend/src/main/updater/types.ts diff --git a/auto-claude-ui/src/main/updater/update-checker.ts b/apps/frontend/src/main/updater/update-checker.ts similarity index 100% rename from auto-claude-ui/src/main/updater/update-checker.ts rename to apps/frontend/src/main/updater/update-checker.ts diff --git a/auto-claude-ui/src/main/updater/update-installer.ts b/apps/frontend/src/main/updater/update-installer.ts similarity index 100% rename from auto-claude-ui/src/main/updater/update-installer.ts rename to apps/frontend/src/main/updater/update-installer.ts diff --git a/auto-claude-ui/src/main/updater/update-status.ts b/apps/frontend/src/main/updater/update-status.ts similarity index 100% rename from auto-claude-ui/src/main/updater/update-status.ts rename to apps/frontend/src/main/updater/update-status.ts diff --git a/auto-claude-ui/src/main/updater/version-manager.ts b/apps/frontend/src/main/updater/version-manager.ts similarity index 100% rename from auto-claude-ui/src/main/updater/version-manager.ts rename to apps/frontend/src/main/updater/version-manager.ts diff --git a/auto-claude-ui/src/preload/api/agent-api.ts b/apps/frontend/src/preload/api/agent-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/agent-api.ts rename to apps/frontend/src/preload/api/agent-api.ts diff --git a/auto-claude-ui/src/preload/api/app-update-api.ts b/apps/frontend/src/preload/api/app-update-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/app-update-api.ts rename to apps/frontend/src/preload/api/app-update-api.ts diff --git a/auto-claude-ui/src/preload/api/file-api.ts b/apps/frontend/src/preload/api/file-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/file-api.ts rename to apps/frontend/src/preload/api/file-api.ts diff --git a/auto-claude-ui/src/preload/api/index.ts b/apps/frontend/src/preload/api/index.ts similarity index 100% rename from auto-claude-ui/src/preload/api/index.ts rename to apps/frontend/src/preload/api/index.ts diff --git a/auto-claude-ui/src/preload/api/modules/README.md b/apps/frontend/src/preload/api/modules/README.md similarity index 100% rename from auto-claude-ui/src/preload/api/modules/README.md rename to apps/frontend/src/preload/api/modules/README.md diff --git a/auto-claude-ui/src/preload/api/modules/autobuild-api.ts b/apps/frontend/src/preload/api/modules/autobuild-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/autobuild-api.ts rename to apps/frontend/src/preload/api/modules/autobuild-api.ts diff --git a/auto-claude-ui/src/preload/api/modules/changelog-api.ts b/apps/frontend/src/preload/api/modules/changelog-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/changelog-api.ts rename to apps/frontend/src/preload/api/modules/changelog-api.ts diff --git a/auto-claude-ui/src/preload/api/modules/github-api.ts b/apps/frontend/src/preload/api/modules/github-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/github-api.ts rename to apps/frontend/src/preload/api/modules/github-api.ts diff --git a/auto-claude-ui/src/preload/api/modules/ideation-api.ts b/apps/frontend/src/preload/api/modules/ideation-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/ideation-api.ts rename to apps/frontend/src/preload/api/modules/ideation-api.ts diff --git a/auto-claude-ui/src/preload/api/modules/index.ts b/apps/frontend/src/preload/api/modules/index.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/index.ts rename to apps/frontend/src/preload/api/modules/index.ts diff --git a/auto-claude-ui/src/preload/api/modules/insights-api.ts b/apps/frontend/src/preload/api/modules/insights-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/insights-api.ts rename to apps/frontend/src/preload/api/modules/insights-api.ts diff --git a/auto-claude-ui/src/preload/api/modules/ipc-utils.ts b/apps/frontend/src/preload/api/modules/ipc-utils.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/ipc-utils.ts rename to apps/frontend/src/preload/api/modules/ipc-utils.ts diff --git a/auto-claude-ui/src/preload/api/modules/linear-api.ts b/apps/frontend/src/preload/api/modules/linear-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/linear-api.ts rename to apps/frontend/src/preload/api/modules/linear-api.ts diff --git a/auto-claude-ui/src/preload/api/modules/roadmap-api.ts b/apps/frontend/src/preload/api/modules/roadmap-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/roadmap-api.ts rename to apps/frontend/src/preload/api/modules/roadmap-api.ts diff --git a/auto-claude-ui/src/preload/api/modules/shell-api.ts b/apps/frontend/src/preload/api/modules/shell-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/modules/shell-api.ts rename to apps/frontend/src/preload/api/modules/shell-api.ts diff --git a/auto-claude-ui/src/preload/api/project-api.ts b/apps/frontend/src/preload/api/project-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/project-api.ts rename to apps/frontend/src/preload/api/project-api.ts diff --git a/auto-claude-ui/src/preload/api/settings-api.ts b/apps/frontend/src/preload/api/settings-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/settings-api.ts rename to apps/frontend/src/preload/api/settings-api.ts diff --git a/auto-claude-ui/src/preload/api/task-api.ts b/apps/frontend/src/preload/api/task-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/task-api.ts rename to apps/frontend/src/preload/api/task-api.ts diff --git a/auto-claude-ui/src/preload/api/terminal-api.ts b/apps/frontend/src/preload/api/terminal-api.ts similarity index 100% rename from auto-claude-ui/src/preload/api/terminal-api.ts rename to apps/frontend/src/preload/api/terminal-api.ts diff --git a/auto-claude-ui/src/preload/index.ts b/apps/frontend/src/preload/index.ts similarity index 100% rename from auto-claude-ui/src/preload/index.ts rename to apps/frontend/src/preload/index.ts diff --git a/auto-claude-ui/src/renderer/App.tsx b/apps/frontend/src/renderer/App.tsx similarity index 100% rename from auto-claude-ui/src/renderer/App.tsx rename to apps/frontend/src/renderer/App.tsx diff --git a/auto-claude-ui/src/renderer/__tests__/OAuthStep.test.tsx b/apps/frontend/src/renderer/__tests__/OAuthStep.test.tsx similarity index 100% rename from auto-claude-ui/src/renderer/__tests__/OAuthStep.test.tsx rename to apps/frontend/src/renderer/__tests__/OAuthStep.test.tsx diff --git a/auto-claude-ui/src/renderer/__tests__/TaskEditDialog.test.ts b/apps/frontend/src/renderer/__tests__/TaskEditDialog.test.ts similarity index 100% rename from auto-claude-ui/src/renderer/__tests__/TaskEditDialog.test.ts rename to apps/frontend/src/renderer/__tests__/TaskEditDialog.test.ts diff --git a/auto-claude-ui/src/renderer/__tests__/project-store-tabs.test.ts b/apps/frontend/src/renderer/__tests__/project-store-tabs.test.ts similarity index 100% rename from auto-claude-ui/src/renderer/__tests__/project-store-tabs.test.ts rename to apps/frontend/src/renderer/__tests__/project-store-tabs.test.ts diff --git a/auto-claude-ui/src/renderer/__tests__/roadmap-store.test.ts b/apps/frontend/src/renderer/__tests__/roadmap-store.test.ts similarity index 100% rename from auto-claude-ui/src/renderer/__tests__/roadmap-store.test.ts rename to apps/frontend/src/renderer/__tests__/roadmap-store.test.ts diff --git a/auto-claude-ui/src/renderer/__tests__/task-store.test.ts b/apps/frontend/src/renderer/__tests__/task-store.test.ts similarity index 100% rename from auto-claude-ui/src/renderer/__tests__/task-store.test.ts rename to apps/frontend/src/renderer/__tests__/task-store.test.ts diff --git a/auto-claude-ui/src/renderer/components/AddFeatureDialog.tsx b/apps/frontend/src/renderer/components/AddFeatureDialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/AddFeatureDialog.tsx rename to apps/frontend/src/renderer/components/AddFeatureDialog.tsx diff --git a/auto-claude-ui/src/renderer/components/AddProjectModal.tsx b/apps/frontend/src/renderer/components/AddProjectModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/AddProjectModal.tsx rename to apps/frontend/src/renderer/components/AddProjectModal.tsx diff --git a/auto-claude-ui/src/renderer/components/AgentProfileSelector.tsx b/apps/frontend/src/renderer/components/AgentProfileSelector.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/AgentProfileSelector.tsx rename to apps/frontend/src/renderer/components/AgentProfileSelector.tsx diff --git a/auto-claude-ui/src/renderer/components/AgentProfiles.tsx b/apps/frontend/src/renderer/components/AgentProfiles.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/AgentProfiles.tsx rename to apps/frontend/src/renderer/components/AgentProfiles.tsx diff --git a/auto-claude-ui/src/renderer/components/AppSettings.tsx b/apps/frontend/src/renderer/components/AppSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/AppSettings.tsx rename to apps/frontend/src/renderer/components/AppSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/AppUpdateNotification.tsx b/apps/frontend/src/renderer/components/AppUpdateNotification.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/AppUpdateNotification.tsx rename to apps/frontend/src/renderer/components/AppUpdateNotification.tsx diff --git a/auto-claude-ui/src/renderer/components/Changelog.tsx b/apps/frontend/src/renderer/components/Changelog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/Changelog.tsx rename to apps/frontend/src/renderer/components/Changelog.tsx diff --git a/auto-claude-ui/src/renderer/components/ChatHistorySidebar.tsx b/apps/frontend/src/renderer/components/ChatHistorySidebar.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ChatHistorySidebar.tsx rename to apps/frontend/src/renderer/components/ChatHistorySidebar.tsx diff --git a/auto-claude-ui/src/renderer/components/CompetitorAnalysisDialog.tsx b/apps/frontend/src/renderer/components/CompetitorAnalysisDialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/CompetitorAnalysisDialog.tsx rename to apps/frontend/src/renderer/components/CompetitorAnalysisDialog.tsx diff --git a/auto-claude-ui/src/renderer/components/CompetitorAnalysisViewer.tsx b/apps/frontend/src/renderer/components/CompetitorAnalysisViewer.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/CompetitorAnalysisViewer.tsx rename to apps/frontend/src/renderer/components/CompetitorAnalysisViewer.tsx diff --git a/auto-claude-ui/src/renderer/components/Context.tsx b/apps/frontend/src/renderer/components/Context.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/Context.tsx rename to apps/frontend/src/renderer/components/Context.tsx diff --git a/auto-claude-ui/src/renderer/components/CustomModelModal.tsx b/apps/frontend/src/renderer/components/CustomModelModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/CustomModelModal.tsx rename to apps/frontend/src/renderer/components/CustomModelModal.tsx diff --git a/auto-claude-ui/src/renderer/components/EnvConfigModal.tsx b/apps/frontend/src/renderer/components/EnvConfigModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/EnvConfigModal.tsx rename to apps/frontend/src/renderer/components/EnvConfigModal.tsx diff --git a/auto-claude-ui/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx b/apps/frontend/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx rename to apps/frontend/src/renderer/components/ExistingCompetitorAnalysisDialog.tsx diff --git a/auto-claude-ui/src/renderer/components/FileAutocomplete.tsx b/apps/frontend/src/renderer/components/FileAutocomplete.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/FileAutocomplete.tsx rename to apps/frontend/src/renderer/components/FileAutocomplete.tsx diff --git a/auto-claude-ui/src/renderer/components/FileExplorerPanel.tsx b/apps/frontend/src/renderer/components/FileExplorerPanel.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/FileExplorerPanel.tsx rename to apps/frontend/src/renderer/components/FileExplorerPanel.tsx diff --git a/auto-claude-ui/src/renderer/components/FileTree.tsx b/apps/frontend/src/renderer/components/FileTree.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/FileTree.tsx rename to apps/frontend/src/renderer/components/FileTree.tsx diff --git a/auto-claude-ui/src/renderer/components/FileTreeItem.tsx b/apps/frontend/src/renderer/components/FileTreeItem.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/FileTreeItem.tsx rename to apps/frontend/src/renderer/components/FileTreeItem.tsx diff --git a/auto-claude-ui/src/renderer/components/GitHubIssues.tsx b/apps/frontend/src/renderer/components/GitHubIssues.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/GitHubIssues.tsx rename to apps/frontend/src/renderer/components/GitHubIssues.tsx diff --git a/auto-claude-ui/src/renderer/components/GitHubSetupModal.tsx b/apps/frontend/src/renderer/components/GitHubSetupModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/GitHubSetupModal.tsx rename to apps/frontend/src/renderer/components/GitHubSetupModal.tsx diff --git a/auto-claude-ui/src/renderer/components/GitSetupModal.tsx b/apps/frontend/src/renderer/components/GitSetupModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/GitSetupModal.tsx rename to apps/frontend/src/renderer/components/GitSetupModal.tsx diff --git a/auto-claude-ui/src/renderer/components/Ideation.tsx b/apps/frontend/src/renderer/components/Ideation.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/Ideation.tsx rename to apps/frontend/src/renderer/components/Ideation.tsx diff --git a/auto-claude-ui/src/renderer/components/ImageUpload.tsx b/apps/frontend/src/renderer/components/ImageUpload.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ImageUpload.tsx rename to apps/frontend/src/renderer/components/ImageUpload.tsx diff --git a/auto-claude-ui/src/renderer/components/Insights.tsx b/apps/frontend/src/renderer/components/Insights.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/Insights.tsx rename to apps/frontend/src/renderer/components/Insights.tsx diff --git a/auto-claude-ui/src/renderer/components/InsightsModelSelector.tsx b/apps/frontend/src/renderer/components/InsightsModelSelector.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/InsightsModelSelector.tsx rename to apps/frontend/src/renderer/components/InsightsModelSelector.tsx diff --git a/auto-claude-ui/src/renderer/components/KanbanBoard.tsx b/apps/frontend/src/renderer/components/KanbanBoard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/KanbanBoard.tsx rename to apps/frontend/src/renderer/components/KanbanBoard.tsx diff --git a/auto-claude-ui/src/renderer/components/LinearTaskImportModal.tsx b/apps/frontend/src/renderer/components/LinearTaskImportModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/LinearTaskImportModal.tsx rename to apps/frontend/src/renderer/components/LinearTaskImportModal.tsx diff --git a/auto-claude-ui/src/renderer/components/PhaseProgressIndicator.tsx b/apps/frontend/src/renderer/components/PhaseProgressIndicator.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/PhaseProgressIndicator.tsx rename to apps/frontend/src/renderer/components/PhaseProgressIndicator.tsx diff --git a/auto-claude-ui/src/renderer/components/ProactiveSwapListener.tsx b/apps/frontend/src/renderer/components/ProactiveSwapListener.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ProactiveSwapListener.tsx rename to apps/frontend/src/renderer/components/ProactiveSwapListener.tsx diff --git a/auto-claude-ui/src/renderer/components/ProjectSettings.tsx b/apps/frontend/src/renderer/components/ProjectSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ProjectSettings.tsx rename to apps/frontend/src/renderer/components/ProjectSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/ProjectTabBar.tsx b/apps/frontend/src/renderer/components/ProjectTabBar.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ProjectTabBar.tsx rename to apps/frontend/src/renderer/components/ProjectTabBar.tsx diff --git a/auto-claude-ui/src/renderer/components/RateLimitIndicator.tsx b/apps/frontend/src/renderer/components/RateLimitIndicator.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/RateLimitIndicator.tsx rename to apps/frontend/src/renderer/components/RateLimitIndicator.tsx diff --git a/auto-claude-ui/src/renderer/components/RateLimitModal.tsx b/apps/frontend/src/renderer/components/RateLimitModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/RateLimitModal.tsx rename to apps/frontend/src/renderer/components/RateLimitModal.tsx diff --git a/auto-claude-ui/src/renderer/components/ReferencedFilesSection.tsx b/apps/frontend/src/renderer/components/ReferencedFilesSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ReferencedFilesSection.tsx rename to apps/frontend/src/renderer/components/ReferencedFilesSection.tsx diff --git a/auto-claude-ui/src/renderer/components/Roadmap.tsx b/apps/frontend/src/renderer/components/Roadmap.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/Roadmap.tsx rename to apps/frontend/src/renderer/components/Roadmap.tsx diff --git a/auto-claude-ui/src/renderer/components/RoadmapGenerationProgress.tsx b/apps/frontend/src/renderer/components/RoadmapGenerationProgress.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/RoadmapGenerationProgress.tsx rename to apps/frontend/src/renderer/components/RoadmapGenerationProgress.tsx diff --git a/auto-claude-ui/src/renderer/components/RoadmapKanbanView.tsx b/apps/frontend/src/renderer/components/RoadmapKanbanView.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/RoadmapKanbanView.tsx rename to apps/frontend/src/renderer/components/RoadmapKanbanView.tsx diff --git a/auto-claude-ui/src/renderer/components/SDKRateLimitModal.tsx b/apps/frontend/src/renderer/components/SDKRateLimitModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/SDKRateLimitModal.tsx rename to apps/frontend/src/renderer/components/SDKRateLimitModal.tsx diff --git a/auto-claude-ui/src/renderer/components/Sidebar.tsx b/apps/frontend/src/renderer/components/Sidebar.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/Sidebar.tsx rename to apps/frontend/src/renderer/components/Sidebar.tsx diff --git a/auto-claude-ui/src/renderer/components/SortableFeatureCard.tsx b/apps/frontend/src/renderer/components/SortableFeatureCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/SortableFeatureCard.tsx rename to apps/frontend/src/renderer/components/SortableFeatureCard.tsx diff --git a/auto-claude-ui/src/renderer/components/SortableProjectTab.tsx b/apps/frontend/src/renderer/components/SortableProjectTab.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/SortableProjectTab.tsx rename to apps/frontend/src/renderer/components/SortableProjectTab.tsx diff --git a/auto-claude-ui/src/renderer/components/SortableTaskCard.tsx b/apps/frontend/src/renderer/components/SortableTaskCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/SortableTaskCard.tsx rename to apps/frontend/src/renderer/components/SortableTaskCard.tsx diff --git a/auto-claude-ui/src/renderer/components/TaskCard.tsx b/apps/frontend/src/renderer/components/TaskCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/TaskCard.tsx rename to apps/frontend/src/renderer/components/TaskCard.tsx diff --git a/auto-claude-ui/src/renderer/components/TaskCreationWizard.tsx b/apps/frontend/src/renderer/components/TaskCreationWizard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/TaskCreationWizard.tsx rename to apps/frontend/src/renderer/components/TaskCreationWizard.tsx diff --git a/auto-claude-ui/src/renderer/components/TaskDetailPanel.tsx b/apps/frontend/src/renderer/components/TaskDetailPanel.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/TaskDetailPanel.tsx rename to apps/frontend/src/renderer/components/TaskDetailPanel.tsx diff --git a/auto-claude-ui/src/renderer/components/TaskEditDialog.tsx b/apps/frontend/src/renderer/components/TaskEditDialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/TaskEditDialog.tsx rename to apps/frontend/src/renderer/components/TaskEditDialog.tsx diff --git a/auto-claude-ui/src/renderer/components/TaskFileExplorerDrawer.tsx b/apps/frontend/src/renderer/components/TaskFileExplorerDrawer.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/TaskFileExplorerDrawer.tsx rename to apps/frontend/src/renderer/components/TaskFileExplorerDrawer.tsx diff --git a/auto-claude-ui/src/renderer/components/Terminal.tsx b/apps/frontend/src/renderer/components/Terminal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/Terminal.tsx rename to apps/frontend/src/renderer/components/Terminal.tsx diff --git a/auto-claude-ui/src/renderer/components/TerminalGrid.tsx b/apps/frontend/src/renderer/components/TerminalGrid.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/TerminalGrid.tsx rename to apps/frontend/src/renderer/components/TerminalGrid.tsx diff --git a/auto-claude-ui/src/renderer/components/UsageIndicator.tsx b/apps/frontend/src/renderer/components/UsageIndicator.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/UsageIndicator.tsx rename to apps/frontend/src/renderer/components/UsageIndicator.tsx diff --git a/auto-claude-ui/src/renderer/components/WelcomeScreen.tsx b/apps/frontend/src/renderer/components/WelcomeScreen.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/WelcomeScreen.tsx rename to apps/frontend/src/renderer/components/WelcomeScreen.tsx diff --git a/auto-claude-ui/src/renderer/components/Worktrees.tsx b/apps/frontend/src/renderer/components/Worktrees.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/Worktrees.tsx rename to apps/frontend/src/renderer/components/Worktrees.tsx diff --git a/auto-claude-ui/src/renderer/components/__tests__/ProjectTabBar.test.tsx b/apps/frontend/src/renderer/components/__tests__/ProjectTabBar.test.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/__tests__/ProjectTabBar.test.tsx rename to apps/frontend/src/renderer/components/__tests__/ProjectTabBar.test.tsx diff --git a/auto-claude-ui/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx b/apps/frontend/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx rename to apps/frontend/src/renderer/components/__tests__/RoadmapGenerationProgress.test.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/ArchiveTasksCard.tsx b/apps/frontend/src/renderer/components/changelog/ArchiveTasksCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/ArchiveTasksCard.tsx rename to apps/frontend/src/renderer/components/changelog/ArchiveTasksCard.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/Changelog.tsx b/apps/frontend/src/renderer/components/changelog/Changelog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/Changelog.tsx rename to apps/frontend/src/renderer/components/changelog/Changelog.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogDetails.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogDetails.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/ChangelogDetails.tsx rename to apps/frontend/src/renderer/components/changelog/ChangelogDetails.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogEntry.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogEntry.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/ChangelogEntry.tsx rename to apps/frontend/src/renderer/components/changelog/ChangelogEntry.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogFilters.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogFilters.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/ChangelogFilters.tsx rename to apps/frontend/src/renderer/components/changelog/ChangelogFilters.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogHeader.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogHeader.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/ChangelogHeader.tsx rename to apps/frontend/src/renderer/components/changelog/ChangelogHeader.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/ChangelogList.tsx b/apps/frontend/src/renderer/components/changelog/ChangelogList.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/ChangelogList.tsx rename to apps/frontend/src/renderer/components/changelog/ChangelogList.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/ConfigurationPanel.tsx b/apps/frontend/src/renderer/components/changelog/ConfigurationPanel.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/ConfigurationPanel.tsx rename to apps/frontend/src/renderer/components/changelog/ConfigurationPanel.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/GitHubReleaseCard.tsx b/apps/frontend/src/renderer/components/changelog/GitHubReleaseCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/GitHubReleaseCard.tsx rename to apps/frontend/src/renderer/components/changelog/GitHubReleaseCard.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/PreviewPanel.tsx b/apps/frontend/src/renderer/components/changelog/PreviewPanel.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/PreviewPanel.tsx rename to apps/frontend/src/renderer/components/changelog/PreviewPanel.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/changelog/REFACTORING_SUMMARY.md similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/REFACTORING_SUMMARY.md rename to apps/frontend/src/renderer/components/changelog/REFACTORING_SUMMARY.md diff --git a/auto-claude-ui/src/renderer/components/changelog/Step3SuccessScreen.tsx b/apps/frontend/src/renderer/components/changelog/Step3SuccessScreen.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/Step3SuccessScreen.tsx rename to apps/frontend/src/renderer/components/changelog/Step3SuccessScreen.tsx diff --git a/auto-claude-ui/src/renderer/components/changelog/hooks/useChangelog.ts b/apps/frontend/src/renderer/components/changelog/hooks/useChangelog.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/hooks/useChangelog.ts rename to apps/frontend/src/renderer/components/changelog/hooks/useChangelog.ts diff --git a/auto-claude-ui/src/renderer/components/changelog/hooks/useImageUpload.ts b/apps/frontend/src/renderer/components/changelog/hooks/useImageUpload.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/hooks/useImageUpload.ts rename to apps/frontend/src/renderer/components/changelog/hooks/useImageUpload.ts diff --git a/auto-claude-ui/src/renderer/components/changelog/index.ts b/apps/frontend/src/renderer/components/changelog/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/index.ts rename to apps/frontend/src/renderer/components/changelog/index.ts diff --git a/auto-claude-ui/src/renderer/components/changelog/utils.ts b/apps/frontend/src/renderer/components/changelog/utils.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/changelog/utils.ts rename to apps/frontend/src/renderer/components/changelog/utils.ts diff --git a/auto-claude-ui/src/renderer/components/context/Context.tsx b/apps/frontend/src/renderer/components/context/Context.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/Context.tsx rename to apps/frontend/src/renderer/components/context/Context.tsx diff --git a/auto-claude-ui/src/renderer/components/context/InfoItem.tsx b/apps/frontend/src/renderer/components/context/InfoItem.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/InfoItem.tsx rename to apps/frontend/src/renderer/components/context/InfoItem.tsx diff --git a/auto-claude-ui/src/renderer/components/context/MemoriesTab.tsx b/apps/frontend/src/renderer/components/context/MemoriesTab.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/MemoriesTab.tsx rename to apps/frontend/src/renderer/components/context/MemoriesTab.tsx diff --git a/auto-claude-ui/src/renderer/components/context/MemoryCard.tsx b/apps/frontend/src/renderer/components/context/MemoryCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/MemoryCard.tsx rename to apps/frontend/src/renderer/components/context/MemoryCard.tsx diff --git a/auto-claude-ui/src/renderer/components/context/ProjectIndexTab.tsx b/apps/frontend/src/renderer/components/context/ProjectIndexTab.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/ProjectIndexTab.tsx rename to apps/frontend/src/renderer/components/context/ProjectIndexTab.tsx diff --git a/auto-claude-ui/src/renderer/components/context/README.md b/apps/frontend/src/renderer/components/context/README.md similarity index 100% rename from auto-claude-ui/src/renderer/components/context/README.md rename to apps/frontend/src/renderer/components/context/README.md diff --git a/auto-claude-ui/src/renderer/components/context/ServiceCard.tsx b/apps/frontend/src/renderer/components/context/ServiceCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/ServiceCard.tsx rename to apps/frontend/src/renderer/components/context/ServiceCard.tsx diff --git a/auto-claude-ui/src/renderer/components/context/constants.ts b/apps/frontend/src/renderer/components/context/constants.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/context/constants.ts rename to apps/frontend/src/renderer/components/context/constants.ts diff --git a/auto-claude-ui/src/renderer/components/context/hooks.ts b/apps/frontend/src/renderer/components/context/hooks.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/context/hooks.ts rename to apps/frontend/src/renderer/components/context/hooks.ts diff --git a/auto-claude-ui/src/renderer/components/context/index.ts b/apps/frontend/src/renderer/components/context/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/context/index.ts rename to apps/frontend/src/renderer/components/context/index.ts diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/APIRoutesSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/APIRoutesSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/service-sections/APIRoutesSection.tsx rename to apps/frontend/src/renderer/components/context/service-sections/APIRoutesSection.tsx diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/DatabaseSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/DatabaseSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/service-sections/DatabaseSection.tsx rename to apps/frontend/src/renderer/components/context/service-sections/DatabaseSection.tsx diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/DependenciesSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/DependenciesSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/service-sections/DependenciesSection.tsx rename to apps/frontend/src/renderer/components/context/service-sections/DependenciesSection.tsx diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/EnvironmentSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/EnvironmentSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/service-sections/EnvironmentSection.tsx rename to apps/frontend/src/renderer/components/context/service-sections/EnvironmentSection.tsx diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/ExternalServicesSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/ExternalServicesSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/service-sections/ExternalServicesSection.tsx rename to apps/frontend/src/renderer/components/context/service-sections/ExternalServicesSection.tsx diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/MonitoringSection.tsx b/apps/frontend/src/renderer/components/context/service-sections/MonitoringSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/context/service-sections/MonitoringSection.tsx rename to apps/frontend/src/renderer/components/context/service-sections/MonitoringSection.tsx diff --git a/auto-claude-ui/src/renderer/components/context/service-sections/index.ts b/apps/frontend/src/renderer/components/context/service-sections/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/context/service-sections/index.ts rename to apps/frontend/src/renderer/components/context/service-sections/index.ts diff --git a/auto-claude-ui/src/renderer/components/context/types.ts b/apps/frontend/src/renderer/components/context/types.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/context/types.ts rename to apps/frontend/src/renderer/components/context/types.ts diff --git a/auto-claude-ui/src/renderer/components/context/utils.ts b/apps/frontend/src/renderer/components/context/utils.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/context/utils.ts rename to apps/frontend/src/renderer/components/context/utils.ts diff --git a/auto-claude-ui/src/renderer/components/github-issues/ARCHITECTURE.md b/apps/frontend/src/renderer/components/github-issues/ARCHITECTURE.md similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/ARCHITECTURE.md rename to apps/frontend/src/renderer/components/github-issues/ARCHITECTURE.md diff --git a/auto-claude-ui/src/renderer/components/github-issues/README.md b/apps/frontend/src/renderer/components/github-issues/README.md similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/README.md rename to apps/frontend/src/renderer/components/github-issues/README.md diff --git a/auto-claude-ui/src/renderer/components/github-issues/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/github-issues/REFACTORING_SUMMARY.md similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/REFACTORING_SUMMARY.md rename to apps/frontend/src/renderer/components/github-issues/REFACTORING_SUMMARY.md diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/EmptyStates.tsx b/apps/frontend/src/renderer/components/github-issues/components/EmptyStates.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/components/EmptyStates.tsx rename to apps/frontend/src/renderer/components/github-issues/components/EmptyStates.tsx diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/InvestigationDialog.tsx b/apps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/components/InvestigationDialog.tsx rename to apps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsx diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/IssueDetail.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/components/IssueDetail.tsx rename to apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/IssueList.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueList.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/components/IssueList.tsx rename to apps/frontend/src/renderer/components/github-issues/components/IssueList.tsx diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/IssueListHeader.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/components/IssueListHeader.tsx rename to apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/IssueListItem.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/components/IssueListItem.tsx rename to apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx diff --git a/auto-claude-ui/src/renderer/components/github-issues/components/index.ts b/apps/frontend/src/renderer/components/github-issues/components/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/components/index.ts rename to apps/frontend/src/renderer/components/github-issues/components/index.ts diff --git a/auto-claude-ui/src/renderer/components/github-issues/hooks/index.ts b/apps/frontend/src/renderer/components/github-issues/hooks/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/hooks/index.ts rename to apps/frontend/src/renderer/components/github-issues/hooks/index.ts diff --git a/auto-claude-ui/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts b/apps/frontend/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts rename to apps/frontend/src/renderer/components/github-issues/hooks/useGitHubInvestigation.ts diff --git a/auto-claude-ui/src/renderer/components/github-issues/hooks/useGitHubIssues.ts b/apps/frontend/src/renderer/components/github-issues/hooks/useGitHubIssues.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/hooks/useGitHubIssues.ts rename to apps/frontend/src/renderer/components/github-issues/hooks/useGitHubIssues.ts diff --git a/auto-claude-ui/src/renderer/components/github-issues/hooks/useIssueFiltering.ts b/apps/frontend/src/renderer/components/github-issues/hooks/useIssueFiltering.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/hooks/useIssueFiltering.ts rename to apps/frontend/src/renderer/components/github-issues/hooks/useIssueFiltering.ts diff --git a/auto-claude-ui/src/renderer/components/github-issues/index.ts b/apps/frontend/src/renderer/components/github-issues/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/index.ts rename to apps/frontend/src/renderer/components/github-issues/index.ts diff --git a/auto-claude-ui/src/renderer/components/github-issues/types/index.ts b/apps/frontend/src/renderer/components/github-issues/types/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/types/index.ts rename to apps/frontend/src/renderer/components/github-issues/types/index.ts diff --git a/auto-claude-ui/src/renderer/components/github-issues/utils/index.ts b/apps/frontend/src/renderer/components/github-issues/utils/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/github-issues/utils/index.ts rename to apps/frontend/src/renderer/components/github-issues/utils/index.ts diff --git a/auto-claude-ui/src/renderer/components/ideation/GenerationProgressScreen.tsx b/apps/frontend/src/renderer/components/ideation/GenerationProgressScreen.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/GenerationProgressScreen.tsx rename to apps/frontend/src/renderer/components/ideation/GenerationProgressScreen.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeaCard.tsx b/apps/frontend/src/renderer/components/ideation/IdeaCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/IdeaCard.tsx rename to apps/frontend/src/renderer/components/ideation/IdeaCard.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeaDetailPanel.tsx b/apps/frontend/src/renderer/components/ideation/IdeaDetailPanel.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/IdeaDetailPanel.tsx rename to apps/frontend/src/renderer/components/ideation/IdeaDetailPanel.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeaSkeletonCard.tsx b/apps/frontend/src/renderer/components/ideation/IdeaSkeletonCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/IdeaSkeletonCard.tsx rename to apps/frontend/src/renderer/components/ideation/IdeaSkeletonCard.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/Ideation.tsx b/apps/frontend/src/renderer/components/ideation/Ideation.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/Ideation.tsx rename to apps/frontend/src/renderer/components/ideation/Ideation.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeationDialogs.tsx b/apps/frontend/src/renderer/components/ideation/IdeationDialogs.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/IdeationDialogs.tsx rename to apps/frontend/src/renderer/components/ideation/IdeationDialogs.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeationEmptyState.tsx b/apps/frontend/src/renderer/components/ideation/IdeationEmptyState.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/IdeationEmptyState.tsx rename to apps/frontend/src/renderer/components/ideation/IdeationEmptyState.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeationFilters.tsx b/apps/frontend/src/renderer/components/ideation/IdeationFilters.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/IdeationFilters.tsx rename to apps/frontend/src/renderer/components/ideation/IdeationFilters.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/IdeationHeader.tsx b/apps/frontend/src/renderer/components/ideation/IdeationHeader.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/IdeationHeader.tsx rename to apps/frontend/src/renderer/components/ideation/IdeationHeader.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/TypeIcon.tsx b/apps/frontend/src/renderer/components/ideation/TypeIcon.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/TypeIcon.tsx rename to apps/frontend/src/renderer/components/ideation/TypeIcon.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/TypeStateIcon.tsx b/apps/frontend/src/renderer/components/ideation/TypeStateIcon.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/TypeStateIcon.tsx rename to apps/frontend/src/renderer/components/ideation/TypeStateIcon.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/constants.ts b/apps/frontend/src/renderer/components/ideation/constants.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/constants.ts rename to apps/frontend/src/renderer/components/ideation/constants.ts diff --git a/auto-claude-ui/src/renderer/components/ideation/details/CodeImprovementDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/CodeImprovementDetails.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/details/CodeImprovementDetails.tsx rename to apps/frontend/src/renderer/components/ideation/details/CodeImprovementDetails.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/details/CodeQualityDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/CodeQualityDetails.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/details/CodeQualityDetails.tsx rename to apps/frontend/src/renderer/components/ideation/details/CodeQualityDetails.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/details/DocumentationGapDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/DocumentationGapDetails.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/details/DocumentationGapDetails.tsx rename to apps/frontend/src/renderer/components/ideation/details/DocumentationGapDetails.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx rename to apps/frontend/src/renderer/components/ideation/details/PerformanceOptimizationDetails.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx rename to apps/frontend/src/renderer/components/ideation/details/SecurityHardeningDetails.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/details/UIUXDetails.tsx b/apps/frontend/src/renderer/components/ideation/details/UIUXDetails.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/details/UIUXDetails.tsx rename to apps/frontend/src/renderer/components/ideation/details/UIUXDetails.tsx diff --git a/auto-claude-ui/src/renderer/components/ideation/hooks/useIdeation.ts b/apps/frontend/src/renderer/components/ideation/hooks/useIdeation.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/hooks/useIdeation.ts rename to apps/frontend/src/renderer/components/ideation/hooks/useIdeation.ts diff --git a/auto-claude-ui/src/renderer/components/ideation/index.ts b/apps/frontend/src/renderer/components/ideation/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/index.ts rename to apps/frontend/src/renderer/components/ideation/index.ts diff --git a/auto-claude-ui/src/renderer/components/ideation/type-guards.ts b/apps/frontend/src/renderer/components/ideation/type-guards.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/ideation/type-guards.ts rename to apps/frontend/src/renderer/components/ideation/type-guards.ts diff --git a/auto-claude-ui/src/renderer/components/index.ts b/apps/frontend/src/renderer/components/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/index.ts rename to apps/frontend/src/renderer/components/index.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx b/apps/frontend/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx rename to apps/frontend/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx diff --git a/auto-claude-ui/src/renderer/components/linear-import/README.md b/apps/frontend/src/renderer/components/linear-import/README.md similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/README.md rename to apps/frontend/src/renderer/components/linear-import/README.md diff --git a/auto-claude-ui/src/renderer/components/linear-import/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/linear-import/REFACTORING_SUMMARY.md similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/REFACTORING_SUMMARY.md rename to apps/frontend/src/renderer/components/linear-import/REFACTORING_SUMMARY.md diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/ErrorBanner.tsx b/apps/frontend/src/renderer/components/linear-import/components/ErrorBanner.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/components/ErrorBanner.tsx rename to apps/frontend/src/renderer/components/linear-import/components/ErrorBanner.tsx diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx b/apps/frontend/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx rename to apps/frontend/src/renderer/components/linear-import/components/ImportSuccessBanner.tsx diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/IssueCard.tsx b/apps/frontend/src/renderer/components/linear-import/components/IssueCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/components/IssueCard.tsx rename to apps/frontend/src/renderer/components/linear-import/components/IssueCard.tsx diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/IssueList.tsx b/apps/frontend/src/renderer/components/linear-import/components/IssueList.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/components/IssueList.tsx rename to apps/frontend/src/renderer/components/linear-import/components/IssueList.tsx diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx b/apps/frontend/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx rename to apps/frontend/src/renderer/components/linear-import/components/SearchAndFilterBar.tsx diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/SelectionControls.tsx b/apps/frontend/src/renderer/components/linear-import/components/SelectionControls.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/components/SelectionControls.tsx rename to apps/frontend/src/renderer/components/linear-import/components/SelectionControls.tsx diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/TeamProjectSelector.tsx b/apps/frontend/src/renderer/components/linear-import/components/TeamProjectSelector.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/components/TeamProjectSelector.tsx rename to apps/frontend/src/renderer/components/linear-import/components/TeamProjectSelector.tsx diff --git a/auto-claude-ui/src/renderer/components/linear-import/components/index.ts b/apps/frontend/src/renderer/components/linear-import/components/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/components/index.ts rename to apps/frontend/src/renderer/components/linear-import/components/index.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/index.ts b/apps/frontend/src/renderer/components/linear-import/hooks/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/hooks/index.ts rename to apps/frontend/src/renderer/components/linear-import/hooks/index.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useIssueFiltering.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useIssueFiltering.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useIssueFiltering.ts rename to apps/frontend/src/renderer/components/linear-import/hooks/useIssueFiltering.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useIssueSelection.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useIssueSelection.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useIssueSelection.ts rename to apps/frontend/src/renderer/components/linear-import/hooks/useIssueSelection.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearImport.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearImport.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearImport.ts rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearImport.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearImportModal.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearImportModal.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearImportModal.ts rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearImportModal.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearIssues.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearIssues.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearIssues.ts rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearIssues.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearProjects.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearProjects.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearProjects.ts rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearProjects.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearTeams.ts b/apps/frontend/src/renderer/components/linear-import/hooks/useLinearTeams.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/hooks/useLinearTeams.ts rename to apps/frontend/src/renderer/components/linear-import/hooks/useLinearTeams.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/index.ts b/apps/frontend/src/renderer/components/linear-import/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/index.ts rename to apps/frontend/src/renderer/components/linear-import/index.ts diff --git a/auto-claude-ui/src/renderer/components/linear-import/types.ts b/apps/frontend/src/renderer/components/linear-import/types.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/linear-import/types.ts rename to apps/frontend/src/renderer/components/linear-import/types.ts diff --git a/auto-claude-ui/src/renderer/components/onboarding/CompletionStep.tsx b/apps/frontend/src/renderer/components/onboarding/CompletionStep.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/onboarding/CompletionStep.tsx rename to apps/frontend/src/renderer/components/onboarding/CompletionStep.tsx diff --git a/auto-claude-ui/src/renderer/components/onboarding/FirstSpecStep.tsx b/apps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/onboarding/FirstSpecStep.tsx rename to apps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsx diff --git a/auto-claude-ui/src/renderer/components/onboarding/GraphitiStep.tsx b/apps/frontend/src/renderer/components/onboarding/GraphitiStep.tsx similarity index 99% rename from auto-claude-ui/src/renderer/components/onboarding/GraphitiStep.tsx rename to apps/frontend/src/renderer/components/onboarding/GraphitiStep.tsx index 7dbea07d..d72d485c 100644 --- a/auto-claude-ui/src/renderer/components/onboarding/GraphitiStep.tsx +++ b/apps/frontend/src/renderer/components/onboarding/GraphitiStep.tsx @@ -99,8 +99,7 @@ interface ValidationStatus { /** * Graphiti memory configuration step for the onboarding wizard. * Uses LadybugDB (embedded database) - no Docker required. - * Allows users to optionally configure Graphiti memory backend with multiple provider options. - * This step is entirely optional and can be skipped. + * Allows users to configure Graphiti memory backend with multiple provider options. */ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) { const { settings, updateSettings } = useSettingsStore(); @@ -688,7 +687,7 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {

- Memory & Context (Optional) + Memory & Context

Enable Graphiti for persistent memory across coding sessions diff --git a/auto-claude-ui/src/renderer/components/onboarding/MemoryStep.tsx b/apps/frontend/src/renderer/components/onboarding/MemoryStep.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/onboarding/MemoryStep.tsx rename to apps/frontend/src/renderer/components/onboarding/MemoryStep.tsx diff --git a/auto-claude-ui/src/renderer/components/onboarding/OAuthStep.tsx b/apps/frontend/src/renderer/components/onboarding/OAuthStep.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/onboarding/OAuthStep.tsx rename to apps/frontend/src/renderer/components/onboarding/OAuthStep.tsx diff --git a/auto-claude-ui/src/renderer/components/onboarding/OllamaModelSelector.tsx b/apps/frontend/src/renderer/components/onboarding/OllamaModelSelector.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/onboarding/OllamaModelSelector.tsx rename to apps/frontend/src/renderer/components/onboarding/OllamaModelSelector.tsx diff --git a/auto-claude-ui/src/renderer/components/onboarding/OnboardingWizard.tsx b/apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/onboarding/OnboardingWizard.tsx rename to apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx diff --git a/auto-claude-ui/src/renderer/components/onboarding/WelcomeStep.tsx b/apps/frontend/src/renderer/components/onboarding/WelcomeStep.tsx similarity index 95% rename from auto-claude-ui/src/renderer/components/onboarding/WelcomeStep.tsx rename to apps/frontend/src/renderer/components/onboarding/WelcomeStep.tsx index 1d2e3108..e8744ce5 100644 --- a/auto-claude-ui/src/renderer/components/onboarding/WelcomeStep.tsx +++ b/apps/frontend/src/renderer/components/onboarding/WelcomeStep.tsx @@ -50,7 +50,7 @@ export function WelcomeStep({ onGetStarted, onSkip }: WelcomeStepProps) { { icon: , title: 'Memory & Context', - description: 'Optional Graphiti integration for persistent memory across sessions' + description: 'Persistent memory across sessions with Graphiti' }, { icon: , @@ -88,7 +88,7 @@ export function WelcomeStep({ onGetStarted, onSkip }: WelcomeStepProps) {

This wizard will help you set up your environment in just a few steps. - You can configure your Claude OAuth token, optionally set up memory features, + You can configure your Claude OAuth token, set up memory features, and create your first task.

diff --git a/auto-claude-ui/src/renderer/components/onboarding/WizardProgress.tsx b/apps/frontend/src/renderer/components/onboarding/WizardProgress.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/onboarding/WizardProgress.tsx rename to apps/frontend/src/renderer/components/onboarding/WizardProgress.tsx diff --git a/auto-claude-ui/src/renderer/components/onboarding/index.ts b/apps/frontend/src/renderer/components/onboarding/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/onboarding/index.ts rename to apps/frontend/src/renderer/components/onboarding/index.ts diff --git a/auto-claude-ui/src/renderer/components/project-settings/AgentConfigSection.tsx b/apps/frontend/src/renderer/components/project-settings/AgentConfigSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/AgentConfigSection.tsx rename to apps/frontend/src/renderer/components/project-settings/AgentConfigSection.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/AutoBuildIntegration.tsx b/apps/frontend/src/renderer/components/project-settings/AutoBuildIntegration.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/AutoBuildIntegration.tsx rename to apps/frontend/src/renderer/components/project-settings/AutoBuildIntegration.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/ClaudeAuthSection.tsx b/apps/frontend/src/renderer/components/project-settings/ClaudeAuthSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/ClaudeAuthSection.tsx rename to apps/frontend/src/renderer/components/project-settings/ClaudeAuthSection.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx b/apps/frontend/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx rename to apps/frontend/src/renderer/components/project-settings/ClaudeOAuthFlow.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/CollapsibleSection.tsx b/apps/frontend/src/renderer/components/project-settings/CollapsibleSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/CollapsibleSection.tsx rename to apps/frontend/src/renderer/components/project-settings/CollapsibleSection.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/ConnectionStatus.tsx b/apps/frontend/src/renderer/components/project-settings/ConnectionStatus.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/ConnectionStatus.tsx rename to apps/frontend/src/renderer/components/project-settings/ConnectionStatus.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/EnvironmentSettings.tsx b/apps/frontend/src/renderer/components/project-settings/EnvironmentSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/EnvironmentSettings.tsx rename to apps/frontend/src/renderer/components/project-settings/EnvironmentSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/GeneralSettings.tsx b/apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/GeneralSettings.tsx rename to apps/frontend/src/renderer/components/project-settings/GeneralSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/GitHubIntegrationSection.tsx b/apps/frontend/src/renderer/components/project-settings/GitHubIntegrationSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/GitHubIntegrationSection.tsx rename to apps/frontend/src/renderer/components/project-settings/GitHubIntegrationSection.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/GitHubOAuthFlow.tsx b/apps/frontend/src/renderer/components/project-settings/GitHubOAuthFlow.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/GitHubOAuthFlow.tsx rename to apps/frontend/src/renderer/components/project-settings/GitHubOAuthFlow.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/InfrastructureStatus.tsx b/apps/frontend/src/renderer/components/project-settings/InfrastructureStatus.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/InfrastructureStatus.tsx rename to apps/frontend/src/renderer/components/project-settings/InfrastructureStatus.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/IntegrationSettings.tsx b/apps/frontend/src/renderer/components/project-settings/IntegrationSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/IntegrationSettings.tsx rename to apps/frontend/src/renderer/components/project-settings/IntegrationSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/LinearIntegrationSection.tsx b/apps/frontend/src/renderer/components/project-settings/LinearIntegrationSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/LinearIntegrationSection.tsx rename to apps/frontend/src/renderer/components/project-settings/LinearIntegrationSection.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/MemoryBackendSection.tsx b/apps/frontend/src/renderer/components/project-settings/MemoryBackendSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/MemoryBackendSection.tsx rename to apps/frontend/src/renderer/components/project-settings/MemoryBackendSection.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/NotificationsSection.tsx b/apps/frontend/src/renderer/components/project-settings/NotificationsSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/NotificationsSection.tsx rename to apps/frontend/src/renderer/components/project-settings/NotificationsSection.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/PasswordInput.tsx b/apps/frontend/src/renderer/components/project-settings/PasswordInput.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/PasswordInput.tsx rename to apps/frontend/src/renderer/components/project-settings/PasswordInput.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/ProjectSettings.tsx b/apps/frontend/src/renderer/components/project-settings/ProjectSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/ProjectSettings.tsx rename to apps/frontend/src/renderer/components/project-settings/ProjectSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/README.md b/apps/frontend/src/renderer/components/project-settings/README.md similarity index 95% rename from auto-claude-ui/src/renderer/components/project-settings/README.md rename to apps/frontend/src/renderer/components/project-settings/README.md index f74c44e5..d7b42c44 100644 --- a/auto-claude-ui/src/renderer/components/project-settings/README.md +++ b/apps/frontend/src/renderer/components/project-settings/README.md @@ -33,7 +33,7 @@ project-settings/ ├── PasswordInput.tsx # Reusable password input with toggle ├── StatusBadge.tsx # Reusable status badge component ├── ConnectionStatus.tsx # Reusable connection status display -└── InfrastructureStatus.tsx # Docker/FalkorDB status display +└── InfrastructureStatus.tsx # LadybugDB memory status display hooks/ ├── index.ts # Barrel export for all hooks @@ -42,7 +42,7 @@ hooks/ ├── useClaudeAuth.ts # Claude authentication status ├── useLinearConnection.ts # Linear connection status ├── useGitHubConnection.ts # GitHub connection status -└── useInfrastructureStatus.ts # Docker/FalkorDB infrastructure status +└── useInfrastructureStatus.ts # LadybugDB memory status ``` ## Component Breakdown @@ -125,14 +125,14 @@ hooks/ - `settings`: Project settings - `onUpdateConfig`: Configuration update handler - `onUpdateSettings`: Settings update handler -- `infrastructureStatus`: Docker/FalkorDB status +- `infrastructureStatus`: LadybugDB memory status - Infrastructure management handlers **Responsibilities**: - Toggle between Graphiti and file-based memory - Configure LLM and embedding providers -- Manage FalkorDB connection settings -- Display infrastructure status (Docker/FalkorDB) +- Manage LadybugDB connection settings +- Display infrastructure status (LadybugDB) - Handle infrastructure startup #### AgentConfigSection.tsx @@ -202,7 +202,7 @@ hooks/ **Usage**: Used by Linear and GitHub sections to display connection status. #### InfrastructureStatus.tsx -**Purpose**: Displays Docker and FalkorDB status for Graphiti. +**Purpose**: Displays LadybugDB memory status for Graphiti. **Props**: - `infrastructureStatus`: Status object - `isCheckingInfrastructure`: Loading state @@ -252,7 +252,7 @@ hooks/ - `isCheckingGitHub`: Loading state ### useInfrastructureStatus.ts -**Purpose**: Monitors Docker and FalkorDB infrastructure status. +**Purpose**: Monitors LadybugDB memory infrastructure status. **Returns**: - `infrastructureStatus`: Status object - `isCheckingInfrastructure`: Loading state diff --git a/auto-claude-ui/src/renderer/components/project-settings/SecuritySettings.tsx b/apps/frontend/src/renderer/components/project-settings/SecuritySettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/SecuritySettings.tsx rename to apps/frontend/src/renderer/components/project-settings/SecuritySettings.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/StatusBadge.tsx b/apps/frontend/src/renderer/components/project-settings/StatusBadge.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/StatusBadge.tsx rename to apps/frontend/src/renderer/components/project-settings/StatusBadge.tsx diff --git a/auto-claude-ui/src/renderer/components/project-settings/hooks/useProjectSettings.ts b/apps/frontend/src/renderer/components/project-settings/hooks/useProjectSettings.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/hooks/useProjectSettings.ts rename to apps/frontend/src/renderer/components/project-settings/hooks/useProjectSettings.ts diff --git a/auto-claude-ui/src/renderer/components/project-settings/index.ts b/apps/frontend/src/renderer/components/project-settings/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/project-settings/index.ts rename to apps/frontend/src/renderer/components/project-settings/index.ts diff --git a/auto-claude-ui/src/renderer/components/roadmap/FeatureCard.tsx b/apps/frontend/src/renderer/components/roadmap/FeatureCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/FeatureCard.tsx rename to apps/frontend/src/renderer/components/roadmap/FeatureCard.tsx diff --git a/auto-claude-ui/src/renderer/components/roadmap/FeatureDetailPanel.tsx b/apps/frontend/src/renderer/components/roadmap/FeatureDetailPanel.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/FeatureDetailPanel.tsx rename to apps/frontend/src/renderer/components/roadmap/FeatureDetailPanel.tsx diff --git a/auto-claude-ui/src/renderer/components/roadmap/PhaseCard.tsx b/apps/frontend/src/renderer/components/roadmap/PhaseCard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/PhaseCard.tsx rename to apps/frontend/src/renderer/components/roadmap/PhaseCard.tsx diff --git a/auto-claude-ui/src/renderer/components/roadmap/README.md b/apps/frontend/src/renderer/components/roadmap/README.md similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/README.md rename to apps/frontend/src/renderer/components/roadmap/README.md diff --git a/auto-claude-ui/src/renderer/components/roadmap/RoadmapEmptyState.tsx b/apps/frontend/src/renderer/components/roadmap/RoadmapEmptyState.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/RoadmapEmptyState.tsx rename to apps/frontend/src/renderer/components/roadmap/RoadmapEmptyState.tsx diff --git a/auto-claude-ui/src/renderer/components/roadmap/RoadmapHeader.tsx b/apps/frontend/src/renderer/components/roadmap/RoadmapHeader.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/RoadmapHeader.tsx rename to apps/frontend/src/renderer/components/roadmap/RoadmapHeader.tsx diff --git a/auto-claude-ui/src/renderer/components/roadmap/RoadmapTabs.tsx b/apps/frontend/src/renderer/components/roadmap/RoadmapTabs.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/RoadmapTabs.tsx rename to apps/frontend/src/renderer/components/roadmap/RoadmapTabs.tsx diff --git a/auto-claude-ui/src/renderer/components/roadmap/hooks.ts b/apps/frontend/src/renderer/components/roadmap/hooks.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/hooks.ts rename to apps/frontend/src/renderer/components/roadmap/hooks.ts diff --git a/auto-claude-ui/src/renderer/components/roadmap/index.ts b/apps/frontend/src/renderer/components/roadmap/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/index.ts rename to apps/frontend/src/renderer/components/roadmap/index.ts diff --git a/auto-claude-ui/src/renderer/components/roadmap/types.ts b/apps/frontend/src/renderer/components/roadmap/types.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/types.ts rename to apps/frontend/src/renderer/components/roadmap/types.ts diff --git a/auto-claude-ui/src/renderer/components/roadmap/utils.ts b/apps/frontend/src/renderer/components/roadmap/utils.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/roadmap/utils.ts rename to apps/frontend/src/renderer/components/roadmap/utils.ts diff --git a/auto-claude-ui/src/renderer/components/settings/AdvancedSettings.tsx b/apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/AdvancedSettings.tsx rename to apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/AgentProfileSettings.tsx b/apps/frontend/src/renderer/components/settings/AgentProfileSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/AgentProfileSettings.tsx rename to apps/frontend/src/renderer/components/settings/AgentProfileSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/AppSettings.tsx b/apps/frontend/src/renderer/components/settings/AppSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/AppSettings.tsx rename to apps/frontend/src/renderer/components/settings/AppSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/GeneralSettings.tsx b/apps/frontend/src/renderer/components/settings/GeneralSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/GeneralSettings.tsx rename to apps/frontend/src/renderer/components/settings/GeneralSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/IntegrationSettings.tsx b/apps/frontend/src/renderer/components/settings/IntegrationSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/IntegrationSettings.tsx rename to apps/frontend/src/renderer/components/settings/IntegrationSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/ProjectSelector.tsx b/apps/frontend/src/renderer/components/settings/ProjectSelector.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/ProjectSelector.tsx rename to apps/frontend/src/renderer/components/settings/ProjectSelector.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/ProjectSettingsContent.tsx b/apps/frontend/src/renderer/components/settings/ProjectSettingsContent.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/ProjectSettingsContent.tsx rename to apps/frontend/src/renderer/components/settings/ProjectSettingsContent.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/README.md b/apps/frontend/src/renderer/components/settings/README.md similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/README.md rename to apps/frontend/src/renderer/components/settings/README.md diff --git a/auto-claude-ui/src/renderer/components/settings/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/settings/REFACTORING_SUMMARY.md similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/REFACTORING_SUMMARY.md rename to apps/frontend/src/renderer/components/settings/REFACTORING_SUMMARY.md diff --git a/auto-claude-ui/src/renderer/components/settings/SettingsSection.tsx b/apps/frontend/src/renderer/components/settings/SettingsSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/SettingsSection.tsx rename to apps/frontend/src/renderer/components/settings/SettingsSection.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/ThemeSelector.tsx b/apps/frontend/src/renderer/components/settings/ThemeSelector.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/ThemeSelector.tsx rename to apps/frontend/src/renderer/components/settings/ThemeSelector.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/ThemeSettings.tsx b/apps/frontend/src/renderer/components/settings/ThemeSettings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/ThemeSettings.tsx rename to apps/frontend/src/renderer/components/settings/ThemeSettings.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/common/EmptyProjectState.tsx b/apps/frontend/src/renderer/components/settings/common/EmptyProjectState.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/common/EmptyProjectState.tsx rename to apps/frontend/src/renderer/components/settings/common/EmptyProjectState.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/common/ErrorDisplay.tsx b/apps/frontend/src/renderer/components/settings/common/ErrorDisplay.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/common/ErrorDisplay.tsx rename to apps/frontend/src/renderer/components/settings/common/ErrorDisplay.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/common/InitializationGuard.tsx b/apps/frontend/src/renderer/components/settings/common/InitializationGuard.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/common/InitializationGuard.tsx rename to apps/frontend/src/renderer/components/settings/common/InitializationGuard.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/common/index.ts b/apps/frontend/src/renderer/components/settings/common/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/common/index.ts rename to apps/frontend/src/renderer/components/settings/common/index.ts diff --git a/auto-claude-ui/src/renderer/components/settings/hooks/useSettings.ts b/apps/frontend/src/renderer/components/settings/hooks/useSettings.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/hooks/useSettings.ts rename to apps/frontend/src/renderer/components/settings/hooks/useSettings.ts diff --git a/auto-claude-ui/src/renderer/components/settings/index.ts b/apps/frontend/src/renderer/components/settings/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/index.ts rename to apps/frontend/src/renderer/components/settings/index.ts diff --git a/auto-claude-ui/src/renderer/components/settings/integrations/GitHubIntegration.tsx b/apps/frontend/src/renderer/components/settings/integrations/GitHubIntegration.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/integrations/GitHubIntegration.tsx rename to apps/frontend/src/renderer/components/settings/integrations/GitHubIntegration.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/integrations/LinearIntegration.tsx b/apps/frontend/src/renderer/components/settings/integrations/LinearIntegration.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/integrations/LinearIntegration.tsx rename to apps/frontend/src/renderer/components/settings/integrations/LinearIntegration.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/integrations/index.ts b/apps/frontend/src/renderer/components/settings/integrations/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/integrations/index.ts rename to apps/frontend/src/renderer/components/settings/integrations/index.ts diff --git a/auto-claude-ui/src/renderer/components/settings/sections/SectionRouter.tsx b/apps/frontend/src/renderer/components/settings/sections/SectionRouter.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/sections/SectionRouter.tsx rename to apps/frontend/src/renderer/components/settings/sections/SectionRouter.tsx diff --git a/auto-claude-ui/src/renderer/components/settings/sections/index.ts b/apps/frontend/src/renderer/components/settings/sections/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/sections/index.ts rename to apps/frontend/src/renderer/components/settings/sections/index.ts diff --git a/auto-claude-ui/src/renderer/components/settings/utils/hookProxyFactory.ts b/apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/utils/hookProxyFactory.ts rename to apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts diff --git a/auto-claude-ui/src/renderer/components/settings/utils/index.ts b/apps/frontend/src/renderer/components/settings/utils/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/settings/utils/index.ts rename to apps/frontend/src/renderer/components/settings/utils/index.ts diff --git a/auto-claude-ui/src/renderer/components/task-detail/README.md b/apps/frontend/src/renderer/components/task-detail/README.md similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/README.md rename to apps/frontend/src/renderer/components/task-detail/README.md diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskActions.tsx b/apps/frontend/src/renderer/components/task-detail/TaskActions.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskActions.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskActions.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskDetailModal.tsx b/apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskDetailModal.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskDetailModal.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskDetailPanel.tsx b/apps/frontend/src/renderer/components/task-detail/TaskDetailPanel.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskDetailPanel.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskDetailPanel.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskHeader.tsx b/apps/frontend/src/renderer/components/task-detail/TaskHeader.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskHeader.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskHeader.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskLogs.tsx b/apps/frontend/src/renderer/components/task-detail/TaskLogs.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskLogs.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskLogs.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskMetadata.tsx b/apps/frontend/src/renderer/components/task-detail/TaskMetadata.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskMetadata.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskMetadata.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskProgress.tsx b/apps/frontend/src/renderer/components/task-detail/TaskProgress.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskProgress.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskProgress.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskReview.tsx b/apps/frontend/src/renderer/components/task-detail/TaskReview.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskReview.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskReview.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskSubtasks.tsx b/apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskSubtasks.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskSubtasks.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/TaskWarnings.tsx b/apps/frontend/src/renderer/components/task-detail/TaskWarnings.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/TaskWarnings.tsx rename to apps/frontend/src/renderer/components/task-detail/TaskWarnings.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/hooks/useTaskDetail.ts b/apps/frontend/src/renderer/components/task-detail/hooks/useTaskDetail.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/hooks/useTaskDetail.ts rename to apps/frontend/src/renderer/components/task-detail/hooks/useTaskDetail.ts diff --git a/auto-claude-ui/src/renderer/components/task-detail/index.ts b/apps/frontend/src/renderer/components/task-detail/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/index.ts rename to apps/frontend/src/renderer/components/task-detail/index.ts diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/ConflictDetailsDialog.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/DiffViewDialog.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/DiscardDialog.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/DiscardDialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/DiscardDialog.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/DiscardDialog.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/MergePreviewSummary.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/QAFeedbackSection.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/README.md b/apps/frontend/src/renderer/components/task-detail/task-review/README.md similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/README.md rename to apps/frontend/src/renderer/components/task-detail/task-review/README.md diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/StagedSuccessMessage.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceMessages.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/WorkspaceStatus.tsx diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/index.ts b/apps/frontend/src/renderer/components/task-detail/task-review/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/index.ts rename to apps/frontend/src/renderer/components/task-detail/task-review/index.ts diff --git a/auto-claude-ui/src/renderer/components/task-detail/task-review/utils.tsx b/apps/frontend/src/renderer/components/task-detail/task-review/utils.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/task-detail/task-review/utils.tsx rename to apps/frontend/src/renderer/components/task-detail/task-review/utils.tsx diff --git a/auto-claude-ui/src/renderer/components/terminal/README.md b/apps/frontend/src/renderer/components/terminal/README.md similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/README.md rename to apps/frontend/src/renderer/components/terminal/README.md diff --git a/auto-claude-ui/src/renderer/components/terminal/REFACTORING_SUMMARY.md b/apps/frontend/src/renderer/components/terminal/REFACTORING_SUMMARY.md similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/REFACTORING_SUMMARY.md rename to apps/frontend/src/renderer/components/terminal/REFACTORING_SUMMARY.md diff --git a/auto-claude-ui/src/renderer/components/terminal/TaskSelector.tsx b/apps/frontend/src/renderer/components/terminal/TaskSelector.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/TaskSelector.tsx rename to apps/frontend/src/renderer/components/terminal/TaskSelector.tsx diff --git a/auto-claude-ui/src/renderer/components/terminal/TerminalHeader.tsx b/apps/frontend/src/renderer/components/terminal/TerminalHeader.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/TerminalHeader.tsx rename to apps/frontend/src/renderer/components/terminal/TerminalHeader.tsx diff --git a/auto-claude-ui/src/renderer/components/terminal/TerminalTitle.tsx b/apps/frontend/src/renderer/components/terminal/TerminalTitle.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/TerminalTitle.tsx rename to apps/frontend/src/renderer/components/terminal/TerminalTitle.tsx diff --git a/auto-claude-ui/src/renderer/components/terminal/index.ts b/apps/frontend/src/renderer/components/terminal/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/index.ts rename to apps/frontend/src/renderer/components/terminal/index.ts diff --git a/auto-claude-ui/src/renderer/components/terminal/types.ts b/apps/frontend/src/renderer/components/terminal/types.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/types.ts rename to apps/frontend/src/renderer/components/terminal/types.ts diff --git a/auto-claude-ui/src/renderer/components/terminal/useAutoNaming.ts b/apps/frontend/src/renderer/components/terminal/useAutoNaming.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/useAutoNaming.ts rename to apps/frontend/src/renderer/components/terminal/useAutoNaming.ts diff --git a/auto-claude-ui/src/renderer/components/terminal/usePtyProcess.ts b/apps/frontend/src/renderer/components/terminal/usePtyProcess.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/usePtyProcess.ts rename to apps/frontend/src/renderer/components/terminal/usePtyProcess.ts diff --git a/auto-claude-ui/src/renderer/components/terminal/useTerminalEvents.ts b/apps/frontend/src/renderer/components/terminal/useTerminalEvents.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/useTerminalEvents.ts rename to apps/frontend/src/renderer/components/terminal/useTerminalEvents.ts diff --git a/auto-claude-ui/src/renderer/components/terminal/useXterm.ts b/apps/frontend/src/renderer/components/terminal/useXterm.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/terminal/useXterm.ts rename to apps/frontend/src/renderer/components/terminal/useXterm.ts diff --git a/auto-claude-ui/src/renderer/components/ui/alert-dialog.tsx b/apps/frontend/src/renderer/components/ui/alert-dialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/alert-dialog.tsx rename to apps/frontend/src/renderer/components/ui/alert-dialog.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/badge.tsx b/apps/frontend/src/renderer/components/ui/badge.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/badge.tsx rename to apps/frontend/src/renderer/components/ui/badge.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/button.tsx b/apps/frontend/src/renderer/components/ui/button.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/button.tsx rename to apps/frontend/src/renderer/components/ui/button.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/card.tsx b/apps/frontend/src/renderer/components/ui/card.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/card.tsx rename to apps/frontend/src/renderer/components/ui/card.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/checkbox.tsx b/apps/frontend/src/renderer/components/ui/checkbox.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/checkbox.tsx rename to apps/frontend/src/renderer/components/ui/checkbox.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/collapsible.tsx b/apps/frontend/src/renderer/components/ui/collapsible.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/collapsible.tsx rename to apps/frontend/src/renderer/components/ui/collapsible.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/dialog.tsx b/apps/frontend/src/renderer/components/ui/dialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/dialog.tsx rename to apps/frontend/src/renderer/components/ui/dialog.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/dropdown-menu.tsx b/apps/frontend/src/renderer/components/ui/dropdown-menu.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/dropdown-menu.tsx rename to apps/frontend/src/renderer/components/ui/dropdown-menu.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/full-screen-dialog.tsx b/apps/frontend/src/renderer/components/ui/full-screen-dialog.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/full-screen-dialog.tsx rename to apps/frontend/src/renderer/components/ui/full-screen-dialog.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/index.ts b/apps/frontend/src/renderer/components/ui/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/index.ts rename to apps/frontend/src/renderer/components/ui/index.ts diff --git a/auto-claude-ui/src/renderer/components/ui/input.tsx b/apps/frontend/src/renderer/components/ui/input.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/input.tsx rename to apps/frontend/src/renderer/components/ui/input.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/label.tsx b/apps/frontend/src/renderer/components/ui/label.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/label.tsx rename to apps/frontend/src/renderer/components/ui/label.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/progress.tsx b/apps/frontend/src/renderer/components/ui/progress.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/progress.tsx rename to apps/frontend/src/renderer/components/ui/progress.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/radio-group.tsx b/apps/frontend/src/renderer/components/ui/radio-group.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/radio-group.tsx rename to apps/frontend/src/renderer/components/ui/radio-group.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/scroll-area.tsx b/apps/frontend/src/renderer/components/ui/scroll-area.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/scroll-area.tsx rename to apps/frontend/src/renderer/components/ui/scroll-area.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/select.tsx b/apps/frontend/src/renderer/components/ui/select.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/select.tsx rename to apps/frontend/src/renderer/components/ui/select.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/separator.tsx b/apps/frontend/src/renderer/components/ui/separator.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/separator.tsx rename to apps/frontend/src/renderer/components/ui/separator.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/switch.tsx b/apps/frontend/src/renderer/components/ui/switch.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/switch.tsx rename to apps/frontend/src/renderer/components/ui/switch.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/tabs.tsx b/apps/frontend/src/renderer/components/ui/tabs.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/tabs.tsx rename to apps/frontend/src/renderer/components/ui/tabs.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/textarea.tsx b/apps/frontend/src/renderer/components/ui/textarea.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/textarea.tsx rename to apps/frontend/src/renderer/components/ui/textarea.tsx diff --git a/auto-claude-ui/src/renderer/components/ui/tooltip.tsx b/apps/frontend/src/renderer/components/ui/tooltip.tsx similarity index 100% rename from auto-claude-ui/src/renderer/components/ui/tooltip.tsx rename to apps/frontend/src/renderer/components/ui/tooltip.tsx diff --git a/auto-claude-ui/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts b/apps/frontend/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts rename to apps/frontend/src/renderer/hooks/__tests__/useVirtualizedTree.test.ts diff --git a/auto-claude-ui/src/renderer/hooks/index.ts b/apps/frontend/src/renderer/hooks/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/index.ts rename to apps/frontend/src/renderer/hooks/index.ts diff --git a/auto-claude-ui/src/renderer/hooks/useClaudeAuth.ts b/apps/frontend/src/renderer/hooks/useClaudeAuth.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/useClaudeAuth.ts rename to apps/frontend/src/renderer/hooks/useClaudeAuth.ts diff --git a/auto-claude-ui/src/renderer/hooks/useEnvironmentConfig.ts b/apps/frontend/src/renderer/hooks/useEnvironmentConfig.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/useEnvironmentConfig.ts rename to apps/frontend/src/renderer/hooks/useEnvironmentConfig.ts diff --git a/auto-claude-ui/src/renderer/hooks/useGitHubConnection.ts b/apps/frontend/src/renderer/hooks/useGitHubConnection.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/useGitHubConnection.ts rename to apps/frontend/src/renderer/hooks/useGitHubConnection.ts diff --git a/auto-claude-ui/src/renderer/hooks/useInfrastructureStatus.ts b/apps/frontend/src/renderer/hooks/useInfrastructureStatus.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/useInfrastructureStatus.ts rename to apps/frontend/src/renderer/hooks/useInfrastructureStatus.ts diff --git a/auto-claude-ui/src/renderer/hooks/useIpc.ts b/apps/frontend/src/renderer/hooks/useIpc.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/useIpc.ts rename to apps/frontend/src/renderer/hooks/useIpc.ts diff --git a/auto-claude-ui/src/renderer/hooks/useLinearConnection.ts b/apps/frontend/src/renderer/hooks/useLinearConnection.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/useLinearConnection.ts rename to apps/frontend/src/renderer/hooks/useLinearConnection.ts diff --git a/auto-claude-ui/src/renderer/hooks/useProjectSettings.ts b/apps/frontend/src/renderer/hooks/useProjectSettings.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/useProjectSettings.ts rename to apps/frontend/src/renderer/hooks/useProjectSettings.ts diff --git a/auto-claude-ui/src/renderer/hooks/useVirtualizedTree.ts b/apps/frontend/src/renderer/hooks/useVirtualizedTree.ts similarity index 100% rename from auto-claude-ui/src/renderer/hooks/useVirtualizedTree.ts rename to apps/frontend/src/renderer/hooks/useVirtualizedTree.ts diff --git a/auto-claude-ui/src/renderer/index.html b/apps/frontend/src/renderer/index.html similarity index 100% rename from auto-claude-ui/src/renderer/index.html rename to apps/frontend/src/renderer/index.html diff --git a/auto-claude-ui/src/renderer/lib/browser-mock.ts b/apps/frontend/src/renderer/lib/browser-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/browser-mock.ts rename to apps/frontend/src/renderer/lib/browser-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/buffer-persistence.ts b/apps/frontend/src/renderer/lib/buffer-persistence.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/buffer-persistence.ts rename to apps/frontend/src/renderer/lib/buffer-persistence.ts diff --git a/auto-claude-ui/src/renderer/lib/flow-controller.ts b/apps/frontend/src/renderer/lib/flow-controller.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/flow-controller.ts rename to apps/frontend/src/renderer/lib/flow-controller.ts diff --git a/auto-claude-ui/src/renderer/lib/icons.ts b/apps/frontend/src/renderer/lib/icons.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/icons.ts rename to apps/frontend/src/renderer/lib/icons.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/README.md b/apps/frontend/src/renderer/lib/mocks/README.md similarity index 97% rename from auto-claude-ui/src/renderer/lib/mocks/README.md rename to apps/frontend/src/renderer/lib/mocks/README.md index fbb0202b..7482215b 100644 --- a/auto-claude-ui/src/renderer/lib/mocks/README.md +++ b/apps/frontend/src/renderer/lib/mocks/README.md @@ -22,7 +22,7 @@ mocks/ ├── integration-mock.ts # External integrations (Linear, GitHub) ├── changelog-mock.ts # Changelog and release operations ├── insights-mock.ts # AI insights and conversations -├── infrastructure-mock.ts # Docker, FalkorDB, ideation, updates +├── infrastructure-mock.ts # LadybugDB, memory, ideation, updates └── settings-mock.ts # App settings and version info ``` diff --git a/auto-claude-ui/src/renderer/lib/mocks/changelog-mock.ts b/apps/frontend/src/renderer/lib/mocks/changelog-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/changelog-mock.ts rename to apps/frontend/src/renderer/lib/mocks/changelog-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/claude-profile-mock.ts b/apps/frontend/src/renderer/lib/mocks/claude-profile-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/claude-profile-mock.ts rename to apps/frontend/src/renderer/lib/mocks/claude-profile-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/context-mock.ts b/apps/frontend/src/renderer/lib/mocks/context-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/context-mock.ts rename to apps/frontend/src/renderer/lib/mocks/context-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/index.ts b/apps/frontend/src/renderer/lib/mocks/index.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/index.ts rename to apps/frontend/src/renderer/lib/mocks/index.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/infrastructure-mock.ts b/apps/frontend/src/renderer/lib/mocks/infrastructure-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/infrastructure-mock.ts rename to apps/frontend/src/renderer/lib/mocks/infrastructure-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/insights-mock.ts b/apps/frontend/src/renderer/lib/mocks/insights-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/insights-mock.ts rename to apps/frontend/src/renderer/lib/mocks/insights-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/integration-mock.ts b/apps/frontend/src/renderer/lib/mocks/integration-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/integration-mock.ts rename to apps/frontend/src/renderer/lib/mocks/integration-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/mock-data.ts b/apps/frontend/src/renderer/lib/mocks/mock-data.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/mock-data.ts rename to apps/frontend/src/renderer/lib/mocks/mock-data.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/project-mock.ts b/apps/frontend/src/renderer/lib/mocks/project-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/project-mock.ts rename to apps/frontend/src/renderer/lib/mocks/project-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/roadmap-mock.ts b/apps/frontend/src/renderer/lib/mocks/roadmap-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/roadmap-mock.ts rename to apps/frontend/src/renderer/lib/mocks/roadmap-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/settings-mock.ts b/apps/frontend/src/renderer/lib/mocks/settings-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/settings-mock.ts rename to apps/frontend/src/renderer/lib/mocks/settings-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/task-mock.ts b/apps/frontend/src/renderer/lib/mocks/task-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/task-mock.ts rename to apps/frontend/src/renderer/lib/mocks/task-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/terminal-mock.ts b/apps/frontend/src/renderer/lib/mocks/terminal-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/terminal-mock.ts rename to apps/frontend/src/renderer/lib/mocks/terminal-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/mocks/workspace-mock.ts b/apps/frontend/src/renderer/lib/mocks/workspace-mock.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/mocks/workspace-mock.ts rename to apps/frontend/src/renderer/lib/mocks/workspace-mock.ts diff --git a/auto-claude-ui/src/renderer/lib/scroll-controller.ts b/apps/frontend/src/renderer/lib/scroll-controller.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/scroll-controller.ts rename to apps/frontend/src/renderer/lib/scroll-controller.ts diff --git a/auto-claude-ui/src/renderer/lib/terminal-buffer-manager.ts b/apps/frontend/src/renderer/lib/terminal-buffer-manager.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/terminal-buffer-manager.ts rename to apps/frontend/src/renderer/lib/terminal-buffer-manager.ts diff --git a/auto-claude-ui/src/renderer/lib/utils.ts b/apps/frontend/src/renderer/lib/utils.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/utils.ts rename to apps/frontend/src/renderer/lib/utils.ts diff --git a/auto-claude-ui/src/renderer/lib/webgl-context-manager.ts b/apps/frontend/src/renderer/lib/webgl-context-manager.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/webgl-context-manager.ts rename to apps/frontend/src/renderer/lib/webgl-context-manager.ts diff --git a/auto-claude-ui/src/renderer/lib/webgl-utils.ts b/apps/frontend/src/renderer/lib/webgl-utils.ts similarity index 100% rename from auto-claude-ui/src/renderer/lib/webgl-utils.ts rename to apps/frontend/src/renderer/lib/webgl-utils.ts diff --git a/auto-claude-ui/src/renderer/main.tsx b/apps/frontend/src/renderer/main.tsx similarity index 100% rename from auto-claude-ui/src/renderer/main.tsx rename to apps/frontend/src/renderer/main.tsx diff --git a/auto-claude-ui/src/renderer/stores/changelog-store.ts b/apps/frontend/src/renderer/stores/changelog-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/changelog-store.ts rename to apps/frontend/src/renderer/stores/changelog-store.ts diff --git a/auto-claude-ui/src/renderer/stores/claude-profile-store.ts b/apps/frontend/src/renderer/stores/claude-profile-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/claude-profile-store.ts rename to apps/frontend/src/renderer/stores/claude-profile-store.ts diff --git a/auto-claude-ui/src/renderer/stores/context-store.ts b/apps/frontend/src/renderer/stores/context-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/context-store.ts rename to apps/frontend/src/renderer/stores/context-store.ts diff --git a/auto-claude-ui/src/renderer/stores/file-explorer-store.ts b/apps/frontend/src/renderer/stores/file-explorer-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/file-explorer-store.ts rename to apps/frontend/src/renderer/stores/file-explorer-store.ts diff --git a/auto-claude-ui/src/renderer/stores/github-store.ts b/apps/frontend/src/renderer/stores/github-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/github-store.ts rename to apps/frontend/src/renderer/stores/github-store.ts diff --git a/auto-claude-ui/src/renderer/stores/ideation-store.ts b/apps/frontend/src/renderer/stores/ideation-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/ideation-store.ts rename to apps/frontend/src/renderer/stores/ideation-store.ts diff --git a/auto-claude-ui/src/renderer/stores/insights-store.ts b/apps/frontend/src/renderer/stores/insights-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/insights-store.ts rename to apps/frontend/src/renderer/stores/insights-store.ts diff --git a/auto-claude-ui/src/renderer/stores/project-store.ts b/apps/frontend/src/renderer/stores/project-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/project-store.ts rename to apps/frontend/src/renderer/stores/project-store.ts diff --git a/auto-claude-ui/src/renderer/stores/rate-limit-store.ts b/apps/frontend/src/renderer/stores/rate-limit-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/rate-limit-store.ts rename to apps/frontend/src/renderer/stores/rate-limit-store.ts diff --git a/auto-claude-ui/src/renderer/stores/release-store.ts b/apps/frontend/src/renderer/stores/release-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/release-store.ts rename to apps/frontend/src/renderer/stores/release-store.ts diff --git a/auto-claude-ui/src/renderer/stores/roadmap-store.ts b/apps/frontend/src/renderer/stores/roadmap-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/roadmap-store.ts rename to apps/frontend/src/renderer/stores/roadmap-store.ts diff --git a/auto-claude-ui/src/renderer/stores/settings-store.ts b/apps/frontend/src/renderer/stores/settings-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/settings-store.ts rename to apps/frontend/src/renderer/stores/settings-store.ts diff --git a/auto-claude-ui/src/renderer/stores/task-store.ts b/apps/frontend/src/renderer/stores/task-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/task-store.ts rename to apps/frontend/src/renderer/stores/task-store.ts diff --git a/auto-claude-ui/src/renderer/stores/terminal-store.ts b/apps/frontend/src/renderer/stores/terminal-store.ts similarity index 100% rename from auto-claude-ui/src/renderer/stores/terminal-store.ts rename to apps/frontend/src/renderer/stores/terminal-store.ts diff --git a/auto-claude-ui/src/renderer/styles/globals.css b/apps/frontend/src/renderer/styles/globals.css similarity index 100% rename from auto-claude-ui/src/renderer/styles/globals.css rename to apps/frontend/src/renderer/styles/globals.css diff --git a/auto-claude-ui/src/shared/__tests__/progress.test.ts b/apps/frontend/src/shared/__tests__/progress.test.ts similarity index 100% rename from auto-claude-ui/src/shared/__tests__/progress.test.ts rename to apps/frontend/src/shared/__tests__/progress.test.ts diff --git a/auto-claude-ui/src/shared/constants.ts b/apps/frontend/src/shared/constants.ts similarity index 100% rename from auto-claude-ui/src/shared/constants.ts rename to apps/frontend/src/shared/constants.ts diff --git a/auto-claude-ui/src/shared/constants/changelog.ts b/apps/frontend/src/shared/constants/changelog.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/changelog.ts rename to apps/frontend/src/shared/constants/changelog.ts diff --git a/auto-claude-ui/src/shared/constants/config.ts b/apps/frontend/src/shared/constants/config.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/config.ts rename to apps/frontend/src/shared/constants/config.ts diff --git a/auto-claude-ui/src/shared/constants/github.ts b/apps/frontend/src/shared/constants/github.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/github.ts rename to apps/frontend/src/shared/constants/github.ts diff --git a/auto-claude-ui/src/shared/constants/ideation.ts b/apps/frontend/src/shared/constants/ideation.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/ideation.ts rename to apps/frontend/src/shared/constants/ideation.ts diff --git a/auto-claude-ui/src/shared/constants/index.ts b/apps/frontend/src/shared/constants/index.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/index.ts rename to apps/frontend/src/shared/constants/index.ts diff --git a/auto-claude-ui/src/shared/constants/ipc.ts b/apps/frontend/src/shared/constants/ipc.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/ipc.ts rename to apps/frontend/src/shared/constants/ipc.ts diff --git a/auto-claude-ui/src/shared/constants/models.ts b/apps/frontend/src/shared/constants/models.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/models.ts rename to apps/frontend/src/shared/constants/models.ts diff --git a/auto-claude-ui/src/shared/constants/roadmap.ts b/apps/frontend/src/shared/constants/roadmap.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/roadmap.ts rename to apps/frontend/src/shared/constants/roadmap.ts diff --git a/auto-claude-ui/src/shared/constants/task.ts b/apps/frontend/src/shared/constants/task.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/task.ts rename to apps/frontend/src/shared/constants/task.ts diff --git a/auto-claude-ui/src/shared/constants/themes.ts b/apps/frontend/src/shared/constants/themes.ts similarity index 100% rename from auto-claude-ui/src/shared/constants/themes.ts rename to apps/frontend/src/shared/constants/themes.ts diff --git a/auto-claude-ui/src/shared/progress.ts b/apps/frontend/src/shared/progress.ts similarity index 100% rename from auto-claude-ui/src/shared/progress.ts rename to apps/frontend/src/shared/progress.ts diff --git a/auto-claude-ui/src/shared/types.ts b/apps/frontend/src/shared/types.ts similarity index 100% rename from auto-claude-ui/src/shared/types.ts rename to apps/frontend/src/shared/types.ts diff --git a/auto-claude-ui/src/shared/types/agent.ts b/apps/frontend/src/shared/types/agent.ts similarity index 100% rename from auto-claude-ui/src/shared/types/agent.ts rename to apps/frontend/src/shared/types/agent.ts diff --git a/auto-claude-ui/src/shared/types/app-update.ts b/apps/frontend/src/shared/types/app-update.ts similarity index 100% rename from auto-claude-ui/src/shared/types/app-update.ts rename to apps/frontend/src/shared/types/app-update.ts diff --git a/auto-claude-ui/src/shared/types/changelog.ts b/apps/frontend/src/shared/types/changelog.ts similarity index 100% rename from auto-claude-ui/src/shared/types/changelog.ts rename to apps/frontend/src/shared/types/changelog.ts diff --git a/auto-claude-ui/src/shared/types/common.ts b/apps/frontend/src/shared/types/common.ts similarity index 100% rename from auto-claude-ui/src/shared/types/common.ts rename to apps/frontend/src/shared/types/common.ts diff --git a/auto-claude-ui/src/shared/types/index.ts b/apps/frontend/src/shared/types/index.ts similarity index 100% rename from auto-claude-ui/src/shared/types/index.ts rename to apps/frontend/src/shared/types/index.ts diff --git a/auto-claude-ui/src/shared/types/insights.ts b/apps/frontend/src/shared/types/insights.ts similarity index 100% rename from auto-claude-ui/src/shared/types/insights.ts rename to apps/frontend/src/shared/types/insights.ts diff --git a/auto-claude-ui/src/shared/types/integrations.ts b/apps/frontend/src/shared/types/integrations.ts similarity index 100% rename from auto-claude-ui/src/shared/types/integrations.ts rename to apps/frontend/src/shared/types/integrations.ts diff --git a/auto-claude-ui/src/shared/types/ipc.ts b/apps/frontend/src/shared/types/ipc.ts similarity index 100% rename from auto-claude-ui/src/shared/types/ipc.ts rename to apps/frontend/src/shared/types/ipc.ts diff --git a/auto-claude-ui/src/shared/types/project.ts b/apps/frontend/src/shared/types/project.ts similarity index 100% rename from auto-claude-ui/src/shared/types/project.ts rename to apps/frontend/src/shared/types/project.ts diff --git a/auto-claude-ui/src/shared/types/roadmap.ts b/apps/frontend/src/shared/types/roadmap.ts similarity index 100% rename from auto-claude-ui/src/shared/types/roadmap.ts rename to apps/frontend/src/shared/types/roadmap.ts diff --git a/auto-claude-ui/src/shared/types/settings.ts b/apps/frontend/src/shared/types/settings.ts similarity index 100% rename from auto-claude-ui/src/shared/types/settings.ts rename to apps/frontend/src/shared/types/settings.ts diff --git a/auto-claude-ui/src/shared/types/task.ts b/apps/frontend/src/shared/types/task.ts similarity index 100% rename from auto-claude-ui/src/shared/types/task.ts rename to apps/frontend/src/shared/types/task.ts diff --git a/auto-claude-ui/src/shared/types/terminal-session.ts b/apps/frontend/src/shared/types/terminal-session.ts similarity index 100% rename from auto-claude-ui/src/shared/types/terminal-session.ts rename to apps/frontend/src/shared/types/terminal-session.ts diff --git a/auto-claude-ui/src/shared/types/terminal.ts b/apps/frontend/src/shared/types/terminal.ts similarity index 100% rename from auto-claude-ui/src/shared/types/terminal.ts rename to apps/frontend/src/shared/types/terminal.ts diff --git a/auto-claude-ui/src/shared/utils/debug-logger.ts b/apps/frontend/src/shared/utils/debug-logger.ts similarity index 100% rename from auto-claude-ui/src/shared/utils/debug-logger.ts rename to apps/frontend/src/shared/utils/debug-logger.ts diff --git a/auto-claude-ui/src/shared/utils/shell-escape.ts b/apps/frontend/src/shared/utils/shell-escape.ts similarity index 100% rename from auto-claude-ui/src/shared/utils/shell-escape.ts rename to apps/frontend/src/shared/utils/shell-escape.ts diff --git a/auto-claude-ui/tsconfig.json b/apps/frontend/tsconfig.json similarity index 68% rename from auto-claude-ui/tsconfig.json rename to apps/frontend/tsconfig.json index 1cfff5f5..30866c15 100644 --- a/auto-claude-ui/tsconfig.json +++ b/apps/frontend/tsconfig.json @@ -15,7 +15,11 @@ "baseUrl": ".", "paths": { "@/*": ["src/renderer/*"], - "@shared/*": ["src/shared/*"] + "@shared/*": ["src/shared/*"], + "@features/*": ["src/renderer/features/*"], + "@components/*": ["src/renderer/shared/components/*"], + "@hooks/*": ["src/renderer/shared/hooks/*"], + "@lib/*": ["src/renderer/shared/lib/*"] } }, "include": ["src/**/*"], diff --git a/auto-claude-ui/vitest.config.ts b/apps/frontend/vitest.config.ts similarity index 100% rename from auto-claude-ui/vitest.config.ts rename to apps/frontend/vitest.config.ts diff --git a/auto-claude-ui/.husky/pre-commit b/auto-claude-ui/.husky/pre-commit deleted file mode 100644 index 98475b50..00000000 --- a/auto-claude-ui/.husky/pre-commit +++ /dev/null @@ -1 +0,0 @@ -pnpm test diff --git a/auto-claude-ui/.npmrc b/auto-claude-ui/.npmrc deleted file mode 100644 index 9bfb782b..00000000 --- a/auto-claude-ui/.npmrc +++ /dev/null @@ -1 +0,0 @@ -side-effects-cache=true diff --git a/auto-claude-ui/README.md b/auto-claude-ui/README.md deleted file mode 100644 index c4230d1c..00000000 --- a/auto-claude-ui/README.md +++ /dev/null @@ -1,131 +0,0 @@ -# Auto Claude UI - -A desktop application for managing AI-driven development tasks using the Auto Claude autonomous coding framework. - -## Quick Start - -```bash -# 1. Clone the repo (if you haven't already) -git clone https://github.com/AndyMik90/Auto-Claude.git -cd Auto-Claude/auto-claude-ui - -# 2. Install dependencies -npm install - -# 3. Build the desktop app -npm run package:win # Windows -npm run package:mac # macOS -npm run package:linux # Linux - -# 4. Run the app -# Windows: .\dist\win-unpacked\Auto Claude.exe -# macOS: open dist/mac-arm64/Auto\ Claude.app -# Linux: ./dist/linux-unpacked/auto-claude -``` - -## Prerequisites - -- Node.js 18+ -- npm or pnpm -- Python 3.10+ (for auto-claude backend) -- **Windows only**: Visual Studio Build Tools 2022 with "Desktop development with C++" workload -- **Windows only**: Developer Mode enabled (Settings → System → For developers) - -## How to Run - -### Building for Production (Recommended) - -Build the Electron desktop app for your platform: - -```bash -# Build for Windows -npm run package:win - -# Build for macOS -npm run package:mac - -# Build for Linux -npm run package:linux -``` - -### Running the Production Build - -After building, run the application from the `dist` folder: - -```bash -# Windows - run the executable -.\dist\win-unpacked\Auto Claude.exe - -# Windows - or use the installer -.\dist\Auto Claude Setup X.X.X.exe - -# macOS -open dist/mac-arm64/Auto\ Claude.app - -# Linux -./dist/linux-unpacked/auto-claude -``` - -### Development Mode - -For development with hot reload (optional): - -```bash -npm run dev -``` - -> **Note**: Some features like auto-updates only work in packaged builds. - -## Distribution Files - -After packaging, the `dist` folder contains: - -| Platform | Files | -|----------|-------| -| macOS | `Auto Claude.app`, `.dmg`, `.zip` | -| Windows | `Auto Claude Setup X.X.X.exe` (installer), `.zip`, `win-unpacked/` | -| Linux | `.AppImage`, `.deb`, `linux-unpacked/` | - -## Testing - -```bash -# Run tests -npm run test -``` - -## Linting - -```bash -# Run ESLint -npm run lint - -# Run type checking -npm run typecheck -``` - -## Features - -- **Project Management**: Add, configure, and switch between multiple projects -- **Kanban Board**: Visual task board with columns for Backlog, In Progress, AI Review, Human Review, and Done -- **Task Creation Wizard**: Form-based interface for creating new tasks -- **Real-Time Progress**: Live updates during agent execution -- **Human Review Workflow**: Review QA results and provide feedback -- **Theme Support**: Light and dark mode -- **Auto Updates**: Automatic update notifications - -## Tech Stack - -- **Framework**: Electron + React 18 (TypeScript) -- **Build Tool**: electron-vite + electron-builder -- **UI Components**: Radix UI (shadcn/ui pattern) -- **Styling**: TailwindCSS -- **State Management**: Zustand - -## Environment Variables - -- `CLAUDE_CODE_OAUTH_TOKEN`: OAuth token for Claude Code SDK (from auto-claude/.env) -- `FALKORDB_URL`: FalkorDB connection URL (optional) - -## License - -AGPL-3.0 diff --git a/auto-claude-ui/pnpm-lock.yaml b/auto-claude-ui/pnpm-lock.yaml deleted file mode 100644 index 808e9cb7..00000000 --- a/auto-claude-ui/pnpm-lock.yaml +++ /dev/null @@ -1,9588 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -overrides: - electron-builder-squirrel-windows: ^26.0.12 - dmg-builder: ^26.0.12 - node-pty: npm:@lydell/node-pty@^1.1.0 - -importers: - - .: - dependencies: - '@dnd-kit/core': - specifier: ^6.3.1 - version: 6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@dnd-kit/sortable': - specifier: ^10.0.0 - version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) - '@dnd-kit/utilities': - specifier: ^3.2.2 - version: 3.2.2(react@19.2.3) - '@lydell/node-pty': - specifier: ^1.1.0 - version: 1.1.0 - '@radix-ui/react-alert-dialog': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-checkbox': - specifier: ^1.1.4 - version: 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-collapsible': - specifier: ^1.1.3 - version: 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-dialog': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-dropdown-menu': - specifier: ^2.1.16 - version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-progress': - specifier: ^1.1.8 - version: 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-radio-group': - specifier: ^1.3.8 - version: 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-scroll-area': - specifier: ^1.2.10 - version: 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-select': - specifier: ^2.2.6 - version: 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-separator': - specifier: ^1.1.8 - version: 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': - specifier: ^1.2.4 - version: 1.2.4(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-switch': - specifier: ^1.2.6 - version: 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-tabs': - specifier: ^1.1.13 - version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-toast': - specifier: ^1.2.15 - version: 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-tooltip': - specifier: ^1.2.8 - version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tailwindcss/typography': - specifier: ^0.5.19 - version: 0.5.19(tailwindcss@4.1.18) - '@tanstack/react-virtual': - specifier: ^3.13.13 - version: 3.13.13(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@xterm/addon-fit': - specifier: ^0.10.0 - version: 0.10.0(@xterm/xterm@5.5.0) - '@xterm/addon-serialize': - specifier: ^0.13.0 - version: 0.13.0(@xterm/xterm@5.5.0) - '@xterm/addon-web-links': - specifier: ^0.11.0 - version: 0.11.0(@xterm/xterm@5.5.0) - '@xterm/addon-webgl': - specifier: ^0.18.0 - version: 0.18.0(@xterm/xterm@5.5.0) - '@xterm/xterm': - specifier: ^5.5.0 - version: 5.5.0 - chokidar: - specifier: ^5.0.0 - version: 5.0.0 - class-variance-authority: - specifier: ^0.7.1 - version: 0.7.1 - clsx: - specifier: ^2.1.1 - version: 2.1.1 - electron-updater: - specifier: ^6.6.2 - version: 6.6.2 - lucide-react: - specifier: ^0.560.0 - version: 0.560.0(react@19.2.3) - motion: - specifier: ^12.23.26 - version: 12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: - specifier: ^19.2.3 - version: 19.2.3 - react-dom: - specifier: ^19.2.3 - version: 19.2.3(react@19.2.3) - react-markdown: - specifier: ^10.1.0 - version: 10.1.0(@types/react@19.2.7)(react@19.2.3) - react-resizable-panels: - specifier: ^3.0.6 - version: 3.0.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - remark-gfm: - specifier: ^4.0.1 - version: 4.0.1 - tailwind-merge: - specifier: ^3.4.0 - version: 3.4.0 - uuid: - specifier: ^13.0.0 - version: 13.0.0 - zustand: - specifier: ^5.0.9 - version: 5.0.9(@types/react@19.2.7)(react@19.2.3) - devDependencies: - '@electron-toolkit/preload': - specifier: ^3.0.2 - version: 3.0.2(electron@39.2.7) - '@electron-toolkit/utils': - specifier: ^4.0.0 - version: 4.0.0(electron@39.2.7) - '@electron/rebuild': - specifier: ^3.7.1 - version: 3.7.2 - '@eslint/js': - specifier: ^9.39.1 - version: 9.39.2 - '@playwright/test': - specifier: ^1.52.0 - version: 1.57.0 - '@tailwindcss/postcss': - specifier: ^4.1.17 - version: 4.1.18 - '@testing-library/react': - specifier: ^16.1.0 - version: 16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@types/node': - specifier: ^25.0.0 - version: 25.0.3 - '@types/react': - specifier: ^19.2.7 - version: 19.2.7 - '@types/react-dom': - specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.7) - '@types/uuid': - specifier: ^10.0.0 - version: 10.0.0 - '@vitejs/plugin-react': - specifier: ^5.1.2 - version: 5.1.2(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)) - autoprefixer: - specifier: ^10.4.22 - version: 10.4.23(postcss@8.5.6) - electron: - specifier: ^39.2.6 - version: 39.2.7 - electron-builder: - specifier: ^26.0.12 - version: 26.0.12(electron-builder-squirrel-windows@26.0.12) - electron-vite: - specifier: ^5.0.0 - version: 5.0.0(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)) - eslint: - specifier: ^9.39.1 - version: 9.39.2(jiti@2.6.1) - eslint-plugin-react: - specifier: ^7.37.5 - version: 7.37.5(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-react-hooks: - specifier: ^7.0.1 - version: 7.0.1(eslint@9.39.2(jiti@2.6.1)) - globals: - specifier: ^16.5.0 - version: 16.5.0 - husky: - specifier: ^9.1.7 - version: 9.1.7 - jsdom: - specifier: ^26.0.0 - version: 26.1.0 - lint-staged: - specifier: ^16.2.7 - version: 16.2.7 - postcss: - specifier: ^8.5.6 - version: 8.5.6 - tailwindcss: - specifier: ^4.1.17 - version: 4.1.18 - typescript: - specifier: ^5.9.3 - version: 5.9.3 - typescript-eslint: - specifier: ^8.49.0 - version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - vite: - specifier: ^7.2.7 - version: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2) - vitest: - specifier: ^4.0.15 - version: 4.0.16(@types/node@25.0.3)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(yaml@2.8.2) - -packages: - - 7zip-bin@5.2.0: - resolution: {integrity: sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==} - - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - - '@asamuzakjp/css-color@3.2.0': - resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} - - '@babel/code-frame@7.27.1': - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.28.5': - resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.28.5': - resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.28.5': - resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.27.2': - resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.27.1': - resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.28.3': - resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.27.1': - resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.28.4': - resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.28.5': - resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-transform-arrow-functions@7.27.1': - resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-self@7.27.1': - resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.27.1': - resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/runtime@7.28.4': - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} - engines: {node: '>=6.9.0'} - - '@babel/template@7.27.2': - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.28.5': - resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.28.5': - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} - engines: {node: '>=6.9.0'} - - '@csstools/color-helpers@5.1.0': - resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} - engines: {node: '>=18'} - - '@csstools/css-calc@2.1.4': - resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-color-parser@3.1.0': - resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-parser-algorithms@3.0.5': - resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-tokenizer@3.0.4': - resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} - engines: {node: '>=18'} - - '@develar/schema-utils@2.6.5': - resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==} - engines: {node: '>= 8.9.0'} - - '@dnd-kit/accessibility@3.1.1': - resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==} - peerDependencies: - react: '>=16.8.0' - - '@dnd-kit/core@6.3.1': - resolution: {integrity: sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - - '@dnd-kit/sortable@10.0.0': - resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==} - peerDependencies: - '@dnd-kit/core': ^6.3.0 - react: '>=16.8.0' - - '@dnd-kit/utilities@3.2.2': - resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} - peerDependencies: - react: '>=16.8.0' - - '@electron-toolkit/preload@3.0.2': - resolution: {integrity: sha512-TWWPToXd8qPRfSXwzf5KVhpXMfONaUuRAZJHsKthKgZR/+LqX1dZVSSClQ8OTAEduvLGdecljCsoT2jSshfoUg==} - peerDependencies: - electron: '>=13.0.0' - - '@electron-toolkit/utils@4.0.0': - resolution: {integrity: sha512-qXSntwEzluSzKl4z5yFNBknmPGjPa3zFhE4mp9+h0cgokY5ornAeP+CJQDBhKsL1S58aOQfcwkD3NwLZCl+64g==} - peerDependencies: - electron: '>=13.0.0' - - '@electron/asar@3.2.18': - resolution: {integrity: sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==} - engines: {node: '>=10.12.0'} - hasBin: true - - '@electron/asar@3.4.1': - resolution: {integrity: sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==} - engines: {node: '>=10.12.0'} - hasBin: true - - '@electron/fuses@1.8.0': - resolution: {integrity: sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==} - hasBin: true - - '@electron/get@2.0.3': - resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} - engines: {node: '>=12'} - - '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': - resolution: {tarball: https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2} - version: 10.2.0-electron.1 - engines: {node: '>=12.13.0'} - hasBin: true - - '@electron/notarize@2.5.0': - resolution: {integrity: sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==} - engines: {node: '>= 10.0.0'} - - '@electron/osx-sign@1.3.1': - resolution: {integrity: sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==} - engines: {node: '>=12.0.0'} - hasBin: true - - '@electron/rebuild@3.7.0': - resolution: {integrity: sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==} - engines: {node: '>=12.13.0'} - hasBin: true - - '@electron/rebuild@3.7.2': - resolution: {integrity: sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg==} - engines: {node: '>=12.13.0'} - hasBin: true - - '@electron/universal@2.0.1': - resolution: {integrity: sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==} - engines: {node: '>=16.4'} - - '@electron/windows-sign@1.2.2': - resolution: {integrity: sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==} - engines: {node: '>=14.14'} - hasBin: true - - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/aix-ppc64@0.27.2': - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm64@0.27.2': - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-arm@0.27.2': - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/android-x64@0.27.2': - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-arm64@0.27.2': - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/darwin-x64@0.27.2': - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-arm64@0.27.2': - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.27.2': - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm64@0.27.2': - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-arm@0.27.2': - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.27.2': - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.27.2': - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.27.2': - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.27.2': - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.27.2': - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.27.2': - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.27.2': - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-arm64@0.27.2': - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.27.2': - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-arm64@0.27.2': - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.27.2': - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/openharmony-arm64@0.27.2': - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.27.2': - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.27.2': - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.27.2': - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.27.2': - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@eslint-community/eslint-utils@4.9.0': - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.21.1': - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.3.3': - resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.39.2': - resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@floating-ui/core@1.7.3': - resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} - - '@floating-ui/dom@1.7.4': - resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} - - '@floating-ui/react-dom@2.1.6': - resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - - '@floating-ui/utils@0.2.10': - resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} - - '@gar/promisify@1.1.3': - resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} - - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} - engines: {node: 20 || >=22} - - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - - '@lydell/node-pty-darwin-arm64@1.1.0': - resolution: {integrity: sha512-7kFD+owAA61qmhJCtoMbqj3Uvff3YHDiU+4on5F2vQdcMI3MuwGi7dM6MkFG/yuzpw8LF2xULpL71tOPUfxs0w==} - cpu: [arm64] - os: [darwin] - - '@lydell/node-pty-darwin-x64@1.1.0': - resolution: {integrity: sha512-XZdvqj5FjAMjH8bdp0YfaZjur5DrCIDD1VYiE9EkkYVMDQqRUPHYV3U8BVEQVT9hYfjmpr7dNaELF2KyISWSNA==} - cpu: [x64] - os: [darwin] - - '@lydell/node-pty-linux-arm64@1.1.0': - resolution: {integrity: sha512-yyDBmalCfHpLiQMT2zyLcqL2Fay4Xy7rIs8GH4dqKLnEviMvPGOK7LADVkKAsbsyXBSISL3Lt1m1MtxhPH6ckg==} - cpu: [arm64] - os: [linux] - - '@lydell/node-pty-linux-x64@1.1.0': - resolution: {integrity: sha512-NcNqRTD14QT+vXcEuqSSvmWY+0+WUBn2uRE8EN0zKtDpIEr9d+YiFj16Uqds6QfcLCHfZmC+Ls7YzwTaqDnanA==} - cpu: [x64] - os: [linux] - - '@lydell/node-pty-win32-arm64@1.1.0': - resolution: {integrity: sha512-JOMbCou+0fA7d/m97faIIfIU0jOv8sn2OR7tI45u3AmldKoKoLP8zHY6SAvDDnI3fccO1R2HeR1doVjpS7HM0w==} - cpu: [arm64] - os: [win32] - - '@lydell/node-pty-win32-x64@1.1.0': - resolution: {integrity: sha512-3N56BZ+WDFnUMYRtsrr7Ky2mhWGl9xXcyqR6cexfuCqcz9RNWL+KoXRv/nZylY5dYaXkft4JaR1uVu+roiZDAw==} - cpu: [x64] - os: [win32] - - '@lydell/node-pty@1.1.0': - resolution: {integrity: sha512-VDD8LtlMTOrPKWMXUAcB9+LTktzuunqrMwkYR1DMRBkS6LQrCt+0/Ws1o2rMml/n3guePpS7cxhHF7Nm5K4iMw==} - - '@malept/cross-spawn-promise@2.0.0': - resolution: {integrity: sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==} - engines: {node: '>= 12.13.0'} - - '@malept/flatpak-bundler@0.4.0': - resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==} - engines: {node: '>= 10.0.0'} - - '@npmcli/fs@2.1.2': - resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - '@npmcli/move-file@2.0.1': - resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This functionality has been moved to @npmcli/fs - - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - - '@playwright/test@1.57.0': - resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==} - engines: {node: '>=18'} - hasBin: true - - '@radix-ui/number@1.1.1': - resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} - - '@radix-ui/primitive@1.1.3': - resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - - '@radix-ui/react-alert-dialog@1.1.15': - resolution: {integrity: sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-arrow@1.1.7': - resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-checkbox@1.3.3': - resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-collapsible@1.1.12': - resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-collection@1.1.7': - resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-compose-refs@1.1.2': - resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-context@1.1.2': - resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-context@1.1.3': - resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-dialog@1.1.15': - resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-direction@1.1.1': - resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-dismissable-layer@1.1.11': - resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-dropdown-menu@2.1.16': - resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-focus-guards@1.1.3': - resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-focus-scope@1.1.7': - resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-id@1.1.1': - resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-menu@2.1.16': - resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-popper@1.2.8': - resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-portal@1.1.9': - resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-presence@1.1.5': - resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-primitive@2.1.3': - resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-primitive@2.1.4': - resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-progress@1.1.8': - resolution: {integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-radio-group@1.3.8': - resolution: {integrity: sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-roving-focus@1.1.11': - resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-scroll-area@1.2.10': - resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-select@2.2.6': - resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-separator@1.1.8': - resolution: {integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-slot@1.2.3': - resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-slot@1.2.4': - resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-switch@1.2.6': - resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-tabs@1.1.13': - resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-toast@1.2.15': - resolution: {integrity: sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-tooltip@1.2.8': - resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-use-callback-ref@1.1.1': - resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-controllable-state@1.2.2': - resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-effect-event@0.0.2': - resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-escape-keydown@1.1.1': - resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-layout-effect@1.1.1': - resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-previous@1.1.1': - resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-rect@1.1.1': - resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-size@1.1.1': - resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-visually-hidden@1.2.3': - resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/rect@1.1.1': - resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} - - '@rolldown/pluginutils@1.0.0-beta.53': - resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} - - '@rollup/rollup-android-arm-eabi@4.53.5': - resolution: {integrity: sha512-iDGS/h7D8t7tvZ1t6+WPK04KD0MwzLZrG0se1hzBjSi5fyxlsiggoJHwh18PCFNn7tG43OWb6pdZ6Y+rMlmyNQ==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.53.5': - resolution: {integrity: sha512-wrSAViWvZHBMMlWk6EJhvg8/rjxzyEhEdgfMMjREHEq11EtJ6IP6yfcCH57YAEca2Oe3FNCE9DSTgU70EIGmVw==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.53.5': - resolution: {integrity: sha512-S87zZPBmRO6u1YXQLwpveZm4JfPpAa6oHBX7/ghSiGH3rz/KDgAu1rKdGutV+WUI6tKDMbaBJomhnT30Y2t4VQ==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.53.5': - resolution: {integrity: sha512-YTbnsAaHo6VrAczISxgpTva8EkfQus0VPEVJCEaboHtZRIb6h6j0BNxRBOwnDciFTZLDPW5r+ZBmhL/+YpTZgA==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.53.5': - resolution: {integrity: sha512-1T8eY2J8rKJWzaznV7zedfdhD1BqVs1iqILhmHDq/bqCUZsrMt+j8VCTHhP0vdfbHK3e1IQ7VYx3jlKqwlf+vw==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.53.5': - resolution: {integrity: sha512-sHTiuXyBJApxRn+VFMaw1U+Qsz4kcNlxQ742snICYPrY+DDL8/ZbaC4DVIB7vgZmp3jiDaKA0WpBdP0aqPJoBQ==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.53.5': - resolution: {integrity: sha512-dV3T9MyAf0w8zPVLVBptVlzaXxka6xg1f16VAQmjg+4KMSTWDvhimI/Y6mp8oHwNrmnmVl9XxJ/w/mO4uIQONA==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.53.5': - resolution: {integrity: sha512-wIGYC1x/hyjP+KAu9+ewDI+fi5XSNiUi9Bvg6KGAh2TsNMA3tSEs+Sh6jJ/r4BV/bx/CyWu2ue9kDnIdRyafcQ==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.53.5': - resolution: {integrity: sha512-Y+qVA0D9d0y2FRNiG9oM3Hut/DgODZbU9I8pLLPwAsU0tUKZ49cyV1tzmB/qRbSzGvY8lpgGkJuMyuhH7Ma+Vg==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.53.5': - resolution: {integrity: sha512-juaC4bEgJsyFVfqhtGLz8mbopaWD+WeSOYr5E16y+1of6KQjc0BpwZLuxkClqY1i8sco+MdyoXPNiCkQou09+g==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-loong64-gnu@4.53.5': - resolution: {integrity: sha512-rIEC0hZ17A42iXtHX+EPJVL/CakHo+tT7W0pbzdAGuWOt2jxDFh7A/lRhsNHBcqL4T36+UiAgwO8pbmn3dE8wA==} - cpu: [loong64] - os: [linux] - - '@rollup/rollup-linux-ppc64-gnu@4.53.5': - resolution: {integrity: sha512-T7l409NhUE552RcAOcmJHj3xyZ2h7vMWzcwQI0hvn5tqHh3oSoclf9WgTl+0QqffWFG8MEVZZP1/OBglKZx52Q==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.53.5': - resolution: {integrity: sha512-7OK5/GhxbnrMcxIFoYfhV/TkknarkYC1hqUw1wU2xUN3TVRLNT5FmBv4KkheSG2xZ6IEbRAhTooTV2+R5Tk0lQ==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-riscv64-musl@4.53.5': - resolution: {integrity: sha512-GwuDBE/PsXaTa76lO5eLJTyr2k8QkPipAyOrs4V/KJufHCZBJ495VCGJol35grx9xryk4V+2zd3Ri+3v7NPh+w==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.53.5': - resolution: {integrity: sha512-IAE1Ziyr1qNfnmiQLHBURAD+eh/zH1pIeJjeShleII7Vj8kyEm2PF77o+lf3WTHDpNJcu4IXJxNO0Zluro8bOw==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.53.5': - resolution: {integrity: sha512-Pg6E+oP7GvZ4XwgRJBuSXZjcqpIW3yCBhK4BcsANvb47qMvAbCjR6E+1a/U2WXz1JJxp9/4Dno3/iSJLcm5auw==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.53.5': - resolution: {integrity: sha512-txGtluxDKTxaMDzUduGP0wdfng24y1rygUMnmlUJ88fzCCULCLn7oE5kb2+tRB+MWq1QDZT6ObT5RrR8HFRKqg==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-openharmony-arm64@4.53.5': - resolution: {integrity: sha512-3DFiLPnTxiOQV993fMc+KO8zXHTcIjgaInrqlG8zDp1TlhYl6WgrOHuJkJQ6M8zHEcntSJsUp1XFZSY8C1DYbg==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.53.5': - resolution: {integrity: sha512-nggc/wPpNTgjGg75hu+Q/3i32R00Lq1B6N1DO7MCU340MRKL3WZJMjA9U4K4gzy3dkZPXm9E1Nc81FItBVGRlA==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.53.5': - resolution: {integrity: sha512-U/54pTbdQpPLBdEzCT6NBCFAfSZMvmjr0twhnD9f4EIvlm9wy3jjQ38yQj1AGznrNO65EWQMgm/QUjuIVrYF9w==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.53.5': - resolution: {integrity: sha512-2NqKgZSuLH9SXBBV2dWNRCZmocgSOx8OJSdpRaEcRlIfX8YrKxUT6z0F1NpvDVhOsl190UFTRh2F2WDWWCYp3A==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.53.5': - resolution: {integrity: sha512-JRpZUhCfhZ4keB5v0fe02gQJy05GqboPOaxvjugW04RLSYYoB/9t2lx2u/tMs/Na/1NXfY8QYjgRljRpN+MjTQ==} - cpu: [x64] - os: [win32] - - '@sindresorhus/is@4.6.0': - resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} - engines: {node: '>=10'} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - - '@szmarczak/http-timer@4.0.6': - resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} - engines: {node: '>=10'} - - '@tailwindcss/node@4.1.18': - resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} - - '@tailwindcss/oxide-android-arm64@4.1.18': - resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - - '@tailwindcss/oxide-darwin-arm64@4.1.18': - resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@tailwindcss/oxide-darwin-x64@4.1.18': - resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@tailwindcss/oxide-freebsd-x64@4.1.18': - resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': - resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': - resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-musl@4.1.18': - resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@tailwindcss/oxide-linux-x64-gnu@4.1.18': - resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@tailwindcss/oxide-linux-x64-musl@4.1.18': - resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@tailwindcss/oxide-wasm32-wasi@4.1.18': - resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' - - tslib - - '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': - resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@tailwindcss/oxide-win32-x64-msvc@4.1.18': - resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@tailwindcss/oxide@4.1.18': - resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==} - engines: {node: '>= 10'} - - '@tailwindcss/postcss@4.1.18': - resolution: {integrity: sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==} - - '@tailwindcss/typography@0.5.19': - resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} - peerDependencies: - tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' - - '@tanstack/react-virtual@3.13.13': - resolution: {integrity: sha512-4o6oPMDvQv+9gMi8rE6gWmsOjtUZUYIJHv7EB+GblyYdi8U6OqLl8rhHWIUZSL1dUU2dPwTdTgybCKf9EjIrQg==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - '@tanstack/virtual-core@3.13.13': - resolution: {integrity: sha512-uQFoSdKKf5S8k51W5t7b2qpfkyIbdHMzAn+AMQvHPxKUPeo1SsGaA4JRISQT87jm28b7z8OEqPcg1IOZagQHcA==} - - '@testing-library/dom@10.4.1': - resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} - engines: {node: '>=18'} - - '@testing-library/react@16.3.1': - resolution: {integrity: sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==} - engines: {node: '>=18'} - peerDependencies: - '@testing-library/dom': ^10.0.0 - '@types/react': ^18.0.0 || ^19.0.0 - '@types/react-dom': ^18.0.0 || ^19.0.0 - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@tootallnate/once@2.0.0': - resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} - engines: {node: '>= 10'} - - '@types/aria-query@5.0.4': - resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} - - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.28.0': - resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - - '@types/cacheable-request@6.0.3': - resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} - - '@types/chai@5.2.3': - resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - - '@types/debug@4.1.12': - resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - - '@types/deep-eql@4.0.2': - resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - - '@types/estree-jsx@1.0.5': - resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@types/fs-extra@9.0.13': - resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} - - '@types/hast@3.0.4': - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - - '@types/http-cache-semantics@4.0.4': - resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/keyv@3.1.4': - resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - - '@types/mdast@4.0.4': - resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - - '@types/ms@2.1.0': - resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - - '@types/node@22.19.3': - resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==} - - '@types/node@25.0.3': - resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==} - - '@types/plist@3.0.5': - resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} - - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} - peerDependencies: - '@types/react': ^19.2.0 - - '@types/react@19.2.7': - resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} - - '@types/responselike@1.0.3': - resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} - - '@types/unist@2.0.11': - resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - - '@types/unist@3.0.3': - resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - - '@types/uuid@10.0.0': - resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} - - '@types/verror@1.10.11': - resolution: {integrity: sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==} - - '@types/yauzl@2.10.3': - resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - - '@typescript-eslint/eslint-plugin@8.50.0': - resolution: {integrity: sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.50.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/parser@8.50.0': - resolution: {integrity: sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/project-service@8.50.0': - resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/scope-manager@8.50.0': - resolution: {integrity: sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/tsconfig-utils@8.50.0': - resolution: {integrity: sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/type-utils@8.50.0': - resolution: {integrity: sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/types@8.50.0': - resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.50.0': - resolution: {integrity: sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/utils@8.50.0': - resolution: {integrity: sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - '@typescript-eslint/visitor-keys@8.50.0': - resolution: {integrity: sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@ungap/structured-clone@1.3.0': - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - - '@vitejs/plugin-react@5.1.2': - resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - - '@vitest/expect@4.0.16': - resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==} - - '@vitest/mocker@4.0.16': - resolution: {integrity: sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==} - peerDependencies: - msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0-0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - '@vitest/pretty-format@4.0.16': - resolution: {integrity: sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==} - - '@vitest/runner@4.0.16': - resolution: {integrity: sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==} - - '@vitest/snapshot@4.0.16': - resolution: {integrity: sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==} - - '@vitest/spy@4.0.16': - resolution: {integrity: sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==} - - '@vitest/utils@4.0.16': - resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==} - - '@xmldom/xmldom@0.8.11': - resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} - engines: {node: '>=10.0.0'} - - '@xterm/addon-fit@0.10.0': - resolution: {integrity: sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==} - peerDependencies: - '@xterm/xterm': ^5.0.0 - - '@xterm/addon-serialize@0.13.0': - resolution: {integrity: sha512-kGs8o6LWAmN1l2NpMp01/YkpxbmO4UrfWybeGu79Khw5K9+Krp7XhXbBTOTc3GJRRhd6EmILjpR8k5+odY39YQ==} - peerDependencies: - '@xterm/xterm': ^5.0.0 - - '@xterm/addon-web-links@0.11.0': - resolution: {integrity: sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q==} - peerDependencies: - '@xterm/xterm': ^5.0.0 - - '@xterm/addon-webgl@0.18.0': - resolution: {integrity: sha512-xCnfMBTI+/HKPdRnSOHaJDRqEpq2Ugy8LEj9GiY4J3zJObo3joylIFaMvzBwbYRg8zLtkO0KQaStCeSfoaI2/w==} - peerDependencies: - '@xterm/xterm': ^5.0.0 - - '@xterm/xterm@5.5.0': - resolution: {integrity: sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==} - - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} - engines: {node: '>=0.4.0'} - hasBin: true - - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - - agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} - - agentkeepalive@4.6.0: - resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} - engines: {node: '>= 8.0.0'} - - aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - - ajv-keywords@3.5.2: - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-escapes@7.2.0: - resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} - engines: {node: '>=18'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - - app-builder-bin@5.0.0-alpha.12: - resolution: {integrity: sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==} - - app-builder-lib@26.0.12: - resolution: {integrity: sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==} - engines: {node: '>=14.0.0'} - peerDependencies: - dmg-builder: ^26.0.12 - electron-builder-squirrel-windows: ^26.0.12 - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - aria-hidden@1.2.6: - resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} - engines: {node: '>=10'} - - aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - - array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - - array-includes@3.1.9: - resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} - engines: {node: '>= 0.4'} - - array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - - array.prototype.flat@1.3.3: - resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} - engines: {node: '>= 0.4'} - - array.prototype.flatmap@1.3.3: - resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} - engines: {node: '>= 0.4'} - - array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} - - arraybuffer.prototype.slice@1.0.4: - resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} - engines: {node: '>= 0.4'} - - assert-plus@1.0.0: - resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} - engines: {node: '>=0.8'} - - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - - astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - - async-exit-hook@2.0.1: - resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==} - engines: {node: '>=0.12.0'} - - async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} - - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - - autoprefixer@10.4.23: - resolution: {integrity: sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - baseline-browser-mapping@2.9.10: - resolution: {integrity: sha512-2VIKvDx8Z1a9rTB2eCkdPE5nSe28XnA+qivGnWHoB40hMMt/h1hSz0960Zqsn6ZyxWXUie0EBdElKv8may20AA==} - hasBin: true - - bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - - boolean@3.2.0: - resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - - builder-util-runtime@9.3.1: - resolution: {integrity: sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==} - engines: {node: '>=12.0.0'} - - builder-util@26.0.11: - resolution: {integrity: sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==} - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - cacache@16.1.3: - resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - cacheable-lookup@5.0.4: - resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} - engines: {node: '>=10.6.0'} - - cacheable-request@7.0.4: - resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} - engines: {node: '>=8'} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - caniuse-lite@1.0.30001761: - resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==} - - ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - - chai@6.2.1: - resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} - engines: {node: '>=18'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - character-entities-html4@2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - - character-entities-legacy@3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - - character-entities@2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - - character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - - chokidar@5.0.0: - resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} - engines: {node: '>= 20.19.0'} - - chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - - chromium-pickle-js@0.2.0: - resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==} - - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - - class-variance-authority@0.7.1: - resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} - - clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - - cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} - - cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - - cli-truncate@2.1.0: - resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} - engines: {node: '>=8'} - - cli-truncate@5.1.1: - resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} - engines: {node: '>=20'} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - - clone-response@1.0.3: - resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} - - clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - - comma-separated-tokens@2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - - commander@14.0.2: - resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} - engines: {node: '>=20'} - - commander@5.1.0: - resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} - engines: {node: '>= 6'} - - commander@9.5.0: - resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} - engines: {node: ^12.20.0 || >=14} - - compare-version@0.1.2: - resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} - engines: {node: '>=0.10.0'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - config-file-ts@0.2.8-rc1: - resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - core-util-is@1.0.2: - resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} - - crc@3.8.0: - resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==} - - cross-dirname@0.1.0: - resolution: {integrity: sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - - cssstyle@4.6.0: - resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} - engines: {node: '>=18'} - - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - - data-urls@5.0.0: - resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} - engines: {node: '>=18'} - - data-view-buffer@1.0.2: - resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} - engines: {node: '>= 0.4'} - - data-view-byte-length@1.0.2: - resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} - engines: {node: '>= 0.4'} - - data-view-byte-offset@1.0.1: - resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} - engines: {node: '>= 0.4'} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decimal.js@10.6.0: - resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - - decode-named-character-reference@1.2.0: - resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==} - - decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - - defer-to-connect@2.0.1: - resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} - engines: {node: '>=10'} - - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - detect-node-es@1.1.0: - resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} - - detect-node@2.1.0: - resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - - devlop@1.1.0: - resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - - dir-compare@4.2.0: - resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} - - dmg-builder@26.0.12: - resolution: {integrity: sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==} - - dmg-license@1.0.11: - resolution: {integrity: sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==} - engines: {node: '>=8'} - os: [darwin] - hasBin: true - - doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - - dom-accessibility-api@0.5.16: - resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} - - dotenv-expand@11.0.7: - resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} - engines: {node: '>=12'} - - dotenv@16.6.1: - resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} - engines: {node: '>=12'} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - - electron-builder-squirrel-windows@26.0.12: - resolution: {integrity: sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==} - - electron-builder@26.0.12: - resolution: {integrity: sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==} - engines: {node: '>=14.0.0'} - hasBin: true - - electron-publish@26.0.11: - resolution: {integrity: sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==} - - electron-to-chromium@1.5.267: - resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} - - electron-updater@6.6.2: - resolution: {integrity: sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==} - - electron-vite@5.0.0: - resolution: {integrity: sha512-OHp/vjdlubNlhNkPkL/+3JD34ii5ov7M0GpuXEVdQeqdQ3ulvVR7Dg/rNBLfS5XPIFwgoBLDf9sjjrL+CuDyRQ==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@swc/core': ^1.0.0 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 - peerDependenciesMeta: - '@swc/core': - optional: true - - electron-winstaller@5.4.0: - resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} - engines: {node: '>=8.0.0'} - - electron@39.2.7: - resolution: {integrity: sha512-KU0uFS6LSTh4aOIC3miolcbizOFP7N1M46VTYVfqIgFiuA2ilfNaOHLDS9tCMvwwHRowAsvqBrh9NgMXcTOHCQ==} - engines: {node: '>= 12.20.55'} - hasBin: true - - emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - - end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - - enhanced-resolve@5.18.4: - resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} - engines: {node: '>=10.13.0'} - - entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} - - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - - err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - - es-abstract@1.24.1: - resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} - engines: {node: '>= 0.4'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-iterator-helpers@1.2.2: - resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==} - engines: {node: '>= 0.4'} - - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - - es-shim-unscopables@1.1.0: - resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} - engines: {node: '>= 0.4'} - - es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} - engines: {node: '>= 0.4'} - - es6-error@4.1.1: - resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} - - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true - - esbuild@0.27.2: - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} - engines: {node: '>=18'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - - eslint-plugin-react-hooks@7.0.1: - resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} - engines: {node: '>=18'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - - eslint-plugin-react@7.37.5: - resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - - eslint-scope@8.4.0: - resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.1: - resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.39.2: - resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - espree@10.4.0: - resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - estree-util-is-identifier-name@3.0.0: - resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} - - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - - expect-type@1.3.0: - resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} - engines: {node: '>=12.0.0'} - - exponential-backoff@3.1.3: - resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} - - extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - - extract-zip@2.0.1: - resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} - engines: {node: '>= 10.17.0'} - hasBin: true - - extsprintf@1.4.1: - resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==} - engines: {'0': node >=0.6.0} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fd-slicer@1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - - for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} - - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} - - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} - engines: {node: '>= 6'} - - fraction.js@5.3.4: - resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} - - framer-motion@12.23.26: - resolution: {integrity: sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - - fs-extra@11.3.3: - resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} - engines: {node: '>=14.14'} - - fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} - - fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - - fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} - - fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} - engines: {node: '>= 0.4'} - - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - - generator-function@2.0.1: - resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} - engines: {node: '>= 0.4'} - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-east-asian-width@1.4.0: - resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} - engines: {node: '>=18'} - - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-nonce@1.0.1: - resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} - engines: {node: '>=6'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} - - get-symbol-description@1.1.0: - resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} - engines: {node: '>= 0.4'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob@10.5.0: - resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} - hasBin: true - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported - - global-agent@3.0.0: - resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} - engines: {node: '>=10.0'} - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - globals@16.5.0: - resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} - engines: {node: '>=18'} - - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - got@11.8.6: - resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} - engines: {node: '>=10.19.0'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-proto@1.2.0: - resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} - engines: {node: '>= 0.4'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - hast-util-to-jsx-runtime@2.3.6: - resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} - - hast-util-whitespace@3.0.0: - resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} - - hermes-estree@0.25.1: - resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} - - hermes-parser@0.25.1: - resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - - hosted-git-info@4.1.0: - resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} - engines: {node: '>=10'} - - html-encoding-sniffer@4.0.0: - resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} - engines: {node: '>=18'} - - html-url-attributes@3.0.1: - resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} - - http-cache-semantics@4.2.0: - resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} - - http-proxy-agent@5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} - - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - - http2-wrapper@1.0.3: - resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} - engines: {node: '>=10.19.0'} - - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - - https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} - - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - - husky@9.1.7: - resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} - engines: {node: '>=18'} - hasBin: true - - iconv-corefoundation@1.1.7: - resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==} - engines: {node: ^8.11.2 || >=10} - os: [darwin] - - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} - - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - infer-owner@1.0.4: - resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - inline-style-parser@0.2.7: - resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} - - internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - - ip-address@10.1.0: - resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} - engines: {node: '>= 12'} - - is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - - is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - - is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} - - is-async-function@2.1.1: - resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} - engines: {node: '>= 0.4'} - - is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} - - is-boolean-object@1.2.2: - resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} - engines: {node: '>= 0.4'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-ci@3.0.1: - resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} - hasBin: true - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-data-view@1.0.2: - resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} - engines: {node: '>= 0.4'} - - is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} - - is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-finalizationregistry@1.1.1: - resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} - engines: {node: '>= 0.4'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-fullwidth-code-point@5.1.0: - resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} - engines: {node: '>=18'} - - is-generator-function@1.1.2: - resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} - engines: {node: '>= 0.4'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - - is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - - is-lambda@1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - - is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - - is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - - is-potential-custom-element-name@1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - - is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} - - is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} - - is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - is-weakref@1.1.1: - resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} - engines: {node: '>= 0.4'} - - is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isbinaryfile@4.0.10: - resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} - engines: {node: '>= 8.0.0'} - - isbinaryfile@5.0.7: - resolution: {integrity: sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==} - engines: {node: '>= 18.0.0'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - iterator.prototype@1.1.5: - resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} - engines: {node: '>= 0.4'} - - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - jake@10.9.4: - resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} - engines: {node: '>=10'} - hasBin: true - - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} - hasBin: true - - jsdom@26.1.0: - resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} - engines: {node: '>=18'} - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - - jsonfile@6.2.0: - resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - - jsx-ast-utils@3.3.5: - resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} - engines: {node: '>=4.0'} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - lazy-val@1.0.5: - resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - lightningcss-android-arm64@1.30.2: - resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - - lightningcss-darwin-arm64@1.30.2: - resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - - lightningcss-darwin-x64@1.30.2: - resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - - lightningcss-freebsd-x64@1.30.2: - resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - - lightningcss-linux-arm-gnueabihf@1.30.2: - resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - - lightningcss-linux-arm64-gnu@1.30.2: - resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - - lightningcss-linux-arm64-musl@1.30.2: - resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - - lightningcss-linux-x64-gnu@1.30.2: - resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - - lightningcss-linux-x64-musl@1.30.2: - resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - - lightningcss-win32-arm64-msvc@1.30.2: - resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - - lightningcss-win32-x64-msvc@1.30.2: - resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - - lightningcss@1.30.2: - resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} - engines: {node: '>= 12.0.0'} - - lint-staged@16.2.7: - resolution: {integrity: sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==} - engines: {node: '>=20.17'} - hasBin: true - - listr2@9.0.5: - resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==} - engines: {node: '>=20.0.0'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.escaperegexp@4.1.2: - resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} - - lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} - - longest-streak@3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - - lowercase-keys@2.0.0: - resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} - engines: {node: '>=8'} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - - lucide-react@0.560.0: - resolution: {integrity: sha512-NwKoUA/aBShsdL8WE5lukV2F/tjHzQRlonQs7fkNGI1sCT0Ay4a9Ap3ST2clUUkcY+9eQ0pBe2hybTQd2fmyDA==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - lz-string@1.5.0: - resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} - hasBin: true - - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - - make-fetch-happen@10.2.1: - resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - markdown-table@3.0.4: - resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} - - matcher@3.0.0: - resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} - engines: {node: '>=10'} - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - mdast-util-find-and-replace@3.0.2: - resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} - - mdast-util-from-markdown@2.0.2: - resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} - - mdast-util-gfm-autolink-literal@2.0.1: - resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} - - mdast-util-gfm-footnote@2.1.0: - resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} - - mdast-util-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} - - mdast-util-gfm-table@2.0.0: - resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} - - mdast-util-gfm-task-list-item@2.0.0: - resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} - - mdast-util-gfm@3.1.0: - resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} - - mdast-util-mdx-expression@2.0.1: - resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} - - mdast-util-mdx-jsx@3.2.0: - resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} - - mdast-util-mdxjs-esm@2.0.1: - resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} - - mdast-util-phrasing@4.1.0: - resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - - mdast-util-to-hast@13.2.1: - resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} - - mdast-util-to-markdown@2.1.2: - resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} - - mdast-util-to-string@4.0.0: - resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - - micromark-core-commonmark@2.0.3: - resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} - - micromark-extension-gfm-autolink-literal@2.1.0: - resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} - - micromark-extension-gfm-footnote@2.1.0: - resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} - - micromark-extension-gfm-strikethrough@2.1.0: - resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} - - micromark-extension-gfm-table@2.1.1: - resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} - - micromark-extension-gfm-tagfilter@2.0.0: - resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} - - micromark-extension-gfm-task-list-item@2.1.0: - resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} - - micromark-extension-gfm@3.0.0: - resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} - - micromark-factory-destination@2.0.1: - resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} - - micromark-factory-label@2.0.1: - resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} - - micromark-factory-space@2.0.1: - resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} - - micromark-factory-title@2.0.1: - resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} - - micromark-factory-whitespace@2.0.1: - resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} - - micromark-util-character@2.1.1: - resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} - - micromark-util-chunked@2.0.1: - resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} - - micromark-util-classify-character@2.0.1: - resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} - - micromark-util-combine-extensions@2.0.1: - resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} - - micromark-util-decode-numeric-character-reference@2.0.2: - resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} - - micromark-util-decode-string@2.0.1: - resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} - - micromark-util-encode@2.0.1: - resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} - - micromark-util-html-tag-name@2.0.1: - resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} - - micromark-util-normalize-identifier@2.0.1: - resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} - - micromark-util-resolve-all@2.0.1: - resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} - - micromark-util-sanitize-uri@2.0.1: - resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} - - micromark-util-subtokenize@2.1.0: - resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} - - micromark-util-symbol@2.0.1: - resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} - - micromark-util-types@2.0.2: - resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} - - micromark@4.0.2: - resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mime@2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} - hasBin: true - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} - - mimic-response@1.0.1: - resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} - engines: {node: '>=4'} - - mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - minimatch@10.1.1: - resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} - engines: {node: 20 || >=22} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - - minipass-fetch@2.1.2: - resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - - minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - - minipass-sized@1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} - - minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - - minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - - motion-dom@12.23.23: - resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==} - - motion-utils@12.23.6: - resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} - - motion@12.23.26: - resolution: {integrity: sha512-Ll8XhVxY8LXMVYTCfme27WH2GjBrCIzY4+ndr5QKxsK+YwCtOi2B/oBi5jcIbik5doXuWT/4KKDOVAZJkeY5VQ==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nano-spawn@2.0.0: - resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==} - engines: {node: '>=20.17'} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - negotiator@0.6.4: - resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} - engines: {node: '>= 0.6'} - - node-abi@3.85.0: - resolution: {integrity: sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==} - engines: {node: '>=10'} - - node-addon-api@1.7.2: - resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} - - node-api-version@0.2.1: - resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} - - node-releases@2.0.27: - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} - - nopt@6.0.0: - resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - hasBin: true - - normalize-url@6.1.0: - resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} - engines: {node: '>=10'} - - nwsapi@2.2.23: - resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} - - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - - object.entries@1.1.9: - resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} - engines: {node: '>= 0.4'} - - object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - - object.values@1.2.1: - resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} - engines: {node: '>= 0.4'} - - obug@2.1.1: - resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - - own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} - engines: {node: '>= 0.4'} - - p-cancelable@2.1.1: - resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} - engines: {node: '>=8'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse-entities@4.0.2: - resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} - - parse5@7.3.0: - resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - - pe-library@0.4.1: - resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==} - engines: {node: '>=12', npm: '>=6'} - - pend@1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} - engines: {node: '>=12'} - - pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - - playwright-core@1.57.0: - resolution: {integrity: sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==} - engines: {node: '>=18'} - hasBin: true - - playwright@1.57.0: - resolution: {integrity: sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==} - engines: {node: '>=18'} - hasBin: true - - plist@3.1.0: - resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} - engines: {node: '>=10.4.0'} - - possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} - - postcss-selector-parser@6.0.10: - resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} - engines: {node: '>=4'} - - postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} - - postject@1.0.0-alpha.6: - resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==} - engines: {node: '>=14.0.0'} - hasBin: true - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - - proc-log@2.0.1: - resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - - promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - - promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - - prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - - property-information@7.1.0: - resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} - - pump@3.0.3: - resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - quick-lru@5.1.1: - resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} - engines: {node: '>=10'} - - react-dom@19.2.3: - resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} - peerDependencies: - react: ^19.2.3 - - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - - react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - - react-markdown@10.1.0: - resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} - peerDependencies: - '@types/react': '>=18' - react: '>=18' - - react-refresh@0.18.0: - resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} - engines: {node: '>=0.10.0'} - - react-remove-scroll-bar@2.3.8: - resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - react-remove-scroll@2.7.2: - resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - react-resizable-panels@3.0.6: - resolution: {integrity: sha512-b3qKHQ3MLqOgSS+FRYKapNkJZf5EQzuf6+RLiq1/IlTHw99YrZ2NJZLk4hQIzTnnIkRg2LUqyVinu6YWWpUYew==} - peerDependencies: - react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - - react-style-singleton@2.2.3: - resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - react@19.2.3: - resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} - engines: {node: '>=0.10.0'} - - read-binary-file-arch@1.0.6: - resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==} - hasBin: true - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} - engines: {node: '>= 20.19.0'} - - reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - - remark-gfm@4.0.1: - resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} - - remark-parse@11.0.0: - resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - - remark-rehype@11.1.2: - resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} - - remark-stringify@11.0.0: - resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - resedit@1.7.2: - resolution: {integrity: sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==} - engines: {node: '>=12', npm: '>=6'} - - resolve-alpn@1.2.1: - resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - - responselike@2.0.1: - resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} - - restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} - - retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - - rimraf@2.6.3: - resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - - roarr@2.15.4: - resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} - engines: {node: '>=8.0'} - - rollup@4.53.5: - resolution: {integrity: sha512-iTNAbFSlRpcHeeWu73ywU/8KuU/LZmNCSxp6fjQkJBD3ivUb8tpDrXhIxEzA05HlYMEwmtaUnb3RP+YNv162OQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - rrweb-cssom@0.8.0: - resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} - - safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} - engines: {node: '>=0.4'} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safe-push-apply@1.0.0: - resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} - engines: {node: '>= 0.4'} - - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - sanitize-filename@1.6.3: - resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} - - sax@1.4.3: - resolution: {integrity: sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==} - - saxes@6.0.0: - resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} - engines: {node: '>=v12.22.7'} - - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - - semver-compare@1.0.0: - resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} - - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} - engines: {node: '>=10'} - hasBin: true - - serialize-error@7.0.1: - resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} - engines: {node: '>=10'} - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - - set-proto@1.0.0: - resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} - engines: {node: '>= 0.4'} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - simple-update-notifier@2.0.0: - resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} - engines: {node: '>=10'} - - slice-ansi@3.0.0: - resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} - engines: {node: '>=8'} - - slice-ansi@7.1.2: - resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} - engines: {node: '>=18'} - - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - - socks-proxy-agent@7.0.0: - resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} - engines: {node: '>= 10'} - - socks@2.8.7: - resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - space-separated-tokens@2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - - sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - - ssri@9.0.1: - resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - stat-mode@1.0.0: - resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==} - engines: {node: '>= 6'} - - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} - - stop-iteration-iterator@1.1.0: - resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} - engines: {node: '>= 0.4'} - - string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - string-width@8.1.0: - resolution: {integrity: sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==} - engines: {node: '>=20'} - - string.prototype.matchall@4.0.12: - resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} - engines: {node: '>= 0.4'} - - string.prototype.repeat@1.0.0: - resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} - - string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} - engines: {node: '>= 0.4'} - - string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - stringify-entities@4.0.4: - resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} - engines: {node: '>=12'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - style-to-js@1.1.21: - resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} - - style-to-object@1.0.14: - resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} - - sumchecker@3.0.1: - resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} - engines: {node: '>= 8.0'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - - tailwind-merge@3.4.0: - resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} - - tailwindcss@4.1.18: - resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} - - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} - engines: {node: '>=6'} - - tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - - temp-file@3.4.0: - resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} - - temp@0.9.4: - resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} - engines: {node: '>=6.0.0'} - - tiny-async-pool@1.3.0: - resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==} - - tiny-typed-emitter@2.1.0: - resolution: {integrity: sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==} - - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinyexec@1.0.2: - resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} - engines: {node: '>=18'} - - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - - tinyrainbow@3.0.3: - resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} - engines: {node: '>=14.0.0'} - - tldts-core@6.1.86: - resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - - tldts@6.1.86: - resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} - hasBin: true - - tmp-promise@3.0.3: - resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} - - tmp@0.2.5: - resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} - engines: {node: '>=14.14'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - tough-cookie@5.1.2: - resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} - engines: {node: '>=16'} - - tr46@5.1.1: - resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} - engines: {node: '>=18'} - - trim-lines@3.0.1: - resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - - trough@2.2.0: - resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - - truncate-utf8-bytes@1.0.2: - resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} - - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} - - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - - typed-array-byte-length@1.0.3: - resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} - engines: {node: '>= 0.4'} - - typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} - engines: {node: '>= 0.4'} - - typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} - engines: {node: '>= 0.4'} - - typescript-eslint@8.50.0: - resolution: {integrity: sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - - undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - - unified@11.0.5: - resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} - - unique-filename@2.0.1: - resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - unique-slug@3.0.0: - resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - unist-util-is@6.0.1: - resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} - - unist-util-position@5.0.0: - resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} - - unist-util-stringify-position@4.0.0: - resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - - unist-util-visit-parents@6.0.2: - resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} - - unist-util-visit@5.0.0: - resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - - universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - use-callback-ref@1.3.3: - resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - use-sidecar@1.1.3: - resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - utf8-byte-length@1.0.5: - resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - uuid@13.0.0: - resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} - hasBin: true - - verror@1.10.1: - resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} - engines: {node: '>=0.6.0'} - - vfile-message@4.0.3: - resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} - - vfile@6.0.3: - resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - - vite@7.3.0: - resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - jiti: '>=1.21.0' - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vitest@4.0.16: - resolution: {integrity: sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.0.16 - '@vitest/browser-preview': 4.0.16 - '@vitest/browser-webdriverio': 4.0.16 - '@vitest/ui': 4.0.16 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@opentelemetry/api': - optional: true - '@types/node': - optional: true - '@vitest/browser-playwright': - optional: true - '@vitest/browser-preview': - optional: true - '@vitest/browser-webdriverio': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} - engines: {node: '>=18'} - - wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - - webidl-conversions@7.0.0: - resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} - engines: {node: '>=12'} - - whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} - - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - - whatwg-url@14.2.0: - resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} - engines: {node: '>=18'} - - which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} - - which-builtin-type@1.2.1: - resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} - engines: {node: '>= 0.4'} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - - which-typed-array@1.1.19: - resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} - engines: {node: '>= 0.4'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - xml-name-validator@5.0.0: - resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} - engines: {node: '>=18'} - - xmlbuilder@15.1.1: - resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} - engines: {node: '>=8.0'} - - xmlchars@2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - yaml@2.8.2: - resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} - engines: {node: '>= 14.6'} - hasBin: true - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - - yauzl@2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - - zod-validation-error@4.0.2: - resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - zod: ^3.25.0 || ^4.0.0 - - zod@4.2.1: - resolution: {integrity: sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==} - - zustand@5.0.9: - resolution: {integrity: sha512-ALBtUj0AfjJt3uNRQoL1tL2tMvj6Gp/6e39dnfT6uzpelGru8v1tPOGBzayOWbPJvujM8JojDk3E1LxeFisBNg==} - engines: {node: '>=12.20.0'} - peerDependencies: - '@types/react': '>=18.0.0' - immer: '>=9.0.6' - react: '>=18.0.0' - use-sync-external-store: '>=1.2.0' - peerDependenciesMeta: - '@types/react': - optional: true - immer: - optional: true - react: - optional: true - use-sync-external-store: - optional: true - - zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - -snapshots: - - 7zip-bin@5.2.0: {} - - '@alloc/quick-lru@5.2.0': {} - - '@asamuzakjp/css-color@3.2.0': - dependencies: - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - lru-cache: 10.4.3 - - '@babel/code-frame@7.27.1': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.28.5': {} - - '@babel/core@7.28.5': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) - '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.28.5': - dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.27.2': - dependencies: - '@babel/compat-data': 7.28.5 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-module-imports@7.27.1': - dependencies: - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': - dependencies: - '@babel/core': 7.28.5 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.27.1': {} - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helpers@7.28.4': - dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 - - '@babel/parser@7.28.5': - dependencies: - '@babel/types': 7.28.5 - - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.5)': - dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)': - dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)': - dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/runtime@7.28.4': {} - - '@babel/template@7.27.2': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 - - '@babel/traverse@7.28.5': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - '@babel/types@7.28.5': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@csstools/color-helpers@5.1.0': {} - - '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/color-helpers': 5.1.0 - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-tokenizer@3.0.4': {} - - '@develar/schema-utils@2.6.5': - dependencies: - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - - '@dnd-kit/accessibility@3.1.1(react@19.2.3)': - dependencies: - react: 19.2.3 - tslib: 2.8.1 - - '@dnd-kit/core@6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@dnd-kit/accessibility': 3.1.1(react@19.2.3) - '@dnd-kit/utilities': 3.2.2(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - tslib: 2.8.1 - - '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)': - dependencies: - '@dnd-kit/core': 6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@dnd-kit/utilities': 3.2.2(react@19.2.3) - react: 19.2.3 - tslib: 2.8.1 - - '@dnd-kit/utilities@3.2.2(react@19.2.3)': - dependencies: - react: 19.2.3 - tslib: 2.8.1 - - '@electron-toolkit/preload@3.0.2(electron@39.2.7)': - dependencies: - electron: 39.2.7 - - '@electron-toolkit/utils@4.0.0(electron@39.2.7)': - dependencies: - electron: 39.2.7 - - '@electron/asar@3.2.18': - dependencies: - commander: 5.1.0 - glob: 7.2.3 - minimatch: 3.1.2 - - '@electron/asar@3.4.1': - dependencies: - commander: 5.1.0 - glob: 7.2.3 - minimatch: 3.1.2 - - '@electron/fuses@1.8.0': - dependencies: - chalk: 4.1.2 - fs-extra: 9.1.0 - minimist: 1.2.8 - - '@electron/get@2.0.3': - dependencies: - debug: 4.4.3 - env-paths: 2.2.1 - fs-extra: 8.1.0 - got: 11.8.6 - progress: 2.0.3 - semver: 6.3.1 - sumchecker: 3.0.1 - optionalDependencies: - global-agent: 3.0.0 - transitivePeerDependencies: - - supports-color - - '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': - dependencies: - env-paths: 2.2.1 - exponential-backoff: 3.1.3 - glob: 8.1.0 - graceful-fs: 4.2.11 - make-fetch-happen: 10.2.1 - nopt: 6.0.0 - proc-log: 2.0.1 - semver: 7.7.3 - tar: 6.2.1 - which: 2.0.2 - transitivePeerDependencies: - - bluebird - - supports-color - - '@electron/notarize@2.5.0': - dependencies: - debug: 4.4.3 - fs-extra: 9.1.0 - promise-retry: 2.0.1 - transitivePeerDependencies: - - supports-color - - '@electron/osx-sign@1.3.1': - dependencies: - compare-version: 0.1.2 - debug: 4.4.3 - fs-extra: 10.1.0 - isbinaryfile: 4.0.10 - minimist: 1.2.8 - plist: 3.1.0 - transitivePeerDependencies: - - supports-color - - '@electron/rebuild@3.7.0': - dependencies: - '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2 - '@malept/cross-spawn-promise': 2.0.0 - chalk: 4.1.2 - debug: 4.4.3 - detect-libc: 2.1.2 - fs-extra: 10.1.0 - got: 11.8.6 - node-abi: 3.85.0 - node-api-version: 0.2.1 - ora: 5.4.1 - read-binary-file-arch: 1.0.6 - semver: 7.7.3 - tar: 6.2.1 - yargs: 17.7.2 - transitivePeerDependencies: - - bluebird - - supports-color - - '@electron/rebuild@3.7.2': - dependencies: - '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2 - '@malept/cross-spawn-promise': 2.0.0 - chalk: 4.1.2 - debug: 4.4.3 - detect-libc: 2.1.2 - fs-extra: 10.1.0 - got: 11.8.6 - node-abi: 3.85.0 - node-api-version: 0.2.1 - ora: 5.4.1 - read-binary-file-arch: 1.0.6 - semver: 7.7.3 - tar: 6.2.1 - yargs: 17.7.2 - transitivePeerDependencies: - - bluebird - - supports-color - - '@electron/universal@2.0.1': - dependencies: - '@electron/asar': 3.2.18 - '@malept/cross-spawn-promise': 2.0.0 - debug: 4.4.3 - dir-compare: 4.2.0 - fs-extra: 11.3.3 - minimatch: 9.0.5 - plist: 3.1.0 - transitivePeerDependencies: - - supports-color - - '@electron/windows-sign@1.2.2': - dependencies: - cross-dirname: 0.1.0 - debug: 4.4.3 - fs-extra: 11.3.3 - minimist: 1.2.8 - postject: 1.0.0-alpha.6 - transitivePeerDependencies: - - supports-color - optional: true - - '@esbuild/aix-ppc64@0.25.12': - optional: true - - '@esbuild/aix-ppc64@0.27.2': - optional: true - - '@esbuild/android-arm64@0.25.12': - optional: true - - '@esbuild/android-arm64@0.27.2': - optional: true - - '@esbuild/android-arm@0.25.12': - optional: true - - '@esbuild/android-arm@0.27.2': - optional: true - - '@esbuild/android-x64@0.25.12': - optional: true - - '@esbuild/android-x64@0.27.2': - optional: true - - '@esbuild/darwin-arm64@0.25.12': - optional: true - - '@esbuild/darwin-arm64@0.27.2': - optional: true - - '@esbuild/darwin-x64@0.25.12': - optional: true - - '@esbuild/darwin-x64@0.27.2': - optional: true - - '@esbuild/freebsd-arm64@0.25.12': - optional: true - - '@esbuild/freebsd-arm64@0.27.2': - optional: true - - '@esbuild/freebsd-x64@0.25.12': - optional: true - - '@esbuild/freebsd-x64@0.27.2': - optional: true - - '@esbuild/linux-arm64@0.25.12': - optional: true - - '@esbuild/linux-arm64@0.27.2': - optional: true - - '@esbuild/linux-arm@0.25.12': - optional: true - - '@esbuild/linux-arm@0.27.2': - optional: true - - '@esbuild/linux-ia32@0.25.12': - optional: true - - '@esbuild/linux-ia32@0.27.2': - optional: true - - '@esbuild/linux-loong64@0.25.12': - optional: true - - '@esbuild/linux-loong64@0.27.2': - optional: true - - '@esbuild/linux-mips64el@0.25.12': - optional: true - - '@esbuild/linux-mips64el@0.27.2': - optional: true - - '@esbuild/linux-ppc64@0.25.12': - optional: true - - '@esbuild/linux-ppc64@0.27.2': - optional: true - - '@esbuild/linux-riscv64@0.25.12': - optional: true - - '@esbuild/linux-riscv64@0.27.2': - optional: true - - '@esbuild/linux-s390x@0.25.12': - optional: true - - '@esbuild/linux-s390x@0.27.2': - optional: true - - '@esbuild/linux-x64@0.25.12': - optional: true - - '@esbuild/linux-x64@0.27.2': - optional: true - - '@esbuild/netbsd-arm64@0.25.12': - optional: true - - '@esbuild/netbsd-arm64@0.27.2': - optional: true - - '@esbuild/netbsd-x64@0.25.12': - optional: true - - '@esbuild/netbsd-x64@0.27.2': - optional: true - - '@esbuild/openbsd-arm64@0.25.12': - optional: true - - '@esbuild/openbsd-arm64@0.27.2': - optional: true - - '@esbuild/openbsd-x64@0.25.12': - optional: true - - '@esbuild/openbsd-x64@0.27.2': - optional: true - - '@esbuild/openharmony-arm64@0.25.12': - optional: true - - '@esbuild/openharmony-arm64@0.27.2': - optional: true - - '@esbuild/sunos-x64@0.25.12': - optional: true - - '@esbuild/sunos-x64@0.27.2': - optional: true - - '@esbuild/win32-arm64@0.25.12': - optional: true - - '@esbuild/win32-arm64@0.27.2': - optional: true - - '@esbuild/win32-ia32@0.25.12': - optional: true - - '@esbuild/win32-ia32@0.27.2': - optional: true - - '@esbuild/win32-x64@0.25.12': - optional: true - - '@esbuild/win32-x64@0.27.2': - optional: true - - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.6.1))': - dependencies: - eslint: 9.39.2(jiti@2.6.1) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.2': {} - - '@eslint/config-array@0.21.1': - dependencies: - '@eslint/object-schema': 2.1.7 - debug: 4.4.3 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@eslint/config-helpers@0.4.2': - dependencies: - '@eslint/core': 0.17.0 - - '@eslint/core@0.17.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/eslintrc@3.3.3': - dependencies: - ajv: 6.12.6 - debug: 4.4.3 - espree: 10.4.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.39.2': {} - - '@eslint/object-schema@2.1.7': {} - - '@eslint/plugin-kit@0.4.1': - dependencies: - '@eslint/core': 0.17.0 - levn: 0.4.1 - - '@floating-ui/core@1.7.3': - dependencies: - '@floating-ui/utils': 0.2.10 - - '@floating-ui/dom@1.7.4': - dependencies: - '@floating-ui/core': 1.7.3 - '@floating-ui/utils': 0.2.10 - - '@floating-ui/react-dom@2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@floating-ui/dom': 1.7.4 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - - '@floating-ui/utils@0.2.10': {} - - '@gar/promisify@1.1.3': {} - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.7': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.4.3 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.4.3': {} - - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.0': - dependencies: - '@isaacs/balanced-match': 4.0.1 - - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.2 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@lydell/node-pty-darwin-arm64@1.1.0': - optional: true - - '@lydell/node-pty-darwin-x64@1.1.0': - optional: true - - '@lydell/node-pty-linux-arm64@1.1.0': - optional: true - - '@lydell/node-pty-linux-x64@1.1.0': - optional: true - - '@lydell/node-pty-win32-arm64@1.1.0': - optional: true - - '@lydell/node-pty-win32-x64@1.1.0': - optional: true - - '@lydell/node-pty@1.1.0': - optionalDependencies: - '@lydell/node-pty-darwin-arm64': 1.1.0 - '@lydell/node-pty-darwin-x64': 1.1.0 - '@lydell/node-pty-linux-arm64': 1.1.0 - '@lydell/node-pty-linux-x64': 1.1.0 - '@lydell/node-pty-win32-arm64': 1.1.0 - '@lydell/node-pty-win32-x64': 1.1.0 - - '@malept/cross-spawn-promise@2.0.0': - dependencies: - cross-spawn: 7.0.6 - - '@malept/flatpak-bundler@0.4.0': - dependencies: - debug: 4.4.3 - fs-extra: 9.1.0 - lodash: 4.17.21 - tmp-promise: 3.0.3 - transitivePeerDependencies: - - supports-color - - '@npmcli/fs@2.1.2': - dependencies: - '@gar/promisify': 1.1.3 - semver: 7.7.3 - - '@npmcli/move-file@2.0.1': - dependencies: - mkdirp: 1.0.4 - rimraf: 3.0.2 - - '@pkgjs/parseargs@0.11.0': - optional: true - - '@playwright/test@1.57.0': - dependencies: - playwright: 1.57.0 - - '@radix-ui/number@1.1.1': {} - - '@radix-ui/primitive@1.1.3': {} - - '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.7)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-context@1.1.2(@types/react@19.2.7)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-context@1.1.3(@types/react@19.2.7)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - aria-hidden: 1.2.6 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - react-remove-scroll: 2.7.2(@types/react@19.2.7)(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-direction@1.1.1(@types/react@19.2.7)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.7)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-id@1.1.1(@types/react@19.2.7)(react@19.2.3)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - aria-hidden: 1.2.6 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - react-remove-scroll: 2.7.2(@types/react@19.2.7)(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@floating-ui/react-dom': 2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/rect': 1.1.1 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-slot': 1.2.4(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-progress@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-context': 1.1.3(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-radio-group@1.3.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - aria-hidden: 1.2.6 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - react-remove-scroll: 2.7.2(@types/react@19.2.7)(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-separator@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-slot@1.2.3(@types/react@19.2.7)(react@19.2.3)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-slot@1.2.4(@types/react@19.2.7)(react@19.2.3)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-toast@1.2.15(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.7)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.7)(react@19.2.3)': - dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.7)(react@19.2.3) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.7)(react@19.2.3)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.7)(react@19.2.3)': - dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.7)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.7)(react@19.2.3)': - dependencies: - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.7)(react@19.2.3)': - dependencies: - '@radix-ui/rect': 1.1.1 - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-use-size@1.1.1(@types/react@19.2.7)(react@19.2.3)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3) - react: 19.2.3 - optionalDependencies: - '@types/react': 19.2.7 - - '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@radix-ui/rect@1.1.1': {} - - '@rolldown/pluginutils@1.0.0-beta.53': {} - - '@rollup/rollup-android-arm-eabi@4.53.5': - optional: true - - '@rollup/rollup-android-arm64@4.53.5': - optional: true - - '@rollup/rollup-darwin-arm64@4.53.5': - optional: true - - '@rollup/rollup-darwin-x64@4.53.5': - optional: true - - '@rollup/rollup-freebsd-arm64@4.53.5': - optional: true - - '@rollup/rollup-freebsd-x64@4.53.5': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.53.5': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.53.5': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.53.5': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.53.5': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.53.5': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.53.5': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.53.5': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.53.5': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.53.5': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.53.5': - optional: true - - '@rollup/rollup-linux-x64-musl@4.53.5': - optional: true - - '@rollup/rollup-openharmony-arm64@4.53.5': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.53.5': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.53.5': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.53.5': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.53.5': - optional: true - - '@sindresorhus/is@4.6.0': {} - - '@standard-schema/spec@1.1.0': {} - - '@szmarczak/http-timer@4.0.6': - dependencies: - defer-to-connect: 2.0.1 - - '@tailwindcss/node@4.1.18': - dependencies: - '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.18.4 - jiti: 2.6.1 - lightningcss: 1.30.2 - magic-string: 0.30.21 - source-map-js: 1.2.1 - tailwindcss: 4.1.18 - - '@tailwindcss/oxide-android-arm64@4.1.18': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.1.18': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.1.18': - optional: true - - '@tailwindcss/oxide-freebsd-x64@4.1.18': - optional: true - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': - optional: true - - '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': - optional: true - - '@tailwindcss/oxide-linux-arm64-musl@4.1.18': - optional: true - - '@tailwindcss/oxide-linux-x64-gnu@4.1.18': - optional: true - - '@tailwindcss/oxide-linux-x64-musl@4.1.18': - optional: true - - '@tailwindcss/oxide-wasm32-wasi@4.1.18': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.1.18': - optional: true - - '@tailwindcss/oxide@4.1.18': - optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.18 - '@tailwindcss/oxide-darwin-arm64': 4.1.18 - '@tailwindcss/oxide-darwin-x64': 4.1.18 - '@tailwindcss/oxide-freebsd-x64': 4.1.18 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.18 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.18 - '@tailwindcss/oxide-linux-x64-musl': 4.1.18 - '@tailwindcss/oxide-wasm32-wasi': 4.1.18 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - - '@tailwindcss/postcss@4.1.18': - dependencies: - '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.1.18 - '@tailwindcss/oxide': 4.1.18 - postcss: 8.5.6 - tailwindcss: 4.1.18 - - '@tailwindcss/typography@0.5.19(tailwindcss@4.1.18)': - dependencies: - postcss-selector-parser: 6.0.10 - tailwindcss: 4.1.18 - - '@tanstack/react-virtual@3.13.13(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@tanstack/virtual-core': 3.13.13 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - - '@tanstack/virtual-core@3.13.13': {} - - '@testing-library/dom@10.4.1': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/runtime': 7.28.4 - '@types/aria-query': 5.0.4 - aria-query: 5.3.0 - dom-accessibility-api: 0.5.16 - lz-string: 1.5.0 - picocolors: 1.1.1 - pretty-format: 27.5.1 - - '@testing-library/react@16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': - dependencies: - '@babel/runtime': 7.28.4 - '@testing-library/dom': 10.4.1 - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - '@types/react-dom': 19.2.3(@types/react@19.2.7) - - '@tootallnate/once@2.0.0': {} - - '@types/aria-query@5.0.4': {} - - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.28.0 - - '@types/babel__generator@7.27.0': - dependencies: - '@babel/types': 7.28.5 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 - - '@types/babel__traverse@7.28.0': - dependencies: - '@babel/types': 7.28.5 - - '@types/cacheable-request@6.0.3': - dependencies: - '@types/http-cache-semantics': 4.0.4 - '@types/keyv': 3.1.4 - '@types/node': 25.0.3 - '@types/responselike': 1.0.3 - - '@types/chai@5.2.3': - dependencies: - '@types/deep-eql': 4.0.2 - assertion-error: 2.0.1 - - '@types/debug@4.1.12': - dependencies: - '@types/ms': 2.1.0 - - '@types/deep-eql@4.0.2': {} - - '@types/estree-jsx@1.0.5': - dependencies: - '@types/estree': 1.0.8 - - '@types/estree@1.0.8': {} - - '@types/fs-extra@9.0.13': - dependencies: - '@types/node': 25.0.3 - - '@types/hast@3.0.4': - dependencies: - '@types/unist': 3.0.3 - - '@types/http-cache-semantics@4.0.4': {} - - '@types/json-schema@7.0.15': {} - - '@types/keyv@3.1.4': - dependencies: - '@types/node': 25.0.3 - - '@types/mdast@4.0.4': - dependencies: - '@types/unist': 3.0.3 - - '@types/ms@2.1.0': {} - - '@types/node@22.19.3': - dependencies: - undici-types: 6.21.0 - - '@types/node@25.0.3': - dependencies: - undici-types: 7.16.0 - - '@types/plist@3.0.5': - dependencies: - '@types/node': 25.0.3 - xmlbuilder: 15.1.1 - optional: true - - '@types/react-dom@19.2.3(@types/react@19.2.7)': - dependencies: - '@types/react': 19.2.7 - - '@types/react@19.2.7': - dependencies: - csstype: 3.2.3 - - '@types/responselike@1.0.3': - dependencies: - '@types/node': 25.0.3 - - '@types/unist@2.0.11': {} - - '@types/unist@3.0.3': {} - - '@types/uuid@10.0.0': {} - - '@types/verror@1.10.11': - optional: true - - '@types/yauzl@2.10.3': - dependencies: - '@types/node': 25.0.3 - optional: true - - '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 - eslint: 9.39.2(jiti@2.6.1) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 - debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/project-service@8.50.0(typescript@5.9.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 - debug: 4.4.3 - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.50.0': - dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 - - '@typescript-eslint/tsconfig-utils@8.50.0(typescript@5.9.3)': - dependencies: - typescript: 5.9.3 - - '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - ts-api-utils: 2.1.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.50.0': {} - - '@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)': - dependencies: - '@typescript-eslint/project-service': 8.50.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 - debug: 4.4.3 - minimatch: 9.0.5 - semver: 7.7.3 - tinyglobby: 0.2.15 - ts-api-utils: 2.1.0(typescript@5.9.3) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.50.0': - dependencies: - '@typescript-eslint/types': 8.50.0 - eslint-visitor-keys: 4.2.1 - - '@ungap/structured-clone@1.3.0': {} - - '@vitejs/plugin-react@5.1.2(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))': - dependencies: - '@babel/core': 7.28.5 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) - '@rolldown/pluginutils': 1.0.0-beta.53 - '@types/babel__core': 7.20.5 - react-refresh: 0.18.0 - vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2) - transitivePeerDependencies: - - supports-color - - '@vitest/expect@4.0.16': - dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.0.16 - '@vitest/utils': 4.0.16 - chai: 6.2.1 - tinyrainbow: 3.0.3 - - '@vitest/mocker@4.0.16(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2))': - dependencies: - '@vitest/spy': 4.0.16 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2) - - '@vitest/pretty-format@4.0.16': - dependencies: - tinyrainbow: 3.0.3 - - '@vitest/runner@4.0.16': - dependencies: - '@vitest/utils': 4.0.16 - pathe: 2.0.3 - - '@vitest/snapshot@4.0.16': - dependencies: - '@vitest/pretty-format': 4.0.16 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@4.0.16': {} - - '@vitest/utils@4.0.16': - dependencies: - '@vitest/pretty-format': 4.0.16 - tinyrainbow: 3.0.3 - - '@xmldom/xmldom@0.8.11': {} - - '@xterm/addon-fit@0.10.0(@xterm/xterm@5.5.0)': - dependencies: - '@xterm/xterm': 5.5.0 - - '@xterm/addon-serialize@0.13.0(@xterm/xterm@5.5.0)': - dependencies: - '@xterm/xterm': 5.5.0 - - '@xterm/addon-web-links@0.11.0(@xterm/xterm@5.5.0)': - dependencies: - '@xterm/xterm': 5.5.0 - - '@xterm/addon-webgl@0.18.0(@xterm/xterm@5.5.0)': - dependencies: - '@xterm/xterm': 5.5.0 - - '@xterm/xterm@5.5.0': {} - - abbrev@1.1.1: {} - - acorn-jsx@5.3.2(acorn@8.15.0): - dependencies: - acorn: 8.15.0 - - acorn@8.15.0: {} - - agent-base@6.0.2: - dependencies: - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - agent-base@7.1.4: {} - - agentkeepalive@4.6.0: - dependencies: - humanize-ms: 1.2.1 - - aggregate-error@3.1.0: - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - - ajv-keywords@3.5.2(ajv@6.12.6): - dependencies: - ajv: 6.12.6 - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-escapes@7.2.0: - dependencies: - environment: 1.1.0 - - ansi-regex@5.0.1: {} - - ansi-regex@6.2.2: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@5.2.0: {} - - ansi-styles@6.2.3: {} - - app-builder-bin@5.0.0-alpha.12: {} - - app-builder-lib@26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12): - dependencies: - '@develar/schema-utils': 2.6.5 - '@electron/asar': 3.2.18 - '@electron/fuses': 1.8.0 - '@electron/notarize': 2.5.0 - '@electron/osx-sign': 1.3.1 - '@electron/rebuild': 3.7.0 - '@electron/universal': 2.0.1 - '@malept/flatpak-bundler': 0.4.0 - '@types/fs-extra': 9.0.13 - async-exit-hook: 2.0.1 - builder-util: 26.0.11 - builder-util-runtime: 9.3.1 - chromium-pickle-js: 0.2.0 - config-file-ts: 0.2.8-rc1 - debug: 4.4.3 - dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12) - dotenv: 16.6.1 - dotenv-expand: 11.0.7 - ejs: 3.1.10 - electron-builder-squirrel-windows: 26.0.12(dmg-builder@26.0.12) - electron-publish: 26.0.11 - fs-extra: 10.1.0 - hosted-git-info: 4.1.0 - is-ci: 3.0.1 - isbinaryfile: 5.0.7 - js-yaml: 4.1.1 - json5: 2.2.3 - lazy-val: 1.0.5 - minimatch: 10.1.1 - plist: 3.1.0 - resedit: 1.7.2 - semver: 7.7.3 - tar: 6.2.1 - temp-file: 3.4.0 - tiny-async-pool: 1.3.0 - transitivePeerDependencies: - - bluebird - - supports-color - - argparse@2.0.1: {} - - aria-hidden@1.2.6: - dependencies: - tslib: 2.8.1 - - aria-query@5.3.0: - dependencies: - dequal: 2.0.3 - - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - is-array-buffer: 3.0.5 - - array-includes@3.1.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - is-string: 1.1.1 - math-intrinsics: 1.1.0 - - array.prototype.findlast@1.2.5: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-shim-unscopables: 1.1.0 - - array.prototype.flat@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-shim-unscopables: 1.1.0 - - array.prototype.flatmap@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-shim-unscopables: 1.1.0 - - array.prototype.tosorted@1.1.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-shim-unscopables: 1.1.0 - - arraybuffer.prototype.slice@1.0.4: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - is-array-buffer: 3.0.5 - - assert-plus@1.0.0: - optional: true - - assertion-error@2.0.1: {} - - astral-regex@2.0.0: - optional: true - - async-exit-hook@2.0.1: {} - - async-function@1.0.0: {} - - async@3.2.6: {} - - asynckit@0.4.0: {} - - at-least-node@1.0.0: {} - - autoprefixer@10.4.23(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - caniuse-lite: 1.0.30001761 - fraction.js: 5.3.4 - picocolors: 1.1.1 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 - - bail@2.0.2: {} - - balanced-match@1.0.2: {} - - base64-js@1.5.1: {} - - baseline-browser-mapping@2.9.10: {} - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - boolean@3.2.0: - optional: true - - brace-expansion@1.1.12: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.2: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - browserslist@4.28.1: - dependencies: - baseline-browser-mapping: 2.9.10 - caniuse-lite: 1.0.30001761 - electron-to-chromium: 1.5.267 - node-releases: 2.0.27 - update-browserslist-db: 1.2.3(browserslist@4.28.1) - - buffer-crc32@0.2.13: {} - - buffer-from@1.1.2: {} - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - builder-util-runtime@9.3.1: - dependencies: - debug: 4.4.3 - sax: 1.4.3 - transitivePeerDependencies: - - supports-color - - builder-util@26.0.11: - dependencies: - 7zip-bin: 5.2.0 - '@types/debug': 4.1.12 - app-builder-bin: 5.0.0-alpha.12 - builder-util-runtime: 9.3.1 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3 - fs-extra: 10.1.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - is-ci: 3.0.1 - js-yaml: 4.1.1 - sanitize-filename: 1.6.3 - source-map-support: 0.5.21 - stat-mode: 1.0.0 - temp-file: 3.4.0 - tiny-async-pool: 1.3.0 - transitivePeerDependencies: - - supports-color - - cac@6.7.14: {} - - cacache@16.1.3: - dependencies: - '@npmcli/fs': 2.1.2 - '@npmcli/move-file': 2.0.1 - chownr: 2.0.0 - fs-minipass: 2.1.0 - glob: 8.1.0 - infer-owner: 1.0.4 - lru-cache: 7.18.3 - minipass: 3.3.6 - minipass-collect: 1.0.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - mkdirp: 1.0.4 - p-map: 4.0.0 - promise-inflight: 1.0.1 - rimraf: 3.0.2 - ssri: 9.0.1 - tar: 6.2.1 - unique-filename: 2.0.1 - transitivePeerDependencies: - - bluebird - - cacheable-lookup@5.0.4: {} - - cacheable-request@7.0.4: - dependencies: - clone-response: 1.0.3 - get-stream: 5.2.0 - http-cache-semantics: 4.2.0 - keyv: 4.5.4 - lowercase-keys: 2.0.0 - normalize-url: 6.1.0 - responselike: 2.0.1 - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.8: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - get-intrinsic: 1.3.0 - set-function-length: 1.2.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - - callsites@3.1.0: {} - - caniuse-lite@1.0.30001761: {} - - ccount@2.0.1: {} - - chai@6.2.1: {} - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - character-entities-html4@2.1.0: {} - - character-entities-legacy@3.0.0: {} - - character-entities@2.0.2: {} - - character-reference-invalid@2.0.1: {} - - chokidar@5.0.0: - dependencies: - readdirp: 5.0.0 - - chownr@2.0.0: {} - - chromium-pickle-js@0.2.0: {} - - ci-info@3.9.0: {} - - class-variance-authority@0.7.1: - dependencies: - clsx: 2.1.1 - - clean-stack@2.2.0: {} - - cli-cursor@3.1.0: - dependencies: - restore-cursor: 3.1.0 - - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-spinners@2.9.2: {} - - cli-truncate@2.1.0: - dependencies: - slice-ansi: 3.0.0 - string-width: 4.2.3 - optional: true - - cli-truncate@5.1.1: - dependencies: - slice-ansi: 7.1.2 - string-width: 8.1.0 - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - clone-response@1.0.3: - dependencies: - mimic-response: 1.0.1 - - clone@1.0.4: {} - - clsx@2.1.1: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - colorette@2.0.20: {} - - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - - comma-separated-tokens@2.0.3: {} - - commander@14.0.2: {} - - commander@5.1.0: {} - - commander@9.5.0: - optional: true - - compare-version@0.1.2: {} - - concat-map@0.0.1: {} - - config-file-ts@0.2.8-rc1: - dependencies: - glob: 10.5.0 - typescript: 5.9.3 - - convert-source-map@2.0.0: {} - - core-util-is@1.0.2: - optional: true - - crc@3.8.0: - dependencies: - buffer: 5.7.1 - optional: true - - cross-dirname@0.1.0: - optional: true - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - cssesc@3.0.0: {} - - cssstyle@4.6.0: - dependencies: - '@asamuzakjp/css-color': 3.2.0 - rrweb-cssom: 0.8.0 - - csstype@3.2.3: {} - - data-urls@5.0.0: - dependencies: - whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 - - data-view-buffer@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-offset@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - decimal.js@10.6.0: {} - - decode-named-character-reference@1.2.0: - dependencies: - character-entities: 2.0.2 - - decompress-response@6.0.0: - dependencies: - mimic-response: 3.1.0 - - deep-is@0.1.4: {} - - defaults@1.0.4: - dependencies: - clone: 1.0.4 - - defer-to-connect@2.0.1: {} - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - delayed-stream@1.0.0: {} - - dequal@2.0.3: {} - - detect-libc@2.1.2: {} - - detect-node-es@1.1.0: {} - - detect-node@2.1.0: - optional: true - - devlop@1.1.0: - dependencies: - dequal: 2.0.3 - - dir-compare@4.2.0: - dependencies: - minimatch: 3.1.2 - p-limit: 3.1.0 - - dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12): - dependencies: - app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) - builder-util: 26.0.11 - builder-util-runtime: 9.3.1 - fs-extra: 10.1.0 - iconv-lite: 0.6.3 - js-yaml: 4.1.1 - optionalDependencies: - dmg-license: 1.0.11 - transitivePeerDependencies: - - bluebird - - electron-builder-squirrel-windows - - supports-color - - dmg-license@1.0.11: - dependencies: - '@types/plist': 3.0.5 - '@types/verror': 1.10.11 - ajv: 6.12.6 - crc: 3.8.0 - iconv-corefoundation: 1.1.7 - plist: 3.1.0 - smart-buffer: 4.2.0 - verror: 1.10.1 - optional: true - - doctrine@2.1.0: - dependencies: - esutils: 2.0.3 - - dom-accessibility-api@0.5.16: {} - - dotenv-expand@11.0.7: - dependencies: - dotenv: 16.6.1 - - dotenv@16.6.1: {} - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - eastasianwidth@0.2.0: {} - - ejs@3.1.10: - dependencies: - jake: 10.9.4 - - electron-builder-squirrel-windows@26.0.12(dmg-builder@26.0.12): - dependencies: - app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) - builder-util: 26.0.11 - electron-winstaller: 5.4.0 - transitivePeerDependencies: - - bluebird - - dmg-builder - - supports-color - - electron-builder@26.0.12(electron-builder-squirrel-windows@26.0.12): - dependencies: - app-builder-lib: 26.0.12(dmg-builder@26.0.12)(electron-builder-squirrel-windows@26.0.12) - builder-util: 26.0.11 - builder-util-runtime: 9.3.1 - chalk: 4.1.2 - dmg-builder: 26.0.12(electron-builder-squirrel-windows@26.0.12) - fs-extra: 10.1.0 - is-ci: 3.0.1 - lazy-val: 1.0.5 - simple-update-notifier: 2.0.0 - yargs: 17.7.2 - transitivePeerDependencies: - - bluebird - - electron-builder-squirrel-windows - - supports-color - - electron-publish@26.0.11: - dependencies: - '@types/fs-extra': 9.0.13 - builder-util: 26.0.11 - builder-util-runtime: 9.3.1 - chalk: 4.1.2 - form-data: 4.0.5 - fs-extra: 10.1.0 - lazy-val: 1.0.5 - mime: 2.6.0 - transitivePeerDependencies: - - supports-color - - electron-to-chromium@1.5.267: {} - - electron-updater@6.6.2: - dependencies: - builder-util-runtime: 9.3.1 - fs-extra: 10.1.0 - js-yaml: 4.1.1 - lazy-val: 1.0.5 - lodash.escaperegexp: 4.1.2 - lodash.isequal: 4.5.0 - semver: 7.7.3 - tiny-typed-emitter: 2.1.0 - transitivePeerDependencies: - - supports-color - - electron-vite@5.0.0(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)): - dependencies: - '@babel/core': 7.28.5 - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.5) - cac: 6.7.14 - esbuild: 0.25.12 - magic-string: 0.30.21 - picocolors: 1.1.1 - vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2) - transitivePeerDependencies: - - supports-color - - electron-winstaller@5.4.0: - dependencies: - '@electron/asar': 3.4.1 - debug: 4.4.3 - fs-extra: 7.0.1 - lodash: 4.17.21 - temp: 0.9.4 - optionalDependencies: - '@electron/windows-sign': 1.2.2 - transitivePeerDependencies: - - supports-color - - electron@39.2.7: - dependencies: - '@electron/get': 2.0.3 - '@types/node': 22.19.3 - extract-zip: 2.0.1 - transitivePeerDependencies: - - supports-color - - emoji-regex@10.6.0: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - - encoding@0.1.13: - dependencies: - iconv-lite: 0.6.3 - optional: true - - end-of-stream@1.4.5: - dependencies: - once: 1.4.0 - - enhanced-resolve@5.18.4: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 - - entities@6.0.1: {} - - env-paths@2.2.1: {} - - environment@1.1.0: {} - - err-code@2.0.3: {} - - es-abstract@1.24.1: - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.4 - data-view-buffer: 1.0.2 - data-view-byte-length: 1.0.2 - data-view-byte-offset: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - get-symbol-description: 1.1.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - internal-slot: 1.1.0 - is-array-buffer: 3.0.5 - is-callable: 1.2.7 - is-data-view: 1.0.2 - is-negative-zero: 2.0.3 - is-regex: 1.2.1 - is-set: 2.0.3 - is-shared-array-buffer: 1.0.4 - is-string: 1.1.1 - is-typed-array: 1.1.15 - is-weakref: 1.1.1 - math-intrinsics: 1.1.0 - object-inspect: 1.13.4 - object-keys: 1.1.1 - object.assign: 4.1.7 - own-keys: 1.0.1 - regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 - safe-push-apply: 1.0.0 - safe-regex-test: 1.1.0 - set-proto: 1.0.0 - stop-iteration-iterator: 1.1.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.3 - typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.19 - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-iterator-helpers@1.2.2: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-set-tostringtag: 2.1.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - iterator.prototype: 1.1.5 - safe-array-concat: 1.1.3 - - es-module-lexer@1.7.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - es-shim-unscopables@1.1.0: - dependencies: - hasown: 2.0.2 - - es-to-primitive@1.3.0: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - - es6-error@4.1.1: - optional: true - - esbuild@0.25.12: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 - - esbuild@0.27.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.2 - '@esbuild/android-arm': 0.27.2 - '@esbuild/android-arm64': 0.27.2 - '@esbuild/android-x64': 0.27.2 - '@esbuild/darwin-arm64': 0.27.2 - '@esbuild/darwin-x64': 0.27.2 - '@esbuild/freebsd-arm64': 0.27.2 - '@esbuild/freebsd-x64': 0.27.2 - '@esbuild/linux-arm': 0.27.2 - '@esbuild/linux-arm64': 0.27.2 - '@esbuild/linux-ia32': 0.27.2 - '@esbuild/linux-loong64': 0.27.2 - '@esbuild/linux-mips64el': 0.27.2 - '@esbuild/linux-ppc64': 0.27.2 - '@esbuild/linux-riscv64': 0.27.2 - '@esbuild/linux-s390x': 0.27.2 - '@esbuild/linux-x64': 0.27.2 - '@esbuild/netbsd-arm64': 0.27.2 - '@esbuild/netbsd-x64': 0.27.2 - '@esbuild/openbsd-arm64': 0.27.2 - '@esbuild/openbsd-x64': 0.27.2 - '@esbuild/openharmony-arm64': 0.27.2 - '@esbuild/sunos-x64': 0.27.2 - '@esbuild/win32-arm64': 0.27.2 - '@esbuild/win32-ia32': 0.27.2 - '@esbuild/win32-x64': 0.27.2 - - escalade@3.2.0: {} - - escape-string-regexp@4.0.0: {} - - escape-string-regexp@5.0.0: {} - - eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)): - dependencies: - '@babel/core': 7.28.5 - '@babel/parser': 7.28.5 - eslint: 9.39.2(jiti@2.6.1) - hermes-parser: 0.25.1 - zod: 4.2.1 - zod-validation-error: 4.0.2(zod@4.2.1) - transitivePeerDependencies: - - supports-color - - eslint-plugin-react@7.37.5(eslint@9.39.2(jiti@2.6.1)): - dependencies: - array-includes: 3.1.9 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.3 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.2.2 - eslint: 9.39.2(jiti@2.6.1) - estraverse: 5.3.0 - hasown: 2.0.2 - jsx-ast-utils: 3.3.5 - minimatch: 3.1.2 - object.entries: 1.1.9 - object.fromentries: 2.0.8 - object.values: 1.2.1 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.12 - string.prototype.repeat: 1.0.0 - - eslint-scope@8.4.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.1: {} - - eslint@9.39.2(jiti@2.6.1): - dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.1 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.3 - '@eslint/js': 9.39.2 - '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.6.1 - transitivePeerDependencies: - - supports-color - - espree@10.4.0: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 4.2.1 - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - estree-util-is-identifier-name@3.0.0: {} - - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.8 - - esutils@2.0.3: {} - - eventemitter3@5.0.1: {} - - expect-type@1.3.0: {} - - exponential-backoff@3.1.3: {} - - extend@3.0.2: {} - - extract-zip@2.0.1: - dependencies: - debug: 4.4.3 - get-stream: 5.2.0 - yauzl: 2.10.0 - optionalDependencies: - '@types/yauzl': 2.10.3 - transitivePeerDependencies: - - supports-color - - extsprintf@1.4.1: - optional: true - - fast-deep-equal@3.1.3: {} - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fd-slicer@1.1.0: - dependencies: - pend: 1.2.0 - - fdir@6.5.0(picomatch@4.0.3): - optionalDependencies: - picomatch: 4.0.3 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - filelist@1.0.4: - dependencies: - minimatch: 5.1.6 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.3 - keyv: 4.5.4 - - flatted@3.3.3: {} - - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 - - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - - form-data@4.0.5: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - - fraction.js@5.3.4: {} - - framer-motion@12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3): - dependencies: - motion-dom: 12.23.23 - motion-utils: 12.23.6 - tslib: 2.8.1 - optionalDependencies: - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fs-extra@11.3.3: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fs-extra@7.0.1: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - - fs-extra@8.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - - fs-extra@9.1.0: - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fs-minipass@2.1.0: - dependencies: - minipass: 3.3.6 - - fs.realpath@1.0.0: {} - - fsevents@2.3.2: - optional: true - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - function.prototype.name@1.1.8: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - hasown: 2.0.2 - is-callable: 1.2.7 - - functions-have-names@1.2.3: {} - - generator-function@2.0.1: {} - - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - - get-east-asian-width@1.4.0: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-nonce@1.0.1: {} - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - get-stream@5.2.0: - dependencies: - pump: 3.0.3 - - get-symbol-description@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@10.5.0: - dependencies: - foreground-child: 3.3.1 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - - global-agent@3.0.0: - dependencies: - boolean: 3.2.0 - es6-error: 4.1.1 - matcher: 3.0.0 - roarr: 2.15.4 - semver: 7.7.3 - serialize-error: 7.0.1 - optional: true - - globals@14.0.0: {} - - globals@16.5.0: {} - - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - - gopd@1.2.0: {} - - got@11.8.6: - dependencies: - '@sindresorhus/is': 4.6.0 - '@szmarczak/http-timer': 4.0.6 - '@types/cacheable-request': 6.0.3 - '@types/responselike': 1.0.3 - cacheable-lookup: 5.0.4 - cacheable-request: 7.0.4 - decompress-response: 6.0.0 - http2-wrapper: 1.0.3 - lowercase-keys: 2.0.0 - p-cancelable: 2.1.1 - responselike: 2.0.1 - - graceful-fs@4.2.11: {} - - has-bigints@1.1.0: {} - - has-flag@4.0.0: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - - has-proto@1.2.0: - dependencies: - dunder-proto: 1.0.1 - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - hast-util-to-jsx-runtime@2.3.6: - dependencies: - '@types/estree': 1.0.8 - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.2.0 - mdast-util-mdxjs-esm: 2.0.1 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - style-to-js: 1.1.21 - unist-util-position: 5.0.0 - vfile-message: 4.0.3 - transitivePeerDependencies: - - supports-color - - hast-util-whitespace@3.0.0: - dependencies: - '@types/hast': 3.0.4 - - hermes-estree@0.25.1: {} - - hermes-parser@0.25.1: - dependencies: - hermes-estree: 0.25.1 - - hosted-git-info@4.1.0: - dependencies: - lru-cache: 6.0.0 - - html-encoding-sniffer@4.0.0: - dependencies: - whatwg-encoding: 3.1.1 - - html-url-attributes@3.0.1: {} - - http-cache-semantics@4.2.0: {} - - http-proxy-agent@5.0.0: - dependencies: - '@tootallnate/once': 2.0.0 - agent-base: 6.0.2 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - http2-wrapper@1.0.3: - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - https-proxy-agent@7.0.6: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - - husky@9.1.7: {} - - iconv-corefoundation@1.1.7: - dependencies: - cli-truncate: 2.1.0 - node-addon-api: 1.7.2 - optional: true - - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - - ieee754@1.2.1: {} - - ignore@5.3.2: {} - - ignore@7.0.5: {} - - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - imurmurhash@0.1.4: {} - - indent-string@4.0.0: {} - - infer-owner@1.0.4: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - inline-style-parser@0.2.7: {} - - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - - ip-address@10.1.0: {} - - is-alphabetical@2.0.1: {} - - is-alphanumerical@2.0.1: - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - - is-async-function@2.1.1: - dependencies: - async-function: 1.0.0 - call-bound: 1.0.4 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-bigint@1.1.0: - dependencies: - has-bigints: 1.1.0 - - is-boolean-object@1.2.2: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-callable@1.2.7: {} - - is-ci@3.0.1: - dependencies: - ci-info: 3.9.0 - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-data-view@1.0.2: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - is-typed-array: 1.1.15 - - is-date-object@1.1.0: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-decimal@2.0.1: {} - - is-extglob@2.1.1: {} - - is-finalizationregistry@1.1.1: - dependencies: - call-bound: 1.0.4 - - is-fullwidth-code-point@3.0.0: {} - - is-fullwidth-code-point@5.1.0: - dependencies: - get-east-asian-width: 1.4.0 - - is-generator-function@1.1.2: - dependencies: - call-bound: 1.0.4 - generator-function: 2.0.1 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-hexadecimal@2.0.1: {} - - is-interactive@1.0.0: {} - - is-lambda@1.0.1: {} - - is-map@2.0.3: {} - - is-negative-zero@2.0.3: {} - - is-number-object@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-number@7.0.0: {} - - is-plain-obj@4.1.0: {} - - is-potential-custom-element-name@1.0.1: {} - - is-regex@1.2.1: - dependencies: - call-bound: 1.0.4 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.4 - - is-string@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-symbol@1.1.1: - dependencies: - call-bound: 1.0.4 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.19 - - is-unicode-supported@0.1.0: {} - - is-weakmap@2.0.2: {} - - is-weakref@1.1.1: - dependencies: - call-bound: 1.0.4 - - is-weakset@2.0.4: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - - isarray@2.0.5: {} - - isbinaryfile@4.0.10: {} - - isbinaryfile@5.0.7: {} - - isexe@2.0.0: {} - - iterator.prototype@1.1.5: - dependencies: - define-data-property: 1.1.4 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - has-symbols: 1.1.0 - set-function-name: 2.0.2 - - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jake@10.9.4: - dependencies: - async: 3.2.6 - filelist: 1.0.4 - picocolors: 1.1.1 - - jiti@2.6.1: {} - - js-tokens@4.0.0: {} - - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 - - jsdom@26.1.0: - dependencies: - cssstyle: 4.6.0 - data-urls: 5.0.0 - decimal.js: 10.6.0 - html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.23 - parse5: 7.3.0 - rrweb-cssom: 0.8.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 5.1.2 - w3c-xmlserializer: 5.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 3.1.1 - whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 - ws: 8.18.3 - xml-name-validator: 5.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - jsesc@3.1.0: {} - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json-stringify-safe@5.0.1: - optional: true - - json5@2.2.3: {} - - jsonfile@4.0.0: - optionalDependencies: - graceful-fs: 4.2.11 - - jsonfile@6.2.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - jsx-ast-utils@3.3.5: - dependencies: - array-includes: 3.1.9 - array.prototype.flat: 1.3.3 - object.assign: 4.1.7 - object.values: 1.2.1 - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - lazy-val@1.0.5: {} - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lightningcss-android-arm64@1.30.2: - optional: true - - lightningcss-darwin-arm64@1.30.2: - optional: true - - lightningcss-darwin-x64@1.30.2: - optional: true - - lightningcss-freebsd-x64@1.30.2: - optional: true - - lightningcss-linux-arm-gnueabihf@1.30.2: - optional: true - - lightningcss-linux-arm64-gnu@1.30.2: - optional: true - - lightningcss-linux-arm64-musl@1.30.2: - optional: true - - lightningcss-linux-x64-gnu@1.30.2: - optional: true - - lightningcss-linux-x64-musl@1.30.2: - optional: true - - lightningcss-win32-arm64-msvc@1.30.2: - optional: true - - lightningcss-win32-x64-msvc@1.30.2: - optional: true - - lightningcss@1.30.2: - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.30.2 - lightningcss-darwin-arm64: 1.30.2 - lightningcss-darwin-x64: 1.30.2 - lightningcss-freebsd-x64: 1.30.2 - lightningcss-linux-arm-gnueabihf: 1.30.2 - lightningcss-linux-arm64-gnu: 1.30.2 - lightningcss-linux-arm64-musl: 1.30.2 - lightningcss-linux-x64-gnu: 1.30.2 - lightningcss-linux-x64-musl: 1.30.2 - lightningcss-win32-arm64-msvc: 1.30.2 - lightningcss-win32-x64-msvc: 1.30.2 - - lint-staged@16.2.7: - dependencies: - commander: 14.0.2 - listr2: 9.0.5 - micromatch: 4.0.8 - nano-spawn: 2.0.0 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.8.2 - - listr2@9.0.5: - dependencies: - cli-truncate: 5.1.1 - colorette: 2.0.20 - eventemitter3: 5.0.1 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 9.0.2 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.escaperegexp@4.1.2: {} - - lodash.isequal@4.5.0: {} - - lodash.merge@4.6.2: {} - - lodash@4.17.21: {} - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - - log-update@6.1.0: - dependencies: - ansi-escapes: 7.2.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.2 - strip-ansi: 7.1.2 - wrap-ansi: 9.0.2 - - longest-streak@3.1.0: {} - - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - - lowercase-keys@2.0.0: {} - - lru-cache@10.4.3: {} - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - - lru-cache@7.18.3: {} - - lucide-react@0.560.0(react@19.2.3): - dependencies: - react: 19.2.3 - - lz-string@1.5.0: {} - - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - make-fetch-happen@10.2.1: - dependencies: - agentkeepalive: 4.6.0 - cacache: 16.1.3 - http-cache-semantics: 4.2.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - is-lambda: 1.0.1 - lru-cache: 7.18.3 - minipass: 3.3.6 - minipass-collect: 1.0.2 - minipass-fetch: 2.1.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - negotiator: 0.6.4 - promise-retry: 2.0.1 - socks-proxy-agent: 7.0.0 - ssri: 9.0.1 - transitivePeerDependencies: - - bluebird - - supports-color - - markdown-table@3.0.4: {} - - matcher@3.0.0: - dependencies: - escape-string-regexp: 4.0.0 - optional: true - - math-intrinsics@1.1.0: {} - - mdast-util-find-and-replace@3.0.2: - dependencies: - '@types/mdast': 4.0.4 - escape-string-regexp: 5.0.0 - unist-util-is: 6.0.1 - unist-util-visit-parents: 6.0.2 - - mdast-util-from-markdown@2.0.2: - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - decode-named-character-reference: 1.2.0 - devlop: 1.1.0 - mdast-util-to-string: 4.0.0 - micromark: 4.0.2 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-decode-string: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - unist-util-stringify-position: 4.0.0 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-autolink-literal@2.0.1: - dependencies: - '@types/mdast': 4.0.4 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-find-and-replace: 3.0.2 - micromark-util-character: 2.1.1 - - mdast-util-gfm-footnote@2.1.0: - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - micromark-util-normalize-identifier: 2.0.1 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-strikethrough@2.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-table@2.0.0: - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - markdown-table: 3.0.4 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-task-list-item@2.0.0: - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm@3.1.0: - dependencies: - mdast-util-from-markdown: 2.0.2 - mdast-util-gfm-autolink-literal: 2.0.1 - mdast-util-gfm-footnote: 2.1.0 - mdast-util-gfm-strikethrough: 2.0.0 - mdast-util-gfm-table: 2.0.0 - mdast-util-gfm-task-list-item: 2.0.0 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-mdx-expression@2.0.1: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-mdx-jsx@3.2.0: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - parse-entities: 4.0.2 - stringify-entities: 4.0.4 - unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.3 - transitivePeerDependencies: - - supports-color - - mdast-util-mdxjs-esm@2.0.1: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-phrasing@4.1.0: - dependencies: - '@types/mdast': 4.0.4 - unist-util-is: 6.0.1 - - mdast-util-to-hast@13.2.1: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.3.0 - devlop: 1.1.0 - micromark-util-sanitize-uri: 2.0.1 - trim-lines: 3.0.1 - unist-util-position: 5.0.0 - unist-util-visit: 5.0.0 - vfile: 6.0.3 - - mdast-util-to-markdown@2.1.2: - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - longest-streak: 3.1.0 - mdast-util-phrasing: 4.1.0 - mdast-util-to-string: 4.0.0 - micromark-util-classify-character: 2.0.1 - micromark-util-decode-string: 2.0.1 - unist-util-visit: 5.0.0 - zwitch: 2.0.4 - - mdast-util-to-string@4.0.0: - dependencies: - '@types/mdast': 4.0.4 - - micromark-core-commonmark@2.0.3: - dependencies: - decode-named-character-reference: 1.2.0 - devlop: 1.1.0 - micromark-factory-destination: 2.0.1 - micromark-factory-label: 2.0.1 - micromark-factory-space: 2.0.1 - micromark-factory-title: 2.0.1 - micromark-factory-whitespace: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-chunked: 2.0.1 - micromark-util-classify-character: 2.0.1 - micromark-util-html-tag-name: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-subtokenize: 2.1.0 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-autolink-literal@2.1.0: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-footnote@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-strikethrough@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.1 - micromark-util-classify-character: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-table@2.1.1: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-tagfilter@2.0.0: - dependencies: - micromark-util-types: 2.0.2 - - micromark-extension-gfm-task-list-item@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm@3.0.0: - dependencies: - micromark-extension-gfm-autolink-literal: 2.1.0 - micromark-extension-gfm-footnote: 2.1.0 - micromark-extension-gfm-strikethrough: 2.1.0 - micromark-extension-gfm-table: 2.1.1 - micromark-extension-gfm-tagfilter: 2.0.0 - micromark-extension-gfm-task-list-item: 2.1.0 - micromark-util-combine-extensions: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-destination@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-label@2.0.1: - dependencies: - devlop: 1.1.0 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-space@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-types: 2.0.2 - - micromark-factory-title@2.0.1: - dependencies: - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-whitespace@2.0.1: - dependencies: - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-character@2.1.1: - dependencies: - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-chunked@2.0.1: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-classify-character@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-combine-extensions@2.0.1: - dependencies: - micromark-util-chunked: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-decode-numeric-character-reference@2.0.2: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-decode-string@2.0.1: - dependencies: - decode-named-character-reference: 1.2.0 - micromark-util-character: 2.1.1 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-symbol: 2.0.1 - - micromark-util-encode@2.0.1: {} - - micromark-util-html-tag-name@2.0.1: {} - - micromark-util-normalize-identifier@2.0.1: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-resolve-all@2.0.1: - dependencies: - micromark-util-types: 2.0.2 - - micromark-util-sanitize-uri@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-encode: 2.0.1 - micromark-util-symbol: 2.0.1 - - micromark-util-subtokenize@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-symbol@2.0.1: {} - - micromark-util-types@2.0.2: {} - - micromark@4.0.2: - dependencies: - '@types/debug': 4.1.12 - debug: 4.4.3 - decode-named-character-reference: 1.2.0 - devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-chunked: 2.0.1 - micromark-util-combine-extensions: 2.0.1 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-encode: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-subtokenize: 2.1.0 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - transitivePeerDependencies: - - supports-color - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mime@2.6.0: {} - - mimic-fn@2.1.0: {} - - mimic-function@5.0.1: {} - - mimic-response@1.0.1: {} - - mimic-response@3.1.0: {} - - minimatch@10.1.1: - dependencies: - '@isaacs/brace-expansion': 5.0.0 - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 - - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.2 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.2 - - minimist@1.2.8: {} - - minipass-collect@1.0.2: - dependencies: - minipass: 3.3.6 - - minipass-fetch@2.1.2: - dependencies: - minipass: 3.3.6 - minipass-sized: 1.0.3 - minizlib: 2.1.2 - optionalDependencies: - encoding: 0.1.13 - - minipass-flush@1.0.5: - dependencies: - minipass: 3.3.6 - - minipass-pipeline@1.2.4: - dependencies: - minipass: 3.3.6 - - minipass-sized@1.0.3: - dependencies: - minipass: 3.3.6 - - minipass@3.3.6: - dependencies: - yallist: 4.0.0 - - minipass@5.0.0: {} - - minipass@7.1.2: {} - - minizlib@2.1.2: - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - mkdirp@1.0.4: {} - - motion-dom@12.23.23: - dependencies: - motion-utils: 12.23.6 - - motion-utils@12.23.6: {} - - motion@12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3): - dependencies: - framer-motion: 12.23.26(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - tslib: 2.8.1 - optionalDependencies: - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - - ms@2.1.3: {} - - nano-spawn@2.0.0: {} - - nanoid@3.3.11: {} - - natural-compare@1.4.0: {} - - negotiator@0.6.4: {} - - node-abi@3.85.0: - dependencies: - semver: 7.7.3 - - node-addon-api@1.7.2: - optional: true - - node-api-version@0.2.1: - dependencies: - semver: 7.7.3 - - node-releases@2.0.27: {} - - nopt@6.0.0: - dependencies: - abbrev: 1.1.1 - - normalize-url@6.1.0: {} - - nwsapi@2.2.23: {} - - object-assign@4.1.1: {} - - object-inspect@1.13.4: {} - - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - - object.entries@1.1.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - object.fromentries@2.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - - object.values@1.2.1: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - obug@2.1.1: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - onetime@7.0.0: - dependencies: - mimic-function: 5.0.1 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - ora@5.4.1: - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - - own-keys@1.0.1: - dependencies: - get-intrinsic: 1.3.0 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - - p-cancelable@2.1.1: {} - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - p-map@4.0.0: - dependencies: - aggregate-error: 3.1.0 - - package-json-from-dist@1.0.1: {} - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse-entities@4.0.2: - dependencies: - '@types/unist': 2.0.11 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.2.0 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - - parse5@7.3.0: - dependencies: - entities: 6.0.1 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-parse@1.0.7: {} - - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - - pathe@2.0.3: {} - - pe-library@0.4.1: {} - - pend@1.2.0: {} - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - picomatch@4.0.3: {} - - pidtree@0.6.0: {} - - playwright-core@1.57.0: {} - - playwright@1.57.0: - dependencies: - playwright-core: 1.57.0 - optionalDependencies: - fsevents: 2.3.2 - - plist@3.1.0: - dependencies: - '@xmldom/xmldom': 0.8.11 - base64-js: 1.5.1 - xmlbuilder: 15.1.1 - - possible-typed-array-names@1.1.0: {} - - postcss-selector-parser@6.0.10: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-value-parser@4.2.0: {} - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - postject@1.0.0-alpha.6: - dependencies: - commander: 9.5.0 - optional: true - - prelude-ls@1.2.1: {} - - pretty-format@27.5.1: - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - - proc-log@2.0.1: {} - - progress@2.0.3: {} - - promise-inflight@1.0.1: {} - - promise-retry@2.0.1: - dependencies: - err-code: 2.0.3 - retry: 0.12.0 - - prop-types@15.8.1: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - property-information@7.1.0: {} - - pump@3.0.3: - dependencies: - end-of-stream: 1.4.5 - once: 1.4.0 - - punycode@2.3.1: {} - - quick-lru@5.1.1: {} - - react-dom@19.2.3(react@19.2.3): - dependencies: - react: 19.2.3 - scheduler: 0.27.0 - - react-is@16.13.1: {} - - react-is@17.0.2: {} - - react-markdown@10.1.0(@types/react@19.2.7)(react@19.2.3): - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/react': 19.2.7 - devlop: 1.1.0 - hast-util-to-jsx-runtime: 2.3.6 - html-url-attributes: 3.0.1 - mdast-util-to-hast: 13.2.1 - react: 19.2.3 - remark-parse: 11.0.0 - remark-rehype: 11.1.2 - unified: 11.0.5 - unist-util-visit: 5.0.0 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - - react-refresh@0.18.0: {} - - react-remove-scroll-bar@2.3.8(@types/react@19.2.7)(react@19.2.3): - dependencies: - react: 19.2.3 - react-style-singleton: 2.2.3(@types/react@19.2.7)(react@19.2.3) - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.7 - - react-remove-scroll@2.7.2(@types/react@19.2.7)(react@19.2.3): - dependencies: - react: 19.2.3 - react-remove-scroll-bar: 2.3.8(@types/react@19.2.7)(react@19.2.3) - react-style-singleton: 2.2.3(@types/react@19.2.7)(react@19.2.3) - tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.2.7)(react@19.2.3) - use-sidecar: 1.1.3(@types/react@19.2.7)(react@19.2.3) - optionalDependencies: - '@types/react': 19.2.7 - - react-resizable-panels@3.0.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3): - dependencies: - react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) - - react-style-singleton@2.2.3(@types/react@19.2.7)(react@19.2.3): - dependencies: - get-nonce: 1.0.1 - react: 19.2.3 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.7 - - react@19.2.3: {} - - read-binary-file-arch@1.0.6: - dependencies: - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - readdirp@5.0.0: {} - - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - - remark-gfm@4.0.1: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-gfm: 3.1.0 - micromark-extension-gfm: 3.0.0 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - - remark-parse@11.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.2 - micromark-util-types: 2.0.2 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - - remark-rehype@11.1.2: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - mdast-util-to-hast: 13.2.1 - unified: 11.0.5 - vfile: 6.0.3 - - remark-stringify@11.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-to-markdown: 2.1.2 - unified: 11.0.5 - - require-directory@2.1.1: {} - - resedit@1.7.2: - dependencies: - pe-library: 0.4.1 - - resolve-alpn@1.2.1: {} - - resolve-from@4.0.0: {} - - resolve@2.0.0-next.5: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - responselike@2.0.1: - dependencies: - lowercase-keys: 2.0.0 - - restore-cursor@3.1.0: - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - - retry@0.12.0: {} - - rfdc@1.4.1: {} - - rimraf@2.6.3: - dependencies: - glob: 7.2.3 - - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - - roarr@2.15.4: - dependencies: - boolean: 3.2.0 - detect-node: 2.1.0 - globalthis: 1.0.4 - json-stringify-safe: 5.0.1 - semver-compare: 1.0.0 - sprintf-js: 1.1.3 - optional: true - - rollup@4.53.5: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.5 - '@rollup/rollup-android-arm64': 4.53.5 - '@rollup/rollup-darwin-arm64': 4.53.5 - '@rollup/rollup-darwin-x64': 4.53.5 - '@rollup/rollup-freebsd-arm64': 4.53.5 - '@rollup/rollup-freebsd-x64': 4.53.5 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.5 - '@rollup/rollup-linux-arm-musleabihf': 4.53.5 - '@rollup/rollup-linux-arm64-gnu': 4.53.5 - '@rollup/rollup-linux-arm64-musl': 4.53.5 - '@rollup/rollup-linux-loong64-gnu': 4.53.5 - '@rollup/rollup-linux-ppc64-gnu': 4.53.5 - '@rollup/rollup-linux-riscv64-gnu': 4.53.5 - '@rollup/rollup-linux-riscv64-musl': 4.53.5 - '@rollup/rollup-linux-s390x-gnu': 4.53.5 - '@rollup/rollup-linux-x64-gnu': 4.53.5 - '@rollup/rollup-linux-x64-musl': 4.53.5 - '@rollup/rollup-openharmony-arm64': 4.53.5 - '@rollup/rollup-win32-arm64-msvc': 4.53.5 - '@rollup/rollup-win32-ia32-msvc': 4.53.5 - '@rollup/rollup-win32-x64-gnu': 4.53.5 - '@rollup/rollup-win32-x64-msvc': 4.53.5 - fsevents: 2.3.3 - - rrweb-cssom@0.8.0: {} - - safe-array-concat@1.1.3: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - isarray: 2.0.5 - - safe-buffer@5.2.1: {} - - safe-push-apply@1.0.0: - dependencies: - es-errors: 1.3.0 - isarray: 2.0.5 - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-regex: 1.2.1 - - safer-buffer@2.1.2: {} - - sanitize-filename@1.6.3: - dependencies: - truncate-utf8-bytes: 1.0.2 - - sax@1.4.3: {} - - saxes@6.0.0: - dependencies: - xmlchars: 2.2.0 - - scheduler@0.27.0: {} - - semver-compare@1.0.0: - optional: true - - semver@5.7.2: {} - - semver@6.3.1: {} - - semver@7.7.3: {} - - serialize-error@7.0.1: - dependencies: - type-fest: 0.13.1 - optional: true - - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - - set-proto@1.0.0: - dependencies: - dunder-proto: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - siginfo@2.0.0: {} - - signal-exit@3.0.7: {} - - signal-exit@4.1.0: {} - - simple-update-notifier@2.0.0: - dependencies: - semver: 7.7.3 - - slice-ansi@3.0.0: - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - optional: true - - slice-ansi@7.1.2: - dependencies: - ansi-styles: 6.2.3 - is-fullwidth-code-point: 5.1.0 - - smart-buffer@4.2.0: {} - - socks-proxy-agent@7.0.0: - dependencies: - agent-base: 6.0.2 - debug: 4.4.3 - socks: 2.8.7 - transitivePeerDependencies: - - supports-color - - socks@2.8.7: - dependencies: - ip-address: 10.1.0 - smart-buffer: 4.2.0 - - source-map-js@1.2.1: {} - - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - space-separated-tokens@2.0.2: {} - - sprintf-js@1.1.3: - optional: true - - ssri@9.0.1: - dependencies: - minipass: 3.3.6 - - stackback@0.0.2: {} - - stat-mode@1.0.0: {} - - std-env@3.10.0: {} - - stop-iteration-iterator@1.1.0: - dependencies: - es-errors: 1.3.0 - internal-slot: 1.1.0 - - string-argv@0.3.2: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.2 - - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 - - string-width@8.1.0: - dependencies: - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 - - string.prototype.matchall@4.0.12: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-symbols: 1.1.0 - internal-slot: 1.1.0 - regexp.prototype.flags: 1.5.4 - set-function-name: 2.0.2 - side-channel: 1.1.0 - - string.prototype.repeat@1.0.0: - dependencies: - define-properties: 1.2.1 - es-abstract: 1.24.1 - - string.prototype.trim@1.2.10: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - has-property-descriptors: 1.0.2 - - string.prototype.trimend@1.0.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - stringify-entities@4.0.4: - dependencies: - character-entities-html4: 2.1.0 - character-entities-legacy: 3.0.0 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.2: - dependencies: - ansi-regex: 6.2.2 - - strip-json-comments@3.1.1: {} - - style-to-js@1.1.21: - dependencies: - style-to-object: 1.0.14 - - style-to-object@1.0.14: - dependencies: - inline-style-parser: 0.2.7 - - sumchecker@3.0.1: - dependencies: - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - symbol-tree@3.2.4: {} - - tailwind-merge@3.4.0: {} - - tailwindcss@4.1.18: {} - - tapable@2.3.0: {} - - tar@6.2.1: - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - - temp-file@3.4.0: - dependencies: - async-exit-hook: 2.0.1 - fs-extra: 10.1.0 - - temp@0.9.4: - dependencies: - mkdirp: 0.5.6 - rimraf: 2.6.3 - - tiny-async-pool@1.3.0: - dependencies: - semver: 5.7.2 - - tiny-typed-emitter@2.1.0: {} - - tinybench@2.9.0: {} - - tinyexec@1.0.2: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - tinyrainbow@3.0.3: {} - - tldts-core@6.1.86: {} - - tldts@6.1.86: - dependencies: - tldts-core: 6.1.86 - - tmp-promise@3.0.3: - dependencies: - tmp: 0.2.5 - - tmp@0.2.5: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - tough-cookie@5.1.2: - dependencies: - tldts: 6.1.86 - - tr46@5.1.1: - dependencies: - punycode: 2.3.1 - - trim-lines@3.0.1: {} - - trough@2.2.0: {} - - truncate-utf8-bytes@1.0.2: - dependencies: - utf8-byte-length: 1.0.5 - - ts-api-utils@2.1.0(typescript@5.9.3): - dependencies: - typescript: 5.9.3 - - tslib@2.8.1: {} - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-fest@0.13.1: - optional: true - - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - typed-array-byte-length@1.0.3: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - - typed-array-byte-offset@1.0.4: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - reflect.getprototypeof: 1.0.10 - - typed-array-length@1.0.7: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - is-typed-array: 1.1.15 - possible-typed-array-names: 1.1.0 - reflect.getprototypeof: 1.0.10 - - typescript-eslint@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 - transitivePeerDependencies: - - supports-color - - typescript@5.9.3: {} - - unbox-primitive@1.1.0: - dependencies: - call-bound: 1.0.4 - has-bigints: 1.1.0 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.1 - - undici-types@6.21.0: {} - - undici-types@7.16.0: {} - - unified@11.0.5: - dependencies: - '@types/unist': 3.0.3 - bail: 2.0.2 - devlop: 1.1.0 - extend: 3.0.2 - is-plain-obj: 4.1.0 - trough: 2.2.0 - vfile: 6.0.3 - - unique-filename@2.0.1: - dependencies: - unique-slug: 3.0.0 - - unique-slug@3.0.0: - dependencies: - imurmurhash: 0.1.4 - - unist-util-is@6.0.1: - dependencies: - '@types/unist': 3.0.3 - - unist-util-position@5.0.0: - dependencies: - '@types/unist': 3.0.3 - - unist-util-stringify-position@4.0.0: - dependencies: - '@types/unist': 3.0.3 - - unist-util-visit-parents@6.0.2: - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.1 - - unist-util-visit@5.0.0: - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.1 - unist-util-visit-parents: 6.0.2 - - universalify@0.1.2: {} - - universalify@2.0.1: {} - - update-browserslist-db@1.2.3(browserslist@4.28.1): - dependencies: - browserslist: 4.28.1 - escalade: 3.2.0 - picocolors: 1.1.1 - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.2.3): - dependencies: - react: 19.2.3 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.7 - - use-sidecar@1.1.3(@types/react@19.2.7)(react@19.2.3): - dependencies: - detect-node-es: 1.1.0 - react: 19.2.3 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.7 - - utf8-byte-length@1.0.5: {} - - util-deprecate@1.0.2: {} - - uuid@13.0.0: {} - - verror@1.10.1: - dependencies: - assert-plus: 1.0.0 - core-util-is: 1.0.2 - extsprintf: 1.4.1 - optional: true - - vfile-message@4.0.3: - dependencies: - '@types/unist': 3.0.3 - unist-util-stringify-position: 4.0.0 - - vfile@6.0.3: - dependencies: - '@types/unist': 3.0.3 - vfile-message: 4.0.3 - - vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2): - dependencies: - esbuild: 0.27.2 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.53.5 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 25.0.3 - fsevents: 2.3.3 - jiti: 2.6.1 - lightningcss: 1.30.2 - yaml: 2.8.2 - - vitest@4.0.16(@types/node@25.0.3)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(yaml@2.8.2): - dependencies: - '@vitest/expect': 4.0.16 - '@vitest/mocker': 4.0.16(vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2)) - '@vitest/pretty-format': 4.0.16 - '@vitest/runner': 4.0.16 - '@vitest/snapshot': 4.0.16 - '@vitest/spy': 4.0.16 - '@vitest/utils': 4.0.16 - es-module-lexer: 1.7.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.3 - std-env: 3.10.0 - tinybench: 2.9.0 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tinyrainbow: 3.0.3 - vite: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(yaml@2.8.2) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 25.0.3 - jsdom: 26.1.0 - transitivePeerDependencies: - - jiti - - less - - lightningcss - - msw - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - yaml - - w3c-xmlserializer@5.0.0: - dependencies: - xml-name-validator: 5.0.0 - - wcwidth@1.0.1: - dependencies: - defaults: 1.0.4 - - webidl-conversions@7.0.0: {} - - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 - - whatwg-mimetype@4.0.0: {} - - whatwg-url@14.2.0: - dependencies: - tr46: 5.1.1 - webidl-conversions: 7.0.0 - - which-boxed-primitive@1.1.1: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.2 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - - which-builtin-type@1.2.1: - dependencies: - call-bound: 1.0.4 - function.prototype.name: 1.1.8 - has-tostringtag: 1.0.2 - is-async-function: 2.1.1 - is-date-object: 1.1.0 - is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.2 - is-regex: 1.2.1 - is-weakref: 1.1.1 - isarray: 2.0.5 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.19 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - - which-typed-array@1.1.19: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.4 - for-each: 0.3.5 - get-proto: 1.0.1 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - - word-wrap@1.2.5: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 5.1.2 - strip-ansi: 7.1.2 - - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.1.2 - - wrappy@1.0.2: {} - - ws@8.18.3: {} - - xml-name-validator@5.0.0: {} - - xmlbuilder@15.1.1: {} - - xmlchars@2.2.0: {} - - y18n@5.0.8: {} - - yallist@3.1.1: {} - - yallist@4.0.0: {} - - yaml@2.8.2: {} - - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yauzl@2.10.0: - dependencies: - buffer-crc32: 0.2.13 - fd-slicer: 1.1.0 - - yocto-queue@0.1.0: {} - - zod-validation-error@4.0.2(zod@4.2.1): - dependencies: - zod: 4.2.1 - - zod@4.2.1: {} - - zustand@5.0.9(@types/react@19.2.7)(react@19.2.3): - optionalDependencies: - '@types/react': 19.2.7 - react: 19.2.3 - - zwitch@2.0.4: {} diff --git a/auto-claude-ui/src/main/agent-manager.ts.backup b/auto-claude-ui/src/main/agent-manager.ts.backup deleted file mode 100644 index 0436a024..00000000 --- a/auto-claude-ui/src/main/agent-manager.ts.backup +++ /dev/null @@ -1,1101 +0,0 @@ -import { spawn, ChildProcess } from 'child_process'; -import { EventEmitter } from 'events'; -import path from 'path'; -import { existsSync, readFileSync } from 'fs'; -import { app } from 'electron'; -import { projectStore } from './project-store'; -import { detectRateLimit, createSDKRateLimitInfo, getProfileEnv } from './rate-limit-detector'; - -interface AgentProcess { - taskId: string; - process: ChildProcess; - startedAt: Date; - projectPath?: string; // For ideation processes to load session on completion - spawnId: number; // Unique ID to identify this specific spawn -} - -export interface ExecutionProgressData { - phase: 'idle' | 'planning' | 'coding' | 'qa_review' | 'qa_fixing' | 'complete' | 'failed'; - phaseProgress: number; - overallProgress: number; - currentSubtask?: string; - message?: string; -} - -export type ProcessType = 'spec-creation' | 'task-execution' | 'qa-process'; - -export interface AgentManagerEvents { - log: (taskId: string, log: string) => void; - error: (taskId: string, error: string) => void; - exit: (taskId: string, code: number | null, processType: ProcessType) => void; - 'execution-progress': (taskId: string, progress: ExecutionProgressData) => void; -} - -/** - * Manages Python subprocess spawning for auto-claude agents - */ -export class AgentManager extends EventEmitter { - private processes: Map = new Map(); - private killedSpawnIds: Set = new Set(); // Track spawn IDs whose processes were killed - private spawnCounter: number = 0; // Unique ID for each spawn - private pythonPath: string = 'python3'; - private autoBuildSourcePath: string = ''; // Source auto-claude repo location - - constructor() { - super(); - } - - /** - * Configure paths for Python and auto-claude source - */ - configure(pythonPath?: string, autoBuildSourcePath?: string): void { - if (pythonPath) { - this.pythonPath = pythonPath; - } - if (autoBuildSourcePath) { - this.autoBuildSourcePath = autoBuildSourcePath; - } - } - - /** - * Get the auto-claude source path (detects automatically if not configured) - */ - private getAutoBuildSourcePath(): string | null { - // If manually configured, use that - if (this.autoBuildSourcePath && existsSync(this.autoBuildSourcePath)) { - return this.autoBuildSourcePath; - } - - // Auto-detect from app location - const possiblePaths = [ - // Dev mode: from dist/main -> ../../auto-claude (sibling to auto-claude-ui) - path.resolve(__dirname, '..', '..', '..', 'auto-claude'), - // Alternative: from app root - path.resolve(app.getAppPath(), '..', 'auto-claude'), - // If running from repo root - path.resolve(process.cwd(), 'auto-claude') - ]; - - for (const p of possiblePaths) { - if (existsSync(p) && existsSync(path.join(p, 'VERSION'))) { - return p; - } - } - return null; - } - - /** - * Get project-specific environment variables based on project settings - */ - private getProjectEnvVars(projectPath: string): Record { - const env: Record = {}; - - // Find project by path - const projects = projectStore.getProjects(); - const project = projects.find((p) => p.path === projectPath); - - if (project?.settings) { - // Graphiti MCP integration - if (project.settings.graphitiMcpEnabled) { - const graphitiUrl = project.settings.graphitiMcpUrl || 'http://localhost:8000/mcp/'; - env['GRAPHITI_MCP_URL'] = graphitiUrl; - } - } - - return env; - } - - /** - * Load environment variables from auto-claude .env file - */ - private loadAutoBuildEnv(): Record { - const autoBuildSource = this.getAutoBuildSourcePath(); - if (!autoBuildSource) { - console.log('[loadAutoBuildEnv] No auto-build source path found'); - return {}; - } - - const envPath = path.join(autoBuildSource, '.env'); - console.log('[loadAutoBuildEnv] Looking for .env at:', envPath); - if (!existsSync(envPath)) { - console.log('[loadAutoBuildEnv] .env file does not exist'); - return {}; - } - - try { - const envContent = readFileSync(envPath, 'utf-8'); - const envVars: Record = {}; - - // Handle both Unix (\n) and Windows (\r\n) line endings - for (const line of envContent.split(/\r?\n/)) { - const trimmed = line.trim(); - // Skip comments and empty lines - if (!trimmed || trimmed.startsWith('#')) { - continue; - } - - const eqIndex = trimmed.indexOf('='); - if (eqIndex > 0) { - const key = trimmed.substring(0, eqIndex).trim(); - let value = trimmed.substring(eqIndex + 1).trim(); - - // Remove quotes if present - if ((value.startsWith('"') && value.endsWith('"')) || - (value.startsWith("'") && value.endsWith("'"))) { - value = value.slice(1, -1); - } - - envVars[key] = value; - } - } - - return envVars; - } catch { - return {}; - } - } - - /** - * Start spec creation process - */ - startSpecCreation( - taskId: string, - projectPath: string, - taskDescription: string, - specDir?: string, // Optional spec directory (when task already has a directory created by UI) - metadata?: { requireReviewBeforeCoding?: boolean } // Task metadata to check for review requirement - ): void { - // Use source auto-claude path (the repo), not the project's auto-claude - const autoBuildSource = this.getAutoBuildSourcePath(); - - if (!autoBuildSource) { - this.emit('error', taskId, 'Auto-build source path not found. Please configure it in App Settings.'); - return; - } - - const specRunnerPath = path.join(autoBuildSource, 'spec_runner.py'); - - if (!existsSync(specRunnerPath)) { - this.emit('error', taskId, `Spec runner not found at: ${specRunnerPath}`); - return; - } - - // Load environment variables from auto-claude .env file and project settings - const autoBuildEnv = this.loadAutoBuildEnv(); - const projectEnv = this.getProjectEnvVars(projectPath); - const combinedEnv = { ...autoBuildEnv, ...projectEnv }; - - // spec_runner.py will auto-start run.py after spec creation completes - const args = [specRunnerPath, '--task', taskDescription, '--project-dir', projectPath]; - - // Pass spec directory if provided (for UI-created tasks that already have a directory) - if (specDir) { - args.push('--spec-dir', specDir); - } - - // Check if user requires review before coding - // If requireReviewBeforeCoding is true, skip auto-approve to trigger review checkpoint - if (!metadata?.requireReviewBeforeCoding) { - // Auto-approve: When user starts a task from the UI without requiring review, that IS their approval - // No need for interactive review checkpoint - user explicitly clicked "Start" - args.push('--auto-approve'); - } - // If requireReviewBeforeCoding is true, don't add --auto-approve, allowing the review checkpoint to appear - - // Note: This is spec-creation but it chains to task-execution via run.py - // So we treat the whole thing as task-execution for status purposes - this.spawnProcess(taskId, autoBuildSource, args, combinedEnv, 'task-execution'); - } - - /** - * Start task execution (run.py) - */ - startTaskExecution( - taskId: string, - projectPath: string, - specId: string, - options: { parallel?: boolean; workers?: number } = {} - ): void { - console.log('[AgentManager] startTaskExecution called for:', taskId, specId); - // Use source auto-claude path (the repo), not the project's auto-claude - const autoBuildSource = this.getAutoBuildSourcePath(); - - if (!autoBuildSource) { - console.log('[AgentManager] ERROR: Auto-build source path not found'); - this.emit('error', taskId, 'Auto-build source path not found. Please configure it in App Settings.'); - return; - } - - const runPath = path.join(autoBuildSource, 'run.py'); - console.log('[AgentManager] runPath:', runPath); - - if (!existsSync(runPath)) { - console.log('[AgentManager] ERROR: Run script not found at:', runPath); - this.emit('error', taskId, `Run script not found at: ${runPath}`); - return; - } - - // Load environment variables from auto-claude .env file and project settings - const autoBuildEnv = this.loadAutoBuildEnv(); - const projectEnv = this.getProjectEnvVars(projectPath); - const combinedEnv = { ...autoBuildEnv, ...projectEnv }; - - const args = [runPath, '--spec', specId, '--project-dir', projectPath]; - - // Always use auto-continue when running from UI (non-interactive) - args.push('--auto-continue'); - - // Force: When user starts a task from the UI, that IS their approval - // The review checkpoint is for CLI users who need to review before building - // UI users have already seen the spec in the interface before clicking "Start" - args.push('--force'); - - if (options.parallel && options.workers) { - args.push('--parallel', options.workers.toString()); - } - - console.log('[AgentManager] Spawning process with args:', args); - this.spawnProcess(taskId, autoBuildSource, args, combinedEnv, 'task-execution'); - } - - /** - * Start QA process - */ - startQAProcess( - taskId: string, - projectPath: string, - specId: string - ): void { - // Use source auto-claude path (the repo), not the project's auto-claude - const autoBuildSource = this.getAutoBuildSourcePath(); - - if (!autoBuildSource) { - this.emit('error', taskId, 'Auto-build source path not found. Please configure it in App Settings.'); - return; - } - - const runPath = path.join(autoBuildSource, 'run.py'); - - if (!existsSync(runPath)) { - this.emit('error', taskId, `Run script not found at: ${runPath}`); - return; - } - - // Load environment variables from auto-claude .env file and project settings - const autoBuildEnv = this.loadAutoBuildEnv(); - const projectEnv = this.getProjectEnvVars(projectPath); - const combinedEnv = { ...autoBuildEnv, ...projectEnv }; - - const args = [runPath, '--spec', specId, '--project-dir', projectPath, '--qa']; - - this.spawnProcess(taskId, autoBuildSource, args, combinedEnv, 'qa-process'); - } - - /** - * Start roadmap generation process - */ - startRoadmapGeneration( - projectId: string, - projectPath: string, - refresh: boolean = false - ): void { - // Use source auto-claude path (the repo), not the project's auto-claude - const autoBuildSource = this.getAutoBuildSourcePath(); - - if (!autoBuildSource) { - this.emit('roadmap-error', projectId, 'Auto-build source path not found. Please configure it in App Settings.'); - return; - } - - const roadmapRunnerPath = path.join(autoBuildSource, 'roadmap_runner.py'); - - if (!existsSync(roadmapRunnerPath)) { - this.emit('roadmap-error', projectId, `Roadmap runner not found at: ${roadmapRunnerPath}`); - return; - } - - const args = [roadmapRunnerPath, '--project', projectPath]; - - if (refresh) { - args.push('--refresh'); - } - - // Use projectId as taskId for roadmap operations - this.spawnRoadmapProcess(projectId, projectPath, args); - } - - /** - * Start ideation generation process - */ - startIdeationGeneration( - projectId: string, - projectPath: string, - config: { - enabledTypes: string[]; - includeRoadmapContext: boolean; - includeKanbanContext: boolean; - maxIdeasPerType: number; - append?: boolean; - }, - refresh: boolean = false - ): void { - // Use source auto-claude path (the repo), not the project's auto-claude - const autoBuildSource = this.getAutoBuildSourcePath(); - - if (!autoBuildSource) { - this.emit('ideation-error', projectId, 'Auto-build source path not found. Please configure it in App Settings.'); - return; - } - - const ideationRunnerPath = path.join(autoBuildSource, 'ideation_runner.py'); - - if (!existsSync(ideationRunnerPath)) { - this.emit('ideation-error', projectId, `Ideation runner not found at: ${ideationRunnerPath}`); - return; - } - - const args = [ideationRunnerPath, '--project', projectPath]; - - // Add enabled types as comma-separated list - if (config.enabledTypes.length > 0) { - args.push('--types', config.enabledTypes.join(',')); - } - - // Add context flags (script uses --no-roadmap/--no-kanban negative flags) - if (!config.includeRoadmapContext) { - args.push('--no-roadmap'); - } - if (!config.includeKanbanContext) { - args.push('--no-kanban'); - } - - // Add max ideas per type - if (config.maxIdeasPerType) { - args.push('--max-ideas', config.maxIdeasPerType.toString()); - } - - if (refresh) { - args.push('--refresh'); - } - - // Add append flag to preserve existing ideas - if (config.append) { - args.push('--append'); - } - - // Use projectId as taskId for ideation operations - this.spawnIdeationProcess(projectId, projectPath, args); - } - - /** - * Spawn a Python process for ideation generation - */ - private spawnIdeationProcess( - projectId: string, - projectPath: string, - args: string[] - ): void { - // Kill existing process for this project if any - this.killTask(projectId); - - // Generate unique spawn ID for this process instance - const spawnId = ++this.spawnCounter; - - // Run from auto-claude source directory so imports work correctly - const autoBuildSource = this.getAutoBuildSourcePath(); - const cwd = autoBuildSource || process.cwd(); - - // Load environment variables from auto-claude .env file and project settings - const autoBuildEnv = this.loadAutoBuildEnv(); - const projectEnv = this.getProjectEnvVars(projectPath); - const combinedEnv = { ...autoBuildEnv, ...projectEnv }; - - // Get active Claude profile environment (CLAUDE_CONFIG_DIR if not default) - const profileEnv = getProfileEnv(); - - const childProcess = spawn(this.pythonPath, args, { - cwd, - env: { - ...process.env, - ...combinedEnv, // Include auto-claude .env variables and project-specific env vars - ...profileEnv, // Include active Claude profile config - PYTHONUNBUFFERED: '1' - } - }); - - this.processes.set(projectId, { - taskId: projectId, - process: childProcess, - startedAt: new Date(), - projectPath, // Store project path for loading session on completion - spawnId - }); - - // Track progress through output - let progressPhase = 'analyzing'; - let progressPercent = 10; - // Collect output for rate limit detection - let allOutput = ''; - - // Helper to emit logs - split multi-line output into individual log lines - const emitLogs = (log: string) => { - const lines = log.split('\n').filter(line => line.trim().length > 0); - for (const line of lines) { - const trimmed = line.trim(); - if (trimmed.length > 0) { - console.log('[Ideation]', trimmed); - this.emit('ideation-log', projectId, trimmed); - } - } - }; - - console.log('[Ideation] Starting ideation process with args:', args); - console.log('[Ideation] CWD:', cwd); - console.log('[Ideation] Python path:', this.pythonPath); - console.log('[Ideation] Env vars loaded:', Object.keys(autoBuildEnv)); - console.log('[Ideation] Has CLAUDE_CODE_OAUTH_TOKEN:', !!autoBuildEnv['CLAUDE_CODE_OAUTH_TOKEN']); - - // Track completed types for progress calculation - const completedTypes = new Set(); - const totalTypes = args.filter(a => a !== '--types').length > 0 ? 7 : 7; // Default all types - - // Handle stdout - childProcess.stdout?.on('data', (data: Buffer) => { - const log = data.toString(); - // Collect output for rate limit detection (keep last 10KB) - allOutput = (allOutput + log).slice(-10000); - - // Emit all log lines for the activity log - emitLogs(log); - - // Check for streaming type completion signals - const typeCompleteMatch = log.match(/IDEATION_TYPE_COMPLETE:(\w+):(\d+)/); - if (typeCompleteMatch) { - const [, ideationType, ideasCount] = typeCompleteMatch; - completedTypes.add(ideationType); - console.log(`[Ideation] Type complete: ${ideationType} with ${ideasCount} ideas`); - - // Emit event for UI to load this type's ideas immediately - this.emit('ideation-type-complete', projectId, ideationType, parseInt(ideasCount, 10)); - } - - const typeFailedMatch = log.match(/IDEATION_TYPE_FAILED:(\w+)/); - if (typeFailedMatch) { - const [, ideationType] = typeFailedMatch; - completedTypes.add(ideationType); - console.log(`[Ideation] Type failed: ${ideationType}`); - this.emit('ideation-type-failed', projectId, ideationType); - } - - // Parse progress from output - track phase transitions - if (log.includes('PROJECT INDEX') || log.includes('PROJECT ANALYSIS')) { - progressPhase = 'analyzing'; - progressPercent = 10; - } else if (log.includes('CONTEXT GATHERING')) { - progressPhase = 'discovering'; - progressPercent = 20; - } else if (log.includes('GENERATING IDEAS (PARALLEL)') || log.includes('Starting') && log.includes('ideation agents in parallel')) { - progressPhase = 'generating'; - progressPercent = 30; - } else if (log.includes('MERGE') || log.includes('FINALIZE')) { - progressPhase = 'finalizing'; - progressPercent = 90; - } else if (log.includes('IDEATION COMPLETE')) { - progressPhase = 'complete'; - progressPercent = 100; - } - - // Update progress based on completed types during generation phase - if (progressPhase === 'generating' && completedTypes.size > 0) { - // Progress from 30% to 90% based on completed types - progressPercent = 30 + Math.floor((completedTypes.size / totalTypes) * 60); - } - - // Emit progress update with a clean message for the status bar - const statusMessage = log.trim().split('\n')[0].substring(0, 200); - this.emit('ideation-progress', projectId, { - phase: progressPhase, - progress: progressPercent, - message: statusMessage, - completedTypes: Array.from(completedTypes) - }); - }); - - // Handle stderr - also emit as logs - childProcess.stderr?.on('data', (data: Buffer) => { - const log = data.toString(); - // Collect stderr for rate limit detection too - allOutput = (allOutput + log).slice(-10000); - console.error('[Ideation STDERR]', log); - emitLogs(log); - this.emit('ideation-progress', projectId, { - phase: progressPhase, - progress: progressPercent, - message: log.trim().split('\n')[0].substring(0, 200) - }); - }); - - // Handle process exit - childProcess.on('exit', (code: number | null) => { - console.log('[Ideation] Process exited with code:', code); - - // Get the stored project path before deleting from map - const processInfo = this.processes.get(projectId); - const storedProjectPath = processInfo?.projectPath; - this.processes.delete(projectId); - - // Check for rate limit if process failed - if (code !== 0) { - const rateLimitDetection = detectRateLimit(allOutput); - if (rateLimitDetection.isRateLimited) { - console.log('[Ideation] Rate limit detected:', { - projectId, - resetTime: rateLimitDetection.resetTime, - limitType: rateLimitDetection.limitType, - suggestedProfile: rateLimitDetection.suggestedProfile?.name - }); - - const rateLimitInfo = createSDKRateLimitInfo('ideation', rateLimitDetection, { - projectId - }); - this.emit('sdk-rate-limit', rateLimitInfo); - } - } - - if (code === 0) { - this.emit('ideation-progress', projectId, { - phase: 'complete', - progress: 100, - message: 'Ideation generation complete' - }); - - // Load and emit the complete ideation session - if (storedProjectPath) { - try { - const ideationFilePath = path.join( - storedProjectPath, - '.auto-claude', - 'ideation', - 'ideation.json' - ); - if (existsSync(ideationFilePath)) { - const content = readFileSync(ideationFilePath, 'utf-8'); - const session = JSON.parse(content); - console.log('[Ideation] Emitting ideation-complete with session data'); - this.emit('ideation-complete', projectId, session); - } else { - console.warn('[Ideation] ideation.json not found at:', ideationFilePath); - } - } catch (err) { - console.error('[Ideation] Failed to load ideation session:', err); - } - } - } else { - this.emit('ideation-error', projectId, `Ideation generation failed with exit code ${code}`); - } - }); - - // Handle process error - childProcess.on('error', (err: Error) => { - console.error('[Ideation] Process error:', err.message); - this.processes.delete(projectId); - this.emit('ideation-error', projectId, err.message); - }); - } - - /** - * Spawn a Python process for roadmap generation - */ - private spawnRoadmapProcess( - projectId: string, - projectPath: string, - args: string[] - ): void { - // Kill existing process for this project if any - this.killTask(projectId); - - // Generate unique spawn ID for this process instance - const spawnId = ++this.spawnCounter; - - // Run from auto-claude source directory so imports work correctly - const autoBuildSource = this.getAutoBuildSourcePath(); - const cwd = autoBuildSource || process.cwd(); - - // Load environment variables from auto-claude .env file and project settings - const autoBuildEnv = this.loadAutoBuildEnv(); - const projectEnv = this.getProjectEnvVars(projectPath); - const combinedEnv = { ...autoBuildEnv, ...projectEnv }; - - // Get active Claude profile environment (CLAUDE_CONFIG_DIR if not default) - const ideationProfileEnv = getProfileEnv(); - - const childProcess = spawn(this.pythonPath, args, { - cwd, - env: { - ...process.env, - ...combinedEnv, // Include auto-claude .env variables and project-specific env vars - ...ideationProfileEnv, // Include active Claude profile config - PYTHONUNBUFFERED: '1' - } - }); - - this.processes.set(projectId, { - taskId: projectId, - process: childProcess, - startedAt: new Date(), - spawnId - }); - - // Track progress through output - let progressPhase = 'analyzing'; - let progressPercent = 10; - // Collect output for rate limit detection - let allRoadmapOutput = ''; - - // Handle stdout - childProcess.stdout?.on('data', (data: Buffer) => { - const log = data.toString(); - // Collect output for rate limit detection (keep last 10KB) - allRoadmapOutput = (allRoadmapOutput + log).slice(-10000); - - // Parse progress from output - if (log.includes('PROJECT ANALYSIS')) { - progressPhase = 'analyzing'; - progressPercent = 20; - } else if (log.includes('PROJECT DISCOVERY')) { - progressPhase = 'discovering'; - progressPercent = 40; - } else if (log.includes('FEATURE GENERATION')) { - progressPhase = 'generating'; - progressPercent = 70; - } else if (log.includes('ROADMAP GENERATED')) { - progressPhase = 'complete'; - progressPercent = 100; - } - - // Emit progress update - this.emit('roadmap-progress', projectId, { - phase: progressPhase, - progress: progressPercent, - message: log.trim().substring(0, 200) // Truncate long messages - }); - }); - - // Handle stderr - childProcess.stderr?.on('data', (data: Buffer) => { - const log = data.toString(); - // Collect stderr for rate limit detection too - allRoadmapOutput = (allRoadmapOutput + log).slice(-10000); - this.emit('roadmap-progress', projectId, { - phase: progressPhase, - progress: progressPercent, - message: log.trim().substring(0, 200) - }); - }); - - // Handle process exit - childProcess.on('exit', (code: number | null) => { - this.processes.delete(projectId); - - // Check for rate limit if process failed - if (code !== 0) { - const rateLimitDetection = detectRateLimit(allRoadmapOutput); - if (rateLimitDetection.isRateLimited) { - console.log('[Roadmap] Rate limit detected:', { - projectId, - resetTime: rateLimitDetection.resetTime, - limitType: rateLimitDetection.limitType, - suggestedProfile: rateLimitDetection.suggestedProfile?.name - }); - - const rateLimitInfo = createSDKRateLimitInfo('roadmap', rateLimitDetection, { - projectId - }); - this.emit('sdk-rate-limit', rateLimitInfo); - } - } - - if (code === 0) { - this.emit('roadmap-progress', projectId, { - phase: 'complete', - progress: 100, - message: 'Roadmap generation complete' - }); - } else { - this.emit('roadmap-error', projectId, `Roadmap generation failed with exit code ${code}`); - } - }); - - // Handle process error - childProcess.on('error', (err: Error) => { - this.processes.delete(projectId); - this.emit('roadmap-error', projectId, err.message); - }); - } - - /** - * Parse log output to detect execution phase transitions - */ - private parseExecutionPhase( - log: string, - currentPhase: ExecutionProgressData['phase'], - isSpecRunner: boolean - ): { phase: ExecutionProgressData['phase']; message?: string; currentSubtask?: string } | null { - const lowerLog = log.toLowerCase(); - - // Spec runner phase detection (all part of "planning") - if (isSpecRunner) { - if (lowerLog.includes('discovering') || lowerLog.includes('discovery')) { - return { phase: 'planning', message: 'Discovering project context...' }; - } - if (lowerLog.includes('requirements') || lowerLog.includes('gathering')) { - return { phase: 'planning', message: 'Gathering requirements...' }; - } - if (lowerLog.includes('writing spec') || lowerLog.includes('spec writer')) { - return { phase: 'planning', message: 'Writing specification...' }; - } - if (lowerLog.includes('validating') || lowerLog.includes('validation')) { - return { phase: 'planning', message: 'Validating specification...' }; - } - if (lowerLog.includes('spec complete') || lowerLog.includes('specification complete')) { - return { phase: 'planning', message: 'Specification complete' }; - } - } - - // Run.py phase detection - // Planner agent running - if (lowerLog.includes('planner agent') || lowerLog.includes('creating implementation plan')) { - return { phase: 'planning', message: 'Creating implementation plan...' }; - } - - // Coder agent running - if (lowerLog.includes('coder agent') || lowerLog.includes('starting coder')) { - return { phase: 'coding', message: 'Implementing code changes...' }; - } - - // Subtask progress detection - const subtaskMatch = log.match(/subtask[:\s]+(\d+(?:\/\d+)?|\w+[-_]\w+)/i); - if (subtaskMatch && currentPhase === 'coding') { - return { phase: 'coding', currentSubtask: subtaskMatch[1], message: `Working on subtask ${subtaskMatch[1]}...` }; - } - - // Subtask completion detection - if (lowerLog.includes('subtask completed') || lowerLog.includes('subtask done')) { - const completedSubtask = log.match(/subtask[:\s]+"?([^"]+)"?\s+completed/i); - return { - phase: 'coding', - currentSubtask: completedSubtask?.[1], - message: `Subtask ${completedSubtask?.[1] || ''} completed` - }; - } - - // QA Review phase - if (lowerLog.includes('qa reviewer') || lowerLog.includes('qa_reviewer') || lowerLog.includes('starting qa')) { - return { phase: 'qa_review', message: 'Running QA review...' }; - } - - // QA Fixer phase - if (lowerLog.includes('qa fixer') || lowerLog.includes('qa_fixer') || lowerLog.includes('fixing issues')) { - return { phase: 'qa_fixing', message: 'Fixing QA issues...' }; - } - - // Completion detection - be conservative, require explicit success markers - // The AI agent prints "=== BUILD COMPLETE ===" when truly done (from coder.md) - // Only trust this pattern, not generic "all subtasks completed" which could be false positive - if (lowerLog.includes('=== build complete ===') || lowerLog.includes('qa passed')) { - return { phase: 'complete', message: 'Build completed successfully' }; - } - - // "All subtasks completed" is informational - don't change phase based on this alone - // The coordinator may print this even when subtasks are blocked, so we stay in coding phase - // and let the actual implementation_plan.json status drive the UI - if (lowerLog.includes('all subtasks completed')) { - return { phase: 'coding', message: 'Subtasks marked complete' }; - } - - // Incomplete build detection - when coordinator exits with pending subtasks - if (lowerLog.includes('build incomplete') || lowerLog.includes('subtasks still pending')) { - return { phase: 'coding', message: 'Build paused - subtasks still pending' }; - } - - // Error/failure detection - if (lowerLog.includes('build failed') || lowerLog.includes('error:') || lowerLog.includes('fatal')) { - return { phase: 'failed', message: log.trim().substring(0, 200) }; - } - - return null; - } - - /** - * Calculate overall progress based on phase and phase progress - */ - private calculateOverallProgress(phase: ExecutionProgressData['phase'], phaseProgress: number): number { - // Phase weight ranges (same as in constants.ts) - const weights: Record = { - idle: { start: 0, end: 0 }, - planning: { start: 0, end: 20 }, - coding: { start: 20, end: 80 }, - qa_review: { start: 80, end: 95 }, - qa_fixing: { start: 80, end: 95 }, - complete: { start: 100, end: 100 }, - failed: { start: 0, end: 0 } - }; - - const phaseWeight = weights[phase] || { start: 0, end: 0 }; - const phaseRange = phaseWeight.end - phaseWeight.start; - return Math.round(phaseWeight.start + (phaseRange * phaseProgress / 100)); - } - - /** - * Spawn a Python process - */ - private spawnProcess( - taskId: string, - cwd: string, - args: string[], - extraEnv: Record = {}, - processType: ProcessType = 'task-execution' - ): void { - const isSpecRunner = processType === 'spec-creation'; - // Kill existing process for this task if any - this.killTask(taskId); - - // Generate unique spawn ID for this process instance - const spawnId = ++this.spawnCounter; - - console.log('[spawnProcess] Spawning with pythonPath:', this.pythonPath); - console.log('[spawnProcess] cwd:', cwd); - console.log('[spawnProcess] processType:', processType); - console.log('[spawnProcess] spawnId:', spawnId); - - // Get active Claude profile environment (CLAUDE_CONFIG_DIR if not default) - const spawnProfileEnv = getProfileEnv(); - - const childProcess = spawn(this.pythonPath, args, { - cwd, - env: { - ...process.env, - ...extraEnv, - ...spawnProfileEnv, // Include active Claude profile config - PYTHONUNBUFFERED: '1' // Ensure real-time output - } - }); - - console.log('[spawnProcess] Process spawned, pid:', childProcess.pid); - - this.processes.set(taskId, { - taskId, - process: childProcess, - startedAt: new Date(), - spawnId - }); - - // Track execution progress - let currentPhase: ExecutionProgressData['phase'] = isSpecRunner ? 'planning' : 'planning'; - let phaseProgress = 0; - let currentSubtask: string | undefined; - let lastMessage: string | undefined; - // Collect all output for rate limit detection - let allOutput = ''; - - // Emit initial progress - this.emit('execution-progress', taskId, { - phase: currentPhase, - phaseProgress: 0, - overallProgress: this.calculateOverallProgress(currentPhase, 0), - message: isSpecRunner ? 'Starting spec creation...' : 'Starting build process...' - }); - - const processLog = (log: string) => { - // Collect output for rate limit detection (keep last 10KB) - allOutput = (allOutput + log).slice(-10000); - // Parse for phase transitions - const phaseUpdate = this.parseExecutionPhase(log, currentPhase, isSpecRunner); - - if (phaseUpdate) { - const phaseChanged = phaseUpdate.phase !== currentPhase; - currentPhase = phaseUpdate.phase; - - if (phaseUpdate.currentSubtask) { - currentSubtask = phaseUpdate.currentSubtask; - } - if (phaseUpdate.message) { - lastMessage = phaseUpdate.message; - } - - // Reset phase progress on phase change, otherwise increment - if (phaseChanged) { - phaseProgress = 10; // Start new phase at 10% - } else { - phaseProgress = Math.min(90, phaseProgress + 5); // Increment within phase - } - - const overallProgress = this.calculateOverallProgress(currentPhase, phaseProgress); - - this.emit('execution-progress', taskId, { - phase: currentPhase, - phaseProgress, - overallProgress, - currentSubtask, - message: lastMessage - }); - } - }; - - // Handle stdout - childProcess.stdout?.on('data', (data: Buffer) => { - const log = data.toString(); - console.log('[spawnProcess] stdout:', log.substring(0, 200)); - this.emit('log', taskId, log); - processLog(log); - }); - - // Handle stderr - childProcess.stderr?.on('data', (data: Buffer) => { - const log = data.toString(); - console.log('[spawnProcess] stderr:', log.substring(0, 200)); - // Some Python output goes to stderr (like progress bars) - // so we treat it as log, not error - this.emit('log', taskId, log); - processLog(log); - }); - - // Handle process exit - childProcess.on('exit', (code: number | null) => { - console.log('[spawnProcess] Process exited with code:', code, 'spawnId:', spawnId); - this.processes.delete(taskId); - - // Check if this specific spawn was killed (vs exited naturally) - // If killed, don't emit exit event to prevent race condition with new process - if (this.killedSpawnIds.has(spawnId)) { - console.log('[spawnProcess] Process was killed, skipping exit event for spawnId:', spawnId); - this.killedSpawnIds.delete(spawnId); - return; - } - - // Check for rate limit if process failed - if (code !== 0) { - const rateLimitDetection = detectRateLimit(allOutput); - if (rateLimitDetection.isRateLimited) { - console.log('[spawnProcess] Rate limit detected in task output:', { - taskId, - resetTime: rateLimitDetection.resetTime, - limitType: rateLimitDetection.limitType, - suggestedProfile: rateLimitDetection.suggestedProfile?.name - }); - - // Determine source type based on processType - const source = processType === 'spec-creation' ? 'task' : 'task'; - - // Emit rate limit event - const rateLimitInfo = createSDKRateLimitInfo(source, rateLimitDetection, { - taskId - }); - this.emit('sdk-rate-limit', rateLimitInfo); - } - } - - // Emit final progress - const finalPhase = code === 0 ? 'complete' : 'failed'; - this.emit('execution-progress', taskId, { - phase: finalPhase, - phaseProgress: 100, - overallProgress: code === 0 ? 100 : this.calculateOverallProgress(currentPhase, phaseProgress), - message: code === 0 ? 'Process completed successfully' : `Process exited with code ${code}` - }); - - this.emit('exit', taskId, code, processType); - }); - - // Handle process error - childProcess.on('error', (err: Error) => { - console.log('[spawnProcess] Process error:', err.message); - this.processes.delete(taskId); - - this.emit('execution-progress', taskId, { - phase: 'failed', - phaseProgress: 0, - overallProgress: 0, - message: `Error: ${err.message}` - }); - - this.emit('error', taskId, err.message); - }); - } - - /** - * Kill a specific task's process - */ - killTask(taskId: string): boolean { - const agentProcess = this.processes.get(taskId); - if (agentProcess) { - try { - // Mark this specific spawn as killed so its exit handler knows to ignore - this.killedSpawnIds.add(agentProcess.spawnId); - - // Send SIGTERM first for graceful shutdown - agentProcess.process.kill('SIGTERM'); - - // Force kill after timeout - setTimeout(() => { - if (!agentProcess.process.killed) { - agentProcess.process.kill('SIGKILL'); - } - }, 5000); - - this.processes.delete(taskId); - return true; - } catch { - return false; - } - } - return false; - } - - /** - * Stop ideation generation for a project - */ - stopIdeation(projectId: string): boolean { - const wasRunning = this.isRunning(projectId); - if (wasRunning) { - this.killTask(projectId); - this.emit('ideation-stopped', projectId); - return true; - } - return false; - } - - /** - * Check if ideation is running for a project - */ - isIdeationRunning(projectId: string): boolean { - return this.isRunning(projectId); - } - - /** - * Kill all running processes - */ - async killAll(): Promise { - const killPromises = Array.from(this.processes.keys()).map((taskId) => { - return new Promise((resolve) => { - this.killTask(taskId); - resolve(); - }); - }); - await Promise.all(killPromises); - } - - /** - * Check if a task is running - */ - isRunning(taskId: string): boolean { - return this.processes.has(taskId); - } - - /** - * Get all running task IDs - */ - getRunningTasks(): string[] { - return Array.from(this.processes.keys()); - } -} diff --git a/auto-claude-ui/src/main/ipc-handlers.ts.backup b/auto-claude-ui/src/main/ipc-handlers.ts.backup deleted file mode 100644 index 2773f823..00000000 --- a/auto-claude-ui/src/main/ipc-handlers.ts.backup +++ /dev/null @@ -1,6913 +0,0 @@ -import { ipcMain, dialog, BrowserWindow, app } from 'electron'; -import path from 'path'; -import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, mkdirSync } from 'fs'; -import { spawn, execSync } from 'child_process'; -import { IPC_CHANNELS, DEFAULT_APP_SETTINGS, AUTO_BUILD_PATHS, getSpecsDir } from '../shared/constants'; -import type { - Project, - ProjectSettings, - Task, - TaskMetadata, - TaskCategory, - TaskComplexity, - TaskImpact, - TaskStatus, - AppSettings, - IPCResult, - TaskStartOptions, - ImplementationPlan, - TerminalCreateOptions, - AutoBuildVersionInfo, - InitializationResult, - Roadmap, - RoadmapFeature, - RoadmapFeatureStatus, - RoadmapGenerationStatus, - ProjectIndex, - ProjectContextData, - GraphitiMemoryStatus, - GraphitiMemoryState, - MemoryEpisode, - ContextSearchResult, - ProjectEnvConfig, - ClaudeAuthResult, - LinearIssue, - LinearTeam, - LinearProject, - LinearImportResult, - LinearSyncStatus, - GitHubRepository, - GitHubIssue, - GitHubSyncStatus, - GitHubImportResult, - GitHubInvestigationResult, - GitHubInvestigationStatus, - IdeationSession, - IdeationConfig, - IdeationGenerationStatus, - IdeationStatus, - SourceEnvConfig, - SourceEnvCheckResult, - ClaudeProfile, - ClaudeProfileSettings -} from '../shared/types'; -import { projectStore } from './project-store'; -import { fileWatcher } from './file-watcher'; -import { AgentManager } from './agent'; -import { TerminalManager } from './terminal-manager'; -import { getClaudeProfileManager } from './claude-profile-manager'; -import { - initializeProject, - isInitialized, - getAutoBuildPath, - hasLocalSource -} from './project-initializer'; -import { - checkForUpdates as checkSourceUpdates, - downloadAndApplyUpdate, - getBundledVersion, - getEffectiveSourcePath -} from './auto-claude-updater'; -import { changelogService } from './changelog-service'; -import { insightsService } from './insights-service'; -import { taskLogService } from './task-log-service'; -import { titleGenerator } from './title-generator'; -import { PythonEnvManager, PythonEnvStatus } from './python-env-manager'; -import type { AutoBuildSourceUpdateProgress, InsightsSession, InsightsSessionSummary, InsightsChatStatus, InsightsStreamChunk, TaskLogs, TaskLogStreamChunk, FileNode } from '../shared/types'; - -/** - * Setup all IPC handlers - */ -export function setupIpcHandlers( - agentManager: AgentManager, - terminalManager: TerminalManager, - getMainWindow: () => BrowserWindow | null, - pythonEnvManager: PythonEnvManager -): void { - // ============================================ - // Project Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.PROJECT_ADD, - async (_, projectPath: string): Promise> => { - try { - // Validate path exists - if (!existsSync(projectPath)) { - return { success: false, error: 'Directory does not exist' }; - } - - const project = projectStore.addProject(projectPath); - return { success: true, data: project }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Unknown error' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.PROJECT_REMOVE, - async (_, projectId: string): Promise => { - const success = projectStore.removeProject(projectId); - return { success }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.PROJECT_LIST, - async (): Promise> => { - // Validate that .auto-claude folders still exist for all projects - // If a folder was deleted, reset autoBuildPath so UI prompts for reinitialization - const resetIds = projectStore.validateProjects(); - if (resetIds.length > 0) { - console.log('[IPC] PROJECT_LIST: Detected missing .auto-claude folders for', resetIds.length, 'project(s)'); - } - - const projects = projectStore.getProjects(); - console.log('[IPC] PROJECT_LIST returning', projects.length, 'projects'); - return { success: true, data: projects }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.PROJECT_UPDATE_SETTINGS, - async ( - _, - projectId: string, - settings: Partial - ): Promise => { - const project = projectStore.updateProjectSettings(projectId, settings); - if (project) { - return { success: true }; - } - return { success: false, error: 'Project not found' }; - } - ); - - // ============================================ - // Project Initialization Operations - // ============================================ - - const settingsPath = path.join(app.getPath('userData'), 'settings.json'); - - /** - * Auto-detect the auto-claude source path relative to the app location - * In dev: auto-claude-ui/../auto-claude - * In prod: Could be bundled or configured - */ - const detectAutoBuildSourcePath = (): string | null => { - // Try relative to app directory (works in dev and if repo structure is maintained) - // __dirname in main process points to out/main in dev - const possiblePaths = [ - // Dev mode: from out/main -> ../../../auto-claude (sibling to auto-claude-ui) - path.resolve(__dirname, '..', '..', '..', 'auto-claude'), - // Alternative: from app root (useful in some packaged scenarios) - path.resolve(app.getAppPath(), '..', 'auto-claude'), - // If running from repo root - path.resolve(process.cwd(), 'auto-claude'), - // Try one more level up (in case of different build output structure) - path.resolve(__dirname, '..', '..', 'auto-claude') - ]; - - for (const p of possiblePaths) { - if (existsSync(p) && existsSync(path.join(p, 'VERSION'))) { - return p; - } - } - return null; - }; - - /** - * Get the configured auto-claude source path from settings, or auto-detect - */ - const getAutoBuildSourcePath = (): string | null => { - // First check if manually configured - if (existsSync(settingsPath)) { - try { - const content = readFileSync(settingsPath, 'utf-8'); - const settings = JSON.parse(content); - if (settings.autoBuildPath && existsSync(settings.autoBuildPath)) { - return settings.autoBuildPath; - } - } catch { - // Fall through to auto-detect - } - } - - // Auto-detect from app location - return detectAutoBuildSourcePath(); - }; - - /** - * Configure all Python-dependent services with the managed Python path - */ - const configureServicesWithPython = (pythonPath: string, autoBuildPath: string): void => { - console.log('[IPC] Configuring services with Python:', pythonPath); - agentManager.configure(pythonPath, autoBuildPath); - changelogService.configure(pythonPath, autoBuildPath); - insightsService.configure(pythonPath, autoBuildPath); - titleGenerator.configure(pythonPath, autoBuildPath); - }; - - /** - * Initialize the Python environment and configure services - */ - const initializePythonEnvironment = async (): Promise => { - const autoBuildSource = getAutoBuildSourcePath(); - if (!autoBuildSource) { - console.log('[IPC] Auto-build source not found, skipping Python env init'); - return { - ready: false, - pythonPath: null, - venvExists: false, - depsInstalled: false, - error: 'Auto-build source not found' - }; - } - - console.log('[IPC] Initializing Python environment...'); - const status = await pythonEnvManager.initialize(autoBuildSource); - - if (status.ready && status.pythonPath) { - configureServicesWithPython(status.pythonPath, autoBuildSource); - } - - return status; - }; - - // Set up Python environment status events - pythonEnvManager.on('status', (message: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send('python-env:status', message); - } - }); - - pythonEnvManager.on('error', (error: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send('python-env:error', error); - } - }); - - pythonEnvManager.on('ready', (pythonPath: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send('python-env:ready', pythonPath); - } - }); - - // Initialize Python environment on startup (non-blocking) - initializePythonEnvironment().then((status) => { - console.log('[IPC] Python environment initialized:', status); - }); - - // IPC handler to get Python environment status - ipcMain.handle( - 'python-env:get-status', - async (): Promise> => { - const status = await pythonEnvManager.getStatus(); - return { success: true, data: status }; - } - ); - - // IPC handler to reinitialize Python environment - ipcMain.handle( - 'python-env:reinitialize', - async (): Promise> => { - const status = await initializePythonEnvironment(); - return { success: status.ready, data: status, error: status.error }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.PROJECT_INITIALIZE, - async (_, projectId: string): Promise> => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const result = initializeProject(project.path); - - if (result.success) { - // Update project's autoBuildPath - projectStore.updateAutoBuildPath(projectId, '.auto-claude'); - } - - return { success: result.success, data: result, error: result.error }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Unknown error' - }; - } - } - ); - - // PROJECT_UPDATE_AUTOBUILD is deprecated - .auto-claude only contains data, no code to update - // Kept for API compatibility, returns success immediately - ipcMain.handle( - IPC_CHANNELS.PROJECT_UPDATE_AUTOBUILD, - async (_, projectId: string): Promise> => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // Nothing to update - .auto-claude only contains data directories - // The framework runs from the source repo - return { success: true, data: { success: true } }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Unknown error' - }; - } - } - ); - - // PROJECT_CHECK_VERSION now just checks if project is initialized - // Version tracking for .auto-claude is removed since it only contains data - ipcMain.handle( - IPC_CHANNELS.PROJECT_CHECK_VERSION, - async (_, projectId: string): Promise> => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - return { - success: true, - data: { - isInitialized: isInitialized(project.path), - updateAvailable: false // No updates for .auto-claude - it's just data - } - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Unknown error' - }; - } - } - ); - - // Check if project has local auto-claude source (is dev project) - ipcMain.handle( - 'project:has-local-source', - async (_, projectId: string): Promise> => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - return { success: true, data: hasLocalSource(project.path) }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Unknown error' - }; - } - } - ); - - // ============================================ - // Task Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.TASK_LIST, - async (_, projectId: string): Promise> => { - console.log('[IPC] TASK_LIST called with projectId:', projectId); - const tasks = projectStore.getTasks(projectId); - console.log('[IPC] TASK_LIST returning', tasks.length, 'tasks'); - return { success: true, data: tasks }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_CREATE, - async ( - _, - projectId: string, - title: string, - description: string, - metadata?: TaskMetadata - ): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // Auto-generate title if empty using Claude AI - let finalTitle = title; - if (!title || !title.trim()) { - console.log('[TASK_CREATE] Title is empty, generating with Claude AI...'); - try { - const generatedTitle = await titleGenerator.generateTitle(description); - if (generatedTitle) { - finalTitle = generatedTitle; - console.log('[TASK_CREATE] Generated title:', finalTitle); - } else { - // Fallback: create title from first line of description - finalTitle = description.split('\n')[0].substring(0, 60); - if (finalTitle.length === 60) finalTitle += '...'; - console.log('[TASK_CREATE] AI generation failed, using fallback:', finalTitle); - } - } catch (err) { - console.error('[TASK_CREATE] Title generation error:', err); - // Fallback: create title from first line of description - finalTitle = description.split('\n')[0].substring(0, 60); - if (finalTitle.length === 60) finalTitle += '...'; - } - } - - // Generate a unique spec ID based on existing specs - // Get specs directory path - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - - // Find next available spec number - let specNumber = 1; - if (existsSync(specsDir)) { - const existingDirs = readdirSync(specsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => d.name); - - // Extract numbers from spec directory names (e.g., "001-feature" -> 1) - const existingNumbers = existingDirs - .map(name => { - const match = name.match(/^(\d+)/); - return match ? parseInt(match[1], 10) : 0; - }) - .filter(n => n > 0); - - if (existingNumbers.length > 0) { - specNumber = Math.max(...existingNumbers) + 1; - } - } - - // Create spec ID with zero-padded number and slugified title - const slugifiedTitle = finalTitle - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-|-$/g, '') - .substring(0, 50); - const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`; - - // Create spec directory - const specDir = path.join(specsDir, specId); - mkdirSync(specDir, { recursive: true }); - - // Build metadata with source type - const taskMetadata: TaskMetadata = { - sourceType: 'manual', - ...metadata - }; - - // Process and save attached images - if (taskMetadata.attachedImages && taskMetadata.attachedImages.length > 0) { - const attachmentsDir = path.join(specDir, 'attachments'); - mkdirSync(attachmentsDir, { recursive: true }); - - const savedImages: typeof taskMetadata.attachedImages = []; - - for (const image of taskMetadata.attachedImages) { - if (image.data) { - try { - // Decode base64 and save to file - const buffer = Buffer.from(image.data, 'base64'); - const imagePath = path.join(attachmentsDir, image.filename); - writeFileSync(imagePath, buffer); - - // Store relative path instead of base64 data - savedImages.push({ - id: image.id, - filename: image.filename, - mimeType: image.mimeType, - size: image.size, - path: `attachments/${image.filename}` - // Don't include data or thumbnail to save space - }); - } catch (err) { - console.error(`Failed to save image ${image.filename}:`, err); - } - } - } - - // Update metadata with saved image paths (without base64 data) - taskMetadata.attachedImages = savedImages; - } - - // Create initial implementation_plan.json (task is created but not started) - const now = new Date().toISOString(); - const implementationPlan = { - feature: finalTitle, - description: description, - created_at: now, - updated_at: now, - status: 'pending', - phases: [] - }; - - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - writeFileSync(planPath, JSON.stringify(implementationPlan, null, 2)); - - // Save task metadata if provided - if (taskMetadata) { - const metadataPath = path.join(specDir, 'task_metadata.json'); - writeFileSync(metadataPath, JSON.stringify(taskMetadata, null, 2)); - } - - // Create requirements.json with attached images - const requirements: Record = { - task_description: description, - workflow_type: taskMetadata.category || 'feature' - }; - - // Add attached images to requirements if present - if (taskMetadata.attachedImages && taskMetadata.attachedImages.length > 0) { - requirements.attached_images = taskMetadata.attachedImages.map(img => ({ - filename: img.filename, - path: img.path, - description: '' // User can add descriptions later - })); - } - - const requirementsPath = path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS); - writeFileSync(requirementsPath, JSON.stringify(requirements, null, 2)); - - // Create the task object - const task: Task = { - id: specId, - specId: specId, - projectId, - title: finalTitle, - description, - status: 'backlog', - subtasks: [], - logs: [], - metadata: taskMetadata, - createdAt: new Date(), - updatedAt: new Date() - }; - - return { success: true, data: task }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_DELETE, - async (_, taskId: string): Promise => { - const { rm } = await import('fs/promises'); - - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task or project not found' }; - } - - // Check if task is currently running - const isRunning = agentManager.isRunning(taskId); - if (isRunning) { - return { success: false, error: 'Cannot delete a running task. Stop the task first.' }; - } - - // Delete the spec directory - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join(project.path, specsBaseDir, task.specId); - - try { - if (existsSync(specDir)) { - await rm(specDir, { recursive: true, force: true }); - console.log(`[TASK_DELETE] Deleted spec directory: ${specDir}`); - } - return { success: true }; - } catch (error) { - console.error('[TASK_DELETE] Error deleting spec directory:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to delete task files' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_UPDATE, - async ( - _, - taskId: string, - updates: { title?: string; description?: string } - ): Promise> => { - try { - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - const autoBuildDir = project.autoBuildPath || '.auto-claude'; - const specDir = path.join(project.path, autoBuildDir, 'specs', task.specId); - - if (!existsSync(specDir)) { - return { success: false, error: 'Spec directory not found' }; - } - - // Auto-generate title if empty - let finalTitle = updates.title; - if (updates.title !== undefined && !updates.title.trim()) { - // Get description to use for title generation - const descriptionToUse = updates.description ?? task.description; - console.log('[TASK_UPDATE] Title is empty, generating with Claude AI...'); - try { - const generatedTitle = await titleGenerator.generateTitle(descriptionToUse); - if (generatedTitle) { - finalTitle = generatedTitle; - console.log('[TASK_UPDATE] Generated title:', finalTitle); - } else { - // Fallback: create title from first line of description - finalTitle = descriptionToUse.split('\n')[0].substring(0, 60); - if (finalTitle.length === 60) finalTitle += '...'; - console.log('[TASK_UPDATE] AI generation failed, using fallback:', finalTitle); - } - } catch (err) { - console.error('[TASK_UPDATE] Title generation error:', err); - // Fallback: create title from first line of description - finalTitle = descriptionToUse.split('\n')[0].substring(0, 60); - if (finalTitle.length === 60) finalTitle += '...'; - } - } - - // Update implementation_plan.json - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - if (existsSync(planPath)) { - try { - const planContent = readFileSync(planPath, 'utf-8'); - const plan = JSON.parse(planContent); - - if (finalTitle !== undefined) { - plan.feature = finalTitle; - } - if (updates.description !== undefined) { - plan.description = updates.description; - } - plan.updated_at = new Date().toISOString(); - - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } catch { - // Plan file might not be valid JSON, continue anyway - } - } - - // Update spec.md if it exists - const specPath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE); - if (existsSync(specPath)) { - try { - let specContent = readFileSync(specPath, 'utf-8'); - - // Update title (first # heading) - if (finalTitle !== undefined) { - specContent = specContent.replace( - /^#\s+.*$/m, - `# ${finalTitle}` - ); - } - - // Update description (## Overview section content) - if (updates.description !== undefined) { - // Replace content between ## Overview and the next ## section - specContent = specContent.replace( - /(## Overview\n)([\s\S]*?)((?=\n## )|$)/, - `$1${updates.description}\n\n$3` - ); - } - - writeFileSync(specPath, specContent); - } catch { - // Spec file update failed, continue anyway - } - } - - // Build the updated task object - const updatedTask: Task = { - ...task, - title: finalTitle ?? task.title, - description: updates.description ?? task.description, - updatedAt: new Date() - }; - - return { success: true, data: updatedTask }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Unknown error' - }; - } - } - ); - - ipcMain.on( - IPC_CHANNELS.TASK_START, - (_, taskId: string, options?: TaskStartOptions) => { - console.log('[TASK_START] Received request for taskId:', taskId); - const mainWindow = getMainWindow(); - if (!mainWindow) { - console.log('[TASK_START] No main window found'); - return; - } - - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - console.log('[TASK_START] Task or project not found for taskId:', taskId); - mainWindow.webContents.send( - IPC_CHANNELS.TASK_ERROR, - taskId, - 'Task or project not found' - ); - return; - } - - console.log('[TASK_START] Found task:', task.specId, 'status:', task.status, 'subtasks:', task.subtasks.length); - - // Start file watcher for this task - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join( - project.path, - specsBaseDir, - task.specId - ); - fileWatcher.watch(taskId, specDir); - - // Check if spec.md exists (indicates spec creation was already done or in progress) - const specFilePath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE); - const hasSpec = existsSync(specFilePath); - - // Check if this task needs spec creation first (no spec file = not yet created) - // OR if it has a spec but no implementation plan subtasks (spec created, needs planning/building) - const needsSpecCreation = !hasSpec; - const needsImplementation = hasSpec && task.subtasks.length === 0; - - console.log('[TASK_START] hasSpec:', hasSpec, 'needsSpecCreation:', needsSpecCreation, 'needsImplementation:', needsImplementation); - - if (needsSpecCreation) { - // No spec file - need to run spec_runner.py to create the spec - const taskDescription = task.description || task.title; - console.log('[TASK_START] Starting spec creation for:', task.specId, 'in:', specDir); - - // Start spec creation process - pass the existing spec directory - // so spec_runner uses it instead of creating a new one - agentManager.startSpecCreation(task.specId, project.path, taskDescription, specDir, task.metadata); - } else if (needsImplementation) { - // Spec exists but no subtasks - run run.py to create implementation plan and execute - // Read the spec.md to get the task description - let taskDescription = task.description || task.title; - try { - taskDescription = readFileSync(specFilePath, 'utf-8'); - } catch { - // Use default description - } - - console.log('[TASK_START] Starting task execution (no subtasks) for:', task.specId); - // Start task execution which will create the implementation plan - // Note: No parallel mode for planning phase - parallel only makes sense with multiple subtasks - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: false, // Sequential for planning phase - workers: 1 - } - ); - } else { - // Task has subtasks, start normal execution - // Only enable parallel if there are multiple subtasks AND user has parallel enabled - const hasMultipleSubtasks = task.subtasks.length > 1; - const pendingSubtasks = task.subtasks.filter(s => s.status === 'pending' || s.status === 'in_progress').length; - const parallelEnabled = options?.parallel ?? project.settings.parallelEnabled; - const useParallel = parallelEnabled && hasMultipleSubtasks && pendingSubtasks > 1; - const workers = useParallel ? (options?.workers ?? project.settings.maxWorkers) : 1; - - console.log('[TASK_START] Starting task execution (has subtasks) for:', task.specId); - console.log('[TASK_START] Parallel decision:', { - hasMultipleSubtasks, - pendingSubtasks, - parallelEnabled, - useParallel, - workers - }); - - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: useParallel, - workers - } - ); - } - - // Notify status change - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'in_progress' - ); - } - ); - - ipcMain.on(IPC_CHANNELS.TASK_STOP, (_, taskId: string) => { - agentManager.killTask(taskId); - fileWatcher.unwatch(taskId); - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'backlog' - ); - } - }); - - ipcMain.handle( - IPC_CHANNELS.TASK_REVIEW, - async ( - _, - taskId: string, - approved: boolean, - feedback?: string - ): Promise => { - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Check if dev mode is enabled for this project - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join( - project.path, - specsBaseDir, - task.specId - ); - - if (approved) { - // Write approval to QA report - const qaReportPath = path.join(specDir, AUTO_BUILD_PATHS.QA_REPORT); - writeFileSync( - qaReportPath, - `# QA Review\n\nStatus: APPROVED\n\nReviewed at: ${new Date().toISOString()}\n` - ); - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'done' - ); - } - } else { - // Write feedback for QA fixer - const fixRequestPath = path.join(specDir, 'QA_FIX_REQUEST.md'); - writeFileSync( - fixRequestPath, - `# QA Fix Request\n\nStatus: REJECTED\n\n## Feedback\n\n${feedback || 'No feedback provided'}\n\nCreated at: ${new Date().toISOString()}\n` - ); - - // Restart QA process with dev mode - agentManager.startQAProcess(taskId, project.path, task.specId); - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'in_progress' - ); - } - } - - return { success: true }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_UPDATE_STATUS, - async ( - _, - taskId: string, - status: TaskStatus - ): Promise => { - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Get the spec directory - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join( - project.path, - specsBaseDir, - task.specId - ); - - // Update implementation_plan.json if it exists - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - - try { - if (existsSync(planPath)) { - const planContent = readFileSync(planPath, 'utf-8'); - const plan = JSON.parse(planContent); - - // Store the exact UI status - project-store.ts will map it back - plan.status = status; - // Also store mapped version for Python compatibility - plan.planStatus = status === 'done' ? 'completed' - : status === 'in_progress' ? 'in_progress' - : status === 'ai_review' ? 'review' - : status === 'human_review' ? 'review' - : 'pending'; - plan.updated_at = new Date().toISOString(); - - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } else { - // If no implementation plan exists yet, create a basic one - const plan = { - feature: task.title, - description: task.description || '', - created_at: task.createdAt.toISOString(), - updated_at: new Date().toISOString(), - status: status, // Store exact UI status for persistence - planStatus: status === 'done' ? 'completed' - : status === 'in_progress' ? 'in_progress' - : status === 'ai_review' ? 'review' - : status === 'human_review' ? 'review' - : 'pending', - phases: [] - }; - - // Ensure spec directory exists - if (!existsSync(specDir)) { - mkdirSync(specDir, { recursive: true }); - } - - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } - - // Auto-start task when status changes to 'in_progress' and no process is running - if (status === 'in_progress' && !agentManager.isRunning(taskId)) { - const mainWindow = getMainWindow(); - console.log('[TASK_UPDATE_STATUS] Auto-starting task:', taskId); - - // Start file watcher for this task - fileWatcher.watch(taskId, specDir); - - // Check if spec.md exists - const specFilePath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE); - const hasSpec = existsSync(specFilePath); - const needsSpecCreation = !hasSpec; - const needsImplementation = hasSpec && task.subtasks.length === 0; - - console.log('[TASK_UPDATE_STATUS] hasSpec:', hasSpec, 'needsSpecCreation:', needsSpecCreation, 'needsImplementation:', needsImplementation); - - if (needsSpecCreation) { - // No spec file - need to run spec_runner.py to create the spec - const taskDescription = task.description || task.title; - console.log('[TASK_UPDATE_STATUS] Starting spec creation for:', task.specId); - agentManager.startSpecCreation(task.specId, project.path, taskDescription, specDir, task.metadata); - } else if (needsImplementation) { - // Spec exists but no subtasks - run run.py to create implementation plan and execute - console.log('[TASK_UPDATE_STATUS] Starting task execution (no subtasks) for:', task.specId); - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: false, - workers: 1 - } - ); - } else { - // Task has subtasks, start normal execution - const hasMultipleSubtasks = task.subtasks.length > 1; - const pendingSubtasks = task.subtasks.filter(s => s.status === 'pending' || s.status === 'in_progress').length; - const parallelEnabled = project.settings.parallelEnabled; - const useParallel = parallelEnabled && hasMultipleSubtasks && pendingSubtasks > 1; - const workers = useParallel ? project.settings.maxWorkers : 1; - - console.log('[TASK_UPDATE_STATUS] Starting task execution (has subtasks) for:', task.specId); - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: useParallel, - workers - } - ); - } - - // Notify renderer about status change - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'in_progress' - ); - } - } - - return { success: true }; - } catch (error) { - console.error('Failed to update task status:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update task status' - }; - } - } - ); - - // Handler to check if a task is actually running (has active process) - ipcMain.handle( - IPC_CHANNELS.TASK_CHECK_RUNNING, - async (_, taskId: string): Promise> => { - const isRunning = agentManager.isRunning(taskId); - return { success: true, data: isRunning }; - } - ); - - // Handler to recover a stuck task (status says in_progress but no process running) - ipcMain.handle( - IPC_CHANNELS.TASK_RECOVER_STUCK, - async ( - _, - taskId: string, - options?: { targetStatus?: TaskStatus; autoRestart?: boolean } - ): Promise> => { - const targetStatus = options?.targetStatus; - const autoRestart = options?.autoRestart ?? false; - // Check if task is actually running - const isActuallyRunning = agentManager.isRunning(taskId); - - if (isActuallyRunning) { - return { - success: false, - error: 'Task is still running. Stop it first before recovering.', - data: { - taskId, - recovered: false, - newStatus: 'in_progress' as TaskStatus, - message: 'Task is still running' - } - }; - } - - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Get the spec directory - const autoBuildDir = project.autoBuildPath || '.auto-claude'; - const specDir = path.join( - project.path, - autoBuildDir, - 'specs', - task.specId - ); - - // Update implementation_plan.json - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - - try { - // Read the plan to analyze subtask progress - let plan: Record | null = null; - if (existsSync(planPath)) { - const planContent = readFileSync(planPath, 'utf-8'); - plan = JSON.parse(planContent); - } - - // Determine the target status intelligently based on subtask progress - // If targetStatus is explicitly provided, use it; otherwise calculate from subtasks - let newStatus: TaskStatus = targetStatus || 'backlog'; - - if (!targetStatus && plan?.phases && Array.isArray(plan.phases)) { - // Analyze subtask statuses to determine appropriate recovery status - const allSubtasks: Array<{ status: string }> = []; - for (const phase of plan.phases as Array<{ subtasks?: Array<{ status: string }> }>) { - if (phase.subtasks && Array.isArray(phase.subtasks)) { - allSubtasks.push(...phase.subtasks); - } - } - - if (allSubtasks.length > 0) { - const completedCount = allSubtasks.filter(s => s.status === 'completed').length; - const allCompleted = completedCount === allSubtasks.length; - - if (allCompleted) { - // All subtasks completed - should go to review (ai_review or human_review based on source) - // For recovery, human_review is safer as it requires manual verification - newStatus = 'human_review'; - } else if (completedCount > 0) { - // Some subtasks completed, some still pending - task is in progress - newStatus = 'in_progress'; - } - // else: no subtasks completed, stay with 'backlog' - } - } - - if (plan) { - // Update status - plan.status = newStatus; - plan.planStatus = newStatus === 'done' ? 'completed' - : newStatus === 'in_progress' ? 'in_progress' - : newStatus === 'ai_review' ? 'review' - : newStatus === 'human_review' ? 'review' - : 'pending'; - plan.updated_at = new Date().toISOString(); - - // Add recovery note - plan.recoveryNote = `Task recovered from stuck state at ${new Date().toISOString()}`; - - // Reset in_progress and failed subtask statuses to 'pending' so they can be retried - // Keep completed subtasks as-is so run.py can resume from where it left off - if (plan.phases && Array.isArray(plan.phases)) { - for (const phase of plan.phases as Array<{ subtasks?: Array<{ status: string; actual_output?: string; started_at?: string; completed_at?: string }> }>) { - if (phase.subtasks && Array.isArray(phase.subtasks)) { - for (const subtask of phase.subtasks) { - // Reset in_progress subtasks to pending (they were interrupted) - // Keep completed subtasks as-is so run.py can resume - if (subtask.status === 'in_progress') { - subtask.status = 'pending'; - // Clear execution data to maintain consistency - delete subtask.actual_output; - delete subtask.started_at; - delete subtask.completed_at; - } - // Also reset failed subtasks so they can be retried - if (subtask.status === 'failed') { - subtask.status = 'pending'; - // Clear execution data to maintain consistency - delete subtask.actual_output; - delete subtask.started_at; - delete subtask.completed_at; - } - } - } - } - } - - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } - - // Stop file watcher if it was watching this task - fileWatcher.unwatch(taskId); - - // Auto-restart the task if requested - let autoRestarted = false; - if (autoRestart && project) { - try { - // Set status to in_progress for the restart - newStatus = 'in_progress'; - - // Update plan status for restart - if (plan) { - plan.status = 'in_progress'; - plan.planStatus = 'in_progress'; - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } - - // Start the task execution - - // Check if we should use parallel mode - const hasMultipleSubtasks = task.subtasks.length > 1; - const pendingSubtasks = task.subtasks.filter(s => s.status === 'pending').length; - const parallelEnabled = project.settings.parallelEnabled; - const useParallel = parallelEnabled && hasMultipleSubtasks && pendingSubtasks > 1; - const workers = useParallel ? project.settings.maxWorkers : 1; - - // Start file watcher for this task - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDirForWatcher = path.join(project.path, specsBaseDir, task.specId); - fileWatcher.watch(taskId, specDirForWatcher); - - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: useParallel, - workers - } - ); - - autoRestarted = true; - console.log(`[Recovery] Auto-restarted task ${taskId}`); - } catch (restartError) { - console.error('Failed to auto-restart task after recovery:', restartError); - // Recovery succeeded but restart failed - still report success - } - } - - // Notify renderer of status change - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - newStatus - ); - } - - return { - success: true, - data: { - taskId, - recovered: true, - newStatus, - message: autoRestarted - ? 'Task recovered and restarted successfully' - : `Task recovered successfully and moved to ${newStatus}`, - autoRestarted - } - }; - } catch (error) { - console.error('Failed to recover stuck task:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to recover task' - }; - } - } - ); - - // ============================================ - // Workspace Management Operations (for human review) - // ============================================ - - /** - * Helper function to find task and project by taskId - */ - const findTaskAndProject = (taskId: string): { task: Task | undefined; project: Project | undefined } => { - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - return { task, project }; - }; - - /** - * Get the worktree status for a task - * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/ - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_STATUS, - async (_, taskId: string): Promise> => { - try { - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Per-spec worktree path: .worktrees/{spec-name}/ - const worktreePath = path.join(project.path, '.worktrees', task.specId); - - if (!existsSync(worktreePath)) { - return { - success: true, - data: { exists: false } - }; - } - - // Get branch info from git - try { - // Get current branch in worktree - const branch = execSync('git rev-parse --abbrev-ref HEAD', { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Get base branch (usually main or master) - let baseBranch = 'main'; - try { - // Try to get the default branch - baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', { - cwd: project.path, - encoding: 'utf-8' - }).trim().replace('origin/', ''); - } catch { - baseBranch = 'main'; - } - - // Get commit count - let commitCount = 0; - try { - const countOutput = execSync(`git rev-list --count ${baseBranch}..HEAD 2>/dev/null || echo 0`, { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - commitCount = parseInt(countOutput, 10) || 0; - } catch { - commitCount = 0; - } - - // Get diff stats - let filesChanged = 0; - let additions = 0; - let deletions = 0; - - try { - const diffStat = execSync(`git diff --stat ${baseBranch}...HEAD 2>/dev/null || echo ""`, { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Parse the summary line (e.g., "3 files changed, 50 insertions(+), 10 deletions(-)") - const summaryMatch = diffStat.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/); - if (summaryMatch) { - filesChanged = parseInt(summaryMatch[1], 10) || 0; - additions = parseInt(summaryMatch[2], 10) || 0; - deletions = parseInt(summaryMatch[3], 10) || 0; - } - } catch { - // Ignore diff errors - } - - return { - success: true, - data: { - exists: true, - worktreePath, - branch, - baseBranch, - commitCount, - filesChanged, - additions, - deletions - } - }; - } catch (gitError) { - console.error('Git error getting worktree status:', gitError); - return { - success: true, - data: { exists: true, worktreePath } - }; - } - } catch (error) { - console.error('Failed to get worktree status:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get worktree status' - }; - } - } - ); - - /** - * Get the diff for a task's worktree - * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/ - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_DIFF, - async (_, taskId: string): Promise> => { - try { - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Per-spec worktree path: .worktrees/{spec-name}/ - const worktreePath = path.join(project.path, '.worktrees', task.specId); - - if (!existsSync(worktreePath)) { - return { success: false, error: 'No worktree found for this task' }; - } - - // Get base branch - let baseBranch = 'main'; - try { - baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', { - cwd: project.path, - encoding: 'utf-8' - }).trim().replace('origin/', ''); - } catch { - baseBranch = 'main'; - } - - // Get the diff with file stats - const files: import('../shared/types').WorktreeDiffFile[] = []; - - try { - // Get numstat for additions/deletions per file - const numstat = execSync(`git diff --numstat ${baseBranch}...HEAD 2>/dev/null || echo ""`, { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Get name-status for file status - const nameStatus = execSync(`git diff --name-status ${baseBranch}...HEAD 2>/dev/null || echo ""`, { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Parse name-status to get file statuses - const statusMap: Record = {}; - nameStatus.split('\n').filter(Boolean).forEach((line: string) => { - const [status, ...pathParts] = line.split('\t'); - const filePath = pathParts.join('\t'); // Handle files with tabs in name - switch (status[0]) { - case 'A': statusMap[filePath] = 'added'; break; - case 'M': statusMap[filePath] = 'modified'; break; - case 'D': statusMap[filePath] = 'deleted'; break; - case 'R': statusMap[pathParts[1] || filePath] = 'renamed'; break; - default: statusMap[filePath] = 'modified'; - } - }); - - // Parse numstat for additions/deletions - numstat.split('\n').filter(Boolean).forEach((line: string) => { - const [adds, dels, filePath] = line.split('\t'); - files.push({ - path: filePath, - status: statusMap[filePath] || 'modified', - additions: parseInt(adds, 10) || 0, - deletions: parseInt(dels, 10) || 0 - }); - }); - } catch (diffError) { - console.error('Error getting diff:', diffError); - } - - // Generate summary - const totalAdditions = files.reduce((sum, f) => sum + f.additions, 0); - const totalDeletions = files.reduce((sum, f) => sum + f.deletions, 0); - const summary = `${files.length} files changed, ${totalAdditions} insertions(+), ${totalDeletions} deletions(-)`; - - return { - success: true, - data: { files, summary } - }; - } catch (error) { - console.error('Failed to get worktree diff:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get worktree diff' - }; - } - } - ); - - /** - * Merge the worktree changes into the main branch - * @param taskId - The task ID to merge - * @param options - Merge options { noCommit?: boolean } - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_MERGE, - async (_, taskId: string, options?: { noCommit?: boolean }): Promise> => { - try { - // Ensure Python environment is ready - if (!pythonEnvManager.isEnvReady()) { - const autoBuildSource = getEffectiveSourcePath(); - if (autoBuildSource) { - const status = await pythonEnvManager.initialize(autoBuildSource); - if (!status.ready) { - return { success: false, error: `Python environment not ready: ${status.error || 'Unknown error'}` }; - } - } else { - return { success: false, error: 'Python environment not ready and Auto Claude source not found' }; - } - } - - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Use run.py --merge to handle the merge - const sourcePath = getEffectiveSourcePath(); - if (!sourcePath) { - return { success: false, error: 'Auto Claude source not found' }; - } - - const runScript = path.join(sourcePath, 'run.py'); - const specDir = path.join(project.path, project.autoBuildPath || '.auto-claude', 'specs', task.specId); - - if (!existsSync(specDir)) { - return { success: false, error: 'Spec directory not found' }; - } - - const args = [ - runScript, - '--spec', task.specId, - '--project-dir', project.path, - '--merge' - ]; - - // Add --no-commit flag if requested (stage changes without committing) - if (options?.noCommit) { - args.push('--no-commit'); - } - - return new Promise((resolve) => { - const pythonPath = pythonEnvManager.getPythonPath() || 'python3'; - const mergeProcess = spawn(pythonPath, args, { - cwd: sourcePath, - env: { - ...process.env, - PYTHONUNBUFFERED: '1' - } - }); - - let stdout = ''; - let stderr = ''; - - mergeProcess.stdout.on('data', (data: Buffer) => { - stdout += data.toString(); - }); - - mergeProcess.stderr.on('data', (data: Buffer) => { - stderr += data.toString(); - }); - - mergeProcess.on('close', (code: number) => { - if (code === 0) { - // Persist the status change to implementation_plan.json - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - try { - if (existsSync(planPath)) { - const planContent = readFileSync(planPath, 'utf-8'); - const plan = JSON.parse(planContent); - plan.status = 'done'; - plan.planStatus = 'completed'; - plan.updated_at = new Date().toISOString(); - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } - } catch (persistError) { - console.error('Failed to persist task status:', persistError); - } - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_STATUS_CHANGE, taskId, 'done'); - } - - resolve({ - success: true, - data: { - success: true, - message: 'Changes merged successfully' - } - }); - } else { - // Check if there were conflicts - const hasConflicts = stdout.includes('conflict') || stderr.includes('conflict'); - - resolve({ - success: true, - data: { - success: false, - message: hasConflicts ? 'Merge conflicts detected' : `Merge failed: ${stderr || stdout}`, - conflictFiles: hasConflicts ? [] : undefined - } - }); - } - }); - - mergeProcess.on('error', (err: Error) => { - resolve({ - success: false, - error: `Failed to run merge: ${err.message}` - }); - }); - }); - } catch (error) { - console.error('Failed to merge worktree:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to merge worktree' - }; - } - } - ); - - /** - * Discard the worktree changes - * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/ - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_DISCARD, - async (_, taskId: string): Promise> => { - try { - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Per-spec worktree path: .worktrees/{spec-name}/ - const worktreePath = path.join(project.path, '.worktrees', task.specId); - - if (!existsSync(worktreePath)) { - return { - success: true, - data: { - success: true, - message: 'No worktree to discard' - } - }; - } - - try { - // Get the branch name before removing - const branch = execSync('git rev-parse --abbrev-ref HEAD', { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Remove the worktree - execSync(`git worktree remove --force "${worktreePath}"`, { - cwd: project.path, - encoding: 'utf-8' - }); - - // Delete the branch - try { - execSync(`git branch -D "${branch}"`, { - cwd: project.path, - encoding: 'utf-8' - }); - } catch { - // Branch might already be deleted or not exist - } - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_STATUS_CHANGE, taskId, 'backlog'); - } - - return { - success: true, - data: { - success: true, - message: 'Worktree discarded successfully' - } - }; - } catch (gitError) { - console.error('Git error discarding worktree:', gitError); - return { - success: false, - error: `Failed to discard worktree: ${gitError instanceof Error ? gitError.message : 'Unknown error'}` - }; - } - } catch (error) { - console.error('Failed to discard worktree:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to discard worktree' - }; - } - } - ); - - /** - * List all spec worktrees for a project - * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/ - */ - ipcMain.handle( - IPC_CHANNELS.TASK_LIST_WORKTREES, - async (_, projectId: string): Promise> => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const worktreesDir = path.join(project.path, '.worktrees'); - const worktrees: import('../shared/types').WorktreeListItem[] = []; - - if (!existsSync(worktreesDir)) { - return { success: true, data: { worktrees } }; - } - - // Get all directories in .worktrees - const entries = readdirSync(worktreesDir); - for (const entry of entries) { - const entryPath = path.join(worktreesDir, entry); - const stat = statSync(entryPath); - - // Skip worker directories and non-directories - if (!stat.isDirectory() || entry.startsWith('worker-')) { - continue; - } - - try { - // Get branch info - const branch = execSync('git rev-parse --abbrev-ref HEAD', { - cwd: entryPath, - encoding: 'utf-8' - }).trim(); - - // Get base branch - let baseBranch = 'main'; - try { - baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', { - cwd: project.path, - encoding: 'utf-8' - }).trim().replace('origin/', ''); - } catch { - baseBranch = 'main'; - } - - // Get commit count - let commitCount = 0; - try { - const countOutput = execSync(`git rev-list --count ${baseBranch}..HEAD 2>/dev/null || echo 0`, { - cwd: entryPath, - encoding: 'utf-8' - }).trim(); - commitCount = parseInt(countOutput, 10) || 0; - } catch { - commitCount = 0; - } - - // Get diff stats - let filesChanged = 0; - let additions = 0; - let deletions = 0; - - try { - const diffStat = execSync(`git diff --shortstat ${baseBranch}...HEAD 2>/dev/null || echo ""`, { - cwd: entryPath, - encoding: 'utf-8' - }).trim(); - - const filesMatch = diffStat.match(/(\d+) files? changed/); - const addMatch = diffStat.match(/(\d+) insertions?/); - const delMatch = diffStat.match(/(\d+) deletions?/); - - if (filesMatch) filesChanged = parseInt(filesMatch[1], 10) || 0; - if (addMatch) additions = parseInt(addMatch[1], 10) || 0; - if (delMatch) deletions = parseInt(delMatch[1], 10) || 0; - } catch { - // Ignore diff errors - } - - worktrees.push({ - specName: entry, - path: entryPath, - branch, - baseBranch, - commitCount, - filesChanged, - additions, - deletions - }); - } catch (gitError) { - console.error(`Error getting info for worktree ${entry}:`, gitError); - // Skip this worktree if we can't get git info - } - } - - return { success: true, data: { worktrees } }; - } catch (error) { - console.error('Failed to list worktrees:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to list worktrees' - }; - } - } - ); - - // ============================================ - // Task Archive Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.TASK_ARCHIVE, - async (_, projectId: string, taskIds: string[], version?: string): Promise> => { - try { - const success = projectStore.archiveTasks(projectId, taskIds, version); - return { success, data: success }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to archive tasks' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_UNARCHIVE, - async (_, projectId: string, taskIds: string[]): Promise> => { - try { - const success = projectStore.unarchiveTasks(projectId, taskIds); - return { success, data: success }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to unarchive tasks' - }; - } - } - ); - - // ============================================ - // Task Phase Logs (collapsible by phase) - // ============================================ - - /** - * Get task logs from spec directory - * Returns logs organized by phase (planning, coding, validation) - * Also checks worktree spec directory for coding/validation logs - */ - ipcMain.handle( - IPC_CHANNELS.TASK_LOGS_GET, - async (_, projectId: string, specId: string): Promise> => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // Get specs dir relative to project path - const specsRelPath = getSpecsDir(project.autoBuildPath); - const specDir = path.join(project.path, specsRelPath, specId); - - if (!existsSync(specDir)) { - return { success: false, error: 'Spec directory not found' }; - } - - // Pass project path and specs path so logs can be loaded from worktree too - const logs = taskLogService.loadLogs(specDir, project.path, specsRelPath, specId); - return { success: true, data: logs }; - } catch (error) { - console.error('Failed to get task logs:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get task logs' - }; - } - } - ); - - /** - * Start watching a spec for log changes - * Emits TASK_LOGS_CHANGED and TASK_LOGS_STREAM events - */ - ipcMain.handle( - IPC_CHANNELS.TASK_LOGS_WATCH, - async (_, projectId: string, specId: string): Promise => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // Get specs dir relative to project path - const specsRelPath = getSpecsDir(project.autoBuildPath); - const specDir = path.join(project.path, specsRelPath, specId); - - if (!existsSync(specDir)) { - return { success: false, error: 'Spec directory not found' }; - } - - // Pass project path and specs relative path so the service can also watch - // the worktree spec directory (where coding/validation logs are written) - taskLogService.startWatching(specId, specDir, project.path, specsRelPath); - return { success: true }; - } catch (error) { - console.error('Failed to start watching task logs:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to start watching' - }; - } - } - ); - - /** - * Stop watching a spec for log changes - */ - ipcMain.handle( - IPC_CHANNELS.TASK_LOGS_UNWATCH, - async (_, specId: string): Promise => { - try { - taskLogService.stopWatching(specId); - return { success: true }; - } catch (error) { - console.error('Failed to stop watching task logs:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to stop watching' - }; - } - } - ); - - // Setup task log service event forwarding to renderer - taskLogService.on('logs-changed', (specId: string, logs: TaskLogs) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_LOGS_CHANGED, specId, logs); - } - }); - - taskLogService.on('stream-chunk', (specId: string, chunk: TaskLogStreamChunk) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_LOGS_STREAM, specId, chunk); - } - }); - - // ============================================ - // Settings Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.SETTINGS_GET, - async (): Promise> => { - let settings = { ...DEFAULT_APP_SETTINGS }; - - if (existsSync(settingsPath)) { - try { - const content = readFileSync(settingsPath, 'utf-8'); - settings = { ...settings, ...JSON.parse(content) }; - } catch { - // Use defaults - } - } - - // If no manual autoBuildPath is set, try to auto-detect - if (!settings.autoBuildPath) { - const detectedPath = detectAutoBuildSourcePath(); - if (detectedPath) { - settings.autoBuildPath = detectedPath; - } - } - - return { success: true, data: settings as AppSettings }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.SETTINGS_SAVE, - async (_, settings: Partial): Promise => { - try { - let currentSettings = DEFAULT_APP_SETTINGS; - if (existsSync(settingsPath)) { - const content = readFileSync(settingsPath, 'utf-8'); - currentSettings = { ...currentSettings, ...JSON.parse(content) }; - } - - const newSettings = { ...currentSettings, ...settings }; - writeFileSync(settingsPath, JSON.stringify(newSettings, null, 2)); - - // Apply Python path if changed - if (settings.pythonPath || settings.autoBuildPath) { - agentManager.configure(settings.pythonPath, settings.autoBuildPath); - } - - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to save settings' - }; - } - } - ); - - // ============================================ - // Dialog Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.DIALOG_SELECT_DIRECTORY, - async (): Promise => { - const mainWindow = getMainWindow(); - if (!mainWindow) return null; - - const result = await dialog.showOpenDialog(mainWindow, { - properties: ['openDirectory'], - title: 'Select Project Directory' - }); - - if (result.canceled || result.filePaths.length === 0) { - return null; - } - - return result.filePaths[0]; - } - ); - - ipcMain.handle( - IPC_CHANNELS.DIALOG_CREATE_PROJECT_FOLDER, - async ( - _, - location: string, - name: string, - initGit: boolean - ): Promise> => { - try { - // Validate inputs - if (!location || !name) { - return { success: false, error: 'Location and name are required' }; - } - - // Sanitize project name (convert to kebab-case, remove invalid chars) - const sanitizedName = name - .toLowerCase() - .replace(/\s+/g, '-') - .replace(/[^a-z0-9-_]/g, '') - .replace(/-+/g, '-') - .replace(/^-|-$/g, ''); - - if (!sanitizedName) { - return { success: false, error: 'Invalid project name' }; - } - - const projectPath = path.join(location, sanitizedName); - - // Check if folder already exists - if (existsSync(projectPath)) { - return { success: false, error: `Folder "${sanitizedName}" already exists at this location` }; - } - - // Create the directory - mkdirSync(projectPath, { recursive: true }); - - // Initialize git if requested - let gitInitialized = false; - if (initGit) { - try { - execSync('git init', { cwd: projectPath, stdio: 'ignore' }); - gitInitialized = true; - } catch { - // Git init failed, but folder was created - continue without git - console.warn('Failed to initialize git repository'); - } - } - - return { - success: true, - data: { - path: projectPath, - name: sanitizedName, - gitInitialized - } - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to create project folder' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.DIALOG_GET_DEFAULT_PROJECT_LOCATION, - async (): Promise => { - try { - // Return user's home directory + common project folders - const homeDir = app.getPath('home'); - const commonPaths = [ - path.join(homeDir, 'Projects'), - path.join(homeDir, 'Developer'), - path.join(homeDir, 'Code'), - path.join(homeDir, 'Documents') - ]; - - // Return the first one that exists, or Documents as fallback - for (const p of commonPaths) { - if (existsSync(p)) { - return p; - } - } - - return path.join(homeDir, 'Documents'); - } catch { - return null; - } - } - ); - - // ============================================ - // App Info - // ============================================ - - ipcMain.handle(IPC_CHANNELS.APP_VERSION, async (): Promise => { - return app.getVersion(); - }); - - // ============================================ - // Terminal Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.TERMINAL_CREATE, - async (_, options: TerminalCreateOptions): Promise => { - return terminalManager.create(options); - } - ); - - ipcMain.handle( - IPC_CHANNELS.TERMINAL_DESTROY, - async (_, id: string): Promise => { - return terminalManager.destroy(id); - } - ); - - ipcMain.on( - IPC_CHANNELS.TERMINAL_INPUT, - (_, id: string, data: string) => { - terminalManager.write(id, data); - } - ); - - ipcMain.on( - IPC_CHANNELS.TERMINAL_RESIZE, - (_, id: string, cols: number, rows: number) => { - terminalManager.resize(id, cols, rows); - } - ); - - ipcMain.on( - IPC_CHANNELS.TERMINAL_INVOKE_CLAUDE, - (_, id: string, cwd?: string) => { - terminalManager.invokeClaude(id, cwd); - } - ); - - // Claude profile management (multi-account support) - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILES_GET, - async (): Promise> => { - try { - const profileManager = getClaudeProfileManager(); - const settings = profileManager.getSettings(); - return { success: true, data: settings }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get Claude profiles' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_SAVE, - async (_, profile: ClaudeProfile): Promise> => { - try { - const profileManager = getClaudeProfileManager(); - - // If this is a new profile without an ID, generate one - if (!profile.id) { - profile.id = profileManager.generateProfileId(profile.name); - } - - // Ensure config directory exists for non-default profiles - if (!profile.isDefault && profile.configDir) { - const { mkdirSync, existsSync } = await import('fs'); - if (!existsSync(profile.configDir)) { - mkdirSync(profile.configDir, { recursive: true }); - } - } - - const savedProfile = profileManager.saveProfile(profile); - return { success: true, data: savedProfile }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to save Claude profile' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_DELETE, - async (_, profileId: string): Promise => { - try { - const profileManager = getClaudeProfileManager(); - const success = profileManager.deleteProfile(profileId); - if (!success) { - return { success: false, error: 'Cannot delete default or last profile' }; - } - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to delete Claude profile' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_RENAME, - async (_, profileId: string, newName: string): Promise => { - try { - const profileManager = getClaudeProfileManager(); - const success = profileManager.renameProfile(profileId, newName); - if (!success) { - return { success: false, error: 'Profile not found or invalid name' }; - } - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to rename Claude profile' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_SET_ACTIVE, - async (_, profileId: string): Promise => { - try { - const profileManager = getClaudeProfileManager(); - const success = profileManager.setActiveProfile(profileId); - if (!success) { - return { success: false, error: 'Profile not found' }; - } - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to set active Claude profile' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_SWITCH, - async (_, terminalId: string, profileId: string): Promise => { - try { - const result = await terminalManager.switchClaudeProfile(terminalId, profileId); - return result; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to switch Claude profile' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_INITIALIZE, - async (_, profileId: string): Promise => { - try { - const profileManager = getClaudeProfileManager(); - const profile = profileManager.getProfile(profileId); - if (!profile) { - return { success: false, error: 'Profile not found' }; - } - - // Ensure the config directory exists for non-default profiles - if (!profile.isDefault && profile.configDir) { - const { mkdirSync, existsSync } = await import('fs'); - if (!existsSync(profile.configDir)) { - mkdirSync(profile.configDir, { recursive: true }); - console.log('[IPC] Created config directory:', profile.configDir); - } - } - - // Create a terminal and run claude setup-token there - // This is needed because claude setup-token requires TTY/raw mode - const terminalId = `claude-login-${profileId}-${Date.now()}`; - const homeDir = process.env.HOME || process.env.USERPROFILE || '/tmp'; - - console.log('[IPC] Initializing Claude profile:', { - profileId, - profileName: profile.name, - configDir: profile.configDir, - isDefault: profile.isDefault - }); - - // Create a new terminal for the login process - await terminalManager.create({ id: terminalId, cwd: homeDir }); - - // Wait a moment for the terminal to initialize - await new Promise(resolve => setTimeout(resolve, 500)); - - // Build the login command with the profile's config dir - // Use export to ensure the variable persists, then run setup-token - let loginCommand: string; - if (!profile.isDefault && profile.configDir) { - // Use export and run in subshell to ensure CLAUDE_CONFIG_DIR is properly set - loginCommand = `export CLAUDE_CONFIG_DIR="${profile.configDir}" && echo "Config dir: $CLAUDE_CONFIG_DIR" && claude setup-token`; - } else { - loginCommand = 'claude setup-token'; - } - - console.log('[IPC] Sending login command to terminal:', loginCommand); - - // Write the login command to the terminal - terminalManager.write(terminalId, `${loginCommand}\r`); - - // Notify the renderer that a login terminal was created - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send('claude-profile-login-terminal', { - terminalId, - profileId, - profileName: profile.name - }); - } - - return { - success: true, - data: { - terminalId, - message: `A terminal has been opened to authenticate "${profile.name}". Complete the OAuth flow in your browser, then copy the token shown in the terminal.` - } - }; - } catch (error) { - console.error('[IPC] Failed to initialize Claude profile:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to initialize Claude profile' - }; - } - } - ); - - // Set OAuth token for a profile (used when capturing from terminal or manual input) - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_SET_TOKEN, - async (_, profileId: string, token: string, email?: string): Promise => { - try { - const profileManager = getClaudeProfileManager(); - const success = profileManager.setProfileToken(profileId, token, email); - if (!success) { - return { success: false, error: 'Profile not found' }; - } - return { success: true }; - } catch (error) { - console.error('[IPC] Failed to set OAuth token:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to set OAuth token' - }; - } - } - ); - - // Get auto-switch settings - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_AUTO_SWITCH_SETTINGS, - async (): Promise> => { - try { - const profileManager = getClaudeProfileManager(); - const settings = profileManager.getAutoSwitchSettings(); - return { success: true, data: settings }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get auto-switch settings' - }; - } - } - ); - - // Update auto-switch settings - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_UPDATE_AUTO_SWITCH, - async (_, settings: Partial): Promise => { - try { - const profileManager = getClaudeProfileManager(); - profileManager.updateAutoSwitchSettings(settings); - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update auto-switch settings' - }; - } - } - ); - - // Fetch usage by sending /usage command to terminal - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_FETCH_USAGE, - async (_, terminalId: string): Promise => { - try { - // Send /usage command to the terminal - terminalManager.write(terminalId, '/usage\r'); - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch usage' - }; - } - } - ); - - // Get best available profile - ipcMain.handle( - IPC_CHANNELS.CLAUDE_PROFILE_GET_BEST_PROFILE, - async (_, excludeProfileId?: string): Promise> => { - try { - const profileManager = getClaudeProfileManager(); - const bestProfile = profileManager.getBestAvailableProfile(excludeProfileId); - return { success: true, data: bestProfile }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get best profile' - }; - } - } - ); - - // Retry rate-limited operation with a different profile - ipcMain.handle( - IPC_CHANNELS.CLAUDE_RETRY_WITH_PROFILE, - async (_, request: import('../shared/types').RetryWithProfileRequest): Promise => { - try { - const profileManager = getClaudeProfileManager(); - - // Set the new active profile - profileManager.setActiveProfile(request.profileId); - - // Get the project - const project = projectStore.getProject(request.projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // Retry based on the source - switch (request.source) { - case 'changelog': - // The changelog UI will handle retrying by re-submitting the form - // We just need to confirm the profile switch was successful - return { success: true }; - - case 'task': - // For tasks, we would need to restart the task - // This is complex and would need task state restoration - return { success: true, data: { message: 'Please restart the task manually' } }; - - case 'roadmap': - // For roadmap, the UI can trigger a refresh - return { success: true }; - - case 'ideation': - // For ideation, the UI can trigger a refresh - return { success: true }; - - default: - return { success: true }; - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to retry with profile' - }; - } - } - ); - - // Terminal session management (persistence/restore) - ipcMain.handle( - IPC_CHANNELS.TERMINAL_GET_SESSIONS, - async (_, projectPath: string): Promise> => { - try { - const sessions = terminalManager.getSavedSessions(projectPath); - return { success: true, data: sessions }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get terminal sessions' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.TERMINAL_RESTORE_SESSION, - async (_, session: import('../shared/types').TerminalSession, cols?: number, rows?: number): Promise> => { - try { - const result = await terminalManager.restore(session, cols, rows); - return { - success: result.success, - data: { - success: result.success, - terminalId: session.id, - outputBuffer: result.outputBuffer, - error: result.error - } - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to restore terminal session' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.TERMINAL_CLEAR_SESSIONS, - async (_, projectPath: string): Promise => { - try { - terminalManager.clearSavedSessions(projectPath); - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to clear terminal sessions' - }; - } - } - ); - - ipcMain.on( - IPC_CHANNELS.TERMINAL_RESUME_CLAUDE, - (_, id: string, sessionId?: string) => { - terminalManager.resumeClaude(id, sessionId); - } - ); - - // Get available session dates for a project - ipcMain.handle( - IPC_CHANNELS.TERMINAL_GET_SESSION_DATES, - async (_, projectPath?: string) => { - try { - const dates = terminalManager.getAvailableSessionDates(projectPath); - return { success: true, data: dates }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get session dates' - }; - } - } - ); - - // Get sessions for a specific date and project - ipcMain.handle( - IPC_CHANNELS.TERMINAL_GET_SESSIONS_FOR_DATE, - async (_, date: string, projectPath: string) => { - try { - const sessions = terminalManager.getSessionsForDate(date, projectPath); - return { success: true, data: sessions }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get sessions for date' - }; - } - } - ); - - // Restore all sessions from a specific date - ipcMain.handle( - IPC_CHANNELS.TERMINAL_RESTORE_FROM_DATE, - async (_, date: string, projectPath: string, cols?: number, rows?: number) => { - try { - const result = await terminalManager.restoreSessionsFromDate( - date, - projectPath, - cols || 80, - rows || 24 - ); - return { success: true, data: result }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to restore sessions from date' - }; - } - } - ); - - // ============================================ - // Agent Manager Events → Renderer - // ============================================ - - agentManager.on('log', (taskId: string, log: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_LOG, taskId, log); - } - }); - - agentManager.on('error', (taskId: string, error: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_ERROR, taskId, error); - } - }); - - // Handle SDK rate limit events from agent manager - agentManager.on('sdk-rate-limit', (rateLimitInfo: import('../shared/types').SDKRateLimitInfo) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo); - } - }); - - // Handle SDK rate limit events from title generator - titleGenerator.on('sdk-rate-limit', (rateLimitInfo: import('../shared/types').SDKRateLimitInfo) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo); - } - }); - - agentManager.on('exit', (taskId: string, code: number | null, processType: import('./agent').ProcessType) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - // Stop file watcher - fileWatcher.unwatch(taskId); - - // Determine new status based on process type and exit code - // Flow: Planning → In Progress → AI Review (QA agent) → Human Review (QA passed) - let newStatus: TaskStatus; - - if (processType === 'task-execution') { - // Task execution completed (includes spec_runner → run.py chain) - // Success (code 0) = QA agent signed off → Human Review - // Failure = needs human attention → Human Review - newStatus = 'human_review'; - } else if (processType === 'qa-process') { - // QA retry process completed - newStatus = 'human_review'; - } else if (processType === 'spec-creation') { - // Pure spec creation (shouldn't happen with current flow, but handle it) - // Stay in backlog/planning - console.log(`[Task ${taskId}] Spec creation completed with code ${code}`); - return; - } else { - // Unknown process type - newStatus = 'human_review'; - } - - // Persist status to disk so it survives hot reload - // This is a backup in case the Python backend didn't sync properly - try { - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (task && project) { - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join(project.path, specsBaseDir, task.specId); - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - - if (existsSync(planPath)) { - const planContent = readFileSync(planPath, 'utf-8'); - const plan = JSON.parse(planContent); - - // Only update if not already set to a "further along" status - // (e.g., don't override 'done' with 'human_review') - const currentStatus = plan.status; - const shouldUpdate = !currentStatus || - currentStatus === 'in_progress' || - currentStatus === 'ai_review' || - currentStatus === 'backlog' || - currentStatus === 'pending'; - - if (shouldUpdate) { - plan.status = newStatus; - plan.planStatus = 'review'; - plan.updated_at = new Date().toISOString(); - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - console.log(`[Task ${taskId}] Persisted status '${newStatus}' to implementation_plan.json`); - } - } - } - } catch (persistError) { - console.error(`[Task ${taskId}] Failed to persist status:`, persistError); - } - - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - newStatus - ); - } - }); - - agentManager.on('execution-progress', (taskId: string, progress: import('./agent').ExecutionProgressData) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_EXECUTION_PROGRESS, taskId, progress); - - // Auto-move task to AI Review when entering qa_review phase - if (progress.phase === 'qa_review') { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'ai_review' - ); - } - } - }); - - // ============================================ - // File Watcher Events → Renderer - // ============================================ - - fileWatcher.on('progress', (taskId: string, plan: ImplementationPlan) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_PROGRESS, taskId, plan); - } - }); - - fileWatcher.on('error', (taskId: string, error: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_ERROR, taskId, error); - } - }); - - // ============================================ - // Roadmap Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.ROADMAP_GET, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const roadmapPath = path.join( - project.path, - AUTO_BUILD_PATHS.ROADMAP_DIR, - AUTO_BUILD_PATHS.ROADMAP_FILE - ); - - if (!existsSync(roadmapPath)) { - return { success: true, data: null }; - } - - try { - const content = readFileSync(roadmapPath, 'utf-8'); - const rawRoadmap = JSON.parse(content); - - // Transform snake_case to camelCase for frontend - const roadmap: Roadmap = { - id: rawRoadmap.id || `roadmap-${Date.now()}`, - projectId, - projectName: rawRoadmap.project_name || project.name, - version: rawRoadmap.version || '1.0', - vision: rawRoadmap.vision || '', - targetAudience: { - primary: rawRoadmap.target_audience?.primary || '', - secondary: rawRoadmap.target_audience?.secondary || [] - }, - phases: (rawRoadmap.phases || []).map((phase: Record) => ({ - id: phase.id, - name: phase.name, - description: phase.description, - order: phase.order, - status: phase.status || 'planned', - features: phase.features || [], - milestones: (phase.milestones as Array> || []).map((m) => ({ - id: m.id, - title: m.title, - description: m.description, - features: m.features || [], - status: m.status || 'planned', - targetDate: m.target_date ? new Date(m.target_date as string) : undefined - })) - })), - features: (rawRoadmap.features || []).map((feature: Record) => ({ - id: feature.id, - title: feature.title, - description: feature.description, - rationale: feature.rationale || '', - priority: feature.priority || 'should', - complexity: feature.complexity || 'medium', - impact: feature.impact || 'medium', - phaseId: feature.phase_id, - dependencies: feature.dependencies || [], - status: feature.status || 'idea', - acceptanceCriteria: feature.acceptance_criteria || [], - userStories: feature.user_stories || [], - linkedSpecId: feature.linked_spec_id - })), - status: rawRoadmap.status || 'draft', - createdAt: rawRoadmap.metadata?.created_at ? new Date(rawRoadmap.metadata.created_at) : new Date(), - updatedAt: rawRoadmap.metadata?.updated_at ? new Date(rawRoadmap.metadata.updated_at) : new Date() - }; - - return { success: true, data: roadmap }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to read roadmap' - }; - } - } - ); - - ipcMain.on( - IPC_CHANNELS.ROADMAP_GENERATE, - (_, projectId: string) => { - const mainWindow = getMainWindow(); - if (!mainWindow) return; - - const project = projectStore.getProject(projectId); - if (!project) { - mainWindow.webContents.send( - IPC_CHANNELS.ROADMAP_ERROR, - projectId, - 'Project not found' - ); - return; - } - - // Start roadmap generation via agent manager - agentManager.startRoadmapGeneration(projectId, project.path, false); - - // Send initial progress - mainWindow.webContents.send( - IPC_CHANNELS.ROADMAP_PROGRESS, - projectId, - { - phase: 'analyzing', - progress: 10, - message: 'Analyzing project structure...' - } as RoadmapGenerationStatus - ); - } - ); - - ipcMain.on( - IPC_CHANNELS.ROADMAP_REFRESH, - (_, projectId: string) => { - const mainWindow = getMainWindow(); - if (!mainWindow) return; - - const project = projectStore.getProject(projectId); - if (!project) { - mainWindow.webContents.send( - IPC_CHANNELS.ROADMAP_ERROR, - projectId, - 'Project not found' - ); - return; - } - - // Start roadmap regeneration with refresh flag - agentManager.startRoadmapGeneration(projectId, project.path, true); - - // Send initial progress - mainWindow.webContents.send( - IPC_CHANNELS.ROADMAP_PROGRESS, - projectId, - { - phase: 'analyzing', - progress: 10, - message: 'Refreshing roadmap...' - } as RoadmapGenerationStatus - ); - } - ); - - ipcMain.handle( - IPC_CHANNELS.ROADMAP_UPDATE_FEATURE, - async ( - _, - projectId: string, - featureId: string, - status: RoadmapFeatureStatus - ): Promise => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const roadmapPath = path.join( - project.path, - AUTO_BUILD_PATHS.ROADMAP_DIR, - AUTO_BUILD_PATHS.ROADMAP_FILE - ); - - if (!existsSync(roadmapPath)) { - return { success: false, error: 'Roadmap not found' }; - } - - try { - const content = readFileSync(roadmapPath, 'utf-8'); - const roadmap = JSON.parse(content); - - // Find and update the feature - const feature = roadmap.features?.find((f: { id: string }) => f.id === featureId); - if (!feature) { - return { success: false, error: 'Feature not found' }; - } - - feature.status = status; - roadmap.metadata = roadmap.metadata || {}; - roadmap.metadata.updated_at = new Date().toISOString(); - - writeFileSync(roadmapPath, JSON.stringify(roadmap, null, 2)); - - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update feature' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.ROADMAP_CONVERT_TO_SPEC, - async ( - _, - projectId: string, - featureId: string - ): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const roadmapPath = path.join( - project.path, - AUTO_BUILD_PATHS.ROADMAP_DIR, - AUTO_BUILD_PATHS.ROADMAP_FILE - ); - - if (!existsSync(roadmapPath)) { - return { success: false, error: 'Roadmap not found' }; - } - - try { - const content = readFileSync(roadmapPath, 'utf-8'); - const roadmap = JSON.parse(content); - - // Find the feature - const feature = roadmap.features?.find((f: { id: string }) => f.id === featureId); - if (!feature) { - return { success: false, error: 'Feature not found' }; - } - - // Build task description from feature - const taskDescription = `# ${feature.title} - -${feature.description} - -## Rationale -${feature.rationale || 'N/A'} - -## User Stories -${(feature.user_stories || []).map((s: string) => `- ${s}`).join('\n') || 'N/A'} - -## Acceptance Criteria -${(feature.acceptance_criteria || []).map((c: string) => `- [ ] ${c}`).join('\n') || 'N/A'} -`; - - // Generate proper spec directory (like task creation) - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - - // Ensure specs directory exists - if (!existsSync(specsDir)) { - mkdirSync(specsDir, { recursive: true }); - } - - // Find next available spec number - let specNumber = 1; - const existingDirs = existsSync(specsDir) - ? readdirSync(specsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => d.name) - : []; - const existingNumbers = existingDirs - .map(name => { - const match = name.match(/^(\d+)/); - return match ? parseInt(match[1], 10) : 0; - }) - .filter(n => n > 0); - if (existingNumbers.length > 0) { - specNumber = Math.max(...existingNumbers) + 1; - } - - // Create spec ID with zero-padded number and slugified title - const slugifiedTitle = feature.title - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-|-$/g, '') - .substring(0, 50); - const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`; - - // Create spec directory - const specDir = path.join(specsDir, specId); - mkdirSync(specDir, { recursive: true }); - - // Create initial implementation_plan.json - const now = new Date().toISOString(); - const implementationPlan = { - feature: feature.title, - description: taskDescription, - created_at: now, - updated_at: now, - status: 'pending', - phases: [] - }; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2)); - - // Create requirements.json - const requirements = { - task_description: taskDescription, - workflow_type: 'feature' - }; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2)); - - // Build metadata - const metadata: TaskMetadata = { - sourceType: 'roadmap', - featureId: feature.id, - category: 'feature' - }; - writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2)); - - // Start spec creation with the existing spec directory - agentManager.startSpecCreation(specId, project.path, taskDescription, specDir, metadata); - - // Update feature with linked spec - feature.status = 'planned'; - feature.linked_spec_id = specId; - roadmap.metadata = roadmap.metadata || {}; - roadmap.metadata.updated_at = new Date().toISOString(); - writeFileSync(roadmapPath, JSON.stringify(roadmap, null, 2)); - - // Create task object - const task: Task = { - id: specId, - specId: specId, - projectId, - title: feature.title, - description: taskDescription, - status: 'backlog', - subtasks: [], - logs: [], - metadata, - createdAt: new Date(), - updatedAt: new Date() - }; - - return { success: true, data: task }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to convert feature to spec' - }; - } - } - ); - - // ============================================ - // Roadmap Agent Events → Renderer - // ============================================ - - agentManager.on('roadmap-progress', (projectId: string, status: RoadmapGenerationStatus) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.ROADMAP_PROGRESS, projectId, status); - } - }); - - agentManager.on('roadmap-complete', (projectId: string, roadmap: Roadmap) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.ROADMAP_COMPLETE, projectId, roadmap); - } - }); - - agentManager.on('roadmap-error', (projectId: string, error: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.ROADMAP_ERROR, projectId, error); - } - }); - - // ============================================ - // Context Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.CONTEXT_GET, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - // Load project index - let projectIndex: ProjectIndex | null = null; - const indexPath = path.join(project.path, AUTO_BUILD_PATHS.PROJECT_INDEX); - if (existsSync(indexPath)) { - const content = readFileSync(indexPath, 'utf-8'); - projectIndex = JSON.parse(content); - } - - // Load graphiti state from most recent spec or project root - let memoryState: GraphitiMemoryState | null = null; - let memoryStatus: GraphitiMemoryStatus = { - enabled: false, - available: false, - reason: 'Graphiti not configured' - }; - - // Check for graphiti state in specs - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - if (existsSync(specsDir)) { - const specDirs = readdirSync(specsDir) - .filter((f: string) => { - const specPath = path.join(specsDir, f); - return statSync(specPath).isDirectory(); - }) - .sort() - .reverse(); - - for (const specDir of specDirs) { - const statePath = path.join(specsDir, specDir, AUTO_BUILD_PATHS.GRAPHITI_STATE); - if (existsSync(statePath)) { - const stateContent = readFileSync(statePath, 'utf-8'); - memoryState = JSON.parse(stateContent); - - // If we found a state, update memory status - if (memoryState?.initialized) { - memoryStatus = { - enabled: true, - available: true, - database: memoryState.database || 'auto_build_memory', - host: process.env.GRAPHITI_FALKORDB_HOST || 'localhost', - port: parseInt(process.env.GRAPHITI_FALKORDB_PORT || '6380', 10) - }; - } - break; - } - } - } - - // Check environment for Graphiti config if not found in specs - if (!memoryState) { - // Load project .env file and global settings to check for Graphiti config - let projectEnvVars: Record = {}; - if (project.autoBuildPath) { - const projectEnvPath = path.join(project.path, project.autoBuildPath, '.env'); - if (existsSync(projectEnvPath)) { - try { - const envContent = readFileSync(projectEnvPath, 'utf-8'); - // Parse .env file inline - handle both Unix and Windows line endings - for (const line of envContent.split(/\r?\n/)) { - const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith('#')) continue; - const eqIndex = trimmed.indexOf('='); - if (eqIndex > 0) { - const key = trimmed.substring(0, eqIndex).trim(); - let value = trimmed.substring(eqIndex + 1).trim(); - if ((value.startsWith('"') && value.endsWith('"')) || - (value.startsWith("'") && value.endsWith("'"))) { - value = value.slice(1, -1); - } - projectEnvVars[key] = value; - } - } - } catch { - // Continue with empty vars - } - } - } - - // Load global settings for OpenAI API key fallback - let globalOpenAIKey: string | undefined; - if (existsSync(settingsPath)) { - try { - const settingsContent = readFileSync(settingsPath, 'utf-8'); - const globalSettings = JSON.parse(settingsContent); - globalOpenAIKey = globalSettings.globalOpenAIApiKey; - } catch { - // Continue without global settings - } - } - - // Check for Graphiti config: project .env > process.env - const graphitiEnabled = - projectEnvVars['GRAPHITI_ENABLED']?.toLowerCase() === 'true' || - process.env.GRAPHITI_ENABLED?.toLowerCase() === 'true'; - - // Check for OpenAI key: project .env > global settings > process.env - const hasOpenAI = - !!projectEnvVars['OPENAI_API_KEY'] || - !!globalOpenAIKey || - !!process.env.OPENAI_API_KEY; - - // Get Graphiti connection details from project .env or process.env - const graphitiHost = projectEnvVars['GRAPHITI_FALKORDB_HOST'] || process.env.GRAPHITI_FALKORDB_HOST || 'localhost'; - const graphitiPort = parseInt(projectEnvVars['GRAPHITI_FALKORDB_PORT'] || process.env.GRAPHITI_FALKORDB_PORT || '6380', 10); - const graphitiDatabase = projectEnvVars['GRAPHITI_DATABASE'] || process.env.GRAPHITI_DATABASE || 'auto_build_memory'; - - if (graphitiEnabled && hasOpenAI) { - memoryStatus = { - enabled: true, - available: true, - host: graphitiHost, - port: graphitiPort, - database: graphitiDatabase - }; - } else if (graphitiEnabled && !hasOpenAI) { - memoryStatus = { - enabled: true, - available: false, - reason: 'OPENAI_API_KEY not set (required for Graphiti embeddings)' - }; - } - } - - // Load recent memories from file-based memory (session insights) - const recentMemories: MemoryEpisode[] = []; - if (existsSync(specsDir)) { - const recentSpecDirs = readdirSync(specsDir) - .filter((f: string) => { - const specPath = path.join(specsDir, f); - return statSync(specPath).isDirectory(); - }) - .sort() - .reverse() - .slice(0, 10); // Last 10 specs - - for (const specDir of recentSpecDirs) { - const memoryDir = path.join(specsDir, specDir, 'memory'); - if (existsSync(memoryDir)) { - // Load session insights from session_insights subdirectory - const sessionInsightsDir = path.join(memoryDir, 'session_insights'); - if (existsSync(sessionInsightsDir)) { - const sessionFiles = readdirSync(sessionInsightsDir) - .filter((f: string) => f.startsWith('session_') && f.endsWith('.json')) - .sort() - .reverse(); - - for (const sessionFile of sessionFiles.slice(0, 3)) { - try { - const sessionPath = path.join(sessionInsightsDir, sessionFile); - const sessionContent = readFileSync(sessionPath, 'utf-8'); - const sessionData = JSON.parse(sessionContent); - - // Session files have: session_number, timestamp, subtasks_completed, - // discoveries, what_worked, what_failed, recommendations_for_next_session - if (sessionData.session_number !== undefined) { - recentMemories.push({ - id: `${specDir}-${sessionFile}`, - type: 'session_insight', - timestamp: sessionData.timestamp || new Date().toISOString(), - content: JSON.stringify({ - discoveries: sessionData.discoveries, - what_worked: sessionData.what_worked, - what_failed: sessionData.what_failed, - recommendations: sessionData.recommendations_for_next_session, - subtasks_completed: sessionData.subtasks_completed - }, null, 2), - session_number: sessionData.session_number - }); - } - } catch { - // Skip invalid files - } - } - } - - // Also load codebase_map.json as a memory item - const codebaseMapPath = path.join(memoryDir, 'codebase_map.json'); - if (existsSync(codebaseMapPath)) { - try { - const mapContent = readFileSync(codebaseMapPath, 'utf-8'); - const mapData = JSON.parse(mapContent); - if (mapData.discovered_files && Object.keys(mapData.discovered_files).length > 0) { - recentMemories.push({ - id: `${specDir}-codebase_map`, - type: 'codebase_map', - timestamp: mapData.last_updated || new Date().toISOString(), - content: JSON.stringify(mapData.discovered_files, null, 2), - session_number: undefined - }); - } - } catch { - // Skip invalid files - } - } - } - } - } - - return { - success: true, - data: { - projectIndex, - memoryStatus, - memoryState, - recentMemories: recentMemories.slice(0, 20), - isLoading: false - } - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to load project context' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CONTEXT_REFRESH_INDEX, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - // Run the analyzer script to regenerate project_index.json - const autoBuildSource = getAutoBuildSourcePath(); - - if (!autoBuildSource) { - return { - success: false, - error: 'Auto-build source path not configured' - }; - } - - const analyzerPath = path.join(autoBuildSource, 'analyzer.py'); - const indexOutputPath = path.join(project.path, AUTO_BUILD_PATHS.PROJECT_INDEX); - - // Run analyzer - await new Promise((resolve, reject) => { - const proc = spawn('python', [ - analyzerPath, - '--project-dir', project.path, - '--output', indexOutputPath - ], { - cwd: project.path, - env: { ...process.env } - }); - - proc.on('close', (code: number) => { - if (code === 0) { - resolve(); - } else { - reject(new Error(`Analyzer exited with code ${code}`)); - } - }); - - proc.on('error', reject); - }); - - // Read the new index - if (existsSync(indexOutputPath)) { - const content = readFileSync(indexOutputPath, 'utf-8'); - const projectIndex = JSON.parse(content); - return { success: true, data: projectIndex }; - } - - return { success: false, error: 'Failed to generate project index' }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to refresh project index' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CONTEXT_MEMORY_STATUS, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // Load project .env file to check for Graphiti config - let projectEnvVars: Record = {}; - if (project.autoBuildPath) { - const projectEnvPath = path.join(project.path, project.autoBuildPath, '.env'); - if (existsSync(projectEnvPath)) { - try { - const envContent = readFileSync(projectEnvPath, 'utf-8'); - // Parse .env file inline - handle both Unix and Windows line endings - for (const line of envContent.split(/\r?\n/)) { - const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith('#')) continue; - const eqIndex = trimmed.indexOf('='); - if (eqIndex > 0) { - const key = trimmed.substring(0, eqIndex).trim(); - let value = trimmed.substring(eqIndex + 1).trim(); - if ((value.startsWith('"') && value.endsWith('"')) || - (value.startsWith("'") && value.endsWith("'"))) { - value = value.slice(1, -1); - } - projectEnvVars[key] = value; - } - } - } catch { - // Continue with empty vars - } - } - } - - // Load global settings for OpenAI API key fallback - let globalOpenAIKey: string | undefined; - if (existsSync(settingsPath)) { - try { - const settingsContent = readFileSync(settingsPath, 'utf-8'); - const globalSettings = JSON.parse(settingsContent); - globalOpenAIKey = globalSettings.globalOpenAIApiKey; - } catch { - // Continue without global settings - } - } - - // Check for Graphiti config: project .env > process.env - const graphitiEnabled = - projectEnvVars['GRAPHITI_ENABLED']?.toLowerCase() === 'true' || - process.env.GRAPHITI_ENABLED?.toLowerCase() === 'true'; - - // Check for OpenAI key: project .env > global settings > process.env - const hasOpenAI = - !!projectEnvVars['OPENAI_API_KEY'] || - !!globalOpenAIKey || - !!process.env.OPENAI_API_KEY; - - // Get Graphiti connection details from project .env or process.env - const graphitiHost = projectEnvVars['GRAPHITI_FALKORDB_HOST'] || process.env.GRAPHITI_FALKORDB_HOST || 'localhost'; - const graphitiPort = parseInt(projectEnvVars['GRAPHITI_FALKORDB_PORT'] || process.env.GRAPHITI_FALKORDB_PORT || '6380', 10); - const graphitiDatabase = projectEnvVars['GRAPHITI_DATABASE'] || process.env.GRAPHITI_DATABASE || 'auto_build_memory'; - - if (!graphitiEnabled) { - return { - success: true, - data: { - enabled: false, - available: false, - reason: 'GRAPHITI_ENABLED not set to true' - } - }; - } - - if (!hasOpenAI) { - return { - success: true, - data: { - enabled: true, - available: false, - reason: 'OPENAI_API_KEY not set (required for embeddings)' - } - }; - } - - return { - success: true, - data: { - enabled: true, - available: true, - host: graphitiHost, - port: graphitiPort, - database: graphitiDatabase - } - }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.CONTEXT_SEARCH_MEMORIES, - async (_, projectId: string, query: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // For now, do simple text search in file-based memories - // Graphiti search would require running Python subprocess - const results: ContextSearchResult[] = []; - const queryLower = query.toLowerCase(); - - // Get specs directory path - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - if (existsSync(specsDir)) { - const allSpecDirs = readdirSync(specsDir) - .filter((f: string) => { - const specPath = path.join(specsDir, f); - return statSync(specPath).isDirectory(); - }); - - for (const specDir of allSpecDirs) { - const memoryDir = path.join(specsDir, specDir, 'memory'); - if (existsSync(memoryDir)) { - const memoryFiles = readdirSync(memoryDir) - .filter((f: string) => f.endsWith('.json')); - - for (const memFile of memoryFiles) { - try { - const memPath = path.join(memoryDir, memFile); - const memContent = readFileSync(memPath, 'utf-8'); - - if (memContent.toLowerCase().includes(queryLower)) { - const memData = JSON.parse(memContent); - results.push({ - content: JSON.stringify(memData.insights || memData, null, 2), - score: 1.0, - type: 'session_insight' - }); - } - } catch { - // Skip invalid files - } - } - } - } - } - - return { success: true, data: results.slice(0, 20) }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.CONTEXT_GET_MEMORIES, - async (_, projectId: string, limit: number = 20): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const memories: MemoryEpisode[] = []; - - // Get specs directory path - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - - if (existsSync(specsDir)) { - const sortedSpecDirs = readdirSync(specsDir) - .filter((f: string) => { - const specPath = path.join(specsDir, f); - return statSync(specPath).isDirectory(); - }) - .sort() - .reverse(); - - for (const specDir of sortedSpecDirs) { - const memoryDir = path.join(specsDir, specDir, 'memory'); - if (existsSync(memoryDir)) { - const memoryFiles = readdirSync(memoryDir) - .filter((f: string) => f.endsWith('.json')) - .sort() - .reverse(); - - for (const memFile of memoryFiles) { - try { - const memPath = path.join(memoryDir, memFile); - const memContent = readFileSync(memPath, 'utf-8'); - const memData = JSON.parse(memContent); - - memories.push({ - id: `${specDir}-${memFile}`, - type: memData.type || 'session_insight', - timestamp: memData.timestamp || new Date().toISOString(), - content: JSON.stringify(memData.insights || memData, null, 2), - session_number: memData.session_number - }); - - if (memories.length >= limit) { - break; - } - } catch { - // Skip invalid files - } - } - } - - if (memories.length >= limit) { - break; - } - } - } - - return { success: true, data: memories }; - } - ); - - // ============================================ - // Environment Configuration Operations - // ============================================ - - /** - * Parse .env file into key-value object - */ - const parseEnvFile = (content: string): Record => { - const result: Record = {}; - const lines = content.split('\n'); - - for (const line of lines) { - const trimmed = line.trim(); - // Skip empty lines and comments - if (!trimmed || trimmed.startsWith('#')) continue; - - const equalsIndex = trimmed.indexOf('='); - if (equalsIndex > 0) { - const key = trimmed.substring(0, equalsIndex).trim(); - let value = trimmed.substring(equalsIndex + 1).trim(); - // Remove quotes if present - if ((value.startsWith('"') && value.endsWith('"')) || - (value.startsWith("'") && value.endsWith("'"))) { - value = value.slice(1, -1); - } - result[key] = value; - } - } - return result; - }; - - /** - * Generate .env file content from config - */ - const generateEnvContent = ( - config: Partial, - existingContent?: string - ): string => { - // Parse existing content to preserve comments and structure - const existingVars = existingContent ? parseEnvFile(existingContent) : {}; - - // Update with new values - if (config.claudeOAuthToken !== undefined) { - existingVars['CLAUDE_CODE_OAUTH_TOKEN'] = config.claudeOAuthToken; - } - if (config.autoBuildModel !== undefined) { - existingVars['AUTO_BUILD_MODEL'] = config.autoBuildModel; - } - if (config.linearApiKey !== undefined) { - existingVars['LINEAR_API_KEY'] = config.linearApiKey; - } - if (config.linearTeamId !== undefined) { - existingVars['LINEAR_TEAM_ID'] = config.linearTeamId; - } - if (config.linearProjectId !== undefined) { - existingVars['LINEAR_PROJECT_ID'] = config.linearProjectId; - } - if (config.linearRealtimeSync !== undefined) { - existingVars['LINEAR_REALTIME_SYNC'] = config.linearRealtimeSync ? 'true' : 'false'; - } - // GitHub Integration - if (config.githubToken !== undefined) { - existingVars['GITHUB_TOKEN'] = config.githubToken; - } - if (config.githubRepo !== undefined) { - existingVars['GITHUB_REPO'] = config.githubRepo; - } - if (config.githubAutoSync !== undefined) { - existingVars['GITHUB_AUTO_SYNC'] = config.githubAutoSync ? 'true' : 'false'; - } - if (config.graphitiEnabled !== undefined) { - existingVars['GRAPHITI_ENABLED'] = config.graphitiEnabled ? 'true' : 'false'; - } - if (config.openaiApiKey !== undefined) { - existingVars['OPENAI_API_KEY'] = config.openaiApiKey; - } - if (config.graphitiFalkorDbHost !== undefined) { - existingVars['GRAPHITI_FALKORDB_HOST'] = config.graphitiFalkorDbHost; - } - if (config.graphitiFalkorDbPort !== undefined) { - existingVars['GRAPHITI_FALKORDB_PORT'] = String(config.graphitiFalkorDbPort); - } - if (config.graphitiFalkorDbPassword !== undefined) { - existingVars['GRAPHITI_FALKORDB_PASSWORD'] = config.graphitiFalkorDbPassword; - } - if (config.graphitiDatabase !== undefined) { - existingVars['GRAPHITI_DATABASE'] = config.graphitiDatabase; - } - if (config.enableFancyUi !== undefined) { - existingVars['ENABLE_FANCY_UI'] = config.enableFancyUi ? 'true' : 'false'; - } - - // Generate content with sections - let content = `# Auto Claude Framework Environment Variables -# Managed by Auto Claude UI - -# Claude Code OAuth Token (REQUIRED) -CLAUDE_CODE_OAUTH_TOKEN=${existingVars['CLAUDE_CODE_OAUTH_TOKEN'] || ''} - -# Model override (OPTIONAL) -${existingVars['AUTO_BUILD_MODEL'] ? `AUTO_BUILD_MODEL=${existingVars['AUTO_BUILD_MODEL']}` : '# AUTO_BUILD_MODEL=claude-opus-4-5-20251101'} - -# ============================================================================= -# LINEAR INTEGRATION (OPTIONAL) -# ============================================================================= -${existingVars['LINEAR_API_KEY'] ? `LINEAR_API_KEY=${existingVars['LINEAR_API_KEY']}` : '# LINEAR_API_KEY='} -${existingVars['LINEAR_TEAM_ID'] ? `LINEAR_TEAM_ID=${existingVars['LINEAR_TEAM_ID']}` : '# LINEAR_TEAM_ID='} -${existingVars['LINEAR_PROJECT_ID'] ? `LINEAR_PROJECT_ID=${existingVars['LINEAR_PROJECT_ID']}` : '# LINEAR_PROJECT_ID='} -${existingVars['LINEAR_REALTIME_SYNC'] !== undefined ? `LINEAR_REALTIME_SYNC=${existingVars['LINEAR_REALTIME_SYNC']}` : '# LINEAR_REALTIME_SYNC=false'} - -# ============================================================================= -# GITHUB INTEGRATION (OPTIONAL) -# ============================================================================= -${existingVars['GITHUB_TOKEN'] ? `GITHUB_TOKEN=${existingVars['GITHUB_TOKEN']}` : '# GITHUB_TOKEN='} -${existingVars['GITHUB_REPO'] ? `GITHUB_REPO=${existingVars['GITHUB_REPO']}` : '# GITHUB_REPO=owner/repo'} -${existingVars['GITHUB_AUTO_SYNC'] !== undefined ? `GITHUB_AUTO_SYNC=${existingVars['GITHUB_AUTO_SYNC']}` : '# GITHUB_AUTO_SYNC=false'} - -# ============================================================================= -# UI SETTINGS (OPTIONAL) -# ============================================================================= -${existingVars['ENABLE_FANCY_UI'] !== undefined ? `ENABLE_FANCY_UI=${existingVars['ENABLE_FANCY_UI']}` : '# ENABLE_FANCY_UI=true'} - -# ============================================================================= -# GRAPHITI MEMORY INTEGRATION (OPTIONAL) -# ============================================================================= -${existingVars['GRAPHITI_ENABLED'] ? `GRAPHITI_ENABLED=${existingVars['GRAPHITI_ENABLED']}` : '# GRAPHITI_ENABLED=false'} -${existingVars['OPENAI_API_KEY'] ? `OPENAI_API_KEY=${existingVars['OPENAI_API_KEY']}` : '# OPENAI_API_KEY='} -${existingVars['GRAPHITI_FALKORDB_HOST'] ? `GRAPHITI_FALKORDB_HOST=${existingVars['GRAPHITI_FALKORDB_HOST']}` : '# GRAPHITI_FALKORDB_HOST=localhost'} -${existingVars['GRAPHITI_FALKORDB_PORT'] ? `GRAPHITI_FALKORDB_PORT=${existingVars['GRAPHITI_FALKORDB_PORT']}` : '# GRAPHITI_FALKORDB_PORT=6380'} -${existingVars['GRAPHITI_FALKORDB_PASSWORD'] ? `GRAPHITI_FALKORDB_PASSWORD=${existingVars['GRAPHITI_FALKORDB_PASSWORD']}` : '# GRAPHITI_FALKORDB_PASSWORD='} -${existingVars['GRAPHITI_DATABASE'] ? `GRAPHITI_DATABASE=${existingVars['GRAPHITI_DATABASE']}` : '# GRAPHITI_DATABASE=auto_build_memory'} -`; - - return content; - }; - - ipcMain.handle( - IPC_CHANNELS.ENV_GET, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - if (!project.autoBuildPath) { - return { success: false, error: 'Project not initialized' }; - } - - const envPath = path.join(project.path, project.autoBuildPath, '.env'); - - // Load global settings for fallbacks - let globalSettings: AppSettings = { ...DEFAULT_APP_SETTINGS }; - if (existsSync(settingsPath)) { - try { - const content = readFileSync(settingsPath, 'utf-8'); - globalSettings = { ...globalSettings, ...JSON.parse(content) }; - } catch { - // Use defaults - } - } - - // Default config - const config: ProjectEnvConfig = { - claudeAuthStatus: 'not_configured', - linearEnabled: false, - githubEnabled: false, - graphitiEnabled: false, - enableFancyUi: true, - claudeTokenIsGlobal: false, - openaiKeyIsGlobal: false - }; - - // Parse project-specific .env if it exists - let vars: Record = {}; - if (existsSync(envPath)) { - try { - const content = readFileSync(envPath, 'utf-8'); - vars = parseEnvFile(content); - } catch { - // Continue with empty vars - } - } - - // Claude OAuth Token: project-specific takes precedence, then global - if (vars['CLAUDE_CODE_OAUTH_TOKEN']) { - config.claudeOAuthToken = vars['CLAUDE_CODE_OAUTH_TOKEN']; - config.claudeAuthStatus = 'token_set'; - config.claudeTokenIsGlobal = false; - } else if (globalSettings.globalClaudeOAuthToken) { - config.claudeOAuthToken = globalSettings.globalClaudeOAuthToken; - config.claudeAuthStatus = 'token_set'; - config.claudeTokenIsGlobal = true; - } - - if (vars['AUTO_BUILD_MODEL']) { - config.autoBuildModel = vars['AUTO_BUILD_MODEL']; - } - - if (vars['LINEAR_API_KEY']) { - config.linearEnabled = true; - config.linearApiKey = vars['LINEAR_API_KEY']; - } - if (vars['LINEAR_TEAM_ID']) { - config.linearTeamId = vars['LINEAR_TEAM_ID']; - } - if (vars['LINEAR_PROJECT_ID']) { - config.linearProjectId = vars['LINEAR_PROJECT_ID']; - } - if (vars['LINEAR_REALTIME_SYNC']?.toLowerCase() === 'true') { - config.linearRealtimeSync = true; - } - - // GitHub config - if (vars['GITHUB_TOKEN']) { - config.githubEnabled = true; - config.githubToken = vars['GITHUB_TOKEN']; - } - if (vars['GITHUB_REPO']) { - config.githubRepo = vars['GITHUB_REPO']; - } - if (vars['GITHUB_AUTO_SYNC']?.toLowerCase() === 'true') { - config.githubAutoSync = true; - } - - if (vars['GRAPHITI_ENABLED']?.toLowerCase() === 'true') { - config.graphitiEnabled = true; - } - - // OpenAI API Key: project-specific takes precedence, then global - if (vars['OPENAI_API_KEY']) { - config.openaiApiKey = vars['OPENAI_API_KEY']; - config.openaiKeyIsGlobal = false; - } else if (globalSettings.globalOpenAIApiKey) { - config.openaiApiKey = globalSettings.globalOpenAIApiKey; - config.openaiKeyIsGlobal = true; - } - - if (vars['GRAPHITI_FALKORDB_HOST']) { - config.graphitiFalkorDbHost = vars['GRAPHITI_FALKORDB_HOST']; - } - if (vars['GRAPHITI_FALKORDB_PORT']) { - config.graphitiFalkorDbPort = parseInt(vars['GRAPHITI_FALKORDB_PORT'], 10); - } - if (vars['GRAPHITI_FALKORDB_PASSWORD']) { - config.graphitiFalkorDbPassword = vars['GRAPHITI_FALKORDB_PASSWORD']; - } - if (vars['GRAPHITI_DATABASE']) { - config.graphitiDatabase = vars['GRAPHITI_DATABASE']; - } - - if (vars['ENABLE_FANCY_UI']?.toLowerCase() === 'false') { - config.enableFancyUi = false; - } - - return { success: true, data: config }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.ENV_UPDATE, - async (_, projectId: string, config: Partial): Promise => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - if (!project.autoBuildPath) { - return { success: false, error: 'Project not initialized' }; - } - - const envPath = path.join(project.path, project.autoBuildPath, '.env'); - - try { - // Read existing content if file exists - let existingContent: string | undefined; - if (existsSync(envPath)) { - existingContent = readFileSync(envPath, 'utf-8'); - } - - // Generate new content - const newContent = generateEnvContent(config, existingContent); - - // Write to file - writeFileSync(envPath, newContent); - - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update .env file' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.ENV_CHECK_CLAUDE_AUTH, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - // Check if Claude CLI is available and authenticated - const result = await new Promise((resolve) => { - const proc = spawn('claude', ['--version'], { - cwd: project.path, - env: { ...process.env }, - shell: true - }); - - let stdout = ''; - let stderr = ''; - - proc.stdout?.on('data', (data: Buffer) => { - stdout += data.toString(); - }); - - proc.stderr?.on('data', (data: Buffer) => { - stderr += data.toString(); - }); - - proc.on('close', (code: number | null) => { - if (code === 0) { - // Claude CLI is available, check if authenticated - // Run a simple command that requires auth - const authCheck = spawn('claude', ['api', '--help'], { - cwd: project.path, - env: { ...process.env }, - shell: true - }); - - authCheck.on('close', (authCode: number | null) => { - resolve({ - success: true, - authenticated: authCode === 0 - }); - }); - - authCheck.on('error', () => { - resolve({ - success: true, - authenticated: false, - error: 'Could not verify authentication' - }); - }); - } else { - resolve({ - success: false, - authenticated: false, - error: 'Claude CLI not found. Please install it first.' - }); - } - }); - - proc.on('error', () => { - resolve({ - success: false, - authenticated: false, - error: 'Claude CLI not found. Please install it first.' - }); - }); - }); - - return { success: true, data: result }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to check Claude auth' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.ENV_INVOKE_CLAUDE_SETUP, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - // Run claude setup-token which will open browser for OAuth - const result = await new Promise((resolve) => { - const proc = spawn('claude', ['setup-token'], { - cwd: project.path, - env: { ...process.env }, - shell: true, - stdio: 'inherit' // This allows the terminal to handle the interactive auth - }); - - proc.on('close', (code: number | null) => { - if (code === 0) { - resolve({ - success: true, - authenticated: true - }); - } else { - resolve({ - success: false, - authenticated: false, - error: 'Setup cancelled or failed' - }); - } - }); - - proc.on('error', (err: Error) => { - resolve({ - success: false, - authenticated: false, - error: err.message - }); - }); - }); - - return { success: true, data: result }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to invoke Claude setup' - }; - } - } - ); - - // ============================================ - // Linear Integration Operations - // ============================================ - - /** - * Helper to get Linear API key from project env - */ - const getLinearApiKey = (project: Project): string | null => { - if (!project.autoBuildPath) return null; - const envPath = path.join(project.path, project.autoBuildPath, '.env'); - if (!existsSync(envPath)) return null; - - try { - const content = readFileSync(envPath, 'utf-8'); - const vars = parseEnvFile(content); - return vars['LINEAR_API_KEY'] || null; - } catch { - return null; - } - }; - - /** - * Make a request to the Linear API - */ - const linearGraphQL = async ( - apiKey: string, - query: string, - variables?: Record - ): Promise => { - const response = await fetch('https://api.linear.app/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': apiKey - }, - body: JSON.stringify({ query, variables }) - }); - - if (!response.ok) { - throw new Error(`Linear API error: ${response.status} ${response.statusText}`); - } - - const result = await response.json(); - if (result.errors) { - throw new Error(result.errors[0]?.message || 'Linear API error'); - } - - return result.data; - }; - - ipcMain.handle( - IPC_CHANNELS.LINEAR_CHECK_CONNECTION, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const apiKey = getLinearApiKey(project); - if (!apiKey) { - return { - success: true, - data: { - connected: false, - error: 'No Linear API key configured' - } - }; - } - - try { - const query = ` - query { - viewer { - id - name - } - teams { - nodes { - id - name - key - } - } - } - `; - - const data = await linearGraphQL(apiKey, query) as { - viewer: { id: string; name: string }; - teams: { nodes: Array<{ id: string; name: string; key: string }> }; - }; - - // Get issue count for the first team - let issueCount = 0; - let teamName: string | undefined; - - if (data.teams.nodes.length > 0) { - teamName = data.teams.nodes[0].name; - const countQuery = ` - query($teamId: String!) { - team(id: $teamId) { - issues { - totalCount: nodes { id } - } - } - } - `; - // Get approximate count - const issuesQuery = ` - query($teamId: String!) { - issues(filter: { team: { id: { eq: $teamId } } }, first: 0) { - pageInfo { - hasNextPage - } - } - } - `; - - // Simple count estimation - get first 250 issues - const countData = await linearGraphQL(apiKey, ` - query($teamId: String!) { - issues(filter: { team: { id: { eq: $teamId } } }, first: 250) { - nodes { id } - } - } - `, { teamId: data.teams.nodes[0].id }) as { - issues: { nodes: Array<{ id: string }> }; - }; - issueCount = countData.issues.nodes.length; - } - - return { - success: true, - data: { - connected: true, - teamName, - issueCount, - lastSyncedAt: new Date().toISOString() - } - }; - } catch (error) { - return { - success: true, - data: { - connected: false, - error: error instanceof Error ? error.message : 'Failed to connect to Linear' - } - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.LINEAR_GET_TEAMS, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const apiKey = getLinearApiKey(project); - if (!apiKey) { - return { success: false, error: 'No Linear API key configured' }; - } - - try { - const query = ` - query { - teams { - nodes { - id - name - key - } - } - } - `; - - const data = await linearGraphQL(apiKey, query) as { - teams: { nodes: LinearTeam[] }; - }; - - return { success: true, data: data.teams.nodes }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch teams' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.LINEAR_GET_PROJECTS, - async (_, projectId: string, teamId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const apiKey = getLinearApiKey(project); - if (!apiKey) { - return { success: false, error: 'No Linear API key configured' }; - } - - try { - const query = ` - query($teamId: String!) { - team(id: $teamId) { - projects { - nodes { - id - name - state - } - } - } - } - `; - - const data = await linearGraphQL(apiKey, query, { teamId }) as { - team: { projects: { nodes: LinearProject[] } }; - }; - - return { success: true, data: data.team.projects.nodes }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch projects' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.LINEAR_GET_ISSUES, - async (_, projectId: string, teamId?: string, linearProjectId?: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const apiKey = getLinearApiKey(project); - if (!apiKey) { - return { success: false, error: 'No Linear API key configured' }; - } - - try { - // Build filter based on provided parameters - const filters: string[] = []; - if (teamId) { - filters.push(`team: { id: { eq: "${teamId}" } }`); - } - if (linearProjectId) { - filters.push(`project: { id: { eq: "${linearProjectId}" } }`); - } - - const filterClause = filters.length > 0 ? `filter: { ${filters.join(', ')} }` : ''; - - const query = ` - query { - issues(${filterClause}, first: 250, orderBy: updatedAt) { - nodes { - id - identifier - title - description - state { - id - name - type - } - priority - priorityLabel - labels { - nodes { - id - name - color - } - } - assignee { - id - name - email - } - project { - id - name - } - createdAt - updatedAt - url - } - } - } - `; - - const data = await linearGraphQL(apiKey, query) as { - issues: { - nodes: Array<{ - id: string; - identifier: string; - title: string; - description?: string; - state: { id: string; name: string; type: string }; - priority: number; - priorityLabel: string; - labels: { nodes: Array<{ id: string; name: string; color: string }> }; - assignee?: { id: string; name: string; email: string }; - project?: { id: string; name: string }; - createdAt: string; - updatedAt: string; - url: string; - }>; - }; - }; - - // Transform to our LinearIssue format - const issues: LinearIssue[] = data.issues.nodes.map(issue => ({ - ...issue, - labels: issue.labels.nodes - })); - - return { success: true, data: issues }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch issues' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.LINEAR_IMPORT_ISSUES, - async (_, projectId: string, issueIds: string[]): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const apiKey = getLinearApiKey(project); - if (!apiKey) { - return { success: false, error: 'No Linear API key configured' }; - } - - try { - // First, fetch the full details of selected issues - const query = ` - query($ids: [String!]!) { - issues(filter: { id: { in: $ids } }) { - nodes { - id - identifier - title - description - state { - id - name - type - } - priority - priorityLabel - labels { - nodes { - id - name - color - } - } - url - } - } - } - `; - - const data = await linearGraphQL(apiKey, query, { ids: issueIds }) as { - issues: { - nodes: Array<{ - id: string; - identifier: string; - title: string; - description?: string; - state: { id: string; name: string; type: string }; - priority: number; - priorityLabel: string; - labels: { nodes: Array<{ id: string; name: string; color: string }> }; - url: string; - }>; - }; - }; - - let imported = 0; - let failed = 0; - const errors: string[] = []; - - // Set up specs directory - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - if (!existsSync(specsDir)) { - mkdirSync(specsDir, { recursive: true }); - } - - // Create tasks for each imported issue - for (const issue of data.issues.nodes) { - try { - // Build description from Linear issue - const labels = issue.labels.nodes.map(l => l.name).join(', '); - const description = `# ${issue.title} - -**Linear Issue:** [${issue.identifier}](${issue.url}) -**Priority:** ${issue.priorityLabel} -**Status:** ${issue.state.name} -${labels ? `**Labels:** ${labels}` : ''} - -## Description - -${issue.description || 'No description provided.'} -`; - - // Find next available spec number - let specNumber = 1; - const existingDirs = readdirSync(specsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => d.name); - const existingNumbers = existingDirs - .map(name => { - const match = name.match(/^(\d+)/); - return match ? parseInt(match[1], 10) : 0; - }) - .filter(n => n > 0); - if (existingNumbers.length > 0) { - specNumber = Math.max(...existingNumbers) + 1; - } - - // Create spec ID with zero-padded number and slugified title - const slugifiedTitle = issue.title - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-|-$/g, '') - .substring(0, 50); - const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`; - - // Create spec directory - const specDir = path.join(specsDir, specId); - mkdirSync(specDir, { recursive: true }); - - // Create initial implementation_plan.json - const now = new Date().toISOString(); - const implementationPlan = { - feature: issue.title, - description: description, - created_at: now, - updated_at: now, - status: 'pending', - phases: [] - }; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2)); - - // Create requirements.json - const requirements = { - task_description: description, - workflow_type: 'feature' - }; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2)); - - // Build metadata - const metadata: TaskMetadata = { - sourceType: 'linear', - linearIssueId: issue.id, - linearIdentifier: issue.identifier, - linearUrl: issue.url, - category: 'feature' - }; - writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2)); - - // Start spec creation with the existing spec directory - agentManager.startSpecCreation(specId, project.path, description, specDir, metadata); - - imported++; - } catch (err) { - failed++; - errors.push(`Failed to import ${issue.identifier}: ${err instanceof Error ? err.message : 'Unknown error'}`); - } - } - - return { - success: true, - data: { - success: failed === 0, - imported, - failed, - errors: errors.length > 0 ? errors : undefined - } - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to import issues' - }; - } - } - ); - - // ============================================ - // GitHub Integration Operations - // ============================================ - - /** - * Helper to get GitHub config from project env - */ - const getGitHubConfig = (project: Project): { token: string; repo: string } | null => { - if (!project.autoBuildPath) return null; - const envPath = path.join(project.path, project.autoBuildPath, '.env'); - if (!existsSync(envPath)) return null; - - try { - const content = readFileSync(envPath, 'utf-8'); - const vars = parseEnvFile(content); - const token = vars['GITHUB_TOKEN']; - const repo = vars['GITHUB_REPO']; - - if (!token || !repo) return null; - return { token, repo }; - } catch { - return null; - } - }; - - /** - * Make a request to the GitHub API - */ - const githubFetch = async ( - token: string, - endpoint: string, - options: RequestInit = {} - ): Promise => { - const url = endpoint.startsWith('http') - ? endpoint - : `https://api.github.com${endpoint}`; - - const response = await fetch(url, { - ...options, - headers: { - 'Accept': 'application/vnd.github.v3+json', - 'Authorization': `Bearer ${token}`, - 'User-Agent': 'Auto-Claude-UI', - ...options.headers - } - }); - - if (!response.ok) { - const errorBody = await response.text(); - throw new Error(`GitHub API error: ${response.status} ${response.statusText} - ${errorBody}`); - } - - return response.json(); - }; - - ipcMain.handle( - IPC_CHANNELS.GITHUB_CHECK_CONNECTION, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const config = getGitHubConfig(project); - if (!config) { - return { - success: true, - data: { - connected: false, - error: 'No GitHub token or repository configured' - } - }; - } - - try { - // Fetch repo info - const repoData = await githubFetch( - config.token, - `/repos/${config.repo}` - ) as { full_name: string; description?: string }; - - // Count open issues - const issuesData = await githubFetch( - config.token, - `/repos/${config.repo}/issues?state=open&per_page=1` - ) as unknown[]; - - const openCount = Array.isArray(issuesData) ? issuesData.length : 0; - - return { - success: true, - data: { - connected: true, - repoFullName: repoData.full_name, - repoDescription: repoData.description, - issueCount: openCount, - lastSyncedAt: new Date().toISOString() - } - }; - } catch (error) { - return { - success: true, - data: { - connected: false, - error: error instanceof Error ? error.message : 'Failed to connect to GitHub' - } - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.GITHUB_GET_REPOSITORIES, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const config = getGitHubConfig(project); - if (!config) { - return { success: false, error: 'No GitHub token configured' }; - } - - try { - const repos = await githubFetch( - config.token, - '/user/repos?per_page=100&sort=updated' - ) as Array<{ - id: number; - name: string; - full_name: string; - description?: string; - html_url: string; - default_branch: string; - private: boolean; - owner: { login: string; avatar_url?: string }; - }>; - - const result: GitHubRepository[] = repos.map(repo => ({ - id: repo.id, - name: repo.name, - fullName: repo.full_name, - description: repo.description, - url: repo.html_url, - defaultBranch: repo.default_branch, - private: repo.private, - owner: { - login: repo.owner.login, - avatarUrl: repo.owner.avatar_url - } - })); - - return { success: true, data: result }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch repositories' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.GITHUB_GET_ISSUES, - async (_, projectId: string, state: 'open' | 'closed' | 'all' = 'open'): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const config = getGitHubConfig(project); - if (!config) { - return { success: false, error: 'No GitHub token or repository configured' }; - } - - try { - const issues = await githubFetch( - config.token, - `/repos/${config.repo}/issues?state=${state}&per_page=100&sort=updated` - ) as Array<{ - id: number; - number: number; - title: string; - body?: string; - state: 'open' | 'closed'; - labels: Array<{ id: number; name: string; color: string; description?: string }>; - assignees: Array<{ login: string; avatar_url?: string }>; - user: { login: string; avatar_url?: string }; - milestone?: { id: number; title: string; state: 'open' | 'closed' }; - created_at: string; - updated_at: string; - closed_at?: string; - comments: number; - url: string; - html_url: string; - pull_request?: unknown; - }>; - - // Filter out pull requests - const issuesOnly = issues.filter(issue => !issue.pull_request); - - const result: GitHubIssue[] = issuesOnly.map(issue => ({ - id: issue.id, - number: issue.number, - title: issue.title, - body: issue.body, - state: issue.state, - labels: issue.labels, - assignees: issue.assignees.map(a => ({ - login: a.login, - avatarUrl: a.avatar_url - })), - author: { - login: issue.user.login, - avatarUrl: issue.user.avatar_url - }, - milestone: issue.milestone, - createdAt: issue.created_at, - updatedAt: issue.updated_at, - closedAt: issue.closed_at, - commentsCount: issue.comments, - url: issue.url, - htmlUrl: issue.html_url, - repoFullName: config.repo - })); - - return { success: true, data: result }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch issues' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.GITHUB_GET_ISSUE, - async (_, projectId: string, issueNumber: number): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const config = getGitHubConfig(project); - if (!config) { - return { success: false, error: 'No GitHub token or repository configured' }; - } - - try { - const issue = await githubFetch( - config.token, - `/repos/${config.repo}/issues/${issueNumber}` - ) as { - id: number; - number: number; - title: string; - body?: string; - state: 'open' | 'closed'; - labels: Array<{ id: number; name: string; color: string; description?: string }>; - assignees: Array<{ login: string; avatar_url?: string }>; - user: { login: string; avatar_url?: string }; - milestone?: { id: number; title: string; state: 'open' | 'closed' }; - created_at: string; - updated_at: string; - closed_at?: string; - comments: number; - url: string; - html_url: string; - }; - - const result: GitHubIssue = { - id: issue.id, - number: issue.number, - title: issue.title, - body: issue.body, - state: issue.state, - labels: issue.labels, - assignees: issue.assignees.map(a => ({ - login: a.login, - avatarUrl: a.avatar_url - })), - author: { - login: issue.user.login, - avatarUrl: issue.user.avatar_url - }, - milestone: issue.milestone, - createdAt: issue.created_at, - updatedAt: issue.updated_at, - closedAt: issue.closed_at, - commentsCount: issue.comments, - url: issue.url, - htmlUrl: issue.html_url, - repoFullName: config.repo - }; - - return { success: true, data: result }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to fetch issue' - }; - } - } - ); - - ipcMain.on( - IPC_CHANNELS.GITHUB_INVESTIGATE_ISSUE, - async (_, projectId: string, issueNumber: number) => { - const mainWindow = getMainWindow(); - if (!mainWindow) return; - - const project = projectStore.getProject(projectId); - if (!project) { - mainWindow.webContents.send( - IPC_CHANNELS.GITHUB_INVESTIGATION_ERROR, - projectId, - 'Project not found' - ); - return; - } - - const config = getGitHubConfig(project); - if (!config) { - mainWindow.webContents.send( - IPC_CHANNELS.GITHUB_INVESTIGATION_ERROR, - projectId, - 'No GitHub token or repository configured' - ); - return; - } - - try { - // Send progress update: fetching issue - mainWindow.webContents.send( - IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS, - projectId, - { - phase: 'fetching', - issueNumber, - progress: 10, - message: 'Fetching issue details...' - } as GitHubInvestigationStatus - ); - - // Fetch the issue - const issue = await githubFetch( - config.token, - `/repos/${config.repo}/issues/${issueNumber}` - ) as { - number: number; - title: string; - body?: string; - labels: Array<{ name: string }>; - html_url: string; - }; - - // Fetch issue comments for more context - const comments = await githubFetch( - config.token, - `/repos/${config.repo}/issues/${issueNumber}/comments` - ) as Array<{ body: string; user: { login: string } }>; - - // Build context for the AI investigation - const issueContext = ` -# GitHub Issue #${issue.number}: ${issue.title} - -${issue.body || 'No description provided.'} - -${comments.length > 0 ? `## Comments (${comments.length}): -${comments.map(c => `**${c.user.login}:** ${c.body}`).join('\n\n')}` : ''} - -**Labels:** ${issue.labels.map(l => l.name).join(', ') || 'None'} -**URL:** ${issue.html_url} -`; - - // Send progress update: analyzing - mainWindow.webContents.send( - IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS, - projectId, - { - phase: 'analyzing', - issueNumber, - progress: 30, - message: 'AI is analyzing the issue...' - } as GitHubInvestigationStatus - ); - - // Build task description - const taskDescription = `Investigate GitHub Issue #${issue.number}: ${issue.title} - -${issueContext} - -Please analyze this issue and provide: -1. A brief summary of what the issue is about -2. A proposed solution approach -3. The files that would likely need to be modified -4. Estimated complexity (simple/standard/complex) -5. Acceptance criteria for resolving this issue`; - - // Create proper spec directory - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - if (!existsSync(specsDir)) { - mkdirSync(specsDir, { recursive: true }); - } - - // Find next available spec number - let specNumber = 1; - const existingDirs = readdirSync(specsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => d.name); - const existingNumbers = existingDirs - .map(name => { - const match = name.match(/^(\d+)/); - return match ? parseInt(match[1], 10) : 0; - }) - .filter(n => n > 0); - if (existingNumbers.length > 0) { - specNumber = Math.max(...existingNumbers) + 1; - } - - // Create spec ID with zero-padded number and slugified title - const slugifiedTitle = issue.title - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-|-$/g, '') - .substring(0, 50); - const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`; - - // Create spec directory - const specDir = path.join(specsDir, specId); - mkdirSync(specDir, { recursive: true }); - - // Create initial implementation_plan.json - const now = new Date().toISOString(); - const implementationPlan = { - feature: issue.title, - description: taskDescription, - created_at: now, - updated_at: now, - status: 'pending', - phases: [] - }; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2)); - - // Create requirements.json - const requirements = { - task_description: taskDescription, - workflow_type: 'feature' - }; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2)); - - // Build metadata - const metadata: TaskMetadata = { - sourceType: 'github', - githubIssueNumber: issue.number, - githubUrl: issue.html_url, - category: 'feature' - }; - writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2)); - - // Start spec creation with the existing spec directory - agentManager.startSpecCreation(specId, project.path, taskDescription, specDir, metadata); - - // Send progress update: creating task - mainWindow.webContents.send( - IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS, - projectId, - { - phase: 'creating_task', - issueNumber, - progress: 70, - message: 'Creating task from investigation...' - } as GitHubInvestigationStatus - ); - - const investigationResult: GitHubInvestigationResult = { - success: true, - issueNumber, - analysis: { - summary: `Investigation of issue #${issueNumber}: ${issue.title}`, - proposedSolution: 'Task has been created for AI agent to implement the solution.', - affectedFiles: [], - estimatedComplexity: 'standard', - acceptanceCriteria: [ - `Issue #${issueNumber} requirements are met`, - 'All existing tests pass', - 'New functionality is tested' - ] - }, - taskId: specId - }; - - // Send completion - mainWindow.webContents.send( - IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS, - projectId, - { - phase: 'complete', - issueNumber, - progress: 100, - message: 'Investigation complete!' - } as GitHubInvestigationStatus - ); - - mainWindow.webContents.send( - IPC_CHANNELS.GITHUB_INVESTIGATION_COMPLETE, - projectId, - investigationResult - ); - - } catch (error) { - mainWindow.webContents.send( - IPC_CHANNELS.GITHUB_INVESTIGATION_ERROR, - projectId, - error instanceof Error ? error.message : 'Failed to investigate issue' - ); - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.GITHUB_IMPORT_ISSUES, - async (_, projectId: string, issueNumbers: number[]): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const config = getGitHubConfig(project); - if (!config) { - return { success: false, error: 'No GitHub token or repository configured' }; - } - - let imported = 0; - let failed = 0; - const errors: string[] = []; - const tasks: Task[] = []; - - // Set up specs directory - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - if (!existsSync(specsDir)) { - mkdirSync(specsDir, { recursive: true }); - } - - for (const issueNumber of issueNumbers) { - try { - const issue = await githubFetch( - config.token, - `/repos/${config.repo}/issues/${issueNumber}` - ) as { - number: number; - title: string; - body?: string; - labels: Array<{ name: string }>; - html_url: string; - }; - - const labels = issue.labels.map(l => l.name).join(', '); - const description = `# ${issue.title} - -**GitHub Issue:** [#${issue.number}](${issue.html_url}) -${labels ? `**Labels:** ${labels}` : ''} - -## Description - -${issue.body || 'No description provided.'} -`; - - // Find next available spec number - let specNumber = 1; - const existingDirs = readdirSync(specsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => d.name); - const existingNumbers = existingDirs - .map(name => { - const match = name.match(/^(\d+)/); - return match ? parseInt(match[1], 10) : 0; - }) - .filter(n => n > 0); - if (existingNumbers.length > 0) { - specNumber = Math.max(...existingNumbers) + 1; - } - - // Create spec ID with zero-padded number and slugified title - const slugifiedTitle = issue.title - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-|-$/g, '') - .substring(0, 50); - const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`; - - // Create spec directory - const specDir = path.join(specsDir, specId); - mkdirSync(specDir, { recursive: true }); - - // Create initial implementation_plan.json - const now = new Date().toISOString(); - const implementationPlan = { - feature: issue.title, - description: description, - created_at: now, - updated_at: now, - status: 'pending', - phases: [] - }; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2)); - - // Create requirements.json - const requirements = { - task_description: description, - workflow_type: 'feature' - }; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2)); - - // Build metadata - const metadata: TaskMetadata = { - sourceType: 'github', - githubIssueNumber: issue.number, - githubUrl: issue.html_url, - category: 'feature' - }; - writeFileSync(path.join(specDir, 'task_metadata.json'), JSON.stringify(metadata, null, 2)); - - // Start spec creation with the existing spec directory - agentManager.startSpecCreation(specId, project.path, description, specDir, metadata); - imported++; - } catch (err) { - failed++; - errors.push(`Failed to import #${issueNumber}: ${err instanceof Error ? err.message : 'Unknown error'}`); - } - } - - return { - success: true, - data: { - success: failed === 0, - imported, - failed, - errors: errors.length > 0 ? errors : undefined, - tasks - } - }; - } - ); - - /** - * Create a GitHub release using the gh CLI - */ - ipcMain.handle( - IPC_CHANNELS.GITHUB_CREATE_RELEASE, - async ( - _, - projectId: string, - version: string, - releaseNotes: string, - options?: { draft?: boolean; prerelease?: boolean } - ): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - // Check if gh CLI is available - // Use 'where' on Windows, 'which' on Unix - try { - const checkCmd = process.platform === 'win32' ? 'where gh' : 'which gh'; - execSync(checkCmd, { encoding: 'utf-8', stdio: 'pipe' }); - } catch { - return { - success: false, - error: 'GitHub CLI (gh) not found. Please install it: https://cli.github.com/' - }; - } - - // Check if user is authenticated - try { - execSync('gh auth status', { cwd: project.path, encoding: 'utf-8', stdio: 'pipe' }); - } catch { - return { - success: false, - error: 'Not authenticated with GitHub. Run "gh auth login" in terminal first.' - }; - } - - // Prepare tag name (ensure v prefix) - const tag = version.startsWith('v') ? version : `v${version}`; - - // Build gh release command - const args = ['release', 'create', tag, '--title', tag, '--notes', releaseNotes]; - if (options?.draft) args.push('--draft'); - if (options?.prerelease) args.push('--prerelease'); - - // Create the release - const output = execSync(`gh ${args.map(a => `"${a.replace(/"/g, '\\"')}"`).join(' ')}`, { - cwd: project.path, - encoding: 'utf-8', - stdio: 'pipe' - }).trim(); - - // Output is typically the release URL - const releaseUrl = output || `https://github.com/releases/tag/${tag}`; - - return { - success: true, - data: { url: releaseUrl } - }; - } catch (error) { - const errorMsg = error instanceof Error ? error.message : 'Failed to create release'; - // Try to extract more useful error message from stderr - if (error && typeof error === 'object' && 'stderr' in error) { - return { success: false, error: String(error.stderr) || errorMsg }; - } - return { success: false, error: errorMsg }; - } - } - ); - - // ============================================ - // Auto Claude Source Update Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.AUTOBUILD_SOURCE_CHECK, - async (): Promise> => { - try { - const result = await checkSourceUpdates(); - return { success: true, data: result }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to check for updates' - }; - } - } - ); - - ipcMain.on( - IPC_CHANNELS.AUTOBUILD_SOURCE_DOWNLOAD, - () => { - const mainWindow = getMainWindow(); - if (!mainWindow) return; - - // Start download in background - downloadAndApplyUpdate((progress) => { - mainWindow.webContents.send( - IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS, - progress - ); - }).then((result) => { - if (result.success) { - mainWindow.webContents.send( - IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS, - { - stage: 'complete', - message: `Updated to version ${result.version}` - } as AutoBuildSourceUpdateProgress - ); - } else { - mainWindow.webContents.send( - IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS, - { - stage: 'error', - message: result.error || 'Update failed' - } as AutoBuildSourceUpdateProgress - ); - } - }).catch((error) => { - mainWindow.webContents.send( - IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS, - { - stage: 'error', - message: error instanceof Error ? error.message : 'Update failed' - } as AutoBuildSourceUpdateProgress - ); - }); - - // Send initial progress - mainWindow.webContents.send( - IPC_CHANNELS.AUTOBUILD_SOURCE_PROGRESS, - { - stage: 'checking', - message: 'Starting update...' - } as AutoBuildSourceUpdateProgress - ); - } - ); - - ipcMain.handle( - IPC_CHANNELS.AUTOBUILD_SOURCE_VERSION, - async (): Promise> => { - try { - const version = getBundledVersion(); - return { success: true, data: version }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get version' - }; - } - } - ); - - // ============================================ - // Auto Claude Source Environment Operations - // ============================================ - - /** - * Parse an .env file content into a key-value object - */ - const parseSourceEnvFile = (content: string): Record => { - const vars: Record = {}; - for (const line of content.split('\n')) { - const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith('#')) continue; - - const eqIndex = trimmed.indexOf('='); - if (eqIndex > 0) { - const key = trimmed.substring(0, eqIndex).trim(); - let value = trimmed.substring(eqIndex + 1).trim(); - // Remove quotes if present - if ((value.startsWith('"') && value.endsWith('"')) || - (value.startsWith("'") && value.endsWith("'"))) { - value = value.slice(1, -1); - } - vars[key] = value; - } - } - return vars; - }; - - ipcMain.handle( - IPC_CHANNELS.AUTOBUILD_SOURCE_ENV_GET, - async (): Promise> => { - try { - const sourcePath = getEffectiveSourcePath(); - if (!sourcePath) { - return { - success: true, - data: { - hasClaudeToken: false, - envExists: false, - sourcePath: undefined - } - }; - } - - const envPath = path.join(sourcePath, '.env'); - const envExists = existsSync(envPath); - - if (!envExists) { - return { - success: true, - data: { - hasClaudeToken: false, - envExists: false, - sourcePath - } - }; - } - - const content = readFileSync(envPath, 'utf-8'); - const vars = parseSourceEnvFile(content); - const hasToken = !!vars['CLAUDE_CODE_OAUTH_TOKEN']; - - return { - success: true, - data: { - hasClaudeToken: hasToken, - claudeOAuthToken: hasToken ? vars['CLAUDE_CODE_OAUTH_TOKEN'] : undefined, - envExists: true, - sourcePath - } - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get source env' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.AUTOBUILD_SOURCE_ENV_UPDATE, - async (_, config: { claudeOAuthToken?: string }): Promise => { - try { - const sourcePath = getEffectiveSourcePath(); - if (!sourcePath) { - return { - success: false, - error: 'Auto-Claude source path not found. Please configure it in App Settings.' - }; - } - - const envPath = path.join(sourcePath, '.env'); - - // Read existing content or start fresh - let existingContent = ''; - const existingVars: Record = {}; - - if (existsSync(envPath)) { - existingContent = readFileSync(envPath, 'utf-8'); - Object.assign(existingVars, parseSourceEnvFile(existingContent)); - } - - // Update the token - if (config.claudeOAuthToken !== undefined) { - existingVars['CLAUDE_CODE_OAUTH_TOKEN'] = config.claudeOAuthToken; - } - - // Rebuild the .env file preserving comments and structure - const lines = existingContent.split('\n'); - const processedKeys = new Set(); - const outputLines: string[] = []; - - for (const line of lines) { - const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith('#')) { - outputLines.push(line); - continue; - } - - const eqIndex = trimmed.indexOf('='); - if (eqIndex > 0) { - const key = trimmed.substring(0, eqIndex).trim(); - if (key in existingVars) { - outputLines.push(`${key}=${existingVars[key]}`); - processedKeys.add(key); - } else { - outputLines.push(line); - } - } else { - outputLines.push(line); - } - } - - // Add any new keys that weren't in the original file - for (const [key, value] of Object.entries(existingVars)) { - if (!processedKeys.has(key)) { - outputLines.push(`${key}=${value}`); - } - } - - writeFileSync(envPath, outputLines.join('\n')); - - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update source env' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.AUTOBUILD_SOURCE_ENV_CHECK_TOKEN, - async (): Promise> => { - try { - const sourcePath = getEffectiveSourcePath(); - if (!sourcePath) { - return { - success: true, - data: { - hasToken: false, - sourcePath: undefined, - error: 'Auto-Claude source path not found' - } - }; - } - - const envPath = path.join(sourcePath, '.env'); - if (!existsSync(envPath)) { - return { - success: true, - data: { - hasToken: false, - sourcePath, - error: '.env file does not exist' - } - }; - } - - const content = readFileSync(envPath, 'utf-8'); - const vars = parseSourceEnvFile(content); - const hasToken = !!vars['CLAUDE_CODE_OAUTH_TOKEN'] && vars['CLAUDE_CODE_OAUTH_TOKEN'].length > 0; - - return { - success: true, - data: { - hasToken, - sourcePath - } - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to check source token' - }; - } - } - ); - - // ============================================ - // Ideation Operations - // ============================================ - - /** - * Transform an idea from snake_case (Python backend) to camelCase (TypeScript frontend) - */ - const transformIdeaFromSnakeCase = (idea: Record) => { - const base = { - id: idea.id as string, - type: idea.type as string, - title: idea.title as string, - description: idea.description as string, - rationale: idea.rationale as string, - status: idea.status as string || 'draft', - createdAt: idea.created_at ? new Date(idea.created_at as string) : new Date() - }; - - if (idea.type === 'code_improvements') { - return { - ...base, - buildsUpon: idea.builds_upon || idea.buildsUpon || [], - estimatedEffort: idea.estimated_effort || idea.estimatedEffort || 'small', - affectedFiles: idea.affected_files || idea.affectedFiles || [], - existingPatterns: idea.existing_patterns || idea.existingPatterns || [], - implementationApproach: idea.implementation_approach || idea.implementationApproach || '' - }; - } else if (idea.type === 'ui_ux_improvements') { - return { - ...base, - category: idea.category || 'usability', - affectedComponents: idea.affected_components || idea.affectedComponents || [], - screenshots: idea.screenshots || [], - currentState: idea.current_state || idea.currentState || '', - proposedChange: idea.proposed_change || idea.proposedChange || '', - userBenefit: idea.user_benefit || idea.userBenefit || '' - }; - } else if (idea.type === 'documentation_gaps') { - return { - ...base, - category: idea.category || 'readme', - targetAudience: idea.target_audience || idea.targetAudience || 'developers', - affectedAreas: idea.affected_areas || idea.affectedAreas || [], - currentDocumentation: idea.current_documentation || idea.currentDocumentation || '', - proposedContent: idea.proposed_content || idea.proposedContent || '', - priority: idea.priority || 'medium', - estimatedEffort: idea.estimated_effort || idea.estimatedEffort || 'small' - }; - } else if (idea.type === 'security_hardening') { - return { - ...base, - category: idea.category || 'configuration', - severity: idea.severity || 'medium', - affectedFiles: idea.affected_files || idea.affectedFiles || [], - vulnerability: idea.vulnerability || '', - currentRisk: idea.current_risk || idea.currentRisk || '', - remediation: idea.remediation || '', - references: idea.references || [], - compliance: idea.compliance || [] - }; - } else if (idea.type === 'performance_optimizations') { - return { - ...base, - category: idea.category || 'runtime', - impact: idea.impact || 'medium', - affectedAreas: idea.affected_areas || idea.affectedAreas || [], - currentMetric: idea.current_metric || idea.currentMetric || '', - expectedImprovement: idea.expected_improvement || idea.expectedImprovement || '', - implementation: idea.implementation || '', - tradeoffs: idea.tradeoffs || '', - estimatedEffort: idea.estimated_effort || idea.estimatedEffort || 'medium' - }; - } else if (idea.type === 'code_quality') { - return { - ...base, - category: idea.category || 'code_smells', - severity: idea.severity || 'minor', - affectedFiles: idea.affected_files || idea.affectedFiles || [], - currentState: idea.current_state || idea.currentState || '', - proposedChange: idea.proposed_change || idea.proposedChange || '', - codeExample: idea.code_example || idea.codeExample || '', - bestPractice: idea.best_practice || idea.bestPractice || '', - metrics: idea.metrics || {}, - estimatedEffort: idea.estimated_effort || idea.estimatedEffort || 'medium', - breakingChange: idea.breaking_change ?? idea.breakingChange ?? false, - prerequisites: idea.prerequisites || [] - }; - } - - return base; - }; - - ipcMain.handle( - IPC_CHANNELS.IDEATION_GET, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const ideationPath = path.join( - project.path, - AUTO_BUILD_PATHS.IDEATION_DIR, - AUTO_BUILD_PATHS.IDEATION_FILE - ); - - if (!existsSync(ideationPath)) { - return { success: true, data: null }; - } - - try { - const content = readFileSync(ideationPath, 'utf-8'); - const rawIdeation = JSON.parse(content); - - // Transform snake_case to camelCase for frontend - const session: IdeationSession = { - id: rawIdeation.id || `ideation-${Date.now()}`, - projectId, - config: { - enabledTypes: rawIdeation.config?.enabled_types || rawIdeation.config?.enabledTypes || [], - includeRoadmapContext: rawIdeation.config?.include_roadmap_context ?? rawIdeation.config?.includeRoadmapContext ?? true, - includeKanbanContext: rawIdeation.config?.include_kanban_context ?? rawIdeation.config?.includeKanbanContext ?? true, - maxIdeasPerType: rawIdeation.config?.max_ideas_per_type || rawIdeation.config?.maxIdeasPerType || 5 - }, - ideas: (rawIdeation.ideas || []).map((idea: Record) => - transformIdeaFromSnakeCase(idea) - ), - projectContext: { - existingFeatures: rawIdeation.project_context?.existing_features || rawIdeation.projectContext?.existingFeatures || [], - techStack: rawIdeation.project_context?.tech_stack || rawIdeation.projectContext?.techStack || [], - targetAudience: rawIdeation.project_context?.target_audience || rawIdeation.projectContext?.targetAudience, - plannedFeatures: rawIdeation.project_context?.planned_features || rawIdeation.projectContext?.plannedFeatures || [] - }, - generatedAt: rawIdeation.generated_at ? new Date(rawIdeation.generated_at) : new Date(), - updatedAt: rawIdeation.updated_at ? new Date(rawIdeation.updated_at) : new Date() - }; - - return { success: true, data: session }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to read ideation' - }; - } - } - ); - - ipcMain.on( - IPC_CHANNELS.IDEATION_GENERATE, - (_, projectId: string, config: IdeationConfig) => { - const mainWindow = getMainWindow(); - if (!mainWindow) return; - - const project = projectStore.getProject(projectId); - if (!project) { - mainWindow.webContents.send( - IPC_CHANNELS.IDEATION_ERROR, - projectId, - 'Project not found' - ); - return; - } - - // Start ideation generation via agent manager - agentManager.startIdeationGeneration(projectId, project.path, config, false); - - // Send initial progress - mainWindow.webContents.send( - IPC_CHANNELS.IDEATION_PROGRESS, - projectId, - { - phase: 'analyzing', - progress: 10, - message: 'Analyzing project structure...' - } as IdeationGenerationStatus - ); - } - ); - - ipcMain.on( - IPC_CHANNELS.IDEATION_REFRESH, - (_, projectId: string, config: IdeationConfig) => { - const mainWindow = getMainWindow(); - if (!mainWindow) return; - - const project = projectStore.getProject(projectId); - if (!project) { - mainWindow.webContents.send( - IPC_CHANNELS.IDEATION_ERROR, - projectId, - 'Project not found' - ); - return; - } - - // Start ideation regeneration with refresh flag - agentManager.startIdeationGeneration(projectId, project.path, config, true); - - // Send initial progress - mainWindow.webContents.send( - IPC_CHANNELS.IDEATION_PROGRESS, - projectId, - { - phase: 'analyzing', - progress: 10, - message: 'Refreshing ideation...' - } as IdeationGenerationStatus - ); - } - ); - - // Stop ideation generation - ipcMain.handle( - IPC_CHANNELS.IDEATION_STOP, - async (_, projectId: string): Promise => { - const mainWindow = getMainWindow(); - const wasStopped = agentManager.stopIdeation(projectId); - - if (wasStopped && mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.IDEATION_STOPPED, projectId); - } - - return { success: wasStopped }; - } - ); - - // Dismiss all ideas - ipcMain.handle( - IPC_CHANNELS.IDEATION_DISMISS_ALL, - async (_, projectId: string): Promise => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const ideationPath = path.join( - project.path, - AUTO_BUILD_PATHS.IDEATION_DIR, - AUTO_BUILD_PATHS.IDEATION_FILE - ); - - if (!existsSync(ideationPath)) { - return { success: false, error: 'Ideation not found' }; - } - - try { - const content = readFileSync(ideationPath, 'utf-8'); - const ideation = JSON.parse(content); - - // Dismiss all ideas that are not already dismissed or converted - let dismissedCount = 0; - ideation.ideas?.forEach((idea: { status: string }) => { - if (idea.status !== 'dismissed' && idea.status !== 'converted') { - idea.status = 'dismissed'; - dismissedCount++; - } - }); - ideation.updated_at = new Date().toISOString(); - - writeFileSync(ideationPath, JSON.stringify(ideation, null, 2)); - - return { success: true, data: { dismissedCount } }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to dismiss all ideas' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.IDEATION_UPDATE_IDEA, - async ( - _, - projectId: string, - ideaId: string, - status: IdeationStatus - ): Promise => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const ideationPath = path.join( - project.path, - AUTO_BUILD_PATHS.IDEATION_DIR, - AUTO_BUILD_PATHS.IDEATION_FILE - ); - - if (!existsSync(ideationPath)) { - return { success: false, error: 'Ideation not found' }; - } - - try { - const content = readFileSync(ideationPath, 'utf-8'); - const ideation = JSON.parse(content); - - // Find and update the idea - const idea = ideation.ideas?.find((i: { id: string }) => i.id === ideaId); - if (!idea) { - return { success: false, error: 'Idea not found' }; - } - - idea.status = status; - ideation.updated_at = new Date().toISOString(); - - writeFileSync(ideationPath, JSON.stringify(ideation, null, 2)); - - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update idea' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.IDEATION_DISMISS, - async (_, projectId: string, ideaId: string): Promise => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const ideationPath = path.join( - project.path, - AUTO_BUILD_PATHS.IDEATION_DIR, - AUTO_BUILD_PATHS.IDEATION_FILE - ); - - if (!existsSync(ideationPath)) { - return { success: false, error: 'Ideation not found' }; - } - - try { - const content = readFileSync(ideationPath, 'utf-8'); - const ideation = JSON.parse(content); - - // Find and dismiss the idea - const idea = ideation.ideas?.find((i: { id: string }) => i.id === ideaId); - if (!idea) { - return { success: false, error: 'Idea not found' }; - } - - idea.status = 'dismissed'; - ideation.updated_at = new Date().toISOString(); - - writeFileSync(ideationPath, JSON.stringify(ideation, null, 2)); - - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to dismiss idea' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.IDEATION_CONVERT_TO_TASK, - async (_, projectId: string, ideaId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const ideationPath = path.join( - project.path, - AUTO_BUILD_PATHS.IDEATION_DIR, - AUTO_BUILD_PATHS.IDEATION_FILE - ); - - if (!existsSync(ideationPath)) { - return { success: false, error: 'Ideation not found' }; - } - - try { - const content = readFileSync(ideationPath, 'utf-8'); - const ideation = JSON.parse(content); - - // Find the idea - const idea = ideation.ideas?.find((i: { id: string }) => i.id === ideaId); - if (!idea) { - return { success: false, error: 'Idea not found' }; - } - - // Generate spec ID by finding next available number - // Get specs directory path - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - - // Ensure specs directory exists - if (!existsSync(specsDir)) { - mkdirSync(specsDir, { recursive: true }); - } - - // Find next spec number - let nextNum = 1; - try { - const existingSpecs = readdirSync(specsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => { - const match = d.name.match(/^(\d+)-/); - return match ? parseInt(match[1], 10) : 0; - }) - .filter(n => n > 0); - if (existingSpecs.length > 0) { - nextNum = Math.max(...existingSpecs) + 1; - } - } catch { - // Use default 1 - } - - // Create spec directory name from idea title - const slugifiedTitle = idea.title - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-|-$/g, '') - .substring(0, 50); - const specId = `${String(nextNum).padStart(3, '0')}-${slugifiedTitle}`; - const specDir = path.join(specsDir, specId); - - // Create the spec directory - mkdirSync(specDir, { recursive: true }); - - // Build task description based on idea type - let taskDescription = `# ${idea.title}\n\n`; - taskDescription += `${idea.description}\n\n`; - taskDescription += `## Rationale\n${idea.rationale}\n\n`; - - // Note: high_value_features removed - strategic features belong to Roadmap - // low_hanging_fruit renamed to code_improvements - if (idea.type === 'code_improvements') { - if (idea.builds_upon?.length) { - taskDescription += `## Builds Upon\n${idea.builds_upon.map((b: string) => `- ${b}`).join('\n')}\n\n`; - } - if (idea.implementation_approach) { - taskDescription += `## Implementation Approach\n${idea.implementation_approach}\n\n`; - } - if (idea.affected_files?.length) { - taskDescription += `## Affected Files\n${idea.affected_files.map((f: string) => `- ${f}`).join('\n')}\n\n`; - } - if (idea.existing_patterns?.length) { - taskDescription += `## Patterns to Follow\n${idea.existing_patterns.map((p: string) => `- ${p}`).join('\n')}\n\n`; - } - } else if (idea.type === 'ui_ux_improvements') { - taskDescription += `## Category\n${idea.category}\n\n`; - taskDescription += `## Current State\n${idea.current_state}\n\n`; - taskDescription += `## Proposed Change\n${idea.proposed_change}\n\n`; - taskDescription += `## User Benefit\n${idea.user_benefit}\n\n`; - if (idea.affected_components?.length) { - taskDescription += `## Affected Components\n${idea.affected_components.map((c: string) => `- ${c}`).join('\n')}\n\n`; - } - } - - // Create initial implementation_plan.json so task shows in kanban immediately - const initialPlan: ImplementationPlan = { - feature: idea.title, - description: idea.description, - created_at: new Date().toISOString(), - updated_at: new Date().toISOString(), - status: 'backlog', - planStatus: 'pending', - phases: [], - workflow_type: 'development', - services_involved: [], - final_acceptance: [], - spec_file: 'spec.md' - }; - writeFileSync( - path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), - JSON.stringify(initialPlan, null, 2) - ); - - // Create initial spec.md with the task description - const specContent = `# ${idea.title} - -## Overview - -${idea.description} - -## Rationale - -${idea.rationale} - ---- -*This spec was created from ideation and is pending detailed specification.* -`; - writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE), specContent); - - // Update idea with converted status - idea.status = 'converted'; - idea.linked_task_id = specId; - ideation.updated_at = new Date().toISOString(); - writeFileSync(ideationPath, JSON.stringify(ideation, null, 2)); - - // Build metadata from idea type - const metadata: TaskMetadata = { - sourceType: 'ideation', - ideationType: idea.type, - ideaId: idea.id, - rationale: idea.rationale - }; - - // Map idea type to task category - // Note: high_value_features removed, low_hanging_fruit renamed to code_improvements - const ideaTypeToCategory: Record = { - 'code_improvements': 'feature', - 'ui_ux_improvements': 'ui_ux', - 'documentation_gaps': 'documentation', - 'security_hardening': 'security', - 'performance_optimizations': 'performance', - 'code_quality': 'refactoring' - }; - metadata.category = ideaTypeToCategory[idea.type] || 'feature'; - - // Extract type-specific metadata - // Note: high_value_features removed - strategic features belong to Roadmap - // low_hanging_fruit renamed to code_improvements - if (idea.type === 'code_improvements') { - metadata.estimatedEffort = idea.estimated_effort; - metadata.complexity = idea.estimated_effort; // trivial/small/medium/large/complex - metadata.affectedFiles = idea.affected_files; - } else if (idea.type === 'ui_ux_improvements') { - metadata.uiuxCategory = idea.category; - metadata.affectedFiles = idea.affected_components; - metadata.problemSolved = idea.current_state; - } else if (idea.type === 'documentation_gaps') { - metadata.estimatedEffort = idea.estimated_effort; - metadata.priority = idea.priority; - metadata.targetAudience = idea.target_audience; - metadata.affectedFiles = idea.affected_areas; - } else if (idea.type === 'security_hardening') { - metadata.securitySeverity = idea.severity; - metadata.impact = idea.severity as TaskImpact; // Map severity to impact - metadata.priority = idea.severity === 'critical' ? 'urgent' : idea.severity === 'high' ? 'high' : 'medium'; - metadata.affectedFiles = idea.affected_files; - } else if (idea.type === 'performance_optimizations') { - metadata.performanceCategory = idea.category; - metadata.impact = idea.impact as TaskImpact; - metadata.estimatedEffort = idea.estimated_effort; - metadata.affectedFiles = idea.affected_areas; - } else if (idea.type === 'code_quality') { - metadata.codeQualitySeverity = idea.severity; - metadata.estimatedEffort = idea.estimated_effort; - metadata.affectedFiles = idea.affected_files; - metadata.priority = idea.severity === 'critical' ? 'urgent' : idea.severity === 'major' ? 'high' : 'medium'; - } - - // Save metadata to a separate file for persistence - const metadataPath = path.join(specDir, 'task_metadata.json'); - writeFileSync(metadataPath, JSON.stringify(metadata, null, 2)); - - // Task is created in Planning (backlog) - user must manually start it - // Previously auto-started spec creation here, but user should control when to start - - // Create task object to return - const task: Task = { - id: specId, - specId: specId, - projectId, - title: idea.title, - description: taskDescription, - status: 'backlog', - subtasks: [], - logs: [], - metadata, - createdAt: new Date(), - updatedAt: new Date() - }; - - return { success: true, data: task }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to convert idea to task' - }; - } - } - ); - - // ============================================ - // Ideation Agent Events → Renderer - // ============================================ - - agentManager.on('ideation-progress', (projectId: string, status: IdeationGenerationStatus) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.IDEATION_PROGRESS, projectId, status); - } - }); - - agentManager.on('ideation-log', (projectId: string, log: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.IDEATION_LOG, projectId, log); - } - }); - - agentManager.on('ideation-complete', (projectId: string, session: IdeationSession) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.IDEATION_COMPLETE, projectId, session); - } - }); - - agentManager.on('ideation-error', (projectId: string, error: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.IDEATION_ERROR, projectId, error); - } - }); - - agentManager.on('ideation-stopped', (projectId: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.IDEATION_STOPPED, projectId); - } - }); - - // Handle streaming ideation type completion - load ideas for this type immediately - agentManager.on('ideation-type-complete', (projectId: string, ideationType: string, ideasCount: number) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - // Read the type-specific ideas file and send to renderer - const project = projectStore.getProject(projectId); - if (project) { - const typeFile = path.join( - project.path, - AUTO_BUILD_PATHS.IDEATION_DIR, - `${ideationType}_ideas.json` - ); - if (existsSync(typeFile)) { - try { - const content = readFileSync(typeFile, 'utf-8'); - const data = JSON.parse(content); - const rawIdeas = data[ideationType] || []; - // Transform ideas from snake_case to camelCase - const ideas = rawIdeas.map((idea: Record) => transformIdeaFromSnakeCase(idea)); - mainWindow.webContents.send( - IPC_CHANNELS.IDEATION_TYPE_COMPLETE, - projectId, - ideationType, - ideas - ); - } catch (err) { - console.error(`[Ideation] Failed to read ${ideationType} ideas:`, err); - } - } - } - } - }); - - agentManager.on('ideation-type-failed', (projectId: string, ideationType: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.IDEATION_TYPE_FAILED, projectId, ideationType); - } - }); - - // ============================================ - // Changelog Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.CHANGELOG_GET_DONE_TASKS, - async (_, projectId: string, rendererTasks?: import('../shared/types').Task[]): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // Use renderer tasks if provided (they have the correct UI status), - // otherwise fall back to reading from filesystem - const tasks = rendererTasks || projectStore.getTasks(projectId); - - // Get specs directory path - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const doneTasks = changelogService.getCompletedTasks(project.path, tasks, specsBaseDir); - - return { success: true, data: doneTasks }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.CHANGELOG_LOAD_TASK_SPECS, - async (_, projectId: string, taskIds: string[]): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const tasks = projectStore.getTasks(projectId); - - // Get specs directory path - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specs = await changelogService.loadTaskSpecs(project.path, taskIds, tasks, specsBaseDir); - - return { success: true, data: specs }; - } - ); - - ipcMain.on( - IPC_CHANNELS.CHANGELOG_GENERATE, - async (_, request: import('../shared/types').ChangelogGenerationRequest) => { - const mainWindow = getMainWindow(); - if (!mainWindow) return; - - const project = projectStore.getProject(request.projectId); - if (!project) { - mainWindow.webContents.send( - IPC_CHANNELS.CHANGELOG_GENERATION_ERROR, - request.projectId, - 'Project not found' - ); - return; - } - - // Load specs for selected tasks (only in tasks mode) - let specs: import('../shared/types').TaskSpecContent[] = []; - if (request.sourceMode === 'tasks' && request.taskIds && request.taskIds.length > 0) { - const tasks = projectStore.getTasks(request.projectId); - const specsBaseDir = getSpecsDir(project.autoBuildPath); - specs = await changelogService.loadTaskSpecs(project.path, request.taskIds, tasks, specsBaseDir); - } - - // Start generation - changelogService.generateChangelog(request.projectId, project.path, request, specs); - } - ); - - ipcMain.handle( - IPC_CHANNELS.CHANGELOG_SAVE, - async (_, request: import('../shared/types').ChangelogSaveRequest): Promise> => { - const project = projectStore.getProject(request.projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - const result = changelogService.saveChangelog(project.path, request); - return { success: true, data: result }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to save changelog' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CHANGELOG_READ_EXISTING, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const result = changelogService.readExistingChangelog(project.path); - return { success: true, data: result }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.CHANGELOG_SUGGEST_VERSION, - async (_, projectId: string, taskIds: string[]): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - // Get current version from existing changelog - const existing = changelogService.readExistingChangelog(project.path); - const currentVersion = existing.lastVersion; - - // Load specs for selected tasks to analyze change types - const tasks = projectStore.getTasks(projectId); - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specs = await changelogService.loadTaskSpecs(project.path, taskIds, tasks, specsBaseDir); - - // Analyze specs and suggest version - const suggestedVersion = changelogService.suggestVersion(specs, currentVersion); - - // Determine reason for the suggestion - let reason = 'patch'; - if (currentVersion) { - const [oldMajor, oldMinor] = currentVersion.split('.').map(Number); - const [newMajor, newMinor] = suggestedVersion.split('.').map(Number); - if (newMajor > oldMajor) { - reason = 'breaking'; - } else if (newMinor > oldMinor) { - reason = 'feature'; - } - } - - return { - success: true, - data: { version: suggestedVersion, reason } - }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to suggest version' - }; - } - } - ); - - // ============================================ - // Changelog Git Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.CHANGELOG_GET_BRANCHES, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - const branches = changelogService.getBranches(project.path); - return { success: true, data: branches }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get branches' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CHANGELOG_GET_TAGS, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - const tags = changelogService.getTags(project.path); - return { success: true, data: tags }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get tags' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.CHANGELOG_GET_COMMITS_PREVIEW, - async ( - _, - projectId: string, - options: import('../shared/types').GitHistoryOptions | import('../shared/types').BranchDiffOptions, - mode: 'git-history' | 'branch-diff' - ): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - try { - let commits: import('../shared/types').GitCommit[]; - - if (mode === 'git-history') { - commits = changelogService.getCommits( - project.path, - options as import('../shared/types').GitHistoryOptions - ); - } else { - commits = changelogService.getBranchDiffCommits( - project.path, - options as import('../shared/types').BranchDiffOptions - ); - } - - return { success: true, data: commits }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get commits preview' - }; - } - } - ); - - // ============================================ - // Changelog Agent Events → Renderer - // ============================================ - - changelogService.on('generation-progress', (projectId: string, progress: import('../shared/types').ChangelogGenerationProgress) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.CHANGELOG_GENERATION_PROGRESS, projectId, progress); - } - }); - - changelogService.on('generation-complete', (projectId: string, result: import('../shared/types').ChangelogGenerationResult) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.CHANGELOG_GENERATION_COMPLETE, projectId, result); - } - }); - - changelogService.on('generation-error', (projectId: string, error: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.CHANGELOG_GENERATION_ERROR, projectId, error); - } - }); - - changelogService.on('rate-limit', (projectId: string, rateLimitInfo: import('../shared/types').SDKRateLimitInfo) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo); - } - }); - - // ============================================ - // Insights Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.INSIGHTS_GET_SESSION, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const session = insightsService.loadSession(projectId, project.path); - return { success: true, data: session }; - } - ); - - ipcMain.on( - IPC_CHANNELS.INSIGHTS_SEND_MESSAGE, - async (_, projectId: string, message: string) => { - const project = projectStore.getProject(projectId); - if (!project) { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_ERROR, projectId, 'Project not found'); - } - return; - } - - // Ensure Python environment is ready before sending message - if (!pythonEnvManager.isEnvReady()) { - const autoBuildSource = getAutoBuildSourcePath(); - if (autoBuildSource) { - const status = await pythonEnvManager.initialize(autoBuildSource); - if (status.ready && status.pythonPath) { - configureServicesWithPython(status.pythonPath, autoBuildSource); - } else { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.INSIGHTS_ERROR, - projectId, - status.error || 'Python environment not ready' - ); - } - return; - } - } - } - - insightsService.sendMessage(projectId, project.path, message); - } - ); - - ipcMain.handle( - IPC_CHANNELS.INSIGHTS_CLEAR_SESSION, - async (_, projectId: string): Promise => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - insightsService.clearSession(projectId, project.path); - return { success: true }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.INSIGHTS_CREATE_TASK, - async ( - _, - projectId: string, - title: string, - description: string, - metadata?: TaskMetadata - ): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - if (!project.autoBuildPath) { - return { success: false, error: 'Auto Claude not initialized for this project' }; - } - - try { - // Generate a unique spec ID based on existing specs - // Get specs directory path - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - - // Find next available spec number - let specNumber = 1; - if (existsSync(specsDir)) { - const existingDirs = readdirSync(specsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => d.name); - - const existingNumbers = existingDirs - .map(name => { - const match = name.match(/^(\d+)/); - return match ? parseInt(match[1], 10) : 0; - }) - .filter(n => n > 0); - - if (existingNumbers.length > 0) { - specNumber = Math.max(...existingNumbers) + 1; - } - } - - // Create spec ID with zero-padded number and slugified title - const slugifiedTitle = title - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-|-$/g, '') - .substring(0, 50); - const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`; - - // Create spec directory - const specDir = path.join(specsDir, specId); - mkdirSync(specDir, { recursive: true }); - - // Build metadata with source type - const taskMetadata: TaskMetadata = { - sourceType: 'insights', - ...metadata - }; - - // Create initial implementation_plan.json - const now = new Date().toISOString(); - const implementationPlan = { - feature: title, - description: description, - created_at: now, - updated_at: now, - status: 'pending', - phases: [] - }; - - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - writeFileSync(planPath, JSON.stringify(implementationPlan, null, 2)); - - // Save task metadata - const metadataPath = path.join(specDir, 'task_metadata.json'); - writeFileSync(metadataPath, JSON.stringify(taskMetadata, null, 2)); - - // Create the task object - const task: Task = { - id: specId, - specId: specId, - projectId, - title, - description, - status: 'backlog', - subtasks: [], - logs: [], - metadata: taskMetadata, - createdAt: new Date(), - updatedAt: new Date() - }; - - return { success: true, data: task }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to create task' - }; - } - } - ); - - // List all sessions for a project - ipcMain.handle( - IPC_CHANNELS.INSIGHTS_LIST_SESSIONS, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const sessions = insightsService.listSessions(project.path); - return { success: true, data: sessions }; - } - ); - - // Create a new session - ipcMain.handle( - IPC_CHANNELS.INSIGHTS_NEW_SESSION, - async (_, projectId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const session = insightsService.createNewSession(projectId, project.path); - return { success: true, data: session }; - } - ); - - // Switch to a different session - ipcMain.handle( - IPC_CHANNELS.INSIGHTS_SWITCH_SESSION, - async (_, projectId: string, sessionId: string): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const session = insightsService.switchSession(projectId, project.path, sessionId); - return { success: true, data: session }; - } - ); - - // Delete a session - ipcMain.handle( - IPC_CHANNELS.INSIGHTS_DELETE_SESSION, - async (_, projectId: string, sessionId: string): Promise => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const success = insightsService.deleteSession(projectId, project.path, sessionId); - if (success) { - return { success: true }; - } - return { success: false, error: 'Failed to delete session' }; - } - ); - - // Rename a session - ipcMain.handle( - IPC_CHANNELS.INSIGHTS_RENAME_SESSION, - async (_, projectId: string, sessionId: string, newTitle: string): Promise => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const success = insightsService.renameSession(project.path, sessionId, newTitle); - if (success) { - return { success: true }; - } - return { success: false, error: 'Failed to rename session' }; - } - ); - - // ============================================ - // File Explorer Operations - // ============================================ - - // Directories to ignore when listing - const IGNORED_DIRS = new Set([ - 'node_modules', '.git', '__pycache__', 'dist', 'build', - '.next', '.nuxt', 'coverage', '.cache', '.venv', 'venv', - '.idea', '.vscode', 'out', '.turbo', '.auto-claude', - '.worktrees', 'vendor', 'target', '.gradle', '.maven' - ]); - - ipcMain.handle( - IPC_CHANNELS.FILE_EXPLORER_LIST, - async (_, dirPath: string): Promise> => { - try { - const entries = readdirSync(dirPath, { withFileTypes: true }); - - // Filter and map entries - const nodes: FileNode[] = []; - for (const entry of entries) { - // Skip hidden files (except .env which is often useful) - if (entry.name.startsWith('.') && entry.name !== '.env') continue; - // Skip ignored directories - if (entry.isDirectory() && IGNORED_DIRS.has(entry.name)) continue; - - nodes.push({ - path: path.join(dirPath, entry.name), - name: entry.name, - isDirectory: entry.isDirectory() - }); - } - - // Sort: directories first, then alphabetically - nodes.sort((a, b) => { - if (a.isDirectory && !b.isDirectory) return -1; - if (!a.isDirectory && b.isDirectory) return 1; - return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }); - }); - - return { success: true, data: nodes }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to read directory' - }; - } - } - ); - - // ============================================ - // Insights Agent Events → Renderer - // ============================================ - - insightsService.on('stream-chunk', (projectId: string, chunk: InsightsStreamChunk) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_STREAM_CHUNK, projectId, chunk); - } - }); - - insightsService.on('status', (projectId: string, status: InsightsChatStatus) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_STATUS, projectId, status); - } - }); - - insightsService.on('error', (projectId: string, error: string) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.INSIGHTS_ERROR, projectId, error); - } - }); - - // Handle SDK rate limit events from insights service - insightsService.on('sdk-rate-limit', (rateLimitInfo: import('../shared/types').SDKRateLimitInfo) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.CLAUDE_SDK_RATE_LIMIT, rateLimitInfo); - } - }); -} diff --git a/auto-claude-ui/src/main/ipc-handlers/docker-handlers.ts b/auto-claude-ui/src/main/ipc-handlers/docker-handlers.ts deleted file mode 100644 index 7d818a80..00000000 --- a/auto-claude-ui/src/main/ipc-handlers/docker-handlers.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Docker & Infrastructure IPC Handlers - * - * DEPRECATED: This file is kept for backward compatibility. - * Memory infrastructure has moved to LadybugDB (no Docker required). - * See memory-handlers.ts for the new implementation. - * - * This file now re-exports from memory-handlers.ts - */ - -import { registerMemoryHandlers } from './memory-handlers'; - -/** - * Register all Docker-related IPC handlers - * @deprecated Use registerMemoryHandlers() instead - */ -export function registerDockerHandlers(): void { - // Register the new memory handlers instead - registerMemoryHandlers(); -} diff --git a/auto-claude-ui/src/main/ipc-handlers/task-handlers.ts.backup b/auto-claude-ui/src/main/ipc-handlers/task-handlers.ts.backup deleted file mode 100644 index e4f1f7f4..00000000 --- a/auto-claude-ui/src/main/ipc-handlers/task-handlers.ts.backup +++ /dev/null @@ -1,1885 +0,0 @@ -import { ipcMain, BrowserWindow } from 'electron'; -import { IPC_CHANNELS, AUTO_BUILD_PATHS, getSpecsDir } from '../../shared/constants'; -import type { IPCResult, Task, TaskMetadata, TaskStartOptions, ImplementationPlan, TaskStatus, Project } from '../../shared/types'; -import path from 'path'; -import { existsSync, readFileSync, writeFileSync, readdirSync, mkdirSync, rmSync, statSync } from 'fs'; -import { execSync, spawn } from 'child_process'; -import { projectStore } from '../project-store'; -import { fileWatcher } from '../file-watcher'; -import { taskLogService } from '../task-log-service'; -import { titleGenerator } from '../title-generator'; -import { AgentManager } from '../agent'; -import { PythonEnvManager } from '../python-env-manager'; -import { getEffectiveSourcePath } from '../auto-claude-updater'; -import { getProfileEnv } from '../rate-limit-detector'; - - -/** - * Register all task-related IPC handlers - */ -export function registerTaskHandlers( - agentManager: AgentManager, - pythonEnvManager: PythonEnvManager, - getMainWindow: () => BrowserWindow | null -): void { - // ============================================ - // Task Operations - // ============================================ - - ipcMain.handle( - IPC_CHANNELS.TASK_LIST, - async (_, projectId: string): Promise> => { - console.log('[IPC] TASK_LIST called with projectId:', projectId); - const tasks = projectStore.getTasks(projectId); - console.log('[IPC] TASK_LIST returning', tasks.length, 'tasks'); - return { success: true, data: tasks }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_CREATE, - async ( - _, - projectId: string, - title: string, - description: string, - metadata?: TaskMetadata - ): Promise> => { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - // Auto-generate title if empty using Claude AI - let finalTitle = title; - if (!title || !title.trim()) { - console.log('[TASK_CREATE] Title is empty, generating with Claude AI...'); - try { - const generatedTitle = await titleGenerator.generateTitle(description); - if (generatedTitle) { - finalTitle = generatedTitle; - console.log('[TASK_CREATE] Generated title:', finalTitle); - } else { - // Fallback: create title from first line of description - finalTitle = description.split('\n')[0].substring(0, 60); - if (finalTitle.length === 60) finalTitle += '...'; - console.log('[TASK_CREATE] AI generation failed, using fallback:', finalTitle); - } - } catch (err) { - console.error('[TASK_CREATE] Title generation error:', err); - // Fallback: create title from first line of description - finalTitle = description.split('\n')[0].substring(0, 60); - if (finalTitle.length === 60) finalTitle += '...'; - } - } - - // Generate a unique spec ID based on existing specs - // Get specs directory path - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specsDir = path.join(project.path, specsBaseDir); - - // Find next available spec number - let specNumber = 1; - if (existsSync(specsDir)) { - const existingDirs = readdirSync(specsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()) - .map(d => d.name); - - // Extract numbers from spec directory names (e.g., "001-feature" -> 1) - const existingNumbers = existingDirs - .map(name => { - const match = name.match(/^(\d+)/); - return match ? parseInt(match[1], 10) : 0; - }) - .filter(n => n > 0); - - if (existingNumbers.length > 0) { - specNumber = Math.max(...existingNumbers) + 1; - } - } - - // Create spec ID with zero-padded number and slugified title - const slugifiedTitle = finalTitle - .toLowerCase() - .replace(/[^a-z0-9]+/g, '-') - .replace(/^-|-$/g, '') - .substring(0, 50); - const specId = `${String(specNumber).padStart(3, '0')}-${slugifiedTitle}`; - - // Create spec directory - const specDir = path.join(specsDir, specId); - mkdirSync(specDir, { recursive: true }); - - // Build metadata with source type - const taskMetadata: TaskMetadata = { - sourceType: 'manual', - ...metadata - }; - - // Process and save attached images - if (taskMetadata.attachedImages && taskMetadata.attachedImages.length > 0) { - const attachmentsDir = path.join(specDir, 'attachments'); - mkdirSync(attachmentsDir, { recursive: true }); - - const savedImages: typeof taskMetadata.attachedImages = []; - - for (const image of taskMetadata.attachedImages) { - if (image.data) { - try { - // Decode base64 and save to file - const buffer = Buffer.from(image.data, 'base64'); - const imagePath = path.join(attachmentsDir, image.filename); - writeFileSync(imagePath, buffer); - - // Store relative path instead of base64 data - savedImages.push({ - id: image.id, - filename: image.filename, - mimeType: image.mimeType, - size: image.size, - path: `attachments/${image.filename}` - // Don't include data or thumbnail to save space - }); - } catch (err) { - console.error(`Failed to save image ${image.filename}:`, err); - } - } - } - - // Update metadata with saved image paths (without base64 data) - taskMetadata.attachedImages = savedImages; - } - - // Create initial implementation_plan.json (task is created but not started) - const now = new Date().toISOString(); - const implementationPlan = { - feature: finalTitle, - description: description, - created_at: now, - updated_at: now, - status: 'pending', - phases: [] - }; - - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - writeFileSync(planPath, JSON.stringify(implementationPlan, null, 2)); - - // Save task metadata if provided - if (taskMetadata) { - const metadataPath = path.join(specDir, 'task_metadata.json'); - writeFileSync(metadataPath, JSON.stringify(taskMetadata, null, 2)); - } - - // Create requirements.json with attached images - const requirements: Record = { - task_description: description, - workflow_type: taskMetadata.category || 'feature' - }; - - // Add attached images to requirements if present - if (taskMetadata.attachedImages && taskMetadata.attachedImages.length > 0) { - requirements.attached_images = taskMetadata.attachedImages.map(img => ({ - filename: img.filename, - path: img.path, - description: '' // User can add descriptions later - })); - } - - const requirementsPath = path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS); - writeFileSync(requirementsPath, JSON.stringify(requirements, null, 2)); - - // Create the task object - const task: Task = { - id: specId, - specId: specId, - projectId, - title: finalTitle, - description, - status: 'backlog', - subtasks: [], - logs: [], - metadata: taskMetadata, - createdAt: new Date(), - updatedAt: new Date() - }; - - return { success: true, data: task }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_DELETE, - async (_, taskId: string): Promise => { - const { rm } = await import('fs/promises'); - - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task or project not found' }; - } - - // Check if task is currently running - const isRunning = agentManager.isRunning(taskId); - if (isRunning) { - return { success: false, error: 'Cannot delete a running task. Stop the task first.' }; - } - - // Delete the spec directory - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join(project.path, specsBaseDir, task.specId); - - try { - if (existsSync(specDir)) { - await rm(specDir, { recursive: true, force: true }); - console.log(`[TASK_DELETE] Deleted spec directory: ${specDir}`); - } - return { success: true }; - } catch (error) { - console.error('[TASK_DELETE] Error deleting spec directory:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to delete task files' - }; - } - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_UPDATE, - async ( - _, - taskId: string, - updates: { title?: string; description?: string; metadata?: Partial } - ): Promise> => { - try { - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - const autoBuildDir = project.autoBuildPath || '.auto-claude'; - const specDir = path.join(project.path, autoBuildDir, 'specs', task.specId); - - if (!existsSync(specDir)) { - return { success: false, error: 'Spec directory not found' }; - } - - // Auto-generate title if empty - let finalTitle = updates.title; - if (updates.title !== undefined && !updates.title.trim()) { - // Get description to use for title generation - const descriptionToUse = updates.description ?? task.description; - console.log('[TASK_UPDATE] Title is empty, generating with Claude AI...'); - try { - const generatedTitle = await titleGenerator.generateTitle(descriptionToUse); - if (generatedTitle) { - finalTitle = generatedTitle; - console.log('[TASK_UPDATE] Generated title:', finalTitle); - } else { - // Fallback: create title from first line of description - finalTitle = descriptionToUse.split('\n')[0].substring(0, 60); - if (finalTitle.length === 60) finalTitle += '...'; - console.log('[TASK_UPDATE] AI generation failed, using fallback:', finalTitle); - } - } catch (err) { - console.error('[TASK_UPDATE] Title generation error:', err); - // Fallback: create title from first line of description - finalTitle = descriptionToUse.split('\n')[0].substring(0, 60); - if (finalTitle.length === 60) finalTitle += '...'; - } - } - - // Update implementation_plan.json - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - if (existsSync(planPath)) { - try { - const planContent = readFileSync(planPath, 'utf-8'); - const plan = JSON.parse(planContent); - - if (finalTitle !== undefined) { - plan.feature = finalTitle; - } - if (updates.description !== undefined) { - plan.description = updates.description; - } - plan.updated_at = new Date().toISOString(); - - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } catch { - // Plan file might not be valid JSON, continue anyway - } - } - - // Update spec.md if it exists - const specPath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE); - if (existsSync(specPath)) { - try { - let specContent = readFileSync(specPath, 'utf-8'); - - // Update title (first # heading) - if (finalTitle !== undefined) { - specContent = specContent.replace( - /^#\s+.*$/m, - `# ${finalTitle}` - ); - } - - // Update description (## Overview section content) - if (updates.description !== undefined) { - // Replace content between ## Overview and the next ## section - specContent = specContent.replace( - /(## Overview\n)([\s\S]*?)((?=\n## )|$)/, - `$1${updates.description}\n\n$3` - ); - } - - writeFileSync(specPath, specContent); - } catch { - // Spec file update failed, continue anyway - } - } - - // Update metadata if provided - let updatedMetadata = task.metadata; - if (updates.metadata) { - updatedMetadata = { ...task.metadata, ...updates.metadata }; - - // Process and save attached images if provided - if (updates.metadata.attachedImages && updates.metadata.attachedImages.length > 0) { - const attachmentsDir = path.join(specDir, 'attachments'); - mkdirSync(attachmentsDir, { recursive: true }); - - const savedImages: typeof updates.metadata.attachedImages = []; - - for (const image of updates.metadata.attachedImages) { - // If image has data (new image), save it - if (image.data) { - try { - const buffer = Buffer.from(image.data, 'base64'); - const imagePath = path.join(attachmentsDir, image.filename); - writeFileSync(imagePath, buffer); - - savedImages.push({ - id: image.id, - filename: image.filename, - mimeType: image.mimeType, - size: image.size, - path: `attachments/${image.filename}` - }); - } catch (err) { - console.error(`Failed to save image ${image.filename}:`, err); - } - } else if (image.path) { - // Existing image, keep it - savedImages.push(image); - } - } - - updatedMetadata.attachedImages = savedImages; - } - - // Update task_metadata.json - const metadataPath = path.join(specDir, 'task_metadata.json'); - try { - writeFileSync(metadataPath, JSON.stringify(updatedMetadata, null, 2)); - } catch (err) { - console.error('Failed to update task_metadata.json:', err); - } - - // Update requirements.json if it exists - const requirementsPath = path.join(specDir, 'requirements.json'); - if (existsSync(requirementsPath)) { - try { - const requirementsContent = readFileSync(requirementsPath, 'utf-8'); - const requirements = JSON.parse(requirementsContent); - - if (updates.description !== undefined) { - requirements.task_description = updates.description; - } - if (updates.metadata.category) { - requirements.workflow_type = updates.metadata.category; - } - - writeFileSync(requirementsPath, JSON.stringify(requirements, null, 2)); - } catch (err) { - console.error('Failed to update requirements.json:', err); - } - } - } - - // Build the updated task object - const updatedTask: Task = { - ...task, - title: finalTitle ?? task.title, - description: updates.description ?? task.description, - metadata: updatedMetadata, - updatedAt: new Date() - }; - - return { success: true, data: updatedTask }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Unknown error' - }; - } - } - ); - - ipcMain.on( - IPC_CHANNELS.TASK_START, - (_, taskId: string, options?: TaskStartOptions) => { - console.log('[TASK_START] Received request for taskId:', taskId); - const mainWindow = getMainWindow(); - if (!mainWindow) { - console.log('[TASK_START] No main window found'); - return; - } - - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - console.log('[TASK_START] Task or project not found for taskId:', taskId); - mainWindow.webContents.send( - IPC_CHANNELS.TASK_ERROR, - taskId, - 'Task or project not found' - ); - return; - } - - console.log('[TASK_START] Found task:', task.specId, 'status:', task.status, 'subtasks:', task.subtasks.length); - - // Start file watcher for this task - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join( - project.path, - specsBaseDir, - task.specId - ); - fileWatcher.watch(taskId, specDir); - - // Check if spec.md exists (indicates spec creation was already done or in progress) - const specFilePath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE); - const hasSpec = existsSync(specFilePath); - - // Check if this task needs spec creation first (no spec file = not yet created) - // OR if it has a spec but no implementation plan subtasks (spec created, needs planning/building) - const needsSpecCreation = !hasSpec; - const needsImplementation = hasSpec && task.subtasks.length === 0; - - console.log('[TASK_START] hasSpec:', hasSpec, 'needsSpecCreation:', needsSpecCreation, 'needsImplementation:', needsImplementation); - - if (needsSpecCreation) { - // No spec file - need to run spec_runner.py to create the spec - const taskDescription = task.description || task.title; - console.log('[TASK_START] Starting spec creation for:', task.specId, 'in:', specDir); - - // Start spec creation process - pass the existing spec directory - // so spec_runner uses it instead of creating a new one - agentManager.startSpecCreation(task.specId, project.path, taskDescription, specDir, task.metadata); - } else if (needsImplementation) { - // Spec exists but no subtasks - run run.py to create implementation plan and execute - // Read the spec.md to get the task description - let taskDescription = task.description || task.title; - try { - taskDescription = readFileSync(specFilePath, 'utf-8'); - } catch { - // Use default description - } - - console.log('[TASK_START] Starting task execution (no subtasks) for:', task.specId); - // Start task execution which will create the implementation plan - // Note: No parallel mode for planning phase - parallel only makes sense with multiple subtasks - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: false, // Sequential for planning phase - workers: 1 - } - ); - } else { - // Task has subtasks, start normal execution - // Note: Parallel execution is handled internally by the agent, not via CLI flags - console.log('[TASK_START] Starting task execution (has subtasks) for:', task.specId); - - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: false, - workers: 1 - } - ); - } - - // Notify status change - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'in_progress' - ); - } - ); - - ipcMain.on(IPC_CHANNELS.TASK_STOP, (_, taskId: string) => { - agentManager.killTask(taskId); - fileWatcher.unwatch(taskId); - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'backlog' - ); - } - }); - - ipcMain.handle( - IPC_CHANNELS.TASK_REVIEW, - async ( - _, - taskId: string, - approved: boolean, - feedback?: string - ): Promise => { - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Check if dev mode is enabled for this project - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join( - project.path, - specsBaseDir, - task.specId - ); - - if (approved) { - // Write approval to QA report - const qaReportPath = path.join(specDir, AUTO_BUILD_PATHS.QA_REPORT); - writeFileSync( - qaReportPath, - `# QA Review\n\nStatus: APPROVED\n\nReviewed at: ${new Date().toISOString()}\n` - ); - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'done' - ); - } - } else { - // Write feedback for QA fixer - const fixRequestPath = path.join(specDir, 'QA_FIX_REQUEST.md'); - writeFileSync( - fixRequestPath, - `# QA Fix Request\n\nStatus: REJECTED\n\n## Feedback\n\n${feedback || 'No feedback provided'}\n\nCreated at: ${new Date().toISOString()}\n` - ); - - // Restart QA process with dev mode - agentManager.startQAProcess(taskId, project.path, task.specId); - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'in_progress' - ); - } - } - - return { success: true }; - } - ); - - ipcMain.handle( - IPC_CHANNELS.TASK_UPDATE_STATUS, - async ( - _, - taskId: string, - status: TaskStatus - ): Promise => { - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Get the spec directory - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDir = path.join( - project.path, - specsBaseDir, - task.specId - ); - - // Update implementation_plan.json if it exists - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - - try { - if (existsSync(planPath)) { - const planContent = readFileSync(planPath, 'utf-8'); - const plan = JSON.parse(planContent); - - // Store the exact UI status - project-store.ts will map it back - plan.status = status; - // Also store mapped version for Python compatibility - plan.planStatus = status === 'done' ? 'completed' - : status === 'in_progress' ? 'in_progress' - : status === 'ai_review' ? 'review' - : status === 'human_review' ? 'review' - : 'pending'; - plan.updated_at = new Date().toISOString(); - - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } else { - // If no implementation plan exists yet, create a basic one - const plan = { - feature: task.title, - description: task.description || '', - created_at: task.createdAt.toISOString(), - updated_at: new Date().toISOString(), - status: status, // Store exact UI status for persistence - planStatus: status === 'done' ? 'completed' - : status === 'in_progress' ? 'in_progress' - : status === 'ai_review' ? 'review' - : status === 'human_review' ? 'review' - : 'pending', - phases: [] - }; - - // Ensure spec directory exists - if (!existsSync(specDir)) { - mkdirSync(specDir, { recursive: true }); - } - - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } - - // Auto-start task when status changes to 'in_progress' and no process is running - if (status === 'in_progress' && !agentManager.isRunning(taskId)) { - const mainWindow = getMainWindow(); - console.log('[TASK_UPDATE_STATUS] Auto-starting task:', taskId); - - // Start file watcher for this task - fileWatcher.watch(taskId, specDir); - - // Check if spec.md exists - const specFilePath = path.join(specDir, AUTO_BUILD_PATHS.SPEC_FILE); - const hasSpec = existsSync(specFilePath); - const needsSpecCreation = !hasSpec; - const needsImplementation = hasSpec && task.subtasks.length === 0; - - console.log('[TASK_UPDATE_STATUS] hasSpec:', hasSpec, 'needsSpecCreation:', needsSpecCreation, 'needsImplementation:', needsImplementation); - - if (needsSpecCreation) { - // No spec file - need to run spec_runner.py to create the spec - const taskDescription = task.description || task.title; - console.log('[TASK_UPDATE_STATUS] Starting spec creation for:', task.specId); - agentManager.startSpecCreation(task.specId, project.path, taskDescription, specDir, task.metadata); - } else if (needsImplementation) { - // Spec exists but no subtasks - run run.py to create implementation plan and execute - console.log('[TASK_UPDATE_STATUS] Starting task execution (no subtasks) for:', task.specId); - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: false, - workers: 1 - } - ); - } else { - // Task has subtasks, start normal execution - // Note: Parallel execution is handled internally by the agent - console.log('[TASK_UPDATE_STATUS] Starting task execution (has subtasks) for:', task.specId); - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: false, - workers: 1 - } - ); - } - - // Notify renderer about status change - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - 'in_progress' - ); - } - } - - return { success: true }; - } catch (error) { - console.error('Failed to update task status:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to update task status' - }; - } - } - ); - - // Handler to check if a task is actually running (has active process) - ipcMain.handle( - IPC_CHANNELS.TASK_CHECK_RUNNING, - async (_, taskId: string): Promise> => { - const isRunning = agentManager.isRunning(taskId); - return { success: true, data: isRunning }; - } - ); - - // Handler to recover a stuck task (status says in_progress but no process running) - ipcMain.handle( - IPC_CHANNELS.TASK_RECOVER_STUCK, - async ( - _, - taskId: string, - options?: { targetStatus?: TaskStatus; autoRestart?: boolean } - ): Promise> => { - const targetStatus = options?.targetStatus; - const autoRestart = options?.autoRestart ?? false; - // Check if task is actually running - const isActuallyRunning = agentManager.isRunning(taskId); - - if (isActuallyRunning) { - return { - success: false, - error: 'Task is still running. Stop it first before recovering.', - data: { - taskId, - recovered: false, - newStatus: 'in_progress' as TaskStatus, - message: 'Task is still running' - } - }; - } - - // Find task and project - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Get the spec directory - const autoBuildDir = project.autoBuildPath || '.auto-claude'; - const specDir = path.join( - project.path, - autoBuildDir, - 'specs', - task.specId - ); - - // Update implementation_plan.json - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - - try { - // Read the plan to analyze subtask progress - let plan: Record | null = null; - if (existsSync(planPath)) { - const planContent = readFileSync(planPath, 'utf-8'); - plan = JSON.parse(planContent); - } - - // Determine the target status intelligently based on subtask progress - // If targetStatus is explicitly provided, use it; otherwise calculate from subtasks - let newStatus: TaskStatus = targetStatus || 'backlog'; - - if (!targetStatus && plan?.phases && Array.isArray(plan.phases)) { - // Analyze subtask statuses to determine appropriate recovery status - const allSubtasks: Array<{ status: string }> = []; - for (const phase of plan.phases as Array<{ subtasks?: Array<{ status: string }> }>) { - if (phase.subtasks && Array.isArray(phase.subtasks)) { - allSubtasks.push(...phase.subtasks); - } - } - - if (allSubtasks.length > 0) { - const completedCount = allSubtasks.filter(s => s.status === 'completed').length; - const allCompleted = completedCount === allSubtasks.length; - - if (allCompleted) { - // All subtasks completed - should go to review (ai_review or human_review based on source) - // For recovery, human_review is safer as it requires manual verification - newStatus = 'human_review'; - } else if (completedCount > 0) { - // Some subtasks completed, some still pending - task is in progress - newStatus = 'in_progress'; - } - // else: no subtasks completed, stay with 'backlog' - } - } - - if (plan) { - // Update status - plan.status = newStatus; - plan.planStatus = newStatus === 'done' ? 'completed' - : newStatus === 'in_progress' ? 'in_progress' - : newStatus === 'ai_review' ? 'review' - : newStatus === 'human_review' ? 'review' - : 'pending'; - plan.updated_at = new Date().toISOString(); - - // Add recovery note - plan.recoveryNote = `Task recovered from stuck state at ${new Date().toISOString()}`; - - // Reset in_progress and failed subtask statuses to 'pending' so they can be retried - // Keep completed subtasks as-is so run.py can resume from where it left off - if (plan.phases && Array.isArray(plan.phases)) { - for (const phase of plan.phases as Array<{ subtasks?: Array<{ status: string; actual_output?: string; started_at?: string; completed_at?: string }> }>) { - if (phase.subtasks && Array.isArray(phase.subtasks)) { - for (const subtask of phase.subtasks) { - // Reset in_progress subtasks to pending (they were interrupted) - // Keep completed subtasks as-is so run.py can resume - if (subtask.status === 'in_progress') { - subtask.status = 'pending'; - // Clear execution data to maintain consistency - delete subtask.actual_output; - delete subtask.started_at; - delete subtask.completed_at; - } - // Also reset failed subtasks so they can be retried - if (subtask.status === 'failed') { - subtask.status = 'pending'; - // Clear execution data to maintain consistency - delete subtask.actual_output; - delete subtask.started_at; - delete subtask.completed_at; - } - } - } - } - } - - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } - - // Stop file watcher if it was watching this task - fileWatcher.unwatch(taskId); - - // Auto-restart the task if requested - let autoRestarted = false; - if (autoRestart && project) { - try { - // Set status to in_progress for the restart - newStatus = 'in_progress'; - - // Update plan status for restart - if (plan) { - plan.status = 'in_progress'; - plan.planStatus = 'in_progress'; - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } - - // Start the task execution - // Start file watcher for this task - const specsBaseDir = getSpecsDir(project.autoBuildPath); - const specDirForWatcher = path.join(project.path, specsBaseDir, task.specId); - fileWatcher.watch(taskId, specDirForWatcher); - - // Note: Parallel execution is handled internally by the agent - agentManager.startTaskExecution( - taskId, - project.path, - task.specId, - { - parallel: false, - workers: 1 - } - ); - - autoRestarted = true; - console.log(`[Recovery] Auto-restarted task ${taskId}`); - } catch (restartError) { - console.error('Failed to auto-restart task after recovery:', restartError); - // Recovery succeeded but restart failed - still report success - } - } - - // Notify renderer of status change - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send( - IPC_CHANNELS.TASK_STATUS_CHANGE, - taskId, - newStatus - ); - } - - return { - success: true, - data: { - taskId, - recovered: true, - newStatus, - message: autoRestarted - ? 'Task recovered and restarted successfully' - : `Task recovered successfully and moved to ${newStatus}`, - autoRestarted - } - }; - } catch (error) { - console.error('Failed to recover stuck task:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to recover task' - }; - } - } - ); - - // ============================================ - // Workspace Management Operations (for human review) - // ============================================ - - /** - * Helper function to find task and project by taskId - */ - const findTaskAndProject = (taskId: string): { task: Task | undefined; project: Project | undefined } => { - const projects = projectStore.getProjects(); - let task: Task | undefined; - let project: Project | undefined; - - for (const p of projects) { - const tasks = projectStore.getTasks(p.id); - task = tasks.find((t) => t.id === taskId || t.specId === taskId); - if (task) { - project = p; - break; - } - } - - return { task, project }; - }; - - /** - * Get the worktree status for a task - * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/ - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_STATUS, - async (_, taskId: string): Promise> => { - try { - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Per-spec worktree path: .worktrees/{spec-name}/ - const worktreePath = path.join(project.path, '.worktrees', task.specId); - - if (!existsSync(worktreePath)) { - return { - success: true, - data: { exists: false } - }; - } - - // Get branch info from git - try { - // Get current branch in worktree - const branch = execSync('git rev-parse --abbrev-ref HEAD', { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Get base branch (usually main or master) - let baseBranch = 'main'; - try { - // Try to get the default branch - baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', { - cwd: project.path, - encoding: 'utf-8' - }).trim().replace('origin/', ''); - } catch { - baseBranch = 'main'; - } - - // Get commit count - let commitCount = 0; - try { - const countOutput = execSync(`git rev-list --count ${baseBranch}..HEAD 2>/dev/null || echo 0`, { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - commitCount = parseInt(countOutput, 10) || 0; - } catch { - commitCount = 0; - } - - // Get diff stats - let filesChanged = 0; - let additions = 0; - let deletions = 0; - - try { - const diffStat = execSync(`git diff --stat ${baseBranch}...HEAD 2>/dev/null || echo ""`, { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Parse the summary line (e.g., "3 files changed, 50 insertions(+), 10 deletions(-)") - const summaryMatch = diffStat.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/); - if (summaryMatch) { - filesChanged = parseInt(summaryMatch[1], 10) || 0; - additions = parseInt(summaryMatch[2], 10) || 0; - deletions = parseInt(summaryMatch[3], 10) || 0; - } - } catch { - // Ignore diff errors - } - - return { - success: true, - data: { - exists: true, - worktreePath, - branch, - baseBranch, - commitCount, - filesChanged, - additions, - deletions - } - }; - } catch (gitError) { - console.error('Git error getting worktree status:', gitError); - return { - success: true, - data: { exists: true, worktreePath } - }; - } - } catch (error) { - console.error('Failed to get worktree status:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get worktree status' - }; - } - } - ); - - /** - * Get the diff for a task's worktree - * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/ - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_DIFF, - async (_, taskId: string): Promise> => { - try { - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Per-spec worktree path: .worktrees/{spec-name}/ - const worktreePath = path.join(project.path, '.worktrees', task.specId); - - if (!existsSync(worktreePath)) { - return { success: false, error: 'No worktree found for this task' }; - } - - // Get base branch - let baseBranch = 'main'; - try { - baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', { - cwd: project.path, - encoding: 'utf-8' - }).trim().replace('origin/', ''); - } catch { - baseBranch = 'main'; - } - - // Get the diff with file stats - const files: import('../../shared/types').WorktreeDiffFile[] = []; - - try { - // Get numstat for additions/deletions per file - const numstat = execSync(`git diff --numstat ${baseBranch}...HEAD 2>/dev/null || echo ""`, { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Get name-status for file status - const nameStatus = execSync(`git diff --name-status ${baseBranch}...HEAD 2>/dev/null || echo ""`, { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Parse name-status to get file statuses - const statusMap: Record = {}; - nameStatus.split('\n').filter(Boolean).forEach((line: string) => { - const [status, ...pathParts] = line.split('\t'); - const filePath = pathParts.join('\t'); // Handle files with tabs in name - switch (status[0]) { - case 'A': statusMap[filePath] = 'added'; break; - case 'M': statusMap[filePath] = 'modified'; break; - case 'D': statusMap[filePath] = 'deleted'; break; - case 'R': statusMap[pathParts[1] || filePath] = 'renamed'; break; - default: statusMap[filePath] = 'modified'; - } - }); - - // Parse numstat for additions/deletions - numstat.split('\n').filter(Boolean).forEach((line: string) => { - const [adds, dels, filePath] = line.split('\t'); - files.push({ - path: filePath, - status: statusMap[filePath] || 'modified', - additions: parseInt(adds, 10) || 0, - deletions: parseInt(dels, 10) || 0 - }); - }); - } catch (diffError) { - console.error('Error getting diff:', diffError); - } - - // Generate summary - const totalAdditions = files.reduce((sum, f) => sum + f.additions, 0); - const totalDeletions = files.reduce((sum, f) => sum + f.deletions, 0); - const summary = `${files.length} files changed, ${totalAdditions} insertions(+), ${totalDeletions} deletions(-)`; - - return { - success: true, - data: { files, summary } - }; - } catch (error) { - console.error('Failed to get worktree diff:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get worktree diff' - }; - } - } - ); - - /** - * Merge the worktree changes into the main branch - * @param taskId - The task ID to merge - * @param options - Merge options { noCommit?: boolean } - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_MERGE, - async (_, taskId: string, options?: { noCommit?: boolean }): Promise> => { - // Enable verbose debug logging via environment variables - const DEBUG_MERGE = process.env.DEBUG_MERGE === 'true' || process.env.DEBUG === 'true'; - const debug = (...args: unknown[]) => { - if (DEBUG_MERGE) console.log('[MERGE DEBUG]', ...args); - }; - - try { - console.log('[MERGE] Handler called with taskId:', taskId, 'options:', options); - debug('Starting merge for taskId:', taskId, 'options:', options); - - // Ensure Python environment is ready - if (!pythonEnvManager.isEnvReady()) { - const autoBuildSource = getEffectiveSourcePath(); - if (autoBuildSource) { - const status = await pythonEnvManager.initialize(autoBuildSource); - if (!status.ready) { - return { success: false, error: `Python environment not ready: ${status.error || 'Unknown error'}` }; - } - } else { - return { success: false, error: 'Python environment not ready and Auto Claude source not found' }; - } - } - - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - debug('Task or project not found'); - return { success: false, error: 'Task not found' }; - } - - debug('Found task:', task.specId, 'project:', project.path); - - // Use run.py --merge to handle the merge - const sourcePath = getEffectiveSourcePath(); - if (!sourcePath) { - return { success: false, error: 'Auto Claude source not found' }; - } - - const runScript = path.join(sourcePath, 'run.py'); - const specDir = path.join(project.path, project.autoBuildPath || '.auto-claude', 'specs', task.specId); - - if (!existsSync(specDir)) { - debug('Spec directory not found:', specDir); - return { success: false, error: 'Spec directory not found' }; - } - - // Check worktree exists before merge - const worktreePath = path.join(project.path, '.worktrees', task.specId); - debug('Worktree path:', worktreePath, 'exists:', existsSync(worktreePath)); - - // Get git status before merge - if (DEBUG_MERGE) { - try { - const gitStatusBefore = execSync('git status --short', { cwd: project.path, encoding: 'utf-8' }); - debug('Git status BEFORE merge in main project:\n', gitStatusBefore || '(clean)'); - const gitBranch = execSync('git branch --show-current', { cwd: project.path, encoding: 'utf-8' }).trim(); - debug('Current branch:', gitBranch); - } catch (e) { - debug('Failed to get git status before:', e); - } - } - - const args = [ - runScript, - '--spec', task.specId, - '--project-dir', project.path, - '--merge' - ]; - - // Add --no-commit flag if requested (stage changes without committing) - if (options?.noCommit) { - args.push('--no-commit'); - } - - const pythonPath = pythonEnvManager.getPythonPath() || 'python3'; - debug('Running command:', pythonPath, args.join(' ')); - debug('Working directory:', sourcePath); - - // Get profile environment with OAuth token for AI merge resolution - const profileEnv = getProfileEnv(); - debug('Profile env for merge:', { - hasOAuthToken: !!profileEnv.CLAUDE_CODE_OAUTH_TOKEN, - hasConfigDir: !!profileEnv.CLAUDE_CONFIG_DIR - }); - - return new Promise((resolve) => { - const mergeProcess = spawn(pythonPath, args, { - cwd: sourcePath, - env: { - ...process.env, - ...profileEnv, // Include active Claude profile OAuth token - PYTHONUNBUFFERED: '1' - } - }); - - let stdout = ''; - let stderr = ''; - - mergeProcess.stdout.on('data', (data: Buffer) => { - const chunk = data.toString(); - stdout += chunk; - debug('STDOUT:', chunk); - }); - - mergeProcess.stderr.on('data', (data: Buffer) => { - const chunk = data.toString(); - stderr += chunk; - debug('STDERR:', chunk); - }); - - mergeProcess.on('close', (code: number) => { - debug('Process exited with code:', code); - debug('Full stdout:', stdout); - debug('Full stderr:', stderr); - - // Get git status after merge - if (DEBUG_MERGE) { - try { - const gitStatusAfter = execSync('git status --short', { cwd: project.path, encoding: 'utf-8' }); - debug('Git status AFTER merge in main project:\n', gitStatusAfter || '(clean)'); - const gitDiffStaged = execSync('git diff --staged --stat', { cwd: project.path, encoding: 'utf-8' }); - debug('Staged changes:\n', gitDiffStaged || '(none)'); - } catch (e) { - debug('Failed to get git status after:', e); - } - } - - if (code === 0) { - const isStageOnly = options?.noCommit === true; - - // For stage-only: keep in human_review so user commits manually - // For full merge: mark as done - const newStatus = isStageOnly ? 'human_review' : 'done'; - const planStatus = isStageOnly ? 'review' : 'completed'; - - debug('Merge successful. isStageOnly:', isStageOnly, 'newStatus:', newStatus); - - // Persist the status change to implementation_plan.json - const planPath = path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN); - try { - if (existsSync(planPath)) { - const planContent = readFileSync(planPath, 'utf-8'); - const plan = JSON.parse(planContent); - plan.status = newStatus; - plan.planStatus = planStatus; - plan.updated_at = new Date().toISOString(); - if (isStageOnly) { - plan.stagedAt = new Date().toISOString(); - plan.stagedInMainProject = true; - } - writeFileSync(planPath, JSON.stringify(plan, null, 2)); - } - } catch (persistError) { - console.error('Failed to persist task status:', persistError); - } - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_STATUS_CHANGE, taskId, newStatus as TaskStatus); - } - - const message = isStageOnly - ? 'Changes staged in main project. Review with git status and commit when ready.' - : 'Changes merged successfully'; - - resolve({ - success: true, - data: { - success: true, - message, - staged: isStageOnly, - projectPath: isStageOnly ? project.path : undefined - } - }); - } else { - // Check if there were conflicts - const hasConflicts = stdout.includes('conflict') || stderr.includes('conflict'); - debug('Merge failed. hasConflicts:', hasConflicts); - - resolve({ - success: true, - data: { - success: false, - message: hasConflicts ? 'Merge conflicts detected' : `Merge failed: ${stderr || stdout}`, - conflictFiles: hasConflicts ? [] : undefined - } - }); - } - }); - - mergeProcess.on('error', (err: Error) => { - console.error('[MERGE] Process spawn error:', err); - resolve({ - success: false, - error: `Failed to run merge: ${err.message}` - }); - }); - }); - } catch (error) { - console.error('[MERGE] Exception in merge handler:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to merge worktree' - }; - } - } - ); - - /** - * Discard the worktree changes - * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/ - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_DISCARD, - async (_, taskId: string): Promise> => { - try { - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - return { success: false, error: 'Task not found' }; - } - - // Per-spec worktree path: .worktrees/{spec-name}/ - const worktreePath = path.join(project.path, '.worktrees', task.specId); - - if (!existsSync(worktreePath)) { - return { - success: true, - data: { - success: true, - message: 'No worktree to discard' - } - }; - } - - try { - // Get the branch name before removing - const branch = execSync('git rev-parse --abbrev-ref HEAD', { - cwd: worktreePath, - encoding: 'utf-8' - }).trim(); - - // Remove the worktree - execSync(`git worktree remove --force "${worktreePath}"`, { - cwd: project.path, - encoding: 'utf-8' - }); - - // Delete the branch - try { - execSync(`git branch -D "${branch}"`, { - cwd: project.path, - encoding: 'utf-8' - }); - } catch { - // Branch might already be deleted or not exist - } - - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_STATUS_CHANGE, taskId, 'backlog'); - } - - return { - success: true, - data: { - success: true, - message: 'Worktree discarded successfully' - } - }; - } catch (gitError) { - console.error('Git error discarding worktree:', gitError); - return { - success: false, - error: `Failed to discard worktree: ${gitError instanceof Error ? gitError.message : 'Unknown error'}` - }; - } - } catch (error) { - console.error('Failed to discard worktree:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to discard worktree' - }; - } - } - ); - - /** - * List all spec worktrees for a project - * Per-spec architecture: Each spec has its own worktree at .worktrees/{spec-name}/ - */ - ipcMain.handle( - IPC_CHANNELS.TASK_LIST_WORKTREES, - async (_, projectId: string): Promise> => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const worktreesDir = path.join(project.path, '.worktrees'); - const worktrees: import('../../shared/types').WorktreeListItem[] = []; - - if (!existsSync(worktreesDir)) { - return { success: true, data: { worktrees } }; - } - - // Get all directories in .worktrees - const entries = readdirSync(worktreesDir); - for (const entry of entries) { - const entryPath = path.join(worktreesDir, entry); - const stat = statSync(entryPath); - - // Skip worker directories and non-directories - if (!stat.isDirectory() || entry.startsWith('worker-')) { - continue; - } - - try { - // Get branch info - const branch = execSync('git rev-parse --abbrev-ref HEAD', { - cwd: entryPath, - encoding: 'utf-8' - }).trim(); - - // Get base branch - let baseBranch = 'main'; - try { - baseBranch = execSync('git rev-parse --abbrev-ref origin/HEAD 2>/dev/null || echo main', { - cwd: project.path, - encoding: 'utf-8' - }).trim().replace('origin/', ''); - } catch { - baseBranch = 'main'; - } - - // Get commit count - let commitCount = 0; - try { - const countOutput = execSync(`git rev-list --count ${baseBranch}..HEAD 2>/dev/null || echo 0`, { - cwd: entryPath, - encoding: 'utf-8' - }).trim(); - commitCount = parseInt(countOutput, 10) || 0; - } catch { - commitCount = 0; - } - - // Get diff stats - let filesChanged = 0; - let additions = 0; - let deletions = 0; - - try { - const diffStat = execSync(`git diff --shortstat ${baseBranch}...HEAD 2>/dev/null || echo ""`, { - cwd: entryPath, - encoding: 'utf-8' - }).trim(); - - const filesMatch = diffStat.match(/(\d+) files? changed/); - const addMatch = diffStat.match(/(\d+) insertions?/); - const delMatch = diffStat.match(/(\d+) deletions?/); - - if (filesMatch) filesChanged = parseInt(filesMatch[1], 10) || 0; - if (addMatch) additions = parseInt(addMatch[1], 10) || 0; - if (delMatch) deletions = parseInt(delMatch[1], 10) || 0; - } catch { - // Ignore diff errors - } - - worktrees.push({ - specName: entry, - path: entryPath, - branch, - baseBranch, - commitCount, - filesChanged, - additions, - deletions - }); - } catch (gitError) { - console.error(`Error getting info for worktree ${entry}:`, gitError); - // Skip this worktree if we can't get git info - } - } - - return { success: true, data: { worktrees } }; - } catch (error) { - console.error('Failed to list worktrees:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to list worktrees' - }; - } - } - ); - - // ============================================ - // Task Logs Operations - // ============================================ - - /** - * Get task logs from spec directory - * Returns logs organized by phase (planning, coding, validation) - */ - ipcMain.handle( - IPC_CHANNELS.TASK_LOGS_GET, - async (_, projectId: string, specId: string): Promise> => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const specsRelPath = getSpecsDir(project.autoBuildPath); - const specDir = path.join(project.path, specsRelPath, specId); - - if (!existsSync(specDir)) { - return { success: false, error: 'Spec directory not found' }; - } - - const logs = taskLogService.loadLogs(specDir, project.path, specsRelPath, specId); - return { success: true, data: logs }; - } catch (error) { - console.error('Failed to get task logs:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to get task logs' - }; - } - } - ); - - /** - * Start watching a spec for log changes - */ - ipcMain.handle( - IPC_CHANNELS.TASK_LOGS_WATCH, - async (_, projectId: string, specId: string): Promise => { - try { - const project = projectStore.getProject(projectId); - if (!project) { - return { success: false, error: 'Project not found' }; - } - - const specsRelPath = getSpecsDir(project.autoBuildPath); - const specDir = path.join(project.path, specsRelPath, specId); - - if (!existsSync(specDir)) { - return { success: false, error: 'Spec directory not found' }; - } - - taskLogService.startWatching(specId, specDir, project.path, specsRelPath); - return { success: true }; - } catch (error) { - console.error('Failed to start watching task logs:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to start watching' - }; - } - } - ); - - /** - * Stop watching a spec for log changes - */ - ipcMain.handle( - IPC_CHANNELS.TASK_LOGS_UNWATCH, - async (_, specId: string): Promise => { - try { - taskLogService.stopWatching(specId); - return { success: true }; - } catch (error) { - console.error('Failed to stop watching task logs:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to stop watching' - }; - } - } - ); - - /** - * Preview merge conflicts before actually merging - * Uses the smart merge system to analyze potential conflicts - */ - ipcMain.handle( - IPC_CHANNELS.TASK_WORKTREE_MERGE_PREVIEW, - async (_, taskId: string): Promise> => { - console.log('[IPC] TASK_WORKTREE_MERGE_PREVIEW called with taskId:', taskId); - try { - // Ensure Python environment is ready - if (!pythonEnvManager.isEnvReady()) { - console.log('[IPC] Python environment not ready, initializing...'); - const autoBuildSource = getEffectiveSourcePath(); - if (autoBuildSource) { - const status = await pythonEnvManager.initialize(autoBuildSource); - if (!status.ready) { - console.error('[IPC] Python environment failed to initialize:', status.error); - return { success: false, error: `Python environment not ready: ${status.error || 'Unknown error'}` }; - } - } else { - console.error('[IPC] Auto Claude source not found'); - return { success: false, error: 'Python environment not ready and Auto Claude source not found' }; - } - } - - const { task, project } = findTaskAndProject(taskId); - if (!task || !project) { - console.error('[IPC] Task not found:', taskId); - return { success: false, error: 'Task not found' }; - } - console.log('[IPC] Found task:', task.specId, 'project:', project.name); - - const sourcePath = getEffectiveSourcePath(); - if (!sourcePath) { - console.error('[IPC] Auto Claude source not found'); - return { success: false, error: 'Auto Claude source not found' }; - } - - const runScript = path.join(sourcePath, 'run.py'); - const args = [ - runScript, - '--spec', task.specId, - '--project-dir', project.path, - '--merge-preview' - ]; - - const pythonPath = pythonEnvManager.getPythonPath() || 'python3'; - console.log('[IPC] Running merge preview:', pythonPath, args.join(' ')); - - // Get profile environment for consistency - const previewProfileEnv = getProfileEnv(); - - return new Promise((resolve) => { - const previewProcess = spawn(pythonPath, args, { - cwd: sourcePath, - env: { ...process.env, ...previewProfileEnv, PYTHONUNBUFFERED: '1', DEBUG: 'true' } - }); - - let stdout = ''; - let stderr = ''; - - previewProcess.stdout.on('data', (data: Buffer) => { - const chunk = data.toString(); - stdout += chunk; - console.log('[IPC] merge-preview stdout:', chunk); - }); - - previewProcess.stderr.on('data', (data: Buffer) => { - const chunk = data.toString(); - stderr += chunk; - console.log('[IPC] merge-preview stderr:', chunk); - }); - - previewProcess.on('close', (code: number) => { - console.log('[IPC] merge-preview process exited with code:', code); - if (code === 0) { - try { - // Parse JSON output from Python - const result = JSON.parse(stdout.trim()); - console.log('[IPC] merge-preview result:', JSON.stringify(result, null, 2)); - resolve({ - success: true, - data: { - success: result.success, - message: result.error || 'Preview completed', - preview: { - files: result.files || [], - conflicts: result.conflicts || [], - summary: result.summary || { - totalFiles: 0, - conflictFiles: 0, - totalConflicts: 0, - autoMergeable: 0, - hasGitConflicts: false - }, - gitConflicts: result.gitConflicts || null - } - } - }); - } catch (parseError) { - console.error('[IPC] Failed to parse preview result:', parseError); - console.error('[IPC] stdout:', stdout); - console.error('[IPC] stderr:', stderr); - resolve({ - success: false, - error: `Failed to parse preview result: ${stderr || stdout}` - }); - } - } else { - console.error('[IPC] Preview failed with exit code:', code); - console.error('[IPC] stderr:', stderr); - console.error('[IPC] stdout:', stdout); - resolve({ - success: false, - error: `Preview failed: ${stderr || stdout}` - }); - } - }); - - previewProcess.on('error', (err: Error) => { - console.error('[IPC] merge-preview spawn error:', err); - resolve({ - success: false, - error: `Failed to run preview: ${err.message}` - }); - }); - }); - } catch (error) { - console.error('[IPC] TASK_WORKTREE_MERGE_PREVIEW error:', error); - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to preview merge' - }; - } - } - ); - - // Setup task log service event forwarding to renderer - taskLogService.on('logs-changed', (specId: string, logs: import('../../shared/types').TaskLogs) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_LOGS_CHANGED, specId, logs); - } - }); - - taskLogService.on('stream-chunk', (specId: string, chunk: import('../../shared/types').TaskLogStreamChunk) => { - const mainWindow = getMainWindow(); - if (mainWindow) { - mainWindow.webContents.send(IPC_CHANNELS.TASK_LOGS_STREAM, specId, chunk); - } - }); - -} diff --git a/auto-claude-ui/src/renderer/components/project-settings/REFACTORING_SUMMARY.md b/auto-claude-ui/src/renderer/components/project-settings/REFACTORING_SUMMARY.md deleted file mode 100644 index 451ca34e..00000000 --- a/auto-claude-ui/src/renderer/components/project-settings/REFACTORING_SUMMARY.md +++ /dev/null @@ -1,325 +0,0 @@ -# ProjectSettings Refactoring Summary - -## Overview - -Successfully refactored the monolithic `ProjectSettings.tsx` component (1,445 lines) into a modular, maintainable architecture with clear separation of concerns. - -## Metrics - -### Before Refactoring -- **Total Lines**: 1,445 lines in a single file -- **Components**: 1 monolithic component -- **Hooks**: All logic embedded in component -- **State Variables**: 15+ useState hooks in one component -- **useEffect Hooks**: 7 complex effects managing different concerns - -### After Refactoring -- **Main Component**: 321 lines (78% reduction) -- **New Files Created**: 23 files - - 7 section components - - 5 utility components - - 6 custom hooks - - 2 index files - - 2 documentation files -- **Custom Hooks**: 6 specialized hooks for state management -- **Reusable Components**: 5 utility components for common patterns - -## File Structure - -``` -ProjectSettings.tsx (321 lines) ← Main orchestrator -├── Hooks (6 custom hooks) -│ ├── useProjectSettings.ts -│ ├── useEnvironmentConfig.ts -│ ├── useClaudeAuth.ts -│ ├── useLinearConnection.ts -│ ├── useGitHubConnection.ts -│ └── useInfrastructureStatus.ts -│ -├── Section Components (7 feature components) -│ ├── AutoBuildIntegration.tsx -│ ├── ClaudeAuthSection.tsx -│ ├── LinearIntegrationSection.tsx -│ ├── GitHubIntegrationSection.tsx -│ ├── MemoryBackendSection.tsx -│ ├── AgentConfigSection.tsx -│ └── NotificationsSection.tsx -│ -└── Utility Components (5 reusable components) - ├── CollapsibleSection.tsx - ├── PasswordInput.tsx - ├── StatusBadge.tsx - ├── ConnectionStatus.tsx - └── InfrastructureStatus.tsx -``` - -## Key Improvements - -### 1. Separation of Concerns - -**Before**: Single component handled everything -- State management -- API calls -- UI rendering -- Business logic -- Effects management - -**After**: Clear responsibility boundaries -- **Hooks**: State management and side effects -- **Section Components**: Feature-specific UI and logic -- **Utility Components**: Reusable UI patterns -- **Main Component**: Orchestration and composition - -### 2. State Management - -**Before**: 15+ useState hooks in one place -```tsx -const [settings, setSettings] = useState(...) -const [envConfig, setEnvConfig] = useState(...) -const [isSaving, setIsSaving] = useState(...) -const [error, setError] = useState(...) -// ... 11 more state variables -``` - -**After**: Organized into custom hooks by domain -```tsx -// Clean, organized hook usage -const { settings, setSettings, versionInfo } = useProjectSettings(project, open); -const { envConfig, updateEnvConfig } = useEnvironmentConfig(project.id, ...); -const { claudeAuthStatus } = useClaudeAuth(project.id, ...); -``` - -### 3. Component Composition - -**Before**: Deeply nested JSX with 800+ lines of markup -```tsx -return ( - - - {/* 800+ lines of nested JSX */} - - -); -``` - -**After**: Clean composition with semantic components -```tsx -return ( - - - - - - - - - - - -); -``` - -### 4. Reusability - -**Before**: Repeated patterns throughout the file -- Password inputs with show/hide (implemented 4 times) -- Collapsible sections (implemented 4 times) -- Status badges (inline everywhere) -- Connection status displays (duplicated) - -**After**: DRY components used multiple times -```tsx -// Used in 4+ places - - -// Used in 4 section components - - {children} - - -// Used throughout for status display - - -``` - -### 5. Testing Capability - -**Before**: Nearly impossible to test -- Single 1,445-line component -- Tightly coupled logic -- Mock entire component tree - -**After**: Fully testable in isolation -```tsx -// Test individual hooks -describe('useClaudeAuth', () => { - it('should check authentication status', () => { ... }); -}); - -// Test individual components -describe('ClaudeAuthSection', () => { - it('should render authentication status', () => { ... }); -}); - -// Test utility components -describe('PasswordInput', () => { - it('should toggle password visibility', () => { ... }); -}); -``` - -## Component Breakdown by Size - -| Component | Lines | Purpose | -|-----------|-------|---------| -| ProjectSettings.tsx | 321 | Main orchestrator | -| MemoryBackendSection.tsx | ~240 | Graphiti configuration (largest section) | -| LinearIntegrationSection.tsx | ~160 | Linear integration | -| GitHubIntegrationSection.tsx | ~140 | GitHub integration | -| ClaudeAuthSection.tsx | ~100 | Claude authentication | -| InfrastructureStatus.tsx | ~100 | Docker/FalkorDB status | -| AutoBuildIntegration.tsx | ~70 | Auto-Build setup | -| NotificationsSection.tsx | ~60 | Notification preferences | -| AgentConfigSection.tsx | ~35 | Agent configuration | -| CollapsibleSection.tsx | ~40 | Reusable wrapper | -| ConnectionStatus.tsx | ~40 | Reusable status display | -| PasswordInput.tsx | ~25 | Reusable input | -| StatusBadge.tsx | ~15 | Reusable badge | - -## Hook Breakdown - -| Hook | Lines | Purpose | -|------|-------|---------| -| useInfrastructureStatus.ts | ~95 | Docker/FalkorDB monitoring | -| useEnvironmentConfig.ts | ~75 | Environment config management | -| useClaudeAuth.ts | ~55 | Claude auth checking | -| useGitHubConnection.ts | ~45 | GitHub connection monitoring | -| useLinearConnection.ts | ~40 | Linear connection monitoring | -| useProjectSettings.ts | ~35 | Settings state management | - -## Type Safety Improvements - -**Before**: Implicit prop types, easy to break -```tsx -// No clear interface, props passed ad-hoc -``` - -**After**: Explicit interfaces for all components -```tsx -interface ClaudeAuthSectionProps { - isExpanded: boolean; - onToggle: () => void; - envConfig: ProjectEnvConfig | null; - isLoadingEnv: boolean; - // ... all props explicitly typed -} -``` - -## Maintainability Benefits - -### Easy to Locate Code -- **Before**: Search through 1,445 lines to find Linear integration logic -- **After**: Open `LinearIntegrationSection.tsx` - -### Easy to Modify -- **Before**: Changing Linear logic risks breaking Claude, GitHub, or Graphiti -- **After**: Change `LinearIntegrationSection.tsx` in isolation - -### Easy to Add Features -- **Before**: Add 100+ lines to already massive component -- **After**: Create new section component, add to main component - -### Easy to Debug -- **Before**: Complex state interactions across entire component -- **After**: Debug specific hook or component in isolation - -## Performance Considerations - -### Potential Optimizations Enabled -1. **Memoization**: Can wrap individual sections with `React.memo()` -2. **Code Splitting**: Can lazy load heavy sections -3. **Selective Re-renders**: Changes to one section don't force re-render of others - -```tsx -// Easy to add memoization -export const MemoryBackendSection = React.memo(({ ... }) => { - // Component logic -}); - -// Easy to lazy load -const MemoryBackendSection = lazy(() => import('./MemoryBackendSection')); -``` - -## Migration Path - -### Zero Breaking Changes -The refactored component maintains **100% compatibility** with existing usage: - -```tsx -// Before refactoring - - -// After refactoring (same API) - -``` - -### Internal Structure Only -- External API unchanged -- Props interface unchanged -- Behavior unchanged -- Pure refactoring for code quality - -## Developer Experience - -### Before Refactoring -- 😰 Overwhelming 1,445-line file -- 🔍 Hard to find specific functionality -- ⚠️ Risky to make changes -- 🐛 Difficult to debug -- 🚫 Can't work in parallel with other devs - -### After Refactoring -- ✅ Small, focused files -- 🎯 Easy to navigate by feature -- 🛡️ Safe to modify isolated components -- 🔬 Easy to debug specific sections -- 👥 Multiple devs can work simultaneously - -## Code Quality Metrics - -### Complexity Reduction -- **Cyclomatic Complexity**: Reduced from ~50+ to <10 per component -- **Lines per File**: Average 60 lines (vs 1,445) -- **Responsibilities**: 1 per component (vs 15+) - -### Maintainability Index -- **Before**: Low (complex, large file) -- **After**: High (simple, small files with clear purpose) - -## Next Steps - -### Immediate Benefits -- ✅ Code is more maintainable -- ✅ Components are reusable -- ✅ Logic is testable -- ✅ Team can work in parallel - -### Future Enhancements -1. Add unit tests for each component and hook -2. Add Storybook stories for visual testing -3. Add performance monitoring -4. Implement optimistic updates -5. Add error boundaries -6. Extract more common patterns - -## Conclusion - -This refactoring successfully transformed a monolithic, difficult-to-maintain component into a well-structured, modular architecture that follows React best practices and separation of concerns principles. The code is now: - -- **78% smaller** main component (321 vs 1,445 lines) -- **Highly testable** with isolated units -- **Easy to maintain** with clear responsibilities -- **Reusable** with extracted utility components -- **Type-safe** with explicit interfaces -- **Developer-friendly** with clear organization - -All while maintaining 100% backward compatibility with zero breaking changes. diff --git a/auto-claude/__init__.py b/auto-claude/__init__.py deleted file mode 100644 index 57b862ea..00000000 --- a/auto-claude/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -Auto Claude - Autonomous Coding Framework -========================================== - -Multi-agent autonomous coding framework that builds software through -coordinated AI agent sessions. -""" - -import json -from pathlib import Path - - -def _get_version() -> str: - """Get version from package.json (single source of truth).""" - package_json = Path(__file__).parent.parent / "auto-claude-ui" / "package.json" - try: - with open(package_json, encoding="utf-8") as f: - return json.load(f).get("version", "0.0.0") - except (FileNotFoundError, json.JSONDecodeError, KeyError): - return "0.0.0" - - -__version__ = _get_version() diff --git a/auto-claude/agents/__init__.py b/auto-claude/agents/__init__.py deleted file mode 100644 index 977fcb13..00000000 --- a/auto-claude/agents/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -Agents Module -============= - -Modular agent system for autonomous coding. - -This module provides: -- run_autonomous_agent: Main coder agent loop -- run_followup_planner: Follow-up planner for completed specs -- Memory management (Graphiti + file-based fallback) -- Session management and post-processing -- Utility functions for git and plan management -""" - -# Main agent functions (public API) -# Constants -from .base import ( - AUTO_CONTINUE_DELAY_SECONDS, - HUMAN_INTERVENTION_FILE, -) -from .coder import run_autonomous_agent - -# Memory functions -from .memory_manager import ( - debug_memory_system_status, - get_graphiti_context, - save_session_memory, - save_session_to_graphiti, # Backwards compatibility -) -from .planner import run_followup_planner - -# Session management -from .session import ( - post_session_processing, - run_agent_session, -) - -# Utility functions -from .utils import ( - find_phase_for_subtask, - find_subtask_in_plan, - get_commit_count, - get_latest_commit, - load_implementation_plan, - sync_plan_to_source, -) - -__all__ = [ - # Main API - "run_autonomous_agent", - "run_followup_planner", - # Memory - "debug_memory_system_status", - "get_graphiti_context", - "save_session_memory", - "save_session_to_graphiti", - # Session - "run_agent_session", - "post_session_processing", - # Utils - "get_latest_commit", - "get_commit_count", - "load_implementation_plan", - "find_subtask_in_plan", - "find_phase_for_subtask", - "sync_plan_to_source", - # Constants - "AUTO_CONTINUE_DELAY_SECONDS", - "HUMAN_INTERVENTION_FILE", -] diff --git a/auto-claude/analyzer.py b/auto-claude/analyzer.py deleted file mode 100644 index 1cd4c705..00000000 --- a/auto-claude/analyzer.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Backward compatibility shim - import from analysis.analyzer instead.""" - -from analysis.analyzer import * # noqa: F403 -from analysis.analyzer import main - -if __name__ == "__main__": - main() diff --git a/auto-claude/analyzers/__init__.py b/auto-claude/analyzers/__init__.py deleted file mode 100644 index e871cd82..00000000 --- a/auto-claude/analyzers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Backward compatibility shim - import from analysis.analyzers instead.""" - -from analysis.analyzers import * # noqa: F403 diff --git a/auto-claude/auto_claude_tools.py b/auto-claude/auto_claude_tools.py deleted file mode 100644 index 5c7cee4e..00000000 --- a/auto-claude/auto_claude_tools.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Backward compatibility shim - import from agents.tools_pkg instead.""" - -# Direct import to avoid triggering agents.__init__ circular dependencies -import sys -from pathlib import Path - -# Add agents directory to path if needed -agents_dir = Path(__file__).parent / "agents" -if str(agents_dir) not in sys.path: - sys.path.insert(0, str(agents_dir)) - -# Import directly from tools_pkg to avoid agents.__init__ circular imports -from tools_pkg import * # noqa: F403, E402 diff --git a/auto-claude/client.py b/auto-claude/client.py deleted file mode 100644 index 61271333..00000000 --- a/auto-claude/client.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Backward compatibility shim - import from core.client instead.""" - -import os -import sys - -# Add auto-claude to path if not present -_auto_claude_dir = os.path.dirname(os.path.abspath(__file__)) -if _auto_claude_dir not in sys.path: - sys.path.insert(0, _auto_claude_dir) - - -# Use lazy imports to avoid circular dependency -def __getattr__(name): - """Lazy import to avoid circular imports with auto_claude_tools.""" - from core import client as _client - - return getattr(_client, name) diff --git a/auto-claude/debug.py b/auto-claude/debug.py deleted file mode 100644 index e3759336..00000000 --- a/auto-claude/debug.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Backward compatibility shim - import from core.debug instead.""" - -from core.debug import * # noqa: F403 diff --git a/auto-claude/implementation_plan.py b/auto-claude/implementation_plan.py deleted file mode 100644 index 6669efbe..00000000 --- a/auto-claude/implementation_plan.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Backward compatibility shim - import from implementation_plan package instead.""" - -from implementation_plan import * # noqa: F403 -from implementation_plan.main import * # noqa: F403 diff --git a/auto-claude/linear_integration.py b/auto-claude/linear_integration.py deleted file mode 100644 index cf052f3a..00000000 --- a/auto-claude/linear_integration.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Backward compatibility shim - import from integrations.linear.integration instead.""" - -from integrations.linear.integration import * # noqa: F403 diff --git a/auto-claude/linear_updater.py b/auto-claude/linear_updater.py deleted file mode 100644 index ab44130c..00000000 --- a/auto-claude/linear_updater.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Backward compatibility shim - import from integrations.linear.updater instead.""" - -from integrations.linear.updater import * # noqa: F403 diff --git a/auto-claude/merge/ARCHITECTURE.md b/auto-claude/merge/ARCHITECTURE.md deleted file mode 100644 index 4e3ac5c7..00000000 --- a/auto-claude/merge/ARCHITECTURE.md +++ /dev/null @@ -1,200 +0,0 @@ -# File Timeline Architecture - -## Component Diagram - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ file_timeline.py │ -│ (Public API Entry Point) │ -│ 83 lines │ -│ │ -│ Re-exports all public classes and functions │ -│ Maintains backward compatibility │ -└─────────────────────────────────────────────────────────────────┘ - │ - │ imports and re-exports - ▼ -┌─────────────────────────────────────────────────────────────────┐ -│ timeline_tracker.py │ -│ (Main Coordination Service) │ -│ 560 lines │ -│ │ -│ ┌────────────────────────────────────────────────────────────┐ │ -│ │ FileTimelineTracker │ │ -│ │ • Event handlers (task start, commit, merge, abandon) │ │ -│ │ • Query methods (get context, files, drift, timeline) │ │ -│ │ • Worktree capture and initialization │ │ -│ └────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────┘ - │ │ │ - │ │ │ - ▼ ▼ ▼ -┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ -│ timeline_git.py │ │timeline_models.py│ │timeline_persist- │ -│ │ │ │ │ence.py │ -│ 256 lines │ │ 321 lines │ │ 136 lines │ -│ │ │ │ │ │ -│ ┌──────────────┐ │ │ Data Classes: │ │ ┌──────────────┐ │ -│ │TimelineGit- │ │ │ • MainBranchEvent│ │ │Timeline- │ │ -│ │Helper │ │ │ • BranchPoint │ │ │Persistence │ │ -│ │ │ │ │ • WorktreeState │ │ │ │ │ -│ │Git Ops: │ │ │ • TaskIntent │ │ │Storage: │ │ -│ │• File content│ │ │ • TaskFileView │ │ │• Load all │ │ -│ │• Commit info │ │ │ • FileTimeline │ │ │• Save one │ │ -│ │• Changed files│ │ │ • MergeContext │ │ │• Update index│ │ -│ │• Worktree ops│ │ │ │ │ │• File paths │ │ -│ └──────────────┘ │ │ Methods: │ │ └──────────────┘ │ -│ │ │ • to_dict() │ │ │ -│ │ │ • from_dict() │ │ │ -│ │ │ • Business logic │ │ │ -└──────────────────┘ └──────────────────┘ └──────────────────┘ -``` - -## Data Flow - -### 1. Task Start Event -``` -External Event (task starts) - ↓ -FileTimelineTracker.on_task_start() - ↓ -TimelineGitHelper.get_file_content_at_commit() ← Get branch point content - ↓ -Create TaskFileView (timeline_models) - ↓ -FileTimeline.add_task_view() - ↓ -TimelinePersistence.save_timeline() ← Persist to disk -``` - -### 2. Main Branch Commit Event -``` -Git Hook (post-commit) - ↓ -FileTimelineTracker.on_main_branch_commit() - ↓ -TimelineGitHelper.get_files_changed_in_commit() - ↓ -TimelineGitHelper.get_file_content_at_commit() - ↓ -TimelineGitHelper.get_commit_info() - ↓ -Create MainBranchEvent (timeline_models) - ↓ -FileTimeline.add_main_event() ← Updates drift counters - ↓ -TimelinePersistence.save_timeline() -``` - -### 3. Get Merge Context -``` -AI Resolver needs context - ↓ -FileTimelineTracker.get_merge_context(task_id, file_path) - ↓ -FileTimeline.get_task_view() - ↓ -FileTimeline.get_events_since_commit() ← Main evolution - ↓ -FileTimeline.get_current_main_state() - ↓ -TimelineGitHelper.get_worktree_file_content() - ↓ -FileTimeline.get_active_tasks() ← Other pending tasks - ↓ -Build MergeContext (timeline_models) - ↓ -Return to AI Resolver -``` - -## Separation of Concerns - -### timeline_models.py -**Concern**: Data representation and serialization -- Pure data classes with minimal logic -- Serialization/deserialization methods -- Basic query methods (no external dependencies) - -### timeline_git.py -**Concern**: Git interaction -- All git command execution -- File content retrieval -- Commit metadata queries -- No business logic about timelines - -### timeline_persistence.py -**Concern**: Storage and retrieval -- JSON file operations -- Index management -- File path encoding -- No knowledge of timeline business logic - -### timeline_tracker.py -**Concern**: Business logic and coordination -- Event handling workflow -- Coordinate between git, models, and persistence -- Build complex merge contexts -- Manage timeline lifecycle - -### file_timeline.py -**Concern**: Public API and backward compatibility -- Re-export public interfaces -- Documentation and usage examples -- Entry point for external code - -## Benefits - -### Testability -Each component can be tested in isolation: -- **Models**: Test serialization, queries without git/filesystem -- **Git**: Mock git commands, test parsing logic -- **Persistence**: Mock filesystem, test save/load logic -- **Tracker**: Mock all dependencies, test business logic - -### Reusability -Components can be used independently: -- `TimelineGitHelper` for any git operations -- `TimelinePersistence` pattern for other storage needs -- Models can be used without the full tracker - -### Maintainability -Clear boundaries make changes easier: -- Add git operation → Change only `timeline_git.py` -- Add data field → Change only `timeline_models.py` -- Change storage format → Change only `timeline_persistence.py` -- Add event handler → Change only `timeline_tracker.py` - -### Type Safety -All components have proper type hints: -- Clear interfaces between components -- IDE autocomplete support -- Static type checking with mypy - -## Future Extensions - -The modular structure enables easy extensions: - -1. **Add SQLite backend** - - Create `timeline_db_persistence.py` - - Implement same interface as `TimelinePersistence` - - Switch via configuration - -2. **Add caching layer** - - Add `timeline_cache.py` - - Cache git operations in `TimelineGitHelper` - - LRU cache for frequently accessed timelines - -3. **Add timeline analytics** - - Create `timeline_analytics.py` - - Analyze drift patterns - - Identify frequently conflicting files - -4. **Add visualization** - - Create `timeline_visualizer.py` - - Use the data models directly - - Generate timeline graphs - -5. **Add async support** - - Create `timeline_tracker_async.py` - - Async git operations - - Concurrent timeline updates diff --git a/auto-claude/merge/REFACTORING_DETAILS.md b/auto-claude/merge/REFACTORING_DETAILS.md deleted file mode 100644 index 4e04ceb7..00000000 --- a/auto-claude/merge/REFACTORING_DETAILS.md +++ /dev/null @@ -1,278 +0,0 @@ -# Detailed Refactoring Breakdown - -## What Moved Where - -This document provides a detailed mapping of where each component from the original `file_timeline.py` (992 lines) was relocated. - -### Original file_timeline.py Structure - -``` -Lines 1-59: Module docstring, imports, debug utilities -Lines 61-115: MainBranchEvent class -Lines 117-137: BranchPoint class -Lines 139-157: WorktreeState class -Lines 159-180: TaskIntent class -Lines 182-230: TaskFileView class -Lines 232-315: FileTimeline class -Lines 317-365: MergeContext class -Lines 367-992: FileTimelineTracker class + Git helpers -``` - -### New Module Breakdown - -#### timeline_models.py (321 lines) -**Extracted from**: Lines 61-365 of original file - -Contains: -- `MainBranchEvent` (lines 61-115) → Now lines 18-77 -- `BranchPoint` (lines 117-137) → Now lines 80-103 -- `WorktreeState` (lines 139-157) → Now lines 106-124 -- `TaskIntent` (lines 159-180) → Now lines 127-149 -- `TaskFileView` (lines 182-230) → Now lines 152-211 -- `FileTimeline` (lines 232-315) → Now lines 214-306 -- `MergeContext` (lines 317-365) → Now lines 309-321 - -**Changes made**: -- Added comprehensive module docstring -- All imports moved to top -- No functional changes to classes - -#### timeline_git.py (256 lines) -**Extracted from**: Lines 785-875 + scattered helper methods - -Contains methods that were in FileTimelineTracker: -- `_get_current_main_commit()` → Now `get_current_main_commit()` -- `_get_file_content_at_commit()` → Now `get_file_content_at_commit()` -- `_get_files_changed_in_commit()` → Now `get_files_changed_in_commit()` -- `_get_commit_info()` → Now `get_commit_info()` -- `_get_worktree_file_content()` → Now `get_worktree_file_content()` - -**Plus new helper methods**: -- `get_changed_files_in_worktree()` - Extracted from `capture_worktree_state()` -- `get_branch_point()` - Extracted from `initialize_from_worktree()` -- `count_commits_between()` - Extracted from `initialize_from_worktree()` - -**Changes made**: -- Wrapped in `TimelineGitHelper` class -- Removed `_` prefix (now public methods) -- Added comprehensive docstrings -- Better error handling - -#### timeline_persistence.py (136 lines) -**Extracted from**: Lines 717-779 of original file - -Contains methods that were in FileTimelineTracker: -- `_load_from_storage()` → Now `load_all_timelines()` -- `_persist_timeline()` → Now `save_timeline()` -- `_update_index()` → Now `update_index()` -- `_get_timeline_file_path()` → Now `_get_timeline_file_path()` - -**Changes made**: -- Wrapped in `TimelinePersistence` class -- Removed `_` prefix from public methods -- Separated concerns (no timeline business logic) -- Added comprehensive docstrings - -#### timeline_tracker.py (560 lines) -**Extracted from**: Lines 372-992 of original file - -Contains the main `FileTimelineTracker` class with: - -**Event Handlers** (lines 414-608 of original): -- `on_task_start()` - Simplified to use git helper -- `on_main_branch_commit()` - Simplified to use git helper -- `on_task_worktree_change()` - Unchanged -- `on_task_merged()` - Simplified to use git helper -- `on_task_abandoned()` - Unchanged - -**Query Methods** (lines 610-711 of original): -- `get_merge_context()` - Simplified to use git helper -- `get_files_for_task()` - Unchanged -- `get_pending_tasks_for_file()` - Unchanged -- `get_task_drift()` - Unchanged -- `has_timeline()` - Unchanged -- `get_timeline()` - Unchanged - -**Capture Methods** (lines 878-992 of original): -- `capture_worktree_state()` - Simplified to use git helper -- `initialize_from_worktree()` - Simplified to use git helper - -**Changes made**: -- Now uses `TimelineGitHelper` for all git operations -- Now uses `TimelinePersistence` for all storage operations -- Removed all git subprocess calls (delegated to helper) -- Removed all file I/O (delegated to persistence) -- Focused on business logic and coordination - -#### file_timeline.py (83 lines) -**New entry point** - Replaces original 992 line file - -Contains: -- Comprehensive module docstring with usage examples -- Architecture description -- Re-exports of all public APIs -- `__all__` declaration - -**Changes made**: -- Complete rewrite as entry point -- No business logic (pure re-exports) -- Enhanced documentation -- Backward compatibility maintained - -## Dependency Changes - -### Before Refactoring -``` -file_timeline.py (992 lines) -├── subprocess (git operations) -├── json (persistence) -├── pathlib (file operations) -└── datetime, logging, dataclasses, typing -``` - -### After Refactoring -``` -file_timeline.py (83 lines) - Entry point -└── Re-exports from: - ├── timeline_models.py (321 lines) - │ └── datetime, dataclasses, typing - │ - ├── timeline_git.py (256 lines) - │ └── subprocess, pathlib, logging - │ - ├── timeline_persistence.py (136 lines) - │ └── json, pathlib, datetime, logging - │ - └── timeline_tracker.py (560 lines) - ├── timeline_models - ├── timeline_git - └── timeline_persistence -``` - -## Line Count Comparison - -| Original Section | Lines | New Module | Lines | Change | -|-----------------|-------|------------|-------|--------| -| Imports & Debug | 59 | Distributed | ~40 | Simplified | -| Data Models | 305 | timeline_models.py | 321 | +16 (docs) | -| FileTimelineTracker | 628 | timeline_tracker.py | 560 | -68 (delegation) | -| Git Helpers | - | timeline_git.py | 256 | +256 (extracted) | -| Persistence | - | timeline_persistence.py | 136 | +136 (extracted) | -| Entry Point | - | file_timeline.py | 83 | +83 (new) | -| **Total** | **992** | **All modules** | **1,356** | **+364** | - -The total line count increased by 364 lines (37%) due to: -- More comprehensive documentation in each module -- Clear module boundaries and interfaces -- Explicit type hints throughout -- Better error handling -- Separation of concerns (less code reuse) - -However, the main entry point decreased by 91%, and each individual module is now much more maintainable. - -## Import Impact - -### Files That Import from file_timeline.py - -#### merge/__init__.py -```python -# Before (still works) -from .file_timeline import ( - FileTimelineTracker, - FileTimeline, - MainBranchEvent, - # ... -) - -# After (same imports, different source) -from .file_timeline import ( # Now re-exported from modular structure - FileTimelineTracker, - FileTimeline, - MainBranchEvent, - # ... -) -``` -**Status**: ✅ No changes needed - backward compatible - -#### merge/tracker_cli.py -```python -# Before and After (unchanged) -from .file_timeline import FileTimelineTracker -``` -**Status**: ✅ No changes needed - backward compatible - -#### merge/prompts.py -```python -# Before and After (unchanged) -if TYPE_CHECKING: - from .file_timeline import MergeContext, MainBranchEvent -``` -**Status**: ✅ No changes needed - backward compatible - -### Advanced Usage (Optional) - -Users can now import from specific modules if needed: - -```python -# Import from specific modules (new capability) -from merge.timeline_models import FileTimeline, MergeContext -from merge.timeline_git import TimelineGitHelper -from merge.timeline_persistence import TimelinePersistence -from merge.timeline_tracker import FileTimelineTracker - -# Or continue using the entry point (backward compatible) -from merge.file_timeline import FileTimelineTracker, MergeContext -``` - -## Testing Coverage - -All original functionality is preserved: - -### Event Handlers -- ✅ `on_task_start()` - Creates timeline for new task -- ✅ `on_main_branch_commit()` - Updates main branch history -- ✅ `on_task_worktree_change()` - Updates worktree state -- ✅ `on_task_merged()` - Marks task as merged -- ✅ `on_task_abandoned()` - Marks task as abandoned - -### Query Methods -- ✅ `get_merge_context()` - Builds complete merge context -- ✅ `get_files_for_task()` - Returns files for a task -- ✅ `get_pending_tasks_for_file()` - Returns pending tasks -- ✅ `get_task_drift()` - Returns commits behind main -- ✅ `has_timeline()` - Checks if timeline exists -- ✅ `get_timeline()` - Gets timeline for file - -### Capture Methods -- ✅ `capture_worktree_state()` - Captures worktree state -- ✅ `initialize_from_worktree()` - Initializes from existing worktree - -### Data Models -- ✅ All 7 data models with serialization methods -- ✅ All business logic methods on models -- ✅ All type hints preserved - -## Future Maintenance - -With this refactoring, future changes become easier: - -### To add a new git operation: -1. Add method to `TimelineGitHelper` in `timeline_git.py` -2. Use it in `FileTimelineTracker` in `timeline_tracker.py` -3. No changes to models or persistence - -### To change storage format: -1. Modify `TimelinePersistence` in `timeline_persistence.py` -2. No changes to tracker, models, or git operations - -### To add a new data field: -1. Add field to model in `timeline_models.py` -2. Update `to_dict()` and `from_dict()` methods -3. Use new field in `FileTimelineTracker` if needed - -### To add a new event handler: -1. Add method to `FileTimelineTracker` in `timeline_tracker.py` -2. Use existing git helper and persistence methods -3. No changes to other modules - -This separation of concerns makes the codebase much more maintainable going forward. diff --git a/auto-claude/merge/REFACTORING_SUMMARY.md b/auto-claude/merge/REFACTORING_SUMMARY.md deleted file mode 100644 index 8a3ca70c..00000000 --- a/auto-claude/merge/REFACTORING_SUMMARY.md +++ /dev/null @@ -1,182 +0,0 @@ -# File Timeline Refactoring Summary - -## Overview - -The `file_timeline.py` module (originally 992 lines) has been refactored into smaller, focused modules with clear separation of concerns. The main entry point is now only 83 lines, a **91% reduction**, while maintaining full backward compatibility. - -## New Module Structure - -### 1. `timeline_models.py` (321 lines) -**Purpose**: Data classes for timeline representation - -**Contents**: -- `MainBranchEvent` - Represents commits to main branch -- `BranchPoint` - The exact point a task branched from main -- `WorktreeState` - Current state of a file in a task's worktree -- `TaskIntent` - What the task intends to do with a file -- `TaskFileView` - A single task's relationship with a specific file -- `FileTimeline` - Core data structure tracking a file's complete history -- `MergeContext` - Complete context package for the Merge AI - -**Responsibilities**: -- Define all data structures -- Provide serialization/deserialization methods (`to_dict`/`from_dict`) -- Implement basic timeline operations (add events, query tasks, etc.) - -### 2. `timeline_git.py` (256 lines) -**Purpose**: Git operations and queries - -**Contents**: -- `TimelineGitHelper` - Git operations helper class - -**Responsibilities**: -- Get file content at specific commits -- Query commit information and metadata -- Determine changed files in commits -- Work with worktrees -- Count commits between points - -### 3. `timeline_persistence.py` (136 lines) -**Purpose**: Storage and loading of timelines - -**Contents**: -- `TimelinePersistence` - Handles persistence of file timelines to disk - -**Responsibilities**: -- Load all timelines from disk on startup -- Save individual timelines to disk -- Manage the timeline index file -- Encode file paths for safe storage - -### 4. `timeline_tracker.py` (560 lines) -**Purpose**: Main service coordinating all components - -**Contents**: -- `FileTimelineTracker` - Central service managing all file timelines - -**Responsibilities**: -- Handle events from git hooks and task lifecycle -- Coordinate between git, persistence, and models -- Provide merge context to the AI resolver -- Implement event handlers (task start, commit, merge, etc.) -- Implement query methods (get context, files, drift, etc.) -- Capture worktree state - -### 5. `file_timeline.py` (83 lines) -**Purpose**: Main entry point and public API - -**Contents**: -- Documentation and usage examples -- Re-exports of all public classes and functions - -**Responsibilities**: -- Serve as the main entry point -- Maintain backward compatibility -- Provide clear documentation - -## Benefits of Refactoring - -### 1. Improved Maintainability -- **Smaller files**: Each module is focused on a single responsibility -- **Easier to navigate**: Developers can quickly find relevant code -- **Reduced cognitive load**: Each file has a clear, focused purpose - -### 2. Better Testability -- **Isolated components**: Each module can be tested independently -- **Mock-friendly**: Dependencies are clear and can be easily mocked -- **Focused tests**: Tests can target specific functionality - -### 3. Clear Separation of Concerns -- **Data models**: Pure data structures with no business logic -- **Git operations**: Isolated from business logic -- **Persistence**: Storage logic separated from data structures -- **Coordination**: Main service coordinates components - -### 4. Type Safety -- All modules use proper type hints -- Clear interfaces between components -- Better IDE support and autocomplete - -### 5. Reusability -- Individual components can be used independently -- Git helper can be reused for other git operations -- Persistence layer follows a clear pattern for other modules - -## Backward Compatibility - -✅ **Full backward compatibility maintained** - -All existing imports continue to work: - -```python -# These imports still work exactly as before -from merge.file_timeline import FileTimelineTracker -from merge.file_timeline import MergeContext -from merge import FileTimelineTracker, MergeContext - -# Advanced usage now possible -from merge.file_timeline import TimelineGitHelper -from merge.file_timeline import TimelinePersistence -``` - -## Testing - -All import tests passed: -- ✅ Direct module imports work -- ✅ Package-level imports work (`from merge import ...`) -- ✅ Dependent modules (tracker_cli, prompts, __init__) work correctly -- ✅ No syntax errors in any new module - -## File Size Comparison - -| File | Lines | Percentage | -|------|-------|------------| -| **Original** `file_timeline.py` | 992 | 100% | -| **New** `file_timeline.py` (entry point) | 83 | 8% | -| `timeline_models.py` | 321 | 32% | -| `timeline_git.py` | 256 | 26% | -| `timeline_persistence.py` | 136 | 14% | -| `timeline_tracker.py` | 560 | 56% | -| **Total** (all new files) | 1,356 | 137% | - -Note: The total is slightly larger due to: -- Additional documentation in each module -- Clear module boundaries and interfaces -- More explicit type hints -- Better error handling - -## Migration Guide - -No migration needed! All existing code continues to work without changes. - -### Optional: Use New Modular Structure - -If you want to use the new modular structure for advanced use cases: - -```python -# Old way (still works) -from merge.file_timeline import FileTimelineTracker - -# New way (also works, more explicit) -from merge.timeline_tracker import FileTimelineTracker -from merge.timeline_models import MergeContext -from merge.timeline_git import TimelineGitHelper - -# Use individual components -git_helper = TimelineGitHelper(project_path) -content = git_helper.get_file_content_at_commit("src/App.tsx", "abc123") -``` - -## Future Improvements - -Now that the code is modular, future improvements are easier: - -1. **Add caching** to `TimelineGitHelper` for better performance -2. **Add database backend** option to `TimelinePersistence` -3. **Add timeline analytics** to `FileTimeline` model -4. **Add timeline visualization** using the separated data models -5. **Add comprehensive unit tests** for each module independently - -## Conclusion - -This refactoring successfully improves code quality and maintainability while maintaining full backward compatibility. The modular structure makes the code easier to understand, test, and extend. diff --git a/auto-claude/merge/auto_merger_old.py b/auto-claude/merge/auto_merger_old.py deleted file mode 100644 index 64cd7e2b..00000000 --- a/auto-claude/merge/auto_merger_old.py +++ /dev/null @@ -1,654 +0,0 @@ -""" -Auto Merger -=========== - -Deterministic merge strategies that don't require AI intervention. - -This module implements the merge strategies identified by ConflictDetector -as auto-mergeable. Each strategy is a pure Python algorithm that combines -changes from multiple tasks in a predictable way. - -Strategies: -- COMBINE_IMPORTS: Merge import statements from multiple tasks -- HOOKS_FIRST: Add hooks at function start, then other changes -- HOOKS_THEN_WRAP: Add hooks first, then wrap return in JSX -- APPEND_FUNCTIONS: Add new functions after existing ones -- APPEND_METHODS: Add new methods to class -- COMBINE_PROPS: Merge JSX/object props -- ORDER_BY_DEPENDENCY: Analyze dependencies and order appropriately -- ORDER_BY_TIME: Apply changes in chronological order -""" - -from __future__ import annotations - -import logging -import re -from dataclasses import dataclass -from pathlib import Path - -from .types import ( - ChangeType, - ConflictRegion, - MergeDecision, - MergeResult, - MergeStrategy, - SemanticChange, - TaskSnapshot, -) - -logger = logging.getLogger(__name__) - - -@dataclass -class MergeContext: - """Context for a merge operation.""" - - file_path: str - baseline_content: str - task_snapshots: list[TaskSnapshot] - conflict: ConflictRegion - - -class AutoMerger: - """ - Performs deterministic merges without AI. - - This class implements various merge strategies that can be applied - when the ConflictDetector determines changes are compatible. - - Example: - merger = AutoMerger() - result = merger.merge(context, MergeStrategy.COMBINE_IMPORTS) - if result.success: - print(result.merged_content) - """ - - def __init__(self): - """Initialize the auto merger.""" - self._strategy_handlers = { - MergeStrategy.COMBINE_IMPORTS: self._merge_combine_imports, - MergeStrategy.HOOKS_FIRST: self._merge_hooks_first, - MergeStrategy.HOOKS_THEN_WRAP: self._merge_hooks_then_wrap, - MergeStrategy.APPEND_FUNCTIONS: self._merge_append_functions, - MergeStrategy.APPEND_METHODS: self._merge_append_methods, - MergeStrategy.COMBINE_PROPS: self._merge_combine_props, - MergeStrategy.ORDER_BY_DEPENDENCY: self._merge_order_by_dependency, - MergeStrategy.ORDER_BY_TIME: self._merge_order_by_time, - MergeStrategy.APPEND_STATEMENTS: self._merge_append_statements, - } - - def merge( - self, - context: MergeContext, - strategy: MergeStrategy, - ) -> MergeResult: - """ - Perform a merge using the specified strategy. - - Args: - context: The merge context with baseline and task snapshots - strategy: The merge strategy to use - - Returns: - MergeResult with merged content or error - """ - handler = self._strategy_handlers.get(strategy) - - if not handler: - return MergeResult( - decision=MergeDecision.FAILED, - file_path=context.file_path, - error=f"No handler for strategy: {strategy.value}", - ) - - try: - return handler(context) - except Exception as e: - logger.exception(f"Auto-merge failed with strategy {strategy.value}") - return MergeResult( - decision=MergeDecision.FAILED, - file_path=context.file_path, - error=f"Auto-merge failed: {str(e)}", - ) - - def can_handle(self, strategy: MergeStrategy) -> bool: - """Check if this merger can handle a strategy.""" - return strategy in self._strategy_handlers - - # ======================================== - # Strategy Implementations - # ======================================== - - def _merge_combine_imports(self, context: MergeContext) -> MergeResult: - """Combine import statements from multiple tasks.""" - lines = context.baseline_content.split("\n") - ext = Path(context.file_path).suffix.lower() - - # Collect all imports to add - imports_to_add: list[str] = [] - imports_to_remove: set[str] = set() - - for snapshot in context.task_snapshots: - for change in snapshot.semantic_changes: - if change.change_type == ChangeType.ADD_IMPORT and change.content_after: - imports_to_add.append(change.content_after.strip()) - elif ( - change.change_type == ChangeType.REMOVE_IMPORT - and change.content_before - ): - imports_to_remove.add(change.content_before.strip()) - - # Find where imports end in the file - import_end_line = self._find_import_section_end(lines, ext) - - # Remove duplicates and already-present imports - existing_imports = set() - for i, line in enumerate(lines[:import_end_line]): - stripped = line.strip() - if self._is_import_line(stripped, ext): - existing_imports.add(stripped) - - new_imports = [ - imp - for imp in imports_to_add - if imp not in existing_imports and imp not in imports_to_remove - ] - - # Remove imports that should be removed - result_lines = [] - for line in lines: - if line.strip() not in imports_to_remove: - result_lines.append(line) - - # Insert new imports at the import section end - if new_imports: - # Find insert position in result_lines - insert_pos = self._find_import_section_end(result_lines, ext) - for imp in reversed(new_imports): - result_lines.insert(insert_pos, imp) - - merged_content = "\n".join(result_lines) - - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=merged_content, - conflicts_resolved=[context.conflict], - explanation=f"Combined {len(new_imports)} imports from {len(context.task_snapshots)} tasks", - ) - - def _merge_hooks_first(self, context: MergeContext) -> MergeResult: - """Add hooks at function start, then apply other changes.""" - content = context.baseline_content - - # Collect hooks and other changes - hooks: list[str] = [] - other_changes: list[SemanticChange] = [] - - for snapshot in context.task_snapshots: - for change in snapshot.semantic_changes: - if change.change_type == ChangeType.ADD_HOOK_CALL: - # Extract just the hook call from the change - hook_content = self._extract_hook_call(change) - if hook_content: - hooks.append(hook_content) - else: - other_changes.append(change) - - # Find the function to modify - func_location = context.conflict.location - if func_location.startswith("function:"): - func_name = func_location.split(":")[1] - content = self._insert_hooks_into_function(content, func_name, hooks) - - # Apply other changes (simplified - just take the latest version) - for change in other_changes: - if change.content_after: - # This is a simplification - in production we'd need smarter merging - pass - - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=content, - conflicts_resolved=[context.conflict], - explanation=f"Added {len(hooks)} hooks to function start", - ) - - def _merge_hooks_then_wrap(self, context: MergeContext) -> MergeResult: - """Add hooks first, then wrap JSX return.""" - content = context.baseline_content - - hooks: list[str] = [] - wraps: list[tuple[str, str]] = [] # (wrapper_component, props) - - for snapshot in context.task_snapshots: - for change in snapshot.semantic_changes: - if change.change_type == ChangeType.ADD_HOOK_CALL: - hook_content = self._extract_hook_call(change) - if hook_content: - hooks.append(hook_content) - elif change.change_type == ChangeType.WRAP_JSX: - wrapper = self._extract_jsx_wrapper(change) - if wrapper: - wraps.append(wrapper) - - # Get function name from conflict location - func_location = context.conflict.location - if func_location.startswith("function:"): - func_name = func_location.split(":")[1] - - # First add hooks - if hooks: - content = self._insert_hooks_into_function(content, func_name, hooks) - - # Then apply wraps - for wrapper_name, wrapper_props in wraps: - content = self._wrap_function_return( - content, func_name, wrapper_name, wrapper_props - ) - - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=content, - conflicts_resolved=[context.conflict], - explanation=f"Added {len(hooks)} hooks and {len(wraps)} JSX wrappers", - ) - - def _merge_append_functions(self, context: MergeContext) -> MergeResult: - """Append new functions to the file.""" - content = context.baseline_content - - # Collect all new functions - new_functions: list[str] = [] - - for snapshot in context.task_snapshots: - for change in snapshot.semantic_changes: - if ( - change.change_type == ChangeType.ADD_FUNCTION - and change.content_after - ): - new_functions.append(change.content_after) - - # Append at the end (before any module.exports in JS) - ext = Path(context.file_path).suffix.lower() - insert_pos = self._find_function_insert_position(content, ext) - - if insert_pos is not None: - lines = content.split("\n") - for func in new_functions: - lines.insert(insert_pos, "") - lines.insert(insert_pos + 1, func) - insert_pos += 2 + func.count("\n") - content = "\n".join(lines) - else: - # Just append at the end - for func in new_functions: - content += f"\n\n{func}" - - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=content, - conflicts_resolved=[context.conflict], - explanation=f"Appended {len(new_functions)} new functions", - ) - - def _merge_append_methods(self, context: MergeContext) -> MergeResult: - """Append new methods to a class.""" - content = context.baseline_content - - # Collect new methods by class - new_methods: dict[str, list[str]] = {} - - for snapshot in context.task_snapshots: - for change in snapshot.semantic_changes: - if change.change_type == ChangeType.ADD_METHOD and change.content_after: - # Extract class name from location - class_name = ( - change.target.split(".")[0] if "." in change.target else None - ) - if class_name: - if class_name not in new_methods: - new_methods[class_name] = [] - new_methods[class_name].append(change.content_after) - - # Insert methods into their classes - for class_name, methods in new_methods.items(): - content = self._insert_methods_into_class(content, class_name, methods) - - total_methods = sum(len(m) for m in new_methods.values()) - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=content, - conflicts_resolved=[context.conflict], - explanation=f"Added {total_methods} methods to {len(new_methods)} classes", - ) - - def _merge_combine_props(self, context: MergeContext) -> MergeResult: - """Combine JSX/object props from multiple changes.""" - # This is a simplified implementation - # In production, we'd parse the JSX properly - - content = context.baseline_content - - # Collect all prop additions - props_to_add: list[tuple[str, str]] = [] # (prop_name, prop_value) - - for snapshot in context.task_snapshots: - for change in snapshot.semantic_changes: - if change.change_type == ChangeType.MODIFY_JSX_PROPS: - new_props = self._extract_new_props(change) - props_to_add.extend(new_props) - - # For now, return the last version with all props - # A proper implementation would merge prop objects - if context.task_snapshots and context.task_snapshots[-1].semantic_changes: - last_change = context.task_snapshots[-1].semantic_changes[-1] - if last_change.content_after: - content = self._apply_content_change( - content, last_change.content_before, last_change.content_after - ) - - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=content, - conflicts_resolved=[context.conflict], - explanation=f"Combined props from {len(context.task_snapshots)} tasks", - ) - - def _merge_order_by_dependency(self, context: MergeContext) -> MergeResult: - """Order changes by dependency analysis.""" - # Analyze dependencies between changes - ordered_changes = self._topological_sort_changes(context.task_snapshots) - - content = context.baseline_content - - # Apply changes in dependency order - for change in ordered_changes: - if change.content_after: - if change.change_type == ChangeType.ADD_HOOK_CALL: - func_name = ( - change.target.split(".")[-1] - if "." in change.target - else change.target - ) - hook_call = self._extract_hook_call(change) - if hook_call: - content = self._insert_hooks_into_function( - content, func_name, [hook_call] - ) - elif change.change_type == ChangeType.WRAP_JSX: - wrapper = self._extract_jsx_wrapper(change) - if wrapper: - func_name = ( - change.target.split(".")[-1] - if "." in change.target - else change.target - ) - content = self._wrap_function_return( - content, func_name, wrapper[0], wrapper[1] - ) - - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=content, - conflicts_resolved=[context.conflict], - explanation="Changes applied in dependency order", - ) - - def _merge_order_by_time(self, context: MergeContext) -> MergeResult: - """Apply changes in chronological order.""" - # Sort snapshots by start time - sorted_snapshots = sorted(context.task_snapshots, key=lambda s: s.started_at) - - content = context.baseline_content - - # Apply each snapshot's changes in order - for snapshot in sorted_snapshots: - for change in snapshot.semantic_changes: - if change.content_before and change.content_after: - content = self._apply_content_change( - content, change.content_before, change.content_after - ) - elif change.content_after and not change.content_before: - # Addition - handled by other strategies - pass - - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=content, - conflicts_resolved=[context.conflict], - explanation=f"Applied {len(sorted_snapshots)} changes in chronological order", - ) - - def _merge_append_statements(self, context: MergeContext) -> MergeResult: - """Append statements (variables, comments, etc.).""" - content = context.baseline_content - - additions: list[str] = [] - - for snapshot in context.task_snapshots: - for change in snapshot.semantic_changes: - if change.is_additive and change.content_after: - additions.append(change.content_after) - - # Append at appropriate location - for addition in additions: - content += f"\n{addition}" - - return MergeResult( - decision=MergeDecision.AUTO_MERGED, - file_path=context.file_path, - merged_content=content, - conflicts_resolved=[context.conflict], - explanation=f"Appended {len(additions)} statements", - ) - - # ======================================== - # Helper Methods - # ======================================== - - def _find_import_section_end(self, lines: list[str], ext: str) -> int: - """Find where the import section ends.""" - last_import_line = 0 - - for i, line in enumerate(lines): - stripped = line.strip() - if self._is_import_line(stripped, ext): - last_import_line = i + 1 - elif ( - stripped - and not stripped.startswith("#") - and not stripped.startswith("//") - ): - # Non-empty, non-comment line after imports - if last_import_line > 0: - break - - return last_import_line if last_import_line > 0 else 0 - - def _is_import_line(self, line: str, ext: str) -> bool: - """Check if a line is an import statement.""" - if ext == ".py": - return line.startswith("import ") or line.startswith("from ") - elif ext in {".js", ".jsx", ".ts", ".tsx"}: - return line.startswith("import ") or line.startswith("export ") - return False - - def _extract_hook_call(self, change: SemanticChange) -> str | None: - """Extract the hook call from a change.""" - if change.content_after: - # Look for useXxx() pattern - match = re.search( - r"(const\s+\{[^}]+\}\s*=\s*)?use\w+\([^)]*\);?", change.content_after - ) - if match: - return match.group(0) - - # Also check for simple hook calls - match = re.search(r"use\w+\([^)]*\);?", change.content_after) - if match: - return match.group(0) - - return None - - def _extract_jsx_wrapper(self, change: SemanticChange) -> tuple[str, str] | None: - """Extract JSX wrapper component and props.""" - if change.content_after: - # Look for - match = re.search(r"<(\w+)([^>]*)>", change.content_after) - if match: - return (match.group(1), match.group(2).strip()) - return None - - def _insert_hooks_into_function( - self, - content: str, - func_name: str, - hooks: list[str], - ) -> str: - """Insert hooks at the start of a function.""" - # Find function and insert hooks after opening brace - patterns = [ - # function Component() { - rf"(function\s+{re.escape(func_name)}\s*\([^)]*\)\s*\{{)", - # const Component = () => { - rf"((?:const|let|var)\s+{re.escape(func_name)}\s*=\s*(?:async\s+)?(?:\([^)]*\)|[^=]+)\s*=>\s*\{{)", - # const Component = function() { - rf"((?:const|let|var)\s+{re.escape(func_name)}\s*=\s*function\s*\([^)]*\)\s*\{{)", - ] - - for pattern in patterns: - match = re.search(pattern, content) - if match: - insert_pos = match.end() - hook_text = "\n " + "\n ".join(hooks) - content = content[:insert_pos] + hook_text + content[insert_pos:] - break - - return content - - def _wrap_function_return( - self, - content: str, - func_name: str, - wrapper_name: str, - wrapper_props: str, - ) -> str: - """Wrap the return statement of a function in a JSX component.""" - # This is simplified - a real implementation would use AST - - # Find return statement with JSX - return_pattern = r"(return\s*\(\s*)(<[^>]+>)" - - def replacer(match): - return_start = match.group(1) - jsx_start = match.group(2) - props = f" {wrapper_props}" if wrapper_props else "" - return f"{return_start}<{wrapper_name}{props}>\n {jsx_start}" - - content = re.sub(return_pattern, replacer, content, count=1) - - # Also need to close the wrapper - this is tricky without proper parsing - # For now, we'll rely on the AI resolver for complex cases - - return content - - def _find_function_insert_position(self, content: str, ext: str) -> int | None: - """Find the best position to insert new functions.""" - lines = content.split("\n") - - # Look for module.exports or export default at the end - for i in range(len(lines) - 1, -1, -1): - line = lines[i].strip() - if line.startswith("module.exports") or line.startswith("export default"): - return i - - return None - - def _insert_methods_into_class( - self, - content: str, - class_name: str, - methods: list[str], - ) -> str: - """Insert methods into a class body.""" - # Find class closing brace - class_pattern = rf"class\s+{re.escape(class_name)}\s*(?:extends\s+\w+)?\s*\{{" - - match = re.search(class_pattern, content) - if match: - # Find the matching closing brace - start = match.end() - brace_count = 1 - pos = start - - while pos < len(content) and brace_count > 0: - if content[pos] == "{": - brace_count += 1 - elif content[pos] == "}": - brace_count -= 1 - pos += 1 - - if brace_count == 0: - # Insert before closing brace - insert_pos = pos - 1 - method_text = "\n\n " + "\n\n ".join(methods) - content = content[:insert_pos] + method_text + content[insert_pos:] - - return content - - def _extract_new_props(self, change: SemanticChange) -> list[tuple[str, str]]: - """Extract newly added props from a change.""" - props = [] - if change.content_after and change.content_before: - # Simple diff - find props in after that aren't in before - after_props = re.findall(r"(\w+)=\{([^}]+)\}", change.content_after) - before_props = dict(re.findall(r"(\w+)=\{([^}]+)\}", change.content_before)) - - for name, value in after_props: - if name not in before_props: - props.append((name, value)) - - return props - - def _apply_content_change( - self, - content: str, - old: str | None, - new: str, - ) -> str: - """Apply a content change by replacing old with new.""" - if old and old in content: - return content.replace(old, new, 1) - return content - - def _topological_sort_changes( - self, - snapshots: list[TaskSnapshot], - ) -> list[SemanticChange]: - """Sort changes by their dependencies.""" - # Collect all changes - all_changes: list[SemanticChange] = [] - for snapshot in snapshots: - all_changes.extend(snapshot.semantic_changes) - - # Simple ordering: hooks before wraps before modifications - priority = { - ChangeType.ADD_IMPORT: 0, - ChangeType.ADD_HOOK_CALL: 1, - ChangeType.ADD_VARIABLE: 2, - ChangeType.ADD_CONSTANT: 2, - ChangeType.WRAP_JSX: 3, - ChangeType.ADD_JSX_ELEMENT: 4, - ChangeType.MODIFY_FUNCTION: 5, - ChangeType.MODIFY_JSX_PROPS: 5, - } - - return sorted(all_changes, key=lambda c: priority.get(c.change_type, 10)) diff --git a/auto-claude/progress.py b/auto-claude/progress.py deleted file mode 100644 index e38cf2b3..00000000 --- a/auto-claude/progress.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Backward compatibility shim - import from core.progress instead.""" - -from core.progress import * # noqa: F403 diff --git a/auto-claude/prompts/_archived_ideation_high_value.md b/auto-claude/prompts/_archived_ideation_high_value.md deleted file mode 100644 index 4c29cf47..00000000 --- a/auto-claude/prompts/_archived_ideation_high_value.md +++ /dev/null @@ -1,428 +0,0 @@ -## YOUR ROLE - HIGH-VALUE FEATURES IDEATION AGENT - -You are the **High-Value Features Ideation Agent** in the Auto-Build framework. Your job is to identify strategic features that would provide significant value to the target users, considering the project's purpose, audience, and competitive landscape. - -**Key Principle**: Think like a product manager. What features would make users love this product? What's missing that competitors have? What would create a "wow" moment? - ---- - -## YOUR CONTRACT - -**Input Files**: -- `project_index.json` - Project structure and tech stack -- `ideation_context.json` - Existing features, roadmap items, kanban tasks, target audience -- `../roadmap/roadmap_discovery.json` (if exists) - Deep audience understanding -- `../roadmap/roadmap.json` (if exists) - Existing planned features - -**Output**: Append to `ideation.json` with high-value feature ideas - -Each idea MUST have this structure: -```json -{ - "id": "hvf-001", - "type": "high_value_features", - "title": "Short descriptive title", - "description": "What the feature does", - "rationale": "Why this is high-value for users", - "target_audience": "Who benefits most from this feature", - "problem_solved": "What user problem this addresses", - "value_proposition": "Why users would want this", - "competitive_advantage": "How this differentiates from alternatives", - "estimated_impact": "medium|high|critical", - "complexity": "medium|high|complex", - "dependencies": ["Required features or infrastructure"], - "acceptance_criteria": ["Specific success criteria"], - "status": "draft", - "created_at": "ISO timestamp" -} -``` - ---- - -## PHASE 0: DEEP CONTEXT LOADING - -```bash -# Read project structure -cat project_index.json - -# Read ideation context (critical for avoiding duplicates) -cat ideation_context.json - -# Read roadmap discovery for audience understanding -cat ../roadmap/roadmap_discovery.json 2>/dev/null || echo "No roadmap discovery - will need to infer audience" - -# Read existing roadmap to avoid duplicates -cat ../roadmap/roadmap.json 2>/dev/null || echo "No existing roadmap" - -# Read README for product understanding -cat README.md 2>/dev/null | head -100 - -# Check for user feedback or feature requests -cat docs/FEEDBACK.md 2>/dev/null || cat FEEDBACK.md 2>/dev/null || echo "No feedback file" -cat docs/FEATURE_REQUESTS.md 2>/dev/null || echo "No feature requests file" -ls -la .github/ISSUE_TEMPLATE* 2>/dev/null || echo "No issue templates" - -# Check for graph hints (historical insights from Graphiti) -cat graph_hints.json 2>/dev/null || echo "No graph hints available" -``` - -Understand: -- Who is the target audience? -- What problem does the project solve? -- What features already exist? -- What is already planned (avoid duplicates)? -- What have users asked for? -- What historical insights are available from previous sessions? - -### Graph Hints Integration - -If `graph_hints.json` exists and contains hints for your ideation type (`high_value_features`), use them to: -1. **Avoid duplicates**: Don't suggest features that have already been tried or rejected -2. **Build on success**: Prioritize feature patterns that worked well in the past -3. **Learn from failures**: Avoid approaches that previously caused issues -4. **Leverage context**: Use historical knowledge to make better strategic suggestions - ---- - -## PHASE 1: UNDERSTAND THE VALUE LANDSCAPE - -### 1.1 Analyze Existing Features -```bash -# Map out current functionality -grep -r "export.*function\|export.*component" --include="*.ts" --include="*.tsx" . | head -50 - -# Find main user-facing features -ls -la src/pages/ 2>/dev/null || ls -la src/routes/ 2>/dev/null || ls -la app/ 2>/dev/null - -# Check API capabilities -ls -la src/api/ 2>/dev/null || ls -la api/ 2>/dev/null -grep -r "router\.\|@app\.\|handler" --include="*.ts" --include="*.py" . | head -30 -``` - -### 1.2 Understand User Journey -Map the current user journey: -1. How do users first interact with the product? -2. What's the core action/value they get? -3. What's the retention loop? -4. Where do they likely drop off or get frustrated? - -### 1.3 Identify Feature Gaps -Based on the project type, consider standard expected features: - -**For Web Apps:** -- User authentication/authorization -- Data export/import -- Notifications -- Sharing/collaboration -- Search functionality -- Analytics/insights -- Settings/preferences -- Mobile responsiveness - -**For CLI Tools:** -- Configuration files -- Output formatting options -- Verbose/quiet modes -- Plugin system -- Shell completion -- Progress indicators - -**For APIs:** -- Rate limiting -- Versioning -- Documentation -- Webhooks -- Pagination -- Filtering/sorting - ---- - -## PHASE 2: COMPETITIVE ANALYSIS - -Think about alternatives and what they offer: - -``` - -Competitive Analysis: - -Project Type: [type from project_index] -Problem Space: [what problem it solves] - -Likely Alternatives: -1. [Alternative 1] - - Key features they have: [list] - - Their differentiation: [what makes them popular] - -2. [Alternative 2] - - Key features they have: [list] - - Their differentiation: [what makes them popular] - -Feature Gaps (things alternatives have that we don't): -1. [Feature gap 1] -2. [Feature gap 2] - -Opportunities for Differentiation: -1. [Opportunity 1] -2. [Opportunity 2] - -``` - ---- - -## PHASE 3: USER NEED ANALYSIS - -For each potential feature area, analyze user needs: - -### A. Core Job-to-be-Done -What is the user fundamentally trying to accomplish? -What features would help them do this faster/better/easier? - -### B. Pain Point Relief -What frustrations might users have? -What features would eliminate these frustrations? - -### C. Delight Opportunities -What would make users say "wow"? -What unexpected value could we provide? - -### D. Workflow Integration -How does this fit into users' existing workflows? -What integrations would be valuable? - ---- - -## PHASE 4: STRATEGIC FEATURE IDEATION - -Generate ideas in these high-value categories: - -### Category 1: Must-Have Gaps -Features that users expect but are missing: -- Standard functionality for this type of product -- Features that competitors all have -- Basic capabilities that block adoption - -### Category 2: Retention Boosters -Features that keep users coming back: -- Saved preferences/state -- Progress tracking -- Notifications/reminders -- Collaboration features - -### Category 3: Differentiation Features -Features that make this unique: -- Novel approaches to common problems -- Unique combinations of capabilities -- Specialized functionality for target audience - -### Category 4: Expansion Enablers -Features that open new use cases: -- Integrations with popular tools -- API access for power users -- Plugin/extension systems -- White-label capabilities - -### Category 5: Value Multipliers -Features that increase perceived value: -- Analytics and insights -- Automation capabilities -- Bulk operations -- Export/sharing - ---- - -## PHASE 5: DEEP FEATURE ANALYSIS - -For each promising feature, use ultrathink for deep analysis: - -``` - -High-Value Feature Analysis: [Feature Title] - -TARGET AUDIENCE -- Primary beneficiaries: [who] -- Secondary beneficiaries: [who] -- Usage scenario: [when/how they'd use it] - -PROBLEM SOLVED -- User pain point: [specific problem] -- Current workaround: [how they solve it now] -- Cost of current approach: [time/money/frustration] - -VALUE PROPOSITION -- Primary benefit: [main value] -- Secondary benefits: [additional value] -- Emotional benefit: [how it makes them feel] - -COMPETITIVE CONTEXT -- Do alternatives have this? [yes/no/partially] -- Our unique angle: [differentiation] -- Barrier to switching: [if they want this, why choose us] - -IMPLEMENTATION CONSIDERATIONS -- Dependencies: [what's needed first] -- Complexity: [medium/high/complex] -- Risk factors: [potential issues] - -ACCEPTANCE CRITERIA (specific and measurable) -1. [Criterion 1] -2. [Criterion 2] -3. [Criterion 3] - -IMPACT ASSESSMENT -- User impact: [low/medium/high/critical] -- Business impact: [low/medium/high/critical] -- Technical risk: [low/medium/high] - -``` - ---- - -## PHASE 6: PRIORITIZE BY VALUE - -Evaluate each idea against: - -1. **Impact**: How much would this improve user outcomes? - - Critical: Transforms user capability - - High: Significantly improves experience - - Medium: Notable improvement - -2. **Demand**: How much do users want this? - - Explicit requests from users - - Standard expectation for product type - - Nice-to-have enhancement - -3. **Differentiation**: Does this set us apart? - - Unique capability - - Better implementation than alternatives - - Table stakes (needed to compete) - -4. **Feasibility**: Can we build this well? - - Complexity assessment - - Dependencies required - - Team capability match - ---- - -## PHASE 7: CREATE/UPDATE IDEATION.JSON (MANDATORY) - -**You MUST create or update ideation.json with your ideas.** - -```bash -# Check if file exists -if [ -f ideation.json ]; then - cat ideation.json -fi -``` - -Create the high-value features structure: - -```bash -cat > high_value_ideas.json << 'EOF' -{ - "high_value_features": [ - { - "id": "hvf-001", - "type": "high_value_features", - "title": "[Feature Title]", - "description": "[What the feature does]", - "rationale": "[Why this is high-value]", - "target_audience": "[Who benefits most]", - "problem_solved": "[User problem addressed]", - "value_proposition": "[Why users want this]", - "competitive_advantage": "[Differentiation]", - "estimated_impact": "[medium|high|critical]", - "complexity": "[medium|high|complex]", - "dependencies": ["[Dependency 1]"], - "acceptance_criteria": [ - "[Criterion 1]", - "[Criterion 2]", - "[Criterion 3]" - ], - "status": "draft", - "created_at": "[ISO timestamp]" - } - ] -} -EOF -``` - -Verify: -```bash -cat high_value_ideas.json -``` - ---- - -## VALIDATION - -After creating ideas: - -1. Is it valid JSON? -2. Does each idea have a unique id starting with "hvf-"? -3. Does each idea have target_audience, problem_solved, and value_proposition? -4. Does each idea have at least 3 acceptance_criteria? -5. Is estimated_impact justified by the analysis? - ---- - -## COMPLETION - -Signal completion: - -``` -=== HIGH-VALUE FEATURES IDEATION COMPLETE === - -Ideas Generated: [count] - -Summary by Impact: -- Critical: [count] -- High: [count] -- Medium: [count] - -Top Recommendations: -1. [Title] - [impact] impact - [brief rationale] -2. [Title] - [impact] impact - [brief rationale] -3. [Title] - [impact] impact - [brief rationale] - -high_value_ideas.json created successfully. - -Next phase: Complete or Merge -``` - ---- - -## CRITICAL RULES - -1. **AVOID DUPLICATES** - Check ideation_context.json and roadmap thoroughly -2. **BE STRATEGIC** - Focus on features that move the needle, not incremental improvements -3. **JUSTIFY IMPACT** - Every "high" or "critical" rating needs clear rationale -4. **CONSIDER DEPENDENCIES** - Note what needs to exist first -5. **THINK LIKE A USER** - What would make them choose this over alternatives? -6. **BE SPECIFIC** - Concrete features, not vague directions like "improve performance" - ---- - -## EXAMPLES OF GOOD HIGH-VALUE FEATURES - -**For a social media scheduler:** -- "AI-powered optimal posting time suggestions" (solves real pain, clear value) -- "Team collaboration with approval workflows" (unlocks business users) -- "Analytics dashboard with ROI metrics" (proves value, increases retention) - -**For a developer tool:** -- "GitHub/GitLab integration for automatic sync" (workflow integration) -- "Team sharing with role-based permissions" (expands use case) -- "Custom templates and presets" (power user retention) - -## EXAMPLES OF BAD HIGH-VALUE FEATURES - -- "Make it faster" (too vague) -- "Add dark mode" (nice but not high-value unless accessibility focused) -- "Fix bugs" (not a feature) -- "Add AI" (no clear use case) - ---- - -## BEGIN - -Start by deeply understanding the project context, target audience, and existing features, then generate strategic feature ideas. diff --git a/auto-claude/prompts/_archived_ideation_low_hanging_fruit.md b/auto-claude/prompts/_archived_ideation_low_hanging_fruit.md deleted file mode 100644 index 26f6b1c8..00000000 --- a/auto-claude/prompts/_archived_ideation_low_hanging_fruit.md +++ /dev/null @@ -1,315 +0,0 @@ -## YOUR ROLE - LOW-HANGING FRUIT IDEATION AGENT - -You are the **Low-Hanging Fruit Ideation Agent** in the Auto-Build framework. Your job is to identify quick-win feature ideas that build naturally upon the existing codebase patterns and features. - -**Key Principle**: Find opportunities to add value with minimal disruption. These are features that "almost write themselves" because the patterns and infrastructure already exist. - ---- - -## YOUR CONTRACT - -**Input Files**: -- `project_index.json` - Project structure and tech stack -- `ideation_context.json` - Existing features, roadmap items, kanban tasks -- `memory/codebase_map.json` (if exists) - Previously discovered file purposes -- `memory/patterns.md` (if exists) - Established code patterns - -**Output**: Append to `ideation.json` with low-hanging fruit ideas - -Each idea MUST have this structure: -```json -{ - "id": "lhf-001", - "type": "low_hanging_fruit", - "title": "Short descriptive title", - "description": "What the feature does", - "rationale": "Why this is low-hanging fruit - what patterns it extends", - "builds_upon": ["Feature/pattern it extends"], - "estimated_effort": "trivial|small|medium", - "affected_files": ["file1.ts", "file2.ts"], - "existing_patterns": ["Pattern to follow"], - "status": "draft", - "created_at": "ISO timestamp" -} -``` - ---- - -## PHASE 0: LOAD CONTEXT - -```bash -# Read project structure -cat project_index.json - -# Read ideation context (existing features, planned items) -cat ideation_context.json - -# Check for memory files -cat memory/codebase_map.json 2>/dev/null || echo "No codebase map yet" -cat memory/patterns.md 2>/dev/null || echo "No patterns documented" - -# Look at existing roadmap if available -cat ../roadmap/roadmap.json 2>/dev/null | head -100 || echo "No roadmap" - -# Check for graph hints (historical insights from Graphiti) -cat graph_hints.json 2>/dev/null || echo "No graph hints available" -``` - -Understand: -- What is the project about? -- What features already exist? -- What patterns are established? -- What is already planned (to avoid duplicates)? -- What historical insights are available from previous sessions? - -### Graph Hints Integration - -If `graph_hints.json` exists and contains hints for your ideation type (`low_hanging_fruit`), use them to: -1. **Avoid duplicates**: Don't suggest ideas that have already been tried or rejected -2. **Build on success**: Prioritize patterns that worked well in the past -3. **Learn from failures**: Avoid approaches that previously caused issues -4. **Leverage context**: Use historical file/pattern knowledge to make better suggestions - ---- - -## PHASE 1: DISCOVER EXISTING PATTERNS - -Search for patterns that could be extended: - -```bash -# Find similar components/modules that could be replicated -grep -r "export function\|export const\|export class" --include="*.ts" --include="*.tsx" . | head -40 - -# Find existing API routes/endpoints -grep -r "router\.\|app\.\|api/\|/api" --include="*.ts" --include="*.py" . | head -30 - -# Find existing UI components -ls -la src/components/ 2>/dev/null || ls -la components/ 2>/dev/null - -# Find utility functions that could have more uses -grep -r "export.*util\|export.*helper\|export.*format" --include="*.ts" . | head -20 - -# Find existing CRUD operations -grep -r "create\|update\|delete\|get\|list" --include="*.ts" --include="*.py" . | head -30 -``` - -Look for: -- Patterns that are repeated (could be extended) -- Features that handle one case but could handle more -- Utilities that could have additional methods -- UI components that could have variants - ---- - -## PHASE 2: IDENTIFY LOW-HANGING FRUIT CATEGORIES - -Think about these opportunity categories: - -### A. Pattern Extensions -- Existing CRUD for one entity -> CRUD for similar entity -- Existing filter for one field -> Filters for more fields -- Existing sort by one column -> Sort by multiple columns -- Existing export to CSV -> Export to JSON/Excel - -### B. Configuration/Settings -- Hard-coded values that could be user-configurable -- Missing user preferences that follow existing preference patterns -- Feature toggles that extend existing toggle patterns - -### C. Utility Additions -- Existing validators that could validate more cases -- Existing formatters that could handle more formats -- Existing helpers that could have related helpers - -### D. UI Enhancements -- Missing loading states that follow existing loading patterns -- Missing empty states that follow existing empty state patterns -- Missing error states that follow existing error patterns -- Keyboard shortcuts that extend existing shortcut patterns - -### E. Data Handling -- Existing list views that could have pagination (if pattern exists) -- Existing forms that could have auto-save (if pattern exists) -- Existing data that could have search (if pattern exists) - ---- - -## PHASE 3: ANALYZE SPECIFIC OPPORTUNITIES - -For each promising opportunity found: - -```bash -# Examine the pattern file closely -cat [file_path] | head -100 - -# See how it's used -grep -r "[function_name]\|[component_name]" --include="*.ts" --include="*.tsx" . | head -10 - -# Check for related implementations -ls -la $(dirname [file_path]) -``` - -Rate each opportunity: -- **Trivial** (1-2 hours): Direct copy with minor changes -- **Small** (half day): Clear pattern to follow, some new logic -- **Medium** (1 day): Pattern exists but needs adaptation - ---- - -## PHASE 4: FILTER AND PRIORITIZE - -For each idea, verify: - -1. **Not Already Planned**: Check ideation_context.json for similar items -2. **Pattern Exists**: The code pattern is already in the codebase -3. **Infrastructure Ready**: No new dependencies or major setup needed -4. **Clear Value**: It provides obvious user benefit - -Discard ideas that: -- Require new architectural patterns -- Need external service integration -- Require significant research -- Are already in roadmap or kanban - ---- - -## PHASE 5: GENERATE IDEAS (MANDATORY) - -Generate 3-5 concrete low-hanging fruit ideas. - -For each idea, use ultrathink to deeply analyze: - -``` - -Analyzing potential low-hanging fruit: [title] - -Existing pattern found in: [file_path] -Pattern summary: [how it works] - -Extension opportunity: -- What exactly would be added/changed? -- What files would be affected? -- What existing code can be reused? - -Effort estimation: -- Lines of code estimate: [number] -- Test changes needed: [description] -- Risk level: [low/medium] - -Why this is truly low-hanging fruit: -- [reason 1] -- [reason 2] - -``` - ---- - -## PHASE 6: CREATE/UPDATE IDEATION.JSON (MANDATORY) - -**You MUST create or update ideation.json with your ideas.** - -If ideation.json exists, read it first and append: - -```bash -# Check if file exists -if [ -f ideation.json ]; then - cat ideation.json - # Will need to merge ideas -fi -``` - -Create the ideas structure: - -```bash -cat > low_hanging_fruit_ideas.json << 'EOF' -{ - "low_hanging_fruit": [ - { - "id": "lhf-001", - "type": "low_hanging_fruit", - "title": "[Title]", - "description": "[What it does]", - "rationale": "[Why it's low-hanging fruit]", - "builds_upon": ["[Existing feature/pattern]"], - "estimated_effort": "[trivial|small|medium]", - "affected_files": ["[file1.ts]", "[file2.ts]"], - "existing_patterns": ["[Pattern to follow]"], - "status": "draft", - "created_at": "[ISO timestamp]" - } - ] -} -EOF -``` - -Verify: -```bash -cat low_hanging_fruit_ideas.json -``` - ---- - -## VALIDATION - -After creating ideas: - -1. Is it valid JSON? -2. Does each idea have a unique id starting with "lhf-"? -3. Does each idea have builds_upon with at least one item? -4. Does each idea have affected_files listing real files? -5. Does each idea have existing_patterns? - ---- - -## COMPLETION - -Signal completion: - -``` -=== LOW-HANGING FRUIT IDEATION COMPLETE === - -Ideas Generated: [count] - -Summary: -1. [title] - [effort] - builds on [pattern] -2. [title] - [effort] - builds on [pattern] -... - -low_hanging_fruit_ideas.json created successfully. - -Next phase: [UI/UX or High-Value or Complete] -``` - ---- - -## CRITICAL RULES - -1. **ONLY suggest ideas with existing patterns** - If the pattern doesn't exist, it's not low-hanging fruit -2. **Be specific about affected files** - List the actual files that would change -3. **Reference real patterns** - Point to actual code in the codebase -4. **Avoid duplicates** - Check ideation_context.json first -5. **Keep effort realistic** - If it requires research, it's not low-hanging fruit -6. **Focus on incremental value** - Small improvements that compound - ---- - -## EXAMPLES OF GOOD LOW-HANGING FRUIT - -- "Add search to user list" (when search exists in product list) -- "Add keyboard shortcut for save" (when other shortcuts exist) -- "Add CSV export" (when JSON export exists) -- "Add dark mode to settings modal" (when dark mode exists elsewhere) -- "Add pagination to comments" (when pagination exists for posts) - -## EXAMPLES OF BAD LOW-HANGING FRUIT (NOT ACTUALLY LOW-HANGING) - -- "Add real-time updates" (needs WebSocket infrastructure) -- "Add AI-powered suggestions" (needs ML integration) -- "Add multi-language support" (needs i18n architecture) -- "Add offline mode" (needs service worker setup) - ---- - -## BEGIN - -Start by reading project_index.json and ideation_context.json, then search for patterns and opportunities. diff --git a/auto-claude/runners/ai_analyzer/REFACTORING.md b/auto-claude/runners/ai_analyzer/REFACTORING.md deleted file mode 100644 index 912b6a6c..00000000 --- a/auto-claude/runners/ai_analyzer/REFACTORING.md +++ /dev/null @@ -1,284 +0,0 @@ -# AI Analyzer Refactoring Report - -## Executive Summary - -Successfully refactored `ai_analyzer_runner.py` from a monolithic 650-line file into a well-structured, modular package with 9 focused components. - -## Metrics - -| Metric | Before | After | Improvement | -|--------|--------|-------|-------------| -| Entry Point Size | 650 lines | 86 lines | 87% reduction | -| Number of Files | 1 | 10 | Better organization | -| Largest Module | 650 lines | 312 lines | 52% reduction | -| Type Hints | Partial | Comprehensive | 100% coverage | -| Test Isolation | Poor | Excellent | Modular design | - -## Module Breakdown - -### 1. `__init__.py` (10 lines) -- Package initialization -- Public API exports -- Clean entry point for imports - -### 2. `models.py` (89 lines) -**Responsibility**: Data models and type definitions - -**Exports**: -- `AnalyzerType` enum -- `CostEstimate` dataclass -- `AnalysisResult` dataclass -- `Vulnerability`, `PerformanceBottleneck`, `CodeSmell` dataclasses - -**Benefits**: -- Centralized type definitions -- Type safety throughout the package -- Easy to extend with new models - -### 3. `runner.py` (197 lines) -**Responsibility**: Main orchestration - -**Exports**: -- `AIAnalyzerRunner` class - -**Key Methods**: -- `run_full_analysis()` - Orchestrates complete analysis -- `_run_single_analyzer()` - Executes individual analyzer -- `_calculate_overall_score()` - Aggregates scores -- `print_summary()` - Delegates to SummaryPrinter - -**Benefits**: -- Clear control flow -- Coordinates all components -- Single entry point for analysis - -### 4. `analyzers.py` (312 lines) -**Responsibility**: Individual analyzer implementations - -**Exports**: -- `BaseAnalyzer` - Abstract base class -- 6 specific analyzers: - - `CodeRelationshipsAnalyzer` - - `BusinessLogicAnalyzer` - - `ArchitectureAnalyzer` - - `SecurityAnalyzer` - - `PerformanceAnalyzer` - - `CodeQualityAnalyzer` -- `AnalyzerFactory` - Factory pattern implementation - -**Benefits**: -- Each analyzer is self-contained -- Easy to add new analyzers -- Factory pattern simplifies creation -- Prompts separated from execution logic - -### 5. `claude_client.py` (144 lines) -**Responsibility**: Claude SDK integration - -**Exports**: -- `ClaudeAnalysisClient` class -- `CLAUDE_SDK_AVAILABLE` flag - -**Key Features**: -- OAuth token validation -- Security settings management -- Response collection -- Automatic cleanup - -**Benefits**: -- Isolates SDK-specific code -- Handles connection lifecycle -- Graceful error handling - -### 6. `cost_estimator.py` (95 lines) -**Responsibility**: API cost estimation - -**Exports**: -- `CostEstimator` class - -**Key Features**: -- Token estimation based on project size -- Python file counting -- Cost calculation -- Configurable pricing - -**Benefits**: -- Transparent cost visibility -- Easy to update pricing -- Excludes virtual environments - -### 7. `cache_manager.py` (61 lines) -**Responsibility**: Result caching - -**Exports**: -- `CacheManager` class - -**Key Features**: -- 24-hour cache validity -- Automatic directory creation -- Cache age reporting -- Skip cache option - -**Benefits**: -- Reduces API costs -- Faster repeated analyses -- Configurable validity period - -### 8. `result_parser.py` (59 lines) -**Responsibility**: JSON parsing - -**Exports**: -- `ResultParser` class - -**Key Features**: -- Multiple parsing strategies -- Markdown code block extraction -- Fallback to defaults -- Error resilience - -**Benefits**: -- Robust parsing -- Handles various response formats -- Never fails catastrophically - -### 9. `summary_printer.py` (97 lines) -**Responsibility**: Output formatting - -**Exports**: -- `SummaryPrinter` class - -**Key Features**: -- Formatted score display -- Security vulnerability summary -- Performance bottleneck summary -- Cost estimate display - -**Benefits**: -- Consistent output format -- Easy to modify presentation -- Separated from business logic - -### 10. `ai_analyzer_runner.py` (86 lines) -**Responsibility**: CLI entry point - -**Key Features**: -- Argument parsing -- Index file validation -- Graceful import error handling -- Async execution - -**Benefits**: -- Clean separation of CLI and library -- Minimal dependencies at entry point -- Clear error messages - -## Design Patterns Applied - -1. **Factory Pattern**: `AnalyzerFactory` for creating analyzer instances -2. **Strategy Pattern**: Different analyzers implement common interface -3. **Single Responsibility**: Each module has one clear purpose -4. **Dependency Injection**: Dependencies passed via constructors -5. **Separation of Concerns**: UI, business logic, and data separated - -## Code Quality Improvements - -### Type Safety -- Added comprehensive type hints to all functions -- Used dataclasses for structured data -- Enum for analyzer types - -### Error Handling -- Graceful degradation with defaults -- Clear error messages -- Import error handling - -### Testability -- Each module can be tested independently -- Minimal coupling between components -- Mock-friendly interfaces - -### Maintainability -- Clear module boundaries -- Self-documenting code structure -- Comprehensive docstrings - -## Migration Guide - -### For External Code - -No changes required! The refactored code maintains 100% backward compatibility: - -```python -# This still works exactly the same -from ai_analyzer import AIAnalyzerRunner -``` - -### Adding New Analyzers - -Before (required modifying 650-line file): -1. Add method to `AIAnalyzerRunner` class -2. Update `_run_analyzer()` dispatcher -3. Update analyzer list -4. Hope you didn't break anything - -After (clear, focused changes): -1. Create new class in `analyzers.py` extending `BaseAnalyzer` -2. Add to `AnalyzerFactory.ANALYZER_CLASSES` (1 line) -3. Add to `AnalyzerType` enum (1 line) -4. Optional: Update summary printer - -## Testing Strategy - -Each module can now be tested independently: - -```python -# Test cost estimator in isolation -from ai_analyzer.cost_estimator import CostEstimator -estimator = CostEstimator(project_dir, mock_index) -assert estimator.estimate_cost().estimated_tokens > 0 - -# Test cache manager -from ai_analyzer.cache_manager import CacheManager -cache = CacheManager(tmp_path) -cache.save_result({"score": 85}) -assert cache.get_cached_result() is not None - -# Test analyzers -from ai_analyzer.analyzers import SecurityAnalyzer -analyzer = SecurityAnalyzer(mock_index) -prompt = analyzer.get_prompt() -assert "OWASP" in prompt -``` - -## Performance Impact - -- No performance degradation -- Module loading is lazy (only imported when needed) -- Cache management remains efficient -- Same API call patterns - -## Future Enhancements - -The modular structure now makes these enhancements easy: - -1. **Parallel Analyzer Execution**: Run analyzers concurrently -2. **Custom Analyzers**: Plugin system for external analyzers -3. **Alternative Backends**: Support other LLMs besides Claude -4. **Enhanced Caching**: Redis or database-backed caching -5. **Progressive Results**: Stream results as analyzers complete -6. **Detailed Logging**: Per-module logging configuration - -## Conclusion - -The refactoring achieved all goals: - -✅ **Reduced complexity**: Entry point 87% smaller -✅ **Clear responsibilities**: Each module has single purpose -✅ **Type safety**: Comprehensive type hints -✅ **Maintainability**: Easy to locate and modify features -✅ **Testability**: Modules can be tested independently -✅ **Extensibility**: Simple to add new analyzers -✅ **Documentation**: README and inline docs -✅ **Zero breaking changes**: 100% backward compatible - -The codebase is now production-ready, maintainable, and professional. diff --git a/auto-claude/spec/validate_pkg/MIGRATION.md b/auto-claude/spec/validate_pkg/MIGRATION.md deleted file mode 100644 index 5441a22b..00000000 --- a/auto-claude/spec/validate_pkg/MIGRATION.md +++ /dev/null @@ -1,198 +0,0 @@ -# Migration Guide - -This document describes the changes made during the refactoring of `validate_spec.py` and how to update code that depends on it. - -## Summary of Changes - -The monolithic 633-line `validate_spec.py` file has been refactored into a modular package structure with: -- Main entry point reduced from 633 to 109 lines (83% reduction) -- 10 focused modules with clear responsibilities -- Total package size: 784 lines (including extensive documentation) - -## File Structure - -### Before -``` -auto-claude/ -└── validate_spec.py (633 lines) -``` - -### After -``` -auto-claude/ -├── validate_spec.py (109 lines - entry point) -└── validate_spec/ - ├── __init__.py - ├── models.py - ├── schemas.py - ├── auto_fix.py - ├── spec_validator.py - ├── README.md - ├── MIGRATION.md - └── validators/ - ├── __init__.py - ├── prereqs_validator.py - ├── context_validator.py - ├── spec_document_validator.py - └── implementation_plan_validator.py -``` - -## Import Changes - -### SpecValidator - -**Before:** -```python -from validate_spec import SpecValidator -``` - -**After (option 1 - recommended):** -```python -from validate_spec import SpecValidator -``` - -**After (option 2 - explicit):** -```python -from validate_spec.spec_validator import SpecValidator -``` - -### ValidationResult - -**Before:** -```python -from validate_spec import ValidationResult -``` - -**After (option 1 - recommended):** -```python -from validate_spec import ValidationResult -``` - -**After (option 2 - explicit):** -```python -from validate_spec.models import ValidationResult -``` - -### auto_fix_plan - -**Before:** -```python -from validate_spec import auto_fix_plan -``` - -**After (option 1 - recommended):** -```python -from validate_spec import auto_fix_plan -``` - -**After (option 2 - explicit):** -```python -from validate_spec.auto_fix import auto_fix_plan -``` - -## Files Updated - -The following files have been updated to use the new import structure: - -### 1. `auto-claude/spec/phases/planning_phases.py` -**Changed:** -```python -# Before -from validate_spec import auto_fix_plan - -# After -from validate_spec.auto_fix import auto_fix_plan -``` - -### 2. `auto-claude/spec/pipeline/orchestrator.py` -**Changed:** -```python -# Before -from validate_spec import SpecValidator - -# After -from validate_spec.spec_validator import SpecValidator -``` - -## Backward Compatibility - -The package exports maintain backward compatibility through `__init__.py`: - -```python -# validate_spec/__init__.py -from .auto_fix import auto_fix_plan -from .models import ValidationResult -from .spec_validator import SpecValidator - -__all__ = ["SpecValidator", "ValidationResult", "auto_fix_plan"] -``` - -This means existing code using: -```python -from validate_spec import SpecValidator, ValidationResult, auto_fix_plan -``` - -Will continue to work without changes. - -## CLI Usage - -The CLI interface remains **completely unchanged**: - -```bash -# All existing commands work exactly the same -python auto-claude/validate_spec.py --spec-dir path/to/spec --checkpoint all -python auto-claude/validate_spec.py --spec-dir path/to/spec --checkpoint context -python auto-claude/validate_spec.py --spec-dir path/to/spec --auto-fix --checkpoint plan -python auto-claude/validate_spec.py --spec-dir path/to/spec --checkpoint all --json -``` - -## Testing - -All existing functionality has been preserved: - -1. **Validation logic**: Identical behavior -2. **Error messages**: Same format -3. **Auto-fix**: Same functionality -4. **CLI**: Same interface -5. **JSON output**: Same structure - -## Benefits - -### Maintainability -- Each validator is in its own file -- Easy to locate and modify specific validation logic -- Clear separation of concerns - -### Testability -- Individual validators can be tested in isolation -- Mock dependencies are easier to set up -- Unit tests can focus on specific functionality - -### Extensibility -- Adding new validators is straightforward -- New validation rules can be added without touching existing code -- Schema changes are centralized - -### Readability -- Main entry point is now 109 lines instead of 633 -- Each file has a single, clear purpose -- Documentation is embedded in each module - -## Rollback - -If needed, the original file is preserved as `validate_spec.py.backup`: - -```bash -# To rollback -cd auto-claude -mv validate_spec.py validate_spec.py.refactored -mv validate_spec.py.backup validate_spec.py -rm -rf validate_spec/ -``` - -## Questions? - -For questions or issues related to this refactoring: -1. Check the [README.md](README.md) for usage examples -2. Review the inline documentation in each module -3. Compare with `validate_spec.py.backup` if needed diff --git a/auto-claude/validate_spec/__init__.py b/auto-claude/validate_spec/__init__.py deleted file mode 100644 index acd5d2d7..00000000 --- a/auto-claude/validate_spec/__init__.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Backward compatibility shim for validate_spec package. - -DEPRECATED: This package has been moved to spec.validate_pkg. - -Please update your imports: - OLD: from validate_spec import SpecValidator, ValidationResult, auto_fix_plan - NEW: from spec.validate_pkg import SpecValidator, ValidationResult, auto_fix_plan - -This shim provides compatibility but will be removed in a future version. -""" - -import sys -from pathlib import Path - - -# Lazy import to avoid circular dependencies -def __getattr__(name): - """Lazy import mechanism to avoid circular imports.""" - if name in ("SpecValidator", "ValidationResult", "auto_fix_plan"): - # Add spec directory to path temporarily to allow direct imports - # without triggering spec.__init__ - spec_dir = Path(__file__).parent.parent / "spec" - if str(spec_dir) not in sys.path: - sys.path.insert(0, str(spec_dir)) - - try: - # Import directly from validate_pkg without going through spec package - from validate_pkg import SpecValidator, ValidationResult, auto_fix_plan - - # Cache the imported values in this module - globals()["SpecValidator"] = SpecValidator - globals()["ValidationResult"] = ValidationResult - globals()["auto_fix_plan"] = auto_fix_plan - - return globals()[name] - finally: - # Clean up path modification - if str(spec_dir) in sys.path: - sys.path.remove(str(spec_dir)) - - raise AttributeError(f"module 'validate_spec' has no attribute '{name}'") - - -__all__ = ["SpecValidator", "ValidationResult", "auto_fix_plan"] diff --git a/auto-claude/validate_spec/auto_fix.py b/auto-claude/validate_spec/auto_fix.py deleted file mode 100644 index d3b1660c..00000000 --- a/auto-claude/validate_spec/auto_fix.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Backward compatibility shim for auto_fix module. - -DEPRECATED: This module has been moved to spec.validate_pkg.auto_fix. - -Please update your imports: - OLD: from validate_spec.auto_fix import auto_fix_plan - NEW: from spec.validate_pkg.auto_fix import auto_fix_plan - -This shim provides compatibility but will be removed in a future version. -""" - -import sys -from pathlib import Path - - -# Lazy import to avoid circular dependencies -def __getattr__(name): - """Lazy import mechanism to avoid circular imports.""" - if name == "auto_fix_plan": - # Add spec directory to path temporarily to allow direct imports - # without triggering spec.__init__ - spec_dir = Path(__file__).parent.parent / "spec" - if str(spec_dir) not in sys.path: - sys.path.insert(0, str(spec_dir)) - - try: - # Import directly from validate_pkg without going through spec package - from validate_pkg.auto_fix import auto_fix_plan - - # Cache the imported value in this module - globals()["auto_fix_plan"] = auto_fix_plan - return auto_fix_plan - finally: - # Clean up path modification - if str(spec_dir) in sys.path: - sys.path.remove(str(spec_dir)) - - raise AttributeError(f"module 'validate_spec.auto_fix' has no attribute '{name}'") diff --git a/auto-claude/validate_spec/spec_validator.py b/auto-claude/validate_spec/spec_validator.py deleted file mode 100644 index a304d1ae..00000000 --- a/auto-claude/validate_spec/spec_validator.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Backward compatibility shim for spec_validator module. - -DEPRECATED: This module has been moved to spec.validate_pkg.spec_validator. - -Please update your imports: - OLD: from validate_spec.spec_validator import SpecValidator - NEW: from spec.validate_pkg.spec_validator import SpecValidator - -This shim provides compatibility but will be removed in a future version. -""" - -import sys -from pathlib import Path - - -# Lazy import to avoid circular dependencies -def __getattr__(name): - """Lazy import mechanism to avoid circular imports.""" - if name == "SpecValidator": - # Add spec directory to path temporarily to allow direct imports - # without triggering spec.__init__ - spec_dir = Path(__file__).parent.parent / "spec" - if str(spec_dir) not in sys.path: - sys.path.insert(0, str(spec_dir)) - - try: - # Import directly from validate_pkg without going through spec package - from validate_pkg.spec_validator import SpecValidator - - # Cache the imported value in this module - globals()["SpecValidator"] = SpecValidator - return SpecValidator - finally: - # Clean up path modification - if str(spec_dir) in sys.path: - sys.path.remove(str(spec_dir)) - - raise AttributeError( - f"module 'validate_spec.spec_validator' has no attribute '{name}'" - ) diff --git a/auto-claude/workspace.py b/auto-claude/workspace.py deleted file mode 100644 index fec822f1..00000000 --- a/auto-claude/workspace.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Backward compatibility shim - import from core.workspace package. - -This file exists to maintain backward compatibility for code that imports -from 'workspace' instead of 'core.workspace'. The workspace module has been -refactored into a package (core/workspace/) with multiple sub-modules. - -IMPLEMENTATION: To avoid triggering core/__init__.py (which imports modules -with heavy dependencies like claude_agent_sdk), we: -1. Create a minimal fake 'core' module to satisfy Python's import system -2. Load core.workspace package directly using importlib -3. Register it in sys.modules -4. Re-export everything - -This allows 'from workspace import X' to work without requiring all of core's dependencies. -""" - -import importlib.util -import sys -from pathlib import Path -from types import ModuleType - -# Ensure auto-claude is in sys.path -_auto_claude_dir = Path(__file__).parent -if str(_auto_claude_dir) not in sys.path: - sys.path.insert(0, str(_auto_claude_dir)) - -# Create a minimal 'core' module if it doesn't exist (to avoid importing core/__init__.py) -if "core" not in sys.modules: - _core_module = ModuleType("core") - _core_module.__file__ = str(_auto_claude_dir / "core" / "__init__.py") - _core_module.__path__ = [str(_auto_claude_dir / "core")] - sys.modules["core"] = _core_module - -# Now load core.workspace package directly -_workspace_init = _auto_claude_dir / "core" / "workspace" / "__init__.py" -_spec = importlib.util.spec_from_file_location("core.workspace", _workspace_init) -_workspace_module = importlib.util.module_from_spec(_spec) -sys.modules["core.workspace"] = _workspace_module -_spec.loader.exec_module(_workspace_module) - -# Re-export everything from core.workspace -from core.workspace import * # noqa: F401, F403 - -__all__ = _workspace_module.__all__ diff --git a/guides/CLI-USAGE.md b/guides/CLI-USAGE.md index 4e9534ef..09ee315f 100644 --- a/guides/CLI-USAGE.md +++ b/guides/CLI-USAGE.md @@ -15,10 +15,10 @@ This document covers terminal-only usage of Auto Claude. **For most users, we re ## Setup -**Step 1:** Navigate to the auto-claude directory +**Step 1:** Navigate to the backend directory ```bash -cd auto-claude +cd apps/backend ``` **Step 2:** Set up Python environment @@ -39,14 +39,16 @@ cp .env.example .env # Get your OAuth token claude setup-token -# Add the token to .env +# Add the token to apps/backend/.env # CLAUDE_CODE_OAUTH_TOKEN=your-token-here ``` ## Creating Specs +All commands below should be run from the `apps/backend/` directory: + ```bash -# Activate the virtual environment +# Activate the virtual environment (if not already active) source .venv/bin/activate # Create a spec interactively @@ -116,6 +118,9 @@ Auto Claude uses Git worktrees for isolated builds: cd .worktrees/auto-claude/ npm run dev # or your project's run command +# Return to backend directory to run management commands +cd apps/backend + # See what was changed python run.py --spec 001 --review diff --git a/guides/DOCKER-SETUP.md b/guides/DOCKER-SETUP.md deleted file mode 100644 index 8acd6964..00000000 --- a/guides/DOCKER-SETUP.md +++ /dev/null @@ -1,435 +0,0 @@ -# Docker & FalkorDB Setup Guide - -This guide covers installing and troubleshooting Docker for Auto Claude's Memory Layer. The Memory Layer uses FalkorDB (a graph database) to provide persistent cross-session memory for AI agents. - -> **Good news!** If you're using the Desktop UI, it automatically detects Docker and FalkorDB status and offers one-click setup. This guide is for manual setup or troubleshooting. - -## Table of Contents - -- [Quick Start](#quick-start) -- [What is Docker?](#what-is-docker) -- [Installing Docker Desktop](#installing-docker-desktop) - - [macOS](#macos) - - [Windows](#windows) - - [Linux](#linux) -- [Starting FalkorDB](#starting-falkordb) -- [Verifying Your Setup](#verifying-your-setup) -- [Troubleshooting](#troubleshooting) -- [Advanced Configuration](#advanced-configuration) -- [Uninstalling](#uninstalling) - ---- - -## Quick Start - -If Docker Desktop is already installed and running: - -```bash -# Start FalkorDB -docker run -d --name auto-claude-falkordb -p 6379:6379 falkordb/falkordb:latest - -# Verify it's running -docker ps | grep falkordb -``` - ---- - -## What is Docker? - -Docker is a tool that runs applications in isolated "containers". Think of it as a lightweight virtual machine that: - -- **Keeps things contained** - FalkorDB runs inside Docker without affecting your system -- **Makes setup easy** - One command to start, no complex installation -- **Works everywhere** - Same setup on Mac, Windows, and Linux - -**You don't need to understand Docker** - just install Docker Desktop and Auto Claude handles the rest. - ---- - -## Installing Docker Desktop - -### macOS - -#### Step 1: Download - -| Mac Type | Download Link | -|----------|---------------| -| **Apple Silicon (M1/M2/M3/M4)** | [Download for Apple Chip](https://desktop.docker.com/mac/main/arm64/Docker.dmg) | -| **Intel** | [Download for Intel Chip](https://desktop.docker.com/mac/main/amd64/Docker.dmg) | - -> **Which do I have?** Click the Apple logo () → "About This Mac". Look for "Chip" - if it says Apple M1/M2/M3/M4, use Apple Silicon. If it says Intel, use Intel. - -#### Step 2: Install - -1. Open the downloaded `.dmg` file -2. Drag the Docker icon to your Applications folder -3. Open Docker from Applications (or Spotlight: ⌘+Space, type "Docker") -4. Click "Open" if you see a security warning -5. **Wait** - Docker takes 1-2 minutes to start the first time - -#### Step 3: Verify - -Look for the whale icon (🐳) in your menu bar. When it stops animating, Docker is ready. - -Open Terminal and run: - -```bash -docker --version -# Expected: Docker version 24.x.x or higher -``` - -### Windows - -#### Prerequisites - -- Windows 10 (version 2004 or higher) or Windows 11 -- WSL 2 enabled (Docker will prompt you to install it) - -#### Step 1: Download - -[Download Docker Desktop for Windows](https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe) - -#### Step 2: Install - -1. Run the downloaded installer -2. **Keep "Use WSL 2" checked** (recommended) -3. Follow the installation wizard with default settings -4. **Restart your computer** when prompted -5. After restart, Docker Desktop will start automatically - -#### Step 3: WSL 2 Setup (if prompted) - -If Docker shows a WSL 2 warning: - -1. Open PowerShell as Administrator -2. Run: - ```powershell - wsl --install - ``` -3. Restart your computer -4. Open Docker Desktop again - -#### Step 4: Verify - -Look for the whale icon (🐳) in your system tray. When it stops animating, Docker is ready. - -Open PowerShell or Command Prompt and run: - -```bash -docker --version -# Expected: Docker version 24.x.x or higher -``` - -### Linux - -#### Ubuntu/Debian - -```bash -# Update package index -sudo apt-get update - -# Install prerequisites -sudo apt-get install ca-certificates curl gnupg - -# Add Docker's official GPG key -sudo install -m 0755 -d /etc/apt/keyrings -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg -sudo chmod a+r /etc/apt/keyrings/docker.gpg - -# Add the repository -echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ - $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ - sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - -# Install Docker -sudo apt-get update -sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin - -# Add your user to the docker group (to run without sudo) -sudo usermod -aG docker $USER - -# Log out and back in, then verify -docker --version -``` - -#### Fedora - -```bash -# Install Docker -sudo dnf -y install dnf-plugins-core -sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo -sudo dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin - -# Start Docker -sudo systemctl start docker -sudo systemctl enable docker - -# Add your user to the docker group -sudo usermod -aG docker $USER -``` - ---- - -## Starting FalkorDB - -### Option 1: Using Docker Compose (Recommended) - -From the Auto Claude root directory: - -```bash -# Start FalkorDB only (for Python library integration) -docker-compose up -d falkordb - -# Or start both FalkorDB + Graphiti MCP server (for agent memory access) -docker-compose up -d -``` - -This uses the project's `docker-compose.yml` which is pre-configured. - -### Option 2: Using Docker Run - -```bash -docker run -d \ - --name auto-claude-falkordb \ - -p 6379:6379 \ - --restart unless-stopped \ - falkordb/falkordb:latest -``` - -### Option 3: Let the Desktop UI Handle It - -If you're using the Auto Claude Desktop UI: - -1. Go to Project Settings → Memory Backend -2. Enable "Use Graphiti" -3. The UI will show Docker/FalkorDB status -4. Click "Start" to launch FalkorDB automatically - ---- - -## Starting the Graphiti MCP Server (Optional) - -The Graphiti MCP server allows Claude agents to directly search and add to the knowledge graph during builds. This is optional but recommended for the best memory experience. - -### Prerequisites - -1. FalkorDB must be running -2. OpenAI API key (for embeddings) - -### Setup - -**For CLI users** - The API key is read from `auto-claude/.env`: - -```bash -docker-compose up -d -``` - -**For Frontend/UI users** - Create a `.env` file in the project root: - -```bash -# Copy the example file -cp .env.example .env - -# Edit and add your OpenAI API key -nano .env # or use any text editor - -# Start the services -docker-compose up -d -``` - -### Verify MCP Server is Running - -```bash -# Check container status -docker ps | grep graphiti-mcp - -# Check health endpoint -curl http://localhost:8000/health - -# View logs if there are issues -docker logs auto-claude-graphiti-mcp -``` - -### Configure Auto Claude to Use MCP - -In Project Settings → Memory Backend: -- Enable "Enable Agent Memory Access" -- Set MCP URL to: `http://localhost:8000/mcp/` - ---- - -## Verifying Your Setup - -### Check Docker is Running - -```bash -docker info -# Should show Docker system information without errors -``` - -### Check FalkorDB is Running - -```bash -docker ps | grep falkordb -# Should show the running container -``` - -### Test FalkorDB Connection - -```bash -docker exec auto-claude-falkordb redis-cli PING -# Expected response: PONG -``` - -### Check Logs (if something seems wrong) - -```bash -docker logs auto-claude-falkordb -``` - ---- - -## Troubleshooting - -### Docker Issues - -| Problem | Solution | -|---------|----------| -| **"docker: command not found"** | Docker Desktop isn't installed or isn't in PATH. Reinstall Docker Desktop. | -| **"Cannot connect to Docker daemon"** | Docker Desktop isn't running. Open Docker Desktop and wait for it to start. | -| **"permission denied"** | On Linux, add your user to the docker group: `sudo usermod -aG docker $USER` then log out and back in. | -| **Docker Desktop won't start** | Try restarting your computer. On Mac, check System Preferences → Security for blocked apps. | -| **"Docker Desktop requires macOS 12"** | Update macOS in System Preferences → Software Update. | -| **"WSL 2 installation incomplete"** | Run `wsl --install` in PowerShell (as Admin) and restart. | - -### FalkorDB Issues - -| Problem | Solution | -|---------|----------| -| **Container won't start** | Check if port 6379 is in use: `lsof -i :6379` (Mac/Linux) or `netstat -ano | findstr 6379` (Windows) | -| **"port is already allocated"** | Stop conflicting container: `docker stop auto-claude-falkordb && docker rm auto-claude-falkordb` | -| **Connection refused** | Verify container is running: `docker ps`. If not listed, start it again. | -| **Container crashes immediately** | Check logs: `docker logs auto-claude-falkordb`. May need more memory. | - -### Graphiti MCP Server Issues - -| Problem | Solution | -|---------|----------| -| **"OPENAI_API_KEY must be set"** | Create `.env` file with your API key: `echo "OPENAI_API_KEY=sk-your-key" > .env` | -| **"DATABASE_TYPE must be set"** | Using old docker run command. Use `docker-compose up -d` instead. | -| **Container keeps restarting** | Check logs: `docker logs auto-claude-graphiti-mcp`. Usually missing API key. | -| **Platform warning on Apple Silicon** | This is normal - the image runs via Rosetta emulation. It may be slower but works. | -| **Health check fails** | Wait 30 seconds for startup. Check: `curl http://localhost:8000/health` | - -### Memory/Performance Issues - -| Problem | Solution | -|---------|----------| -| **Docker using too much memory** | Open Docker Desktop → Settings → Resources → Memory. Reduce to 2-4GB. | -| **Docker using too much disk** | Run `docker system prune -a` to clean unused images and containers. | -| **Computer running slow** | Quit Docker Desktop when not using Auto Claude. FalkorDB only needs to run during active sessions. | - -### Network Issues - -| Problem | Solution | -|---------|----------| -| **"network not found"** | Run `docker network create auto-claude-network` or use `docker-compose up` | -| **Can't connect from app** | Ensure port 6379 is exposed. Check firewall isn't blocking localhost connections. | - ---- - -## Advanced Configuration - -### Custom Port - -If port 6379 is in use, change it: - -```bash -# Using docker run -docker run -d --name auto-claude-falkordb -p 6381:6379 falkordb/falkordb:latest -``` - -Then update Auto Claude settings to use port 6381. - -### Persistent Data - -To persist FalkorDB data between container restarts: - -```bash -docker run -d \ - --name auto-claude-falkordb \ - -p 6379:6379 \ - -v auto-claude-falkordb-data:/data \ - --restart unless-stopped \ - falkordb/falkordb:latest -``` - -### Memory Limits - -To limit FalkorDB memory usage: - -```bash -docker run -d \ - --name auto-claude-falkordb \ - -p 6379:6379 \ - --memory=2g \ - --restart unless-stopped \ - falkordb/falkordb:latest -``` - -### Running on a Remote Server - -If running Docker on a different machine: - -1. Expose the port on the server: - ```bash - docker run -d -p 0.0.0.0:6379:6379 falkordb/falkordb:latest - ``` - -2. Update Auto Claude settings: - - Set `GRAPHITI_FALKORDB_HOST=your-server-ip` - - Set `GRAPHITI_FALKORDB_PORT=6379` - ---- - -## Uninstalling - -### Stop and Remove FalkorDB - -```bash -docker stop auto-claude-falkordb -docker rm auto-claude-falkordb -``` - -### Remove FalkorDB Image - -```bash -docker rmi falkordb/falkordb:latest -``` - -### Remove All Docker Data - -```bash -docker system prune -a --volumes -``` - -### Uninstall Docker Desktop - -- **Mac**: Drag Docker from Applications to Trash, then empty Trash -- **Windows**: Control Panel → Programs → Uninstall Docker Desktop -- **Linux**: `sudo apt-get remove docker-ce docker-ce-cli containerd.io` - ---- - -## Getting Help - -If you're still having issues: - -1. Check the [Auto Claude GitHub Issues](https://github.com/auto-claude/auto-claude/issues) -2. Search for your error message -3. Create a new issue with: - - Your operating system and version - - Docker version (`docker --version`) - - Error message or logs - - Steps you've already tried diff --git a/package.json b/package.json new file mode 100644 index 00000000..2ea8b276 --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "auto-claude", + "version": "2.7.2", + "description": "Autonomous multi-agent coding framework powered by Claude AI", + "license": "AGPL-3.0", + "author": "Auto Claude Team", + "scripts": { + "install:backend": "node scripts/install-backend.js", + "install:frontend": "cd apps/frontend && npm install", + "install:all": "npm run install:backend && npm run install:frontend", + "start": "cd apps/frontend && npm run build && npm run start", + "dev": "cd apps/frontend && npm run dev", + "dev:debug": "DEBUG=true cd apps/frontend && npm run dev", + "dev:mcp": "cd apps/frontend && npm run dev:mcp", + "build": "cd apps/frontend && npm run build", + "lint": "cd apps/frontend && npm run lint", + "test": "cd apps/frontend && npm test", + "test:backend": "node scripts/test-backend.js", + "package": "cd apps/frontend && npm run package", + "package:mac": "cd apps/frontend && npm run package:mac", + "package:win": "cd apps/frontend && npm run package:win", + "package:linux": "cd apps/frontend && npm run package:linux" + }, + "engines": { + "node": ">=24.0.0", + "npm": ">=10.0.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/AndyMik90/Auto-Claude.git" + }, + "keywords": [ + "ai", + "claude", + "autonomous", + "coding", + "agents", + "electron" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..9b60ae17 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,9 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: {} diff --git a/scripts/bump-version.js b/scripts/bump-version.js index c9308aab..22ee2dc3 100644 --- a/scripts/bump-version.js +++ b/scripts/bump-version.js @@ -100,20 +100,27 @@ function checkGitStatus() { // Update package.json version function updatePackageJson(newVersion) { - const packagePath = path.join(__dirname, '..', 'auto-claude-ui', 'package.json'); + const frontendPath = path.join(__dirname, '..', 'apps', 'frontend', 'package.json'); + const rootPath = path.join(__dirname, '..', 'package.json'); - if (!fs.existsSync(packagePath)) { - error(`package.json not found at ${packagePath}`); + if (!fs.existsSync(frontendPath)) { + error(`package.json not found at ${frontendPath}`); } - const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); - const oldVersion = packageJson.version; + // Update frontend package.json + const frontendJson = JSON.parse(fs.readFileSync(frontendPath, 'utf8')); + const oldVersion = frontendJson.version; + frontendJson.version = newVersion; + fs.writeFileSync(frontendPath, JSON.stringify(frontendJson, null, 2) + '\n'); - packageJson.version = newVersion; + // Update root package.json if it exists + if (fs.existsSync(rootPath)) { + const rootJson = JSON.parse(fs.readFileSync(rootPath, 'utf8')); + rootJson.version = newVersion; + fs.writeFileSync(rootPath, JSON.stringify(rootJson, null, 2) + '\n'); + } - fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2) + '\n'); - - return { oldVersion, packagePath }; + return { oldVersion, packagePath: frontendPath }; } // Main function @@ -133,7 +140,7 @@ function main() { success('Git working directory is clean'); // 2. Read current version - const packagePath = path.join(__dirname, '..', 'auto-claude-ui', 'package.json'); + const packagePath = path.join(__dirname, '..', 'apps', 'frontend', 'package.json'); const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8')); const currentVersion = packageJson.version; info(`Current version: ${currentVersion}`); @@ -153,7 +160,7 @@ function main() { // 5. Create git commit info('Creating git commit...'); - exec('git add auto-claude-ui/package.json'); + exec('git add apps/frontend/package.json package.json'); exec(`git commit -m "chore: bump version to ${newVersion}"`); success(`Created commit: "chore: bump version to ${newVersion}"`); diff --git a/scripts/install-backend.js b/scripts/install-backend.js new file mode 100644 index 00000000..d1507a08 --- /dev/null +++ b/scripts/install-backend.js @@ -0,0 +1,104 @@ +#!/usr/bin/env node +/** + * Cross-platform backend installer script + * Handles Python venv creation and dependency installation on Windows/Mac/Linux + */ + +const { execSync, spawnSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); +const os = require('os'); + +const isWindows = os.platform() === 'win32'; +const backendDir = path.join(__dirname, '..', 'apps', 'backend'); +const venvDir = path.join(backendDir, '.venv'); + +console.log('Installing Auto Claude backend dependencies...\n'); + +// Helper to run commands +function run(cmd, options = {}) { + console.log(`> ${cmd}`); + try { + execSync(cmd, { stdio: 'inherit', cwd: backendDir, ...options }); + return true; + } catch (error) { + return false; + } +} + +// Find Python 3.12 +function findPython() { + const candidates = isWindows + ? ['py -3.12', 'python3.12', 'python'] + : ['python3.12', 'python3', 'python']; + + for (const cmd of candidates) { + try { + const result = spawnSync(cmd.split(' ')[0], [...cmd.split(' ').slice(1), '--version'], { + encoding: 'utf8', + shell: true, + }); + if (result.status === 0 && result.stdout.includes('3.12')) { + console.log(`Found Python 3.12: ${cmd} -> ${result.stdout.trim()}`); + return cmd; + } + } catch (e) { + // Continue to next candidate + } + } + return null; +} + +// Get pip path based on platform +function getPipPath() { + return isWindows + ? path.join(venvDir, 'Scripts', 'pip.exe') + : path.join(venvDir, 'bin', 'pip'); +} + +// Main installation +async function main() { + // Check for Python 3.12 + const python = findPython(); + if (!python) { + console.error('\nError: Python 3.12 is required but not found.'); + console.error('Please install Python 3.12:'); + if (isWindows) { + console.error(' winget install Python.Python.3.12'); + } else if (os.platform() === 'darwin') { + console.error(' brew install python@3.12'); + } else { + console.error(' sudo apt install python3.12 python3.12-venv'); + } + process.exit(1); + } + + // Remove existing venv if present + if (fs.existsSync(venvDir)) { + console.log('\nRemoving existing virtual environment...'); + fs.rmSync(venvDir, { recursive: true, force: true }); + } + + // Create virtual environment + console.log('\nCreating virtual environment...'); + if (!run(`${python} -m venv .venv`)) { + console.error('Failed to create virtual environment'); + process.exit(1); + } + + // Install dependencies + console.log('\nInstalling dependencies...'); + const pip = getPipPath(); + if (!run(`"${pip}" install -r requirements.txt`)) { + console.error('Failed to install dependencies'); + process.exit(1); + } + + console.log('\nBackend installation complete!'); + console.log(`Virtual environment: ${venvDir}`); +} + +main().catch((err) => { + console.error('Installation failed:', err); + process.exit(1); +}); diff --git a/scripts/test-backend.js b/scripts/test-backend.js new file mode 100644 index 00000000..9a1b9098 --- /dev/null +++ b/scripts/test-backend.js @@ -0,0 +1,53 @@ +#!/usr/bin/env node +/** + * Cross-platform backend test runner script + * Runs pytest using the correct virtual environment path for Windows/Mac/Linux + */ + +const { execSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); +const os = require('os'); + +const isWindows = os.platform() === 'win32'; +const rootDir = path.join(__dirname, '..'); +const backendDir = path.join(rootDir, 'apps', 'backend'); +const testsDir = path.join(rootDir, 'tests'); +const venvDir = path.join(backendDir, '.venv'); + +// Get pytest path based on platform +const pytestPath = isWindows + ? path.join(venvDir, 'Scripts', 'pytest.exe') + : path.join(venvDir, 'bin', 'pytest'); + +// Check if venv exists +if (!fs.existsSync(venvDir)) { + console.error('Error: Virtual environment not found.'); + console.error('Run "npm run install:backend" first.'); + process.exit(1); +} + +// Check if pytest is installed +if (!fs.existsSync(pytestPath)) { + console.error('Error: pytest not found in virtual environment.'); + console.error('Install test dependencies:'); + const pipPath = isWindows + ? path.join(venvDir, 'Scripts', 'pip.exe') + : path.join(venvDir, 'bin', 'pip'); + console.error(` "${pipPath}" install -r tests/requirements-test.txt`); + process.exit(1); +} + +// Get any additional args passed to the script +const args = process.argv.slice(2); +const testArgs = args.length > 0 ? args.join(' ') : '-v'; + +// Run pytest +const cmd = `"${pytestPath}" "${testsDir}" ${testArgs}`; +console.log(`> ${cmd}\n`); + +try { + execSync(cmd, { stdio: 'inherit', cwd: rootDir }); +} catch (error) { + process.exit(error.status || 1); +} diff --git a/tests/conftest.py b/tests/conftest.py index 44ff36a4..6a76c075 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -42,8 +42,8 @@ if 'claude_code_sdk' not in sys.modules: sys.modules['claude_code_sdk'] = _create_sdk_mock() sys.modules['claude_code_sdk.types'] = MagicMock() -# Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +# Add apps/backend directory to path for imports +sys.path.insert(0, str(Path(__file__).parent.parent / "apps" / "backend")) # ============================================================================= diff --git a/tests/qa_report_helpers.py b/tests/qa_report_helpers.py index 95084522..2f116efe 100644 --- a/tests/qa_report_helpers.py +++ b/tests/qa_report_helpers.py @@ -101,7 +101,7 @@ def setup_qa_report_mocks() -> None: sys.modules['client'] = mock_client # Add auto-claude path for imports - sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) + sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) def cleanup_qa_report_mocks() -> None: diff --git a/tests/review_fixtures.py b/tests/review_fixtures.py index 5fab6be0..6580cc0a 100644 --- a/tests/review_fixtures.py +++ b/tests/review_fixtures.py @@ -12,7 +12,7 @@ from typing import Generator import pytest -from review import ReviewState +from review.state import ReviewState @pytest.fixture diff --git a/tests/test_agent_architecture.py b/tests/test_agent_architecture.py index c03ce7d8..54262880 100644 --- a/tests/test_agent_architecture.py +++ b/tests/test_agent_architecture.py @@ -21,8 +21,8 @@ from pathlib import Path import pytest -# Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +# Add apps/backend directory to path for imports +sys.path.insert(0, str(Path(__file__).parent.parent / "apps" / "backend")) class TestNoExternalParallelism: @@ -30,7 +30,7 @@ class TestNoExternalParallelism: def test_no_coordinator_module(self): """No external coordinator module should exist.""" - coordinator_path = Path(__file__).parent.parent / "auto-claude" / "coordinator.py" + coordinator_path = Path(__file__).parent.parent / "apps" / "backend" / "coordinator.py" assert not coordinator_path.exists(), ( "coordinator.py should not exist. Parallel orchestration is handled " "internally by the agent using Claude Code's Task tool." @@ -38,7 +38,7 @@ class TestNoExternalParallelism: def test_no_task_tool_module(self): """No task_tool wrapper module should exist.""" - task_tool_path = Path(__file__).parent.parent / "auto-claude" / "task_tool.py" + task_tool_path = Path(__file__).parent.parent / "apps" / "backend" / "task_tool.py" assert not task_tool_path.exists(), ( "task_tool.py should not exist. The agent spawns subagents directly " "using Claude Code's built-in Task tool." @@ -58,7 +58,7 @@ class TestCLIInterface: def test_no_parallel_flag(self): """CLI should not have --parallel argument.""" - run_py_path = Path(__file__).parent.parent / "auto-claude" / "run.py" + run_py_path = Path(__file__).parent.parent / "apps" / "backend" / "run.py" content = run_py_path.read_text() # Check that --parallel is not defined as an argument @@ -73,7 +73,7 @@ class TestCLIInterface: def test_no_parallel_examples_in_docs(self): """CLI documentation should not mention parallel mode.""" - run_py_path = Path(__file__).parent.parent / "auto-claude" / "run.py" + run_py_path = Path(__file__).parent.parent / "apps" / "backend" / "run.py" content = run_py_path.read_text() # The docstring should not have --parallel examples @@ -125,7 +125,7 @@ class TestAgentPrompt: def test_mentions_subagents(self): """Agent prompt mentions subagent capability.""" - coder_prompt_path = Path(__file__).parent.parent / "auto-claude" / "prompts" / "coder.md" + coder_prompt_path = Path(__file__).parent.parent / "apps" / "backend" / "prompts" / "coder.md" content = coder_prompt_path.read_text() assert "subagent" in content.lower(), ( @@ -134,7 +134,7 @@ class TestAgentPrompt: def test_mentions_parallel_capability(self): """Agent prompt mentions parallel/concurrent capability.""" - coder_prompt_path = Path(__file__).parent.parent / "auto-claude" / "prompts" / "coder.md" + coder_prompt_path = Path(__file__).parent.parent / "apps" / "backend" / "prompts" / "coder.md" content = coder_prompt_path.read_text() has_task_tool = "task tool" in content.lower() or "Task tool" in content @@ -158,7 +158,7 @@ class TestModuleIntegrity: def test_run_module_valid_syntax(self): """Run module has valid Python syntax.""" - run_py_path = Path(__file__).parent.parent / "auto-claude" / "run.py" + run_py_path = Path(__file__).parent.parent / "apps" / "backend" / "run.py" content = run_py_path.read_text() try: @@ -169,7 +169,7 @@ class TestModuleIntegrity: def test_no_coordinator_imports(self): """Core modules don't import coordinator.""" for filename in ["run.py", "core/agent.py"]: - filepath = Path(__file__).parent.parent / "auto-claude" / filename + filepath = Path(__file__).parent.parent / "apps" / "backend" / filename content = filepath.read_text() assert "from coordinator import" not in content, ( @@ -182,7 +182,7 @@ class TestModuleIntegrity: def test_no_task_tool_imports(self): """Core modules don't import task_tool.""" for filename in ["run.py", "core/agent.py"]: - filepath = Path(__file__).parent.parent / "auto-claude" / filename + filepath = Path(__file__).parent.parent / "apps" / "backend" / filename content = filepath.read_text() assert "from task_tool import" not in content, ( @@ -199,7 +199,7 @@ class TestProjectDocumentation: def test_no_parallel_cli_documented(self): """CLAUDE.md doesn't document --parallel flag.""" claude_md_path = Path(__file__).parent.parent / "CLAUDE.md" - content = claude_md_path.read_text() + content = claude_md_path.read_text(encoding="utf-8") assert "--parallel 2" not in content, ( "CLAUDE.md should not document --parallel flag" @@ -208,7 +208,7 @@ class TestProjectDocumentation: def test_subagent_architecture_documented(self): """CLAUDE.md documents subagent-based architecture.""" claude_md_path = Path(__file__).parent.parent / "CLAUDE.md" - content = claude_md_path.read_text() + content = claude_md_path.read_text(encoding="utf-8") has_subagent = "subagent" in content.lower() has_task_tool = "task tool" in content.lower() @@ -305,7 +305,7 @@ class TestSubtaskTerminology: def test_implementation_plan_uses_subtask_class(self): """Implementation plan uses Subtask class.""" - impl_plan_path = Path(__file__).parent.parent / "auto-claude" / "implementation_plan" / "main.py" + impl_plan_path = Path(__file__).parent.parent / "apps" / "backend" / "implementation_plan" / "main.py" content = impl_plan_path.read_text() # Check that it re-exports or imports Subtask and SubtaskStatus @@ -318,7 +318,7 @@ class TestSubtaskTerminology: def test_progress_uses_subtask_terminology(self): """Progress module uses subtask terminology.""" - progress_path = Path(__file__).parent.parent / "auto-claude" / "core" / "progress.py" + progress_path = Path(__file__).parent.parent / "apps" / "backend" / "core" / "progress.py" content = progress_path.read_text() assert "subtask" in content.lower(), ( diff --git a/tests/test_analyzer_port_detection.py b/tests/test_analyzer_port_detection.py index 3451f208..eada6586 100644 --- a/tests/test_analyzer_port_detection.py +++ b/tests/test_analyzer_port_detection.py @@ -17,7 +17,7 @@ import sys import json # Add parent directory to path to import analyzer -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from analyzer import ServiceAnalyzer diff --git a/tests/test_ci_discovery.py b/tests/test_ci_discovery.py index 8f2c2e8d..a55d6b91 100644 --- a/tests/test_ci_discovery.py +++ b/tests/test_ci_discovery.py @@ -18,7 +18,7 @@ import pytest # Add auto-claude to path for imports import sys -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from ci_discovery import ( CIConfig, diff --git a/tests/test_critique_integration.py b/tests/test_critique_integration.py index 1dfb776c..ad80e95e 100644 --- a/tests/test_critique_integration.py +++ b/tests/test_critique_integration.py @@ -13,7 +13,7 @@ import sys from pathlib import Path # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from critique import ( generate_critique_prompt, diff --git a/tests/test_discovery.py b/tests/test_discovery.py index 5eb20d46..c83f4626 100644 --- a/tests/test_discovery.py +++ b/tests/test_discovery.py @@ -18,7 +18,7 @@ import pytest # Add auto-claude to path for imports import sys -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from test_discovery import ( TestFramework, diff --git a/tests/test_graphiti.py b/tests/test_graphiti.py index a5fb775f..6243e833 100644 --- a/tests/test_graphiti.py +++ b/tests/test_graphiti.py @@ -6,7 +6,7 @@ from unittest.mock import patch, MagicMock # Add auto-claude to path import sys -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from graphiti_config import is_graphiti_enabled, get_graphiti_status, GraphitiConfig diff --git a/tests/test_merge_auto_merger.py b/tests/test_merge_auto_merger.py index a3b57163..af5d1a1b 100644 --- a/tests/test_merge_auto_merger.py +++ b/tests/test_merge_auto_merger.py @@ -23,7 +23,7 @@ from pathlib import Path import pytest # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from merge import ( ChangeType, diff --git a/tests/test_merge_conflict_detector.py b/tests/test_merge_conflict_detector.py index 11ee0c39..47eb845d 100644 --- a/tests/test_merge_conflict_detector.py +++ b/tests/test_merge_conflict_detector.py @@ -20,7 +20,7 @@ from pathlib import Path import pytest # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from merge import ( ChangeType, diff --git a/tests/test_merge_file_tracker.py b/tests/test_merge_file_tracker.py index 656fa1a1..4a6839da 100644 --- a/tests/test_merge_file_tracker.py +++ b/tests/test_merge_file_tracker.py @@ -21,7 +21,7 @@ from pathlib import Path import pytest # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) # Add tests directory to path for test_fixtures sys.path.insert(0, str(Path(__file__).parent)) diff --git a/tests/test_merge_fixtures.py b/tests/test_merge_fixtures.py index f1edb38e..c201d66d 100644 --- a/tests/test_merge_fixtures.py +++ b/tests/test_merge_fixtures.py @@ -19,7 +19,7 @@ from unittest.mock import MagicMock import pytest # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from merge import ( SemanticAnalyzer, diff --git a/tests/test_merge_orchestrator.py b/tests/test_merge_orchestrator.py index b6aca437..ecaa65c8 100644 --- a/tests/test_merge_orchestrator.py +++ b/tests/test_merge_orchestrator.py @@ -23,7 +23,7 @@ from pathlib import Path import pytest # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) # Add tests directory to path for test_fixtures sys.path.insert(0, str(Path(__file__).parent)) diff --git a/tests/test_merge_parallel.py b/tests/test_merge_parallel.py index be2f9159..fe409f8a 100644 --- a/tests/test_merge_parallel.py +++ b/tests/test_merge_parallel.py @@ -18,7 +18,7 @@ from pathlib import Path import pytest # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from workspace import ParallelMergeTask, ParallelMergeResult from core.workspace import _run_parallel_merges diff --git a/tests/test_merge_semantic_analyzer.py b/tests/test_merge_semantic_analyzer.py index 6afc049b..e3c58d65 100644 --- a/tests/test_merge_semantic_analyzer.py +++ b/tests/test_merge_semantic_analyzer.py @@ -19,7 +19,7 @@ from pathlib import Path import pytest # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) # Add tests directory to path for test_fixtures sys.path.insert(0, str(Path(__file__).parent)) diff --git a/tests/test_merge_types.py b/tests/test_merge_types.py index a2a420ed..68e0a157 100644 --- a/tests/test_merge_types.py +++ b/tests/test_merge_types.py @@ -21,7 +21,7 @@ from pathlib import Path import pytest # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from merge import ( ChangeType, diff --git a/tests/test_qa_criteria.py b/tests/test_qa_criteria.py index 47bf947f..00e963f0 100644 --- a/tests/test_qa_criteria.py +++ b/tests/test_qa_criteria.py @@ -100,7 +100,7 @@ mock_client.create_client = MagicMock() sys.modules['client'] = mock_client # Now we can safely add the auto-claude path and import -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) # Import criteria functions directly to avoid going through qa/__init__.py # which imports reviewer and fixer that need the SDK diff --git a/tests/test_qa_loop_enhancements.py b/tests/test_qa_loop_enhancements.py index f758f627..4fcbf309 100644 --- a/tests/test_qa_loop_enhancements.py +++ b/tests/test_qa_loop_enhancements.py @@ -18,7 +18,7 @@ import pytest # Add auto-claude to path for imports import sys -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from qa_loop import ( # Iteration tracking diff --git a/tests/test_risk_classifier.py b/tests/test_risk_classifier.py index 5c45a1c8..2f12fccd 100644 --- a/tests/test_risk_classifier.py +++ b/tests/test_risk_classifier.py @@ -17,7 +17,7 @@ from pathlib import Path import sys -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from risk_classifier import ( RiskClassifier, diff --git a/tests/test_security_scanner.py b/tests/test_security_scanner.py index d829dcd1..0f1e95be 100644 --- a/tests/test_security_scanner.py +++ b/tests/test_security_scanner.py @@ -19,7 +19,7 @@ import pytest # Add auto-claude to path for imports import sys -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from security_scanner import ( SecurityVulnerability, diff --git a/tests/test_service_orchestrator.py b/tests/test_service_orchestrator.py index 54375786..5a59efd9 100644 --- a/tests/test_service_orchestrator.py +++ b/tests/test_service_orchestrator.py @@ -17,7 +17,7 @@ import pytest # Add auto-claude to path for imports import sys -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from service_orchestrator import ( ServiceConfig, diff --git a/tests/test_spec_complexity.py b/tests/test_spec_complexity.py index 71ec43cf..48b09220 100644 --- a/tests/test_spec_complexity.py +++ b/tests/test_spec_complexity.py @@ -50,7 +50,7 @@ sys.modules['claude_agent_sdk'] = mock_agent_sdk sys.modules['claude_agent_sdk.types'] = mock_agent_types # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from spec.complexity import ( Complexity, diff --git a/tests/test_spec_pipeline.py b/tests/test_spec_pipeline.py index 4d4e7ec1..a6778cd9 100644 --- a/tests/test_spec_pipeline.py +++ b/tests/test_spec_pipeline.py @@ -19,7 +19,7 @@ from pathlib import Path from unittest.mock import MagicMock, patch, AsyncMock # Add auto-claude directory to path for imports -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) # Store original modules for cleanup _original_modules = {} diff --git a/tests/test_thinking_level_validation.py b/tests/test_thinking_level_validation.py index 09e6b066..186fd193 100644 --- a/tests/test_thinking_level_validation.py +++ b/tests/test_thinking_level_validation.py @@ -12,7 +12,7 @@ from pathlib import Path import pytest # Add auto-claude to path -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from phase_config import THINKING_BUDGET_MAP, get_thinking_budget diff --git a/tests/test_validation_strategy.py b/tests/test_validation_strategy.py index c392f2b7..db916091 100644 --- a/tests/test_validation_strategy.py +++ b/tests/test_validation_strategy.py @@ -18,7 +18,7 @@ import pytest # Add auto-claude to path for imports import sys -sys.path.insert(0, str(Path(__file__).parent.parent / "auto-claude")) +sys.path.insert(0, str(Path(__file__).parent.parent / "Apps" / "backend")) from validation_strategy import ( ValidationStep,