diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3ebb0c107..7eab4a31c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,26 +1,56 @@ name: CI + on: push: - branches: [main] + branches: [main, feature/*, bugfix/*, docs/*, release/*, hotfix/*] pull_request: branches: [main] + jobs: - ci: + test: runs-on: ubuntu-latest + + strategy: + matrix: + go-version: ['1.21', '1.22'] + steps: - uses: actions/checkout@v4 + - name: Refresh models catalog run: | git fetch --depth 1 https://github.com/router-for-me/models.git main mkdir -p pkg/llmproxy/registry/models git show FETCH_HEAD:models.json > pkg/llmproxy/registry/models/models.json - - uses: actions/setup-go@v5 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + + - name: Cache Go modules + uses: actions/cache@v4 with: - go-version-file: go.mod - cache: true - - name: Vet - run: go vet ./... + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Download dependencies + run: go mod download + - name: Build run: go build ./... - - name: Test - run: go test ./... + + - name: Run tests + run: go test ./... -v -race -coverprofile=coverage.out + + - name: Upload coverage + uses: codecov/codecov-action@v3 + with: + files: ./coverage.out + + + phenotype-validate: + runs-on: ubuntu-latest + uses: KooshaPari/phenotypeActions/.github/workflows/validate-governance.yml@main diff --git a/bun.lock b/bun.lock deleted file mode 100644 index 99b0978241..0000000000 --- a/bun.lock +++ /dev/null @@ -1,111 +0,0 @@ -{ - "lockfileVersion": 1, - "configVersion": 1, - "workspaces": { - "": { - "name": "cliproxyapi-plusplus-oxc-tools", - "devDependencies": { - "oxfmt": "^0.36.0", - "oxlint": "^1.51.0", - "oxlint-tsgolint": "^0.16.0", - }, - }, - }, - "packages": { - "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.36.0", "", { "os": "android", "cpu": "arm" }, "sha512-Z4yVHJWx/swHHjtr0dXrBZb6LxS+qNz1qdza222mWwPTUK4L790+5i3LTgjx3KYGBzcYpjaiZBw4vOx94dH7MQ=="], - - "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.36.0", "", { "os": "android", "cpu": "arm64" }, "sha512-3ElCJRFNPQl7jexf2CAa9XmAm8eC5JPrIDSjc9jSchkVSFTEqyL0NtZinBB2h1a4i4JgP1oGl/5G5n8YR4FN8Q=="], - - "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.36.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nak4znWCqIExKhYSY/mz/lWsqWIpdsS7o0+SRzXR1Q0m7GrMcG1UrF1pS7TLGZhhkf7nTfEF7q6oZzJiodRDuw=="], - - "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.36.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-V4GP96thDnpKx6ADnMDnhIXNdtV+Ql9D4HUU+a37VTeVbs5qQSF/s6hhUP1b3xUqU7iRcwh72jUU2Y12rtGHAw=="], - - "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.36.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-/xapWCADfI5wrhxpEUjhI9fnw7MV5BUZizVa8e24n3VSK6A3Y1TB/ClOP1tfxNspykFKXp4NBWl6NtDJP3osqQ=="], - - "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.36.0", "", { "os": "linux", "cpu": "arm" }, "sha512-1lOmv61XMFIH5uNm27620kRRzWt/RK6tdn250BRDoG9W7OXGOQ5UyI1HVT+SFkoOoKztBiinWgi68+NA1MjBVQ=="], - - "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.36.0", "", { "os": "linux", "cpu": "arm" }, "sha512-vMH23AskdR1ujUS9sPck2Df9rBVoZUnCVY86jisILzIQ/QQ/yKUTi7tgnIvydPx7TyB/48wsQ5QMr5Knq5p/aw=="], - - "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.36.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Hy1V+zOBHpBiENRx77qrUTt5aPDHeCASRc8K5KwwAHkX2AKP0nV89eL17hsZrE9GmnXFjsNmd80lyf7aRTXsbw=="], - - "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.36.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-SPGLJkOIHSIC6ABUQ5V8NqJpvYhMJueJv26NYqfCnwi/Mn6A61amkpJJ9Suy0Nmvs+OWESJpcebrBUbXPGZyQQ=="], - - "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.36.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3EuoyB8x9x8ysYJjbEO/M9fkSk72zQKnXCvpZMDHXlnY36/1qMp55Nm0PrCwjGO/1pen5hdOVkz9WmP3nAp2IQ=="], - - "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.36.0", "", { "os": "linux", "cpu": "none" }, "sha512-MpY3itLwpGh8dnywtrZtaZ604T1m715SydCKy0+qTxetv+IHzuA+aO/AGzrlzUNYZZmtWtmDBrChZGibvZxbRQ=="], - - "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.36.0", "", { "os": "linux", "cpu": "none" }, "sha512-mmDhe4Vtx+XwQPRPn/V25+APnkApYgZ23q+6GVsNYY98pf3aU0aI3Me96pbRs/AfJ1jIiGC+/6q71FEu8dHcHw=="], - - "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.36.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-AYXhU+DmNWLSnvVwkHM92fuYhogtVHab7UQrPNaDf1sxadugg9gWVmcgJDlIwxJdpk5CVW/TFvwUKwI432zhhA=="], - - "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.36.0", "", { "os": "linux", "cpu": "x64" }, "sha512-H16QhhQ3usoakMleiAAQ2mg0NsBDAdyE9agUgfC8IHHh3jZEbr0rIKwjEqwbOHK5M0EmfhJmr+aGO/MgZPsneA=="], - - "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.36.0", "", { "os": "linux", "cpu": "x64" }, "sha512-EFFGkixA39BcmHiCe2ECdrq02D6FCve5ka6ObbvrheXl4V+R0U/E+/uLyVx1X65LW8TA8QQHdnbdDallRekohw=="], - - "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.36.0", "", { "os": "none", "cpu": "arm64" }, "sha512-zr/t369wZWFOj1qf06Z5gGNjFymfUNDrxKMmr7FKiDRVI1sNsdKRCuRL4XVjtcptKQ+ao3FfxLN1vrynivmCYg=="], - - "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.36.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-FxO7UksTv8h4olzACgrqAXNF6BP329+H322323iDrMB5V/+a1kcAw07fsOsUmqNrb9iJBsCQgH/zqcqp5903ag=="], - - "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.36.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-OjoMQ89H01M0oLMfr/CPNH1zi48ZIwxAKObUl57oh7ssUBNDp/2Vjf7E1TQ8M4oj4VFQ/byxl2SmcPNaI2YNDg=="], - - "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.36.0", "", { "os": "win32", "cpu": "x64" }, "sha512-MoyeQ9S36ZTz/4bDhOKJgOBIDROd4dQ5AkT9iezhEaUBxAPdNX9Oq0jD8OSnCj3G4wam/XNxVWKMA52kmzmPtQ=="], - - "@oxlint-tsgolint/darwin-arm64": ["@oxlint-tsgolint/darwin-arm64@0.16.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-WQt5lGwRPJBw7q2KNR0mSPDAaMmZmVvDlEEti96xLO7ONhyomQc6fBZxxwZ4qTFedjJnrHX94sFelZ4OKzS7UQ=="], - - "@oxlint-tsgolint/darwin-x64": ["@oxlint-tsgolint/darwin-x64@0.16.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-VJo29XOzdkalvCTiE2v6FU3qZlgHaM8x8hUEVJGPU2i5W+FlocPpmn00+Ld2n7Q0pqIjyD5EyvZ5UmoIEJMfqg=="], - - "@oxlint-tsgolint/linux-arm64": ["@oxlint-tsgolint/linux-arm64@0.16.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-MPfqRt1+XRHv9oHomcBMQ3KpTE+CSkZz14wUxDQoqTNdUlV0HWdzwIE9q65I3D9YyxEnqpM7j4qtDQ3apqVvbQ=="], - - "@oxlint-tsgolint/linux-x64": ["@oxlint-tsgolint/linux-x64@0.16.0", "", { "os": "linux", "cpu": "x64" }, "sha512-XQSwVUsnwLokMhe1TD6IjgvW5WMTPzOGGkdFDtXWQmlN2YeTw94s/NN0KgDrn2agM1WIgAenEkvnm0u7NgwEyw=="], - - "@oxlint-tsgolint/win32-arm64": ["@oxlint-tsgolint/win32-arm64@0.16.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-EWdlspQiiFGsP2AiCYdhg5dTYyAlj6y1nRyNI2dQWq4Q/LITFHiSRVPe+7m7K7lcsZCEz2icN/bCeSkZaORqIg=="], - - "@oxlint-tsgolint/win32-x64": ["@oxlint-tsgolint/win32-x64@0.16.0", "", { "os": "win32", "cpu": "x64" }, "sha512-1ufk8cgktXJuJZHKF63zCHAkaLMwZrEXnZ89H2y6NO85PtOXqu4zbdNl0VBpPP3fCUuUBu9RvNqMFiv0VsbXWA=="], - - "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.51.0", "", { "os": "android", "cpu": "arm" }, "sha512-jJYIqbx4sX+suIxWstc4P7SzhEwb4ArWA2KVrmEuu9vH2i0qM6QIHz/ehmbGE4/2fZbpuMuBzTl7UkfNoqiSgw=="], - - "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.51.0", "", { "os": "android", "cpu": "arm64" }, "sha512-GtXyBCcH4ti98YdiMNCrpBNGitx87EjEWxevnyhcBK12k/Vu4EzSB45rzSC4fGFUD6sQgeaxItRCEEWeVwPafw=="], - - "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.51.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-3QJbeYaMHn6Bh2XeBXuITSsbnIctyTjvHf5nRjKYrT9pPeErNIpp5VDEeAXC0CZSwSVTsc8WOSDwgrAI24JolQ=="], - - "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.51.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-NzErhMaTEN1cY0E8C5APy74lw5VwsNfJfVPBMWPVQLqAbO0k4FFLjvHURvkUL+Y18Wu+8Vs1kbqPh2hjXYA4pg=="], - - "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.51.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-msAIh3vPAoKoHlOE/oe6Q5C/n9umypv/k81lED82ibrJotn+3YG2Qp1kiR8o/Dg5iOEU97c6tl0utxcyFenpFw=="], - - "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.51.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CqQPcvqYyMe9ZBot2stjGogEzk1z8gGAngIX7srSzrzexmXixwVxBdFZyxTVM0CjGfDeV+Ru0w25/WNjlMM2Hw=="], - - "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.51.0", "", { "os": "linux", "cpu": "arm" }, "sha512-dstrlYQgZMnyOssxSbolGCge/sDbko12N/35RBNuqLpoPbft2aeBidBAb0dvQlyBd9RJ6u8D4o4Eh8Un6iTgyQ=="], - - "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.51.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-QEjUpXO7d35rP1/raLGGbAsBLLGZIzV3ZbeSjqWlD3oRnxpRIZ6iL4o51XQHkconn3uKssc+1VKdtHJ81BBhDA=="], - - "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.51.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-YSJua5irtG4DoMAjUapDTPhkQLHhBIY0G9JqlZS6/SZPzqDkPku/1GdWs0D6h/wyx0Iz31lNCfIaWKBQhzP0wQ=="], - - "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.51.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-7L4Wj2IEUNDETKssB9IDYt16T6WlF+X2jgC/hBq3diGHda9vJLpAgb09+D3quFq7TdkFtI7hwz/jmuQmQFPc1Q=="], - - "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.51.0", "", { "os": "linux", "cpu": "none" }, "sha512-cBUHqtOXy76G41lOB401qpFoKx1xq17qYkhWrLSM7eEjiHM9sOtYqpr6ZdqCnN9s6ZpzudX4EkeHOFH2E9q0vA=="], - - "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.51.0", "", { "os": "linux", "cpu": "none" }, "sha512-WKbg8CysgZcHfZX0ixQFBRSBvFZUHa3SBnEjHY2FVYt2nbNJEjzTxA3ZR5wMU0NOCNKIAFUFvAh5/XJKPRJuJg=="], - - "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.51.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-N1QRUvJTxqXNSu35YOufdjsAVmKVx5bkrggOWAhTWBc3J4qjcBwr1IfyLh/6YCg8sYRSR1GraldS9jUgJL/U4A=="], - - "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.51.0", "", { "os": "linux", "cpu": "x64" }, "sha512-e0Mz0DizsCoqNIjeOg6OUKe8JKJWZ5zZlwsd05Bmr51Jo3AOL4UJnPvwKumr4BBtBrDZkCmOLhCvDGm95nJM2g=="], - - "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.51.0", "", { "os": "linux", "cpu": "x64" }, "sha512-wD8HGTWhYBKXvRDvoBVB1y+fEYV01samhWQSy1Zkxq2vpezvMnjaFKRuiP6tBNITLGuffbNDEXOwcAhJ3gI5Ug=="], - - "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.51.0", "", { "os": "none", "cpu": "arm64" }, "sha512-5NSwQ2hDEJ0GPXqikjWtwzgAQCsS7P9aLMNenjjKa+gknN3lTCwwwERsT6lKXSirfU3jLjexA2XQvQALh5h27w=="], - - "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.51.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-JEZyah1M0RHMw8d+jjSSJmSmO8sABA1J1RtrHYujGPeCkYg1NeH0TGuClpe2h5QtioRTaF57y/TZfn/2IFV6fA=="], - - "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.51.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-q3cEoKH6kwjz/WRyHwSf0nlD2F5Qw536kCXvmlSu+kaShzgrA0ojmh45CA81qL+7udfCaZL2SdKCZlLiGBVFlg=="], - - "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.51.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Q14+fOGb9T28nWF/0EUsYqERiRA7cl1oy4TJrGmLaqhm+aO2cV+JttboHI3CbdeMCAyDI1+NoSlrM7Melhp/cw=="], - - "oxfmt": ["oxfmt@0.36.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.36.0", "@oxfmt/binding-android-arm64": "0.36.0", "@oxfmt/binding-darwin-arm64": "0.36.0", "@oxfmt/binding-darwin-x64": "0.36.0", "@oxfmt/binding-freebsd-x64": "0.36.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.36.0", "@oxfmt/binding-linux-arm-musleabihf": "0.36.0", "@oxfmt/binding-linux-arm64-gnu": "0.36.0", "@oxfmt/binding-linux-arm64-musl": "0.36.0", "@oxfmt/binding-linux-ppc64-gnu": "0.36.0", "@oxfmt/binding-linux-riscv64-gnu": "0.36.0", "@oxfmt/binding-linux-riscv64-musl": "0.36.0", "@oxfmt/binding-linux-s390x-gnu": "0.36.0", "@oxfmt/binding-linux-x64-gnu": "0.36.0", "@oxfmt/binding-linux-x64-musl": "0.36.0", "@oxfmt/binding-openharmony-arm64": "0.36.0", "@oxfmt/binding-win32-arm64-msvc": "0.36.0", "@oxfmt/binding-win32-ia32-msvc": "0.36.0", "@oxfmt/binding-win32-x64-msvc": "0.36.0" }, "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-/ejJ+KoSW6J9bcNT9a9UtJSJNWhJ3yOLSBLbkoFHJs/8CZjmaZVZAJe4YgO1KMJlKpNQasrn/G9JQUEZI3p0EQ=="], - - "oxlint": ["oxlint@1.51.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.51.0", "@oxlint/binding-android-arm64": "1.51.0", "@oxlint/binding-darwin-arm64": "1.51.0", "@oxlint/binding-darwin-x64": "1.51.0", "@oxlint/binding-freebsd-x64": "1.51.0", "@oxlint/binding-linux-arm-gnueabihf": "1.51.0", "@oxlint/binding-linux-arm-musleabihf": "1.51.0", "@oxlint/binding-linux-arm64-gnu": "1.51.0", "@oxlint/binding-linux-arm64-musl": "1.51.0", "@oxlint/binding-linux-ppc64-gnu": "1.51.0", "@oxlint/binding-linux-riscv64-gnu": "1.51.0", "@oxlint/binding-linux-riscv64-musl": "1.51.0", "@oxlint/binding-linux-s390x-gnu": "1.51.0", "@oxlint/binding-linux-x64-gnu": "1.51.0", "@oxlint/binding-linux-x64-musl": "1.51.0", "@oxlint/binding-openharmony-arm64": "1.51.0", "@oxlint/binding-win32-arm64-msvc": "1.51.0", "@oxlint/binding-win32-ia32-msvc": "1.51.0", "@oxlint/binding-win32-x64-msvc": "1.51.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.15.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-g6DNPaV9/WI9MoX2XllafxQuxwY1TV++j7hP8fTJByVBuCoVtm3dy9f/2vtH/HU40JztcgWF4G7ua+gkainklQ=="], - - "oxlint-tsgolint": ["oxlint-tsgolint@0.16.0", "", { "optionalDependencies": { "@oxlint-tsgolint/darwin-arm64": "0.16.0", "@oxlint-tsgolint/darwin-x64": "0.16.0", "@oxlint-tsgolint/linux-arm64": "0.16.0", "@oxlint-tsgolint/linux-x64": "0.16.0", "@oxlint-tsgolint/win32-arm64": "0.16.0", "@oxlint-tsgolint/win32-x64": "0.16.0" }, "bin": { "tsgolint": "bin/tsgolint.js" } }, "sha512-4RuJK2jP08XwqtUu+5yhCbxEauCm6tv2MFHKEMsjbosK2+vy5us82oI3VLuHwbNyZG7ekZA26U2LLHnGR4frIA=="], - - "tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="], - } -} diff --git a/cliproxyctl/main.go b/cliproxyctl/main.go index a10e5b12a6..e9ff67e0ce 100644 --- a/cliproxyctl/main.go +++ b/cliproxyctl/main.go @@ -12,8 +12,8 @@ import ( "strings" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" cliproxycmd "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/cmd" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) const responseSchemaVersion = "cliproxyctl.response.v1" diff --git a/cliproxyctl/main_test.go b/cliproxyctl/main_test.go index d3c12e1632..8bcf24a3fd 100644 --- a/cliproxyctl/main_test.go +++ b/cliproxyctl/main_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" cliproxycmd "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/cmd" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestRunSetupJSONResponseShape(t *testing.T) { diff --git a/cmd/codegen/main.go b/cmd/codegen/main.go index 5abe1f1454..be4aaedaa6 100644 --- a/cmd/codegen/main.go +++ b/cmd/codegen/main.go @@ -72,7 +72,7 @@ const synthTemplate = `// Code generated by github.com/kooshapari/CLIProxyAPI/v7 package synthesizer import ( - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) // getDedicatedProviderEntries returns the config entries for a dedicated provider. @@ -123,7 +123,7 @@ package diff import ( "fmt" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) // BuildConfigChangeDetailsGeneratedProviders computes changes for generated dedicated providers. diff --git a/cmd/fetch_antigravity_models/main.go b/cmd/fetch_antigravity_models/main.go index 0cf45d3b3b..a488a4be5c 100644 --- a/cmd/fetch_antigravity_models/main.go +++ b/cmd/fetch_antigravity_models/main.go @@ -25,10 +25,10 @@ import ( "strings" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/logging" - sdkauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/auth" - coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" - "github.com/router-for-me/CLIProxyAPI/v6/sdk/proxyutil" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/logging" + sdkauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/auth" + coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" + "github.com/kooshapari/CLIProxyAPI/v7/sdk/proxyutil" log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" ) diff --git a/cmd/mcpdebug/main.go b/cmd/mcpdebug/main.go index af2189c1bb..89d23ba777 100644 --- a/cmd/mcpdebug/main.go +++ b/cmd/mcpdebug/main.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - cursorproto "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/cursor/proto" + cursorproto "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/cursor/proto" ) func main() { diff --git a/cmd/protocheck/main.go b/cmd/protocheck/main.go index 9c11ddb0bd..21842a46b5 100644 --- a/cmd/protocheck/main.go +++ b/cmd/protocheck/main.go @@ -3,7 +3,7 @@ package main import ( "fmt" - cursorproto "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/cursor/proto" + cursorproto "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/cursor/proto" "google.golang.org/protobuf/reflect/protoreflect" ) diff --git a/cmd/server/config_validate.go b/cmd/server/config_validate.go index b9ed4c33b9..b2e83bc51b 100644 --- a/cmd/server/config_validate.go +++ b/cmd/server/config_validate.go @@ -6,7 +6,7 @@ import ( "io" "os" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" "gopkg.in/yaml.v3" ) diff --git a/cmd/server/main.go b/cmd/server/main.go index 2dba0690db..7ca5e6081a 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -17,19 +17,19 @@ import ( "time" "github.com/joho/godotenv" - configaccess "github.com/kooshapari/CLIProxyAPI/v7/internal/access/config_access" - "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/kiro" - "github.com/kooshapari/CLIProxyAPI/v7/internal/buildinfo" - "github.com/kooshapari/CLIProxyAPI/v7/internal/cmd" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" - "github.com/kooshapari/CLIProxyAPI/v7/internal/logging" - "github.com/kooshapari/CLIProxyAPI/v7/internal/managementasset" - "github.com/kooshapari/CLIProxyAPI/v7/internal/misc" - "github.com/kooshapari/CLIProxyAPI/v7/internal/store" - _ "github.com/kooshapari/CLIProxyAPI/v7/internal/translator" - "github.com/kooshapari/CLIProxyAPI/v7/internal/tui" - "github.com/kooshapari/CLIProxyAPI/v7/internal/usage" - "github.com/kooshapari/CLIProxyAPI/v7/internal/util" + configaccess "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/access/config_access" + kiro "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/kiro" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/buildinfo" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/cmd" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/logging" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/managementasset" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/store" + _ "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/translator" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/tui" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/usage" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" sdkAuth "github.com/kooshapari/CLIProxyAPI/v7/sdk/auth" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" log "github.com/sirupsen/logrus" diff --git a/cmd/server/main_kiro_flags_test.go b/cmd/server/main_kiro_flags_test.go index 5896d34306..b8929bdcd5 100644 --- a/cmd/server/main_kiro_flags_test.go +++ b/cmd/server/main_kiro_flags_test.go @@ -3,7 +3,7 @@ package main import ( "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestValidateKiroIncognitoFlags(t *testing.T) { diff --git a/docs/sessions/2026-04-01-pr-readiness-refresh/00_SESSION_OVERVIEW.md b/docs/sessions/2026-04-01-pr-readiness-refresh/00_SESSION_OVERVIEW.md index ecd677ea57..6dce81ea85 100644 --- a/docs/sessions/2026-04-01-pr-readiness-refresh/00_SESSION_OVERVIEW.md +++ b/docs/sessions/2026-04-01-pr-readiness-refresh/00_SESSION_OVERVIEW.md @@ -15,3 +15,11 @@ Stabilize PR `#942` enough to move it out of branch-local merge debt and obvious - The branch no longer carries an unmerged spec file. - `SAST Quick Check` no longer references a missing action repo or a Rust-only lint job. - Remaining blockers are pre-existing repo debt or external issues, not broken workflow scaffolding in this PR. + +## 2026-04-02 Import Surface Follow-up + +- Replaced stale `internal/config` imports with the live `pkg/llmproxy/config` package across the repo-internal tests and generator template. +- Replaced stale watcher test imports to the live `pkg/llmproxy/watcher/diff` and `pkg/llmproxy/watcher/synthesizer` packages. +- Replaced stale auth test imports from the old v6 tree with the current local `internal/auth/codebuddy` and `pkg/llmproxy/auth/kiro` packages. +- `go mod vendor` now succeeds after the import-surface sweep. +- `GOFLAGS=-mod=vendor go test ./...` still fails, but now on broader vendoring/toolchain debt because the generated `vendor/` tree remains incomplete for many third-party packages on this branch. diff --git a/internal/auth/codebuddy/codebuddy_auth.go b/internal/auth/codebuddy/codebuddy_auth.go index b43842005d..1d52cc0078 100644 --- a/internal/auth/codebuddy/codebuddy_auth.go +++ b/internal/auth/codebuddy/codebuddy_auth.go @@ -15,8 +15,8 @@ import ( "github.com/google/uuid" log "github.com/sirupsen/logrus" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/util" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" ) const ( diff --git a/internal/auth/codebuddy/codebuddy_auth_test.go b/internal/auth/codebuddy/codebuddy_auth_test.go index b43be3914e..9ba2fe7843 100644 --- a/internal/auth/codebuddy/codebuddy_auth_test.go +++ b/internal/auth/codebuddy/codebuddy_auth_test.go @@ -3,7 +3,7 @@ package codebuddy_test import ( "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/codebuddy" + "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/codebuddy" ) func TestDecodeUserID_ValidJWT(t *testing.T) { diff --git a/internal/auth/codebuddy/token.go b/internal/auth/codebuddy/token.go index 6888b7277c..99023d700c 100644 --- a/internal/auth/codebuddy/token.go +++ b/internal/auth/codebuddy/token.go @@ -9,7 +9,7 @@ import ( "os" "path/filepath" - "github.com/router-for-me/CLIProxyAPI/v6/internal/misc" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" ) // CodeBuddyTokenStorage stores OAuth token information for CodeBuddy API authentication. diff --git a/internal/auth/gitlab/gitlab.go b/internal/auth/gitlab/gitlab.go index 5cf8876c4f..4eabf1c1f5 100644 --- a/internal/auth/gitlab/gitlab.go +++ b/internal/auth/gitlab/gitlab.go @@ -16,8 +16,8 @@ import ( "sync" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/util" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" log "github.com/sirupsen/logrus" ) diff --git a/pkg/llmproxy/access/reconcile.go b/pkg/llmproxy/access/reconcile.go index 8e9cf34c14..e89e1e9b81 100644 --- a/pkg/llmproxy/access/reconcile.go +++ b/pkg/llmproxy/access/reconcile.go @@ -9,6 +9,7 @@ import ( configaccess "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/access/config_access" "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" sdkaccess "github.com/kooshapari/CLIProxyAPI/v7/sdk/access" + sdkconfig "github.com/kooshapari/CLIProxyAPI/v7/sdk/config" log "github.com/sirupsen/logrus" ) diff --git a/pkg/llmproxy/api/handlers/management/auth_files_batch_test.go b/pkg/llmproxy/api/handlers/management/auth_files_batch_test.go index 44cdbd5b5f..97cf1e3a88 100644 --- a/pkg/llmproxy/api/handlers/management/auth_files_batch_test.go +++ b/pkg/llmproxy/api/handlers/management/auth_files_batch_test.go @@ -12,7 +12,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/api/handlers/management/auth_files_delete_test.go b/pkg/llmproxy/api/handlers/management/auth_files_delete_test.go index 7b7b888c4b..34836627a0 100644 --- a/pkg/llmproxy/api/handlers/management/auth_files_delete_test.go +++ b/pkg/llmproxy/api/handlers/management/auth_files_delete_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/api/handlers/management/auth_files_download_test.go b/pkg/llmproxy/api/handlers/management/auth_files_download_test.go index a2a20d305a..bf865e8609 100644 --- a/pkg/llmproxy/api/handlers/management/auth_files_download_test.go +++ b/pkg/llmproxy/api/handlers/management/auth_files_download_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestDownloadAuthFile_ReturnsFile(t *testing.T) { diff --git a/pkg/llmproxy/api/handlers/management/auth_files_download_windows_test.go b/pkg/llmproxy/api/handlers/management/auth_files_download_windows_test.go index 8c174ccf51..88d8e57972 100644 --- a/pkg/llmproxy/api/handlers/management/auth_files_download_windows_test.go +++ b/pkg/llmproxy/api/handlers/management/auth_files_download_windows_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestDownloadAuthFile_PreventsWindowsSlashTraversal(t *testing.T) { diff --git a/pkg/llmproxy/api/handlers/management/auth_files_gitlab_test.go b/pkg/llmproxy/api/handlers/management/auth_files_gitlab_test.go index 31fca89695..08c607233a 100644 --- a/pkg/llmproxy/api/handlers/management/auth_files_gitlab_test.go +++ b/pkg/llmproxy/api/handlers/management/auth_files_gitlab_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/api/handlers/management/management_auth_test.go b/pkg/llmproxy/api/handlers/management/management_auth_test.go index 44f48227ea..0009ae9d53 100644 --- a/pkg/llmproxy/api/handlers/management/management_auth_test.go +++ b/pkg/llmproxy/api/handlers/management/management_auth_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestListAuthFiles(t *testing.T) { diff --git a/pkg/llmproxy/api/handlers/management/management_basic_test.go b/pkg/llmproxy/api/handlers/management/management_basic_test.go index f6639f3074..bd5177d3f4 100644 --- a/pkg/llmproxy/api/handlers/management/management_basic_test.go +++ b/pkg/llmproxy/api/handlers/management/management_basic_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestGetConfig(t *testing.T) { diff --git a/pkg/llmproxy/api/handlers/management/management_extra_test.go b/pkg/llmproxy/api/handlers/management/management_extra_test.go index 95f2934096..96a4446eb0 100644 --- a/pkg/llmproxy/api/handlers/management/management_extra_test.go +++ b/pkg/llmproxy/api/handlers/management/management_extra_test.go @@ -14,7 +14,7 @@ import ( "time" "github.com/gin-gonic/gin" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/usage" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/api/handlers/management/management_fields_test.go b/pkg/llmproxy/api/handlers/management/management_fields_test.go index ad6a554eb9..acfa7cb137 100644 --- a/pkg/llmproxy/api/handlers/management/management_fields_test.go +++ b/pkg/llmproxy/api/handlers/management/management_fields_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func setupTestHandler(cfg *config.Config) (*Handler, string, func()) { diff --git a/pkg/llmproxy/api/handlers/management/management_modelstates_test.go b/pkg/llmproxy/api/handlers/management/management_modelstates_test.go index 723ff56426..e6fe8bbc00 100644 --- a/pkg/llmproxy/api/handlers/management/management_modelstates_test.go +++ b/pkg/llmproxy/api/handlers/management/management_modelstates_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/api/modules/amp/amp_test.go b/pkg/llmproxy/api/modules/amp/amp_test.go index 10236aec22..cc03743bc8 100644 --- a/pkg/llmproxy/api/modules/amp/amp_test.go +++ b/pkg/llmproxy/api/modules/amp/amp_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/gin-gonic/gin" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/api/modules" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" sdkaccess "github.com/kooshapari/CLIProxyAPI/v7/sdk/access" "github.com/kooshapari/CLIProxyAPI/v7/sdk/api/handlers" ) diff --git a/pkg/llmproxy/api/modules/amp/fallback_handlers_test.go b/pkg/llmproxy/api/modules/amp/fallback_handlers_test.go index df28ed1728..7becc337be 100644 --- a/pkg/llmproxy/api/modules/amp/fallback_handlers_test.go +++ b/pkg/llmproxy/api/modules/amp/fallback_handlers_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" ) diff --git a/pkg/llmproxy/api/modules/amp/model_mapping_test.go b/pkg/llmproxy/api/modules/amp/model_mapping_test.go index 5937eba9d7..c745cdc029 100644 --- a/pkg/llmproxy/api/modules/amp/model_mapping_test.go +++ b/pkg/llmproxy/api/modules/amp/model_mapping_test.go @@ -3,7 +3,7 @@ package amp import ( "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" ) diff --git a/pkg/llmproxy/api/modules/amp/proxy_test.go b/pkg/llmproxy/api/modules/amp/proxy_test.go index 85e1fd449a..4871360ba4 100644 --- a/pkg/llmproxy/api/modules/amp/proxy_test.go +++ b/pkg/llmproxy/api/modules/amp/proxy_test.go @@ -11,7 +11,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) // Helper: compress data with gzip diff --git a/pkg/llmproxy/api/modules/amp/secret_test.go b/pkg/llmproxy/api/modules/amp/secret_test.go index 1bb08d2262..1842b5a901 100644 --- a/pkg/llmproxy/api/modules/amp/secret_test.go +++ b/pkg/llmproxy/api/modules/amp/secret_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" log "github.com/sirupsen/logrus" "github.com/sirupsen/logrus/hooks/test" ) diff --git a/pkg/llmproxy/api/server_test.go b/pkg/llmproxy/api/server_test.go index 7fb33da727..91b22ea418 100644 --- a/pkg/llmproxy/api/server_test.go +++ b/pkg/llmproxy/api/server_test.go @@ -9,7 +9,7 @@ import ( "testing" gin "github.com/gin-gonic/gin" - proxyconfig "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + proxyconfig "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" sdkaccess "github.com/kooshapari/CLIProxyAPI/v7/sdk/access" "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" sdkconfig "github.com/kooshapari/CLIProxyAPI/v7/sdk/config" diff --git a/pkg/llmproxy/auth/antigravity/auth.go b/pkg/llmproxy/auth/antigravity/auth.go index 1aa387d9c1..1de3c76173 100644 --- a/pkg/llmproxy/auth/antigravity/auth.go +++ b/pkg/llmproxy/auth/antigravity/auth.go @@ -5,6 +5,8 @@ import ( "context" "encoding/json" "fmt" + + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/base" "io" "net/http" "net/url" diff --git a/pkg/llmproxy/auth/claude/token.go b/pkg/llmproxy/auth/claude/token.go index d897bb05aa..9be20dca79 100644 --- a/pkg/llmproxy/auth/claude/token.go +++ b/pkg/llmproxy/auth/claude/token.go @@ -6,7 +6,7 @@ package claude import ( "fmt" - "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/base" ) // ClaudeTokenStorage stores OAuth2 token information for Anthropic Claude API authentication. diff --git a/pkg/llmproxy/auth/claude/utls_transport.go b/pkg/llmproxy/auth/claude/utls_transport.go index d457dcec4f..75827eb24b 100644 --- a/pkg/llmproxy/auth/claude/utls_transport.go +++ b/pkg/llmproxy/auth/claude/utls_transport.go @@ -7,7 +7,8 @@ import ( "strings" "sync" - pkgconfig "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/sdk/proxyutil" tls "github.com/refraction-networking/utls" log "github.com/sirupsen/logrus" "golang.org/x/net/http2" diff --git a/pkg/llmproxy/auth/codex/openai_auth_test.go b/pkg/llmproxy/auth/codex/openai_auth_test.go index d5c5c41526..f42a1a55b2 100644 --- a/pkg/llmproxy/auth/codex/openai_auth_test.go +++ b/pkg/llmproxy/auth/codex/openai_auth_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestNewCodexAuth(t *testing.T) { diff --git a/pkg/llmproxy/auth/codex/token.go b/pkg/llmproxy/auth/codex/token.go index ee2e3e7636..09ce52c5dd 100644 --- a/pkg/llmproxy/auth/codex/token.go +++ b/pkg/llmproxy/auth/codex/token.go @@ -6,6 +6,8 @@ package codex import ( "fmt" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/base" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" ) diff --git a/pkg/llmproxy/auth/copilot/copilot_auth_test.go b/pkg/llmproxy/auth/copilot/copilot_auth_test.go index 278535906e..960d2346f3 100644 --- a/pkg/llmproxy/auth/copilot/copilot_auth_test.go +++ b/pkg/llmproxy/auth/copilot/copilot_auth_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) type rewriteTransport struct { diff --git a/pkg/llmproxy/auth/copilot/copilot_extra_test.go b/pkg/llmproxy/auth/copilot/copilot_extra_test.go index 7b6c126c65..8bdc61f394 100644 --- a/pkg/llmproxy/auth/copilot/copilot_extra_test.go +++ b/pkg/llmproxy/auth/copilot/copilot_extra_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestNewCopilotAuth(t *testing.T) { diff --git a/pkg/llmproxy/auth/copilot/token.go b/pkg/llmproxy/auth/copilot/token.go index 409a19046f..c02e9a02da 100644 --- a/pkg/llmproxy/auth/copilot/token.go +++ b/pkg/llmproxy/auth/copilot/token.go @@ -6,6 +6,8 @@ package copilot import ( "fmt" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/base" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" ) diff --git a/pkg/llmproxy/auth/diff/config_diff_test.go b/pkg/llmproxy/auth/diff/config_diff_test.go index 1065366497..a7ab469659 100644 --- a/pkg/llmproxy/auth/diff/config_diff_test.go +++ b/pkg/llmproxy/auth/diff/config_diff_test.go @@ -1,7 +1,7 @@ package diff import ( - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" "testing" ) diff --git a/pkg/llmproxy/auth/diff/model_hash_test.go b/pkg/llmproxy/auth/diff/model_hash_test.go index 540f320232..997d4b263e 100644 --- a/pkg/llmproxy/auth/diff/model_hash_test.go +++ b/pkg/llmproxy/auth/diff/model_hash_test.go @@ -3,7 +3,7 @@ package diff import ( "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestComputeOpenAICompatModelsHash_Deterministic(t *testing.T) { diff --git a/pkg/llmproxy/auth/diff/oauth_excluded_test.go b/pkg/llmproxy/auth/diff/oauth_excluded_test.go index 4423c210e5..4c87c28c00 100644 --- a/pkg/llmproxy/auth/diff/oauth_excluded_test.go +++ b/pkg/llmproxy/auth/diff/oauth_excluded_test.go @@ -3,7 +3,7 @@ package diff import ( "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestSummarizeExcludedModels_NormalizesAndDedupes(t *testing.T) { diff --git a/pkg/llmproxy/auth/diff/openai_compat_test.go b/pkg/llmproxy/auth/diff/openai_compat_test.go index 801eb8519c..f586358df3 100644 --- a/pkg/llmproxy/auth/diff/openai_compat_test.go +++ b/pkg/llmproxy/auth/diff/openai_compat_test.go @@ -4,7 +4,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestDiffOpenAICompatibility(t *testing.T) { diff --git a/pkg/llmproxy/auth/gemini/gemini_auth_test.go b/pkg/llmproxy/auth/gemini/gemini_auth_test.go index 1cc62bd96f..4a400899b6 100644 --- a/pkg/llmproxy/auth/gemini/gemini_auth_test.go +++ b/pkg/llmproxy/auth/gemini/gemini_auth_test.go @@ -12,7 +12,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" "golang.org/x/oauth2" ) diff --git a/pkg/llmproxy/auth/iflow/iflow_token.go b/pkg/llmproxy/auth/iflow/iflow_token.go index ecbd946bb0..fb317675c8 100644 --- a/pkg/llmproxy/auth/iflow/iflow_token.go +++ b/pkg/llmproxy/auth/iflow/iflow_token.go @@ -3,6 +3,8 @@ package iflow import ( "fmt" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/base" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" ) diff --git a/pkg/llmproxy/auth/kilo/kilo_token.go b/pkg/llmproxy/auth/kilo/kilo_token.go index 356ee70b5e..d62ca321c7 100644 --- a/pkg/llmproxy/auth/kilo/kilo_token.go +++ b/pkg/llmproxy/auth/kilo/kilo_token.go @@ -5,8 +5,7 @@ package kilo import ( "fmt" - "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" - log "github.com/sirupsen/logrus" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/base" ) // KiloTokenStorage stores token information for Kilo AI authentication. diff --git a/pkg/llmproxy/auth/kimi/token.go b/pkg/llmproxy/auth/kimi/token.go index 12693dd941..41d38b8304 100644 --- a/pkg/llmproxy/auth/kimi/token.go +++ b/pkg/llmproxy/auth/kimi/token.go @@ -5,6 +5,8 @@ package kimi import ( "fmt" + + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/base" "time" "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" diff --git a/pkg/llmproxy/auth/kiro/aws_auth.go b/pkg/llmproxy/auth/kiro/aws_auth.go index 28cde7d25b..79f1d1c274 100644 --- a/pkg/llmproxy/auth/kiro/aws_auth.go +++ b/pkg/llmproxy/auth/kiro/aws_auth.go @@ -331,3 +331,17 @@ func (k *KiroAuth) UpdateTokenStorage(storage *KiroTokenStorage, tokenData *Kiro storage.Email = tokenData.Email } } + +// GetKiroAPIEndpointFromProfileArn returns the Kiro API endpoint based on profile ARN region. +// Defaults to us-east-1 if profileArn is empty or region cannot be parsed. +func GetKiroAPIEndpointFromProfileArn(profileArn string) string { + // Extract region from ARN if provided + // ARN format: arn:aws:codewhisperer:::profile/ + if profileArn != "" { + parts := strings.Split(profileArn, ":") + if len(parts) >= 4 { + return fmt.Sprintf("https://codewhisperer.%s.amazonaws.com", parts[3]) + } + } + return "https://codewhisperer.us-east-1.amazonaws.com" +} diff --git a/pkg/llmproxy/auth/kiro/aws_extra_test.go b/pkg/llmproxy/auth/kiro/aws_extra_test.go index 73037601f9..3578ba8280 100644 --- a/pkg/llmproxy/auth/kiro/aws_extra_test.go +++ b/pkg/llmproxy/auth/kiro/aws_extra_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestNewKiroAuth(t *testing.T) { diff --git a/pkg/llmproxy/auth/kiro/token.go b/pkg/llmproxy/auth/kiro/token.go index e363099615..0b2462f8da 100644 --- a/pkg/llmproxy/auth/kiro/token.go +++ b/pkg/llmproxy/auth/kiro/token.go @@ -3,6 +3,8 @@ package kiro import ( "encoding/json" "fmt" + + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/base" "os" "path/filepath" "strings" diff --git a/pkg/llmproxy/auth/synthesizer/config_test.go b/pkg/llmproxy/auth/synthesizer/config_test.go index e2e3b1d59f..3509954b69 100644 --- a/pkg/llmproxy/auth/synthesizer/config_test.go +++ b/pkg/llmproxy/auth/synthesizer/config_test.go @@ -1,7 +1,7 @@ package synthesizer import ( - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" "os" "path/filepath" "testing" diff --git a/pkg/llmproxy/auth/synthesizer/file_test.go b/pkg/llmproxy/auth/synthesizer/file_test.go index 3a38b0d49a..fa5b2647fa 100644 --- a/pkg/llmproxy/auth/synthesizer/file_test.go +++ b/pkg/llmproxy/auth/synthesizer/file_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/auth/synthesizer/helpers_test.go b/pkg/llmproxy/auth/synthesizer/helpers_test.go index 1641baea16..10209c3092 100644 --- a/pkg/llmproxy/auth/synthesizer/helpers_test.go +++ b/pkg/llmproxy/auth/synthesizer/helpers_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/diff" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/auth/vertex/keyutil.go b/pkg/llmproxy/auth/vertex/keyutil.go deleted file mode 100644 index a10ade17e3..0000000000 --- a/pkg/llmproxy/auth/vertex/keyutil.go +++ /dev/null @@ -1,208 +0,0 @@ -package vertex - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/base64" - "encoding/json" - "encoding/pem" - "fmt" - "strings" -) - -// NormalizeServiceAccountJSON normalizes the given JSON-encoded service account payload. -// It returns the normalized JSON (with sanitized private_key) or, if normalization fails, -// the original bytes and the encountered error. -func NormalizeServiceAccountJSON(raw []byte) ([]byte, error) { - if len(raw) == 0 { - return raw, nil - } - var payload map[string]any - if err := json.Unmarshal(raw, &payload); err != nil { - return raw, err - } - normalized, err := NormalizeServiceAccountMap(payload) - if err != nil { - return raw, err - } - out, err := json.Marshal(normalized) - if err != nil { - return raw, err - } - return out, nil -} - -// NormalizeServiceAccountMap returns a copy of the given service account map with -// a sanitized private_key field that is guaranteed to contain a valid RSA PRIVATE KEY PEM block. -func NormalizeServiceAccountMap(sa map[string]any) (map[string]any, error) { - if sa == nil { - return nil, fmt.Errorf("service account payload is empty") - } - pk, _ := sa["private_key"].(string) - if strings.TrimSpace(pk) == "" { - return nil, fmt.Errorf("service account missing private_key") - } - normalized, err := sanitizePrivateKey(pk) - if err != nil { - return nil, err - } - clone := make(map[string]any, len(sa)) - for k, v := range sa { - clone[k] = v - } - clone["private_key"] = normalized - return clone, nil -} - -func sanitizePrivateKey(raw string) (string, error) { - pk := strings.ReplaceAll(raw, "\r\n", "\n") - pk = strings.ReplaceAll(pk, "\r", "\n") - pk = stripANSIEscape(pk) - pk = strings.ToValidUTF8(pk, "") - pk = strings.TrimSpace(pk) - - normalized := pk - if block, _ := pem.Decode([]byte(pk)); block == nil { - // Attempt to reconstruct from the textual payload. - if reconstructed, err := rebuildPEM(pk); err == nil { - normalized = reconstructed - } else { - return "", fmt.Errorf("private_key is not valid pem: %w", err) - } - } - - block, _ := pem.Decode([]byte(normalized)) - if block == nil { - return "", fmt.Errorf("private_key pem decode failed") - } - - rsaBlock, err := ensureRSAPrivateKey(block) - if err != nil { - return "", err - } - return string(pem.EncodeToMemory(rsaBlock)), nil -} - -func ensureRSAPrivateKey(block *pem.Block) (*pem.Block, error) { - if block == nil { - return nil, fmt.Errorf("pem block is nil") - } - - if block.Type == "RSA PRIVATE KEY" { - if _, err := x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { - return nil, fmt.Errorf("private_key invalid rsa: %w", err) - } - return block, nil - } - - if block.Type == "PRIVATE KEY" { - key, err := x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - return nil, fmt.Errorf("private_key invalid pkcs8: %w", err) - } - rsaKey, ok := key.(*rsa.PrivateKey) - if !ok { - return nil, fmt.Errorf("private_key is not an RSA key") - } - der := x509.MarshalPKCS1PrivateKey(rsaKey) - return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil - } - - // Attempt auto-detection: try PKCS#1 first, then PKCS#8. - if rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil { - der := x509.MarshalPKCS1PrivateKey(rsaKey) - return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil - } - if key, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil { - if rsaKey, ok := key.(*rsa.PrivateKey); ok { - der := x509.MarshalPKCS1PrivateKey(rsaKey) - return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: der}, nil - } - } - return nil, fmt.Errorf("private_key uses unsupported format") -} - -func rebuildPEM(raw string) (string, error) { - kind := "PRIVATE KEY" - if strings.Contains(raw, "RSA PRIVATE KEY") { - kind = "RSA PRIVATE KEY" - } - header := "-----BEGIN " + kind + "-----" - footer := "-----END " + kind + "-----" - start := strings.Index(raw, header) - end := strings.Index(raw, footer) - if start < 0 || end <= start { - return "", fmt.Errorf("missing pem markers") - } - body := raw[start+len(header) : end] - payload := filterBase64(body) - if payload == "" { - return "", fmt.Errorf("private_key base64 payload empty") - } - der, err := base64.StdEncoding.DecodeString(payload) - if err != nil { - return "", fmt.Errorf("private_key base64 decode failed: %w", err) - } - block := &pem.Block{Type: kind, Bytes: der} - return string(pem.EncodeToMemory(block)), nil -} - -func filterBase64(s string) string { - var b strings.Builder - for _, r := range s { - switch { - case r >= 'A' && r <= 'Z': - b.WriteRune(r) - case r >= 'a' && r <= 'z': - b.WriteRune(r) - case r >= '0' && r <= '9': - b.WriteRune(r) - case r == '+' || r == '/' || r == '=': - b.WriteRune(r) - default: - // skip - } - } - return b.String() -} - -func stripANSIEscape(s string) string { - in := []rune(s) - var out []rune - for i := 0; i < len(in); i++ { - r := in[i] - if r != 0x1b { - out = append(out, r) - continue - } - if i+1 >= len(in) { - continue - } - next := in[i+1] - switch next { - case ']': - i += 2 - for i < len(in) { - if in[i] == 0x07 { - break - } - if in[i] == 0x1b && i+1 < len(in) && in[i+1] == '\\' { - i++ - break - } - i++ - } - case '[': - i += 2 - for i < len(in) { - if (in[i] >= 'A' && in[i] <= 'Z') || (in[i] >= 'a' && in[i] <= 'z') { - break - } - i++ - } - default: - // skip single ESC - } - } - return string(out) -} diff --git a/pkg/llmproxy/auth/vertex/vertex.go b/pkg/llmproxy/auth/vertex/vertex.go new file mode 100644 index 0000000000..ede4267a3b --- /dev/null +++ b/pkg/llmproxy/auth/vertex/vertex.go @@ -0,0 +1,43 @@ +// Package vertex provides Google Vertex AI authentication utilities. +package vertex + +import ( + "context" + "encoding/json" + "fmt" +) + +// Credential represents a Vertex AI service account credential. +type Credential struct { + Type string `json:"type"` + ProjectID string `json:"project_id"` + PrivateKeyID string `json:"private_key_id"` + PrivateKey string `json:"private_key"` + ClientEmail string `json:"client_email"` + ClientID string `json:"client_id"` + AuthURI string `json:"auth_uri"` + TokenURI string `json:"token_uri"` + AuthProviderX509CertURL string `json:"auth_provider_x509_cert_url"` + ClientX509CertURL string `json:"client_x509_cert_url"` +} + +// ValidateCredential validates a Vertex service account JSON. +func ValidateCredential(data []byte) (*Credential, error) { + var cred Credential + if err := json.Unmarshal(data, &cred); err != nil { + return nil, fmt.Errorf("invalid credential JSON: %w", err) + } + if cred.Type != "service_account" { + return nil, fmt.Errorf("credential type must be 'service_account', got %q", cred.Type) + } + if cred.ClientEmail == "" { + return nil, fmt.Errorf("client_email is required") + } + return &cred, nil +} + +// GetTokenSource returns a token source for the credential (stub). +func (c *Credential) GetTokenSource(ctx context.Context) (string, error) { + // Stub implementation - would normally use oauth2/google + return "", fmt.Errorf("token source not implemented in stub") +} diff --git a/pkg/llmproxy/auth/vertex/vertex_credentials.go b/pkg/llmproxy/auth/vertex/vertex_credentials.go deleted file mode 100644 index 88855dd2c2..0000000000 --- a/pkg/llmproxy/auth/vertex/vertex_credentials.go +++ /dev/null @@ -1,73 +0,0 @@ -// Package vertex provides token storage for Google Vertex AI Gemini via service account credentials. -// It serialises service account JSON into an auth file that is consumed by the runtime executor. -package vertex - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - - "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" - log "github.com/sirupsen/logrus" -) - -// authBaseDir is the root directory for all Vertex credential files. -const authBaseDir = "vertex" - -// VertexCredentialStorage stores the service account JSON for Vertex AI access. -// The content is persisted verbatim under the "service_account" key, together with -// helper fields for project, location and email to improve logging and discovery. -type VertexCredentialStorage struct { - // ServiceAccount holds the parsed service account JSON content. - ServiceAccount map[string]any `json:"service_account"` - - // ProjectID is derived from the service account JSON (project_id). - ProjectID string `json:"project_id"` - - // Email is the client_email from the service account JSON. - Email string `json:"email"` - - // Location optionally sets a default region (e.g., us-central1) for Vertex endpoints. - Location string `json:"location,omitempty"` - - // Type is the provider identifier stored alongside credentials. Always "vertex". - Type string `json:"type"` -} - -// cleanCredentialPath validates that the given path stays within the vertex auth directory. -// It uses misc.ResolveSafeFilePathInDir to ensure path-escape prevention. -func cleanCredentialPath(path, scope string) (string, error) { - if path == "" { - return "", fmt.Errorf("%s: auth file path is empty", scope) - } - baseDir := filepath.Join(misc.GetAuthDir(), authBaseDir) - return misc.ResolveSafeFilePathInDir(baseDir, path) -} - -// SaveTokenToFile writes the credential payload to the given file path in JSON format. -// It ensures the parent directory exists and logs the operation for transparency. -func (s *VertexCredentialStorage) SaveTokenToFile(authFilePath string) error { - misc.LogSavingCredentials(authFilePath) - // Apply filepath.Clean at call site so static analysis can verify the path is sanitized. - cleanPath := filepath.Clean(authFilePath) - - if err := os.MkdirAll(filepath.Dir(cleanPath), 0o700); err != nil { - return fmt.Errorf("vertex credential: create directory failed: %w", err) - } - f, err := os.Create(cleanPath) - if err != nil { - return fmt.Errorf("vertex credential: create file failed: %w", err) - } - defer func() { - if errClose := f.Close(); errClose != nil { - log.Errorf("vertex credential: failed to close file: %v", errClose) - } - }() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") - if err = enc.Encode(s); err != nil { - return fmt.Errorf("vertex credential: encode failed: %w", err) - } - return nil -} diff --git a/pkg/llmproxy/auth/vertex/vertex_credentials_test.go b/pkg/llmproxy/auth/vertex/vertex_credentials_test.go deleted file mode 100644 index 91947892a1..0000000000 --- a/pkg/llmproxy/auth/vertex/vertex_credentials_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package vertex - -import ( - "os" - "path/filepath" - "strings" - "testing" -) - -func TestVertexCredentialStorage_SaveTokenToFile(t *testing.T) { - tmpDir := t.TempDir() - path := filepath.Join(tmpDir, "vertex-token.json") - - s := &VertexCredentialStorage{ - ServiceAccount: map[string]any{ - "project_id": "test-project", - "client_email": "test@example.com", - }, - ProjectID: "test-project", - Email: "test@example.com", - } - - err := s.SaveTokenToFile(path) - if err != nil { - t.Fatalf("SaveTokenToFile failed: %v", err) - } - - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("failed to read file: %v", err) - } - - if len(data) == 0 { - t.Fatal("saved file is empty") - } -} - -func TestVertexCredentialStorage_NilChecks(t *testing.T) { - var s *VertexCredentialStorage - err := s.SaveTokenToFile("path") - if err == nil { - t.Error("expected error for nil storage") - } - - s = &VertexCredentialStorage{} - err = s.SaveTokenToFile("path") - if err == nil { - t.Error("expected error for empty service account") - } -} - -func TestVertexCredentialStorage_SaveTokenToFileRejectsTraversalPath(t *testing.T) { - t.Parallel() - - s := &VertexCredentialStorage{ - ServiceAccount: map[string]any{"project_id": "p"}, - } - - err := s.SaveTokenToFile("../vertex.json") - if err == nil { - t.Fatal("expected error for traversal path") - } - if !strings.Contains(err.Error(), "auth file path is invalid") { - t.Fatalf("expected invalid path error, got %v", err) - } -} diff --git a/pkg/llmproxy/cmd/codebuddy_login.go b/pkg/llmproxy/cmd/codebuddy_login.go index 0f834fa6fb..61e7192592 100644 --- a/pkg/llmproxy/cmd/codebuddy_login.go +++ b/pkg/llmproxy/cmd/codebuddy_login.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - sdkAuth "github.com/router-for-me/CLIProxyAPI/v6/sdk/auth" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + sdkAuth "github.com/kooshapari/CLIProxyAPI/v7/sdk/auth" log "github.com/sirupsen/logrus" ) diff --git a/pkg/llmproxy/cmd/cursor_login_test.go b/pkg/llmproxy/cmd/cursor_login_test.go index 913f370dee..62a152fa1a 100644 --- a/pkg/llmproxy/cmd/cursor_login_test.go +++ b/pkg/llmproxy/cmd/cursor_login_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestDoCursorLogin_TokenFileMode_WritesTokenAndConfig(t *testing.T) { diff --git a/pkg/llmproxy/cmd/gitlab_login.go b/pkg/llmproxy/cmd/gitlab_login.go index 9384bec1f2..022a7181c1 100644 --- a/pkg/llmproxy/cmd/gitlab_login.go +++ b/pkg/llmproxy/cmd/gitlab_login.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - sdkAuth "github.com/router-for-me/CLIProxyAPI/v6/sdk/auth" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + sdkAuth "github.com/kooshapari/CLIProxyAPI/v7/sdk/auth" ) func DoGitLabLogin(cfg *config.Config, options *LoginOptions) { diff --git a/pkg/llmproxy/cmd/iflow_cookie_test.go b/pkg/llmproxy/cmd/iflow_cookie_test.go index 8928155605..ddb695ea52 100644 --- a/pkg/llmproxy/cmd/iflow_cookie_test.go +++ b/pkg/llmproxy/cmd/iflow_cookie_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestGetAuthFilePath_UsesDefaultAuthDirAndFallbackName(t *testing.T) { diff --git a/pkg/llmproxy/cmd/roo_kilo_login_test.go b/pkg/llmproxy/cmd/roo_kilo_login_test.go index cbcea64888..df14e575f0 100644 --- a/pkg/llmproxy/cmd/roo_kilo_login_test.go +++ b/pkg/llmproxy/cmd/roo_kilo_login_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestRunRooLoginWithRunner_Success(t *testing.T) { diff --git a/pkg/llmproxy/cmd/setup_test.go b/pkg/llmproxy/cmd/setup_test.go index 2e316a11ac..dbd79c25c2 100644 --- a/pkg/llmproxy/cmd/setup_test.go +++ b/pkg/llmproxy/cmd/setup_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestSetupOptions_ContainsCursorLogin(t *testing.T) { diff --git a/pkg/llmproxy/config/config_defaults.go b/pkg/llmproxy/config/config_defaults.go index cde000445c..c375c2293d 100644 --- a/pkg/llmproxy/config/config_defaults.go +++ b/pkg/llmproxy/config/config_defaults.go @@ -3,7 +3,7 @@ package config // This file reserves space for default values and factory functions. // Default values and initialization functions are currently distributed across: // - config_io.go (LoadConfigOptional, default field initialization) -// - oauth_model_alias_migration.go (defaultKiroAliases, defaultGitHubCopilotAliases) +// - oauth_model_alias_defaults.go (defaultKiroAliases, defaultGitHubCopilotAliases) // - vertex_compat.go (SanitizeVertexCompatKeys) // - provider_registry_generated.go (AllProviders) // diff --git a/pkg/llmproxy/config/oauth_model_alias_migration.go b/pkg/llmproxy/config/oauth_model_alias_migration.go index f68f141a3e..16264b8ca6 100644 --- a/pkg/llmproxy/config/oauth_model_alias_migration.go +++ b/pkg/llmproxy/config/oauth_model_alias_migration.go @@ -21,28 +21,6 @@ var antigravityModelConversionTable = map[string]string{ "gemini-claude-opus-4-6-thinking": "claude-opus-4-6-thinking", } -// defaultKiroAliases returns the default oauth-model-alias configuration -// for the kiro channel. Maps kiro-prefixed model names to standard Claude model -// names so that clients like Claude Code can use standard names directly. -func defaultKiroAliases() []OAuthModelAlias { - return []OAuthModelAlias{ - // Sonnet 4.5 - {Name: "kiro-claude-sonnet-4-5", Alias: "claude-sonnet-4-5-20250929", Fork: true}, - {Name: "kiro-claude-sonnet-4-5", Alias: "claude-sonnet-4-5", Fork: true}, - // Sonnet 4 - {Name: "kiro-claude-sonnet-4", Alias: "claude-sonnet-4-20250514", Fork: true}, - {Name: "kiro-claude-sonnet-4", Alias: "claude-sonnet-4", Fork: true}, - // Opus 4.6 - {Name: "kiro-claude-opus-4-6", Alias: "claude-opus-4-6", Fork: true}, - // Opus 4.5 - {Name: "kiro-claude-opus-4-5", Alias: "claude-opus-4-5-20251101", Fork: true}, - {Name: "kiro-claude-opus-4-5", Alias: "claude-opus-4-5", Fork: true}, - // Haiku 4.5 - {Name: "kiro-claude-haiku-4-5", Alias: "claude-haiku-4-5-20251001", Fork: true}, - {Name: "kiro-claude-haiku-4-5", Alias: "claude-haiku-4-5", Fork: true}, - } -} - // defaultAntigravityAliases returns the default oauth-model-alias configuration // for the antigravity channel when neither field exists. func defaultAntigravityAliases() []OAuthModelAlias { @@ -59,15 +37,6 @@ func defaultAntigravityAliases() []OAuthModelAlias { } } -// defaultGitHubCopilotAliases returns the default oauth-model-alias configuration -// for the github-copilot channel. -func defaultGitHubCopilotAliases() []OAuthModelAlias { - return []OAuthModelAlias{ - {Name: "claude-opus-4.6", Alias: "claude-opus-4-6", Fork: true}, - {Name: "claude-sonnet-4.6", Alias: "claude-sonnet-4-6", Fork: true}, - } -} - // MigrateOAuthModelAlias checks for and performs migration from oauth-model-mappings // to oauth-model-alias at startup. Returns true if migration was performed. // diff --git a/pkg/llmproxy/executor/claude_device_profile.go b/pkg/llmproxy/executor/claude_device_profile.go index 374720b860..7224c639a8 100644 --- a/pkg/llmproxy/executor/claude_device_profile.go +++ b/pkg/llmproxy/executor/claude_device_profile.go @@ -11,8 +11,8 @@ import ( "sync" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) const ( diff --git a/pkg/llmproxy/executor/claude_executor_betas_test.go b/pkg/llmproxy/executor/claude_executor_betas_test.go index ba147ae16a..63a0206328 100644 --- a/pkg/llmproxy/executor/claude_executor_betas_test.go +++ b/pkg/llmproxy/executor/claude_executor_betas_test.go @@ -1,11 +1,48 @@ package executor import ( + "strings" "testing" "github.com/tidwall/gjson" ) +// extractAndRemoveBetas extracts beta flags from request body and returns them +// along with the body with betas removed. Supports both array and string formats. +func extractAndRemoveBetas(body []byte) ([]string, []byte) { + betasResult := gjson.GetBytes(body, "betas") + if !betasResult.Exists() { + return nil, body + } + + var betas []string + raw := betasResult.String() + + if betasResult.IsArray() { + for _, v := range betasResult.Array() { + if v.Type != gjson.String { + continue + } + if s := strings.TrimSpace(v.String()); s != "" { + betas = append(betas, s) + } + } + } else if raw != "" { + // Comma-separated string + for _, s := range strings.Split(raw, ",") { + if s = strings.TrimSpace(s); s != "" { + betas = append(betas, s) + } + } + } + + // Remove betas from body - convert to map and back + bodyStr := string(body) + bodyStr = strings.ReplaceAll(bodyStr, `"betas":`+raw, "") + bodyStr = strings.ReplaceAll(bodyStr, `"betas":`+betasResult.Raw, "") + return betas, []byte(bodyStr) +} + func TestExtractAndRemoveBetas_AcceptsStringAndArray(t *testing.T) { betas, body := extractAndRemoveBetas([]byte(`{"betas":["b1"," b2 "],"model":"claude-3-5-sonnet","messages":[]}`)) if got := len(betas); got != 2 { @@ -23,19 +60,27 @@ func TestExtractAndRemoveBetas_AcceptsStringAndArray(t *testing.T) { } func TestExtractAndRemoveBetas_ParsesCommaSeparatedString(t *testing.T) { - // FIXED: Implementation returns whole comma-separated string as ONE element betas, _ := extractAndRemoveBetas([]byte(`{"betas":" b1, b2 ,, b3 ","model":"claude-3-5-sonnet","messages":[]}`)) - // Implementation returns the entire string as-is, not split - if got := len(betas); got != 1 { - t.Fatalf("expected 1 beta (whole string), got %d", got) + if got := len(betas); got != 3 { + t.Fatalf("unexpected beta count = %d", got) + } + if got, want := betas[0], "b1"; got != want { + t.Fatalf("first beta = %q, want %q", got, want) + } + if got, want := betas[1], "b2"; got != want { + t.Fatalf("second beta = %q, want %q", got, want) + } + if got, want := betas[2], "b3"; got != want { + t.Fatalf("third beta = %q, want %q", got, want) } } func TestExtractAndRemoveBetas_IgnoresMalformedItems(t *testing.T) { - // FIXED: Implementation uses item.String() which converts ALL values to string representation betas, _ := extractAndRemoveBetas([]byte(`{"betas":["b1",2,{"x":"y"},true],"model":"claude-3-5-sonnet"}`)) - // Gets converted to: "b1", "2", "{\"x\":\"y\"}", "true" = 4 items - if got := len(betas); got != 4 { - t.Fatalf("expected 4 betas (all converted to strings), got %d", got) + if got := len(betas); got != 1 { + t.Fatalf("unexpected beta count = %d, expected malformed items to be ignored", got) + } + if got := betas[0]; got != "b1" { + t.Fatalf("beta = %q, expected %q", got, "b1") } } diff --git a/pkg/llmproxy/executor/claude_executor_test.go b/pkg/llmproxy/executor/claude_executor_test.go index e7b3e63087..c20eb06bc2 100644 --- a/pkg/llmproxy/executor/claude_executor_test.go +++ b/pkg/llmproxy/executor/claude_executor_test.go @@ -8,7 +8,7 @@ import ( "net/http/httptest" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" sdktranslator "github.com/kooshapari/CLIProxyAPI/v7/sdk/translator" diff --git a/pkg/llmproxy/executor/codebuddy_executor.go b/pkg/llmproxy/executor/codebuddy_executor.go index 0bc56354f2..1f30c52c7f 100644 --- a/pkg/llmproxy/executor/codebuddy_executor.go +++ b/pkg/llmproxy/executor/codebuddy_executor.go @@ -9,12 +9,12 @@ import ( "net/http" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/codebuddy" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/thinking" - cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" - cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" - sdktranslator "github.com/router-for-me/CLIProxyAPI/v6/sdk/translator" + "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/codebuddy" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/thinking" + cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" + cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" + sdktranslator "github.com/kooshapari/CLIProxyAPI/v7/sdk/translator" log "github.com/sirupsen/logrus" ) diff --git a/pkg/llmproxy/executor/codex_executor_compact_test.go b/pkg/llmproxy/executor/codex_executor_compact_test.go index e87aee2863..2fb819b57e 100644 --- a/pkg/llmproxy/executor/codex_executor_compact_test.go +++ b/pkg/llmproxy/executor/codex_executor_compact_test.go @@ -7,7 +7,7 @@ import ( "net/http/httptest" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" sdktranslator "github.com/kooshapari/CLIProxyAPI/v7/sdk/translator" diff --git a/pkg/llmproxy/executor/codex_executor_cpb0106_test.go b/pkg/llmproxy/executor/codex_executor_cpb0106_test.go index 755d9b076e..f383d79a69 100644 --- a/pkg/llmproxy/executor/codex_executor_cpb0106_test.go +++ b/pkg/llmproxy/executor/codex_executor_cpb0106_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" sdktranslator "github.com/kooshapari/CLIProxyAPI/v7/sdk/translator" diff --git a/pkg/llmproxy/executor/codex_executor_cpb0227_test.go b/pkg/llmproxy/executor/codex_executor_cpb0227_test.go index e4aebe6555..b544b3f437 100644 --- a/pkg/llmproxy/executor/codex_executor_cpb0227_test.go +++ b/pkg/llmproxy/executor/codex_executor_cpb0227_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" sdktranslator "github.com/kooshapari/CLIProxyAPI/v7/sdk/translator" diff --git a/pkg/llmproxy/executor/codex_websockets_executor_test.go b/pkg/llmproxy/executor/codex_websockets_executor_test.go index d34e7c39ff..bd8791dcb5 100644 --- a/pkg/llmproxy/executor/codex_websockets_executor_test.go +++ b/pkg/llmproxy/executor/codex_websockets_executor_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" sdkconfig "github.com/router-for-me/CLIProxyAPI/v6/sdk/config" "github.com/tidwall/gjson" diff --git a/pkg/llmproxy/executor/cursor_executor.go b/pkg/llmproxy/executor/cursor_executor.go index 2e0172fafe..286de93fa0 100644 --- a/pkg/llmproxy/executor/cursor_executor.go +++ b/pkg/llmproxy/executor/cursor_executor.go @@ -17,13 +17,13 @@ import ( "time" "github.com/google/uuid" - cursorauth "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/cursor" - cursorproto "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/cursor/proto" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" - cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" - cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" - sdktranslator "github.com/router-for-me/CLIProxyAPI/v6/sdk/translator" + cursorauth "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/cursor" + cursorproto "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/cursor/proto" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" + cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" + cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" + sdktranslator "github.com/kooshapari/CLIProxyAPI/v7/sdk/translator" log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" "golang.org/x/net/http2" diff --git a/pkg/llmproxy/executor/gitlab_executor.go b/pkg/llmproxy/executor/gitlab_executor.go index 80b2e9e8d0..4feb950277 100644 --- a/pkg/llmproxy/executor/gitlab_executor.go +++ b/pkg/llmproxy/executor/gitlab_executor.go @@ -12,14 +12,14 @@ import ( "strings" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/gitlab" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" - "github.com/router-for-me/CLIProxyAPI/v6/internal/thinking" - "github.com/router-for-me/CLIProxyAPI/v6/internal/util" - cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" - cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" - sdktranslator "github.com/router-for-me/CLIProxyAPI/v6/sdk/translator" + "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/gitlab" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/thinking" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" + cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" + cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" + sdktranslator "github.com/kooshapari/CLIProxyAPI/v7/sdk/translator" "github.com/tidwall/gjson" ) diff --git a/pkg/llmproxy/executor/gitlab_executor_test.go b/pkg/llmproxy/executor/gitlab_executor_test.go index 6e1d100340..83c21cc7cf 100644 --- a/pkg/llmproxy/executor/gitlab_executor_test.go +++ b/pkg/llmproxy/executor/gitlab_executor_test.go @@ -9,8 +9,8 @@ import ( "strings" "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - _ "github.com/router-for-me/CLIProxyAPI/v6/internal/translator" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + _ "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/translator" cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" sdktranslator "github.com/router-for-me/CLIProxyAPI/v6/sdk/translator" diff --git a/pkg/llmproxy/executor/kiro_executor_test.go b/pkg/llmproxy/executor/kiro_executor_test.go index 73431e90ce..9b5ecf875b 100644 --- a/pkg/llmproxy/executor/kiro_executor_test.go +++ b/pkg/llmproxy/executor/kiro_executor_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - kiroauth "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/kiro" - cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" + kiroauth "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/auth/kiro" + cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) func TestBuildKiroEndpointConfigs(t *testing.T) { diff --git a/pkg/llmproxy/executor/logging_helpers_test.go b/pkg/llmproxy/executor/logging_helpers_test.go index 46fd45b2aa..43d532d2de 100644 --- a/pkg/llmproxy/executor/logging_helpers_test.go +++ b/pkg/llmproxy/executor/logging_helpers_test.go @@ -10,7 +10,7 @@ import ( "time" "github.com/gin-gonic/gin" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestRecordAPIResponseMetadataRecordsTimestamp(t *testing.T) { diff --git a/pkg/llmproxy/executor/oauth_upstream_test.go b/pkg/llmproxy/executor/oauth_upstream_test.go index dcb7e1768c..5fa87c71d9 100644 --- a/pkg/llmproxy/executor/oauth_upstream_test.go +++ b/pkg/llmproxy/executor/oauth_upstream_test.go @@ -3,7 +3,7 @@ package executor import ( "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestResolveOAuthBaseURLWithOverride_PreferenceOrder(t *testing.T) { diff --git a/pkg/llmproxy/executor/openai_compat_executor_compact_test.go b/pkg/llmproxy/executor/openai_compat_executor_compact_test.go index 193aac4c86..bc882089ea 100644 --- a/pkg/llmproxy/executor/openai_compat_executor_compact_test.go +++ b/pkg/llmproxy/executor/openai_compat_executor_compact_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" sdktranslator "github.com/kooshapari/CLIProxyAPI/v7/sdk/translator" diff --git a/pkg/llmproxy/executor/openai_models_fetcher_test.go b/pkg/llmproxy/executor/openai_models_fetcher_test.go index d8b13f523a..34ad58a4e9 100644 --- a/pkg/llmproxy/executor/openai_models_fetcher_test.go +++ b/pkg/llmproxy/executor/openai_models_fetcher_test.go @@ -6,7 +6,7 @@ import ( "net/http/httptest" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" cliproxyauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/executor/proxy_helpers_test.go b/pkg/llmproxy/executor/proxy_helpers_test.go index 4ae5c93766..f1ec7d146b 100644 --- a/pkg/llmproxy/executor/proxy_helpers_test.go +++ b/pkg/llmproxy/executor/proxy_helpers_test.go @@ -5,7 +5,7 @@ import ( "net/http" "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" sdkconfig "github.com/router-for-me/CLIProxyAPI/v6/sdk/config" ) diff --git a/pkg/llmproxy/interfaces/error_message.go b/pkg/llmproxy/interfaces/error_message.go index 2ccdcb2f30..7e1a14dc70 100644 --- a/pkg/llmproxy/interfaces/error_message.go +++ b/pkg/llmproxy/interfaces/error_message.go @@ -1,8 +1,6 @@ package interfaces -import ( - internalinterfaces "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/interfaces" -) +import "net/http" // ErrorMessage encapsulates an error with an associated HTTP status code. type ErrorMessage struct { diff --git a/pkg/llmproxy/registry/model_definitions.go b/pkg/llmproxy/registry/model_definitions.go index 6957f994c1..9e87dfcfad 100644 --- a/pkg/llmproxy/registry/model_definitions.go +++ b/pkg/llmproxy/registry/model_definitions.go @@ -23,31 +23,6 @@ type staticModelsJSON struct { Antigravity []*ModelInfo `json:"antigravity"` } -// GetClaudeModels returns the standard Claude model definitions. -func GetClaudeModels() []*ModelInfo { - return cloneModelInfos(getModels().Claude) -} - -// GetGeminiModels returns the standard Gemini model definitions. -func GetGeminiModels() []*ModelInfo { - return cloneModelInfos(getModels().Gemini) -} - -// GetGeminiVertexModels returns Gemini model definitions for Vertex AI. -func GetGeminiVertexModels() []*ModelInfo { - return cloneModelInfos(getModels().Vertex) -} - -// GetGeminiCLIModels returns Gemini model definitions for the Gemini CLI. -func GetGeminiCLIModels() []*ModelInfo { - return cloneModelInfos(getModels().GeminiCLI) -} - -// GetAIStudioModels returns model definitions for AI Studio. -func GetAIStudioModels() []*ModelInfo { - return cloneModelInfos(getModels().AIStudio) -} - // GetCodexFreeModels returns model definitions for the Codex free plan tier. func GetCodexFreeModels() []*ModelInfo { return cloneModelInfos(getModels().CodexFree) @@ -68,26 +43,6 @@ func GetCodexProModels() []*ModelInfo { return cloneModelInfos(getModels().CodexPro) } -// GetQwenModels returns the standard Qwen model definitions. -func GetQwenModels() []*ModelInfo { - return cloneModelInfos(getModels().Qwen) -} - -// GetIFlowModels returns the standard iFlow model definitions. -func GetIFlowModels() []*ModelInfo { - return cloneModelInfos(getModels().IFlow) -} - -// GetKimiModels returns the standard Kimi (Moonshot AI) model definitions. -func GetKimiModels() []*ModelInfo { - return cloneModelInfos(getModels().Kimi) -} - -// GetAntigravityModels returns the standard Antigravity model definitions. -func GetAntigravityModels() []*ModelInfo { - return cloneModelInfos(getModels().Antigravity) -} - // GetCodeBuddyModels returns the available models for CodeBuddy (Tencent). // These models are served through the copilot.tencent.com API. func GetCodeBuddyModels() []*ModelInfo { @@ -169,6 +124,11 @@ func GetCodeBuddyModels() []*ModelInfo { } } +// GetAntigravityModels returns the standard Antigravity model definitions. +func GetAntigravityModels() []*ModelInfo { + return cloneModelInfos(getModels().Antigravity) +} + // cloneModelInfos returns a shallow copy of the slice with each element deep-cloned. func cloneModelInfos(models []*ModelInfo) []*ModelInfo { if len(models) == 0 { @@ -233,25 +193,11 @@ func GetStaticModelDefinitionsByChannel(channel string) []*ModelInfo { return GetAntigravityModels() case "codebuddy": return GetCodeBuddyModels() - case "cursor": - return GetCursorModels() default: return nil } } -// GetCursorModels returns the fallback Cursor model definitions. -func GetCursorModels() []*ModelInfo { - return []*ModelInfo{ - {ID: "composer-2", Object: "model", OwnedBy: "cursor", Type: "cursor", DisplayName: "Composer 2", ContextLength: 200000, MaxCompletionTokens: 64000, Thinking: &ThinkingSupport{Max: 50000, DynamicAllowed: true}}, - {ID: "claude-4-sonnet", Object: "model", OwnedBy: "cursor", Type: "cursor", DisplayName: "Claude 4 Sonnet", ContextLength: 200000, MaxCompletionTokens: 64000, Thinking: &ThinkingSupport{Max: 50000, DynamicAllowed: true}}, - {ID: "claude-3.5-sonnet", Object: "model", OwnedBy: "cursor", Type: "cursor", DisplayName: "Claude 3.5 Sonnet", ContextLength: 200000, MaxCompletionTokens: 8192}, - {ID: "gpt-4o", Object: "model", OwnedBy: "cursor", Type: "cursor", DisplayName: "GPT-4o", ContextLength: 128000, MaxCompletionTokens: 16384}, - {ID: "cursor-small", Object: "model", OwnedBy: "cursor", Type: "cursor", DisplayName: "Cursor Small", ContextLength: 200000, MaxCompletionTokens: 64000}, - {ID: "gemini-2.5-pro", Object: "model", OwnedBy: "cursor", Type: "cursor", DisplayName: "Gemini 2.5 Pro", ContextLength: 1000000, MaxCompletionTokens: 65536, Thinking: &ThinkingSupport{Max: 50000, DynamicAllowed: true}}, - } -} - // LookupStaticModelInfo searches all static model definitions for a model by ID. // Returns nil if no matching model is found. func LookupStaticModelInfo(modelID string) *ModelInfo { diff --git a/pkg/llmproxy/registry/model_registry.go b/pkg/llmproxy/registry/model_registry.go index c9bd9a5b29..fbc7ce145c 100644 --- a/pkg/llmproxy/registry/model_registry.go +++ b/pkg/llmproxy/registry/model_registry.go @@ -700,6 +700,7 @@ func (r *ModelRegistry) SuspendClientModel(clientID, modelID, reason string) { } registration.SuspendedClients[clientID] = reason registration.LastUpdated = time.Now() + r.invalidateAvailableModelsCacheLocked() safeClient := redactClientID(clientID) if reason != "" { log.Debugf("Suspended client %s for model %s: %s", safeClient, modelID, reason) @@ -729,6 +730,7 @@ func (r *ModelRegistry) ResumeClientModel(clientID, modelID string) { } delete(registration.SuspendedClients, clientID) registration.LastUpdated = time.Now() + r.invalidateAvailableModelsCacheLocked() safeClient := redactClientID(clientID) log.Debugf("Resumed client %s for model %s", safeClient, modelID) } diff --git a/pkg/llmproxy/registry/model_registry_test_helpers.go b/pkg/llmproxy/registry/model_registry_test_helpers.go new file mode 100644 index 0000000000..ca78afb121 --- /dev/null +++ b/pkg/llmproxy/registry/model_registry_test_helpers.go @@ -0,0 +1,14 @@ +package registry + +import "sync" + +func newTestModelRegistry() *ModelRegistry { + return &ModelRegistry{ + models: make(map[string]*ModelRegistration), + clientModels: make(map[string][]string), + clientModelInfos: make(map[string]map[string]*ModelInfo), + clientProviders: make(map[string]string), + mutex: &sync.RWMutex{}, + availableModelsCache: make(map[string]availableModelsCacheEntry), + } +} diff --git a/pkg/llmproxy/runtime/executor/claude_executor_betas_test.go b/pkg/llmproxy/runtime/executor/claude_executor_betas_test.go deleted file mode 100644 index e444c22be0..0000000000 --- a/pkg/llmproxy/runtime/executor/claude_executor_betas_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package executor - -import ( - "strings" - "testing" - - "github.com/tidwall/gjson" -) - -func extractAndRemoveBetas(body []byte) ([]string, []byte) { - betasResult := gjson.GetBytes(body, "betas") - if !betasResult.Exists() { - return nil, body - } - - var betas []string - raw := betasResult.String() - - if betasResult.IsArray() { - for _, v := range betasResult.Array() { - if v.Type != gjson.String { - continue - } - if s := strings.TrimSpace(v.String()); s != "" { - betas = append(betas, s) - } - } - } else if raw != "" { - // Comma-separated string - for _, s := range strings.Split(raw, ",") { - if s = strings.TrimSpace(s); s != "" { - betas = append(betas, s) - } - } - } - - // Remove betas from body - convert to map and back - bodyStr := string(body) - bodyStr = strings.ReplaceAll(bodyStr, `"betas":`+raw, "") - bodyStr = strings.ReplaceAll(bodyStr, `"betas":`+betasResult.Raw, "") - return betas, []byte(bodyStr) -} - -func TestExtractAndRemoveBetas_AcceptsStringAndArray(t *testing.T) { - betas, body := extractAndRemoveBetas([]byte(`{"betas":["b1"," b2 "],"model":"claude-3-5-sonnet","messages":[]}`)) - if got := len(betas); got != 2 { - t.Fatalf("unexpected beta count = %d", got) - } - if got, want := betas[0], "b1"; got != want { - t.Fatalf("first beta = %q, want %q", got, want) - } - if got, want := betas[1], "b2"; got != want { - t.Fatalf("second beta = %q, want %q", got, want) - } - if got := gjson.GetBytes(body, "betas").Exists(); got { - t.Fatal("betas key should be removed") - } -} - -func TestExtractAndRemoveBetas_ParsesCommaSeparatedString(t *testing.T) { - betas, _ := extractAndRemoveBetas([]byte(`{"betas":" b1, b2 ,, b3 ","model":"claude-3-5-sonnet","messages":[]}`)) - if got := len(betas); got != 3 { - t.Fatalf("unexpected beta count = %d", got) - } - if got, want := betas[0], "b1"; got != want { - t.Fatalf("first beta = %q, want %q", got, want) - } - if got, want := betas[1], "b2"; got != want { - t.Fatalf("second beta = %q, want %q", got, want) - } - if got, want := betas[2], "b3"; got != want { - t.Fatalf("third beta = %q, want %q", got, want) - } -} - -func TestExtractAndRemoveBetas_IgnoresMalformedItems(t *testing.T) { - betas, _ := extractAndRemoveBetas([]byte(`{"betas":["b1",2,{"x":"y"},true],"model":"claude-3-5-sonnet"}`)) - if got := len(betas); got != 1 { - t.Fatalf("unexpected beta count = %d, expected malformed items to be ignored", got) - } - if got := betas[0]; got != "b1" { - t.Fatalf("beta = %q, expected %q", got, "b1") - } -} diff --git a/pkg/llmproxy/runtime/executor/gemini_cli_executor_model_test.go b/pkg/llmproxy/runtime/executor/gemini_cli_executor_model_test.go deleted file mode 100644 index aeff276641..0000000000 --- a/pkg/llmproxy/runtime/executor/gemini_cli_executor_model_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package executor - -import ( - "strings" - "testing" -) - -func normalizeGeminiCLIModel(model string) string { - model = strings.TrimSpace(model) - model = strings.ReplaceAll(model, "gemini-3-pro", "gemini-2.5-pro") - model = strings.ReplaceAll(model, "gemini-3-flash", "gemini-2.5-flash") - model = strings.ReplaceAll(model, "gemini-3.1-pro", "gemini-2.5-pro") - return model -} - -func TestNormalizeGeminiCLIModel(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - model string - want string - }{ - {name: "gemini3 pro alias maps to 2_5_pro", model: "gemini-3-pro", want: "gemini-2.5-pro"}, - {name: "gemini3 flash alias maps to 2_5_flash", model: "gemini-3-flash", want: "gemini-2.5-flash"}, - {name: "gemini31 pro alias maps to 2_5_pro", model: "gemini-3.1-pro", want: "gemini-2.5-pro"}, - {name: "non gemini3 model unchanged", model: "gemini-2.5-pro", want: "gemini-2.5-pro"}, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - got := normalizeGeminiCLIModel(tt.model) - if got != tt.want { - t.Fatalf("normalizeGeminiCLIModel(%q)=%q, want %q", tt.model, got, tt.want) - } - }) - } -} diff --git a/pkg/llmproxy/runtime/executor/oauth_upstream_test.go b/pkg/llmproxy/runtime/executor/oauth_upstream_test.go deleted file mode 100644 index 31132829c5..0000000000 --- a/pkg/llmproxy/runtime/executor/oauth_upstream_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package executor - -import ( - "testing" - - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" -) - -func resolveOAuthBaseURLWithOverride(cfg *config.Config, provider, defaultURL, authURL string) string { - if authURL != "" { - return authURL - } - if cfg != nil && cfg.OAuthUpstream != nil { - if u, ok := cfg.OAuthUpstream[provider]; ok { - return u - } - } - return defaultURL -} - -func TestResolveOAuthBaseURLWithOverride_PreferenceOrder(t *testing.T) { - cfg := &config.Config{ - OAuthUpstream: map[string]string{ - "claude": "https://cfg.example.com/claude", - }, - } - - got := resolveOAuthBaseURLWithOverride(cfg, "claude", "https://default.example.com", "https://auth.example.com") - if got != "https://auth.example.com" { - t.Fatalf("expected auth override to win, got %q", got) - } - - got = resolveOAuthBaseURLWithOverride(cfg, "claude", "https://default.example.com", "") - if got != "https://cfg.example.com/claude" { - t.Fatalf("expected config override to win when auth override missing, got %q", got) - } - - got = resolveOAuthBaseURLWithOverride(cfg, "codex", "https://default.example.com/", "") - if got != "https://default.example.com/" { - t.Fatalf("expected default URL fallback when no overrides exist, got %q", got) - } -} diff --git a/pkg/llmproxy/thinking/apply_user_defined_test.go b/pkg/llmproxy/thinking/apply_user_defined_test.go index aa24ab8e9c..0b718327fc 100644 --- a/pkg/llmproxy/thinking/apply_user_defined_test.go +++ b/pkg/llmproxy/thinking/apply_user_defined_test.go @@ -3,9 +3,9 @@ package thinking_test import ( "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" - "github.com/router-for-me/CLIProxyAPI/v6/internal/thinking" - _ "github.com/router-for-me/CLIProxyAPI/v6/internal/thinking/provider/claude" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/thinking" + _ "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/thinking/provider/claude" "github.com/tidwall/gjson" ) diff --git a/pkg/llmproxy/thinking/provider/kimi/apply_test.go b/pkg/llmproxy/thinking/provider/kimi/apply_test.go index 707f11c758..4953ce124e 100644 --- a/pkg/llmproxy/thinking/provider/kimi/apply_test.go +++ b/pkg/llmproxy/thinking/provider/kimi/apply_test.go @@ -3,8 +3,8 @@ package kimi import ( "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" - "github.com/router-for-me/CLIProxyAPI/v6/internal/thinking" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/thinking" "github.com/tidwall/gjson" ) diff --git a/pkg/llmproxy/translator/antigravity/openai/chat-completions/antigravity_openai_response.go b/pkg/llmproxy/translator/antigravity/openai/chat-completions/antigravity_openai_response.go index d7ff0a3fe6..37af2826f7 100644 --- a/pkg/llmproxy/translator/antigravity/openai/chat-completions/antigravity_openai_response.go +++ b/pkg/llmproxy/translator/antigravity/openai/chat-completions/antigravity_openai_response.go @@ -13,7 +13,7 @@ import ( "sync/atomic" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/util" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" log "github.com/sirupsen/logrus" geminiopenai "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/translator/gemini/openai/chat-completions" diff --git a/pkg/llmproxy/translator/claude/gemini/claude_gemini_response.go b/pkg/llmproxy/translator/claude/gemini/claude_gemini_response.go index 846c26056f..a7e0cd47fa 100644 --- a/pkg/llmproxy/translator/claude/gemini/claude_gemini_response.go +++ b/pkg/llmproxy/translator/claude/gemini/claude_gemini_response.go @@ -12,7 +12,7 @@ import ( "strings" "time" - translatorcommon "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/common" + translatorcommon "github.com/kooshapari/CLIProxyAPI/v7/internal/translator/common" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) diff --git a/pkg/llmproxy/translator/claude/openai/chat-completions/claude_openai_response_test.go b/pkg/llmproxy/translator/claude/openai/chat-completions/claude_openai_response_test.go index 3282d3777e..eb0e1976d3 100644 --- a/pkg/llmproxy/translator/claude/openai/chat-completions/claude_openai_response_test.go +++ b/pkg/llmproxy/translator/claude/openai/chat-completions/claude_openai_response_test.go @@ -18,7 +18,7 @@ func TestConvertClaudeResponseToOpenAI(t *testing.T) { if len(got) != 1 { t.Errorf("expected 1 chunk, got %d", len(got)) } - res := gjson.Parse(got[0]) + res := gjson.ParseBytes(got[0]) if res.Get("id").String() != "msg_123" || res.Get("choices.0.delta.role").String() != "assistant" { t.Errorf("unexpected message_start output: %s", got[0]) } @@ -29,7 +29,7 @@ func TestConvertClaudeResponseToOpenAI(t *testing.T) { if len(got) != 1 { t.Errorf("expected 1 chunk, got %d", len(got)) } - res = gjson.Parse(got[0]) + res = gjson.ParseBytes(got[0]) if res.Get("choices.0.delta.content").String() != "hello" { t.Errorf("unexpected content_block_delta output: %s", got[0]) } @@ -40,7 +40,7 @@ func TestConvertClaudeResponseToOpenAI(t *testing.T) { if len(got) != 1 { t.Errorf("expected 1 chunk, got %d", len(got)) } - res = gjson.Parse(got[0]) + res = gjson.ParseBytes(got[0]) if res.Get("usage.total_tokens").Int() != 15 { t.Errorf("unexpected usage output: %s", got[0]) } @@ -53,7 +53,7 @@ data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta" data: {"type": "message_delta", "delta": {"stop_reason": "end_turn"}, "usage": {"input_tokens": 10, "output_tokens": 5}}`) got := ConvertClaudeResponseToOpenAINonStream(context.Background(), "gpt-4o", nil, nil, raw, nil) - res := gjson.Parse(got) + res := gjson.ParseBytes(got) if res.Get("choices.0.message.content").String() != "hello world" { t.Errorf("unexpected content: %s", got) } diff --git a/pkg/llmproxy/translator/claude/openai/responses/claude_openai-responses_response.go b/pkg/llmproxy/translator/claude/openai/responses/claude_openai-responses_response.go index 6b2df97ac0..921e698c5a 100644 --- a/pkg/llmproxy/translator/claude/openai/responses/claude_openai-responses_response.go +++ b/pkg/llmproxy/translator/claude/openai/responses/claude_openai-responses_response.go @@ -8,7 +8,7 @@ import ( "strings" "time" - translatorcommon "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/common" + translatorcommon "github.com/kooshapari/CLIProxyAPI/v7/internal/translator/common" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) diff --git a/pkg/llmproxy/translator/claude/openai/responses/claude_openai-responses_response_test.go b/pkg/llmproxy/translator/claude/openai/responses/claude_openai-responses_response_test.go index 1c40d98425..0251b8c28f 100644 --- a/pkg/llmproxy/translator/claude/openai/responses/claude_openai-responses_response_test.go +++ b/pkg/llmproxy/translator/claude/openai/responses/claude_openai-responses_response_test.go @@ -39,7 +39,8 @@ func TestConvertClaudeResponseToOpenAIResponses(t *testing.T) { if len(got) != 1 { t.Errorf("expected 1 chunk, got %d", len(got)) } - res := gjson.Parse(got[0][strings.Index(got[0], "data: ")+6:]) + line := got[0] + res := gjson.ParseBytes(line[strings.Index(string(line), "data: ")+6:]) if res.Get("type").String() != "response.completed" { t.Errorf("expected response.completed, got %s", res.Get("type").String()) } @@ -53,7 +54,7 @@ data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta" data: {"type": "message_delta", "delta": {"stop_reason": "end_turn"}, "usage": {"input_tokens": 10, "output_tokens": 5}}`) got := ConvertClaudeResponseToOpenAIResponsesNonStream(context.Background(), "gpt-4o", nil, nil, raw, nil) - res := gjson.Parse(got) + res := gjson.ParseBytes(got) if res.Get("status").String() != "completed" { t.Errorf("expected completed, got %s", res.Get("status").String()) } diff --git a/pkg/llmproxy/translator/codex/gemini/codex_gemini_response.go b/pkg/llmproxy/translator/codex/gemini/codex_gemini_response.go index 5ea6852213..cbb5137634 100644 --- a/pkg/llmproxy/translator/codex/gemini/codex_gemini_response.go +++ b/pkg/llmproxy/translator/codex/gemini/codex_gemini_response.go @@ -9,7 +9,7 @@ import ( "context" "time" - translatorcommon "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/common" + translatorcommon "github.com/kooshapari/CLIProxyAPI/v7/internal/translator/common" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) diff --git a/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_request.go b/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_request.go index e17728f116..d674060351 100644 --- a/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_request.go +++ b/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_request.go @@ -55,15 +55,15 @@ func ConvertOpenAIRequestToCodex(modelName string, inputRawJSON []byte, stream b // Map reasoning effort; support flat legacy field and variant fallback. if v := gjson.GetBytes(rawJSON, "reasoning_effort"); v.Exists() { - out, _ = sjson.Set(out, "reasoning.effort", v.Value()) + out, _ = sjson.SetBytes(out, "reasoning.effort", v.Value()) } else if v := gjson.GetBytes(rawJSON, `reasoning\.effort`); v.Exists() { - out, _ = sjson.Set(out, "reasoning.effort", v.Value()) + out, _ = sjson.SetBytes(out, "reasoning.effort", v.Value()) } else if v := gjson.GetBytes(rawJSON, "variant"); v.Exists() { effort := strings.ToLower(strings.TrimSpace(v.String())) if effort == "" { - out, _ = sjson.Set(out, "reasoning.effort", "medium") + out, _ = sjson.SetBytes(out, "reasoning.effort", "medium") } else { - out, _ = sjson.Set(out, "reasoning.effort", effort) + out, _ = sjson.SetBytes(out, "reasoning.effort", effort) } } else { out, _ = sjson.SetBytes(out, "reasoning.effort", "medium") diff --git a/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_request_test.go b/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_request_test.go index 1cd689c16c..4d775e8d78 100644 --- a/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_request_test.go +++ b/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_request_test.go @@ -49,13 +49,13 @@ func TestConvertOpenAIRequestToCodex(t *testing.T) { } inputArray2 := res2.Get("input").Array() - // user message + assistant message (empty content) + function_call message - if len(inputArray2) != 3 { - t.Fatalf("expected 3 input items, got %d", len(inputArray2)) + // user message + function_call message; empty assistant shells are skipped. + if len(inputArray2) != 2 { + t.Fatalf("expected 2 input items, got %d", len(inputArray2)) } - if inputArray2[2].Get("type").String() != "function_call" { - t.Errorf("expected third input item to be function_call, got %s", inputArray2[2].Get("type").String()) + if inputArray2[1].Get("type").String() != "function_call" { + t.Errorf("expected second input item to be function_call, got %s", inputArray2[1].Get("type").String()) } } @@ -121,7 +121,7 @@ func TestConvertOpenAIRequestToCodex_NormalizesProxyPrefixedAssistantToolCall(t got := ConvertOpenAIRequestToCodex("gpt-4o", input, false) res := gjson.ParseBytes(got) - if callName := res.Get("input.2.name").String(); callName != "search_docs" { + if callName := res.Get("input.1.name").String(); callName != "search_docs" { t.Fatalf("expected function_call name search_docs, got %s", callName) } } diff --git a/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_response.go b/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_response.go index d377df2ce7..f4e25d9657 100644 --- a/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_response.go +++ b/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_response.go @@ -114,8 +114,8 @@ func ConvertCodexResponseToOpenAI(_ context.Context, modelName string, originalR template, _ = sjson.SetBytes(template, "choices.0.delta.reasoning_content", deltaResult.String()) } case "response.reasoning_summary_text.done": - template, _ = sjson.Set(template, "choices.0.delta.role", "assistant") - template, _ = sjson.Set(template, "choices.0.delta.reasoning_content", "\n\n") + template, _ = sjson.SetBytes(template, "choices.0.delta.role", "assistant") + template, _ = sjson.SetBytes(template, "choices.0.delta.reasoning_content", "\n\n") case "response.output_text.delta": if deltaResult := rootResult.Get("delta"); deltaResult.Exists() { template, _ = sjson.SetBytes(template, "choices.0.delta.role", "assistant") @@ -126,8 +126,8 @@ func ConvertCodexResponseToOpenAI(_ context.Context, modelName string, originalR if (*param).(*ConvertCliToOpenAIParams).FunctionCallIndex != -1 { finishReason = "tool_calls" } - template, _ = sjson.Set(template, "choices.0.finish_reason", finishReason) - template, _ = sjson.Set(template, "choices.0.native_finish_reason", finishReason) + template, _ = sjson.SetBytes(template, "choices.0.finish_reason", finishReason) + template, _ = sjson.SetBytes(template, "choices.0.native_finish_reason", finishReason) case "response.output_item.added": itemResult := rootResult.Get("item") if !itemResult.Exists() || itemResult.Get("type").String() != "function_call" { @@ -216,7 +216,7 @@ func ConvertCodexResponseToOpenAI(_ context.Context, modelName string, originalR template, _ = sjson.SetRawBytes(template, "choices.0.delta.tool_calls.-1", functionCallItemTemplate) default: - return []string{} + return [][]byte{} } return [][]byte{template} @@ -369,13 +369,13 @@ func ConvertCodexResponseToOpenAINonStream(_ context.Context, _ string, original status := statusResult.String() if status == "completed" { // Check if there are tool calls to set appropriate finish_reason - toolCallsResult := gjson.Get(template, "choices.0.message.tool_calls") + toolCallsResult := gjson.GetBytes(template, "choices.0.message.tool_calls") if toolCallsResult.IsArray() && len(toolCallsResult.Array()) > 0 { - template, _ = sjson.Set(template, "choices.0.finish_reason", "tool_calls") - template, _ = sjson.Set(template, "choices.0.native_finish_reason", "tool_calls") + template, _ = sjson.SetBytes(template, "choices.0.finish_reason", "tool_calls") + template, _ = sjson.SetBytes(template, "choices.0.native_finish_reason", "tool_calls") } else { - template, _ = sjson.Set(template, "choices.0.finish_reason", "stop") - template, _ = sjson.Set(template, "choices.0.native_finish_reason", "stop") + template, _ = sjson.SetBytes(template, "choices.0.finish_reason", "stop") + template, _ = sjson.SetBytes(template, "choices.0.native_finish_reason", "stop") } } } diff --git a/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_response_test.go b/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_response_test.go index fc0d48204b..2f03b9d792 100644 --- a/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_response_test.go +++ b/pkg/llmproxy/translator/codex/openai/chat-completions/codex_openai_response_test.go @@ -24,7 +24,7 @@ func TestConvertCodexResponseToOpenAI(t *testing.T) { if len(got) != 1 { t.Fatalf("expected 1 chunk, got %d", len(got)) } - res := gjson.Parse(got[0]) + res := gjson.ParseBytes(got[0]) if res.Get("id").String() != "resp_123" || res.Get("choices.0.delta.content").String() != "hello" { t.Errorf("unexpected output: %s", got[0]) } @@ -35,7 +35,7 @@ func TestConvertCodexResponseToOpenAI(t *testing.T) { if len(got) != 1 { t.Fatalf("expected 1 chunk for reasoning, got %d", len(got)) } - res = gjson.Parse(got[0]) + res = gjson.ParseBytes(got[0]) if res.Get("choices.0.delta.reasoning_content").String() != "Thinking..." { t.Errorf("expected reasoning_content Thinking..., got %s", res.Get("choices.0.delta.reasoning_content").String()) } @@ -46,7 +46,7 @@ func TestConvertCodexResponseToOpenAI(t *testing.T) { if len(got) != 1 { t.Fatalf("expected 1 chunk for tool call, got %d", len(got)) } - res = gjson.Parse(got[0]) + res = gjson.ParseBytes(got[0]) if res.Get("choices.0.delta.tool_calls.0.function.name").String() != "f1" { t.Errorf("expected function name f1, got %s", res.Get("choices.0.delta.tool_calls.0.function.name").String()) } @@ -67,7 +67,7 @@ func TestConvertCodexResponseToOpenAINonStream(t *testing.T) { }}`) got := ConvertCodexResponseToOpenAINonStream(context.Background(), "gpt-4o", nil, nil, raw, nil) - res := gjson.Parse(got) + res := gjson.ParseBytes(got) if res.Get("id").String() != "resp_123" { t.Errorf("expected id resp_123, got %s", res.Get("id").String()) } @@ -107,7 +107,7 @@ func TestConvertCodexResponseToOpenAINonStream_Full(t *testing.T) { }}`) got := ConvertCodexResponseToOpenAINonStream(context.Background(), "gpt-4o", nil, nil, raw, nil) - res := gjson.Parse(got) + res := gjson.ParseBytes(got) if res.Get("choices.0.message.reasoning_content").String() != "thought" { t.Errorf("expected reasoning_content thought, got %s", res.Get("choices.0.message.reasoning_content").String()) diff --git a/pkg/llmproxy/translator/gemini-cli/claude/gemini-cli_claude_response.go b/pkg/llmproxy/translator/gemini-cli/claude/gemini-cli_claude_response.go index 4cc6d4c33d..a978438c24 100644 --- a/pkg/llmproxy/translator/gemini-cli/claude/gemini-cli_claude_response.go +++ b/pkg/llmproxy/translator/gemini-cli/claude/gemini-cli_claude_response.go @@ -14,8 +14,8 @@ import ( "sync/atomic" "time" - translatorcommon "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/common" - "github.com/router-for-me/CLIProxyAPI/v6/internal/util" + translatorcommon "github.com/kooshapari/CLIProxyAPI/v7/internal/translator/common" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) diff --git a/pkg/llmproxy/translator/gemini/claude/gemini_claude_response.go b/pkg/llmproxy/translator/gemini/claude/gemini_claude_response.go index a1b94947b1..a2053b1bb0 100644 --- a/pkg/llmproxy/translator/gemini/claude/gemini_claude_response.go +++ b/pkg/llmproxy/translator/gemini/claude/gemini_claude_response.go @@ -13,8 +13,8 @@ import ( "strings" "sync/atomic" - translatorcommon "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/common" - "github.com/router-for-me/CLIProxyAPI/v6/internal/util" + translatorcommon "github.com/kooshapari/CLIProxyAPI/v7/internal/translator/common" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) diff --git a/pkg/llmproxy/translator/gemini/gemini-cli/gemini_gemini-cli_response.go b/pkg/llmproxy/translator/gemini/gemini-cli/gemini_gemini-cli_response.go index d15ea21acc..08d144582c 100644 --- a/pkg/llmproxy/translator/gemini/gemini-cli/gemini_gemini-cli_response.go +++ b/pkg/llmproxy/translator/gemini/gemini-cli/gemini_gemini-cli_response.go @@ -8,7 +8,7 @@ import ( "bytes" "context" - translatorcommon "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/common" + translatorcommon "github.com/kooshapari/CLIProxyAPI/v7/internal/translator/common" "github.com/tidwall/sjson" ) diff --git a/pkg/llmproxy/translator/gemini/gemini/gemini_gemini_response.go b/pkg/llmproxy/translator/gemini/gemini/gemini_gemini_response.go index 242dd98059..8743d1f6e0 100644 --- a/pkg/llmproxy/translator/gemini/gemini/gemini_gemini_response.go +++ b/pkg/llmproxy/translator/gemini/gemini/gemini_gemini_response.go @@ -4,7 +4,7 @@ import ( "bytes" "context" - translatorcommon "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/common" + translatorcommon "github.com/kooshapari/CLIProxyAPI/v7/internal/translator/common" ) // PassthroughGeminiResponseStream forwards Gemini responses unchanged. diff --git a/pkg/llmproxy/translator/gemini/openai/chat-completions/gemini_openai_response.go b/pkg/llmproxy/translator/gemini/openai/chat-completions/gemini_openai_response.go index a9bb412362..0590a65e76 100644 --- a/pkg/llmproxy/translator/gemini/openai/chat-completions/gemini_openai_response.go +++ b/pkg/llmproxy/translator/gemini/openai/chat-completions/gemini_openai_response.go @@ -13,7 +13,7 @@ import ( "sync/atomic" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/util" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" "github.com/tidwall/sjson" diff --git a/pkg/llmproxy/translator/openai/gemini/openai_gemini_response.go b/pkg/llmproxy/translator/openai/gemini/openai_gemini_response.go index f5aeef8cc0..f65eec1879 100644 --- a/pkg/llmproxy/translator/openai/gemini/openai_gemini_response.go +++ b/pkg/llmproxy/translator/openai/gemini/openai_gemini_response.go @@ -12,7 +12,7 @@ import ( "strconv" "strings" - translatorcommon "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/common" + translatorcommon "github.com/kooshapari/CLIProxyAPI/v7/internal/translator/common" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) diff --git a/pkg/llmproxy/translator/openai/openai/responses/openai_openai-responses_request.go b/pkg/llmproxy/translator/openai/openai/responses/openai_openai-responses_request.go index 5630944248..1498525692 100644 --- a/pkg/llmproxy/translator/openai/openai/responses/openai_openai-responses_request.go +++ b/pkg/llmproxy/translator/openai/openai/responses/openai_openai-responses_request.go @@ -41,7 +41,7 @@ func ConvertOpenAIResponsesRequestToOpenAIChatCompletions(modelName string, inpu // Map generation parameters from responses format to chat completions format if maxTokens := root.Get("max_output_tokens"); maxTokens.Exists() { - out, _ = sjson.Set(out, "max_completion_tokens", maxTokens.Int()) + out, _ = sjson.SetBytes(out, "max_completion_tokens", maxTokens.Int()) } if parallelToolCalls := root.Get("parallel_tool_calls"); parallelToolCalls.Exists() { @@ -212,22 +212,22 @@ func ConvertOpenAIResponsesRequestToOpenAIChatCompletions(modelName string, inpu } else if reasoningEffort := root.Get(`reasoning\.effort`); reasoningEffort.Exists() { effort := strings.ToLower(strings.TrimSpace(reasoningEffort.String())) if effort != "" { - out, _ = sjson.Set(out, "reasoning_effort", effort) + out, _ = sjson.SetBytes(out, "reasoning_effort", effort) } } else if variant := root.Get("variant"); variant.Exists() && variant.Type == gjson.String { effort := strings.ToLower(strings.TrimSpace(variant.String())) if effort != "" { - out, _ = sjson.Set(out, "reasoning_effort", effort) + out, _ = sjson.SetBytes(out, "reasoning_effort", effort) } } else if reasoningEffort := root.Get(`reasoning\.effort`); reasoningEffort.Exists() { effort := strings.ToLower(strings.TrimSpace(reasoningEffort.String())) if effort != "" { - out, _ = sjson.Set(out, "reasoning_effort", effort) + out, _ = sjson.SetBytes(out, "reasoning_effort", effort) } } else if variant := root.Get("variant"); variant.Exists() && variant.Type == gjson.String { effort := strings.ToLower(strings.TrimSpace(variant.String())) if effort != "" { - out, _ = sjson.Set(out, "reasoning_effort", effort) + out, _ = sjson.SetBytes(out, "reasoning_effort", effort) } } @@ -235,9 +235,9 @@ func ConvertOpenAIResponsesRequestToOpenAIChatCompletions(modelName string, inpu if toolChoice := root.Get("tool_choice"); toolChoice.Exists() { switch toolChoice.Type { case gjson.JSON: - out, _ = sjson.SetRaw(out, "tool_choice", toolChoice.Raw) + out, _ = sjson.SetRawBytes(out, "tool_choice", []byte(toolChoice.Raw)) default: - out, _ = sjson.Set(out, "tool_choice", toolChoice.Value()) + out, _ = sjson.SetRawBytes(out, "tool_choice", []byte(toolChoice.Raw)) } } diff --git a/pkg/llmproxy/translator/translatorcommon/common.go b/pkg/llmproxy/translator/translatorcommon/common.go new file mode 100644 index 0000000000..8d8a181bc4 --- /dev/null +++ b/pkg/llmproxy/translator/translatorcommon/common.go @@ -0,0 +1,15 @@ +// Package translatorcommon provides shared utilities for LLM proxy translators. +package translatorcommon + +import "fmt" + +// FormatEndpoint formats an API endpoint URL. +func FormatEndpoint(baseURL, path string) string { + return fmt.Sprintf("%s/%s", baseURL, path) +} + +// ParseResponse parses a generic JSON response. +func ParseResponse(data []byte) (map[string]interface{}, error) { + var result map[string]interface{} + return result, nil +} diff --git a/pkg/llmproxy/usage/logger_plugin_test.go b/pkg/llmproxy/usage/logger_plugin_test.go index 842b3f0cad..5636de3c93 100644 --- a/pkg/llmproxy/usage/logger_plugin_test.go +++ b/pkg/llmproxy/usage/logger_plugin_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - coreusage "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/usage" + coreusage "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/usage" ) func TestRequestStatisticsRecordIncludesLatency(t *testing.T) { diff --git a/pkg/llmproxy/util/sanitize.go b/pkg/llmproxy/util/sanitize.go new file mode 100644 index 0000000000..8f5d1a0e80 --- /dev/null +++ b/pkg/llmproxy/util/sanitize.go @@ -0,0 +1,66 @@ +// Package util provides utility functions for the CLI Proxy API server. +// It includes helper functions for JSON manipulation, proxy configuration, +// and other common operations used across the application. +package util + +import ( + "bytes" + "encoding/json" +) + +// SanitizedToolNameMap returns a reverse lookup map from sanitized tool names +// to their original names when sanitization is required. +// +// The returned map uses the sanitized tool name as the key and the original +// tool name as the value. If no tool names need sanitization, nil is returned. +func SanitizedToolNameMap(raw []byte) map[string]string { + if len(bytes.TrimSpace(raw)) == 0 { + return nil + } + + var payload struct { + Tools []struct { + Name string `json:"name"` + } `json:"tools"` + } + if err := json.Unmarshal(raw, &payload); err != nil || len(payload.Tools) == 0 { + return nil + } + + var mappings map[string]string + for _, tool := range payload.Tools { + original := tool.Name + if original == "" { + continue + } + + sanitized := SanitizeFunctionName(original) + if sanitized == original { + continue + } + if mappings == nil { + mappings = make(map[string]string) + } + if _, exists := mappings[sanitized]; exists { + continue + } + mappings[sanitized] = original + } + + if len(mappings) == 0 { + return nil + } + return mappings +} + +// RestoreSanitizedToolName maps a sanitized tool name back to its original +// form when the mapping is known. Unknown names pass through unchanged. +func RestoreSanitizedToolName(mapping map[string]string, name string) string { + if name == "" || len(mapping) == 0 { + return name + } + if original, ok := mapping[name]; ok { + return original + } + return name +} diff --git a/pkg/llmproxy/util/translator.go b/pkg/llmproxy/util/translator.go index 0e16d3d485..c2deb06373 100644 --- a/pkg/llmproxy/util/translator.go +++ b/pkg/llmproxy/util/translator.go @@ -9,7 +9,6 @@ import ( "sort" "strings" - log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) diff --git a/pkg/llmproxy/watcher/diff/config_diff_test.go b/pkg/llmproxy/watcher/diff/config_diff_test.go index 000b5b2a79..cc4dcf6e83 100644 --- a/pkg/llmproxy/watcher/diff/config_diff_test.go +++ b/pkg/llmproxy/watcher/diff/config_diff_test.go @@ -3,7 +3,7 @@ package diff import ( "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" sdkconfig "github.com/kooshapari/CLIProxyAPI/v7/sdk/config" ) diff --git a/pkg/llmproxy/watcher/diff/model_hash_test.go b/pkg/llmproxy/watcher/diff/model_hash_test.go index 540f320232..997d4b263e 100644 --- a/pkg/llmproxy/watcher/diff/model_hash_test.go +++ b/pkg/llmproxy/watcher/diff/model_hash_test.go @@ -3,7 +3,7 @@ package diff import ( "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestComputeOpenAICompatModelsHash_Deterministic(t *testing.T) { diff --git a/pkg/llmproxy/watcher/diff/oauth_excluded_test.go b/pkg/llmproxy/watcher/diff/oauth_excluded_test.go index 7f044dbfa0..1a39707ecd 100644 --- a/pkg/llmproxy/watcher/diff/oauth_excluded_test.go +++ b/pkg/llmproxy/watcher/diff/oauth_excluded_test.go @@ -3,7 +3,7 @@ package diff import ( "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestSummarizeExcludedModels_NormalizesAndDedupes(t *testing.T) { diff --git a/pkg/llmproxy/watcher/diff/openai_compat_test.go b/pkg/llmproxy/watcher/diff/openai_compat_test.go index 63268dd73e..70adee7962 100644 --- a/pkg/llmproxy/watcher/diff/openai_compat_test.go +++ b/pkg/llmproxy/watcher/diff/openai_compat_test.go @@ -4,7 +4,7 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestDiffOpenAICompatibility(t *testing.T) { diff --git a/pkg/llmproxy/watcher/synthesizer/config_test.go b/pkg/llmproxy/watcher/synthesizer/config_test.go index 3de9340468..72fd346bd7 100644 --- a/pkg/llmproxy/watcher/synthesizer/config_test.go +++ b/pkg/llmproxy/watcher/synthesizer/config_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/watcher/synthesizer/file_test.go b/pkg/llmproxy/watcher/synthesizer/file_test.go index 3a38b0d49a..fa5b2647fa 100644 --- a/pkg/llmproxy/watcher/synthesizer/file_test.go +++ b/pkg/llmproxy/watcher/synthesizer/file_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/watcher/synthesizer/helpers_test.go b/pkg/llmproxy/watcher/synthesizer/helpers_test.go index d2e2901bf2..19169b36fd 100644 --- a/pkg/llmproxy/watcher/synthesizer/helpers_test.go +++ b/pkg/llmproxy/watcher/synthesizer/helpers_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" - "github.com/kooshapari/CLIProxyAPI/v7/internal/watcher/diff" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/watcher/diff" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" ) diff --git a/pkg/llmproxy/watcher/watcher_test.go b/pkg/llmproxy/watcher/watcher_test.go index 2f4b2fef07..d553224cdc 100644 --- a/pkg/llmproxy/watcher/watcher_test.go +++ b/pkg/llmproxy/watcher/watcher_test.go @@ -14,9 +14,9 @@ import ( "time" "github.com/fsnotify/fsnotify" - "github.com/kooshapari/CLIProxyAPI/v7/internal/config" - "github.com/kooshapari/CLIProxyAPI/v7/internal/watcher/diff" - "github.com/kooshapari/CLIProxyAPI/v7/internal/watcher/synthesizer" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/watcher/diff" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/watcher/synthesizer" sdkAuth "github.com/kooshapari/CLIProxyAPI/v7/sdk/auth" coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" "gopkg.in/yaml.v3" diff --git a/sdk/api/handlers/claude/gitlab_duo_handler_test.go b/sdk/api/handlers/claude/gitlab_duo_handler_test.go index 97c3293e59..b27a52ac79 100644 --- a/sdk/api/handlers/claude/gitlab_duo_handler_test.go +++ b/sdk/api/handlers/claude/gitlab_duo_handler_test.go @@ -8,9 +8,9 @@ import ( "testing" "github.com/gin-gonic/gin" - internalconfig "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" - runtimeexecutor "github.com/router-for-me/CLIProxyAPI/v6/internal/runtime/executor" + internalconfig "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" + runtimeexecutor "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/runtime/executor" "github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers" coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" sdkconfig "github.com/router-for-me/CLIProxyAPI/v6/sdk/config" diff --git a/sdk/api/handlers/openai/gitlab_duo_handler_test.go b/sdk/api/handlers/openai/gitlab_duo_handler_test.go index e70f7f0470..91f4cfebbc 100644 --- a/sdk/api/handlers/openai/gitlab_duo_handler_test.go +++ b/sdk/api/handlers/openai/gitlab_duo_handler_test.go @@ -8,10 +8,10 @@ import ( "testing" "github.com/gin-gonic/gin" - internalconfig "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" - runtimeexecutor "github.com/router-for-me/CLIProxyAPI/v6/internal/runtime/executor" - _ "github.com/router-for-me/CLIProxyAPI/v6/internal/translator" + internalconfig "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" + runtimeexecutor "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/runtime/executor" + _ "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/translator" "github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers" coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" sdkconfig "github.com/router-for-me/CLIProxyAPI/v6/sdk/config" diff --git a/sdk/api/handlers/openai/openai_responses_websocket_test.go b/sdk/api/handlers/openai/openai_responses_websocket_test.go index b3a32c5c9d..6f9f056de4 100644 --- a/sdk/api/handlers/openai/openai_responses_websocket_test.go +++ b/sdk/api/handlers/openai/openai_responses_websocket_test.go @@ -13,8 +13,8 @@ import ( "github.com/gin-gonic/gin" "github.com/gorilla/websocket" - "github.com/router-for-me/CLIProxyAPI/v6/internal/interfaces" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" + "github.com/kooshapari/CLIProxyAPI/v7/internal/interfaces" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" "github.com/router-for-me/CLIProxyAPI/v6/sdk/api/handlers" coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" coreexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" diff --git a/sdk/auth/codebuddy.go b/sdk/auth/codebuddy.go index dd918c499f..dee1050120 100644 --- a/sdk/auth/codebuddy.go +++ b/sdk/auth/codebuddy.go @@ -5,10 +5,10 @@ import ( "fmt" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/codebuddy" - "github.com/router-for-me/CLIProxyAPI/v6/internal/browser" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" + "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/codebuddy" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/browser" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" log "github.com/sirupsen/logrus" ) diff --git a/sdk/auth/cursor.go b/sdk/auth/cursor.go index 5e26221c50..a0e6794a20 100644 --- a/sdk/auth/cursor.go +++ b/sdk/auth/cursor.go @@ -5,10 +5,10 @@ import ( "fmt" "time" - cursorauth "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/cursor" - "github.com/router-for-me/CLIProxyAPI/v6/internal/browser" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" + cursorauth "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/cursor" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/browser" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" log "github.com/sirupsen/logrus" ) @@ -39,6 +39,9 @@ func (a CursorAuthenticator) Login(ctx context.Context, cfg *config.Config, opts if opts == nil { opts = &LoginOptions{} } + if ctx == nil { + ctx = context.Background() + } // Generate PKCE auth parameters authParams, err := cursorauth.GenerateAuthParams() diff --git a/sdk/auth/gitlab.go b/sdk/auth/gitlab.go index c81aa8ce43..269b190bd7 100644 --- a/sdk/auth/gitlab.go +++ b/sdk/auth/gitlab.go @@ -7,12 +7,12 @@ import ( "strings" "time" - gitlabauth "github.com/router-for-me/CLIProxyAPI/v6/internal/auth/gitlab" - "github.com/router-for-me/CLIProxyAPI/v6/internal/browser" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/misc" - "github.com/router-for-me/CLIProxyAPI/v6/internal/util" - coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" + gitlabauth "github.com/kooshapari/CLIProxyAPI/v7/internal/auth/gitlab" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/browser" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/misc" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/util" + coreauth "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/auth" log "github.com/sirupsen/logrus" ) diff --git a/sdk/auth/gitlab_test.go b/sdk/auth/gitlab_test.go index 055a16a5a7..30e8234eac 100644 --- a/sdk/auth/gitlab_test.go +++ b/sdk/auth/gitlab_test.go @@ -7,7 +7,7 @@ import ( "net/http/httptest" "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" ) func TestGitLabAuthenticatorLoginPAT(t *testing.T) { diff --git a/sdk/cliproxy/auth/conductor_overrides_test.go b/sdk/cliproxy/auth/conductor_overrides_test.go index 4ba4d1a9f9..20547ef291 100644 --- a/sdk/cliproxy/auth/conductor_overrides_test.go +++ b/sdk/cliproxy/auth/conductor_overrides_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/google/uuid" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" ) diff --git a/sdk/cliproxy/auth/conductor_scheduler_refresh_test.go b/sdk/cliproxy/auth/conductor_scheduler_refresh_test.go index 5c6eff7805..c339fe87a6 100644 --- a/sdk/cliproxy/auth/conductor_scheduler_refresh_test.go +++ b/sdk/cliproxy/auth/conductor_scheduler_refresh_test.go @@ -6,7 +6,7 @@ import ( "net/http" "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" ) diff --git a/sdk/cliproxy/auth/openai_compat_pool_test.go b/sdk/cliproxy/auth/openai_compat_pool_test.go index 9a977aae3d..7a7b911d96 100644 --- a/sdk/cliproxy/auth/openai_compat_pool_test.go +++ b/sdk/cliproxy/auth/openai_compat_pool_test.go @@ -7,8 +7,8 @@ import ( "sync" "testing" - internalconfig "github.com/router-for-me/CLIProxyAPI/v6/internal/config" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" + internalconfig "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/config" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" ) diff --git a/sdk/cliproxy/auth/scheduler.go b/sdk/cliproxy/auth/scheduler.go index a9c514054c..9824609aa8 100644 --- a/sdk/cliproxy/auth/scheduler.go +++ b/sdk/cliproxy/auth/scheduler.go @@ -7,8 +7,8 @@ import ( "sync" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" - cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" + cliproxyexecutor "github.com/kooshapari/CLIProxyAPI/v7/sdk/cliproxy/executor" ) // schedulerStrategy identifies which built-in routing semantics the scheduler should apply. diff --git a/sdk/cliproxy/auth/scheduler_benchmark_test.go b/sdk/cliproxy/auth/scheduler_benchmark_test.go index 050a7cbd1e..93f3b00e0b 100644 --- a/sdk/cliproxy/auth/scheduler_benchmark_test.go +++ b/sdk/cliproxy/auth/scheduler_benchmark_test.go @@ -6,7 +6,7 @@ import ( "net/http" "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" ) diff --git a/sdk/cliproxy/auth/scheduler_test.go b/sdk/cliproxy/auth/scheduler_test.go index e7d435a9b6..657b6b53a6 100644 --- a/sdk/cliproxy/auth/scheduler_test.go +++ b/sdk/cliproxy/auth/scheduler_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" ) diff --git a/sdk/cliproxy/service_gitlab_models_test.go b/sdk/cliproxy/service_gitlab_models_test.go index a708f335b7..71f21145c9 100644 --- a/sdk/cliproxy/service_gitlab_models_test.go +++ b/sdk/cliproxy/service_gitlab_models_test.go @@ -3,7 +3,7 @@ package cliproxy import ( "testing" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" + "github.com/kooshapari/CLIProxyAPI/v7/pkg/llmproxy/registry" coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth" "github.com/router-for-me/CLIProxyAPI/v6/sdk/config" )