lynkr 8.0.0 → 9.0.1

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 (128) hide show
  1. package/.lynkr/telemetry.db +0 -0
  2. package/.lynkr/telemetry.db-shm +0 -0
  3. package/.lynkr/telemetry.db-wal +0 -0
  4. package/README.md +196 -322
  5. package/lynkr-skill.tar.gz +0 -0
  6. package/package.json +4 -3
  7. package/src/api/openai-router.js +64 -13
  8. package/src/api/providers-handler.js +171 -3
  9. package/src/api/router.js +9 -2
  10. package/src/clients/circuit-breaker.js +10 -247
  11. package/src/clients/codex-process.js +342 -0
  12. package/src/clients/codex-utils.js +143 -0
  13. package/src/clients/databricks.js +210 -63
  14. package/src/clients/resilience.js +540 -0
  15. package/src/clients/retry.js +22 -167
  16. package/src/clients/standard-tools.js +23 -0
  17. package/src/config/index.js +77 -0
  18. package/src/context/compression.js +42 -9
  19. package/src/context/distill.js +492 -0
  20. package/src/orchestrator/index.js +48 -8
  21. package/src/routing/complexity-analyzer.js +258 -5
  22. package/src/routing/index.js +12 -2
  23. package/src/routing/latency-tracker.js +148 -0
  24. package/src/routing/model-tiers.js +2 -0
  25. package/src/routing/quality-scorer.js +113 -0
  26. package/src/routing/telemetry.js +464 -0
  27. package/src/server.js +13 -12
  28. package/src/tools/code-graph.js +538 -0
  29. package/src/tools/code-mode.js +304 -0
  30. package/src/tools/index.js +4 -0
  31. package/src/tools/lazy-loader.js +18 -0
  32. package/src/tools/mcp-remote.js +7 -0
  33. package/src/tools/smart-selection.js +11 -0
  34. package/src/tools/tinyfish.js +358 -0
  35. package/src/tools/truncate.js +1 -0
  36. package/src/utils/payload.js +206 -0
  37. package/src/utils/perf-timer.js +80 -0
  38. package/.github/FUNDING.yml +0 -15
  39. package/.github/workflows/README.md +0 -215
  40. package/.github/workflows/ci.yml +0 -69
  41. package/.github/workflows/index.yml +0 -62
  42. package/.github/workflows/web-tools-tests.yml +0 -56
  43. package/CITATIONS.bib +0 -6
  44. package/DEPLOYMENT.md +0 -1001
  45. package/LYNKR-TUI-PLAN.md +0 -984
  46. package/PERFORMANCE-REPORT.md +0 -866
  47. package/PLAN-per-client-model-routing.md +0 -252
  48. package/docs/42642f749da6234f41b6b425c3bb07c9.txt +0 -1
  49. package/docs/BingSiteAuth.xml +0 -4
  50. package/docs/docs-style.css +0 -478
  51. package/docs/docs.html +0 -198
  52. package/docs/google5be250e608e6da39.html +0 -1
  53. package/docs/index.html +0 -577
  54. package/docs/index.md +0 -584
  55. package/docs/robots.txt +0 -4
  56. package/docs/sitemap.xml +0 -44
  57. package/docs/style.css +0 -1223
  58. package/docs/toon-integration-spec.md +0 -130
  59. package/documentation/README.md +0 -101
  60. package/documentation/api.md +0 -806
  61. package/documentation/claude-code-cli.md +0 -679
  62. package/documentation/codex-cli.md +0 -397
  63. package/documentation/contributing.md +0 -571
  64. package/documentation/cursor-integration.md +0 -734
  65. package/documentation/docker.md +0 -874
  66. package/documentation/embeddings.md +0 -762
  67. package/documentation/faq.md +0 -713
  68. package/documentation/features.md +0 -403
  69. package/documentation/headroom.md +0 -519
  70. package/documentation/installation.md +0 -758
  71. package/documentation/memory-system.md +0 -476
  72. package/documentation/production.md +0 -636
  73. package/documentation/providers.md +0 -1009
  74. package/documentation/routing.md +0 -476
  75. package/documentation/testing.md +0 -629
  76. package/documentation/token-optimization.md +0 -325
  77. package/documentation/tools.md +0 -697
  78. package/documentation/troubleshooting.md +0 -969
  79. package/final-test.js +0 -33
  80. package/headroom-sidecar/config.py +0 -93
  81. package/headroom-sidecar/requirements.txt +0 -14
  82. package/headroom-sidecar/server.py +0 -451
  83. package/monitor-agents.sh +0 -31
  84. package/scripts/audit-log-reader.js +0 -399
  85. package/scripts/compact-dictionary.js +0 -204
  86. package/scripts/test-deduplication.js +0 -448
  87. package/src/db/database.sqlite +0 -0
  88. package/te +0 -11622
  89. package/test/README.md +0 -212
  90. package/test/azure-openai-config.test.js +0 -213
  91. package/test/azure-openai-error-resilience.test.js +0 -238
  92. package/test/azure-openai-format-conversion.test.js +0 -354
  93. package/test/azure-openai-integration.test.js +0 -287
  94. package/test/azure-openai-routing.test.js +0 -175
  95. package/test/azure-openai-streaming.test.js +0 -171
  96. package/test/bedrock-integration.test.js +0 -457
  97. package/test/comprehensive-test-suite.js +0 -928
  98. package/test/config-validation.test.js +0 -207
  99. package/test/cursor-integration.test.js +0 -484
  100. package/test/format-conversion.test.js +0 -578
  101. package/test/hybrid-routing-integration.test.js +0 -269
  102. package/test/hybrid-routing-performance.test.js +0 -428
  103. package/test/llamacpp-integration.test.js +0 -882
  104. package/test/lmstudio-integration.test.js +0 -347
  105. package/test/memory/extractor.test.js +0 -398
  106. package/test/memory/retriever.test.js +0 -613
  107. package/test/memory/retriever.test.js.bak +0 -585
  108. package/test/memory/search.test.js +0 -537
  109. package/test/memory/search.test.js.bak +0 -389
  110. package/test/memory/store.test.js +0 -344
  111. package/test/memory/store.test.js.bak +0 -312
  112. package/test/memory/surprise.test.js +0 -300
  113. package/test/memory-performance.test.js +0 -472
  114. package/test/openai-integration.test.js +0 -683
  115. package/test/openrouter-error-resilience.test.js +0 -418
  116. package/test/passthrough-mode.test.js +0 -385
  117. package/test/performance-benchmark.js +0 -351
  118. package/test/performance-tests.js +0 -528
  119. package/test/routing.test.js +0 -225
  120. package/test/toon-compression.test.js +0 -131
  121. package/test/web-tools.test.js +0 -329
  122. package/test-agents-simple.js +0 -43
  123. package/test-cli-connection.sh +0 -33
  124. package/test-learning-unit.js +0 -126
  125. package/test-learning.js +0 -112
  126. package/test-parallel-agents.sh +0 -124
  127. package/test-parallel-direct.js +0 -155
  128. package/test-subagents.sh +0 -117
