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,