npm-ai-hooks 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/Readme.md +379 -137
- package/dist/cjs/index.js +14 -0
- package/dist/cjs/providers/base/BaseProvider.js +121 -0
- package/dist/cjs/providers/base/ProviderConfig.js +118 -0
- package/dist/cjs/providers/base/ProviderConfigs.js +185 -0
- package/dist/cjs/providers/base/ProviderRegistry.js +47 -0
- package/dist/cjs/providers/base/SpecializedProviders.js +58 -0
- package/dist/cjs/providers/index.js +82 -0
- package/dist/cjs/providers/init.js +90 -0
- package/dist/{wrap.js → cjs/wrap.js} +43 -12
- package/dist/esm/errors.js +17 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/providers/base/BaseProvider.js +114 -0
- package/dist/esm/providers/base/ProviderConfig.js +114 -0
- package/dist/esm/providers/base/ProviderConfigs.js +182 -0
- package/dist/esm/providers/base/ProviderRegistry.js +43 -0
- package/dist/esm/providers/base/SpecializedProviders.js +52 -0
- package/dist/esm/providers/index.js +75 -0
- package/dist/esm/providers/init.js +81 -0
- package/dist/esm/types/claude.js +4 -0
- package/dist/esm/types/core/providers.js +1 -0
- package/dist/esm/types/deepseek.js +4 -0
- package/dist/esm/types/gemini.js +4 -0
- package/dist/esm/types/groq.js +1 -0
- package/dist/esm/types/index.js +20 -0
- package/dist/esm/types/mistral.js +4 -0
- package/dist/esm/types/openai.js +4 -0
- package/dist/esm/types/openrouter.js +1 -0
- package/dist/esm/types/perplexity.js +4 -0
- package/dist/esm/types/xai.js +4 -0
- package/dist/esm/wrap.js +113 -0
- package/dist/index.d.ts +1 -0
- package/dist/providers/base/BaseProvider.d.ts +33 -0
- package/dist/providers/base/ProviderConfig.d.ts +28 -0
- package/dist/providers/base/ProviderConfigs.d.ts +31 -0
- package/dist/providers/base/ProviderRegistry.d.ts +12 -0
- package/dist/providers/base/SpecializedProviders.d.ts +68 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/init.d.ts +58 -0
- package/package.json +50 -12
- package/dist/index.js +0 -6
- package/dist/providers/claude.d.ts +0 -2
- package/dist/providers/claude.js +0 -60
- package/dist/providers/deepkseek.d.ts +0 -2
- package/dist/providers/deepkseek.js +0 -57
- package/dist/providers/gemini.d.ts +0 -2
- package/dist/providers/gemini.js +0 -58
- package/dist/providers/groq.d.ts +0 -2
- package/dist/providers/groq.js +0 -57
- package/dist/providers/index.js +0 -75
- package/dist/providers/mistral.d.ts +0 -2
- package/dist/providers/mistral.js +0 -57
- package/dist/providers/openai.d.ts +0 -2
- package/dist/providers/openai.js +0 -57
- package/dist/providers/openrouter.d.ts +0 -1
- package/dist/providers/openrouter.js +0 -55
- package/dist/providers/perplexity.d.ts +0 -2
- package/dist/providers/perplexity.js +0 -57
- package/dist/providers/xai.d.ts +0 -2
- package/dist/providers/xai.js +0 -57
- /package/dist/{errors.js → cjs/errors.js} +0 -0
- /package/dist/{types → cjs/types}/claude.js +0 -0
- /package/dist/{types → cjs/types}/core/providers.js +0 -0
- /package/dist/{types → cjs/types}/deepseek.js +0 -0
- /package/dist/{types → cjs/types}/gemini.js +0 -0
- /package/dist/{types → cjs/types}/groq.js +0 -0
- /package/dist/{types → cjs/types}/index.js +0 -0
- /package/dist/{types → cjs/types}/mistral.js +0 -0
- /package/dist/{types → cjs/types}/openai.js +0 -0
- /package/dist/{types → cjs/types}/openrouter.js +0 -0
- /package/dist/{types → cjs/types}/perplexity.js +0 -0
- /package/dist/{types → cjs/types}/xai.js +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { BaseProvider } from "./BaseProvider";
|
|
2
|
+
import { providerConfigs } from "./ProviderConfigs";
|
|
3
|
+
import { AIHookError } from "../../errors";
|
|
4
|
+
// Claude provider with custom auth headers
|
|
5
|
+
export class ClaudeProvider extends BaseProvider {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(providerConfigs.claude);
|
|
8
|
+
}
|
|
9
|
+
buildAuthHeaders(apiKey) {
|
|
10
|
+
return {
|
|
11
|
+
"x-api-key": apiKey,
|
|
12
|
+
"anthropic-version": "2023-06-01"
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
// Gemini provider with custom URL and auth
|
|
17
|
+
export class GeminiProvider extends BaseProvider {
|
|
18
|
+
constructor() {
|
|
19
|
+
super(providerConfigs.gemini);
|
|
20
|
+
}
|
|
21
|
+
buildRequestConfig(prompt, model, apiKey) {
|
|
22
|
+
const baseConfig = super.buildRequestConfig(prompt, model, apiKey);
|
|
23
|
+
return {
|
|
24
|
+
...baseConfig,
|
|
25
|
+
url: `${this.config.baseUrl}/${model}:generateContent?key=${apiKey}`,
|
|
26
|
+
headers: {
|
|
27
|
+
...baseConfig.headers,
|
|
28
|
+
// Remove Authorization header for Gemini
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
buildAuthHeaders() {
|
|
33
|
+
return {}; // Gemini uses API key in URL
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// OpenRouter provider with custom error handling
|
|
37
|
+
export class OpenRouterProvider extends BaseProvider {
|
|
38
|
+
constructor() {
|
|
39
|
+
super(providerConfigs.openrouter);
|
|
40
|
+
}
|
|
41
|
+
handleHttpError(error) {
|
|
42
|
+
const status = error.response.status;
|
|
43
|
+
const text = error.response.data?.error
|
|
44
|
+
? JSON.stringify(error.response.data.error)
|
|
45
|
+
: error.response.statusText || "Unknown error";
|
|
46
|
+
const providerName = this.config.name;
|
|
47
|
+
if (status === 403) {
|
|
48
|
+
return new AIHookError("MODEL_NOT_ALLOWED", `Your API key cannot access this model: ${text}`, providerName, "Try a different model or check API key permissions");
|
|
49
|
+
}
|
|
50
|
+
return super.handleHttpError(error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AIHookError } from "../errors";
|
|
2
|
+
import { providerRegistry } from "./base/ProviderRegistry";
|
|
3
|
+
import { providerConfigs } from "./base/ProviderConfigs";
|
|
4
|
+
import { BaseProvider } from "./base/BaseProvider";
|
|
5
|
+
import { ClaudeProvider, GeminiProvider, OpenRouterProvider } from "./base/SpecializedProviders";
|
|
6
|
+
// Import the new initialization system
|
|
7
|
+
import { initAIHooks, addProvider, removeProvider, getAvailableProviders as getNewAvailableProviders, getProvider as getNewProvider, isInitialized, reset } from "./init";
|
|
8
|
+
// Initialize all providers (legacy environment-based system)
|
|
9
|
+
function initializeProviders() {
|
|
10
|
+
// Standard providers using BaseProvider
|
|
11
|
+
const standardProviders = ['openai', 'groq', 'deepseek', 'mistral', 'xai', 'perplexity'];
|
|
12
|
+
standardProviders.forEach(providerName => {
|
|
13
|
+
const config = providerConfigs[providerName];
|
|
14
|
+
if (config) {
|
|
15
|
+
const provider = new BaseProvider(config);
|
|
16
|
+
providerRegistry.register(providerName, provider);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
// Specialized providers
|
|
20
|
+
providerRegistry.register("claude", new ClaudeProvider());
|
|
21
|
+
providerRegistry.register("gemini", new GeminiProvider());
|
|
22
|
+
providerRegistry.register("openrouter", new OpenRouterProvider());
|
|
23
|
+
}
|
|
24
|
+
// Initialize providers on module load (legacy)
|
|
25
|
+
initializeProviders();
|
|
26
|
+
// Legacy compatibility - create the old provider map
|
|
27
|
+
const providers = {
|
|
28
|
+
openrouter: providerRegistry.get("openrouter"),
|
|
29
|
+
groq: providerRegistry.get("groq"),
|
|
30
|
+
openai: providerRegistry.get("openai"),
|
|
31
|
+
gemini: providerRegistry.get("gemini"),
|
|
32
|
+
claude: providerRegistry.get("claude"),
|
|
33
|
+
deepseek: providerRegistry.get("deepseek"),
|
|
34
|
+
xai: providerRegistry.get("xai"),
|
|
35
|
+
perplexity: providerRegistry.get("perplexity"),
|
|
36
|
+
mistral: providerRegistry.get("mistral"),
|
|
37
|
+
mock: async (prompt, model) => `[MOCK OUTPUT] ${prompt}`
|
|
38
|
+
};
|
|
39
|
+
// Returns an array of providers whose API keys exist in environment (legacy)
|
|
40
|
+
export function getAvailableProviders() {
|
|
41
|
+
// If new system is initialized, use it
|
|
42
|
+
if (isInitialized()) {
|
|
43
|
+
return getNewAvailableProviders();
|
|
44
|
+
}
|
|
45
|
+
// Otherwise use legacy system
|
|
46
|
+
return providerRegistry.getAvailableProviders();
|
|
47
|
+
}
|
|
48
|
+
// Returns both the provider function and the actual provider name (legacy)
|
|
49
|
+
export function getProvider(name) {
|
|
50
|
+
// If new system is initialized, use it
|
|
51
|
+
if (isInitialized()) {
|
|
52
|
+
const result = getNewProvider(name);
|
|
53
|
+
return { fn: result.fn, provider: result.provider };
|
|
54
|
+
}
|
|
55
|
+
// Otherwise use legacy system
|
|
56
|
+
const available = getAvailableProviders();
|
|
57
|
+
// 1. If user specified provider and it's available
|
|
58
|
+
if (name && providers[name]) {
|
|
59
|
+
return { fn: providers[name], provider: name };
|
|
60
|
+
}
|
|
61
|
+
// 2. If at least one provider is available, pick the first one (openrouter always preferred if present)
|
|
62
|
+
if (available.length > 0) {
|
|
63
|
+
// Only log in non-test environments to avoid Jest warnings
|
|
64
|
+
if (process.env.NODE_ENV !== "test" && !process.env.JEST_WORKER_ID) {
|
|
65
|
+
console.log(`[ai-hooks] ✅ Auto-selected provider: ${available[0]}`);
|
|
66
|
+
}
|
|
67
|
+
return { fn: providers[available[0]], provider: available[0] };
|
|
68
|
+
}
|
|
69
|
+
// 3. No valid keys found → throw error (single instruction, no fallback)
|
|
70
|
+
throw new AIHookError("NO_PROVIDER_FOUND", "No valid AI provider API key was found.\n\nAt least one provider API key is required in your .env file.\n\nPlease add one of the following to your .env (see .env.example for details):\n - AI_HOOK_OPENAI_KEY\n - AI_HOOK_OPENROUTER_KEY\n - AI_HOOK_GROQ_KEY\n", undefined, "Reference .env.example for setup instructions.");
|
|
71
|
+
}
|
|
72
|
+
// Export the new initialization system
|
|
73
|
+
export { initAIHooks, addProvider, removeProvider, isInitialized, reset };
|
|
74
|
+
// Export the registry for advanced usage (legacy)
|
|
75
|
+
export { providerRegistry };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ProviderManager } from "./base/ProviderConfig";
|
|
2
|
+
// Global provider manager instance
|
|
3
|
+
let providerManager = null;
|
|
4
|
+
/**
|
|
5
|
+
* Initialize the AI hooks system with provider configurations
|
|
6
|
+
* @param options - Provider initialization options
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { initAIHooks } from 'npm-ai-hooks';
|
|
10
|
+
*
|
|
11
|
+
* initAIHooks({
|
|
12
|
+
* providers: [
|
|
13
|
+
* { provider: 'openai', key: 'sk-...', defaultModel: 'gpt-4' },
|
|
14
|
+
* { provider: 'claude', key: 'sk-ant-...', defaultModel: 'claude-3-sonnet-20240229' },
|
|
15
|
+
* { provider: 'groq', key: 'gsk_...', defaultModel: 'llama-3.1-70b-versatile' }
|
|
16
|
+
* ],
|
|
17
|
+
* defaultProvider: 'openai' // optional
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function initAIHooks(options) {
|
|
22
|
+
providerManager = new ProviderManager(options);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Add a new provider after initialization
|
|
26
|
+
* @param config - Provider configuration
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* addProvider({ provider: 'mistral', key: '...', defaultModel: 'mistral-large' });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function addProvider(config) {
|
|
33
|
+
if (!providerManager) {
|
|
34
|
+
throw new Error('AI hooks not initialized. Call initAIHooks() first.');
|
|
35
|
+
}
|
|
36
|
+
providerManager.addProvider(config);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Remove a provider
|
|
40
|
+
* @param provider - Provider to remove
|
|
41
|
+
*/
|
|
42
|
+
export function removeProvider(provider) {
|
|
43
|
+
if (!providerManager) {
|
|
44
|
+
throw new Error('AI hooks not initialized. Call initAIHooks() first.');
|
|
45
|
+
}
|
|
46
|
+
providerManager.removeProvider(provider);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get available providers
|
|
50
|
+
* @returns Array of available provider names
|
|
51
|
+
*/
|
|
52
|
+
export function getAvailableProviders() {
|
|
53
|
+
if (!providerManager) {
|
|
54
|
+
throw new Error('AI hooks not initialized. Call initAIHooks() first.');
|
|
55
|
+
}
|
|
56
|
+
return providerManager.getAvailableProviders();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get a provider function
|
|
60
|
+
* @param name - Optional provider name
|
|
61
|
+
* @returns Provider function and name
|
|
62
|
+
*/
|
|
63
|
+
export function getProvider(name) {
|
|
64
|
+
if (!providerManager) {
|
|
65
|
+
throw new Error('AI hooks not initialized. Call initAIHooks() first.');
|
|
66
|
+
}
|
|
67
|
+
return providerManager.getProvider(name);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check if AI hooks is initialized
|
|
71
|
+
* @returns True if initialized
|
|
72
|
+
*/
|
|
73
|
+
export function isInitialized() {
|
|
74
|
+
return providerManager !== null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Reset the provider manager (useful for testing)
|
|
78
|
+
*/
|
|
79
|
+
export function reset() {
|
|
80
|
+
providerManager = null;
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const GroqDefaultModel = "groq/compound";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OpenAIDefaultModel } from "./openai";
|
|
2
|
+
import { OpenRouterDefaultModel } from "./openrouter";
|
|
3
|
+
import { GroqDefaultModel } from "./groq";
|
|
4
|
+
import { GeminiDefaultModel } from "./gemini";
|
|
5
|
+
import { ClaudeDefaultModel } from "./claude";
|
|
6
|
+
import { DeepSeekDefaultModel } from "./deepseek";
|
|
7
|
+
import { XAIDefaultModel } from "./xai";
|
|
8
|
+
import { PerplexityDefaultModel } from "./perplexity";
|
|
9
|
+
import { MistralDefaultModel } from "./mistral";
|
|
10
|
+
export const DEFAULT_MODEL = {
|
|
11
|
+
openrouter: OpenRouterDefaultModel,
|
|
12
|
+
groq: GroqDefaultModel,
|
|
13
|
+
openai: OpenAIDefaultModel,
|
|
14
|
+
gemini: GeminiDefaultModel,
|
|
15
|
+
claude: ClaudeDefaultModel,
|
|
16
|
+
deepseek: DeepSeekDefaultModel,
|
|
17
|
+
xai: XAIDefaultModel,
|
|
18
|
+
perplexity: PerplexityDefaultModel,
|
|
19
|
+
mistral: MistralDefaultModel
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const OpenRouterDefaultModel = "openai/gpt-oss-20b:free";
|
package/dist/esm/wrap.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// dotenv removed - using explicit provider initialization instead
|
|
2
|
+
import { getProvider } from "./providers";
|
|
3
|
+
import { DEFAULT_MODEL } from "./types";
|
|
4
|
+
import { AIHookError } from "./errors";
|
|
5
|
+
function handleError(err) {
|
|
6
|
+
if (err && typeof err === "object" && "pretty" in err && typeof err.pretty === "function") {
|
|
7
|
+
// Print pretty message
|
|
8
|
+
console.error(err.pretty());
|
|
9
|
+
// Only exit in Node.js test environment, not in browser
|
|
10
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "test" && !process.env.JEST_WORKER_ID) {
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
// In browser or test mode, just throw the error instead of exiting
|
|
14
|
+
throw err;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
console.error(err);
|
|
18
|
+
// Only exit in Node.js test environment, not in browser
|
|
19
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "test" && !process.env.JEST_WORKER_ID) {
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
// In browser or test mode, just throw the error instead of exiting
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function wrap(fn, options) {
|
|
27
|
+
// Validate task type immediately when wrap() is called
|
|
28
|
+
const validTasks = ["summarize", "translate", "explain", "rewrite", "sentiment", "codeReview"];
|
|
29
|
+
if (options.task && !validTasks.includes(options.task)) {
|
|
30
|
+
throw new AIHookError("INVALID_TASK", `Invalid task type: ${options.task}. Valid tasks are: ${validTasks.join(", ")}`, options.provider, "Please use one of the supported task types.");
|
|
31
|
+
}
|
|
32
|
+
return async (...args) => {
|
|
33
|
+
try {
|
|
34
|
+
const input = fn(...args);
|
|
35
|
+
// Step 1: get provider function and the actual provider name
|
|
36
|
+
const { fn: providerFn, provider: providerKey } = getProvider(options.provider);
|
|
37
|
+
// Step 2: pick model: passed model or provider-specific default
|
|
38
|
+
const model = options.model || (providerKey in DEFAULT_MODEL ? DEFAULT_MODEL[providerKey] : undefined);
|
|
39
|
+
if (!model) {
|
|
40
|
+
throw new AIHookError("NO_MODEL_FOUND", "No model found: You must specify a provider or pass a valid model.\n\nAt least one provider API key is required in your .env file.\n\nPlease add one of the following to your .env (see .env.example for details):\n - AI_HOOK_OPENAI_KEY\n - AI_HOOK_OPENROUTER_KEY\n - AI_HOOK_GROQ_KEY\n", options.provider, "Reference .env.example for setup instructions.");
|
|
41
|
+
}
|
|
42
|
+
// Step 3: build prompt
|
|
43
|
+
const prompt = buildPrompt(options.task, input, options.targetLanguage);
|
|
44
|
+
const startTime = Date.now();
|
|
45
|
+
let output;
|
|
46
|
+
try {
|
|
47
|
+
output = await providerFn(prompt, model);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
if (err instanceof AIHookError) {
|
|
51
|
+
// For AIHookError, just re-throw it - it will be handled by the outer catch
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
if (err instanceof Error) {
|
|
55
|
+
throw new Error(`[ai-hooks] Unknown error calling provider: ${err.message}`);
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`[ai-hooks] Unknown non-error thrown by provider: ${String(err)}`);
|
|
58
|
+
}
|
|
59
|
+
const endTime = Date.now();
|
|
60
|
+
return {
|
|
61
|
+
output,
|
|
62
|
+
meta: {
|
|
63
|
+
provider: providerKey,
|
|
64
|
+
model,
|
|
65
|
+
cached: false,
|
|
66
|
+
estimatedCostUSD: 0.0,
|
|
67
|
+
latencyMs: endTime - startTime
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
if (err instanceof AIHookError) {
|
|
73
|
+
// For AIHookError, just log the pretty message without the full error handling
|
|
74
|
+
console.error(err.pretty());
|
|
75
|
+
// Return a mock response to prevent the demo from crashing
|
|
76
|
+
return {
|
|
77
|
+
output: "Error occurred",
|
|
78
|
+
meta: {
|
|
79
|
+
provider: "unknown",
|
|
80
|
+
model: "unknown",
|
|
81
|
+
cached: false,
|
|
82
|
+
estimatedCostUSD: 0.0,
|
|
83
|
+
latencyMs: 0,
|
|
84
|
+
error: true
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
handleError(err);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function buildPrompt(task, text, targetLanguage) {
|
|
93
|
+
if (!task) {
|
|
94
|
+
return text; // If no task specified, just return the text as-is
|
|
95
|
+
}
|
|
96
|
+
switch (task) {
|
|
97
|
+
case "summarize":
|
|
98
|
+
return `Summarize the following text:\n${text}`;
|
|
99
|
+
case "translate":
|
|
100
|
+
const language = targetLanguage || "English"; // default to English
|
|
101
|
+
return `Translate this text into ${language}:\n${text}`;
|
|
102
|
+
case "explain":
|
|
103
|
+
return `Explain this clearly:\n${text}`;
|
|
104
|
+
case "rewrite":
|
|
105
|
+
return `Rewrite this text with better clarity:\n${text}`;
|
|
106
|
+
case "sentiment":
|
|
107
|
+
return `Analyze the sentiment of this text:\n${text}`;
|
|
108
|
+
case "codeReview":
|
|
109
|
+
return `Review this code and suggest improvements:\n${text}`;
|
|
110
|
+
default:
|
|
111
|
+
return text;
|
|
112
|
+
}
|
|
113
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AxiosRequestConfig, AxiosResponse } from "axios";
|
|
2
|
+
import { AIHookError } from "../../errors";
|
|
3
|
+
export interface ProviderConfig {
|
|
4
|
+
name: string;
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
envKey: string;
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
requestBody: (prompt: string, model: string) => any;
|
|
9
|
+
responseParser: (response: AxiosResponse) => string;
|
|
10
|
+
errorMessages: {
|
|
11
|
+
missingKey: string;
|
|
12
|
+
emptyResponse: string;
|
|
13
|
+
badRequest: string;
|
|
14
|
+
invalidKey: string;
|
|
15
|
+
rateLimit: string;
|
|
16
|
+
networkError: string;
|
|
17
|
+
unknownError: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export declare class BaseProvider {
|
|
21
|
+
protected config: ProviderConfig;
|
|
22
|
+
constructor(config: ProviderConfig);
|
|
23
|
+
call(prompt: string, model: string): Promise<string>;
|
|
24
|
+
protected getApiKey(): string | undefined;
|
|
25
|
+
protected validateApiKey(apiKey: string | undefined): void;
|
|
26
|
+
protected buildRequestConfig(prompt: string, model: string, apiKey: string): AxiosRequestConfig;
|
|
27
|
+
protected buildAuthHeaders(apiKey: string): Record<string, string>;
|
|
28
|
+
protected makeRequest(config: AxiosRequestConfig): Promise<AxiosResponse>;
|
|
29
|
+
protected parseResponse(response: AxiosResponse): string;
|
|
30
|
+
protected handleError(error: any): AIHookError;
|
|
31
|
+
protected getCapitalizedProviderName(): string;
|
|
32
|
+
protected handleHttpError(error: any): AIHookError;
|
|
33
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Provider } from "../../types";
|
|
2
|
+
export interface UserProviderConfig {
|
|
3
|
+
provider: Provider;
|
|
4
|
+
key: string;
|
|
5
|
+
defaultModel?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ProviderInitializationOptions {
|
|
8
|
+
providers: UserProviderConfig[];
|
|
9
|
+
defaultProvider?: Provider;
|
|
10
|
+
}
|
|
11
|
+
export declare class ProviderManager {
|
|
12
|
+
private providers;
|
|
13
|
+
private defaultProvider?;
|
|
14
|
+
private providerFunctions;
|
|
15
|
+
constructor(options: ProviderInitializationOptions);
|
|
16
|
+
private initializeProviders;
|
|
17
|
+
private createProviderFunctions;
|
|
18
|
+
private createProviderFunction;
|
|
19
|
+
private createProviderInstance;
|
|
20
|
+
private getDefaultModelForProvider;
|
|
21
|
+
getAvailableProviders(): Provider[];
|
|
22
|
+
getProvider(name?: Provider): {
|
|
23
|
+
fn: any;
|
|
24
|
+
provider: Provider;
|
|
25
|
+
};
|
|
26
|
+
addProvider(config: UserProviderConfig): void;
|
|
27
|
+
removeProvider(provider: Provider): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ProviderConfig } from "./BaseProvider";
|
|
2
|
+
export declare const responseParsers: {
|
|
3
|
+
openaiStyle: (response: any) => any;
|
|
4
|
+
claudeStyle: (response: any) => any;
|
|
5
|
+
geminiStyle: (response: any) => any;
|
|
6
|
+
};
|
|
7
|
+
export declare const requestBodyBuilders: {
|
|
8
|
+
openaiStyle: (prompt: string, model: string) => {
|
|
9
|
+
model: string;
|
|
10
|
+
messages: {
|
|
11
|
+
role: string;
|
|
12
|
+
content: string;
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
15
|
+
claudeStyle: (prompt: string, model: string) => {
|
|
16
|
+
model: string;
|
|
17
|
+
max_tokens: number;
|
|
18
|
+
messages: {
|
|
19
|
+
role: string;
|
|
20
|
+
content: string;
|
|
21
|
+
}[];
|
|
22
|
+
};
|
|
23
|
+
geminiStyle: (prompt: string, model: string) => {
|
|
24
|
+
contents: {
|
|
25
|
+
parts: {
|
|
26
|
+
text: string;
|
|
27
|
+
}[];
|
|
28
|
+
}[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export declare const providerConfigs: Record<string, ProviderConfig>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseProvider } from "./BaseProvider";
|
|
2
|
+
import { Provider } from "../../types";
|
|
3
|
+
import { ProviderFunction } from "../../types/core/providers";
|
|
4
|
+
export declare class ProviderRegistry {
|
|
5
|
+
private providers;
|
|
6
|
+
private providerFunctions;
|
|
7
|
+
register<T extends Provider>(name: T, provider: BaseProvider): void;
|
|
8
|
+
get(name: Provider): ProviderFunction<any> | undefined;
|
|
9
|
+
getAvailableProviders(): Provider[];
|
|
10
|
+
private createProviderFunction;
|
|
11
|
+
}
|
|
12
|
+
export declare const providerRegistry: ProviderRegistry;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { BaseProvider } from "./BaseProvider";
|
|
2
|
+
import { AIHookError } from "../../errors";
|
|
3
|
+
export declare class ClaudeProvider extends BaseProvider {
|
|
4
|
+
constructor();
|
|
5
|
+
protected buildAuthHeaders(apiKey: string): Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
export declare class GeminiProvider extends BaseProvider {
|
|
8
|
+
constructor();
|
|
9
|
+
protected buildRequestConfig(prompt: string, model: string, apiKey: string): {
|
|
10
|
+
url: string;
|
|
11
|
+
headers: {};
|
|
12
|
+
method?: import("axios").Method | string;
|
|
13
|
+
baseURL?: string;
|
|
14
|
+
allowAbsoluteUrls?: boolean;
|
|
15
|
+
transformRequest?: import("axios").AxiosRequestTransformer | import("axios").AxiosRequestTransformer[];
|
|
16
|
+
transformResponse?: import("axios").AxiosResponseTransformer | import("axios").AxiosResponseTransformer[];
|
|
17
|
+
params?: any;
|
|
18
|
+
paramsSerializer?: import("axios").ParamsSerializerOptions | import("axios").CustomParamsSerializer;
|
|
19
|
+
data?: any;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
timeoutErrorMessage?: string;
|
|
22
|
+
withCredentials?: boolean;
|
|
23
|
+
adapter?: (import("axios").AxiosAdapter | ("fetch" | "xhr" | "http" | (string & {}))) | (import("axios").AxiosAdapter | ("fetch" | "xhr" | "http" | (string & {})))[];
|
|
24
|
+
auth?: import("axios").AxiosBasicCredentials;
|
|
25
|
+
responseType?: import("axios").ResponseType;
|
|
26
|
+
responseEncoding?: import("axios").responseEncoding | string;
|
|
27
|
+
xsrfCookieName?: string;
|
|
28
|
+
xsrfHeaderName?: string;
|
|
29
|
+
onUploadProgress?: (progressEvent: import("axios").AxiosProgressEvent) => void;
|
|
30
|
+
onDownloadProgress?: (progressEvent: import("axios").AxiosProgressEvent) => void;
|
|
31
|
+
maxContentLength?: number;
|
|
32
|
+
validateStatus?: ((status: number) => boolean) | null;
|
|
33
|
+
maxBodyLength?: number;
|
|
34
|
+
maxRedirects?: number;
|
|
35
|
+
maxRate?: number | [number, number];
|
|
36
|
+
beforeRedirect?: (options: Record<string, any>, responseDetails: {
|
|
37
|
+
headers: Record<string, string>;
|
|
38
|
+
statusCode: import("axios").HttpStatusCode;
|
|
39
|
+
}) => void;
|
|
40
|
+
socketPath?: string | null;
|
|
41
|
+
transport?: any;
|
|
42
|
+
httpAgent?: any;
|
|
43
|
+
httpsAgent?: any;
|
|
44
|
+
proxy?: import("axios").AxiosProxyConfig | false;
|
|
45
|
+
cancelToken?: import("axios").CancelToken;
|
|
46
|
+
decompress?: boolean;
|
|
47
|
+
transitional?: import("axios").TransitionalOptions;
|
|
48
|
+
signal?: import("axios").GenericAbortSignal;
|
|
49
|
+
insecureHTTPParser?: boolean;
|
|
50
|
+
env?: {
|
|
51
|
+
FormData?: new (...args: any[]) => object;
|
|
52
|
+
fetch?: (input: URL | Request | string, init?: RequestInit) => Promise<Response>;
|
|
53
|
+
Request?: new (input: URL | Request | string, init?: RequestInit) => Request;
|
|
54
|
+
Response?: new (body?: ArrayBuffer | ArrayBufferView | Blob | FormData | URLSearchParams | string | null, init?: ResponseInit) => Response;
|
|
55
|
+
};
|
|
56
|
+
formSerializer?: import("axios").FormSerializerOptions;
|
|
57
|
+
family?: import("axios").AddressFamily;
|
|
58
|
+
lookup?: ((hostname: string, options: object, cb: (err: Error | null, address: import("axios").LookupAddress | import("axios").LookupAddress[], family?: import("axios").AddressFamily) => void) => void) | ((hostname: string, options: object) => Promise<[address: import("axios").LookupAddressEntry | import("axios").LookupAddressEntry[], family?: import("axios").AddressFamily] | import("axios").LookupAddress>);
|
|
59
|
+
withXSRFToken?: boolean | ((config: import("axios").InternalAxiosRequestConfig) => boolean | undefined);
|
|
60
|
+
parseReviver?: (this: any, key: string, value: any) => any;
|
|
61
|
+
fetchOptions?: Omit<RequestInit, "body" | "headers" | "method" | "signal"> | Record<string, any>;
|
|
62
|
+
};
|
|
63
|
+
protected buildAuthHeaders(): Record<string, string>;
|
|
64
|
+
}
|
|
65
|
+
export declare class OpenRouterProvider extends BaseProvider {
|
|
66
|
+
constructor();
|
|
67
|
+
protected handleHttpError(error: any): AIHookError;
|
|
68
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { Provider } from "../types";
|
|
2
2
|
import { ProviderFunction } from "../types/core/providers";
|
|
3
|
+
import { providerRegistry } from "./base/ProviderRegistry";
|
|
4
|
+
import { initAIHooks, addProvider, removeProvider, isInitialized, reset, UserProviderConfig, ProviderInitializationOptions } from "./init";
|
|
3
5
|
export declare function getAvailableProviders(): Provider[];
|
|
4
6
|
export declare function getProvider(name?: Provider): {
|
|
5
7
|
fn: ProviderFunction<any>;
|
|
6
8
|
provider: Provider | "mock";
|
|
7
9
|
};
|
|
10
|
+
export { initAIHooks, addProvider, removeProvider, isInitialized, reset, UserProviderConfig, ProviderInitializationOptions };
|
|
11
|
+
export { providerRegistry };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { UserProviderConfig, ProviderInitializationOptions } from "./base/ProviderConfig";
|
|
2
|
+
import { Provider } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Initialize the AI hooks system with provider configurations
|
|
5
|
+
* @param options - Provider initialization options
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { initAIHooks } from 'npm-ai-hooks';
|
|
9
|
+
*
|
|
10
|
+
* initAIHooks({
|
|
11
|
+
* providers: [
|
|
12
|
+
* { provider: 'openai', key: 'sk-...', defaultModel: 'gpt-4' },
|
|
13
|
+
* { provider: 'claude', key: 'sk-ant-...', defaultModel: 'claude-3-sonnet-20240229' },
|
|
14
|
+
* { provider: 'groq', key: 'gsk_...', defaultModel: 'llama-3.1-70b-versatile' }
|
|
15
|
+
* ],
|
|
16
|
+
* defaultProvider: 'openai' // optional
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function initAIHooks(options: ProviderInitializationOptions): void;
|
|
21
|
+
/**
|
|
22
|
+
* Add a new provider after initialization
|
|
23
|
+
* @param config - Provider configuration
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* addProvider({ provider: 'mistral', key: '...', defaultModel: 'mistral-large' });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function addProvider(config: UserProviderConfig): void;
|
|
30
|
+
/**
|
|
31
|
+
* Remove a provider
|
|
32
|
+
* @param provider - Provider to remove
|
|
33
|
+
*/
|
|
34
|
+
export declare function removeProvider(provider: Provider): void;
|
|
35
|
+
/**
|
|
36
|
+
* Get available providers
|
|
37
|
+
* @returns Array of available provider names
|
|
38
|
+
*/
|
|
39
|
+
export declare function getAvailableProviders(): Provider[];
|
|
40
|
+
/**
|
|
41
|
+
* Get a provider function
|
|
42
|
+
* @param name - Optional provider name
|
|
43
|
+
* @returns Provider function and name
|
|
44
|
+
*/
|
|
45
|
+
export declare function getProvider(name?: Provider): {
|
|
46
|
+
fn: any;
|
|
47
|
+
provider: Provider;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Check if AI hooks is initialized
|
|
51
|
+
* @returns True if initialized
|
|
52
|
+
*/
|
|
53
|
+
export declare function isInitialized(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Reset the provider manager (useful for testing)
|
|
56
|
+
*/
|
|
57
|
+
export declare function reset(): void;
|
|
58
|
+
export type { UserProviderConfig, ProviderInitializationOptions };
|