lynkr 7.2.5 → 8.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 (124) hide show
  1. package/README.md +3 -3
  2. package/config/model-tiers.json +89 -0
  3. package/install.sh +6 -1
  4. package/package.json +4 -2
  5. package/scripts/setup.js +0 -1
  6. package/src/agents/executor.js +14 -6
  7. package/src/api/middleware/session.js +15 -2
  8. package/src/api/openai-router.js +162 -37
  9. package/src/api/providers-handler.js +15 -1
  10. package/src/api/router.js +107 -2
  11. package/src/budget/index.js +4 -3
  12. package/src/clients/databricks.js +431 -234
  13. package/src/clients/gpt-utils.js +181 -0
  14. package/src/clients/ollama-utils.js +66 -140
  15. package/src/clients/routing.js +0 -1
  16. package/src/clients/standard-tools.js +99 -3
  17. package/src/config/index.js +133 -35
  18. package/src/context/toon.js +173 -0
  19. package/src/logger/index.js +23 -0
  20. package/src/orchestrator/index.js +688 -213
  21. package/src/routing/agentic-detector.js +320 -0
  22. package/src/routing/complexity-analyzer.js +202 -2
  23. package/src/routing/cost-optimizer.js +305 -0
  24. package/src/routing/index.js +168 -159
  25. package/src/routing/model-tiers.js +365 -0
  26. package/src/server.js +4 -14
  27. package/src/sessions/cleanup.js +3 -3
  28. package/src/sessions/record.js +10 -1
  29. package/src/sessions/store.js +7 -2
  30. package/src/tools/agent-task.js +48 -1
  31. package/src/tools/index.js +19 -2
  32. package/src/tools/lazy-loader.js +7 -0
  33. package/src/tools/tinyfish.js +358 -0
  34. package/src/tools/truncate.js +1 -0
  35. package/.github/FUNDING.yml +0 -15
  36. package/.github/workflows/README.md +0 -215
  37. package/.github/workflows/ci.yml +0 -69
  38. package/.github/workflows/index.yml +0 -62
  39. package/.github/workflows/web-tools-tests.yml +0 -56
  40. package/CITATIONS.bib +0 -6
  41. package/CLAWROUTER_ROUTING_PLAN.md +0 -910
  42. package/DEPLOYMENT.md +0 -1001
  43. package/LYNKR-TUI-PLAN.md +0 -984
  44. package/PERFORMANCE-REPORT.md +0 -866
  45. package/PLAN-per-client-model-routing.md +0 -252
  46. package/ROUTER_COMPARISON.md +0 -173
  47. package/TIER_ROUTING_PLAN.md +0 -771
  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 -197
  52. package/docs/google5be250e608e6da39.html +0 -1
  53. package/docs/index.html +0 -577
  54. package/docs/index.md +0 -577
  55. package/docs/robots.txt +0 -4
  56. package/docs/sitemap.xml +0 -44
  57. package/docs/style.css +0 -1223
  58. package/documentation/README.md +0 -100
  59. package/documentation/api.md +0 -806
  60. package/documentation/claude-code-cli.md +0 -672
  61. package/documentation/codex-cli.md +0 -397
  62. package/documentation/contributing.md +0 -571
  63. package/documentation/cursor-integration.md +0 -731
  64. package/documentation/docker.md +0 -867
  65. package/documentation/embeddings.md +0 -760
  66. package/documentation/faq.md +0 -659
  67. package/documentation/features.md +0 -396
  68. package/documentation/headroom.md +0 -519
  69. package/documentation/installation.md +0 -706
  70. package/documentation/memory-system.md +0 -476
  71. package/documentation/production.md +0 -601
  72. package/documentation/providers.md +0 -906
  73. package/documentation/testing.md +0 -629
  74. package/documentation/token-optimization.md +0 -323
  75. package/documentation/tools.md +0 -697
  76. package/documentation/troubleshooting.md +0 -893
  77. package/final-test.js +0 -33
  78. package/headroom-sidecar/config.py +0 -93
  79. package/headroom-sidecar/requirements.txt +0 -14
  80. package/headroom-sidecar/server.py +0 -451
  81. package/monitor-agents.sh +0 -31
  82. package/scripts/audit-log-reader.js +0 -399
  83. package/scripts/compact-dictionary.js +0 -204
  84. package/scripts/test-deduplication.js +0 -448
  85. package/src/db/database.sqlite +0 -0
  86. package/test/README.md +0 -212
  87. package/test/azure-openai-config.test.js +0 -204
  88. package/test/azure-openai-error-resilience.test.js +0 -238
  89. package/test/azure-openai-format-conversion.test.js +0 -354
  90. package/test/azure-openai-integration.test.js +0 -281
  91. package/test/azure-openai-routing.test.js +0 -177
  92. package/test/azure-openai-streaming.test.js +0 -171
  93. package/test/bedrock-integration.test.js +0 -471
  94. package/test/comprehensive-test-suite.js +0 -928
  95. package/test/config-validation.test.js +0 -207
  96. package/test/cursor-integration.test.js +0 -484
  97. package/test/format-conversion.test.js +0 -578
  98. package/test/hybrid-routing-integration.test.js +0 -254
  99. package/test/hybrid-routing-performance.test.js +0 -418
  100. package/test/llamacpp-integration.test.js +0 -863
  101. package/test/lmstudio-integration.test.js +0 -335
  102. package/test/memory/extractor.test.js +0 -398
  103. package/test/memory/retriever.test.js +0 -613
  104. package/test/memory/retriever.test.js.bak +0 -585
  105. package/test/memory/search.test.js +0 -537
  106. package/test/memory/search.test.js.bak +0 -389
  107. package/test/memory/store.test.js +0 -344
  108. package/test/memory/store.test.js.bak +0 -312
  109. package/test/memory/surprise.test.js +0 -300
  110. package/test/memory-performance.test.js +0 -472
  111. package/test/openai-integration.test.js +0 -686
  112. package/test/openrouter-error-resilience.test.js +0 -418
  113. package/test/passthrough-mode.test.js +0 -385
  114. package/test/performance-benchmark.js +0 -351
  115. package/test/performance-tests.js +0 -528
  116. package/test/routing.test.js +0 -219
  117. package/test/web-tools.test.js +0 -329
  118. package/test-agents-simple.js +0 -43
  119. package/test-cli-connection.sh +0 -33
  120. package/test-learning-unit.js +0 -126
  121. package/test-learning.js +0 -112
  122. package/test-parallel-agents.sh +0 -124
  123. package/test-parallel-direct.js +0 -155
  124. package/test-subagents.sh +0 -117
