diff --git a/package-lock.json b/package-lock.json index 33fd41c9..183fd7ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,8 @@ "google-auth-library": "^10.5.0" }, "devDependencies": { + "@esbuild/darwin-arm64": "^0.28.0", + "@rollup/rollup-darwin-arm64": "^4.60.2", "baseline-browser-mapping": "^2.9.11" }, "workspaces": { @@ -1866,6 +1868,90 @@ "tslib": "^2.4.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/darwin-x64": { "version": "0.25.12", "cpu": [ @@ -1881,6 +1967,346 @@ "node": ">=18" } }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@fastify/accept-negotiator": { "version": "1.1.0", "license": "MIT", @@ -2930,6 +3356,47 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz", + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", + "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "os": [ + "darwin" + ] + }, "node_modules/@rollup/rollup-darwin-x64": { "version": "4.52.5", "cpu": [ @@ -2942,6 +3409,291 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz", + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz", + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz", + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz", + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz", + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz", + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz", + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz", + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz", + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz", + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz", + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz", + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz", + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz", + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz", + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz", + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz", + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz", + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@shikijs/core": { "version": "3.15.0", "license": "MIT", @@ -3289,6 +4041,22 @@ "@tauri-apps/cli-win32-x64-msvc": "2.9.4" } }, + "node_modules/@tauri-apps/cli-darwin-arm64": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.9.4.tgz", + "integrity": "sha512-9rHkMVtbMhe0AliVbrGpzMahOBg3rwV46JYRELxR9SN6iu1dvPOaMaiC4cP6M/aD1424ziXnnMdYU06RAH8oIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 OR MIT", + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@tauri-apps/cli-darwin-x64": { "version": "2.9.4", "cpu": [ @@ -5806,6 +6574,23 @@ "@esbuild/win32-x64": "0.25.12" } }, + "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/escalade": { "version": "3.2.0", "dev": true, @@ -9281,6 +10066,20 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz", + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, "node_modules/run-parallel": { "version": "1.2.0", "dev": true, @@ -11162,6 +11961,91 @@ } } }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/vite/node_modules/@esbuild/darwin-x64": { "version": "0.21.5", "cpu": [ @@ -11177,6 +12061,295 @@ "node": ">=12" } }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/vite/node_modules/esbuild": { "version": "0.21.5", "dev": true, @@ -12150,7 +13323,8 @@ "version": "0.14.0", "license": "MIT", "devDependencies": { - "@tauri-apps/cli": "^2.9.4" + "@tauri-apps/cli": "^2.9.4", + "@tauri-apps/cli-darwin-arm64": "^2.9.4" } }, "packages/ui": { diff --git a/package.json b/package.json index 3c7422c7..311aa879 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "google-auth-library": "^10.5.0" }, "devDependencies": { + "@esbuild/darwin-arm64": "^0.28.0", + "@rollup/rollup-darwin-arm64": "^4.60.2", "baseline-browser-mapping": "^2.9.11" } } diff --git a/packages/server/src/api-types.ts b/packages/server/src/api-types.ts index f46796b4..ac739903 100644 --- a/packages/server/src/api-types.ts +++ b/packages/server/src/api-types.ts @@ -337,6 +337,15 @@ export interface RemoteServerProbeResponse { errorCode?: string } +export interface RemoteProxySessionCreateRequest { + baseUrl: string + skipTlsVerify?: boolean +} + +export interface RemoteProxySessionCreateResponse { + windowUrl: string +} + export type WorkspaceEventType = | "workspace.created" | "workspace.started" diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 72c98425..ad02bc8a 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -21,6 +21,7 @@ import { launchInBrowser } from "./launcher" import { resolveUi } from "./ui/remote-ui" import { AuthManager, BOOTSTRAP_TOKEN_STDOUT_PREFIX, DEFAULT_AUTH_COOKIE_NAME, DEFAULT_AUTH_USERNAME } from "./auth/manager" import { resolveHttpsOptions } from "./server/tls" +import { RemoteProxySessionManager } from "./server/remote-proxy" import { resolveNetworkAddresses, resolveRemoteAddresses } from "./server/network-addresses" import { startDevReleaseMonitor } from "./releases/dev-release-monitor" import { SpeechService } from "./speech/service" @@ -383,6 +384,11 @@ async function main() { const clientConnectionManager = new ClientConnectionManager(logger.child({ component: "client-connections" })) const pluginChannel = new PluginChannelManager(logger.child({ component: "plugin-channel" })) + const remoteProxySessionManager = new RemoteProxySessionManager({ + authManager, + logger: logger.child({ component: "remote-proxy" }), + httpsOptions: tlsResolution?.httpsOptions, + }) const voiceModeManager = new VoiceModeManager({ connections: clientConnectionManager, channel: pluginChannel, @@ -422,6 +428,7 @@ async function main() { clientConnectionManager, pluginChannel, voiceModeManager, + remoteProxySessionManager, uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR, uiDevServerUrl: uiResolution.uiDevServerUrl, logger, @@ -447,6 +454,7 @@ async function main() { clientConnectionManager, pluginChannel, voiceModeManager, + remoteProxySessionManager, uiStaticDir: uiResolution.uiStaticDir ?? DEFAULT_UI_STATIC_DIR, uiDevServerUrl: undefined, logger, diff --git a/packages/server/src/server/http-server.ts b/packages/server/src/server/http-server.ts index 9d4e0e1a..e196cb73 100644 --- a/packages/server/src/server/http-server.ts +++ b/packages/server/src/server/http-server.ts @@ -26,6 +26,7 @@ import { registerBackgroundProcessRoutes } from "./routes/background-processes" import { registerWorktreeRoutes } from "./routes/worktrees" import { registerSpeechRoutes } from "./routes/speech" import { registerRemoteServerRoutes } from "./routes/remote-servers" +import { registerRemoteProxyRoutes } from "./routes/remote-proxy" import { registerSideCarRoutes } from "./routes/sidecars" import { ServerMeta } from "../api-types" import { InstanceStore } from "../storage/instance-store" @@ -38,6 +39,7 @@ import { ClientConnectionManager } from "../clients/connection-manager" import { PluginChannelManager } from "../plugins/channel" import { VoiceModeManager } from "../plugins/voice-mode" import type { SideCarManager } from "../sidecars/manager" +import type { RemoteProxySessionManager } from "./remote-proxy" interface HttpServerDeps { bindHost: string @@ -58,6 +60,7 @@ interface HttpServerDeps { clientConnectionManager: ClientConnectionManager pluginChannel: PluginChannelManager voiceModeManager: VoiceModeManager + remoteProxySessionManager: RemoteProxySessionManager uiStaticDir: string uiDevServerUrl?: string logger: Logger @@ -274,6 +277,7 @@ export function createHttpServer(deps: HttpServerDeps) { workspaceManager: deps.workspaceManager, }) registerRemoteServerRoutes(app, { logger: apiLogger }) + registerRemoteProxyRoutes(app, { logger: proxyLogger, sessionManager: deps.remoteProxySessionManager }) registerSpeechRoutes(app, { speechService: deps.speechService }) registerSideCarRoutes(app, { sidecarManager: deps.sidecarManager }) registerSideCarProxyRoutes(app, { sidecarManager: deps.sidecarManager, logger: proxyLogger }) diff --git a/packages/server/src/server/remote-proxy.ts b/packages/server/src/server/remote-proxy.ts new file mode 100644 index 00000000..b8f82da5 --- /dev/null +++ b/packages/server/src/server/remote-proxy.ts @@ -0,0 +1,533 @@ +import Fastify, { type FastifyInstance, type FastifyReply, type FastifyRequest } from "fastify" +import { randomBytes, randomUUID } from "crypto" +import { Readable } from "stream" +import { Agent, fetch } from "undici" +import type { AuthManager } from "../auth/manager" +import type { Logger } from "../logger" + +const LOOPBACK_HOST = "127.0.0.1" +const BOOTSTRAP_PAGE_PATH = "/__codenomad/auth/token" +const BOOTSTRAP_EXCHANGE_PATH = "/__codenomad/api/auth/token" +const SESSION_IDLE_TTL_MS = 30 * 60_000 + +interface RemoteProxySession { + id: string + targetBaseUrl: URL + skipTlsVerify: boolean + localBaseUrl: URL + entryUrl: URL + bootstrapUrl: string + activated: boolean + cookiePrefix: string + app: FastifyInstance + dispatcher?: Agent + createdAt: number + lastAccessAt: number +} + +export interface RemoteProxySessionManagerOptions { + authManager: AuthManager + logger: Logger + httpsOptions?: { key: string | Buffer; cert: string | Buffer; ca?: string | Buffer } +} + +export class RemoteProxySessionManager { + private readonly sessions = new Map() + private readonly cleanupTimer: NodeJS.Timeout + + constructor(private readonly options: RemoteProxySessionManagerOptions) { + this.cleanupTimer = setInterval(() => { + void this.cleanupExpiredSessions() + }, 60_000) + this.cleanupTimer.unref() + } + + async createSession(baseUrl: string, skipTlsVerify: boolean): Promise { + if (!this.options.httpsOptions) { + throw new Error("Local HTTPS is required for remote proxy sessions") + } + + const targetBaseUrl = normalizeBaseUrl(baseUrl) + const token = this.options.authManager.issueBootstrapToken() + if (!token) { + throw new Error("Bootstrap token generation is unavailable") + } + + const sessionId = randomUUID() + const dispatcher = skipTlsVerify ? new Agent({ connect: { rejectUnauthorized: false } }) : undefined + const app = Fastify({ logger: false, https: this.options.httpsOptions }) + let session: RemoteProxySession | null = null + + app.removeAllContentTypeParsers() + app.addContentTypeParser("*", (req, body, done) => done(null, body)) + + app.get(BOOTSTRAP_PAGE_PATH, async (request, reply) => { + if (!this.options.authManager.isLoopbackRequest(request)) { + reply.code(404).send({ error: "Not found" }) + return + } + + reply.header("Cache-Control", "no-store") + reply.header("Pragma", "no-cache") + reply.header("Expires", "0") + reply.type("text/html").send(buildBootstrapPageHtml()) + }) + + app.post(BOOTSTRAP_EXCHANGE_PATH, async (request, reply) => { + if (!this.options.authManager.isLoopbackRequest(request)) { + reply.code(404).send({ error: "Not found" }) + return + } + + const body = parseTokenBody(request.body) + if (!this.options.authManager.consumeBootstrapToken(body.token)) { + reply.code(401).send({ error: "Invalid token" }) + return + } + + if (!session) { + reply.code(503).send({ error: "Remote proxy session is unavailable" }) + return + } + + session.activated = true + session.lastAccessAt = Date.now() + reply.send({ ok: true }) + }) + + app.all("/*", async (request, reply) => { + if (!session) { + reply.code(503).send({ error: "Remote proxy session is unavailable" }) + return + } + + if (!session.activated) { + reply.code(403).send({ error: "Remote proxy session is not activated" }) + return + } + + session.lastAccessAt = Date.now() + await proxyRequest({ request, reply, session, logger: this.options.logger }) + }) + + app.setNotFoundHandler(async (request, reply) => { + if (!session) { + reply.code(503).send({ error: "Remote proxy session is unavailable" }) + return + } + + if (!session.activated) { + reply.code(403).send({ error: "Remote proxy session is not activated" }) + return + } + + session.lastAccessAt = Date.now() + await proxyRequest({ request, reply, session, logger: this.options.logger }) + }) + + const addressInfo = await app.listen({ host: LOOPBACK_HOST, port: 0 }) + const address = new URL(addressInfo) + const localBaseUrl = new URL(`https://${LOOPBACK_HOST}:${address.port}`) + const entryUrl = new URL(targetBaseUrl.pathname || "/", localBaseUrl) + const returnTo = buildReturnToTarget(entryUrl) + + session = { + id: sessionId, + targetBaseUrl, + skipTlsVerify, + localBaseUrl, + entryUrl, + bootstrapUrl: `${localBaseUrl.origin}${BOOTSTRAP_PAGE_PATH}?returnTo=${encodeURIComponent(returnTo)}#${encodeURIComponent(token)}`, + activated: false, + cookiePrefix: `cnrp_${randomBytes(6).toString("hex")}_`, + app, + dispatcher, + createdAt: Date.now(), + lastAccessAt: Date.now(), + } + + this.sessions.set(sessionId, session) + this.options.logger.info( + { sessionId, targetBaseUrl: targetBaseUrl.toString(), localBaseUrl: localBaseUrl.toString() }, + "Created remote proxy session", + ) + + return session.bootstrapUrl + } + + private async cleanupExpiredSessions() { + const now = Date.now() + for (const session of Array.from(this.sessions.values())) { + if (now - session.lastAccessAt <= SESSION_IDLE_TTL_MS) { + continue + } + await this.disposeSession(session.id) + } + } + + private async disposeSession(sessionId: string) { + const session = this.sessions.get(sessionId) + if (!session) { + return + } + + this.sessions.delete(sessionId) + session.dispatcher?.close().catch(() => {}) + await session.app.close().catch(() => {}) + this.options.logger.info({ sessionId }, "Disposed remote proxy session") + } +} + +function normalizeBaseUrl(input: string): URL { + const parsed = new URL(input.trim()) + if (parsed.protocol !== "http:" && parsed.protocol !== "https:") { + throw new Error("Server URL must use http:// or https://") + } + + parsed.hash = "" + parsed.search = "" + parsed.pathname = parsed.pathname === "/" ? "/" : parsed.pathname.replace(/\/+$/, "") || "/" + return parsed +} + +function buildReturnToTarget(entryUrl: URL): string { + const query = entryUrl.search ? entryUrl.search : "" + return `${entryUrl.pathname || "/"}${query}` +} + +function buildBootstrapPageHtml(): string { + return ` + + + + + CodeNomad + + + +
+

Connecting...

+

Finalizing local authentication.

+
+
+ + +` +} + +function parseTokenBody(body: unknown): { token: string } { + const value = normalizeJsonBody(body) as { token?: unknown } | null | undefined + const token = typeof value?.token === "string" ? value.token.trim() : "" + if (!token) { + throw new Error("Missing bootstrap token") + } + return { token } +} + +function normalizeJsonBody(body: unknown): unknown { + if (Buffer.isBuffer(body)) { + return JSON.parse(body.toString("utf-8")) + } + if (typeof body === "string") { + return JSON.parse(body) + } + return body +} + +function toRequestBody(body: unknown): any { + if (body == null) { + return undefined + } + if (Buffer.isBuffer(body) || typeof body === "string" || body instanceof Uint8Array) { + return body + } + return JSON.stringify(body) +} + +async function proxyRequest(args: { + request: FastifyRequest + reply: FastifyReply + session: RemoteProxySession + logger: Logger +}) { + const { request, reply, session, logger } = args + const upstreamUrl = buildUpstreamUrl(session.targetBaseUrl, request.raw.url ?? request.url) + const headers = filterRequestHeaders(request.headers, session) + + const init: any = { + method: request.method, + headers, + dispatcher: session.dispatcher, + redirect: "manual", + } + + if (request.method !== "GET" && request.method !== "HEAD") { + const body = toRequestBody(request.body) + if (body !== undefined) { + init.body = body + init.duplex = "half" + } + } + + try { + const response = await fetch(upstreamUrl, init as any) + reply.code(response.status) + applyResponseHeaders(reply, response, session) + + if (!response.body || request.method === "HEAD") { + reply.send() + return + } + + reply.send(Readable.fromWeb(response.body as any)) + } catch (error) { + logger.error({ err: error, upstreamUrl }, "Failed to proxy remote session request") + if (!reply.sent) { + reply.code(502).send({ error: "Remote proxy request failed" }) + } + } +} + +function buildUpstreamUrl(baseUrl: URL, rawUrl: string): string { + const parsed = new URL(rawUrl, "https://localhost") + const url = new URL(baseUrl.toString()) + url.pathname = rewriteRequestPath(baseUrl, parsed.pathname) + url.search = stripInternalQuery(parsed.search) + url.hash = "" + return url.toString() +} + +function rewriteRequestPath(baseUrl: URL, requestPath: string): string { + const basePath = normalizedBasePath(baseUrl) + if (basePath === "/") { + return requestPath + } + + if (requestPath === "/") { + return basePath + } + + if (pathHasBasePrefix(basePath, requestPath)) { + return requestPath + } + + return `${basePath}${requestPath}` +} + +function normalizedBasePath(baseUrl: URL): string { + return baseUrl.pathname || "/" +} + +function pathHasBasePrefix(basePath: string, requestPath: string): boolean { + return requestPath === basePath || requestPath.startsWith(`${basePath}/`) +} + +function stripInternalQuery(search: string): string { + if (!search || search === "?") { + return "" + } + return search +} + +function filterRequestHeaders( + headers: FastifyRequest["headers"], + session: RemoteProxySession, +): Record { + const next: Record = {} + for (const [key, value] of Object.entries(headers ?? {})) { + if (!value) continue + const lower = key.toLowerCase() + if (isHopByHopHeader(lower) || lower === "host" || lower === "content-length") { + continue + } + if (lower === "origin") { + next[key] = session.targetBaseUrl.origin + continue + } + if (lower === "referer") { + const rewritten = rewriteRefererHeader(Array.isArray(value) ? value[0] : value, session.targetBaseUrl) + if (rewritten) { + next[key] = rewritten + } + continue + } + if (lower === "cookie") { + const rewritten = rewriteRequestCookieHeader(Array.isArray(value) ? value.join("; ") : value, session.cookiePrefix) + if (rewritten) { + next[key] = rewritten + } + continue + } + next[key] = Array.isArray(value) ? value.join(",") : value + } + + next.host = session.targetBaseUrl.port ? `${session.targetBaseUrl.hostname}:${session.targetBaseUrl.port}` : session.targetBaseUrl.hostname + if (!next.origin) { + next.origin = session.targetBaseUrl.origin + } + return next +} + +function rewriteRefererHeader(referer: string | undefined, targetBaseUrl: URL): string | null { + if (!referer) { + return null + } + + try { + const parsed = new URL(referer) + const rewritten = new URL(targetBaseUrl.toString()) + rewritten.pathname = rewriteRequestPath(targetBaseUrl, parsed.pathname) + rewritten.search = parsed.search + rewritten.hash = parsed.hash + return rewritten.toString() + } catch { + return null + } +} + +function applyResponseHeaders(reply: FastifyReply, response: any, session: RemoteProxySession) { + const setCookie = (response.headers as any).getSetCookie?.() as string[] | undefined + if (Array.isArray(setCookie)) { + for (const cookie of setCookie) { + reply.header("set-cookie", rewriteSetCookie(cookie, session.cookiePrefix)) + } + } + + response.headers.forEach((value: string, key: string) => { + const lower = key.toLowerCase() + if (isHopByHopHeader(lower) || lower === "set-cookie") { + return + } + + if (lower === "location") { + reply.header(key, rewriteLocation(value, session.targetBaseUrl, session.localBaseUrl)) + return + } + + reply.header(key, value) + }) +} + +function rewriteSetCookie(cookie: string, cookiePrefix: string): string { + const parts = cookie.split(";").map((part) => part.trim()) + const first = parts.shift() ?? "" + const separator = first.indexOf("=") + if (separator <= 0) { + return cookie + } + + const name = first.slice(0, separator).trim() + const value = first.slice(separator + 1) + const rewritten = [`${cookiePrefix}${name}=${value}`] + for (const part of parts) { + if (part.slice(0, 7).toLowerCase().startsWith("domain=")) { + continue + } + rewritten.push(part) + } + return rewritten.join("; ") +} + +function rewriteRequestCookieHeader(cookieHeader: string, cookiePrefix: string): string { + const next: string[] = [] + for (const rawPart of cookieHeader.split(";")) { + const part = rawPart.trim() + if (!part) continue + const separator = part.indexOf("=") + if (separator <= 0) continue + const name = part.slice(0, separator).trim() + const value = part.slice(separator + 1) + if (!name.startsWith(cookiePrefix)) { + continue + } + next.push(`${name.slice(cookiePrefix.length)}=${value}`) + } + return next.join("; ") +} + +function rewriteLocation(location: string, targetBaseUrl: URL, localBaseUrl: URL): string { + try { + const parsed = new URL(location, targetBaseUrl) + if (parsed.origin !== targetBaseUrl.origin) { + return location + } + + const rewritten = new URL(localBaseUrl.toString()) + rewritten.pathname = parsed.pathname + rewritten.search = parsed.search + rewritten.hash = parsed.hash + return rewritten.toString() + } catch { + return location + } +} + +function isHopByHopHeader(name: string): boolean { + return new Set([ + "connection", + "keep-alive", + "proxy-authenticate", + "proxy-authorization", + "te", + "trailer", + "transfer-encoding", + "upgrade", + ]).has(name) +} diff --git a/packages/server/src/server/routes/remote-proxy.ts b/packages/server/src/server/routes/remote-proxy.ts new file mode 100644 index 00000000..6787bd5f --- /dev/null +++ b/packages/server/src/server/routes/remote-proxy.ts @@ -0,0 +1,29 @@ +import type { FastifyInstance } from "fastify" +import { z } from "zod" +import type { RemoteProxySessionCreateResponse } from "../../api-types" +import type { Logger } from "../../logger" +import type { RemoteProxySessionManager } from "../remote-proxy" + +interface RouteDeps { + logger: Logger + sessionManager: RemoteProxySessionManager +} + +const CreateSessionSchema = z.object({ + baseUrl: z.string().min(1), + skipTlsVerify: z.boolean().optional(), +}) + +export function registerRemoteProxyRoutes(app: FastifyInstance, deps: RouteDeps) { + app.post("/api/remote-proxy/sessions", async (request, reply): Promise => { + try { + const body = CreateSessionSchema.parse(request.body ?? {}) + const windowUrl = await deps.sessionManager.createSession(body.baseUrl, Boolean(body.skipTlsVerify)) + return { windowUrl } + } catch (error) { + deps.logger.warn({ err: error }, "Failed to create remote proxy session") + reply.code(400) + return { error: error instanceof Error ? error.message : "Failed to create remote proxy session" } + } + }) +} diff --git a/packages/tauri-app/package.json b/packages/tauri-app/package.json index c09a70ac..c679b5dc 100644 --- a/packages/tauri-app/package.json +++ b/packages/tauri-app/package.json @@ -14,6 +14,7 @@ "build": "tauri build" }, "devDependencies": { - "@tauri-apps/cli": "^2.9.4" + "@tauri-apps/cli": "^2.9.4", + "@tauri-apps/cli-darwin-arm64": "^2.9.4" } } diff --git a/packages/tauri-app/src-tauri/src/main.rs b/packages/tauri-app/src-tauri/src/main.rs index 52de199c..35fd7c3c 100644 --- a/packages/tauri-app/src-tauri/src/main.rs +++ b/packages/tauri-app/src-tauri/src/main.rs @@ -1,18 +1,13 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -#[cfg_attr(target_os = "linux", allow(dead_code))] +#[allow(dead_code)] mod cert_manager; mod cli_manager; #[cfg(target_os = "linux")] mod linux_tls; -#[cfg_attr(target_os = "linux", allow(dead_code))] -mod remote_proxy; use cli_manager::{CliProcessManager, CliStatus}; use keepawake::KeepAwake; -#[cfg(not(target_os = "linux"))] -use remote_proxy::start_remote_proxy; -use remote_proxy::{ProxyTlsConfig, RemoteProxyHandle}; use serde::Deserialize; use serde_json::json; use std::collections::{HashMap, HashSet}; @@ -56,7 +51,6 @@ pub struct AppState { pub remote_origins: Mutex>, pub remote_skip_tls_verify: Mutex>, pub remote_tls_handlers: Mutex>, - pub remote_proxies: Mutex>, } #[derive(Debug, Deserialize)] @@ -65,6 +59,8 @@ struct RemoteWindowPayload { id: String, name: String, base_url: String, + entry_url: Option, + #[allow(dead_code)] skip_tls_verify: bool, } @@ -182,49 +178,21 @@ fn intercept_navigation(webview: &Webview, url: &Url) -> bool { async fn open_remote_window_impl( app: AppHandle, payload: RemoteWindowPayload, - _tls_config: Option, ) -> Result<(), String> { - let parsed = Url::parse(&payload.base_url).map_err(|err| err.to_string())?; + let entry_url = payload.entry_url.as_deref().unwrap_or(payload.base_url.as_str()); + let parsed = Url::parse(entry_url).map_err(|err| err.to_string())?; let label = format!("remote-{}", payload.id); let title = format!( "{} - {}", payload.name, - parsed.host_str().unwrap_or(payload.base_url.as_str()) + Url::parse(&payload.base_url) + .ok() + .and_then(|url| url.host_str().map(str::to_string)) + .unwrap_or_else(|| payload.base_url.clone()) ); - #[cfg(target_os = "linux")] let window_url = parsed.clone(); - #[cfg(not(target_os = "linux"))] - let window_url = { - let state = app.state::(); - let reuses_existing_proxy = { - let proxies = state.remote_proxies.lock().map_err(|err| err.to_string())?; - proxies - .get(&label) - .map(|existing| existing.matches(&parsed, payload.skip_tls_verify)) - .unwrap_or(false) - }; - - if reuses_existing_proxy { - let proxies = state.remote_proxies.lock().map_err(|err| err.to_string())?; - proxies - .get(&label) - .map(|handle| handle.entry_url().clone()) - .ok_or_else(|| "Remote proxy disappeared before reuse".to_string())? - } else { - let new_proxy = - start_remote_proxy(parsed.clone(), payload.skip_tls_verify, _tls_config).await?; - let local_url = new_proxy.entry_url().clone(); - let mut proxies = state.remote_proxies.lock().map_err(|err| err.to_string())?; - if let Some(existing) = proxies.remove(&label) { - existing.shutdown(); - } - proxies.insert(label.clone(), new_proxy); - local_url - } - }; - app.state::() .remote_origins .lock() @@ -234,7 +202,7 @@ async fn open_remote_window_impl( .remote_skip_tls_verify .lock() .map_err(|err| err.to_string())? - .insert(label.clone(), payload.skip_tls_verify); + .insert(label.clone(), parsed.scheme() == "https"); if let Some(existing) = app.get_webview_window(&label) { #[cfg(target_os = "linux")] @@ -287,11 +255,6 @@ async fn open_remote_window_impl( if let Ok(mut handlers) = app_handle.state::().remote_tls_handlers.lock() { handlers.remove(&label_for_cleanup); } - if let Ok(mut proxies) = app_handle.state::().remote_proxies.lock() { - if let Some(handle) = proxies.remove(&label_for_cleanup) { - handle.shutdown(); - } - } } }); @@ -300,33 +263,25 @@ async fn open_remote_window_impl( #[tauri::command] async fn open_remote_window(app: AppHandle, payload: RemoteWindowPayload) -> Result<(), String> { - #[cfg(target_os = "linux")] - { - return open_remote_window_impl(app, payload, None).await; - } - #[cfg(not(target_os = "linux"))] - let tls_config = match cert_manager::ensure_local_cert() { - Ok(local_cert) => { + { + let entry_url = payload.entry_url.as_deref().unwrap_or(payload.base_url.as_str()); + let parsed = Url::parse(entry_url).map_err(|err| err.to_string())?; + if parsed.scheme() == "https" { + let local_cert = cert_manager::ensure_local_cert().map_err(|err| { + format!( + "Failed to load the local HTTPS certificate for the remote proxy window: {err}" + ) + })?; if let Err(err) = cert_manager::trust_cert_in_store(&local_cert.ca_cert_der) { return Err(format!( "Failed to trust the local CodeNomad CA certificate. Accept the certificate installation prompt and try again: {err}" )); } - Some(ProxyTlsConfig { - cert_pem: local_cert.cert_pem, - key_pem: local_cert.key_pem, - }) } - Err(err) => { - return Err(format!( - "Failed to create the local HTTPS proxy certificate. This remote HTTPS connection cannot fall back to HTTP because secure cookies would break: {err}" - )); - } - }; + } - #[cfg(not(target_os = "linux"))] - open_remote_window_impl(app, payload, tls_config).await + open_remote_window_impl(app, payload).await } fn collect_directory_paths(paths: &[std::path::PathBuf]) -> Vec { @@ -487,7 +442,6 @@ fn main() { remote_origins: Mutex::new(HashMap::new()), remote_skip_tls_verify: Mutex::new(HashMap::new()), remote_tls_handlers: Mutex::new(HashSet::new()), - remote_proxies: Mutex::new(HashMap::new()), }) .setup(|app| { set_windows_app_user_model_id(); diff --git a/packages/ui/src/components/folder-selection-view.tsx b/packages/ui/src/components/folder-selection-view.tsx index 90459ada..9368ddf1 100644 --- a/packages/ui/src/components/folder-selection-view.tsx +++ b/packages/ui/src/components/folder-selection-view.tsx @@ -16,6 +16,7 @@ import { showAlertDialog } from "../stores/alerts" import { openSettings, settingsOpen } from "../stores/settings-screen" import { openExternalUrl } from "../lib/external-url" import { serverApi } from "../lib/api-client" +import { runtimeEnv } from "../lib/runtime-env" import { openRemoteServerWindow } from "../lib/native/remote-window" const codeNomadLogo = new URL("../images/CodeNomad-Icon.png", import.meta.url).href @@ -332,7 +333,15 @@ const FolderSelectionView: Component = (props) => { }) if (openWindow) { - await openRemoteServerWindow(profile) + const windowUrl = + runtimeEnv.host === "tauri" + ? (await serverApi.createRemoteProxySession({ + baseUrl: profile.baseUrl, + skipTlsVerify: profile.skipTlsVerify, + })).windowUrl + : undefined + + await openRemoteServerWindow(profile, windowUrl) await markRemoteServerConnected(profile.id) } diff --git a/packages/ui/src/lib/api-client.ts b/packages/ui/src/lib/api-client.ts index 96dad79e..14474316 100644 --- a/packages/ui/src/lib/api-client.ts +++ b/packages/ui/src/lib/api-client.ts @@ -12,6 +12,8 @@ import type { SpeechTranscriptionResponse, SideCar, ServerMeta, + RemoteProxySessionCreateRequest, + RemoteProxySessionCreateResponse, RemoteServerProbeRequest, RemoteServerProbeResponse, VoiceModeStateResponse, @@ -256,6 +258,12 @@ export const serverApi = { body: JSON.stringify(payload), }) }, + createRemoteProxySession(payload: RemoteProxySessionCreateRequest): Promise { + return request("/api/remote-proxy/sessions", { + method: "POST", + body: JSON.stringify(payload), + }) + }, fetchAuthStatus(): Promise<{ authenticated: boolean; username?: string; passwordUserProvided?: boolean }> { return request<{ authenticated: boolean; username?: string; passwordUserProvided?: boolean }>("/api/auth/status") }, diff --git a/packages/ui/src/lib/native/remote-window.ts b/packages/ui/src/lib/native/remote-window.ts index 96b36cd5..9ec3cde5 100644 --- a/packages/ui/src/lib/native/remote-window.ts +++ b/packages/ui/src/lib/native/remote-window.ts @@ -6,14 +6,19 @@ export interface RemoteWindowOpenPayload { id: string name: string baseUrl: string + entryUrl?: string skipTlsVerify: boolean } -export async function openRemoteServerWindow(profile: Pick): Promise { +export async function openRemoteServerWindow( + profile: Pick, + entryUrl?: string, +): Promise { const payload: RemoteWindowOpenPayload = { id: profile.id, name: profile.name, baseUrl: profile.baseUrl, + entryUrl, skipTlsVerify: profile.skipTlsVerify, } diff --git a/packages/ui/src/types/global.d.ts b/packages/ui/src/types/global.d.ts index 8e6a475e..4f5dd240 100644 --- a/packages/ui/src/types/global.d.ts +++ b/packages/ui/src/types/global.d.ts @@ -37,6 +37,7 @@ declare global { id: string name: string baseUrl: string + entryUrl?: string skipTlsVerify: boolean }) => Promise<{ ok: boolean }> }