@loonylabs/llm-middleware 2.27.1 → 2.29.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 (65) hide show
  1. package/.env.example +13 -0
  2. package/README.md +4 -2
  3. package/dist/middleware/services/llm/llm.service.d.ts.map +1 -1
  4. package/dist/middleware/services/llm/llm.service.js +4 -0
  5. package/dist/middleware/services/llm/llm.service.js.map +1 -1
  6. package/dist/middleware/services/llm/providers/azure-openai-capabilities.d.ts +33 -0
  7. package/dist/middleware/services/llm/providers/azure-openai-capabilities.d.ts.map +1 -0
  8. package/dist/middleware/services/llm/providers/azure-openai-capabilities.js +66 -0
  9. package/dist/middleware/services/llm/providers/azure-openai-capabilities.js.map +1 -0
  10. package/dist/middleware/services/llm/providers/azure-openai-provider.d.ts +53 -0
  11. package/dist/middleware/services/llm/providers/azure-openai-provider.d.ts.map +1 -0
  12. package/dist/middleware/services/llm/providers/azure-openai-provider.js +333 -0
  13. package/dist/middleware/services/llm/providers/azure-openai-provider.js.map +1 -0
  14. package/dist/middleware/services/llm/providers/bedrock-provider.d.ts +43 -0
  15. package/dist/middleware/services/llm/providers/bedrock-provider.d.ts.map +1 -0
  16. package/dist/middleware/services/llm/providers/bedrock-provider.js +328 -0
  17. package/dist/middleware/services/llm/providers/bedrock-provider.js.map +1 -0
  18. package/dist/middleware/services/llm/providers/bedrock-reasoning/bedrock-reasoning.factory.d.ts +21 -0
  19. package/dist/middleware/services/llm/providers/bedrock-reasoning/bedrock-reasoning.factory.d.ts.map +1 -0
  20. package/dist/middleware/services/llm/providers/bedrock-reasoning/bedrock-reasoning.factory.js +36 -0
  21. package/dist/middleware/services/llm/providers/bedrock-reasoning/bedrock-reasoning.factory.js.map +1 -0
  22. package/dist/middleware/services/llm/providers/bedrock-reasoning/bedrock-reasoning.types.d.ts +53 -0
  23. package/dist/middleware/services/llm/providers/bedrock-reasoning/bedrock-reasoning.types.d.ts.map +1 -0
  24. package/dist/middleware/services/llm/providers/bedrock-reasoning/bedrock-reasoning.types.js +18 -0
  25. package/dist/middleware/services/llm/providers/bedrock-reasoning/bedrock-reasoning.types.js.map +1 -0
  26. package/dist/middleware/services/llm/providers/bedrock-reasoning/index.d.ts +6 -0
  27. package/dist/middleware/services/llm/providers/bedrock-reasoning/index.d.ts.map +1 -0
  28. package/dist/middleware/services/llm/providers/bedrock-reasoning/index.js +22 -0
  29. package/dist/middleware/services/llm/providers/bedrock-reasoning/index.js.map +1 -0
  30. package/dist/middleware/services/llm/providers/bedrock-reasoning/noop-reasoning.strategy.d.ts +17 -0
  31. package/dist/middleware/services/llm/providers/bedrock-reasoning/noop-reasoning.strategy.d.ts.map +1 -0
  32. package/dist/middleware/services/llm/providers/bedrock-reasoning/noop-reasoning.strategy.js +24 -0
  33. package/dist/middleware/services/llm/providers/bedrock-reasoning/noop-reasoning.strategy.js.map +1 -0
  34. package/dist/middleware/services/llm/providers/bedrock-reasoning/nova-reasoning.strategy.d.ts +16 -0
  35. package/dist/middleware/services/llm/providers/bedrock-reasoning/nova-reasoning.strategy.d.ts.map +1 -0
  36. package/dist/middleware/services/llm/providers/bedrock-reasoning/nova-reasoning.strategy.js +40 -0
  37. package/dist/middleware/services/llm/providers/bedrock-reasoning/nova-reasoning.strategy.js.map +1 -0
  38. package/dist/middleware/services/llm/providers/bedrock-reasoning/reasoning-effort.strategy.d.ts +15 -0
  39. package/dist/middleware/services/llm/providers/bedrock-reasoning/reasoning-effort.strategy.d.ts.map +1 -0
  40. package/dist/middleware/services/llm/providers/bedrock-reasoning/reasoning-effort.strategy.js +32 -0
  41. package/dist/middleware/services/llm/providers/bedrock-reasoning/reasoning-effort.strategy.js.map +1 -0
  42. package/dist/middleware/services/llm/providers/index.d.ts +3 -0
  43. package/dist/middleware/services/llm/providers/index.d.ts.map +1 -1
  44. package/dist/middleware/services/llm/providers/index.js +3 -0
  45. package/dist/middleware/services/llm/providers/index.js.map +1 -1
  46. package/dist/middleware/services/llm/types/azure-openai.types.d.ts +135 -0
  47. package/dist/middleware/services/llm/types/azure-openai.types.d.ts.map +1 -0
  48. package/dist/middleware/services/llm/types/azure-openai.types.js +19 -0
  49. package/dist/middleware/services/llm/types/azure-openai.types.js.map +1 -0
  50. package/dist/middleware/services/llm/types/bedrock.types.d.ts +114 -0
  51. package/dist/middleware/services/llm/types/bedrock.types.d.ts.map +1 -0
  52. package/dist/middleware/services/llm/types/bedrock.types.js +14 -0
  53. package/dist/middleware/services/llm/types/bedrock.types.js.map +1 -0
  54. package/dist/middleware/services/llm/types/common.types.d.ts +12 -1
  55. package/dist/middleware/services/llm/types/common.types.d.ts.map +1 -1
  56. package/dist/middleware/services/llm/types/common.types.js +4 -0
  57. package/dist/middleware/services/llm/types/common.types.js.map +1 -1
  58. package/dist/middleware/services/llm/types/index.d.ts +2 -0
  59. package/dist/middleware/services/llm/types/index.d.ts.map +1 -1
  60. package/dist/middleware/services/llm/types/index.js +2 -0
  61. package/dist/middleware/services/llm/types/index.js.map +1 -1
  62. package/dist/middleware/services/llm/utils/debug-llm.utils.d.ts.map +1 -1
  63. package/dist/middleware/services/llm/utils/debug-llm.utils.js +4 -0
  64. package/dist/middleware/services/llm/utils/debug-llm.utils.js.map +1 -1
  65. package/package.json +3 -1
