@node-llm/core 1.8.0 → 1.10.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 (101) hide show
  1. package/README.md +35 -0
  2. package/dist/aliases.d.ts +105 -9
  3. package/dist/aliases.d.ts.map +1 -1
  4. package/dist/aliases.js +105 -9
  5. package/dist/chat/Chat.d.ts +8 -3
  6. package/dist/chat/Chat.d.ts.map +1 -1
  7. package/dist/chat/Chat.js +181 -131
  8. package/dist/chat/ChatOptions.d.ts +2 -0
  9. package/dist/chat/ChatOptions.d.ts.map +1 -1
  10. package/dist/chat/ChatResponse.d.ts +24 -3
  11. package/dist/chat/ChatResponse.d.ts.map +1 -1
  12. package/dist/chat/ChatResponse.js +72 -5
  13. package/dist/chat/ChatStream.d.ts.map +1 -1
  14. package/dist/chat/ChatStream.js +111 -56
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js +9 -7
  17. package/dist/constants.d.ts +6 -0
  18. package/dist/constants.d.ts.map +1 -1
  19. package/dist/constants.js +6 -0
  20. package/dist/errors/index.d.ts +20 -2
  21. package/dist/errors/index.d.ts.map +1 -1
  22. package/dist/errors/index.js +31 -3
  23. package/dist/index.d.ts +5 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -0
  26. package/dist/llm.d.ts +8 -1
  27. package/dist/llm.d.ts.map +1 -1
  28. package/dist/llm.js +156 -59
  29. package/dist/middlewares/CostGuardMiddleware.d.ts +24 -0
  30. package/dist/middlewares/CostGuardMiddleware.d.ts.map +1 -0
  31. package/dist/middlewares/CostGuardMiddleware.js +23 -0
  32. package/dist/middlewares/PIIMaskMiddleware.d.ts +23 -0
  33. package/dist/middlewares/PIIMaskMiddleware.d.ts.map +1 -0
  34. package/dist/middlewares/PIIMaskMiddleware.js +41 -0
  35. package/dist/middlewares/UsageLoggerMiddleware.d.ts +22 -0
  36. package/dist/middlewares/UsageLoggerMiddleware.d.ts.map +1 -0
  37. package/dist/middlewares/UsageLoggerMiddleware.js +30 -0
  38. package/dist/middlewares/index.d.ts +4 -0
  39. package/dist/middlewares/index.d.ts.map +1 -0
  40. package/dist/middlewares/index.js +3 -0
  41. package/dist/models/ModelRegistry.d.ts.map +1 -1
  42. package/dist/models/ModelRegistry.js +4 -2
  43. package/dist/models/PricingRegistry.js +3 -3
  44. package/dist/models/{models.js → models.json} +9934 -8196
  45. package/dist/providers/BaseProvider.d.ts +6 -1
  46. package/dist/providers/BaseProvider.d.ts.map +1 -1
  47. package/dist/providers/BaseProvider.js +19 -0
  48. package/dist/providers/anthropic/AnthropicProvider.d.ts.map +1 -1
  49. package/dist/providers/anthropic/AnthropicProvider.js +2 -1
  50. package/dist/providers/anthropic/Chat.d.ts.map +1 -1
  51. package/dist/providers/anthropic/Chat.js +2 -1
  52. package/dist/providers/anthropic/Errors.d.ts.map +1 -1
  53. package/dist/providers/anthropic/Errors.js +15 -1
  54. package/dist/providers/anthropic/Streaming.d.ts.map +1 -1
  55. package/dist/providers/anthropic/Streaming.js +19 -3
  56. package/dist/providers/bedrock/Chat.d.ts.map +1 -1
  57. package/dist/providers/bedrock/Chat.js +2 -20
  58. package/dist/providers/bedrock/Errors.d.ts +2 -0
  59. package/dist/providers/bedrock/Errors.d.ts.map +1 -0
  60. package/dist/providers/bedrock/Errors.js +51 -0
  61. package/dist/providers/bedrock/Streaming.d.ts.map +1 -1
  62. package/dist/providers/bedrock/Streaming.js +2 -3
  63. package/dist/providers/deepseek/Chat.d.ts.map +1 -1
  64. package/dist/providers/deepseek/Chat.js +2 -2
  65. package/dist/providers/deepseek/DeepSeekProvider.d.ts.map +1 -1
  66. package/dist/providers/deepseek/DeepSeekProvider.js +2 -1
  67. package/dist/providers/deepseek/Errors.d.ts +2 -0
  68. package/dist/providers/deepseek/Errors.d.ts.map +1 -0
  69. package/dist/providers/deepseek/Errors.js +45 -0
  70. package/dist/providers/deepseek/Streaming.d.ts.map +1 -1
  71. package/dist/providers/deepseek/Streaming.js +13 -2
  72. package/dist/providers/gemini/Errors.d.ts.map +1 -1
  73. package/dist/providers/gemini/Errors.js +13 -1
  74. package/dist/providers/gemini/GeminiProvider.d.ts.map +1 -1
  75. package/dist/providers/gemini/GeminiProvider.js +2 -1
  76. package/dist/providers/ollama/OllamaProvider.d.ts.map +1 -1
  77. package/dist/providers/ollama/OllamaProvider.js +2 -2
  78. package/dist/providers/openai/Errors.d.ts.map +1 -1
  79. package/dist/providers/openai/Errors.js +31 -5
  80. package/dist/providers/openai/OpenAIProvider.d.ts +1 -1
  81. package/dist/providers/openai/OpenAIProvider.d.ts.map +1 -1
  82. package/dist/providers/openai/OpenAIProvider.js +15 -3
  83. package/dist/providers/openai/Streaming.d.ts.map +1 -1
  84. package/dist/providers/openai/Streaming.js +10 -0
  85. package/dist/providers/openrouter/OpenRouterProvider.d.ts.map +1 -1
  86. package/dist/providers/openrouter/OpenRouterProvider.js +2 -1
  87. package/dist/providers/registry.d.ts +3 -0
  88. package/dist/providers/registry.d.ts.map +1 -1
  89. package/dist/providers/registry.js +10 -2
  90. package/dist/types/Middleware.d.ts +98 -0
  91. package/dist/types/Middleware.d.ts.map +1 -0
  92. package/dist/types/Middleware.js +1 -0
  93. package/dist/utils/json.d.ts +6 -0
  94. package/dist/utils/json.d.ts.map +1 -0
  95. package/dist/utils/json.js +43 -0
  96. package/dist/utils/middleware-runner.d.ts +7 -0
  97. package/dist/utils/middleware-runner.d.ts.map +1 -0
  98. package/dist/utils/middleware-runner.js +20 -0
  99. package/package.json +1 -1
  100. package/dist/models/models.d.ts +0 -572
  101. package/dist/models/models.d.ts.map +0 -1
