npm-ai-hooks 2.0.5 → 2.0.6
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/dist/cjs/providers/base/BaseProvider.js +10 -8
- package/dist/cjs/providers/base/ProviderConfigs.js +4 -1
- package/dist/cjs/providers/base/ProviderRegistry.js +3 -0
- package/dist/cjs/providers/index.js +4 -3
- package/dist/cjs/utils/keyValidator.js +9 -5
- package/dist/cjs/wrap.js +4 -2
- package/dist/esm/providers/base/BaseProvider.js +10 -8
- package/dist/esm/providers/base/ProviderConfigs.js +4 -1
- package/dist/esm/providers/base/ProviderRegistry.js +3 -0
- package/dist/esm/providers/index.js +4 -3
- package/dist/esm/utils/keyValidator.js +9 -5
- package/dist/esm/wrap.js +4 -2
- package/dist/providers/base/BaseProvider.d.ts +11 -5
- package/dist/providers/base/ProviderConfig.d.ts +2 -2
- package/dist/providers/base/ProviderConfigs.d.ts +5 -5
- package/dist/providers/base/SpecializedProviders.d.ts +8 -2
- package/dist/providers/init.d.ts +2 -2
- package/dist/wrap.d.ts +12 -2
- package/package.json +9 -4
|
@@ -61,7 +61,7 @@ class BaseProvider {
|
|
|
61
61
|
try {
|
|
62
62
|
data = await response.json();
|
|
63
63
|
}
|
|
64
|
-
catch
|
|
64
|
+
catch {
|
|
65
65
|
data = await response.text();
|
|
66
66
|
}
|
|
67
67
|
if (!response.ok) {
|
|
@@ -77,13 +77,14 @@ class BaseProvider {
|
|
|
77
77
|
return { data };
|
|
78
78
|
}
|
|
79
79
|
catch (error) {
|
|
80
|
+
const err = error;
|
|
80
81
|
// If it's already an HTTP error we just threw, rethrow it
|
|
81
|
-
if (
|
|
82
|
-
throw
|
|
82
|
+
if (err.response) {
|
|
83
|
+
throw err;
|
|
83
84
|
}
|
|
84
85
|
// Otherwise, it's a network error (e.g. fetch failed entirely)
|
|
85
86
|
// Emulate axios network error shape
|
|
86
|
-
throw Object.assign(new Error(
|
|
87
|
+
throw Object.assign(new Error(err.message || "Network Error"), {
|
|
87
88
|
request: {}
|
|
88
89
|
});
|
|
89
90
|
}
|
|
@@ -96,14 +97,15 @@ class BaseProvider {
|
|
|
96
97
|
return output;
|
|
97
98
|
}
|
|
98
99
|
handleError(error) {
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
const err = error;
|
|
101
|
+
if (err.response) {
|
|
102
|
+
return this.handleHttpError(err);
|
|
101
103
|
}
|
|
102
|
-
else if (
|
|
104
|
+
else if (err.request) {
|
|
103
105
|
return new errors_1.AIHookError("NETWORK_ERROR", this.config.errorMessages.networkError, this.config.name, "Check your internet connection");
|
|
104
106
|
}
|
|
105
107
|
else {
|
|
106
|
-
return new errors_1.AIHookError("UNKNOWN_ERROR",
|
|
108
|
+
return new errors_1.AIHookError("UNKNOWN_ERROR", err.message || this.config.errorMessages.unknownError, this.config.name);
|
|
107
109
|
}
|
|
108
110
|
}
|
|
109
111
|
getCapitalizedProviderName() {
|
|
@@ -3,8 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.providerConfigs = exports.requestBodyBuilders = exports.responseParsers = void 0;
|
|
4
4
|
// Common response parsers
|
|
5
5
|
exports.responseParsers = {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
7
|
openaiStyle: (response) => response.data?.choices?.[0]?.message?.content,
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
9
|
claudeStyle: (response) => response.data?.content?.[0]?.text,
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
11
|
geminiStyle: (response) => response.data?.candidates?.[0]?.content?.parts?.[0]?.text,
|
|
9
12
|
};
|
|
10
13
|
// Common request body builders
|
|
@@ -18,7 +21,7 @@ exports.requestBodyBuilders = {
|
|
|
18
21
|
max_tokens: 4096,
|
|
19
22
|
messages: [{ role: "user", content: prompt }]
|
|
20
23
|
}),
|
|
21
|
-
geminiStyle: (prompt,
|
|
24
|
+
geminiStyle: (prompt, _model) => ({
|
|
22
25
|
contents: [{
|
|
23
26
|
parts: [{ text: prompt }]
|
|
24
27
|
}]
|
|
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.providerRegistry = exports.ProviderRegistry = void 0;
|
|
4
4
|
class ProviderRegistry {
|
|
5
5
|
providers = new Map();
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
7
|
providerFunctions = new Map();
|
|
7
8
|
register(name, provider) {
|
|
8
9
|
this.providers.set(name, provider);
|
|
9
10
|
this.providerFunctions.set(name, this.createProviderFunction(provider));
|
|
10
11
|
}
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
13
|
get(name) {
|
|
12
14
|
return this.providerFunctions.get(name);
|
|
13
15
|
}
|
|
@@ -34,6 +36,7 @@ class ProviderRegistry {
|
|
|
34
36
|
}
|
|
35
37
|
return available;
|
|
36
38
|
}
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
40
|
createProviderFunction(provider) {
|
|
38
41
|
return async (prompt, model) => {
|
|
39
42
|
return provider.call(prompt, model);
|
|
@@ -46,7 +46,7 @@ const providers = {
|
|
|
46
46
|
xai: ProviderRegistry_1.providerRegistry.get("xai"),
|
|
47
47
|
perplexity: ProviderRegistry_1.providerRegistry.get("perplexity"),
|
|
48
48
|
mistral: ProviderRegistry_1.providerRegistry.get("mistral"),
|
|
49
|
-
mock: async (prompt,
|
|
49
|
+
mock: async (prompt, _model) => `[MOCK OUTPUT] ${prompt}`
|
|
50
50
|
};
|
|
51
51
|
// Returns an array of providers whose API keys exist in environment (legacy)
|
|
52
52
|
function getAvailableProviders() {
|
|
@@ -57,7 +57,7 @@ function getAvailableProviders() {
|
|
|
57
57
|
// Otherwise use legacy system
|
|
58
58
|
return ProviderRegistry_1.providerRegistry.getAvailableProviders();
|
|
59
59
|
}
|
|
60
|
-
//
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
61
|
function getProvider(name) {
|
|
62
62
|
// If new system is initialized, use it
|
|
63
63
|
if ((0, init_1.isInitialized)()) {
|
|
@@ -81,7 +81,7 @@ function getProvider(name) {
|
|
|
81
81
|
// 3. No valid keys found → throw error (single instruction, no fallback)
|
|
82
82
|
throw new errors_1.AIHookError("NO_PROVIDER_FOUND", "No valid AI provider API key was found.\n\nIf you are using a .env file, please ensure you have installed the 'dotenv' package (npm i dotenv) and called require('dotenv').config() at the very top of your entry file.\n\nAlternatively, you can initialize providers explicitly:\ninitAIHooks({ providers: [{ provider: 'openai', key: 'your-key-here' }] })", undefined, "Reference documentation for setup instructions.");
|
|
83
83
|
}
|
|
84
|
-
//
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
85
|
function getProviderChain(name) {
|
|
86
86
|
if ((0, init_1.isInitialized)()) {
|
|
87
87
|
return (0, init_1.getProviderChain)(name);
|
|
@@ -89,6 +89,7 @@ function getProviderChain(name) {
|
|
|
89
89
|
// Legacy fallback: wrap available providers into a chain
|
|
90
90
|
const available = getAvailableProviders();
|
|
91
91
|
const seen = new Set();
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
92
93
|
const chain = [];
|
|
93
94
|
const tryPush = (p) => {
|
|
94
95
|
if (!seen.has(p) && providers[p]) {
|
|
@@ -31,7 +31,7 @@ async function validateApiKey(provider, apiKey) {
|
|
|
31
31
|
case 'openrouter':
|
|
32
32
|
providerInstance = new SpecializedProviders_1.OpenRouterProvider();
|
|
33
33
|
break;
|
|
34
|
-
default:
|
|
34
|
+
default: {
|
|
35
35
|
const config = ProviderConfigs_1.providerConfigs[provider];
|
|
36
36
|
if (!config) {
|
|
37
37
|
return {
|
|
@@ -42,9 +42,12 @@ async function validateApiKey(provider, apiKey) {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
providerInstance = new BaseProvider_1.BaseProvider(config);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
45
47
|
}
|
|
46
48
|
// Set the API key temporarily
|
|
47
|
-
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
providerInstance.getApiKey = () => apiKey;
|
|
48
51
|
// Make a minimal test request
|
|
49
52
|
const testPrompt = "Hi";
|
|
50
53
|
const testModel = getDefaultModel(provider);
|
|
@@ -56,8 +59,9 @@ async function validateApiKey(provider, apiKey) {
|
|
|
56
59
|
};
|
|
57
60
|
}
|
|
58
61
|
catch (error) {
|
|
62
|
+
const err = error;
|
|
59
63
|
// Check for common error types
|
|
60
|
-
if (
|
|
64
|
+
if (err.message?.includes('401') || err.message?.includes('Unauthorized') || err.message?.includes('Invalid API key')) {
|
|
61
65
|
return {
|
|
62
66
|
valid: false,
|
|
63
67
|
provider,
|
|
@@ -65,7 +69,7 @@ async function validateApiKey(provider, apiKey) {
|
|
|
65
69
|
message: 'API key is invalid or unauthorized'
|
|
66
70
|
};
|
|
67
71
|
}
|
|
68
|
-
if (
|
|
72
|
+
if (err.message?.includes('403') || err.message?.includes('Forbidden')) {
|
|
69
73
|
return {
|
|
70
74
|
valid: false,
|
|
71
75
|
provider,
|
|
@@ -73,7 +77,7 @@ async function validateApiKey(provider, apiKey) {
|
|
|
73
77
|
message: 'API key does not have access to this resource'
|
|
74
78
|
};
|
|
75
79
|
}
|
|
76
|
-
if (
|
|
80
|
+
if (err.message?.includes('429') || err.message?.includes('rate limit')) {
|
|
77
81
|
// Rate limit means the key is valid, just too many requests
|
|
78
82
|
return {
|
|
79
83
|
valid: true,
|
package/dist/cjs/wrap.js
CHANGED
|
@@ -6,7 +6,7 @@ const providers_1 = require("./providers");
|
|
|
6
6
|
const types_1 = require("./types");
|
|
7
7
|
const errors_1 = require("./errors");
|
|
8
8
|
function handleError(err) {
|
|
9
|
-
if (err
|
|
9
|
+
if (err instanceof errors_1.AIHookError) {
|
|
10
10
|
// Print pretty message
|
|
11
11
|
console.error(err.pretty());
|
|
12
12
|
// Only exit in Node.js test environment, not in browser
|
|
@@ -26,6 +26,7 @@ function handleError(err) {
|
|
|
26
26
|
throw err;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
30
|
function wrap(fn, options) {
|
|
30
31
|
// Validate task type immediately when wrap() is called
|
|
31
32
|
const validTasks = ["summarize", "translate", "explain", "rewrite", "sentiment", "codeReview"];
|
|
@@ -126,9 +127,10 @@ function buildPrompt(task, text, targetLanguage) {
|
|
|
126
127
|
switch (task) {
|
|
127
128
|
case "summarize":
|
|
128
129
|
return `Summarize the following text:\n${text}`;
|
|
129
|
-
case "translate":
|
|
130
|
+
case "translate": {
|
|
130
131
|
const language = targetLanguage || "English"; // default to English
|
|
131
132
|
return `Translate this text into ${language}:\n${text}`;
|
|
133
|
+
}
|
|
132
134
|
case "explain":
|
|
133
135
|
return `Explain this clearly:\n${text}`;
|
|
134
136
|
case "rewrite":
|
|
@@ -58,7 +58,7 @@ export class BaseProvider {
|
|
|
58
58
|
try {
|
|
59
59
|
data = await response.json();
|
|
60
60
|
}
|
|
61
|
-
catch
|
|
61
|
+
catch {
|
|
62
62
|
data = await response.text();
|
|
63
63
|
}
|
|
64
64
|
if (!response.ok) {
|
|
@@ -74,13 +74,14 @@ export class BaseProvider {
|
|
|
74
74
|
return { data };
|
|
75
75
|
}
|
|
76
76
|
catch (error) {
|
|
77
|
+
const err = error;
|
|
77
78
|
// If it's already an HTTP error we just threw, rethrow it
|
|
78
|
-
if (
|
|
79
|
-
throw
|
|
79
|
+
if (err.response) {
|
|
80
|
+
throw err;
|
|
80
81
|
}
|
|
81
82
|
// Otherwise, it's a network error (e.g. fetch failed entirely)
|
|
82
83
|
// Emulate axios network error shape
|
|
83
|
-
throw Object.assign(new Error(
|
|
84
|
+
throw Object.assign(new Error(err.message || "Network Error"), {
|
|
84
85
|
request: {}
|
|
85
86
|
});
|
|
86
87
|
}
|
|
@@ -93,14 +94,15 @@ export class BaseProvider {
|
|
|
93
94
|
return output;
|
|
94
95
|
}
|
|
95
96
|
handleError(error) {
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
const err = error;
|
|
98
|
+
if (err.response) {
|
|
99
|
+
return this.handleHttpError(err);
|
|
98
100
|
}
|
|
99
|
-
else if (
|
|
101
|
+
else if (err.request) {
|
|
100
102
|
return new AIHookError("NETWORK_ERROR", this.config.errorMessages.networkError, this.config.name, "Check your internet connection");
|
|
101
103
|
}
|
|
102
104
|
else {
|
|
103
|
-
return new AIHookError("UNKNOWN_ERROR",
|
|
105
|
+
return new AIHookError("UNKNOWN_ERROR", err.message || this.config.errorMessages.unknownError, this.config.name);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
getCapitalizedProviderName() {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// Common response parsers
|
|
2
2
|
export const responseParsers = {
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
4
|
openaiStyle: (response) => response.data?.choices?.[0]?.message?.content,
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
6
|
claudeStyle: (response) => response.data?.content?.[0]?.text,
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
8
|
geminiStyle: (response) => response.data?.candidates?.[0]?.content?.parts?.[0]?.text,
|
|
6
9
|
};
|
|
7
10
|
// Common request body builders
|
|
@@ -15,7 +18,7 @@ export const requestBodyBuilders = {
|
|
|
15
18
|
max_tokens: 4096,
|
|
16
19
|
messages: [{ role: "user", content: prompt }]
|
|
17
20
|
}),
|
|
18
|
-
geminiStyle: (prompt,
|
|
21
|
+
geminiStyle: (prompt, _model) => ({
|
|
19
22
|
contents: [{
|
|
20
23
|
parts: [{ text: prompt }]
|
|
21
24
|
}]
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export class ProviderRegistry {
|
|
2
2
|
providers = new Map();
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3
4
|
providerFunctions = new Map();
|
|
4
5
|
register(name, provider) {
|
|
5
6
|
this.providers.set(name, provider);
|
|
6
7
|
this.providerFunctions.set(name, this.createProviderFunction(provider));
|
|
7
8
|
}
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
10
|
get(name) {
|
|
9
11
|
return this.providerFunctions.get(name);
|
|
10
12
|
}
|
|
@@ -31,6 +33,7 @@ export class ProviderRegistry {
|
|
|
31
33
|
}
|
|
32
34
|
return available;
|
|
33
35
|
}
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
37
|
createProviderFunction(provider) {
|
|
35
38
|
return async (prompt, model) => {
|
|
36
39
|
return provider.call(prompt, model);
|
|
@@ -34,7 +34,7 @@ const providers = {
|
|
|
34
34
|
xai: providerRegistry.get("xai"),
|
|
35
35
|
perplexity: providerRegistry.get("perplexity"),
|
|
36
36
|
mistral: providerRegistry.get("mistral"),
|
|
37
|
-
mock: async (prompt,
|
|
37
|
+
mock: async (prompt, _model) => `[MOCK OUTPUT] ${prompt}`
|
|
38
38
|
};
|
|
39
39
|
// Returns an array of providers whose API keys exist in environment (legacy)
|
|
40
40
|
export function getAvailableProviders() {
|
|
@@ -45,7 +45,7 @@ export function getAvailableProviders() {
|
|
|
45
45
|
// Otherwise use legacy system
|
|
46
46
|
return providerRegistry.getAvailableProviders();
|
|
47
47
|
}
|
|
48
|
-
//
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
49
|
export function getProvider(name) {
|
|
50
50
|
// If new system is initialized, use it
|
|
51
51
|
if (isInitialized()) {
|
|
@@ -69,7 +69,7 @@ export function getProvider(name) {
|
|
|
69
69
|
// 3. No valid keys found → throw error (single instruction, no fallback)
|
|
70
70
|
throw new AIHookError("NO_PROVIDER_FOUND", "No valid AI provider API key was found.\n\nIf you are using a .env file, please ensure you have installed the 'dotenv' package (npm i dotenv) and called require('dotenv').config() at the very top of your entry file.\n\nAlternatively, you can initialize providers explicitly:\ninitAIHooks({ providers: [{ provider: 'openai', key: 'your-key-here' }] })", undefined, "Reference documentation for setup instructions.");
|
|
71
71
|
}
|
|
72
|
-
//
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
73
|
export function getProviderChain(name) {
|
|
74
74
|
if (isInitialized()) {
|
|
75
75
|
return getNewProviderChain(name);
|
|
@@ -77,6 +77,7 @@ export function getProviderChain(name) {
|
|
|
77
77
|
// Legacy fallback: wrap available providers into a chain
|
|
78
78
|
const available = getAvailableProviders();
|
|
79
79
|
const seen = new Set();
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
81
|
const chain = [];
|
|
81
82
|
const tryPush = (p) => {
|
|
82
83
|
if (!seen.has(p) && providers[p]) {
|
|
@@ -26,7 +26,7 @@ export async function validateApiKey(provider, apiKey) {
|
|
|
26
26
|
case 'openrouter':
|
|
27
27
|
providerInstance = new OpenRouterProvider();
|
|
28
28
|
break;
|
|
29
|
-
default:
|
|
29
|
+
default: {
|
|
30
30
|
const config = providerConfigs[provider];
|
|
31
31
|
if (!config) {
|
|
32
32
|
return {
|
|
@@ -37,9 +37,12 @@ export async function validateApiKey(provider, apiKey) {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
providerInstance = new BaseProvider(config);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
40
42
|
}
|
|
41
43
|
// Set the API key temporarily
|
|
42
|
-
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
providerInstance.getApiKey = () => apiKey;
|
|
43
46
|
// Make a minimal test request
|
|
44
47
|
const testPrompt = "Hi";
|
|
45
48
|
const testModel = getDefaultModel(provider);
|
|
@@ -51,8 +54,9 @@ export async function validateApiKey(provider, apiKey) {
|
|
|
51
54
|
};
|
|
52
55
|
}
|
|
53
56
|
catch (error) {
|
|
57
|
+
const err = error;
|
|
54
58
|
// Check for common error types
|
|
55
|
-
if (
|
|
59
|
+
if (err.message?.includes('401') || err.message?.includes('Unauthorized') || err.message?.includes('Invalid API key')) {
|
|
56
60
|
return {
|
|
57
61
|
valid: false,
|
|
58
62
|
provider,
|
|
@@ -60,7 +64,7 @@ export async function validateApiKey(provider, apiKey) {
|
|
|
60
64
|
message: 'API key is invalid or unauthorized'
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
|
-
if (
|
|
67
|
+
if (err.message?.includes('403') || err.message?.includes('Forbidden')) {
|
|
64
68
|
return {
|
|
65
69
|
valid: false,
|
|
66
70
|
provider,
|
|
@@ -68,7 +72,7 @@ export async function validateApiKey(provider, apiKey) {
|
|
|
68
72
|
message: 'API key does not have access to this resource'
|
|
69
73
|
};
|
|
70
74
|
}
|
|
71
|
-
if (
|
|
75
|
+
if (err.message?.includes('429') || err.message?.includes('rate limit')) {
|
|
72
76
|
// Rate limit means the key is valid, just too many requests
|
|
73
77
|
return {
|
|
74
78
|
valid: true,
|
package/dist/esm/wrap.js
CHANGED
|
@@ -3,7 +3,7 @@ import { getProviderChain } from "./providers";
|
|
|
3
3
|
import { DEFAULT_MODEL } from "./types";
|
|
4
4
|
import { AIHookError } from "./errors";
|
|
5
5
|
function handleError(err) {
|
|
6
|
-
if (err
|
|
6
|
+
if (err instanceof AIHookError) {
|
|
7
7
|
// Print pretty message
|
|
8
8
|
console.error(err.pretty());
|
|
9
9
|
// Only exit in Node.js test environment, not in browser
|
|
@@ -23,6 +23,7 @@ function handleError(err) {
|
|
|
23
23
|
throw err;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
27
|
export function wrap(fn, options) {
|
|
27
28
|
// Validate task type immediately when wrap() is called
|
|
28
29
|
const validTasks = ["summarize", "translate", "explain", "rewrite", "sentiment", "codeReview"];
|
|
@@ -123,9 +124,10 @@ function buildPrompt(task, text, targetLanguage) {
|
|
|
123
124
|
switch (task) {
|
|
124
125
|
case "summarize":
|
|
125
126
|
return `Summarize the following text:\n${text}`;
|
|
126
|
-
case "translate":
|
|
127
|
+
case "translate": {
|
|
127
128
|
const language = targetLanguage || "English"; // default to English
|
|
128
129
|
return `Translate this text into ${language}:\n${text}`;
|
|
130
|
+
}
|
|
129
131
|
case "explain":
|
|
130
132
|
return `Explain this clearly:\n${text}`;
|
|
131
133
|
case "rewrite":
|
|
@@ -2,18 +2,18 @@ import { AIHookError } from "../../errors";
|
|
|
2
2
|
export interface FetchRequestConfig {
|
|
3
3
|
url: string;
|
|
4
4
|
method?: string;
|
|
5
|
-
data?:
|
|
5
|
+
data?: unknown;
|
|
6
6
|
headers?: Record<string, string>;
|
|
7
7
|
}
|
|
8
8
|
export interface FetchResponse {
|
|
9
|
-
data:
|
|
9
|
+
data: unknown;
|
|
10
10
|
}
|
|
11
11
|
export interface ProviderConfig {
|
|
12
12
|
name: string;
|
|
13
13
|
baseUrl: string;
|
|
14
14
|
envKey: string;
|
|
15
15
|
headers: Record<string, string>;
|
|
16
|
-
requestBody: (prompt: string, model: string) =>
|
|
16
|
+
requestBody: (prompt: string, model: string) => unknown;
|
|
17
17
|
responseParser: (response: FetchResponse) => string;
|
|
18
18
|
errorMessages: {
|
|
19
19
|
missingKey: string;
|
|
@@ -35,7 +35,13 @@ export declare class BaseProvider {
|
|
|
35
35
|
protected buildAuthHeaders(apiKey: string): Record<string, string>;
|
|
36
36
|
protected makeRequest(config: FetchRequestConfig): Promise<FetchResponse>;
|
|
37
37
|
protected parseResponse(response: FetchResponse): string;
|
|
38
|
-
protected handleError(error:
|
|
38
|
+
protected handleError(error: unknown): AIHookError;
|
|
39
39
|
protected getCapitalizedProviderName(): string;
|
|
40
|
-
protected handleHttpError(error:
|
|
40
|
+
protected handleHttpError(error: Error & {
|
|
41
|
+
response: {
|
|
42
|
+
status: number;
|
|
43
|
+
statusText?: string;
|
|
44
|
+
data?: any;
|
|
45
|
+
};
|
|
46
|
+
}): AIHookError;
|
|
41
47
|
}
|
|
@@ -25,11 +25,11 @@ export declare class ProviderManager {
|
|
|
25
25
|
* Used by the fallback mechanism in wrap().
|
|
26
26
|
*/
|
|
27
27
|
getProviderChain(name?: Provider): Array<{
|
|
28
|
-
fn:
|
|
28
|
+
fn: (prompt: string, model?: string) => Promise<string>;
|
|
29
29
|
provider: Provider;
|
|
30
30
|
}>;
|
|
31
31
|
getProvider(name?: Provider): {
|
|
32
|
-
fn:
|
|
32
|
+
fn: (prompt: string, model?: string) => Promise<string>;
|
|
33
33
|
provider: Provider;
|
|
34
34
|
};
|
|
35
35
|
addProvider(config: UserProviderConfig): void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ProviderConfig } from "./BaseProvider";
|
|
1
|
+
import { FetchResponse, ProviderConfig } from "./BaseProvider";
|
|
2
2
|
export declare const responseParsers: {
|
|
3
|
-
openaiStyle: (response:
|
|
4
|
-
claudeStyle: (response:
|
|
5
|
-
geminiStyle: (response:
|
|
3
|
+
openaiStyle: (response: FetchResponse) => any;
|
|
4
|
+
claudeStyle: (response: FetchResponse) => any;
|
|
5
|
+
geminiStyle: (response: FetchResponse) => any;
|
|
6
6
|
};
|
|
7
7
|
export declare const requestBodyBuilders: {
|
|
8
8
|
openaiStyle: (prompt: string, model: string) => {
|
|
@@ -20,7 +20,7 @@ export declare const requestBodyBuilders: {
|
|
|
20
20
|
content: string;
|
|
21
21
|
}[];
|
|
22
22
|
};
|
|
23
|
-
geminiStyle: (prompt: string,
|
|
23
|
+
geminiStyle: (prompt: string, _model: string) => {
|
|
24
24
|
contents: {
|
|
25
25
|
parts: {
|
|
26
26
|
text: string;
|
|
@@ -12,11 +12,17 @@ export declare class GeminiProvider extends BaseProvider {
|
|
|
12
12
|
[x: string]: string;
|
|
13
13
|
};
|
|
14
14
|
method?: string;
|
|
15
|
-
data?:
|
|
15
|
+
data?: unknown;
|
|
16
16
|
};
|
|
17
17
|
protected buildAuthHeaders(): Record<string, string>;
|
|
18
18
|
}
|
|
19
19
|
export declare class OpenRouterProvider extends BaseProvider {
|
|
20
20
|
constructor();
|
|
21
|
-
protected handleHttpError(error:
|
|
21
|
+
protected handleHttpError(error: Error & {
|
|
22
|
+
response: {
|
|
23
|
+
status: number;
|
|
24
|
+
statusText?: string;
|
|
25
|
+
data?: any;
|
|
26
|
+
};
|
|
27
|
+
}): AIHookError;
|
|
22
28
|
}
|
package/dist/providers/init.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export declare function getAvailableProviders(): Provider[];
|
|
|
43
43
|
* @returns Provider function and name
|
|
44
44
|
*/
|
|
45
45
|
export declare function getProvider(name?: Provider): {
|
|
46
|
-
fn:
|
|
46
|
+
fn: (prompt: string, model?: string) => Promise<string>;
|
|
47
47
|
provider: Provider;
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
@@ -52,7 +52,7 @@ export declare function getProvider(name?: Provider): {
|
|
|
52
52
|
* @returns Ordered array of {fn, provider} to try in sequence
|
|
53
53
|
*/
|
|
54
54
|
export declare function getProviderChain(name?: Provider): Array<{
|
|
55
|
-
fn:
|
|
55
|
+
fn: (prompt: string, model?: string) => Promise<string>;
|
|
56
56
|
provider: Provider;
|
|
57
57
|
}>;
|
|
58
58
|
/**
|
package/dist/wrap.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WrapOptions, Provider } from "./types";
|
|
1
|
+
import { WrapOptions, TaskType, Provider } from "./types";
|
|
2
2
|
export interface MultimodalInput {
|
|
3
3
|
text?: string;
|
|
4
4
|
image?: string;
|
|
@@ -8,7 +8,17 @@ export interface MultimodalInput {
|
|
|
8
8
|
type: string;
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
+
export interface WrapResultMeta {
|
|
12
|
+
provider: Provider;
|
|
13
|
+
model: string;
|
|
14
|
+
task?: TaskType;
|
|
15
|
+
targetLanguage?: string;
|
|
16
|
+
cached: boolean;
|
|
17
|
+
estimatedCostUSD: number;
|
|
18
|
+
latencyMs: number;
|
|
19
|
+
fallback: boolean;
|
|
20
|
+
}
|
|
11
21
|
export declare function wrap<T extends (...args: any[]) => any, P extends Provider | undefined = undefined>(fn: T, options: WrapOptions<P>): (...args: Parameters<T>) => Promise<{
|
|
12
22
|
output: string;
|
|
13
|
-
meta:
|
|
23
|
+
meta: WrapResultMeta;
|
|
14
24
|
}>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "npm-ai-hooks",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"description": "Universal AI Hook Layer for Node.js and React – one wrapper for all AI providers. Inject LLM-like behavior into any JavaScript or TypeScript function with a single line, without writing prompts, handling SDKs, or locking into any provider.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"test:performance": "jest tests/performance.test.ts --verbose",
|
|
35
35
|
"test:env": "jest --testNamePattern=\"Real API|Environment-based\" --verbose",
|
|
36
36
|
"test:mock": "jest --testNamePattern=\"Provider Detection|Task Tests\" --verbose",
|
|
37
|
-
"lint": "eslint .
|
|
37
|
+
"lint": "eslint .",
|
|
38
38
|
"format": "prettier --write .",
|
|
39
39
|
"prepare": "npm run build",
|
|
40
40
|
"demo": "npx ts-node examples/demo.ts",
|
|
@@ -49,15 +49,17 @@
|
|
|
49
49
|
},
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"devDependencies": {
|
|
52
|
+
"@eslint/js": "^10.0.1",
|
|
52
53
|
"@types/jest": "^30.0.0",
|
|
53
|
-
"@types/node": "^
|
|
54
|
+
"@types/node": "^26.0.1",
|
|
54
55
|
"eslint": "^10.5.0",
|
|
55
56
|
"jest": "^30.2.0",
|
|
56
57
|
"prettier": "^3.6.2",
|
|
57
58
|
"rimraf": "^6.0.1",
|
|
58
59
|
"ts-jest": "^29.4.4",
|
|
59
60
|
"ts-node": "^10.9.2",
|
|
60
|
-
"typescript": "^6.0.3"
|
|
61
|
+
"typescript": "^6.0.3",
|
|
62
|
+
"typescript-eslint": "^8.62.0"
|
|
61
63
|
},
|
|
62
64
|
"keywords": [
|
|
63
65
|
"ai",
|
|
@@ -90,5 +92,8 @@
|
|
|
90
92
|
"allowScripts": {
|
|
91
93
|
"fsevents@2.3.3": true,
|
|
92
94
|
"unrs-resolver@1.12.2": true
|
|
95
|
+
},
|
|
96
|
+
"overrides": {
|
|
97
|
+
"js-yaml": "^5.2.0"
|
|
93
98
|
}
|
|
94
99
|
}
|