diff --git a/.github/guidelines-check.yml b/.github/guidelines-check.yml new file mode 100644 index 000000000..522e52a5b --- /dev/null +++ b/.github/guidelines-check.yml @@ -0,0 +1,57 @@ +# +# This file is intentionally in the wrong dir, will move and add later.... +# + +name: Guidelines Check + +on: + # Disabled - uncomment to re-enable + # pull_request_target: + # types: [opened, synchronize] + +jobs: + check-guidelines: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Install opencode + run: curl -fsSL https://opencode.ai/install | bash + + - name: Check PR guidelines compliance + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + OPENCODE_PERMISSION: '{ "bash": { "gh*": "allow", "gh pr review*": "deny", "*": "deny" } }' + run: | + opencode run -m anthropic/claude-sonnet-4-20250514 "A new pull request has been created: '${{ github.event.pull_request.title }}' + + + ${{ github.event.pull_request.number }} + + + + ${{ github.event.pull_request.body }} + + + Please check all the code changes in this pull request against the guidelines in AGENTS.md file in this repository. Diffs are important but make sure you read the entire file to get proper context. Make it clear the suggestions are merely suggestions and the human can decide what to do + + Use the gh cli to create comments on the files for the violations. Try to leave the comment on the exact line number. If you have a suggested fix include it in a suggestion code block. + + Command MUST be like this. + ``` + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/comments \ + -f 'body=[summary of issue]' -f 'commit_id=${{ github.event.pull_request.head.sha }}' -f 'path=[path-to-file]' -F "line=[line]" -f 'side=RIGHT' + ``` + + Only create comments for actual violations. If the code follows all guidelines, don't run any gh commands." diff --git a/.github/workflows/auto-label-tui.yml b/.github/workflows/auto-label-tui.yml new file mode 100644 index 000000000..0f03bb68d --- /dev/null +++ b/.github/workflows/auto-label-tui.yml @@ -0,0 +1,63 @@ +name: Auto-label TUI Issues + +on: + issues: + types: [opened] + +jobs: + auto-label: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + steps: + - name: Auto-label and assign issues + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const issue = context.payload.issue; + const title = issue.title; + const description = issue.body || ''; + + // Check for "opencode web" keyword + const webPattern = /(opencode web)/i; + const isWebRelated = webPattern.test(title) || webPattern.test(description); + + // Check for version patterns like v1.0.x or 1.0.x + const versionPattern = /[v]?1\.0\./i; + const isVersionRelated = versionPattern.test(title) || versionPattern.test(description); + + // Check for "nix" keyword + const nixPattern = /\bnix\b/i; + const isNixRelated = nixPattern.test(title) || nixPattern.test(description); + + const labels = []; + + if (isWebRelated) { + labels.push('web'); + + // Assign to adamdotdevin + await github.rest.issues.addAssignees({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + assignees: ['adamdotdevin'] + }); + } else if (isVersionRelated) { + // Only add opentui if NOT web-related + labels.push('opentui'); + } + + if (isNixRelated) { + labels.push('nix'); + } + + if (labels.length > 0) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: labels + }); + } diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 25466a63e..0cc239e31 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,7 +11,7 @@ concurrency: ${{ github.workflow }}-${{ github.ref }} jobs: deploy: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/docs-update.yml b/.github/workflows/docs-update.yml deleted file mode 100644 index 11d6a9c82..000000000 --- a/.github/workflows/docs-update.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Docs Update - -on: - schedule: - - cron: "0 */12 * * *" - workflow_dispatch: - -jobs: - update-docs: - if: github.repository == 'sst/opencode' - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - id-token: write - contents: write - pull-requests: write - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Fetch full history to access commits - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Get recent commits - id: commits - run: | - COMMITS=$(git log --since="4 hours ago" --pretty=format:"- %h %s" 2>/dev/null || echo "") - if [ -z "$COMMITS" ]; then - echo "No commits in the last 4 hours" - echo "has_commits=false" >> $GITHUB_OUTPUT - else - echo "has_commits=true" >> $GITHUB_OUTPUT - { - echo "list<> $GITHUB_OUTPUT - fi - - - name: Run opencode - if: steps.commits.outputs.has_commits == 'true' - uses: sst/opencode/github@latest - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - with: - model: opencode/gpt-5.2 - agent: docs - prompt: | - Review the following commits from the last 4 hours and identify any new features that may need documentation. - - - ${{ steps.commits.outputs.list }} - - - Steps: - 1. For each commit that looks like a new feature or significant change: - - Read the changed files to understand what was added - - Check if the feature is already documented in packages/web/src/content/docs/* - 2. If you find undocumented features: - - Update the relevant documentation files in packages/web/src/content/docs/* - - Follow the existing documentation style and structure - - Make sure to document the feature clearly with examples where appropriate - 3. If all new features are already documented, report that no updates are needed - 4. If you are creating a new documentation file be sure to update packages/web/astro.config.mjs too. - - Focus on user-facing features and API changes. Skip internal refactors, bug fixes, and test updates unless they affect user-facing behavior. - Don't feel the need to document every little thing. It is perfectly okay to make 0 changes at all. - Try to keep documentation only for large features or changes that already have a good spot to be documented. diff --git a/.github/workflows/duplicate-issues.yml b/.github/workflows/duplicate-issues.yml index dc82d297b..3b5c39193 100644 --- a/.github/workflows/duplicate-issues.yml +++ b/.github/workflows/duplicate-issues.yml @@ -6,7 +6,7 @@ on: jobs: check-duplicates: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest permissions: contents: read issues: write @@ -16,8 +16,6 @@ jobs: with: fetch-depth: 1 - - uses: ./.github/actions/setup-bun - - name: Install opencode run: curl -fsSL https://opencode.ai/install | bash @@ -57,7 +55,4 @@ jobs: Feel free to ignore if none of these address your specific case.' - Additionally, if the issue mentions keybinds, keyboard shortcuts, or key bindings, please add a comment mentioning the pinned keybinds issue #4997: - 'For keybind-related issues, please also check our pinned keybinds documentation: #4997' - If no clear duplicates are found, do not comment." diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 000000000..718ab27c7 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,29 @@ +name: format + +on: + push: + branches-ignore: + - production + pull_request: + branches-ignore: + - production + workflow_dispatch: +jobs: + format: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Bun + uses: ./.github/actions/setup-bun + + - name: run + run: | + ./script/format.ts + env: + CI: true diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml deleted file mode 100644 index 29cc98953..000000000 --- a/.github/workflows/generate.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: generate - -on: - push: - branches: - - dev - workflow_dispatch: - -jobs: - generate: - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: write - pull-requests: write - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} - ref: ${{ github.event.pull_request.head.ref || github.ref_name }} - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Generate - run: ./script/generate.ts - - - name: Commit and push - run: | - if [ -z "$(git status --porcelain)" ]; then - echo "No changes to commit" - exit 0 - fi - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add -A - git commit -m "chore: generate" - git push origin HEAD:${{ github.ref_name }} --no-verify - # if ! git push origin HEAD:${{ github.event.pull_request.head.ref || github.ref_name }} --no-verify; then - # echo "" - # echo "============================================" - # echo "Failed to push generated code." - # echo "Please run locally and push:" - # echo "" - # echo " ./script/generate.ts" - # echo " git add -A && git commit -m \"chore: generate\" && git push" - # echo "" - # echo "============================================" - # exit 1 - # fi diff --git a/.github/workflows/notify-discord.yml b/.github/workflows/notify-discord.yml index 62577ecf0..fde896410 100644 --- a/.github/workflows/notify-discord.yml +++ b/.github/workflows/notify-discord.yml @@ -2,11 +2,11 @@ name: discord on: release: - types: [released] # fires when a draft release is published + types: [published] # fires only when a release is published jobs: notify: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Send nicely-formatted embed to Discord uses: SethCohen/github-releases-to-discord@v1 diff --git a/.github/workflows/opencode.yml b/.github/workflows/opencode.yml index 37210191e..f7d7f6081 100644 --- a/.github/workflows/opencode.yml +++ b/.github/workflows/opencode.yml @@ -13,7 +13,7 @@ jobs: startsWith(github.event.comment.body, '/oc') || contains(github.event.comment.body, ' /opencode') || startsWith(github.event.comment.body, '/opencode') - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest permissions: id-token: write contents: read @@ -29,6 +29,5 @@ jobs: uses: sst/opencode/github@latest env: OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - OPENCODE_PERMISSION: '{"bash": "deny"}' with: - model: opencode/claude-opus-4-5 + model: opencode/glm-4.6 diff --git a/.github/workflows/publish-github-action.yml b/.github/workflows/publish-github-action.yml index d2789373a..cfd14148c 100644 --- a/.github/workflows/publish-github-action.yml +++ b/.github/workflows/publish-github-action.yml @@ -14,7 +14,7 @@ permissions: jobs: publish: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/publish-vscode.yml b/.github/workflows/publish-vscode.yml index f49a10578..48357813f 100644 --- a/.github/workflows/publish-vscode.yml +++ b/.github/workflows/publish-vscode.yml @@ -13,7 +13,7 @@ permissions: jobs: publish: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ec98d7061..710d7c0a1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,15 +2,11 @@ name: publish run-name: "${{ format('release {0}', inputs.bump) }}" on: - push: - branches: - - dev - - snapshot-* workflow_dispatch: inputs: bump: description: "Bump major, minor, or patch" - required: false + required: true type: choice options: - major @@ -21,17 +17,15 @@ on: required: false type: string -concurrency: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.version || inputs.bump }} +concurrency: ${{ github.workflow }}-${{ github.ref }} permissions: - id-token: write contents: write packages: write jobs: publish: - runs-on: blacksmith-4vcpu-ubuntu-2404 - if: github.repository == 'sst/opencode' + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: @@ -39,11 +33,33 @@ jobs: - run: git fetch --force --tags + - uses: actions/setup-go@v5 + with: + go-version: ">=1.24.0" + cache: true + cache-dependency-path: go.sum + - uses: ./.github/actions/setup-bun + - name: Install makepkg + run: | + sudo apt-get update + sudo apt-get install -y pacman-package-manager + - name: Setup SSH for AUR + run: | + mkdir -p ~/.ssh + echo "${{ secrets.AUR_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + git config --global user.email "opencode@sst.dev" + git config --global user.name "opencode" + ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts || true + - name: Install OpenCode - if: inputs.bump || inputs.version - run: bun i -g opencode-ai@1.0.169 + run: curl -fsSL https://opencode.ai/install | bash + + - name: Setup npm auth + run: | + echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc - name: Login to GitHub Container Registry uses: docker/login-action@v3 @@ -52,182 +68,14 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - uses: actions/setup-node@v4 - with: - node-version: "24" - registry-url: "https://registry.npmjs.org" - - - name: Setup Git Identity - run: | - git config --global user.email "opencode@sst.dev" - git config --global user.name "opencode" - git remote set-url origin https://x-access-token:${{ secrets.SST_GITHUB_TOKEN }}@github.com/${{ github.repository }} - - name: Publish - id: publish - run: ./script/publish-start.ts + run: | + ./script/publish.ts env: OPENCODE_BUMP: ${{ inputs.bump }} OPENCODE_VERSION: ${{ inputs.version }} - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - AUR_KEY: ${{ secrets.AUR_KEY }} - GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} - NPM_CONFIG_PROVENANCE: false - - - uses: actions/upload-artifact@v4 - with: - name: opencode-cli - path: packages/opencode/dist - - outputs: - release: ${{ steps.publish.outputs.release }} - tag: ${{ steps.publish.outputs.tag }} - version: ${{ steps.publish.outputs.version }} - - publish-tauri: - needs: publish - continue-on-error: true - strategy: - fail-fast: false - matrix: - settings: - - host: macos-latest - target: x86_64-apple-darwin - - host: macos-latest - target: aarch64-apple-darwin - - host: blacksmith-4vcpu-windows-2025 - target: x86_64-pc-windows-msvc - - host: blacksmith-4vcpu-ubuntu-2404 - target: x86_64-unknown-linux-gnu - - host: blacksmith-4vcpu-ubuntu-2404-arm - target: aarch64-unknown-linux-gnu - runs-on: ${{ matrix.settings.host }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ needs.publish.outputs.tag }} - - - uses: apple-actions/import-codesign-certs@v2 - if: ${{ runner.os == 'macOS' }} - with: - keychain: build - p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }} - p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - - - name: Verify Certificate - if: ${{ runner.os == 'macOS' }} - run: | - CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application") - CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}') - echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV - echo "Certificate imported." - - - name: Setup Apple API Key - if: ${{ runner.os == 'macOS' }} - run: | - echo "${{ secrets.APPLE_API_KEY_PATH }}" > $RUNNER_TEMP/apple-api-key.p8 - - - run: git fetch --force --tags - - - uses: ./.github/actions/setup-bun - - - name: install dependencies (ubuntu only) - if: contains(matrix.settings.host, 'ubuntu') - run: | - sudo apt-get update - sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf - - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - targets: ${{ matrix.settings.target }} - - - uses: Swatinem/rust-cache@v2 - with: - workspaces: packages/desktop/src-tauri - shared-key: ${{ matrix.settings.target }} - - - name: Prepare - run: | - cd packages/desktop - bun ./scripts/prepare.ts - env: - OPENCODE_VERSION: ${{ needs.publish.outputs.version }} + OPENCODE_CHANNEL: latest NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} AUR_KEY: ${{ secrets.AUR_KEY }} OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - RUST_TARGET: ${{ matrix.settings.target }} - GH_TOKEN: ${{ github.token }} - GITHUB_RUN_ID: ${{ github.run_id }} - - # Fixes AppImage build issues, can be removed when https://github.com/tauri-apps/tauri/pull/12491 is released - - name: Install tauri-cli from portable appimage branch - if: contains(matrix.settings.host, 'ubuntu') - run: | - cargo install tauri-cli --git https://github.com/tauri-apps/tauri --branch feat/truly-portable-appimage --force - echo "Installed tauri-cli version:" - cargo tauri --version - - - name: Build and upload artifacts - timeout-minutes: 20 - uses: tauri-apps/tauri-action@390cbe447412ced1303d35abe75287949e43437a - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAURI_BUNDLER_NEW_APPIMAGE_FORMAT: true - TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} - TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }} - APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} - APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }} - APPLE_API_KEY_PATH: ${{ runner.temp }}/apple-api-key.p8 - with: - projectPath: packages/desktop - uploadWorkflowArtifacts: true - tauriScript: ${{ (contains(matrix.settings.host, 'ubuntu') && 'cargo tauri') || '' }} - args: --target ${{ matrix.settings.target }} --config ./src-tauri/tauri.prod.conf.json --verbose - updaterJsonPreferNsis: true - releaseId: ${{ needs.publish.outputs.release }} - tagName: ${{ needs.publish.outputs.tag }} - releaseAssetNamePattern: opencode-desktop-[platform]-[arch][ext] - releaseDraft: true - - publish-release: - needs: - - publish - - publish-tauri - if: needs.publish.outputs.tag - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ needs.publish.outputs.tag }} - - - uses: ./.github/actions/setup-bun - - - name: Setup SSH for AUR - run: | - sudo apt-get update - sudo apt-get install -y pacman-package-manager - mkdir -p ~/.ssh - echo "${{ secrets.AUR_KEY }}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - git config --global user.email "opencode@sst.dev" - git config --global user.name "opencode" - ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts || true - - - run: ./script/publish-complete.ts - env: - OPENCODE_VERSION: ${{ needs.publish.outputs.version }} - AUR_KEY: ${{ secrets.AUR_KEY }} - GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} diff --git a/.github/workflows/release-github-action.yml b/.github/workflows/release-github-action.yml deleted file mode 100644 index 3f5caa55c..000000000 --- a/.github/workflows/release-github-action.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: release-github-action - -on: - push: - branches: - - dev - paths: - - "github/**" - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -permissions: - contents: write - -jobs: - release: - runs-on: blacksmith-4vcpu-ubuntu-2404 - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - run: git fetch --force --tags - - - name: Release - run: | - git config --global user.email "opencode@sst.dev" - git config --global user.name "opencode" - ./github/script/release diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml deleted file mode 100644 index c0e3a5deb..000000000 --- a/.github/workflows/review.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Guidelines Check - -on: - issue_comment: - types: [created] - -jobs: - check-guidelines: - if: | - github.event.issue.pull_request && - startsWith(github.event.comment.body, '/review') && - contains(fromJson('["OWNER","MEMBER"]'), github.event.comment.author_association) - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: read - pull-requests: write - steps: - - name: Get PR number - id: pr-number - run: | - if [ "${{ github.event_name }}" = "pull_request_target" ]; then - echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT - else - echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT - fi - - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - uses: ./.github/actions/setup-bun - - - name: Install opencode - run: curl -fsSL https://opencode.ai/install | bash - - - name: Get PR details - id: pr-details - run: | - gh api /repos/${{ github.repository }}/pulls/${{ steps.pr-number.outputs.number }} > pr_data.json - echo "title=$(jq -r .title pr_data.json)" >> $GITHUB_OUTPUT - echo "sha=$(jq -r .head.sha pr_data.json)" >> $GITHUB_OUTPUT - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Check PR guidelines compliance - env: - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - OPENCODE_PERMISSION: '{ "bash": { "gh*": "allow", "gh pr review*": "deny", "*": "deny" } }' - PR_TITLE: ${{ steps.pr-details.outputs.title }} - run: | - PR_BODY=$(jq -r .body pr_data.json) - opencode run -m anthropic/claude-opus-4-5 "A new pull request has been created: '${PR_TITLE}' - - - ${{ steps.pr-number.outputs.number }} - - - - $PR_BODY - - - Please check all the code changes in this pull request against the style guide, also look for any bugs if they exist. Diffs are important but make sure you read the entire file to get proper context. Make it clear the suggestions are merely suggestions and the human can decide what to do - - When critiquing code against the style guide, be sure that the code is ACTUALLY in violation, don't complain about else statements if they already use early returns there. You may complain about excessive nesting though, regardless of else statement usage. - When critiquing code style don't be a zealot, we don't like "let" statements but sometimes they are the simpliest option, if someone does a bunch of nesting with let, they should consider using iife (see packages/opencode/src/util.iife.ts) - - Use the gh cli to create comments on the files for the violations. Try to leave the comment on the exact line number. If you have a suggested fix include it in a suggestion code block. - If you are writing suggested fixes, BE SURE THAT the change you are recommending is actually valid typescript, often I have seen missing closing "}" or other syntax errors. - Generally, write a comment instead of writing suggested change if you can help it. - - Command MUST be like this. - \`\`\` - gh api \ - --method POST \ - -H \"Accept: application/vnd.github+json\" \ - -H \"X-GitHub-Api-Version: 2022-11-28\" \ - /repos/${{ github.repository }}/pulls/${{ steps.pr-number.outputs.number }}/comments \ - -f 'body=[summary of issue]' -f 'commit_id=${{ steps.pr-details.outputs.sha }}' -f 'path=[path-to-file]' -F \"line=[line]\" -f 'side=RIGHT' - \`\`\` - - Only create comments for actual violations. If the code follows all guidelines, comment on the issue using gh cli: 'lgtm' AND NOTHING ELSE!!!!." diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 000000000..f8bbb78c6 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,35 @@ +name: snapshot + +on: + push: + branches: + - dev + - test-bedrock + - v0 + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - run: git fetch --force --tags + + - uses: actions/setup-go@v5 + with: + go-version: ">=1.24.0" + cache: true + cache-dependency-path: go.sum + + - uses: ./.github/actions/setup-bun + + - name: Publish + run: | + ./script/publish.ts + env: + GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} + NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/stats.yml b/.github/workflows/stats.yml index 57e93642b..01ddf314a 100644 --- a/.github/workflows/stats.yml +++ b/.github/workflows/stats.yml @@ -5,12 +5,9 @@ on: - cron: "0 12 * * *" # Run daily at 12:00 UTC workflow_dispatch: # Allow manual trigger -concurrency: ${{ github.workflow }}-${{ github.ref }} - jobs: stats: - if: github.repository == 'sst/opencode' - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest permissions: contents: write diff --git a/.github/workflows/sync-zed-extension.yml b/.github/workflows/sync-zed-extension.yml index a504582c3..c9dea7bb7 100644 --- a/.github/workflows/sync-zed-extension.yml +++ b/.github/workflows/sync-zed-extension.yml @@ -2,13 +2,13 @@ name: "sync-zed-extension" on: workflow_dispatch: - # release: - # types: [published] + release: + types: [published] jobs: zed: name: Release Zed Extension - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ac1a24fd5..ccce2aa25 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ on: workflow_dispatch: jobs: test: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 @@ -28,3 +28,9 @@ jobs: bun turbo test env: CI: true + + - name: Check SDK is up to date + run: | + bun ./packages/sdk/js/script/build.ts + git diff --exit-code packages/sdk/js/src/gen packages/sdk/js/dist + continue-on-error: false diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml deleted file mode 100644 index 6e1509572..000000000 --- a/.github/workflows/triage.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Issue Triage - -on: - issues: - types: [opened] - -jobs: - triage: - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: read - issues: write - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Setup Bun - uses: ./.github/actions/setup-bun - - - name: Install opencode - run: curl -fsSL https://opencode.ai/install | bash - - - name: Triage issue - env: - OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ISSUE_NUMBER: ${{ github.event.issue.number }} - ISSUE_TITLE: ${{ github.event.issue.title }} - ISSUE_BODY: ${{ github.event.issue.body }} - run: | - opencode run --agent triage "The following issue was just opened, triage it: - - Title: $ISSUE_TITLE - - $ISSUE_BODY" diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 011e23f5f..8943e10be 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -7,7 +7,7 @@ on: jobs: typecheck: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/update-nix-hashes.yml b/.github/workflows/update-nix-hashes.yml index d2c60b08f..38dba2e35 100644 --- a/.github/workflows/update-nix-hashes.yml +++ b/.github/workflows/update-nix-hashes.yml @@ -18,8 +18,7 @@ on: jobs: update: - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest env: SYSTEM: x86_64-linux @@ -30,7 +29,6 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 ref: ${{ github.head_ref || github.ref_name }} - repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} - name: Setup Nix uses: DeterminateSystems/nix-installer-action@v20 diff --git a/.gitignore b/.gitignore index 7b9c006f9..62cb12717 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,10 @@ node_modules .idea .vscode *~ +openapi.json playground tmp dist -ts-dist .turbo **/.serena .serena/ @@ -18,5 +18,3 @@ refs Session.vim opencode.json a.out -target -.scripts diff --git a/.husky/pre-push b/.husky/pre-push index 2fd039d56..b26017ee9 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,9 +1,2 @@ #!/bin/sh -# Check if bun version matches package.json -EXPECTED_VERSION=$(grep '"packageManager"' package.json | sed 's/.*"bun@\([^"]*\)".*/\1/') -CURRENT_VERSION=$(bun --version) -if [ "$CURRENT_VERSION" != "$EXPECTED_VERSION" ]; then - echo "Error: Bun version $CURRENT_VERSION does not match expected version $EXPECTED_VERSION from package.json" - exit 1 -fi bun typecheck diff --git a/.opencode/agent/triage.md b/.opencode/agent/triage.md deleted file mode 100644 index b2db100e9..000000000 --- a/.opencode/agent/triage.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -mode: primary -hidden: true -model: opencode/claude-haiku-4-5 -tools: - "*": false - "github-triage": true ---- - -You are a triage agent responsible for triaging github issues. - -Use your github-triage tool to triage issues. - -## Labels - -### windows - -Use for any issue that mentions Windows (the OS). Be sure they are saying that they are on Windows. - -- Use if they mention WSL too - -#### perf - -Performance-related issues: - -- Slow performance -- High RAM usage -- High CPU usage - -**Only** add if it's likely a RAM or CPU issue. **Do not** add for LLM slowness. - -#### desktop - -Desktop app issues: - -- `opencode web` command -- The desktop app itself - -**Only** add if it's specifically about the Desktop application or `opencode web` view. **Do not** add for terminal, TUI, or general opencode issues. - -#### nix - -**Only** add if the issue explicitly mentions nix. - -#### zen - -**Only** add if the issue mentions "zen" or "opencode zen". Zen is our gateway for coding models. **Do not** add for other gateways or inference providers. - -If the issue doesn't have "zen" in it then don't add zen label - -#### docs - -Add if the issue requests better documentation or docs updates. - -#### opentui - -TUI issues potentially caused by our underlying TUI library: - -- Keybindings not working -- Scroll speed issues (too fast/slow/laggy) -- Screen flickering -- Crashes with opentui in the log - -**Do not** add for general TUI bugs. - -When assigning to people here are the following rules: - -adamdotdev: -ONLY assign adam if the issue will have the "desktop" label. - -fwang: -ONLY assign fwang if the issue will have the "zen" label. - -jayair: -ONLY assign jayair if the issue will have the "docs" label. - -In all other cases use best judgment. Avoid assigning to kommander needlessly, when in doubt assign to rekram1-node. diff --git a/.opencode/command/commit.md b/.opencode/command/commit.md index 8e9346ebc..2e3d759b6 100644 --- a/.opencode/command/commit.md +++ b/.opencode/command/commit.md @@ -1,7 +1,5 @@ --- -description: git commit and push -model: opencode/glm-4.6 -subtask: true +description: Git commit and push --- commit and push @@ -23,6 +21,3 @@ WHAT was done. do not do generic messages like "improved agent experience" be very specific about what user facing changes were made - -if there are changes do a git pull --rebase -if there are conflicts DO NOT FIX THEM. notify me and I will fix them diff --git a/.opencode/command/hello.md b/.opencode/command/hello.md new file mode 100644 index 000000000..003bc4a76 --- /dev/null +++ b/.opencode/command/hello.md @@ -0,0 +1,8 @@ +--- +description: hello world iaosd ioasjdoiasjd oisadjoisajd osiajd oisaj dosaij dsoajsajdaijdoisa jdoias jdoias jdoia jois jo jdois jdoias jdoias j djoasdj +--- + +hey there $ARGUMENTS + +!`ls` +check out @README.md diff --git a/.opencode/command/issues.md b/.opencode/command/issues.md index 20ac4c180..793dce651 100644 --- a/.opencode/command/issues.md +++ b/.opencode/command/issues.md @@ -1,5 +1,5 @@ --- -description: "find issue(s) on github" +description: "Find issue(s) on github" model: opencode/claude-haiku-4-5 --- diff --git a/.opencode/command/rmslop.md b/.opencode/command/rmslop.md deleted file mode 100644 index 02c9fc084..000000000 --- a/.opencode/command/rmslop.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -description: Remove AI code slop ---- - -Check the diff against dev, and remove all AI generated slop introduced in this branch. - -This includes: - -- Extra comments that a human wouldn't add or is inconsistent with the rest of the file -- Extra defensive checks or try/catch blocks that are abnormal for that area of the codebase (especially if called by trusted / validated codepaths) -- Casts to any to get around type issues -- Any other style that is inconsistent with the file -- Unnecessary emoji usage - -Report at the end with only a 1-3 sentence summary of what you changed diff --git a/.opencode/command/spellcheck.md b/.opencode/command/spellcheck.md index 0abf23c4f..afa1970b7 100644 --- a/.opencode/command/spellcheck.md +++ b/.opencode/command/spellcheck.md @@ -1,5 +1,5 @@ --- -description: spellcheck all markdown file changes +description: Spellcheck all markdown file changes --- Look at all the unstaged changes to markdown (.md, .mdx) files, pull out the lines that have changed, and check for spelling and grammar errors. diff --git a/.opencode/env.d.ts b/.opencode/env.d.ts deleted file mode 100644 index f2b13a934..000000000 --- a/.opencode/env.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module "*.txt" { - const content: string - export default content -} diff --git a/.opencode/opencode.jsonc b/.opencode/opencode.jsonc index cbcbb0c65..369832f9f 100644 --- a/.opencode/opencode.jsonc +++ b/.opencode/opencode.jsonc @@ -1,17 +1,20 @@ { "$schema": "https://opencode.ai/config.json", - // "plugin": ["opencode-openai-codex-auth"], + "plugin": ["opencode-openai-codex-auth"], // "enterprise": { // "url": "https://enterprise.dev.opencode.ai", // }, - "instructions": ["STYLE_GUIDE.md"], "provider": { "opencode": { - "options": {}, + "options": { + // "baseURL": "http://localhost:8080", + }, }, }, - "mcp": {}, - "tools": { - "github-triage": false, + "mcp": { + "exa": { + "type": "remote", + "url": "https://mcp.exa.ai/mcp", + }, }, } diff --git a/.opencode/skill/test-skill/SKILL.md b/.opencode/skill/test-skill/SKILL.md deleted file mode 100644 index 3fef059f2..000000000 --- a/.opencode/skill/test-skill/SKILL.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -name: test-skill -description: use this when asked to test skill ---- - -woah this is a test skill diff --git a/.opencode/tool/github-triage.ts b/.opencode/tool/github-triage.ts deleted file mode 100644 index a5e6c811d..000000000 --- a/.opencode/tool/github-triage.ts +++ /dev/null @@ -1,90 +0,0 @@ -/// -// import { Octokit } from "@octokit/rest" -import { tool } from "@opencode-ai/plugin" -import DESCRIPTION from "./github-triage.txt" - -function getIssueNumber(): number { - const issue = parseInt(process.env.ISSUE_NUMBER ?? "", 10) - if (!issue) throw new Error("ISSUE_NUMBER env var not set") - return issue -} - -async function githubFetch(endpoint: string, options: RequestInit = {}) { - const response = await fetch(`https://api.github.com${endpoint}`, { - ...options, - headers: { - Authorization: `Bearer ${process.env.GITHUB_TOKEN}`, - Accept: "application/vnd.github+json", - "Content-Type": "application/json", - ...options.headers, - }, - }) - if (!response.ok) { - throw new Error(`GitHub API error: ${response.status} ${response.statusText}`) - } - return response.json() -} - -export default tool({ - description: DESCRIPTION, - args: { - assignee: tool.schema - .enum(["thdxr", "adamdotdevin", "rekram1-node", "fwang", "jayair", "kommander"]) - .describe("The username of the assignee") - .default("rekram1-node"), - labels: tool.schema - .array(tool.schema.enum(["nix", "opentui", "perf", "desktop", "zen", "docs", "windows"])) - .describe("The labels(s) to add to the issue") - .default([]), - }, - async execute(args) { - const issue = getIssueNumber() - // const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN }) - const owner = "sst" - const repo = "opencode" - - const results: string[] = [] - - if (args.assignee === "adamdotdevin" && !args.labels.includes("desktop")) { - throw new Error("Only desktop issues should be assigned to adamdotdevin") - } - - if (args.assignee === "fwang" && !args.labels.includes("zen")) { - throw new Error("Only zen issues should be assigned to fwang") - } - - if (args.assignee === "kommander" && !args.labels.includes("opentui")) { - throw new Error("Only opentui issues should be assigned to kommander") - } - - // await octokit.rest.issues.addAssignees({ - // owner, - // repo, - // issue_number: issue, - // assignees: [args.assignee], - // }) - await githubFetch(`/repos/${owner}/${repo}/issues/${issue}/assignees`, { - method: "POST", - body: JSON.stringify({ assignees: [args.assignee] }), - }) - results.push(`Assigned @${args.assignee} to issue #${issue}`) - - const labels: string[] = args.labels.map((label) => (label === "desktop" ? "web" : label)) - - if (labels.length > 0) { - // await octokit.rest.issues.addLabels({ - // owner, - // repo, - // issue_number: issue, - // labels, - // }) - await githubFetch(`/repos/${owner}/${repo}/issues/${issue}/labels`, { - method: "POST", - body: JSON.stringify({ labels }), - }) - results.push(`Added labels: ${args.labels.join(", ")}`) - } - - return results.join("\n") - }, -}) diff --git a/.opencode/tool/github-triage.txt b/.opencode/tool/github-triage.txt deleted file mode 100644 index 4c46a72c1..000000000 --- a/.opencode/tool/github-triage.txt +++ /dev/null @@ -1,88 +0,0 @@ -Use this tool to assign and/or label a Github issue. - -You can assign the following users: -- thdxr -- adamdotdevin -- fwang -- jayair -- kommander -- rekram1-node - - -You can use the following labels: -- nix -- opentui -- perf -- web -- zen -- docs - -Always try to assign an issue, if in doubt, assign rekram1-node to it. - -## Breakdown of responsibilities: - -### thdxr - -Dax is responsible for managing core parts of the application, for large feature requests, api changes, or things that require significant changes to the codebase assign him. - -This relates to OpenCode server primarily but has overlap with just about anything - -### adamdotdevin - -Adam is responsible for managing the Desktop/Web app. If there is an issue relating to the desktop app or `opencode web` command. Assign him. - - -### fwang - -Frank is responsible for managing Zen, if you see complaints about OpenCode Zen, maybe it's the dashboard, the model quality, billing issues, etc. Assign him to the issue. - -### jayair - -Jay is responsible for documentation. If there is an issue relating to documentation assign him. - -### kommander - -Sebastian is responsible for managing an OpenTUI (a library for building terminal user interfaces). OpenCode's TUI is built with OpenTUI. If there are issues about: -- random characters on screen -- keybinds not working on different terminals -- general terminal stuff -Then assign the issue to Him. - -### rekram1-node - -ALL BUGS SHOULD BE assigned to rekram1-node unless they have the `opentui` label. - -Assign Aiden to an issue as a catch all, if you can't assign anyone else. Most of the time this will be bugs/polish things. -If no one else makes sense to assign, assign rekram1-node to it. - -Always assign to aiden if the issue mentions "acp", "zed", or model performance issues - -## Breakdown of Labels: - -### nix - -Any issue that mentions nix, or nixos should have a nix label - -### opentui - -Anything relating to the TUI itself should have an opentui label - -### perf - -Anything related to slow performance, high ram, high cpu usage, or any other performance related issue should have a perf label - -### desktop - -Anything related to `opencode web` command or the desktop app should have a desktop label. Never add this label for anything terminal/tui related - -### zen - -Anything related to OpenCode Zen, billing, or model quality from Zen should have a zen label - -### docs - -Anything related to the documentation should have a docs label - -### windows - -Use for any issue that involves the windows OS diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index aa3a7ce23..000000000 --- a/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -sst-env.d.ts \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index bbb2a96f2..22b305dac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,47 @@ +## IMPORTANT + +- Try to keep things in one function unless composable or reusable +- DO NOT do unnecessary destructuring of variables +- DO NOT use `else` statements unless necessary +- DO NOT use `try`/`catch` if it can be avoided +- AVOID `try`/`catch` where possible +- AVOID `else` statements +- AVOID using `any` type +- AVOID `let` statements +- PREFER single word variable names where possible +- Use as many bun apis as possible like Bun.file() + ## Debugging - To test opencode in the `packages/opencode` directory you can run `bun dev` ## Tool Calling -- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE. +- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE. Here is an example illustrating how to execute 3 parallel file reads in this chat environment: + +json +{ +"recipient_name": "multi_tool_use.parallel", +"parameters": { +"tool_uses": [ +{ +"recipient_name": "functions.read", +"parameters": { +"filePath": "path/to/file.tsx" +} +}, +{ +"recipient_name": "functions.read", +"parameters": { +"filePath": "path/to/file.ts" +} +}, +{ +"recipient_name": "functions.read", +"parameters": { +"filePath": "path/to/file.md" +} +} +] +} +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c16d664a2..2fc5737d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,9 +40,7 @@ Want to take on an issue? Leave a comment and a maintainer may assign it to you - `packages/plugin`: Source for `@opencode-ai/plugin` > [!NOTE] -> If you make changes to the API or SDK (e.g. `packages/opencode/src/server/server.ts`), run `./script/generate.ts` to regenerate the SDK and related files. - -Please try to follow the [style guide](./STYLE_GUIDE.md) +> After touching `packages/opencode/src/server/server.ts`, run "./packages/sdk/js/script/build.ts" to regenerate the JS sdk. ### Setting up a Debugger diff --git a/README.md b/README.md index 5295810b6..799cf00a2 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@

-

The open source AI coding agent.

+

The AI coding agent built for the terminal.

Discord npm @@ -30,29 +30,13 @@ scoop bucket add extras; scoop install extras/opencode # Windows choco install opencode # Windows brew install opencode # macOS and Linux paru -S opencode-bin # Arch Linux -mise use -g github:sst/opencode # Any OS +mise use --pin -g ubi:sst/opencode # Any OS nix run nixpkgs#opencode # or github:sst/opencode for latest dev branch ``` > [!TIP] > Remove versions older than 0.1.x before installing. -### Desktop App (BETA) - -OpenCode is also available as a desktop application. Download directly from the [releases page](https://github.com/sst/opencode/releases) or [opencode.ai/download](https://opencode.ai/download). - -| Platform | Download | -| --------------------- | ------------------------------------- | -| macOS (Apple Silicon) | `opencode-desktop-darwin-aarch64.dmg` | -| macOS (Intel) | `opencode-desktop-darwin-x64.dmg` | -| Windows | `opencode-desktop-windows-x64.exe` | -| Linux | `.deb`, `.rpm`, or AppImage | - -```bash -# macOS (Homebrew) -brew install --cask opencode-desktop -``` - #### Installation Directory The install script respects the following priority order for the installation path: @@ -94,7 +78,7 @@ If you're interested in contributing to OpenCode, please read our [contributing ### Building on OpenCode -If you are working on a project that's related to OpenCode and is using "opencode" as a part of its name; for example, "opencode-dashboard" or "opencode-mobile", please add a note to your README to clarify that it is not built by the OpenCode team and is not affiliated with us in any way. +If you are working on a project that's related to OpenCode and is using "opencode" as a part of its name; for example, "opencode-dashboard" or "opencode-mobile", please add a note to your README to clarify that it is not built by the OpenCode team and is not affiliated with us in anyway. ### FAQ diff --git a/README.zh-TW.md b/README.zh-TW.md deleted file mode 100644 index d3cbb263c..000000000 --- a/README.zh-TW.md +++ /dev/null @@ -1,115 +0,0 @@ -

- - - - - OpenCode logo - - -

-

開源的 AI Coding Agent。

-

- Discord - npm - Build status -

- -[![OpenCode Terminal UI](packages/web/src/assets/lander/screenshot.png)](https://opencode.ai) - ---- - -### 安裝 - -```bash -# 直接安裝 (YOLO) -curl -fsSL https://opencode.ai/install | bash - -# 套件管理員 -npm i -g opencode-ai@latest # 也可使用 bun/pnpm/yarn -scoop bucket add extras; scoop install extras/opencode # Windows -choco install opencode # Windows -brew install opencode # macOS 與 Linux -paru -S opencode-bin # Arch Linux -mise use -g github:sst/opencode # 任何作業系統 -nix run nixpkgs#opencode # 或使用 github:sst/opencode 以取得最新開發分支 -``` - -> [!TIP] -> 安裝前請先移除 0.1.x 以前的舊版本。 - -### 桌面應用程式 (BETA) - -OpenCode 也提供桌面版應用程式。您可以直接從 [發佈頁面 (releases page)](https://github.com/sst/opencode/releases) 或 [opencode.ai/download](https://opencode.ai/download) 下載。 - -| 平台 | 下載連結 | -| --------------------- | ------------------------------------- | -| macOS (Apple Silicon) | `opencode-desktop-darwin-aarch64.dmg` | -| macOS (Intel) | `opencode-desktop-darwin-x64.dmg` | -| Windows | `opencode-desktop-windows-x64.exe` | -| Linux | `.deb`, `.rpm`, 或 AppImage | - -```bash -# macOS (Homebrew Cask) -brew install --cask opencode-desktop -``` - -#### 安裝目錄 - -安裝腳本會依據以下優先順序決定安裝路徑: - -1. `$OPENCODE_INSTALL_DIR` - 自定義安裝目錄 -2. `$XDG_BIN_DIR` - 符合 XDG 基礎目錄規範的路徑 -3. `$HOME/bin` - 標準使用者執行檔目錄 (若存在或可建立) -4. `$HOME/.opencode/bin` - 預設備用路徑 - -```bash -# 範例 -OPENCODE_INSTALL_DIR=/usr/local/bin curl -fsSL https://opencode.ai/install | bash -XDG_BIN_DIR=$HOME/.local/bin curl -fsSL https://opencode.ai/install | bash -``` - -### Agents - -OpenCode 內建了兩種 Agent,您可以使用 `Tab` 鍵快速切換。 - -- **build** - 預設模式,具備完整權限的 Agent,適用於開發工作。 -- **plan** - 唯讀模式,適用於程式碼分析與探索。 - - 預設禁止修改檔案。 - - 執行 bash 指令前會詢問權限。 - - 非常適合用來探索陌生的程式碼庫或規劃變更。 - -此外,OpenCode 還包含一個 **general** 子 Agent,用於處理複雜搜尋與多步驟任務。此 Agent 供系統內部使用,亦可透過在訊息中輸入 `@general` 來呼叫。 - -了解更多關於 [Agents](https://opencode.ai/docs/agents) 的資訊。 - -### 線上文件 - -關於如何設定 OpenCode 的詳細資訊,請參閱我們的 [**官方文件**](https://opencode.ai/docs)。 - -### 參與貢獻 - -如果您有興趣參與 OpenCode 的開發,請在提交 Pull Request 前先閱讀我們的 [貢獻指南 (Contributing Docs)](./CONTRIBUTING.md)。 - -### 基於 OpenCode 進行開發 - -如果您正在開發與 OpenCode 相關的專案,並在名稱中使用了 "opencode"(例如 "opencode-dashboard" 或 "opencode-mobile"),請在您的 README 中加入聲明,說明該專案並非由 OpenCode 團隊開發,且與我們沒有任何隸屬關係。 - -### 常見問題 (FAQ) - -#### 這跟 Claude Code 有什麼不同? - -在功能面上與 Claude Code 非常相似。以下是關鍵差異: - -- 100% 開源。 -- 不綁定特定的服務提供商。雖然我們推薦使用透過 [OpenCode Zen](https://opencode.ai/zen) 提供的模型,但 OpenCode 也可搭配 Claude, OpenAI, Google 甚至本地模型使用。隨著模型不斷演進,彼此間的差距會縮小且價格會下降,因此具備「不限廠商 (provider-agnostic)」的特性至關重要。 -- 內建 LSP (語言伺服器協定) 支援。 -- 專注於終端機介面 (TUI)。OpenCode 由 Neovim 愛好者與 [terminal.shop](https://terminal.shop) 的創作者打造;我們將不斷挑戰終端機介面的極限。 -- 客戶端/伺服器架構 (Client/Server Architecture)。這讓 OpenCode 能夠在您的電腦上運行的同時,由行動裝置進行遠端操控。這意味著 TUI 前端只是眾多可能的客戶端之一。 - -#### 另一個同名的 Repo 是什麼? - -另一個名稱相近的儲存庫與本專案無關。您可以點此[閱讀背後的故事](https://x.com/thdxr/status/1933561254481666466)。 - ---- - -**加入我們的社群** [Discord](https://discord.gg/opencode) | [X.com](https://x.com/opencode) diff --git a/STATS.md b/STATS.md index 7f59be1aa..b58a8f1c5 100644 --- a/STATS.md +++ b/STATS.md @@ -1,180 +1,154 @@ # Download Stats -| Date | GitHub Downloads | npm Downloads | Total | -| ---------- | ------------------- | ------------------- | ------------------- | -| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) | -| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) | -| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) | -| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) | -| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) | -| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) | -| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) | -| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) | -| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) | -| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) | -| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) | -| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) | -| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) | -| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) | -| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) | -| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) | -| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) | -| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) | -| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) | -| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) | -| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) | -| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) | -| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) | -| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) | -| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) | -| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) | -| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) | -| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) | -| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) | -| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) | -| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) | -| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) | -| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) | -| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) | -| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) | -| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) | -| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) | -| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) | -| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) | -| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) | -| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) | -| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) | -| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) | -| 2025-08-12 | 176,307 (+7,010) | 171,876 (+3,923) | 348,183 (+10,933) | -| 2025-08-13 | 182,997 (+6,690) | 177,182 (+5,306) | 360,179 (+11,996) | -| 2025-08-14 | 189,063 (+6,066) | 179,741 (+2,559) | 368,804 (+8,625) | -| 2025-08-15 | 193,608 (+4,545) | 181,792 (+2,051) | 375,400 (+6,596) | -| 2025-08-16 | 198,118 (+4,510) | 184,558 (+2,766) | 382,676 (+7,276) | -| 2025-08-17 | 201,299 (+3,181) | 186,269 (+1,711) | 387,568 (+4,892) | -| 2025-08-18 | 204,559 (+3,260) | 187,399 (+1,130) | 391,958 (+4,390) | -| 2025-08-19 | 209,814 (+5,255) | 189,668 (+2,269) | 399,482 (+7,524) | -| 2025-08-20 | 214,497 (+4,683) | 191,481 (+1,813) | 405,978 (+6,496) | -| 2025-08-21 | 220,465 (+5,968) | 194,784 (+3,303) | 415,249 (+9,271) | -| 2025-08-22 | 225,899 (+5,434) | 197,204 (+2,420) | 423,103 (+7,854) | -| 2025-08-23 | 229,005 (+3,106) | 199,238 (+2,034) | 428,243 (+5,140) | -| 2025-08-24 | 232,098 (+3,093) | 201,157 (+1,919) | 433,255 (+5,012) | -| 2025-08-25 | 236,607 (+4,509) | 202,650 (+1,493) | 439,257 (+6,002) | -| 2025-08-26 | 242,783 (+6,176) | 205,242 (+2,592) | 448,025 (+8,768) | -| 2025-08-27 | 248,409 (+5,626) | 205,242 (+0) | 453,651 (+5,626) | -| 2025-08-28 | 252,796 (+4,387) | 205,242 (+0) | 458,038 (+4,387) | -| 2025-08-29 | 256,045 (+3,249) | 211,075 (+5,833) | 467,120 (+9,082) | -| 2025-08-30 | 258,863 (+2,818) | 212,397 (+1,322) | 471,260 (+4,140) | -| 2025-08-31 | 262,004 (+3,141) | 213,944 (+1,547) | 475,948 (+4,688) | -| 2025-09-01 | 265,359 (+3,355) | 215,115 (+1,171) | 480,474 (+4,526) | -| 2025-09-02 | 270,483 (+5,124) | 217,075 (+1,960) | 487,558 (+7,084) | -| 2025-09-03 | 274,793 (+4,310) | 219,755 (+2,680) | 494,548 (+6,990) | -| 2025-09-04 | 280,430 (+5,637) | 222,103 (+2,348) | 502,533 (+7,985) | -| 2025-09-05 | 283,769 (+3,339) | 223,793 (+1,690) | 507,562 (+5,029) | -| 2025-09-06 | 286,245 (+2,476) | 225,036 (+1,243) | 511,281 (+3,719) | -| 2025-09-07 | 288,623 (+2,378) | 225,866 (+830) | 514,489 (+3,208) | -| 2025-09-08 | 293,341 (+4,718) | 227,073 (+1,207) | 520,414 (+5,925) | -| 2025-09-09 | 300,036 (+6,695) | 229,788 (+2,715) | 529,824 (+9,410) | -| 2025-09-10 | 307,287 (+7,251) | 233,435 (+3,647) | 540,722 (+10,898) | -| 2025-09-11 | 314,083 (+6,796) | 237,356 (+3,921) | 551,439 (+10,717) | -| 2025-09-12 | 321,046 (+6,963) | 240,728 (+3,372) | 561,774 (+10,335) | -| 2025-09-13 | 324,894 (+3,848) | 245,539 (+4,811) | 570,433 (+8,659) | -| 2025-09-14 | 328,876 (+3,982) | 248,245 (+2,706) | 577,121 (+6,688) | -| 2025-09-15 | 334,201 (+5,325) | 250,983 (+2,738) | 585,184 (+8,063) | -| 2025-09-16 | 342,609 (+8,408) | 255,264 (+4,281) | 597,873 (+12,689) | -| 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) | -| 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) | -| 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) | -| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) | -| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) | -| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) | -| 2025-09-23 | 387,008 (+4,516) | 289,129 (+5,120) | 676,137 (+9,636) | -| 2025-09-24 | 393,325 (+6,317) | 294,927 (+5,798) | 688,252 (+12,115) | -| 2025-09-25 | 398,879 (+5,554) | 301,663 (+6,736) | 700,542 (+12,290) | -| 2025-09-26 | 404,334 (+5,455) | 306,713 (+5,050) | 711,047 (+10,505) | -| 2025-09-27 | 411,618 (+7,284) | 317,763 (+11,050) | 729,381 (+18,334) | -| 2025-09-28 | 414,910 (+3,292) | 322,522 (+4,759) | 737,432 (+8,051) | -| 2025-09-29 | 419,919 (+5,009) | 328,033 (+5,511) | 747,952 (+10,520) | -| 2025-09-30 | 427,991 (+8,072) | 336,472 (+8,439) | 764,463 (+16,511) | -| 2025-10-01 | 433,591 (+5,600) | 341,742 (+5,270) | 775,333 (+10,870) | -| 2025-10-02 | 440,852 (+7,261) | 348,099 (+6,357) | 788,951 (+13,618) | -| 2025-10-03 | 446,829 (+5,977) | 359,937 (+11,838) | 806,766 (+17,815) | -| 2025-10-04 | 452,561 (+5,732) | 370,386 (+10,449) | 822,947 (+16,181) | -| 2025-10-05 | 455,559 (+2,998) | 374,745 (+4,359) | 830,304 (+7,357) | -| 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) | -| 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) | -| 2025-10-08 | 474,643 (+7,307) | 394,139 (+8,701) | 868,782 (+16,008) | -| 2025-10-09 | 479,203 (+4,560) | 400,526 (+6,387) | 879,729 (+10,947) | -| 2025-10-10 | 484,374 (+5,171) | 406,015 (+5,489) | 890,389 (+10,660) | -| 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) | -| 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) | -| 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) | -| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) | -| 2025-10-16 | 517,719 (+5,002) | 447,137 (+7,847) | 964,856 (+12,849) | -| 2025-10-17 | 526,239 (+8,520) | 457,467 (+10,330) | 983,706 (+18,850) | -| 2025-10-18 | 531,564 (+5,325) | 465,272 (+7,805) | 996,836 (+13,130) | -| 2025-10-19 | 536,209 (+4,645) | 469,078 (+3,806) | 1,005,287 (+8,451) | -| 2025-10-20 | 541,264 (+5,055) | 472,952 (+3,874) | 1,014,216 (+8,929) | -| 2025-10-21 | 548,721 (+7,457) | 479,703 (+6,751) | 1,028,424 (+14,208) | -| 2025-10-22 | 557,949 (+9,228) | 491,395 (+11,692) | 1,049,344 (+20,920) | -| 2025-10-23 | 564,716 (+6,767) | 498,736 (+7,341) | 1,063,452 (+14,108) | -| 2025-10-24 | 572,692 (+7,976) | 506,905 (+8,169) | 1,079,597 (+16,145) | -| 2025-10-25 | 578,927 (+6,235) | 516,129 (+9,224) | 1,095,056 (+15,459) | -| 2025-10-26 | 584,409 (+5,482) | 521,179 (+5,050) | 1,105,588 (+10,532) | -| 2025-10-27 | 589,999 (+5,590) | 526,001 (+4,822) | 1,116,000 (+10,412) | -| 2025-10-28 | 595,776 (+5,777) | 532,438 (+6,437) | 1,128,214 (+12,214) | -| 2025-10-29 | 606,259 (+10,483) | 542,064 (+9,626) | 1,148,323 (+20,109) | -| 2025-10-30 | 613,746 (+7,487) | 542,064 (+0) | 1,155,810 (+7,487) | -| 2025-10-30 | 617,846 (+4,100) | 555,026 (+12,962) | 1,172,872 (+17,062) | -| 2025-10-31 | 626,612 (+8,766) | 564,579 (+9,553) | 1,191,191 (+18,319) | -| 2025-11-01 | 636,100 (+9,488) | 581,806 (+17,227) | 1,217,906 (+26,715) | -| 2025-11-02 | 644,067 (+7,967) | 590,004 (+8,198) | 1,234,071 (+16,165) | -| 2025-11-03 | 653,130 (+9,063) | 597,139 (+7,135) | 1,250,269 (+16,198) | -| 2025-11-04 | 663,912 (+10,782) | 608,056 (+10,917) | 1,271,968 (+21,699) | -| 2025-11-05 | 675,074 (+11,162) | 619,690 (+11,634) | 1,294,764 (+22,796) | -| 2025-11-06 | 686,252 (+11,178) | 630,885 (+11,195) | 1,317,137 (+22,373) | -| 2025-11-07 | 696,646 (+10,394) | 642,146 (+11,261) | 1,338,792 (+21,655) | -| 2025-11-08 | 706,035 (+9,389) | 653,489 (+11,343) | 1,359,524 (+20,732) | -| 2025-11-09 | 713,462 (+7,427) | 660,459 (+6,970) | 1,373,921 (+14,397) | -| 2025-11-10 | 722,288 (+8,826) | 668,225 (+7,766) | 1,390,513 (+16,592) | -| 2025-11-11 | 729,769 (+7,481) | 677,501 (+9,276) | 1,407,270 (+16,757) | -| 2025-11-12 | 740,180 (+10,411) | 686,454 (+8,953) | 1,426,634 (+19,364) | -| 2025-11-13 | 749,905 (+9,725) | 696,157 (+9,703) | 1,446,062 (+19,428) | -| 2025-11-14 | 759,928 (+10,023) | 705,237 (+9,080) | 1,465,165 (+19,103) | -| 2025-11-15 | 765,955 (+6,027) | 712,870 (+7,633) | 1,478,825 (+13,660) | -| 2025-11-16 | 771,069 (+5,114) | 716,596 (+3,726) | 1,487,665 (+8,840) | -| 2025-11-17 | 780,161 (+9,092) | 723,339 (+6,743) | 1,503,500 (+15,835) | -| 2025-11-18 | 791,563 (+11,402) | 732,544 (+9,205) | 1,524,107 (+20,607) | -| 2025-11-19 | 804,409 (+12,846) | 747,624 (+15,080) | 1,552,033 (+27,926) | -| 2025-11-20 | 814,620 (+10,211) | 757,907 (+10,283) | 1,572,527 (+20,494) | -| 2025-11-21 | 826,309 (+11,689) | 769,307 (+11,400) | 1,595,616 (+23,089) | -| 2025-11-22 | 837,269 (+10,960) | 780,996 (+11,689) | 1,618,265 (+22,649) | -| 2025-11-23 | 846,609 (+9,340) | 795,069 (+14,073) | 1,641,678 (+23,413) | -| 2025-11-24 | 856,733 (+10,124) | 804,033 (+8,964) | 1,660,766 (+19,088) | -| 2025-11-25 | 869,423 (+12,690) | 817,339 (+13,306) | 1,686,762 (+25,996) | -| 2025-11-26 | 881,414 (+11,991) | 832,518 (+15,179) | 1,713,932 (+27,170) | -| 2025-11-27 | 893,960 (+12,546) | 846,180 (+13,662) | 1,740,140 (+26,208) | -| 2025-11-28 | 901,741 (+7,781) | 856,482 (+10,302) | 1,758,223 (+18,083) | -| 2025-11-29 | 908,689 (+6,948) | 863,361 (+6,879) | 1,772,050 (+13,827) | -| 2025-11-30 | 916,116 (+7,427) | 870,194 (+6,833) | 1,786,310 (+14,260) | -| 2025-12-01 | 925,898 (+9,782) | 876,500 (+6,306) | 1,802,398 (+16,088) | -| 2025-12-02 | 939,250 (+13,352) | 890,919 (+14,419) | 1,830,169 (+27,771) | -| 2025-12-03 | 952,249 (+12,999) | 903,713 (+12,794) | 1,855,962 (+25,793) | -| 2025-12-04 | 965,611 (+13,362) | 916,471 (+12,758) | 1,882,082 (+26,120) | -| 2025-12-05 | 977,996 (+12,385) | 930,616 (+14,145) | 1,908,612 (+26,530) | -| 2025-12-06 | 987,884 (+9,888) | 943,773 (+13,157) | 1,931,657 (+23,045) | -| 2025-12-07 | 994,046 (+6,162) | 951,425 (+7,652) | 1,945,471 (+13,814) | -| 2025-12-08 | 1,000,898 (+6,852) | 957,149 (+5,724) | 1,958,047 (+12,576) | -| 2025-12-09 | 1,011,488 (+10,590) | 973,922 (+16,773) | 1,985,410 (+27,363) | -| 2025-12-10 | 1,025,891 (+14,403) | 991,708 (+17,786) | 2,017,599 (+32,189) | -| 2025-12-11 | 1,045,110 (+19,219) | 1,010,559 (+18,851) | 2,055,669 (+38,070) | -| 2025-12-12 | 1,061,340 (+16,230) | 1,030,838 (+20,279) | 2,092,178 (+36,509) | -| 2025-12-13 | 1,073,561 (+12,221) | 1,044,608 (+13,770) | 2,118,169 (+25,991) | -| 2025-12-14 | 1,082,042 (+8,481) | 1,052,425 (+7,817) | 2,134,467 (+16,298) | -| 2025-12-15 | 1,093,632 (+11,590) | 1,059,078 (+6,653) | 2,152,710 (+18,243) | -| 2025-12-16 | 1,120,477 (+26,845) | 1,078,022 (+18,944) | 2,198,499 (+45,789) | -| 2025-12-17 | 1,151,067 (+30,590) | 1,097,661 (+19,639) | 2,248,728 (+50,229) | -| 2025-12-18 | 1,178,658 (+27,591) | 1,113,418 (+15,757) | 2,292,076 (+43,348) | -| 2025-12-19 | 1,203,485 (+24,827) | 1,129,698 (+16,280) | 2,333,183 (+41,107) | -| 2025-12-20 | 1,223,000 (+19,515) | 1,146,258 (+16,560) | 2,369,258 (+36,075) | -| 2025-12-21 | 1,242,675 (+19,675) | 1,158,909 (+12,651) | 2,401,584 (+32,326) | -| 2025-12-22 | 1,262,522 (+19,847) | 1,169,121 (+10,212) | 2,431,643 (+30,059) | +| Date | GitHub Downloads | npm Downloads | Total | +| ---------- | ----------------- | ----------------- | ------------------- | +| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) | +| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) | +| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) | +| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) | +| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) | +| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) | +| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) | +| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) | +| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) | +| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) | +| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) | +| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) | +| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) | +| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) | +| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) | +| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) | +| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) | +| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) | +| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) | +| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) | +| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) | +| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) | +| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) | +| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) | +| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) | +| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) | +| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) | +| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) | +| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) | +| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) | +| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) | +| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) | +| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) | +| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) | +| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) | +| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) | +| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) | +| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) | +| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) | +| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) | +| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) | +| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) | +| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) | +| 2025-08-12 | 176,307 (+7,010) | 171,876 (+3,923) | 348,183 (+10,933) | +| 2025-08-13 | 182,997 (+6,690) | 177,182 (+5,306) | 360,179 (+11,996) | +| 2025-08-14 | 189,063 (+6,066) | 179,741 (+2,559) | 368,804 (+8,625) | +| 2025-08-15 | 193,608 (+4,545) | 181,792 (+2,051) | 375,400 (+6,596) | +| 2025-08-16 | 198,118 (+4,510) | 184,558 (+2,766) | 382,676 (+7,276) | +| 2025-08-17 | 201,299 (+3,181) | 186,269 (+1,711) | 387,568 (+4,892) | +| 2025-08-18 | 204,559 (+3,260) | 187,399 (+1,130) | 391,958 (+4,390) | +| 2025-08-19 | 209,814 (+5,255) | 189,668 (+2,269) | 399,482 (+7,524) | +| 2025-08-20 | 214,497 (+4,683) | 191,481 (+1,813) | 405,978 (+6,496) | +| 2025-08-21 | 220,465 (+5,968) | 194,784 (+3,303) | 415,249 (+9,271) | +| 2025-08-22 | 225,899 (+5,434) | 197,204 (+2,420) | 423,103 (+7,854) | +| 2025-08-23 | 229,005 (+3,106) | 199,238 (+2,034) | 428,243 (+5,140) | +| 2025-08-24 | 232,098 (+3,093) | 201,157 (+1,919) | 433,255 (+5,012) | +| 2025-08-25 | 236,607 (+4,509) | 202,650 (+1,493) | 439,257 (+6,002) | +| 2025-08-26 | 242,783 (+6,176) | 205,242 (+2,592) | 448,025 (+8,768) | +| 2025-08-27 | 248,409 (+5,626) | 205,242 (+0) | 453,651 (+5,626) | +| 2025-08-28 | 252,796 (+4,387) | 205,242 (+0) | 458,038 (+4,387) | +| 2025-08-29 | 256,045 (+3,249) | 211,075 (+5,833) | 467,120 (+9,082) | +| 2025-08-30 | 258,863 (+2,818) | 212,397 (+1,322) | 471,260 (+4,140) | +| 2025-08-31 | 262,004 (+3,141) | 213,944 (+1,547) | 475,948 (+4,688) | +| 2025-09-01 | 265,359 (+3,355) | 215,115 (+1,171) | 480,474 (+4,526) | +| 2025-09-02 | 270,483 (+5,124) | 217,075 (+1,960) | 487,558 (+7,084) | +| 2025-09-03 | 274,793 (+4,310) | 219,755 (+2,680) | 494,548 (+6,990) | +| 2025-09-04 | 280,430 (+5,637) | 222,103 (+2,348) | 502,533 (+7,985) | +| 2025-09-05 | 283,769 (+3,339) | 223,793 (+1,690) | 507,562 (+5,029) | +| 2025-09-06 | 286,245 (+2,476) | 225,036 (+1,243) | 511,281 (+3,719) | +| 2025-09-07 | 288,623 (+2,378) | 225,866 (+830) | 514,489 (+3,208) | +| 2025-09-08 | 293,341 (+4,718) | 227,073 (+1,207) | 520,414 (+5,925) | +| 2025-09-09 | 300,036 (+6,695) | 229,788 (+2,715) | 529,824 (+9,410) | +| 2025-09-10 | 307,287 (+7,251) | 233,435 (+3,647) | 540,722 (+10,898) | +| 2025-09-11 | 314,083 (+6,796) | 237,356 (+3,921) | 551,439 (+10,717) | +| 2025-09-12 | 321,046 (+6,963) | 240,728 (+3,372) | 561,774 (+10,335) | +| 2025-09-13 | 324,894 (+3,848) | 245,539 (+4,811) | 570,433 (+8,659) | +| 2025-09-14 | 328,876 (+3,982) | 248,245 (+2,706) | 577,121 (+6,688) | +| 2025-09-15 | 334,201 (+5,325) | 250,983 (+2,738) | 585,184 (+8,063) | +| 2025-09-16 | 342,609 (+8,408) | 255,264 (+4,281) | 597,873 (+12,689) | +| 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) | +| 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) | +| 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) | +| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) | +| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) | +| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) | +| 2025-09-23 | 387,008 (+4,516) | 289,129 (+5,120) | 676,137 (+9,636) | +| 2025-09-24 | 393,325 (+6,317) | 294,927 (+5,798) | 688,252 (+12,115) | +| 2025-09-25 | 398,879 (+5,554) | 301,663 (+6,736) | 700,542 (+12,290) | +| 2025-09-26 | 404,334 (+5,455) | 306,713 (+5,050) | 711,047 (+10,505) | +| 2025-09-27 | 411,618 (+7,284) | 317,763 (+11,050) | 729,381 (+18,334) | +| 2025-09-28 | 414,910 (+3,292) | 322,522 (+4,759) | 737,432 (+8,051) | +| 2025-09-29 | 419,919 (+5,009) | 328,033 (+5,511) | 747,952 (+10,520) | +| 2025-09-30 | 427,991 (+8,072) | 336,472 (+8,439) | 764,463 (+16,511) | +| 2025-10-01 | 433,591 (+5,600) | 341,742 (+5,270) | 775,333 (+10,870) | +| 2025-10-02 | 440,852 (+7,261) | 348,099 (+6,357) | 788,951 (+13,618) | +| 2025-10-03 | 446,829 (+5,977) | 359,937 (+11,838) | 806,766 (+17,815) | +| 2025-10-04 | 452,561 (+5,732) | 370,386 (+10,449) | 822,947 (+16,181) | +| 2025-10-05 | 455,559 (+2,998) | 374,745 (+4,359) | 830,304 (+7,357) | +| 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) | +| 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) | +| 2025-10-08 | 474,643 (+7,307) | 394,139 (+8,701) | 868,782 (+16,008) | +| 2025-10-09 | 479,203 (+4,560) | 400,526 (+6,387) | 879,729 (+10,947) | +| 2025-10-10 | 484,374 (+5,171) | 406,015 (+5,489) | 890,389 (+10,660) | +| 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) | +| 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) | +| 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) | +| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) | +| 2025-10-16 | 517,719 (+5,002) | 447,137 (+7,847) | 964,856 (+12,849) | +| 2025-10-17 | 526,239 (+8,520) | 457,467 (+10,330) | 983,706 (+18,850) | +| 2025-10-18 | 531,564 (+5,325) | 465,272 (+7,805) | 996,836 (+13,130) | +| 2025-10-19 | 536,209 (+4,645) | 469,078 (+3,806) | 1,005,287 (+8,451) | +| 2025-10-20 | 541,264 (+5,055) | 472,952 (+3,874) | 1,014,216 (+8,929) | +| 2025-10-21 | 548,721 (+7,457) | 479,703 (+6,751) | 1,028,424 (+14,208) | +| 2025-10-22 | 557,949 (+9,228) | 491,395 (+11,692) | 1,049,344 (+20,920) | +| 2025-10-23 | 564,716 (+6,767) | 498,736 (+7,341) | 1,063,452 (+14,108) | +| 2025-10-24 | 572,692 (+7,976) | 506,905 (+8,169) | 1,079,597 (+16,145) | +| 2025-10-25 | 578,927 (+6,235) | 516,129 (+9,224) | 1,095,056 (+15,459) | +| 2025-10-26 | 584,409 (+5,482) | 521,179 (+5,050) | 1,105,588 (+10,532) | +| 2025-10-27 | 589,999 (+5,590) | 526,001 (+4,822) | 1,116,000 (+10,412) | +| 2025-10-28 | 595,776 (+5,777) | 532,438 (+6,437) | 1,128,214 (+12,214) | +| 2025-10-29 | 606,259 (+10,483) | 542,064 (+9,626) | 1,148,323 (+20,109) | +| 2025-10-30 | 613,746 (+7,487) | 542,064 (+0) | 1,155,810 (+7,487) | +| 2025-10-30 | 617,846 (+4,100) | 555,026 (+12,962) | 1,172,872 (+17,062) | +| 2025-10-31 | 626,612 (+8,766) | 564,579 (+9,553) | 1,191,191 (+18,319) | +| 2025-11-01 | 636,100 (+9,488) | 581,806 (+17,227) | 1,217,906 (+26,715) | +| 2025-11-02 | 644,067 (+7,967) | 590,004 (+8,198) | 1,234,071 (+16,165) | +| 2025-11-03 | 653,130 (+9,063) | 597,139 (+7,135) | 1,250,269 (+16,198) | +| 2025-11-04 | 663,912 (+10,782) | 608,056 (+10,917) | 1,271,968 (+21,699) | +| 2025-11-05 | 675,074 (+11,162) | 619,690 (+11,634) | 1,294,764 (+22,796) | +| 2025-11-06 | 686,252 (+11,178) | 630,885 (+11,195) | 1,317,137 (+22,373) | +| 2025-11-07 | 696,646 (+10,394) | 642,146 (+11,261) | 1,338,792 (+21,655) | +| 2025-11-08 | 706,035 (+9,389) | 653,489 (+11,343) | 1,359,524 (+20,732) | +| 2025-11-09 | 713,462 (+7,427) | 660,459 (+6,970) | 1,373,921 (+14,397) | +| 2025-11-10 | 722,288 (+8,826) | 668,225 (+7,766) | 1,390,513 (+16,592) | +| 2025-11-11 | 729,769 (+7,481) | 677,501 (+9,276) | 1,407,270 (+16,757) | +| 2025-11-12 | 740,180 (+10,411) | 686,454 (+8,953) | 1,426,634 (+19,364) | +| 2025-11-13 | 749,905 (+9,725) | 696,157 (+9,703) | 1,446,062 (+19,428) | +| 2025-11-14 | 759,928 (+10,023) | 705,237 (+9,080) | 1,465,165 (+19,103) | +| 2025-11-15 | 765,955 (+6,027) | 712,870 (+7,633) | 1,478,825 (+13,660) | +| 2025-11-16 | 771,069 (+5,114) | 716,596 (+3,726) | 1,487,665 (+8,840) | +| 2025-11-17 | 780,161 (+9,092) | 723,339 (+6,743) | 1,503,500 (+15,835) | +| 2025-11-18 | 791,563 (+11,402) | 732,544 (+9,205) | 1,524,107 (+20,607) | +| 2025-11-19 | 804,409 (+12,846) | 747,624 (+15,080) | 1,552,033 (+27,926) | +| 2025-11-20 | 814,620 (+10,211) | 757,907 (+10,283) | 1,572,527 (+20,494) | +| 2025-11-21 | 826,309 (+11,689) | 769,307 (+11,400) | 1,595,616 (+23,089) | +| 2025-11-22 | 837,269 (+10,960) | 780,996 (+11,689) | 1,618,265 (+22,649) | +| 2025-11-23 | 846,609 (+9,340) | 795,069 (+14,073) | 1,641,678 (+23,413) | +| 2025-11-24 | 856,733 (+10,124) | 804,033 (+8,964) | 1,660,766 (+19,088) | +| 2025-11-25 | 869,423 (+12,690) | 817,339 (+13,306) | 1,686,762 (+25,996) | +| 2025-11-26 | 881,414 (+11,991) | 832,518 (+15,179) | 1,713,932 (+27,170) | diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md deleted file mode 100644 index 164f69bd4..000000000 --- a/STYLE_GUIDE.md +++ /dev/null @@ -1,12 +0,0 @@ -## Style Guide - -- Try to keep things in one function unless composable or reusable -- DO NOT do unnecessary destructuring of variables -- DO NOT use `else` statements unless necessary -- DO NOT use `try`/`catch` if it can be avoided -- AVOID `try`/`catch` where possible -- AVOID `else` statements -- AVOID using `any` type -- AVOID `let` statements -- PREFER single word variable names where possible -- Use as many bun apis as possible like Bun.file() diff --git a/bun.lock b/bun.lock index 11099e1ed..d71694a30 100644 --- a/bun.lock +++ b/bun.lock @@ -5,21 +5,12 @@ "": { "name": "opencode", "dependencies": { - "@ai-sdk/cerebras": "1.0.33", - "@ai-sdk/cohere": "2.0.21", - "@ai-sdk/deepinfra": "1.0.30", - "@ai-sdk/gateway": "2.0.23", - "@ai-sdk/groq": "2.0.33", - "@ai-sdk/perplexity": "2.0.22", - "@ai-sdk/togetherai": "1.0.30", "@aws-sdk/client-s3": "3.933.0", - "@opencode-ai/plugin": "workspace:*", "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", "typescript": "catalog:", }, "devDependencies": { - "@actions/artifact": "5.0.1", "@tsconfig/bun": "catalog:", "husky": "9.1.7", "prettier": "3.6.2", @@ -27,57 +18,9 @@ "turbo": "2.5.6", }, }, - "packages/app": { - "name": "@opencode-ai/app", - "version": "1.0.191", - "dependencies": { - "@kobalte/core": "catalog:", - "@opencode-ai/sdk": "workspace:*", - "@opencode-ai/ui": "workspace:*", - "@opencode-ai/util": "workspace:*", - "@shikijs/transformers": "3.9.2", - "@solid-primitives/active-element": "2.1.3", - "@solid-primitives/audio": "1.4.2", - "@solid-primitives/event-bus": "1.1.2", - "@solid-primitives/media": "2.3.3", - "@solid-primitives/resize-observer": "2.1.3", - "@solid-primitives/scroll": "2.1.3", - "@solid-primitives/storage": "catalog:", - "@solid-primitives/websocket": "1.3.1", - "@solidjs/meta": "catalog:", - "@solidjs/router": "catalog:", - "@thisbeyond/solid-dnd": "0.7.5", - "diff": "catalog:", - "fuzzysort": "catalog:", - "ghostty-web": "0.3.0", - "luxon": "catalog:", - "marked": "16.2.0", - "marked-shiki": "1.2.1", - "remeda": "catalog:", - "shiki": "catalog:", - "solid-js": "catalog:", - "solid-list": "catalog:", - "tailwindcss": "catalog:", - "virtua": "catalog:", - "zod": "catalog:", - }, - "devDependencies": { - "@happy-dom/global-registrator": "20.0.11", - "@tailwindcss/vite": "catalog:", - "@tsconfig/bun": "1.0.9", - "@types/bun": "catalog:", - "@types/luxon": "catalog:", - "@types/node": "catalog:", - "@typescript/native-preview": "catalog:", - "typescript": "catalog:", - "vite": "catalog:", - "vite-plugin-icons-spritesheet": "3.0.1", - "vite-plugin-solid": "catalog:", - }, - }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -105,7 +48,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -132,7 +75,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -156,7 +99,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -180,45 +123,58 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { - "@opencode-ai/app": "workspace:*", - "@solid-primitives/storage": "catalog:", - "@tauri-apps/api": "^2", - "@tauri-apps/plugin-dialog": "~2", - "@tauri-apps/plugin-http": "~2", - "@tauri-apps/plugin-opener": "^2", - "@tauri-apps/plugin-os": "~2", - "@tauri-apps/plugin-process": "~2", - "@tauri-apps/plugin-shell": "~2", - "@tauri-apps/plugin-store": "~2", - "@tauri-apps/plugin-updater": "~2", - "@tauri-apps/plugin-window-state": "~2", + "@kobalte/core": "catalog:", + "@opencode-ai/sdk": "workspace:*", + "@opencode-ai/ui": "workspace:*", + "@opencode-ai/util": "workspace:*", + "@shikijs/transformers": "3.9.2", + "@solid-primitives/active-element": "2.1.3", + "@solid-primitives/event-bus": "1.1.2", + "@solid-primitives/resize-observer": "2.1.3", + "@solid-primitives/scroll": "2.1.3", + "@solid-primitives/storage": "4.3.3", + "@solidjs/meta": "catalog:", + "@solidjs/router": "catalog:", + "@thisbeyond/solid-dnd": "0.7.5", + "diff": "catalog:", + "fuzzysort": "catalog:", + "luxon": "catalog:", + "marked": "16.2.0", + "marked-shiki": "1.2.1", + "remeda": "catalog:", + "shiki": "3.9.2", "solid-js": "catalog:", + "solid-list": "catalog:", + "tailwindcss": "catalog:", + "virtua": "catalog:", }, "devDependencies": { - "@actions/artifact": "4.0.0", - "@tauri-apps/cli": "^2", - "@types/bun": "catalog:", + "@tailwindcss/vite": "catalog:", + "@tsconfig/bun": "1.0.9", + "@types/luxon": "catalog:", + "@types/node": "catalog:", "@typescript/native-preview": "catalog:", - "typescript": "~5.6.2", + "typescript": "catalog:", "vite": "catalog:", + "vite-plugin-icons-spritesheet": "3.0.1", + "vite-plugin-solid": "catalog:", }, }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", - "@pierre/diffs": "catalog:", + "@pierre/precision-diffs": "catalog:", "@solidjs/meta": "catalog:", "@solidjs/router": "catalog:", "@solidjs/start": "catalog:", "aws4fetch": "^1.0.20", "hono": "catalog:", "hono-openapi": "catalog:", - "js-base64": "3.7.7", "luxon": "catalog:", "nitro": "3.0.1-alpha.1", "solid-js": "catalog:", @@ -236,10 +192,10 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@octokit/auth-app": "8.0.1", - "@octokit/rest": "catalog:", + "@octokit/rest": "22.0.0", "hono": "catalog:", "jose": "6.0.11", }, @@ -252,7 +208,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.191", + "version": "1.0.118", "bin": { "opencode": "./bin/opencode", }, @@ -261,38 +217,33 @@ "@actions/github": "6.0.1", "@agentclientprotocol/sdk": "0.5.1", "@ai-sdk/amazon-bedrock": "3.0.57", - "@ai-sdk/anthropic": "2.0.50", + "@ai-sdk/anthropic": "2.0.45", "@ai-sdk/azure": "2.0.73", - "@ai-sdk/google": "2.0.44", - "@ai-sdk/google-vertex": "3.0.81", + "@ai-sdk/google": "2.0.42", + "@ai-sdk/google-vertex": "3.0.74", "@ai-sdk/mcp": "0.0.8", - "@ai-sdk/mistral": "2.0.26", "@ai-sdk/openai": "2.0.71", "@ai-sdk/openai-compatible": "1.0.27", - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.18", - "@ai-sdk/xai": "2.0.42", "@clack/prompts": "1.0.0-alpha.1", "@hono/standard-validator": "0.1.5", "@hono/zod-validator": "catalog:", "@modelcontextprotocol/sdk": "1.15.1", "@octokit/graphql": "9.0.2", - "@octokit/rest": "catalog:", + "@octokit/rest": "22.0.0", "@openauthjs/openauth": "catalog:", "@opencode-ai/plugin": "workspace:*", "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", "@opencode-ai/util": "workspace:*", - "@openrouter/ai-sdk-provider": "1.5.2", - "@opentui/core": "0.1.63", - "@opentui/solid": "0.1.63", + "@openrouter/ai-sdk-provider": "1.2.5", + "@opentui/core": "0.1.50", + "@opentui/solid": "0.1.50", "@parcel/watcher": "2.5.1", - "@pierre/diffs": "catalog:", + "@pierre/precision-diffs": "catalog:", "@solid-primitives/event-bus": "1.1.2", "@standard-schema/spec": "1.0.0", "@zip.js/zip.js": "2.7.62", "ai": "catalog:", - "bun-pty": "0.4.2", "chokidar": "4.0.3", "clipboardy": "4.0.0", "decimal.js": "10.5.0", @@ -305,7 +256,7 @@ "jsonc-parser": "3.3.1", "minimatch": "10.0.3", "open": "10.1.2", - "opentui-spinner": "0.0.6", + "opentui-spinner": "0.0.5", "partial-json": "0.1.7", "remeda": "catalog:", "solid-js": "catalog:", @@ -327,9 +278,7 @@ "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", - "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", - "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1", "@standard-schema/spec": "1.0.0", "@tsconfig/bun": "catalog:", @@ -346,7 +295,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -366,9 +315,9 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.191", + "version": "1.0.118", "devDependencies": { - "@hey-api/openapi-ts": "0.88.1", + "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", "@types/node": "catalog:", "@typescript/native-preview": "catalog:", @@ -377,7 +326,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -388,17 +337,28 @@ "typescript": "catalog:", }, }, + "packages/tauri": { + "name": "@opencode-ai/tauri", + "version": "1.0.118", + "dependencies": { + "@tauri-apps/api": "^2", + "@tauri-apps/plugin-opener": "^2", + }, + "devDependencies": { + "@tauri-apps/cli": "^2", + "typescript": "~5.6.2", + "vite": "^6.0.3", + }, + }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", "@opencode-ai/util": "workspace:*", - "@pierre/diffs": "catalog:", + "@pierre/precision-diffs": "catalog:", "@shikijs/transformers": "3.9.2", - "@solid-primitives/bounds": "0.1.3", - "@solid-primitives/resize-observer": "2.1.3", "@solidjs/meta": "catalog:", "@typescript/native-preview": "catalog:", "fuzzysort": "catalog:", @@ -406,7 +366,7 @@ "marked": "16.2.0", "marked-shiki": "1.2.1", "remeda": "catalog:", - "shiki": "catalog:", + "shiki": "3.9.2", "solid-js": "catalog:", "solid-list": "catalog:", "virtua": "catalog:", @@ -415,7 +375,6 @@ "@tailwindcss/vite": "catalog:", "@tsconfig/node22": "catalog:", "@types/bun": "catalog:", - "@types/luxon": "catalog:", "tailwindcss": "catalog:", "typescript": "catalog:", "vite": "catalog:", @@ -425,18 +384,17 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "zod": "catalog:", }, "devDependencies": { - "@types/bun": "catalog:", "typescript": "catalog:", }, }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", @@ -455,7 +413,8 @@ "marked-shiki": "1.2.1", "rehype-autolink-headings": "7.1.0", "remeda": "catalog:", - "shiki": "catalog:", + "sharp": "0.32.5", + "shiki": "3.4.2", "solid-js": "catalog:", "toolbeam-docs-theme": "0.4.8", }, @@ -467,13 +426,11 @@ }, }, "trustedDependencies": [ + "sharp", "esbuild", "web-tree-sitter", "tree-sitter-bash", ], - "patchedDependencies": { - "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch", - }, "overrides": { "@types/bun": "catalog:", "@types/node": "catalog:", @@ -482,28 +439,25 @@ "@cloudflare/workers-types": "4.20251008.0", "@hono/zod-validator": "0.4.2", "@kobalte/core": "0.13.11", - "@octokit/rest": "22.0.0", "@openauthjs/openauth": "0.0.0-20250322224806", - "@pierre/diffs": "1.0.2", - "@solid-primitives/storage": "4.3.3", + "@pierre/precision-diffs": "0.5.7", "@solidjs/meta": "0.29.4", "@solidjs/router": "0.15.4", "@solidjs/start": "https://pkg.pr.new/@solidjs/start@dfb2020", "@tailwindcss/vite": "4.1.11", "@tsconfig/bun": "1.0.9", "@tsconfig/node22": "22.0.2", - "@types/bun": "1.3.4", + "@types/bun": "1.3.3", "@types/luxon": "3.7.1", "@types/node": "22.13.9", - "@typescript/native-preview": "7.0.0-dev.20251207.1", + "@typescript/native-preview": "7.0.0-dev.20251014.1", "ai": "5.0.97", "diff": "8.0.2", "fuzzysort": "3.1.0", - "hono": "4.10.7", - "hono-openapi": "1.1.2", + "hono": "4.7.10", + "hono-openapi": "1.1.1", "luxon": "3.6.1", "remeda": "2.26.0", - "shiki": "3.20.0", "solid-js": "1.9.10", "solid-list": "0.3.0", "tailwindcss": "4.1.11", @@ -515,15 +469,13 @@ "zod": "4.1.8", }, "packages": { - "@actions/artifact": ["@actions/artifact@5.0.1", "", { "dependencies": { "@actions/core": "^2.0.0", "@actions/github": "^6.0.1", "@actions/http-client": "^3.0.0", "@azure/storage-blob": "^12.29.1", "@octokit/core": "^5.2.1", "@octokit/plugin-request-log": "^1.0.4", "@octokit/plugin-retry": "^3.0.9", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@protobuf-ts/plugin": "^2.2.3-alpha.1", "archiver": "^7.0.1", "jwt-decode": "^3.1.2", "unzip-stream": "^0.3.1" } }, "sha512-dHJ5rHduhCKUikKTT9eXeWoUvfKia3IjR1sO/VTAV3DVAL4yMTRnl2iO5mcfiBjySHLwPNezwENAVskKYU5ymw=="], - "@actions/core": ["@actions/core@1.11.1", "", { "dependencies": { "@actions/exec": "^1.1.1", "@actions/http-client": "^2.0.1" } }, "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A=="], "@actions/exec": ["@actions/exec@1.1.1", "", { "dependencies": { "@actions/io": "^1.0.1" } }, "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w=="], "@actions/github": ["@actions/github@6.0.1", "", { "dependencies": { "@actions/http-client": "^2.2.0", "@octokit/core": "^5.0.1", "@octokit/plugin-paginate-rest": "^9.2.2", "@octokit/plugin-rest-endpoint-methods": "^10.4.0", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "undici": "^5.28.5" } }, "sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw=="], - "@actions/http-client": ["@actions/http-client@3.0.0", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.28.5" } }, "sha512-1s3tXAfVMSz9a4ZEBkXXRQD4QhY3+GAsWSbaYpeknPOKEeyRiU3lH+bHiLMZdo2x/fIeQ/hscL1wCkDLVM2DZQ=="], + "@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], "@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="], @@ -537,37 +489,21 @@ "@ai-sdk/azure": ["@ai-sdk/azure@2.0.73", "", { "dependencies": { "@ai-sdk/openai": "2.0.71", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-LpAg3Ak/V3WOemBu35Qbx9jfQfApsHNXX9p3bXVsnRu3XXi1QQUt5gMOCIb4znPonz+XnHenIDZMBwdsb1TfRQ=="], - "@ai-sdk/cerebras": ["@ai-sdk/cerebras@1.0.33", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.29", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-2gSSS/7kunIwMdC4td5oWsUAzoLw84ccGpz6wQbxVnrb1iWnrEnKa5tRBduaP6IXpzLWsu8wME3+dQhZy+gT7w=="], + "@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.12", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W+cB1sOWvPcz9qiIsNtD+HxUrBUva2vWv2K1EFukuImX+HA0uZx3EyyOjhYQ9gtf/teqEG80M6OvJ7xx/VLV2A=="], - "@ai-sdk/cohere": ["@ai-sdk/cohere@2.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZjaZFvJlc5XOPi3QwTLEFZbHIgTJc6YGvxz+8zIMGVZi/hdynR8/f/C1A9x6mhzmBtAqi/dZ2h11oouAQH5z4g=="], + "@ai-sdk/google": ["@ai-sdk/google@2.0.42", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Jdn+3TZm4iIt62CUjjUoIOshqFIXyzNmUDfkSVV4FcjlSo5+AuhzI1KC7QiNHlqPNejzR6NLIqGJx96VAES34g=="], - "@ai-sdk/deepinfra": ["@ai-sdk/deepinfra@1.0.30", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.29", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-XK8oRZFApzo6xnS5C+FhWUUkB2itA5Nfon3pU9dJVM0goViq8GwdleZTBRqhu4DE4KJURo5DGWpJr2hfV54cEg=="], - - "@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.23", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-qmX7afPRszUqG5hryHF3UN8ITPIRSGmDW6VYCmByzjoUkgm3MekzSx2hMV1wr0P+llDeuXb378SjqUfpvWJulg=="], - - "@ai-sdk/google": ["@ai-sdk/google@2.0.44", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.18" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-c5dck36FjqiVoeeMJQLTEmUheoURcGTU/nBT6iJu8/nZiKFT/y8pD85KMDRB7RerRYaaQOtslR2d6/5PditiRw=="], - - "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.81", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.50", "@ai-sdk/google": "2.0.44", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.18", "google-auth-library": "^9.15.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-yrl5Ug0Mqwo9ya45oxczgy2RWgpEA/XQQCSFYP+3NZMQ4yA3Iim1vkOjVCsGaZZ8rjVk395abi1ZMZV0/6rqVA=="], - - "@ai-sdk/groq": ["@ai-sdk/groq@2.0.33", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-FWGl7xNr88NBveao3y9EcVWYUt9ABPrwLFY7pIutSNgaTf32vgvyhREobaMrLU4Scr5G/2tlNqOPZ5wkYMaZig=="], + "@ai-sdk/google-vertex": ["@ai-sdk/google-vertex@3.0.74", "", { "dependencies": { "@ai-sdk/anthropic": "2.0.45", "@ai-sdk/google": "2.0.42", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "google-auth-library": "^9.15.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W0375p41RQOheAmy7iJGtuJWQWX/aKkO4sJHf6eIYa3bkz93Cbo1aRG1X7ocyMusLZ3dIaW7x6X9WHD8IHkNfg=="], "@ai-sdk/mcp": ["@ai-sdk/mcp@0.0.8", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "pkce-challenge": "^5.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-9y9GuGcZ9/+pMIHfpOCJgZVp+AZMv6TkjX2NVT17SQZvTF2N8LXuCXyoUPyi1PxIxzxl0n463LxxaB2O6olC+Q=="], - "@ai-sdk/mistral": ["@ai-sdk/mistral@2.0.26", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-jxDB++4WI1wEx5ONNBI+VbkmYJOYIuS8UQY13/83UGRaiW7oB/WHiH4ETe6KzbKpQPB3XruwTJQjUMsMfKyTXA=="], - "@ai-sdk/openai": ["@ai-sdk/openai@2.0.2", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-D4zYz2uR90aooKQvX1XnS00Z7PkbrcY+snUvPfm5bCabTG7bzLrVtD56nJ5bSaZG8lmuOMfXpyiEEArYLyWPpw=="], "@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.1", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-luHVcU+yKzwv3ekKgbP3v+elUVxb2Rt+8c6w9qi7g2NYG2/pEL21oIrnaEnc6UtTZLLZX9EFBcpq2N1FQKDIMw=="], - "@ai-sdk/perplexity": ["@ai-sdk/perplexity@2.0.22", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-zwzcnk08R2J3mZcQPn4Ifl4wYGrvANR7jsBB0hCTUSbb+Rx3ybpikSWiGuXQXxdiRc1I5MWXgj70m+bZaLPvHw=="], - "@ai-sdk/provider": ["@ai-sdk/provider@2.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA=="], - "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.18", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ=="], - - "@ai-sdk/togetherai": ["@ai-sdk/togetherai@1.0.30", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.29", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-9bxQbIXnWSN4bNismrza3NvIo+ui/Y3pj3UN6e9vCszCWFCN45RgISi4oDe10RqmzaJ/X8cfO/Tem+K8MT3wGQ=="], - - "@ai-sdk/xai": ["@ai-sdk/xai@2.0.42", "", { "dependencies": { "@ai-sdk/openai-compatible": "1.0.29", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-wlwO4yRoZ/d+ca29vN8SDzxus7POdnL7GBTyRdSrt6icUF0hooLesauC8qRUC4aLxtqvMEc1YHtJOU7ZnLWbTQ=="], + "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-BoQZtGcBxkeSH1zK+SRYNDtJPIPpacTeiMZqnG4Rv6xXjEwM0FH4MGs9c+PlhyEWmQCzjRM2HAotEydFhD4dYw=="], "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], @@ -675,34 +611,6 @@ "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.1", "", {}, "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww=="], - "@azure/abort-controller": ["@azure/abort-controller@2.1.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA=="], - - "@azure/core-auth": ["@azure/core-auth@1.10.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-util": "^1.13.0", "tslib": "^2.6.2" } }, "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg=="], - - "@azure/core-client": ["@azure/core-client@1.10.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "tslib": "^2.6.2" } }, "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w=="], - - "@azure/core-http": ["@azure/core-http@3.0.5", "", { "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.3.0", "@azure/core-tracing": "1.0.0-preview.13", "@azure/core-util": "^1.1.1", "@azure/logger": "^1.0.0", "@types/node-fetch": "^2.5.0", "@types/tunnel": "^0.0.3", "form-data": "^4.0.0", "node-fetch": "^2.6.7", "process": "^0.11.10", "tslib": "^2.2.0", "tunnel": "^0.0.6", "uuid": "^8.3.0", "xml2js": "^0.5.0" } }, "sha512-T8r2q/c3DxNu6mEJfPuJtptUVqwchxzjj32gKcnMi06rdiVONS9rar7kT9T2Am+XvER7uOzpsP79WsqNbdgdWg=="], - - "@azure/core-http-compat": ["@azure/core-http-compat@2.3.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-client": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0" } }, "sha512-az9BkXND3/d5VgdRRQVkiJb2gOmDU8Qcq4GvjtBmDICNiQ9udFmDk4ZpSB5Qq1OmtDJGlQAfBaS4palFsazQ5g=="], - - "@azure/core-lro": ["@azure/core-lro@2.7.2", "", { "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-util": "^1.2.0", "@azure/logger": "^1.0.0", "tslib": "^2.6.2" } }, "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw=="], - - "@azure/core-paging": ["@azure/core-paging@1.6.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA=="], - - "@azure/core-rest-pipeline": ["@azure/core-rest-pipeline@1.22.2", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg=="], - - "@azure/core-tracing": ["@azure/core-tracing@1.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ=="], - - "@azure/core-util": ["@azure/core-util@1.13.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A=="], - - "@azure/core-xml": ["@azure/core-xml@1.5.0", "", { "dependencies": { "fast-xml-parser": "^5.0.7", "tslib": "^2.8.1" } }, "sha512-D/sdlJBMJfx7gqoj66PKVmhDDaU6TKA49ptcolxdas29X7AfvLTmfAGLjAcIMBK7UZ2o4lygHIqVckOlQU3xWw=="], - - "@azure/logger": ["@azure/logger@1.3.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA=="], - - "@azure/storage-blob": ["@azure/storage-blob@12.29.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-client": "^1.9.3", "@azure/core-http-compat": "^2.2.0", "@azure/core-lro": "^2.2.0", "@azure/core-paging": "^1.6.2", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/core-xml": "^1.4.5", "@azure/logger": "^1.1.4", "@azure/storage-common": "^12.1.1", "events": "^3.0.0", "tslib": "^2.8.1" } }, "sha512-7ktyY0rfTM0vo7HvtK6E3UvYnI9qfd6Oz6z/+92VhGRveWng3kJwMKeUpqmW/NmwcDNbxHpSlldG+vsUnRFnBg=="], - - "@azure/storage-common": ["@azure/storage-common@12.1.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-http-compat": "^2.2.0", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/logger": "^1.1.4", "events": "^3.3.0", "tslib": "^2.8.1" } }, "sha512-eIOH1pqFwI6UmVNnDQvmFeSg0XppuzDLFeUNO/Xht7ODAzRLgGDh7h550pSxoA+lPDxBl1+D2m/KG3jWzCUjTg=="], - "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], "@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="], @@ -765,10 +673,6 @@ "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], - "@bufbuild/protobuf": ["@bufbuild/protobuf@2.10.1", "", {}, "sha512-ckS3+vyJb5qGpEYv/s1OebUHDi/xSNtfgw1wqKZo7MR9F2z+qXr0q5XagafAG/9O0QPVIUfST0smluYSTpYFkg=="], - - "@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.10.1", "", { "dependencies": { "@bufbuild/protobuf": "2.10.1", "@typescript/vfs": "^1.6.2", "typescript": "5.4.5" } }, "sha512-imB8dKEjrOnG5+XqVS+CeYn924WGLU/g3wogKhk11XtX9y9NJ7432OS6h24asuBbLrQcPdEZ6QkfM7KeOCeeyQ=="], - "@capsizecss/unpack": ["@capsizecss/unpack@2.4.0", "", { "dependencies": { "blob-to-buffer": "^1.2.8", "cross-fetch": "^3.0.4", "fontkit": "^2.0.2" } }, "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q=="], "@clack/core": ["@clack/core@1.0.0-alpha.1", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-rFbCU83JnN7l3W1nfgCqqme4ZZvTTgsiKQ6FM0l+r0P+o2eJpExcocBUWUIwnDzL76Aca9VhUdWmB2MbUv+Qyg=="], @@ -893,13 +797,9 @@ "@fontsource/inter": ["@fontsource/inter@5.2.8", "", {}, "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg=="], - "@happy-dom/global-registrator": ["@happy-dom/global-registrator@20.0.11", "", { "dependencies": { "@types/node": "^20.0.0", "happy-dom": "^20.0.11" } }, "sha512-GqNqiShBT/lzkHTMC/slKBrvN0DsD4Di8ssBk4aDaVgEn+2WMzE6DXxq701ndSXj7/0cJ8mNT71pM7Bnrr6JRw=="], + "@hey-api/json-schema-ref-parser": ["@hey-api/json-schema-ref-parser@1.0.6", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0", "lodash": "^4.17.21" } }, "sha512-yktiFZoWPtEW8QKS65eqKwA5MTKp88CyiL8q72WynrBs/73SAaxlSWlA2zW/DZlywZ5hX1OYzrCC0wFdvO9c2w=="], - "@hey-api/codegen-core": ["@hey-api/codegen-core@0.3.3", "", { "peerDependencies": { "typescript": ">=5.5.3" } }, "sha512-vArVDtrvdzFewu1hnjUm4jX1NBITlSCeO81EdWq676MxQbyxsGcDPAgohaSA+Wvr4HjPSvsg2/1s2zYxUtXebg=="], - - "@hey-api/json-schema-ref-parser": ["@hey-api/json-schema-ref-parser@1.2.2", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.1", "lodash": "^4.17.21" } }, "sha512-oS+5yAdwnK20lSeFO1d53Ku+yaGCsY8PcrmSq2GtSs3bsBfRnHAbpPKSVzQcaxAOrzj5NB+f34WhZglVrNayBA=="], - - "@hey-api/openapi-ts": ["@hey-api/openapi-ts@0.88.1", "", { "dependencies": { "@hey-api/codegen-core": "^0.3.3", "@hey-api/json-schema-ref-parser": "1.2.2", "ansi-colors": "4.1.3", "c12": "3.3.2", "color-support": "1.1.3", "commander": "14.0.2", "open": "11.0.0", "semver": "7.7.2" }, "peerDependencies": { "typescript": ">=5.5.3" }, "bin": { "openapi-ts": "bin/run.js" } }, "sha512-x/nDTupOnV9VuSeNIiJpgIpc915GHduhyseJeMTnI0JMsXaObmpa0rgPr3ASVEYMLgpvqozIEG1RTOOnal6zLQ=="], + "@hey-api/openapi-ts": ["@hey-api/openapi-ts@0.81.0", "", { "dependencies": { "@hey-api/json-schema-ref-parser": "1.0.6", "ansi-colors": "4.1.3", "c12": "2.0.1", "color-support": "1.1.3", "commander": "13.0.0", "handlebars": "4.7.8", "js-yaml": "4.1.0", "open": "10.1.2", "semver": "7.7.2" }, "peerDependencies": { "typescript": "^5.5.3" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-PoJukNBkUfHOoMDpN33bBETX49TUhy7Hu8Sa0jslOvFndvZ5VjQr4Nl/Dzjb9LG1Lp5HjybyTJMA6a1zYk/q6A=="], "@hono/standard-validator": ["@hono/standard-validator@0.1.5", "", { "peerDependencies": { "@standard-schema/spec": "1.0.0", "hono": ">=3.9.0" } }, "sha512-EIyZPPwkyLn6XKwFj5NBEWHXhXbgmnVh2ceIFo5GO7gKI9WmzTjPDKnppQB0KrqKeAkq3kpoW4SIbu5X1dgx3w=="], @@ -1113,11 +1013,11 @@ "@octokit/auth-oauth-user": ["@octokit/auth-oauth-user@6.0.2", "", { "dependencies": { "@octokit/auth-oauth-device": "^8.0.3", "@octokit/oauth-methods": "^6.0.2", "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-qLoPPc6E6GJoz3XeDG/pnDhJpTkODTGG4kY0/Py154i/I003O9NazkrwJwRuzgCalhzyIeWQ+6MDvkUmKXjg/A=="], - "@octokit/auth-token": ["@octokit/auth-token@4.0.0", "", {}, "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA=="], + "@octokit/auth-token": ["@octokit/auth-token@6.0.0", "", {}, "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w=="], - "@octokit/core": ["@octokit/core@5.2.2", "", { "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.1.0", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg=="], + "@octokit/core": ["@octokit/core@7.0.6", "", { "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", "@octokit/request": "^10.0.6", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "before-after-hook": "^4.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q=="], - "@octokit/endpoint": ["@octokit/endpoint@9.0.6", "", { "dependencies": { "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" } }, "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw=="], + "@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], "@octokit/graphql": ["@octokit/graphql@9.0.2", "", { "dependencies": { "@octokit/request": "^10.0.4", "@octokit/types": "^15.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-iz6KzZ7u95Fzy9Nt2L8cG88lGRMr/qy1Q36ih/XVzMIlPDMYwaNLE/ENhqmIzgPrlNWiYJkwmveEetvxAgFBJw=="], @@ -1129,15 +1029,13 @@ "@octokit/plugin-paginate-rest": ["@octokit/plugin-paginate-rest@13.2.1", "", { "dependencies": { "@octokit/types": "^15.0.1" }, "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-Tj4PkZyIL6eBMYcG/76QGsedF0+dWVeLhYprTmuFVVxzDW7PQh23tM0TP0z+1MvSkxB29YFZwnUX+cXfTiSdyw=="], - "@octokit/plugin-request-log": ["@octokit/plugin-request-log@1.0.4", "", { "peerDependencies": { "@octokit/core": ">=3" } }, "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA=="], + "@octokit/plugin-request-log": ["@octokit/plugin-request-log@6.0.0", "", { "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q=="], "@octokit/plugin-rest-endpoint-methods": ["@octokit/plugin-rest-endpoint-methods@16.1.1", "", { "dependencies": { "@octokit/types": "^15.0.1" }, "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-VztDkhM0ketQYSh5Im3IcKWFZl7VIrrsCaHbDINkdYeiiAsJzjhS2xRFCSJgfN6VOcsoW4laMtsmf3HcNqIimg=="], - "@octokit/plugin-retry": ["@octokit/plugin-retry@3.0.9", "", { "dependencies": { "@octokit/types": "^6.0.3", "bottleneck": "^2.15.3" } }, "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ=="], + "@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - "@octokit/request": ["@octokit/request@8.4.1", "", { "dependencies": { "@octokit/endpoint": "^9.0.6", "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" } }, "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw=="], - - "@octokit/request-error": ["@octokit/request-error@5.1.1", "", { "dependencies": { "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" } }, "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g=="], + "@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], "@octokit/rest": ["@octokit/rest@22.0.0", "", { "dependencies": { "@octokit/core": "^7.0.2", "@octokit/plugin-paginate-rest": "^13.0.1", "@octokit/plugin-request-log": "^6.0.0", "@octokit/plugin-rest-endpoint-methods": "^16.0.0" } }, "sha512-z6tmTu9BTnw51jYGulxrlernpsQYXpui1RK21vmXn8yF5bp6iX16yfTtJYGK5Mh1qDkvDOmp2n8sRMcQmR8jiA=="], @@ -1149,8 +1047,6 @@ "@openauthjs/openauth": ["@openauthjs/openauth@0.0.0-20250322224806", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-p5IWSRXvABcwocH2dNI0w8c1QJelIOFulwhKk+aLLFfUbs8u1pr7kQbYe8yCSM2+bcLHiwbogpUQc2ovrGwCuw=="], - "@opencode-ai/app": ["@opencode-ai/app@workspace:packages/app"], - "@opencode-ai/console-app": ["@opencode-ai/console-app@workspace:packages/console/app"], "@opencode-ai/console-core": ["@opencode-ai/console-core@workspace:packages/console/core"], @@ -1175,33 +1071,35 @@ "@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"], + "@opencode-ai/tauri": ["@opencode-ai/tauri@workspace:packages/tauri"], + "@opencode-ai/ui": ["@opencode-ai/ui@workspace:packages/ui"], "@opencode-ai/util": ["@opencode-ai/util@workspace:packages/util"], "@opencode-ai/web": ["@opencode-ai/web@workspace:packages/web"], - "@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@1.5.2", "", { "dependencies": { "@openrouter/sdk": "^0.1.27" }, "peerDependencies": { "@toon-format/toon": "^2.0.0", "ai": "^5.0.0", "zod": "^3.24.1 || ^v4" }, "optionalPeers": ["@toon-format/toon"] }, "sha512-3Th0vmJ9pjnwcPc2H1f59Mb0LFvwaREZAScfOQIpUxAHjZ7ZawVKDP27qgsteZPmMYqccNMy4r4Y3kgUnNcKAg=="], + "@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@1.2.5", "", { "dependencies": { "@openrouter/sdk": "^0.1.8" }, "peerDependencies": { "ai": "^5.0.0", "zod": "^3.24.1 || ^v4" } }, "sha512-NrvJFPvdEUo6DYUQIVWPGfhafuZ2PAIX7+CUMKGknv8TcTNVo0TyP1y5SU7Bgjf/Wup9/74UFKUB07icOhVZjQ=="], "@openrouter/sdk": ["@openrouter/sdk@0.1.27", "", { "dependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-RH//L10bSmc81q25zAZudiI4kNkLgxF2E+WU42vghp3N6TEvZ6F0jK7uT3tOxkEn91gzmMw9YVmDENy7SJsajQ=="], "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], - "@opentui/core": ["@opentui/core@0.1.63", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.63", "@opentui/core-darwin-x64": "0.1.63", "@opentui/core-linux-arm64": "0.1.63", "@opentui/core-linux-x64": "0.1.63", "@opentui/core-win32-arm64": "0.1.63", "@opentui/core-win32-x64": "0.1.63", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-m4xZQTNCnHXWUWCnGvacJ3Gts1H2aMwP5V/puAG77SDb51jm4W/QOyqAAdgeSakkb9II+8FfUpApX7sfwRXPUg=="], + "@opentui/core": ["@opentui/core@0.1.50", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.50", "@opentui/core-darwin-x64": "0.1.50", "@opentui/core-linux-arm64": "0.1.50", "@opentui/core-linux-x64": "0.1.50", "@opentui/core-win32-arm64": "0.1.50", "@opentui/core-win32-x64": "0.1.50", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-QhjwT2f8AIQj0gbL/WQ2M93sl2/qp9+Kqxyh4dOhp8z3qnTc5D7J105VrMyeWZW7/P27ubgbFAqqWXrZ4FsuLw=="], - "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.63", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jKCThZGiiublKkP/hMtDtl1MLCw5NU0hMNJdEYvz1WLT9bzliWf6Kb7MIDAmk32XlbQW8/RHdp+hGyGDXK62OQ=="], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.50", "", { "os": "darwin", "cpu": "arm64" }, "sha512-FKqTDOsZl9TXF7KN2SdZKoRHQNvqKSY27AG3jhKCoiyLGdaNCAsaeBWqAmpnL4E4kMkV3aiQSCrKTrYsaevvOg=="], - "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.63", "", { "os": "darwin", "cpu": "x64" }, "sha512-rfNxynHzJpxN9i+SAMnn1NToEc8rYj64BsOxY78JNsm4Gg1Js1uyMaawwh2WbdGknFy4cDXS9QwkUMdMcfnjiw=="], + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.50", "", { "os": "darwin", "cpu": "x64" }, "sha512-GczVNqqpM/HtsgeBB08K6zL1B7oc6Y5G2cMklo06LrYRdDkFdDtY5fNNnJR2/psZWzTrI3M+sLnKWgUGD5CxUQ=="], - "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.63", "", { "os": "linux", "cpu": "arm64" }, "sha512-wG9d6mHWWKZGrzxYS4c+BrcEGXBv/MYBUPSyjP/lD0CxT+X3h6CYhI317JkRyMNfh3vI9CpAKGFTOFvrTTHimQ=="], + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.50", "", { "os": "linux", "cpu": "arm64" }, "sha512-+CKMhweEXH0tLGM6qqaqk6DyCEmwrTVubTtez/pSM3GgcROSXIBui9TEZpIlPgSCVmjbotGS6eSIg4oU+p9o7w=="], - "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.63", "", { "os": "linux", "cpu": "x64" }, "sha512-TKSzFv4BgWW3RB/iZmq5qxTR4/tRaXo8IZNnVR+LFzShbPOqhUi466AByy9SUmCxD8uYjmMDFYfKtkCy0AnAwA=="], + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.50", "", { "os": "linux", "cpu": "x64" }, "sha512-yv5KWiMohAK9bsi1gth9DDZDpoJA1EDHexjhThsPT8EH82g13T088dnJZuJWUE9dr1OwTCQG8DyorNxX3ViEGQ=="], - "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.63", "", { "os": "win32", "cpu": "arm64" }, "sha512-CBWPyPognERP0Mq4eC1q01Ado2C2WU+BLTgMdhyt+E2P4w8rPhJ2kCt2MNxO66vQUiynspmZkgjQr0II/VjxWA=="], + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.50", "", { "os": "win32", "cpu": "arm64" }, "sha512-6/6pURTRNTLFKF8IhYVi7U+T/HGMeURav9LIYw7yfcOibd0kLMthmemhS0Lzyk5dmtp0T4V4NmRmtlq/fIzyjQ=="], - "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.63", "", { "os": "win32", "cpu": "x64" }, "sha512-qEp6h//FrT+TQiiHm87wZWUwqTPTqIy1ZD+8R+VCUK+usoQiOAD2SqrYnM7W8JkCMGn5/TKm/GaKLyx/qlK4VA=="], + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.50", "", { "os": "win32", "cpu": "x64" }, "sha512-EME8GBFq9uCLbH5js8fH7/xY4ZtLIZlt3bkYKT6lPiCNdaf/6ebg+F/ObPXFkJrc8VeV1ql2bXhQ6RLi7izvAA=="], - "@opentui/solid": ["@opentui/solid@0.1.63", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.63", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-Gccln4qRucAoaoQEZ4NPAHvGmVYzU/8aKCLG8EPgwCKTcpUzlqYt4357cDHq4cnCNOcXOC06hTz/0pK9r0dqXA=="], + "@opentui/solid": ["@opentui/solid@0.1.50", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.50", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-q778kp/eksh8UOPSQO2h8h9CGGDqepTf9u2WYTS2HYHRAI2SRtUWpN9L7Euyt3BtG9L/wpsIOHK/ufPhQH1X6A=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], @@ -1317,7 +1215,7 @@ "@petamoriken/float16": ["@petamoriken/float16@3.9.3", "", {}, "sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g=="], - "@pierre/diffs": ["@pierre/diffs@1.0.2", "", { "dependencies": { "@shikijs/core": "^3.0.0", "@shikijs/engine-javascript": "3.19.0", "@shikijs/transformers": "3.19.0", "diff": "8.0.2", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "3.19.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-RkFSDD5X/U+8QjyilPViYGJfmJNWXR17zTL8zw48+DcVC1Ujbh6I1edyuRnFfgRzpft05x2DSCkz2cjoIAxPvQ=="], + "@pierre/precision-diffs": ["@pierre/precision-diffs@0.5.7", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/transformers": "3.15.0", "diff": "8.0.2", "fast-deep-equal": "3.1.3", "hast-util-to-html": "9.0.5", "shiki": "3.15.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-Y+e4kJ9pT2I4NS5fE39KdoiXtwMkVPRvrwLM6O2IqO7PDCRWLBS7CYxcSgSyngEndccUll2krx66I2QnfO0Ovg=="], "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], @@ -1329,14 +1227,6 @@ "@poppinss/exception": ["@poppinss/exception@1.2.2", "", {}, "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg=="], - "@protobuf-ts/plugin": ["@protobuf-ts/plugin@2.11.1", "", { "dependencies": { "@bufbuild/protobuf": "^2.4.0", "@bufbuild/protoplugin": "^2.4.0", "@protobuf-ts/protoc": "^2.11.1", "@protobuf-ts/runtime": "^2.11.1", "@protobuf-ts/runtime-rpc": "^2.11.1", "typescript": "^3.9" }, "bin": { "protoc-gen-ts": "bin/protoc-gen-ts", "protoc-gen-dump": "bin/protoc-gen-dump" } }, "sha512-HyuprDcw0bEEJqkOWe1rnXUP0gwYLij8YhPuZyZk6cJbIgc/Q0IFgoHQxOXNIXAcXM4Sbehh6kjVnCzasElw1A=="], - - "@protobuf-ts/protoc": ["@protobuf-ts/protoc@2.11.1", "", { "bin": { "protoc": "protoc.js" } }, "sha512-mUZJaV0daGO6HUX90o/atzQ6A7bbN2RSuHtdwo8SSF2Qoe3zHwa4IHyCN1evftTeHfLmdz+45qo47sL+5P8nyg=="], - - "@protobuf-ts/runtime": ["@protobuf-ts/runtime@2.11.1", "", {}, "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ=="], - - "@protobuf-ts/runtime-rpc": ["@protobuf-ts/runtime-rpc@2.11.1", "", { "dependencies": { "@protobuf-ts/runtime": "^2.11.1" } }, "sha512-4CqqUmNA+/uMz00+d3CYKgElXO9VrEbucjnBFEjqI4GuDrEQ32MaI3q+9qPBvIGOlL4PmHXrzM32vBPWRhQKWQ=="], - "@radix-ui/colors": ["@radix-ui/colors@1.0.1", "", {}, "sha512-xySw8f0ZVsAEP+e7iLl3EvcBXX7gsIlC1Zso/sPBW9gIWerBTgz6axrjU+MZ39wD+WFi5h5zdWpsg3+hwt2Qsg=="], "@radix-ui/primitive": ["@radix-ui/primitive@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10" } }, "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw=="], @@ -1453,13 +1343,13 @@ "@shikijs/core": ["@shikijs/core@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-3q/mzmw09B2B6PgFNeiaN8pkNOixWS726IHmJEpjDAcneDPMQmUg2cweT9cWXY4XcyQS3i6mOOUgQz9RRUP6HA=="], - "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg=="], + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-kUTRVKPsB/28H5Ko6qEsyudBiWEDLst+Sfi+hwr59E0GLHV0h8RfgbQU7fdN5Lt9A8R1ulRiZyTvAizkROjwDA=="], - "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ=="], + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-Vn/w5oyQ6TUgTVDIC/BrpXwIlfK6V6kGWDVVz2eRkF2v13YoENUvaNwxMsQU/t6oCuZKzqp9vqtEtEzKl9VegA=="], - "@shikijs/langs": ["@shikijs/langs@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-le+bssCxcSHrygCWuOrYJHvjus6zhQ2K7q/0mgjiffRbkhM4o1EWu2m+29l0yEsHDbWaWPNnDUTRVVBvBBeKaA=="], + "@shikijs/langs": ["@shikijs/langs@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2" } }, "sha512-X1Q6wRRQXY7HqAuX3I8WjMscjeGjqXCg/Sve7J2GWFORXkSrXud23UECqTBIdCSNKJioFtmUGJQNKtlMMZMn0w=="], - "@shikijs/themes": ["@shikijs/themes@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ=="], + "@shikijs/themes": ["@shikijs/themes@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2" } }, "sha512-6z5lBPBMRfLyyEsgf6uJDHPa6NAGVzFJqH4EAZ+03+7sedYir2yJBRu2uPZOKmj43GyhVHWHvyduLDAwJQfDjA=="], "@shikijs/transformers": ["@shikijs/transformers@3.9.2", "", { "dependencies": { "@shikijs/core": "3.9.2", "@shikijs/types": "3.9.2" } }, "sha512-MW5hT4TyUp6bNAgTExRYLk1NNasVQMTCw1kgbxHcEC0O5cbepPWaB+1k+JzW9r3SP2/R8kiens8/3E6hGKfgsA=="], @@ -1585,10 +1475,6 @@ "@solid-primitives/active-element": ["@solid-primitives/active-element@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-9t5K4aR2naVDj950XU8OjnLgOg94a8k5wr6JNOPK+N5ESLsJDq42c1ZP8UKpewi1R+wplMMxiM6OPKRzbxJY7A=="], - "@solid-primitives/audio": ["@solid-primitives/audio@1.4.2", "", { "dependencies": { "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-UMD3ORQfI5Ky8yuKPxidDiEazsjv/dsoiKK5yZxLnsgaeNR1Aym3/77h/qT1jBYeXUgj4DX6t7NMpFUSVr14OQ=="], - - "@solid-primitives/bounds": ["@solid-primitives/bounds@0.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/resize-observer": "^2.1.3", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-UbiyKMdSPmtijcEDnYLQL3zzaejpwWDAJJ4Gt5P0hgVs6A72piov0GyNw7V2SroH7NZFwxlYS22YmOr8A5xc1Q=="], - "@solid-primitives/event-bus": ["@solid-primitives/event-bus@1.1.2", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-l+n10/51neGcMaP3ypYt21bXfoeWh8IaC8k7fYuY3ww2a8S1Zv2N2a7FF5Qn+waTu86l0V8/nRHjkyqVIZBYwA=="], "@solid-primitives/event-listener": ["@solid-primitives/event-listener@2.4.3", "", { "dependencies": { "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg=="], @@ -1617,8 +1503,6 @@ "@solid-primitives/utils": ["@solid-primitives/utils@6.3.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ=="], - "@solid-primitives/websocket": ["@solid-primitives/websocket@1.3.1", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-F06tA2FKa5VsnS4E4WEc3jHpsJfXRlMTGOtolugTzCqV3JmJTyvk9UVg1oz6PgGHKGi1CQ91OP8iW34myyJgaQ=="], - "@solidjs/meta": ["@solidjs/meta@0.29.4", "", { "peerDependencies": { "solid-js": ">=1.8.4" } }, "sha512-zdIWBGpR9zGx1p1bzIPqF5Gs+Ks/BH8R6fWhmUa/dcK1L2rUC8BAcZJzNRYBQv74kScf1TSOs0EY//Vd/I0V8g=="], "@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="], @@ -1697,24 +1581,8 @@ "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-EdYd4c9wGvtPB95kqtEyY+bUR+k4kRw3IA30mAQ1jPH6z57AftT8q84qwv0RDp6kkEqOBKxeInKfqi4BESYuqg=="], - "@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.4.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-lNIn5CZuw8WZOn8zHzmFmDSzg5zfohWoa3mdULP0YFh/VogVdMVWZPcWSHlydsiJhRQYaTNSYKN7RmZKE2lCYQ=="], - - "@tauri-apps/plugin-http": ["@tauri-apps/plugin-http@2.5.4", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-/i4U/9za3mrytTgfRn5RHneKubZE/dwRmshYwyMvNRlkWjvu1m4Ma72kcbVJMZFGXpkbl+qLyWMGrihtWB76Zg=="], - "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew=="], - "@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A=="], - - "@tauri-apps/plugin-process": ["@tauri-apps/plugin-process@2.3.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-nCa4fGVaDL/B9ai03VyPOjfAHRHSBz5v6F/ObsB73r/dA3MHHhZtldaDMIc0V/pnUw9ehzr2iEG+XkSEyC0JJA=="], - - "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Xod+pRcFxmOWFWEnqH5yZcA7qwAMuaaDkMR1Sply+F8VfBj++CGnj2xf5UoialmjZ2Cvd8qrvSCbU+7GgNVsKQ=="], - - "@tauri-apps/plugin-store": ["@tauri-apps/plugin-store@2.4.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ckGSEzZ5Ii4Hf2D5x25Oqnm2Zf9MfDWAzR+volY0z/OOBz6aucPKEY0F649JvQ0Vupku6UJo7ugpGRDOFOunkA=="], - - "@tauri-apps/plugin-updater": ["@tauri-apps/plugin-updater@2.9.0", "", { "dependencies": { "@tauri-apps/api": "^2.6.0" } }, "sha512-j++sgY8XpeDvzImTrzWA08OqqGqgkNyxczLD7FjNJJx/uXxMZFz5nDcfkyoI/rCjYuj2101Tci/r/HFmOmoxCg=="], - - "@tauri-apps/plugin-window-state": ["@tauri-apps/plugin-window-state@2.4.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-OuvdrzyY8Q5Dbzpj+GcrnV1iCeoZbcFdzMjanZMMcAEUNy/6PH5pxZPXpaZLOR7whlzXiuzx0L9EKZbH7zpdRw=="], - "@thisbeyond/solid-dnd": ["@thisbeyond/solid-dnd@0.7.5", "", { "peerDependencies": { "solid-js": "^1.5" } }, "sha512-DfI5ff+yYGpK9M21LhYwIPlbP2msKxN2ARwuu6GF8tT1GgNVDTI8VCQvH4TJFoVApP9d44izmAcTh/iTCH2UUw=="], "@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="], @@ -1737,7 +1605,7 @@ "@types/braces": ["@types/braces@3.0.5", "", {}, "sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w=="], - "@types/bun": ["@types/bun@1.3.4", "", { "dependencies": { "bun-types": "1.3.4" } }, "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA=="], + "@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="], "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], @@ -1809,39 +1677,31 @@ "@types/tsscmp": ["@types/tsscmp@1.0.2", "", {}, "sha512-cy7BRSU8GYYgxjcx0Py+8lo5MthuDhlyu076KUcYzVNXL23luYgRHkMG2fIFEc6neckeh/ntP82mw+U4QjZq+g=="], - "@types/tunnel": ["@types/tunnel@0.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA=="], - "@types/turndown": ["@types/turndown@5.0.5", "", {}, "sha512-TL2IgGgc7B5j78rIccBtlYAnkuv8nUQqhQc+DSYV5j9Be9XOcm/SKOVRuA47xAVI3680Tk9B1d8flK2GWT2+4w=="], "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], - "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], - "@types/ws": ["@types/ws@7.4.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww=="], "@types/yargs": ["@types/yargs@17.0.33", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA=="], "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="], - "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20251207.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20251207.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20251207.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20251207.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20251207.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20251207.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20251207.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20251207.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-4QcRnzB0pi9rS0AOvg8kWbmuwHv5X7B2EXHbgcms9+56hsZ8SZrZjNgBJb2rUIodJ4kU5mrkj/xlTTT4r9VcpQ=="], + "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20251014.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20251014.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20251014.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20251014.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20251014.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20251014.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20251014.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20251014.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-IqmX5CYCBqXbfL+HKlcQAMaDlfJ0Z8OhUxvADFV2TENnzSYI4CuhvKxwOB2wFSLXufVsgtAlf3Fjwn24KmMyPQ=="], - "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20251207.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-waWJnuuvkXh4WdpbTjYf7pyahJzx0ycesV2BylyHrE9OxU9FSKcD/cRLQYvbq3YcBSdF7sZwRLDBer7qTeLsYA=="], + "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20251014.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-7rQoLlerWnwnvrM56hP4rdEbo4xDE4zr7cch+EzgENq/tbXYereGq1fmnR83UNglb1Eyy53OvJZ3O2csYBa2vg=="], - "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20251207.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-3bkD9QuIjxETtp6J1l5X2oKgudJ8z+8fwUq0izCjK1JrIs2vW1aQnbzxhynErSyHWH7URGhHHzcsXHbikckAsg=="], + "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20251014.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-SF29o9NFRGDM23Jz0nVO4/yS78GQ81rtOemmCVNXuJotoY4bP3npGDyEmfkZQHZgDOXogs2OWy3t7NUJ235ANQ=="], - "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20251207.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OjrZBq8XJkB7uCQvT1AZ1FPsp+lT0cHxY5SisE+ZTAU6V0IHAZMwJ7J/mnwlGsBcCKRLBT+lX3hgEuOTSwHr9w=="], + "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20251014.1", "", { "os": "linux", "cpu": "arm" }, "sha512-o5cu7h+BBAp6V4qxYY5RWuaYouN3j+MGFLrrUtvvNj4XKM+kbq5qwsgVRsmJZ1LfUvHmzyQs86vt9djAWedzjQ=="], - "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20251207.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qhp06OObkwy5B+PlAhAmq+Ls3GVt4LHAovrTRcpLB3Mk3yJ0h9DnIQwPQiayp16TdvTsGHI3jdIX4MGm5L/ghA=="], + "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20251014.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+YWbW/JF4uggEUBr+vflqI5i7bL4Z3XInCOyUO1qQEY7VmfDCsPEzIwGi37O1mixfxw9Qj8LQsptCkU+fqKwGw=="], - "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20251207.1", "", { "os": "linux", "cpu": "x64" }, "sha512-fPRw0zfTBeVmrkgi5Le+sSwoeAz6pIdvcsa1OYZcrspueS9hn3qSC5bLEc5yX4NJP1vItadBqyGLUQ7u8FJjow=="], + "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20251014.1", "", { "os": "linux", "cpu": "x64" }, "sha512-3LC4tgcgi6zWJWBUpBNXOGSY3yISJrQezSP/T+v+mQRApkdoIpTSHIyQAhgaagcs3MOQRaqiIPaLOVrdHXdU6A=="], - "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20251207.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-KxY1i+HxeSFfzZ+HVsKwMGBM79laTRZv1ibFqHu22CEsfSPDt4yiV1QFis8Nw7OBXswNqJG/UGqY47VP8FeTvw=="], + "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20251014.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-P0D4UEXwzFZh3pHexe2Ky1tW/HjY/HxTBTIajz2ViDCNPw7uDSEsXSB4H9TTiFJw8gVdTUFbsoAQp1MteTeORA=="], - "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20251207.1", "", { "os": "win32", "cpu": "x64" }, "sha512-5l51HlXjX7lXwo65DEl1IaCFLjmkMtL6K3NrSEamPNeNTtTQwZRa3pQ9V65dCglnnCQ0M3+VF1RqzC7FU0iDKg=="], - - "@typescript/vfs": ["@typescript/vfs@1.6.2", "", { "dependencies": { "debug": "^4.1.1" }, "peerDependencies": { "typescript": "*" } }, "sha512-hoBwJwcbKHmvd2QVebiytN1aELvpk9B74B4L1mFm/XT1Q/VOYAWl2vQ9AWRFtQq8zmz6enTpfTV8WRc4ATjW/g=="], - - "@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.2", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-IlqQ/Gv22xUC1r/WQm4StLkYQmaaTsXAhUVsNE0+xiyf0yRFiH5++q78U3bw6bLKDCTmh0uqKB9eG9+Bt75Dkg=="], + "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20251014.1", "", { "os": "win32", "cpu": "x64" }, "sha512-fi53g2ihH7tkQLlz8hZGAb2V+3aNZpcxrZ530CQ4xcWwAqssEj0EaZJX0VLEtIQBar1ttGVK9Pz/wJU9sYyVzg=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], @@ -1849,19 +1709,19 @@ "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], - "@vitest/expect": ["@vitest/expect@4.0.16", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.16", "@vitest/utils": "4.0.16", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA=="], + "@vitest/expect": ["@vitest/expect@4.0.13", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.13", "@vitest/utils": "4.0.13", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-zYtcnNIBm6yS7Gpr7nFTmq8ncowlMdOJkWLqYvhr/zweY6tFbDkDi8BPPOeHxEtK1rSI69H7Fd4+1sqvEGli6w=="], - "@vitest/mocker": ["@vitest/mocker@4.0.16", "", { "dependencies": { "@vitest/spy": "4.0.16", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg=="], + "@vitest/mocker": ["@vitest/mocker@4.0.13", "", { "dependencies": { "@vitest/spy": "4.0.13", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-eNCwzrI5djoauklwP1fuslHBjrbR8rqIVbvNlAnkq1OTa6XT+lX68mrtPirNM9TnR69XUPt4puBCx2Wexseylg=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.0.16", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.0.13", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-ooqfze8URWbI2ozOeLDMh8YZxWDpGXoeY3VOgcDnsUxN0jPyPWSUvjPQWqDGCBks+opWlN1E4oP1UYl3C/2EQA=="], - "@vitest/runner": ["@vitest/runner@4.0.16", "", { "dependencies": { "@vitest/utils": "4.0.16", "pathe": "^2.0.3" } }, "sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q=="], + "@vitest/runner": ["@vitest/runner@4.0.13", "", { "dependencies": { "@vitest/utils": "4.0.13", "pathe": "^2.0.3" } }, "sha512-9IKlAru58wcVaWy7hz6qWPb2QzJTKt+IOVKjAx5vb5rzEFPTL6H4/R9BMvjZ2ppkxKgTrFONEJFtzvnyEpiT+A=="], - "@vitest/snapshot": ["@vitest/snapshot@4.0.16", "", { "dependencies": { "@vitest/pretty-format": "4.0.16", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA=="], + "@vitest/snapshot": ["@vitest/snapshot@4.0.13", "", { "dependencies": { "@vitest/pretty-format": "4.0.13", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-hb7Usvyika1huG6G6l191qu1urNPsq1iFc2hmdzQY3F5/rTgqQnwwplyf8zoYHkpt7H6rw5UfIw6i/3qf9oSxQ=="], - "@vitest/spy": ["@vitest/spy@4.0.16", "", {}, "sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw=="], + "@vitest/spy": ["@vitest/spy@4.0.13", "", {}, "sha512-hSu+m4se0lDV5yVIcNWqjuncrmBgwaXa2utFLIrBkQCQkt+pSwyZTPFQAZiiF/63j8jYa8uAeUZ3RSfcdWaYWw=="], - "@vitest/utils": ["@vitest/utils@4.0.16", "", { "dependencies": { "@vitest/pretty-format": "4.0.16", "tinyrainbow": "^3.0.3" } }, "sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA=="], + "@vitest/utils": ["@vitest/utils@4.0.13", "", { "dependencies": { "@vitest/pretty-format": "4.0.13", "tinyrainbow": "^3.0.3" } }, "sha512-ydozWyQ4LZuu8rLp47xFUWis5VOKMdHjXCWhs1LuJsTNKww+pTHQNK4e0assIB9K80TxFyskENL6vCu3j34EYA=="], "@webgpu/types": ["@webgpu/types@0.1.66", "", {}, "sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA=="], @@ -1903,10 +1763,6 @@ "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - "archiver": ["archiver@7.0.1", "", { "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", "zip-stream": "^6.0.1" } }, "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ=="], - - "archiver-utils": ["archiver-utils@5.0.2", "", { "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA=="], - "arctic": ["arctic@2.3.4", "", { "dependencies": { "@oslojs/crypto": "1.0.1", "@oslojs/encoding": "1.1.0", "@oslojs/jwt": "0.2.0" } }, "sha512-+p30BOWsctZp+CVYCt7oAean/hWGW42sH5LAcRQX56ttEkFJWbzXBhmSpibbzwSJkRrotmsA+oAoJoVsU0f5xA=="], "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], @@ -1937,8 +1793,6 @@ "astro-expressive-code": ["astro-expressive-code@0.41.3", "", { "dependencies": { "rehype-expressive-code": "^0.41.3" }, "peerDependencies": { "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0" } }, "sha512-u+zHMqo/QNLE2eqYRCrK3+XMlKakv33Bzuz+56V1gs8H0y6TZ0hIi3VNbIxeTn51NLn+mJfUV/A0kMNfE4rANw=="], - "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], - "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], @@ -1975,6 +1829,16 @@ "bare-events": ["bare-events@2.8.2", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ=="], + "bare-fs": ["bare-fs@4.5.1", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-zGUCsm3yv/ePt2PHNbVxjjn0nNB1MkIaR4wOCxJ2ig5pCf5cCVAYJXVhQg/3OhhJV6DB1ts7Hv0oUaElc2TPQg=="], + + "bare-os": ["bare-os@3.6.2", "", {}, "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A=="], + + "bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="], + + "bare-stream": ["bare-stream@2.7.0", "", { "dependencies": { "streamx": "^2.21.0" }, "peerDependencies": { "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-buffer", "bare-events"] }, "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A=="], + + "bare-url": ["bare-url@2.3.2", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw=="], + "base-64": ["base-64@1.0.0", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], @@ -1985,14 +1849,14 @@ "bcp-47-match": ["bcp-47-match@2.0.3", "", {}, "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ=="], - "before-after-hook": ["before-after-hook@2.2.3", "", {}, "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="], + "before-after-hook": ["before-after-hook@4.0.0", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="], "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], - "binary": ["binary@0.3.0", "", { "dependencies": { "buffers": "~0.1.1", "chainsaw": "~0.1.0" } }, "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg=="], - "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], "blob-to-buffer": ["blob-to-buffer@1.2.9", "", {}, "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA=="], @@ -2003,8 +1867,6 @@ "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - "bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="], - "bowser": ["bowser@2.12.1", "", {}, "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw=="], "boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="], @@ -2019,19 +1881,13 @@ "buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="], - "buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="], - "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - "buffers": ["buffers@0.1.1", "", {}, "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ=="], - "bun-ffi-structs": ["bun-ffi-structs@0.1.2", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-Lh1oQAYHDcnesJauieA4UNkWGXY9hYck7OA5IaRwE3Bp6K2F2pJSNYqq+hIy7P3uOvo3km3oxS8304g5gDMl/w=="], - "bun-pty": ["bun-pty@0.4.2", "", {}, "sha512-sHImDz6pJDsHAroYpC9ouKVgOyqZ7FP3N+stX5IdMddHve3rf9LIZBDomQcXrACQ7sQDNuwZQHG8BKR7w8krkQ=="], - - "bun-types": ["bun-types@1.3.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="], + "bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="], "bun-webgpu": ["bun-webgpu@0.1.4", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.4", "bun-webgpu-darwin-x64": "^0.1.4", "bun-webgpu-linux-x64": "^0.1.4", "bun-webgpu-win32-x64": "^0.1.4" } }, "sha512-Kw+HoXl1PMWJTh9wvh63SSRofTA8vYBFCw0XEP1V1fFdQEDhI8Sgf73sdndE/oDpN/7CMx0Yv/q8FCvO39ROMQ=="], @@ -2047,7 +1903,7 @@ "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], - "c12": ["c12@3.3.2", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.3", "exsolve": "^1.0.8", "giget": "^2.0.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "*" }, "optionalPeers": ["magicast"] }, "sha512-QkikB2X5voO1okL3QsES0N690Sn/K9WokXqUsDQsWy5SnYb+psYQFGA10iy1bZHj3fjISKsI67Q90gruvWWM3A=="], + "c12": ["c12@2.0.1", "", { "dependencies": { "chokidar": "^4.0.1", "confbox": "^0.1.7", "defu": "^6.1.4", "dotenv": "^16.4.5", "giget": "^1.2.3", "jiti": "^2.3.0", "mlly": "^1.7.1", "ohash": "^1.1.4", "pathe": "^1.1.2", "perfect-debounce": "^1.0.0", "pkg-types": "^1.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A=="], "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], @@ -2067,9 +1923,7 @@ "chai": ["chai@6.2.1", "", {}, "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg=="], - "chainsaw": ["chainsaw@0.1.0", "", { "dependencies": { "traverse": ">=0.3.0 <0.4" } }, "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ=="], - - "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], @@ -2129,15 +1983,13 @@ "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], - "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="], + "commander": ["commander@13.0.0", "", {}, "sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ=="], "common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="], - "compress-commons": ["compress-commons@6.0.2", "", { "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", "is-stream": "^2.0.1", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg=="], - "condense-newlines": ["condense-newlines@0.2.1", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-whitespace": "^0.3.0", "kind-of": "^3.0.2" } }, "sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg=="], - "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], + "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], "config-chain": ["config-chain@1.1.13", "", { "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" } }, "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ=="], @@ -2155,14 +2007,8 @@ "cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="], - "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], - "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], - "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="], - - "crc32-stream": ["crc32-stream@6.0.0", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" } }, "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g=="], - "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -2195,6 +2041,10 @@ "decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="], + "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], + + "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], "default-browser": ["default-browser@5.4.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg=="], @@ -2223,7 +2073,7 @@ "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="], - "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], @@ -2257,7 +2107,7 @@ "dot-prop": ["dot-prop@8.0.2", "", { "dependencies": { "type-fest": "^3.8.0" } }, "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ=="], - "dotenv": ["dotenv@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="], + "dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], "drizzle-kit": ["drizzle-kit@0.30.5", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0", "gel": "^2.0.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-l6dMSE100u7sDaTbLczibrQZjA35jLsHNqIV+jmhNVO3O8jzM6kywMOmV9uOz9ZVSCMPQhAZEFjL/qDPVrqpUA=="], @@ -2283,6 +2133,8 @@ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], + "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="], "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], @@ -2349,7 +2201,7 @@ "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], - "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + "events": ["events@1.1.1", "", {}, "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="], "events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="], @@ -2363,7 +2215,9 @@ "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], - "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], + "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], + + "expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="], "express": ["express@4.21.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA=="], @@ -2371,8 +2225,6 @@ "expressive-code": ["expressive-code@0.41.3", "", { "dependencies": { "@expressive-code/core": "^0.41.3", "@expressive-code/plugin-frames": "^0.41.3", "@expressive-code/plugin-shiki": "^0.41.3", "@expressive-code/plugin-text-markers": "^0.41.3" } }, "sha512-YLnD62jfgBZYrXIPQcJ0a51Afv9h8VlWqEGK9uU2T5nL/5rb8SnA86+7+mgCZe5D34Tff5RNEA5hjNVJYHzrFg=="], - "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], - "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], "extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="], @@ -2431,8 +2283,12 @@ "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], + "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], + "fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], + "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], @@ -2475,11 +2331,11 @@ "get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="], - "ghostty-web": ["ghostty-web@0.3.0", "", {}, "sha512-SAdSHWYF20GMZUB0n8kh1N6Z4ljMnuUqT8iTB2n5FAPswEV10MejEpLlhW/769GL5+BQa1NYwEg9y/XCckV5+A=="], - "gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="], - "giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="], + "giget": ["giget@1.2.5", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.5.4", "pathe": "^2.0.3", "tar": "^6.2.1" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug=="], + + "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="], "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], @@ -2507,7 +2363,7 @@ "h3": ["h3@2.0.1-rc.4", "", { "dependencies": { "rou3": "^0.7.8", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-vZq8pEUp6THsXKXrUXX44eOqfChic2wVQ1GlSzQCBr7DeFBkfIZAo2WyNND4GSv54TAa0E4LYIK73WSPdgKUgw=="], - "happy-dom": ["happy-dom@20.0.11", "", { "dependencies": { "@types/node": "^20.0.0", "@types/whatwg-mimetype": "^3.0.2", "whatwg-mimetype": "^3.0.0" } }, "sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g=="], + "handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="], "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], @@ -2569,9 +2425,9 @@ "hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="], - "hono": ["hono@4.10.7", "", {}, "sha512-icXIITfw/07Q88nLSkB9aiUrd8rYzSweK681Kjo/TSggaGbOX4RRyxxm71v+3PC8C/j+4rlxGeoTRxQDkaJkUw=="], + "hono": ["hono@4.7.10", "", {}, "sha512-QkACju9MiN59CKSY5JsGZCYmPZkA6sIW6OFCUp7qDjZu6S6KHtJHhAc9Uy9mV9F8PJ1/HQ3ybZF2yjCa/73fvQ=="], - "hono-openapi": ["hono-openapi@1.1.2", "", { "peerDependencies": { "@hono/standard-validator": "^0.2.0", "@standard-community/standard-json": "^0.3.5", "@standard-community/standard-openapi": "^0.2.9", "@types/json-schema": "^7.0.15", "hono": "^4.8.3", "openapi-types": "^12.1.3" }, "optionalPeers": ["@hono/standard-validator", "hono"] }, "sha512-toUcO60MftRBxqcVyxsHNYs2m4vf4xkQaiARAucQx3TiBPDtMNNkoh+C4I1vAretQZiGyaLOZNWn1YxfSyUA5g=="], + "hono-openapi": ["hono-openapi@1.1.1", "", { "peerDependencies": { "@hono/standard-validator": "^0.1.2", "@standard-community/standard-json": "^0.3.5", "@standard-community/standard-openapi": "^0.2.8", "@types/json-schema": "^7.0.15", "hono": "^4.8.3", "openapi-types": "^12.1.3" }, "optionalPeers": ["@hono/standard-validator", "hono"] }, "sha512-AC3HNhZYPHhnZdSy2Je7GDoTTNxPos6rKRQKVDBbSilY3cWJPqsxRnN6zA4pU7tfxmQEMTqkiLXbw6sAaemB8Q=="], "html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="], @@ -2593,8 +2449,6 @@ "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], - "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], - "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], "human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="], @@ -2679,8 +2533,6 @@ "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], - "is-in-ssh": ["is-in-ssh@1.0.0", "", {}, "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw=="], - "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], @@ -2775,8 +2627,6 @@ "jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], - "jwt-decode": ["jwt-decode@3.1.2", "", {}, "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="], - "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], @@ -2787,8 +2637,6 @@ "language-map": ["language-map@1.5.0", "", {}, "sha512-n7gFZpe+DwEAX9cXVTw43i3wiudWDDtSn28RmdnS/HCPr284dQI/SztsamWanRr75oSlKSaGbV2nmWCTzGCoVg=="], - "lazystream": ["lazystream@1.0.1", "", { "dependencies": { "readable-stream": "^2.0.5" } }, "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw=="], - "leac": ["leac@0.6.0", "", {}, "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="], "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], @@ -2853,8 +2701,6 @@ "lru.min": ["lru.min@1.1.3", "", {}, "sha512-Lkk/vx6ak3rYkRR0Nhu4lFUT2VDnQSxBe8Hbl7f36358p6ow8Bnvr8lrLt98H8J1aGxfhbX4Fs5tYg2+FTwr5Q=="], - "lru_map": ["lru_map@0.4.1", "", {}, "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg=="], - "luxon": ["luxon@3.6.1", "", {}, "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], @@ -3005,6 +2851,8 @@ "mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="], + "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + "miniflare": ["miniflare@4.20251118.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20251118.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-uLSAE/DvOm392fiaig4LOaatxLjM7xzIniFRG5Y3yF9IduOYLLK/pkCPQNCgKQH3ou0YJRHnTN+09LPfqYNTQQ=="], "minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="], @@ -3015,7 +2863,11 @@ "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="], - "mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], + "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="], + + "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], @@ -3031,8 +2883,12 @@ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + "neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="], "nf3": ["nf3@0.1.12", "", {}, "sha512-qbMXT7RTGh74MYWPeqTIED8nDW70NXOULVHpdWcdZ7IVHVnAsMV9fNugSNnvooipDc1FMOzpis7T9nXJEbJhvQ=="], @@ -3043,7 +2899,9 @@ "no-case": ["no-case@3.0.4", "", { "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg=="], - "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], + "node-abi": ["node-abi@3.85.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg=="], + + "node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="], "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], @@ -3069,7 +2927,7 @@ "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], - "nypm": ["nypm@0.6.2", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.2", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "tinyexec": "^1.0.1" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g=="], + "nypm": ["nypm@0.5.4", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "tinyexec": "^0.3.2", "ufo": "^1.5.4" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], @@ -3081,8 +2939,6 @@ "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], - "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], - "ofetch": ["ofetch@2.0.0-alpha.3", "", {}, "sha512-zpYTCs2byOuft65vI3z43Dd6iSdFbOZZLb9/d21aCpx2rGastVU9dOCv0lu4ykc1Ur1anAYjDi3SUvR0vq50JA=="], "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], @@ -3113,7 +2969,7 @@ "openid-client": ["openid-client@5.6.4", "", { "dependencies": { "jose": "^4.15.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" } }, "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA=="], - "opentui-spinner": ["opentui-spinner@0.0.6", "", { "dependencies": { "cli-spinners": "^3.3.0" }, "peerDependencies": { "@opentui/core": "^0.1.49", "@opentui/react": "^0.1.49", "@opentui/solid": "^0.1.49", "typescript": "^5" }, "optionalPeers": ["@opentui/react", "@opentui/solid"] }, "sha512-xupLOeVQEAXEvVJCvHkfX6fChDWmJIPHe5jyUrVb8+n4XVTX8mBNhitFfB9v2ZbkC1H2UwPab/ElePHoW37NcA=="], + "opentui-spinner": ["opentui-spinner@0.0.5", "", { "dependencies": { "cli-spinners": "^3.3.0" }, "peerDependencies": { "@opentui/core": "^0.1.49", "@opentui/react": "^0.1.49", "@opentui/solid": "^0.1.49", "typescript": "^5" }, "optionalPeers": ["@opentui/react", "@opentui/solid"] }, "sha512-abSWzWA7eyuD0PjerAWbBznLmOQn+8xRDaLGCVIs4ctETi2laNFr5KwicYnPXsHZpPc2neV7WtQm+diCEfOhLA=="], "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], @@ -3187,7 +3043,7 @@ "peek-readable": ["peek-readable@4.1.0", "", {}, "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg=="], - "perfect-debounce": ["perfect-debounce@2.0.0", "", {}, "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow=="], + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], "piccolore": ["piccolore@0.1.3", "", {}, "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw=="], @@ -3205,7 +3061,7 @@ "pkg-dir": ["pkg-dir@4.2.0", "", { "dependencies": { "find-up": "^4.0.0" } }, "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ=="], - "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], + "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], "pkg-up": ["pkg-up@3.1.0", "", { "dependencies": { "find-up": "^3.0.0" } }, "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA=="], @@ -3233,7 +3089,7 @@ "postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="], - "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], + "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], @@ -3243,8 +3099,6 @@ "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], - "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], - "promise.allsettled": ["promise.allsettled@1.0.7", "", { "dependencies": { "array.prototype.map": "^1.0.5", "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", "get-intrinsic": "^1.2.1", "iterate-value": "^1.0.2" } }, "sha512-hezvKvQQmsFkOdrZfYxUxkyxl8mgFQeT259Ajj9PXdbg9VzBCWrItOev72JyWxkCD5VSSqAeHmlN3tWx4DlmsA=="], "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], @@ -3257,6 +3111,8 @@ "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], + "punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="], "qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="], @@ -3273,6 +3129,8 @@ "raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="], + "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], + "rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="], "react": ["react@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="], @@ -3293,12 +3151,10 @@ "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], - "readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], "readable-web-to-node-stream": ["readable-web-to-node-stream@3.0.4", "", { "dependencies": { "readable-stream": "^4.7.0" } }, "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw=="], - "readdir-glob": ["readdir-glob@1.1.3", "", { "dependencies": { "minimatch": "^5.1.0" } }, "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA=="], - "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="], @@ -3431,7 +3287,7 @@ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], - "sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], + "sharp": ["sharp@0.32.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.2", "node-addon-api": "^6.1.0", "prebuild-install": "^7.1.1", "semver": "^7.5.4", "simple-get": "^4.0.1", "tar-fs": "^3.0.4", "tunnel-agent": "^0.6.0" } }, "sha512-0dap3iysgDkNaPOaOL4X/0akdu0ma62GcdC2NBQ+93eqpePdDdr2/LM0sFdDSMmN7yS+odyZtPsb7tx/cYBKnQ=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], @@ -3439,7 +3295,7 @@ "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="], - "shiki": ["shiki@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/engine-javascript": "3.20.0", "@shikijs/engine-oniguruma": "3.20.0", "@shikijs/langs": "3.20.0", "@shikijs/themes": "3.20.0", "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg=="], + "shiki": ["shiki@3.9.2", "", { "dependencies": { "@shikijs/core": "3.9.2", "@shikijs/engine-javascript": "3.9.2", "@shikijs/engine-oniguruma": "3.9.2", "@shikijs/langs": "3.9.2", "@shikijs/themes": "3.9.2", "@shikijs/types": "3.9.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-t6NKl5e/zGTvw/IyftLcumolgOczhuroqwXngDeMqJ3h3EQiTY/7wmfgPlsmloD8oYfqkEDqxiaH37Pjm1zUhQ=="], "shikiji": ["shikiji@0.6.13", "", { "dependencies": { "hast-util-to-html": "^9.0.0" } }, "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA=="], @@ -3455,6 +3311,10 @@ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="], + + "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="], + "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], "simple-xml-to-json": ["simple-xml-to-json@1.2.3", "", {}, "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA=="], @@ -3479,7 +3339,7 @@ "solid-use": ["solid-use@0.9.1", "", { "peerDependencies": { "solid-js": "^1.7" } }, "sha512-UwvXDVPlrrbj/9ewG9ys5uL2IO4jSiwys2KPzK4zsnAcmEl7iDafZWW1Mo4BSEWOmQCGK6IvpmGHo1aou8iOFw=="], - "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], @@ -3553,6 +3413,8 @@ "strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="], + "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], + "stripe": ["stripe@18.0.0", "", { "dependencies": { "@types/node": ">=8.1.0", "qs": "^6.11.0" } }, "sha512-3Fs33IzKUby//9kCkCa1uRpinAoTvj6rJgQ2jrBEysoxEvfsclvXdna1amyEYbA2EKkjynuB4+L/kleCCaWTpA=="], "strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="], @@ -3579,6 +3441,8 @@ "tar": ["tar@7.5.2", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg=="], + "tar-fs": ["tar-fs@3.1.1", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg=="], + "tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="], "terracotta": ["terracotta@1.0.6", "", { "dependencies": { "solid-use": "^0.9.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-yVrmT/Lg6a3tEbeYEJH8ksb1PYkR5FA9k5gr1TchaSNIiA2ZWs5a+koEbePXwlBP0poaV7xViZ/v50bQFcMgqw=="], @@ -3621,8 +3485,6 @@ "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - "traverse": ["traverse@0.3.9", "", {}, "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ=="], - "tree-sitter-bash": ["tree-sitter-bash@0.25.0", "", { "dependencies": { "node-addon-api": "^8.2.1", "node-gyp-build": "^4.8.2" }, "peerDependencies": { "tree-sitter": "^0.25.0" }, "optionalPeers": ["tree-sitter"] }, "sha512-gZtlj9+qFS81qKxpLfD6H0UssQ3QBc/F0nKkPsiFDyfQF2YBqYvglFJUzchrPpVhZe9kLZTrJ9n2J6lmka69Vg=="], "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], @@ -3639,6 +3501,8 @@ "tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="], + "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], + "turbo": ["turbo@2.5.6", "", { "optionalDependencies": { "turbo-darwin-64": "2.5.6", "turbo-darwin-arm64": "2.5.6", "turbo-linux-64": "2.5.6", "turbo-linux-arm64": "2.5.6", "turbo-windows-64": "2.5.6", "turbo-windows-arm64": "2.5.6" }, "bin": { "turbo": "bin/turbo" } }, "sha512-gxToHmi9oTBNB05UjUsrWf0OyN5ZXtD0apOarC1KIx232Vp3WimRNy3810QzeNSgyD5rsaIDXlxlbnOzlouo+w=="], "turbo-darwin-64": ["turbo-darwin-64@2.5.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-3C1xEdo4aFwMJAPvtlPqz1Sw/+cddWIOmsalHFMrsqqydcptwBfu26WW2cDm3u93bUzMbBJ8k3zNKFqxJ9ei2A=="], @@ -3673,6 +3537,8 @@ "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], + "uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="], + "ulid": ["ulid@3.0.1", "", { "bin": { "ulid": "dist/cli.js" } }, "sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q=="], "ultrahtml": ["ultrahtml@1.6.0", "", {}, "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw=="], @@ -3725,8 +3591,6 @@ "unstorage": ["unstorage@2.0.0-alpha.4", "", { "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "chokidar": "^4.0.3", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "lru-cache": "^11.2.2", "mongodb": "^6.20.0", "ofetch": "*", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "chokidar", "db0", "idb-keyval", "ioredis", "lru-cache", "mongodb", "ofetch", "uploadthing"] }, "sha512-ywXZMZRfrvmO1giJeMTCw6VUn0ALYxVl8pFqJPStiyQUvgJImejtAHrKvXPj4QGJAoS/iLGcVGF6ljN/lkh1bw=="], - "unzip-stream": ["unzip-stream@0.3.4", "", { "dependencies": { "binary": "^0.3.0", "mkdirp": "^0.5.1" } }, "sha512-PyofABPVv+d7fL7GOpusx7eRT9YETY2X04PhwbSipdj6bMxVCFJrr+nm0Mxqbf9hUiTin/UsnuFWBXlDZFy0Cw=="], - "update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], @@ -3767,7 +3631,7 @@ "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], - "vitest": ["vitest@4.0.16", "", { "dependencies": { "@vitest/expect": "4.0.16", "@vitest/mocker": "4.0.16", "@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.2.2", "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": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "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": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q=="], + "vitest": ["vitest@4.0.13", "", { "dependencies": { "@vitest/expect": "4.0.13", "@vitest/mocker": "4.0.13", "@vitest/pretty-format": "4.0.13", "@vitest/runner": "4.0.13", "@vitest/snapshot": "4.0.13", "@vitest/spy": "4.0.13", "@vitest/utils": "4.0.13", "debug": "^4.4.3", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/debug": "^4.1.12", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.13", "@vitest/browser-preview": "4.0.13", "@vitest/browser-webdriverio": "4.0.13", "@vitest/ui": "4.0.13", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/debug", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-QSD4I0fN6uZQfftryIXuqvqgBxTvJ3ZNkF6RWECd82YGAYAfhcppBLFXzXJHQAAhVFyYEuFTrq6h0hQqjB7jIQ=="], "vscode-jsonrpc": ["vscode-jsonrpc@8.2.1", "", {}, "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ=="], @@ -3781,8 +3645,6 @@ "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], - "whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], - "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], "which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="], @@ -3801,6 +3663,8 @@ "widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="], + "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], + "workerd": ["workerd@1.20251118.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20251118.0", "@cloudflare/workerd-darwin-arm64": "1.20251118.0", "@cloudflare/workerd-linux-64": "1.20251118.0", "@cloudflare/workerd-linux-arm64": "1.20251118.0", "@cloudflare/workerd-windows-64": "1.20251118.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-Om5ns0Lyx/LKtYI04IV0bjIrkBgoFNg0p6urzr2asekJlfP18RqFzyqMFZKf0i9Gnjtz/JfAS/Ol6tjCe5JJsQ=="], "wrangler": ["wrangler@4.50.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.11", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20251118.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20251118.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20251118.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-+nuZuHZxDdKmAyXOSrHlciGshCoAPiy5dM+t6mEohWm7HpXvTHmWQGUf/na9jjWlWJHCJYOWzkA1P5HBJqrIEA=="], @@ -3813,8 +3677,6 @@ "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], - "wsl-utils": ["wsl-utils@0.3.0", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-3sFIGLiaDP7rTO4xh3g+b3AzhYDIUGGywE/WsmqzJWDxus5aJXVnPTNC/6L+r2WzrwXqVOdD262OaO+cEyPMSQ=="], - "xdg-basedir": ["xdg-basedir@5.1.0", "", {}, "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ=="], "xml-parse-from-string": ["xml-parse-from-string@1.0.1", "", {}, "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g=="], @@ -3847,8 +3709,6 @@ "youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="], - "zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="], - "zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="], "zod-to-json-schema": ["zod-to-json-schema@3.24.5", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g=="], @@ -3857,16 +3717,16 @@ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], - "@actions/artifact/@actions/core": ["@actions/core@2.0.1", "", { "dependencies": { "@actions/exec": "^2.0.0", "@actions/http-client": "^3.0.0" } }, "sha512-oBfqT3GwkvLlo1fjvhQLQxuwZCGTarTE5OuZ2Wg10hvhBj7LRIlF611WT4aZS6fDhO5ZKlY7lCAZTlpmyaHaeg=="], - - "@actions/core/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], - - "@actions/github/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], + "@actions/github/@octokit/core": ["@octokit/core@5.2.2", "", { "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.1.0", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg=="], "@actions/github/@octokit/plugin-paginate-rest": ["@octokit/plugin-paginate-rest@9.2.2", "", { "dependencies": { "@octokit/types": "^12.6.0" }, "peerDependencies": { "@octokit/core": "5" } }, "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ=="], "@actions/github/@octokit/plugin-rest-endpoint-methods": ["@octokit/plugin-rest-endpoint-methods@10.4.1", "", { "dependencies": { "@octokit/types": "^12.6.0" }, "peerDependencies": { "@octokit/core": "5" } }, "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg=="], + "@actions/github/@octokit/request": ["@octokit/request@8.4.1", "", { "dependencies": { "@octokit/endpoint": "^9.0.6", "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" } }, "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw=="], + + "@actions/github/@octokit/request-error": ["@octokit/request-error@5.1.1", "", { "dependencies": { "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" } }, "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g=="], + "@actions/github/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], "@actions/http-client/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], @@ -3877,46 +3737,20 @@ "@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], - "@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-BoQZtGcBxkeSH1zK+SRYNDtJPIPpacTeiMZqnG4Rv6xXjEwM0FH4MGs9c+PlhyEWmQCzjRM2HAotEydFhD4dYw=="], - "@ai-sdk/azure/@ai-sdk/openai": ["@ai-sdk/openai@2.0.71", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tg+gj+R0z/On9P4V7hy7/7o04cQPjKGayMCL3gzWD/aNGjAKkhEnaocuNDidSnghizt8g2zJn16cAuAolnW+qQ=="], "@ai-sdk/azure/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], - "@ai-sdk/cerebras/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.29", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cZUppWzxjfpNaH1oVZ6U8yDLKKsdGbC9X0Pex8cG9CXhKWSoVLLnW1rKr6tu9jDISK5okjBIW/O1ZzfnbUrtEw=="], + "@ai-sdk/gateway/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], - "@ai-sdk/cerebras/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], + "@ai-sdk/google/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], - "@ai-sdk/cohere/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], + "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.45", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Ipv62vavDCmrV/oE/lXehL9FzwQuZOnnlhPEftWizx464Wb6lvnBTJx8uhmEYruFSzOWTI95Z33ncZ4tA8E6RQ=="], - "@ai-sdk/deepinfra/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.29", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cZUppWzxjfpNaH1oVZ6U8yDLKKsdGbC9X0Pex8cG9CXhKWSoVLLnW1rKr6tu9jDISK5okjBIW/O1ZzfnbUrtEw=="], - - "@ai-sdk/deepinfra/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], - - "@ai-sdk/gateway/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], - - "@ai-sdk/google-vertex/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.50", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.18" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-21PaHfoLmouOXXNINTsZJsMw+wE5oLR2He/1kq/sKokTVKyq7ObGT1LDk6ahwxaz/GoaNaGankMh+EgVcdv2Cw=="], - - "@ai-sdk/groq/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], + "@ai-sdk/google-vertex/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], "@ai-sdk/mcp/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], - "@ai-sdk/mistral/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], - - "@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-BoQZtGcBxkeSH1zK+SRYNDtJPIPpacTeiMZqnG4Rv6xXjEwM0FH4MGs9c+PlhyEWmQCzjRM2HAotEydFhD4dYw=="], - - "@ai-sdk/openai-compatible/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.0", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.3", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.25.76 || ^4" } }, "sha512-BoQZtGcBxkeSH1zK+SRYNDtJPIPpacTeiMZqnG4Rv6xXjEwM0FH4MGs9c+PlhyEWmQCzjRM2HAotEydFhD4dYw=="], - - "@ai-sdk/perplexity/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], - - "@ai-sdk/togetherai/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.29", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cZUppWzxjfpNaH1oVZ6U8yDLKKsdGbC9X0Pex8cG9CXhKWSoVLLnW1rKr6tu9jDISK5okjBIW/O1ZzfnbUrtEw=="], - - "@ai-sdk/togetherai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], - - "@ai-sdk/xai/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@1.0.29", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cZUppWzxjfpNaH1oVZ6U8yDLKKsdGbC9X0Pex8cG9CXhKWSoVLLnW1rKr6tu9jDISK5okjBIW/O1ZzfnbUrtEw=="], - - "@ai-sdk/xai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="], - "@astrojs/cloudflare/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], "@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], @@ -3925,6 +3759,8 @@ "@astrojs/mdx/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.9", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.5", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.13.0", "smol-toml": "^1.4.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.2", "vfile": "^6.0.3" } }, "sha512-hX2cLC/KW74Io1zIbn92kI482j9J7LleBLGCVU9EP3BeH5MVrnFawOnqD0t/q6D1Z+ZNeQG2gNKMslCcO36wng=="], + "@astrojs/mdx/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "@astrojs/sitemap/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "@astrojs/solid-js/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], @@ -3961,16 +3797,6 @@ "@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], - "@azure/core-http/@azure/abort-controller": ["@azure/abort-controller@1.1.0", "", { "dependencies": { "tslib": "^2.2.0" } }, "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw=="], - - "@azure/core-http/@azure/core-tracing": ["@azure/core-tracing@1.0.0-preview.13", "", { "dependencies": { "@opentelemetry/api": "^1.0.1", "tslib": "^2.2.0" } }, "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ=="], - - "@azure/core-http/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - - "@azure/core-http/xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="], - - "@azure/core-xml/fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], @@ -3979,20 +3805,12 @@ "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "@bufbuild/protoplugin/typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="], - "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], - "@dot/log/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], "@expressive-code/plugin-shiki/shiki": ["shiki@3.15.0", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/engine-javascript": "3.15.0", "@shikijs/engine-oniguruma": "3.15.0", "@shikijs/langs": "3.15.0", "@shikijs/themes": "3.15.0", "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw=="], - "@hey-api/json-schema-ref-parser/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - - "@hey-api/openapi-ts/open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], - "@hono/zod-validator/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -4031,8 +3849,6 @@ "@jimp/types/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@jsx-email/cli/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "@jsx-email/cli/esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], "@jsx-email/cli/tailwindcss": ["tailwindcss@3.3.3", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.18.2", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", "postcss": "^8.4.23", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.1", "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", "resolve": "^1.22.2", "sucrase": "^3.32.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w=="], @@ -4041,108 +3857,72 @@ "@jsx-email/doiuse-email/htmlparser2": ["htmlparser2@9.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ=="], + "@mdx-js/mdx/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "@modelcontextprotocol/sdk/express": ["express@5.1.0", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="], "@modelcontextprotocol/sdk/raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], "@modelcontextprotocol/sdk/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@octokit/auth-app/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - - "@octokit/auth-app/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - - "@octokit/auth-oauth-app/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - "@octokit/auth-oauth-app/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - "@octokit/auth-oauth-device/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - "@octokit/auth-oauth-device/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - "@octokit/auth-oauth-user/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - "@octokit/auth-oauth-user/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - "@octokit/core/@octokit/graphql": ["@octokit/graphql@7.1.1", "", { "dependencies": { "@octokit/request": "^8.4.1", "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" } }, "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g=="], + "@octokit/core/@octokit/graphql": ["@octokit/graphql@9.0.3", "", { "dependencies": { "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA=="], - "@octokit/core/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], + "@octokit/core/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - "@octokit/core/universal-user-agent": ["universal-user-agent@6.0.1", "", {}, "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="], - - "@octokit/endpoint/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], - - "@octokit/endpoint/universal-user-agent": ["universal-user-agent@6.0.1", "", {}, "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="], - - "@octokit/graphql/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], + "@octokit/endpoint/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], "@octokit/graphql/@octokit/types": ["@octokit/types@15.0.2", "", { "dependencies": { "@octokit/openapi-types": "^26.0.0" } }, "sha512-rR+5VRjhYSer7sC51krfCctQhVTmjyUMAaShfPB8mscVa8tSoLyon3coxQmXu0ahJoLVWl8dSGD/3OGZlFV44Q=="], - "@octokit/oauth-methods/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - - "@octokit/oauth-methods/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - "@octokit/oauth-methods/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - "@octokit/plugin-paginate-rest/@octokit/core": ["@octokit/core@7.0.6", "", { "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", "@octokit/request": "^10.0.6", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "before-after-hook": "^4.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q=="], - "@octokit/plugin-paginate-rest/@octokit/types": ["@octokit/types@15.0.2", "", { "dependencies": { "@octokit/openapi-types": "^26.0.0" } }, "sha512-rR+5VRjhYSer7sC51krfCctQhVTmjyUMAaShfPB8mscVa8tSoLyon3coxQmXu0ahJoLVWl8dSGD/3OGZlFV44Q=="], - "@octokit/plugin-rest-endpoint-methods/@octokit/core": ["@octokit/core@7.0.6", "", { "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", "@octokit/request": "^10.0.6", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "before-after-hook": "^4.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q=="], - "@octokit/plugin-rest-endpoint-methods/@octokit/types": ["@octokit/types@15.0.2", "", { "dependencies": { "@octokit/openapi-types": "^26.0.0" } }, "sha512-rR+5VRjhYSer7sC51krfCctQhVTmjyUMAaShfPB8mscVa8tSoLyon3coxQmXu0ahJoLVWl8dSGD/3OGZlFV44Q=="], - "@octokit/plugin-retry/@octokit/types": ["@octokit/types@6.41.0", "", { "dependencies": { "@octokit/openapi-types": "^12.11.0" } }, "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg=="], + "@octokit/request/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - "@octokit/request/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], - - "@octokit/request/universal-user-agent": ["universal-user-agent@6.0.1", "", {}, "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="], - - "@octokit/request-error/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], - - "@octokit/rest/@octokit/core": ["@octokit/core@7.0.6", "", { "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", "@octokit/request": "^10.0.6", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "before-after-hook": "^4.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q=="], - - "@octokit/rest/@octokit/plugin-request-log": ["@octokit/plugin-request-log@6.0.0", "", { "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q=="], + "@octokit/request-error/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], "@openauthjs/openauth/@standard-schema/spec": ["@standard-schema/spec@1.0.0-beta.3", "", {}, "sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw=="], "@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="], - "@opencode-ai/desktop/@actions/artifact": ["@actions/artifact@4.0.0", "", { "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^6.0.1", "@actions/http-client": "^2.1.0", "@azure/core-http": "^3.0.5", "@azure/storage-blob": "^12.15.0", "@octokit/core": "^5.2.1", "@octokit/plugin-request-log": "^1.0.4", "@octokit/plugin-retry": "^3.0.9", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@protobuf-ts/plugin": "^2.2.3-alpha.1", "archiver": "^7.0.1", "jwt-decode": "^3.1.2", "unzip-stream": "^0.3.1" } }, "sha512-HCc2jMJRAfviGFAh0FsOR/jNfWhirxl7W6z8zDtttt0GltwxBLdEIjLiweOPFl9WbyJRW1VWnPUSAixJqcWUMQ=="], + "@opencode-ai/tauri/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], - "@opencode-ai/desktop/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], + "@opencode-ai/tauri/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], "@opencode-ai/web/@shikijs/transformers": ["@shikijs/transformers@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/types": "3.4.2" } }, "sha512-I5baLVi/ynLEOZoWSAMlACHNnG+yw5HDmse0oe+GW6U1u+ULdEB3UHiVWaHoJSSONV7tlcVxuaMy74sREDkSvg=="], "@opencode-ai/web/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], + "@opencode-ai/web/shiki": ["shiki@3.4.2", "", { "dependencies": { "@shikijs/core": "3.4.2", "@shikijs/engine-javascript": "3.4.2", "@shikijs/engine-oniguruma": "3.4.2", "@shikijs/langs": "3.4.2", "@shikijs/themes": "3.4.2", "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-wuxzZzQG8kvZndD7nustrNFIKYJ1jJoWIPaBpVe2+KHSvtzMi4SBjOxrigs8qeqce/l3U0cwiC+VAkLKSunHQQ=="], + "@opentui/solid/@babel/core": ["@babel/core@7.28.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.6", "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.0", "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ=="], "@opentui/solid/babel-preset-solid": ["babel-preset-solid@1.9.9", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.1" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.8" }, "optionalPeers": ["solid-js"] }, "sha512-pCnxWrciluXCeli/dj5PIEHgbNzim3evtTn12snjqqg8QZWJNMjH1AWIp4iG/tbVjqQ72aBEymMSagvmgxubXw=="], "@oslojs/jwt/@oslojs/encoding": ["@oslojs/encoding@0.4.1", "", {}, "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q=="], - "@pierre/diffs/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], + "@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], - "@pierre/diffs/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-ZfWJNm2VMhKkQIKT9qXbs76RRcT0SF/CAvEz0+RkpUDAoDaCx0uFdCGzSRiD9gSlhm6AHkjdieOBJMaO2eC1rQ=="], + "@parcel/watcher/node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], - "@pierre/diffs/@shikijs/transformers": ["@shikijs/transformers@3.19.0", "", { "dependencies": { "@shikijs/core": "3.19.0", "@shikijs/types": "3.19.0" } }, "sha512-e6vwrsyw+wx4OkcrDbL+FVCxwx8jgKiCoXzakVur++mIWVcgpzIi8vxf4/b4dVTYrV/nUx5RjinMf4tq8YV8Fw=="], + "@pierre/precision-diffs/@shikijs/core": ["@shikijs/core@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg=="], - "@pierre/diffs/shiki": ["shiki@3.19.0", "", { "dependencies": { "@shikijs/core": "3.19.0", "@shikijs/engine-javascript": "3.19.0", "@shikijs/engine-oniguruma": "3.19.0", "@shikijs/langs": "3.19.0", "@shikijs/themes": "3.19.0", "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-77VJr3OR/VUZzPiStyRhADmO2jApMM0V2b1qf0RpfWya8Zr1PeZev5AEpPGAAKWdiYUtcZGBE4F5QvJml1PvWA=="], + "@pierre/precision-diffs/@shikijs/transformers": ["@shikijs/transformers@3.15.0", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/types": "3.15.0" } }, "sha512-Hmwip5ovvSkg+Kc41JTvSHHVfCYF+C8Cp1omb5AJj4Xvd+y9IXz2rKJwmFRGsuN0vpHxywcXJ1+Y4B9S7EG1/A=="], + + "@pierre/precision-diffs/shiki": ["shiki@3.15.0", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/engine-javascript": "3.15.0", "@shikijs/engine-oniguruma": "3.15.0", "@shikijs/langs": "3.15.0", "@shikijs/themes": "3.15.0", "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw=="], "@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], - "@protobuf-ts/plugin/typescript": ["typescript@3.9.10", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q=="], - "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], - "@shikijs/engine-javascript/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - - "@shikijs/engine-oniguruma/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - - "@shikijs/langs/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - - "@shikijs/themes/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - "@slack/bolt/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], "@slack/oauth/@slack/logger": ["@slack/logger@3.0.0", "", { "dependencies": { "@types/node": ">=12.0.0" } }, "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA=="], @@ -4167,8 +3947,6 @@ "@solidjs/start/vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "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" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], - "@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="], @@ -4183,22 +3961,18 @@ "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "ai/@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.12", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W+cB1sOWvPcz9qiIsNtD+HxUrBUva2vWv2K1EFukuImX+HA0uZx3EyyOjhYQ9gtf/teqEG80M6OvJ7xx/VLV2A=="], - "ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "archiver-utils/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - - "archiver-utils/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], - "astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], "astro/diff": ["diff@5.2.0", "", {}, "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A=="], + "astro/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], + "astro/shiki": ["shiki@3.15.0", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/engine-javascript": "3.15.0", "@shikijs/engine-oniguruma": "3.15.0", "@shikijs/langs": "3.15.0", "@shikijs/themes": "3.15.0", "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw=="], "astro/unstorage": ["unstorage@1.17.3", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^4.0.3", "destr": "^2.0.5", "h3": "^1.15.4", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.1" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q=="], @@ -4207,21 +3981,23 @@ "astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "aws-sdk/events": ["events@1.1.1", "", {}, "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="], - "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], "babel-plugin-module-resolver/glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], + "bl/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "body-parser/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "body-parser/qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="], - "clean-css/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + "boxen/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - "compress-commons/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + "c12/ohash": ["ohash@1.1.6", "", {}, "sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg=="], + + "c12/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], "condense-newlines/kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="], @@ -4237,10 +4013,10 @@ "es-get-iterator/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], - "esbuild-plugin-copy/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "esbuild-plugin-copy/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + "estree-util-to-js/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "execa/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="], "express/cookie": ["cookie@0.7.1", "", {}, "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w=="], @@ -4255,10 +4031,14 @@ "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "gaxios/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], "gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + "giget/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + "glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], "globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], @@ -4273,10 +4053,6 @@ "jsonwebtoken/jws": ["jws@3.2.2", "", { "dependencies": { "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } }, "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA=="], - "lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], - - "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "md-to-react-email/marked": ["marked@7.0.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ=="], "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -4285,6 +4061,8 @@ "miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + "miniflare/sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], + "miniflare/undici": ["undici@7.14.0", "", {}, "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ=="], "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], @@ -4295,9 +4073,7 @@ "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], - "nypm/tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], - - "opencode/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.50", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.18" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-21PaHfoLmouOXXNINTsZJsMw+wE5oLR2He/1kq/sKokTVKyq7ObGT1LDk6ahwxaz/GoaNaGankMh+EgVcdv2Cw=="], + "opencode/@ai-sdk/anthropic": ["@ai-sdk/anthropic@2.0.45", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Ipv62vavDCmrV/oE/lXehL9FzwQuZOnnlhPEftWizx464Wb6lvnBTJx8uhmEYruFSzOWTI95Z33ncZ4tA8E6RQ=="], "opencode/@ai-sdk/openai": ["@ai-sdk/openai@2.0.71", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.17" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tg+gj+R0z/On9P4V7hy7/7o04cQPjKGayMCL3gzWD/aNGjAKkhEnaocuNDidSnghizt8g2zJn16cAuAolnW+qQ=="], @@ -4331,13 +4107,13 @@ "postcss-load-config/lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + "prebuild-install/tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="], + "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], "raw-body/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], - "readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], - - "readdir-glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + "readable-web-to-node-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], "router/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], @@ -4351,16 +4127,8 @@ "send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - "sharp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - - "shiki/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], - - "shiki/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - "sitemap/sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], - "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - "sst/aws4fetch": ["aws4fetch@1.0.18", "", {}, "sha512-3Cf+YaUl07p24MoQ46rFwulAmiyCwH2+1zw1ZyPAX5OtJ34Hh185DwB8y/qRLb6cYYYtSFJ9pthyLc0MD4e8sQ=="], "sst/jose": ["jose@5.2.3", "", {}, "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA=="], @@ -4393,7 +4161,7 @@ "utif2/pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], - "vitest/tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], + "vite-plugin-icons-spritesheet/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], "vitest/vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "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" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], @@ -4415,14 +4183,28 @@ "zod-to-ts/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@actions/artifact/@actions/core/@actions/exec": ["@actions/exec@2.0.0", "", { "dependencies": { "@actions/io": "^2.0.0" } }, "sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw=="], + "@actions/github/@octokit/core/@octokit/auth-token": ["@octokit/auth-token@4.0.0", "", {}, "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA=="], - "@actions/core/@actions/http-client/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], + "@actions/github/@octokit/core/@octokit/graphql": ["@octokit/graphql@7.1.1", "", { "dependencies": { "@octokit/request": "^8.4.1", "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" } }, "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g=="], + + "@actions/github/@octokit/core/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], + + "@actions/github/@octokit/core/before-after-hook": ["before-after-hook@2.2.3", "", {}, "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="], + + "@actions/github/@octokit/core/universal-user-agent": ["universal-user-agent@6.0.1", "", {}, "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="], "@actions/github/@octokit/plugin-paginate-rest/@octokit/types": ["@octokit/types@12.6.0", "", { "dependencies": { "@octokit/openapi-types": "^20.0.0" } }, "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw=="], "@actions/github/@octokit/plugin-rest-endpoint-methods/@octokit/types": ["@octokit/types@12.6.0", "", { "dependencies": { "@octokit/openapi-types": "^20.0.0" } }, "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw=="], + "@actions/github/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@9.0.6", "", { "dependencies": { "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" } }, "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw=="], + + "@actions/github/@octokit/request/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], + + "@actions/github/@octokit/request/universal-user-agent": ["universal-user-agent@6.0.1", "", {}, "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="], + + "@actions/github/@octokit/request-error/@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], + "@astrojs/markdown-remark/shiki/@shikijs/core": ["@shikijs/core@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg=="], "@astrojs/markdown-remark/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg=="], @@ -4461,10 +4243,6 @@ "@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.1.1", "", {}, "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw=="], - "@azure/core-http/xml2js/sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], - - "@azure/core-xml/fast-xml-parser/strnum": ["strnum@2.1.1", "", {}, "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw=="], - "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], @@ -4613,117 +4391,59 @@ "@modelcontextprotocol/sdk/raw-body/http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], - "@octokit/auth-app/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - - "@octokit/auth-app/@octokit/request/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - - "@octokit/auth-app/@octokit/request-error/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - - "@octokit/auth-oauth-app/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - - "@octokit/auth-oauth-app/@octokit/request/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - "@octokit/auth-oauth-app/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "@octokit/auth-oauth-device/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - - "@octokit/auth-oauth-device/@octokit/request/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - "@octokit/auth-oauth-device/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "@octokit/auth-oauth-user/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - - "@octokit/auth-oauth-user/@octokit/request/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - "@octokit/auth-oauth-user/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], + "@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "@octokit/endpoint/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], - - "@octokit/graphql/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - - "@octokit/graphql/@octokit/request/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - - "@octokit/graphql/@octokit/request/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], + "@octokit/endpoint/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], "@octokit/graphql/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@26.0.0", "", {}, "sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA=="], - "@octokit/oauth-methods/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - "@octokit/oauth-methods/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "@octokit/plugin-paginate-rest/@octokit/core/@octokit/auth-token": ["@octokit/auth-token@6.0.0", "", {}, "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w=="], - - "@octokit/plugin-paginate-rest/@octokit/core/@octokit/graphql": ["@octokit/graphql@9.0.3", "", { "dependencies": { "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA=="], - - "@octokit/plugin-paginate-rest/@octokit/core/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - - "@octokit/plugin-paginate-rest/@octokit/core/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - - "@octokit/plugin-paginate-rest/@octokit/core/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - - "@octokit/plugin-paginate-rest/@octokit/core/before-after-hook": ["before-after-hook@4.0.0", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="], - "@octokit/plugin-paginate-rest/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@26.0.0", "", {}, "sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA=="], - "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/auth-token": ["@octokit/auth-token@6.0.0", "", {}, "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w=="], - - "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/graphql": ["@octokit/graphql@9.0.3", "", { "dependencies": { "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA=="], - - "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - - "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - - "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - - "@octokit/plugin-rest-endpoint-methods/@octokit/core/before-after-hook": ["before-after-hook@4.0.0", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="], - "@octokit/plugin-rest-endpoint-methods/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@26.0.0", "", {}, "sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA=="], - "@octokit/plugin-retry/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@12.11.0", "", {}, "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ=="], + "@octokit/request-error/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - "@octokit/request-error/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], - - "@octokit/request/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], - - "@octokit/rest/@octokit/core/@octokit/auth-token": ["@octokit/auth-token@6.0.0", "", {}, "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w=="], - - "@octokit/rest/@octokit/core/@octokit/graphql": ["@octokit/graphql@9.0.3", "", { "dependencies": { "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA=="], - - "@octokit/rest/@octokit/core/@octokit/request": ["@octokit/request@10.0.7", "", { "dependencies": { "@octokit/endpoint": "^11.0.2", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA=="], - - "@octokit/rest/@octokit/core/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - - "@octokit/rest/@octokit/core/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - - "@octokit/rest/@octokit/core/before-after-hook": ["before-after-hook@4.0.0", "", {}, "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ=="], - - "@opencode-ai/desktop/@actions/artifact/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], + "@octokit/request/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], "@opencode-ai/web/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-AG8vnSi1W2pbgR2B911EfGqtLE9c4hQBYkv/x7Z+Kt0VxhgQKcW7UNDVYsu9YxwV6u+OJrvdJrMq6DNWoBjihQ=="], "@opencode-ai/web/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.4.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zHC1l7L+eQlDXLnxvM9R91Efh2V4+rN3oMVS2swCBssbj2U/FBwybD1eeLaq8yl/iwT+zih8iUbTBCgGZOYlVg=="], + "@opencode-ai/web/shiki/@shikijs/core": ["@shikijs/core@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-AG8vnSi1W2pbgR2B911EfGqtLE9c4hQBYkv/x7Z+Kt0VxhgQKcW7UNDVYsu9YxwV6u+OJrvdJrMq6DNWoBjihQ=="], + + "@opencode-ai/web/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-1/adJbSMBOkpScCE/SB6XkjJU17ANln3Wky7lOmrnpl+zBdQ1qXUJg2GXTYVHRq+2j3hd1DesmElTXYDgtfSOQ=="], + + "@opencode-ai/web/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-zcZKMnNndgRa3ORja6Iemsr3DrLtkX3cAF7lTJkdMB6v9alhlBsX9uNiCpqofNrXOvpA3h6lHcLJxgCIhVOU5Q=="], + + "@opencode-ai/web/shiki/@shikijs/langs": ["@shikijs/langs@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2" } }, "sha512-H6azIAM+OXD98yztIfs/KH5H4PU39t+SREhmM8LaNXyUrqj2mx+zVkr8MWYqjceSjDw9I1jawm1WdFqU806rMA=="], + + "@opencode-ai/web/shiki/@shikijs/themes": ["@shikijs/themes@3.4.2", "", { "dependencies": { "@shikijs/types": "3.4.2" } }, "sha512-qAEuAQh+brd8Jyej2UDDf+b4V2g1Rm8aBIdvt32XhDPrHvDkEnpb7Kzc9hSuHUxz0Iuflmq7elaDuQAP9bHIhg=="], + + "@opencode-ai/web/shiki/@shikijs/types": ["@shikijs/types@3.4.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zHC1l7L+eQlDXLnxvM9R91Efh2V4+rN3oMVS2swCBssbj2U/FBwybD1eeLaq8yl/iwT+zih8iUbTBCgGZOYlVg=="], + "@opentui/solid/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "@pierre/diffs/@shikijs/core/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], + "@pierre/precision-diffs/@shikijs/core/@shikijs/types": ["@shikijs/types@3.15.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw=="], - "@pierre/diffs/@shikijs/engine-javascript/@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="], + "@pierre/precision-diffs/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.15.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw=="], - "@pierre/diffs/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-L7SrRibU7ZoYi1/TrZsJOFAnnHyLTE1SwHG1yNWjZIVCqjOEmCSuK2ZO9thnRbJG6TOkPp+Z963JmpCNw5nzvA=="], + "@pierre/precision-diffs/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg=="], - "@pierre/diffs/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="], + "@pierre/precision-diffs/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA=="], - "@pierre/diffs/shiki/@shikijs/core": ["@shikijs/core@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-L7SrRibU7ZoYi1/TrZsJOFAnnHyLTE1SwHG1yNWjZIVCqjOEmCSuK2ZO9thnRbJG6TOkPp+Z963JmpCNw5nzvA=="], + "@pierre/precision-diffs/shiki/@shikijs/langs": ["@shikijs/langs@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A=="], - "@pierre/diffs/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1hRxtYIJfJSZeM5ivbUXv9hcJP3PWRo5prG/V2sWwiubUKTa+7P62d2qxCW8jiVFX4pgRHhnHNp+qeR7Xl+6kg=="], + "@pierre/precision-diffs/shiki/@shikijs/themes": ["@shikijs/themes@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ=="], - "@pierre/diffs/shiki/@shikijs/langs": ["@shikijs/langs@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0" } }, "sha512-dBMFzzg1QiXqCVQ5ONc0z2ebyoi5BKz+MtfByLm0o5/nbUu3Iz8uaTCa5uzGiscQKm7lVShfZHU1+OG3t5hgwg=="], - - "@pierre/diffs/shiki/@shikijs/themes": ["@shikijs/themes@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0" } }, "sha512-H36qw+oh91Y0s6OlFfdSuQ0Ld+5CgB/VE6gNPK+Hk4VRbVG/XQgkjnt4KzfnnoO6tZPtKJKHPjwebOCfjd6F8A=="], - - "@pierre/diffs/shiki/@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="], + "@pierre/precision-diffs/shiki/@shikijs/types": ["@shikijs/types@3.15.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw=="], "@slack/web-api/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], @@ -4801,12 +4521,6 @@ "ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "archiver-utils/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - - "archiver-utils/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "archiver-utils/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "astro/shiki/@shikijs/core": ["@shikijs/core@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg=="], "astro/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg=="], @@ -4889,6 +4603,12 @@ "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + "giget/tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + + "giget/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "giget/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + "gray-matter/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], "js-beautify/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], @@ -4899,9 +4619,7 @@ "jsonwebtoken/jws/jwa": ["jwa@1.4.2", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw=="], - "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - - "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + "opencode/@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], "opencode/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw=="], @@ -4921,7 +4639,13 @@ "pkg-up/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], - "readable-stream/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + "prebuild-install/tar-fs/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="], + + "prebuild-install/tar-fs/tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], + + "readable-web-to-node-stream/readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + + "readable-web-to-node-stream/readable-stream/events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], @@ -4945,12 +4669,16 @@ "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "@actions/artifact/@actions/core/@actions/exec/@actions/io": ["@actions/io@2.0.0", "", {}, "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg=="], + "@actions/github/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], "@actions/github/@octokit/plugin-paginate-rest/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@20.0.0", "", {}, "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="], "@actions/github/@octokit/plugin-rest-endpoint-methods/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@20.0.0", "", {}, "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="], + "@actions/github/@octokit/request-error/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], + + "@actions/github/@octokit/request/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], + "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/core": ["@shikijs/core@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg=="], "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg=="], @@ -5033,34 +4761,12 @@ "@modelcontextprotocol/sdk/raw-body/http-errors/statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], - "@octokit/auth-app/@octokit/request-error/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - - "@octokit/auth-app/@octokit/request/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - - "@octokit/graphql/@octokit/request/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - - "@octokit/plugin-paginate-rest/@octokit/core/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - - "@octokit/plugin-paginate-rest/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - - "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - - "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - - "@octokit/rest/@octokit/core/@octokit/request/@octokit/endpoint": ["@octokit/endpoint@11.0.2", "", { "dependencies": { "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ=="], - - "@octokit/rest/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], - - "@opencode-ai/desktop/@actions/artifact/@actions/http-client/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], - "@slack/web-api/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es": ["oniguruma-to-es@2.3.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^5.1.1", "regex-recursion": "^5.1.1" } }, "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g=="], "ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "archiver-utils/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "astro/unstorage/h3/cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="], "astro/unstorage/h3/crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="], @@ -5071,6 +4777,8 @@ "esbuild-plugin-copy/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "giget/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "js-beautify/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "opencontrol/@modelcontextprotocol/sdk/express/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], @@ -5105,6 +4813,8 @@ "pkg-up/find-up/locate-path/path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], + "readable-web-to-node-stream/readable-stream/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + "tw-to-css/tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "tw-to-css/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], diff --git a/flake.lock b/flake.lock index 6beb162c7..b0749bea4 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1766314097, - "narHash": "sha256-laJftWbghBehazn/zxVJ8NdENVgjccsWAdAqKXhErrM=", + "lastModified": 1764138170, + "narHash": "sha256-2bCmfCUZyi2yj9FFXYKwsDiaZmizN75cLhI/eWmf3tk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "306ea70f9eb0fb4e040f8540e2deab32ed7e2055", + "rev": "bb813de6d2241bcb1b5af2d3059f560c66329967", "type": "github" }, "original": { diff --git a/github/README.md b/github/README.md index e35860340..36342b409 100644 --- a/github/README.md +++ b/github/README.md @@ -6,7 +6,7 @@ Mention `/opencode` in your comment, and opencode will execute tasks within your ## Features -#### Explain an issue +#### Explain an issues Leave the following comment on a GitHub issue. `opencode` will read the entire thread, including all comments, and reply with a clear explanation. @@ -14,7 +14,7 @@ Leave the following comment on a GitHub issue. `opencode` will read the entire t /opencode explain this issue ``` -#### Fix an issue +#### Fix an issues Leave the following comment on a GitHub issue. opencode will create a new branch, implement the changes, and open a PR with the changes. diff --git a/github/action.yml b/github/action.yml index 57e26d856..0b7367ded 100644 --- a/github/action.yml +++ b/github/action.yml @@ -9,66 +9,21 @@ inputs: description: "Model to use" required: true - agent: - description: "Agent to use. Must be a primary agent. Falls back to default_agent from config or 'build' if not found." - required: false - share: description: "Share the opencode session (defaults to true for public repos)" required: false - prompt: - description: "Custom prompt to override the default prompt" - required: false - - use_github_token: - description: "Use GITHUB_TOKEN directly instead of OpenCode App token exchange. When true, skips OIDC and uses the GITHUB_TOKEN env var." - required: false - default: "false" - - mentions: - description: "Comma-separated list of trigger phrases (case-insensitive). Defaults to '/opencode,/oc'" - required: false - - oidc_base_url: - description: "Base URL for OIDC token exchange API. Only required when running a custom GitHub App install. Defaults to https://api.opencode.ai" - required: false - runs: using: "composite" steps: - - name: Get opencode version - id: version - shell: bash - run: | - VERSION=$(curl -sf https://api.github.com/repos/sst/opencode/releases/latest | grep -o '"tag_name": *"[^"]*"' | cut -d'"' -f4) - echo "version=${VERSION:-latest}" >> $GITHUB_OUTPUT - - - name: Cache opencode - id: cache - uses: actions/cache@v4 - with: - path: ~/.opencode/bin - key: opencode-${{ runner.os }}-${{ runner.arch }}-${{ steps.version.outputs.version }} - - name: Install opencode - if: steps.cache.outputs.cache-hit != 'true' shell: bash run: curl -fsSL https://opencode.ai/install | bash - - name: Add opencode to PATH - shell: bash - run: echo "$HOME/.opencode/bin" >> $GITHUB_PATH - - name: Run opencode shell: bash id: run_opencode run: opencode github run env: MODEL: ${{ inputs.model }} - AGENT: ${{ inputs.agent }} SHARE: ${{ inputs.share }} - PROMPT: ${{ inputs.prompt }} - USE_GITHUB_TOKEN: ${{ inputs.use_github_token }} - MENTIONS: ${{ inputs.mentions }} - OIDC_BASE_URL: ${{ inputs.oidc_base_url }} diff --git a/github/index.ts b/github/index.ts index 2dcf6e754..6d826326e 100644 --- a/github/index.ts +++ b/github/index.ts @@ -318,10 +318,6 @@ function useEnvRunUrl() { return `/${repo.owner}/${repo.repo}/actions/runs/${runId}` } -function useEnvAgent() { - return process.env["AGENT"] || undefined -} - function useEnvShare() { const value = process.env["SHARE"] if (!value) return undefined @@ -574,49 +570,24 @@ async function subscribeSessionEvents() { } async function summarize(response: string) { + const payload = useContext().payload as IssueCommentEvent try { return await chat(`Summarize the following in less than 40 characters:\n\n${response}`) } catch (e) { - if (isScheduleEvent()) { - return "Scheduled task changes" - } - const payload = useContext().payload as IssueCommentEvent return `Fix issue: ${payload.issue.title}` } } -async function resolveAgent(): Promise { - const envAgent = useEnvAgent() - if (!envAgent) return undefined - - // Validate the agent exists and is a primary agent - const agents = await client.agent.list() - const agent = agents.data?.find((a) => a.name === envAgent) - - if (!agent) { - console.warn(`agent "${envAgent}" not found. Falling back to default agent`) - return undefined - } - - if (agent.mode === "subagent") { - console.warn(`agent "${envAgent}" is a subagent, not a primary agent. Falling back to default agent`) - return undefined - } - - return envAgent -} - async function chat(text: string, files: PromptFiles = []) { console.log("Sending message to opencode...") const { providerID, modelID } = useEnvModel() - const agent = await resolveAgent() const chat = await client.session.chat({ path: session, body: { providerID, modelID, - agent, + agent: "build", parts: [ { type: "text", diff --git a/github/package.json b/github/package.json index 4d447716f..1a6598d6b 100644 --- a/github/package.json +++ b/github/package.json @@ -13,7 +13,7 @@ "@actions/core": "1.11.1", "@actions/github": "6.0.1", "@octokit/graphql": "9.0.1", - "@octokit/rest": "catalog:", + "@octokit/rest": "22.0.0", "@opencode-ai/sdk": "workspace:*" } } diff --git a/github/sst-env.d.ts b/github/sst-env.d.ts index f742a1200..6b69016e7 100644 --- a/github/sst-env.d.ts +++ b/github/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/infra/app.ts b/infra/app.ts index da4ac45b8..7215995ba 100644 --- a/infra/app.ts +++ b/infra/app.ts @@ -44,12 +44,3 @@ new sst.cloudflare.x.Astro("Web", { VITE_API_URL: api.url.apply((url) => url!), }, }) - -new sst.cloudflare.StaticSite("App", { - domain: "app." + domain, - path: "packages/app", - build: { - command: "bun turbo build", - output: "./dist", - }, -}) diff --git a/infra/console.ts b/infra/console.ts index 0cc6a404b..eddc97d2f 100644 --- a/infra/console.ts +++ b/infra/console.ts @@ -102,7 +102,6 @@ const ZEN_MODELS = [ new sst.Secret("ZEN_MODELS2"), new sst.Secret("ZEN_MODELS3"), new sst.Secret("ZEN_MODELS4"), - new sst.Secret("ZEN_MODELS5"), ] const STRIPE_SECRET_KEY = new sst.Secret("STRIPE_SECRET_KEY") const AUTH_API_URL = new sst.Linkable("AUTH_API_URL", { @@ -117,8 +116,7 @@ const gatewayKv = new sst.cloudflare.Kv("GatewayKv") // CONSOLE //////////////// -const bucket = new sst.cloudflare.Bucket("ZenData") -const bucketNew = new sst.cloudflare.Bucket("ZenDataNew") +const bucket = new sst.cloudflare.Bucket("ConsoleData") const AWS_SES_ACCESS_KEY_ID = new sst.Secret("AWS_SES_ACCESS_KEY_ID") const AWS_SES_SECRET_ACCESS_KEY = new sst.Secret("AWS_SES_SECRET_ACCESS_KEY") @@ -137,7 +135,6 @@ new sst.cloudflare.x.SolidStart("Console", { path: "packages/console/app", link: [ bucket, - bucketNew, database, AUTH_API_URL, STRIPE_WEBHOOK_SECRET, diff --git a/infra/desktop.ts b/infra/desktop.ts index 5c4155cc9..d4e32c65d 100644 --- a/infra/desktop.ts +++ b/infra/desktop.ts @@ -2,7 +2,7 @@ import { domain } from "./stage" new sst.cloudflare.StaticSite("Desktop", { domain: "desktop." + domain, - path: "packages/app", + path: "packages/desktop", build: { command: "bun turbo build", output: "./dist", diff --git a/infra/enterprise.ts b/infra/enterprise.ts index 22b4c6f44..70693846a 100644 --- a/infra/enterprise.ts +++ b/infra/enterprise.ts @@ -1,10 +1,10 @@ import { SECRET } from "./secret" -import { domain, shortDomain } from "./stage" +import { domain } from "./stage" const storage = new sst.cloudflare.Bucket("EnterpriseStorage") -const teams = new sst.cloudflare.x.SolidStart("Teams", { - domain: shortDomain, +const enterprise = new sst.cloudflare.x.SolidStart("Enterprise", { + domain: "enterprise." + domain, path: "packages/enterprise", buildCommand: "bun run build:cloudflare", environment: { diff --git a/infra/stage.ts b/infra/stage.ts index f9a6fd755..729422905 100644 --- a/infra/stage.ts +++ b/infra/stage.ts @@ -11,9 +11,3 @@ new cloudflare.RegionalHostname("RegionalHostname", { regionKey: "us", zoneId: zoneID, }) - -export const shortDomain = (() => { - if ($app.stage === "production") return "opncd.ai" - if ($app.stage === "dev") return "dev.opncd.ai" - return `${$app.stage}.dev.opncd.ai` -})() diff --git a/install b/install index 67690b9a3..77ecf34b9 100755 --- a/install +++ b/install @@ -4,7 +4,7 @@ APP=opencode MUTED='\033[0;2m' RED='\033[0;31m' -ORANGE='\033[38;5;214m' +ORANGE='\033[38;2;255;140;0m' NC='\033[0m' # No Color requested_version=${VERSION:-} @@ -240,23 +240,22 @@ download_with_progress() { download_and_install() { print_message info "\n${MUTED}Installing ${NC}opencode ${MUTED}version: ${NC}$specific_version" - local tmp_dir="${TMPDIR:-/tmp}/opencode_install_$$" - mkdir -p "$tmp_dir" + mkdir -p opencodetmp && cd opencodetmp - if [[ "$os" == "windows" ]] || ! [ -t 2 ] || ! download_with_progress "$url" "$tmp_dir/$filename"; then - # Fallback to standard curl on Windows, non-TTY environments, or if custom progress fails - curl -# -L -o "$tmp_dir/$filename" "$url" + if [[ "$os" == "windows" ]] || ! download_with_progress "$url" "$filename"; then + # Fallback to standard curl on Windows or if custom progress fails + curl -# -L -o "$filename" "$url" fi if [ "$os" = "linux" ]; then - tar -xzf "$tmp_dir/$filename" -C "$tmp_dir" + tar -xzf "$filename" else - unzip -q "$tmp_dir/$filename" -d "$tmp_dir" + unzip -q "$filename" fi - mv "$tmp_dir/opencode" "$INSTALL_DIR" + mv opencode "$INSTALL_DIR" chmod 755 "${INSTALL_DIR}/opencode" - rm -rf "$tmp_dir" + cd .. && rm -rf opencodetmp } check_version @@ -354,10 +353,10 @@ echo -e "${MUTED}█░░█ █░░█ █▀▀▀ █░░█ ${NC}█░ echo -e "${MUTED}▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀ ▀ ${NC}▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀" echo -e "" echo -e "" -echo -e "${MUTED}OpenCode includes free models, to start:${NC}" -echo -e "" -echo -e "cd ${MUTED}# Open directory${NC}" -echo -e "opencode ${MUTED}# Run command${NC}" +echo -e "${MUTED}To get started, navigate to a project and run:${NC}" +echo -e "opencode ${MUTED}Use free models${NC}" +echo -e "opencode auth login ${MUTED}Add paid provider API keys${NC}" +echo -e "opencode help ${MUTED}List commands and options${NC}" echo -e "" echo -e "${MUTED}For more information visit ${NC}https://opencode.ai/docs" echo -e "" diff --git a/nix/hashes.json b/nix/hashes.json index dbf753171..1f11430f2 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,3 +1,3 @@ { - "nodeModules": "sha256-QlQblkUq49DOdvNNMNAzHHAfHxR6cZNmJtyzc4rD168=" + "nodeModules": "sha256-dTGBX5mde/hQP36MSFwq3G81OdwpcYRl8bcjLpesbPw=" } diff --git a/nix/opencode.nix b/nix/opencode.nix index 87b3f17ba..8c4e9fb57 100644 --- a/nix/opencode.nix +++ b/nix/opencode.nix @@ -1,4 +1,4 @@ -{ lib, stdenvNoCC, bun, ripgrep, makeBinaryWrapper }: +{ lib, stdenvNoCC, bun, fzf, ripgrep, makeBinaryWrapper }: args: let scripts = args.scripts; @@ -97,7 +97,7 @@ stdenvNoCC.mkDerivation (finalAttrs: { makeWrapper ${bun}/bin/bun $out/bin/opencode \ --add-flags "run" \ --add-flags "$out/lib/opencode/dist/src/index.js" \ - --prefix PATH : ${lib.makeBinPath [ ripgrep ]} \ + --prefix PATH : ${lib.makeBinPath [ fzf ripgrep ]} \ --argv0 opencode runHook postInstall diff --git a/package.json b/package.json index 23ef2253a..e85f08e4e 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "AI-powered development tool", "private": true, "type": "module", - "packageManager": "bun@1.3.5", + "packageManager": "bun@1.3.3", "scripts": { "dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts", "typecheck": "bun turbo typecheck", @@ -20,8 +20,7 @@ "packages/slack" ], "catalog": { - "@types/bun": "1.3.4", - "@octokit/rest": "22.0.0", + "@types/bun": "1.3.3", "@hono/zod-validator": "0.4.2", "ulid": "3.0.1", "@kobalte/core": "0.13.11", @@ -31,20 +30,18 @@ "@tsconfig/bun": "1.0.9", "@cloudflare/workers-types": "4.20251008.0", "@openauthjs/openauth": "0.0.0-20250322224806", - "@pierre/diffs": "1.0.2", - "@solid-primitives/storage": "4.3.3", + "@pierre/precision-diffs": "0.5.7", "@tailwindcss/vite": "4.1.11", "diff": "8.0.2", "ai": "5.0.97", - "hono": "4.10.7", - "hono-openapi": "1.1.2", + "hono": "4.7.10", + "hono-openapi": "1.1.1", "fuzzysort": "3.1.0", "luxon": "3.6.1", "typescript": "5.8.2", - "@typescript/native-preview": "7.0.0-dev.20251207.1", + "@typescript/native-preview": "7.0.0-dev.20251014.1", "zod": "4.1.8", "remeda": "2.26.0", - "shiki": "3.20.0", "solid-list": "0.3.0", "tailwindcss": "4.1.11", "virtua": "0.42.3", @@ -57,7 +54,6 @@ } }, "devDependencies": { - "@actions/artifact": "5.0.1", "@tsconfig/bun": "catalog:", "husky": "9.1.7", "prettier": "3.6.2", @@ -65,15 +61,7 @@ "turbo": "2.5.6" }, "dependencies": { - "@ai-sdk/cerebras": "1.0.33", - "@ai-sdk/cohere": "2.0.21", - "@ai-sdk/deepinfra": "1.0.30", - "@ai-sdk/gateway": "2.0.23", - "@ai-sdk/groq": "2.0.33", - "@ai-sdk/perplexity": "2.0.22", - "@ai-sdk/togetherai": "1.0.30", "@aws-sdk/client-s3": "3.933.0", - "@opencode-ai/plugin": "workspace:*", "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", "typescript": "catalog:" @@ -90,6 +78,7 @@ "trustedDependencies": [ "esbuild", "protobufjs", + "sharp", "tree-sitter", "tree-sitter-bash", "web-tree-sitter" @@ -97,8 +86,5 @@ "overrides": { "@types/bun": "catalog:", "@types/node": "catalog:" - }, - "patchedDependencies": { - "ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch" } } diff --git a/packages/app/.gitignore b/packages/app/.gitignore deleted file mode 100644 index 4a20d55a7..000000000 --- a/packages/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -src/assets/theme.css diff --git a/packages/app/README.md b/packages/app/README.md deleted file mode 100644 index 6a1764536..000000000 --- a/packages/app/README.md +++ /dev/null @@ -1,34 +0,0 @@ -## Usage - -Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`. - -This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template. - -```bash -$ npm install # or pnpm install or yarn install -``` - -### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs) - -## Available Scripts - -In the project directory, you can run: - -### `npm run dev` or `npm start` - -Runs the app in the development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will reload if you make edits.
- -### `npm run build` - -Builds the app for production to the `dist` folder.
-It correctly bundles Solid in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-Your app is ready to be deployed! - -## Deployment - -You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.) diff --git a/packages/app/bunfig.toml b/packages/app/bunfig.toml deleted file mode 100644 index 363990451..000000000 --- a/packages/app/bunfig.toml +++ /dev/null @@ -1,2 +0,0 @@ -[test] -preload = ["./happydom.ts"] diff --git a/packages/app/happydom.ts b/packages/app/happydom.ts deleted file mode 100644 index de726718f..000000000 --- a/packages/app/happydom.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { GlobalRegistrator } from "@happy-dom/global-registrator" - -GlobalRegistrator.register() - -const originalGetContext = HTMLCanvasElement.prototype.getContext -// @ts-expect-error - we're overriding with a simplified mock -HTMLCanvasElement.prototype.getContext = function (contextType: string, _options?: unknown) { - if (contextType === "2d") { - return { - canvas: this, - fillStyle: "#000000", - strokeStyle: "#000000", - font: "12px monospace", - textAlign: "start", - textBaseline: "alphabetic", - globalAlpha: 1, - globalCompositeOperation: "source-over", - imageSmoothingEnabled: true, - lineWidth: 1, - lineCap: "butt", - lineJoin: "miter", - miterLimit: 10, - shadowBlur: 0, - shadowColor: "rgba(0, 0, 0, 0)", - shadowOffsetX: 0, - shadowOffsetY: 0, - fillRect: () => {}, - strokeRect: () => {}, - clearRect: () => {}, - fillText: () => {}, - strokeText: () => {}, - measureText: (text: string) => ({ width: text.length * 8 }), - drawImage: () => {}, - save: () => {}, - restore: () => {}, - scale: () => {}, - rotate: () => {}, - translate: () => {}, - transform: () => {}, - setTransform: () => {}, - resetTransform: () => {}, - createLinearGradient: () => ({ addColorStop: () => {} }), - createRadialGradient: () => ({ addColorStop: () => {} }), - createPattern: () => null, - beginPath: () => {}, - closePath: () => {}, - moveTo: () => {}, - lineTo: () => {}, - bezierCurveTo: () => {}, - quadraticCurveTo: () => {}, - arc: () => {}, - arcTo: () => {}, - ellipse: () => {}, - rect: () => {}, - fill: () => {}, - stroke: () => {}, - clip: () => {}, - isPointInPath: () => false, - isPointInStroke: () => false, - getTransform: () => ({}), - getImageData: () => ({ - data: new Uint8ClampedArray(0), - width: 0, - height: 0, - }), - putImageData: () => {}, - createImageData: () => ({ - data: new Uint8ClampedArray(0), - width: 0, - height: 0, - }), - } as unknown as CanvasRenderingContext2D - } - return originalGetContext.call(this, contextType as "2d", _options) -} diff --git a/packages/app/index.html b/packages/app/index.html deleted file mode 100644 index 9803517a0..000000000 --- a/packages/app/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - OpenCode - - - - - - - - - - - - - -
- - - diff --git a/packages/app/package.json b/packages/app/package.json deleted file mode 100644 index 9280bec2b..000000000 --- a/packages/app/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "@opencode-ai/app", - "version": "1.0.191", - "description": "", - "type": "module", - "exports": { - ".": "./src/index.ts", - "./vite": "./vite.js" - }, - "scripts": { - "typecheck": "tsgo -b", - "start": "vite", - "dev": "vite", - "build": "vite build", - "serve": "vite preview" - }, - "license": "MIT", - "devDependencies": { - "@happy-dom/global-registrator": "20.0.11", - "@tailwindcss/vite": "catalog:", - "@tsconfig/bun": "1.0.9", - "@types/bun": "catalog:", - "@types/luxon": "catalog:", - "@types/node": "catalog:", - "@typescript/native-preview": "catalog:", - "typescript": "catalog:", - "vite": "catalog:", - "vite-plugin-icons-spritesheet": "3.0.1", - "vite-plugin-solid": "catalog:" - }, - "dependencies": { - "@kobalte/core": "catalog:", - "@opencode-ai/sdk": "workspace:*", - "@opencode-ai/ui": "workspace:*", - "@opencode-ai/util": "workspace:*", - "@shikijs/transformers": "3.9.2", - "@solid-primitives/active-element": "2.1.3", - "@solid-primitives/audio": "1.4.2", - "@solid-primitives/event-bus": "1.1.2", - "@solid-primitives/media": "2.3.3", - "@solid-primitives/resize-observer": "2.1.3", - "@solid-primitives/scroll": "2.1.3", - "@solid-primitives/storage": "catalog:", - "@solid-primitives/websocket": "1.3.1", - "@solidjs/meta": "catalog:", - "@solidjs/router": "catalog:", - "@thisbeyond/solid-dnd": "0.7.5", - "diff": "catalog:", - "fuzzysort": "catalog:", - "ghostty-web": "0.3.0", - "luxon": "catalog:", - "marked": "16.2.0", - "marked-shiki": "1.2.1", - "remeda": "catalog:", - "shiki": "catalog:", - "solid-js": "catalog:", - "solid-list": "catalog:", - "tailwindcss": "catalog:", - "virtua": "catalog:", - "zod": "catalog:" - } -} diff --git a/packages/app/public/social-share-zen.png b/packages/app/public/social-share-zen.png deleted file mode 120000 index 02f205fc5..000000000 --- a/packages/app/public/social-share-zen.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/images/social-share-zen.png \ No newline at end of file diff --git a/packages/app/public/social-share.png b/packages/app/public/social-share.png deleted file mode 120000 index 88bf2d4c6..000000000 --- a/packages/app/public/social-share.png +++ /dev/null @@ -1 +0,0 @@ -../../ui/src/assets/images/social-share.png \ No newline at end of file diff --git a/packages/app/src/addons/serialize.test.ts b/packages/app/src/addons/serialize.test.ts deleted file mode 100644 index ad165f43f..000000000 --- a/packages/app/src/addons/serialize.test.ts +++ /dev/null @@ -1,272 +0,0 @@ -import { describe, test, expect, beforeAll, afterEach } from "bun:test" -import { Terminal, Ghostty } from "ghostty-web" -import { SerializeAddon } from "./serialize" - -let ghostty: Ghostty -beforeAll(async () => { - ghostty = await Ghostty.load() -}) - -const terminals: Terminal[] = [] - -afterEach(() => { - for (const term of terminals) { - term.dispose() - } - terminals.length = 0 - document.body.innerHTML = "" -}) - -function createTerminal(cols = 80, rows = 24): { term: Terminal; addon: SerializeAddon; container: HTMLElement } { - const container = document.createElement("div") - document.body.appendChild(container) - - const term = new Terminal({ cols, rows, ghostty }) - const addon = new SerializeAddon() - term.loadAddon(addon) - term.open(container) - terminals.push(term) - - return { term, addon, container } -} - -function writeAndWait(term: Terminal, data: string): Promise { - return new Promise((resolve) => { - term.write(data, resolve) - }) -} - -describe("SerializeAddon", () => { - describe("ANSI color preservation", () => { - test("should preserve text attributes (bold, italic, underline)", async () => { - const { term, addon } = createTerminal() - - const input = "\x1b[1mBOLD\x1b[0m \x1b[3mITALIC\x1b[0m \x1b[4mUNDER\x1b[0m" - await writeAndWait(term, input) - - const origLine = term.buffer.active.getLine(0) - expect(origLine!.getCell(0)!.isBold()).toBe(1) - expect(origLine!.getCell(5)!.isItalic()).toBe(1) - expect(origLine!.getCell(12)!.isUnderline()).toBe(1) - - const serialized = addon.serialize({ range: { start: 0, end: 0 } }) - - const { term: term2 } = createTerminal() - terminals.push(term2) - await writeAndWait(term2, serialized) - - const line = term2.buffer.active.getLine(0) - - const boldCell = line!.getCell(0) - expect(boldCell!.getChars()).toBe("B") - expect(boldCell!.isBold()).toBe(1) - - const italicCell = line!.getCell(5) - expect(italicCell!.getChars()).toBe("I") - expect(italicCell!.isItalic()).toBe(1) - - const underCell = line!.getCell(12) - expect(underCell!.getChars()).toBe("U") - expect(underCell!.isUnderline()).toBe(1) - }) - - test("should preserve basic 16-color foreground colors", async () => { - const { term, addon } = createTerminal() - - const input = "\x1b[31mRED\x1b[32mGREEN\x1b[34mBLUE\x1b[0mNORMAL" - await writeAndWait(term, input) - - const origLine = term.buffer.active.getLine(0) - const origRedFg = origLine!.getCell(0)!.getFgColor() - const origGreenFg = origLine!.getCell(3)!.getFgColor() - const origBlueFg = origLine!.getCell(8)!.getFgColor() - - const serialized = addon.serialize({ range: { start: 0, end: 0 } }) - - const { term: term2 } = createTerminal() - terminals.push(term2) - await writeAndWait(term2, serialized) - - const line = term2.buffer.active.getLine(0) - expect(line).toBeDefined() - - const redCell = line!.getCell(0) - expect(redCell!.getChars()).toBe("R") - expect(redCell!.getFgColor()).toBe(origRedFg) - - const greenCell = line!.getCell(3) - expect(greenCell!.getChars()).toBe("G") - expect(greenCell!.getFgColor()).toBe(origGreenFg) - - const blueCell = line!.getCell(8) - expect(blueCell!.getChars()).toBe("B") - expect(blueCell!.getFgColor()).toBe(origBlueFg) - }) - - test("should preserve 256-color palette colors", async () => { - const { term, addon } = createTerminal() - - const input = "\x1b[38;5;196mRED256\x1b[0mNORMAL" - await writeAndWait(term, input) - - const origLine = term.buffer.active.getLine(0) - const origRedFg = origLine!.getCell(0)!.getFgColor() - - const serialized = addon.serialize({ range: { start: 0, end: 0 } }) - - const { term: term2 } = createTerminal() - terminals.push(term2) - await writeAndWait(term2, serialized) - - const line = term2.buffer.active.getLine(0) - const redCell = line!.getCell(0) - expect(redCell!.getChars()).toBe("R") - expect(redCell!.getFgColor()).toBe(origRedFg) - }) - - test("should preserve RGB/truecolor colors", async () => { - const { term, addon } = createTerminal() - - const input = "\x1b[38;2;255;128;64mRGB_TEXT\x1b[0mNORMAL" - await writeAndWait(term, input) - - const origLine = term.buffer.active.getLine(0) - const origRgbFg = origLine!.getCell(0)!.getFgColor() - - const serialized = addon.serialize({ range: { start: 0, end: 0 } }) - - const { term: term2 } = createTerminal() - terminals.push(term2) - await writeAndWait(term2, serialized) - - const line = term2.buffer.active.getLine(0) - const rgbCell = line!.getCell(0) - expect(rgbCell!.getChars()).toBe("R") - expect(rgbCell!.getFgColor()).toBe(origRgbFg) - }) - - test("should preserve background colors", async () => { - const { term, addon } = createTerminal() - - const input = "\x1b[48;2;255;0;0mRED_BG\x1b[48;2;0;255;0mGREEN_BG\x1b[0mNORMAL" - await writeAndWait(term, input) - - const origLine = term.buffer.active.getLine(0) - const origRedBg = origLine!.getCell(0)!.getBgColor() - const origGreenBg = origLine!.getCell(6)!.getBgColor() - - const serialized = addon.serialize({ range: { start: 0, end: 0 } }) - - const { term: term2 } = createTerminal() - terminals.push(term2) - await writeAndWait(term2, serialized) - - const line = term2.buffer.active.getLine(0) - - const redBgCell = line!.getCell(0) - expect(redBgCell!.getChars()).toBe("R") - expect(redBgCell!.getBgColor()).toBe(origRedBg) - - const greenBgCell = line!.getCell(6) - expect(greenBgCell!.getChars()).toBe("G") - expect(greenBgCell!.getBgColor()).toBe(origGreenBg) - }) - - test("should handle combined colors and attributes", async () => { - const { term, addon } = createTerminal() - - const input = - "\x1b[1;38;2;255;0;0;48;2;255;255;0mCOMBO\x1b[0mNORMAL " - await writeAndWait(term, input) - - const origLine = term.buffer.active.getLine(0) - const origFg = origLine!.getCell(0)!.getFgColor() - const origBg = origLine!.getCell(0)!.getBgColor() - expect(origLine!.getCell(0)!.isBold()).toBe(1) - - const serialized = addon.serialize({ range: { start: 0, end: 0 } }) - const cleanSerialized = serialized.replace(/\x1b\[\d+X/g, "") - - expect(cleanSerialized.startsWith("\x1b[1;")).toBe(true) - - const { term: term2 } = createTerminal() - terminals.push(term2) - await writeAndWait(term2, cleanSerialized) - - const line = term2.buffer.active.getLine(0) - const comboCell = line!.getCell(0) - - expect(comboCell!.getChars()).toBe("C") - expect(cleanSerialized).toContain("\x1b[1;38;2;255;0;0;48;2;255;255;0m") - }) - }) - - describe("round-trip serialization", () => { - test("should not produce ECH sequences", async () => { - const { term, addon } = createTerminal() - - await writeAndWait(term, "\x1b[31mHello\x1b[0m World") - - const serialized = addon.serialize() - - const hasECH = /\x1b\[\d+X/.test(serialized) - expect(hasECH).toBe(false) - }) - - test("multi-line content should not have garbage characters", async () => { - const { term, addon } = createTerminal() - - const content = [ - "\x1b[1;32m❯\x1b[0m \x1b[34mcd\x1b[0m /some/path", - "\x1b[1;32m❯\x1b[0m \x1b[34mls\x1b[0m -la", - "total 42", - ].join("\r\n") - - await writeAndWait(term, content) - - const serialized = addon.serialize() - - expect(/\x1b\[\d+X/.test(serialized)).toBe(false) - - const { term: term2 } = createTerminal() - terminals.push(term2) - await writeAndWait(term2, serialized) - - for (let row = 0; row < 3; row++) { - const line = term2.buffer.active.getLine(row)?.translateToString(true) - expect(line?.includes("𑼝")).toBe(false) - } - - expect(term2.buffer.active.getLine(0)?.translateToString(true)).toContain("cd /some/path") - expect(term2.buffer.active.getLine(1)?.translateToString(true)).toContain("ls -la") - expect(term2.buffer.active.getLine(2)?.translateToString(true)).toBe("total 42") - }) - - test("serialized output written to new terminal should match original colors", async () => { - const { term, addon } = createTerminal(40, 5) - - const input = "\x1b[38;2;255;0;0mHello\x1b[0m \x1b[38;2;0;255;0mWorld\x1b[0m! " - await writeAndWait(term, input) - - const origLine = term.buffer.active.getLine(0) - const origHelloFg = origLine!.getCell(0)!.getFgColor() - const origWorldFg = origLine!.getCell(6)!.getFgColor() - - const serialized = addon.serialize({ range: { start: 0, end: 0 } }) - - const { term: term2 } = createTerminal(40, 5) - terminals.push(term2) - await writeAndWait(term2, serialized) - - const newLine = term2.buffer.active.getLine(0) - - expect(newLine!.getCell(0)!.getChars()).toBe("H") - expect(newLine!.getCell(0)!.getFgColor()).toBe(origHelloFg) - - expect(newLine!.getCell(6)!.getChars()).toBe("W") - expect(newLine!.getCell(6)!.getFgColor()).toBe(origWorldFg) - - expect(newLine!.getCell(11)!.getChars()).toBe("!") - }) - }) -}) diff --git a/packages/app/src/addons/serialize.ts b/packages/app/src/addons/serialize.ts deleted file mode 100644 index cb1ff8442..000000000 --- a/packages/app/src/addons/serialize.ts +++ /dev/null @@ -1,595 +0,0 @@ -/** - * SerializeAddon - Serialize terminal buffer contents - * - * Port of xterm.js addon-serialize for ghostty-web. - * Enables serialization of terminal contents to a string that can - * be written back to restore terminal state. - * - * Usage: - * ```typescript - * const serializeAddon = new SerializeAddon(); - * term.loadAddon(serializeAddon); - * const content = serializeAddon.serialize(); - * ``` - */ - -import type { ITerminalAddon, ITerminalCore, IBufferRange } from "ghostty-web" - -// ============================================================================ -// Buffer Types (matching ghostty-web internal interfaces) -// ============================================================================ - -interface IBuffer { - readonly type: "normal" | "alternate" - readonly cursorX: number - readonly cursorY: number - readonly viewportY: number - readonly baseY: number - readonly length: number - getLine(y: number): IBufferLine | undefined - getNullCell(): IBufferCell -} - -interface IBufferLine { - readonly length: number - readonly isWrapped: boolean - getCell(x: number): IBufferCell | undefined - translateToString(trimRight?: boolean, startColumn?: number, endColumn?: number): string -} - -interface IBufferCell { - getChars(): string - getCode(): number - getWidth(): number - getFgColorMode(): number - getBgColorMode(): number - getFgColor(): number - getBgColor(): number - isBold(): number - isItalic(): number - isUnderline(): number - isStrikethrough(): number - isBlink(): number - isInverse(): number - isInvisible(): number - isFaint(): number - isDim(): boolean -} - -// ============================================================================ -// Types -// ============================================================================ - -export interface ISerializeOptions { - /** - * The row range to serialize. When an explicit range is specified, the cursor - * will get its final repositioning. - */ - range?: ISerializeRange - /** - * The number of rows in the scrollback buffer to serialize, starting from - * the bottom of the scrollback buffer. When not specified, all available - * rows in the scrollback buffer will be serialized. - */ - scrollback?: number - /** - * Whether to exclude the terminal modes from the serialization. - * Default: false - */ - excludeModes?: boolean - /** - * Whether to exclude the alt buffer from the serialization. - * Default: false - */ - excludeAltBuffer?: boolean -} - -export interface ISerializeRange { - /** - * The line to start serializing (inclusive). - */ - start: number - /** - * The line to end serializing (inclusive). - */ - end: number -} - -export interface IHTMLSerializeOptions { - /** - * The number of rows in the scrollback buffer to serialize, starting from - * the bottom of the scrollback buffer. - */ - scrollback?: number - /** - * Whether to only serialize the selection. - * Default: false - */ - onlySelection?: boolean - /** - * Whether to include the global background of the terminal. - * Default: false - */ - includeGlobalBackground?: boolean - /** - * The range to serialize. This is prioritized over onlySelection. - */ - range?: { - startLine: number - endLine: number - startCol: number - } -} - -// ============================================================================ -// Helper Functions -// ============================================================================ - -function constrain(value: number, low: number, high: number): number { - return Math.max(low, Math.min(value, high)) -} - -function equalFg(cell1: IBufferCell, cell2: IBufferCell): boolean { - return cell1.getFgColorMode() === cell2.getFgColorMode() && cell1.getFgColor() === cell2.getFgColor() -} - -function equalBg(cell1: IBufferCell, cell2: IBufferCell): boolean { - return cell1.getBgColorMode() === cell2.getBgColorMode() && cell1.getBgColor() === cell2.getBgColor() -} - -function equalFlags(cell1: IBufferCell, cell2: IBufferCell): boolean { - return ( - !!cell1.isInverse() === !!cell2.isInverse() && - !!cell1.isBold() === !!cell2.isBold() && - !!cell1.isUnderline() === !!cell2.isUnderline() && - !!cell1.isBlink() === !!cell2.isBlink() && - !!cell1.isInvisible() === !!cell2.isInvisible() && - !!cell1.isItalic() === !!cell2.isItalic() && - !!cell1.isDim() === !!cell2.isDim() && - !!cell1.isStrikethrough() === !!cell2.isStrikethrough() - ) -} - -// ============================================================================ -// Base Serialize Handler -// ============================================================================ - -abstract class BaseSerializeHandler { - constructor(protected readonly _buffer: IBuffer) {} - - private _isRealContent(codepoint: number): boolean { - if (codepoint === 0) return false - if (codepoint >= 0xf000) return false - return true - } - - private _findLastContentColumn(line: IBufferLine): number { - let lastContent = -1 - for (let col = 0; col < line.length; col++) { - const cell = line.getCell(col) - if (cell && this._isRealContent(cell.getCode())) { - lastContent = col - } - } - return lastContent + 1 - } - - public serialize(range: IBufferRange, excludeFinalCursorPosition?: boolean): string { - let oldCell = this._buffer.getNullCell() - - const startRow = range.start.y - const endRow = range.end.y - const startColumn = range.start.x - const endColumn = range.end.x - - this._beforeSerialize(endRow - startRow, startRow, endRow) - - for (let row = startRow; row <= endRow; row++) { - const line = this._buffer.getLine(row) - if (line) { - const startLineColumn = row === range.start.y ? startColumn : 0 - const maxColumn = row === range.end.y ? endColumn : this._findLastContentColumn(line) - const endLineColumn = Math.min(maxColumn, line.length) - for (let col = startLineColumn; col < endLineColumn; col++) { - const c = line.getCell(col) - if (!c) { - continue - } - this._nextCell(c, oldCell, row, col) - oldCell = c - } - } - this._rowEnd(row, row === endRow) - } - - this._afterSerialize() - - return this._serializeString(excludeFinalCursorPosition) - } - - protected _nextCell(_cell: IBufferCell, _oldCell: IBufferCell, _row: number, _col: number): void {} - protected _rowEnd(_row: number, _isLastRow: boolean): void {} - protected _beforeSerialize(_rows: number, _startRow: number, _endRow: number): void {} - protected _afterSerialize(): void {} - protected _serializeString(_excludeFinalCursorPosition?: boolean): string { - return "" - } -} - -// ============================================================================ -// String Serialize Handler -// ============================================================================ - -class StringSerializeHandler extends BaseSerializeHandler { - private _rowIndex: number = 0 - private _allRows: string[] = [] - private _allRowSeparators: string[] = [] - private _currentRow: string = "" - private _nullCellCount: number = 0 - private _cursorStyle: IBufferCell - private _firstRow: number = 0 - private _lastCursorRow: number = 0 - private _lastCursorCol: number = 0 - private _lastContentCursorRow: number = 0 - private _lastContentCursorCol: number = 0 - - constructor( - buffer: IBuffer, - private readonly _terminal: ITerminalCore, - ) { - super(buffer) - this._cursorStyle = this._buffer.getNullCell() - } - - protected _beforeSerialize(rows: number, start: number, _end: number): void { - this._allRows = new Array(rows) - this._lastContentCursorRow = start - this._lastCursorRow = start - this._firstRow = start - } - - protected _rowEnd(row: number, isLastRow: boolean): void { - let rowSeparator = "" - - if (!isLastRow) { - const nextLine = this._buffer.getLine(row + 1) - - if (!nextLine?.isWrapped) { - rowSeparator = "\r\n" - this._lastCursorRow = row + 1 - this._lastCursorCol = 0 - } - } - - this._allRows[this._rowIndex] = this._currentRow - this._allRowSeparators[this._rowIndex++] = rowSeparator - this._currentRow = "" - this._nullCellCount = 0 - } - - private _diffStyle(cell: IBufferCell, oldCell: IBufferCell): number[] { - const sgrSeq: number[] = [] - const fgChanged = !equalFg(cell, oldCell) - const bgChanged = !equalBg(cell, oldCell) - const flagsChanged = !equalFlags(cell, oldCell) - - if (fgChanged || bgChanged || flagsChanged) { - if (this._isAttributeDefault(cell)) { - if (!this._isAttributeDefault(oldCell)) { - sgrSeq.push(0) - } - } else { - if (flagsChanged) { - if (!!cell.isInverse() !== !!oldCell.isInverse()) { - sgrSeq.push(cell.isInverse() ? 7 : 27) - } - if (!!cell.isBold() !== !!oldCell.isBold()) { - sgrSeq.push(cell.isBold() ? 1 : 22) - } - if (!!cell.isUnderline() !== !!oldCell.isUnderline()) { - sgrSeq.push(cell.isUnderline() ? 4 : 24) - } - if (!!cell.isBlink() !== !!oldCell.isBlink()) { - sgrSeq.push(cell.isBlink() ? 5 : 25) - } - if (!!cell.isInvisible() !== !!oldCell.isInvisible()) { - sgrSeq.push(cell.isInvisible() ? 8 : 28) - } - if (!!cell.isItalic() !== !!oldCell.isItalic()) { - sgrSeq.push(cell.isItalic() ? 3 : 23) - } - if (!!cell.isDim() !== !!oldCell.isDim()) { - sgrSeq.push(cell.isDim() ? 2 : 22) - } - if (!!cell.isStrikethrough() !== !!oldCell.isStrikethrough()) { - sgrSeq.push(cell.isStrikethrough() ? 9 : 29) - } - } - if (fgChanged) { - const color = cell.getFgColor() - const mode = cell.getFgColorMode() - if (mode === 2 || mode === 3 || mode === -1) { - sgrSeq.push(38, 2, (color >>> 16) & 0xff, (color >>> 8) & 0xff, color & 0xff) - } else if (mode === 1) { - // Palette - if (color >= 16) { - sgrSeq.push(38, 5, color) - } else { - sgrSeq.push(color & 8 ? 90 + (color & 7) : 30 + (color & 7)) - } - } else { - sgrSeq.push(39) - } - } - if (bgChanged) { - const color = cell.getBgColor() - const mode = cell.getBgColorMode() - if (mode === 2 || mode === 3 || mode === -1) { - sgrSeq.push(48, 2, (color >>> 16) & 0xff, (color >>> 8) & 0xff, color & 0xff) - } else if (mode === 1) { - // Palette - if (color >= 16) { - sgrSeq.push(48, 5, color) - } else { - sgrSeq.push(color & 8 ? 100 + (color & 7) : 40 + (color & 7)) - } - } else { - sgrSeq.push(49) - } - } - } - } - - return sgrSeq - } - - private _isAttributeDefault(cell: IBufferCell): boolean { - const mode = cell.getFgColorMode() - const bgMode = cell.getBgColorMode() - - if (mode === 0 && bgMode === 0) { - return ( - !cell.isBold() && - !cell.isItalic() && - !cell.isUnderline() && - !cell.isBlink() && - !cell.isInverse() && - !cell.isInvisible() && - !cell.isDim() && - !cell.isStrikethrough() - ) - } - - const fgColor = cell.getFgColor() - const bgColor = cell.getBgColor() - const nullCell = this._buffer.getNullCell() - const nullFg = nullCell.getFgColor() - const nullBg = nullCell.getBgColor() - - return ( - fgColor === nullFg && - bgColor === nullBg && - !cell.isBold() && - !cell.isItalic() && - !cell.isUnderline() && - !cell.isBlink() && - !cell.isInverse() && - !cell.isInvisible() && - !cell.isDim() && - !cell.isStrikethrough() - ) - } - - protected _nextCell(cell: IBufferCell, _oldCell: IBufferCell, row: number, col: number): void { - const isPlaceHolderCell = cell.getWidth() === 0 - - if (isPlaceHolderCell) { - return - } - - const codepoint = cell.getCode() - const isGarbage = codepoint >= 0xf000 - const isEmptyCell = codepoint === 0 || cell.getChars() === "" || isGarbage - - const sgrSeq = this._diffStyle(cell, this._cursorStyle) - - const styleChanged = isEmptyCell ? !equalBg(this._cursorStyle, cell) : sgrSeq.length > 0 - - if (styleChanged) { - if (this._nullCellCount > 0) { - this._currentRow += `\u001b[${this._nullCellCount}C` - this._nullCellCount = 0 - } - - this._lastContentCursorRow = this._lastCursorRow = row - this._lastContentCursorCol = this._lastCursorCol = col - - this._currentRow += `\u001b[${sgrSeq.join(";")}m` - - const line = this._buffer.getLine(row) - const cellFromLine = line?.getCell(col) - if (cellFromLine) { - this._cursorStyle = cellFromLine - } - } - - if (isEmptyCell) { - this._nullCellCount += cell.getWidth() - } else { - if (this._nullCellCount > 0) { - this._currentRow += `\u001b[${this._nullCellCount}C` - this._nullCellCount = 0 - } - - this._currentRow += cell.getChars() - - this._lastContentCursorRow = this._lastCursorRow = row - this._lastContentCursorCol = this._lastCursorCol = col + cell.getWidth() - } - } - - protected _serializeString(excludeFinalCursorPosition?: boolean): string { - let rowEnd = this._allRows.length - - if (this._buffer.length - this._firstRow <= this._terminal.rows) { - rowEnd = this._lastContentCursorRow + 1 - this._firstRow - this._lastCursorCol = this._lastContentCursorCol - this._lastCursorRow = this._lastContentCursorRow - } - - let content = "" - - for (let i = 0; i < rowEnd; i++) { - content += this._allRows[i] - if (i + 1 < rowEnd) { - content += this._allRowSeparators[i] - } - } - - if (!excludeFinalCursorPosition) { - const absoluteCursorRow = (this._buffer.baseY ?? 0) + this._buffer.cursorY - const cursorRow = constrain(absoluteCursorRow - this._firstRow + 1, 1, Number.MAX_SAFE_INTEGER) - const cursorCol = this._buffer.cursorX + 1 - content += `\u001b[${cursorRow};${cursorCol}H` - } - - return content - } -} - -// ============================================================================ -// SerializeAddon Class -// ============================================================================ - -export class SerializeAddon implements ITerminalAddon { - private _terminal?: ITerminalCore - - /** - * Activate the addon (called by Terminal.loadAddon) - */ - public activate(terminal: ITerminalCore): void { - this._terminal = terminal - } - - /** - * Dispose the addon and clean up resources - */ - public dispose(): void { - this._terminal = undefined - } - - /** - * Serializes terminal rows into a string that can be written back to the - * terminal to restore the state. The cursor will also be positioned to the - * correct cell. - * - * @param options Custom options to allow control over what gets serialized. - */ - public serialize(options?: ISerializeOptions): string { - if (!this._terminal) { - throw new Error("Cannot use addon until it has been loaded") - } - - const terminal = this._terminal as any - const buffer = terminal.buffer - - if (!buffer) { - return "" - } - - const normalBuffer = buffer.normal || buffer.active - const altBuffer = buffer.alternate - - if (!normalBuffer) { - return "" - } - - let content = options?.range - ? this._serializeBufferByRange(normalBuffer, options.range, true) - : this._serializeBufferByScrollback(normalBuffer, options?.scrollback) - - if (!options?.excludeAltBuffer && buffer.active?.type === "alternate" && altBuffer) { - const alternateContent = this._serializeBufferByScrollback(altBuffer, undefined) - content += `\u001b[?1049h\u001b[H${alternateContent}` - } - - return content - } - - /** - * Serializes terminal content as plain text (no escape sequences) - * @param options Custom options to allow control over what gets serialized. - */ - public serializeAsText(options?: { scrollback?: number; trimWhitespace?: boolean }): string { - if (!this._terminal) { - throw new Error("Cannot use addon until it has been loaded") - } - - const terminal = this._terminal as any - const buffer = terminal.buffer - - if (!buffer) { - return "" - } - - const activeBuffer = buffer.active || buffer.normal - if (!activeBuffer) { - return "" - } - - const maxRows = activeBuffer.length - const scrollback = options?.scrollback - const correctRows = scrollback === undefined ? maxRows : constrain(scrollback + this._terminal.rows, 0, maxRows) - - const startRow = maxRows - correctRows - const endRow = maxRows - 1 - const lines: string[] = [] - - for (let row = startRow; row <= endRow; row++) { - const line = activeBuffer.getLine(row) - if (line) { - const text = line.translateToString(options?.trimWhitespace ?? true) - lines.push(text) - } - } - - // Trim trailing empty lines if requested - if (options?.trimWhitespace) { - while (lines.length > 0 && lines[lines.length - 1] === "") { - lines.pop() - } - } - - return lines.join("\n") - } - - private _serializeBufferByScrollback(buffer: IBuffer, scrollback?: number): string { - const maxRows = buffer.length - const rows = this._terminal?.rows ?? 24 - const correctRows = scrollback === undefined ? maxRows : constrain(scrollback + rows, 0, maxRows) - return this._serializeBufferByRange( - buffer, - { - start: maxRows - correctRows, - end: maxRows - 1, - }, - false, - ) - } - - private _serializeBufferByRange( - buffer: IBuffer, - range: ISerializeRange, - excludeFinalCursorPosition: boolean, - ): string { - const handler = new StringSerializeHandler(buffer, this._terminal!) - const cols = this._terminal?.cols ?? 80 - return handler.serialize( - { - start: { x: 0, y: range.start }, - end: { x: cols, y: range.end }, - }, - excludeFinalCursorPosition, - ) - } -} diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx deleted file mode 100644 index 11216643e..000000000 --- a/packages/app/src/app.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import "@/index.css" -import { ErrorBoundary, Show } from "solid-js" -import { Router, Route, Navigate } from "@solidjs/router" -import { MetaProvider } from "@solidjs/meta" -import { Font } from "@opencode-ai/ui/font" -import { MarkedProvider } from "@opencode-ai/ui/context/marked" -import { DiffComponentProvider } from "@opencode-ai/ui/context/diff" -import { CodeComponentProvider } from "@opencode-ai/ui/context/code" -import { Diff } from "@opencode-ai/ui/diff" -import { Code } from "@opencode-ai/ui/code" -import { GlobalSyncProvider } from "@/context/global-sync" -import { LayoutProvider } from "@/context/layout" -import { GlobalSDKProvider } from "@/context/global-sdk" -import { TerminalProvider } from "@/context/terminal" -import { PromptProvider } from "@/context/prompt" -import { NotificationProvider } from "@/context/notification" -import { DialogProvider } from "@opencode-ai/ui/context/dialog" -import { CommandProvider } from "@/context/command" -import Layout from "@/pages/layout" -import Home from "@/pages/home" -import DirectoryLayout from "@/pages/directory-layout" -import Session from "@/pages/session" -import { ErrorPage } from "./pages/error" -import { iife } from "@opencode-ai/util/iife" - -declare global { - interface Window { - __OPENCODE__?: { updaterEnabled?: boolean; port?: number } - } -} - -const url = iife(() => { - const param = new URLSearchParams(document.location.search).get("url") - if (param) return param - - if (location.hostname.includes("opencode.ai")) return "http://localhost:4096" - if (window.__OPENCODE__) return `http://127.0.0.1:${window.__OPENCODE__.port}` - if (import.meta.env.DEV) - return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}` - - return "http://localhost:4096" -}) - -export function App() { - return ( - - - }> - - - - - - - - - ( - - {props.children} - - )} - > - - - } /> - ( - - - - - - - - )} - /> - - - - - - - - - - - - - ) -} diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx deleted file mode 100644 index 789a5d3b7..000000000 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ /dev/null @@ -1,383 +0,0 @@ -import type { ProviderAuthAuthorization } from "@opencode-ai/sdk/v2/client" -import { Button } from "@opencode-ai/ui/button" -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { Dialog } from "@opencode-ai/ui/dialog" -import { Icon } from "@opencode-ai/ui/icon" -import { IconButton } from "@opencode-ai/ui/icon-button" -import type { IconName } from "@opencode-ai/ui/icons/provider" -import { List, type ListRef } from "@opencode-ai/ui/list" -import { ProviderIcon } from "@opencode-ai/ui/provider-icon" -import { Spinner } from "@opencode-ai/ui/spinner" -import { TextField } from "@opencode-ai/ui/text-field" -import { showToast } from "@opencode-ai/ui/toast" -import { iife } from "@opencode-ai/util/iife" -import { createMemo, Match, onCleanup, onMount, Switch } from "solid-js" -import { createStore, produce } from "solid-js/store" -import { Link } from "@/components/link" -import { useGlobalSDK } from "@/context/global-sdk" -import { useGlobalSync } from "@/context/global-sync" -import { usePlatform } from "@/context/platform" -import { DialogSelectModel } from "./dialog-select-model" -import { DialogSelectProvider } from "./dialog-select-provider" - -export function DialogConnectProvider(props: { provider: string }) { - const dialog = useDialog() - const globalSync = useGlobalSync() - const globalSDK = useGlobalSDK() - const platform = usePlatform() - const provider = createMemo(() => globalSync.data.provider.all.find((x) => x.id === props.provider)!) - const methods = createMemo( - () => - globalSync.data.provider_auth[props.provider] ?? [ - { - type: "api", - label: "API key", - }, - ], - ) - const [store, setStore] = createStore({ - methodIndex: undefined as undefined | number, - authorization: undefined as undefined | ProviderAuthAuthorization, - state: "pending" as undefined | "pending" | "complete" | "error", - error: undefined as string | undefined, - }) - - const method = createMemo(() => (store.methodIndex !== undefined ? methods().at(store.methodIndex!) : undefined)) - - async function selectMethod(index: number) { - const method = methods()[index] - setStore( - produce((draft) => { - draft.methodIndex = index - draft.authorization = undefined - draft.state = undefined - draft.error = undefined - }), - ) - - if (method.type === "oauth") { - setStore("state", "pending") - const start = Date.now() - await globalSDK.client.provider.oauth - .authorize( - { - providerID: props.provider, - method: index, - }, - { throwOnError: true }, - ) - .then((x) => { - const elapsed = Date.now() - start - const delay = 1000 - elapsed - - if (delay > 0) { - setTimeout(() => { - setStore("state", "complete") - setStore("authorization", x.data!) - }, delay) - return - } - setStore("state", "complete") - setStore("authorization", x.data!) - }) - .catch((e) => { - setStore("state", "error") - setStore("error", String(e)) - }) - } - } - - let listRef: ListRef | undefined - function handleKey(e: KeyboardEvent) { - if (e.key === "Enter" && e.target instanceof HTMLInputElement) { - return - } - if (e.key === "Escape") return - listRef?.onKeyDown(e) - } - - onMount(() => { - if (methods().length === 1) { - selectMethod(0) - } - document.addEventListener("keydown", handleKey) - onCleanup(() => { - document.removeEventListener("keydown", handleKey) - }) - }) - - async function complete() { - await globalSDK.client.global.dispose() - dialog.close() - showToast({ - variant: "success", - icon: "circle-check", - title: `${provider().name} connected`, - description: `${provider().name} models are now available to use.`, - }) - } - - function goBack() { - if (methods().length === 1) { - dialog.show(() => ) - return - } - if (store.authorization) { - setStore("authorization", undefined) - setStore("methodIndex", undefined) - return - } - if (store.methodIndex) { - setStore("methodIndex", undefined) - return - } - dialog.show(() => ) - } - - return ( - }> -
-
- -
- - - Login with Claude Pro/Max - - Connect {provider().name} - -
-
-
- - -
Select login method for {provider().name}.
-
- { - listRef = ref - }} - items={methods} - key={(m) => m?.label} - onSelect={async (method, index) => { - if (!method) return - selectMethod(index) - }} - > - {(i) => ( -
-
- - {i.label} -
- )} - -
- - -
-
- - Authorization in progress... -
-
-
- -
-
- - Authorization failed: {store.error} -
-
-
- - {iife(() => { - const [formStore, setFormStore] = createStore({ - value: "", - error: undefined as string | undefined, - }) - - async function handleSubmit(e: SubmitEvent) { - e.preventDefault() - - const form = e.currentTarget as HTMLFormElement - const formData = new FormData(form) - const apiKey = formData.get("apiKey") as string - - if (!apiKey?.trim()) { - setFormStore("error", "API key is required") - return - } - - setFormStore("error", undefined) - await globalSDK.client.auth.set({ - providerID: props.provider, - auth: { - type: "api", - key: apiKey, - }, - }) - await complete() - } - - return ( -
- - -
-
- OpenCode Zen gives you access to a curated set of reliable optimized models for coding - agents. -
-
- With a single API key you'll get access to models such as Claude, GPT, Gemini, GLM and more. -
-
- Visit{" "} - - opencode.ai/zen - {" "} - to collect your API key. -
-
-
- -
- Enter your {provider().name} API key to connect your account and use {provider().name} models - in OpenCode. -
-
-
-
- - - -
- ) - })} -
- - - - {iife(() => { - const [formStore, setFormStore] = createStore({ - value: "", - error: undefined as string | undefined, - }) - - onMount(() => { - if (store.authorization?.method === "code" && store.authorization?.url) { - platform.openLink(store.authorization.url) - } - }) - - async function handleSubmit(e: SubmitEvent) { - e.preventDefault() - - const form = e.currentTarget as HTMLFormElement - const formData = new FormData(form) - const code = formData.get("code") as string - - if (!code?.trim()) { - setFormStore("error", "Authorization code is required") - return - } - - setFormStore("error", undefined) - const { error } = await globalSDK.client.provider.oauth.callback({ - providerID: props.provider, - method: store.methodIndex, - code, - }) - if (!error) { - await complete() - return - } - setFormStore("error", "Invalid authorization code") - } - - return ( -
-
- Visit this link to collect your authorization - code to connect your account and use {provider().name} models in OpenCode. -
-
- - - -
- ) - })} -
- - {iife(() => { - const code = createMemo(() => { - const instructions = store.authorization?.instructions - if (instructions?.includes(":")) { - return instructions?.split(":")[1]?.trim() - } - return instructions - }) - - onMount(async () => { - const result = await globalSDK.client.provider.oauth.callback({ - providerID: props.provider, - method: store.methodIndex, - }) - if (result.error) { - // TODO: show error - dialog.close() - return - } - await complete() - }) - - return ( -
-
- Visit this link and enter the code below to - connect your account and use {provider().name} models in OpenCode. -
- -
- - Waiting for authorization... -
-
- ) - })} -
-
-
- -
-
-
- ) -} diff --git a/packages/app/src/components/dialog-manage-models.tsx b/packages/app/src/components/dialog-manage-models.tsx deleted file mode 100644 index 66d125288..000000000 --- a/packages/app/src/components/dialog-manage-models.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { Dialog } from "@opencode-ai/ui/dialog" -import { List } from "@opencode-ai/ui/list" -import { Switch } from "@opencode-ai/ui/switch" -import type { Component } from "solid-js" -import { useLocal } from "@/context/local" -import { popularProviders } from "@/hooks/use-providers" - -export const DialogManageModels: Component = () => { - const local = useLocal() - return ( - - `${x?.provider?.id}:${x?.id}`} - items={local.model.list()} - filterKeys={["provider.name", "name", "id"]} - sortBy={(a, b) => a.name.localeCompare(b.name)} - groupBy={(x) => x.provider.name} - sortGroupsBy={(a, b) => { - const aProvider = a.items[0].provider.id - const bProvider = b.items[0].provider.id - if (popularProviders.includes(aProvider) && !popularProviders.includes(bProvider)) return -1 - if (!popularProviders.includes(aProvider) && popularProviders.includes(bProvider)) return 1 - return popularProviders.indexOf(aProvider) - popularProviders.indexOf(bProvider) - }} - onSelect={(x) => { - if (!x) return - const visible = local.model.visible({ - modelID: x.id, - providerID: x.provider.id, - }) - local.model.setVisibility({ modelID: x.id, providerID: x.provider.id }, !visible) - }} - > - {(i) => ( -
- {i.name} -
e.stopPropagation()}> - { - local.model.setVisibility({ modelID: i.id, providerID: i.provider.id }, checked) - }} - /> -
-
- )} -
-
- ) -} diff --git a/packages/app/src/components/dialog-select-file.tsx b/packages/app/src/components/dialog-select-file.tsx deleted file mode 100644 index b27afdc8b..000000000 --- a/packages/app/src/components/dialog-select-file.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { Dialog } from "@opencode-ai/ui/dialog" -import { FileIcon } from "@opencode-ai/ui/file-icon" -import { List } from "@opencode-ai/ui/list" -import { getDirectory, getFilename } from "@opencode-ai/util/path" -import { useParams } from "@solidjs/router" -import { createMemo } from "solid-js" -import { useLayout } from "@/context/layout" -import { useLocal } from "@/context/local" - -export function DialogSelectFile() { - const layout = useLayout() - const local = useLocal() - const dialog = useDialog() - const params = useParams() - const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) - const tabs = createMemo(() => layout.tabs(sessionKey())) - return ( - - x} - onSelect={(path) => { - if (path) { - tabs().open("file://" + path) - } - dialog.close() - }} - > - {(i) => ( -
-
- -
- - {getDirectory(i)} - - {getFilename(i)} -
-
-
- )} -
-
- ) -} diff --git a/packages/app/src/components/dialog-select-model-unpaid.tsx b/packages/app/src/components/dialog-select-model-unpaid.tsx deleted file mode 100644 index 24ec8092d..000000000 --- a/packages/app/src/components/dialog-select-model-unpaid.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { Button } from "@opencode-ai/ui/button" -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { Dialog } from "@opencode-ai/ui/dialog" -import type { IconName } from "@opencode-ai/ui/icons/provider" -import { List, type ListRef } from "@opencode-ai/ui/list" -import { ProviderIcon } from "@opencode-ai/ui/provider-icon" -import { Tag } from "@opencode-ai/ui/tag" -import { type Component, onCleanup, onMount, Show } from "solid-js" -import { useLocal } from "@/context/local" -import { popularProviders, useProviders } from "@/hooks/use-providers" -import { DialogConnectProvider } from "./dialog-connect-provider" -import { DialogSelectProvider } from "./dialog-select-provider" - -export const DialogSelectModelUnpaid: Component = () => { - const local = useLocal() - const dialog = useDialog() - const providers = useProviders() - - let listRef: ListRef | undefined - const handleKey = (e: KeyboardEvent) => { - if (e.key === "Escape") return - listRef?.onKeyDown(e) - } - - onMount(() => { - document.addEventListener("keydown", handleKey) - onCleanup(() => { - document.removeEventListener("keydown", handleKey) - }) - }) - - return ( - -
-
Free models provided by OpenCode
- (listRef = ref)} - items={local.model.list} - current={local.model.current()} - key={(x) => `${x.provider.id}:${x.id}`} - onSelect={(x) => { - local.model.set(x ? { modelID: x.id, providerID: x.provider.id } : undefined, { - recent: true, - }) - dialog.close() - }} - > - {(i) => ( -
- {i.name} - Free - - Latest - -
- )} -
-
-
-
-
-
-
-
Add more models from popular providers
-
- x?.id} - items={providers.popular} - activeIcon="plus-small" - sortBy={(a, b) => { - if (popularProviders.includes(a.id) && popularProviders.includes(b.id)) - return popularProviders.indexOf(a.id) - popularProviders.indexOf(b.id) - return a.name.localeCompare(b.name) - }} - onSelect={(x) => { - if (!x) return - dialog.show(() => ) - }} - > - {(i) => ( -
- - {i.name} - - Recommended - - -
Connect with Claude Pro/Max or API key
-
-
- )} -
- -
-
-
-
-
- ) -} diff --git a/packages/app/src/components/dialog-select-model.tsx b/packages/app/src/components/dialog-select-model.tsx deleted file mode 100644 index 54783386a..000000000 --- a/packages/app/src/components/dialog-select-model.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { Component, createMemo, Show } from "solid-js" -import { useLocal } from "@/context/local" -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { popularProviders } from "@/hooks/use-providers" -import { Button } from "@opencode-ai/ui/button" -import { Tag } from "@opencode-ai/ui/tag" -import { Dialog } from "@opencode-ai/ui/dialog" -import { List } from "@opencode-ai/ui/list" -import { DialogSelectProvider } from "./dialog-select-provider" -import { DialogManageModels } from "./dialog-manage-models" - -export const DialogSelectModel: Component<{ provider?: string }> = (props) => { - const local = useLocal() - const dialog = useDialog() - - const models = createMemo(() => - local.model - .list() - .filter((m) => local.model.visible({ modelID: m.id, providerID: m.provider.id })) - .filter((m) => (props.provider ? m.provider.id === props.provider : true)), - ) - - return ( - dialog.show(() => )} - > - Connect provider - - } - > - `${x.provider.id}:${x.id}`} - items={models} - current={local.model.current()} - filterKeys={["provider.name", "name", "id"]} - sortBy={(a, b) => a.name.localeCompare(b.name)} - groupBy={(x) => x.provider.name} - sortGroupsBy={(a, b) => { - if (a.category === "Recent" && b.category !== "Recent") return -1 - if (b.category === "Recent" && a.category !== "Recent") return 1 - const aProvider = a.items[0].provider.id - const bProvider = b.items[0].provider.id - if (popularProviders.includes(aProvider) && !popularProviders.includes(bProvider)) return -1 - if (!popularProviders.includes(aProvider) && popularProviders.includes(bProvider)) return 1 - return popularProviders.indexOf(aProvider) - popularProviders.indexOf(bProvider) - }} - onSelect={(x) => { - local.model.set(x ? { modelID: x.id, providerID: x.provider.id } : undefined, { - recent: true, - }) - dialog.close() - }} - > - {(i) => ( -
- {i.name} - - Free - - - Latest - -
- )} -
- -
- ) -} diff --git a/packages/app/src/components/dialog-select-provider.tsx b/packages/app/src/components/dialog-select-provider.tsx deleted file mode 100644 index 5bbde5d41..000000000 --- a/packages/app/src/components/dialog-select-provider.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { Component, Show } from "solid-js" -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { popularProviders, useProviders } from "@/hooks/use-providers" -import { Dialog } from "@opencode-ai/ui/dialog" -import { List } from "@opencode-ai/ui/list" -import { Tag } from "@opencode-ai/ui/tag" -import { ProviderIcon } from "@opencode-ai/ui/provider-icon" -import { IconName } from "@opencode-ai/ui/icons/provider" -import { DialogConnectProvider } from "./dialog-connect-provider" - -export const DialogSelectProvider: Component = () => { - const dialog = useDialog() - const providers = useProviders() - - return ( - - x?.id} - items={providers.all} - filterKeys={["id", "name"]} - groupBy={(x) => (popularProviders.includes(x.id) ? "Popular" : "Other")} - sortBy={(a, b) => { - if (popularProviders.includes(a.id) && popularProviders.includes(b.id)) - return popularProviders.indexOf(a.id) - popularProviders.indexOf(b.id) - return a.name.localeCompare(b.name) - }} - sortGroupsBy={(a, b) => { - if (a.category === "Popular" && b.category !== "Popular") return -1 - if (b.category === "Popular" && a.category !== "Popular") return 1 - return 0 - }} - onSelect={(x) => { - if (!x) return - dialog.show(() => ) - }} - > - {(i) => ( -
- - {i.name} - - Recommended - - -
Connect with Claude Pro/Max or API key
-
-
- )} -
-
- ) -} diff --git a/packages/app/src/components/header.tsx b/packages/app/src/components/header.tsx deleted file mode 100644 index ec7cdfa25..000000000 --- a/packages/app/src/components/header.tsx +++ /dev/null @@ -1,209 +0,0 @@ -import { useGlobalSync } from "@/context/global-sync" -import { useGlobalSDK } from "@/context/global-sdk" -import { useLayout } from "@/context/layout" -import { Session } from "@opencode-ai/sdk/v2/client" -import { Button } from "@opencode-ai/ui/button" -import { Icon } from "@opencode-ai/ui/icon" -import { Mark } from "@opencode-ai/ui/logo" -import { Popover } from "@opencode-ai/ui/popover" -import { Select } from "@opencode-ai/ui/select" -import { TextField } from "@opencode-ai/ui/text-field" -import { Tooltip } from "@opencode-ai/ui/tooltip" -import { base64Decode } from "@opencode-ai/util/encode" -import { useCommand } from "@/context/command" -import { getFilename } from "@opencode-ai/util/path" -import { A, useParams } from "@solidjs/router" -import { createMemo, createResource, Show } from "solid-js" -import { IconButton } from "@opencode-ai/ui/icon-button" -import { iife } from "@opencode-ai/util/iife" - -export function Header(props: { - navigateToProject: (directory: string) => void - navigateToSession: (session: Session | undefined) => void - onMobileMenuToggle?: () => void -}) { - const globalSync = useGlobalSync() - const globalSDK = useGlobalSDK() - const layout = useLayout() - const params = useParams() - const command = useCommand() - - return ( -
- - - - -
- 0 && params.dir}> - {(directory) => { - const currentDirectory = createMemo(() => base64Decode(directory())) - const store = createMemo(() => globalSync.child(currentDirectory())[0]) - const sessions = createMemo(() => (store().session ?? []).filter((s) => !s.parentID)) - const currentSession = createMemo(() => sessions().find((s) => s.id === params.id)) - const shareEnabled = createMemo(() => store().config.share !== "disabled") - return ( - <> -
-
- - agent.name)} - current={local.agent.current().name} - onSelect={local.agent.set} - class="capitalize" - variant="ghost" - /> - - - Choose model - {command.keybind("model.choose")} -
- } - > - - - - - -
-
- { - const file = e.currentTarget.files?.[0] - if (file) addImageAttachment(file) - e.currentTarget.value = "" - }} - /> - - - fileInputRef.click()} - /> - - - - -
- Stop - ESC -
-
- -
- Send - -
-
- - } - > - -
-
-
- - - ) -} - -function getCursorPosition(parent: HTMLElement): number { - const selection = window.getSelection() - if (!selection || selection.rangeCount === 0) return 0 - const range = selection.getRangeAt(0) - const preCaretRange = range.cloneRange() - preCaretRange.selectNodeContents(parent) - preCaretRange.setEnd(range.startContainer, range.startOffset) - return preCaretRange.toString().length -} - -function setCursorPosition(parent: HTMLElement, position: number) { - let remaining = position - let node = parent.firstChild - while (node) { - const length = node.textContent ? node.textContent.length : 0 - const isText = node.nodeType === Node.TEXT_NODE - const isFile = node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).dataset.type === "file" - - if (isText && remaining <= length) { - const range = document.createRange() - const selection = window.getSelection() - range.setStart(node, remaining) - range.collapse(true) - selection?.removeAllRanges() - selection?.addRange(range) - return - } - - if (isFile && remaining <= length) { - const range = document.createRange() - const selection = window.getSelection() - range.setStartAfter(node) - range.collapse(true) - selection?.removeAllRanges() - selection?.addRange(range) - return - } - - remaining -= length - node = node.nextSibling - } - - const fallbackRange = document.createRange() - const fallbackSelection = window.getSelection() - const last = parent.lastChild - if (last && last.nodeType === Node.TEXT_NODE) { - const len = last.textContent ? last.textContent.length : 0 - fallbackRange.setStart(last, len) - } - if (!last || last.nodeType !== Node.TEXT_NODE) { - fallbackRange.selectNodeContents(parent) - } - fallbackRange.collapse(false) - fallbackSelection?.removeAllRanges() - fallbackSelection?.addRange(fallbackRange) -} diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx deleted file mode 100644 index 5474005c7..000000000 --- a/packages/app/src/components/session-context-usage.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { createMemo, Show } from "solid-js" -import { Tooltip } from "@opencode-ai/ui/tooltip" -import { ProgressCircle } from "@opencode-ai/ui/progress-circle" -import { useSync } from "@/context/sync" -import { useParams } from "@solidjs/router" -import { AssistantMessage } from "@opencode-ai/sdk/v2" - -export function SessionContextUsage() { - const sync = useSync() - const params = useParams() - const messages = createMemo(() => (params.id ? (sync.data.message[params.id] ?? []) : [])) - - const cost = createMemo(() => { - const total = messages().reduce((sum, x) => sum + (x.role === "assistant" ? x.cost : 0), 0) - return new Intl.NumberFormat("en-US", { - style: "currency", - currency: "USD", - }).format(total) - }) - - const context = createMemo(() => { - const last = messages().findLast((x) => x.role === "assistant" && x.tokens.output > 0) as AssistantMessage - if (!last) return - const total = - last.tokens.input + last.tokens.output + last.tokens.reasoning + last.tokens.cache.read + last.tokens.cache.write - const model = sync.data.provider.all.find((x) => x.id === last.providerID)?.models[last.modelID] - return { - tokens: total.toLocaleString(), - percentage: model?.limit.context ? Math.round((total / model.limit.context) * 100) : null, - } - }) - - return ( - - {(ctx) => ( - -
- Tokens - {ctx().tokens} -
-
- Usage - {ctx().percentage ?? 0}% -
-
- Cost - {cost()} -
- - } - placement="top" - > -
- {`${ctx().percentage ?? 0}%`} - -
-
- )} -
- ) -} diff --git a/packages/app/src/components/terminal.tsx b/packages/app/src/components/terminal.tsx deleted file mode 100644 index c05ddfbf6..000000000 --- a/packages/app/src/components/terminal.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { Ghostty, Terminal as Term, FitAddon } from "ghostty-web" -import { ComponentProps, onCleanup, onMount, splitProps } from "solid-js" -import { useSDK } from "@/context/sdk" -import { SerializeAddon } from "@/addons/serialize" -import { LocalPTY } from "@/context/terminal" -import { usePrefersDark } from "@solid-primitives/media" - -export interface TerminalProps extends ComponentProps<"div"> { - pty: LocalPTY - onSubmit?: () => void - onCleanup?: (pty: LocalPTY) => void - onConnectError?: (error: unknown) => void -} - -export const Terminal = (props: TerminalProps) => { - const sdk = useSDK() - let container!: HTMLDivElement - const [local, others] = splitProps(props, ["pty", "class", "classList", "onConnectError"]) - let ws: WebSocket - let term: Term - let ghostty: Ghostty - let serializeAddon: SerializeAddon - let fitAddon: FitAddon - let handleResize: () => void - const prefersDark = usePrefersDark() - - onMount(async () => { - ghostty = await Ghostty.load() - - ws = new WebSocket(sdk.url + `/pty/${local.pty.id}/connect?directory=${encodeURIComponent(sdk.directory)}`) - term = new Term({ - cursorBlink: true, - fontSize: 14, - fontFamily: "IBM Plex Mono, monospace", - allowTransparency: true, - theme: prefersDark() - ? { - background: "#191515", - foreground: "#d4d4d4", - cursor: "#d4d4d4", - } - : { - background: "#fcfcfc", - foreground: "#211e1e", - cursor: "#211e1e", - }, - scrollback: 10_000, - ghostty, - }) - term.attachCustomKeyEventHandler((event) => { - // allow for ctrl-` to toggle terminal in parent - if (event.ctrlKey && event.key.toLowerCase() === "`") { - event.preventDefault() - return true - } - return false - }) - - fitAddon = new FitAddon() - serializeAddon = new SerializeAddon() - term.loadAddon(serializeAddon) - term.loadAddon(fitAddon) - - term.open(container) - - if (local.pty.buffer) { - if (local.pty.rows && local.pty.cols) { - term.resize(local.pty.cols, local.pty.rows) - } - term.reset() - term.write(local.pty.buffer) - if (local.pty.scrollY) { - term.scrollToLine(local.pty.scrollY) - } - fitAddon.fit() - } - - container.focus() - - fitAddon.observeResize() - handleResize = () => fitAddon.fit() - window.addEventListener("resize", handleResize) - term.onResize(async (size) => { - if (ws && ws.readyState === WebSocket.OPEN) { - await sdk.client.pty.update({ - ptyID: local.pty.id, - size: { - cols: size.cols, - rows: size.rows, - }, - }) - } - }) - term.onData((data) => { - if (ws && ws.readyState === WebSocket.OPEN) { - ws.send(data) - } - }) - term.onKey((key) => { - if (key.key == "Enter") { - props.onSubmit?.() - } - }) - // term.onScroll((ydisp) => { - // console.log("Scroll position:", ydisp) - // }) - ws.addEventListener("open", () => { - console.log("WebSocket connected") - sdk.client.pty.update({ - ptyID: local.pty.id, - size: { - cols: term.cols, - rows: term.rows, - }, - }) - }) - ws.addEventListener("message", (event) => { - term.write(event.data) - }) - ws.addEventListener("error", (error) => { - console.error("WebSocket error:", error) - props.onConnectError?.(error) - }) - ws.addEventListener("close", () => { - console.log("WebSocket disconnected") - }) - }) - - onCleanup(() => { - if (handleResize) { - window.removeEventListener("resize", handleResize) - } - if (serializeAddon && props.onCleanup) { - const buffer = serializeAddon.serialize() - props.onCleanup({ - ...local.pty, - buffer, - rows: term.rows, - cols: term.cols, - scrollY: term.getViewportY(), - }) - } - ws?.close() - term?.dispose() - }) - - return ( -
- ) -} diff --git a/packages/app/src/context/command.tsx b/packages/app/src/context/command.tsx deleted file mode 100644 index f91a1cf05..000000000 --- a/packages/app/src/context/command.tsx +++ /dev/null @@ -1,243 +0,0 @@ -import { createMemo, createSignal, onCleanup, onMount, Show, type Accessor } from "solid-js" -import { createSimpleContext } from "@opencode-ai/ui/context" -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { Dialog } from "@opencode-ai/ui/dialog" -import { List } from "@opencode-ai/ui/list" - -const IS_MAC = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) - -export type KeybindConfig = string - -export interface Keybind { - key: string - ctrl: boolean - meta: boolean - shift: boolean - alt: boolean -} - -export interface CommandOption { - id: string - title: string - description?: string - category?: string - keybind?: KeybindConfig - slash?: string - suggested?: boolean - disabled?: boolean - onSelect?: (source?: "palette" | "keybind" | "slash") => void -} - -export function parseKeybind(config: string): Keybind[] { - if (!config || config === "none") return [] - - return config.split(",").map((combo) => { - const parts = combo.trim().toLowerCase().split("+") - const keybind: Keybind = { - key: "", - ctrl: false, - meta: false, - shift: false, - alt: false, - } - - for (const part of parts) { - switch (part) { - case "ctrl": - case "control": - keybind.ctrl = true - break - case "meta": - case "cmd": - case "command": - keybind.meta = true - break - case "mod": - if (IS_MAC) keybind.meta = true - else keybind.ctrl = true - break - case "alt": - case "option": - keybind.alt = true - break - case "shift": - keybind.shift = true - break - default: - keybind.key = part - break - } - } - - return keybind - }) -} - -export function matchKeybind(keybinds: Keybind[], event: KeyboardEvent): boolean { - const eventKey = event.key.toLowerCase() - - for (const kb of keybinds) { - const keyMatch = kb.key === eventKey - const ctrlMatch = kb.ctrl === (event.ctrlKey || false) - const metaMatch = kb.meta === (event.metaKey || false) - const shiftMatch = kb.shift === (event.shiftKey || false) - const altMatch = kb.alt === (event.altKey || false) - - if (keyMatch && ctrlMatch && metaMatch && shiftMatch && altMatch) { - return true - } - } - - return false -} - -export function formatKeybind(config: string): string { - if (!config || config === "none") return "" - - const keybinds = parseKeybind(config) - if (keybinds.length === 0) return "" - - const kb = keybinds[0] - const parts: string[] = [] - - if (kb.ctrl) parts.push(IS_MAC ? "⌃" : "Ctrl") - if (kb.alt) parts.push(IS_MAC ? "⌥" : "Alt") - if (kb.shift) parts.push(IS_MAC ? "⇧" : "Shift") - if (kb.meta) parts.push(IS_MAC ? "⌘" : "Meta") - - if (kb.key) { - const displayKey = kb.key.length === 1 ? kb.key.toUpperCase() : kb.key.charAt(0).toUpperCase() + kb.key.slice(1) - parts.push(displayKey) - } - - return IS_MAC ? parts.join("") : parts.join("+") -} - -function DialogCommand(props: { options: CommandOption[] }) { - const dialog = useDialog() - - return ( - - props.options.filter((x) => !x.id.startsWith("suggested.") || !x.disabled)} - key={(x) => x?.id} - filterKeys={["title", "description", "category"]} - groupBy={(x) => x.category ?? ""} - onSelect={(option) => { - if (option) { - dialog.close() - option.onSelect?.("palette") - } - }} - > - {(option) => ( -
-
- {option.title} - - {option.description} - -
- - {formatKeybind(option.keybind!)} - -
- )} -
-
- ) -} - -export const { use: useCommand, provider: CommandProvider } = createSimpleContext({ - name: "Command", - init: () => { - const [registrations, setRegistrations] = createSignal[]>([]) - const [suspendCount, setSuspendCount] = createSignal(0) - const dialog = useDialog() - - const options = createMemo(() => { - const all = registrations().flatMap((x) => x()) - const suggested = all.filter((x) => x.suggested && !x.disabled) - return [ - ...suggested.map((x) => ({ - ...x, - id: "suggested." + x.id, - category: "Suggested", - })), - ...all, - ] - }) - - const suspended = () => suspendCount() > 0 - - const showPalette = () => { - if (!dialog.active) { - dialog.show(() => !x.disabled)} />) - } - } - - const handleKeyDown = (event: KeyboardEvent) => { - if (suspended()) return - - const paletteKeybinds = parseKeybind("mod+shift+p") - if (matchKeybind(paletteKeybinds, event)) { - event.preventDefault() - showPalette() - return - } - - for (const option of options()) { - if (option.disabled) continue - if (!option.keybind) continue - - const keybinds = parseKeybind(option.keybind) - if (matchKeybind(keybinds, event)) { - event.preventDefault() - option.onSelect?.("keybind") - return - } - } - } - - onMount(() => { - document.addEventListener("keydown", handleKeyDown) - }) - - onCleanup(() => { - document.removeEventListener("keydown", handleKeyDown) - }) - - return { - register(cb: () => CommandOption[]) { - const results = createMemo(cb) - setRegistrations((arr) => [results, ...arr]) - onCleanup(() => { - setRegistrations((arr) => arr.filter((x) => x !== results)) - }) - }, - trigger(id: string, source?: "palette" | "keybind" | "slash") { - for (const option of options()) { - if (option.id === id || option.id === "suggested." + id) { - option.onSelect?.(source) - return - } - } - }, - keybind(id: string) { - const option = options().find((x) => x.id === id || x.id === "suggested." + id) - if (!option?.keybind) return "" - return formatKeybind(option.keybind) - }, - show: showPalette, - keybinds(enabled: boolean) { - setSuspendCount((count) => count + (enabled ? -1 : 1)) - }, - suspended, - get options() { - return options() - }, - } - }, -}) diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx deleted file mode 100644 index ae40555d6..000000000 --- a/packages/app/src/context/global-sync.tsx +++ /dev/null @@ -1,376 +0,0 @@ -import { - type Message, - type Agent, - type Session, - type Part, - type Config, - type Path, - type File, - type FileNode, - type Project, - type FileDiff, - type Todo, - type SessionStatus, - type ProviderListResponse, - type ProviderAuthResponse, - type Command, - createOpencodeClient, -} from "@opencode-ai/sdk/v2/client" -import { createStore, produce, reconcile } from "solid-js/store" -import { Binary } from "@opencode-ai/util/binary" -import { retry } from "@opencode-ai/util/retry" -import { useGlobalSDK } from "./global-sdk" -import { ErrorPage, type InitError } from "../pages/error" -import { createContext, useContext, onMount, type ParentProps, Switch, Match } from "solid-js" -import { showToast } from "@opencode-ai/ui/toast" -import { getFilename } from "@opencode-ai/util/path" - -type State = { - ready: boolean - agent: Agent[] - command: Command[] - project: string - provider: ProviderListResponse - config: Config - path: Path - session: Session[] - session_status: { - [sessionID: string]: SessionStatus - } - session_diff: { - [sessionID: string]: FileDiff[] - } - todo: { - [sessionID: string]: Todo[] - } - limit: number - message: { - [sessionID: string]: Message[] - } - part: { - [messageID: string]: Part[] - } - node: FileNode[] - changes: File[] -} - -function createGlobalSync() { - const globalSDK = useGlobalSDK() - const [globalStore, setGlobalStore] = createStore<{ - ready: boolean - error?: InitError - path: Path - project: Project[] - provider: ProviderListResponse - provider_auth: ProviderAuthResponse - children: Record - }>({ - ready: false, - path: { state: "", config: "", worktree: "", directory: "", home: "" }, - project: [], - provider: { all: [], connected: [], default: {} }, - provider_auth: {}, - children: {}, - }) - - const children: Record>> = {} - function child(directory: string) { - if (!directory) console.error("No directory provided") - if (!children[directory]) { - setGlobalStore("children", directory, { - project: "", - provider: { all: [], connected: [], default: {} }, - config: {}, - path: { state: "", config: "", worktree: "", directory: "", home: "" }, - ready: false, - agent: [], - command: [], - session: [], - session_status: {}, - session_diff: {}, - todo: {}, - limit: 5, - message: {}, - part: {}, - node: [], - changes: [], - }) - children[directory] = createStore(globalStore.children[directory]) - bootstrapInstance(directory) - } - return children[directory] - } - - async function loadSessions(directory: string) { - const [store, setStore] = child(directory) - globalSDK.client.session - .list({ directory }) - .then((x) => { - const fourHoursAgo = Date.now() - 4 * 60 * 60 * 1000 - const nonArchived = (x.data ?? []) - .slice() - .filter((s) => !s.time.archived) - .sort((a, b) => a.id.localeCompare(b.id)) - // Include up to the limit, plus any updated in the last 4 hours - const sessions = nonArchived.filter((s, i) => { - if (i < store.limit) return true - const updated = new Date(s.time.updated).getTime() - return updated > fourHoursAgo - }) - setStore("session", sessions) - }) - .catch((err) => { - console.error("Failed to load sessions", err) - const project = getFilename(directory) - showToast({ title: `Failed to load sessions for ${project}`, description: err.message }) - }) - } - - async function bootstrapInstance(directory: string) { - if (!directory) return - const [, setStore] = child(directory) - const sdk = createOpencodeClient({ - baseUrl: globalSDK.url, - directory, - throwOnError: true, - }) - const load = { - project: () => sdk.project.current().then((x) => setStore("project", x.data!.id)), - provider: () => sdk.provider.list().then((x) => setStore("provider", x.data!)), - path: () => sdk.path.get().then((x) => setStore("path", x.data!)), - agent: () => sdk.app.agents().then((x) => setStore("agent", x.data ?? [])), - command: () => sdk.command.list().then((x) => setStore("command", x.data ?? [])), - session: () => loadSessions(directory), - status: () => sdk.session.status().then((x) => setStore("session_status", x.data!)), - config: () => sdk.config.get().then((x) => setStore("config", x.data!)), - changes: () => sdk.file.status().then((x) => setStore("changes", x.data!)), - node: () => sdk.file.list({ path: "/" }).then((x) => setStore("node", x.data!)), - } - await Promise.all(Object.values(load).map((p) => retry(p).catch((e) => setGlobalStore("error", e)))) - .then(() => setStore("ready", true)) - .catch((e) => setGlobalStore("error", e)) - } - - globalSDK.event.listen((e) => { - const directory = e.name - const event = e.details - - if (directory === "global") { - switch (event?.type) { - case "global.disposed": { - bootstrap() - break - } - case "project.updated": { - const result = Binary.search(globalStore.project, event.properties.id, (s) => s.id) - if (result.found) { - setGlobalStore("project", result.index, reconcile(event.properties)) - return - } - setGlobalStore( - "project", - produce((draft) => { - draft.splice(result.index, 0, event.properties) - }), - ) - break - } - } - return - } - - const [store, setStore] = child(directory) - switch (event.type) { - case "server.instance.disposed": { - bootstrapInstance(directory) - break - } - case "session.updated": { - const result = Binary.search(store.session, event.properties.info.id, (s) => s.id) - if (event.properties.info.time.archived) { - if (result.found) { - setStore( - "session", - produce((draft) => { - draft.splice(result.index, 1) - }), - ) - } - break - } - if (result.found) { - setStore("session", result.index, reconcile(event.properties.info)) - break - } - setStore( - "session", - produce((draft) => { - draft.splice(result.index, 0, event.properties.info) - }), - ) - break - } - case "session.diff": - setStore("session_diff", event.properties.sessionID, event.properties.diff) - break - case "todo.updated": - setStore("todo", event.properties.sessionID, event.properties.todos) - break - case "session.status": { - setStore("session_status", event.properties.sessionID, event.properties.status) - break - } - case "message.updated": { - const messages = store.message[event.properties.info.sessionID] - if (!messages) { - setStore("message", event.properties.info.sessionID, [event.properties.info]) - break - } - const result = Binary.search(messages, event.properties.info.id, (m) => m.id) - if (result.found) { - setStore("message", event.properties.info.sessionID, result.index, reconcile(event.properties.info)) - break - } - setStore( - "message", - event.properties.info.sessionID, - produce((draft) => { - draft.splice(result.index, 0, event.properties.info) - }), - ) - break - } - case "message.removed": { - const messages = store.message[event.properties.sessionID] - if (!messages) break - const result = Binary.search(messages, event.properties.messageID, (m) => m.id) - if (result.found) { - setStore( - "message", - event.properties.sessionID, - produce((draft) => { - draft.splice(result.index, 1) - }), - ) - } - break - } - case "message.part.updated": { - const part = event.properties.part - const parts = store.part[part.messageID] - if (!parts) { - setStore("part", part.messageID, [part]) - break - } - const result = Binary.search(parts, part.id, (p) => p.id) - if (result.found) { - setStore("part", part.messageID, result.index, reconcile(part)) - break - } - setStore( - "part", - part.messageID, - produce((draft) => { - draft.splice(result.index, 0, part) - }), - ) - break - } - case "message.part.removed": { - const parts = store.part[event.properties.messageID] - if (!parts) break - const result = Binary.search(parts, event.properties.partID, (p) => p.id) - if (result.found) { - setStore( - "part", - event.properties.messageID, - produce((draft) => { - draft.splice(result.index, 1) - }), - ) - } - break - } - } - }) - - async function bootstrap() { - const health = await globalSDK.client.global.health().then((x) => x.data) - if (!health?.healthy) { - setGlobalStore( - "error", - new Error(`Could not connect to server. Is there a server running at \`${globalSDK.url}\`?`), - ) - return - } - - return Promise.all([ - retry(() => - globalSDK.client.path.get().then((x) => { - setGlobalStore("path", x.data!) - }), - ), - retry(() => - globalSDK.client.project.list().then(async (x) => { - setGlobalStore( - "project", - x.data!.filter((p) => !p.worktree.includes("opencode-test")).sort((a, b) => a.id.localeCompare(b.id)), - ) - }), - ), - retry(() => - globalSDK.client.provider.list().then((x) => { - setGlobalStore("provider", x.data ?? {}) - }), - ), - retry(() => - globalSDK.client.provider.auth().then((x) => { - setGlobalStore("provider_auth", x.data ?? {}) - }), - ), - ]) - .then(() => setGlobalStore("ready", true)) - .catch((e) => setGlobalStore("error", e)) - } - - onMount(() => { - bootstrap() - }) - - return { - data: globalStore, - get ready() { - return globalStore.ready - }, - get error() { - return globalStore.error - }, - child, - bootstrap, - project: { - loadSessions, - }, - } -} - -const GlobalSyncContext = createContext>() - -export function GlobalSyncProvider(props: ParentProps) { - const value = createGlobalSync() - return ( - - - - - - {props.children} - - - ) -} - -export function useGlobalSync() { - const context = useContext(GlobalSyncContext) - if (!context) throw new Error("useGlobalSync must be used within GlobalSyncProvider") - return context -} diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx deleted file mode 100644 index c6ba5fef5..000000000 --- a/packages/app/src/context/layout.tsx +++ /dev/null @@ -1,260 +0,0 @@ -import { createStore, produce } from "solid-js/store" -import { batch, createMemo, onMount } from "solid-js" -import { createSimpleContext } from "@opencode-ai/ui/context" -import { useGlobalSync } from "./global-sync" -import { useGlobalSDK } from "./global-sdk" -import { Project } from "@opencode-ai/sdk/v2" -import { persisted } from "@/utils/persist" - -const AVATAR_COLOR_KEYS = ["pink", "mint", "orange", "purple", "cyan", "lime"] as const -export type AvatarColorKey = (typeof AVATAR_COLOR_KEYS)[number] - -export function getAvatarColors(key?: string) { - if (key && AVATAR_COLOR_KEYS.includes(key as AvatarColorKey)) { - return { - background: `var(--avatar-background-${key})`, - foreground: `var(--avatar-text-${key})`, - } - } - return { - background: "var(--surface-info-base)", - foreground: "var(--text-base)", - } -} - -type SessionTabs = { - active?: string - all: string[] -} - -export type LocalProject = Partial & { worktree: string; expanded: boolean } - -export const { use: useLayout, provider: LayoutProvider } = createSimpleContext({ - name: "Layout", - init: () => { - const globalSdk = useGlobalSDK() - const globalSync = useGlobalSync() - const [store, setStore, _, ready] = persisted( - "layout.v3", - createStore({ - projects: [] as { worktree: string; expanded: boolean }[], - sidebar: { - opened: false, - width: 280, - }, - terminal: { - opened: false, - height: 280, - }, - review: { - opened: true, - }, - session: { - width: 600, - }, - sessionTabs: {} as Record, - }), - ) - - const usedColors = new Set() - - function pickAvailableColor(): AvatarColorKey { - const available = AVATAR_COLOR_KEYS.filter((c) => !usedColors.has(c)) - if (available.length === 0) return AVATAR_COLOR_KEYS[Math.floor(Math.random() * AVATAR_COLOR_KEYS.length)] - return available[Math.floor(Math.random() * available.length)] - } - - function enrich(project: { worktree: string; expanded: boolean }) { - const metadata = globalSync.data.project.find((x) => x.worktree === project.worktree) - return [ - { - ...project, - ...(metadata ?? {}), - }, - ] - } - - function colorize(project: LocalProject) { - if (project.icon?.color) return project - const color = pickAvailableColor() - usedColors.add(color) - project.icon = { ...project.icon, color } - if (project.id) { - globalSdk.client.project.update({ projectID: project.id, icon: { color } }) - } - return project - } - - const enriched = createMemo(() => store.projects.flatMap(enrich)) - const list = createMemo(() => enriched().flatMap(colorize)) - - onMount(() => { - Promise.all( - store.projects.map((project) => { - return globalSync.project.loadSessions(project.worktree) - }), - ) - }) - - return { - ready, - projects: { - list, - open(directory: string) { - if (store.projects.find((x) => x.worktree === directory)) { - return - } - globalSync.project.loadSessions(directory) - setStore("projects", (x) => [{ worktree: directory, expanded: true }, ...x]) - }, - close(directory: string) { - setStore("projects", (x) => x.filter((x) => x.worktree !== directory)) - }, - expand(directory: string) { - const index = store.projects.findIndex((x) => x.worktree === directory) - if (index !== -1) setStore("projects", index, "expanded", true) - }, - collapse(directory: string) { - const index = store.projects.findIndex((x) => x.worktree === directory) - if (index !== -1) setStore("projects", index, "expanded", false) - }, - move(directory: string, toIndex: number) { - setStore("projects", (projects) => { - const fromIndex = projects.findIndex((x) => x.worktree === directory) - if (fromIndex === -1 || fromIndex === toIndex) return projects - const result = [...projects] - const [item] = result.splice(fromIndex, 1) - result.splice(toIndex, 0, item) - return result - }) - }, - }, - sidebar: { - opened: createMemo(() => store.sidebar.opened), - open() { - setStore("sidebar", "opened", true) - }, - close() { - setStore("sidebar", "opened", false) - }, - toggle() { - setStore("sidebar", "opened", (x) => !x) - }, - width: createMemo(() => store.sidebar.width), - resize(width: number) { - setStore("sidebar", "width", width) - }, - }, - terminal: { - opened: createMemo(() => store.terminal.opened), - open() { - setStore("terminal", "opened", true) - }, - close() { - setStore("terminal", "opened", false) - }, - toggle() { - setStore("terminal", "opened", (x) => !x) - }, - height: createMemo(() => store.terminal.height), - resize(height: number) { - setStore("terminal", "height", height) - }, - }, - review: { - opened: createMemo(() => store.review?.opened ?? true), - open() { - setStore("review", "opened", true) - }, - close() { - setStore("review", "opened", false) - }, - toggle() { - setStore("review", "opened", (x) => !x) - }, - }, - session: { - width: createMemo(() => store.session?.width ?? 600), - resize(width: number) { - if (!store.session) { - setStore("session", { width }) - } else { - setStore("session", "width", width) - } - }, - }, - tabs(sessionKey: string) { - const tabs = createMemo(() => store.sessionTabs[sessionKey] ?? { all: [] }) - return { - tabs, - active: createMemo(() => tabs().active), - all: createMemo(() => tabs().all), - setActive(tab: string | undefined) { - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all: [], active: tab }) - } else { - setStore("sessionTabs", sessionKey, "active", tab) - } - }, - setAll(all: string[]) { - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all, active: undefined }) - } else { - setStore("sessionTabs", sessionKey, "all", all) - } - }, - async open(tab: string) { - const current = store.sessionTabs[sessionKey] ?? { all: [] } - if (tab !== "review") { - if (!current.all.includes(tab)) { - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all: [tab], active: tab }) - } else { - setStore("sessionTabs", sessionKey, "all", [...current.all, tab]) - setStore("sessionTabs", sessionKey, "active", tab) - } - return - } - } - if (!store.sessionTabs[sessionKey]) { - setStore("sessionTabs", sessionKey, { all: [], active: tab }) - } else { - setStore("sessionTabs", sessionKey, "active", tab) - } - }, - close(tab: string) { - const current = store.sessionTabs[sessionKey] - if (!current) return - batch(() => { - setStore( - "sessionTabs", - sessionKey, - "all", - current.all.filter((x) => x !== tab), - ) - if (current.active === tab) { - const index = current.all.findIndex((f) => f === tab) - const previous = current.all[Math.max(0, index - 1)] - setStore("sessionTabs", sessionKey, "active", previous) - } - }) - }, - move(tab: string, to: number) { - const current = store.sessionTabs[sessionKey] - if (!current) return - const index = current.all.findIndex((f) => f === tab) - if (index === -1) return - setStore( - "sessionTabs", - sessionKey, - "all", - produce((opened) => { - opened.splice(to, 0, opened.splice(index, 1)[0]) - }), - ) - }, - } - }, - } - }, -}) diff --git a/packages/app/src/context/notification.tsx b/packages/app/src/context/notification.tsx deleted file mode 100644 index 2b258ebd6..000000000 --- a/packages/app/src/context/notification.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { createStore } from "solid-js/store" -import { createSimpleContext } from "@opencode-ai/ui/context" -import { useGlobalSDK } from "./global-sdk" -import { useGlobalSync } from "./global-sync" -import { Binary } from "@opencode-ai/util/binary" -import { EventSessionError } from "@opencode-ai/sdk/v2" -import { makeAudioPlayer } from "@solid-primitives/audio" -import idleSound from "@opencode-ai/ui/audio/staplebops-01.aac" -import errorSound from "@opencode-ai/ui/audio/nope-03.aac" -import { persisted } from "@/utils/persist" - -type NotificationBase = { - directory?: string - session?: string - metadata?: any - time: number - viewed: boolean -} - -type TurnCompleteNotification = NotificationBase & { - type: "turn-complete" -} - -type ErrorNotification = NotificationBase & { - type: "error" - error: EventSessionError["properties"]["error"] -} - -export type Notification = TurnCompleteNotification | ErrorNotification - -export const { use: useNotification, provider: NotificationProvider } = createSimpleContext({ - name: "Notification", - init: () => { - let idlePlayer: ReturnType | undefined - let errorPlayer: ReturnType | undefined - - try { - idlePlayer = makeAudioPlayer(idleSound) - errorPlayer = makeAudioPlayer(errorSound) - } catch (err) { - console.log("Failed to load audio", err) - } - - const globalSDK = useGlobalSDK() - const globalSync = useGlobalSync() - - const [store, setStore, _, ready] = persisted( - "notification.v1", - createStore({ - list: [] as Notification[], - }), - ) - - globalSDK.event.listen((e) => { - const directory = e.name - const event = e.details - const base = { - directory, - time: Date.now(), - viewed: false, - } - switch (event.type) { - case "session.idle": { - const sessionID = event.properties.sessionID - const [syncStore] = globalSync.child(directory) - const match = Binary.search(syncStore.session, sessionID, (s) => s.id) - const isChild = match.found && syncStore.session[match.index].parentID - if (isChild) break - try { - idlePlayer?.play() - } catch {} - setStore("list", store.list.length, { - ...base, - type: "turn-complete", - session: sessionID, - }) - break - } - case "session.error": { - const sessionID = event.properties.sessionID - if (sessionID) { - const [syncStore] = globalSync.child(directory) - const match = Binary.search(syncStore.session, sessionID, (s) => s.id) - const isChild = match.found && syncStore.session[match.index].parentID - if (isChild) break - } - try { - errorPlayer?.play() - } catch {} - setStore("list", store.list.length, { - ...base, - type: "error", - session: sessionID ?? "global", - error: "error" in event.properties ? event.properties.error : undefined, - }) - break - } - } - }) - - return { - ready, - session: { - all(session: string) { - return store.list.filter((n) => n.session === session) - }, - unseen(session: string) { - return store.list.filter((n) => n.session === session && !n.viewed) - }, - markViewed(session: string) { - setStore("list", (n) => n.session === session, "viewed", true) - }, - }, - project: { - all(directory: string) { - return store.list.filter((n) => n.directory === directory) - }, - unseen(directory: string) { - return store.list.filter((n) => n.directory === directory && !n.viewed) - }, - markViewed(directory: string) { - setStore("list", (n) => n.directory === directory, "viewed", true) - }, - }, - } - }, -}) diff --git a/packages/app/src/context/platform.tsx b/packages/app/src/context/platform.tsx deleted file mode 100644 index 73d4c7f3e..000000000 --- a/packages/app/src/context/platform.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { createSimpleContext } from "@opencode-ai/ui/context" -import { AsyncStorage, SyncStorage } from "@solid-primitives/storage" - -export type Platform = { - /** Platform discriminator */ - platform: "web" | "tauri" - - /** Open a URL in the default browser */ - openLink(url: string): void - - /** Restart the app */ - restart(): Promise - - /** Open native directory picker dialog (Tauri only) */ - openDirectoryPickerDialog?(opts?: { title?: string; multiple?: boolean }): Promise - - /** Open native file picker dialog (Tauri only) */ - openFilePickerDialog?(opts?: { title?: string; multiple?: boolean }): Promise - - /** Save file picker dialog (Tauri only) */ - saveFilePickerDialog?(opts?: { title?: string; defaultPath?: string }): Promise - - /** Storage mechanism, defaults to localStorage */ - storage?: (name?: string) => SyncStorage | AsyncStorage - - /** Check for updates (Tauri only) */ - checkUpdate?(): Promise<{ updateAvailable: boolean; version?: string }> - - /** Install updates (Tauri only) */ - update?(): Promise - - /** Fetch override */ - fetch?: typeof fetch -} - -export const { use: usePlatform, provider: PlatformProvider } = createSimpleContext({ - name: "Platform", - init: (props: { value: Platform }) => { - return props.value - }, -}) diff --git a/packages/app/src/context/prompt.tsx b/packages/app/src/context/prompt.tsx deleted file mode 100644 index 8d3590cd9..000000000 --- a/packages/app/src/context/prompt.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { createStore } from "solid-js/store" -import { createSimpleContext } from "@opencode-ai/ui/context" -import { batch, createMemo } from "solid-js" -import { useParams } from "@solidjs/router" -import { TextSelection } from "./local" -import { persisted } from "@/utils/persist" - -interface PartBase { - content: string - start: number - end: number -} - -export interface TextPart extends PartBase { - type: "text" -} - -export interface FileAttachmentPart extends PartBase { - type: "file" - path: string - selection?: TextSelection -} - -export interface ImageAttachmentPart { - type: "image" - id: string - filename: string - mime: string - dataUrl: string -} - -export type ContentPart = TextPart | FileAttachmentPart | ImageAttachmentPart -export type Prompt = ContentPart[] - -export const DEFAULT_PROMPT: Prompt = [{ type: "text", content: "", start: 0, end: 0 }] - -export function isPromptEqual(promptA: Prompt, promptB: Prompt): boolean { - if (promptA.length !== promptB.length) return false - for (let i = 0; i < promptA.length; i++) { - const partA = promptA[i] - const partB = promptB[i] - if (partA.type !== partB.type) return false - if (partA.type === "text" && partA.content !== (partB as TextPart).content) { - return false - } - if (partA.type === "file" && partA.path !== (partB as FileAttachmentPart).path) { - return false - } - if (partA.type === "image" && partA.id !== (partB as ImageAttachmentPart).id) { - return false - } - } - return true -} - -function cloneSelection(selection?: TextSelection) { - if (!selection) return undefined - return { ...selection } -} - -function clonePart(part: ContentPart): ContentPart { - if (part.type === "text") return { ...part } - if (part.type === "image") return { ...part } - return { - ...part, - selection: cloneSelection(part.selection), - } -} - -function clonePrompt(prompt: Prompt): Prompt { - return prompt.map(clonePart) -} - -export const { use: usePrompt, provider: PromptProvider } = createSimpleContext({ - name: "Prompt", - init: () => { - const params = useParams() - const name = createMemo(() => `${params.dir}/prompt${params.id ? "/" + params.id : ""}.v1`) - - const [store, setStore, _, ready] = persisted( - name(), - createStore<{ - prompt: Prompt - cursor?: number - }>({ - prompt: clonePrompt(DEFAULT_PROMPT), - cursor: undefined, - }), - ) - - return { - ready, - current: createMemo(() => store.prompt), - cursor: createMemo(() => store.cursor), - dirty: createMemo(() => !isPromptEqual(store.prompt, DEFAULT_PROMPT)), - set(prompt: Prompt, cursorPosition?: number) { - const next = clonePrompt(prompt) - batch(() => { - setStore("prompt", next) - if (cursorPosition !== undefined) setStore("cursor", cursorPosition) - }) - }, - reset() { - batch(() => { - setStore("prompt", clonePrompt(DEFAULT_PROMPT)) - setStore("cursor", 0) - }) - }, - } - }, -}) diff --git a/packages/app/src/context/sync.tsx b/packages/app/src/context/sync.tsx deleted file mode 100644 index 941b8b629..000000000 --- a/packages/app/src/context/sync.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { produce } from "solid-js/store" -import { createMemo } from "solid-js" -import { Binary } from "@opencode-ai/util/binary" -import { retry } from "@opencode-ai/util/retry" -import { createSimpleContext } from "@opencode-ai/ui/context" -import { useGlobalSync } from "./global-sync" -import { useSDK } from "./sdk" -import type { Message, Part } from "@opencode-ai/sdk/v2/client" - -export const { use: useSync, provider: SyncProvider } = createSimpleContext({ - name: "Sync", - init: () => { - const globalSync = useGlobalSync() - const sdk = useSDK() - const [store, setStore] = globalSync.child(sdk.directory) - const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/") - - return { - data: store, - set: setStore, - get ready() { - return store.ready - }, - get project() { - const match = Binary.search(globalSync.data.project, store.project, (p) => p.id) - if (match.found) return globalSync.data.project[match.index] - return undefined - }, - session: { - get(sessionID: string) { - const match = Binary.search(store.session, sessionID, (s) => s.id) - if (match.found) return store.session[match.index] - return undefined - }, - addOptimisticMessage(input: { - sessionID: string - messageID: string - parts: Part[] - agent: string - model: { providerID: string; modelID: string } - }) { - const message: Message = { - id: input.messageID, - sessionID: input.sessionID, - role: "user", - time: { created: Date.now() }, - agent: input.agent, - model: input.model, - } - setStore( - produce((draft) => { - const messages = draft.message[input.sessionID] - if (!messages) { - draft.message[input.sessionID] = [message] - } else { - const result = Binary.search(messages, input.messageID, (m) => m.id) - messages.splice(result.index, 0, message) - } - draft.part[input.messageID] = input.parts.slice() - }), - ) - }, - async sync(sessionID: string, _isRetry = false) { - const [session, messages, todo, diff] = await Promise.all([ - retry(() => sdk.client.session.get({ sessionID })), - retry(() => sdk.client.session.messages({ sessionID, limit: 100 })), - retry(() => sdk.client.session.todo({ sessionID })), - retry(() => sdk.client.session.diff({ sessionID })), - ]) - setStore( - produce((draft) => { - const match = Binary.search(draft.session, sessionID, (s) => s.id) - if (match.found) draft.session[match.index] = session.data! - if (!match.found) draft.session.splice(match.index, 0, session.data!) - draft.todo[sessionID] = todo.data ?? [] - draft.message[sessionID] = messages - .data!.map((x) => x.info) - .slice() - .sort((a, b) => a.id.localeCompare(b.id)) - for (const message of messages.data!) { - draft.part[message.info.id] = message.parts.slice().sort((a, b) => a.id.localeCompare(b.id)) - } - draft.session_diff[sessionID] = diff.data ?? [] - }), - ) - }, - fetch: async (count = 10) => { - setStore("limit", (x) => x + count) - await sdk.client.session.list().then((x) => { - const sessions = (x.data ?? []) - .slice() - .sort((a, b) => a.id.localeCompare(b.id)) - .slice(0, store.limit) - setStore("session", sessions) - }) - }, - more: createMemo(() => store.session.length >= store.limit), - archive: async (sessionID: string) => { - await sdk.client.session.update({ sessionID, time: { archived: Date.now() } }) - setStore( - produce((draft) => { - const match = Binary.search(draft.session, sessionID, (s) => s.id) - if (match.found) draft.session.splice(match.index, 1) - }), - ) - }, - }, - absolute, - get directory() { - return store.path.directory - }, - } - }, -}) diff --git a/packages/app/src/context/terminal.tsx b/packages/app/src/context/terminal.tsx deleted file mode 100644 index 6f7c11dea..000000000 --- a/packages/app/src/context/terminal.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { createStore, produce } from "solid-js/store" -import { createSimpleContext } from "@opencode-ai/ui/context" -import { batch, createMemo } from "solid-js" -import { useParams } from "@solidjs/router" -import { useSDK } from "./sdk" -import { persisted } from "@/utils/persist" - -export type LocalPTY = { - id: string - title: string - rows?: number - cols?: number - buffer?: string - scrollY?: number -} - -export const { use: useTerminal, provider: TerminalProvider } = createSimpleContext({ - name: "Terminal", - init: () => { - const sdk = useSDK() - const params = useParams() - const name = createMemo(() => `${params.dir}/terminal${params.id ? "/" + params.id : ""}.v1`) - - const [store, setStore, _, ready] = persisted( - name(), - createStore<{ - active?: string - all: LocalPTY[] - }>({ - all: [], - }), - ) - - return { - ready, - all: createMemo(() => Object.values(store.all)), - active: createMemo(() => store.active), - new() { - sdk.client.pty.create({ title: `Terminal ${store.all.length + 1}` }).then((pty) => { - const id = pty.data?.id - if (!id) return - setStore("all", [ - ...store.all, - { - id, - title: pty.data?.title ?? "Terminal", - }, - ]) - setStore("active", id) - }) - }, - update(pty: Partial & { id: string }) { - setStore("all", (x) => x.map((x) => (x.id === pty.id ? { ...x, ...pty } : x))) - sdk.client.pty.update({ - ptyID: pty.id, - title: pty.title, - size: pty.cols && pty.rows ? { rows: pty.rows, cols: pty.cols } : undefined, - }) - }, - async clone(id: string) { - const index = store.all.findIndex((x) => x.id === id) - const pty = store.all[index] - if (!pty) return - const clone = await sdk.client.pty.create({ - title: pty.title, - }) - if (!clone.data) return - setStore("all", index, { - ...pty, - ...clone.data, - }) - if (store.active === pty.id) { - setStore("active", clone.data.id) - } - }, - open(id: string) { - setStore("active", id) - }, - async close(id: string) { - batch(() => { - setStore( - "all", - store.all.filter((x) => x.id !== id), - ) - if (store.active === id) { - const index = store.all.findIndex((f) => f.id === id) - const previous = store.all[Math.max(0, index - 1)] - setStore("active", previous?.id) - } - }) - await sdk.client.pty.remove({ ptyID: id }) - }, - move(id: string, to: number) { - const index = store.all.findIndex((f) => f.id === id) - if (index === -1) return - setStore( - "all", - produce((all) => { - all.splice(to, 0, all.splice(index, 1)[0]) - }), - ) - }, - } - }, -}) diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx deleted file mode 100644 index ecbce9815..000000000 --- a/packages/app/src/entry.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// @refresh reload -import { render } from "solid-js/web" -import { App } from "@/app" -import { Platform, PlatformProvider } from "@/context/platform" - -const root = document.getElementById("root") -if (import.meta.env.DEV && !(root instanceof HTMLElement)) { - throw new Error( - "Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?", - ) -} - -const platform: Platform = { - platform: "web", - openLink(url: string) { - window.open(url, "_blank") - }, - restart: async () => { - window.location.reload() - }, -} - -render( - () => ( - - - - ), - root!, -) diff --git a/packages/app/src/hooks/use-providers.ts b/packages/app/src/hooks/use-providers.ts deleted file mode 100644 index 4a73fa055..000000000 --- a/packages/app/src/hooks/use-providers.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useGlobalSync } from "@/context/global-sync" -import { base64Decode } from "@opencode-ai/util/encode" -import { useParams } from "@solidjs/router" -import { createMemo } from "solid-js" - -export const popularProviders = ["opencode", "anthropic", "github-copilot", "openai", "google", "openrouter", "vercel"] - -export function useProviders() { - const globalSync = useGlobalSync() - const params = useParams() - const currentDirectory = createMemo(() => base64Decode(params.dir ?? "")) - const providers = createMemo(() => { - if (currentDirectory()) { - const [projectStore] = globalSync.child(currentDirectory()) - return projectStore.provider - } - return globalSync.data.provider - }) - const connected = createMemo(() => providers().all.filter((p) => providers().connected.includes(p.id))) - const paid = createMemo(() => - connected().filter((p) => p.id !== "opencode" || Object.values(p.models).find((m) => m.cost?.input)), - ) - const popular = createMemo(() => providers().all.filter((p) => popularProviders.includes(p.id))) - return { - all: createMemo(() => providers().all), - default: createMemo(() => providers().default), - popular, - connected, - paid, - } -} diff --git a/packages/app/src/index.ts b/packages/app/src/index.ts deleted file mode 100644 index cf5be9f51..000000000 --- a/packages/app/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { PlatformProvider, type Platform } from "./context/platform" -export { App } from "./app" diff --git a/packages/app/src/pages/directory-layout.tsx b/packages/app/src/pages/directory-layout.tsx deleted file mode 100644 index c909a373d..000000000 --- a/packages/app/src/pages/directory-layout.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { createMemo, Show, type ParentProps } from "solid-js" -import { useParams } from "@solidjs/router" -import { SDKProvider } from "@/context/sdk" -import { SyncProvider, useSync } from "@/context/sync" -import { LocalProvider } from "@/context/local" -import { base64Decode } from "@opencode-ai/util/encode" -import { DataProvider } from "@opencode-ai/ui/context" -import { iife } from "@opencode-ai/util/iife" - -export default function Layout(props: ParentProps) { - const params = useParams() - const directory = createMemo(() => { - return base64Decode(params.dir!) - }) - return ( - - - - {iife(() => { - const sync = useSync() - return ( - - {props.children} - - ) - })} - - - - ) -} diff --git a/packages/app/src/pages/error.tsx b/packages/app/src/pages/error.tsx deleted file mode 100644 index 9914279ad..000000000 --- a/packages/app/src/pages/error.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import { TextField } from "@opencode-ai/ui/text-field" -import { Logo } from "@opencode-ai/ui/logo" -import { Button } from "@opencode-ai/ui/button" -import { Component } from "solid-js" -import { usePlatform } from "@/context/platform" -import { Icon } from "@opencode-ai/ui/icon" - -export type InitError = { - name: string - data: Record -} - -function isInitError(error: unknown): error is InitError { - return ( - typeof error === "object" && - error !== null && - "name" in error && - "data" in error && - typeof (error as InitError).data === "object" - ) -} - -function formatInitError(error: InitError): string { - const data = error.data - switch (error.name) { - case "MCPFailed": - return `MCP server "${data.name}" failed. Note, opencode does not support MCP authentication yet.` - case "ProviderModelNotFoundError": { - const { providerID, modelID, suggestions } = data as { - providerID: string - modelID: string - suggestions?: string[] - } - return [ - `Model not found: ${providerID}/${modelID}`, - ...(Array.isArray(suggestions) && suggestions.length ? ["Did you mean: " + suggestions.join(", ")] : []), - `Check your config (opencode.json) provider/model names`, - ].join("\n") - } - case "ProviderInitError": - return `Failed to initialize provider "${data.providerID}". Check credentials and configuration.` - case "ConfigJsonError": - return `Config file at ${data.path} is not valid JSON(C)` + (data.message ? `: ${data.message}` : "") - case "ConfigDirectoryTypoError": - return `Directory "${data.dir}" in ${data.path} is not valid. Rename the directory to "${data.suggestion}" or remove it. This is a common typo.` - case "ConfigFrontmatterError": - return `Failed to parse frontmatter in ${data.path}:\n${data.message}` - case "ConfigInvalidError": { - const issues = Array.isArray(data.issues) - ? data.issues.map( - (issue: { message: string; path: string[] }) => "↳ " + issue.message + " " + issue.path.join("."), - ) - : [] - return [`Config file at ${data.path} is invalid` + (data.message ? `: ${data.message}` : ""), ...issues].join( - "\n", - ) - } - case "UnknownError": - return String(data.message) - default: - return data.message ? String(data.message) : JSON.stringify(data, null, 2) - } -} - -function formatErrorChain(error: unknown, depth = 0, parentMessage?: string): string { - if (!error) return "Unknown error" - - if (isInitError(error)) { - const message = formatInitError(error) - if (depth > 0 && parentMessage === message) return "" - const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : "" - return indent + message - } - - if (error instanceof Error) { - const isDuplicate = depth > 0 && parentMessage === error.message - const parts: string[] = [] - const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : "" - - if (!isDuplicate) { - // Stack already includes error name and message, so prefer it - parts.push(indent + (error.stack ?? `${error.name}: ${error.message}`)) - } else if (error.stack) { - // Duplicate message - only show the stack trace lines (skip message) - const trace = error.stack.split("\n").slice(1).join("\n").trim() - if (trace) { - parts.push(trace) - } - } - - if (error.cause) { - const causeResult = formatErrorChain(error.cause, depth + 1, error.message) - if (causeResult) { - parts.push(causeResult) - } - } - - return parts.join("\n\n") - } - - if (typeof error === "string") { - if (depth > 0 && parentMessage === error) return "" - const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : "" - return indent + error - } - - const indent = depth > 0 ? `\n${"─".repeat(40)}\nCaused by:\n` : "" - return indent + JSON.stringify(error, null, 2) -} - -function formatError(error: unknown): string { - return formatErrorChain(error, 0) -} - -interface ErrorPageProps { - error: unknown -} - -export const ErrorPage: Component = (props) => { - const platform = usePlatform() - return ( -
-
- -
-

Something went wrong

-

An error occurred while loading the application.

-
- - -
- Please report this error to the OpenCode team - -
-
-
- ) -} diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx deleted file mode 100644 index 7cd2916e8..000000000 --- a/packages/app/src/pages/home.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { useGlobalSync } from "@/context/global-sync" -import { createMemo, For, Match, Show, Switch } from "solid-js" -import { Button } from "@opencode-ai/ui/button" -import { Logo } from "@opencode-ai/ui/logo" -import { useLayout } from "@/context/layout" -import { useNavigate } from "@solidjs/router" -import { base64Encode } from "@opencode-ai/util/encode" -import { Icon } from "@opencode-ai/ui/icon" -import { usePlatform } from "@/context/platform" -import { DateTime } from "luxon" - -export default function Home() { - const sync = useGlobalSync() - const layout = useLayout() - const platform = usePlatform() - const navigate = useNavigate() - const homedir = createMemo(() => sync.data.path.home) - - function openProject(directory: string) { - layout.projects.open(directory) - navigate(`/${base64Encode(directory)}`) - } - - async function chooseProject() { - const result = await platform.openDirectoryPickerDialog?.({ - title: "Open project", - multiple: true, - }) - if (Array.isArray(result)) { - for (const directory of result) { - openProject(directory) - } - } else if (result) { - openProject(result) - } - } - - return ( -
- - - 0}> -
-
-
Recent projects
- - - -
-
    - (b.time.updated ?? b.time.created) - (a.time.updated ?? a.time.created)) - .slice(0, 5)} - > - {(project) => ( - - )} - -
-
-
- -
- -
-
No recent projects
-
Get started by opening a local project
-
-
- - - -
- - -
- ) -} diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx deleted file mode 100644 index 489899f88..000000000 --- a/packages/app/src/pages/layout.tsx +++ /dev/null @@ -1,904 +0,0 @@ -import { - createEffect, - createMemo, - createSignal, - For, - Match, - onCleanup, - onMount, - ParentProps, - Show, - Switch, - type JSX, -} from "solid-js" -import { DateTime } from "luxon" -import { A, useNavigate, useParams } from "@solidjs/router" -import { useLayout, getAvatarColors, LocalProject } from "@/context/layout" -import { useGlobalSync } from "@/context/global-sync" -import { base64Decode, base64Encode } from "@opencode-ai/util/encode" -import { Avatar } from "@opencode-ai/ui/avatar" -import { ResizeHandle } from "@opencode-ai/ui/resize-handle" -import { Button } from "@opencode-ai/ui/button" -import { Icon } from "@opencode-ai/ui/icon" -import { IconButton } from "@opencode-ai/ui/icon-button" -import { Tooltip } from "@opencode-ai/ui/tooltip" -import { Collapsible } from "@opencode-ai/ui/collapsible" -import { DiffChanges } from "@opencode-ai/ui/diff-changes" -import { Spinner } from "@opencode-ai/ui/spinner" -import { getFilename } from "@opencode-ai/util/path" -import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu" -import { Session } from "@opencode-ai/sdk/v2/client" -import { usePlatform } from "@/context/platform" -import { createStore, produce } from "solid-js/store" -import { - DragDropProvider, - DragDropSensors, - DragOverlay, - SortableProvider, - closestCenter, - createSortable, -} from "@thisbeyond/solid-dnd" -import type { DragEvent } from "@thisbeyond/solid-dnd" -import { useProviders } from "@/hooks/use-providers" -import { showToast, Toast } from "@opencode-ai/ui/toast" -import { useGlobalSDK } from "@/context/global-sdk" -import { useNotification } from "@/context/notification" -import { Binary } from "@opencode-ai/util/binary" -import { Header } from "@/components/header" -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { DialogSelectProvider } from "@/components/dialog-select-provider" -import { useCommand } from "@/context/command" -import { ConstrainDragXAxis } from "@/utils/solid-dnd" - -export default function Layout(props: ParentProps) { - const [store, setStore] = createStore({ - lastSession: {} as { [directory: string]: string }, - activeDraggable: undefined as string | undefined, - mobileSidebarOpen: false, - mobileProjectsExpanded: {} as Record, - }) - - const mobileSidebar = { - open: () => store.mobileSidebarOpen, - show: () => setStore("mobileSidebarOpen", true), - hide: () => setStore("mobileSidebarOpen", false), - toggle: () => setStore("mobileSidebarOpen", (x) => !x), - } - - const mobileProjects = { - expanded: (directory: string) => store.mobileProjectsExpanded[directory] ?? true, - expand: (directory: string) => setStore("mobileProjectsExpanded", directory, true), - collapse: (directory: string) => setStore("mobileProjectsExpanded", directory, false), - } - - let scrollContainerRef: HTMLDivElement | undefined - const xlQuery = window.matchMedia("(min-width: 1280px)") - const [isLargeViewport, setIsLargeViewport] = createSignal(xlQuery.matches) - const handleViewportChange = (e: MediaQueryListEvent) => setIsLargeViewport(e.matches) - xlQuery.addEventListener("change", handleViewportChange) - onCleanup(() => xlQuery.removeEventListener("change", handleViewportChange)) - - const params = useParams() - const globalSDK = useGlobalSDK() - const globalSync = useGlobalSync() - const layout = useLayout() - const platform = usePlatform() - const notification = useNotification() - const navigate = useNavigate() - const providers = useProviders() - const dialog = useDialog() - const command = useCommand() - - onMount(async () => { - if (platform.checkUpdate && platform.update && platform.restart) { - const { updateAvailable, version } = await platform.checkUpdate() - if (updateAvailable) { - showToast({ - persistent: true, - icon: "download", - title: "Update available", - description: `A new version of OpenCode (${version}) is now available to install.`, - actions: [ - { - label: "Install and restart", - onClick: async () => { - await platform.update!() - await platform.restart!() - }, - }, - { - label: "Not yet", - onClick: "dismiss", - }, - ], - }) - } - } - }) - - function flattenSessions(sessions: Session[]): Session[] { - const childrenMap = new Map() - for (const session of sessions) { - if (session.parentID) { - const children = childrenMap.get(session.parentID) ?? [] - children.push(session) - childrenMap.set(session.parentID, children) - } - } - const result: Session[] = [] - function visit(session: Session) { - result.push(session) - for (const child of childrenMap.get(session.id) ?? []) { - visit(child) - } - } - for (const session of sessions) { - if (!session.parentID) visit(session) - } - return result - } - - function scrollToSession(sessionId: string) { - if (!scrollContainerRef) return - const element = scrollContainerRef.querySelector(`[data-session-id="${sessionId}"]`) - if (element) { - element.scrollIntoView({ block: "center", behavior: "smooth" }) - } - } - - function projectSessions(directory: string) { - if (!directory) return [] - const sessions = globalSync - .child(directory)[0] - .session.toSorted((a, b) => (b.time.updated ?? b.time.created) - (a.time.updated ?? a.time.created)) - return flattenSessions(sessions ?? []) - } - - const currentSessions = createMemo(() => { - if (!params.dir) return [] - const directory = base64Decode(params.dir) - return projectSessions(directory) - }) - - function navigateSessionByOffset(offset: number) { - const projects = layout.projects.list() - if (projects.length === 0) return - - const currentDirectory = params.dir ? base64Decode(params.dir) : undefined - const projectIndex = currentDirectory ? projects.findIndex((p) => p.worktree === currentDirectory) : -1 - - if (projectIndex === -1) { - const targetProject = offset > 0 ? projects[0] : projects[projects.length - 1] - if (targetProject) navigateToProject(targetProject.worktree) - return - } - - const sessions = currentSessions() - const sessionIndex = params.id ? sessions.findIndex((s) => s.id === params.id) : -1 - - let targetIndex: number - if (sessionIndex === -1) { - targetIndex = offset > 0 ? 0 : sessions.length - 1 - } else { - targetIndex = sessionIndex + offset - } - - if (targetIndex >= 0 && targetIndex < sessions.length) { - const session = sessions[targetIndex] - navigateToSession(session) - queueMicrotask(() => scrollToSession(session.id)) - return - } - - const nextProjectIndex = projectIndex + (offset > 0 ? 1 : -1) - const nextProject = projects[nextProjectIndex] - if (!nextProject) return - - const nextProjectSessions = projectSessions(nextProject.worktree) - if (nextProjectSessions.length === 0) { - navigateToProject(nextProject.worktree) - return - } - - const targetSession = offset > 0 ? nextProjectSessions[0] : nextProjectSessions[nextProjectSessions.length - 1] - navigate(`/${base64Encode(nextProject.worktree)}/session/${targetSession.id}`) - queueMicrotask(() => scrollToSession(targetSession.id)) - } - - async function archiveSession(session: Session) { - const [store, setStore] = globalSync.child(session.directory) - const sessions = store.session ?? [] - const index = sessions.findIndex((s) => s.id === session.id) - const nextSession = sessions[index + 1] ?? sessions[index - 1] - - await globalSDK.client.session.update({ - directory: session.directory, - sessionID: session.id, - time: { archived: Date.now() }, - }) - setStore( - produce((draft) => { - const match = Binary.search(draft.session, session.id, (s) => s.id) - if (match.found) draft.session.splice(match.index, 1) - }), - ) - if (session.id === params.id) { - if (nextSession) { - navigate(`/${params.dir}/session/${nextSession.id}`) - } else { - navigate(`/${params.dir}/session`) - } - } - } - - command.register(() => [ - { - id: "sidebar.toggle", - title: "Toggle sidebar", - category: "View", - keybind: "mod+b", - onSelect: () => layout.sidebar.toggle(), - }, - ...(platform.openDirectoryPickerDialog - ? [ - { - id: "project.open", - title: "Open project", - category: "Project", - keybind: "mod+o", - onSelect: () => chooseProject(), - }, - ] - : []), - { - id: "provider.connect", - title: "Connect provider", - category: "Provider", - onSelect: () => connectProvider(), - }, - { - id: "session.previous", - title: "Previous session", - category: "Session", - keybind: "alt+arrowup", - onSelect: () => navigateSessionByOffset(-1), - }, - { - id: "session.next", - title: "Next session", - category: "Session", - keybind: "alt+arrowdown", - onSelect: () => navigateSessionByOffset(1), - }, - { - id: "session.archive", - title: "Archive session", - category: "Session", - keybind: "mod+shift+backspace", - disabled: !params.dir || !params.id, - onSelect: () => { - const session = currentSessions().find((s) => s.id === params.id) - if (session) archiveSession(session) - }, - }, - ]) - - function connectProvider() { - dialog.show(() => ) - } - - function navigateToProject(directory: string | undefined) { - if (!directory) return - const lastSession = store.lastSession[directory] - navigate(`/${base64Encode(directory)}${lastSession ? `/session/${lastSession}` : ""}`) - mobileSidebar.hide() - } - - function navigateToSession(session: Session | undefined) { - if (!session) return - navigate(`/${params.dir}/session/${session?.id}`) - mobileSidebar.hide() - } - - function openProject(directory: string, navigate = true) { - layout.projects.open(directory) - if (navigate) navigateToProject(directory) - } - - function closeProject(directory: string) { - const index = layout.projects.list().findIndex((x) => x.worktree === directory) - const next = layout.projects.list()[index + 1] - layout.projects.close(directory) - if (next) navigateToProject(next.worktree) - else navigate("/") - } - - async function chooseProject() { - const result = await platform.openDirectoryPickerDialog?.({ - title: "Open project", - multiple: true, - }) - if (Array.isArray(result)) { - for (const directory of result) { - openProject(directory, false) - } - navigateToProject(result[0]) - } else if (result) { - openProject(result) - } - } - - createEffect(() => { - if (!params.dir || !params.id) return - const directory = base64Decode(params.dir) - setStore("lastSession", directory, params.id) - notification.session.markViewed(params.id) - }) - - createEffect(() => { - if (isLargeViewport()) { - const sidebarWidth = layout.sidebar.opened() ? layout.sidebar.width() : 48 - document.documentElement.style.setProperty("--dialog-left-margin", `${sidebarWidth}px`) - } else { - document.documentElement.style.setProperty("--dialog-left-margin", "0px") - } - }) - - function getDraggableId(event: unknown): string | undefined { - if (typeof event !== "object" || event === null) return undefined - if (!("draggable" in event)) return undefined - const draggable = (event as { draggable?: { id?: unknown } }).draggable - if (!draggable) return undefined - return typeof draggable.id === "string" ? draggable.id : undefined - } - - function handleDragStart(event: unknown) { - const id = getDraggableId(event) - if (!id) return - setStore("activeDraggable", id) - } - - function handleDragOver(event: DragEvent) { - const { draggable, droppable } = event - if (draggable && droppable) { - const projects = layout.projects.list() - const fromIndex = projects.findIndex((p) => p.worktree === draggable.id.toString()) - const toIndex = projects.findIndex((p) => p.worktree === droppable.id.toString()) - if (fromIndex !== toIndex && toIndex !== -1) { - layout.projects.move(draggable.id.toString(), toIndex) - } - } - } - - function handleDragEnd() { - setStore("activeDraggable", undefined) - } - - const ProjectAvatar = (props: { - project: LocalProject - class?: string - expandable?: boolean - notify?: boolean - }): JSX.Element => { - const notification = useNotification() - const notifications = createMemo(() => notification.project.unseen(props.project.worktree)) - const hasError = createMemo(() => notifications().some((n) => n.type === "error")) - const name = createMemo(() => getFilename(props.project.worktree)) - const mask = "radial-gradient(circle 5px at calc(100% - 2px) 2px, transparent 5px, black 5.5px)" - const opencode = "4b0ea68d7af9a6031a7ffda7ad66e0cb83315750" - - return ( -
- 0 && props.notify ? { "-webkit-mask-image": mask, "mask-image": mask } : undefined - } - /> - - - 0 && props.notify}> -
- -
- ) - } - - const ProjectVisual = (props: { project: LocalProject; class?: string }): JSX.Element => { - const name = createMemo(() => getFilename(props.project.worktree)) - const current = createMemo(() => base64Decode(params.dir ?? "")) - return ( - - - - - - - - - ) - } - - const SessionItem = (props: { - session: Session - slug: string - project: LocalProject - depth?: number - childrenMap: Map - mobile?: boolean - }): JSX.Element => { - const notification = useNotification() - const depth = props.depth ?? 0 - const children = createMemo(() => props.childrenMap.get(props.session.id) ?? []) - const updated = createMemo(() => DateTime.fromMillis(props.session.time.updated)) - const notifications = createMemo(() => notification.session.unseen(props.session.id)) - const hasError = createMemo(() => notifications().some((n) => n.type === "error")) - const isWorking = createMemo(() => { - if (props.session.id === params.id) return false - const status = globalSync.child(props.project.worktree)[0].session_status[props.session.id] - return status?.type === "busy" || status?.type === "retry" - }) - return ( - <> -
- - -
- - {props.session.title} - - - - {(child) => ( - - )} - - - ) - } - - const SortableProject = (props: { project: LocalProject; mobile?: boolean }): JSX.Element => { - const sortable = createSortable(props.project.worktree) - const showExpanded = createMemo(() => props.mobile || layout.sidebar.opened()) - const slug = createMemo(() => base64Encode(props.project.worktree)) - const name = createMemo(() => getFilename(props.project.worktree)) - const [store, setProjectStore] = globalSync.child(props.project.worktree) - const sessions = createMemo(() => - store.session.toSorted((a, b) => (b.time.updated ?? b.time.created) - (a.time.updated ?? a.time.created)), - ) - const rootSessions = createMemo(() => sessions().filter((s) => !s.parentID)) - const childSessionsByParent = createMemo(() => { - const map = new Map() - for (const session of sessions()) { - if (session.parentID) { - const children = map.get(session.parentID) ?? [] - children.push(session) - map.set(session.parentID, children) - } - } - return map - }) - const hasMoreSessions = createMemo(() => store.session.length >= store.limit) - const loadMoreSessions = async () => { - setProjectStore("limit", (limit) => limit + 5) - await globalSync.project.loadSessions(props.project.worktree) - } - const isExpanded = createMemo(() => - props.mobile ? mobileProjects.expanded(props.project.worktree) : props.project.expanded, - ) - const handleOpenChange = (open: boolean) => { - if (props.mobile) { - if (open) mobileProjects.expand(props.project.worktree) - else mobileProjects.collapse(props.project.worktree) - } else { - if (open) layout.projects.expand(props.project.worktree) - else layout.projects.collapse(props.project.worktree) - } - } - return ( - // @ts-ignore -
- - - - - - - - - - - - - - - -
- ) - } - - const ProjectDragOverlay = (): JSX.Element => { - const project = createMemo(() => layout.projects.list().find((p) => p.worktree === store.activeDraggable)) - return ( - - {(p) => ( -
- -
- )} -
- ) - } - - const SidebarContent = (sidebarProps: { mobile?: boolean }) => { - const expanded = () => sidebarProps.mobile || layout.sidebar.opened() - return ( - <> -
- - - Toggle sidebar - {command.keybind("sidebar.toggle")} -
- } - inactive={expanded()} - > - - - - - - -
- p.worktree)}> - - {(project) => } - - -
- - - -
-
-
- - -
-
-
Getting started
-
OpenCode includes free models so you can start immediately.
-
Connect any provider to use models, inc. Claude, GPT, Gemini etc.
-
- - - -
-
- - - - - -
- - - Open project - - {command.keybind("project.open")} - -
- } - inactive={expanded()} - > - -
- - - - -
- - ) - } - - return ( -
-
-
-
- - - - -
-
-
{ - if (e.target === e.currentTarget) mobileSidebar.hide() - }} - /> -
e.stopPropagation()} - > - -
-
- -
{props.children}
-
- -
- ) -} diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx deleted file mode 100644 index 42e43232a..000000000 --- a/packages/app/src/pages/session.tsx +++ /dev/null @@ -1,927 +0,0 @@ -import { - For, - onCleanup, - onMount, - Show, - Match, - Switch, - createResource, - createMemo, - createEffect, - on, - createRenderEffect, - batch, -} from "solid-js" - -import { Dynamic } from "solid-js/web" -import { useLocal, type LocalFile } from "@/context/local" -import { createStore } from "solid-js/store" -import { PromptInput } from "@/components/prompt-input" -import { DateTime } from "luxon" -import { FileIcon } from "@opencode-ai/ui/file-icon" -import { IconButton } from "@opencode-ai/ui/icon-button" -import { Icon } from "@opencode-ai/ui/icon" -import { Tooltip } from "@opencode-ai/ui/tooltip" -import { DiffChanges } from "@opencode-ai/ui/diff-changes" -import { ResizeHandle } from "@opencode-ai/ui/resize-handle" -import { Tabs } from "@opencode-ai/ui/tabs" -import { useCodeComponent } from "@opencode-ai/ui/context/code" -import { SessionTurn } from "@opencode-ai/ui/session-turn" -import { createAutoScroll } from "@opencode-ai/ui/hooks" -import { SessionMessageRail } from "@opencode-ai/ui/session-message-rail" -import { SessionReview } from "@opencode-ai/ui/session-review" -import { - DragDropProvider, - DragDropSensors, - DragOverlay, - SortableProvider, - closestCenter, - createSortable, -} from "@thisbeyond/solid-dnd" -import type { DragEvent } from "@thisbeyond/solid-dnd" -import type { JSX } from "solid-js" -import { useSync } from "@/context/sync" -import { useTerminal, type LocalPTY } from "@/context/terminal" -import { useLayout } from "@/context/layout" -import { getDirectory, getFilename } from "@opencode-ai/util/path" -import { Terminal } from "@/components/terminal" -import { checksum } from "@opencode-ai/util/encode" -import { useDialog } from "@opencode-ai/ui/context/dialog" -import { DialogSelectFile } from "@/components/dialog-select-file" -import { DialogSelectModel } from "@/components/dialog-select-model" -import { useCommand } from "@/context/command" -import { useNavigate, useParams } from "@solidjs/router" -import { UserMessage } from "@opencode-ai/sdk/v2" -import { useSDK } from "@/context/sdk" -import { usePrompt } from "@/context/prompt" -import { extractPromptFromParts } from "@/utils/prompt" -import { ConstrainDragYAxis, getDraggableId } from "@/utils/solid-dnd" - -export default function Page() { - const layout = useLayout() - const local = useLocal() - const sync = useSync() - const terminal = useTerminal() - const dialog = useDialog() - const codeComponent = useCodeComponent() - const command = useCommand() - const params = useParams() - const navigate = useNavigate() - const sdk = useSDK() - const prompt = usePrompt() - - const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) - const tabs = createMemo(() => layout.tabs(sessionKey())) - const info = createMemo(() => (params.id ? sync.session.get(params.id) : undefined)) - const revertMessageID = createMemo(() => info()?.revert?.messageID) - const messages = createMemo(() => (params.id ? (sync.data.message[params.id] ?? []) : [])) - const userMessages = createMemo(() => - messages() - .filter((m) => m.role === "user") - .sort((a, b) => a.id.localeCompare(b.id)), - ) - const visibleUserMessages = createMemo(() => { - const revert = revertMessageID() - if (!revert) return userMessages() - return userMessages().filter((m) => m.id < revert) - }) - const lastUserMessage = createMemo(() => visibleUserMessages()?.at(-1)) - - const [store, setStore] = createStore({ - clickTimer: undefined as number | undefined, - activeDraggable: undefined as string | undefined, - activeTerminalDraggable: undefined as string | undefined, - userInteracted: false, - stepsExpanded: true, - mobileStepsExpanded: {} as Record, - messageId: undefined as string | undefined, - }) - - const activeMessage = createMemo(() => { - if (!store.messageId) return lastUserMessage() - // If the stored message is no longer visible (e.g., was reverted), fall back to last visible - const found = visibleUserMessages()?.find((m) => m.id === store.messageId) - return found ?? lastUserMessage() - }) - const setActiveMessage = (message: UserMessage | undefined) => { - setStore("messageId", message?.id) - } - - function navigateMessageByOffset(offset: number) { - const msgs = visibleUserMessages() - if (msgs.length === 0) return - - const current = activeMessage() - const currentIndex = current ? msgs.findIndex((m) => m.id === current.id) : -1 - - let targetIndex: number - if (currentIndex === -1) { - targetIndex = offset > 0 ? 0 : msgs.length - 1 - } else { - targetIndex = currentIndex + offset - } - - if (targetIndex < 0 || targetIndex >= msgs.length) return - - setActiveMessage(msgs[targetIndex]) - } - - const diffs = createMemo(() => (params.id ? (sync.data.session_diff[params.id] ?? []) : [])) - - let inputRef!: HTMLDivElement - - createEffect(() => { - if (!params.id) return - sync.session.sync(params.id) - }) - - createEffect(() => { - if (layout.terminal.opened()) { - if (terminal.all().length === 0) { - terminal.new() - } - } - }) - - createEffect( - on( - () => visibleUserMessages().at(-1)?.id, - (lastId, prevLastId) => { - if (lastId && prevLastId && lastId > prevLastId) { - setStore("messageId", undefined) - } - }, - { defer: true }, - ), - ) - - createEffect(() => { - params.id - const status = sync.data.session_status[params.id ?? ""] ?? { type: "idle" } - batch(() => { - setStore("userInteracted", false) - setStore("stepsExpanded", status.type !== "idle") - }) - }) - - const status = createMemo(() => sync.data.session_status[params.id ?? ""] ?? { type: "idle" }) - const working = createMemo(() => status().type !== "idle" && activeMessage()?.id === lastUserMessage()?.id) - - createRenderEffect((prev) => { - const isWorking = working() - if (!prev && isWorking) { - setStore("stepsExpanded", true) - } - if (prev && !isWorking && !store.userInteracted) { - setStore("stepsExpanded", false) - } - return isWorking - }, working()) - - command.register(() => [ - { - id: "session.new", - title: "New session", - description: "Create a new session", - category: "Session", - keybind: "mod+shift+s", - slash: "new", - onSelect: () => navigate(`/${params.dir}/session`), - }, - { - id: "file.open", - title: "Open file", - description: "Search and open a file", - category: "File", - keybind: "mod+p", - slash: "open", - onSelect: () => dialog.show(() => ), - }, - // { - // id: "theme.toggle", - // title: "Toggle theme", - // description: "Switch between themes", - // category: "View", - // keybind: "ctrl+t", - // slash: "theme", - // onSelect: () => { - // const currentTheme = localStorage.getItem("theme") ?? "oc-1" - // const themes = ["oc-1", "oc-2-paper"] - // const nextTheme = themes[(themes.indexOf(currentTheme) + 1) % themes.length] - // localStorage.setItem("theme", nextTheme) - // document.documentElement.setAttribute("data-theme", nextTheme) - // }, - // }, - { - id: "terminal.toggle", - title: "Toggle terminal", - description: "Show or hide the terminal", - category: "View", - keybind: "ctrl+`", - slash: "terminal", - onSelect: () => layout.terminal.toggle(), - }, - { - id: "review.toggle", - title: "Toggle review", - description: "Show or hide the review panel", - category: "View", - keybind: "mod+b", - slash: "review", - onSelect: () => layout.review.toggle(), - }, - { - id: "terminal.new", - title: "New terminal", - description: "Create a new terminal tab", - category: "Terminal", - keybind: "ctrl+shift+`", - onSelect: () => terminal.new(), - }, - { - id: "steps.toggle", - title: "Toggle steps", - description: "Show or hide the steps", - category: "View", - keybind: "mod+e", - slash: "steps", - disabled: !params.id, - onSelect: () => setStore("stepsExpanded", (x) => !x), - }, - { - id: "message.previous", - title: "Previous message", - description: "Go to the previous user message", - category: "Session", - keybind: "mod+arrowup", - disabled: !params.id, - onSelect: () => navigateMessageByOffset(-1), - }, - { - id: "message.next", - title: "Next message", - description: "Go to the next user message", - category: "Session", - keybind: "mod+arrowdown", - disabled: !params.id, - onSelect: () => navigateMessageByOffset(1), - }, - { - id: "model.choose", - title: "Choose model", - description: "Select a different model", - category: "Model", - keybind: "mod+'", - slash: "model", - onSelect: () => dialog.show(() => ), - }, - { - id: "agent.cycle", - title: "Cycle agent", - description: "Switch to the next agent", - category: "Agent", - keybind: "mod+.", - slash: "agent", - onSelect: () => local.agent.move(1), - }, - { - id: "agent.cycle.reverse", - title: "Cycle agent backwards", - description: "Switch to the previous agent", - category: "Agent", - keybind: "shift+mod+.", - onSelect: () => local.agent.move(-1), - }, - { - id: "session.undo", - title: "Undo", - description: "Undo the last message", - category: "Session", - slash: "undo", - disabled: !params.id || visibleUserMessages().length === 0, - onSelect: async () => { - const sessionID = params.id - if (!sessionID) return - if (status()?.type !== "idle") { - await sdk.client.session.abort({ sessionID }).catch(() => {}) - } - const revert = info()?.revert?.messageID - // Find the last user message that's not already reverted - const message = userMessages().findLast((x) => !revert || x.id < revert) - if (!message) return - await sdk.client.session.revert({ sessionID, messageID: message.id }) - // Restore the prompt from the reverted message - const parts = sync.data.part[message.id] - if (parts) { - const restored = extractPromptFromParts(parts) - prompt.set(restored) - } - // Navigate to the message before the reverted one (which will be the new last visible message) - const priorMessage = userMessages().findLast((x) => x.id < message.id) - setActiveMessage(priorMessage) - }, - }, - { - id: "session.redo", - title: "Redo", - description: "Redo the last undone message", - category: "Session", - slash: "redo", - disabled: !params.id || !info()?.revert?.messageID, - onSelect: async () => { - const sessionID = params.id - if (!sessionID) return - const revertMessageID = info()?.revert?.messageID - if (!revertMessageID) return - const nextMessage = userMessages().find((x) => x.id > revertMessageID) - if (!nextMessage) { - // Full unrevert - restore all messages and navigate to last - await sdk.client.session.unrevert({ sessionID }) - prompt.reset() - // Navigate to the last message (the one that was at the revert point) - const lastMsg = userMessages().findLast((x) => x.id >= revertMessageID) - setActiveMessage(lastMsg) - return - } - // Partial redo - move forward to next message - await sdk.client.session.revert({ sessionID, messageID: nextMessage.id }) - // Navigate to the message before the new revert point - const priorMsg = userMessages().findLast((x) => x.id < nextMessage.id) - setActiveMessage(priorMsg) - }, - }, - ]) - - const handleKeyDown = (event: KeyboardEvent) => { - const activeElement = document.activeElement as HTMLElement | undefined - if (activeElement) { - const isProtected = activeElement.closest("[data-prevent-autofocus]") - const isInput = /^(INPUT|TEXTAREA|SELECT)$/.test(activeElement.tagName) || activeElement.isContentEditable - if (isProtected || isInput) return - } - if (dialog.active) return - - if (activeElement === inputRef) { - if (event.key === "Escape") inputRef?.blur() - return - } - - if (event.key.length === 1 && event.key !== "Unidentified" && !(event.ctrlKey || event.metaKey)) { - inputRef?.focus() - } - } - - onMount(() => { - document.addEventListener("keydown", handleKeyDown) - }) - - onCleanup(() => { - document.removeEventListener("keydown", handleKeyDown) - }) - - const resetClickTimer = () => { - if (!store.clickTimer) return - clearTimeout(store.clickTimer) - setStore("clickTimer", undefined) - } - - const startClickTimer = () => { - const newClickTimer = setTimeout(() => { - setStore("clickTimer", undefined) - }, 300) - setStore("clickTimer", newClickTimer as unknown as number) - } - - const handleTabClick = async (tab: string) => { - if (store.clickTimer) { - resetClickTimer() - } else { - if (tab.startsWith("file://")) { - local.file.open(tab.replace("file://", "")) - } - startClickTimer() - } - } - - const handleDragStart = (event: unknown) => { - const id = getDraggableId(event) - if (!id) return - setStore("activeDraggable", id) - } - - const handleDragOver = (event: DragEvent) => { - const { draggable, droppable } = event - if (draggable && droppable) { - const currentTabs = tabs().all() - const fromIndex = currentTabs?.indexOf(draggable.id.toString()) - const toIndex = currentTabs?.indexOf(droppable.id.toString()) - if (fromIndex !== toIndex && toIndex !== undefined) { - tabs().move(draggable.id.toString(), toIndex) - } - } - } - - const handleDragEnd = () => { - setStore("activeDraggable", undefined) - } - - const handleTerminalDragStart = (event: unknown) => { - const id = getDraggableId(event) - if (!id) return - setStore("activeTerminalDraggable", id) - } - - const handleTerminalDragOver = (event: DragEvent) => { - const { draggable, droppable } = event - if (draggable && droppable) { - const terminals = terminal.all() - const fromIndex = terminals.findIndex((t: LocalPTY) => t.id === draggable.id.toString()) - const toIndex = terminals.findIndex((t: LocalPTY) => t.id === droppable.id.toString()) - if (fromIndex !== -1 && toIndex !== -1 && fromIndex !== toIndex) { - terminal.move(draggable.id.toString(), toIndex) - } - } - } - - const handleTerminalDragEnd = () => { - setStore("activeTerminalDraggable", undefined) - } - - const SortableTerminalTab = (props: { terminal: LocalPTY }): JSX.Element => { - const sortable = createSortable(props.terminal.id) - return ( - // @ts-ignore -
-
- 1 && ( - terminal.close(props.terminal.id)} /> - ) - } - > - {props.terminal.title} - -
-
- ) - } - - const FileVisual = (props: { file: LocalFile; active?: boolean }): JSX.Element => { - return ( -
- - - {props.file.name} - - -
- ) - } - - const SortableTab = (props: { - tab: string - onTabClick: (tab: string) => void - onTabClose: (tab: string) => void - }): JSX.Element => { - const sortable = createSortable(props.tab) - const [file] = createResource( - () => props.tab, - async (tab) => { - if (tab.startsWith("file://")) { - return local.file.node(tab.replace("file://", "")) - } - return undefined - }, - ) - return ( - // @ts-ignore -
-
- - props.onTabClose(props.tab)} /> - - } - hideCloseButton - onClick={() => props.onTabClick(props.tab)} - > - - {(f) => } - - -
-
- ) - } - - const showTabs = createMemo(() => layout.review.opened() && (diffs().length > 0 || tabs().all().length > 0)) - - const mobileWorking = createMemo(() => status().type !== "idle") - const mobileAutoScroll = createAutoScroll({ - working: mobileWorking, - onUserInteracted: () => setStore("userInteracted", true), - }) - - const MobileTurns = () => ( -
-
- - {(message) => ( - setStore("mobileStepsExpanded", message.id, (x) => !x)} - onUserInteracted={() => setStore("userInteracted", true)} - classes={{ - root: "min-w-0 w-full relative", - content: - "flex flex-col justify-between !overflow-visible [&_[data-slot=session-turn-message-header]]:top-[-32px]", - container: "px-4", - }} - /> - )} - -
-
- ) - - const NewSessionView = () => ( -
-
New session
-
- -
- {getDirectory(sync.data.path.directory)} - {getFilename(sync.data.path.directory)} -
-
- - {(project) => ( -
- -
- Last modified  - - {DateTime.fromMillis(project().time.updated ?? project().time.created).toRelative()} - -
-
- )} -
-
- ) - - const DesktopSessionContent = () => ( - - -
- - - setStore("stepsExpanded", (x) => !x)} - onUserInteracted={() => setStore("userInteracted", true)} - classes={{ - root: "pb-20 flex-1 min-w-0", - content: "pb-20", - container: - "w-full " + - (!showTabs() ? "max-w-200 mx-auto px-6" : visibleUserMessages().length > 1 ? "pr-6 pl-18" : "px-6"), - }} - /> - -
-
- - - -
- ) - - return ( -
-
- - -
- -
-
- 0}> - - - - Session - - - {diffs().length} Files Changed - - - - - - - - - -
- -
-
-
-
-
- { - inputRef = el - }} - /> -
-
-
- - - -
- - - - - - {(pty) => ( - - terminal.clone(pty.id)} /> - - )} - - - - - {(draggedId) => { - const pty = createMemo(() => terminal.all().find((t: LocalPTY) => t.id === draggedId())) - return ( - - {(t) => ( -
- {t().title} -
- )} -
- ) - }} -
-
- -
-
-
- ) -} diff --git a/packages/app/src/utils/id.ts b/packages/app/src/utils/id.ts deleted file mode 100644 index fa27cf4c5..000000000 --- a/packages/app/src/utils/id.ts +++ /dev/null @@ -1,99 +0,0 @@ -import z from "zod" - -const prefixes = { - session: "ses", - message: "msg", - permission: "per", - user: "usr", - part: "prt", - pty: "pty", -} as const - -const LENGTH = 26 -let lastTimestamp = 0 -let counter = 0 - -type Prefix = keyof typeof prefixes -export namespace Identifier { - export function schema(prefix: Prefix) { - return z.string().startsWith(prefixes[prefix]) - } - - export function ascending(prefix: Prefix, given?: string) { - return generateID(prefix, false, given) - } - - export function descending(prefix: Prefix, given?: string) { - return generateID(prefix, true, given) - } -} - -function generateID(prefix: Prefix, descending: boolean, given?: string): string { - if (!given) { - return create(prefix, descending) - } - - if (!given.startsWith(prefixes[prefix])) { - throw new Error(`ID ${given} does not start with ${prefixes[prefix]}`) - } - - return given -} - -function create(prefix: Prefix, descending: boolean, timestamp?: number): string { - const currentTimestamp = timestamp ?? Date.now() - - if (currentTimestamp !== lastTimestamp) { - lastTimestamp = currentTimestamp - counter = 0 - } - - counter += 1 - - let now = BigInt(currentTimestamp) * BigInt(0x1000) + BigInt(counter) - - if (descending) { - now = ~now - } - - const timeBytes = new Uint8Array(6) - for (let i = 0; i < 6; i += 1) { - timeBytes[i] = Number((now >> BigInt(40 - 8 * i)) & BigInt(0xff)) - } - - return prefixes[prefix] + "_" + bytesToHex(timeBytes) + randomBase62(LENGTH - 12) -} - -function bytesToHex(bytes: Uint8Array): string { - let hex = "" - for (let i = 0; i < bytes.length; i += 1) { - hex += bytes[i].toString(16).padStart(2, "0") - } - return hex -} - -function randomBase62(length: number): string { - const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - const bytes = getRandomBytes(length) - let result = "" - for (let i = 0; i < length; i += 1) { - result += chars[bytes[i] % 62] - } - return result -} - -function getRandomBytes(length: number): Uint8Array { - const bytes = new Uint8Array(length) - const cryptoObj = typeof globalThis !== "undefined" ? globalThis.crypto : undefined - - if (cryptoObj && typeof cryptoObj.getRandomValues === "function") { - cryptoObj.getRandomValues(bytes) - return bytes - } - - for (let i = 0; i < length; i += 1) { - bytes[i] = Math.floor(Math.random() * 256) - } - - return bytes -} diff --git a/packages/app/src/utils/index.ts b/packages/app/src/utils/index.ts deleted file mode 100644 index d87053269..000000000 --- a/packages/app/src/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./dom" diff --git a/packages/app/src/utils/persist.ts b/packages/app/src/utils/persist.ts deleted file mode 100644 index 12b334f9f..000000000 --- a/packages/app/src/utils/persist.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { usePlatform } from "@/context/platform" -import { makePersisted } from "@solid-primitives/storage" -import { createResource, type Accessor } from "solid-js" -import type { SetStoreFunction, Store } from "solid-js/store" - -type InitType = Promise | string | null -type PersistedWithReady = [Store, SetStoreFunction, InitType, Accessor] - -export function persisted(key: string, store: [Store, SetStoreFunction]): PersistedWithReady { - const platform = usePlatform() - const [state, setState, init] = makePersisted(store, { name: key, storage: platform.storage?.() ?? localStorage }) - - // Create a resource that resolves when the store is initialized - // This integrates with Suspense and provides a ready signal - const isAsync = init instanceof Promise - const [ready] = createResource( - () => init, - async (initValue) => { - if (initValue instanceof Promise) await initValue - return true - }, - { initialValue: !isAsync }, - ) - - return [state, setState, init, () => ready() === true] -} diff --git a/packages/app/src/utils/prompt.ts b/packages/app/src/utils/prompt.ts deleted file mode 100644 index 45c5ce1f3..000000000 --- a/packages/app/src/utils/prompt.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { Part, TextPart, FilePart } from "@opencode-ai/sdk/v2" -import type { Prompt, FileAttachmentPart } from "@/context/prompt" - -/** - * Extract prompt content from message parts for restoring into the prompt input. - * This is used by undo to restore the original user prompt. - */ -export function extractPromptFromParts(parts: Part[]): Prompt { - const result: Prompt = [] - let position = 0 - - for (const part of parts) { - if (part.type === "text") { - const textPart = part as TextPart - if (!textPart.synthetic && textPart.text) { - result.push({ - type: "text", - content: textPart.text, - start: position, - end: position + textPart.text.length, - }) - position += textPart.text.length - } - } else if (part.type === "file") { - const filePart = part as FilePart - if (filePart.source?.type === "file") { - const path = filePart.source.path - const content = "@" + path - const attachment: FileAttachmentPart = { - type: "file", - path, - content, - start: position, - end: position + content.length, - } - result.push(attachment) - position += content.length - } - } - } - - if (result.length === 0) { - result.push({ type: "text", content: "", start: 0, end: 0 }) - } - - return result -} diff --git a/packages/app/src/utils/solid-dnd.tsx b/packages/app/src/utils/solid-dnd.tsx deleted file mode 100644 index a634be4b4..000000000 --- a/packages/app/src/utils/solid-dnd.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useDragDropContext } from "@thisbeyond/solid-dnd" -import { JSXElement } from "solid-js" -import type { Transformer } from "@thisbeyond/solid-dnd" - -export const getDraggableId = (event: unknown): string | undefined => { - if (typeof event !== "object" || event === null) return undefined - if (!("draggable" in event)) return undefined - const draggable = (event as { draggable?: { id?: unknown } }).draggable - if (!draggable) return undefined - return typeof draggable.id === "string" ? draggable.id : undefined -} - -export const ConstrainDragXAxis = (): JSXElement => { - const context = useDragDropContext() - if (!context) return <> - const [, { onDragStart, onDragEnd, addTransformer, removeTransformer }] = context - const transformer: Transformer = { - id: "constrain-x-axis", - order: 100, - callback: (transform) => ({ ...transform, x: 0 }), - } - onDragStart((event) => { - const id = getDraggableId(event) - if (!id) return - addTransformer("draggables", id, transformer) - }) - onDragEnd((event) => { - const id = getDraggableId(event) - if (!id) return - removeTransformer("draggables", id, transformer.id) - }) - return <> -} - -export const ConstrainDragYAxis = (): JSXElement => { - const context = useDragDropContext() - if (!context) return <> - const [, { onDragStart, onDragEnd, addTransformer, removeTransformer }] = context - const transformer: Transformer = { - id: "constrain-y-axis", - order: 100, - callback: (transform) => ({ ...transform, y: 0 }), - } - onDragStart((event) => { - const id = getDraggableId(event) - if (!id) return - addTransformer("draggables", id, transformer) - }) - onDragEnd((event) => { - const id = getDraggableId(event) - if (!id) return - removeTransformer("draggables", id, transformer.id) - }) - return <> -} diff --git a/packages/app/tsconfig.json b/packages/app/tsconfig.json deleted file mode 100644 index db04f79ca..000000000 --- a/packages/app/tsconfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "composite": true, - "target": "ESNext", - "module": "ESNext", - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "jsx": "preserve", - "jsxImportSource": "solid-js", - "allowJs": true, - "strict": true, - "noEmit": false, - "emitDeclarationOnly": true, - "outDir": "node_modules/.ts-dist", - "isolatedModules": true, - "paths": { - "@/*": ["./src/*"] - } - }, - "exclude": ["dist", "ts-dist"] -} diff --git a/packages/app/vite.config.ts b/packages/app/vite.config.ts deleted file mode 100644 index 57071a894..000000000 --- a/packages/app/vite.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { defineConfig } from "vite" -import desktopPlugin from "./vite" - -export default defineConfig({ - plugins: [desktopPlugin] as any, - server: { - host: "0.0.0.0", - allowedHosts: true, - port: 3000, - }, - build: { - target: "esnext", - sourcemap: true, - }, -}) diff --git a/packages/app/vite.js b/packages/app/vite.js deleted file mode 100644 index 6b8fd6137..000000000 --- a/packages/app/vite.js +++ /dev/null @@ -1,26 +0,0 @@ -import solidPlugin from "vite-plugin-solid" -import tailwindcss from "@tailwindcss/vite" -import { fileURLToPath } from "url" - -/** - * @type {import("vite").PluginOption} - */ -export default [ - { - name: "opencode-desktop:config", - config() { - return { - resolve: { - alias: { - "@": fileURLToPath(new URL("./src", import.meta.url)), - }, - }, - worker: { - format: "es", - }, - } - }, - }, - tailwindcss(), - solidPlugin(), -] diff --git a/packages/console/app/.opencode/agent/css.md b/packages/console/app/.opencode/agent/css.md index d5e68c7bf..d0ec43a48 100644 --- a/packages/console/app/.opencode/agent/css.md +++ b/packages/console/app/.opencode/agent/css.md @@ -49,7 +49,7 @@ use data attributes to represent different states of the component } ``` -this will allow jsx to control the styling +this will allow jsx to control the syling avoid selectors that just target an element type like `> span` you should assign it a slot name. it's ok to do this sometimes where it makes sense semantically diff --git a/packages/console/app/package.json b/packages/console/app/package.json index f22d54b8a..9a94b835e 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.0.191", + "version": "1.0.118", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/console/app/public/social-share-zen.png b/packages/console/app/public/social-share-zen.png deleted file mode 120000 index 2cb95c718..000000000 --- a/packages/console/app/public/social-share-zen.png +++ /dev/null @@ -1 +0,0 @@ -../../../ui/src/assets/images/social-share-zen.png \ No newline at end of file diff --git a/packages/console/app/public/social-share-zen.png b/packages/console/app/public/social-share-zen.png new file mode 100644 index 000000000..33e941441 Binary files /dev/null and b/packages/console/app/public/social-share-zen.png differ diff --git a/packages/console/app/public/social-share.png b/packages/console/app/public/social-share.png deleted file mode 120000 index deb3346c2..000000000 --- a/packages/console/app/public/social-share.png +++ /dev/null @@ -1 +0,0 @@ -../../../ui/src/assets/images/social-share.png \ No newline at end of file diff --git a/packages/console/app/public/social-share.png b/packages/console/app/public/social-share.png new file mode 100644 index 000000000..92224f54c Binary files /dev/null and b/packages/console/app/public/social-share.png differ diff --git a/packages/console/app/src/app.tsx b/packages/console/app/src/app.tsx index cde2f0187..bc94b443e 100644 --- a/packages/console/app/src/app.tsx +++ b/packages/console/app/src/app.tsx @@ -3,7 +3,6 @@ import { Router } from "@solidjs/router" import { FileRoutes } from "@solidjs/start/router" import { Suspense } from "solid-js" import { Favicon } from "@opencode-ai/ui/favicon" -import { Font } from "@opencode-ai/ui/font" import "@ibm/plex/css/ibm-plex.css" import "./app.css" @@ -14,9 +13,8 @@ export default function App() { root={(props) => ( opencode - + - {props.children} )} diff --git a/packages/console/app/src/asset/lander/desktop-app-icon.png b/packages/console/app/src/asset/lander/desktop-app-icon.png deleted file mode 100644 index a35c28f51..000000000 Binary files a/packages/console/app/src/asset/lander/desktop-app-icon.png and /dev/null differ diff --git a/packages/console/app/src/asset/lander/opencode-desktop-icon.png b/packages/console/app/src/asset/lander/opencode-desktop-icon.png deleted file mode 100644 index f2c8d4f5a..000000000 Binary files a/packages/console/app/src/asset/lander/opencode-desktop-icon.png and /dev/null differ diff --git a/packages/console/app/src/asset/lander/opencode-min.mp4 b/packages/console/app/src/asset/lander/opencode-min.mp4 index ffd6c4f7a..47468bedf 100644 Binary files a/packages/console/app/src/asset/lander/opencode-min.mp4 and b/packages/console/app/src/asset/lander/opencode-min.mp4 differ diff --git a/packages/console/app/src/component/email-signup.tsx b/packages/console/app/src/component/email-signup.tsx index 65f81b5fc..4943921e7 100644 --- a/packages/console/app/src/component/email-signup.tsx +++ b/packages/console/app/src/component/email-signup.tsx @@ -25,8 +25,11 @@ export function EmailSignup() { const submission = useSubmission(emailSignup) return (
+
+ +
-

Be the first to know when we release new products

+

OpenCode will be available on desktop soon

Join the waitlist for early access.

diff --git a/packages/console/app/src/component/header.tsx b/packages/console/app/src/component/header.tsx index 7bfcc7825..06e710a18 100644 --- a/packages/console/app/src/component/header.tsx +++ b/packages/console/app/src/component/header.tsx @@ -34,7 +34,7 @@ const fetchSvgContent = async (svgPath: string): Promise => { } } -export function Header(props: { zen?: boolean; hideGetStarted?: boolean }) { +export function Header(props: { zen?: boolean }) { const navigate = useNavigate() const githubData = createAsync(() => github()) const starCount = createMemo(() => @@ -119,8 +119,8 @@ export function Header(props: { zen?: boolean; hideGetStarted?: boolean }) {
@@ -169,25 +169,6 @@ export function Header(props: { zen?: boolean; hideGetStarted?: boolean }) { - - {" "} -
  • - {" "} - - {" "} - - {" "} - {" "} - {" "} - Free{" "} - {" "} -
  • -
    diff --git a/packages/console/app/src/component/icon.tsx b/packages/console/app/src/component/icon.tsx index 1225aeb10..a28fc51a3 100644 --- a/packages/console/app/src/component/icon.tsx +++ b/packages/console/app/src/component/icon.tsx @@ -202,14 +202,6 @@ export function IconZai(props: JSX.SvgSVGAttributes) { ) } -export function IconMiniMax(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} - export function IconGemini(props: JSX.SvgSVGAttributes) { return ( diff --git a/packages/console/app/src/component/legal.tsx b/packages/console/app/src/component/legal.tsx index e971a31e1..c055977e3 100644 --- a/packages/console/app/src/component/legal.tsx +++ b/packages/console/app/src/component/legal.tsx @@ -9,12 +9,6 @@ export function Legal() { Brand - - Privacy - - - Terms -
    ) } diff --git a/packages/console/app/src/config.ts b/packages/console/app/src/config.ts index bf20681ae..19f15c186 100644 --- a/packages/console/app/src/config.ts +++ b/packages/console/app/src/config.ts @@ -9,8 +9,8 @@ export const config = { github: { repoUrl: "https://github.com/sst/opencode", starsFormatted: { - compact: "41K", - full: "41,000", + compact: "30K", + full: "30,000", }, }, @@ -22,8 +22,8 @@ export const config = { // Static stats (used on landing page) stats: { - contributors: "450", - commits: "6,000", - monthlyUsers: "400,000", + contributors: "300", + commits: "4,000", + monthlyUsers: "300,000", }, } as const diff --git a/packages/console/app/src/entry-server.tsx b/packages/console/app/src/entry-server.tsx index deaadc747..913c8ca06 100644 --- a/packages/console/app/src/entry-server.tsx +++ b/packages/console/app/src/entry-server.tsx @@ -1,8 +1,6 @@ // @refresh reload import { createHandler, StartServer } from "@solidjs/start/server" -const criticalCSS = `[data-component="top"]{min-height:80px;display:flex;align-items:center}` - export default createHandler( () => ( - {assets} diff --git a/packages/console/app/src/lib/github.ts b/packages/console/app/src/lib/github.ts index cc266f58c..bc49d2e62 100644 --- a/packages/console/app/src/lib/github.ts +++ b/packages/console/app/src/lib/github.ts @@ -26,7 +26,6 @@ export const github = query(async () => { release: { name: release.name, url: release.html_url, - tag_name: release.tag_name, }, contributors: contributorCount, } diff --git a/packages/console/app/src/routes/api/enterprise.ts b/packages/console/app/src/routes/api/enterprise.ts index 6776a7b3c..e33737d57 100644 --- a/packages/console/app/src/routes/api/enterprise.ts +++ b/packages/console/app/src/routes/api/enterprise.ts @@ -36,7 +36,6 @@ ${body.email}`.trim() to: "contact@anoma.ly", subject: `Enterprise Inquiry from ${body.name}`, body: emailContent, - replyTo: body.email, }) return Response.json({ success: true, message: "Form submitted successfully" }, { status: 200 }) diff --git a/packages/console/app/src/routes/brand/index.css b/packages/console/app/src/routes/brand/index.css index 2bfe5711a..d3c0d0523 100644 --- a/packages/console/app/src/routes/brand/index.css +++ b/packages/console/app/src/routes/brand/index.css @@ -8,8 +8,7 @@ } } -[data-page="enterprise"], -[data-page="legal"] { +[data-page="enterprise"] { --color-background: hsl(0, 20%, 99%); --color-background-weak: hsl(0, 8%, 97%); --color-background-weak-hover: hsl(0, 8%, 94%); @@ -85,16 +84,7 @@ ul { display: flex; justify-content: space-between; - align-items: center; gap: 48px; - - @media (max-width: 55rem) { - gap: 32px; - } - - @media (max-width: 48rem) { - gap: 24px; - } li { display: inline-block; a { @@ -108,25 +98,6 @@ text-underline-offset: 2px; text-decoration-thickness: 1px; } - [data-slot="cta-button"] { - background: var(--color-background-strong); - color: var(--color-text-inverted); - padding: 8px 16px 8px 10px; - border-radius: 4px; - font-weight: 500; - text-decoration: none; - display: flex; - align-items: center; - gap: 8px; - - @media (max-width: 55rem) { - display: none; - } - } - [data-slot="cta-button"]:hover { - background: var(--color-background-strong-hover); - text-decoration: none; - } } } @@ -295,7 +266,7 @@ h1 { font-size: 1.5rem; - font-weight: 700; + font-weight: 500; color: var(--color-text-strong); margin-bottom: 1rem; } diff --git a/packages/console/app/src/routes/download/[platform].ts b/packages/console/app/src/routes/download/[platform].ts deleted file mode 100644 index 427fb132b..000000000 --- a/packages/console/app/src/routes/download/[platform].ts +++ /dev/null @@ -1,38 +0,0 @@ -import { APIEvent } from "@solidjs/start" -import { DownloadPlatform } from "./types" - -const assetNames: Record = { - "darwin-aarch64-dmg": "opencode-desktop-darwin-aarch64.dmg", - "darwin-x64-dmg": "opencode-desktop-darwin-x64.dmg", - "windows-x64-nsis": "opencode-desktop-windows-x64.exe", - "linux-x64-deb": "opencode-desktop-linux-amd64.deb", - "linux-x64-appimage": "opencode-desktop-linux-amd64.AppImage", - "linux-x64-rpm": "opencode-desktop-linux-x86_64.rpm", -} satisfies Record - -// Doing this on the server lets us preserve the original name for platforms we don't care to rename for -const downloadNames: Record = { - "darwin-aarch64-dmg": "OpenCode Desktop.dmg", - "darwin-x64-dmg": "OpenCode Desktop.dmg", - "windows-x64-nsis": "OpenCode Desktop Installer.exe", -} satisfies { [K in DownloadPlatform]?: string } - -export async function GET({ params: { platform } }: APIEvent) { - const assetName = assetNames[platform] - if (!assetName) return new Response("Not Found", { status: 404 }) - - const resp = await fetch(`https://github.com/sst/opencode/releases/latest/download/${assetName}`, { - cf: { - // in case gh releases has rate limits - cacheTtl: 60 * 60 * 24, - cacheEverything: true, - }, - } as any) - - const downloadName = downloadNames[platform] - - const headers = new Headers(resp.headers) - if (downloadName) headers.set("content-disposition", `attachment; filename="${downloadName}"`) - - return new Response(resp.body, { ...resp, headers }) -} diff --git a/packages/console/app/src/routes/download/index.css b/packages/console/app/src/routes/download/index.css deleted file mode 100644 index 5178a6e55..000000000 --- a/packages/console/app/src/routes/download/index.css +++ /dev/null @@ -1,751 +0,0 @@ -::selection { - background: var(--color-background-interactive); - color: var(--color-text-strong); - - @media (prefers-color-scheme: dark) { - background: var(--color-background-interactive); - color: var(--color-text-inverted); - } -} - -[data-page="download"] { - --color-background: hsl(0, 20%, 99%); - --color-background-weak: hsl(0, 8%, 97%); - --color-background-weak-hover: hsl(0, 8%, 94%); - --color-background-strong: hsl(0, 5%, 12%); - --color-background-strong-hover: hsl(0, 5%, 18%); - --color-background-interactive: hsl(62, 84%, 88%); - --color-background-interactive-weaker: hsl(64, 74%, 95%); - - --color-text: hsl(0, 1%, 39%); - --color-text-weak: hsl(0, 1%, 60%); - --color-text-weaker: hsl(30, 2%, 81%); - --color-text-strong: hsl(0, 5%, 12%); - --color-text-inverted: hsl(0, 20%, 99%); - --color-text-success: hsl(119, 100%, 35%); - - --color-border: hsl(30, 2%, 81%); - --color-border-weak: hsl(0, 1%, 85%); - - --color-icon: hsl(0, 1%, 55%); - --color-success: hsl(142, 76%, 36%); - - background: var(--color-background); - font-family: var(--font-mono); - color: var(--color-text); - padding-bottom: 5rem; - overflow-x: hidden; - - @media (prefers-color-scheme: dark) { - --color-background: hsl(0, 9%, 7%); - --color-background-weak: hsl(0, 6%, 10%); - --color-background-weak-hover: hsl(0, 6%, 15%); - --color-background-strong: hsl(0, 15%, 94%); - --color-background-strong-hover: hsl(0, 15%, 97%); - --color-background-interactive: hsl(62, 100%, 90%); - --color-background-interactive-weaker: hsl(60, 20%, 8%); - - --color-text: hsl(0, 4%, 71%); - --color-text-weak: hsl(0, 2%, 49%); - --color-text-weaker: hsl(0, 3%, 28%); - --color-text-strong: hsl(0, 15%, 94%); - --color-text-inverted: hsl(0, 9%, 7%); - --color-text-success: hsl(119, 60%, 72%); - - --color-border: hsl(0, 3%, 28%); - --color-border-weak: hsl(0, 4%, 23%); - - --color-icon: hsl(10, 3%, 43%); - --color-success: hsl(142, 76%, 46%); - } - - /* Header and Footer styles - copied from enterprise */ - [data-component="top"] { - padding: 24px 5rem; - height: 80px; - position: sticky; - top: 0; - display: flex; - justify-content: space-between; - align-items: center; - background: var(--color-background); - border-bottom: 1px solid var(--color-border-weak); - z-index: 10; - - @media (max-width: 60rem) { - padding: 24px 1.5rem; - } - - img { - height: 34px; - width: auto; - } - - [data-component="nav-desktop"] { - ul { - display: flex; - justify-content: space-between; - align-items: center; - gap: 48px; - - @media (max-width: 55rem) { - gap: 32px; - } - - @media (max-width: 48rem) { - gap: 24px; - } - li { - display: inline-block; - a { - text-decoration: none; - span { - color: var(--color-text-weak); - } - } - a:hover { - text-decoration: underline; - text-underline-offset: 2px; - text-decoration-thickness: 1px; - } - [data-slot="cta-button"] { - background: var(--color-background-strong); - color: var(--color-text-inverted); - padding: 8px 16px; - border-radius: 4px; - font-weight: 500; - text-decoration: none; - - @media (max-width: 55rem) { - display: none; - } - } - [data-slot="cta-button"]:hover { - background: var(--color-background-strong-hover); - text-decoration: none; - } - } - } - - @media (max-width: 40rem) { - display: none; - } - } - - [data-component="nav-mobile"] { - button > svg { - color: var(--color-icon); - } - } - - [data-component="nav-mobile-toggle"] { - border: none; - background: none; - outline: none; - height: 40px; - width: 40px; - cursor: pointer; - margin-right: -8px; - } - - [data-component="nav-mobile-toggle"]:hover { - background: var(--color-background-weak); - } - - [data-component="nav-mobile"] { - display: none; - - @media (max-width: 40rem) { - display: block; - - [data-component="nav-mobile-icon"] { - cursor: pointer; - height: 40px; - width: 40px; - display: flex; - align-items: center; - justify-content: center; - } - - [data-component="nav-mobile-menu-list"] { - position: fixed; - background: var(--color-background); - top: 80px; - left: 0; - right: 0; - height: 100vh; - - ul { - list-style: none; - padding: 20px 0; - - li { - a { - text-decoration: none; - padding: 20px; - display: block; - - span { - color: var(--color-text-weak); - } - } - - a:hover { - background: var(--color-background-weak); - } - } - } - } - } - } - - [data-slot="logo dark"] { - display: none; - } - - @media (prefers-color-scheme: dark) { - [data-slot="logo light"] { - display: none; - } - [data-slot="logo dark"] { - display: block; - } - } - } - - [data-component="footer"] { - border-top: 1px solid var(--color-border-weak); - display: flex; - flex-direction: row; - - @media (max-width: 65rem) { - border-bottom: 1px solid var(--color-border-weak); - } - - [data-slot="cell"] { - flex: 1; - text-align: center; - - a { - text-decoration: none; - padding: 2rem 0; - width: 100%; - display: block; - - span { - color: var(--color-text-weak); - - @media (max-width: 40rem) { - display: none; - } - } - } - - a:hover { - background: var(--color-background-weak); - text-decoration: underline; - text-underline-offset: 2px; - text-decoration-thickness: 1px; - } - } - - [data-slot="cell"] + [data-slot="cell"] { - border-left: 1px solid var(--color-border-weak); - - @media (max-width: 40rem) { - border-left: none; - } - } - - @media (max-width: 25rem) { - flex-wrap: wrap; - - [data-slot="cell"] { - flex: 1 0 100%; - border-left: none; - border-top: 1px solid var(--color-border-weak); - } - - [data-slot="cell"]:nth-child(1) { - border-top: none; - } - } - } - - [data-component="container"] { - max-width: 67.5rem; - margin: 0 auto; - border: 1px solid var(--color-border-weak); - border-top: none; - - @media (max-width: 65rem) { - border: none; - } - } - - [data-component="content"] { - padding: 6rem 5rem; - - @media (max-width: 60rem) { - padding: 4rem 1.5rem; - } - } - - [data-component="legal"] { - color: var(--color-text-weak); - text-align: center; - padding: 2rem 5rem; - display: flex; - gap: 32px; - justify-content: center; - - @media (max-width: 60rem) { - padding: 2rem 1.5rem; - } - - a { - color: var(--color-text-weak); - text-decoration: none; - } - - a:hover { - color: var(--color-text); - text-decoration: underline; - } - } - - /* Download Hero Section */ - [data-component="download-hero"] { - display: grid; - grid-template-columns: 260px 1fr; - gap: 4rem; - padding-bottom: 2rem; - margin-bottom: 4rem; - - @media (max-width: 50rem) { - grid-template-columns: 1fr; - gap: 1.5rem; - padding-bottom: 2rem; - margin-bottom: 2rem; - } - - [data-component="hero-icon"] { - display: flex; - justify-content: flex-end; - align-items: center; - - @media (max-width: 40rem) { - display: none; - } - - [data-slot="icon-placeholder"] { - width: 120px; - height: 120px; - background: var(--color-background-weak); - border: 1px solid var(--color-border-weak); - border-radius: 24px; - - @media (max-width: 50rem) { - width: 80px; - height: 80px; - } - } - - img { - width: 120px; - height: 120px; - border-radius: 24px; - box-shadow: - 0 1.467px 2.847px 0 rgba(0, 0, 0, 0.42), - 0 0.779px 1.512px 0 rgba(0, 0, 0, 0.34), - 0 0.324px 0.629px 0 rgba(0, 0, 0, 0.24); - - @media (max-width: 50rem) { - width: 80px; - height: 80px; - border-radius: 16px; - } - } - - @media (max-width: 50rem) { - justify-content: flex-start; - } - } - - [data-component="hero-text"] { - display: flex; - flex-direction: column; - justify-content: center; - - h1 { - font-size: 1.5rem; - font-weight: 700; - color: var(--color-text-strong); - margin-bottom: 4px; - - @media (max-width: 40rem) { - margin-bottom: 1rem; - } - } - - p { - color: var(--color-text); - margin-bottom: 12px; - - @media (max-width: 40rem) { - margin-bottom: 2.5rem; - line-height: 1.6; - } - } - - [data-component="download-button"] { - padding: 8px 20px 8px 16px; - background: var(--color-background-strong); - color: var(--color-text-inverted); - border: none; - border-radius: 4px; - font-weight: 500; - cursor: pointer; - display: inline-flex; - align-items: center; - gap: 10px; - transition: all 0.2s ease; - text-decoration: none; - width: fit-content; - - &:hover:not(:disabled) { - background: var(--color-background-strong-hover); - } - - &:active { - transform: scale(0.98); - } - - &:disabled { - opacity: 0.6; - cursor: not-allowed; - } - } - } - } - - /* Download Sections */ - [data-component="download-section"] { - display: grid; - grid-template-columns: 260px 1fr; - gap: 4rem; - margin-bottom: 4rem; - - @media (max-width: 50rem) { - grid-template-columns: 1fr; - gap: 1rem; - margin-bottom: 3rem; - } - - &:last-child { - margin-bottom: 0; - } - - [data-component="section-label"] { - font-weight: 500; - color: var(--color-text-strong); - padding-top: 1rem; - - span { - color: var(--color-text-weaker); - } - - @media (max-width: 50rem) { - padding-top: 0; - padding-bottom: 0.5rem; - } - } - - [data-component="section-content"] { - display: flex; - flex-direction: column; - gap: 0; - } - } - - /* CLI Rows */ - button[data-component="cli-row"] { - display: flex; - align-items: center; - gap: 12px; - padding: 1rem 0.5rem 1rem 1.5rem; - margin: 0 -0.5rem 0 -1.5rem; - background: none; - border: none; - border-radius: 4px; - width: calc(100% + 2rem); - text-align: left; - cursor: pointer; - transition: background 0.15s ease; - - &:hover { - background: var(--color-background-weak); - } - - code { - font-family: var(--font-mono); - color: var(--color-text-weak); - - strong { - color: var(--color-text-strong); - font-weight: 500; - } - } - - [data-component="copy-status"] { - display: flex; - align-items: center; - opacity: 0; - transition: opacity 0.15s ease; - color: var(--color-icon); - - svg { - width: 18px; - height: 18px; - } - - [data-slot="copy"] { - display: block; - } - - [data-slot="check"] { - display: none; - } - } - - &:hover [data-component="copy-status"] { - opacity: 1; - } - - &[data-copied] [data-component="copy-status"] { - opacity: 1; - - [data-slot="copy"] { - display: none; - } - - [data-slot="check"] { - display: block; - } - } - } - - /* Download Rows */ - [data-component="download-row"] { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0.75rem 0.5rem 0.75rem 1.5rem; - margin: 0 -0.5rem 0 -1.5rem; - border-radius: 4px; - transition: background 0.15s ease; - - &:hover { - background: var(--color-background-weak); - } - - [data-component="download-info"] { - display: flex; - align-items: center; - gap: 0.75rem; - - [data-slot="icon"] { - width: 20px; - height: 20px; - display: flex; - align-items: center; - justify-content: center; - color: var(--color-icon); - - svg { - width: 20px; - height: 20px; - } - - img { - width: 20px; - height: 20px; - } - } - - span { - color: var(--color-text); - } - } - - [data-component="action-button"] { - padding: 6px 16px; - background: var(--color-background); - color: var(--color-text); - border: 1px solid var(--color-border); - border-radius: 4px; - font-weight: 500; - cursor: pointer; - text-decoration: none; - transition: all 0.2s ease; - - &:hover { - background: var(--color-background-weak); - border-color: var(--color-border); - text-decoration: none; - } - - &:active { - transform: scale(0.98); - } - } - } - - a { - color: var(--color-text-strong); - text-decoration: underline; - text-underline-offset: 2px; - text-decoration-thickness: 1px; - - &:hover { - text-decoration-thickness: 2px; - } - } - - /* Narrow screen font sizes */ - @media (max-width: 40rem) { - [data-component="download-section"] { - [data-component="section-label"] { - font-size: 14px; - } - } - - button[data-component="cli-row"] { - margin: 0; - padding: 1rem 0; - width: 100%; - overflow: hidden; - - code { - font-size: 14px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - display: block; - max-width: calc(100vw - 80px); - } - - [data-component="copy-status"] { - opacity: 1 !important; - flex-shrink: 0; - } - } - - [data-component="download-row"] { - margin: 0; - padding: 0.75rem 0; - - [data-component="download-info"] span { - font-size: 14px; - } - - [data-component="action-button"] { - font-size: 14px; - padding-left: 8px; - padding-right: 8px; - } - } - } - - @media (max-width: 22.5rem) { - [data-slot="hide-narrow"] { - display: none; - } - } - - /* FAQ Section */ - [data-component="faq"] { - border-top: 1px solid var(--color-border-weak); - padding: 4rem 5rem; - margin-top: 4rem; - - @media (max-width: 60rem) { - padding: 3rem 1.5rem; - margin-top: 3rem; - } - - [data-slot="section-title"] { - margin-bottom: 24px; - - h3 { - font-size: 16px; - font-weight: 700; - color: var(--color-text-strong); - margin-bottom: 12px; - } - } - - ul { - padding: 0; - - li { - list-style: none; - margin-bottom: 24px; - line-height: 200%; - } - } - - [data-slot="faq-question"] { - display: flex; - gap: 16px; - margin-bottom: 8px; - color: var(--color-text-strong); - font-weight: 500; - cursor: pointer; - background: none; - border: none; - padding: 0; - align-items: start; - min-height: 24px; - - svg { - margin-top: 2px; - } - - [data-slot="faq-icon-plus"] { - flex-shrink: 0; - color: var(--color-text-weak); - margin-top: 2px; - - [data-closed] & { - display: block; - } - [data-expanded] & { - display: none; - } - } - [data-slot="faq-icon-minus"] { - flex-shrink: 0; - color: var(--color-text-weak); - margin-top: 2px; - - [data-closed] & { - display: none; - } - [data-expanded] & { - display: block; - } - } - [data-slot="faq-question-text"] { - flex-grow: 1; - text-align: left; - } - } - - [data-slot="faq-answer"] { - margin-left: 40px; - margin-bottom: 32px; - line-height: 200%; - } - } -} diff --git a/packages/console/app/src/routes/download/index.tsx b/packages/console/app/src/routes/download/index.tsx deleted file mode 100644 index d4de97c68..000000000 --- a/packages/console/app/src/routes/download/index.tsx +++ /dev/null @@ -1,480 +0,0 @@ -import "./index.css" -import { Title, Meta, Link } from "@solidjs/meta" -import { A, createAsync, query } from "@solidjs/router" -import { Header } from "~/component/header" -import { Footer } from "~/component/footer" -import { IconCopy, IconCheck } from "~/component/icon" -import { Faq } from "~/component/faq" -import desktopAppIcon from "../../asset/lander/opencode-desktop-icon.png" -import { Legal } from "~/component/legal" -import { config } from "~/config" -import { createSignal, onMount, Show, JSX } from "solid-js" -import { DownloadPlatform } from "./types" - -type OS = "macOS" | "Windows" | "Linux" | null - -function detectOS(): OS { - if (typeof navigator === "undefined") return null - const platform = navigator.platform.toLowerCase() - const userAgent = navigator.userAgent.toLowerCase() - - if (platform.includes("mac") || userAgent.includes("mac")) return "macOS" - if (platform.includes("win") || userAgent.includes("win")) return "Windows" - if (platform.includes("linux") || userAgent.includes("linux")) return "Linux" - return null -} - -function getDownloadPlatform(os: OS): DownloadPlatform { - switch (os) { - case "macOS": - return "darwin-aarch64-dmg" - case "Windows": - return "windows-x64-nsis" - case "Linux": - return "linux-x64-deb" - default: - return "darwin-aarch64-dmg" - } -} - -function getDownloadHref(platform: DownloadPlatform) { - return `/download/${platform}` -} - -function IconDownload(props: JSX.SvgSVGAttributes) { - return ( - - - - ) -} - -function CopyStatus() { - return ( - - - - - ) -} - -export default function Download() { - const [detectedOS, setDetectedOS] = createSignal(null) - - onMount(() => { - setDetectedOS(detectOS()) - }) - - const handleCopyClick = (command: string) => (event: Event) => { - const button = event.currentTarget as HTMLButtonElement - navigator.clipboard.writeText(command) - button.setAttribute("data-copied", "") - setTimeout(() => { - button.removeAttribute("data-copied") - }, 1500) - } - return ( -
    - OpenCode | Download - - -
    -
    - -
    -
    -
    - OpenCode Desktop -
    -
    -

    Download OpenCode

    -

    Available in Beta for macOS, Windows, and Linux

    - - - - Download for {detectedOS()} - - -
    -
    - -
    -
    - [1] OpenCode Terminal -
    -
    - - - - - -
    -
    - -
    -
    - [2] OpenCode Desktop (Beta) -
    -
    - -
    -
    - - - - - - - macOS (Apple Silicon) - -
    - - Download - -
    -
    -
    - - - - - - macOS (Intel) -
    - - Download - -
    -
    -
    - - - - - - - - - - - - - Windows (x64) -
    - - Download - -
    -
    -
    - - - - - - Linux (.deb) -
    - - Download - -
    -
    -
    - - - - - - Linux (.rpm) -
    - - Download - -
    -
    -
    - - - - - - Linux (.AppImage) -
    - - Download - -
    -
    -
    - -
    -
    - [3] OpenCode Extensions -
    -
    -
    -
    - - - - - - - - - - - - - VS Code -
    - - Install - -
    - -
    -
    - - - - - - - - - - - - - Cursor -
    - - Install - -
    - -
    -
    - - - - - - Zed -
    - - Install - -
    - -
    -
    - - - - - - Windsurf -
    - - Install - -
    - -
    -
    - - - - - - VSCodium -
    - - Install - -
    -
    -
    - -
    -
    - [4] OpenCode Integrations -
    -
    -
    -
    - - - - - - GitHub -
    - - Install - -
    - -
    -
    - - - - - - GitLab -
    - - Install - -
    -
    -
    -
    - -
    -
    -

    FAQ

    -
    -
      -
    • - - OpenCode is an open source agent that helps you write and run code with any AI model. It's available as - a terminal-based interface, desktop app, or IDE extension. - -
    • -
    • - - The easiest way to get started is to read the intro. - -
    • -
    • - - Not necessarily, but probably. You'll need an AI subscription if you want to connect OpenCode to a paid - provider, although you can work with{" "} - - local models - {" "} - for free. While we encourage users to use Zen, OpenCode works with all popular - providers such as OpenAI, Anthropic, xAI etc. - -
    • -
    • - - Not anymore! OpenCode is now available as an app for your desktop. - -
    • -
    • - - OpenCode is 100% free to use. Any additional costs will come from your subscription to a model provider. - While OpenCode works with any model provider, we recommend using Zen. - -
    • -
    • - - Your data and information is only stored when you create sharable links in OpenCode. Learn more about{" "} - share pages. - -
    • -
    • - - Yes, OpenCode is fully open source. The source code is public on{" "} - - GitHub - {" "} - under the{" "} - - MIT License - - , meaning anyone can use, modify, or contribute to its development. Anyone from the community can file - issues, submit pull requests, and extend functionality. - -
    • -
    -
    - -
    -
    - -
    - ) -} diff --git a/packages/console/app/src/routes/download/types.ts b/packages/console/app/src/routes/download/types.ts deleted file mode 100644 index 916f97022..000000000 --- a/packages/console/app/src/routes/download/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type DownloadPlatform = - | `darwin-${"x64" | "aarch64"}-dmg` - | "windows-x64-nsis" - | `linux-x64-${"deb" | "rpm" | "appimage"}` diff --git a/packages/console/app/src/routes/enterprise/index.css b/packages/console/app/src/routes/enterprise/index.css index 7eebf16ce..0178e40a2 100644 --- a/packages/console/app/src/routes/enterprise/index.css +++ b/packages/console/app/src/routes/enterprise/index.css @@ -84,16 +84,7 @@ ul { display: flex; justify-content: space-between; - align-items: center; gap: 48px; - - @media (max-width: 55rem) { - gap: 32px; - } - - @media (max-width: 48rem) { - gap: 24px; - } li { display: inline-block; a { @@ -107,25 +98,6 @@ text-underline-offset: 2px; text-decoration-thickness: 1px; } - [data-slot="cta-button"] { - background: var(--color-background-strong); - color: var(--color-text-inverted); - padding: 8px 16px 8px 10px; - border-radius: 4px; - font-weight: 500; - text-decoration: none; - display: flex; - align-items: center; - gap: 8px; - - @media (max-width: 55rem) { - display: none; - } - } - [data-slot="cta-button"]:hover { - background: var(--color-background-strong-hover); - text-decoration: none; - } } } @@ -317,7 +289,7 @@ [data-component="enterprise-column-1"] { h1 { font-size: 1.5rem; - font-weight: 700; + font-weight: 500; color: var(--color-text-strong); margin-bottom: 1rem; } @@ -469,7 +441,7 @@ h3 { font-size: 16px; - font-weight: 700; + font-weight: 500; color: var(--color-text-strong); margin-bottom: 12px; } diff --git a/packages/console/app/src/routes/index.css b/packages/console/app/src/routes/index.css index f100acf8f..e5101442f 100644 --- a/packages/console/app/src/routes/index.css +++ b/packages/console/app/src/routes/index.css @@ -16,8 +16,6 @@ --color-background-strong-hover: hsl(0, 5%, 18%); --color-background-interactive: hsl(62, 84%, 88%); --color-background-interactive-weaker: hsl(64, 74%, 95%); - --color-surface-raised-base: hsla(0, 100%, 3%, 0.01); - --color-surface-raised-base-active: hsla(0, 100%, 17%, 0.06); --color-text: hsl(0, 1%, 39%); --color-text-weak: hsl(0, 1%, 60%); @@ -26,7 +24,7 @@ --color-text-inverted: hsl(0, 20%, 99%); --color-border: hsl(30, 2%, 81%); - --color-border-weak: hsla(0, 100%, 3%, 0.12); + --color-border-weak: hsl(0, 1%, 85%); --color-icon: hsl(0, 1%, 55%); } @@ -64,14 +62,6 @@ body { } } -[data-slot="br"] { - display: block; - - @media (max-width: 60rem) { - display: none; - } -} - [data-page="opencode"] { background: var(--color-background); --padding: 5rem; @@ -206,7 +196,6 @@ body { [data-component="top"] { padding: 24px var(--padding); height: 80px; - min-height: 80px; position: sticky; top: 0; display: flex; @@ -226,16 +215,7 @@ body { ul { display: flex; justify-content: space-between; - align-items: center; gap: 48px; - - @media (max-width: 55rem) { - gap: 32px; - } - - @media (max-width: 48rem) { - gap: 24px; - } li { display: inline-block; a { @@ -249,25 +229,6 @@ body { text-underline-offset: var(--space-1); text-decoration-thickness: 1px; } - [data-slot="cta-button"] { - background: var(--color-background-strong); - color: var(--color-text-inverted); - padding: 8px 16px 8px 10px; - border-radius: 4px; - font-weight: 500; - text-decoration: none; - display: flex; - align-items: center; - gap: 8px; - - @media (max-width: 55rem) { - display: none; - } - } - [data-slot="cta-button"]:hover { - background: var(--color-background-strong-hover); - text-decoration: none; - } } } @@ -361,7 +322,7 @@ body { display: flex; flex-direction: column; max-width: 100%; - padding: calc(var(--vertical-padding) * 1.5) var(--padding); + padding: calc(var(--vertical-padding) * 2) var(--padding); @media (max-width: 30rem) { padding: var(--vertical-padding) var(--padding); @@ -377,11 +338,6 @@ body { } } - [data-slot="installation-instructions"] { - color: var(--color-text-strong); - margin-bottom: 8px; - } - [data-slot="installation"] { width: 100%; max-width: 100%; @@ -392,11 +348,6 @@ body { } } - [data-slot="installation-options"] { - font-size: 13px; - margin-top: 12px; - } - [data-component="tabs"] { [data-slot="tablist"] { display: flex; @@ -465,7 +416,7 @@ body { cursor: pointer; align-items: center; color: var(--color-text); - gap: 16px; + gap: var(--space-1); color: var(--color-text); padding: 8px 16px 8px 8px; border-radius: 4px; @@ -504,77 +455,6 @@ body { } } - [data-component="desktop-app-banner"] { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 32px; - - [data-slot="badge"] { - background: var(--color-background-strong); - color: var(--color-text-inverted); - font-weight: 500; - padding: 4px 8px; - line-height: 1; - flex-shrink: 0; - } - - [data-slot="content"] { - display: flex; - align-items: center; - gap: 4px; - } - - [data-slot="text"] { - color: var(--color-text-strong); - line-height: 1.4; - - @media (max-width: 30.625rem) { - display: none; - } - } - - [data-slot="platforms"] { - @media (max-width: 49.125rem) { - display: none; - } - } - - [data-slot="link"] { - color: var(--color-text-weak); - white-space: nowrap; - text-decoration: none; - - @media (max-width: 30.625rem) { - display: none; - } - } - - [data-slot="link"]:hover { - color: var(--color-text); - text-decoration: underline; - text-underline-offset: 2px; - text-decoration-thickness: 1px; - } - - [data-slot="link-mobile"] { - display: none; - color: var(--color-text-strong); - white-space: nowrap; - text-decoration: none; - - @media (max-width: 30.625rem) { - display: inline; - } - } - - [data-slot="link-mobile"]:hover { - text-decoration: underline; - text-underline-offset: 2px; - text-decoration-thickness: 1px; - } - } - [data-slot="hero-copy"] { [data-slot="releases"] { background: none; @@ -600,10 +480,10 @@ body { } h1 { - font-size: 38px; + font-size: 28px; color: var(--color-text-strong); - font-weight: 700; - margin-bottom: 8px; + font-weight: 500; + margin-bottom: 16px; @media (max-width: 60rem) { font-size: 22px; @@ -612,7 +492,7 @@ body { p { color: var(--color-text); - margin-bottom: 32px; + margin-bottom: 24px; max-width: 82%; @media (max-width: 50rem) { @@ -628,6 +508,7 @@ body { border-radius: 4px; font-weight: 500; cursor: pointer; + margin-bottom: 80px; display: flex; width: fit-content; gap: 12px; @@ -705,7 +586,7 @@ body { h3 { font-size: 16px; - font-weight: 700; + font-weight: 500; color: var(--color-text-strong); margin-bottom: 12px; } @@ -726,25 +607,6 @@ body { padding: var(--vertical-padding) var(--padding); color: var(--color-text); - a { - background: var(--color-background-strong); - padding: 8px 12px 8px 20px; - color: var(--color-text-inverted); - border: none; - border-radius: 4px; - font-weight: 500; - cursor: pointer; - margin-top: 40px; - display: flex; - width: fit-content; - gap: 12px; - text-decoration: none; - } - - a:hover { - background: var(--color-background-strong-hover); - } - ul { padding: 0; li { @@ -810,7 +672,7 @@ body { [data-slot="privacy-title"] { h3 { font-size: 16px; - font-weight: 700; + font-weight: 500; color: var(--color-text-strong); margin-bottom: 12px; } @@ -836,7 +698,7 @@ body { [data-slot="zen-cta-copy"] { strong { color: var(--color-text-strong); - font-weight: 700; + font-weight: 500; margin-bottom: 16px; display: block; } diff --git a/packages/console/app/src/routes/index.tsx b/packages/console/app/src/routes/index.tsx index 227021b89..1a41f0e6a 100644 --- a/packages/console/app/src/routes/index.tsx +++ b/packages/console/app/src/routes/index.tsx @@ -1,6 +1,6 @@ import "./index.css" import { Title, Meta, Link } from "@solidjs/meta" -//import { HttpHeader } from "@solidjs/start" +// import { HttpHeader } from "@solidjs/start" import video from "../asset/lander/opencode-min.mp4" import videoPoster from "../asset/lander/opencode-poster.png" import { IconCopy, IconCheck } from "../component/icon" @@ -43,7 +43,7 @@ export default function Home() { return (
    {/**/} - OpenCode | The open source AI coding agent + OpenCode | The AI coding agent built for the terminal @@ -52,32 +52,26 @@ export default function Home() {
    -
    - New -
    - - Desktop app available in beta on macOS, Windows, and Linux. - - - Download now - - - Download the desktop beta now - -
    -
    -
    - {/**/} - {/* What’s new in {release()?.name ?? "the latest release"}*/} - {/**/} -

    The open source AI coding agent

    + + What’s new in {release()?.name ?? "the latest release"} + +

    The AI coding agent built for the terminal

    - Free models included or connect any model from any provider, including - Claude, GPT, Gemini and more. + OpenCode is fully open source, giving you control and freedom to use any provider, any model, and any + editor.

    + + Read docs + + + +

    What is OpenCode?

    -

    OpenCode is an open source agent that helps you write code in your terminal, IDE, or desktop.

    +

    OpenCode is an open source agent that helps you write and run code directly from the terminal.

      +
    • + [*] +
      + Native TUI A responsive, native, themeable terminal UI +
      +
    • [*]
      @@ -204,21 +204,10 @@ export default function Home() {
    • [*]
      - Any editor Available as a terminal interface, desktop app, and IDE extension + Any editor OpenCode runs in your terminal, pair it with any IDE
    - - Read docs - - - -
    @@ -228,7 +217,7 @@ export default function Home() { [*]

    With over {config.github.starsFormatted.full} GitHub stars,{" "} - {config.stats.contributors} contributors, and over{" "} + {config.stats.contributors} contributors, and almost{" "} {config.stats.commits} commits, OpenCode is used and trusted by over{" "} {config.stats.monthlyUsers} developers every month.

    @@ -656,8 +645,9 @@ export default function Home() {
    • - OpenCode is an open source agent that helps you write and run code with any AI model. It's available - as a terminal-based interface, desktop app, or IDE extension. + OpenCode is an open source agent that helps you write and run code directly from the terminal. You can + pair OpenCode with any AI model, and because it’s terminal-based you can pair it with your preferred + code editor.
    • @@ -667,38 +657,29 @@ export default function Home() {
    • - Not necessarily, OpenCode comes with a set of free models that you can use without creating an - account. Aside from these, you can use any of the popular coding models by creating a{" "} - Zen account. While we encourage users to use Zen, OpenCode also works with all - popular providers such as OpenAI, Anthropic, xAI etc. You can even connect your{" "} + Not necessarily, but probably. You’ll need an AI subscription if you want to connect OpenCode to a + paid provider, although you can work with{" "} local models - - . - -
    • -
    • - - Yes, OpenCode supports subscription plans from all major providers. You can use your Claude Pro/Max, - ChatGPT Plus/Pro, or GitHub Copilot subscriptions. Learn more - . + {" "} + for free. While we encourage users to use Zen, OpenCode works with all popular + providers such as OpenAI, Anthropic, xAI etc.
    • - Not anymore! OpenCode is now available as an app for your desktop. + Yes, for now. We are actively working on a desktop app. Join the waitlist for early access.
    • - OpenCode is 100% free to use. It also comes with a set of free models. There might be additional costs - if you connect any other provider. + OpenCode is 100% free to use. Any additional costs will come from your subscription to a model + provider. While OpenCode works with any model provider, we recommend using Zen.
    • - Your data and information is only stored when you use our free models or create sharable links. Learn - more about our models and{" "} + Your data and information is only stored when you create sharable links in OpenCode. Learn more about{" "} share pages.
    • @@ -758,17 +739,6 @@ export default function Home() { />
    -
    - - - -
    -
    - - - -
    Learn about Zen diff --git a/packages/console/app/src/routes/legal/privacy-policy/index.css b/packages/console/app/src/routes/legal/privacy-policy/index.css deleted file mode 100644 index dbc9f2aa1..000000000 --- a/packages/console/app/src/routes/legal/privacy-policy/index.css +++ /dev/null @@ -1,343 +0,0 @@ -[data-component="privacy-policy"] { - max-width: 800px; - margin: 0 auto; - line-height: 1.7; -} - -[data-component="privacy-policy"] h1 { - font-size: 2rem; - font-weight: 700; - color: var(--color-text-strong); - margin-bottom: 0.5rem; - margin-top: 0; -} - -[data-component="privacy-policy"] .effective-date { - font-size: 0.95rem; - color: var(--color-text-weak); - margin-bottom: 2rem; -} - -[data-component="privacy-policy"] h2 { - font-size: 1.5rem; - font-weight: 600; - color: var(--color-text-strong); - margin-top: 3rem; - margin-bottom: 1rem; - padding-top: 1rem; - border-top: 1px solid var(--color-border-weak); -} - -[data-component="privacy-policy"] h2:first-of-type { - margin-top: 2rem; -} - -[data-component="privacy-policy"] h3 { - font-size: 1.25rem; - font-weight: 600; - color: var(--color-text-strong); - margin-top: 2rem; - margin-bottom: 1rem; -} - -[data-component="privacy-policy"] h4 { - font-size: 1.1rem; - font-weight: 600; - color: var(--color-text-strong); - margin-top: 1.5rem; - margin-bottom: 0.75rem; -} - -[data-component="privacy-policy"] p { - margin-bottom: 1rem; - color: var(--color-text); -} - -[data-component="privacy-policy"] ul, -[data-component="privacy-policy"] ol { - margin-bottom: 1rem; - padding-left: 1.5rem; - color: var(--color-text); -} - -[data-component="privacy-policy"] li { - margin-bottom: 0.5rem; - line-height: 1.7; -} - -[data-component="privacy-policy"] ul ul, -[data-component="privacy-policy"] ul ol, -[data-component="privacy-policy"] ol ul, -[data-component="privacy-policy"] ol ol { - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} - -[data-component="privacy-policy"] a { - color: var(--color-text-strong); - text-decoration: underline; - text-underline-offset: 2px; - text-decoration-thickness: 1px; - word-break: break-word; -} - -[data-component="privacy-policy"] a:hover { - text-decoration-thickness: 2px; -} - -[data-component="privacy-policy"] strong { - font-weight: 600; - color: var(--color-text-strong); -} - -[data-component="privacy-policy"] .table-wrapper { - overflow-x: auto; - margin: 1.5rem 0; -} - -[data-component="privacy-policy"] table { - width: 100%; - border-collapse: collapse; - border: 1px solid var(--color-border); -} - -[data-component="privacy-policy"] th, -[data-component="privacy-policy"] td { - padding: 0.75rem 1rem; - text-align: left; - border: 1px solid var(--color-border); - vertical-align: top; -} - -[data-component="privacy-policy"] th { - background: var(--color-background-weak); - font-weight: 600; - color: var(--color-text-strong); -} - -[data-component="privacy-policy"] td { - color: var(--color-text); -} - -[data-component="privacy-policy"] td ul { - margin: 0; - padding-left: 1.25rem; -} - -[data-component="privacy-policy"] td li { - margin-bottom: 0.25rem; -} - -/* Mobile responsiveness */ -@media (max-width: 60rem) { - [data-component="privacy-policy"] { - padding: 0; - } - - [data-component="privacy-policy"] h1 { - font-size: 1.75rem; - } - - [data-component="privacy-policy"] h2 { - font-size: 1.35rem; - margin-top: 2.5rem; - } - - [data-component="privacy-policy"] h3 { - font-size: 1.15rem; - } - - [data-component="privacy-policy"] h4 { - font-size: 1rem; - } - - [data-component="privacy-policy"] table { - font-size: 0.9rem; - } - - [data-component="privacy-policy"] th, - [data-component="privacy-policy"] td { - padding: 0.5rem 0.75rem; - } -} - -html { - scroll-behavior: smooth; -} - -[data-component="privacy-policy"] [id] { - scroll-margin-top: 100px; -} - -@media print { - @page { - margin: 2cm; - size: letter; - } - - [data-component="top"], - [data-component="footer"], - [data-component="legal"] { - display: none !important; - } - - [data-page="legal"] { - background: white !important; - padding: 0 !important; - } - - [data-component="container"] { - max-width: none !important; - border: none !important; - margin: 0 !important; - } - - [data-component="content"], - [data-component="brand-content"] { - padding: 0 !important; - margin: 0 !important; - } - - [data-component="privacy-policy"] { - max-width: none !important; - margin: 0 !important; - padding: 0 !important; - } - - [data-component="privacy-policy"] * { - color: black !important; - background: transparent !important; - } - - [data-component="privacy-policy"] h1 { - font-size: 24pt; - margin-top: 0; - margin-bottom: 12pt; - page-break-after: avoid; - } - - [data-component="privacy-policy"] h2 { - font-size: 18pt; - border-top: 2pt solid black !important; - padding-top: 12pt; - margin-top: 24pt; - margin-bottom: 8pt; - page-break-after: avoid; - page-break-before: auto; - } - - [data-component="privacy-policy"] h2:first-of-type { - margin-top: 16pt; - } - - [data-component="privacy-policy"] h3 { - font-size: 14pt; - margin-top: 16pt; - margin-bottom: 8pt; - page-break-after: avoid; - } - - [data-component="privacy-policy"] h4 { - font-size: 12pt; - margin-top: 12pt; - margin-bottom: 6pt; - page-break-after: avoid; - } - - [data-component="privacy-policy"] p { - font-size: 11pt; - line-height: 1.5; - margin-bottom: 8pt; - orphans: 3; - widows: 3; - } - - [data-component="privacy-policy"] .effective-date { - font-size: 10pt; - margin-bottom: 16pt; - } - - [data-component="privacy-policy"] ul, - [data-component="privacy-policy"] ol { - margin-bottom: 8pt; - page-break-inside: auto; - } - - [data-component="privacy-policy"] li { - font-size: 11pt; - line-height: 1.5; - margin-bottom: 4pt; - page-break-inside: avoid; - } - - [data-component="privacy-policy"] a { - color: black !important; - text-decoration: underline; - } - - [data-component="privacy-policy"] .table-wrapper { - overflow: visible !important; - margin: 12pt 0; - } - - [data-component="privacy-policy"] table { - border: 2pt solid black !important; - page-break-inside: avoid; - width: 100% !important; - font-size: 10pt; - } - - [data-component="privacy-policy"] th, - [data-component="privacy-policy"] td { - border: 1pt solid black !important; - padding: 6pt 8pt !important; - background: white !important; - } - - [data-component="privacy-policy"] th { - background: #f0f0f0 !important; - font-weight: bold; - page-break-after: avoid; - } - - [data-component="privacy-policy"] tr { - page-break-inside: avoid; - } - - [data-component="privacy-policy"] td ul { - margin: 2pt 0; - padding-left: 12pt; - } - - [data-component="privacy-policy"] td li { - margin-bottom: 2pt; - font-size: 9pt; - } - - [data-component="privacy-policy"] strong { - font-weight: bold; - color: black !important; - } - - [data-component="privacy-policy"] h1, - [data-component="privacy-policy"] h2, - [data-component="privacy-policy"] h3, - [data-component="privacy-policy"] h4 { - page-break-inside: avoid; - page-break-after: avoid; - } - - [data-component="privacy-policy"] h2 + p, - [data-component="privacy-policy"] h3 + p, - [data-component="privacy-policy"] h4 + p, - [data-component="privacy-policy"] h2 + ul, - [data-component="privacy-policy"] h3 + ul, - [data-component="privacy-policy"] h4 + ul { - page-break-before: avoid; - } - - [data-component="privacy-policy"] table, - [data-component="privacy-policy"] .table-wrapper { - page-break-inside: avoid; - } -} diff --git a/packages/console/app/src/routes/legal/privacy-policy/index.tsx b/packages/console/app/src/routes/legal/privacy-policy/index.tsx deleted file mode 100644 index 8b30ba14e..000000000 --- a/packages/console/app/src/routes/legal/privacy-policy/index.tsx +++ /dev/null @@ -1,1512 +0,0 @@ -import "../../brand/index.css" -import "./index.css" -import { Title, Meta, Link } from "@solidjs/meta" -import { Header } from "~/component/header" -import { config } from "~/config" -import { Footer } from "~/component/footer" -import { Legal } from "~/component/legal" - -export default function PrivacyPolicy() { - return ( -
    - OpenCode | Privacy Policy - - -
    -
    - -
    -
    -
    -

    Privacy Policy

    -

    Effective date: Dec 16, 2025

    - -

    - At OpenCode, we take your privacy seriously. Please read this Privacy Policy to learn how we treat your - personal data.{" "} - - By using or accessing our Services in any manner, you acknowledge that you accept the practices and - policies outlined below, and you hereby consent that we will collect, use and disclose your - information as described in this Privacy Policy. - -

    - -

    - Remember that your use of OpenCode is at all times subject to our Terms of Use,{" "} - https://opencode.ai/legal/terms-of-service, which incorporates - this Privacy Policy. Any terms we use in this Policy without defining them have the definitions given to - them in the Terms of Use. -

    - -

    You may print a copy of this Privacy Policy by clicking the print button in your browser.

    - -

    - As we continually work to improve our Services, we may need to change this Privacy Policy from time to - time. We will alert you of material changes by placing a notice on the OpenCode website, by sending you - an email and/or by some other means. Please note that if you've opted not to receive legal notice emails - from us (or you haven't provided us with your email address), those legal notices will still govern your - use of the Services, and you are still responsible for reading and understanding them. If you use the - Services after any changes to the Privacy Policy have been posted, that means you agree to all of the - changes. -

    - -

    Privacy Policy Table of Contents

    - - -

    What this Privacy Policy Covers

    -

    - This Privacy Policy covers how we treat Personal Data that we gather when you access or use our - Services. "Personal Data" means any information that identifies or relates to a particular individual - and also includes information referred to as "personally identifiable information" or "personal - information" under applicable data privacy laws, rules or regulations. This Privacy Policy does not - cover the practices of companies we don't own or control or people we don't manage. -

    - -

    Personal Data

    - -

    Categories of Personal Data We Collect

    -

    - This chart details the categories of Personal Data that we collect and have collected over the past 12 - months: -

    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Category of Personal Data (and Examples)Business or Commercial Purpose(s) for CollectionCategories of Third Parties With Whom We Disclose this Personal Data
    - Profile or Contact Data such as first and last name, email, phone number and - mailing address. - -
      -
    • Providing, Customizing and Improving the Services
    • -
    • Marketing the Services
    • -
    • Corresponding with You
    • -
    -
    -
      -
    • Service Providers
    • -
    • Business Partners
    • -
    • Parties You Authorize, Access or Authenticate
    • -
    -
    - Payment Data such as financial account information, payment card type, full - number of payment card, last 4 digits of payment card, bank account information, billing - address, billing phone number and billing email - -
      -
    • Providing, Customizing and Improving the Services
    • -
    • Marketing the Services
    • -
    • Corresponding with You
    • -
    -
    -
      -
    • Service Providers (specifically our payment processing partner)
    • -
    • Business Partners
    • -
    • Parties You Authorize, Access or Authenticate
    • -
    -
    - Device/IP Data such as IP address, device ID, domain server, type of - device/operating system/browser used to access the Services. - -
      -
    • Providing, Customizing and Improving the Services
    • -
    • Marketing the Services
    • -
    • Corresponding with You
    • -
    -
    -
      -
    • None
    • -
    • Service Providers
    • -
    • Business Partners
    • -
    • Parties You Authorize, Access or Authenticate
    • -
    -
    - Other Identifying Information that You Voluntarily Choose to Provide such as - information included in conversations or prompts that you submit to AI - -
      -
    • Providing, Customizing and Improving the Services
    • -
    • Marketing the Services
    • -
    • Corresponding with You
    • -
    -
    -
      -
    • Service Providers
    • -
    • Business Partners
    • -
    • Parties You Authorize, Access or Authenticate
    • -
    -
    -
    - -

    Our Commercial or Business Purposes for Collecting Personal Data

    - -

    Providing, Customizing and Improving the Services

    -
      -
    • Creating and managing your account or other user profiles.
    • -
    • Providing you with the products, services or information you request.
    • -
    • Meeting or fulfilling the reason you provided the information to us.
    • -
    • Providing support and assistance for the Services.
    • -
    • - Improving the Services, including testing, research, internal analytics and product development. -
    • -
    • Doing fraud protection, security and debugging.
    • -
    • - Carrying out other business purposes stated when collecting your Personal Data or as otherwise set - forth in applicable data privacy laws, such as the California Consumer Privacy Act, as amended by the - California Privacy Rights Act of 2020 (the "CCPA"), the Colorado Privacy Act (the "CPA"), the - Connecticut Data Privacy Act (the "CTDPA"), the Delaware Personal Data Privacy Act (the "DPDPA"), the - Iowa Consumer Data Protection Act (the "ICDPA"), the Montana Consumer Data Privacy Act ("MCDPA"), the - Nebraska Data Privacy Act (the "NDPA"), the New Hampshire Privacy Act (the "NHPA"), the New Jersey - Privacy Act (the "NJPA"), the Oregon Consumer Privacy Act ("OCPA"), the Texas Data Privacy and - Security Act ("TDPSA"), the Utah Consumer Privacy Act (the "UCPA"), or the Virginia Consumer Data - Protection Act (the "VCDPA") (collectively, the "State Privacy Laws"). -
    • -
    - -

    Marketing the Services

    -
      -
    • Marketing and selling the Services.
    • -
    - -

    Corresponding with You

    -
      -
    • - Responding to correspondence that we receive from you, contacting you when necessary or requested, and - sending you information about OpenCode. -
    • -
    • Sending emails and other communications according to your preferences.
    • -
    - -

    Other Permitted Purposes for Processing Personal Data

    -

    - In addition, each of the above referenced categories of Personal Data may be collected, used, and - disclosed with the government, including law enforcement, or other parties to meet certain legal - requirements and enforcing legal terms including: fulfilling our legal obligations under applicable law, - regulation, court order or other legal process, such as preventing, detecting and investigating security - incidents and potentially illegal or prohibited activities; protecting the rights, property or safety of - you, OpenCode or another party; enforcing any agreements with you; responding to claims that any posting - or other content violates third-party rights; and resolving disputes. -

    - -

    - We will not collect additional categories of Personal Data or use the Personal Data we collected for - materially different, unrelated or incompatible purposes without providing you notice or obtaining your - consent. -

    - -

    Categories of Sources of Personal Data

    -

    We collect Personal Data about you from the following categories of sources:

    - -

    You

    -
      -
    • - When you provide such information directly to us. -
        -
      • When you create an account or use our interactive tools and Services.
      • -
      • - When you voluntarily provide information in free-form text boxes through the Services or through - responses to surveys or questionnaires. -
      • -
      • When you send us an email or otherwise contact us.
      • -
      -
    • -
    • - When you use the Services and such information is collected automatically. -
        -
      • Through Cookies (defined in the "Tracking Tools and Opt-Out" section below).
      • -
      • - If you download and install certain applications and software we make available, we may receive - and collect information transmitted from your computing device for the purpose of providing you - the relevant Services, such as information regarding when you are logged on and available to - receive updates or alert notices. -
      • -
      -
    • -
    - -

    Public Records

    -
      -
    • From the government.
    • -
    - -

    Third Parties

    -
      -
    • - Vendors -
        -
      • - We may use analytics providers to analyze how you interact and engage with the Services, or third - parties may help us provide you with customer support. -
      • -
      • We may use vendors to obtain information to generate leads and create user profiles.
      • -
      -
    • -
    - -

    How We Disclose Your Personal Data

    -

    - We disclose your Personal Data to the categories of service providers and other parties listed in this - section. Depending on state laws that may be applicable to you, some of these disclosures may constitute - a "sale" of your Personal Data. For more information, please refer to the state-specific sections below. -

    - -

    Service Providers

    -

    - These parties help us provide the Services or perform business functions on our behalf. They include: -

    -
      -
    • Hosting, technology and communication providers.
    • -
    • Analytics providers for web traffic or usage of the site.
    • -
    • Security and fraud prevention consultants.
    • -
    • Support and customer service vendors.
    • -
    - -

    Business Partners

    -

    These parties partner with us in offering various services. They include:

    -
      -
    • Businesses that you have a relationship with.
    • -
    • Companies that we partner with to offer joint promotional offers or opportunities.
    • -
    - -

    Parties You Authorize, Access or Authenticate

    -
      -
    • Home buyers
    • -
    - -

    Legal Obligations

    -

    - We may disclose any Personal Data that we collect with third parties in conjunction with any of the - activities set forth under "Other Permitted Purposes for Processing Personal Data" section above. -

    - -

    Business Transfers

    -

    - All of your Personal Data that we collect may be transferred to a third party if we undergo a merger, - acquisition, bankruptcy or other transaction in which that third party assumes control of our business - (in whole or in part). -

    - -

    Data that is Not Personal Data

    -

    - We may create aggregated, de-identified or anonymized data from the Personal Data we collect, including - by removing information that makes the data personally identifiable to a particular user. We may use - such aggregated, de-identified or anonymized data and disclose it with third parties for our lawful - business purposes, including to analyze, build and improve the Services and promote our business, - provided that we will not disclose such data in a manner that could identify you. -

    - -

    Tracking Tools and Opt-Out

    -

    - The Services use cookies and similar technologies such as pixel tags, web beacons, clear GIFs and - JavaScript (collectively, "Cookies") to enable our servers to recognize your web browser, tell us how - and when you visit and use our Services, analyze trends, learn about our user base and operate and - improve our Services. Cookies are small pieces of data– usually text files – placed on your computer, - tablet, phone or similar device when you use that device to access our Services. We may also supplement - the information we collect from you with information received from third parties, including third - parties that have placed their own Cookies on your device(s). -

    - -

    - Please note that because of our use of Cookies, the Services do not support "Do Not Track" requests sent - from a browser at this time. -

    - -

    We use the following types of Cookies:

    - -
      -
    • - Essential Cookies. Essential Cookies are required for providing you with features or - services that you have requested. For example, certain Cookies enable you to log into secure areas of - our Services. Disabling these Cookies may make certain features and services unavailable. -
    • -
    • - Functional Cookies. Functional Cookies are used to record your choices and settings - regarding our Services, maintain your preferences over time and recognize you when you return to our - Services. These Cookies help us to personalize our content for you, greet you by name and remember - your preferences (for example, your choice of language or region). -
    • -
    • - Performance/Analytical Cookies. Performance/Analytical Cookies allow us to understand - how visitors use our Services. They do this by collecting information about the number of visitors to - the Services, what pages visitors view on our Services and how long visitors are viewing pages on the - Services. Performance/Analytical Cookies also help us measure the performance of our advertising - campaigns in order to help us improve our campaigns and the Services' content for those who engage - with our advertising. For example, Google LLC ("Google") uses cookies in connection with its Google - Analytics services. Google's ability to use and disclose information collected by Google Analytics - about your visits to the Services is subject to the Google Analytics Terms of Use and the Google - Privacy Policy. You have the option to opt-out of Google's use of Cookies by visiting the Google - advertising opt-out page at{" "} - www.google.com/privacy_ads.html or the Google - Analytics Opt-out Browser Add-on at{" "} - https://tools.google.com/dlpage/gaoptout/. -
    • -
    - -

    - You can decide whether or not to accept Cookies through your internet browser's settings. Most browsers - have an option for turning off the Cookie feature, which will prevent your browser from accepting new - Cookies, as well as (depending on the sophistication of your browser software) allow you to decide on - acceptance of each new Cookie in a variety of ways. You can also delete all Cookies that are already on - your device. If you do this, however, you may have to manually adjust some preferences every time you - visit our website and some of the Services and functionalities may not work. -

    - -

    - To find out more information about Cookies generally, including information about how to manage and - delete Cookies, please visit{" "} - http://www.allaboutcookies.org/. -

    - -

    Data Security

    -

    - We seek to protect your Personal Data from unauthorized access, use and disclosure using appropriate - physical, technical, organizational and administrative security measures based on the type of Personal - Data and how we are processing that data. You should also help protect your data by appropriately - selecting and protecting your password and/or other sign-on mechanism; limiting access to your computer - or device and browser; and signing off after you have finished accessing your account. Although we work - to protect the security of your account and other data that we hold in our records, please be aware that - no method of transmitting data over the internet or storing data is completely secure. -

    - -

    Data Retention

    -

    - We retain Personal Data about you for as long as necessary to provide you with our Services or to - perform our business or commercial purposes for collecting your Personal Data. When establishing a - retention period for specific categories of data, we consider who we collected the data from, our need - for the Personal Data, why we collected the Personal Data, and the sensitivity of the Personal Data. In - some cases we retain Personal Data for longer, if doing so is necessary to comply with our legal - obligations, resolve disputes or collect fees owed, or is otherwise permitted or required by applicable - law, rule or regulation. We may further retain information in an anonymous or aggregated form where that - information would not identify you personally. -

    - -

    Personal Data of Children

    -

    - As noted in the Terms of Use, we do not knowingly collect or solicit Personal Data from children under - 18 years of age; if you are a child under the age of 18, please do not attempt to register for or - otherwise use the Services or send us any Personal Data. If we learn we have collected Personal Data - from a child under 18 years of age, we will delete that information as quickly as possible. If you - believe that a child under 18 years of age may have provided Personal Data to us, please contact us at{" "} - contact@anoma.ly. -

    - -

    California Resident Rights

    -

    - If you are a California resident, you have the rights set forth in this section. Please see the - "Exercising Your Rights under the State Privacy Laws" section below for instructions regarding how to - exercise these rights. Please note that we may process Personal Data of our customers' end users or - employees in connection with our provision of certain services to our customers. If we are processing - your Personal Data as a service provider, you should contact the entity that collected your Personal - Data in the first instance to address your rights with respect to such data. Additionally, please note - that these rights are subject to certain conditions and exceptions under applicable law, which may - permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a California resident, the portion that is more protective of Personal Data shall control to the - extent of such conflict. If you have any questions about this section or whether any of the following - rights apply to you, please contact us at contact@anoma.ly. -

    - -

    Access

    -

    - You have the right to request certain information about our collection and use of your Personal Data. In - response, we will provide you with the following information in the past 12 months: -

    -
      -
    • The categories of Personal Data that we have collected about you.
    • -
    • The categories of sources from which that Personal Data was collected.
    • -
    • The business or commercial purpose for collecting or selling your Personal Data.
    • -
    • The categories of third parties with whom we have shared your Personal Data.
    • -
    • The specific pieces of Personal Data that we have collected about you.
    • -
    - -

    - If we have disclosed your Personal Data to any third parties for a business purpose over the past 12 - months, we will identify the categories of Personal Data shared with each category of third party - recipient. If we have sold your Personal Data over the past 12 months, we will identify the categories - of Personal Data sold to each category of third party recipient. -

    - -

    - You may request the above information beyond the 12-month period, but no earlier than January 1, 2022. - If you do make such a request, we are required to provide that information unless doing so proves - impossible or would involve disproportionate effort. -

    - -

    Deletion

    -

    - You have the right to request that we delete the Personal Data that we have collected from you. Under - the CCPA, this right is subject to certain exceptions: for example, we may need to retain your Personal - Data to provide you with the Services or complete a transaction or other action you have requested, or - if deletion of your Personal Data involves disproportionate effort. If your deletion request is subject - to one of these exceptions, we may deny your deletion request. -

    - -

    Correction

    -

    - You have the right to request that we correct any inaccurate Personal Data we have collected about you. - Under the CCPA, this right is subject to certain exceptions: for example, if we decide, based on the - totality of circumstances related to your Personal Data, that such data is correct. If your correction - request is subject to one of these exceptions, we may deny your request. -

    - -

    Personal Data Sales Opt-Out

    -

    - We will not sell or share your Personal Data, and have not done so over the last 12 months. To our - knowledge, we do not sell or share the Personal Data of minors under 13 years of age or of consumers - under 16 years of age. -

    - -

    Limit the Use of Sensitive Personal Information

    -

    - Consumers have certain rights over the processing of their Sensitive Personal Information. However, we - do not collect Sensitive Personal Information. -

    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the CCPA

    -

    - We will not discriminate against you for exercising your rights under the CCPA. We will not deny you our - goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the CCPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the CCPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Colorado Resident Rights

    -

    - If you are a Colorado resident, you have the rights set forth under the Colorado Privacy Act ("CPA"). - Please see the "Exercising Your Rights under the State Privacy Laws" section below for instructions - regarding how to exercise these rights. Please note that we may process Personal Data of our customers' - end users or employees in connection with our provision of certain services to our customers. If we are - processing your Personal Data as a service provider, you should contact the entity that collected your - Personal Data in the first instance to address your rights with respect to such data. Additionally, - please note that these rights are subject to certain conditions and exceptions under applicable law, - which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a Colorado resident, the portion that is more protective of Personal Data shall control to the - extent of such conflict. If you have any questions about this section or whether any of the following - rights apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access and request a copy of your Personal Data in a machine-readable format, to the extent technically - feasible, twice within a calendar year. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data concerning you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the CPA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" to make "Decisions" under the CPA. "Profiling" - means any form of automated processing performed on personal data to evaluate, analyze or predict - personal aspects related to an identified or identifiable individual's economic situation, health, - personal preferences, interests, reliability, behavior, location or movements. "Decision" means any - "Decisions that produce legal or similarly significant effects concerning a Consumer," as defined in the - CPA that concern you. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data, 2) - Personal Data from a known child under 13 years of age, 3) to sell, or process Personal Data for - Targeted Advertising or Profiling after you exercise your right to opt-out, or 4) Personal Data for - Secondary Use. -

    - -

    - If you would like to withdraw your consent, please follow the instructions under the "Exercising Your - Rights under the State Privacy Laws" section. -

    - -

    We Will Not Discriminate Against You

    -

    - We will not process your personal data in violation of state and federal laws that prohibit unlawful - discrimination against consumers. -

    - -

    Connecticut Resident Rights

    -

    - If you are a Connecticut resident, you have the rights set forth under the Connecticut Data Privacy Act - ("CTDPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a Connecticut resident, the portion that is more protective of Personal Data shall control to the - extent of such conflict. If you have any questions about this section or whether any of the following - rights apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access your Personal Data and request a copy of your Personal Data in a machine-readable format, to the - extent technically feasible. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us or we have obtained about you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the CTDPA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" as defined under the CTDPA. "Profiling" means any - form of automated processing performed on personal data to evaluate, analyze or predict personal aspects - related to an identified or identifiable individual's economic situation, health, personal preferences, - interests, reliability, behavior, location or movements. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data, 2) - Sensitive Data from a known child under 13 years of age, or 3) to sell, or process Personal Data for - Targeted Advertising of a consumer at least 13 years of age but younger than 16 years of age. -

    - -

    However, we currently do not collect or process your Personal Data as described above.

    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the CTDPA

    -

    - We will not discriminate against you for exercising your rights under the CTDPA. We will not deny you - our goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the CTDPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the CTDPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Delaware Resident Rights

    -

    - If you are a Delaware resident, you have the rights set forth under the Delaware Personal Data Privacy - Act ("DPDPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a Delaware resident, the portion that is more protective of Personal Data shall control to the - extent of such conflict. If you have any questions about this section or whether any of the following - rights apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access and request a copy of your Personal Data in a machine-readable format, to the extent technically - feasible. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us or we have obtained about you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the DPDPA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" to make "Decisions" under the DPDPA. "Profiling" - means any form of automated processing performed on personal data to evaluate, analyze or predict - personal aspects related to an identified or identifiable individual's economic circumstances, health, - personal preferences, interests, reliability, behavior, location or movements. "Decision" means any - "Decisions that produce legal or similarly significant effects concerning a Consumer," as defined in the - DPDPA that concern you. To our knowledge, we do not process the Personal Data of consumers under 18 - years of age for the purpose of Profiling. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data, 2) - Sensitive Data from a known child under 13 years of age, 3) or to sell, or process Personal Data for - Targeted Advertising, or Profiling of a consumer at least 13 years of age but younger than 18 years of - age. -

    - -

    However, we currently do not collect or process your Personal Data as described above.

    - -

    We Will Not Discriminate Against You

    -

    - We will not discriminate against you for exercising your rights under the DPDPA. We will not deny you - our goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the DPDPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the DPDPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Iowa Resident Rights

    -

    - If you are an Iowa resident, you have the rights set forth under the Iowa Consumer Data Protection Act - ("ICDPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are an Iowa resident, the portion that is more protective of Personal Data shall control to the extent - of such conflict. If you have any questions about this section or whether any of the following rights - apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access and request a copy of your Personal Data in a machine-readable format, to the extent technically - feasible, twice within a calendar year. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us.

    - -

    Opt-Out of Certain Processing Activities

    -
      -
    • Targeted Advertising: We do not process your Personal Data for targeted advertising purposes.
    • -
    • Sale of Personal Data: We do not currently sell your Personal Data as defined under the ICDPA.
    • -
    • Processing of Sensitive Personal Data: We do not process Sensitive Personal Data.
    • -
    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the ICDPA

    -

    - We will not discriminate against you for exercising your rights under the ICDPA. We will not deny you - our goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the ICDPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the ICDPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Montana Resident Rights

    -

    - If you are a Montana resident, you have the rights set forth under the Montana Consumer Data Privacy Act - ("MCDPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a Montana resident, the portion that is more protective of Personal Data shall control to the extent - of such conflict. If you have any questions about this section or whether any of the following rights - apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access your Personal Data and request a copy of your Personal Data in a machine-readable format, to the - extent technically feasible. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us or we have obtained about you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the MCDPA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" to make "Decisions" under the MCDPA. "Profiling" - means any form of automated processing performed on personal data to evaluate, analyze or predict - personal aspects related to an identified or identifiable individual's economic circumstances, health, - personal preferences, interests, reliability, behavior, location or movements. "Decision" means any - "Decisions that produce legal or similarly significant effects concerning a Consumer," as defined in the - MCDPA that concern you. To our knowledge, we do not process the Personal Data of consumers under 16 - years of age for the purpose of Profiling. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data, 2) - Sensitive Data from a known child under 13 years of age, or 3) to sell, or process Personal Data for - Targeted Advertising or Profiling of a consumer at least 13 years of age but younger than 16 years of - age. -

    - -

    However, we currently do not collect or process your Personal Data as described above.

    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the MCDPA

    -

    - We will not discriminate against you for exercising your rights under the MCDPA. We will not deny you - our goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the MCDPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the MCDPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Nebraska Resident Rights

    -

    - If you are a Nebraska resident, you have the rights set forth under the Nebraska Data Privacy Act - ("NDPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a Nebraska resident, the portion that is more protective of Personal Data shall control to the - extent of such conflict. If you have any questions about this section or whether any of the following - rights apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access your Personal Data and request a copy of your Personal Data in a machine-readable format, to the - extent technically feasible, twice within a calendar year. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us or we have obtained about you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the NDPA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" to make "Decisions" under the NDPA. "Profiling" - means any form of automated processing performed on personal data to evaluate, analyze or predict - personal aspects related to an identified or identifiable individual's economic circumstances, health, - personal preferences, interests, reliability, behavior, location or movements. "Decision" means any - "Decisions that produce legal or similarly significant effects concerning a Consumer," as defined in the - NDPA that concern you. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data and - 2) Sensitive Data from a known child under 13 years of age. -

    - -

    However, we currently do not collect or process your Personal Data as described above.

    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the NDPA

    -

    - We will not discriminate against you for exercising your rights under the NDPA. We will not deny you our - goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the NDPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the NDPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    New Hampshire Resident Rights

    -

    - If you are a New Hampshire resident, you have the rights set forth under the New Hampshire Privacy Act - ("NHPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a New Hampshire resident, the portion that is more protective of Personal Data shall control to the - extent of such conflict. If you have any questions about this section or whether any of the following - rights apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access your Personal Data and request a copy of your Personal Data in a machine-readable format, to the - extent technically feasible. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us or we have obtained about you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the NHPA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" to make "Decisions" under the NHPA. "Profiling" - means any form of automated processing performed on personal data to evaluate, analyze or predict - personal aspects related to an identified or identifiable individual's economic circumstances, health, - personal preferences, interests, reliability, behavior, location or movements. "Decision" means any - "Decisions that produce legal or similarly significant effects concerning a Consumer," as defined in the - NHPA that concern you. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data and - 2) Sensitive Data from a known child under 13 years of age, 3) or to sell or process Personal Data for - Targeted Advertising of a consumer at least 13 years of age but younger than 16 years of age. -

    - -

    However, we currently do not collect or process your Personal Data as described above.

    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the NHPA

    -

    - We will not discriminate against you for exercising your rights under the NHPA. We will not deny you our - goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the NHPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the NHPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    New Jersey Resident Rights

    -

    - If you are a New Jersey resident, you have the rights set forth under the New Jersey Privacy Act - ("NJPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a New Jersey resident, the portion that is more protective of Personal Data shall control to the - extent of such conflict. If you have any questions about this section or whether any of the following - rights apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access and request a copy of your Personal Data in a machine-readable format, to the extent technically - feasible. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data concerning you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the NJPA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" to make "Decisions" under the NJPA. "Profiling" - means any form of automated processing performed on personal data to evaluate, analyze or predict - personal aspects related to an identified or identifiable individual's economic circumstances, health, - personal preferences, interests, reliability, behavior, location or movements. "Decision" means any - "Decisions that produce legal or similarly significant effects concerning a Consumer," as defined in the - NJPA that concern you. To our knowledge, we do not process the Personal Data of consumers under 17 years - of age for the purpose of Profiling. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data, 2) - Sensitive Data from a known child under 13 years of age, 3) or to sell, or process Personal Data for - Targeted Advertising, or Profiling of a consumer at least 13 years of age but younger than 17 years of - age. -

    - -

    However, we currently do not collect or process your Personal Data as described above.

    - -

    We Will Not Discriminate Against You

    -

    - We will not discriminate against you for exercising your rights under the NJPA. We will not deny you our - goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the NJPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the NJPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Oregon Resident Rights

    -

    - If you are an Oregon resident, you have the rights set forth under the Oregon Consumer Privacy Act - ("OCPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are an Oregon resident, the portion that is more protective of Personal Data shall control to the extent - of such conflict. If you have any questions about this section or whether any of the following rights - apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access and request a copy of your Personal Data, including a list of specific third parties, other than - natural persons, to which we have disclosed your Personal Data or any Personal Data, in a - machine-readable format, to the extent technically feasible. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us or we have obtained about you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the OCPA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" to make "Decisions" under the OCPA. "Profiling" - means any form of automated processing performed on personal data to evaluate, analyze or predict - personal aspects related to an identified or identifiable individual's economic circumstances, health, - personal preferences, interests, reliability, behavior, location or movements. "Decision" means any - "Decisions that produce legal or similarly significant effects concerning a Consumer," as defined in the - OCPA that concern you. To our knowledge, we do not process the Personal Data of consumers under 16 years - of age for the purpose of Profiling. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data, 2) - Sensitive Data from a known child under 13 years of age, or 3) to sell, or process Personal Data for - Targeted Advertising, or Profiling of a consumer at least 13 years of age but younger than 16 years of - age. -

    - -

    However, we currently do not collect or process your Personal Data as described above.

    - -

    We Will Not Discriminate Against You

    -

    - We will not discriminate against you for exercising your rights under the OCPA. We will not deny you our - goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the OCPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the OCPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Texas Resident Rights

    -

    - If you are a Texas resident, you have the rights set forth under the Texas Data Privacy and Security Act - ("TDPSA"). Please see the "Exercising Your Rights under the State Privacy Laws" section below for - instructions regarding how to exercise these rights. Please note that we may process Personal Data of - our customers' end users or employees in connection with our provision of certain services to our - customers. If we are processing your Personal Data as a service provider, you should contact the entity - that collected your Personal Data in the first instance to address your rights with respect to such - data. Additionally, please note that these rights are subject to certain conditions and exceptions under - applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a Texas resident, the portion that is more protective of Personal Data shall control to the extent - of such conflict. If you have any questions about this section or whether any of the following rights - apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access your Personal Data and request a copy of your Personal Data in a machine-readable format, to the - extent technically feasible, twice within a calendar year. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us or we have obtained about you.

    - -

    Personal Data Sales Opt-Out

    -

    - We do not currently sell or process for the purposes of targeted advertising your Personal Data as - defined under the TDPSA. -

    - -

    Profiling Opt-Out

    -

    - We do not process your Personal Data for "Profiling" as defined under the TDPSA. "Profiling" means any - form of solely automated processing performed on personal data to evaluate, analyze, or predict personal - aspects related to an identified or identifiable individual's economic situation, health, personal - preferences, interests, reliability, behavior, location, or movements. -

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data, or - 2) Sensitive Data from a known child under 13 years of age. -

    - -

    However, we currently do not collect or process your Personal Data as described above.

    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the TDPSA

    -

    - We will not discriminate against you for exercising your rights under the TDPSA. We will not deny you - our goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the TDPSA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the TDPSA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Utah Resident Rights

    -

    - If you are a Utah resident, you have the rights set forth under the Utah Consumer Privacy Act ("UCPA"). - Please see the "Exercising Your Rights under the State Privacy Laws" section below for instructions - regarding how to exercise these rights. Please note that we may process Personal Data of our customers' - end users or employees in connection with our provision of certain services to our customers. If we are - processing your Personal Data as a service provider, you should contact the entity that collected your - Personal Data in the first instance to address your rights with respect to such data. Additionally, - please note that these rights are subject to certain conditions and exceptions under applicable law, - which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a Utah resident, the portion that is more protective of Personal Data shall control to the extent of - such conflict. If you have any questions about this section or whether any of the following rights apply - to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access your Personal Data and request a copy of your Personal Data in a machine-readable format, to the - extent technically feasible. -

    - -

    Deletion

    -

    You have the right to delete Personal Data that you have provided to us.

    - -

    Opt-Out of Certain Processing Activities

    -
      -
    • Targeted Advertising: We do not process your Personal Data for targeted advertising purposes.
    • -
    • Sale of Personal Data: We do not currently sell your Personal Data as defined under the UCPA.
    • -
    • Processing of Sensitive Personal Data: We do not process Sensitive Personal Data.
    • -
    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the UCPA

    -

    - We will not discriminate against you for exercising your rights under the UCPA. We will not deny you our - goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the UCPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the UCPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Virginia Resident Rights

    -

    - If you are a Virginia resident, you have the rights set forth under the Virginia Consumer Data - Protection Act ("VCDPA"). Please see the "Exercising Your Rights under the State Privacy Laws" section - below for instructions regarding how to exercise these rights. Please note that we may process Personal - Data of our customers' end users or employees in connection with our provision of certain services to - our customers. If we are processing your Personal Data as a service provider, you should contact the - entity that collected your Personal Data in the first instance to address your rights with respect to - such data. Additionally, please note that these rights are subject to certain conditions and exceptions - under applicable law, which may permit or require us to deny your request. -

    - -

    - If there are any conflicts between this section and any other provision of this Privacy Policy and you - are a Virginia resident, the portion that is more protective of Personal Data shall control to the - extent of such conflict. If you have any questions about this section or whether any of the following - rights apply to you, please contact us at contact@anoma.ly. -

    - -

    Access and Portability

    -

    - You have the right to request confirmation of whether or not we are processing your Personal Data and to - access your Personal Data, and request a copy of your Personal Data in a machine-readable format, to the - extent technically feasible. -

    - -

    Correction

    -

    - You have the right to correct inaccuracies in your Personal Data, to the extent such correction is - appropriate in consideration of the nature of such data and our purposes of processing your Personal - Data. -

    - -

    Deletion

    -

    You have the right to delete Personal Data you have provided to us or we have obtained about you.

    - -

    Consent or "Opt-in" Required and How to Withdraw

    -

    - We may seek your consent to collect or process certain Personal Data, including: 1) Sensitive Data, or - 2) Sensitive Data from a known child under 13 years of age. -

    - -

    However, we currently do not collect or process Personal data as described above.

    - -

    Opt-Out of Certain Processing Activities

    -
      -
    • Targeted Advertising: We do not process your Personal Data for targeted advertising purposes.
    • -
    • Sale of Personal Data: We do not currently sell your Personal Data as defined under the VDCPA.
    • -
    • - Processing for Profiling Purposes: We do not currently process your Personal Data for the purposes of - profiling. -
    • -
    - -

    - To exercise any of your rights for these certain processing activities, please follow the instructions - under the "Exercising Your Rights under the State Privacy Laws" section. -

    - -

    We Will Not Discriminate Against You for Exercising Your Rights Under the VCDPA

    -

    - We will not discriminate against you for exercising your rights under the VCDPA. We will not deny you - our goods or services, charge you different prices or rates, or provide you a lower quality of goods and - services if you exercise your rights under the VCDPA. However, we may offer different tiers of our - Services as allowed by applicable data privacy laws (including the VCDPA) with varying prices, rates or - levels of quality of the goods or services you receive related to the value of Personal Data that we - receive from you. -

    - -

    Exercising Your Rights under the State Privacy Laws

    -

    - To exercise the rights described in this Privacy Policy, you or, if you are a California, Colorado, - Connecticut, Delaware, Montana, Nebraska, New Hampshire, New Jersey, Oregon or Texas resident, your - Authorized Agent (defined below) must send us a request that (1) provides sufficient information to - allow us to verify that you are the person about whom we have collected Personal Data, and (2) describes - your request in sufficient detail to allow us to understand, evaluate and respond to it. Each request - that meets both of these criteria will be considered a "Valid Request." We may not respond to requests - that do not meet these criteria. We will only use Personal Data provided in a Valid Request to verify - your identity and complete your request. You do not need an account to submit a Valid Request. -

    - -

    - We will work to respond to your Valid Request within the time period required by applicable law. We will - not charge you a fee for making a Valid Request unless your Valid Request(s) is excessive, repetitive or - manifestly unfounded. If we determine that your Valid Request warrants a fee, we will notify you of the - fee and explain that decision before completing your request. -

    - -

    Request to Withdraw Consent to Certain Processing Activities

    -

    - If you are a California resident, you may withdraw your consent allowing us: 1) to sell or share your - Personal Data, by using the following method: -

    - - -

    Request to Access, Delete, or Correct

    -

    - You may submit a Valid Request for any other rights afforded to you in this Privacy Policy by using the - following methods: -

    - - -

    - If you are a California, Colorado, Connecticut, Delaware, Montana, Nebraska, New Hampshire, New Jersey, - Oregon or Texas resident, you may also authorize an agent (an "Authorized Agent") to exercise your - rights on your behalf. To do this, you must provide your Authorized Agent with written permission to - exercise your rights on your behalf, and we may request a copy of this written permission from your - Authorized Agent when they make a request on your behalf. -

    - -

    Appealing a Denial

    -

    - If you are a Colorado, Connecticut, Delaware, Iowa, Montana, Nebraska, New Hampshire, New Jersey, - Oregon, Texas or Virginia resident and we refuse to take action on your request within a reasonable - period of time after receiving your request in accordance with this section, you may appeal our - decision. In such appeal, you must (1) provide sufficient information to allow us to verify that you are - the person about whom the original request pertains and to identify the original request, and (2) - provide a description of the basis of your appeal. Please note that your appeal will be subject to your - rights and obligations afforded to you under the State Privacy Laws (as applicable). We will respond to - your appeal within the time period required under the applicable law. You can submit a Verified Request - to appeal by the following methods: -

    - - -

    - If we deny your appeal, you have the right to contact the Attorney General of your State, including by - the following links: Colorado, Connecticut, Delaware, Iowa, Montana, Nebraska, New Hampshire, New - Jersey, Oregon, Texas and Virginia. -

    - -

    Other State Law Privacy Rights

    - -

    California Resident Rights

    -

    - Under California Civil Code Sections 1798.83-1798.84, California residents are entitled to contact us to - prevent disclosure of Personal Data to third parties for such third parties' direct marketing purposes; - in order to submit such a request, please contact us at{" "} - contact@anoma.ly. -

    - -

    - Your browser may offer you a "Do Not Track" option, which allows you to signal to operators of websites - and web applications and services that you do not wish such operators to track certain of your online - activities over time and across different websites. Our Services do not support Do Not Track requests at - this time. To find out more about "Do Not Track," you can visit{" "} - www.allaboutdnt.com. -

    - -

    Nevada Resident Rights

    -

    - Please note that we do not currently sell your Personal Data as sales are defined in Nevada Revised - Statutes Chapter 603A. -

    - -

    Contact Information

    -

    - If you have any questions or comments about this Privacy Policy, the ways in which we collect and use - your Personal Data or your choices and rights regarding such collection and use, please do not hesitate - to contact us at: -

    - -
    -
    -
    -
    -
    - -
    - ) -} diff --git a/packages/console/app/src/routes/legal/terms-of-service/index.css b/packages/console/app/src/routes/legal/terms-of-service/index.css deleted file mode 100644 index 709b3a9c3..000000000 --- a/packages/console/app/src/routes/legal/terms-of-service/index.css +++ /dev/null @@ -1,254 +0,0 @@ -[data-component="terms-of-service"] { - max-width: 800px; - margin: 0 auto; - line-height: 1.7; -} - -[data-component="terms-of-service"] h1 { - font-size: 2rem; - font-weight: 700; - color: var(--color-text-strong); - margin-bottom: 0.5rem; - margin-top: 0; -} - -[data-component="terms-of-service"] .effective-date { - font-size: 0.95rem; - color: var(--color-text-weak); - margin-bottom: 2rem; -} - -[data-component="terms-of-service"] h2 { - font-size: 1.5rem; - font-weight: 600; - color: var(--color-text-strong); - margin-top: 3rem; - margin-bottom: 1rem; - padding-top: 1rem; - border-top: 1px solid var(--color-border-weak); -} - -[data-component="terms-of-service"] h2:first-of-type { - margin-top: 2rem; -} - -[data-component="terms-of-service"] h3 { - font-size: 1.25rem; - font-weight: 600; - color: var(--color-text-strong); - margin-top: 2rem; - margin-bottom: 1rem; -} - -[data-component="terms-of-service"] h4 { - font-size: 1.1rem; - font-weight: 600; - color: var(--color-text-strong); - margin-top: 1.5rem; - margin-bottom: 0.75rem; -} - -[data-component="terms-of-service"] p { - margin-bottom: 1rem; - color: var(--color-text); -} - -[data-component="terms-of-service"] ul, -[data-component="terms-of-service"] ol { - margin-bottom: 1rem; - padding-left: 1.5rem; - color: var(--color-text); -} - -[data-component="terms-of-service"] li { - margin-bottom: 0.5rem; - line-height: 1.7; -} - -[data-component="terms-of-service"] ul ul, -[data-component="terms-of-service"] ul ol, -[data-component="terms-of-service"] ol ul, -[data-component="terms-of-service"] ol ol { - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} - -[data-component="terms-of-service"] a { - color: var(--color-text-strong); - text-decoration: underline; - text-underline-offset: 2px; - text-decoration-thickness: 1px; - word-break: break-word; -} - -[data-component="terms-of-service"] a:hover { - text-decoration-thickness: 2px; -} - -[data-component="terms-of-service"] strong { - font-weight: 600; - color: var(--color-text-strong); -} - -@media (max-width: 60rem) { - [data-component="terms-of-service"] { - padding: 0; - } - - [data-component="terms-of-service"] h1 { - font-size: 1.75rem; - } - - [data-component="terms-of-service"] h2 { - font-size: 1.35rem; - margin-top: 2.5rem; - } - - [data-component="terms-of-service"] h3 { - font-size: 1.15rem; - } - - [data-component="terms-of-service"] h4 { - font-size: 1rem; - } -} - -html { - scroll-behavior: smooth; -} - -[data-component="terms-of-service"] [id] { - scroll-margin-top: 100px; -} - -@media print { - @page { - margin: 2cm; - size: letter; - } - - [data-component="top"], - [data-component="footer"], - [data-component="legal"] { - display: none !important; - } - - [data-page="legal"] { - background: white !important; - padding: 0 !important; - } - - [data-component="container"] { - max-width: none !important; - border: none !important; - margin: 0 !important; - } - - [data-component="content"], - [data-component="brand-content"] { - padding: 0 !important; - margin: 0 !important; - } - - [data-component="terms-of-service"] { - max-width: none !important; - margin: 0 !important; - padding: 0 !important; - } - - [data-component="terms-of-service"] * { - color: black !important; - background: transparent !important; - } - - [data-component="terms-of-service"] h1 { - font-size: 24pt; - margin-top: 0; - margin-bottom: 12pt; - page-break-after: avoid; - } - - [data-component="terms-of-service"] h2 { - font-size: 18pt; - border-top: 2pt solid black !important; - padding-top: 12pt; - margin-top: 24pt; - margin-bottom: 8pt; - page-break-after: avoid; - page-break-before: auto; - } - - [data-component="terms-of-service"] h2:first-of-type { - margin-top: 16pt; - } - - [data-component="terms-of-service"] h3 { - font-size: 14pt; - margin-top: 16pt; - margin-bottom: 8pt; - page-break-after: avoid; - } - - [data-component="terms-of-service"] h4 { - font-size: 12pt; - margin-top: 12pt; - margin-bottom: 6pt; - page-break-after: avoid; - } - - [data-component="terms-of-service"] p { - font-size: 11pt; - line-height: 1.5; - margin-bottom: 8pt; - orphans: 3; - widows: 3; - } - - [data-component="terms-of-service"] .effective-date { - font-size: 10pt; - margin-bottom: 16pt; - } - - [data-component="terms-of-service"] ul, - [data-component="terms-of-service"] ol { - margin-bottom: 8pt; - page-break-inside: auto; - } - - [data-component="terms-of-service"] li { - font-size: 11pt; - line-height: 1.5; - margin-bottom: 4pt; - page-break-inside: avoid; - } - - [data-component="terms-of-service"] a { - color: black !important; - text-decoration: underline; - } - - [data-component="terms-of-service"] strong { - font-weight: bold; - color: black !important; - } - - [data-component="terms-of-service"] h1, - [data-component="terms-of-service"] h2, - [data-component="terms-of-service"] h3, - [data-component="terms-of-service"] h4 { - page-break-inside: avoid; - page-break-after: avoid; - } - - [data-component="terms-of-service"] h2 + p, - [data-component="terms-of-service"] h3 + p, - [data-component="terms-of-service"] h4 + p, - [data-component="terms-of-service"] h2 + ul, - [data-component="terms-of-service"] h3 + ul, - [data-component="terms-of-service"] h4 + ul, - [data-component="terms-of-service"] h2 + ol, - [data-component="terms-of-service"] h3 + ol, - [data-component="terms-of-service"] h4 + ol { - page-break-before: avoid; - } -} diff --git a/packages/console/app/src/routes/legal/terms-of-service/index.tsx b/packages/console/app/src/routes/legal/terms-of-service/index.tsx deleted file mode 100644 index f0d7be61c..000000000 --- a/packages/console/app/src/routes/legal/terms-of-service/index.tsx +++ /dev/null @@ -1,512 +0,0 @@ -import "../../brand/index.css" -import "./index.css" -import { Title, Meta, Link } from "@solidjs/meta" -import { Header } from "~/component/header" -import { config } from "~/config" -import { Footer } from "~/component/footer" -import { Legal } from "~/component/legal" - -export default function TermsOfService() { - return ( -
    - OpenCode | Terms of Service - - -
    -
    - -
    -
    -
    -

    Terms of Use

    -

    Effective date: Dec 16, 2025

    - -

    - Welcome to OpenCode. Please read on to learn the rules and restrictions that govern your use of OpenCode - (the "Services"). If you have any questions, comments, or concerns regarding these terms or the - Services, please contact us at: -

    - -

    - Email: contact@anoma.ly -

    - -

    - These Terms of Use (the "Terms") are a binding contract between you and{" "} - ANOMALY INNOVATIONS, INC. ("OpenCode," "we" and "us"). Your use of the Services in any - way means that you agree to all of these Terms, and these Terms will remain in effect while you use the - Services. These Terms include the provisions in this document as well as those in the Privacy Policy{" "} - https://opencode.ai/legal/privacy-policy.{" "} - - Your use of or participation in certain Services may also be subject to additional policies, rules - and/or conditions ("Additional Terms"), which are incorporated herein by reference, and you understand - and agree that by using or participating in any such Services, you agree to also comply with these - Additional Terms. - -

    - -

    - Please read these Terms carefully. They cover important information about Services provided to you and - any charges, taxes, and fees we bill you. These Terms include information about{" "} - future changes to these Terms,{" "} - automatic renewals,{" "} - limitations of liability,{" "} - a class action waiver and{" "} - resolution of disputes by arbitration instead of in court.{" "} - - PLEASE NOTE THAT YOUR USE OF AND ACCESS TO OUR SERVICES ARE SUBJECT TO THE FOLLOWING TERMS; IF YOU DO - NOT AGREE TO ALL OF THE FOLLOWING, YOU MAY NOT USE OR ACCESS THE SERVICES IN ANY MANNER. - -

    - -

    - ARBITRATION NOTICE AND CLASS ACTION WAIVER: EXCEPT FOR CERTAIN TYPES OF DISPUTES - DESCRIBED IN THE ARBITRATION AGREEMENT SECTION BELOW, YOU AGREE - THAT DISPUTES BETWEEN YOU AND US WILL BE RESOLVED BY BINDING, INDIVIDUAL ARBITRATION AND YOU WAIVE YOUR - RIGHT TO PARTICIPATE IN A CLASS ACTION LAWSUIT OR CLASS-WIDE ARBITRATION. -

    - -

    What is OpenCode?

    -

    - OpenCode is an AI-powered coding agent that helps you write, understand, and modify code using large - language models. Certain of these large language models are provided by third parties ("Third Party - Models") and certain of these models are provided directly by us if you use the OpenCode Zen paid - offering ("Zen"). Regardless of whether you use Third Party Models or Zen, OpenCode enables you to - access the functionality of models through a coding agent running within your terminal. -

    - -

    Will these Terms ever change?

    -

    - We are constantly trying to improve our Services, so these Terms may need to change along with our - Services. We reserve the right to change the Terms at any time, but if we do, we will place a notice on - our site located at opencode.ai, send you an email, and/or notify you by some other means. -

    - -

    - If you don't agree with the new Terms, you are free to reject them; unfortunately, that means you will - no longer be able to use the Services. If you use the Services in any way after a change to the Terms is - effective, that means you agree to all of the changes. -

    - -

    - Except for changes by us as described here, no other amendment or modification of these Terms will be - effective unless in writing and signed by both you and us. -

    - -

    What about my privacy?

    -

    - OpenCode takes the privacy of its users very seriously. For the current OpenCode Privacy Policy, please - click here{" "} - https://opencode.ai/legal/privacy-policy. -

    - -

    Children's Online Privacy Protection Act

    -

    - The Children's Online Privacy Protection Act ("COPPA") requires that online service providers obtain - parental consent before they knowingly collect personally identifiable information online from children - who are under 13 years of age. We do not knowingly collect or solicit personally identifiable - information from children under 13 years of age; if you are a child under 13 years of age, please do not - attempt to register for or otherwise use the Services or send us any personal information. If we learn - we have collected personal information from a child under 13 years of age, we will delete that - information as quickly as possible. If you believe that a child under 13 years of age may have provided - us personal information, please contact us at contact@anoma.ly. -

    - -

    What are the basics of using OpenCode?

    -

    - You represent and warrant that you are an individual of legal age to form a binding contract (or if not, - you've received your parent's or guardian's permission to use the Services and have gotten your parent - or guardian to agree to these Terms on your behalf). If you're agreeing to these Terms on behalf of an - organization or entity, you represent and warrant that you are authorized to agree to these Terms on - that organization's or entity's behalf and bind them to these Terms (in which case, the references to - "you" and "your" in these Terms, except for in this sentence, refer to that organization or entity). -

    - -

    - You will only use the Services for your own internal use, and not on behalf of or for the benefit of any - third party, and only in a manner that complies with all laws that apply to you. If your use of the - Services is prohibited by applicable laws, then you aren't authorized to use the Services. We can't and - won't be responsible for your using the Services in a way that breaks the law. -

    - -

    Are there restrictions in how I can use the Services?

    -

    - You represent, warrant, and agree that you will not provide or contribute anything, including any - Content (as that term is defined below), to the Services, or otherwise use or interact with the - Services, in a manner that: -

    - -
      -
    1. - infringes or violates the intellectual property rights or any other rights of anyone else (including - OpenCode); -
    2. -
    3. - violates any law or regulation, including, without limitation, any applicable export control laws, - privacy laws or any other purpose not reasonably intended by OpenCode; -
    4. -
    5. - is dangerous, harmful, fraudulent, deceptive, threatening, harassing, defamatory, obscene, or - otherwise objectionable; -
    6. -
    7. automatically or programmatically extracts data or Output (defined below);
    8. -
    9. Represent that the Output was human-generated when it was not;
    10. -
    11. - uses Output to develop artificial intelligence models that compete with the Services or any Third - Party Models; -
    12. -
    13. - attempts, in any manner, to obtain the password, account, or other security information from any other - user; -
    14. -
    15. - violates the security of any computer network, or cracks any passwords or security encryption codes; -
    16. -
    17. - runs Maillist, Listserv, any form of auto-responder or "spam" on the Services, or any processes that - run or are activated while you are not logged into the Services, or that otherwise interfere with the - proper working of the Services (including by placing an unreasonable load on the Services' - infrastructure); -
    18. -
    19. - "crawls," "scrapes," or "spiders" any page, data, or portion of or relating to the Services or Content - (through use of manual or automated means); -
    20. -
    21. copies or stores any significant portion of the Content; or
    22. -
    23. - decompiles, reverse engineers, or otherwise attempts to obtain the source code or underlying ideas or - information of or relating to the Services. -
    24. -
    - -

    - A violation of any of the foregoing is grounds for termination of your right to use or access the - Services. -

    - -

    Who Owns the Services and Content?

    - -

    Our IP

    -

    - We retain all right, title and interest in and to the Services. Except as expressly set forth herein, no - rights to the Services or Third Party Models are granted to you. -

    - -

    Your IP

    -

    - You may provide input to the Services ("Input"), and receive output from the Services based on the Input - ("Output"). Input and Output are collectively "Content." You are responsible for Content, including - ensuring that it does not violate any applicable law or these Terms. You represent and warrant that you - have all rights, licenses, and permissions needed to provide Input to our Services. -

    - -

    - As between you and us, and to the extent permitted by applicable law, you (a) retain your ownership - rights in Input and (b) own the Output. We hereby assign to you all our right, title, and interest, if - any, in and to Output. -

    - -

    - Due to the nature of our Services and artificial intelligence generally, output may not be unique and - other users may receive similar output from our Services. Our assignment above does not extend to other - users' output. -

    - -

    - We use Content to provide our Services, comply with applicable law, enforce our terms and policies, and - keep our Services safe. In addition, if you are using the Services through an unpaid account, we may use - Content to further develop and improve our Services. -

    - -

    - If you use OpenCode with Third Party Models, then your Content will be subject to the data retention - policies of the providers of such Third Party Models. Although we will not retain your Content, we - cannot and do not control the retention practices of Third Party Model providers. You should review the - terms and conditions applicable to any Third Party Model for more information about the data use and - retention policies applicable to such Third Party Models. -

    - -

    What about Third Party Models?

    -

    - The Services enable you to access and use Third Party Models, which are not owned or controlled by - OpenCode. Your ability to access Third Party Models is contingent on you having API keys or otherwise - having the right to access such Third Party Models. -

    - -

    - OpenCode has no control over, and assumes no responsibility for, the content, accuracy, privacy - policies, or practices of any providers of Third Party Models. We encourage you to read the terms and - conditions and privacy policy of each provider of a Third Party Model that you choose to utilize. By - using the Services, you release and hold us harmless from any and all liability arising from your use of - any Third Party Model. -

    - -

    Will OpenCode ever change the Services?

    -

    - We're always trying to improve our Services, so they may change over time. We may suspend or discontinue - any part of the Services, or we may introduce new features or impose limits on certain features or - restrict access to parts or all of the Services. -

    - -

    Do the Services cost anything?

    -

    - The Services may be free or we may charge a fee for using the Services. If you are using a free version - of the Services, we will notify you before any Services you are then using begin carrying a fee, and if - you wish to continue using such Services, you must pay all applicable fees for such Services. Any and - all such charges, fees or costs are your sole responsibility. You should consult with your -

    - -

    Paid Services

    -

    - Certain of our Services, including Zen, may be subject to payments now or in the future (the "Paid - Services"). Please see our Paid Services page https://opencode.ai/zen for a - description of the current Paid Services. Please note that any payment terms presented to you in the - process of using or signing up for a Paid Service are deemed part of these Terms. -

    - -

    Billing

    -

    - We use a third-party payment processor (the "Payment Processor") to bill you through a payment account - linked to your account on the Services (your "Billing Account") for use of the Paid Services. The - processing of payments will be subject to the terms, conditions and privacy policies of the Payment - Processor in addition to these Terms. Currently, we use Stripe, Inc. as our Payment Processor. You can - access Stripe's Terms of Service at{" "} - https://stripe.com/us/checkout/legal and their - Privacy Policy at https://stripe.com/us/privacy. We are not - responsible for any error by, or other acts or omissions of, the Payment Processor. By choosing to use - Paid Services, you agree to pay us, through the Payment Processor, all charges at the prices then in - effect for any use of such Paid Services in accordance with the applicable payment terms, and you - authorize us, through the Payment Processor, to charge your chosen payment provider (your "Payment - Method"). You agree to make payment using that selected Payment Method. We reserve the right to correct - any errors or mistakes that the Payment Processor makes even if it has already requested or received - payment. -

    - -

    Payment Method

    -

    - The terms of your payment will be based on your Payment Method and may be determined by agreements - between you and the financial institution, credit card issuer or other provider of your chosen Payment - Method. If we, through the Payment Processor, do not receive payment from you, you agree to pay all - amounts due on your Billing Account upon demand. -

    - -

    Recurring Billing

    -

    - Some of the Paid Services may consist of an initial period, for which there is a one-time charge, - followed by recurring period charges as agreed to by you. By choosing a recurring payment plan, you - acknowledge that such Services have an initial and recurring payment feature and you accept - responsibility for all recurring charges prior to cancellation. WE MAY SUBMIT PERIODIC CHARGES (E.G., - MONTHLY) WITHOUT FURTHER AUTHORIZATION FROM YOU, UNTIL YOU PROVIDE PRIOR NOTICE (RECEIPT OF WHICH IS - CONFIRMED BY US) THAT YOU HAVE TERMINATED THIS AUTHORIZATION OR WISH TO CHANGE YOUR PAYMENT METHOD. SUCH - NOTICE WILL NOT AFFECT CHARGES SUBMITTED BEFORE WE REASONABLY COULD ACT. TO TERMINATE YOUR AUTHORIZATION - OR CHANGE YOUR PAYMENT METHOD, GO TO ACCOUNT SETTINGS{" "} - https://opencode.ai/auth. -

    - -

    Free Trials and Other Promotions

    -

    - Any free trial or other promotion that provides access to a Paid Service must be used within the - specified time of the trial. You must stop using a Paid Service before the end of the trial period in - order to avoid being charged for that Paid Service. If you cancel prior to the end of the trial period - and are inadvertently charged for a Paid Service, please contact us at{" "} - contact@anoma.ly. -

    - -

    What if I want to stop using the Services?

    -

    - You're free to do that at any time; please refer to our Privacy Policy{" "} - https://opencode.ai/legal/privacy-policy, as well as the licenses - above, to understand how we treat information you provide to us after you have stopped using our - Services. -

    - -

    - OpenCode is also free to terminate (or suspend access to) your use of the Services for any reason in our - discretion, including your breach of these Terms. OpenCode has the sole right to decide whether you are - in violation of any of the restrictions set forth in these Terms. -

    - -

    - Provisions that, by their nature, should survive termination of these Terms shall survive termination. - By way of example, all of the following will survive termination: any obligation you have to pay us or - indemnify us, any limitations on our liability, any terms regarding ownership or intellectual property - rights, and terms regarding disputes between us, including without limitation the arbitration agreement. -

    - -

    What else do I need to know?

    - -

    Warranty Disclaimer

    -

    - OpenCode and its licensors, suppliers, partners, parent, subsidiaries or affiliated entities, and each - of their respective officers, directors, members, employees, consultants, contract employees, - representatives and agents, and each of their respective successors and assigns (OpenCode and all such - parties together, the "OpenCode Parties") make no representations or warranties concerning the Services, - including without limitation regarding any Content contained in or accessed through the Services, and - the OpenCode Parties will not be responsible or liable for the accuracy, copyright compliance, legality, - or decency of material contained in or accessed through the Services or any claims, actions, suits - procedures, costs, expenses, damages or liabilities arising out of use of, or in any way related to your - participation in, the Services. The OpenCode Parties make no representations or warranties regarding - suggestions or recommendations of services or products offered or purchased through or in connection - with the Services. THE SERVICES AND CONTENT ARE PROVIDED BY OPENCODE (AND ITS LICENSORS AND SUPPLIERS) - ON AN "AS-IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT - LIMITATION, IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, - OR THAT USE OF THE SERVICES WILL BE UNINTERRUPTED OR ERROR-FREE. SOME STATES DO NOT ALLOW LIMITATIONS ON - HOW LONG AN IMPLIED WARRANTY LASTS, SO THE ABOVE LIMITATIONS MAY NOT APPLY TO YOU. -

    - -

    Limitation of Liability

    -

    - TO THE FULLEST EXTENT ALLOWED BY APPLICABLE LAW, UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY - (INCLUDING, WITHOUT LIMITATION, TORT, CONTRACT, STRICT LIABILITY, OR OTHERWISE) SHALL ANY OF THE - OPENCODE PARTIES BE LIABLE TO YOU OR TO ANY OTHER PERSON FOR (A) ANY INDIRECT, SPECIAL, INCIDENTAL, - PUNITIVE OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING DAMAGES FOR LOST PROFITS, BUSINESS - INTERRUPTION, LOSS OF DATA, LOSS OF GOODWILL, WORK STOPPAGE, ACCURACY OF RESULTS, OR COMPUTER FAILURE OR - MALFUNCTION, (B) ANY SUBSTITUTE GOODS, SERVICES OR TECHNOLOGY, (C) ANY AMOUNT, IN THE AGGREGATE, IN - EXCESS OF THE GREATER OF (I) ONE-HUNDRED ($100) DOLLARS OR (II) THE AMOUNTS PAID AND/OR PAYABLE BY YOU - TO OPENCODE IN CONNECTION WITH THE SERVICES IN THE TWELVE (12) MONTH PERIOD PRECEDING THIS APPLICABLE - CLAIM OR (D) ANY MATTER BEYOND OUR REASONABLE CONTROL. SOME STATES DO NOT ALLOW THE EXCLUSION OR - LIMITATION OF INCIDENTAL OR CONSEQUENTIAL OR CERTAIN OTHER DAMAGES, SO THE ABOVE LIMITATION AND - EXCLUSIONS MAY NOT APPLY TO YOU. -

    - -

    Indemnity

    -

    - You agree to indemnify and hold the OpenCode Parties harmless from and against any and all claims, - liabilities, damages (actual and consequential), losses and expenses (including attorneys' fees) arising - from or in any way related to any claims relating to (a) your use of the Services, and (b) your - violation of these Terms. In the event of such a claim, suit, or action ("Claim"), we will attempt to - provide notice of the Claim to the contact information we have for your account (provided that failure - to deliver such notice shall not eliminate or reduce your indemnification obligations hereunder). -

    - -

    Assignment

    -

    - You may not assign, delegate or transfer these Terms or your rights or obligations hereunder, or your - Services account, in any way (by operation of law or otherwise) without OpenCode's prior written - consent. We may transfer, assign, or delegate these Terms and our rights and obligations without - consent. -

    - -

    Choice of Law

    -

    - These Terms are governed by and will be construed under the Federal Arbitration Act, applicable federal - law, and the laws of the State of Delaware, without regard to the conflicts of laws provisions thereof. -

    - -

    Arbitration Agreement

    -

    - Please read the following ARBITRATION AGREEMENT carefully because it requires you to arbitrate certain - disputes and claims with OpenCode and limits the manner in which you can seek relief from OpenCode. Both - you and OpenCode acknowledge and agree that for the purposes of any dispute arising out of or relating - to the subject matter of these Terms, OpenCode's officers, directors, employees and independent - contractors ("Personnel") are third-party beneficiaries of these Terms, and that upon your acceptance of - these Terms, Personnel will have the right (and will be deemed to have accepted the right) to enforce - these Terms against you as the third-party beneficiary hereof. -

    - -

    Arbitration Rules; Applicability of Arbitration Agreement

    -

    - The parties shall use their best efforts to settle any dispute, claim, question, or disagreement arising - out of or relating to the subject matter of these Terms directly through good-faith negotiations, which - shall be a precondition to either party initiating arbitration. If such negotiations do not resolve the - dispute, it shall be finally settled by binding arbitration in New Castle County, Delaware. The - arbitration will proceed in the English language, in accordance with the JAMS Streamlined Arbitration - Rules and Procedures (the "Rules") then in effect, by one commercial arbitrator with substantial - experience in resolving intellectual property and commercial contract disputes. The arbitrator shall be - selected from the appropriate list of JAMS arbitrators in accordance with such Rules. Judgment upon the - award rendered by such arbitrator may be entered in any court of competent jurisdiction. -

    - -

    Costs of Arbitration

    -

    - The Rules will govern payment of all arbitration fees. OpenCode will pay all arbitration fees for claims - less than seventy-five thousand ($75,000) dollars. OpenCode will not seek its attorneys' fees and costs - in arbitration unless the arbitrator determines that your claim is frivolous. -

    - -

    Small Claims Court; Infringement

    -

    - Either you or OpenCode may assert claims, if they qualify, in small claims court in New Castle County, - Delaware or any United States county where you live or work. Furthermore, notwithstanding the foregoing - obligation to arbitrate disputes, each party shall have the right to pursue injunctive or other - equitable relief at any time, from any court of competent jurisdiction, to prevent the actual or - threatened infringement, misappropriation or violation of a party's copyrights, trademarks, trade - secrets, patents or other intellectual property rights. -

    - -

    Waiver of Jury Trial

    -

    - YOU AND OPENCODE WAIVE ANY CONSTITUTIONAL AND STATUTORY RIGHTS TO GO TO COURT AND HAVE A TRIAL IN FRONT - OF A JUDGE OR JURY. You and OpenCode are instead choosing to have claims and disputes resolved by - arbitration. Arbitration procedures are typically more limited, more efficient, and less costly than - rules applicable in court and are subject to very limited review by a court. In any litigation between - you and OpenCode over whether to vacate or enforce an arbitration award, YOU AND OPENCODE WAIVE ALL - RIGHTS TO A JURY TRIAL, and elect instead to have the dispute be resolved by a judge. -

    - -

    Waiver of Class or Consolidated Actions

    -

    - ALL CLAIMS AND DISPUTES WITHIN THE SCOPE OF THIS ARBITRATION AGREEMENT MUST BE ARBITRATED OR LITIGATED - ON AN INDIVIDUAL BASIS AND NOT ON A CLASS BASIS. CLAIMS OF MORE THAN ONE CUSTOMER OR USER CANNOT BE - ARBITRATED OR LITIGATED JOINTLY OR CONSOLIDATED WITH THOSE OF ANY OTHER CUSTOMER OR USER. If however, - this waiver of class or consolidated actions is deemed invalid or unenforceable, neither you nor - OpenCode is entitled to arbitration; instead all claims and disputes will be resolved in a court as set - forth in (g) below. -

    - -

    Opt-out

    -

    - You have the right to opt out of the provisions of this Section by sending written notice of your - decision to opt out to the following address: [ADDRESS], [CITY], Canada [ZIP CODE] postmarked within - thirty (30) days of first accepting these Terms. You must include (i) your name and residence address, - (ii) the email address and/or telephone number associated with your account, and (iii) a clear statement - that you want to opt out of these Terms' arbitration agreement. -

    - -

    Exclusive Venue

    -

    - If you send the opt-out notice in (f), and/or in any circumstances where the foregoing arbitration - agreement permits either you or OpenCode to litigate any dispute arising out of or relating to the - subject matter of these Terms in court, then the foregoing arbitration agreement will not apply to - either party, and both you and OpenCode agree that any judicial proceeding (other than small claims - actions) will be brought in the state or federal courts located in, respectively, New Castle County, - Delaware, or the federal district in which that county falls. -

    - -

    Severability

    -

    - If the prohibition against class actions and other claims brought on behalf of third parties contained - above is found to be unenforceable, then all of the preceding language in this Arbitration Agreement - section will be null and void. This arbitration agreement will survive the termination of your - relationship with OpenCode. -

    - -

    Miscellaneous

    -

    - You will be responsible for paying, withholding, filing, and reporting all taxes, duties, and other - governmental assessments associated with your activity in connection with the Services, provided that - the OpenCode may, in its sole discretion, do any of the foregoing on your behalf or for itself as it - sees fit. The failure of either you or us to exercise, in any way, any right herein shall not be deemed - a waiver of any further rights hereunder. If any provision of these Terms are found to be unenforceable - or invalid, that provision will be limited or eliminated, to the minimum extent necessary, so that these - Terms shall otherwise remain in full force and effect and enforceable. You and OpenCode agree that these - Terms are the complete and exclusive statement of the mutual understanding between you and OpenCode, and - that these Terms supersede and cancel all previous written and oral agreements, communications and other - understandings relating to the subject matter of these Terms. You hereby acknowledge and agree that you - are not an employee, agent, partner, or joint venture of OpenCode, and you do not have any authority of - any kind to bind OpenCode in any respect whatsoever. -

    - -

    - Except as expressly set forth in the section above regarding the arbitration agreement, you and OpenCode - agree there are no third-party beneficiaries intended under these Terms. -

    -
    -
    -
    -
    -
    - -
    - ) -} diff --git a/packages/console/app/src/routes/openapi.json.ts b/packages/console/app/src/routes/openapi.json.ts deleted file mode 100644 index 8b27cb89a..000000000 --- a/packages/console/app/src/routes/openapi.json.ts +++ /dev/null @@ -1,7 +0,0 @@ -export async function GET() { - const response = await fetch( - "https://raw.githubusercontent.com/sst/opencode/refs/heads/dev/packages/sdk/openapi.json", - ) - const json = await response.json() - return json -} diff --git a/packages/console/app/src/routes/t/[...path].tsx b/packages/console/app/src/routes/t/[...path].tsx deleted file mode 100644 index b877a8d58..000000000 --- a/packages/console/app/src/routes/t/[...path].tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { APIEvent } from "@solidjs/start/server" - -async function handler(evt: APIEvent) { - const req = evt.request.clone() - const url = new URL(req.url) - const targetUrl = `https://enterprise.opencode.ai/${url.pathname}${url.search}` - const response = await fetch(targetUrl, { - method: req.method, - headers: req.headers, - body: req.body, - }) - return response -} - -export const GET = handler -export const POST = handler -export const PUT = handler -export const DELETE = handler -export const OPTIONS = handler -export const PATCH = handler diff --git a/packages/console/app/src/routes/workspace-picker.tsx b/packages/console/app/src/routes/workspace-picker.tsx index 2ba750cea..fa8cf1d21 100644 --- a/packages/console/app/src/routes/workspace-picker.tsx +++ b/packages/console/app/src/routes/workspace-picker.tsx @@ -14,7 +14,7 @@ import "./workspace-picker.css" const getWorkspaces = query(async () => { "use server" return withActor(async () => { - return Database.use((tx) => + return Database.transaction((tx) => tx .select({ id: WorkspaceTable.id, diff --git a/packages/console/app/src/routes/workspace/[id]/graph-section.tsx b/packages/console/app/src/routes/workspace/[id]/graph-section.tsx index c8340286f..b13309d3d 100644 --- a/packages/console/app/src/routes/workspace/[id]/graph-section.tsx +++ b/packages/console/app/src/routes/workspace/[id]/graph-section.tsx @@ -3,7 +3,7 @@ import { UsageTable } from "@opencode-ai/console-core/schema/billing.sql.js" import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js" import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js" import { AuthTable } from "@opencode-ai/console-core/schema/auth.sql.js" -import { useParams } from "@solidjs/router" +import { createAsync, query, useParams } from "@solidjs/router" import { createEffect, createMemo, onCleanup, Show, For } from "solid-js" import { createStore } from "solid-js/store" import { withActor } from "~/context/auth.withActor" @@ -94,6 +94,8 @@ async function getCosts(workspaceID: string, year: number, month: number) { }, workspaceID) } +const queryCosts = query(getCosts, "costs.get") + const MODEL_COLORS: Record = { "claude-sonnet-4-5": "#D4745C", "claude-sonnet-4": "#E8B4A4", @@ -156,27 +158,32 @@ export function GraphSection() { model: null as string | null, modelDropdownOpen: false, keyDropdownOpen: false, - colorScheme: "light" as "light" | "dark", }) + const initialData = createAsync(() => queryCosts(params.id!, store.year, store.month)) + const onPreviousMonth = async () => { const month = store.month === 0 ? 11 : store.month - 1 const year = store.month === 0 ? store.year - 1 : store.year - setStore({ month, year }) + const data = await getCosts(params.id!, year, month) + setStore({ month, year, data }) } const onNextMonth = async () => { const month = store.month === 11 ? 0 : store.month + 1 const year = store.month === 11 ? store.year + 1 : store.year - setStore({ month, year }) + setStore({ month, year, data: await getCosts(params.id!, year, month) }) } const onSelectModel = (model: string | null) => setStore({ model, modelDropdownOpen: false }) const onSelectKey = (keyID: string | null) => setStore({ key: keyID, keyDropdownOpen: false }) + const getData = createMemo(() => store.data ?? initialData()) + const getModels = createMemo(() => { - if (!store.data?.usage) return [] - return Array.from(new Set(store.data.usage.map((row) => row.model))).sort() + const data = getData() + if (!data?.usage) return [] + return Array.from(new Set(data.usage.map((row) => row.model))).sort() }) const getDates = createMemo(() => { @@ -199,19 +206,10 @@ export function GraphSection() { const isCurrentMonth = () => store.year === now.getFullYear() && store.month === now.getMonth() const chartConfig = createMemo((): ChartConfiguration | null => { - const data = store.data + const data = getData() const dates = getDates() if (!data?.usage?.length) return null - store.colorScheme - const styles = getComputedStyle(document.documentElement) - const colorTextMuted = styles.getPropertyValue("--color-text-muted").trim() - const colorBorderMuted = styles.getPropertyValue("--color-border-muted").trim() - const colorBgElevated = styles.getPropertyValue("--color-bg-elevated").trim() - const colorText = styles.getPropertyValue("--color-text").trim() - const colorTextSecondary = styles.getPropertyValue("--color-text-secondary").trim() - const colorBorder = styles.getPropertyValue("--color-border").trim() - const dailyData = new Map>() for (const dateKey of dates) dailyData.set(dateKey, new Map()) @@ -254,7 +252,7 @@ export function GraphSection() { ticks: { maxRotation: 0, autoSkipPadding: 20, - color: colorTextMuted, + color: "rgba(255, 255, 255, 0.5)", font: { family: "monospace", size: 11, @@ -265,10 +263,10 @@ export function GraphSection() { stacked: true, beginAtZero: true, grid: { - color: colorBorderMuted, + color: "rgba(255, 255, 255, 0.1)", }, ticks: { - color: colorTextMuted, + color: "rgba(255, 255, 255, 0.5)", font: { family: "monospace", size: 11, @@ -284,10 +282,10 @@ export function GraphSection() { tooltip: { mode: "index", intersect: false, - backgroundColor: colorBgElevated, - titleColor: colorText, - bodyColor: colorTextSecondary, - borderColor: colorBorder, + backgroundColor: "rgba(0, 0, 0, 0.9)", + titleColor: "rgba(255, 255, 255, 0.9)", + bodyColor: "rgba(255, 255, 255, 0.8)", + borderColor: "rgba(255, 255, 255, 0.1)", borderWidth: 1, padding: 12, displayColors: true, @@ -303,7 +301,7 @@ export function GraphSection() { display: true, position: "bottom", labels: { - color: colorTextSecondary, + color: "rgba(255, 255, 255, 0.7)", font: { size: 12, }, @@ -341,32 +339,15 @@ export function GraphSection() { } }) - createEffect(async () => { - const data = await getCosts(params.id!, store.year, store.month) - setStore({ data }) - }) - createEffect(() => { const config = chartConfig() if (!config || !canvasRef) return if (chartInstance) chartInstance.destroy() chartInstance = new Chart(canvasRef, config) - - onCleanup(() => chartInstance?.destroy()) }) - createEffect(() => { - const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") - setStore({ colorScheme: mediaQuery.matches ? "dark" : "light" }) - - const handleColorSchemeChange = (e: MediaQueryListEvent) => { - setStore({ colorScheme: e.matches ? "dark" : "light" }) - } - - mediaQuery.addEventListener("change", handleColorSchemeChange) - onCleanup(() => mediaQuery.removeEventListener("change", handleColorSchemeChange)) - }) + onCleanup(() => chartInstance?.destroy()) return (
    @@ -375,53 +356,55 @@ export function GraphSection() {

    Usage costs broken down by model.

    -
    -
    - - {formatMonthYear()} - + +
    +
    + + {formatMonthYear()} + +
    + setStore({ modelDropdownOpen: open })} + > + <> + + + {(model) => ( + + )} + + + + setStore({ keyDropdownOpen: open })} + > + <> + + + {(key) => ( + + )} + + +
    - setStore({ modelDropdownOpen: open })} - > - <> - - - {(model) => ( - - )} - - - - setStore({ keyDropdownOpen: open })} - > - <> - - - {(key) => ( - - )} - - - -
    + { if (modelId.startsWith("kimi")) return "Moonshot AI" if (modelId.startsWith("glm")) return "Z.ai" if (modelId.startsWith("qwen")) return "Alibaba" - if (modelId.startsWith("minimax")) return "MiniMax" if (modelId.startsWith("grok")) return "xAI" return "Stealth" } @@ -37,7 +35,7 @@ const getModelsInfo = query(async (workspaceID: string) => { .filter(([id, _model]) => !["claude-3-5-haiku"].includes(id)) .filter(([id, _model]) => !id.startsWith("alpha-")) .sort(([idA, modelA], [idB, modelB]) => { - const priority = ["big-pickle", "minimax", "grok", "claude", "gpt", "gemini"] + const priority = ["big-pickle", "grok", "claude", "gpt", "gemini"] const getPriority = (id: string) => { const index = priority.findIndex((p) => id.startsWith(p)) return index === -1 ? Infinity : index @@ -45,12 +43,9 @@ const getModelsInfo = query(async (workspaceID: string) => { const pA = getPriority(idA) const pB = getPriority(idB) if (pA !== pB) return pA - pB - - const modelAName = Array.isArray(modelA) ? modelA[0].name : modelA.name - const modelBName = Array.isArray(modelB) ? modelB[0].name : modelB.name - return modelAName.localeCompare(modelBName) + return modelA.name.localeCompare(modelB.name) }) - .map(([id, model]) => ({ id, name: Array.isArray(model) ? model[0].name : model.name })), + .map(([id, model]) => ({ id, name: model.name })), disabled: await Model.listDisabled(), } }, workspaceID) @@ -131,8 +126,6 @@ export function ModelSection() { return case "xAI": return - case "MiniMax": - return default: return } diff --git a/packages/console/app/src/routes/zen/index.css b/packages/console/app/src/routes/zen/index.css index 5055bac2a..fbdd15306 100644 --- a/packages/console/app/src/routes/zen/index.css +++ b/packages/console/app/src/routes/zen/index.css @@ -147,16 +147,7 @@ body { ul { display: flex; justify-content: space-between; - align-items: center; gap: 48px; - - @media (max-width: 55rem) { - gap: 32px; - } - - @media (max-width: 48rem) { - gap: 24px; - } li { display: inline-block; a { @@ -170,22 +161,6 @@ body { text-underline-offset: var(--space-1); text-decoration-thickness: 1px; } - [data-slot="cta-button"] { - background: var(--color-background-strong); - color: var(--color-text-inverted); - padding: 8px 16px; - border-radius: 4px; - font-weight: 500; - text-decoration: none; - - @media (max-width: 55rem) { - display: none; - } - } - [data-slot="cta-button"]:hover { - background: var(--color-background-strong-hover); - text-decoration: none; - } } } @@ -305,7 +280,7 @@ body { h1 { font-size: 28px; color: var(--color-text-strong); - font-weight: 700; + font-weight: 500; margin-bottom: 16px; display: block; @@ -394,7 +369,7 @@ body { h3 { font-size: 16px; - font-weight: 700; + font-weight: 500; color: var(--color-text-strong); margin-bottom: 12px; } @@ -467,7 +442,7 @@ body { [data-slot="privacy-title"] { h3 { font-size: 16px; - font-weight: 700; + font-weight: 500; color: var(--color-text); margin-bottom: 12px; } diff --git a/packages/console/app/src/routes/zen/index.tsx b/packages/console/app/src/routes/zen/index.tsx index 5708c238c..7fd393962 100644 --- a/packages/console/app/src/routes/zen/index.tsx +++ b/packages/console/app/src/routes/zen/index.tsx @@ -1,7 +1,7 @@ import "./index.css" import { createAsync, query, redirect } from "@solidjs/router" import { Title, Meta, Link } from "@solidjs/meta" -//import { HttpHeader } from "@solidjs/start" +// import { HttpHeader } from "@solidjs/start" import zenLogoLight from "../../asset/zen-ornate-light.svg" import { config } from "~/config" import zenLogoDark from "../../asset/zen-ornate-dark.svg" @@ -38,7 +38,7 @@ export default function Home() {
    -
    +
    diff --git a/packages/console/app/src/routes/zen/util/dataDumper.ts b/packages/console/app/src/routes/zen/util/dataDumper.ts index b852ca0b5..6a064138a 100644 --- a/packages/console/app/src/routes/zen/util/dataDumper.ts +++ b/packages/console/app/src/routes/zen/util/dataDumper.ts @@ -1,43 +1,25 @@ import { Resource, waitUntil } from "@opencode-ai/console-resource" -export function createDataDumper(sessionId: string, requestId: string, projectId: string) { +export function createDataDumper(sessionId: string, requestId: string) { if (Resource.App.stage !== "production") return - if (sessionId === "") return - let data: Record = { sessionId, requestId, projectId } - let metadata: Record = { sessionId, requestId, projectId } + let data: Record = {} + let modelName: string | undefined return { - provideModel: (model?: string) => { - data.modelName = model - metadata.modelName = model - }, + provideModel: (model?: string) => (modelName = model), provideRequest: (request: string) => (data.request = request), provideResponse: (response: string) => (data.response = response), provideStream: (chunk: string) => (data.response = (data.response ?? "") + chunk), flush: () => { - if (!data.modelName) return + if (!modelName) return - const timestamp = new Date().toISOString().replace(/[^0-9]/g, "") - const year = timestamp.substring(0, 4) - const month = timestamp.substring(4, 6) - const day = timestamp.substring(6, 8) - const hour = timestamp.substring(8, 10) - const minute = timestamp.substring(10, 12) - const second = timestamp.substring(12, 14) + const str = new Date().toISOString().replace(/[^0-9]/g, "") + const yyyymmdd = str.substring(0, 8) + const hh = str.substring(8, 10) waitUntil( - Resource.ZenDataNew.put( - `data/${data.modelName}/${year}/${month}/${day}/${hour}/${minute}/${second}/${requestId}.json`, - JSON.stringify({ timestamp, ...data }), - ), - ) - - waitUntil( - Resource.ZenDataNew.put( - `meta/${data.modelName}/${sessionId}/${requestId}.json`, - JSON.stringify({ timestamp, ...metadata }), - ), + Resource.ConsoleData.put(`${yyyymmdd}/${hh}/${modelName}/${sessionId}/${requestId}.json`, JSON.stringify(data)), ) }, } diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts index bef44d3e4..972b60d6c 100644 --- a/packages/console/app/src/routes/zen/util/handler.ts +++ b/packages/console/app/src/routes/zen/util/handler.ts @@ -13,7 +13,13 @@ import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js" import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js" import { logger } from "./logger" import { AuthError, CreditsError, MonthlyLimitError, UserLimitError, ModelError, RateLimitError } from "./error" -import { createBodyConverter, createStreamPartConverter, createResponseConverter, UsageInfo } from "./provider/provider" +import { + createBodyConverter, + createStreamPartConverter, + createResponseConverter, + ProviderHelper, + UsageInfo, +} from "./provider/provider" import { anthropicHelper } from "./provider/anthropic" import { googleHelper } from "./provider/google" import { openaiHelper } from "./provider/openai" @@ -21,7 +27,6 @@ import { oaCompatHelper } from "./provider/openai-compatible" import { createRateLimiter } from "./rateLimiter" import { createDataDumper } from "./dataDumper" import { createTrialLimiter } from "./trialLimiter" -import { createStickyTracker } from "./stickyProviderTracker" type ZenData = Awaited> type RetryOptions = { @@ -56,35 +61,22 @@ export async function handler( const ip = input.request.headers.get("x-real-ip") ?? "" const sessionId = input.request.headers.get("x-opencode-session") ?? "" const requestId = input.request.headers.get("x-opencode-request") ?? "" - const projectId = input.request.headers.get("x-opencode-project") ?? "" - const ocClient = input.request.headers.get("x-opencode-client") ?? "" logger.metric({ is_tream: isStream, session: sessionId, request: requestId, - client: ocClient, }) const zenData = ZenData.list() const modelInfo = validateModel(zenData, model) - const dataDumper = createDataDumper(sessionId, requestId, projectId) - const trialLimiter = createTrialLimiter(modelInfo.trial, ip, ocClient) + const dataDumper = createDataDumper(sessionId, requestId) + const trialLimiter = createTrialLimiter(modelInfo.trial?.limit, ip) const isTrial = await trialLimiter?.isTrial() const rateLimiter = createRateLimiter(modelInfo.id, modelInfo.rateLimit, ip) await rateLimiter?.check() - const stickyTracker = createStickyTracker(modelInfo.stickyProvider ?? false, sessionId) - const stickyProvider = await stickyTracker?.get() const retriableRequest = async (retry: RetryOptions = { excludeProviders: [], retryCount: 0 }) => { - const authInfo = await authenticate(modelInfo) - const providerInfo = selectProvider( - zenData, - authInfo, - modelInfo, - sessionId, - isTrial ?? false, - retry, - stickyProvider, - ) + const providerInfo = selectProvider(zenData, modelInfo, sessionId, isTrial ?? false, retry) + const authInfo = await authenticate(modelInfo, providerInfo) validateBilling(authInfo, modelInfo) validateModelSettings(authInfo) updateProviderKey(authInfo, providerInfo) @@ -112,21 +104,13 @@ export async function handler( headers.delete("content-length") headers.delete("x-opencode-request") headers.delete("x-opencode-session") - headers.delete("x-opencode-project") - headers.delete("x-opencode-client") return headers })(), body: reqBody, }) // Try another provider => stop retrying if using fallback provider - if ( - res.status !== 200 && - // ie. openai 404 error: Item with id 'msg_0ead8b004a3b165d0069436a6b6834819896da85b63b196a3f' not found. - res.status !== 404 && - modelInfo.fallbackProvider && - providerInfo.id !== modelInfo.fallbackProvider - ) { + if (res.status !== 200 && modelInfo.fallbackProvider && providerInfo.id !== modelInfo.fallbackProvider) { return retriableRequest({ excludeProviders: [...retry.excludeProviders, providerInfo.id], retryCount: retry.retryCount + 1, @@ -142,12 +126,6 @@ export async function handler( dataDumper?.provideModel(providerInfo.storeModel) dataDumper?.provideRequest(reqBody) - // Store sticky provider - await stickyTracker?.set(providerInfo.id) - - // Temporarily change 404 to 400 status code b/c solid start automatically override 404 response - const resStatus = res.status === 404 ? 400 : res.status - // Scrub response headers const resHeaders = new Headers() const keepHeaders = ["content-type", "cache-control"] @@ -173,7 +151,7 @@ export async function handler( await trackUsage(authInfo, modelInfo, providerInfo, tokensInfo) await reload(authInfo) return new Response(body, { - status: resStatus, + status: res.status, statusText: res.statusText, headers: resHeaders, }) @@ -251,7 +229,7 @@ export async function handler( }) return new Response(stream, { - status: resStatus, + status: res.status, statusText: res.statusText, headers: resHeaders, }) @@ -299,14 +277,11 @@ export async function handler( } function validateModel(zenData: ZenData, reqModel: string) { - if (!(reqModel in zenData.models)) throw new ModelError(`Model ${reqModel} not supported`) - + if (!(reqModel in zenData.models)) { + throw new ModelError(`Model ${reqModel} not supported`) + } const modelId = reqModel as keyof typeof zenData.models - const modelData = Array.isArray(zenData.models[modelId]) - ? zenData.models[modelId].find((model) => opts.format === model.formatFilter) - : zenData.models[modelId] - - if (!modelData) throw new ModelError(`Model ${reqModel} not supported for format ${opts.format}`) + const modelData = zenData.models[modelId] logger.metric({ model: modelId }) @@ -315,27 +290,16 @@ export async function handler( function selectProvider( zenData: ZenData, - authInfo: AuthInfo, modelInfo: ModelInfo, sessionId: string, isTrial: boolean, retry: RetryOptions, - stickyProvider: string | undefined, ) { const provider = (() => { - if (authInfo?.provider?.credentials) { - return modelInfo.providers.find((provider) => provider.id === modelInfo.byokProvider) - } - if (isTrial) { return modelInfo.providers.find((provider) => provider.id === modelInfo.trial!.provider) } - if (stickyProvider) { - const provider = modelInfo.providers.find((provider) => provider.id === stickyProvider) - if (provider) return provider - } - if (retry.retryCount === MAX_RETRIES) { return modelInfo.providers.find((provider) => provider.id === modelInfo.fallbackProvider) } @@ -371,7 +335,7 @@ export async function handler( } } - async function authenticate(modelInfo: ModelInfo) { + async function authenticate(modelInfo: ModelInfo, providerInfo: ProviderInfo) { const apiKey = opts.parseApiKey(input.request.headers) if (!apiKey || apiKey === "public") { if (modelInfo.allowAnonymous) return @@ -409,12 +373,7 @@ export async function handler( .leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), eq(ModelTable.model, modelInfo.id))) .leftJoin( ProviderTable, - modelInfo.byokProvider - ? and( - eq(ProviderTable.workspaceID, KeyTable.workspaceID), - eq(ProviderTable.provider, modelInfo.byokProvider), - ) - : sql`false`, + and(eq(ProviderTable.workspaceID, KeyTable.workspaceID), eq(ProviderTable.provider, providerInfo.id)), ) .where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted))) .then((rows) => rows[0]), @@ -491,7 +450,8 @@ export async function handler( } function updateProviderKey(authInfo: AuthInfo, providerInfo: ProviderInfo) { - if (!authInfo?.provider?.credentials) return + if (!authInfo) return + if (!authInfo.provider?.credentials) return providerInfo.apiKey = authInfo.provider.credentials } @@ -604,7 +564,7 @@ export async function handler( tx .update(KeyTable) .set({ timeUsed: sql`now()` }) - .where(and(eq(KeyTable.workspaceID, authInfo.workspaceID), eq(KeyTable.id, authInfo.apiKeyId))), + .where(eq(KeyTable.id, authInfo.apiKeyId)), ) } diff --git a/packages/console/app/src/routes/zen/util/stickyProviderTracker.ts b/packages/console/app/src/routes/zen/util/stickyProviderTracker.ts deleted file mode 100644 index 63cbb0a68..000000000 --- a/packages/console/app/src/routes/zen/util/stickyProviderTracker.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Resource } from "@opencode-ai/console-resource" - -export function createStickyTracker(stickyProvider: boolean, session: string) { - if (!stickyProvider) return - if (!session) return - const key = `sticky:${session}` - - return { - get: async () => { - return await Resource.GatewayKv.get(key) - }, - set: async (providerId: string) => { - await Resource.GatewayKv.put(key, providerId, { expirationTtl: 86400 }) - }, - } -} diff --git a/packages/console/app/src/routes/zen/util/trialLimiter.ts b/packages/console/app/src/routes/zen/util/trialLimiter.ts index 531e5cf0c..15561c9f6 100644 --- a/packages/console/app/src/routes/zen/util/trialLimiter.ts +++ b/packages/console/app/src/routes/zen/util/trialLimiter.ts @@ -1,18 +1,12 @@ import { Database, eq, sql } from "@opencode-ai/console-core/drizzle/index.js" import { IpTable } from "@opencode-ai/console-core/schema/ip.sql.js" import { UsageInfo } from "./provider/provider" -import { ZenData } from "@opencode-ai/console-core/model.js" -export function createTrialLimiter(trial: ZenData.Trial | undefined, ip: string, client: string) { - if (!trial) return +export function createTrialLimiter(limit: number | undefined, ip: string) { + if (!limit) return if (!ip) return - const limit = - trial.limits.find((limit) => limit.client === client)?.limit ?? - trial.limits.find((limit) => limit.client === undefined)?.limit - if (!limit) return - - let _isTrial: boolean + let trial: boolean return { isTrial: async () => { @@ -26,11 +20,11 @@ export function createTrialLimiter(trial: ZenData.Trial | undefined, ip: string, .then((rows) => rows[0]), ) - _isTrial = (data?.usage ?? 0) < limit - return _isTrial + trial = (data?.usage ?? 0) < limit + return trial }, track: async (usageInfo: UsageInfo) => { - if (!_isTrial) return + if (!trial) return const usage = usageInfo.inputTokens + usageInfo.outputTokens + diff --git a/packages/console/app/src/style/token/font.css b/packages/console/app/src/style/token/font.css index 844677b5f..67143e662 100644 --- a/packages/console/app/src/style/token/font.css +++ b/packages/console/app/src/style/token/font.css @@ -15,7 +15,6 @@ body { --font-size-9xl: 8rem; --font-mono: - "Berkeley Mono", "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", - "Courier New", monospace; + "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --font-sans: var(--font-mono); } diff --git a/packages/console/app/sst-env.d.ts b/packages/console/app/sst-env.d.ts index 9b9de7327..bd5588217 100644 --- a/packages/console/app/sst-env.d.ts +++ b/packages/console/app/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 6ffedab0a..085ad3642 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.0.191", + "version": "1.0.118", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/core/script/promote-models.ts b/packages/console/core/script/promote-models.ts index bebef5cfb..0ff859df8 100755 --- a/packages/console/core/script/promote-models.ts +++ b/packages/console/core/script/promote-models.ts @@ -16,19 +16,16 @@ const value1 = lines.find((line) => line.startsWith("ZEN_MODELS1"))?.split("=")[ const value2 = lines.find((line) => line.startsWith("ZEN_MODELS2"))?.split("=")[1] const value3 = lines.find((line) => line.startsWith("ZEN_MODELS3"))?.split("=")[1] const value4 = lines.find((line) => line.startsWith("ZEN_MODELS4"))?.split("=")[1] -const value5 = lines.find((line) => line.startsWith("ZEN_MODELS5"))?.split("=")[1] if (!value1) throw new Error("ZEN_MODELS1 not found") if (!value2) throw new Error("ZEN_MODELS2 not found") if (!value3) throw new Error("ZEN_MODELS3 not found") if (!value4) throw new Error("ZEN_MODELS4 not found") -if (!value5) throw new Error("ZEN_MODELS5 not found") // validate value -ZenData.validate(JSON.parse(value1 + value2 + value3 + value4 + value5)) +ZenData.validate(JSON.parse(value1 + value2 + value3 + value4)) // update the secret await $`bun sst secret set ZEN_MODELS1 ${value1} --stage ${stage}` await $`bun sst secret set ZEN_MODELS2 ${value2} --stage ${stage}` await $`bun sst secret set ZEN_MODELS3 ${value3} --stage ${stage}` await $`bun sst secret set ZEN_MODELS4 ${value4} --stage ${stage}` -await $`bun sst secret set ZEN_MODELS5 ${value5} --stage ${stage}` diff --git a/packages/console/core/script/pull-models.ts b/packages/console/core/script/pull-models.ts index afa865625..a89e3951c 100755 --- a/packages/console/core/script/pull-models.ts +++ b/packages/console/core/script/pull-models.ts @@ -16,19 +16,16 @@ const value1 = lines.find((line) => line.startsWith("ZEN_MODELS1"))?.split("=")[ const value2 = lines.find((line) => line.startsWith("ZEN_MODELS2"))?.split("=")[1] const value3 = lines.find((line) => line.startsWith("ZEN_MODELS3"))?.split("=")[1] const value4 = lines.find((line) => line.startsWith("ZEN_MODELS4"))?.split("=")[1] -const value5 = lines.find((line) => line.startsWith("ZEN_MODELS5"))?.split("=")[1] if (!value1) throw new Error("ZEN_MODELS1 not found") if (!value2) throw new Error("ZEN_MODELS2 not found") if (!value3) throw new Error("ZEN_MODELS3 not found") if (!value4) throw new Error("ZEN_MODELS4 not found") -if (!value5) throw new Error("ZEN_MODELS5 not found") // validate value -ZenData.validate(JSON.parse(value1 + value2 + value3 + value4 + value5)) +ZenData.validate(JSON.parse(value1 + value2 + value3 + value4)) // update the secret await $`bun sst secret set ZEN_MODELS1 ${value1}` await $`bun sst secret set ZEN_MODELS2 ${value2}` await $`bun sst secret set ZEN_MODELS3 ${value3}` await $`bun sst secret set ZEN_MODELS4 ${value4}` -await $`bun sst secret set ZEN_MODELS5 ${value5}` diff --git a/packages/console/core/script/update-models.ts b/packages/console/core/script/update-models.ts index 5d40b4d5a..a8523a5f2 100755 --- a/packages/console/core/script/update-models.ts +++ b/packages/console/core/script/update-models.ts @@ -14,17 +14,15 @@ const oldValue1 = lines.find((line) => line.startsWith("ZEN_MODELS1"))?.split("= const oldValue2 = lines.find((line) => line.startsWith("ZEN_MODELS2"))?.split("=")[1] const oldValue3 = lines.find((line) => line.startsWith("ZEN_MODELS3"))?.split("=")[1] const oldValue4 = lines.find((line) => line.startsWith("ZEN_MODELS4"))?.split("=")[1] -const oldValue5 = lines.find((line) => line.startsWith("ZEN_MODELS5"))?.split("=")[1] if (!oldValue1) throw new Error("ZEN_MODELS1 not found") if (!oldValue2) throw new Error("ZEN_MODELS2 not found") if (!oldValue3) throw new Error("ZEN_MODELS3 not found") if (!oldValue4) throw new Error("ZEN_MODELS4 not found") -if (!oldValue5) throw new Error("ZEN_MODELS5 not found") // store the prettified json to a temp file const filename = `models-${Date.now()}.json` const tempFile = Bun.file(path.join(os.tmpdir(), filename)) -await tempFile.write(JSON.stringify(JSON.parse(oldValue1 + oldValue2 + oldValue3 + oldValue4 + oldValue5), null, 2)) +await tempFile.write(JSON.stringify(JSON.parse(oldValue1 + oldValue2 + oldValue3 + oldValue4), null, 2)) console.log("tempFile", tempFile.name) // open temp file in vim and read the file on close @@ -33,15 +31,12 @@ const newValue = JSON.stringify(JSON.parse(await tempFile.text())) ZenData.validate(JSON.parse(newValue)) // update the secret -const chunk = Math.ceil(newValue.length / 5) +const chunk = Math.ceil(newValue.length / 4) const newValue1 = newValue.slice(0, chunk) const newValue2 = newValue.slice(chunk, chunk * 2) const newValue3 = newValue.slice(chunk * 2, chunk * 3) -const newValue4 = newValue.slice(chunk * 3, chunk * 4) -const newValue5 = newValue.slice(chunk * 4) - +const newValue4 = newValue.slice(chunk * 3) await $`bun sst secret set ZEN_MODELS1 ${newValue1}` await $`bun sst secret set ZEN_MODELS2 ${newValue2}` await $`bun sst secret set ZEN_MODELS3 ${newValue3}` await $`bun sst secret set ZEN_MODELS4 ${newValue4}` -await $`bun sst secret set ZEN_MODELS5 ${newValue5}` diff --git a/packages/console/core/src/account.ts b/packages/console/core/src/account.ts index 6d1773b84..c7e096586 100644 --- a/packages/console/core/src/account.ts +++ b/packages/console/core/src/account.ts @@ -11,7 +11,7 @@ export namespace Account { id: z.string().optional(), }), async (input) => - Database.use(async (tx) => { + Database.transaction(async (tx) => { const id = input.id ?? Identifier.create("account") await tx.insert(AccountTable).values({ id, @@ -21,12 +21,13 @@ export namespace Account { ) export const fromID = fn(z.string(), async (id) => - Database.use((tx) => - tx + Database.transaction(async (tx) => { + return tx .select() .from(AccountTable) .where(eq(AccountTable.id, id)) - .then((rows) => rows[0]), - ), + .execute() + .then((rows) => rows[0]) + }), ) } diff --git a/packages/console/core/src/aws.ts b/packages/console/core/src/aws.ts index a4c151086..e87ada6ef 100644 --- a/packages/console/core/src/aws.ts +++ b/packages/console/core/src/aws.ts @@ -22,7 +22,6 @@ export namespace AWS { to: z.string(), subject: z.string(), body: z.string(), - replyTo: z.string().optional(), }), async (input) => { const res = await createClient().fetch("https://email.us-east-1.amazonaws.com/v2/email/outbound-emails", { @@ -36,7 +35,6 @@ export namespace AWS { Destination: { ToAddresses: [input.to], }, - ...(input.replyTo && { ReplyToAddresses: [input.replyTo] }), Content: { Simple: { Subject: { diff --git a/packages/console/core/src/model.ts b/packages/console/core/src/model.ts index 55d6c895c..8cc181b7c 100644 --- a/packages/console/core/src/model.ts +++ b/packages/console/core/src/model.ts @@ -9,17 +9,7 @@ import { Resource } from "@opencode-ai/console-resource" export namespace ZenData { const FormatSchema = z.enum(["anthropic", "google", "openai", "oa-compat"]) - const TrialSchema = z.object({ - provider: z.string(), - limits: z.array( - z.object({ - limit: z.number(), - client: z.enum(["cli", "desktop"]).optional(), - }), - ), - }) export type Format = z.infer - export type Trial = z.infer const ModelCostSchema = z.object({ input: z.number(), @@ -34,9 +24,12 @@ export namespace ZenData { cost: ModelCostSchema, cost200K: ModelCostSchema.optional(), allowAnonymous: z.boolean().optional(), - byokProvider: z.enum(["openai", "anthropic", "google"]).optional(), - stickyProvider: z.boolean().optional(), - trial: TrialSchema.optional(), + trial: z + .object({ + limit: z.number(), + provider: z.string(), + }) + .optional(), rateLimit: z.number().optional(), fallbackProvider: z.string().optional(), providers: z.array( @@ -58,7 +51,7 @@ export namespace ZenData { }) const ModelsSchema = z.object({ - models: z.record(z.string(), z.union([ModelSchema, z.array(ModelSchema.extend({ formatFilter: FormatSchema }))])), + models: z.record(z.string(), ModelSchema), providers: z.record(z.string(), ProviderSchema), }) @@ -68,11 +61,7 @@ export namespace ZenData { export const list = fn(z.void(), () => { const json = JSON.parse( - Resource.ZEN_MODELS1.value + - Resource.ZEN_MODELS2.value + - Resource.ZEN_MODELS3.value + - Resource.ZEN_MODELS4.value + - Resource.ZEN_MODELS5.value, + Resource.ZEN_MODELS1.value + Resource.ZEN_MODELS2.value + Resource.ZEN_MODELS3.value + Resource.ZEN_MODELS4.value, ) return ModelsSchema.parse(json) }) diff --git a/packages/console/core/src/provider.ts b/packages/console/core/src/provider.ts index 83461155b..cf2040b59 100644 --- a/packages/console/core/src/provider.ts +++ b/packages/console/core/src/provider.ts @@ -47,7 +47,7 @@ export namespace Provider { }), async ({ provider }) => { Actor.assertAdmin() - return Database.use((tx) => + return Database.transaction((tx) => tx .delete(ProviderTable) .where(and(eq(ProviderTable.provider, provider), eq(ProviderTable.workspaceID, Actor.workspace()))), diff --git a/packages/console/core/sst-env.d.ts b/packages/console/core/sst-env.d.ts index ffa17f276..08710b63e 100644 --- a/packages/console/core/sst-env.d.ts +++ b/packages/console/core/sst-env.d.ts @@ -6,135 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string + Console: { + type: "sst.cloudflare.SolidStart" + url: string } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string + R2AccessKey: { + type: "sst.sst.Secret" + value: string } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string + R2SecretKey: { + type: "sst.sst.Secret" + value: string } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string } - "Teams": { - "type": "sst.cloudflare.SolidStart" - "url": string + Web: { + type: "sst.cloudflare.Astro" + url: string } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS5": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "EnterpriseStorage": cloudflare.R2Bucket - "GatewayKv": cloudflare.KVNamespace - "LogProcessor": cloudflare.Service - "ZenData": cloudflare.R2Bucket - "ZenDataNew": cloudflare.R2Bucket + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + ConsoleData: cloudflare.R2Bucket + EnterpriseStorage: cloudflare.R2Bucket + GatewayKv: cloudflare.KVNamespace + LogProcessor: cloudflare.Service } } import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 95fc0e474..4e41d8f18 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.191", + "version": "1.0.118", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/function/src/auth.ts b/packages/console/function/src/auth.ts index 742e0d567..f1f341cec 100644 --- a/packages/console/function/src/auth.ts +++ b/packages/console/function/src/auth.ts @@ -194,7 +194,7 @@ export default { // Get workspace await Actor.provide("account", { accountID, email }, async () => { await User.joinInvitedWorkspaces() - const workspaces = await Database.use((tx) => + const workspaces = await Database.transaction(async (tx) => tx .select({ id: WorkspaceTable.id }) .from(WorkspaceTable) diff --git a/packages/console/function/sst-env.d.ts b/packages/console/function/sst-env.d.ts index ffa17f276..08710b63e 100644 --- a/packages/console/function/sst-env.d.ts +++ b/packages/console/function/sst-env.d.ts @@ -6,135 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string + Console: { + type: "sst.cloudflare.SolidStart" + url: string } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string + R2AccessKey: { + type: "sst.sst.Secret" + value: string } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string + R2SecretKey: { + type: "sst.sst.Secret" + value: string } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string } - "Teams": { - "type": "sst.cloudflare.SolidStart" - "url": string + Web: { + type: "sst.cloudflare.Astro" + url: string } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS5": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "EnterpriseStorage": cloudflare.R2Bucket - "GatewayKv": cloudflare.KVNamespace - "LogProcessor": cloudflare.Service - "ZenData": cloudflare.R2Bucket - "ZenDataNew": cloudflare.R2Bucket + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + ConsoleData: cloudflare.R2Bucket + EnterpriseStorage: cloudflare.R2Bucket + GatewayKv: cloudflare.KVNamespace + LogProcessor: cloudflare.Service } } import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index ff6b3f102..55a04729d 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.191", + "version": "1.0.118", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/console/mail/sst-env.d.ts b/packages/console/mail/sst-env.d.ts index 9b9de7327..bd5588217 100644 --- a/packages/console/mail/sst-env.d.ts +++ b/packages/console/mail/sst-env.d.ts @@ -6,4 +6,4 @@ /// import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/console/resource/resource.node.ts b/packages/console/resource/resource.node.ts index 1470bacf2..46b9629ed 100644 --- a/packages/console/resource/resource.node.ts +++ b/packages/console/resource/resource.node.ts @@ -2,8 +2,8 @@ import type { KVNamespaceListOptions, KVNamespaceListResult, KVNamespacePutOptio import { Resource as ResourceBase } from "sst" import Cloudflare from "cloudflare" -export const waitUntil = async (promise: Promise) => { - await promise +export const waitUntil = async (fn: () => Promise) => { + await fn() } export const Resource = new Proxy( diff --git a/packages/console/resource/sst-env.d.ts b/packages/console/resource/sst-env.d.ts index ffa17f276..08710b63e 100644 --- a/packages/console/resource/sst-env.d.ts +++ b/packages/console/resource/sst-env.d.ts @@ -6,135 +6,126 @@ import "sst" declare module "sst" { export interface Resource { - "ADMIN_SECRET": { - "type": "sst.sst.Secret" - "value": string + ADMIN_SECRET: { + type: "sst.sst.Secret" + value: string } - "AUTH_API_URL": { - "type": "sst.sst.Linkable" - "value": string + AUTH_API_URL: { + type: "sst.sst.Linkable" + value: string } - "AWS_SES_ACCESS_KEY_ID": { - "type": "sst.sst.Secret" - "value": string + AWS_SES_ACCESS_KEY_ID: { + type: "sst.sst.Secret" + value: string } - "AWS_SES_SECRET_ACCESS_KEY": { - "type": "sst.sst.Secret" - "value": string + AWS_SES_SECRET_ACCESS_KEY: { + type: "sst.sst.Secret" + value: string } - "CLOUDFLARE_API_TOKEN": { - "type": "sst.sst.Secret" - "value": string + CLOUDFLARE_API_TOKEN: { + type: "sst.sst.Secret" + value: string } - "CLOUDFLARE_DEFAULT_ACCOUNT_ID": { - "type": "sst.sst.Secret" - "value": string + CLOUDFLARE_DEFAULT_ACCOUNT_ID: { + type: "sst.sst.Secret" + value: string } - "Console": { - "type": "sst.cloudflare.SolidStart" - "url": string + Console: { + type: "sst.cloudflare.SolidStart" + url: string } - "Database": { - "database": string - "host": string - "password": string - "port": number - "type": "sst.sst.Linkable" - "username": string + Database: { + database: string + host: string + password: string + port: number + type: "sst.sst.Linkable" + username: string } - "Desktop": { - "type": "sst.cloudflare.StaticSite" - "url": string + Desktop: { + type: "sst.cloudflare.StaticSite" + url: string } - "EMAILOCTOPUS_API_KEY": { - "type": "sst.sst.Secret" - "value": string + EMAILOCTOPUS_API_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_ID": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_ID: { + type: "sst.sst.Secret" + value: string } - "GITHUB_APP_PRIVATE_KEY": { - "type": "sst.sst.Secret" - "value": string + GITHUB_APP_PRIVATE_KEY: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_ID_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_ID_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GITHUB_CLIENT_SECRET_CONSOLE": { - "type": "sst.sst.Secret" - "value": string + GITHUB_CLIENT_SECRET_CONSOLE: { + type: "sst.sst.Secret" + value: string } - "GOOGLE_CLIENT_ID": { - "type": "sst.sst.Secret" - "value": string + GOOGLE_CLIENT_ID: { + type: "sst.sst.Secret" + value: string } - "HONEYCOMB_API_KEY": { - "type": "sst.sst.Secret" - "value": string + HONEYCOMB_API_KEY: { + type: "sst.sst.Secret" + value: string } - "R2AccessKey": { - "type": "sst.sst.Secret" - "value": string + R2AccessKey: { + type: "sst.sst.Secret" + value: string } - "R2SecretKey": { - "type": "sst.sst.Secret" - "value": string + R2SecretKey: { + type: "sst.sst.Secret" + value: string } - "STRIPE_SECRET_KEY": { - "type": "sst.sst.Secret" - "value": string + STRIPE_SECRET_KEY: { + type: "sst.sst.Secret" + value: string } - "STRIPE_WEBHOOK_SECRET": { - "type": "sst.sst.Linkable" - "value": string + STRIPE_WEBHOOK_SECRET: { + type: "sst.sst.Linkable" + value: string } - "Teams": { - "type": "sst.cloudflare.SolidStart" - "url": string + Web: { + type: "sst.cloudflare.Astro" + url: string } - "Web": { - "type": "sst.cloudflare.Astro" - "url": string + ZEN_MODELS1: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS1": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS2: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS2": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS3: { + type: "sst.sst.Secret" + value: string } - "ZEN_MODELS3": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS4": { - "type": "sst.sst.Secret" - "value": string - } - "ZEN_MODELS5": { - "type": "sst.sst.Secret" - "value": string + ZEN_MODELS4: { + type: "sst.sst.Secret" + value: string } } } -// cloudflare -import * as cloudflare from "@cloudflare/workers-types"; +// cloudflare +import * as cloudflare from "@cloudflare/workers-types" declare module "sst" { export interface Resource { - "Api": cloudflare.Service - "AuthApi": cloudflare.Service - "AuthStorage": cloudflare.KVNamespace - "Bucket": cloudflare.R2Bucket - "EnterpriseStorage": cloudflare.R2Bucket - "GatewayKv": cloudflare.KVNamespace - "LogProcessor": cloudflare.Service - "ZenData": cloudflare.R2Bucket - "ZenDataNew": cloudflare.R2Bucket + Api: cloudflare.Service + AuthApi: cloudflare.Service + AuthStorage: cloudflare.KVNamespace + Bucket: cloudflare.R2Bucket + ConsoleData: cloudflare.R2Bucket + EnterpriseStorage: cloudflare.R2Bucket + GatewayKv: cloudflare.KVNamespace + LogProcessor: cloudflare.Service } } import "sst" -export {} \ No newline at end of file +export {} diff --git a/packages/desktop/.gitignore b/packages/desktop/.gitignore index a547bf36d..4a20d55a7 100644 --- a/packages/desktop/.gitignore +++ b/packages/desktop/.gitignore @@ -1,24 +1 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? +src/assets/theme.css diff --git a/packages/app/AGENTS.md b/packages/desktop/AGENTS.md similarity index 100% rename from packages/app/AGENTS.md rename to packages/desktop/AGENTS.md diff --git a/packages/desktop/README.md b/packages/desktop/README.md index b381dcf5b..6a1764536 100644 --- a/packages/desktop/README.md +++ b/packages/desktop/README.md @@ -1,7 +1,34 @@ -# Tauri + Vanilla TS +## Usage -This template should help get you started developing with Tauri in vanilla HTML, CSS and Typescript. +Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`. -## Recommended IDE Setup +This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template. -- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) +```bash +$ npm install # or pnpm install or yarn install +``` + +### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs) + +## Available Scripts + +In the project directory, you can run: + +### `npm run dev` or `npm start` + +Runs the app in the development mode.
    +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.
    + +### `npm run build` + +Builds the app for production to the `dist` folder.
    +It correctly bundles Solid in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.
    +Your app is ready to be deployed! + +## Deployment + +You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.) diff --git a/packages/desktop/index.html b/packages/desktop/index.html index faeb1a1fd..57e10defa 100644 --- a/packages/desktop/index.html +++ b/packages/desktop/index.html @@ -9,12 +9,11 @@ - - + - + -
    +
    diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 23eab7f4d..d67978610 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,37 +1,51 @@ { "name": "@opencode-ai/desktop", - "private": true, - "version": "1.0.191", + "version": "1.0.118", + "description": "", "type": "module", "scripts": { - "typecheck": "tsgo -b", - "predev": "bun ./scripts/predev.ts", + "typecheck": "tsgo --noEmit", + "start": "vite", "dev": "vite", - "build": "bun run typecheck && vite build", - "preview": "vite preview", - "tauri": "tauri" + "build": "vite build", + "serve": "vite preview" + }, + "license": "MIT", + "devDependencies": { + "@tailwindcss/vite": "catalog:", + "@tsconfig/bun": "1.0.9", + "@types/luxon": "catalog:", + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", + "vite-plugin-icons-spritesheet": "3.0.1", + "vite-plugin-solid": "catalog:" }, "dependencies": { - "@opencode-ai/app": "workspace:*", - "@solid-primitives/storage": "catalog:", - "@tauri-apps/api": "^2", - "@tauri-apps/plugin-dialog": "~2", - "@tauri-apps/plugin-opener": "^2", - "@tauri-apps/plugin-os": "~2", - "@tauri-apps/plugin-process": "~2", - "@tauri-apps/plugin-shell": "~2", - "@tauri-apps/plugin-store": "~2", - "@tauri-apps/plugin-updater": "~2", - "@tauri-apps/plugin-http": "~2", - "@tauri-apps/plugin-window-state": "~2", - "solid-js": "catalog:" - }, - "devDependencies": { - "@actions/artifact": "4.0.0", - "@tauri-apps/cli": "^2", - "@types/bun": "catalog:", - "@typescript/native-preview": "catalog:", - "typescript": "~5.6.2", - "vite": "catalog:" + "@kobalte/core": "catalog:", + "@opencode-ai/sdk": "workspace:*", + "@opencode-ai/ui": "workspace:*", + "@opencode-ai/util": "workspace:*", + "@shikijs/transformers": "3.9.2", + "@solid-primitives/active-element": "2.1.3", + "@solid-primitives/event-bus": "1.1.2", + "@solid-primitives/resize-observer": "2.1.3", + "@solid-primitives/scroll": "2.1.3", + "@solid-primitives/storage": "4.3.3", + "@solidjs/meta": "catalog:", + "@solidjs/router": "catalog:", + "@thisbeyond/solid-dnd": "0.7.5", + "diff": "catalog:", + "fuzzysort": "catalog:", + "luxon": "catalog:", + "marked": "16.2.0", + "marked-shiki": "1.2.1", + "remeda": "catalog:", + "shiki": "3.9.2", + "solid-js": "catalog:", + "solid-list": "catalog:", + "tailwindcss": "catalog:", + "virtua": "catalog:" } } diff --git a/packages/app/public/apple-touch-icon.png b/packages/desktop/public/apple-touch-icon.png similarity index 100% rename from packages/app/public/apple-touch-icon.png rename to packages/desktop/public/apple-touch-icon.png diff --git a/packages/app/public/favicon-96x96.png b/packages/desktop/public/favicon-96x96.png similarity index 100% rename from packages/app/public/favicon-96x96.png rename to packages/desktop/public/favicon-96x96.png diff --git a/packages/app/public/favicon.ico b/packages/desktop/public/favicon.ico similarity index 100% rename from packages/app/public/favicon.ico rename to packages/desktop/public/favicon.ico diff --git a/packages/app/public/favicon.svg b/packages/desktop/public/favicon.svg similarity index 100% rename from packages/app/public/favicon.svg rename to packages/desktop/public/favicon.svg diff --git a/packages/app/public/site.webmanifest b/packages/desktop/public/site.webmanifest similarity index 100% rename from packages/app/public/site.webmanifest rename to packages/desktop/public/site.webmanifest diff --git a/packages/desktop/public/social-share.png b/packages/desktop/public/social-share.png new file mode 100644 index 000000000..92224f54c Binary files /dev/null and b/packages/desktop/public/social-share.png differ diff --git a/packages/app/public/web-app-manifest-192x192.png b/packages/desktop/public/web-app-manifest-192x192.png similarity index 100% rename from packages/app/public/web-app-manifest-192x192.png rename to packages/desktop/public/web-app-manifest-192x192.png diff --git a/packages/app/public/web-app-manifest-512x512.png b/packages/desktop/public/web-app-manifest-512x512.png similarity index 100% rename from packages/app/public/web-app-manifest-512x512.png rename to packages/desktop/public/web-app-manifest-512x512.png diff --git a/packages/desktop/scripts/copy-bundles.ts b/packages/desktop/scripts/copy-bundles.ts deleted file mode 100644 index 3fde1c190..000000000 --- a/packages/desktop/scripts/copy-bundles.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { $ } from "bun" -import * as path from "node:path" - -import { RUST_TARGET } from "./utils" - -if (!RUST_TARGET) throw new Error("RUST_TARGET not defined") - -const BUNDLE_DIR = `src-tauri/target/${RUST_TARGET}/release/bundle` -const BUNDLES_OUT_DIR = path.join(process.cwd(), `src-tauri/target/bundles`) - -await $`mkdir -p ${BUNDLES_OUT_DIR}` -await $`cp -r ${BUNDLE_DIR}/*/OpenCode* ${BUNDLES_OUT_DIR}` diff --git a/packages/desktop/scripts/predev.ts b/packages/desktop/scripts/predev.ts deleted file mode 100644 index 218215197..000000000 --- a/packages/desktop/scripts/predev.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { $ } from "bun" - -import { copyBinaryToSidecarFolder, getCurrentSidecar } from "./utils" - -const RUST_TARGET = Bun.env.TAURI_ENV_TARGET_TRIPLE - -const sidecarConfig = getCurrentSidecar(RUST_TARGET) - -const binaryPath = `../opencode/dist/${sidecarConfig.ocBinary}/bin/opencode` - -await $`cd ../opencode && bun run build --single` - -await copyBinaryToSidecarFolder(binaryPath, RUST_TARGET) diff --git a/packages/desktop/scripts/prepare.ts b/packages/desktop/scripts/prepare.ts deleted file mode 100755 index 495a0baea..000000000 --- a/packages/desktop/scripts/prepare.ts +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bun -import { $ } from "bun" - -import { copyBinaryToSidecarFolder, getCurrentSidecar } from "./utils" - -const sidecarConfig = getCurrentSidecar() - -const dir = "src-tauri/target/opencode-binaries" - -await $`mkdir -p ${dir}` -await $`gh run download ${Bun.env.GITHUB_RUN_ID} -n opencode-cli`.cwd(dir) - -await copyBinaryToSidecarFolder( - `${dir}/${sidecarConfig.ocBinary}/bin/opencode${process.platform === "win32" ? ".exe" : ""}`, -) diff --git a/packages/desktop/scripts/utils.ts b/packages/desktop/scripts/utils.ts deleted file mode 100644 index 885d0afce..000000000 --- a/packages/desktop/scripts/utils.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { $ } from "bun" - -export const SIDECAR_BINARIES: Array<{ rustTarget: string; ocBinary: string; assetExt: string }> = [ - { - rustTarget: "aarch64-apple-darwin", - ocBinary: "opencode-darwin-arm64", - assetExt: "zip", - }, - { - rustTarget: "x86_64-apple-darwin", - ocBinary: "opencode-darwin-x64", - assetExt: "zip", - }, - { - rustTarget: "x86_64-pc-windows-msvc", - ocBinary: "opencode-windows-x64", - assetExt: "zip", - }, - { - rustTarget: "x86_64-unknown-linux-gnu", - ocBinary: "opencode-linux-x64", - assetExt: "tar.gz", - }, - { - rustTarget: "aarch64-unknown-linux-gnu", - ocBinary: "opencode-linux-arm64", - assetExt: "tar.gz", - }, -] - -export const RUST_TARGET = Bun.env.RUST_TARGET - -export function getCurrentSidecar(target = RUST_TARGET) { - if (!target && !RUST_TARGET) throw new Error("RUST_TARGET not set") - - const binaryConfig = SIDECAR_BINARIES.find((b) => b.rustTarget === target) - if (!binaryConfig) throw new Error(`Sidecar configuration not available for Rust target '${RUST_TARGET}'`) - - return binaryConfig -} - -export async function copyBinaryToSidecarFolder(source: string, target = RUST_TARGET) { - await $`mkdir -p src-tauri/sidecars` - const dest = `src-tauri/sidecars/opencode-cli-${target}${process.platform === "win32" ? ".exe" : ""}` - await $`cp ${source} ${dest}` - - console.log(`Copied ${source} to ${dest}`) -} diff --git a/packages/desktop/src-tauri/assets/nsis-header.bmp b/packages/desktop/src-tauri/assets/nsis-header.bmp deleted file mode 100644 index 27480b5f7..000000000 Binary files a/packages/desktop/src-tauri/assets/nsis-header.bmp and /dev/null differ diff --git a/packages/desktop/src-tauri/assets/nsis-sidebar.bmp b/packages/desktop/src-tauri/assets/nsis-sidebar.bmp deleted file mode 100644 index a476f2f2a..000000000 Binary files a/packages/desktop/src-tauri/assets/nsis-sidebar.bmp and /dev/null differ diff --git a/packages/desktop/src-tauri/capabilities/default.json b/packages/desktop/src-tauri/capabilities/default.json deleted file mode 100644 index c805f623b..000000000 --- a/packages/desktop/src-tauri/capabilities/default.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "../gen/schemas/desktop-schema.json", - "identifier": "default", - "description": "Capability for the main window", - "windows": ["main"], - "permissions": [ - "core:default", - "opener:default", - "core:window:allow-start-dragging", - "core:webview:allow-set-webview-zoom", - "shell:default", - "updater:default", - "dialog:default", - "process:default", - "store:default", - "window-state:default", - "os:default", - { - "identifier": "http:default", - "allow": [{ "url": "http://*" }, { "url": "https://*" }, { "url": "http://*:*/*" }] - } - ] -} diff --git a/packages/desktop/src-tauri/entitlements.plist b/packages/desktop/src-tauri/entitlements.plist deleted file mode 100644 index afa54db33..000000000 --- a/packages/desktop/src-tauri/entitlements.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - com.apple.security.cs.allow-jit - - com.apple.security.cs.allow-unsigned-executable-memory - - com.apple.security.cs.disable-executable-page-protection - - com.apple.security.cs.allow-dyld-environment-variables - - com.apple.security.cs.disable-library-validation - - - diff --git a/packages/desktop/src-tauri/icons/README.md b/packages/desktop/src-tauri/icons/README.md deleted file mode 100644 index db86593cc..000000000 --- a/packages/desktop/src-tauri/icons/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Tauri Icons - -Here's the process I've been using to create icons: - -- Save source image as `app-icon.png` in `packages/desktop` -- `cd` to `src-tauri` -- Run `bun tauri icons -o icons/{environment}` -- Use [Image2Icon](https://img2icnsapp.com/)'s 'Big Sur Icon' preset to generate an `icon.icns` file and place it in the appropriate icons folder - -The Image2Icon step is necessary as the `icon.icns` generated by `app-icon.png` does not apply the shadow/padding expected by macOS, -so app icons appear larger than expected. diff --git a/packages/desktop/src-tauri/icons/dev/128x128.png b/packages/desktop/src-tauri/icons/dev/128x128.png deleted file mode 100644 index d7fc4db14..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/128x128.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/128x128@2x.png b/packages/desktop/src-tauri/icons/dev/128x128@2x.png deleted file mode 100644 index 591882306..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/128x128@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/32x32.png b/packages/desktop/src-tauri/icons/dev/32x32.png deleted file mode 100644 index 53925cc4f..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/32x32.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/64x64.png b/packages/desktop/src-tauri/icons/dev/64x64.png deleted file mode 100644 index a88ef15c6..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/64x64.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square107x107Logo.png b/packages/desktop/src-tauri/icons/dev/Square107x107Logo.png deleted file mode 100644 index 0de29ec82..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square107x107Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square142x142Logo.png b/packages/desktop/src-tauri/icons/dev/Square142x142Logo.png deleted file mode 100644 index af62e8e1e..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square142x142Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square150x150Logo.png b/packages/desktop/src-tauri/icons/dev/Square150x150Logo.png deleted file mode 100644 index 2b19dc39c..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square150x150Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square284x284Logo.png b/packages/desktop/src-tauri/icons/dev/Square284x284Logo.png deleted file mode 100644 index eda6d9901..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square284x284Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square30x30Logo.png b/packages/desktop/src-tauri/icons/dev/Square30x30Logo.png deleted file mode 100644 index dad821ba8..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square30x30Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square310x310Logo.png b/packages/desktop/src-tauri/icons/dev/Square310x310Logo.png deleted file mode 100644 index 555b3b197..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square310x310Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square44x44Logo.png b/packages/desktop/src-tauri/icons/dev/Square44x44Logo.png deleted file mode 100644 index 9f8ad001f..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square44x44Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square71x71Logo.png b/packages/desktop/src-tauri/icons/dev/Square71x71Logo.png deleted file mode 100644 index 43feb7848..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square71x71Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/Square89x89Logo.png b/packages/desktop/src-tauri/icons/dev/Square89x89Logo.png deleted file mode 100644 index 628cc597f..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/Square89x89Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/StoreLogo.png b/packages/desktop/src-tauri/icons/dev/StoreLogo.png deleted file mode 100644 index 8d3aa53cf..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/StoreLogo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-anydpi-v26/ic_launcher.xml b/packages/desktop/src-tauri/icons/dev/android/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 2ffbf24b6..000000000 --- a/packages/desktop/src-tauri/icons/dev/android/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index b355e37fe..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index c33f8713b..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 04e37aa65..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 98e53cd22..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 40fe6e378..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 4814f1ddf..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 608493283..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index 898066a3f..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 64035c0f3..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index f47691bf4..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index dba6f5635..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 764702604..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 2e8430a60..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index db953d128..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index d5c9ba6a8..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/android/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/android/values/ic_launcher_background.xml b/packages/desktop/src-tauri/icons/dev/android/values/ic_launcher_background.xml deleted file mode 100644 index ea9c223a6..000000000 --- a/packages/desktop/src-tauri/icons/dev/android/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #fff - \ No newline at end of file diff --git a/packages/desktop/src-tauri/icons/dev/icon.icns b/packages/desktop/src-tauri/icons/dev/icon.icns deleted file mode 100644 index d73a94904..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/icon.icns and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/icon.ico b/packages/desktop/src-tauri/icons/dev/icon.ico deleted file mode 100644 index bec385d9a..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/icon.ico and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/icon.png b/packages/desktop/src-tauri/icons/dev/icon.png deleted file mode 100644 index 6de37ea29..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/icon.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@1x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@1x.png deleted file mode 100644 index 0e823043e..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@1x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@2x-1.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@2x-1.png deleted file mode 100644 index 54e4b2aac..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@2x-1.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@2x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@2x.png deleted file mode 100644 index 54e4b2aac..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@3x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@3x.png deleted file mode 100644 index 645b01561..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-20x20@3x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@1x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@1x.png deleted file mode 100644 index 054225c6e..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@1x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@2x-1.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@2x-1.png deleted file mode 100644 index 0b1b2e0b7..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@2x-1.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@2x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@2x.png deleted file mode 100644 index 0b1b2e0b7..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@3x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@3x.png deleted file mode 100644 index d2c42592b..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-29x29@3x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@1x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@1x.png deleted file mode 100644 index 54e4b2aac..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@1x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@2x-1.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@2x-1.png deleted file mode 100644 index 471ed2eec..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@2x-1.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@2x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@2x.png deleted file mode 100644 index 471ed2eec..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@3x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@3x.png deleted file mode 100644 index 1a490cbf1..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-40x40@3x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-512@2x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-512@2x.png deleted file mode 100644 index f53b404e5..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-512@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-60x60@2x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-60x60@2x.png deleted file mode 100644 index 1a490cbf1..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-60x60@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-60x60@3x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-60x60@3x.png deleted file mode 100644 index bdc759eef..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-60x60@3x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-76x76@1x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-76x76@1x.png deleted file mode 100644 index d22096a2d..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-76x76@1x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-76x76@2x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-76x76@2x.png deleted file mode 100644 index d675773d1..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-76x76@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-83.5x83.5@2x.png b/packages/desktop/src-tauri/icons/dev/ios/AppIcon-83.5x83.5@2x.png deleted file mode 100644 index 31698afce..000000000 Binary files a/packages/desktop/src-tauri/icons/dev/ios/AppIcon-83.5x83.5@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/128x128.png b/packages/desktop/src-tauri/icons/prod/128x128.png deleted file mode 100644 index caf7b02eb..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/128x128.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/128x128@2x.png b/packages/desktop/src-tauri/icons/prod/128x128@2x.png deleted file mode 100644 index 47fe4c61e..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/128x128@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/32x32.png b/packages/desktop/src-tauri/icons/prod/32x32.png deleted file mode 100644 index 5868bcc93..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/32x32.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/64x64.png b/packages/desktop/src-tauri/icons/prod/64x64.png deleted file mode 100644 index 1ed7425d8..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/64x64.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square107x107Logo.png b/packages/desktop/src-tauri/icons/prod/Square107x107Logo.png deleted file mode 100644 index 1db249bf7..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square107x107Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square142x142Logo.png b/packages/desktop/src-tauri/icons/prod/Square142x142Logo.png deleted file mode 100644 index 1961c3408..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square142x142Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square150x150Logo.png b/packages/desktop/src-tauri/icons/prod/Square150x150Logo.png deleted file mode 100644 index abc507347..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square150x150Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square284x284Logo.png b/packages/desktop/src-tauri/icons/prod/Square284x284Logo.png deleted file mode 100644 index 51e2a1b9f..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square284x284Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square30x30Logo.png b/packages/desktop/src-tauri/icons/prod/Square30x30Logo.png deleted file mode 100644 index 066a1fd0c..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square30x30Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square310x310Logo.png b/packages/desktop/src-tauri/icons/prod/Square310x310Logo.png deleted file mode 100644 index 2a85c8e95..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square310x310Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square44x44Logo.png b/packages/desktop/src-tauri/icons/prod/Square44x44Logo.png deleted file mode 100644 index c855b8063..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square44x44Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square71x71Logo.png b/packages/desktop/src-tauri/icons/prod/Square71x71Logo.png deleted file mode 100644 index c8168f711..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square71x71Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/Square89x89Logo.png b/packages/desktop/src-tauri/icons/prod/Square89x89Logo.png deleted file mode 100644 index 19ec1777d..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/Square89x89Logo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/StoreLogo.png b/packages/desktop/src-tauri/icons/prod/StoreLogo.png deleted file mode 100644 index 3fd053d34..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/StoreLogo.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-anydpi-v26/ic_launcher.xml b/packages/desktop/src-tauri/icons/prod/android/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 2ffbf24b6..000000000 --- a/packages/desktop/src-tauri/icons/prod/android/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 4f3ea0e36..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 7db80699b..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index a54ebe652..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 9337ccfa3..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 0bfc1082e..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 5b02ec732..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 322aeaeaa..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index ca1e336cc..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index f71110799..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 287a6b500..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 9d3d06a86..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index d4b6fde1b..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index bde8d7596..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 03df7809d..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher_round.png b/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 62363be04..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/android/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/android/values/ic_launcher_background.xml b/packages/desktop/src-tauri/icons/prod/android/values/ic_launcher_background.xml deleted file mode 100644 index ea9c223a6..000000000 --- a/packages/desktop/src-tauri/icons/prod/android/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #fff - \ No newline at end of file diff --git a/packages/desktop/src-tauri/icons/prod/icon.icns b/packages/desktop/src-tauri/icons/prod/icon.icns deleted file mode 100644 index be910ad5f..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/icon.icns and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/icon.ico b/packages/desktop/src-tauri/icons/prod/icon.ico deleted file mode 100644 index ff88d21e4..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/icon.ico and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/icon.png b/packages/desktop/src-tauri/icons/prod/icon.png deleted file mode 100644 index 0ecbb6d5f..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/icon.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@1x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@1x.png deleted file mode 100644 index eb137e164..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@1x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@2x-1.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@2x-1.png deleted file mode 100644 index aa76ab10b..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@2x-1.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@2x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@2x.png deleted file mode 100644 index aa76ab10b..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@3x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@3x.png deleted file mode 100644 index c58ea3d49..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-20x20@3x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@1x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@1x.png deleted file mode 100644 index 0eeb4d9bf..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@1x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@2x-1.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@2x-1.png deleted file mode 100644 index 32601c70a..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@2x-1.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@2x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@2x.png deleted file mode 100644 index 32601c70a..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@3x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@3x.png deleted file mode 100644 index a372c4a11..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-29x29@3x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@1x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@1x.png deleted file mode 100644 index aa76ab10b..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@1x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@2x-1.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@2x-1.png deleted file mode 100644 index e82ce2765..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@2x-1.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@2x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@2x.png deleted file mode 100644 index e82ce2765..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@3x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@3x.png deleted file mode 100644 index 15ad59362..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-40x40@3x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-512@2x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-512@2x.png deleted file mode 100644 index 2260671c0..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-512@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-60x60@2x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-60x60@2x.png deleted file mode 100644 index 15ad59362..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-60x60@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-60x60@3x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-60x60@3x.png deleted file mode 100644 index 5c66bd3b1..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-60x60@3x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-76x76@1x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-76x76@1x.png deleted file mode 100644 index a5b05f3b5..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-76x76@1x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-76x76@2x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-76x76@2x.png deleted file mode 100644 index 9c0615d41..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-76x76@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-83.5x83.5@2x.png b/packages/desktop/src-tauri/icons/prod/ios/AppIcon-83.5x83.5@2x.png deleted file mode 100644 index 6b792b36a..000000000 Binary files a/packages/desktop/src-tauri/icons/prod/ios/AppIcon-83.5x83.5@2x.png and /dev/null differ diff --git a/packages/desktop/src-tauri/src/lib.rs b/packages/desktop/src-tauri/src/lib.rs deleted file mode 100644 index 3c08841ab..000000000 --- a/packages/desktop/src-tauri/src/lib.rs +++ /dev/null @@ -1,308 +0,0 @@ -mod window_customizer; - -use std::{ - collections::VecDeque, - net::{SocketAddr, TcpListener}, - sync::{Arc, Mutex}, - time::{Duration, Instant}, -}; -use tauri::{AppHandle, LogicalSize, Manager, RunEvent, WebviewUrl, WebviewWindow, path::BaseDirectory}; -use tauri_plugin_clipboard_manager::ClipboardExt; -use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogResult}; -use tauri_plugin_shell::process::{CommandChild, CommandEvent}; -use tauri_plugin_shell::ShellExt; -use tokio::net::TcpSocket; - -use crate::window_customizer::PinchZoomDisablePlugin; - -#[derive(Clone)] -struct ServerState(Arc>>); - -#[derive(Clone)] -struct LogState(Arc>>); - -const MAX_LOG_ENTRIES: usize = 200; - -#[tauri::command] -fn kill_sidecar(app: AppHandle) { - let Some(server_state) = app.try_state::() else { - println!("Server not running"); - return; - }; - - let Some(server_state) = server_state - .0 - .lock() - .expect("Failed to acquire mutex lock") - .take() - else { - println!("Server state missing"); - return; - }; - - let _ = server_state.kill(); - - println!("Killed server"); -} - -#[tauri::command] -async fn copy_logs_to_clipboard(app: AppHandle) -> Result<(), String> { - let log_state = app.try_state::().ok_or("Log state not found")?; - - let logs = log_state - .0 - .lock() - .map_err(|_| "Failed to acquire log lock")?; - - let log_text = logs.iter().cloned().collect::>().join(""); - - app.clipboard() - .write_text(log_text) - .map_err(|e| format!("Failed to copy to clipboard: {}", e))?; - - Ok(()) -} - -#[tauri::command] -async fn get_logs(app: AppHandle) -> Result { - let log_state = app.try_state::().ok_or("Log state not found")?; - - let logs = log_state - .0 - .lock() - .map_err(|_| "Failed to acquire log lock")?; - - Ok(logs.iter().cloned().collect::>().join("")) -} - -fn get_sidecar_port() -> u32 { - option_env!("OPENCODE_PORT") - .map(|s| s.to_string()) - .or_else(|| std::env::var("OPENCODE_PORT").ok()) - .and_then(|port_str| port_str.parse().ok()) - .unwrap_or_else(|| { - TcpListener::bind("127.0.0.1:0") - .expect("Failed to bind to find free port") - .local_addr() - .expect("Failed to get local address") - .port() - }) as u32 -} - -fn get_user_shell() -> String { - std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string()) -} - -fn spawn_sidecar(app: &AppHandle, port: u32) -> CommandChild { - let log_state = app.state::(); - let log_state_clone = log_state.inner().clone(); - - let state_dir = app - .path() - .resolve("", BaseDirectory::AppLocalData) - .expect("Failed to resolve app local data dir"); - - #[cfg(target_os = "windows")] - let (mut rx, child) = app - .shell() - .sidecar("opencode-cli") - .unwrap() - .env("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY", "true") - .env("OPENCODE_CLIENT", "desktop") - .env("XDG_STATE_HOME", &state_dir) - .args(["serve", &format!("--port={port}")]) - .spawn() - .expect("Failed to spawn opencode"); - - #[cfg(not(target_os = "windows"))] - let (mut rx, child) = { - let sidecar_path = tauri::utils::platform::current_exe() - .expect("Failed to get current exe") - .parent() - .expect("Failed to get parent dir") - .join("opencode-cli"); - let shell = get_user_shell(); - app.shell() - .command(&shell) - .env("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY", "true") - .env("OPENCODE_CLIENT", "desktop") - .env("XDG_STATE_HOME", &state_dir) - .args([ - "-il", - "-c", - &format!("{} serve --port={}", sidecar_path.display(), port), - ]) - .spawn() - .expect("Failed to spawn opencode") - }; - - tauri::async_runtime::spawn(async move { - while let Some(event) = rx.recv().await { - match event { - CommandEvent::Stdout(line_bytes) => { - let line = String::from_utf8_lossy(&line_bytes); - print!("{line}"); - - // Store log in shared state - if let Ok(mut logs) = log_state_clone.0.lock() { - logs.push_back(format!("[STDOUT] {}", line)); - // Keep only the last MAX_LOG_ENTRIES - while logs.len() > MAX_LOG_ENTRIES { - logs.pop_front(); - } - } - } - CommandEvent::Stderr(line_bytes) => { - let line = String::from_utf8_lossy(&line_bytes); - eprint!("{line}"); - - // Store log in shared state - if let Ok(mut logs) = log_state_clone.0.lock() { - logs.push_back(format!("[STDERR] {}", line)); - // Keep only the last MAX_LOG_ENTRIES - while logs.len() > MAX_LOG_ENTRIES { - logs.pop_front(); - } - } - } - _ => {} - } - } - }); - - child -} - -async fn is_server_running(port: u32) -> bool { - TcpSocket::new_v4() - .unwrap() - .connect(SocketAddr::new( - "127.0.0.1".parse().expect("Failed to parse IP"), - port as u16, - )) - .await - .is_ok() -} - -#[cfg_attr(mobile, tauri::mobile_entry_point)] -pub fn run() { - let updater_enabled = option_env!("TAURI_SIGNING_PRIVATE_KEY").is_some(); - - let mut builder = tauri::Builder::default() - .plugin(tauri_plugin_os::init()) - .plugin(tauri_plugin_window_state::Builder::new().build()) - .plugin(tauri_plugin_store::Builder::new().build()) - .plugin(tauri_plugin_dialog::init()) - .plugin(tauri_plugin_shell::init()) - .plugin(tauri_plugin_process::init()) - .plugin(tauri_plugin_opener::init()) - .plugin(tauri_plugin_clipboard_manager::init()) - .plugin(tauri_plugin_http::init()) - .plugin(PinchZoomDisablePlugin) - .invoke_handler(tauri::generate_handler![ - kill_sidecar, - copy_logs_to_clipboard, - get_logs - ]) - .setup(move |app| { - let app = app.handle().clone(); - - // Initialize log state - app.manage(LogState(Arc::new(Mutex::new(VecDeque::new())))); - - tauri::async_runtime::spawn(async move { - let port = get_sidecar_port(); - - let should_spawn_sidecar = !is_server_running(port).await; - - let child = if should_spawn_sidecar { - let child = spawn_sidecar(&app, port); - - let timestamp = Instant::now(); - loop { - if timestamp.elapsed() > Duration::from_secs(7) { - let res = app.dialog() - .message("Failed to spawn OpenCode Server. Copy logs using the button below and send them to the team for assistance.") - .title("Startup Failed") - .buttons(MessageDialogButtons::OkCancelCustom("Copy Logs And Exit".to_string(), "Exit".to_string())) - .blocking_show_with_result(); - - if matches!(&res, MessageDialogResult::Custom(name) if name == "Copy Logs And Exit") { - match copy_logs_to_clipboard(app.clone()).await { - Ok(()) => println!("Logs copied to clipboard successfully"), - Err(e) => println!("Failed to copy logs to clipboard: {}", e), - } - } - - app.exit(1); - - return; - } - - tokio::time::sleep(Duration::from_millis(10)).await; - - if is_server_running(port).await { - // give the server a little bit more time to warm up - tokio::time::sleep(Duration::from_millis(10)).await; - - break; - } - } - - println!("Server ready after {:?}", timestamp.elapsed()); - - Some(child) - } else { - None - }; - - let primary_monitor = app.primary_monitor().ok().flatten(); - let size = primary_monitor - .map(|m| m.size().to_logical(m.scale_factor())) - .unwrap_or(LogicalSize::new(1920, 1080)); - - let mut window_builder = - WebviewWindow::builder(&app, "main", WebviewUrl::App("/".into())) - .title("OpenCode") - .inner_size(size.width as f64, size.height as f64) - .decorations(true) - .zoom_hotkeys_enabled(true) - .disable_drag_drop_handler() - .initialization_script(format!( - r#" - window.__OPENCODE__ ??= {{}}; - window.__OPENCODE__.updaterEnabled = {updater_enabled}; - window.__OPENCODE__.port = {port}; - "# - )); - - #[cfg(target_os = "macos")] - { - window_builder = window_builder - .title_bar_style(tauri::TitleBarStyle::Overlay) - .hidden_title(true); - } - - window_builder.build().expect("Failed to create window"); - - app.manage(ServerState(Arc::new(Mutex::new(child)))); - }); - - Ok(()) - }); - - if updater_enabled { - builder = builder.plugin(tauri_plugin_updater::Builder::new().build()); - } - - builder - .build(tauri::generate_context!()) - .expect("error while running tauri application") - .run(|app, event| { - if let RunEvent::Exit = event { - println!("Received Exit"); - - kill_sidecar(app.clone()); - } - }); -} diff --git a/packages/desktop/src-tauri/src/main.rs b/packages/desktop/src-tauri/src/main.rs deleted file mode 100644 index b215f8c55..000000000 --- a/packages/desktop/src-tauri/src/main.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Prevents additional console window on Windows in release, DO NOT REMOVE!! -#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] - -// borrowed from https://github.com/skyline69/balatro-mod-manager -#[cfg(target_os = "linux")] -fn configure_display_backend() -> Option { - use std::env; - - let set_env_if_absent = |key: &str, value: &str| { - if env::var_os(key).is_none() { - // Safety: called during startup before any threads are spawned, so mutating the - // process environment is safe. - unsafe { env::set_var(key, value) }; - } - }; - - let on_wayland = env::var_os("WAYLAND_DISPLAY").is_some() - || matches!( - env::var("XDG_SESSION_TYPE"), - Ok(v) if v.eq_ignore_ascii_case("wayland") - ); - if !on_wayland { - return None; - } - - // Allow users to explicitly keep Wayland if they know their setup is stable. - let allow_wayland = matches!( - env::var("OC_ALLOW_WAYLAND"), - Ok(v) if matches!(v.to_ascii_lowercase().as_str(), "1" | "true" | "yes") - ); - if allow_wayland { - return Some("Wayland session detected; respecting OC_ALLOW_WAYLAND=1".into()); - } - - // Prefer XWayland when available to avoid Wayland protocol errors seen during startup. - if env::var_os("DISPLAY").is_some() { - set_env_if_absent("WINIT_UNIX_BACKEND", "x11"); - set_env_if_absent("GDK_BACKEND", "x11"); - set_env_if_absent("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); - return Some( - "Wayland session detected; forcing X11 backend to avoid compositor protocol errors. \ - Set OC_ALLOW_WAYLAND=1 to keep native Wayland." - .into(), - ); - } - - set_env_if_absent("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); - Some( - "Wayland session detected without X11; leaving Wayland enabled (set WINIT_UNIX_BACKEND/GDK_BACKEND manually if needed)." - .into(), - ) -} - -fn main() { - #[cfg(target_os = "linux")] - { - if let Some(backend_note) = configure_display_backend() { - eprintln!("{backend_note:?}"); - } - } - - opencode_lib::run() -} diff --git a/packages/desktop/src-tauri/src/window_customizer.rs b/packages/desktop/src-tauri/src/window_customizer.rs deleted file mode 100644 index cd42fd029..000000000 --- a/packages/desktop/src-tauri/src/window_customizer.rs +++ /dev/null @@ -1,34 +0,0 @@ -use tauri::{plugin::Plugin, Manager, Runtime, Window}; - -pub struct PinchZoomDisablePlugin; - -impl Default for PinchZoomDisablePlugin { - fn default() -> Self { - Self - } -} - -impl Plugin for PinchZoomDisablePlugin { - fn name(&self) -> &'static str { - "Does not matter here" - } - - fn window_created(&mut self, window: Window) { - let Some(webview_window) = window.get_webview_window(window.label()) else { - return; - }; - - let _ = webview_window.with_webview(|_webview| { - #[cfg(target_os = "linux")] - unsafe { - use gtk::glib::ObjectExt; - use gtk::GestureZoom; - use webkit2gtk::glib::gobject_ffi; - - if let Some(data) = _webview.inner().data::("wk-view-zoom-gesture") { - gobject_ffi::g_signal_handlers_destroy(data.as_ptr().cast()); - } - } - }); - } -} diff --git a/packages/desktop/src-tauri/tauri.conf.json b/packages/desktop/src-tauri/tauri.conf.json deleted file mode 100644 index bcb067a32..000000000 --- a/packages/desktop/src-tauri/tauri.conf.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "https://schema.tauri.app/config/2", - "productName": "OpenCode Dev", - "identifier": "ai.opencode.desktop.dev", - "mainBinaryName": "OpenCode", - "version": "../package.json", - "build": { - "beforeDevCommand": "bun run dev", - "devUrl": "http://localhost:1420", - "beforeBuildCommand": "bun run build", - "frontendDist": "../dist" - }, - "app": { - "withGlobalTauri": true, - "security": { - "csp": null - }, - "macOSPrivateApi": true - }, - "bundle": { - "icon": [ - "icons/dev/32x32.png", - "icons/dev/128x128.png", - "icons/dev/128x128@2x.png", - "icons/dev/icon.icns", - "icons/dev/icon.ico" - ], - "active": true, - "targets": ["deb", "rpm", "dmg", "nsis", "app", "appimage"], - "externalBin": ["sidecars/opencode-cli"], - "macOS": { - "entitlements": "./entitlements.plist" - }, - "windows": { - "nsis": { - "installerIcon": "icons/dev/icon.ico", - "headerImage": "assets/nsis-header.bmp", - "sidebarImage": "assets/nsis-sidebar.bmp" - } - } - } -} diff --git a/packages/desktop/src-tauri/tauri.prod.conf.json b/packages/desktop/src-tauri/tauri.prod.conf.json deleted file mode 100644 index 7894b8ab2..000000000 --- a/packages/desktop/src-tauri/tauri.prod.conf.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "https://schema.tauri.app/config/2", - "productName": "OpenCode", - "identifier": "ai.opencode.desktop", - "bundle": { - "createUpdaterArtifacts": true, - "icon": [ - "icons/prod/32x32.png", - "icons/prod/128x128.png", - "icons/prod/128x128@2x.png", - "icons/prod/icon.icns", - "icons/prod/icon.ico" - ], - "windows": { - "nsis": { - "installerIcon": "icons/prod/icon.ico" - } - } - }, - "plugins": { - "updater": { - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEYwMDM5Nzg5OUMzOUExMDQKUldRRW9UbWNpWmNEOENYT01CV0lhOXR1UFhpaXJsK1Z3aU9lZnNtNzE0TDROWVMwVW9XQnFOelkK", - "endpoints": ["https://github.com/sst/opencode/releases/latest/download/latest.json"] - } - } -} diff --git a/packages/app/src/components/file-tree.tsx b/packages/desktop/src/components/file-tree.tsx similarity index 100% rename from packages/app/src/components/file-tree.tsx rename to packages/desktop/src/components/file-tree.tsx diff --git a/packages/desktop/src/components/prompt-input.tsx b/packages/desktop/src/components/prompt-input.tsx new file mode 100644 index 000000000..976924223 --- /dev/null +++ b/packages/desktop/src/components/prompt-input.tsx @@ -0,0 +1,561 @@ +import { useFilteredList } from "@opencode-ai/ui/hooks" +import { createEffect, on, Component, Show, For, onMount, onCleanup, Switch, Match } from "solid-js" +import { createStore } from "solid-js/store" +import { createFocusSignal } from "@solid-primitives/active-element" +import { useLocal } from "@/context/local" +import { DateTime } from "luxon" +import { ContentPart, DEFAULT_PROMPT, isPromptEqual, Prompt, useSession } from "@/context/session" +import { useSDK } from "@/context/sdk" +import { useNavigate } from "@solidjs/router" +import { useSync } from "@/context/sync" +import { FileIcon } from "@opencode-ai/ui/file-icon" +import { SelectDialog } from "@opencode-ai/ui/select-dialog" +import { Button } from "@opencode-ai/ui/button" +import { Icon } from "@opencode-ai/ui/icon" +import { Tooltip } from "@opencode-ai/ui/tooltip" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { Select } from "@opencode-ai/ui/select" +import { getDirectory, getFilename } from "@opencode-ai/util/path" + +interface PromptInputProps { + class?: string + ref?: (el: HTMLDivElement) => void +} + +export const PromptInput: Component = (props) => { + const navigate = useNavigate() + const sdk = useSDK() + const sync = useSync() + const local = useLocal() + const session = useSession() + let editorRef!: HTMLDivElement + + const [store, setStore] = createStore<{ + popoverIsOpen: boolean + }>({ + popoverIsOpen: false, + }) + + createEffect(() => { + session.id + editorRef.focus() + }) + + const isFocused = createFocusSignal(() => editorRef) + + const handlePaste = (event: ClipboardEvent) => { + event.preventDefault() + event.stopPropagation() + // @ts-expect-error + const plainText = (event.clipboardData || window.clipboardData)?.getData("text/plain") ?? "" + addPart({ type: "text", content: plainText, start: 0, end: 0 }) + } + + onMount(() => { + editorRef.addEventListener("paste", handlePaste) + }) + onCleanup(() => { + editorRef.removeEventListener("paste", handlePaste) + }) + + createEffect(() => { + if (isFocused()) { + handleInput() + } else { + setStore("popoverIsOpen", false) + } + }) + + const handleFileSelect = (path: string | undefined) => { + if (!path) return + addPart({ type: "file", path, content: "@" + getFilename(path), start: 0, end: 0 }) + } + + const { flat, active, onInput, onKeyDown, refetch } = useFilteredList({ + items: local.file.searchFilesAndDirectories, + key: (x) => x, + onSelect: handleFileSelect, + }) + + createEffect(() => { + local.model.recent() + refetch() + }) + + createEffect( + on( + () => session.prompt.current(), + (currentParts) => { + const domParts = parseFromDOM() + if (isPromptEqual(currentParts, domParts)) return + + const selection = window.getSelection() + let cursorPosition: number | null = null + if (selection && selection.rangeCount > 0 && editorRef.contains(selection.anchorNode)) { + cursorPosition = getCursorPosition(editorRef) + } + + editorRef.innerHTML = "" + currentParts.forEach((part) => { + if (part.type === "text") { + editorRef.appendChild(document.createTextNode(part.content)) + } else if (part.type === "file") { + const pill = document.createElement("span") + pill.textContent = part.content + pill.setAttribute("data-type", "file") + pill.setAttribute("data-path", part.path) + pill.setAttribute("contenteditable", "false") + pill.style.userSelect = "text" + pill.style.cursor = "default" + editorRef.appendChild(pill) + } + }) + + if (cursorPosition !== null) { + setCursorPosition(editorRef, cursorPosition) + } + }, + ), + ) + + const parseFromDOM = (): Prompt => { + const newParts: Prompt = [] + let position = 0 + editorRef.childNodes.forEach((node) => { + if (node.nodeType === Node.TEXT_NODE) { + if (node.textContent) { + const content = node.textContent + newParts.push({ type: "text", content, start: position, end: position + content.length }) + position += content.length + } + } else if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).dataset.type) { + switch ((node as HTMLElement).dataset.type) { + case "file": + const content = node.textContent! + newParts.push({ + type: "file", + path: (node as HTMLElement).dataset.path!, + content, + start: position, + end: position + content.length, + }) + position += content.length + break + default: + break + } + } + }) + if (newParts.length === 0) newParts.push(...DEFAULT_PROMPT) + return newParts + } + + const handleInput = () => { + const rawParts = parseFromDOM() + const cursorPosition = getCursorPosition(editorRef) + const rawText = rawParts.map((p) => p.content).join("") + + const atMatch = rawText.substring(0, cursorPosition).match(/@(\S*)$/) + if (atMatch) { + onInput(atMatch[1]) + setStore("popoverIsOpen", true) + } else if (store.popoverIsOpen) { + setStore("popoverIsOpen", false) + } + + session.prompt.set(rawParts, cursorPosition) + } + + const addPart = (part: ContentPart) => { + const selection = window.getSelection() + if (!selection || selection.rangeCount === 0) return + + const cursorPosition = getCursorPosition(editorRef) + const prompt = session.prompt.current() + const rawText = prompt.map((p) => p.content).join("") + const textBeforeCursor = rawText.substring(0, cursorPosition) + const atMatch = textBeforeCursor.match(/@(\S*)$/) + + if (part.type === "file") { + const pill = document.createElement("span") + pill.textContent = part.content + pill.setAttribute("data-type", "file") + pill.setAttribute("data-path", part.path) + pill.setAttribute("contenteditable", "false") + pill.style.userSelect = "text" + pill.style.cursor = "default" + + const gap = document.createTextNode(" ") + const range = selection.getRangeAt(0) + + if (atMatch) { + // let node: Node | null = range.startContainer + // let offset = range.startOffset + let runningLength = 0 + + const walker = document.createTreeWalker(editorRef, NodeFilter.SHOW_TEXT, null) + let currentNode = walker.nextNode() + while (currentNode) { + const textContent = currentNode.textContent || "" + if (runningLength + textContent.length >= atMatch.index!) { + const localStart = atMatch.index! - runningLength + const localEnd = cursorPosition - runningLength + if (currentNode === range.startContainer || runningLength + textContent.length >= cursorPosition) { + range.setStart(currentNode, localStart) + range.setEnd(currentNode, Math.min(localEnd, textContent.length)) + break + } + } + runningLength += textContent.length + currentNode = walker.nextNode() + } + } + + range.deleteContents() + range.insertNode(gap) + range.insertNode(pill) + range.setStartAfter(gap) + range.collapse(true) + selection.removeAllRanges() + selection.addRange(range) + } else if (part.type === "text") { + const textNode = document.createTextNode(part.content) + const range = selection.getRangeAt(0) + range.deleteContents() + range.insertNode(textNode) + range.setStartAfter(textNode) + range.collapse(true) + selection.removeAllRanges() + selection.addRange(range) + } + + handleInput() + setStore("popoverIsOpen", false) + } + + const abort = () => + sdk.client.session.abort({ + path: { + id: session.id!, + }, + }) + + const handleKeyDown = (event: KeyboardEvent) => { + if (store.popoverIsOpen && (event.key === "ArrowUp" || event.key === "ArrowDown" || event.key === "Enter")) { + onKeyDown(event) + event.preventDefault() + return + } + if (event.key === "Enter" && !event.shiftKey) { + handleSubmit(event) + } + if (event.key === "Escape") { + if (store.popoverIsOpen) { + setStore("popoverIsOpen", false) + } else if (session.working()) { + abort() + } + } + } + + const handleSubmit = async (event: Event) => { + event.preventDefault() + const prompt = session.prompt.current() + const text = prompt.map((part) => part.content).join("") + if (text.trim().length === 0) { + if (session.working()) abort() + return + } + + let existing = session.info() + if (!existing) { + const created = await sdk.client.session.create() + existing = created.data ?? undefined + if (existing) navigate(existing.id) + } + if (!existing) return + + // if (!session.id) { + // session.layout.setOpenedTabs( + // session.layout.copyTabs("", session.id) + // } + + const toAbsolutePath = (path: string) => (path.startsWith("/") ? path : sync.absolute(path)) + const attachments = prompt.filter((part) => part.type === "file") + + // const activeFile = local.context.active() + // if (activeFile) { + // registerAttachment( + // activeFile.path, + // activeFile.selection, + // activeFile.name ?? formatAttachmentLabel(activeFile.path, activeFile.selection), + // ) + // } + + // for (const contextFile of local.context.all()) { + // registerAttachment( + // contextFile.path, + // contextFile.selection, + // formatAttachmentLabel(contextFile.path, contextFile.selection), + // ) + // } + + const attachmentParts = attachments.map((attachment) => { + const absolute = toAbsolutePath(attachment.path) + const query = attachment.selection + ? `?start=${attachment.selection.startLine}&end=${attachment.selection.endLine}` + : "" + return { + type: "file" as const, + mime: "text/plain", + url: `file://${absolute}${query}`, + filename: getFilename(attachment.path), + source: { + type: "file" as const, + text: { + value: attachment.content, + start: attachment.start, + end: attachment.end, + }, + path: absolute, + }, + } + }) + + session.layout.setActiveTab(undefined) + session.messages.setActive(undefined) + // Clear the editor DOM directly to ensure it's empty + editorRef.innerHTML = "" + session.prompt.set([{ type: "text", content: "", start: 0, end: 0 }], 0) + + sdk.client.session.prompt({ + path: { id: existing.id }, + body: { + agent: local.agent.current()!.name, + model: { + modelID: local.model.current()!.id, + providerID: local.model.current()!.provider.id, + }, + parts: [ + { + type: "text", + text, + }, + ...attachmentParts, + ], + }, + }) + } + + return ( +
    + +
    + 0} fallback={
    No matching files
    }> + + {(i) => ( + + )} + +
    +
    +
    + +
    +
    { + editorRef = el + props.ref?.(el) + }} + contenteditable="true" + onInput={handleInput} + onKeyDown={handleKeyDown} + classList={{ + "w-full px-5 py-3 text-14-regular text-text-strong focus:outline-none whitespace-pre-wrap": true, + "[&>[data-type=file]]:text-icon-info-active": true, + }} + /> + +
    + Plan and build anything +
    +
    +
    +
    +
    +