Files
claude-task-master/src/ai-providers/google-vertex.js
Oren Me b53065713c feat: add support for MCP Sampling as AI provider (#863)
* feat: support MCP sampling

* support provider registry

* use standard config options for MCP provider

* update fastmcp to support passing params to requestSampling

* move key name definition to base provider

* moved check for required api key to provider class

* remove unused code

* more cleanup

* more cleanup

* refactor provider

* remove not needed files

* more cleanup

* more cleanup

* more cleanup

* update docs

* fix tests

* add tests

* format fix

* clean files

* merge fixes

* format fix

* feat: add support for MCP Sampling as AI provider

* initial mcp ai sdk

* fix references to old provider

* update models

* lint

* fix gemini-cli conflicts

* ran format

* Update src/provider-registry/index.js

Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>

* fix circular dependency

Circular Dependency Issue  FIXED
Root Cause: BaseAIProvider was importing from index.js, which includes commands.js and other modules that eventually import back to AI providers
Solution: Changed imports to use direct paths to avoid circular dependencies:
Updated base-provider.js to import log directly from utils.js
Updated gemini-cli.js to import log directly from utils.js
Result: Fixed 11 failing tests in mcp-provider.test.js

* fix gemini test

* fix(claude-code): recover from CLI JSON truncation bug (#913) (#920)

Gracefully handle SyntaxError thrown by @anthropic-ai/claude-code when the CLI truncates large JSON outputs (4–16 kB cut-offs).\n\nKey points:\n• Detect JSON parse error + existing buffered text in both doGenerate() and doStream() code paths.\n• Convert the failure into a recoverable 'truncated' finish state and push a provider-warning.\n• Allows Task Master to continue parsing long PRDs / expand-task operations instead of crashing.\n\nA patch changeset (.changeset/claude-code-json-truncation.md) is included for the next release.\n\nRef: eyaltoledano/claude-task-master#913

* docs: fix gemini-cli authentication documentation (#923)

Remove erroneous 'gemini auth login' command references and replace with correct 'gemini' command authentication flow. Update documentation to reflect proper OAuth setup process via the gemini CLI interactive interface.

* fix tests

* fix: update ai-sdk-provider-gemini-cli to 0.0.4 for improved authentication (#932)

- Fixed authentication compatibility issues with Google auth
- Added support for 'api-key' auth type alongside 'gemini-api-key'
- Resolved "Unsupported authType: undefined" runtime errors
- Updated @google/gemini-cli-core dependency to 0.1.9
- Improved documentation and removed invalid auth references
- Maintained backward compatibility while enhancing type validation

* call logging directly

Need to patch upstream fastmcp to allow easier access and bootstrap the TM mcp logger to use the fastmcp logger which today is only exposed in the tools handler

* fix tests

* removing logs until we figure out how to pass mcp logger

* format

* fix tests

* format

* clean up

* cleanup

* readme fix

---------

Co-authored-by: Oren Melamed <oren.m@gloat.com>
Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
Co-authored-by: Ben Vargas <ben@vargas.com>
2025-07-09 10:54:38 +02:00

159 lines
4.4 KiB
JavaScript

/**
* google-vertex.js
* AI provider implementation for Google Vertex AI models using Vercel AI SDK.
*/
import { createVertex } from '@ai-sdk/google-vertex';
import { BaseAIProvider } from './base-provider.js';
import { resolveEnvVariable } from '../../scripts/modules/utils.js';
import { log } from '../../scripts/modules/utils.js';
// Vertex-specific error classes
class VertexAuthError extends Error {
constructor(message) {
super(message);
this.name = 'VertexAuthError';
this.code = 'vertex_auth_error';
}
}
class VertexConfigError extends Error {
constructor(message) {
super(message);
this.name = 'VertexConfigError';
this.code = 'vertex_config_error';
}
}
class VertexApiError extends Error {
constructor(message, statusCode) {
super(message);
this.name = 'VertexApiError';
this.code = 'vertex_api_error';
this.statusCode = statusCode;
}
}
export class VertexAIProvider extends BaseAIProvider {
constructor() {
super();
this.name = 'Google Vertex AI';
}
/**
* Returns the required API key environment variable name for Google Vertex AI.
* @returns {string} The environment variable name
*/
getRequiredApiKeyName() {
return 'GOOGLE_API_KEY';
}
/**
* Validates Vertex AI-specific authentication parameters
* @param {object} params - Parameters to validate
* @throws {Error} If required parameters are missing
*/
validateAuth(params) {
const { apiKey, projectId, location, credentials } = params;
// Check for API key OR service account credentials
if (!apiKey && !credentials) {
throw new VertexAuthError(
'Either Google API key (GOOGLE_API_KEY) or service account credentials (GOOGLE_APPLICATION_CREDENTIALS) is required for Vertex AI'
);
}
// Project ID is required for Vertex AI
if (!projectId) {
throw new VertexConfigError(
'Google Cloud project ID is required for Vertex AI. Set VERTEX_PROJECT_ID environment variable.'
);
}
// Location is required for Vertex AI
if (!location) {
throw new VertexConfigError(
'Google Cloud location is required for Vertex AI. Set VERTEX_LOCATION environment variable (e.g., "us-central1").'
);
}
}
/**
* Creates and returns a Google Vertex AI client instance.
* @param {object} params - Parameters for client initialization
* @param {string} [params.apiKey] - Google API key
* @param {string} params.projectId - Google Cloud project ID
* @param {string} params.location - Google Cloud location (e.g., "us-central1")
* @param {object} [params.credentials] - Service account credentials object
* @param {string} [params.baseURL] - Optional custom API endpoint
* @returns {Function} Google Vertex AI client function
* @throws {Error} If required parameters are missing or initialization fails
*/
getClient(params) {
try {
// Validate required parameters
this.validateAuth(params);
const { apiKey, projectId, location, credentials, baseURL } = params;
// Configure auth options - either API key or service account
const authOptions = {};
if (apiKey) {
authOptions.apiKey = apiKey;
} else if (credentials) {
authOptions.googleAuthOptions = credentials;
}
// Return Vertex AI client
return createVertex({
...authOptions,
projectId,
location,
...(baseURL && { baseURL })
});
} catch (error) {
this.handleError('client initialization', error);
}
}
/**
* Handle errors from Vertex AI
* @param {string} operation - Description of the operation that failed
* @param {Error} error - The error object
* @throws {Error} Rethrows the error with additional context
*/
handleError(operation, error) {
log('error', `Vertex AI ${operation} error:`, error);
// Handle known error types
if (
error.name === 'VertexAuthError' ||
error.name === 'VertexConfigError' ||
error.name === 'VertexApiError'
) {
throw error;
}
// Handle network/API errors
if (error.response) {
const statusCode = error.response.status;
const errorMessage = error.response.data?.error?.message || error.message;
// Categorize by status code
if (statusCode === 401 || statusCode === 403) {
throw new VertexAuthError(`Authentication failed: ${errorMessage}`);
} else if (statusCode === 400) {
throw new VertexConfigError(`Invalid request: ${errorMessage}`);
} else {
throw new VertexApiError(
`API error (${statusCode}): ${errorMessage}`,
statusCode
);
}
}
// Generic error handling
throw new Error(`Vertex AI ${operation} failed: ${error.message}`);
}
}