mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2026-01-30 06:12:05 +00:00
feat: Add proxy support for AI providers (#1382)
This commit is contained in:
47
.changeset/proxy-support-for-ai-providers.md
Normal file
47
.changeset/proxy-support-for-ai-providers.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Added opt-in proxy support for all AI providers - respects http_proxy/https_proxy environment variables when enabled.
|
||||||
|
|
||||||
|
When using Task Master in corporate or restricted network environments that require HTTP/HTTPS proxies, API calls to AI providers (OpenAI, Anthropic, Google, AWS Bedrock, etc.) would previously fail with ECONNRESET errors. This update adds seamless proxy support that can be enabled via environment variable or configuration file.
|
||||||
|
|
||||||
|
**How to enable:**
|
||||||
|
|
||||||
|
Proxy support is opt-in. Enable it using either method:
|
||||||
|
|
||||||
|
**Method 1: Environment Variable**
|
||||||
|
```bash
|
||||||
|
export TASKMASTER_ENABLE_PROXY=true
|
||||||
|
export http_proxy=http://your-proxy:port
|
||||||
|
export https_proxy=http://your-proxy:port
|
||||||
|
export no_proxy=localhost,127.0.0.1 # Optional: bypass proxy for specific hosts
|
||||||
|
|
||||||
|
# Then use Task Master normally
|
||||||
|
task-master add-task "Create a new feature"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Method 2: Configuration File**
|
||||||
|
|
||||||
|
Add to `.taskmaster/config.json`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"global": {
|
||||||
|
"enableProxy": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then set your proxy environment variables:
|
||||||
|
```bash
|
||||||
|
export http_proxy=http://your-proxy:port
|
||||||
|
export https_proxy=http://your-proxy:port
|
||||||
|
```
|
||||||
|
|
||||||
|
**Technical details:**
|
||||||
|
|
||||||
|
- Uses undici's `EnvHttpProxyAgent` for automatic proxy detection
|
||||||
|
- Centralized implementation in `BaseAIProvider` for consistency across all providers
|
||||||
|
- Supports all AI providers: OpenAI, Anthropic, Perplexity, Azure OpenAI, Google AI, Google Vertex AI, AWS Bedrock, and OpenAI-compatible providers
|
||||||
|
- Opt-in design ensures users without proxy requirements are not affected
|
||||||
|
- Priority: `TASKMASTER_ENABLE_PROXY` environment variable > `config.json` setting
|
||||||
@@ -15,3 +15,8 @@ VERTEX_PROJECT_ID=your-gcp-project-id
|
|||||||
VERTEX_LOCATION=us-central1
|
VERTEX_LOCATION=us-central1
|
||||||
# Optional: Path to service account credentials JSON file (alternative to API key)
|
# Optional: Path to service account credentials JSON file (alternative to API key)
|
||||||
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-credentials.json
|
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-credentials.json
|
||||||
|
|
||||||
|
# Proxy Configuration (Optional)
|
||||||
|
# Enable proxy support for AI provider API calls
|
||||||
|
# When enabled, automatically uses http_proxy/https_proxy environment variables
|
||||||
|
TASKMASTER_ENABLE_PROXY=false
|
||||||
|
|||||||
37
package-lock.json
generated
37
package-lock.json
generated
@@ -66,6 +66,7 @@
|
|||||||
"ora": "^8.2.0",
|
"ora": "^8.2.0",
|
||||||
"simple-git": "^3.28.0",
|
"simple-git": "^3.28.0",
|
||||||
"steno": "^4.0.2",
|
"steno": "^4.0.2",
|
||||||
|
"undici": "^7.16.0",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"zod": "^4.1.11"
|
"zod": "^4.1.11"
|
||||||
},
|
},
|
||||||
@@ -738,6 +739,7 @@
|
|||||||
"version": "3.25.76",
|
"version": "3.25.76",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
@@ -2815,6 +2817,7 @@
|
|||||||
"version": "7.28.4",
|
"version": "7.28.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/generator": "^7.28.3",
|
"@babel/generator": "^7.28.3",
|
||||||
@@ -3857,6 +3860,7 @@
|
|||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/accessibility": "^3.1.1",
|
"@dnd-kit/accessibility": "^3.1.1",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
@@ -5763,7 +5767,6 @@
|
|||||||
"version": "0.23.2",
|
"version": "0.23.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
}
|
}
|
||||||
@@ -6301,7 +6304,6 @@
|
|||||||
"version": "0.23.2",
|
"version": "0.23.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
}
|
}
|
||||||
@@ -6310,6 +6312,7 @@
|
|||||||
"version": "3.25.76",
|
"version": "3.25.76",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
@@ -6600,6 +6603,7 @@
|
|||||||
"node_modules/@modelcontextprotocol/sdk/node_modules/zod": {
|
"node_modules/@modelcontextprotocol/sdk/node_modules/zod": {
|
||||||
"version": "3.25.76",
|
"version": "3.25.76",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
@@ -6700,6 +6704,7 @@
|
|||||||
"node_modules/@opentelemetry/api": {
|
"node_modules/@opentelemetry/api": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
}
|
}
|
||||||
@@ -9733,6 +9738,7 @@
|
|||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.18.6",
|
"version": "22.18.6",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
}
|
}
|
||||||
@@ -9754,6 +9760,7 @@
|
|||||||
"version": "19.1.8",
|
"version": "19.1.8",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
@@ -9762,6 +9769,7 @@
|
|||||||
"version": "19.1.6",
|
"version": "19.1.6",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.0.0"
|
"@types/react": "^19.0.0"
|
||||||
}
|
}
|
||||||
@@ -10208,6 +10216,7 @@
|
|||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.15.0",
|
"version": "8.15.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -10274,6 +10283,7 @@
|
|||||||
"node_modules/ai": {
|
"node_modules/ai": {
|
||||||
"version": "5.0.57",
|
"version": "5.0.57",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/gateway": "1.0.30",
|
"@ai-sdk/gateway": "1.0.30",
|
||||||
"@ai-sdk/provider": "2.0.0",
|
"@ai-sdk/provider": "2.0.0",
|
||||||
@@ -10493,6 +10503,7 @@
|
|||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "8.17.1",
|
"version": "8.17.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"fast-uri": "^3.0.1",
|
"fast-uri": "^3.0.1",
|
||||||
@@ -11499,6 +11510,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.8.3",
|
"baseline-browser-mapping": "^2.8.3",
|
||||||
"caniuse-lite": "^1.0.30001741",
|
"caniuse-lite": "^1.0.30001741",
|
||||||
@@ -13365,7 +13377,8 @@
|
|||||||
"node_modules/devtools-protocol": {
|
"node_modules/devtools-protocol": {
|
||||||
"version": "0.0.1312386",
|
"version": "0.0.1312386",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/dezalgo": {
|
"node_modules/dezalgo": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
@@ -13961,6 +13974,7 @@
|
|||||||
"version": "0.25.10",
|
"version": "0.25.10",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"esbuild": "bin/esbuild"
|
"esbuild": "bin/esbuild"
|
||||||
},
|
},
|
||||||
@@ -14274,6 +14288,7 @@
|
|||||||
"node_modules/express": {
|
"node_modules/express": {
|
||||||
"version": "4.21.2",
|
"version": "4.21.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
@@ -16616,6 +16631,7 @@
|
|||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alcalzone/ansi-tokenize": "^0.2.0",
|
"@alcalzone/ansi-tokenize": "^0.2.0",
|
||||||
"ansi-escapes": "^7.0.0",
|
"ansi-escapes": "^7.0.0",
|
||||||
@@ -17573,6 +17589,7 @@
|
|||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/core": "^29.7.0",
|
"@jest/core": "^29.7.0",
|
||||||
"@jest/types": "^29.6.3",
|
"@jest/types": "^29.6.3",
|
||||||
@@ -19190,6 +19207,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.16.0"
|
"node": ">= 10.16.0"
|
||||||
}
|
}
|
||||||
@@ -19515,7 +19533,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.0.0"
|
"node": ">= 12.0.0"
|
||||||
},
|
},
|
||||||
@@ -19740,7 +19757,6 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
},
|
},
|
||||||
@@ -19871,6 +19887,7 @@
|
|||||||
"node_modules/marked": {
|
"node_modules/marked": {
|
||||||
"version": "15.0.12",
|
"version": "15.0.12",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"marked": "bin/marked.js"
|
"marked": "bin/marked.js"
|
||||||
},
|
},
|
||||||
@@ -22596,6 +22613,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.11",
|
"nanoid": "^3.3.11",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
@@ -23979,6 +23997,7 @@
|
|||||||
"integrity": "sha512-U+NPR0Bkg3wm61dteD2L4nAM1U9dtaqVrpDXwC36IKRHpEO/Ubpid4Nijpa2imPchcVNHfxVFwSSMJdwdGFUbg==",
|
"integrity": "sha512-U+NPR0Bkg3wm61dteD2L4nAM1U9dtaqVrpDXwC36IKRHpEO/Ubpid4Nijpa2imPchcVNHfxVFwSSMJdwdGFUbg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oxc-project/types": "=0.93.0",
|
"@oxc-project/types": "=0.93.0",
|
||||||
"@rolldown/pluginutils": "1.0.0-beta.41",
|
"@rolldown/pluginutils": "1.0.0-beta.41",
|
||||||
@@ -26444,6 +26463,7 @@
|
|||||||
"version": "5.9.2",
|
"version": "5.9.2",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -26530,6 +26550,8 @@
|
|||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "7.16.0",
|
"version": "7.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz",
|
||||||
|
"integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.18.1"
|
"node": ">=20.18.1"
|
||||||
@@ -26560,6 +26582,7 @@
|
|||||||
"version": "11.0.5",
|
"version": "11.0.5",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/unist": "^3.0.0",
|
"@types/unist": "^3.0.0",
|
||||||
"bail": "^2.0.0",
|
"bail": "^2.0.0",
|
||||||
@@ -27002,6 +27025,7 @@
|
|||||||
"version": "5.4.20",
|
"version": "5.4.20",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.21.3",
|
"esbuild": "^0.21.3",
|
||||||
"postcss": "^8.4.43",
|
"postcss": "^8.4.43",
|
||||||
@@ -27114,7 +27138,6 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
@@ -27842,6 +27865,7 @@
|
|||||||
"node_modules/zod": {
|
"node_modules/zod": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
@@ -28870,6 +28894,7 @@
|
|||||||
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
|
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/chai": "^5.2.2",
|
"@types/chai": "^5.2.2",
|
||||||
"@vitest/expect": "3.2.4",
|
"@vitest/expect": "3.2.4",
|
||||||
|
|||||||
@@ -104,6 +104,7 @@
|
|||||||
"ora": "^8.2.0",
|
"ora": "^8.2.0",
|
||||||
"simple-git": "^3.28.0",
|
"simple-git": "^3.28.0",
|
||||||
"steno": "^4.0.2",
|
"steno": "^4.0.2",
|
||||||
|
"undici": "^7.16.0",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"zod": "^4.1.11"
|
"zod": "^4.1.11"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ const DEFAULTS = {
|
|||||||
ollamaBaseURL: 'http://localhost:11434/api',
|
ollamaBaseURL: 'http://localhost:11434/api',
|
||||||
bedrockBaseURL: 'https://bedrock.us-east-1.amazonaws.com',
|
bedrockBaseURL: 'https://bedrock.us-east-1.amazonaws.com',
|
||||||
responseLanguage: 'English',
|
responseLanguage: 'English',
|
||||||
enableCodebaseAnalysis: true
|
enableCodebaseAnalysis: true,
|
||||||
|
enableProxy: false
|
||||||
},
|
},
|
||||||
claudeCode: {},
|
claudeCode: {},
|
||||||
codexCli: {},
|
codexCli: {},
|
||||||
@@ -703,6 +704,32 @@ function getCodebaseAnalysisEnabled(explicitRoot = null) {
|
|||||||
return getGlobalConfig(explicitRoot).enableCodebaseAnalysis !== false;
|
return getGlobalConfig(explicitRoot).enableCodebaseAnalysis !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getProxyEnabled(explicitRoot = null) {
|
||||||
|
// Return boolean-safe value with default false
|
||||||
|
return getGlobalConfig(explicitRoot).enableProxy === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isProxyEnabled(session = null, projectRoot = null) {
|
||||||
|
// Priority 1: Environment variable
|
||||||
|
const envFlag = resolveEnvVariable(
|
||||||
|
'TASKMASTER_ENABLE_PROXY',
|
||||||
|
session,
|
||||||
|
projectRoot
|
||||||
|
);
|
||||||
|
if (envFlag !== null && envFlag !== undefined && envFlag !== '') {
|
||||||
|
return envFlag.toLowerCase() === 'true' || envFlag === '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priority 2: MCP session environment (explicit check for parity with other flags)
|
||||||
|
if (session?.env?.TASKMASTER_ENABLE_PROXY) {
|
||||||
|
const mcpFlag = session.env.TASKMASTER_ENABLE_PROXY;
|
||||||
|
return mcpFlag.toLowerCase() === 'true' || mcpFlag === '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priority 3: Configuration file
|
||||||
|
return getProxyEnabled(projectRoot);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets model parameters (maxTokens, temperature) for a specific role,
|
* Gets model parameters (maxTokens, temperature) for a specific role,
|
||||||
* considering model-specific overrides from supported-models.json.
|
* considering model-specific overrides from supported-models.json.
|
||||||
@@ -807,9 +834,9 @@ function isApiKeySet(providerName, session = null, projectRoot = null) {
|
|||||||
const providersWithoutApiKeys = [
|
const providersWithoutApiKeys = [
|
||||||
CUSTOM_PROVIDERS.OLLAMA,
|
CUSTOM_PROVIDERS.OLLAMA,
|
||||||
CUSTOM_PROVIDERS.BEDROCK,
|
CUSTOM_PROVIDERS.BEDROCK,
|
||||||
CUSTOM_PROVIDERS.MCP,
|
|
||||||
CUSTOM_PROVIDERS.GEMINI_CLI,
|
CUSTOM_PROVIDERS.GEMINI_CLI,
|
||||||
CUSTOM_PROVIDERS.GROK_CLI,
|
CUSTOM_PROVIDERS.GROK_CLI,
|
||||||
|
CUSTOM_PROVIDERS.MCP,
|
||||||
CUSTOM_PROVIDERS.CODEX_CLI
|
CUSTOM_PROVIDERS.CODEX_CLI
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -1188,6 +1215,8 @@ export {
|
|||||||
getResponseLanguage,
|
getResponseLanguage,
|
||||||
getCodebaseAnalysisEnabled,
|
getCodebaseAnalysisEnabled,
|
||||||
isCodebaseAnalysisEnabled,
|
isCodebaseAnalysisEnabled,
|
||||||
|
getProxyEnabled,
|
||||||
|
isProxyEnabled,
|
||||||
getParametersForRole,
|
getParametersForRole,
|
||||||
getUserId,
|
getUserId,
|
||||||
// API Key Checkers (still relevant)
|
// API Key Checkers (still relevant)
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ export class AnthropicAIProvider extends BaseAIProvider {
|
|||||||
...(baseURL && { baseURL }),
|
...(baseURL && { baseURL }),
|
||||||
headers: {
|
headers: {
|
||||||
'anthropic-beta': 'output-128k-2025-02-19'
|
'anthropic-beta': 'output-128k-2025-02-19'
|
||||||
}
|
},
|
||||||
|
fetch: this.createProxyFetch()
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError('client initialization', error);
|
this.handleError('client initialization', error);
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ export class AzureProvider extends BaseAIProvider {
|
|||||||
|
|
||||||
return createAzure({
|
return createAzure({
|
||||||
apiKey,
|
apiKey,
|
||||||
baseURL
|
baseURL,
|
||||||
|
fetch: this.createProxyFetch()
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError('client initialization', error);
|
this.handleError('client initialization', error);
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import {
|
|||||||
NoObjectGeneratedError
|
NoObjectGeneratedError
|
||||||
} from 'ai';
|
} from 'ai';
|
||||||
import { jsonrepair } from 'jsonrepair';
|
import { jsonrepair } from 'jsonrepair';
|
||||||
import { log } from '../../scripts/modules/utils.js';
|
import { log, findProjectRoot } from '../../scripts/modules/utils.js';
|
||||||
|
import { isProxyEnabled } from '../../scripts/modules/config-manager.js';
|
||||||
|
import { EnvHttpProxyAgent } from 'undici';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all AI providers
|
* Base class for all AI providers
|
||||||
@@ -22,6 +24,9 @@ export class BaseAIProvider {
|
|||||||
// Each provider must set their name
|
// Each provider must set their name
|
||||||
this.name = this.constructor.name;
|
this.name = this.constructor.name;
|
||||||
|
|
||||||
|
// Cache proxy agent to avoid creating multiple instances
|
||||||
|
this._proxyAgent = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this provider needs explicit schema in JSON mode
|
* Whether this provider needs explicit schema in JSON mode
|
||||||
* Can be overridden by subclasses
|
* Can be overridden by subclasses
|
||||||
@@ -48,6 +53,37 @@ export class BaseAIProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a custom fetch function with proxy support.
|
||||||
|
* Only enables proxy when TASKMASTER_ENABLE_PROXY environment variable is set to 'true'
|
||||||
|
* or enableProxy is set to true in config.json.
|
||||||
|
* Automatically reads http_proxy/https_proxy environment variables when enabled.
|
||||||
|
* @returns {Function} Custom fetch function with proxy support, or undefined if proxy is disabled
|
||||||
|
*/
|
||||||
|
createProxyFetch() {
|
||||||
|
// Cache project root to avoid repeated lookups
|
||||||
|
if (!this._projectRoot) {
|
||||||
|
this._projectRoot = findProjectRoot();
|
||||||
|
}
|
||||||
|
const projectRoot = this._projectRoot;
|
||||||
|
|
||||||
|
if (!isProxyEnabled(null, projectRoot)) {
|
||||||
|
// Return undefined to use default fetch without proxy
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proxy is enabled, create and return proxy fetch
|
||||||
|
if (!this._proxyAgent) {
|
||||||
|
this._proxyAgent = new EnvHttpProxyAgent();
|
||||||
|
}
|
||||||
|
return (url, options = {}) => {
|
||||||
|
return fetch(url, {
|
||||||
|
...options,
|
||||||
|
dispatcher: this._proxyAgent
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates common parameters across all methods
|
* Validates common parameters across all methods
|
||||||
* @param {object} params - Parameters to validate
|
* @param {object} params - Parameters to validate
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ export class BedrockAIProvider extends BaseAIProvider {
|
|||||||
const credentialProvider = fromNodeProviderChain();
|
const credentialProvider = fromNodeProviderChain();
|
||||||
|
|
||||||
return createAmazonBedrock({
|
return createAmazonBedrock({
|
||||||
credentialProvider
|
credentialProvider,
|
||||||
|
fetch: this.createProxyFetch()
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError('client initialization', error);
|
this.handleError('client initialization', error);
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ export class VertexAIProvider extends BaseAIProvider {
|
|||||||
...authOptions,
|
...authOptions,
|
||||||
projectId,
|
projectId,
|
||||||
location,
|
location,
|
||||||
...(baseURL && { baseURL })
|
...(baseURL && { baseURL }),
|
||||||
|
fetch: this.createProxyFetch()
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError('client initialization', error);
|
this.handleError('client initialization', error);
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ export class GoogleAIProvider extends BaseAIProvider {
|
|||||||
|
|
||||||
return createGoogleGenerativeAI({
|
return createGoogleGenerativeAI({
|
||||||
apiKey,
|
apiKey,
|
||||||
...(baseURL && { baseURL })
|
...(baseURL && { baseURL }),
|
||||||
|
fetch: this.createProxyFetch()
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError('client initialization', error);
|
this.handleError('client initialization', error);
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ export class OpenAICompatibleProvider extends BaseAIProvider {
|
|||||||
|
|
||||||
const clientConfig = {
|
const clientConfig = {
|
||||||
// Provider name for SDK (required, used for logging/debugging)
|
// Provider name for SDK (required, used for logging/debugging)
|
||||||
name: this.name.toLowerCase().replace(/[^a-z0-9]/g, '-')
|
name: this.name.toLowerCase().replace(/[^a-z0-9]/g, '-'),
|
||||||
|
// Add proxy support
|
||||||
|
fetch: this.createProxyFetch()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only include apiKey if provider requires it
|
// Only include apiKey if provider requires it
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ export class OpenAIProvider extends BaseAIProvider {
|
|||||||
|
|
||||||
return createOpenAI({
|
return createOpenAI({
|
||||||
apiKey,
|
apiKey,
|
||||||
...(baseURL && { baseURL })
|
...(baseURL && { baseURL }),
|
||||||
|
fetch: this.createProxyFetch()
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError('client initialization', error);
|
this.handleError('client initialization', error);
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ export class PerplexityAIProvider extends BaseAIProvider {
|
|||||||
|
|
||||||
return createPerplexity({
|
return createPerplexity({
|
||||||
apiKey,
|
apiKey,
|
||||||
baseURL: baseURL || 'https://api.perplexity.ai'
|
baseURL: baseURL || 'https://api.perplexity.ai',
|
||||||
|
fetch: this.createProxyFetch()
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError('client initialization', error);
|
this.handleError('client initialization', error);
|
||||||
|
|||||||
@@ -10,7 +10,13 @@ jest.unstable_mockModule('@ai-sdk/openai-compatible', () => ({
|
|||||||
// Mock utils
|
// Mock utils
|
||||||
jest.unstable_mockModule('../../../scripts/modules/utils.js', () => ({
|
jest.unstable_mockModule('../../../scripts/modules/utils.js', () => ({
|
||||||
log: jest.fn(),
|
log: jest.fn(),
|
||||||
resolveEnvVariable: jest.fn((key) => process.env[key])
|
resolveEnvVariable: jest.fn((key) => process.env[key]),
|
||||||
|
findProjectRoot: jest.fn(() => process.cwd()),
|
||||||
|
isEmpty: jest.fn(() => false)
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.unstable_mockModule('../../../scripts/modules/config-manager.js', () => ({
|
||||||
|
isProxyEnabled: jest.fn(() => false)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Import after mocking
|
// Import after mocking
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ jest.mock('chalk', () => ({
|
|||||||
blue: jest.fn((text) => text),
|
blue: jest.fn((text) => text),
|
||||||
green: jest.fn((text) => text),
|
green: jest.fn((text) => text),
|
||||||
yellow: jest.fn((text) => text),
|
yellow: jest.fn((text) => text),
|
||||||
white: jest.fn((text) => ({
|
white: jest.fn(() => ({
|
||||||
bold: jest.fn((text) => text)
|
bold: jest.fn((text) => text)
|
||||||
})),
|
})),
|
||||||
reset: jest.fn((text) => text),
|
reset: jest.fn((text) => text),
|
||||||
@@ -70,13 +70,13 @@ const realSupportedModelsPath = path.resolve(
|
|||||||
'../../scripts/modules/supported-models.json'
|
'../../scripts/modules/supported-models.json'
|
||||||
);
|
);
|
||||||
let REAL_SUPPORTED_MODELS_CONTENT;
|
let REAL_SUPPORTED_MODELS_CONTENT;
|
||||||
let REAL_SUPPORTED_MODELS_DATA;
|
let _REAL_SUPPORTED_MODELS_DATA;
|
||||||
try {
|
try {
|
||||||
REAL_SUPPORTED_MODELS_CONTENT = fs.readFileSync(
|
REAL_SUPPORTED_MODELS_CONTENT = fs.readFileSync(
|
||||||
realSupportedModelsPath,
|
realSupportedModelsPath,
|
||||||
'utf-8'
|
'utf-8'
|
||||||
);
|
);
|
||||||
REAL_SUPPORTED_MODELS_DATA = JSON.parse(REAL_SUPPORTED_MODELS_CONTENT);
|
_REAL_SUPPORTED_MODELS_DATA = JSON.parse(REAL_SUPPORTED_MODELS_CONTENT);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(
|
console.error(
|
||||||
'FATAL TEST SETUP ERROR: Could not read or parse real supported-models.json',
|
'FATAL TEST SETUP ERROR: Could not read or parse real supported-models.json',
|
||||||
@@ -146,6 +146,7 @@ const DEFAULT_CONFIG = {
|
|||||||
ollamaBaseURL: 'http://localhost:11434/api',
|
ollamaBaseURL: 'http://localhost:11434/api',
|
||||||
bedrockBaseURL: 'https://bedrock.us-east-1.amazonaws.com',
|
bedrockBaseURL: 'https://bedrock.us-east-1.amazonaws.com',
|
||||||
enableCodebaseAnalysis: true,
|
enableCodebaseAnalysis: true,
|
||||||
|
enableProxy: false,
|
||||||
responseLanguage: 'English'
|
responseLanguage: 'English'
|
||||||
},
|
},
|
||||||
claudeCode: {},
|
claudeCode: {},
|
||||||
|
|||||||
Reference in New Issue
Block a user