beth-copilot 1.0.13 → 1.0.15

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 (104) hide show
  1. package/CHANGELOG.md +195 -170
  2. package/README.md +408 -185
  3. package/bin/cli.js +65 -4
  4. package/dist/cli/commands/doctor.e2e.test.d.ts +8 -0
  5. package/dist/cli/commands/doctor.e2e.test.d.ts.map +1 -0
  6. package/dist/cli/commands/doctor.e2e.test.js +428 -0
  7. package/dist/cli/commands/doctor.e2e.test.js.map +1 -0
  8. package/dist/cli/commands/doctor.test.js +1 -1
  9. package/dist/cli/commands/help.e2e.test.d.ts +9 -0
  10. package/dist/cli/commands/help.e2e.test.d.ts.map +1 -0
  11. package/dist/cli/commands/help.e2e.test.js +150 -0
  12. package/dist/cli/commands/help.e2e.test.js.map +1 -0
  13. package/dist/cli/commands/init.test.d.ts +6 -0
  14. package/dist/cli/commands/init.test.d.ts.map +1 -0
  15. package/dist/cli/commands/init.test.js +289 -0
  16. package/dist/cli/commands/init.test.js.map +1 -0
  17. package/dist/cli/commands/mcp.e2e.test.d.ts +9 -0
  18. package/dist/cli/commands/mcp.e2e.test.d.ts.map +1 -0
  19. package/dist/cli/commands/mcp.e2e.test.js +139 -0
  20. package/dist/cli/commands/mcp.e2e.test.js.map +1 -0
  21. package/dist/cli/commands/pipeline.e2e.test.d.ts +9 -0
  22. package/dist/cli/commands/pipeline.e2e.test.d.ts.map +1 -0
  23. package/dist/cli/commands/pipeline.e2e.test.js +192 -0
  24. package/dist/cli/commands/pipeline.e2e.test.js.map +1 -0
  25. package/dist/cli/commands/quickstart.test.d.ts +6 -0
  26. package/dist/cli/commands/quickstart.test.d.ts.map +1 -0
  27. package/dist/cli/commands/quickstart.test.js +232 -0
  28. package/dist/cli/commands/quickstart.test.js.map +1 -0
  29. package/dist/core/agents/frontmatter.test.d.ts +8 -0
  30. package/dist/core/agents/frontmatter.test.d.ts.map +1 -0
  31. package/dist/core/agents/frontmatter.test.js +589 -0
  32. package/dist/core/agents/frontmatter.test.js.map +1 -0
  33. package/dist/core/agents/handoffs.test.d.ts +8 -0
  34. package/dist/core/agents/handoffs.test.d.ts.map +1 -0
  35. package/dist/core/agents/handoffs.test.js +320 -0
  36. package/dist/core/agents/handoffs.test.js.map +1 -0
  37. package/dist/core/agents/loader.test.js +1 -1
  38. package/dist/core/agents/suite.test.d.ts +8 -0
  39. package/dist/core/agents/suite.test.d.ts.map +1 -0
  40. package/dist/core/agents/suite.test.js +207 -0
  41. package/dist/core/agents/suite.test.js.map +1 -0
  42. package/dist/core/agents/tools.test.d.ts +8 -0
  43. package/dist/core/agents/tools.test.d.ts.map +1 -0
  44. package/dist/core/agents/tools.test.js +332 -0
  45. package/dist/core/agents/tools.test.js.map +1 -0
  46. package/dist/init.test.js +288 -0
  47. package/dist/providers/azure.d.ts +147 -0
  48. package/dist/providers/azure.d.ts.map +1 -0
  49. package/dist/providers/azure.js +491 -0
  50. package/dist/providers/azure.js.map +1 -0
  51. package/dist/providers/azure.test.d.ts +11 -0
  52. package/dist/providers/azure.test.d.ts.map +1 -0
  53. package/dist/providers/azure.test.js +330 -0
  54. package/dist/providers/azure.test.js.map +1 -0
  55. package/dist/providers/config.d.ts +87 -0
  56. package/dist/providers/config.d.ts.map +1 -0
  57. package/dist/providers/config.js +193 -0
  58. package/dist/providers/config.js.map +1 -0
  59. package/dist/providers/config.test.d.ts +7 -0
  60. package/dist/providers/config.test.d.ts.map +1 -0
  61. package/dist/providers/config.test.js +370 -0
  62. package/dist/providers/config.test.js.map +1 -0
  63. package/dist/providers/index.d.ts +18 -0
  64. package/dist/providers/index.d.ts.map +1 -0
  65. package/dist/providers/index.js +14 -0
  66. package/dist/providers/index.js.map +1 -0
  67. package/dist/providers/interface.d.ts +191 -0
  68. package/dist/providers/interface.d.ts.map +1 -0
  69. package/dist/providers/interface.js +94 -0
  70. package/dist/providers/interface.js.map +1 -0
  71. package/dist/providers/retry.d.ts +128 -0
  72. package/dist/providers/retry.d.ts.map +1 -0
  73. package/dist/providers/retry.js +205 -0
  74. package/dist/providers/retry.js.map +1 -0
  75. package/dist/providers/retry.test.d.ts +7 -0
  76. package/dist/providers/retry.test.d.ts.map +1 -0
  77. package/dist/providers/retry.test.js +439 -0
  78. package/dist/providers/retry.test.js.map +1 -0
  79. package/dist/providers/streaming.d.ts +157 -0
  80. package/dist/providers/streaming.d.ts.map +1 -0
  81. package/dist/providers/streaming.js +233 -0
  82. package/dist/providers/streaming.js.map +1 -0
  83. package/dist/providers/streaming.test.d.ts +7 -0
  84. package/dist/providers/streaming.test.d.ts.map +1 -0
  85. package/dist/providers/streaming.test.js +372 -0
  86. package/dist/providers/streaming.test.js.map +1 -0
  87. package/dist/providers/types.d.ts +209 -0
  88. package/dist/providers/types.d.ts.map +1 -0
  89. package/dist/providers/types.js +53 -0
  90. package/dist/providers/types.js.map +1 -0
  91. package/dist/providers/types.test.d.ts +7 -0
  92. package/dist/providers/types.test.d.ts.map +1 -0
  93. package/dist/providers/types.test.js +141 -0
  94. package/dist/providers/types.test.js.map +1 -0
  95. package/package.json +60 -56
  96. package/sbom.json +3302 -8
  97. package/templates/.github/agents/beth.agent.md +329 -329
  98. package/templates/.github/agents/developer.agent.md +572 -572
  99. package/templates/.github/agents/product-manager.agent.md +272 -272
  100. package/templates/.github/agents/researcher.agent.md +338 -338
  101. package/templates/.github/agents/security-reviewer.agent.md +465 -465
  102. package/templates/.github/agents/tester.agent.md +496 -496
  103. package/templates/.github/agents/ux-designer.agent.md +393 -393
  104. package/templates/mcp.json.example +4 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Configuration Tests