package/.env.example CHANGED
@@ -31,6 +31,19 @@ GOOGLE_APPLICATION_CREDENTIALS=./vertex-ai-service-account.json # Path to servi
31
31
  REQUESTY_API_KEY=your_requesty_api_key_here # Your Requesty API key
32
32
  REQUESTY_MODEL=openai/gpt-4o # Default: openai/gpt-4o (format: provider/model-name)
33
33
 
34
+ # AWS Bedrock Configuration (Optional - Bearer token / API key auth, EU data residency)
35
+ BEDROCK_API_KEY=your_bedrock_api_key_here # Amazon Bedrock API key (Bearer token)
36
+ BEDROCK_REGION=eu-central-1 # AWS region (Frankfurt = EU data residency)
37
+ BEDROCK_MODEL=qwen.qwen3-32b-v1:0 # Default model ID (verify via Bedrock console / list-foundation-models)
38
+
39
+ # Azure OpenAI / Foundry Configuration (Optional - api-key auth, OpenAI-compatible, serverless)
40
+ # EU data residency: create the resource in Germany West Central (or Sweden Central) with a Data Zone deployment.
41
+ # Note: some partner models (e.g. Kimi K2.5) are GLOBAL-ONLY on Azure -> they cannot be EU-resident.
42
+ AZURE_OPENAI_API_KEY=your_azure_openai_api_key_here # Azure OpenAI / Foundry API key (sent in the 'api-key' header)
43
+ AZURE_OPENAI_ENDPOINT=https://<resource>.openai.azure.com # Your resource endpoint (region is encoded in the host)
44
+ AZURE_OPENAI_DEPLOYMENT=o4-mini # Your deployment name (= 'model' field in the request body)
45
+ AZURE_OPENAI_API_VERSION= # Optional: empty = v1 route (/openai/v1/); '2024-05-01-preview' = MaaS route (/models/)
46
+
34
47
  # Test Configuration (Optional)
35
48
  TEST_LLM_MODEL=vertex/gemini-2.0-flash-lite # Model for general LLM tests
36
49
  # Reasoning models:
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # 🚀 LLM Middleware
4
4
 
5
- *A comprehensive TypeScript middleware library for building robust multi-provider LLM backends. Currently supports Ollama, Anthropic Claude, Google Gemini (Direct API & Vertex AI), and Requesty.AI (300+ models). Features EU data residency via Vertex AI, reasoning control, advanced JSON cleaning, logging, error handling, cost tracking, and more.*
5
+ *A comprehensive TypeScript middleware library for building robust multi-provider LLM backends. Currently supports Ollama, Anthropic Claude, Google Gemini (Direct API & Vertex AI), Requesty.AI (300+ models), AWS Bedrock, and Azure OpenAI / Foundry. Features EU data residency via Vertex AI / Bedrock / Azure data zones, reasoning control, advanced JSON cleaning, logging, error handling, cost tracking, and more.*
6
6
 
7
7
  <!-- Horizontal Badge Navigation Bar -->