@@ -37,7 +37,7 @@ export declare class OpenAIProvider extends BaseProvider implements Provider {
37
37
  apiBase(): string;
38
38
  headers(): Record<string, string>;
39
39
  protected providerName(): string;
40
- defaultModel(_feature?: string): string;
40
+ defaultModel(feature?: string): string;
41
41
  chat(request: ChatRequest): Promise<ChatResponse>;
42
42
  stream(request: ChatRequest): AsyncGenerator<ChatChunk>;
43
43
  listModels(): Promise<ModelInfo[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"OpenAIProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/OpenAIProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACT,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAe,SAAQ,YAAa,YAAW,QAAQ;IAwBtD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,qBAAqB;IAvB7D,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC;IAClC,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAC;IAC5C,SAAS,CAAC,aAAa,EAAE,YAAY,CAAC;IACtC,SAAS,CAAC,YAAY,EAAE,WAAW,CAAC;IACpC,SAAS,CAAC,oBAAoB,EAAE,mBAAmB,CAAC;IACpD,SAAS,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;IAC9C,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAC;IAErC,YAAY;gCACO,MAAM;+BACP,MAAM;0CACK,MAAM;oCACZ,MAAM;yCACD,MAAM;uCACR,MAAM;oCACT,MAAM;mCACP,MAAM;yCACA,MAAM;kCAEb,MAAM;MAChC;gBAE6B,OAAO,EAAE,qBAAqB;IAYtD,OAAO,IAAI,MAAM;IAIjB,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAOxC,SAAS,CAAC,YAAY,IAAI,MAAM;IAIhB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IAIjD,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAIhD,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC;IAIxD,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAIlC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAIpD,UAAU,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAIzE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIjE,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAGnE"}
1
+ {"version":3,"file":"OpenAIProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/OpenAIProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACT,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAe,SAAQ,YAAa,YAAW,QAAQ;IAwBtD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,qBAAqB;IAvB7D,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC;IAClC,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAC;IAC5C,SAAS,CAAC,aAAa,EAAE,YAAY,CAAC;IACtC,SAAS,CAAC,YAAY,EAAE,WAAW,CAAC;IACpC,SAAS,CAAC,oBAAoB,EAAE,mBAAmB,CAAC;IACpD,SAAS,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;IAC9C,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAC;IAErC,YAAY;gCACO,MAAM;+BACP,MAAM;0CACK,MAAM;oCACZ,MAAM;yCACD,MAAM;uCACR,MAAM;oCACT,MAAM;mCACP,MAAM;yCACA,MAAM;kCAEb,MAAM;MAChC;gBAE6B,OAAO,EAAE,qBAAqB;IAYtD,OAAO,IAAI,MAAM;IAIjB,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAOxC,SAAS,CAAC,YAAY,IAAI,MAAM;IAIhB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;IAehD,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAIhD,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC;IAIxD,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAIlC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAIpD,UAAU,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAIzE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIjE,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAGnE"}
@@ -1,4 +1,5 @@
1
1
  import { BaseProvider } from "../BaseProvider.js";
2
+ import { DEFAULT_OPENAI_BASE_URL } from "../../constants.js";
2
3
  import { Capabilities } from "./Capabilities.js";
3
4
  import { OpenAIChat } from "./Chat.js";
4
5
  import { OpenAIStreaming } from "./Streaming.js";
@@ -32,7 +33,7 @@ export class OpenAIProvider extends BaseProvider {
32
33
  constructor(options) {
33
34
  super();
34
35
  this.options = options;
35
- this.baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
36
+ this.baseUrl = options.baseUrl ?? DEFAULT_OPENAI_BASE_URL;
36
37
  this.chatHandler = new OpenAIChat(this, options.apiKey);
37
38
  this.streamingHandler = new OpenAIStreaming(this, options.apiKey);
38
39
  this.modelsHandler = new OpenAIModels(this.baseUrl, options.apiKey);
@@ -53,8 +54,19 @@ export class OpenAIProvider extends BaseProvider {
53
54
  providerName() {
54
55
  return "OpenAI";
55
56
  }
56
- defaultModel(_feature) {
57
- return "gpt-4o";
57
+ defaultModel(feature) {
58
+ switch (feature) {
59
+ case "embedding":
60
+ return "text-embedding-3-small";
61
+ case "transcription":
62
+ return "whisper-1";
63
+ case "moderation":
64
+ return "omni-moderation-latest";
65
+ case "image":
66
+ return "dall-e-3";
67
+ default:
68
+ return "gpt-4o";
69
+ }
58
70
  }
59
71
  async chat(request) {
60
72
  return this.chatHandler.execute(request);
@@ -1 +1 @@
1
- {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Streaming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQxD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,qBAAa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGd,aAAa,EAAE,cAAc,GAAG,MAAM,EACtC,MAAM,EAAE,MAAM;IAK1B,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC;CAoM9F"}
1
+ {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Streaming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQxD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,qBAAa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGd,aAAa,EAAE,cAAc,GAAG,MAAM,EACtC,MAAM,EAAE,MAAM;IAK1B,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC;CAgN9F"}
@@ -50,6 +50,7 @@ export class OpenAIStreaming {
50
50
  if (request.thinking?.effort && request.thinking.effort !== "none") {
51
51
  body.reasoning_effort = request.thinking.effort;
52
52
  }
53
+ body.stream_options = { include_usage: true };
53
54
  let done = false;
54
55
  // Track tool calls being built across chunks
55
56
  const toolCallsMap = new Map();
@@ -154,6 +155,15 @@ export class OpenAIStreaming {
154
155
  }
155
156
  }
156
157
  }
158
+ // Handle usage (usually in the special chunk when stream_options.include_usage: true)
159
+ if (json.usage) {
160
+ const usage = {
161
+ input_tokens: json.usage.prompt_tokens,
162
+ output_tokens: json.usage.completion_tokens,
163
+ total_tokens: json.usage.total_tokens
164
+ };
165
+ yield { content: "", usage };
166
+ }
157
167
  }
158
168
  catch (e) {
159
169
  // Re-throw APIError
@@ -1 +1 @@
1
- {"version":3,"file":"OpenRouterProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/openrouter/OpenRouterProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,kBAAmB,SAAQ,cAAc;IAC7C,YAAY;gCACO,MAAM;+BACP,MAAM;0CACK,MAAM;oCAEZ,MAAM;yCACD,MAAM;uCAER,MAAM;oCACT,MAAM;mCACP,MAAM;wCACD,MAAM;kCACZ,MAAM;MAChC;gBAEU,OAAO,EAAE,yBAAyB;IAO9C,SAAS,CAAC,YAAY,IAAI,MAAM;CAGjC"}
1
+ {"version":3,"file":"OpenRouterProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/openrouter/OpenRouterProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAI7D,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,kBAAmB,SAAQ,cAAc;IAC7C,YAAY;gCACO,MAAM;+BACP,MAAM;0CACK,MAAM;oCAEZ,MAAM;yCACD,MAAM;uCAER,MAAM;oCACT,MAAM;mCACP,MAAM;wCACD,MAAM;kCACZ,MAAM;MAChC;gBAEU,OAAO,EAAE,yBAAyB;IAO9C,SAAS,CAAC,YAAY,IAAI,MAAM;CAGjC"}
@@ -1,4 +1,5 @@
1
1
  import { OpenAIProvider } from "../openai/OpenAIProvider.js";
2
+ import { DEFAULT_OPENROUTER_BASE_URL } from "../../constants.js";
2
3
  import { OpenRouterCapabilities } from "./Capabilities.js";
3
4
  export class OpenRouterProvider extends OpenAIProvider {
4
5
  capabilities = {
@@ -16,7 +17,7 @@ export class OpenRouterProvider extends OpenAIProvider {
16
17
  constructor(options) {
17
18
  super({
18
19
  apiKey: options.apiKey,
19
- baseUrl: options.baseUrl || "https://openrouter.ai/api/v1"
20
+ baseUrl: options.baseUrl || DEFAULT_OPENROUTER_BASE_URL
20
21
  });
21
22
  }
22
23
  providerName() {
@@ -8,8 +8,11 @@ import { registerOpenRouterProvider } from "./openrouter/index.js";
8
8
  import { registerBedrockProvider } from "./bedrock/index.js";
9
9
  import { NodeLLMConfig } from "../config.js";
10
10
  type ProviderFactory = (config?: NodeLLMConfig) => Provider;
11
+ export type ProviderInterceptor = (provider: Provider) => Provider;
11
12
  declare class ProviderRegistry {
12
13
  private providers;
14
+ private globalInterceptor?;
15
+ setInterceptor(interceptor: ProviderInterceptor | undefined): void;
13
16
  /**
14
17
  * Register a provider factory
15
18
  */
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,KAAK,eAAe,GAAG,CAAC,MAAM,CAAC,EAAE,aAAa,KAAK,QAAQ,CAAC;AAE5D,cAAM,gBAAgB;IACpB,OAAO,CAAC,SAAS,CAAsC;IAEvD;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAQtD;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,QAAQ;IAUvD;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;OAEG;IACH,IAAI,IAAI,MAAM,EAAE;CAGjB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,kBAAyB,CAAC;AAGvD,OAAO,EACL,sBAAsB,IAAI,sBAAsB,EAChD,sBAAsB,EACtB,yBAAyB,EACzB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACxB,CAAC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,KAAK,eAAe,GAAG,CAAC,MAAM,CAAC,EAAE,aAAa,KAAK,QAAQ,CAAC;AAC5D,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC;AAEnE,cAAM,gBAAgB;IACpB,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,iBAAiB,CAAC,CAAsB;IAEzC,cAAc,CAAC,WAAW,EAAE,mBAAmB,GAAG,SAAS;IAIlE;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe;IAO/C;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,QAAQ;IAgBvD;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;OAEG;IACH,IAAI,IAAI,MAAM,EAAE;CAGjB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,kBAAyB,CAAC;AAGvD,OAAO,EACL,sBAAsB,IAAI,sBAAsB,EAChD,sBAAsB,EACtB,yBAAyB,EACzB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACxB,CAAC"}
@@ -7,6 +7,10 @@ import { registerOpenRouterProvider } from "./openrouter/index.js";
7
7
  import { registerBedrockProvider } from "./bedrock/index.js";
8
8
  class ProviderRegistry {
9
9
  providers = new Map();
10
+ globalInterceptor;
11
+ setInterceptor(interceptor) {
12
+ this.globalInterceptor = interceptor;
13
+ }
10
14
  /**
11
15
  * Register a provider factory
12
16
  */
@@ -22,9 +26,13 @@ class ProviderRegistry {
22
26
  resolve(name, config) {
23
27
  const factory = this.providers.get(name);
24
28
  if (!factory) {
25
- throw new Error(`Unknown LLM provider '${name}'`);
29
+ throw new Error(`Provider ${name} not registered`);
30
+ }
31
+ let provider = factory(config);
32
+ if (this.globalInterceptor) {
33
+ provider = this.globalInterceptor(provider);
26
34
  }
27
- return factory(config);
35
+ return provider;
28
36
  }
29
37
  /**
30
38
  * Check if a provider is registered
@@ -0,0 +1,98 @@
1
+ import { Message } from "../chat/Message.js";
2
+ import { ChatOptions } from "../chat/ChatOptions.js";
3
+ import { ChatResponseString } from "../chat/ChatResponse.js";
4
+ import { ToolCall } from "../chat/Tool.js";
5
+ /**
6
+ * Context passed to all middleware hooks.
7
+ * This object is shared across the lifecycle of a single request.
8
+ */
9
+ export interface MiddlewareContext {
10
+ /**
11
+ * Unique ID for tracing the request across the system.
12
+ */
13
+ requestId: string;
14
+ /**
15
+ * The provider being used (e.g., "openai", "anthropic").
16
+ */
17
+ provider: string;
18
+ /**
19
+ * The model identifier being used.
20
+ */
21
+ model: string;
22
+ /**
23
+ * The messages sent to the model (Chat only).
24
+ * Mutating this array in `onRequest` affects the actual call.
25
+ */
26
+ messages?: Message[];
27
+ /**
28
+ * Configuration options for the chat request (Chat only).
29
+ * Mutating this object in `onRequest` affects the actual call.
30
+ */
31
+ options?: ChatOptions;
32
+ /**
33
+ * Input text(s) for embeddings (Embedding only).
34
+ */
35
+ input?: string | string[];
36
+ /**
37
+ * Options passed to the embedding request (Embedding only).
38
+ */
39
+ embeddingOptions?: Record<string, any>;
40
+ /**
41
+ * Options passed to the transcription request (Transcription only).
42
+ */
43
+ transcriptionOptions?: Record<string, any>;
44
+ /**
45
+ * Options passed to the moderation request (Moderation only).
46
+ */
47
+ moderationOptions?: Record<string, any>;
48
+ /**
49
+ * Options passed to the image generation request (Paint only).
50
+ */
51
+ imageOptions?: Record<string, any>;
52
+ /**
53
+ * Shared state storage for passing data between middleware hooks.
54
+ * Example: Storing start time in `onRequest` and reading it in `onResponse`.
55
+ */
56
+ state: Record<string, unknown>;
57
+ }
58
+ /**
59
+ * Directives for handling tool execution errors.
60
+ */
61
+ export type ToolErrorDirective = "STOP" | "CONTINUE" | "RETRY" | void;
62
+ /**
63
+ * Middleware interface for hooking into the LLM execution lifecycle.
64
+ */
65
+ export interface Middleware {
66
+ /**
67
+ * Name of the middleware (useful for debugging).
68
+ */
69
+ name: string;
70
+ /**
71
+ * Called before the request is sent to the provider.
72
+ * Can allow modifying messages or options.
73
+ */
74
+ onRequest?(ctx: MiddlewareContext): Promise<void>;
75
+ /**
76
+ * Called after a successful response from the provider.
77
+ */
78
+ onResponse?(ctx: MiddlewareContext, result: ChatResponseString): Promise<void>;
79
+ /**
80
+ * Called if an error occurs during execution.
81
+ */
82
+ onError?(ctx: MiddlewareContext, error: Error): Promise<void>;
83
+ /**
84
+ * Called before a tool is executed.
85
+ * Throwing here will prevent the tool from running.
86
+ */
87
+ onToolCallStart?(ctx: MiddlewareContext, tool: ToolCall): Promise<void>;
88
+ /**
89
+ * Called after a tool completes successfully.
90
+ */
91
+ onToolCallEnd?(ctx: MiddlewareContext, tool: ToolCall, result: unknown): Promise<void>;
92
+ /**
93
+ * Called if a tool execution fails.
94
+ * Can return a directive to tell the engine how to proceed.
95
+ */
96
+ onToolCallError?(ctx: MiddlewareContext, tool: ToolCall, error: Error): Promise<ToolErrorDirective>;
97
+ }
98
+ //# sourceMappingURL=Middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Middleware.d.ts","sourceRoot":"","sources":["../../src/types/Middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAE1B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEvC;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE3C;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAExC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEnC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,IAAI,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,SAAS,CAAC,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD;;OAEG;IACH,UAAU,CAAC,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/E;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9D;;;OAGG;IACH,eAAe,CAAC,CAAC,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE;;OAEG;IACH,aAAa,CAAC,CAAC,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvF;;;OAGG;IACH,eAAe,CAAC,CACd,GAAG,EAAE,iBAAiB,EACtB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAChC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Boring, standard JSON extraction logic.
3
+ * Avoids cleverness in favor of predictable industry-standard patterns.
4
+ */
5
+ export declare function extractJson(text: string): string;
6
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/utils/json.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwChD"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Boring, standard JSON extraction logic.
3
+ * Avoids cleverness in favor of predictable industry-standard patterns.
4
+ */
5
+ export function extractJson(text) {
6
+ const cleaned = text.trim();
7
+ // 1. Fast path: The string is already just JSON
8
+ try {
9
+ JSON.parse(cleaned);
10
+ return cleaned;
11
+ }
12
+ catch {
13
+ // Continue extraction
14
+ }
15
+ // 2. Handle Markdown blocks (the most common LLM artifact)
16
+ const markdownMatch = cleaned.match(/```(?:json)?\s*([\s\S]*?)```/);
17
+ if (markdownMatch?.[1]) {
18
+ const candidate = markdownMatch[1].trim();
19
+ try {
20
+ JSON.parse(candidate);
21
+ return candidate;
22
+ }
23
+ catch {
24
+ // Invalid JSON inside backticks, fall through
25
+ }
26
+ }
27
+ // 3. Last resort: Find the first '{' and last '}'
28
+ // This handles conversational filler like "Here is your data: { ... }"
29
+ const firstBrace = cleaned.indexOf("{");
30
+ const lastBrace = cleaned.lastIndexOf("}");
31
+ if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {
32
+ const candidate = cleaned.substring(firstBrace, lastBrace + 1);
33
+ try {
34
+ JSON.parse(candidate);
35
+ return candidate;
36
+ }
37
+ catch {
38
+ // Not valid JSON
39
+ }
40
+ }
41
+ // 4. Return as-is and let the final JSON.parse() fail loudly
42
+ return cleaned;
43
+ }
@@ -0,0 +1,7 @@
1
+ import { Middleware, MiddlewareContext } from "../types/Middleware.js";
2
+ /**
3
+ * Helper to execute middleware chains in order.
4
+ * @internal
5
+ */
6
+ export declare function runMiddleware<T = void>(middlewares: Middleware[], hookName: keyof Middleware, context: MiddlewareContext, ...args: any[]): Promise<T | undefined>;
7
+ //# sourceMappingURL=middleware-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware-runner.d.ts","sourceRoot":"","sources":["../../src/utils/middleware-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEvE;;;GAGG;AACH,wBAAsB,aAAa,CAAC,CAAC,GAAG,IAAI,EAC1C,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,MAAM,UAAU,EAC1B,OAAO,EAAE,iBAAiB,EAC1B,GAAG,IAAI,EAAE,GAAG,EAAE,GACb,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAiBxB"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Helper to execute middleware chains in order.
3
+ * @internal
4
+ */
5
+ export async function runMiddleware(middlewares, hookName, context, ...args) {
6
+ if (!middlewares || middlewares.length === 0)
7
+ return undefined;
8
+ let finalResult;
9
+ for (const middleware of middlewares) {
10
+ if (typeof middleware[hookName] === "function") {
11
+ // @ts-ignore
12
+ const result = await middleware[hookName](context, ...args);
13
+ // Capture the first non-void result (for directives)
14
+ if (result !== undefined && finalResult === undefined) {
15
+ finalResult = result;
16
+ }
17
+ }
18
+ }
19
+ return finalResult;
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-llm/core",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",