npm-ai-hooks 1.0.0-beta.0 → 1.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.
Files changed (56) hide show
  1. package/dist/errors.d.ts +8 -0
  2. package/dist/errors.js +21 -0
  3. package/{src/index.ts → dist/index.d.ts} +1 -2
  4. package/dist/index.js +6 -0
  5. package/dist/providers/groq.d.ts +2 -0
  6. package/dist/providers/groq.js +57 -0
  7. package/dist/providers/index.d.ts +7 -0
  8. package/{src/providers/index.ts → dist/providers/index.js} +45 -54
  9. package/dist/providers/openai.d.ts +1 -0
  10. package/dist/providers/openai.js +19 -0
  11. package/dist/providers/openrouter.d.ts +1 -0
  12. package/dist/providers/openrouter.js +55 -0
  13. package/{src/types/core/providers.ts → dist/types/core/providers.d.ts} +10 -13
  14. package/dist/types/core/providers.js +2 -0
  15. package/dist/types/groq.d.ts +2 -0
  16. package/dist/types/groq.js +4 -0
  17. package/dist/types/index.d.ts +24 -0
  18. package/dist/types/index.js +11 -0
  19. package/{src/types/openai.ts → dist/types/openai.d.ts} +2 -3
  20. package/dist/types/openai.js +4 -0
  21. package/dist/types/openrouter.d.ts +2 -0
  22. package/dist/types/openrouter.js +4 -0
  23. package/dist/wrap.d.ts +5 -0
  24. package/dist/wrap.js +85 -0
  25. package/package.json +15 -4
  26. package/.env.example +0 -14
  27. package/CODE_OF_CONDUCT.md +0 -35
  28. package/CONTRIBUTING.md +0 -88
  29. package/EXAMPLES.md +0 -53
  30. package/ROADMAP.md +0 -22
  31. package/SECURITY.md +0 -30
  32. package/examples/basic/explain.ts +0 -18
  33. package/examples/basic/rewrite.ts +0 -10
  34. package/examples/basic/sentiment.ts +0 -10
  35. package/examples/basic/summarize.ts +0 -10
  36. package/examples/basic/translate.ts +0 -10
  37. package/examples/demo.ts +0 -16
  38. package/examples/model-switch/groq-default.ts +0 -10
  39. package/examples/model-switch/groq-text2.ts +0 -10
  40. package/examples/model-switch/openrouter-default.ts +0 -10
  41. package/examples/model-switch/openrouter-gpt5.ts +0 -10
  42. package/examples/model-switch/wrong-models.ts +0 -21
  43. package/examples/openrouter/summarize-switch-model-demo.ts +0 -25
  44. package/examples/openrouter/translate-switch-model-demo.ts +0 -24
  45. package/examples/openrouter/translate-to-urdu-demo.ts +0 -19
  46. package/examples/openrouter-openai/gpt5-demo.ts +0 -25
  47. package/jest.config.js +0 -11
  48. package/src/errors.ts +0 -23
  49. package/src/providers/groq.ts +0 -98
  50. package/src/providers/openai.ts +0 -19
  51. package/src/providers/openrouter.ts +0 -100
  52. package/src/types/groq.ts +0 -20
  53. package/src/types/index.ts +0 -37
  54. package/src/types/openrouter.ts +0 -52
  55. package/src/wrap.ts +0 -93
  56. package/tsconfig.json +0 -11