package/test/README.md DELETED
@@ -1,212 +0,0 @@
1
- # Test Suite Documentation
2
-
3
- All tests for the Lynkr project are consolidated in this `test/` directory.
4
-
5
- ## Test Files
6
-
7
- ### Unit Tests
8
- **File**: `routing.test.js`
9
- **Purpose**: Tests the hybrid routing logic in isolation
10
- **Run**: `DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node --test test/routing.test.js`
11
- **Coverage**: 10 tests
12
- - Routing with tier-based routing disabled (no TIER_* vars set)
13
- - Simple requests → Ollama
14
- - Complex requests → Cloud
15
- - Tool capability checks
16
- - Fallback configuration
17
-
18
- ---
19
-
20
- ### Integration Tests
21
- **File**: `hybrid-routing-integration.test.js`
22
- **Purpose**: Tests configuration validation and metrics recording
23
- **Run**: `node --test test/hybrid-routing-integration.test.js`
24
- **Coverage**: 13 tests
25
- - Configuration validation (5 tests)
26
- - Metrics recording (6 tests)
27
- - Helper functions (2 tests)
28
-
29
- ---
30
-
31
- ### Hybrid Routing Performance Tests
32
- **File**: `hybrid-routing-performance.test.js`
33
- **Purpose**: Measures performance overhead of hybrid routing
34
- **Run**: `node test/hybrid-routing-performance.test.js`
35
- **Key Metrics**:
36
- - Routing decision: <0.01ms (36.8M decisions/sec)
37
- - Metrics overhead: <0.01ms (43.6M ops/sec)
38
- - Combined overhead: <0.02ms (15.6M ops/sec)
39
-
40
- ---
41
-
42
- ### System Performance Tests
43
- **File**: `performance-tests.js`
44
- **Purpose**: Tests system-wide performance optimizations
45
- **Run**: `DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node test/performance-tests.js`
46
- **Coverage**:
47
- - Database indexes (100% complete)
48
- - Persistent prompt cache
49
- - Regex pattern caching (4.5x faster)
50
- - Lazy loading
51
- - HTTP connection pooling
52
- - Response compression
53
-
54
- ---
55
-
56
- ### Middleware Benchmarks
57
- **File**: `performance-benchmark.js`
58
- **Purpose**: Benchmarks middleware overhead
59
- **Run**: `DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node test/performance-benchmark.js`
60
- **Coverage**:
61
- - Metrics collection (3.4M ops/sec)
62
- - Circuit breakers (3.9M ops/sec)
63
- - Input validation (5.7M ops/sec)
64
- - Load shedding
65
- - Combined middleware stack
66
-
67
- ---
68
-
69
- ## Running All Tests
70
-
71
- ### Using npm scripts (Recommended)
72
-
73
- **Run all tests (unit + performance):**
74
- ```bash
75
- npm test
76
- ```
77
-
78
- **Run only unit/integration tests:**
79
- ```bash
80
- npm run test:unit
81
- ```
82
-
83
- **Run only performance tests:**
84
- ```bash
85
- npm run test:performance
86
- ```
87
-
88
- **Run only benchmarks:**
89
- ```bash
90
- npm run test:benchmark
91
- ```
92
-
93
- **Run quick smoke test (routing only):**
94
- ```bash
95
- npm run test:quick
96
- ```
97
-
98
- **Run everything including benchmarks:**
99
- ```bash
100
- npm run test:all
101
- ```
102
-
103
- ### Manual execution (if needed)
104
-
105
- **Quick Test:**
106
- Run all unit and integration tests:
107
- ```bash
108
- DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node --test test/
109
- ```
110
-
111
- **Full Test Suite:**
112
- Run everything including performance tests:
113
- ```bash
114
- # Unit + Integration tests
115
- DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node --test test/routing.test.js
116
- DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node --test test/hybrid-routing-integration.test.js
117
-
118
- # Performance tests
119
- node test/hybrid-routing-performance.test.js
120
- DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node test/performance-tests.js
121
- DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node test/performance-benchmark.js
122
- ```
123
-
124
- ---
125
-
126
- ## Test Organization
127
-
128
- ```
129
- test/
130
- ├── README.md ← This file
131
- ├── routing.test.js ← Unit tests (10 tests)
132
- ├── hybrid-routing-integration.test.js ← Integration tests (13 tests)
133
- ├── hybrid-routing-performance.test.js ← Routing performance benchmarks
134
- ├── performance-tests.js ← System performance tests
135
- └── performance-benchmark.js ← Middleware benchmarks
136
- ```
137
-
138
- ---
139
-
140
- ## Important Notes
141
-
142
- ### Not Test Files
143
- - `src/tests/` - This is **application code**, not tests! It provides test execution functionality as a feature.
144
-
145
- ### Environment Variables
146
- Most tests require Databricks credentials (even though they're not used in actual API calls):
147
- ```bash
148
- export DATABRICKS_API_KEY=test-key
149
- export DATABRICKS_API_BASE=http://test.com
150
- ```
151
-
152
- ### Test Results Summary
153
-
154
- | Test Type | Status | Count |
155
- |-----------|--------|-------|
156
- | Unit Tests | ✅ Passing | 10/10 |
157
- | Integration Tests | ✅ Passing | 13/13 |
158
- | Routing Performance | ✅ Complete | <0.02ms overhead |
159
- | System Performance | ✅ Complete | 100% optimizations |
160
- | Middleware Benchmarks | ✅ Complete | Acceptable overhead |
161
-
162
- ---
163
-
164
- ## CI/CD Integration
165
-
166
- To run in CI/CD pipelines:
167
-
168
- ```bash
169
- #!/bin/bash
170
- set -e
171
-
172
- # Run all tests using npm
173
- echo "Running test suite..."
174
- npm run test:all
175
-
176
- echo "All tests passed!"
177
- ```
178
-
179
- Or for a faster CI pipeline (skip benchmarks):
180
-
181
- ```bash
182
- #!/bin/bash
183
- set -e
184
-
185
- echo "Running tests..."
186
- npm test
187
-
188
- echo "Tests passed!"
189
- ```
190
-
191
- ---
192
-
193
- ## Adding New Tests
194
-
195
- When adding new tests, follow these conventions:
196
-
197
- 1. **Unit tests**: Test individual functions in isolation
198
- - Place in `test/`
199
- - Use `node:test` framework
200
- - Name: `feature-name.test.js`
201
-
202
- 2. **Integration tests**: Test multiple components together
203
- - Place in `test/`
204
- - Use `node:test` framework
205
- - Name: `feature-name-integration.test.js`
206
-
207
- 3. **Performance tests**: Benchmark specific features
208
- - Place in `test/`
209
- - Use custom benchmark utilities
210
- - Name: `feature-name-performance.test.js`
211
-
212
- 4. **Always**: Document in this README!
@@ -1,213 +0,0 @@
1
- const assert = require("assert");
2
- const { describe, it, beforeEach, afterEach } = require("node:test");
3
-
4
- describe("Azure OpenAI Configuration Tests", () => {
5
- let originalConfig;
6
-
7
- beforeEach(() => {
8
- // Clear module cache
9
- delete require.cache[require.resolve("../src/config")];
10
-
11
- // Store original config
12
- originalConfig = { ...process.env };
13
-
14
- // Set Azure OpenAI environment variables to empty strings to override .env values
15
- // (deleting them would cause dotenv to reload from .env file)
16
- process.env.AZURE_OPENAI_ENDPOINT = "";
17
- process.env.AZURE_OPENAI_API_KEY = "";
18
- process.env.AZURE_OPENAI_DEPLOYMENT = "";
19
- process.env.AZURE_OPENAI_API_VERSION = "";
20
-
21
- // Prevent .env TIER_* values from being picked up by dotenv
22
- process.env.TIER_SIMPLE = "";
23
- process.env.TIER_MEDIUM = "";
24
- process.env.TIER_COMPLEX = "";
25
- process.env.TIER_REASONING = "";
26
- });
27
-
28
- afterEach(() => {
29
- // Restore original environment
30
- process.env = originalConfig;
31
- });
32
-
33
- describe("Configuration Loading", () => {
34
- it("should load Azure OpenAI configuration with all values set", () => {
35
- process.env.AZURE_OPENAI_ENDPOINT = "https://test-resource.openai.azure.com";
36
- process.env.AZURE_OPENAI_API_KEY = "test-api-key";
37
- process.env.AZURE_OPENAI_DEPLOYMENT = "gpt-4o";
38
- process.env.AZURE_OPENAI_API_VERSION = "2024-08-01-preview";
39
- process.env.MODEL_PROVIDER = "databricks";
40
- process.env.DATABRICKS_API_KEY = "test-key";
41
- process.env.DATABRICKS_API_BASE = "http://test.com";
42
-
43
- const config = require("../src/config");
44
-
45
- assert.strictEqual(config.azureOpenAI.endpoint, "https://test-resource.openai.azure.com");
46
- assert.strictEqual(config.azureOpenAI.apiKey, "test-api-key");
47
- assert.strictEqual(config.azureOpenAI.deployment, "gpt-4o");
48
- assert.strictEqual(config.azureOpenAI.apiVersion, "2024-08-01-preview");
49
- });
50
-
51
- it("should use default values when optional fields not set", () => {
52
- process.env.AZURE_OPENAI_ENDPOINT = "https://test-resource.openai.azure.com";
53
- process.env.AZURE_OPENAI_API_KEY = "test-api-key";
54
- // Keep as empty strings (don't delete) to prevent dotenv from reloading
55
- process.env.AZURE_OPENAI_DEPLOYMENT = "";
56
- process.env.AZURE_OPENAI_API_VERSION = "";
57
- process.env.MODEL_PROVIDER = "databricks";
58
- process.env.DATABRICKS_API_KEY = "test-key";
59
- process.env.DATABRICKS_API_BASE = "http://test.com";
60
-
61
- const config = require("../src/config");
62
-
63
- assert.strictEqual(config.azureOpenAI.deployment, "gpt-4o");
64
- assert.strictEqual(config.azureOpenAI.apiVersion, "2024-08-01-preview");
65
- });
66
-
67
- it("should load null values when Azure OpenAI not configured", () => {
68
- // Keep as empty strings (don't delete) to prevent dotenv from reloading
69
- process.env.AZURE_OPENAI_ENDPOINT = "";
70
- process.env.AZURE_OPENAI_API_KEY = "";
71
- process.env.MODEL_PROVIDER = "databricks";
72
- process.env.DATABRICKS_API_KEY = "test-key";
73
- process.env.DATABRICKS_API_BASE = "http://test.com";
74
-
75
- const config = require("../src/config");
76
-
77
- assert.strictEqual(config.azureOpenAI.endpoint, null);
78
- assert.strictEqual(config.azureOpenAI.apiKey, null);
79
- assert.strictEqual(config.azureOpenAI.deployment, "gpt-4o"); // default
80
- assert.strictEqual(config.azureOpenAI.apiVersion, "2024-08-01-preview"); // default
81
- });
82
- });
83
-
84
- describe("Primary Provider Validation", () => {
85
- it("should accept azure-openai as MODEL_PROVIDER", () => {
86
- process.env.MODEL_PROVIDER = "azure-openai";
87
- process.env.AZURE_OPENAI_ENDPOINT = "https://test-resource.openai.azure.com";
88
- process.env.AZURE_OPENAI_API_KEY = "test-api-key";
89
-
90
- const config = require("../src/config");
91
-
92
- assert.strictEqual(config.modelProvider.type, "azure-openai");
93
- });
94
-
95
- it("should throw error when azure-openai is primary provider without endpoint", () => {
96
- process.env.MODEL_PROVIDER = "azure-openai";
97
- process.env.AZURE_OPENAI_ENDPOINT = ""; // Empty string, not deleted
98
- process.env.AZURE_OPENAI_API_KEY = "test-api-key";
99
-
100
- assert.throws(() => {
101
- require("../src/config");
102
- }, /AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_API_KEY/);
103
- });
104
-
105
- it("should throw error when azure-openai is primary provider without API key", () => {
106
- process.env.MODEL_PROVIDER = "azure-openai";
107
- process.env.AZURE_OPENAI_ENDPOINT = "https://test-resource.openai.azure.com";
108
- process.env.AZURE_OPENAI_API_KEY = ""; // Empty string, not deleted
109
-
110
- assert.throws(() => {
111
- require("../src/config");
112
- }, /AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_API_KEY/);
113
- });
114
-
115
- it("should throw error when azure-openai is primary provider without both", () => {
116
- process.env.MODEL_PROVIDER = "azure-openai";
117
- process.env.AZURE_OPENAI_ENDPOINT = ""; // Empty string, not deleted
118
- process.env.AZURE_OPENAI_API_KEY = ""; // Empty string, not deleted
119
-
120
- assert.throws(() => {
121
- require("../src/config");
122
- }, /AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_API_KEY/);
123
- });
124
- });
125
-
126
- describe("Fallback Provider Validation", () => {
127
- it("should accept azure-openai as fallback provider with credentials", () => {
128
- process.env.MODEL_PROVIDER = "ollama";
129
- process.env.OLLAMA_ENDPOINT = "http://localhost:11434";
130
- process.env.OLLAMA_MODEL = "qwen2.5-coder:latest";
131
- process.env.FALLBACK_ENABLED = "true";
132
- process.env.FALLBACK_PROVIDER = "azure-openai";
133
- process.env.AZURE_OPENAI_ENDPOINT = "https://test-resource.openai.azure.com";
134
- process.env.AZURE_OPENAI_API_KEY = "test-api-key";
135
- process.env.DATABRICKS_API_KEY = "test-key";
136
- process.env.DATABRICKS_API_BASE = "http://test.com";
137
-
138
- const config = require("../src/config");
139
-
140
- assert.strictEqual(config.modelProvider.fallbackProvider, "azure-openai");
141
- });
142
-
143
- it("should warn when azure-openai is fallback but credentials missing", () => {
144
- process.env.MODEL_PROVIDER = "ollama";
145
- process.env.OLLAMA_ENDPOINT = "http://localhost:11434";
146
- process.env.OLLAMA_MODEL = "qwen2.5-coder:latest";
147
- process.env.FALLBACK_ENABLED = "true";
148
- process.env.FALLBACK_PROVIDER = "azure-openai";
149
- // Set to empty strings instead of deleting (dotenv.config() in config module would reload from .env)
150
- process.env.AZURE_OPENAI_ENDPOINT = "";
151
- process.env.AZURE_OPENAI_API_KEY = "";
152
- process.env.DATABRICKS_API_KEY = "test-key";
153
- process.env.DATABRICKS_API_BASE = "http://test.com";
154
- // Enable tier routing so fallback validation runs
155
- process.env.TIER_SIMPLE = "ollama:llama3.2";
156
- process.env.TIER_MEDIUM = "ollama:llama3.2";
157
- process.env.TIER_COMPLEX = "ollama:llama3.2";
158
- process.env.TIER_REASONING = "ollama:llama3.2";
159
-
160
- // Should warn but not throw (fallback misconfigured warning)
161
- const config = require("../src/config");
162
- assert.strictEqual(config.modelProvider.fallbackProvider, "azure-openai");
163
- });
164
- });
165
-
166
- describe("Deployment and API Version Defaults", () => {
167
- it("should use gpt-4o as default deployment", () => {
168
- // Keep as empty string (don't delete) to prevent dotenv from reloading from .env
169
- process.env.AZURE_OPENAI_DEPLOYMENT = "";
170
- process.env.MODEL_PROVIDER = "azure-openai";
171
- process.env.AZURE_OPENAI_ENDPOINT = "https://test-resource.openai.azure.com";
172
- process.env.AZURE_OPENAI_API_KEY = "test-api-key";
173
-
174
- const config = require("../src/config");
175
-
176
- assert.strictEqual(config.azureOpenAI.deployment, "gpt-4o");
177
- });
178
-
179
- it("should use custom deployment when specified", () => {
180
- process.env.AZURE_OPENAI_DEPLOYMENT = "gpt-5";
181
- process.env.MODEL_PROVIDER = "databricks";
182
- process.env.DATABRICKS_API_KEY = "test-key";
183
- process.env.DATABRICKS_API_BASE = "http://test.com";
184
-
185
- const config = require("../src/config");
186
-
187
- assert.strictEqual(config.azureOpenAI.deployment, "gpt-5");
188
- });
189
-
190
- it("should use 2024-08-01-preview as default API version", () => {
191
- // Keep as empty string (don't delete) to prevent dotenv from reloading from .env
192
- process.env.AZURE_OPENAI_API_VERSION = "";
193
- process.env.MODEL_PROVIDER = "databricks";
194
- process.env.DATABRICKS_API_KEY = "test-key";
195
- process.env.DATABRICKS_API_BASE = "http://test.com";
196
-
197
- const config = require("../src/config");
198
-
199
- assert.strictEqual(config.azureOpenAI.apiVersion, "2024-08-01-preview");
200
- });
201
-
202
- it("should use custom API version when specified", () => {
203
- process.env.AZURE_OPENAI_API_VERSION = "2025-01-01-preview";
204
- process.env.MODEL_PROVIDER = "databricks";
205
- process.env.DATABRICKS_API_KEY = "test-key";
206
- process.env.DATABRICKS_API_BASE = "http://test.com";
207
-
208
- const config = require("../src/config");
209
-
210
- assert.strictEqual(config.azureOpenAI.apiVersion, "2025-01-01-preview");
211
- });
212
- });
213
- });
@@ -1,238 +0,0 @@
1
- const assert = require("assert");
2
- const { describe, it } = require("node:test");
3
-
4
- describe("Azure OpenAI Error Resilience Tests", () => {
5
- describe("Error Response Structure", () => {
6
- it("should recognize 401 authentication error", () => {
7
- const errorResponse = {
8
- status: 401,
9
- json: {
10
- error: {
11
- message: "Incorrect API key provided",
12
- type: "invalid_request_error",
13
- code: "invalid_api_key"
14
- }
15
- }
16
- };
17
-
18
- assert.strictEqual(errorResponse.status, 401);
19
- assert.strictEqual(errorResponse.json.error.code, "invalid_api_key");
20
- });
21
-
22
- it("should recognize 403 permission denied error", () => {
23
- const errorResponse = {
24
- status: 403,
25
- json: {
26
- error: {
27
- message: "The API deployment for this resource does not exist",
28
- type: "invalid_request_error",
29
- code: "DeploymentNotFound"
30
- }
31
- }
32
- };
33
-
34
- assert.strictEqual(errorResponse.status, 403);
35
- });
36
-
37
- it("should recognize 404 deployment not found error", () => {
38
- const errorResponse = {
39
- status: 404,
40
- json: {
41
- error: {
42
- message: "The API deployment for this resource does not exist",
43
- type: "invalid_request_error",
44
- code: "DeploymentNotFound"
45
- }
46
- }
47
- };
48
-
49
- assert.strictEqual(errorResponse.status, 404);
50
- assert.strictEqual(errorResponse.json.error.code, "DeploymentNotFound");
51
- });
52
-
53
- it("should recognize 429 rate limit error with Retry-After header", () => {
54
- const errorResponse = {
55
- status: 429,
56
- headers: {
57
- "retry-after": "2",
58
- "x-ratelimit-remaining-tokens": "0",
59
- "x-ratelimit-remaining-requests": "0"
60
- },
61
- json: {
62
- error: {
63
- message: "Rate limit reached",
64
- type: "rate_limit_error",
65
- code: "rate_limit_exceeded"
66
- }
67
- }
68
- };
69
-
70
- assert.strictEqual(errorResponse.status, 429);
71
- assert.strictEqual(errorResponse.headers["retry-after"], "2");
72
- assert.strictEqual(errorResponse.json.error.code, "rate_limit_exceeded");
73
- });
74
-
75
- it("should recognize 400 content filter error", () => {
76
- const errorResponse = {
77
- status: 400,
78
- json: {
79
- error: {
80
- message: "The response was filtered due to the prompt triggering Azure OpenAI's content management policy",
81
- type: "invalid_request_error",
82
- code: "content_filter"
83
- }
84
- }
85
- };
86
-
87
- assert.strictEqual(errorResponse.status, 400);
88
- assert.strictEqual(errorResponse.json.error.code, "content_filter");
89
- });
90
-
91
- it("should recognize 500 internal server error", () => {
92
- const errorResponse = {
93
- status: 500,
94
- json: {
95
- error: {
96
- message: "The server had an error while processing your request",
97
- type: "server_error",
98
- code: "internal_error"
99
- }
100
- }
101
- };
102
-
103
- assert.strictEqual(errorResponse.status, 500);
104
- assert.strictEqual(errorResponse.json.error.type, "server_error");
105
- });
106
-
107
- it("should recognize 503 service unavailable error", () => {
108
- const errorResponse = {
109
- status: 503,
110
- json: {
111
- error: {
112
- message: "The service is temporarily unavailable",
113
- type: "server_error",
114
- code: "service_unavailable"
115
- }
116
- }
117
- };
118
-
119
- assert.strictEqual(errorResponse.status, 503);
120
- });
121
- });
122
-
123
- describe("Missing Choices Array Validation", () => {
124
- it("should detect missing choices array", () => {
125
- const invalidResponse = {
126
- id: "chatcmpl-123",
127
- object: "chat.completion",
128
- model: "gpt-4o"
129
- // choices array missing
130
- };
131
-
132
- assert.strictEqual(invalidResponse.choices, undefined);
133
- });
134
-
135
- it("should detect empty choices array", () => {
136
- const invalidResponse = {
137
- id: "chatcmpl-123",
138
- object: "chat.completion",
139
- model: "gpt-4o",
140
- choices: []
141
- };
142
-
143
- assert.strictEqual(invalidResponse.choices.length, 0);
144
- });
145
-
146
- it("should validate valid choices array", () => {
147
- const validResponse = {
148
- choices: [
149
- {
150
- message: {
151
- role: "assistant",
152
- content: "Hello"
153
- },
154
- finish_reason: "stop"
155
- }
156
- ]
157
- };
158
-
159
- assert.ok(validResponse.choices?.length > 0);
160
- assert.ok(validResponse.choices[0].message);
161
- });
162
- });
163
-
164
- describe("Network Error Categorization", () => {
165
- it("should categorize ETIMEDOUT as timeout error", () => {
166
- const error = new Error("Request timeout");
167
- error.code = "ETIMEDOUT";
168
-
169
- assert.strictEqual(error.code, "ETIMEDOUT");
170
- });
171
-
172
- it("should categorize ECONNREFUSED as connection error", () => {
173
- const error = new Error("Connection refused");
174
- error.code = "ECONNREFUSED";
175
-
176
- assert.strictEqual(error.code, "ECONNREFUSED");
177
- });
178
-
179
- it("should categorize ENOTFOUND as DNS error", () => {
180
- const error = new Error("DNS lookup failed");
181
- error.code = "ENOTFOUND";
182
-
183
- assert.strictEqual(error.code, "ENOTFOUND");
184
- });
185
- });
186
-
187
- describe("Retry Strategy", () => {
188
- it("should identify retryable 5xx errors", () => {
189
- const retryableStatuses = [500, 502, 503, 504];
190
-
191
- for (const status of retryableStatuses) {
192
- assert.ok(status >= 500 && status < 600);
193
- }
194
- });
195
-
196
- it("should identify non-retryable 4xx errors", () => {
197
- const nonRetryableStatuses = [400, 401, 403, 404];
198
-
199
- for (const status of nonRetryableStatuses) {
200
- assert.ok(status >= 400 && status < 500);
201
- assert.notStrictEqual(status, 429); // 429 is retryable
202
- }
203
- });
204
-
205
- it("should treat 429 as retryable with backoff", () => {
206
- const status = 429;
207
-
208
- assert.strictEqual(status, 429);
209
- assert.ok(status === 429); // Special handling for rate limits
210
- });
211
- });
212
-
213
- describe("Malformed JSON Response", () => {
214
- it("should handle truncated JSON response", () => {
215
- const truncatedJSON = '{"choices":[{"message":{"role":"assistant","content":"Hello';
216
-
217
- assert.throws(() => {
218
- JSON.parse(truncatedJSON);
219
- }, SyntaxError);
220
- });
221
-
222
- it("should handle empty response body", () => {
223
- const emptyBody = "";
224
-
225
- assert.throws(() => {
226
- JSON.parse(emptyBody);
227
- }, SyntaxError);
228
- });
229
-
230
- it("should handle non-JSON response", () => {
231
- const htmlError = "<html><body>Error 503</body></html>";
232
-
233
- assert.throws(() => {
234
- JSON.parse(htmlError);
235
- }, SyntaxError);
236
- });
237
- });
238
- });