npm-ai-hooks 1.0.0 → 1.0.2
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/providers/claude.d.ts +2 -0
- package/dist/providers/claude.js +60 -0
- package/dist/providers/deepkseek.d.ts +2 -0
- package/dist/providers/deepkseek.js +57 -0
- package/dist/providers/gemini.d.ts +2 -0
- package/dist/providers/gemini.js +58 -0
- package/dist/providers/index.js +32 -2
- package/dist/providers/mistral.d.ts +2 -0
- package/dist/providers/mistral.js +57 -0
- package/dist/providers/openai.d.ts +2 -1
- package/dist/providers/openai.js +48 -10
- package/dist/providers/perplexity.d.ts +2 -0
- package/dist/providers/perplexity.js +57 -0
- package/dist/providers/xai.d.ts +2 -0
- package/dist/providers/xai.js +57 -0
- package/dist/types/claude.d.ts +5 -0
- package/dist/types/claude.js +7 -0
- package/dist/types/core/providers.d.ts +7 -1
- package/dist/types/deepseek.d.ts +5 -0
- package/dist/types/deepseek.js +7 -0
- package/dist/types/gemini.d.ts +5 -0
- package/dist/types/gemini.js +7 -0
- package/dist/types/index.d.ts +14 -2
- package/dist/types/index.js +13 -1
- package/dist/types/mistral.d.ts +5 -0
- package/dist/types/mistral.js +7 -0
- package/dist/types/openai.d.ts +8 -1
- package/dist/types/openai.js +4 -1
- package/dist/types/perplexity.d.ts +5 -0
- package/dist/types/perplexity.js +7 -0
- package/dist/types/xai.d.ts +5 -0
- package/dist/types/xai.js +7 -0
- package/package.json +37 -11
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.callClaude = callClaude;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
const BASE_URL = "https://api.anthropic.com/v1";
|
|
10
|
+
const ANTHROPIC_VERSION = "2023-06-01";
|
|
11
|
+
async function callClaude(prompt, model) {
|
|
12
|
+
const apiKey = process.env.AI_HOOK_CLAUDE_KEY;
|
|
13
|
+
if (!apiKey) {
|
|
14
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", "Missing Claude API key.", "claude", "Set AI_HOOK_CLAUDE_KEY in your environment variables.");
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const response = await axios_1.default.post(`${BASE_URL}/messages`, {
|
|
18
|
+
model,
|
|
19
|
+
max_tokens: 4096,
|
|
20
|
+
messages: [
|
|
21
|
+
{
|
|
22
|
+
role: "user",
|
|
23
|
+
content: prompt
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}, {
|
|
27
|
+
headers: {
|
|
28
|
+
"x-api-key": apiKey,
|
|
29
|
+
"anthropic-version": ANTHROPIC_VERSION,
|
|
30
|
+
"Content-Type": "application/json"
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
const output = response.data?.content?.[0]?.text;
|
|
34
|
+
if (!output) {
|
|
35
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", "Claude returned empty response", "claude", "Check your model and API key");
|
|
36
|
+
}
|
|
37
|
+
return output;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (err.response) {
|
|
41
|
+
const status = err.response.status;
|
|
42
|
+
const text = err.response.data?.error
|
|
43
|
+
? JSON.stringify(err.response.data.error)
|
|
44
|
+
: err.response.statusText || "Unknown error";
|
|
45
|
+
if (status === 400)
|
|
46
|
+
throw new errors_1.AIHookError("BAD_REQUEST", `Claude rejected the request: ${text}`, "claude", "Check your prompt and model");
|
|
47
|
+
if (status === 401)
|
|
48
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid Claude API key: ${text}`, "claude", "Verify your AI_HOOK_CLAUDE_KEY environment variable");
|
|
49
|
+
if (status === 429)
|
|
50
|
+
throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to Claude: ${text}`, "claude", "Throttle requests or upgrade your plan");
|
|
51
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", `Claude API error: ${text}`, "claude");
|
|
52
|
+
}
|
|
53
|
+
else if (err.request) {
|
|
54
|
+
throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting Claude", "claude", "Check your internet connection");
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "claude");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.callDeepSeek = callDeepSeek;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
const BASE_URL = "https://api.deepseek.com/v1";
|
|
10
|
+
async function callDeepSeek(prompt, model) {
|
|
11
|
+
const apiKey = process.env.AI_HOOK_DEEPSEEK_KEY;
|
|
12
|
+
if (!apiKey) {
|
|
13
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", "Missing DeepSeek API key.", "deepseek", "Set AI_HOOK_DEEPSEEK_KEY in your environment variables.");
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await axios_1.default.post(`${BASE_URL}/chat/completions`, {
|
|
17
|
+
model,
|
|
18
|
+
messages: [
|
|
19
|
+
{
|
|
20
|
+
role: "user",
|
|
21
|
+
content: prompt
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}, {
|
|
25
|
+
headers: {
|
|
26
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
27
|
+
"Content-Type": "application/json"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const output = response.data?.choices?.[0]?.message?.content;
|
|
31
|
+
if (!output) {
|
|
32
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", "DeepSeek returned empty response", "deepseek", "Check your model and API key");
|
|
33
|
+
}
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err.response) {
|
|
38
|
+
const status = err.response.status;
|
|
39
|
+
const text = err.response.data?.error
|
|
40
|
+
? JSON.stringify(err.response.data.error)
|
|
41
|
+
: err.response.statusText || "Unknown error";
|
|
42
|
+
if (status === 400)
|
|
43
|
+
throw new errors_1.AIHookError("BAD_REQUEST", `DeepSeek rejected the request: ${text}`, "deepseek", "Check your prompt and model");
|
|
44
|
+
if (status === 401)
|
|
45
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid DeepSeek API key: ${text}`, "deepseek", "Verify your AI_HOOK_DEEPSEEK_KEY environment variable");
|
|
46
|
+
if (status === 429)
|
|
47
|
+
throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to DeepSeek: ${text}`, "deepseek", "Throttle requests or upgrade your plan");
|
|
48
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", `DeepSeek API error: ${text}`, "deepseek");
|
|
49
|
+
}
|
|
50
|
+
else if (err.request) {
|
|
51
|
+
throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting DeepSeek", "deepseek", "Check your internet connection");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "deepseek");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.callGemini = callGemini;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
const BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
|
|
10
|
+
async function callGemini(prompt, model) {
|
|
11
|
+
const apiKey = process.env.AI_HOOK_GEMINI_KEY;
|
|
12
|
+
if (!apiKey) {
|
|
13
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", "Missing Gemini API key.", "gemini", "Set AI_HOOK_GEMINI_KEY in your environment variables.");
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await axios_1.default.post(`${BASE_URL}/models/${model}:generateContent?key=${apiKey}`, {
|
|
17
|
+
contents: [
|
|
18
|
+
{
|
|
19
|
+
parts: [
|
|
20
|
+
{
|
|
21
|
+
text: prompt
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}, {
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json"
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const output = response.data?.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
32
|
+
if (!output) {
|
|
33
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", "Gemini returned empty response", "gemini", "Check your model and API key");
|
|
34
|
+
}
|
|
35
|
+
return output;
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (err.response) {
|
|
39
|
+
const status = err.response.status;
|
|
40
|
+
const text = err.response.data?.error
|
|
41
|
+
? JSON.stringify(err.response.data.error)
|
|
42
|
+
: err.response.statusText || "Unknown error";
|
|
43
|
+
if (status === 400)
|
|
44
|
+
throw new errors_1.AIHookError("BAD_REQUEST", `Gemini rejected the request: ${text}`, "gemini", "Check your prompt and model");
|
|
45
|
+
if (status === 401)
|
|
46
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid Gemini API key: ${text}`, "gemini", "Verify your AI_HOOK_GEMINI_KEY environment variable");
|
|
47
|
+
if (status === 429)
|
|
48
|
+
throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to Gemini: ${text}`, "gemini", "Throttle requests or upgrade your plan");
|
|
49
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", `Gemini API error: ${text}`, "gemini");
|
|
50
|
+
}
|
|
51
|
+
else if (err.request) {
|
|
52
|
+
throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting Gemini", "gemini", "Check your internet connection");
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "gemini");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
package/dist/providers/index.js
CHANGED
|
@@ -3,13 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getAvailableProviders = getAvailableProviders;
|
|
4
4
|
exports.getProvider = getProvider;
|
|
5
5
|
const errors_1 = require("../errors");
|
|
6
|
-
const openai_1 = require("./openai");
|
|
7
6
|
const openrouter_1 = require("./openrouter");
|
|
8
7
|
const groq_1 = require("./groq");
|
|
8
|
+
const openai_1 = require("./openai");
|
|
9
|
+
const gemini_1 = require("./gemini");
|
|
10
|
+
const claude_1 = require("./claude");
|
|
11
|
+
const deepkseek_1 = require("./deepkseek");
|
|
12
|
+
const xai_1 = require("./xai");
|
|
13
|
+
const perplexity_1 = require("./perplexity");
|
|
14
|
+
const mistral_1 = require("./mistral");
|
|
9
15
|
const providers = {
|
|
10
|
-
openai: openai_1.callOpenAI,
|
|
11
16
|
openrouter: openrouter_1.callOpenRouter,
|
|
12
17
|
groq: groq_1.callGroq,
|
|
18
|
+
openai: openai_1.callOpenAI,
|
|
19
|
+
gemini: gemini_1.callGemini,
|
|
20
|
+
claude: claude_1.callClaude,
|
|
21
|
+
deepseek: deepkseek_1.callDeepSeek,
|
|
22
|
+
xai: xai_1.callXAI,
|
|
23
|
+
perplexity: perplexity_1.callPerplexity,
|
|
24
|
+
mistral: mistral_1.callMistral,
|
|
13
25
|
mock: async (prompt, model) => `[MOCK OUTPUT] ${prompt}`
|
|
14
26
|
};
|
|
15
27
|
// Returns an array of providers whose API keys exist in environment
|
|
@@ -26,6 +38,24 @@ function getAvailableProviders() {
|
|
|
26
38
|
if (process.env.AI_HOOK_OPENAI_KEY && !available.includes("openai")) {
|
|
27
39
|
available.push("openai");
|
|
28
40
|
}
|
|
41
|
+
if (process.env.AI_HOOK_GEMINI_KEY && !available.includes("gemini")) {
|
|
42
|
+
available.push("gemini");
|
|
43
|
+
}
|
|
44
|
+
if (process.env.AI_HOOK_CLAUDE_KEY && !available.includes("claude")) {
|
|
45
|
+
available.push("claude");
|
|
46
|
+
}
|
|
47
|
+
if (process.env.AI_HOOK_DEEPSEEK_KEY && !available.includes("deepseek")) {
|
|
48
|
+
available.push("deepseek");
|
|
49
|
+
}
|
|
50
|
+
if (process.env.AI_HOOK_XAI_KEY && !available.includes("xai")) {
|
|
51
|
+
available.push("xai");
|
|
52
|
+
}
|
|
53
|
+
if (process.env.AI_HOOK_PERPLEXITY_KEY && !available.includes("perplexity")) {
|
|
54
|
+
available.push("perplexity");
|
|
55
|
+
}
|
|
56
|
+
if (process.env.AI_HOOK_MISTRAL_KEY && !available.includes("mistral")) {
|
|
57
|
+
available.push("mistral");
|
|
58
|
+
}
|
|
29
59
|
return available;
|
|
30
60
|
}
|
|
31
61
|
// ✅ Returns both the provider function and the actual provider name
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.callMistral = callMistral;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
const BASE_URL = "https://api.mistral.ai/v1";
|
|
10
|
+
async function callMistral(prompt, model) {
|
|
11
|
+
const apiKey = process.env.AI_HOOK_MISTRAL_KEY;
|
|
12
|
+
if (!apiKey) {
|
|
13
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", "Missing Mistral API key.", "mistral", "Set AI_HOOK_MISTRAL_KEY in your environment variables.");
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await axios_1.default.post(`${BASE_URL}/chat/completions`, {
|
|
17
|
+
model,
|
|
18
|
+
messages: [
|
|
19
|
+
{
|
|
20
|
+
role: "user",
|
|
21
|
+
content: prompt
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}, {
|
|
25
|
+
headers: {
|
|
26
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
27
|
+
"Content-Type": "application/json"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const output = response.data?.choices?.[0]?.message?.content;
|
|
31
|
+
if (!output) {
|
|
32
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", "Mistral returned empty response", "mistral", "Check your model and API key");
|
|
33
|
+
}
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err.response) {
|
|
38
|
+
const status = err.response.status;
|
|
39
|
+
const text = err.response.data?.error
|
|
40
|
+
? JSON.stringify(err.response.data.error)
|
|
41
|
+
: err.response.statusText || "Unknown error";
|
|
42
|
+
if (status === 400)
|
|
43
|
+
throw new errors_1.AIHookError("BAD_REQUEST", `Mistral rejected the request: ${text}`, "mistral", "Check your prompt and model");
|
|
44
|
+
if (status === 401)
|
|
45
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid Mistral API key: ${text}`, "mistral", "Verify your AI_HOOK_MISTRAL_KEY environment variable");
|
|
46
|
+
if (status === 429)
|
|
47
|
+
throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to Mistral: ${text}`, "mistral", "Throttle requests or upgrade your plan");
|
|
48
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", `Mistral API error: ${text}`, "mistral");
|
|
49
|
+
}
|
|
50
|
+
else if (err.request) {
|
|
51
|
+
throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting Mistral", "mistral", "Check your internet connection");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "mistral");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { OpenAIModel } from "../types/openai";
|
|
2
|
+
export declare function callOpenAI(prompt: string, model: OpenAIModel): Promise<string>;
|
package/dist/providers/openai.js
CHANGED
|
@@ -5,15 +5,53 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.callOpenAI = callOpenAI;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
const BASE_URL = "https://api.openai.com/v1";
|
|
8
10
|
async function callOpenAI(prompt, model) {
|
|
9
|
-
const
|
|
10
|
-
if (!
|
|
11
|
-
throw new
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
const apiKey = process.env.AI_HOOK_OPENAI_KEY;
|
|
12
|
+
if (!apiKey) {
|
|
13
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", "Missing OpenAI API key.", "openai", "Set AI_HOOK_OPENAI_KEY in your environment variables.");
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await axios_1.default.post(`${BASE_URL}/chat/completions`, {
|
|
17
|
+
model,
|
|
18
|
+
messages: [
|
|
19
|
+
{
|
|
20
|
+
role: "user",
|
|
21
|
+
content: prompt
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}, {
|
|
25
|
+
headers: {
|
|
26
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
27
|
+
"Content-Type": "application/json"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const output = response.data?.choices?.[0]?.message?.content;
|
|
31
|
+
if (!output) {
|
|
32
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", "OpenAI returned empty response", "openai", "Check your model and API key");
|
|
33
|
+
}
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err.response) {
|
|
38
|
+
const status = err.response.status;
|
|
39
|
+
const text = err.response.data?.error
|
|
40
|
+
? JSON.stringify(err.response.data.error)
|
|
41
|
+
: err.response.statusText || "Unknown error";
|
|
42
|
+
if (status === 400)
|
|
43
|
+
throw new errors_1.AIHookError("BAD_REQUEST", `OpenAI rejected the request: ${text}`, "openai", "Check your prompt and model");
|
|
44
|
+
if (status === 401)
|
|
45
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid OpenAI API key: ${text}`, "openai", "Verify your AI_HOOK_OPENAI_KEY environment variable");
|
|
46
|
+
if (status === 429)
|
|
47
|
+
throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to OpenAI: ${text}`, "openai", "Throttle requests or upgrade your plan");
|
|
48
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", `OpenAI API error: ${text}`, "openai");
|
|
49
|
+
}
|
|
50
|
+
else if (err.request) {
|
|
51
|
+
throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting OpenAI", "openai", "Check your internet connection");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "openai");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
19
57
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.callPerplexity = callPerplexity;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
const BASE_URL = "https://api.perplexity.ai";
|
|
10
|
+
async function callPerplexity(prompt, model) {
|
|
11
|
+
const apiKey = process.env.AI_HOOK_PERPLEXITY_KEY;
|
|
12
|
+
if (!apiKey) {
|
|
13
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", "Missing Perplexity API key.", "perplexity", "Set AI_HOOK_PERPLEXITY_KEY in your environment variables.");
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await axios_1.default.post(`${BASE_URL}/chat/completions`, {
|
|
17
|
+
model,
|
|
18
|
+
messages: [
|
|
19
|
+
{
|
|
20
|
+
role: "user",
|
|
21
|
+
content: prompt
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}, {
|
|
25
|
+
headers: {
|
|
26
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
27
|
+
"Content-Type": "application/json"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const output = response.data?.choices?.[0]?.message?.content;
|
|
31
|
+
if (!output) {
|
|
32
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", "Perplexity returned empty response", "perplexity", "Check your model and API key");
|
|
33
|
+
}
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err.response) {
|
|
38
|
+
const status = err.response.status;
|
|
39
|
+
const text = err.response.data?.error
|
|
40
|
+
? JSON.stringify(err.response.data.error)
|
|
41
|
+
: err.response.statusText || "Unknown error";
|
|
42
|
+
if (status === 400)
|
|
43
|
+
throw new errors_1.AIHookError("BAD_REQUEST", `Perplexity rejected the request: ${text}`, "perplexity", "Check your prompt and model");
|
|
44
|
+
if (status === 401)
|
|
45
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid Perplexity API key: ${text}`, "perplexity", "Verify your AI_HOOK_PERPLEXITY_KEY environment variable");
|
|
46
|
+
if (status === 429)
|
|
47
|
+
throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to Perplexity: ${text}`, "perplexity", "Throttle requests or upgrade your plan");
|
|
48
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", `Perplexity API error: ${text}`, "perplexity");
|
|
49
|
+
}
|
|
50
|
+
else if (err.request) {
|
|
51
|
+
throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting Perplexity", "perplexity", "Check your internet connection");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "perplexity");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.callXAI = callXAI;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
const BASE_URL = "https://api.x.ai/v1";
|
|
10
|
+
async function callXAI(prompt, model) {
|
|
11
|
+
const apiKey = process.env.AI_HOOK_XAI_KEY;
|
|
12
|
+
if (!apiKey) {
|
|
13
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", "Missing xAI API key.", "xai", "Set AI_HOOK_XAI_KEY in your environment variables.");
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await axios_1.default.post(`${BASE_URL}/chat/completions`, {
|
|
17
|
+
model,
|
|
18
|
+
messages: [
|
|
19
|
+
{
|
|
20
|
+
role: "user",
|
|
21
|
+
content: prompt
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}, {
|
|
25
|
+
headers: {
|
|
26
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
27
|
+
"Content-Type": "application/json"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const output = response.data?.choices?.[0]?.message?.content;
|
|
31
|
+
if (!output) {
|
|
32
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", "xAI returned empty response", "xai", "Check your model and API key");
|
|
33
|
+
}
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err.response) {
|
|
38
|
+
const status = err.response.status;
|
|
39
|
+
const text = err.response.data?.error
|
|
40
|
+
? JSON.stringify(err.response.data.error)
|
|
41
|
+
: err.response.statusText || "Unknown error";
|
|
42
|
+
if (status === 400)
|
|
43
|
+
throw new errors_1.AIHookError("BAD_REQUEST", `xAI rejected the request: ${text}`, "xai", "Check your prompt and model");
|
|
44
|
+
if (status === 401)
|
|
45
|
+
throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid xAI API key: ${text}`, "xai", "Verify your AI_HOOK_XAI_KEY environment variable");
|
|
46
|
+
if (status === 429)
|
|
47
|
+
throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to xAI: ${text}`, "xai", "Throttle requests or upgrade your plan");
|
|
48
|
+
throw new errors_1.AIHookError("PROVIDER_ERROR", `xAI API error: ${text}`, "xai");
|
|
49
|
+
}
|
|
50
|
+
else if (err.request) {
|
|
51
|
+
throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting xAI", "xai", "Check your internet connection");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "xai");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type ClaudeModel = "claude-opus-4-20250514" | "claude-opus-4-0" | "claude-sonnet-4-20250514" | "claude-sonnet-4-0" | "claude-3-7-sonnet-20250219" | "claude-3-7-sonnet-latest" | "claude-3-5-sonnet-20241022" | "claude-3-5-sonnet-20240620" | "claude-3-5-sonnet-latest" | "claude-3-5-haiku-20241022" | "claude-3-5-haiku-latest" | "claude-3-haiku-20240307";
|
|
2
|
+
/**
|
|
3
|
+
* Default model choice - best balance of performance and cost
|
|
4
|
+
*/
|
|
5
|
+
export declare const ClaudeDefaultModel: ClaudeModel;
|
|
@@ -3,8 +3,14 @@ export interface ProviderFunction<P extends Provider = Provider> {
|
|
|
3
3
|
(prompt: string, model: ProviderModels[P]): Promise<string>;
|
|
4
4
|
}
|
|
5
5
|
export interface ProviderMap {
|
|
6
|
-
openai: ProviderFunction<"openai">;
|
|
7
6
|
openrouter: ProviderFunction<"openrouter">;
|
|
8
7
|
groq: ProviderFunction<"groq">;
|
|
8
|
+
openai: ProviderFunction<"openai">;
|
|
9
|
+
gemini: ProviderFunction<"gemini">;
|
|
10
|
+
claude: ProviderFunction<"claude">;
|
|
11
|
+
deepseek: ProviderFunction<"deepseek">;
|
|
12
|
+
xai: ProviderFunction<"xai">;
|
|
13
|
+
perplexity: ProviderFunction<"perplexity">;
|
|
14
|
+
mistral: ProviderFunction<"mistral">;
|
|
9
15
|
mock: ProviderFunction<any>;
|
|
10
16
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type GeminiModel = "gemini-2.5-pro" | "gemini-2.5-flash" | "gemini-2.5-flash-lite" | "gemini-2.0-flash" | "gemini-2.0-flash-exp" | "gemini-2.0-flash-001" | "gemini-2.0-flash-lite" | "gemini-2.0-flash-lite-001" | "gemini-1.5-pro" | "gemini-1.5-pro-001" | "gemini-1.5-pro-002" | "gemini-1.5-pro-latest" | "gemini-1.5-flash" | "gemini-1.5-flash-001" | "gemini-1.5-flash-002" | "gemini-1.5-flash-latest" | "gemini-1.5-flash-8b" | "gemini-1.5-flash-8b-001" | "gemini-1.5-flash-8b-latest";
|
|
2
|
+
/**
|
|
3
|
+
* Default model choice - best price-performance ratio
|
|
4
|
+
*/
|
|
5
|
+
export declare const GeminiDefaultModel: GeminiModel;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { OpenAIModel } from "./openai";
|
|
2
2
|
import { OpenRouterModel } from "./openrouter";
|
|
3
3
|
import { GroqModel } from "./groq";
|
|
4
|
-
|
|
4
|
+
import { GeminiModel } from "./gemini";
|
|
5
|
+
import { ClaudeModel } from "./claude";
|
|
6
|
+
import { DeepSeekModel } from "./deepseek";
|
|
7
|
+
import { XAIModel } from "./xai";
|
|
8
|
+
import { PerplexityModel } from "./perplexity";
|
|
9
|
+
import { MistralModel } from "./mistral";
|
|
10
|
+
export type Provider = "openrouter" | "groq" | "openai" | "gemini" | "claude" | "deepseek" | "xai" | "perplexity" | "mistral";
|
|
5
11
|
export type ProviderModels = {
|
|
6
|
-
openai: OpenAIModel;
|
|
7
12
|
openrouter: OpenRouterModel;
|
|
8
13
|
groq: GroqModel;
|
|
14
|
+
openai: OpenAIModel;
|
|
15
|
+
gemini: GeminiModel;
|
|
16
|
+
claude: ClaudeModel;
|
|
17
|
+
deepseek: DeepSeekModel;
|
|
18
|
+
xai: XAIModel;
|
|
19
|
+
perplexity: PerplexityModel;
|
|
20
|
+
mistral: MistralModel;
|
|
9
21
|
};
|
|
10
22
|
export declare const DEFAULT_MODEL: {
|
|
11
23
|
[P in Provider]: ProviderModels[P];
|
package/dist/types/index.js
CHANGED
|
@@ -4,8 +4,20 @@ exports.DEFAULT_MODEL = void 0;
|
|
|
4
4
|
const openai_1 = require("./openai");
|
|
5
5
|
const openrouter_1 = require("./openrouter");
|
|
6
6
|
const groq_1 = require("./groq");
|
|
7
|
+
const gemini_1 = require("./gemini");
|
|
8
|
+
const claude_1 = require("./claude");
|
|
9
|
+
const deepseek_1 = require("./deepseek");
|
|
10
|
+
const xai_1 = require("./xai");
|
|
11
|
+
const perplexity_1 = require("./perplexity");
|
|
12
|
+
const mistral_1 = require("./mistral");
|
|
7
13
|
exports.DEFAULT_MODEL = {
|
|
8
|
-
openai: openai_1.OpenAIDefaultModel,
|
|
9
14
|
openrouter: openrouter_1.OpenRouterDefaultModel,
|
|
10
15
|
groq: groq_1.GroqDefaultModel,
|
|
16
|
+
openai: openai_1.OpenAIDefaultModel,
|
|
17
|
+
gemini: gemini_1.GeminiDefaultModel,
|
|
18
|
+
claude: claude_1.ClaudeDefaultModel,
|
|
19
|
+
deepseek: deepseek_1.DeepSeekDefaultModel,
|
|
20
|
+
xai: xai_1.XAIDefaultModel,
|
|
21
|
+
perplexity: perplexity_1.PerplexityDefaultModel,
|
|
22
|
+
mistral: mistral_1.MistralDefaultModel
|
|
11
23
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type MistralModel = "mistral-medium-2508" | "mistral-medium-latest" | "mistral-large-2411" | "mistral-large-latest" | "pixtral-large-2411" | "pixtral-large-latest" | "mistral-small-2407" | "codestral-2508" | "codestral-2501" | "codestral-latest" | "devstral-medium-2507" | "devstral-medium-latest" | "ministral-3b-2410" | "ministral-3b-latest" | "ministral-8b-2410" | "ministral-8b-latest" | "mistral-ocr-2505" | "mistral-ocr-latest" | "magistral-medium-2509" | "magistral-medium-latest" | "magistral-small-2509" | "magistral-small-latest" | "mistral-small-2506" | "mistral-small-2503" | "mistral-small-2501" | "mistral-small-latest" | "devstral-small-2507" | "devstral-small-latest" | "open-mistral-nemo" | "open-mistral-nemo-2407" | "pixtral-12b-2409" | "voxtral-small-2507" | "voxtral-small-latest" | "voxtral-mini-2507" | "voxtral-mini-latest";
|
|
2
|
+
/**
|
|
3
|
+
* Default model choice - best balance of performance and cost
|
|
4
|
+
*/
|
|
5
|
+
export declare const MistralDefaultModel: MistralModel;
|
package/dist/types/openai.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Known OpenAI models (text / reasoning / multimodal) as publicly documented.
|
|
3
|
+
* This list is conservative: use `string` fallback for unknown future models.
|
|
4
|
+
*/
|
|
5
|
+
export type OpenAIModel = "gpt-4.1" | "gpt-4.1-mini" | "gpt-4.1-nano" | "gpt-4o" | "gpt-4o-mini" | "chatgpt-4o-latest" | "o1" | "o1-preview" | "o1-mini" | "o3" | "o3-mini" | "o3-mini-high" | "o4-mini" | "o4-mini-high" | "gpt-4" | "gpt-4-turbo" | "gpt-4-turbo-preview" | "gpt-4-0613" | "gpt-4-0314" | "gpt-3.5-turbo" | "gpt-3.5-turbo-16k" | "gpt-3.5-turbo-0125" | "gpt-3.5-turbo-1106" | "gpt-oss-120b" | "gpt-oss-20b";
|
|
6
|
+
/**
|
|
7
|
+
* Default model choice (you can adjust this).
|
|
8
|
+
*/
|
|
2
9
|
export declare const OpenAIDefaultModel: OpenAIModel;
|
package/dist/types/openai.js
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type XAIModel = "grok-code-fast-1" | "grok-4-fast-reasoning" | "grok-4-fast-non-reasoning" | "grok-4-0709" | "grok-3-mini" | "grok-3" | "grok-2-vision-1212" | "grok-2-1212";
|
|
2
|
+
/**
|
|
3
|
+
* Default model choice - best balance of performance and cost
|
|
4
|
+
*/
|
|
5
|
+
export declare const XAIDefaultModel: XAIModel;
|
package/package.json
CHANGED
|
@@ -1,30 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "npm-ai-hooks",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Universal AI Hook Layer for Node.js – one wrapper for all AI providers.",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Universal AI Hook Layer for Node.js – 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/index.js",
|
|
6
|
-
"module": "dist/index.js",
|
|
7
6
|
"types": "dist/index.d.ts",
|
|
8
7
|
"exports": {
|
|
9
8
|
".": {
|
|
10
9
|
"import": "./dist/index.js",
|
|
11
|
-
"require": "./dist/index.js"
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
|
-
"dist
|
|
15
|
+
"dist",
|
|
16
|
+
"Readme.md",
|
|
17
|
+
"LICENSE"
|
|
16
18
|
],
|
|
17
19
|
"scripts": {
|
|
18
20
|
"dev": "ts-node src/index.ts",
|
|
19
|
-
"
|
|
20
|
-
"build": "tsc",
|
|
21
|
+
"clean": "rimraf dist",
|
|
22
|
+
"build": "npm run clean && tsc",
|
|
21
23
|
"test": "jest --verbose",
|
|
24
|
+
"lint": "eslint . --ext .ts",
|
|
25
|
+
"format": "prettier --write .",
|
|
22
26
|
"prepare": "npm run build",
|
|
23
27
|
"demo": "npx ts-node examples/demo.ts"
|
|
24
28
|
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
"keywords": [
|
|
30
|
+
"ai",
|
|
31
|
+
"hooks",
|
|
32
|
+
"llm",
|
|
33
|
+
"nodejs",
|
|
34
|
+
"typescript",
|
|
35
|
+
"openai",
|
|
36
|
+
"gemini",
|
|
37
|
+
"claude",
|
|
38
|
+
"deepseek",
|
|
39
|
+
"groq",
|
|
40
|
+
"mistral"
|
|
41
|
+
],
|
|
42
|
+
"author": "AteebNoOne <rehmanateebur@gmail.com>",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/AteebNoOne/npm-ai-hooks.git"
|
|
46
|
+
},
|
|
47
|
+
"license": "MIT",
|
|
28
48
|
"dependencies": {
|
|
29
49
|
"axios": "^1.12.2",
|
|
30
50
|
"dotenv": "^17.2.3"
|
|
@@ -39,5 +59,11 @@
|
|
|
39
59
|
"ts-jest": "^29.4.4",
|
|
40
60
|
"ts-node": "^10.9.2",
|
|
41
61
|
"typescript": "^5.9.3"
|
|
62
|
+
},
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=18"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
42
68
|
}
|
|
43
|
-
}
|
|
69
|
+
}
|