3
+ *
4
+ * Tests for configuration loading and parsing.
5
+ */
6
+ import { describe, it, beforeEach, afterEach } from 'node:test';
7
+ import assert from 'node:assert';
8
+ import { parseDotEnv, ConfigError, loadConfig } from './config.js';
9
+ describe('parseDotEnv', () => {
10
+ describe('basic parsing', () => {
11
+ it('should parse KEY=VALUE pairs', () => {
12
+ const content = 'KEY=value';
13
+ const result = parseDotEnv(content);
14
+ assert.deepStrictEqual(result, { KEY: 'value' });
15
+ });
16
+ it('should parse multiple KEY=VALUE pairs', () => {
17
+ const content = `
18
+ KEY1=value1
19
+ KEY2=value2
20
+ KEY3=value3
21
+ `.trim();
22
+ const result = parseDotEnv(content);
23
+ assert.deepStrictEqual(result, {
24
+ KEY1: 'value1',
25
+ KEY2: 'value2',
26
+ KEY3: 'value3',
27
+ });
28
+ });
29
+ it('should preserve case of keys and values', () => {
30
+ const content = 'MyKey=MyValue';
31
+ const result = parseDotEnv(content);
32
+ assert.deepStrictEqual(result, { MyKey: 'MyValue' });
33
+ });
34
+ });
35
+ describe('comments', () => {
36
+ it('should skip lines starting with #', () => {
37
+ const content = `
38
+ # This is a comment
39
+ KEY=value
40
+ # Another comment
41
+ `.trim();
42
+ const result = parseDotEnv(content);
43
+ assert.deepStrictEqual(result, { KEY: 'value' });
44
+ });
45
+ it('should handle comments with leading whitespace', () => {
46
+ const content = ` # Comment with spaces
47
+ KEY=value`;
48
+ const result = parseDotEnv(content);
49
+ assert.deepStrictEqual(result, { KEY: 'value' });
50
+ });
51
+ });
52
+ describe('empty lines', () => {
53
+ it('should skip empty lines', () => {
54
+ const content = `
55
+ KEY1=value1
56
+
57
+ KEY2=value2
58
+
59
+ `;
60
+ const result = parseDotEnv(content);
61
+ assert.deepStrictEqual(result, { KEY1: 'value1', KEY2: 'value2' });
62
+ });
63
+ it('should handle lines with only whitespace', () => {
64
+ const content = `KEY1=value1
65
+
66
+ KEY2=value2`;
67
+ const result = parseDotEnv(content);
68
+ assert.deepStrictEqual(result, { KEY1: 'value1', KEY2: 'value2' });
69
+ });
70
+ });
71
+ describe('quoted values', () => {
72
+ it('should handle double quoted values', () => {
73
+ const content = 'KEY="hello world"';
74
+ const result = parseDotEnv(content);
75
+ assert.deepStrictEqual(result, { KEY: 'hello world' });
76
+ });
77
+ it('should handle single quoted values', () => {
78
+ const content = "KEY='hello world'";
79
+ const result = parseDotEnv(content);
80
+ assert.deepStrictEqual(result, { KEY: 'hello world' });
81
+ });
82
+ it('should remove only outer quotes', () => {
83
+ const content = 'KEY="value with \\"nested\\" quotes"';
84
+ const result = parseDotEnv(content);
85
+ // The outer quotes are removed, inner content preserved
86
+ assert.strictEqual(result.KEY, 'value with \\"nested\\" quotes');
87
+ });
88
+ it('should not remove quotes if not matching', () => {
89
+ const content = 'KEY="unmatched';
90
+ const result = parseDotEnv(content);
91
+ assert.strictEqual(result.KEY, '"unmatched');
92
+ });
93
+ });
94
+ describe('values containing = characters', () => {
95
+ it('should handle values with = sign', () => {
96
+ const content = 'URL=https://example.com?param=value';
97
+ const result = parseDotEnv(content);
98
+ assert.deepStrictEqual(result, { URL: 'https://example.com?param=value' });
99
+ });
100
+ it('should handle multiple = signs in value', () => {
101
+ const content = 'EQUATION=a=b=c=d';
102
+ const result = parseDotEnv(content);
103
+ assert.deepStrictEqual(result, { EQUATION: 'a=b=c=d' });
104
+ });
105
+ it('should handle base64 encoded values', () => {
106
+ const content = 'SECRET=dGVzdA==';
107
+ const result = parseDotEnv(content);
108
+ assert.deepStrictEqual(result, { SECRET: 'dGVzdA==' });
109
+ });
110
+ });
111
+ describe('empty keys', () => {
112
+ it('should skip lines with empty keys', () => {
113
+ const content = `=value
114
+ KEY=actual`;
115
+ const result = parseDotEnv(content);
116
+ assert.deepStrictEqual(result, { KEY: 'actual' });
117
+ });
118
+ it('should skip lines where key becomes empty after trim', () => {
119
+ const content = ` =value
120
+ KEY=actual`;
121
+ const result = parseDotEnv(content);
122
+ assert.deepStrictEqual(result, { KEY: 'actual' });
123
+ });
124
+ });
125
+ describe('lines without =', () => {
126
+ it('should skip lines without = character', () => {
127
+ const content = `invalid line
128
+ KEY=value`;
129
+ const result = parseDotEnv(content);
130
+ assert.deepStrictEqual(result, { KEY: 'value' });
131
+ });
132
+ it('should handle all invalid lines', () => {
133
+ const content = `line1
134
+ line2
135
+ line3`;
136
+ const result = parseDotEnv(content);
137
+ assert.deepStrictEqual(result, {});
138
+ });
139
+ });
140
+ describe('whitespace handling', () => {
141
+ it('should trim keys', () => {
142
+ const content = ' KEY =value';
143
+ const result = parseDotEnv(content);
144
+ assert.deepStrictEqual(result, { KEY: 'value' });
145
+ });
146
+ it('should trim values', () => {
147
+ const content = 'KEY= value ';
148
+ const result = parseDotEnv(content);
149
+ assert.deepStrictEqual(result, { KEY: 'value' });
150
+ });
151
+ it('should handle Windows line endings (CRLF)', () => {
152
+ const content = 'KEY1=value1\r\nKEY2=value2';
153
+ const result = parseDotEnv(content);
154
+ assert.deepStrictEqual(result, { KEY1: 'value1', KEY2: 'value2' });
155
+ });
156
+ });
157
+ describe('empty content', () => {
158
+ it('should return empty object for empty string', () => {
159
+ const result = parseDotEnv('');
160
+ assert.deepStrictEqual(result, {});
161
+ });
162
+ it('should return empty object for only whitespace/comments', () => {
163
+ const content = `
164
+ # Only comments
165
+
166
+ # More comments
167
+ `;
168
+ const result = parseDotEnv(content);
169
+ assert.deepStrictEqual(result, {});
170
+ });
171
+ });
172
+ describe('empty values', () => {
173
+ it('should allow empty values', () => {
174
+ const content = 'KEY=';
175
+ const result = parseDotEnv(content);
176
+ assert.deepStrictEqual(result, { KEY: '' });
177
+ });
178
+ });
179
+ });
180
+ describe('ConfigError', () => {
181
+ describe('constructor', () => {
182
+ it('should create message with field list', () => {
183
+ const error = new ConfigError(['FIELD1', 'FIELD2']);
184
+ assert.ok(error.message.includes('FIELD1'));
185
+ assert.ok(error.message.includes('FIELD2'));
186
+ });
187
+ it('should include "Missing required configuration" in message', () => {
188
+ const error = new ConfigError(['MY_FIELD']);
189
+ assert.ok(error.message.includes('Missing required configuration'));
190
+ });
191
+ it('should set missingFields property correctly', () => {
192
+ const fields = ['AZURE_OPENAI_ENDPOINT', 'AZURE_OPENAI_DEPLOYMENT'];
193
+ const error = new ConfigError(fields);
194
+ assert.deepStrictEqual(error.missingFields, fields);
195
+ });
196
+ it('should set name to "ConfigError"', () => {
197
+ const error = new ConfigError(['FIELD']);
198
+ assert.strictEqual(error.name, 'ConfigError');
199
+ });
200
+ it('should inherit from Error', () => {
201
+ const error = new ConfigError(['FIELD']);
202
+ assert.ok(error instanceof Error);
203
+ assert.ok(error instanceof ConfigError);
204
+ });
205
+ it('should have a stack trace', () => {
206
+ const error = new ConfigError(['FIELD']);
207
+ assert.ok(typeof error.stack === 'string');
208
+ assert.ok(error.stack.length > 0);
209
+ });
210
+ it('should handle single field', () => {
211
+ const error = new ConfigError(['SINGLE_FIELD']);
212
+ assert.strictEqual(error.missingFields.length, 1);
213
+ assert.strictEqual(error.missingFields[0], 'SINGLE_FIELD');
214
+ });
215
+ it('should handle multiple fields', () => {
216
+ const fields = ['FIELD1', 'FIELD2', 'FIELD3'];
217
+ const error = new ConfigError(fields);
218
+ assert.strictEqual(error.missingFields.length, 3);
219
+ });
220
+ it('should include Entra ID hint in message', () => {
221
+ const error = new ConfigError(['FIELD']);
222
+ assert.ok(error.message.includes('Entra ID') || error.message.includes('az login'), 'Should mention Entra ID or az login');
223
+ });
224
+ });
225
+ });
226
+ describe('loadConfig', () => {
227
+ // Store original env vars
228
+ const originalEnv = {};
229
+ const envKeys = [
230
+ 'AZURE_OPENAI_ENDPOINT',
231
+ 'AZURE_OPENAI_DEPLOYMENT',
232
+ 'AZURE_OPENAI_API_VERSION',
233
+ ];
234
+ beforeEach(() => {
235
+ // Save original values
236
+ for (const key of envKeys) {
237
+ originalEnv[key] = process.env[key];
238
+ }
239
+ // Clear all env vars for clean test state
240
+ for (const key of envKeys) {
241
+ delete process.env[key];
242
+ }
243
+ });
244
+ afterEach(() => {
245
+ // Restore original values
246
+ for (const key of envKeys) {
247
+ if (originalEnv[key] !== undefined) {
248
+ process.env[key] = originalEnv[key];
249
+ }
250
+ else {
251
+ delete process.env[key];
252
+ }
253
+ }
254
+ });
255
+ // Mock credential that satisfies TokenCredential interface
256
+ const mockCredential = {
257
+ getToken: async () => ({ token: 'mock-token', expiresOnTimestamp: Date.now() + 3600000 }),
258
+ };
259
+ describe('successful configuration', () => {
260
+ it('should return config when all required env vars are set', () => {
261
+ process.env.AZURE_OPENAI_ENDPOINT = 'https://test.openai.azure.com';
262
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
263
+ const config = loadConfig(mockCredential);
264
+ assert.strictEqual(config.endpoint, 'https://test.openai.azure.com');
265
+ assert.strictEqual(config.deployment, 'gpt-4');
266
+ });
267
+ it('should use default API version when not specified', () => {
268
+ process.env.AZURE_OPENAI_ENDPOINT = 'https://test.openai.azure.com';
269
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
270
+ const config = loadConfig(mockCredential);
271
+ assert.strictEqual(config.apiVersion, '2024-12-01-preview');
272
+ });
273
+ it('should use custom API version when AZURE_OPENAI_API_VERSION is set', () => {
274
+ process.env.AZURE_OPENAI_ENDPOINT = 'https://test.openai.azure.com';
275
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
276
+ process.env.AZURE_OPENAI_API_VERSION = '2025-01-01';
277
+ const config = loadConfig(mockCredential);
278
+ assert.strictEqual(config.apiVersion, '2025-01-01');
279
+ });
280
+ it('should accept custom TokenCredential', () => {
281
+ process.env.AZURE_OPENAI_ENDPOINT = 'https://test.openai.azure.com';
282
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
283
+ const customCredential = {
284
+ getToken: async () => ({ token: 'custom-token', expiresOnTimestamp: Date.now() + 1000 }),
285
+ };
286
+ const config = loadConfig(customCredential);
287
+ assert.strictEqual(config.credential, customCredential);
288
+ });
289
+ it('should include credential in returned config', () => {
290
+ process.env.AZURE_OPENAI_ENDPOINT = 'https://test.openai.azure.com';
291
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
292
+ const config = loadConfig(mockCredential);
293
+ assert.ok(config.credential);
294
+ assert.strictEqual(config.credential, mockCredential);
295
+ });
296
+ });
297
+ describe('missing required fields', () => {
298
+ it('should throw ConfigError when AZURE_OPENAI_ENDPOINT is missing', () => {
299
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
300
+ // AZURE_OPENAI_ENDPOINT not set
301
+ assert.throws(() => loadConfig(mockCredential), (error) => {
302
+ assert.ok(error instanceof ConfigError);
303
+ assert.ok(error.missingFields.includes('AZURE_OPENAI_ENDPOINT'));
304
+ return true;
305
+ });
306
+ });
307
+ it('should throw ConfigError when AZURE_OPENAI_DEPLOYMENT is missing', () => {
308
+ process.env.AZURE_OPENAI_ENDPOINT = 'https://test.openai.azure.com';
309
+ // AZURE_OPENAI_DEPLOYMENT not set
310
+ assert.throws(() => loadConfig(mockCredential), (error) => {
311
+ assert.ok(error instanceof ConfigError);
312
+ assert.ok(error.missingFields.includes('AZURE_OPENAI_DEPLOYMENT'));
313
+ return true;
314
+ });
315
+ });
316
+ it('should throw ConfigError with both fields when both are missing', () => {
317
+ // Neither env var set
318
+ assert.throws(() => loadConfig(mockCredential), (error) => {
319
+ assert.ok(error instanceof ConfigError);
320
+ assert.ok(error.missingFields.includes('AZURE_OPENAI_ENDPOINT'));
321
+ assert.ok(error.missingFields.includes('AZURE_OPENAI_DEPLOYMENT'));
322
+ assert.strictEqual(error.missingFields.length, 2);
323
+ return true;
324
+ });
325
+ });
326
+ });
327
+ describe('invalid URL format', () => {
328
+ it('should throw ConfigError when endpoint is invalid URL', () => {
329
+ process.env.AZURE_OPENAI_ENDPOINT = 'not-a-valid-url';
330
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
331
+ assert.throws(() => loadConfig(mockCredential), (error) => {
332
+ assert.ok(error instanceof ConfigError);
333
+ assert.ok(error.missingFields.some((f) => f.includes('invalid URL')), `Expected invalid URL error, got: ${error.missingFields}`);
334
+ return true;
335
+ });
336
+ });
337
+ it('should throw ConfigError when endpoint is empty', () => {
338
+ process.env.AZURE_OPENAI_ENDPOINT = '';
339
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
340
+ assert.throws(() => loadConfig(mockCredential), (error) => {
341
+ assert.ok(error instanceof ConfigError);
342
+ return true;
343
+ });
344
+ });
345
+ it('should accept valid HTTP URL', () => {
346
+ process.env.AZURE_OPENAI_ENDPOINT = 'http://localhost:8080';
347
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
348
+ const config = loadConfig(mockCredential);
349
+ assert.strictEqual(config.endpoint, 'http://localhost:8080');
350
+ });
351
+ it('should accept valid HTTPS URL', () => {
352
+ process.env.AZURE_OPENAI_ENDPOINT = 'https://my-resource.openai.azure.com';
353
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
354
+ const config = loadConfig(mockCredential);
355
+ assert.strictEqual(config.endpoint, 'https://my-resource.openai.azure.com');
356
+ });
357
+ });
358
+ describe('credential handling', () => {
359
+ it('should use provided credential instead of DefaultAzureCredential', () => {
360
+ process.env.AZURE_OPENAI_ENDPOINT = 'https://test.openai.azure.com';
361
+ process.env.AZURE_OPENAI_DEPLOYMENT = 'gpt-4';
362
+ const config = loadConfig(mockCredential);
363
+ assert.strictEqual(config.credential, mockCredential);
364
+ });
365
+ // Note: We don't test DefaultAzureCredential creation here as it would require
366
+ // actual Azure auth infrastructure. The function creates it when no credential
367
+ // is provided, but testing that path would need integration tests.
368
+ });
369
+ });
370
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/providers/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * LLM Provider Module
3
+ *
4
+ * Barrel exports for the LLM provider abstraction layer.
5
+ * Provides Azure OpenAI integration with Entra ID authentication.
6
+ */
7
+ export type { LLMErrorCode, ChatRole, ToolCallFunction, ToolCall, ChatMessage, FinishReason, ToolCallDelta, ChatChunk, JSONSchema, ToolFunctionDefinition, ToolDefinition, LLMProvider, LLMConfig, TokenUsage, LLMResponseChoice, LLMResponse, } from './types.js';
8
+ export { LLMError } from './types.js';
9
+ export type { ChatRequestOptions, ProviderFactory, ProviderRegistry, } from './interface.js';
10
+ export { LLMProviderBase } from './interface.js';
11
+ export type { RetryOptions } from './retry.js';
12
+ export { RetryError, calculateDelay, isTransientError, retry, } from './retry.js';
13
+ export type { CollectedStreamResult } from './streaming.js';
14
+ export { StreamAccumulator, collectStream, mapStream, } from './streaming.js';
15
+ export type { ProviderConfig } from './config.js';
16
+ export { ConfigError, parseDotEnv, loadConfig, } from './config.js';
17
+ export { AzureOpenAIProvider } from './azure.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,aAAa,EACb,SAAS,EACT,UAAU,EACV,sBAAsB,EACtB,cAAc,EACd,WAAW,EACX,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EACL,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,KAAK,GACN,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,SAAS,GACV,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EACL,WAAW,EACX,WAAW,EACX,UAAU,GACX,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * LLM Provider Module
3
+ *
4
+ * Barrel exports for the LLM provider abstraction layer.
5
+ * Provides Azure OpenAI integration with Entra ID authentication.
6
+ */
7
+ export { LLMError } from './types.js';
8
+ export { LLMProviderBase } from './interface.js';
9
+ export { RetryError, calculateDelay, isTransientError, retry, } from './retry.js';
10
+ export { StreamAccumulator, collectStream, mapStream, } from './streaming.js';
11
+ export { ConfigError, parseDotEnv, loadConfig, } from './config.js';
12
+ // Azure OpenAI Provider
13
+ export { AzureOpenAIProvider } from './azure.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAStC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKjD,OAAO,EACL,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,KAAK,GACN,MAAM,YAAY,CAAC;AAKpB,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,SAAS,GACV,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EACL,WAAW,EACX,WAAW,EACX,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,wBAAwB;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * LLM Provider Interface
3
+ *
4
+ * Abstract base class and interfaces for LLM provider implementations.
5
+ * Designed to be provider-agnostic, enabling support for Azure OpenAI,
6
+ * Claude, Ollama, and other providers.
7
+ */
8
+ import type { ChatMessage, ChatChunk, ToolDefinition, LLMResponse, LLMConfig } from './types.js';
9
+ /**
10
+ * Options for a chat completion request.
11
+ *
12
+ * These options allow overriding the provider's default configuration
13
+ * on a per-request basis. All fields are optional.
14
+ */
15
+ export interface ChatRequestOptions {
16
+ /** Tool definitions for function calling */
17
+ tools?: ToolDefinition[];
18
+ /** Sampling temperature (0-2). Higher = more creative, lower = more deterministic */
19
+ temperature?: number;
20
+ /** Maximum tokens to generate in the completion */
21
+ maxTokens?: number;
22
+ /** Top-p (nucleus) sampling. Only sample from tokens comprising top-p probability mass */
23
+ topP?: number;
24
+ /** Frequency penalty (-2 to 2). Reduces repetition based on token frequency */
25
+ frequencyPenalty?: number;
26
+ /** Presence penalty (-2 to 2). Reduces repetition based on token presence */
27
+ presencePenalty?: number;
28
+ /** AbortSignal for request cancellation */
29
+ signal?: AbortSignal;
30
+ }
31
+ /**
32
+ * Abstract base class for LLM provider implementations.
33
+ *
34
+ * Provides a unified interface for interacting with different LLM providers.
35
+ * Concrete implementations handle provider-specific API details while
36
+ * conforming to this common contract.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * class AzureOpenAIProvider extends LLMProviderBase {
41
+ * get name() { return 'azure-openai'; }
42
+ * get isConfigured() { return !!this.config.apiKey; }
43
+ *
44
+ * async chat(messages, options) {
45
+ * // Azure-specific implementation
46
+ * }
47
+ *
48
+ * async *chatStream(messages, options) {
49
+ * // Azure-specific streaming implementation
50
+ * }
51
+ *
52
+ * async countTokens(messages) {
53
+ * // Token counting implementation
54
+ * }
55
+ * }
56
+ * ```
57
+ */
58
+ export declare abstract class LLMProviderBase {
59
+ /** Provider configuration */
60
+ protected readonly config: LLMConfig;
61
+ /**
62
+ * Create a new provider instance.
63
+ *
64
+ * @param config - Provider configuration including credentials and model settings
65
+ */
66
+ constructor(config: LLMConfig);
67
+ /**
68
+ * Unique identifier for this provider.
69
+ *
70
+ * Used for logging, error messages, and provider selection.
71
+ *
72
+ * @example 'azure-openai', 'claude', 'ollama'
73
+ */
74
+ abstract get name(): string;
75
+ /**
76
+ * Check if the provider has valid configuration.
77
+ *
78
+ * Returns true if all required configuration fields are present
79
+ * and properly formatted. Does not validate credentials with the API.
80
+ */
81
+ abstract get isConfigured(): boolean;
82
+ /**
83
+ * Send a non-streaming chat completion request.
84
+ *
85
+ * Sends the conversation history to the LLM and returns the complete
86
+ * response when generation finishes. Use this for simple request/response
87
+ * patterns where streaming is not needed.
88
+ *
89
+ * @param messages - Conversation history as an array of chat messages
90
+ * @param options - Optional request configuration overrides
91
+ * @returns The complete LLM response including message and usage stats
92
+ * @throws {LLMError} On API errors (rate limit, auth, network, etc.)
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * const response = await provider.chat([
97
+ * { role: 'system', content: 'You are a helpful assistant.' },
98
+ * { role: 'user', content: 'Hello!' }
99
+ * ]);
100
+ * console.log(response.choices[0].message.content);
101
+ * ```
102
+ */
103
+ abstract chat(messages: ChatMessage[], options?: ChatRequestOptions): Promise<LLMResponse>;
104
+ /**
105
+ * Send a streaming chat completion request.
106
+ *
107
+ * Sends the conversation history to the LLM and yields response chunks
108
+ * as they are generated. Use this for real-time output display or
109
+ * when handling large responses.
110
+ *
111
+ * @param messages - Conversation history as an array of chat messages
112
+ * @param options - Optional request configuration overrides
113
+ * @yields ChatChunk objects containing incremental response content
114
+ * @throws {LLMError} On API errors (rate limit, auth, network, etc.)
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const stream = provider.chatStream([
119
+ * { role: 'user', content: 'Write a poem' }
120
+ * ]);
121
+ *
122
+ * for await (const chunk of stream) {
123
+ * if (chunk.content) {
124
+ * process.stdout.write(chunk.content);
125
+ * }
126
+ * }
127
+ * ```
128
+ */
129
+ abstract chatStream(messages: ChatMessage[], options?: ChatRequestOptions): AsyncGenerator<ChatChunk, void, undefined>;
130
+ /**
131
+ * Count the number of tokens in a message array.
132
+ *
133
+ * Estimates token usage before sending a request. Useful for:
134
+ * - Checking if messages fit within context limits
135
+ * - Managing conversation history (trimming old messages)
136
+ * - Cost estimation
137
+ *
138
+ * Note: Token counting is model-specific. The implementation should
139
+ * use the appropriate tokenizer for the configured model.
140
+ *
141
+ * @param messages - Messages to count tokens for
142
+ * @returns Estimated token count
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const count = await provider.countTokens(messages);
147
+ * if (count > 100000) {
148
+ * // Trim conversation history
149
+ * }
150
+ * ```
151
+ */
152
+ abstract countTokens(messages: ChatMessage[]): Promise<number>;
153
+ /**
154
+ * Get the configured model name or deployment.
155
+ *
156
+ * Returns the model specified in the provider configuration.
157
+ */
158
+ get model(): string;
159
+ /**
160
+ * Get a redacted summary of the configuration for logging.
161
+ *
162
+ * Returns configuration information safe for logging, with
163
+ * sensitive values (endpoints) masked. Credential type is shown
164
+ * but no secrets are exposed.
165
+ */
166
+ getConfigSummary(): Record<string, string>;
167
+ /**
168
+ * Mask an endpoint URL for safe logging.
169
+ *
170
+ * Preserves the host but masks path segments to avoid leaking
171
+ * deployment names or resource identifiers.
172
+ *
173
+ * @param endpoint - Full endpoint URL
174
+ * @returns Masked endpoint safe for logging
175
+ */
176
+ private maskEndpoint;
177
+ }
178
+ /**
179
+ * Factory function type for creating provider instances.
180
+ *
181
+ * Used by the provider registry to instantiate providers from configuration.
182
+ */
183
+ export type ProviderFactory = (config: LLMConfig) => LLMProviderBase;
184
+ /**
185
+ * Registry of available provider factories.
186
+ *
187
+ * Maps provider names to their factory functions, enabling
188
+ * dynamic provider instantiation based on configuration.
189
+ */
190
+ export type ProviderRegistry = Map<string, ProviderFactory>;
191
+ //# sourceMappingURL=interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/providers/interface.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,cAAc,EACd,WAAW,EACX,SAAS,EACV,MAAM,YAAY,CAAC;AAMpB;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,4CAA4C;IAC5C,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IAEzB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,8BAAsB,eAAe;IACnC,6BAA6B;IAC7B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAErC;;;;OAIG;gBACS,MAAM,EAAE,SAAS;IAQ7B;;;;;;OAMG;IACH,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC;IAE5B;;;;;OAKG;IACH,QAAQ,KAAK,YAAY,IAAI,OAAO,CAAC;IAMrC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,IAAI,CACX,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,WAAW,CAAC;IAEvB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,UAAU,CACjB,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC;IAE7C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAM9D;;;;OAIG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;;;;;OAMG;IACH,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAS1C;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;CAQrB;AAMD;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,eAAe,CAAC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC"}