npm-ai-hooks 2.0.4 → 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.
@@ -2,6 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AIHookError = void 0;
4
4
  class AIHookError extends Error {
5
+ code;
6
+ provider;
7
+ suggestion;
5
8
  constructor(code, message, provider, suggestion) {
6
9
  super(message);
7
10
  this.code = code;
@@ -1,12 +1,9 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.BaseProvider = void 0;
7
- const axios_1 = __importDefault(require("axios"));
8
4
  const errors_1 = require("../../errors");
9
5
  class BaseProvider {
6
+ config;
10
7
  constructor(config) {
11
8
  this.config = config;
12
9
  }
@@ -54,7 +51,43 @@ class BaseProvider {
54
51
  };
55
52
  }
56
53
  async makeRequest(config) {
57
- return (0, axios_1.default)(config);
54
+ try {
55
+ const response = await fetch(config.url, {
56
+ method: config.method || "POST",
57
+ headers: config.headers,
58
+ body: config.data ? JSON.stringify(config.data) : undefined,
59
+ });
60
+ let data;
61
+ try {
62
+ data = await response.json();
63
+ }
64
+ catch {
65
+ data = await response.text();
66
+ }
67
+ if (!response.ok) {
68
+ // Emulate axios error shape for the error handler
69
+ throw Object.assign(new Error(`Request failed with status code ${response.status}`), {
70
+ response: {
71
+ status: response.status,
72
+ statusText: response.statusText,
73
+ data: data
74
+ }
75
+ });
76
+ }
77
+ return { data };
78
+ }
79
+ catch (error) {
80
+ const err = error;
81
+ // If it's already an HTTP error we just threw, rethrow it
82
+ if (err.response) {
83
+ throw err;
84
+ }
85
+ // Otherwise, it's a network error (e.g. fetch failed entirely)
86
+ // Emulate axios network error shape
87
+ throw Object.assign(new Error(err.message || "Network Error"), {
88
+ request: {}
89
+ });
90
+ }
58
91
  }
59
92
  parseResponse(response) {
60
93
  const output = this.config.responseParser(response);
@@ -64,14 +97,15 @@ class BaseProvider {
64
97
  return output;
65
98
  }
66
99
  handleError(error) {
67
- if (error.response) {
68
- return this.handleHttpError(error);
100
+ const err = error;
101
+ if (err.response) {
102
+ return this.handleHttpError(err);
69
103
  }
70
- else if (error.request) {
104
+ else if (err.request) {
71
105
  return new errors_1.AIHookError("NETWORK_ERROR", this.config.errorMessages.networkError, this.config.name, "Check your internet connection");
72
106
  }
73
107
  else {
74
- return new errors_1.AIHookError("UNKNOWN_ERROR", error.message || this.config.errorMessages.unknownError, this.config.name);
108
+ return new errors_1.AIHookError("UNKNOWN_ERROR", err.message || this.config.errorMessages.unknownError, this.config.name);
75
109
  }
76
110
  }
77
111
  getCapitalizedProviderName() {
@@ -6,9 +6,10 @@ const BaseProvider_1 = require("./BaseProvider");
6
6
  const ProviderConfigs_1 = require("./ProviderConfigs");
7
7
  const SpecializedProviders_1 = require("./SpecializedProviders");
8
8
  class ProviderManager {
9
+ providers = new Map();
10
+ defaultProvider;
11
+ providerFunctions = new Map();
9
12
  constructor(options) {
10
- this.providers = new Map();
11
- this.providerFunctions = new Map();
12
13
  this.initializeProviders(options);
13
14
  }
14
15
  initializeProviders(options) {
@@ -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, model) => ({
24
+ geminiStyle: (prompt, _model) => ({
22
25
  contents: [{
23
26
  parts: [{ text: prompt }]
24
27
  }]
@@ -2,14 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.providerRegistry = exports.ProviderRegistry = void 0;
4
4
  class ProviderRegistry {
5
- constructor() {
6
- this.providers = new Map();
7
- this.providerFunctions = new Map();
8
- }
5
+ providers = new Map();
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ providerFunctions = new Map();
9
8
  register(name, provider) {
10
9
  this.providers.set(name, provider);
11
10
  this.providerFunctions.set(name, this.createProviderFunction(provider));
12
11
  }
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
13
  get(name) {
14
14
  return this.providerFunctions.get(name);
15
15
  }
@@ -36,6 +36,7 @@ class ProviderRegistry {
36
36
  }
37
37
  return available;
38
38
  }
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
40
  createProviderFunction(provider) {
40
41
  return async (prompt, model) => {
41
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, model) => `[MOCK OUTPUT] ${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
- // Returns both the provider function and the actual provider name (legacy)
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
- // Returns the full ordered provider chain for fallback (new system only)
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
- providerInstance.apiKey = apiKey;
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 (error.message?.includes('401') || error.message?.includes('Unauthorized') || error.message?.includes('Invalid API key')) {
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 (error.message?.includes('403') || error.message?.includes('Forbidden')) {
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 (error.message?.includes('429') || error.message?.includes('rate limit')) {
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 && typeof err === "object" && "pretty" in err && typeof err.pretty === "function") {
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":
@@ -1,4 +1,7 @@
1
1
  export class AIHookError extends Error {
2
+ code;
3
+ provider;
4
+ suggestion;
2
5
  constructor(code, message, provider, suggestion) {
3
6
  super(message);
4
7
  this.code = code;
@@ -1,6 +1,6 @@
1
- import axios from "axios";
2
1
  import { AIHookError } from "../../errors";
3
2
  export class BaseProvider {
3
+ config;
4
4
  constructor(config) {
5
5
  this.config = config;
6
6
  }
@@ -48,7 +48,43 @@ export class BaseProvider {
48
48
  };
49
49
  }
50
50
  async makeRequest(config) {
51
- return axios(config);
51
+ try {
52
+ const response = await fetch(config.url, {
53
+ method: config.method || "POST",
54
+ headers: config.headers,
55
+ body: config.data ? JSON.stringify(config.data) : undefined,
56
+ });
57
+ let data;
58
+ try {
59
+ data = await response.json();
60
+ }
61
+ catch {
62
+ data = await response.text();
63
+ }
64
+ if (!response.ok) {
65
+ // Emulate axios error shape for the error handler
66
+ throw Object.assign(new Error(`Request failed with status code ${response.status}`), {
67
+ response: {
68
+ status: response.status,
69
+ statusText: response.statusText,
70
+ data: data
71
+ }
72
+ });
73
+ }
74
+ return { data };
75
+ }
76
+ catch (error) {
77
+ const err = error;
78
+ // If it's already an HTTP error we just threw, rethrow it
79
+ if (err.response) {
80
+ throw err;
81
+ }
82
+ // Otherwise, it's a network error (e.g. fetch failed entirely)
83
+ // Emulate axios network error shape
84
+ throw Object.assign(new Error(err.message || "Network Error"), {
85
+ request: {}
86
+ });
87
+ }
52
88
  }
53
89
  parseResponse(response) {
54
90
  const output = this.config.responseParser(response);
@@ -58,14 +94,15 @@ export class BaseProvider {
58
94
  return output;
59
95
  }
60
96
  handleError(error) {
61
- if (error.response) {
62
- return this.handleHttpError(error);
97
+ const err = error;
98
+ if (err.response) {
99
+ return this.handleHttpError(err);
63
100
  }
64
- else if (error.request) {
101
+ else if (err.request) {
65
102
  return new AIHookError("NETWORK_ERROR", this.config.errorMessages.networkError, this.config.name, "Check your internet connection");
66
103
  }
67
104
  else {
68
- return new AIHookError("UNKNOWN_ERROR", error.message || this.config.errorMessages.unknownError, this.config.name);
105
+ return new AIHookError("UNKNOWN_ERROR", err.message || this.config.errorMessages.unknownError, this.config.name);
69
106
  }
70
107
  }
71
108
  getCapitalizedProviderName() {
@@ -3,9 +3,10 @@ import { BaseProvider } from "./BaseProvider";
3
3
  import { providerConfigs } from "./ProviderConfigs";
4
4
  import { ClaudeProvider, GeminiProvider, OpenRouterProvider } from "./SpecializedProviders";
5
5
  export class ProviderManager {
6
+ providers = new Map();
7
+ defaultProvider;
8
+ providerFunctions = new Map();
6
9
  constructor(options) {
7
- this.providers = new Map();
8
- this.providerFunctions = new Map();
9
10
  this.initializeProviders(options);
10
11
  }
11
12
  initializeProviders(options) {
@@ -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, model) => ({
21
+ geminiStyle: (prompt, _model) => ({
19
22
  contents: [{
20
23
  parts: [{ text: prompt }]
21
24
  }]
@@ -1,12 +1,12 @@
1
1
  export class ProviderRegistry {
2
- constructor() {
3
- this.providers = new Map();
4
- this.providerFunctions = new Map();
5
- }
2
+ providers = new Map();
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ providerFunctions = new Map();
6
5
  register(name, provider) {
7
6
  this.providers.set(name, provider);
8
7
  this.providerFunctions.set(name, this.createProviderFunction(provider));
9
8
  }
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
10
  get(name) {
11
11
  return this.providerFunctions.get(name);
12
12
  }
@@ -33,6 +33,7 @@ export class ProviderRegistry {
33
33
  }
34
34
  return available;
35
35
  }
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
37
  createProviderFunction(provider) {
37
38
  return async (prompt, model) => {
38
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, model) => `[MOCK OUTPUT] ${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
- // Returns both the provider function and the actual provider name (legacy)
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
- // Returns the full ordered provider chain for fallback (new system only)
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
- providerInstance.apiKey = apiKey;
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 (error.message?.includes('401') || error.message?.includes('Unauthorized') || error.message?.includes('Invalid API key')) {
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 (error.message?.includes('403') || error.message?.includes('Forbidden')) {
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 (error.message?.includes('429') || error.message?.includes('rate limit')) {
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 && typeof err === "object" && "pretty" in err && typeof err.pretty === "function") {
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":
@@ -1,12 +1,20 @@
1
- import { AxiosRequestConfig, AxiosResponse } from "axios";
2
1
  import { AIHookError } from "../../errors";
2
+ export interface FetchRequestConfig {
3
+ url: string;
4
+ method?: string;
5
+ data?: unknown;
6
+ headers?: Record<string, string>;
7
+ }
8
+ export interface FetchResponse {
9
+ data: unknown;
10
+ }
3
11
  export interface ProviderConfig {
4
12
  name: string;
5
13
  baseUrl: string;
6
14
  envKey: string;
7
15
  headers: Record<string, string>;
8
- requestBody: (prompt: string, model: string) => any;
9
- responseParser: (response: AxiosResponse) => string;
16
+ requestBody: (prompt: string, model: string) => unknown;
17
+ responseParser: (response: FetchResponse) => string;
10
18
  errorMessages: {
11
19
  missingKey: string;
12
20
  emptyResponse: string;
@@ -23,11 +31,17 @@ export declare class BaseProvider {
23
31
  call(prompt: string, model: string): Promise<string>;
24
32
  protected getApiKey(): string | undefined;
25
33
  protected validateApiKey(apiKey: string | undefined): void;
26
- protected buildRequestConfig(prompt: string, model: string, apiKey: string): AxiosRequestConfig;
34
+ protected buildRequestConfig(prompt: string, model: string, apiKey: string): FetchRequestConfig;
27
35
  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;
36
+ protected makeRequest(config: FetchRequestConfig): Promise<FetchResponse>;
37
+ protected parseResponse(response: FetchResponse): string;
38
+ protected handleError(error: unknown): AIHookError;
31
39
  protected getCapitalizedProviderName(): string;
32
- protected handleHttpError(error: any): AIHookError;
40
+ protected handleHttpError(error: Error & {
41
+ response: {
42
+ status: number;
43
+ statusText?: string;
44
+ data?: any;
45
+ };
46
+ }): AIHookError;
33
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: any;
28
+ fn: (prompt: string, model?: string) => Promise<string>;
29
29
  provider: Provider;
30
30
  }>;
31
31
  getProvider(name?: Provider): {
32
- fn: any;
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: any) => any;
4
- claudeStyle: (response: any) => any;
5
- geminiStyle: (response: any) => any;
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, model: string) => {
23
+ geminiStyle: (prompt: string, _model: string) => {
24
24
  contents: {
25
25
  parts: {
26
26
  text: string;
@@ -8,75 +8,21 @@ export declare class GeminiProvider extends BaseProvider {
8
8
  constructor();
9
9
  protected buildRequestConfig(prompt: string, model: string, apiKey: string): {
10
10
  url: string;
11
- headers: {};
12
- method?: (string & {}) | import("axios").Method;
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 | ((string & {}) | "xhr" | "http" | "fetch")) | (import("axios").AxiosAdapter | ((string & {}) | "xhr" | "http" | "fetch"))[];
24
- auth?: import("axios").AxiosBasicCredentials;
25
- responseType?: import("axios").ResponseType;
26
- responseEncoding?: (string & {}) | import("axios").responseEncoding;
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
- }, requestDetails: {
40
- headers: Record<string, string>;
41
- url: string;
42
- method: string;
43
- }) => void;
44
- socketPath?: string | null;
45
- allowedSocketPaths?: string | string[] | null;
46
- transport?: any;
47
- httpAgent?: any;
48
- httpsAgent?: any;
49
- proxy?: import("axios").AxiosProxyConfig | false;
50
- cancelToken?: import("axios").CancelToken | undefined;
51
- decompress?: boolean;
52
- transitional?: import("axios").TransitionalOptions;
53
- signal?: import("axios").GenericAbortSignal;
54
- insecureHTTPParser?: boolean;
55
- env?: {
56
- FormData?: new (...args: any[]) => object;
57
- fetch?: (input: URL | Request | string, init?: RequestInit) => Promise<Response>;
58
- Request?: new (input: URL | Request | string, init?: RequestInit) => Request;
59
- Response?: new (body?: ArrayBuffer | ArrayBufferView | Blob | FormData | URLSearchParams | string | null, init?: ResponseInit) => Response;
11
+ headers: {
12
+ [x: string]: string;
60
13
  };
61
- formSerializer?: import("axios").FormSerializerOptions;
62
- family?: import("axios").AddressFamily;
63
- 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>);
64
- withXSRFToken?: boolean | ((config: import("axios").InternalAxiosRequestConfig) => boolean | undefined);
65
- parseReviver?: (this: any, key: string, value: any, context?: {
66
- source?: string;
67
- }) => any;
68
- fetchOptions?: Omit<RequestInit, "body" | "headers" | "method" | "signal"> | Record<string, any>;
69
- httpVersion?: 1 | 2;
70
- http2Options?: Record<string, any> & {
71
- sessionTimeout?: number;
72
- };
73
- formDataHeaderPolicy?: "legacy" | "content-only";
74
- redact?: string[];
75
- sensitiveHeaders?: string[];
14
+ method?: string;
15
+ data?: unknown;
76
16
  };
77
17
  protected buildAuthHeaders(): Record<string, string>;
78
18
  }
79
19
  export declare class OpenRouterProvider extends BaseProvider {
80
20
  constructor();
81
- protected handleHttpError(error: any): AIHookError;
21
+ protected handleHttpError(error: Error & {
22
+ response: {
23
+ status: number;
24
+ statusText?: string;
25
+ data?: any;
26
+ };
27
+ }): AIHookError;
82
28
  }
@@ -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: any;
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: any;
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: any;
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.4",
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 . --ext .ts",
37
+ "lint": "eslint .",
38
38
  "format": "prettier --write .",
39
39
  "prepare": "npm run build",
40
40
  "demo": "npx ts-node examples/demo.ts",
@@ -48,19 +48,18 @@
48
48
  "url": "git+https://github.com/iTeebot/npm-ai-hooks.git"
49
49
  },
50
50
  "license": "MIT",
51
- "dependencies": {
52
- "axios": "^1.12.2"
53
- },
54
51
  "devDependencies": {
52
+ "@eslint/js": "^10.0.1",
55
53
  "@types/jest": "^30.0.0",
56
- "@types/node": "^24.7.0",
57
- "eslint": "^9.37.0",
54
+ "@types/node": "^26.0.1",
55
+ "eslint": "^10.5.0",
58
56
  "jest": "^30.2.0",
59
57
  "prettier": "^3.6.2",
60
58
  "rimraf": "^6.0.1",
61
59
  "ts-jest": "^29.4.4",
62
60
  "ts-node": "^10.9.2",
63
- "typescript": "^5.9.3"
61
+ "typescript": "^6.0.3",
62
+ "typescript-eslint": "^8.62.0"
64
63
  },
65
64
  "keywords": [
66
65
  "ai",
@@ -93,5 +92,8 @@
93
92
  "allowScripts": {
94
93
  "fsevents@2.3.3": true,
95
94
  "unrs-resolver@1.12.2": true
95
+ },
96
+ "overrides": {
97
+ "js-yaml": "^5.2.0"
96
98
  }
97
99
  }