@@ -1,471 +0,0 @@
1
- const assert = require("assert");
2
- const { describe, it, beforeEach, afterEach } = require("node:test");
3
-
4
- describe("AWS Bedrock Integration", () => {
5
- let originalEnv;
6
-
7
- beforeEach(() => {
8
- originalEnv = { ...process.env };
9
-
10
- // Clear module cache
11
- delete require.cache[require.resolve("../src/config")];
12
- delete require.cache[require.resolve("../src/clients/routing")];
13
- delete require.cache[require.resolve("../src/clients/bedrock-utils")];
14
- });
15
-
16
- afterEach(() => {
17
- process.env = originalEnv;
18
- });
19
-
20
- describe("Configuration", () => {
21
- it("should accept bedrock as a valid MODEL_PROVIDER", () => {
22
- process.env.MODEL_PROVIDER = "bedrock";
23
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
24
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
25
-
26
- const config = require("../src/config");
27
- assert.strictEqual(config.modelProvider.type, "bedrock");
28
- });
29
-
30
- it("should throw error when AWS credentials are missing", () => {
31
- process.env.MODEL_PROVIDER = "bedrock";
32
- // Set to empty string to override .env file values
33
- process.env.AWS_ACCESS_KEY_ID = "";
34
- process.env.AWS_SECRET_ACCESS_KEY = "";
35
-
36
- assert.throws(
37
- () => require("../src/config"),
38
- /AWS Bedrock requires AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY/
39
- );
40
- });
41
-
42
- it("should use default region (us-east-1)", () => {
43
- process.env.MODEL_PROVIDER = "bedrock";
44
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
45
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
46
- process.env.AWS_BEDROCK_REGION = ""; // Override .env value
47
- process.env.AWS_REGION = ""; // Override .env value
48
-
49
- const config = require("../src/config");
50
- assert.strictEqual(config.bedrock.region, "us-east-1");
51
- });
52
-
53
- it("should use custom region when AWS_BEDROCK_REGION is set", () => {
54
- process.env.MODEL_PROVIDER = "bedrock";
55
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
56
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
57
- process.env.AWS_BEDROCK_REGION = "us-west-2";
58
-
59
- const config = require("../src/config");
60
- assert.strictEqual(config.bedrock.region, "us-west-2");
61
- });
62
-
63
- it("should use AWS_REGION as fallback for region", () => {
64
- process.env.MODEL_PROVIDER = "bedrock";
65
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
66
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
67
- process.env.AWS_BEDROCK_REGION = ""; // Override .env value
68
- process.env.AWS_REGION = "ap-southeast-1";
69
-
70
- const config = require("../src/config");
71
- assert.strictEqual(config.bedrock.region, "ap-southeast-1");
72
- });
73
-
74
- it("should use default model ID", () => {
75
- process.env.MODEL_PROVIDER = "bedrock";
76
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
77
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
78
- process.env.AWS_BEDROCK_MODEL_ID = ""; // Override .env value
79
-
80
- const config = require("../src/config");
81
- assert.strictEqual(config.bedrock.modelId, "anthropic.claude-3-5-sonnet-20241022-v2:0");
82
- });
83
-
84
- it("should use custom model ID when AWS_BEDROCK_MODEL_ID is set", () => {
85
- process.env.MODEL_PROVIDER = "bedrock";
86
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
87
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
88
- process.env.AWS_BEDROCK_MODEL_ID = "anthropic.claude-3-opus-20240229-v1:0";
89
-
90
- const config = require("../src/config");
91
- assert.strictEqual(config.bedrock.modelId, "anthropic.claude-3-opus-20240229-v1:0");
92
- });
93
- });
94
-
95
- describe("Model Family Detection", () => {
96
- it("should detect claude family", () => {
97
- process.env.MODEL_PROVIDER = "databricks";
98
- process.env.DATABRICKS_API_KEY = "test";
99
- process.env.DATABRICKS_API_BASE = "http://test.com";
100
-
101
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
102
- assert.strictEqual(
103
- detectModelFamily("anthropic.claude-3-5-sonnet-20241022-v2:0"),
104
- "claude"
105
- );
106
- });
107
-
108
- it("should detect claude family from global inference profile", () => {
109
- process.env.MODEL_PROVIDER = "databricks";
110
- process.env.DATABRICKS_API_KEY = "test";
111
- process.env.DATABRICKS_API_BASE = "http://test.com";
112
-
113
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
114
- assert.strictEqual(
115
- detectModelFamily("global.anthropic.claude-sonnet-4-5-20250929-v1:0"),
116
- "claude"
117
- );
118
- });
119
-
120
- it("should detect claude family from US inference profile", () => {
121
- process.env.MODEL_PROVIDER = "databricks";
122
- process.env.DATABRICKS_API_KEY = "test";
123
- process.env.DATABRICKS_API_BASE = "http://test.com";
124
-
125
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
126
- assert.strictEqual(
127
- detectModelFamily("us.anthropic.claude-sonnet-4-5-20250929-v1:0"),
128
- "claude"
129
- );
130
- });
131
-
132
- it("should detect titan family", () => {
133
- process.env.MODEL_PROVIDER = "databricks";
134
- process.env.DATABRICKS_API_KEY = "test";
135
- process.env.DATABRICKS_API_BASE = "http://test.com";
136
-
137
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
138
- assert.strictEqual(
139
- detectModelFamily("amazon.titan-text-express-v1"),
140
- "titan"
141
- );
142
- });
143
-
144
- it("should detect llama family", () => {
145
- process.env.MODEL_PROVIDER = "databricks";
146
- process.env.DATABRICKS_API_KEY = "test";
147
- process.env.DATABRICKS_API_BASE = "http://test.com";
148
-
149
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
150
- assert.strictEqual(
151
- detectModelFamily("meta.llama3-70b-instruct-v1:0"),
152
- "llama"
153
- );
154
- });
155
-
156
- it("should detect jurassic family", () => {
157
- process.env.MODEL_PROVIDER = "databricks";
158
- process.env.DATABRICKS_API_KEY = "test";
159
- process.env.DATABRICKS_API_BASE = "http://test.com";
160
-
161
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
162
- assert.strictEqual(
163
- detectModelFamily("ai21.j2-ultra-v1"),
164
- "jurassic"
165
- );
166
- });
167
-
168
- it("should detect cohere family", () => {
169
- process.env.MODEL_PROVIDER = "databricks";
170
- process.env.DATABRICKS_API_KEY = "test";
171
- process.env.DATABRICKS_API_BASE = "http://test.com";
172
-
173
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
174
- assert.strictEqual(
175
- detectModelFamily("cohere.command-text-v14"),
176
- "cohere"
177
- );
178
- });
179
-
180
- it("should detect mistral family", () => {
181
- process.env.MODEL_PROVIDER = "databricks";
182
- process.env.DATABRICKS_API_KEY = "test";
183
- process.env.DATABRICKS_API_BASE = "http://test.com";
184
-
185
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
186
- assert.strictEqual(
187
- detectModelFamily("mistral.mistral-7b-instruct-v0:2"),
188
- "mistral"
189
- );
190
- });
191
-
192
- it("should throw error for unsupported model", () => {
193
- process.env.MODEL_PROVIDER = "databricks";
194
- process.env.DATABRICKS_API_KEY = "test";
195
- process.env.DATABRICKS_API_BASE = "http://test.com";
196
-
197
- const { detectModelFamily } = require("../src/clients/bedrock-utils");
198
- assert.throws(
199
- () => detectModelFamily("unknown.model-v1"),
200
- /Unsupported Bedrock model/
201
- );
202
- });
203
- });
204
-
205
- describe("Format Conversion - Request", () => {
206
- it("should keep Claude requests in Anthropic format", () => {
207
- process.env.MODEL_PROVIDER = "databricks";
208
- process.env.DATABRICKS_API_KEY = "test";
209
- process.env.DATABRICKS_API_BASE = "http://test.com";
210
-
211
- const { convertAnthropicToBedrockFormat } = require("../src/clients/bedrock-utils");
212
-
213
- const anthropicBody = {
214
- messages: [{ role: "user", content: "Hello" }],
215
- max_tokens: 1024,
216
- temperature: 0.7,
217
- };
218
-
219
- const result = convertAnthropicToBedrockFormat(anthropicBody, "claude");
220
-
221
- assert.strictEqual(result.anthropic_version, "bedrock-2023-05-31");
222
- assert.strictEqual(result.max_tokens, 1024);
223
- assert.strictEqual(result.temperature, 0.7);
224
- assert.deepStrictEqual(result.messages, anthropicBody.messages);
225
- });
226
-
227
- it("should convert to Titan format", () => {
228
- process.env.MODEL_PROVIDER = "databricks";
229
- process.env.DATABRICKS_API_KEY = "test";
230
- process.env.DATABRICKS_API_BASE = "http://test.com";
231
-
232
- const { convertAnthropicToBedrockFormat } = require("../src/clients/bedrock-utils");
233
-
234
- const anthropicBody = {
235
- messages: [{ role: "user", content: "Hello" }],
236
- max_tokens: 1024,
237
- temperature: 0.8,
238
- };
239
-
240
- const result = convertAnthropicToBedrockFormat(anthropicBody, "titan");
241
-
242
- assert.strictEqual(result.textGenerationConfig.maxTokenCount, 1024);
243
- assert.strictEqual(result.textGenerationConfig.temperature, 0.8);
244
- assert.ok(result.inputText.includes("Human: Hello"));
245
- });
246
-
247
- it("should convert to Llama format", () => {
248
- process.env.MODEL_PROVIDER = "databricks";
249
- process.env.DATABRICKS_API_KEY = "test";
250
- process.env.DATABRICKS_API_BASE = "http://test.com";
251
-
252
- const { convertAnthropicToBedrockFormat } = require("../src/clients/bedrock-utils");
253
-
254
- const anthropicBody = {
255
- messages: [{ role: "user", content: "Test" }],
256
- max_tokens: 512,
257
- temperature: 0.9,
258
- };
259
-
260
- const result = convertAnthropicToBedrockFormat(anthropicBody, "llama");
261
-
262
- assert.strictEqual(result.max_gen_len, 512);
263
- assert.strictEqual(result.temperature, 0.9);
264
- assert.ok(result.prompt.includes("Human: Test"));
265
- });
266
-
267
- it("should convert to Jurassic format", () => {
268
- process.env.MODEL_PROVIDER = "databricks";
269
- process.env.DATABRICKS_API_KEY = "test";
270
- process.env.DATABRICKS_API_BASE = "http://test.com";
271
-
272
- const { convertAnthropicToBedrockFormat } = require("../src/clients/bedrock-utils");
273
-
274
- const anthropicBody = {
275
- messages: [{ role: "user", content: "Test" }],
276
- max_tokens: 200,
277
- temperature: 0.7,
278
- };
279
-
280
- const result = convertAnthropicToBedrockFormat(anthropicBody, "jurassic");
281
-
282
- assert.strictEqual(result.maxTokens, 200);
283
- assert.strictEqual(result.temperature, 0.7);
284
- assert.ok(result.prompt.includes("Human: Test"));
285
- });
286
- });
287
-
288
- describe("Format Conversion - Response", () => {
289
- it("should parse Claude responses (native Anthropic)", () => {
290
- process.env.MODEL_PROVIDER = "databricks";
291
- process.env.DATABRICKS_API_KEY = "test";
292
- process.env.DATABRICKS_API_BASE = "http://test.com";
293
-
294
- const { convertBedrockResponseToAnthropic } = require("../src/clients/bedrock-utils");
295
-
296
- const claudeResponse = {
297
- id: "msg_123",
298
- type: "message",
299
- role: "assistant",
300
- content: [{ type: "text", text: "Hello!" }],
301
- stop_reason: "end_turn",
302
- usage: { input_tokens: 10, output_tokens: 5 },
303
- };
304
-
305
- const result = convertBedrockResponseToAnthropic(
306
- claudeResponse,
307
- "claude",
308
- "anthropic.claude-3-5-sonnet-20241022-v2:0"
309
- );
310
-
311
- assert.deepStrictEqual(result, claudeResponse);
312
- });
313
-
314
- it("should convert Titan responses to Anthropic format", () => {
315
- process.env.MODEL_PROVIDER = "databricks";
316
- process.env.DATABRICKS_API_KEY = "test";
317
- process.env.DATABRICKS_API_BASE = "http://test.com";
318
-
319
- const { convertBedrockResponseToAnthropic } = require("../src/clients/bedrock-utils");
320
-
321
- const titanResponse = {
322
- results: [{
323
- outputText: "Response text",
324
- tokenCount: 50,
325
- completionReason: "FINISH",
326
- }],
327
- inputTextTokenCount: 20,
328
- };
329
-
330
- const result = convertBedrockResponseToAnthropic(
331
- titanResponse,
332
- "titan",
333
- "amazon.titan-text-express-v1"
334
- );
335
-
336
- assert.strictEqual(result.role, "assistant");
337
- assert.strictEqual(result.content[0].type, "text");
338
- assert.strictEqual(result.content[0].text, "Response text");
339
- assert.strictEqual(result.stop_reason, "end_turn");
340
- assert.strictEqual(result.usage.input_tokens, 20);
341
- assert.strictEqual(result.usage.output_tokens, 50);
342
- });
343
-
344
- it("should convert Llama responses to Anthropic format", () => {
345
- process.env.MODEL_PROVIDER = "databricks";
346
- process.env.DATABRICKS_API_KEY = "test";
347
- process.env.DATABRICKS_API_BASE = "http://test.com";
348
-
349
- const { convertBedrockResponseToAnthropic } = require("../src/clients/bedrock-utils");
350
-
351
- const llamaResponse = {
352
- generation: "Llama response",
353
- prompt_token_count: 15,
354
- generation_token_count: 30,
355
- stop_reason: "stop",
356
- };
357
-
358
- const result = convertBedrockResponseToAnthropic(
359
- llamaResponse,
360
- "llama",
361
- "meta.llama3-70b-instruct-v1:0"
362
- );
363
-
364
- assert.strictEqual(result.role, "assistant");
365
- assert.strictEqual(result.content[0].text, "Llama response");
366
- assert.strictEqual(result.stop_reason, "end_turn");
367
- assert.strictEqual(result.usage.input_tokens, 15);
368
- assert.strictEqual(result.usage.output_tokens, 30);
369
- });
370
- });
371
-
372
- describe("Routing", () => {
373
- it("should route to bedrock when MODEL_PROVIDER is bedrock", () => {
374
- process.env.MODEL_PROVIDER = "bedrock";
375
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
376
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
377
- process.env.PREFER_OLLAMA = "false";
378
-
379
- const config = require("../src/config");
380
- const routing = require("../src/clients/routing");
381
-
382
- const payload = { messages: [{ role: "user", content: "test" }] };
383
- const provider = routing.determineProvider(payload);
384
-
385
- // When not in hybrid mode, should use primary provider
386
- assert.strictEqual(provider, "bedrock");
387
- });
388
-
389
- it("should route to bedrock in hybrid mode for moderate tool counts", () => {
390
- process.env.MODEL_PROVIDER = "ollama";
391
- process.env.PREFER_OLLAMA = "true";
392
- process.env.OLLAMA_MODEL = "llama3.1";
393
- process.env.OLLAMA_ENDPOINT = "http://localhost:11434";
394
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
395
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
396
- process.env.OLLAMA_MAX_TOOLS_FOR_ROUTING = "2";
397
- process.env.FALLBACK_ENABLED = "true";
398
- process.env.FALLBACK_PROVIDER = "bedrock";
399
-
400
- // Clear other providers to ensure bedrock is chosen
401
- delete process.env.OPENROUTER_API_KEY;
402
- delete process.env.OPENAI_API_KEY;
403
- delete process.env.AZURE_OPENAI_API_KEY;
404
- delete process.env.AZURE_OPENAI_ENDPOINT;
405
- delete process.env.LLAMACPP_ENDPOINT;
406
- delete process.env.LMSTUDIO_ENDPOINT;
407
- delete process.env.DATABRICKS_API_KEY;
408
- delete process.env.DATABRICKS_API_BASE;
409
-
410
- const config = require("../src/config");
411
- const routing = require("../src/clients/routing");
412
-
413
- // 20 tools should exceed both Ollama and OpenRouter limits, routing to fallback provider (bedrock)
414
- const payload = {
415
- messages: [{ role: "user", content: "test" }],
416
- tools: Array(20).fill({ name: "tool" }),
417
- };
418
- const provider = routing.determineProvider(payload);
419
-
420
- assert.strictEqual(provider, "bedrock");
421
- });
422
- });
423
-
424
- describe("Fallback Provider", () => {
425
- it("should allow bedrock as fallback provider", () => {
426
- process.env.MODEL_PROVIDER = "ollama";
427
- process.env.PREFER_OLLAMA = "true";
428
- process.env.OLLAMA_MODEL = "llama3.1";
429
- process.env.OLLAMA_ENDPOINT = "http://localhost:11434";
430
- process.env.FALLBACK_PROVIDER = "bedrock";
431
- process.env.AWS_ACCESS_KEY_ID = "AKIATEST123";
432
- process.env.AWS_SECRET_ACCESS_KEY = "testSecretKey123";
433
- process.env.FALLBACK_ENABLED = "true";
434
-
435
- // Should not throw
436
- const config = require("../src/config");
437
- assert.strictEqual(config.modelProvider.fallbackProvider, "bedrock");
438
- });
439
-
440
- it("should validate bedrock credentials when used as fallback", () => {
441
- process.env.MODEL_PROVIDER = "ollama";
442
- process.env.PREFER_OLLAMA = "true";
443
- process.env.OLLAMA_MODEL = "llama3.1";
444
- process.env.OLLAMA_ENDPOINT = "http://localhost:11434";
445
- process.env.FALLBACK_PROVIDER = "bedrock";
446
- process.env.FALLBACK_ENABLED = "true";
447
- // Set to empty string to override .env file values
448
- process.env.AWS_ACCESS_KEY_ID = "";
449
- process.env.AWS_SECRET_ACCESS_KEY = "";
450
-
451
- assert.throws(
452
- () => require("../src/config"),
453
- /FALLBACK_PROVIDER is set to 'bedrock' but AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are not configured/
454
- );
455
- });
456
-
457
- it("should not allow local providers as fallback", () => {
458
- process.env.MODEL_PROVIDER = "ollama";
459
- process.env.PREFER_OLLAMA = "true";
460
- process.env.OLLAMA_MODEL = "llama3.1";
461
- process.env.OLLAMA_ENDPOINT = "http://localhost:11434";
462
- process.env.FALLBACK_PROVIDER = "llamacpp";
463
- process.env.FALLBACK_ENABLED = "true";
464
-
465
- assert.throws(
466
- () => require("../src/config"),
467
- /FALLBACK_PROVIDER cannot be 'llamacpp'/
468
- );
469
- });
470
- });
471
- });