@@ -0,0 +1,8 @@
1
+ export declare class AIHookError extends Error {
2
+ code: string;
3
+ provider?: string;
4
+ suggestion?: string;
5
+ constructor(code: string, message: string, provider?: string, suggestion?: string);
6
+ pretty(): string;
7
+ toString(): string;
8
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AIHookError = void 0;
4
+ class AIHookError extends Error {
5
+ constructor(code, message, provider, suggestion) {
6
+ super(message);
7
+ this.code = code;
8
+ this.provider = provider;
9
+ this.suggestion = suggestion;
10
+ // Do NOT print pretty message in constructor
11
+ }
12
+ pretty() {
13
+ return `\n❌ AI-HOOK ERROR: ${this.message}` +
14
+ (this.provider ? `\n Provider: ${this.provider}` : "") +
15
+ (this.suggestion ? `\n Suggestion: ${this.suggestion}\n` : "");
16
+ }
17
+ toString() {
18
+ return this.pretty();
19
+ }
20
+ }
21
+ exports.AIHookError = AIHookError;
@@ -1,2 +1 @@
1
- // src/index.ts
2
- export { wrap } from "./wrap";
1
+ export { wrap } from "./wrap";
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrap = void 0;
4
+ // src/index.ts
5
+ var wrap_1 = require("./wrap");
6
+ Object.defineProperty(exports, "wrap", { enumerable: true, get: function () { return wrap_1.wrap; } });
@@ -0,0 +1,2 @@
1
+ import { GroqModel } from "../types/groq";
2
+ export declare function callGroq(prompt: string, model: GroqModel): Promise<string>;
@@ -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.callGroq = callGroq;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const errors_1 = require("../errors");
9
+ const BASE_URL = "https://api.groq.com/openai/v1";
10
+ async function callGroq(prompt, model) {
11
+ const apiKey = process.env.AI_HOOK_GROQ_KEY;
12
+ if (!apiKey) {
13
+ throw new errors_1.AIHookError("INVALID_API_KEY", "Missing Groq API key.", "groq", "Set AI_HOOK_GROQ_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", "Groq returned empty response", "groq", "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", `Groq rejected the request: ${text}`, "groq", "Check your prompt and model");
44
+ if (status === 401)
45
+ throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid Groq API key: ${text}`, "groq", "Verify your AI_HOOK_GROQ_KEY environment variable");
46
+ if (status === 429)
47
+ throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to Groq: ${text}`, "groq", "Throttle requests or upgrade your plan");
48
+ throw new errors_1.AIHookError("PROVIDER_ERROR", `Groq API error: ${text}`, "groq");
49
+ }
50
+ else if (err.request) {
51
+ throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting Groq", "groq", "Check your internet connection");
52
+ }
53
+ else {
54
+ throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "groq");
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,7 @@
1
+ import { Provider } from "../types";
2
+ import { ProviderFunction } from "../types/core/providers";
3
+ export declare function getAvailableProviders(): Provider[];
4
+ export declare function getProvider(name?: Provider): {
5
+ fn: ProviderFunction<any>;
6
+ provider: Provider | "mock";
7
+ };
@@ -1,54 +1,45 @@
1
- import { AIHookError } from "../errors";
2
- import { callOpenAI } from "./openai";
3
- import { callOpenRouter } from "./openrouter";
4
- import { callGroq } from "./groq";
5
- import { Provider } from "../types";
6
- import { ProviderFunction, ProviderMap } from "../types/core/providers";
7
-
8
- const providers: ProviderMap = {
9
- openai: callOpenAI,
10
- openrouter: callOpenRouter,
11
- groq: callGroq,
12
- mock: async (prompt: string, model?: string) => `[MOCK OUTPUT] ${prompt}`
13
- };
14
-
15
- // Returns an array of providers whose API keys exist in environment
16
- export function getAvailableProviders(): Provider[] {
17
- const available: Provider[] = [];
18
- // Always prefer openrouter if present
19
- if (process.env.AI_HOOK_OPENROUTER_KEY) {
20
- available.push("openrouter");
21
- }
22
- // Add others in order of their presence
23
- if (process.env.AI_HOOK_GROQ_KEY && !available.includes("groq")) {
24
- available.push("groq");
25
- }
26
- if (process.env.AI_HOOK_OPENAI_KEY && !available.includes("openai")) {
27
- available.push("openai");
28
- }
29
- return available;
30
- }
31
-
32
- // ✅ Returns both the provider function and the actual provider name
33
- export function getProvider(name?: Provider): { fn: ProviderFunction<any>; provider: Provider | "mock" } {
34
- const available = getAvailableProviders();
35
-
36
- // 1. If user specified provider and it's available
37
- if (name && providers[name]) {
38
- return { fn: providers[name], provider: name };
39
- }
40
-
41
- // 2. If at least one provider is available, pick the first one (openrouter always preferred if present)
42
- if (available.length > 0) {
43
- console.log(`[ai-hooks] Auto-selected provider: ${available[0]}`);
44
- return { fn: providers[available[0]], provider: available[0] };
45
- }
46
-
47
- // 3. No valid keys found → throw error (single instruction, no fallback)
48
- throw new AIHookError(
49
- "NO_PROVIDER_FOUND",
50
- "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",
51
- undefined,
52
- "Reference .env.example for setup instructions."
53
- );
54
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAvailableProviders = getAvailableProviders;
4
+ exports.getProvider = getProvider;
5
+ const errors_1 = require("../errors");
6
+ const openai_1 = require("./openai");
7
+ const openrouter_1 = require("./openrouter");
8
+ const groq_1 = require("./groq");
9
+ const providers = {
10
+ openai: openai_1.callOpenAI,
11
+ openrouter: openrouter_1.callOpenRouter,
12
+ groq: groq_1.callGroq,
13
+ mock: async (prompt, model) => `[MOCK OUTPUT] ${prompt}`
14
+ };
15
+ // Returns an array of providers whose API keys exist in environment
16
+ function getAvailableProviders() {
17
+ const available = [];
18
+ // Always prefer openrouter if present
19
+ if (process.env.AI_HOOK_OPENROUTER_KEY) {
20
+ available.push("openrouter");
21
+ }
22
+ // Add others in order of their presence
23
+ if (process.env.AI_HOOK_GROQ_KEY && !available.includes("groq")) {
24
+ available.push("groq");
25
+ }
26
+ if (process.env.AI_HOOK_OPENAI_KEY && !available.includes("openai")) {
27
+ available.push("openai");
28
+ }
29
+ return available;
30
+ }
31
+ // ✅ Returns both the provider function and the actual provider name
32
+ function getProvider(name) {
33
+ const available = getAvailableProviders();
34
+ // 1. If user specified provider and it's available
35
+ if (name && providers[name]) {
36
+ return { fn: providers[name], provider: name };
37
+ }
38
+ // 2. If at least one provider is available, pick the first one (openrouter always preferred if present)
39
+ if (available.length > 0) {
40
+ console.log(`[ai-hooks] ✅ Auto-selected provider: ${available[0]}`);
41
+ return { fn: providers[available[0]], provider: available[0] };
42
+ }
43
+ // 3. No valid keys found → throw error (single instruction, no fallback)
44
+ throw new errors_1.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.");
45
+ }
@@ -0,0 +1 @@
1
+ export declare function callOpenAI(prompt: string, model: string): Promise<any>;
@@ -0,0 +1,19 @@
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.callOpenAI = callOpenAI;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ async function callOpenAI(prompt, model) {
9
+ const key = process.env.AI_HOOK_OPENAI_KEY;
10
+ if (!key)
11
+ throw new Error("Missing AI_HOOK_OPENAI_KEY");
12
+ const response = await axios_1.default.post("https://api.openai.com/v1/chat/completions", {
13
+ model,
14
+ messages: [{ role: "user", content: prompt }]
15
+ }, {
16
+ headers: { Authorization: `Bearer ${key}` }
17
+ });
18
+ return response.data.choices[0].message.content;
19
+ }
@@ -0,0 +1 @@
1
+ export declare function callOpenRouter(prompt: string, model: string): Promise<string>;
@@ -0,0 +1,55 @@
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.callOpenRouter = callOpenRouter;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const errors_1 = require("../errors");
9
+ const BASE_URL = "https://openrouter.ai/api/v1";
10
+ async function callOpenRouter(prompt, model) {
11
+ const apiKey = process.env.AI_HOOK_OPENROUTER_KEY;
12
+ if (!apiKey) {
13
+ throw new errors_1.AIHookError("INVALID_API_KEY", "Missing OpenRouter API key.", "openrouter", "Set AI_HOOK_OPENROUTER_KEY in your environment variables.");
14
+ }
15
+ try {
16
+ const response = await axios_1.default.post(`${BASE_URL}/chat/completions`, {
17
+ model,
18
+ messages: [{ role: "user", content: prompt }],
19
+ }, {
20
+ headers: {
21
+ Authorization: `Bearer ${apiKey}`,
22
+ "Content-Type": "application/json",
23
+ },
24
+ });
25
+ const output = response.data?.choices?.[0]?.message?.content;
26
+ if (!output) {
27
+ throw new errors_1.AIHookError("PROVIDER_ERROR", "OpenRouter returned empty response.", "openrouter", "Check that the model name is correct and your API key has access to it.");
28
+ }
29
+ return output;
30
+ }
31
+ catch (err) {
32
+ if (err.response) {
33
+ const status = err.response.status;
34
+ // Make sure we get a string message
35
+ const text = err.response.data?.error
36
+ ? JSON.stringify(err.response.data.error)
37
+ : err.response.statusText || "Unknown error";
38
+ if (status === 400)
39
+ throw new errors_1.AIHookError("BAD_REQUEST", `OpenRouter rejected the request: ${text}`, "openrouter", "Check your prompt, model name, and payload format.");
40
+ if (status === 401)
41
+ throw new errors_1.AIHookError("INVALID_API_KEY", `Invalid OpenRouter API key: ${text}`, "openrouter", "Verify your AI_HOOK_OPENROUTER_KEY environment variable.");
42
+ if (status === 403)
43
+ throw new errors_1.AIHookError("MODEL_NOT_ALLOWED", `Your API key cannot access this model: ${text}`, "openrouter", "Try a different model or check API key permissions.");
44
+ if (status === 429)
45
+ throw new errors_1.AIHookError("RATE_LIMIT", `Too many requests to OpenRouter: ${text}`, "openrouter", "Consider throttling requests or upgrading your plan.");
46
+ throw new errors_1.AIHookError("PROVIDER_ERROR", `OpenRouter API error: ${text}`, "openrouter", "Check your model, prompt, and API key.");
47
+ }
48
+ else if (err.request) {
49
+ throw new errors_1.AIHookError("NETWORK_ERROR", "Network error while contacting OpenRouter.", "openrouter", "Check your internet connection.");
50
+ }
51
+ else {
52
+ throw new errors_1.AIHookError("UNKNOWN_ERROR", err.message, "openrouter");
53
+ }
54
+ }
55
+ }
@@ -1,13 +1,10 @@
1
- import { Provider, ProviderModels } from "../index";
2
-
3
- export interface ProviderFunction<P extends Provider = Provider> {
4
- (prompt: string, model: ProviderModels[P]): Promise<string>;
5
- }
6
-
7
- export interface ProviderMap {
8
- openai: ProviderFunction<"openai">;
9
- openrouter: ProviderFunction<"openrouter">;
10
- groq: ProviderFunction<"groq">;
11
- mock: ProviderFunction<any>; // generic fallback for mock
12
- }
13
-
1
+ import { Provider, ProviderModels } from "../index";
2
+ export interface ProviderFunction<P extends Provider = Provider> {
3
+ (prompt: string, model: ProviderModels[P]): Promise<string>;
4
+ }
5
+ export interface ProviderMap {
6
+ openai: ProviderFunction<"openai">;
7
+ openrouter: ProviderFunction<"openrouter">;
8
+ groq: ProviderFunction<"groq">;
9
+ mock: ProviderFunction<any>;
10
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ export type GroqModel = "allam-2-7b" | "deepseek-r1-distill-llama-70b" | "gemma2-9b-it" | "groq/compound" | "groq/compound-mini" | "llama-3.1-8b-instant" | "llama-3.3-70b-versatile" | "meta-llama/llama-4-maverick-17b-128e-instruct" | "meta-llama/llama-4-scout-17b-16e-instruct" | "meta-llama/llama-guard-4-12b" | "meta-llama/llama-prompt-guard-2-22m" | "meta-llama/llama-prompt-guard-2-86m" | "moonshotai/kimi-k2-instruct" | "moonshotai/kimi-k2-instruct-0905" | "openai/gpt-oss-120b" | "openai/gpt-oss-20b" | "qwen/qwen3-32b";
2
+ export declare const GroqDefaultModel: GroqModel;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GroqDefaultModel = void 0;
4
+ exports.GroqDefaultModel = "groq/compound";
@@ -0,0 +1,24 @@
1
+ import { OpenAIModel } from "./openai";
2
+ import { OpenRouterModel } from "./openrouter";
3
+ import { GroqModel } from "./groq";
4
+ export type Provider = "openai" | "openrouter" | "groq";
5
+ export type ProviderModels = {
6
+ openai: OpenAIModel;
7
+ openrouter: OpenRouterModel;
8
+ groq: GroqModel;
9
+ };
10
+ export declare const DEFAULT_MODEL: {
11
+ [P in Provider]: ProviderModels[P];
12
+ };
13
+ export type TaskType = "summarize" | "translate" | "explain" | "rewrite" | "sentiment" | "codeReview";
14
+ export type WrapOptions<P extends Provider | undefined = undefined> = {
15
+ provider: P extends Provider ? P : never;
16
+ model?: P extends Provider ? ProviderModels[P] : never;
17
+ task: TaskType;
18
+ targetLanguage?: string;
19
+ } | {
20
+ provider?: never;
21
+ model?: never;
22
+ task: TaskType;
23
+ targetLanguage?: string;
24
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_MODEL = void 0;
4
+ const openai_1 = require("./openai");
5
+ const openrouter_1 = require("./openrouter");
6
+ const groq_1 = require("./groq");
7
+ exports.DEFAULT_MODEL = {
8
+ openai: openai_1.OpenAIDefaultModel,
9
+ openrouter: openrouter_1.OpenRouterDefaultModel,
10
+ groq: groq_1.GroqDefaultModel,
11
+ };
@@ -1,3 +1,2 @@
1
- export type OpenAIModel = "gpt-4" | "gpt-4o" | "gpt-3.5-turbo";
2
-
3
- export const OpenAIDefaultModel: OpenAIModel = "gpt-4";
1
+ export type OpenAIModel = "gpt-4" | "gpt-4o" | "gpt-3.5-turbo";
2
+ export declare const OpenAIDefaultModel: OpenAIModel;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpenAIDefaultModel = void 0;
4
+ exports.OpenAIDefaultModel = "gpt-4";
@@ -0,0 +1,2 @@
1
+ export type OpenRouterModel = "openai/gpt-oss-20b:free" | "openai/gpt-4.1" | "openai/gpt-5-pro" | "openai/gpt-5-codex" | "openai/gpt-5-chat" | "openai/gpt-5" | "openai/gpt-5-mini" | "openai/gpt-5-nano" | "openai/gpt-oss-120b" | "openai/gpt-oss-20b" | "openai/o3-pro" | "openai/codex-mini" | "openai/o3" | "openai/o4-mini" | "openai/gpt-4.1-mini" | "openai/gpt-4.1-nano" | "openai/o1-pro" | "openai/gpt-4o-mini-search-preview" | "openai/gpt-4o-search-preview" | "openai/o3-mini-high" | "openai/o3-mini" | "openai/o1" | "openai/gpt-4o-2024-11-20" | "openai/o1-mini" | "openai/o1-mini-2024-09-12" | "openai/chatgpt-4o-latest" | "openai/gpt-4o-2024-08-06" | "openai/gpt-4o-mini" | "openai/gpt-4o-mini-2024-07-18" | "openai/gpt-4o" | "openai/gpt-4o:extended" | "openai/gpt-4o-2024-05-13" | "openai/gpt-4-turbo" | "openai/gpt-3.5-turbo-0613" | "openai/gpt-4-turbo-preview" | "openai/gpt-4-1106-preview" | "openai/gpt-3.5-turbo-instruct" | "openai/gpt-3.5-turbo-16k" | "openai/gpt-3.5-turbo" | "openai/gpt-4" | "openai/gpt-4-0314" | "openai/gpt-4.5-preview" | "openai/o1-preview" | "openai/o1-preview-2024-09-12" | "openai/gpt-4-vision-preview" | "openai/gpt-3.5-turbo-1106" | "openai/gpt-4-32k" | "openai/gpt-4-32k-0314" | "openai/gpt-3.5-turbo-0301" | "openai/gpt-3.5-turbo-0125";
2
+ export declare const OpenRouterDefaultModel: OpenRouterModel;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpenRouterDefaultModel = void 0;
4
+ exports.OpenRouterDefaultModel = "openai/gpt-oss-20b:free";
package/dist/wrap.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { WrapOptions, Provider } from "./types";
2
+ export declare function wrap<T extends (...args: any[]) => any, P extends Provider | undefined = undefined>(fn: T, options: WrapOptions<P>): (...args: Parameters<T>) => Promise<{
3
+ output: string;
4
+ meta: any;
5
+ }>;
package/dist/wrap.js ADDED
@@ -0,0 +1,85 @@
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.wrap = wrap;
7
+ const dotenv_1 = __importDefault(require("dotenv"));
8
+ dotenv_1.default.config();
9
+ const providers_1 = require("./providers");
10
+ const types_1 = require("./types");
11
+ function handleError(err) {
12
+ if (err && typeof err === "object" && "pretty" in err && typeof err.pretty === "function") {
13
+ // Print pretty message and exit
14
+ console.error(err.pretty());
15
+ process.exit(1);
16
+ }
17
+ else {
18
+ console.error(err);
19
+ process.exit(1);
20
+ }
21
+ throw new Error("Process exited due to AIHookError"); // for TS never
22
+ }
23
+ function wrap(fn, options) {
24
+ return async (...args) => {
25
+ try {
26
+ const input = fn(...args);
27
+ // Step 1: get provider function and the actual provider name
28
+ const { fn: providerFn, provider: providerKey } = (0, providers_1.getProvider)(options.provider);
29
+ // Step 2: pick model: passed model or provider-specific default
30
+ const model = options.model || (providerKey in types_1.DEFAULT_MODEL ? types_1.DEFAULT_MODEL[providerKey] : undefined);
31
+ if (!model) {
32
+ throw new (require('./errors').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.");
33
+ }
34
+ // Step 3: build prompt
35
+ const prompt = buildPrompt(options.task, input, options.targetLanguage);
36
+ const startTime = Date.now();
37
+ let output;
38
+ try {
39
+ output = await providerFn(prompt, model);
40
+ }
41
+ catch (err) {
42
+ if (err instanceof require('./errors').AIHookError) {
43
+ handleError(err);
44
+ }
45
+ if (err instanceof Error) {
46
+ throw new Error(`[ai-hooks] Unknown error calling provider: ${err.message}`);
47
+ }
48
+ throw new Error(`[ai-hooks] Unknown non-error thrown by provider: ${String(err)}`);
49
+ }
50
+ const endTime = Date.now();
51
+ return {
52
+ output,
53
+ meta: {
54
+ provider: providerKey,
55
+ model,
56
+ cached: false,
57
+ estimatedCostUSD: 0.0,
58
+ latencyMs: endTime - startTime
59
+ }
60
+ };
61
+ }
62
+ catch (err) {
63
+ handleError(err);
64
+ }
65
+ };
66
+ }
67
+ function buildPrompt(task, text, targetLanguage) {
68
+ switch (task) {
69
+ case "summarize":
70
+ return `Summarize the following text:\n${text}`;
71
+ case "translate":
72
+ const language = targetLanguage || "English"; // default to English
73
+ return `Translate this text into ${language}:\n${text}`;
74
+ case "explain":
75
+ return `Explain this clearly:\n${text}`;
76
+ case "rewrite":
77
+ return `Rewrite this text with better clarity:\n${text}`;
78
+ case "sentiment":
79
+ return `Analyze the sentiment of this text:\n${text}`;
80
+ case "codeReview":
81
+ return `Review this code and suggest improvements:\n${text}`;
82
+ default:
83
+ return text;
84
+ }
85
+ }
package/package.json CHANGED
@@ -1,8 +1,19 @@
1
1
  {
2
2
  "name": "npm-ai-hooks",
3
- "version": "1.0.0-beta.0",
4
- "description": "**Universal AI Hook Layer for Node.js – one wrapper for all AI providers.**\r 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
- "main": "index.js",
3
+ "version": "1.0.0",
4
+ "description": "Universal AI Hook Layer for Node.js – one wrapper for all AI providers.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist/**/*"
16
+ ],
6
17
  "scripts": {
7
18
  "dev": "ts-node src/index.ts",
8
19
  "build:clean": "rimraf dist && tsc",
@@ -12,7 +23,7 @@
12
23
  "demo": "npx ts-node examples/demo.ts"
13
24
  },
14
25
  "keywords": [],
15
- "author": "",
26
+ "author": "AteebNoOne",
16
27
  "license": "ISC",
17
28
  "dependencies": {
18
29
  "axios": "^1.12.2",
package/.env.example DELETED
@@ -1,14 +0,0 @@
1
- # OpenAI API key (for OpenRouter OpenAI models or standalone OpenAI)
2
- AI_HOOK_OPENAI_KEY=your_openai_api_key_here
3
-
4
- # OpenRouter API key
5
- AI_HOOK_OPENROUTER_KEY=your_openrouter_api_key_here
6
-
7
- # Groq API key
8
- AI_HOOK_GROQ_KEY=your_groq_api_key_here
9
-
10
- # Default provider (optional)
11
- # AI_HOOK_DEFAULT_PROVIDER=openrouter
12
-
13
- # Default model is handled by code, so no need to set it here
14
- # AI_HOOK_DEFAULT_MODEL=
@@ -1,35 +0,0 @@
1
-
2
- ---
3
-
4
- ## 3. `CODE_OF_CONDUCT.md`
5
-
6
- ```md
7
- # Contributor Covenant Code of Conduct
8
-
9
- ## Our Pledge
10
-
11
- We as members, contributors, and maintainers pledge to make participation in this project a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
12
-
13
- ## Our Standards
14
-
15
- Examples of behavior that contributes to a positive environment include:
16
-
17
- - Using welcoming and inclusive language
18
- - Being respectful of differing viewpoints and experiences
19
- - Gracefully accepting constructive criticism
20
- - Focusing on what is best for the community
21
- - Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior include:
24
-
25
- - Harassment of public or private forms
26
- - Trolling, insulting/derogatory comments
27
- - Publishing others’ private information without permission
28
- - Other conduct which could reasonably be considered inappropriate
29
-
30
- ## Enforcement
31
-
32
- Instances of abusive behavior may be reported to the maintainers via [issues](https://github.com/RealTeebot/npm-ai-hooks/issues).
33
- All complaints will be reviewed and addressed appropriately.
34
-
35
- This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/).