8
8
  [![npm version](https://img.shields.io/npm/v/@loonylabs/llm-middleware.svg?style=for-the-badge&logo=npm&logoColor=white)](https://www.npmjs.com/package/@loonylabs/llm-middleware)
@@ -45,6 +45,8 @@
45
45
  - ✅ **Google Gemini Direct**: Complete support for Gemini models via API Key
46
46
  - ✅ **Google Vertex AI**: CDPA/GDPR-compliant with EU data residency (Service Account auth)
47
47
  - ✅ **Requesty.AI**: 300+ models via unified API, built-in cost tracking
48
+ - ✅ **AWS Bedrock**: Converse API via Bearer-token auth (no AWS SDK); Claude, Nova, Qwen, GLM, Kimi, DeepSeek, gpt-oss — with central `reasoningEffort` control — **v2.28.0**
49
+ - ✅ **Azure OpenAI / Foundry**: OpenAI-compatible v1 route with `api-key` auth; o-series/GPT-5 reasoning vs. gpt-4o standard auto-handled; EU data-zone residency — **v2.29.0**
48
50
  - 🔌 **Pluggable**: Easy to add custom providers - see [LLM Providers Guide](docs/LLM_PROVIDERS.md)
49
51
  - 👁️ **Vision / Multimodal Input**: Send images alongside text to LLM providers
50
52
  - ✨ **v2.22.0**: Provider-agnostic `MultimodalContent` type (`string | ContentPart[]`)
@@ -370,7 +372,7 @@ VERTEX_AI_MODEL=gemini-2.5-flash # Default Vertex AI model
370
372
  GOOGLE_APPLICATION_CREDENTIALS=./vertex-ai-service-account.json # Service Account
371
373
  ```
372
374
 
373
- **Multi-Provider Support:** The middleware is fully integrated with **Ollama**, **Anthropic Claude**, **Google Gemini** (Direct API & Vertex AI), and **Requesty.AI**. See the [LLM Providers Guide](docs/LLM_PROVIDERS.md) for details on the provider system and how to use or add providers.
375
+ **Multi-Provider Support:** The middleware is fully integrated with **Ollama**, **Anthropic Claude**, **Google Gemini** (Direct API & Vertex AI), **Requesty.AI**, **AWS Bedrock** (Converse API, EU data residency), and **Azure OpenAI / Foundry** (OpenAI-compatible v1 route, EU data zone). See the [LLM Providers Guide](docs/LLM_PROVIDERS.md) for details on the provider system and how to use or add providers. Provider specifics: [AWS Bedrock Guide](docs/AWS_BEDROCK.md) · [Azure OpenAI Guide](docs/AZURE_OPENAI.md).
374
376
 
375
377
  </details>
376
378
 
@@ -1 +1 @@
1
- {"version":3,"file":"llm.service.d.ts","sourceRoot":"","sources":["../../../../src/middleware/services/llm/llm.service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAKhE,OAAO,EAAoB,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,eAAe,CAAmC;gBAE9C,OAAO,CAAC,EAAE,iBAAiB;IAUvC;;OAEG;IACI,WAAW,CAAC,QAAQ,EAAE,WAAW,GAAG,eAAe;IAQ1D;;;;;;;;;;;;;;;;;;OAkBG;IACI,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAI/E;;OAEG;IACI,kBAAkB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAOtD;;OAEG;IACI,kBAAkB,IAAI,WAAW;IAIxC;;;OAGG;IACU,qBAAqB,CAChC,UAAU,EAAE,iBAAiB,EAC7B,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,gBAAgB,GAAG;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAO,GAC1D,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAMpC;;;OAGG;IACU,IAAI,CACf,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,gBAAgB,GAAG;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAO,GAC1D,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAMpC;;OAEG;IACI,qBAAqB,IAAI,WAAW,EAAE;CAG9C;AAGD,eAAO,MAAM,UAAU,YAAmB,CAAC"}
1
+ {"version":3,"file":"llm.service.d.ts","sourceRoot":"","sources":["../../../../src/middleware/services/llm/llm.service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAKhE,OAAO,EAAoB,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAG9E,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,eAAe,CAAmC;gBAE9C,OAAO,CAAC,EAAE,iBAAiB;IAYvC;;OAEG;IACI,WAAW,CAAC,QAAQ,EAAE,WAAW,GAAG,eAAe;IAQ1D;;;;;;;;;;;;;;;;;;OAkBG;IACI,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAI/E;;OAEG;IACI,kBAAkB,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAOtD;;OAEG;IACI,kBAAkB,IAAI,WAAW;IAIxC;;;OAGG;IACU,qBAAqB,CAChC,UAAU,EAAE,iBAAiB,EAC7B,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,gBAAgB,GAAG;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAO,GAC1D,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAMpC;;;OAGG;IACU,IAAI,CACf,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,gBAAgB,GAAG;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAO,GAC1D,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAMpC;;OAEG;IACI,qBAAqB,IAAI,WAAW,EAAE;CAG9C;AAGD,eAAO,MAAM,UAAU,YAAmB,CAAC"}
@@ -10,6 +10,8 @@ const anthropic_provider_1 = require("./providers/anthropic-provider");
10
10
  const gemini_provider_1 = require("./providers/gemini-provider");
11
11
  const requesty_provider_1 = require("./providers/requesty-provider");
12
12
  const gemini_1 = require("./providers/gemini");
13
+ const bedrock_provider_1 = require("./providers/bedrock-provider");
14
+ const azure_openai_provider_1 = require("./providers/azure-openai-provider");
13
15
  const types_1 = require("./types");
14
16
  class LLMService {
15
17
  constructor(options) {
@@ -21,6 +23,8 @@ class LLMService {
21
23
  this.providers.set(types_1.LLMProvider.GOOGLE, new gemini_provider_1.GeminiProvider());
22
24
  this.providers.set(types_1.LLMProvider.REQUESTY, new requesty_provider_1.RequestyProvider());
23
25
  this.providers.set(types_1.LLMProvider.VERTEX_AI, new gemini_1.VertexAIProvider(options?.vertexAIConfig));
26
+ this.providers.set(types_1.LLMProvider.BEDROCK, new bedrock_provider_1.BedrockProvider());
27
+ this.providers.set(types_1.LLMProvider.AZURE_OPENAI, new azure_openai_provider_1.AzureOpenAIProvider());
24
28
  }
25
29
  /**
26
30
  * Get a specific provider instance
@@ -1 +1 @@
1
- {"version":3,"file":"llm.service.js","sourceRoot":"","sources":["../../../../src/middleware/services/llm/llm.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"llm.service.js","sourceRoot":"","sources":["../../../../src/middleware/services/llm/llm.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Azure OpenAI model-capability detection.
3
+ *
4
+ * On Azure, reasoning models (o-series, GPT-5 series) and standard models
5
+ * (gpt-4o, gpt-4o-mini, …) require a *different* parameter set — verified live:
6
+ * - Reasoning models use `max_completion_tokens` and REJECT `temperature`/`max_tokens` (HTTP 400);
7
+ * they accept `reasoning_effort`.
8
+ * - Standard models use `max_tokens` + `temperature` and ignore `reasoning_effort`.
9
+ *
10
+ * The split is binary, so a lightweight helper (rather than a full strategy
11
+ * pattern) is sufficient. Because Azure deployment names are user-chosen, the
12
+ * name heuristic can be overridden explicitly via `AzureOpenAIRequestOptions.reasoningModel`.
13
+ */
14
+ import { ReasoningEffort } from '../types';
15
+ import { AzureOpenAIReasoningEffort } from '../types/azure-openai.types';
16
+ /**
17
+ * Decide whether a deployment should be treated as a reasoning model.
18
+ * @param deployment - The Azure deployment name (sent as `model`).
19
+ * @param override - Explicit override; when a boolean, it wins over the heuristic.
20
+ */
21
+ export declare function isAzureReasoningModel(deployment: string, override?: boolean): boolean;
22
+ /**
23
+ * Map the provider-agnostic {@link ReasoningEffort} to Azure's `reasoning_effort`.
24
+ *
25
+ * Returns `{ value }` to send, or `{ warning }` (and no value) when the effort
26
+ * should be omitted. `none` is intentionally omitted: only gpt-5.1+ accept it,
27
+ * while o-series reject it — omitting lets the model use its default safely.
28
+ */
29
+ export declare function mapAzureReasoningEffort(effort: ReasoningEffort): {
30
+ value?: AzureOpenAIReasoningEffort;
31
+ warning?: string;
32
+ };
33
+ //# sourceMappingURL=azure-openai-capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-openai-capabilities.d.ts","sourceRoot":"","sources":["../../../../../src/middleware/services/llm/providers/azure-openai-capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAezE;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAIrF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,eAAe,GACtB;IAAE,KAAK,CAAC,EAAE,0BAA0B,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAiB1D"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /**
3
+ * Azure OpenAI model-capability detection.
4
+ *
5
+ * On Azure, reasoning models (o-series, GPT-5 series) and standard models
6
+ * (gpt-4o, gpt-4o-mini, …) require a *different* parameter set — verified live:
7
+ * - Reasoning models use `max_completion_tokens` and REJECT `temperature`/`max_tokens` (HTTP 400);
8
+ * they accept `reasoning_effort`.
9
+ * - Standard models use `max_tokens` + `temperature` and ignore `reasoning_effort`.
10
+ *
11
+ * The split is binary, so a lightweight helper (rather than a full strategy
12
+ * pattern) is sufficient. Because Azure deployment names are user-chosen, the
13
+ * name heuristic can be overridden explicitly via `AzureOpenAIRequestOptions.reasoningModel`.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.isAzureReasoningModel = isAzureReasoningModel;
17
+ exports.mapAzureReasoningEffort = mapAzureReasoningEffort;
18
+ /**
19
+ * Deployment-name patterns that indicate a reasoning model. Matched against the
20
+ * deployment name (which usually defaults to the underlying model name).
21
+ * - `o\d` family: o1, o1-mini, o3, o3-mini, o3-pro, o4-mini (separator-anchored to avoid e.g. "neo4j")
22
+ * - GPT-5 series: gpt-5, gpt-5-mini, gpt-5.1, gpt5, gpt-5-codex
23
+ * - codex-mini
24
+ */
25
+ const REASONING_NAME_PATTERNS = [
26
+ /(^|[-_/.])o\d+(-(mini|pro|preview))?($|[-_/.])/i,
27
+ /gpt-?5/i,
28
+ /(^|[-_/.])codex(-mini)?($|[-_/.])/i,
29
+ ];
30
+ /**
31
+ * Decide whether a deployment should be treated as a reasoning model.
32
+ * @param deployment - The Azure deployment name (sent as `model`).
33
+ * @param override - Explicit override; when a boolean, it wins over the heuristic.
34
+ */
35
+ function isAzureReasoningModel(deployment, override) {
36
+ if (typeof override === 'boolean')
37
+ return override;
38
+ if (!deployment)
39
+ return false;
40
+ return REASONING_NAME_PATTERNS.some(re => re.test(deployment));
41
+ }
42
+ /**
43
+ * Map the provider-agnostic {@link ReasoningEffort} to Azure's `reasoning_effort`.
44
+ *
45
+ * Returns `{ value }` to send, or `{ warning }` (and no value) when the effort
46
+ * should be omitted. `none` is intentionally omitted: only gpt-5.1+ accept it,
47
+ * while o-series reject it — omitting lets the model use its default safely.
48
+ */
49
+ function mapAzureReasoningEffort(effort) {
50
+ switch (effort) {
51
+ case 'low':
52
+ case 'medium':
53
+ case 'high':
54
+ return { value: effort };
55
+ case 'none':
56
+ return {
57
+ warning: "reasoningEffort 'none' is not reliably supported across Azure reasoning models " +
58
+ '(only gpt-5.1+ accept it; o-series reject it). Omitting reasoning_effort so the ' +
59
+ 'model uses its default.',
60
+ };
61
+ default:
62
+ // Defensive: unknown value → safe middle ground.
63
+ return { value: 'medium' };
64
+ }
65
+ }
66
+ //# sourceMappingURL=azure-openai-capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-openai-capabilities.js","sourceRoot":"","sources":["../../../../../src/middleware/services/llm/providers/azure-openai-capabilities.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAuBH,sDAIC;AASD,0DAmBC;AAlDD;;;;;;GAMG;AACH,MAAM,uBAAuB,GAAa;IACxC,iDAAiD;IACjD,SAAS;IACT,oCAAoC;CACrC,CAAC;AAEF;;;;GAIG;AACH,SAAgB,qBAAqB,CAAC,UAAkB,EAAE,QAAkB;IAC1E,IAAI,OAAO,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACnD,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,uBAAuB,CACrC,MAAuB;IAEvB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK,CAAC;QACX,KAAK,QAAQ,CAAC;QACd,KAAK,MAAM;YACT,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM;YACT,OAAO;gBACL,OAAO,EACL,iFAAiF;oBACjF,kFAAkF;oBAClF,yBAAyB;aAC5B,CAAC;QACJ;YACE,iDAAiD;YACjD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { BaseLLMProvider } from './base-llm-provider';
2
+ import { CommonLLMResponse } from '../types';
3
+ import { AzureOpenAIRequestOptions } from '../types/azure-openai.types';
4
+ import { MultimodalContent } from '../types/multimodal.types';
5
+ /**
6
+ * Azure OpenAI / Microsoft Foundry provider using the OpenAI-compatible
7
+ * Chat Completions API (v1 route).
8
+ *
9
+ * Why v1 (not the classic deployments route): the deployment name is sent as the
10
+ * `model` field in the body and `api-version` is optional, which keeps the payload
11
+ * identical to a standard OpenAI request and matches the Requesty provider. The
12
+ * same route serves OpenAI and (increasingly) partner models on Foundry.
13
+ *
14
+ * Why `api-key` header (not Authorization: Bearer): Azure passes the static API
15
+ * key in the `api-key` header; `Authorization: Bearer` is reserved for Microsoft
16
+ * Entra ID tokens (a planned follow-up).
17
+ *
18
+ * Reasoning vs standard models take different parameters (verified live) — see
19
+ * `azure-openai-capabilities.ts`.
20
+ *
21
+ * Auth: api-key: <AZURE_OPENAI_API_KEY>
22
+ * Endpoint: {AZURE_OPENAI_ENDPOINT}/openai/v1/chat/completions
23
+ * Residency: data zone is chosen at deployment time (EU = Germany West Central / Sweden Central)
24
+ * @see https://learn.microsoft.com/en-us/azure/foundry/openai/latest
25
+ */
26
+ export declare class AzureOpenAIProvider extends BaseLLMProvider {
27
+ private dataFlowLogger;
28
+ private readonly DEFAULT_TIMEOUT;
29
+ constructor();
30
+ /**
31
+ * Build the Azure OpenAI v1 Chat Completions endpoint.
32
+ * `api-version` is appended only when explicitly provided (the v1 route
33
+ * defaults to no api-version).
34
+ */
35
+ private buildEndpoint;
36
+ /**
37
+ * Build the user message content: multimodal (text + image_url) or plain string.
38
+ * Uses the OpenAI image_url/data-URI format, identical to the Requesty provider.
39
+ */
40
+ private buildUserContent;
41
+ /**
42
+ * Call the Azure OpenAI Chat Completions API with a custom system message.
43
+ * @param userPrompt - The user's prompt (text or multimodal content)
44
+ * @param systemMessage - The system message defining AI behavior
45
+ * @param options - Options for the API call
46
+ * @returns The API response or null on error
47
+ */
48
+ callWithSystemMessage(userPrompt: MultimodalContent, systemMessage: string, options?: AzureOpenAIRequestOptions): Promise<CommonLLMResponse | null>;
49
+ }
50
+ export declare const azureOpenAIProvider: AzureOpenAIProvider;
51
+ export { AzureOpenAIProvider as AzureOpenAIService };
52
+ export { azureOpenAIProvider as azureOpenAIService };
53
+ //# sourceMappingURL=azure-openai-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-openai-provider.d.ts","sourceRoot":"","sources":["../../../../../src/middleware/services/llm/providers/azure-openai-provider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAe,iBAAiB,EAAc,MAAM,UAAU,CAAC;AACtE,OAAO,EACL,yBAAyB,EAK1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAQ9D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,mBAAoB,SAAQ,eAAe;IACtD,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;;IAO1C;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAMrB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAsBxB;;;;;;OAMG;IACU,qBAAqB,CAChC,UAAU,EAAE,iBAAiB,EAC7B,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CAmUrC;AAGD,eAAO,MAAM,mBAAmB,qBAA4B,CAAC;AAG7D,OAAO,EAAE,mBAAmB,IAAI,kBAAkB,EAAE,CAAC;AACrD,OAAO,EAAE,mBAAmB,IAAI,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,333 @@
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.azureOpenAIService = exports.AzureOpenAIService = exports.azureOpenAIProvider = exports.AzureOpenAIProvider = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const uuid_1 = require("uuid");
9
+ const logging_utils_1 = require("../../../shared/utils/logging.utils");
10
+ const base_llm_provider_1 = require("./base-llm-provider");
11
+ const types_1 = require("../types");
12
+ const debug_llm_utils_1 = require("../utils/debug-llm.utils");
13
+ const data_flow_logger_1 = require("../../data-flow-logger");
14
+ const thinking_1 = require("../thinking");
15
+ const retry_utils_1 = require("../utils/retry.utils");
16
+ const multimodal_utils_1 = require("../utils/multimodal.utils");
17
+ const azure_openai_capabilities_1 = require("./azure-openai-capabilities");
18
+ /**
19
+ * Azure OpenAI / Microsoft Foundry provider using the OpenAI-compatible
20
+ * Chat Completions API (v1 route).
21
+ *
22
+ * Why v1 (not the classic deployments route): the deployment name is sent as the
23
+ * `model` field in the body and `api-version` is optional, which keeps the payload
24
+ * identical to a standard OpenAI request and matches the Requesty provider. The
25
+ * same route serves OpenAI and (increasingly) partner models on Foundry.
26
+ *
27
+ * Why `api-key` header (not Authorization: Bearer): Azure passes the static API
28
+ * key in the `api-key` header; `Authorization: Bearer` is reserved for Microsoft
29
+ * Entra ID tokens (a planned follow-up).
30
+ *
31
+ * Reasoning vs standard models take different parameters (verified live) — see
32
+ * `azure-openai-capabilities.ts`.
33
+ *
34
+ * Auth: api-key: <AZURE_OPENAI_API_KEY>
35
+ * Endpoint: {AZURE_OPENAI_ENDPOINT}/openai/v1/chat/completions
36
+ * Residency: data zone is chosen at deployment time (EU = Germany West Central / Sweden Central)
37
+ * @see https://learn.microsoft.com/en-us/azure/foundry/openai/latest
38
+ */
39
+ class AzureOpenAIProvider extends base_llm_provider_1.BaseLLMProvider {
40
+ constructor() {
41
+ super(types_1.LLMProvider.AZURE_OPENAI);
42
+ this.DEFAULT_TIMEOUT = 180000;
43
+ this.dataFlowLogger = data_flow_logger_1.DataFlowLoggerService.getInstance();
44
+ }
45
+ /**
46
+ * Build the Azure OpenAI v1 Chat Completions endpoint.
47
+ * `api-version` is appended only when explicitly provided (the v1 route
48
+ * defaults to no api-version).
49
+ */
50
+ buildEndpoint(endpoint, apiVersion) {
51
+ const base = endpoint.replace(/\/+$/, '');
52
+ const url = `${base}/openai/v1/chat/completions`;
53
+ return apiVersion ? `${url}?api-version=${encodeURIComponent(apiVersion)}` : url;
54
+ }
55
+ /**
56
+ * Build the user message content: multimodal (text + image_url) or plain string.
57
+ * Uses the OpenAI image_url/data-URI format, identical to the Requesty provider.
58
+ */
59
+ buildUserContent(userPrompt) {
60
+ if (!(0, multimodal_utils_1.hasImages)(userPrompt)) {
61
+ return typeof userPrompt === 'string'
62
+ ? userPrompt
63
+ : (0, multimodal_utils_1.normalizeContent)(userPrompt)
64
+ .map(p => p.text)
65
+ .join('\n');
66
+ }
67
+ return (0, multimodal_utils_1.normalizeContent)(userPrompt).map(part => {
68
+ if (part.type === 'text') {
69
+ return { type: 'text', text: part.text };
70
+ }
71
+ return {
72
+ type: 'image_url',
73
+ image_url: {
74
+ url: `data:${part.mimeType};base64,${part.data}`,
75
+ ...(part.detail && { detail: part.detail })
76
+ }
77
+ };
78
+ });
79
+ }
80
+ /**
81
+ * Call the Azure OpenAI Chat Completions API with a custom system message.
82
+ * @param userPrompt - The user's prompt (text or multimodal content)
83
+ * @param systemMessage - The system message defining AI behavior
84
+ * @param options - Options for the API call
85
+ * @returns The API response or null on error
86
+ */
87
+ async callWithSystemMessage(userPrompt, systemMessage, options = {}) {
88
+ const { authToken = process.env.AZURE_OPENAI_API_KEY, endpoint = options.baseUrl || process.env.AZURE_OPENAI_ENDPOINT, deployment = options.model || process.env.AZURE_OPENAI_DEPLOYMENT, apiVersion = process.env.AZURE_OPENAI_API_VERSION || undefined, temperature = 0.7, maxTokens = 4096, topP, timeout = this.DEFAULT_TIMEOUT, debugContext, sessionId = (0, uuid_1.v4)(), chapterNumber, pageNumber, pageName, reasoningEffort, reasoningModel } = options;
89
+ // Validate API key
90
+ if (!authToken) {
91
+ throw new Error('Azure OpenAI API key is required but not provided. ' +
92
+ 'Please set AZURE_OPENAI_API_KEY in your .env file or pass authToken in options.');
93
+ }
94
+ // Validate endpoint
95
+ if (!endpoint) {
96
+ throw new Error('Azure OpenAI endpoint is required but not provided. ' +
97
+ 'Please set AZURE_OPENAI_ENDPOINT in your .env file or pass endpoint in options.');
98
+ }
99
+ // Validate deployment (= model)
100
+ if (!deployment) {
101
+ throw new Error('Azure OpenAI deployment name is required but not provided. ' +
102
+ 'Please set AZURE_OPENAI_DEPLOYMENT in your .env file or pass deployment/model in options.');
103
+ }
104
+ const isReasoning = (0, azure_openai_capabilities_1.isAzureReasoningModel)(deployment, reasoningModel);
105
+ // Build request payload (OpenAI Chat Completions format).
106
+ const requestPayload = {
107
+ model: deployment,
108
+ messages: [
109
+ ...(systemMessage ? [{ role: 'system', content: systemMessage }] : []),
110
+ { role: 'user', content: this.buildUserContent(userPrompt) }
111
+ ]
112
+ };
113
+ // Apply the verified, model-class-specific parameter set.
114
+ if (isReasoning) {
115
+ // Reasoning models: max_completion_tokens, NO temperature/top_p, reasoning_effort.
116
+ requestPayload.max_completion_tokens = maxTokens;
117
+ if (reasoningEffort) {
118
+ const { value, warning } = (0, azure_openai_capabilities_1.mapAzureReasoningEffort)(reasoningEffort);
119
+ if (value)
120
+ requestPayload.reasoning_effort = value;
121
+ if (warning) {
122
+ logging_utils_1.logger.warn(warning, {
123
+ context: 'AzureOpenAIProvider',
124
+ metadata: { deployment, reasoningEffort }
125
+ });
126
+ }
127
+ }
128
+ }
129
+ else {
130
+ // Standard models: max_tokens + temperature (+ top_p); reasoning_effort is ignored.
131
+ requestPayload.max_tokens = maxTokens;
132
+ requestPayload.temperature = temperature;
133
+ if (topP !== undefined)
134
+ requestPayload.top_p = topP;
135
+ if (reasoningEffort) {
136
+ logging_utils_1.logger.warn(`reasoningEffort '${reasoningEffort}' is ignored for the non-reasoning Azure model '${deployment}'. ` +
137
+ 'Set options.reasoningModel=true if this is actually a reasoning deployment.', { context: 'AzureOpenAIProvider', metadata: { deployment } });
138
+ }
139
+ }
140
+ const url = this.buildEndpoint(endpoint, apiVersion);
141
+ const headers = {
142
+ 'Content-Type': 'application/json',
143
+ 'Accept': 'application/json',
144
+ 'api-key': authToken
145
+ };
146
+ // Use debug string to avoid base64 blobs in logs
147
+ const userMessageDebug = (0, multimodal_utils_1.contentToDebugString)(userPrompt);
148
+ const debugInfo = {
149
+ timestamp: new Date(),
150
+ provider: this.providerName,
151
+ model: deployment,
152
+ baseUrl: url,
153
+ systemMessage,
154
+ userMessage: userMessageDebug,
155
+ requestData: requestPayload,
156
+ useCase: debugContext,
157
+ sessionId,
158
+ chapterNumber,
159
+ pageNumber,
160
+ pageName,
161
+ temperature: isReasoning ? undefined : temperature,
162
+ reasoningEffort
163
+ };
164
+ await debug_llm_utils_1.LLMDebugger.logRequest(debugInfo);
165
+ const contextForLogger = {
166
+ currentChapterNr: chapterNumber,
167
+ currentPage: pageNumber,
168
+ debugContext
169
+ };
170
+ const requestId = this.dataFlowLogger.startRequest(debugContext || 'azure-openai', contextForLogger);
171
+ this.dataFlowLogger.logLLMRequest({
172
+ stage: debugContext || 'azure-openai',
173
+ prompt: userMessageDebug,
174
+ systemMessage,
175
+ modelName: deployment,
176
+ temperature: isReasoning ? undefined : temperature,
177
+ contextInfo: { sessionId, chapterNumber, pageNumber, pageName }
178
+ }, contextForLogger, requestId);
179
+ const requestStartTime = Date.now();
180
+ try {
181
+ logging_utils_1.logger.info('Sending request to Azure OpenAI', {
182
+ context: 'AzureOpenAIProvider',
183
+ metadata: {
184
+ url,
185
+ deployment,
186
+ isReasoning,
187
+ promptLength: (0, multimodal_utils_1.contentLength)(userPrompt),
188
+ maxTokens
189
+ }
190
+ });
191
+ const response = await (0, retry_utils_1.retryWithBackoff)(() => axios_1.default.post(url, requestPayload, { headers, timeout }), this.constructor.name, options.retry);
192
+ const requestDuration = Date.now() - requestStartTime;
193
+ if (response && response.status === 200) {
194
+ const apiResponse = response.data;
195
+ const rawResponseText = apiResponse.choices[0]?.message?.content || '';
196
+ // Partner models served via Azure may inline reasoning as <think> tags;
197
+ // native OpenAI reasoning text is hidden by Azure (only token counts exposed).
198
+ const extractor = thinking_1.ThinkingExtractorFactory.forModel(deployment);
199
+ const { content: responseText, thinking } = extractor.extract(rawResponseText);
200
+ // Normalize token usage to the provider-agnostic format.
201
+ const usage = apiResponse.usage;
202
+ const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens;
203
+ const cachedTokens = usage.prompt_tokens_details?.cached_tokens;
204
+ const tokenUsage = {
205
+ inputTokens: usage.prompt_tokens,
206
+ outputTokens: usage.completion_tokens,
207
+ totalTokens: usage.total_tokens,
208
+ ...(reasoningTokens ? { reasoningTokens } : {}),
209
+ ...(cachedTokens ? { cacheMetadata: { cacheReadTokens: cachedTokens } } : {})
210
+ };
211
+ const normalizedResponse = {
212
+ message: {
213
+ content: responseText,
214
+ ...(thinking && { thinking })
215
+ },
216
+ sessionId,
217
+ metadata: {
218
+ provider: this.providerName,
219
+ model: apiResponse.model || deployment,
220
+ tokensUsed: tokenUsage.totalTokens,
221
+ processingTime: requestDuration
222
+ },
223
+ usage: tokenUsage,
224
+ id: apiResponse.id,
225
+ finish_reason: apiResponse.choices[0]?.finish_reason || undefined
226
+ };
227
+ debugInfo.responseTimestamp = new Date();
228
+ debugInfo.response = responseText;
229
+ debugInfo.rawResponseData = apiResponse;
230
+ if (thinking) {
231
+ debugInfo.thinking = thinking;
232
+ }
233
+ // Surface reasoning token count in the log. Azure hides the raw reasoning
234
+ // text for o-series, so this is the signal that reasoning actually happened.
235
+ if (reasoningTokens !== undefined) {
236
+ debugInfo.reasoningTokens = reasoningTokens;
237
+ }
238
+ await debug_llm_utils_1.LLMDebugger.logResponse(debugInfo);
239
+ this.dataFlowLogger.logLLMResponse(debugContext || 'azure-openai', { rawResponse: responseText, processingTime: requestDuration }, contextForLogger, requestId);
240
+ return normalizedResponse;
241
+ }
242
+ else {
243
+ const error = new Error(`Status ${response?.status || 'unknown'}`);
244
+ logging_utils_1.logger.error('Error calling Azure OpenAI', {
245
+ context: this.constructor.name,
246
+ error: error.message,
247
+ metadata: response?.data || {}
248
+ });
249
+ this.dataFlowLogger.logLLMResponse(debugContext || 'azure-openai', { rawResponse: '', processingTime: Date.now() - requestStartTime, error }, contextForLogger, requestId);
250
+ return null;
251
+ }
252
+ }
253
+ catch (error) {
254
+ let errorMessage = 'Unknown error';
255
+ let errorDetails = {};
256
+ if (error instanceof Error) {
257
+ errorMessage = error.message;
258
+ }
259
+ if (error &&
260
+ typeof error === 'object' &&
261
+ 'isAxiosError' in error &&
262
+ error.isAxiosError === true) {
263
+ const axiosError = error;
264
+ if (axiosError.response) {
265
+ errorDetails = {
266
+ statusCode: axiosError.response.status,
267
+ statusText: axiosError.response.statusText,
268
+ data: axiosError.response.data
269
+ };
270
+ if (axiosError.response.status === 401) {
271
+ logging_utils_1.logger.error('Authentication error with Azure OpenAI', {
272
+ context: this.constructor.name,
273
+ error: 'Invalid Azure OpenAI API key (sent in the api-key header)',
274
+ metadata: { statusCode: 401, message: axiosError.response.data?.error?.message }
275
+ });
276
+ }
277
+ else if (axiosError.response.status === 404) {
278
+ logging_utils_1.logger.error('Azure OpenAI deployment or route not found', {
279
+ context: this.constructor.name,
280
+ error: 'Deployment name not found, or endpoint/route incorrect',
281
+ metadata: {
282
+ statusCode: 404,
283
+ deployment,
284
+ hint: 'Verify the deployment name and that AZURE_OPENAI_ENDPOINT points at the resource host.'
285
+ }
286
+ });
287
+ }
288
+ else if (axiosError.response.status === 429) {
289
+ logging_utils_1.logger.error('Rate limit / quota exceeded on Azure OpenAI', {
290
+ context: this.constructor.name,
291
+ error: 'Too many requests',
292
+ metadata: { statusCode: 429, retryAfter: axiosError.response.headers?.['retry-after'] }
293
+ });
294
+ }
295
+ else if (axiosError.response.status === 400) {
296
+ logging_utils_1.logger.error('Bad request to Azure OpenAI', {
297
+ context: this.constructor.name,
298
+ error: axiosError.response.data?.error?.message || 'Invalid request',
299
+ metadata: {
300
+ deployment,
301
+ isReasoning,
302
+ hint: isReasoning
303
+ ? 'Reasoning models reject temperature/max_tokens; they require max_completion_tokens.'
304
+ : 'Check parameter compatibility for this deployment.',
305
+ details: axiosError.response.data?.error
306
+ }
307
+ });
308
+ }
309
+ }
310
+ }
311
+ logging_utils_1.logger.error('Error in Azure OpenAI API request', {
312
+ context: this.constructor.name,
313
+ error: errorMessage,
314
+ metadata: { ...errorDetails, requestDeployment: deployment, sessionId }
315
+ });
316
+ this.dataFlowLogger.logLLMResponse(debugContext || 'azure-openai', {
317
+ rawResponse: '',
318
+ processingTime: Date.now() - requestStartTime,
319
+ error: error instanceof Error ? error : new Error(errorMessage)
320
+ }, contextForLogger, requestId);
321
+ debugInfo.responseTimestamp = new Date();
322
+ debugInfo.error = { message: errorMessage, details: errorDetails };
323
+ await debug_llm_utils_1.LLMDebugger.logError(debugInfo);
324
+ return null;
325
+ }
326
+ }
327
+ }
328
+ exports.AzureOpenAIProvider = AzureOpenAIProvider;
329
+ exports.AzureOpenAIService = AzureOpenAIProvider;
330
+ // Export singleton instance
331
+ exports.azureOpenAIProvider = new AzureOpenAIProvider();
332
+ exports.azureOpenAIService = exports.azureOpenAIProvider;
333
+ //# sourceMappingURL=azure-openai-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-openai-provider.js","sourceRoot":"","sources":["../../../../../src/middleware/services/llm/providers/azure-openai-provider.ts"],"names":[],"mappings":"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"}