lynkr 4.0.0 → 4.2.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.
- package/README.md +276 -2873
- package/documentation/README.md +98 -0
- package/documentation/api.md +806 -0
- package/documentation/claude-code-cli.md +672 -0
- package/documentation/contributing.md +571 -0
- package/documentation/cursor-integration.md +731 -0
- package/documentation/docker.md +867 -0
- package/documentation/embeddings.md +760 -0
- package/documentation/faq.md +659 -0
- package/documentation/features.md +396 -0
- package/documentation/installation.md +706 -0
- package/documentation/memory-system.md +476 -0
- package/documentation/production.md +601 -0
- package/documentation/providers.md +735 -0
- package/documentation/testing.md +629 -0
- package/documentation/token-optimization.md +323 -0
- package/documentation/tools.md +697 -0
- package/documentation/troubleshooting.md +864 -0
- package/package.json +1 -1
- package/src/api/openai-router.js +393 -42
- package/src/api/router.js +172 -22
- package/src/clients/databricks.js +82 -7
- package/src/clients/openai-format.js +48 -12
- package/src/clients/openrouter-utils.js +15 -5
- package/src/clients/responses-format.js +214 -0
- package/src/clients/standard-tools.js +4 -4
- package/src/orchestrator/index.js +32 -0
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
# Contributing Guide
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to Lynkr! This guide will help you get started.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Ways to Contribute
|
|
8
|
+
|
|
9
|
+
### 1. Report Bugs
|
|
10
|
+
|
|
11
|
+
Found a bug? Please report it:
|
|
12
|
+
|
|
13
|
+
1. **Search [existing issues](https://github.com/vishalveerareddy123/Lynkr/issues)** first
|
|
14
|
+
2. **Create a new issue** with:
|
|
15
|
+
- Lynkr version
|
|
16
|
+
- Provider being used
|
|
17
|
+
- Steps to reproduce
|
|
18
|
+
- Expected vs actual behavior
|
|
19
|
+
- Error messages and logs
|
|
20
|
+
- Environment details (OS, Node version)
|
|
21
|
+
|
|
22
|
+
### 2. Suggest Features
|
|
23
|
+
|
|
24
|
+
Have an idea for a new feature?
|
|
25
|
+
|
|
26
|
+
1. **Search [GitHub Discussions](https://github.com/vishalveerareddy123/Lynkr/discussions)** first
|
|
27
|
+
2. **Create a discussion** describing:
|
|
28
|
+
- The problem you're solving
|
|
29
|
+
- Proposed solution
|
|
30
|
+
- Use cases
|
|
31
|
+
- Alternatives considered
|
|
32
|
+
|
|
33
|
+
### 3. Improve Documentation
|
|
34
|
+
|
|
35
|
+
Documentation improvements are always welcome:
|
|
36
|
+
|
|
37
|
+
- Fix typos or unclear wording
|
|
38
|
+
- Add examples
|
|
39
|
+
- Expand explanations
|
|
40
|
+
- Add troubleshooting steps
|
|
41
|
+
- Translate documentation
|
|
42
|
+
|
|
43
|
+
### 4. Submit Code
|
|
44
|
+
|
|
45
|
+
Contributing code? Follow these steps:
|
|
46
|
+
|
|
47
|
+
1. **Fork the repository**
|
|
48
|
+
2. **Create a feature branch**: `git checkout -b feature/your-feature-name`
|
|
49
|
+
3. **Make your changes**
|
|
50
|
+
4. **Add tests** for new functionality
|
|
51
|
+
5. **Run tests**: `npm test`
|
|
52
|
+
6. **Commit with descriptive message**
|
|
53
|
+
7. **Push to your fork**
|
|
54
|
+
8. **Create a Pull Request**
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Development Setup
|
|
59
|
+
|
|
60
|
+
### Prerequisites
|
|
61
|
+
|
|
62
|
+
- **Node.js 18+**
|
|
63
|
+
- **npm** or **yarn**
|
|
64
|
+
- **Git**
|
|
65
|
+
- Optional: **Docker** for testing containerized deployment
|
|
66
|
+
|
|
67
|
+
### Clone and Install
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Fork the repo on GitHub first, then:
|
|
71
|
+
git clone https://github.com/YOUR_USERNAME/Lynkr.git
|
|
72
|
+
cd Lynkr
|
|
73
|
+
|
|
74
|
+
# Install dependencies
|
|
75
|
+
npm install
|
|
76
|
+
|
|
77
|
+
# Copy environment template
|
|
78
|
+
cp .env.example .env
|
|
79
|
+
|
|
80
|
+
# Edit .env with your test credentials
|
|
81
|
+
nano .env
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Run in Development Mode
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Auto-restart on file changes
|
|
88
|
+
npm run dev
|
|
89
|
+
|
|
90
|
+
# Or normal mode
|
|
91
|
+
npm start
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Run Tests
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Run all tests
|
|
98
|
+
npm test
|
|
99
|
+
|
|
100
|
+
# Run specific test file
|
|
101
|
+
npm test test/config.test.js
|
|
102
|
+
|
|
103
|
+
# Run with coverage
|
|
104
|
+
npm run test:coverage
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Code Style
|
|
110
|
+
|
|
111
|
+
### General Guidelines
|
|
112
|
+
|
|
113
|
+
- **Use modern JavaScript** (ES6+)
|
|
114
|
+
- **Follow existing code style** (2-space indentation)
|
|
115
|
+
- **Add comments** for complex logic
|
|
116
|
+
- **Write descriptive variable names**
|
|
117
|
+
- **Keep functions small and focused**
|
|
118
|
+
|
|
119
|
+
### File Organization
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
src/
|
|
123
|
+
├── api/ # Express routes and middleware
|
|
124
|
+
├── clients/ # Provider client implementations
|
|
125
|
+
├── config/ # Configuration loading and validation
|
|
126
|
+
├── orchestrator/ # Agent loop and tool execution
|
|
127
|
+
├── tools/ # Tool implementations
|
|
128
|
+
├── cache/ # Caching layer
|
|
129
|
+
├── observability/ # Metrics and logging
|
|
130
|
+
├── db/ # Database operations
|
|
131
|
+
└── mcp/ # Model Context Protocol integration
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Naming Conventions
|
|
135
|
+
|
|
136
|
+
- **Files**: `kebab-case.js` (e.g., `prompt-cache.js`)
|
|
137
|
+
- **Functions**: `camelCase` (e.g., `invokeModel()`)
|
|
138
|
+
- **Constants**: `UPPER_SNAKE_CASE` (e.g., `DEFAULT_PORT`)
|
|
139
|
+
- **Classes**: `PascalCase` (e.g., `CircuitBreaker`)
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Testing Guidelines
|
|
144
|
+
|
|
145
|
+
### Writing Tests
|
|
146
|
+
|
|
147
|
+
Use Node.js built-in test runner:
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
const assert = require("assert");
|
|
151
|
+
const { describe, it, beforeEach, afterEach } = require("node:test");
|
|
152
|
+
|
|
153
|
+
describe("Feature name", () => {
|
|
154
|
+
beforeEach(() => {
|
|
155
|
+
// Setup
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
afterEach(() => {
|
|
159
|
+
// Cleanup
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("should do something specific", () => {
|
|
163
|
+
// Arrange
|
|
164
|
+
const input = "test";
|
|
165
|
+
|
|
166
|
+
// Act
|
|
167
|
+
const result = myFunction(input);
|
|
168
|
+
|
|
169
|
+
// Assert
|
|
170
|
+
assert.strictEqual(result, "expected");
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Test Coverage
|
|
176
|
+
|
|
177
|
+
- **Aim for 80%+ coverage** for new code
|
|
178
|
+
- **Test edge cases** and error conditions
|
|
179
|
+
- **Mock external dependencies** (API calls, file system)
|
|
180
|
+
- **Test happy paths** and failure scenarios
|
|
181
|
+
|
|
182
|
+
### Running Tests
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# All tests
|
|
186
|
+
npm test
|
|
187
|
+
|
|
188
|
+
# Specific file
|
|
189
|
+
npm test test/config.test.js
|
|
190
|
+
|
|
191
|
+
# With coverage
|
|
192
|
+
npm run test:coverage
|
|
193
|
+
|
|
194
|
+
# Watch mode (runs on file changes)
|
|
195
|
+
npm run test:watch
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Pull Request Process
|
|
201
|
+
|
|
202
|
+
### Before Submitting
|
|
203
|
+
|
|
204
|
+
1. **Ensure tests pass**: `npm test`
|
|
205
|
+
2. **Check code style**: Follow existing conventions
|
|
206
|
+
3. **Update documentation** if needed
|
|
207
|
+
4. **Add test coverage** for new features
|
|
208
|
+
5. **Rebase on latest main**: `git rebase origin/main`
|
|
209
|
+
|
|
210
|
+
### PR Template
|
|
211
|
+
|
|
212
|
+
When creating a pull request, include:
|
|
213
|
+
|
|
214
|
+
```markdown
|
|
215
|
+
## Description
|
|
216
|
+
Brief description of the changes
|
|
217
|
+
|
|
218
|
+
## Type of Change
|
|
219
|
+
- [ ] Bug fix
|
|
220
|
+
- [ ] New feature
|
|
221
|
+
- [ ] Documentation update
|
|
222
|
+
- [ ] Performance improvement
|
|
223
|
+
- [ ] Refactoring
|
|
224
|
+
|
|
225
|
+
## Changes Made
|
|
226
|
+
- Item 1
|
|
227
|
+
- Item 2
|
|
228
|
+
|
|
229
|
+
## Testing
|
|
230
|
+
- [ ] Existing tests pass
|
|
231
|
+
- [ ] Added new tests
|
|
232
|
+
- [ ] Manual testing performed
|
|
233
|
+
|
|
234
|
+
## Checklist
|
|
235
|
+
- [ ] Code follows style guidelines
|
|
236
|
+
- [ ] Documentation updated
|
|
237
|
+
- [ ] Tests added/updated
|
|
238
|
+
- [ ] No new warnings
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Review Process
|
|
242
|
+
|
|
243
|
+
1. **Maintainers will review** your PR
|
|
244
|
+
2. **Address feedback** if requested
|
|
245
|
+
3. **Make changes** in new commits
|
|
246
|
+
4. **Once approved**, maintainer will merge
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Adding a New Provider
|
|
251
|
+
|
|
252
|
+
To add support for a new LLM provider:
|
|
253
|
+
|
|
254
|
+
### 1. Update Configuration
|
|
255
|
+
|
|
256
|
+
**File**: `src/config/index.js`
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
// Add to SUPPORTED_MODEL_PROVIDERS
|
|
260
|
+
const SUPPORTED_MODEL_PROVIDERS = new Set([
|
|
261
|
+
"databricks", "azure-anthropic", "ollama",
|
|
262
|
+
"openrouter", "azure-openai", "openai",
|
|
263
|
+
"llamacpp", "lmstudio", "bedrock", "newprovider" // Add here
|
|
264
|
+
]);
|
|
265
|
+
|
|
266
|
+
// Parse environment variables
|
|
267
|
+
const newProviderApiKey = process.env.NEW_PROVIDER_API_KEY?.trim() || null;
|
|
268
|
+
const newProviderEndpoint = process.env.NEW_PROVIDER_ENDPOINT?.trim() || "https://api.newprovider.com";
|
|
269
|
+
|
|
270
|
+
// Add validation
|
|
271
|
+
if (modelProvider === "newprovider" && !newProviderApiKey) {
|
|
272
|
+
throw new Error("NEW_PROVIDER_API_KEY is required when MODEL_PROVIDER=newprovider");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Export config
|
|
276
|
+
module.exports = {
|
|
277
|
+
// ...
|
|
278
|
+
newProvider: {
|
|
279
|
+
apiKey: newProviderApiKey,
|
|
280
|
+
endpoint: newProviderEndpoint,
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 2. Implement Invocation Function
|
|
286
|
+
|
|
287
|
+
**File**: `src/clients/databricks.js`
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
/**
|
|
291
|
+
* Invoke new provider
|
|
292
|
+
* @param {Object} body - Anthropic-format request body
|
|
293
|
+
* @returns {Object} Response with json and actualProvider
|
|
294
|
+
*/
|
|
295
|
+
async function invokeNewProvider(body) {
|
|
296
|
+
// 1. Validate configuration
|
|
297
|
+
if (!config.newProvider?.apiKey) {
|
|
298
|
+
throw new Error("NEW_PROVIDER_API_KEY is required");
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// 2. Convert Anthropic format to provider format
|
|
302
|
+
const providerRequest = convertAnthropicToNewProviderFormat(body);
|
|
303
|
+
|
|
304
|
+
// 3. Make API request
|
|
305
|
+
const response = await fetch(config.newProvider.endpoint, {
|
|
306
|
+
method: "POST",
|
|
307
|
+
headers: {
|
|
308
|
+
"Content-Type": "application/json",
|
|
309
|
+
"Authorization": `Bearer ${config.newProvider.apiKey}`,
|
|
310
|
+
},
|
|
311
|
+
body: JSON.stringify(providerRequest),
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
if (!response.ok) {
|
|
315
|
+
throw new Error(`Provider API error: ${response.statusText}`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const data = await response.json();
|
|
319
|
+
|
|
320
|
+
// 4. Convert provider format back to Anthropic format
|
|
321
|
+
const anthropicResponse = convertNewProviderToAnthropicFormat(data);
|
|
322
|
+
|
|
323
|
+
return {
|
|
324
|
+
json: anthropicResponse,
|
|
325
|
+
actualProvider: "newprovider",
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Add to invokeModel switch
|
|
330
|
+
async function invokeModel(body, initialProvider) {
|
|
331
|
+
// ...
|
|
332
|
+
} else if (initialProvider === "newprovider") {
|
|
333
|
+
return await invokeNewProvider(body);
|
|
334
|
+
}
|
|
335
|
+
// ...
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### 3. Add Format Conversion
|
|
340
|
+
|
|
341
|
+
Create `src/clients/newprovider-utils.js`:
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
/**
|
|
345
|
+
* Convert Anthropic format to provider format
|
|
346
|
+
*/
|
|
347
|
+
function convertAnthropicToNewProviderFormat(body) {
|
|
348
|
+
return {
|
|
349
|
+
messages: convertMessages(body.messages),
|
|
350
|
+
max_tokens: body.max_tokens || 4096,
|
|
351
|
+
temperature: body.temperature || 0.7,
|
|
352
|
+
// ... provider-specific fields
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Convert provider format to Anthropic format
|
|
358
|
+
*/
|
|
359
|
+
function convertNewProviderToAnthropicFormat(response) {
|
|
360
|
+
return {
|
|
361
|
+
id: response.id || `msg_${Date.now()}`,
|
|
362
|
+
type: "message",
|
|
363
|
+
role: "assistant",
|
|
364
|
+
content: [
|
|
365
|
+
{
|
|
366
|
+
type: "text",
|
|
367
|
+
text: response.output || response.message || "",
|
|
368
|
+
},
|
|
369
|
+
],
|
|
370
|
+
model: response.model,
|
|
371
|
+
stop_reason: "end_turn",
|
|
372
|
+
usage: {
|
|
373
|
+
input_tokens: response.usage?.input || 0,
|
|
374
|
+
output_tokens: response.usage?.output || 0,
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
module.exports = {
|
|
380
|
+
convertAnthropicToNewProviderFormat,
|
|
381
|
+
convertNewProviderToAnthropicFormat,
|
|
382
|
+
};
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### 4. Add Tests
|
|
386
|
+
|
|
387
|
+
**File**: `test/newprovider-integration.test.js`
|
|
388
|
+
|
|
389
|
+
```javascript
|
|
390
|
+
const assert = require("assert");
|
|
391
|
+
const { describe, it, beforeEach, afterEach } = require("node:test");
|
|
392
|
+
|
|
393
|
+
describe("New Provider Integration", () => {
|
|
394
|
+
let originalEnv;
|
|
395
|
+
|
|
396
|
+
beforeEach(() => {
|
|
397
|
+
originalEnv = { ...process.env };
|
|
398
|
+
delete require.cache[require.resolve("../src/config")];
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
afterEach(() => {
|
|
402
|
+
process.env = originalEnv;
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it("should accept newprovider as MODEL_PROVIDER", () => {
|
|
406
|
+
process.env.MODEL_PROVIDER = "newprovider";
|
|
407
|
+
process.env.NEW_PROVIDER_API_KEY = "test-key";
|
|
408
|
+
|
|
409
|
+
const config = require("../src/config");
|
|
410
|
+
assert.strictEqual(config.modelProvider.type, "newprovider");
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it("should throw error when API key is missing", () => {
|
|
414
|
+
process.env.MODEL_PROVIDER = "newprovider";
|
|
415
|
+
delete process.env.NEW_PROVIDER_API_KEY;
|
|
416
|
+
|
|
417
|
+
assert.throws(
|
|
418
|
+
() => require("../src/config"),
|
|
419
|
+
/NEW_PROVIDER_API_KEY is required/
|
|
420
|
+
);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// Add more tests...
|
|
424
|
+
});
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### 5. Update Documentation
|
|
428
|
+
|
|
429
|
+
- Add provider to `documentation/providers.md`
|
|
430
|
+
- Add configuration example to `.env.example`
|
|
431
|
+
- Update README.md provider table
|
|
432
|
+
- Add quick start example
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Adding a New Tool
|
|
437
|
+
|
|
438
|
+
To add a new tool implementation:
|
|
439
|
+
|
|
440
|
+
### 1. Create Tool File
|
|
441
|
+
|
|
442
|
+
**File**: `src/tools/your-tool.js`
|
|
443
|
+
|
|
444
|
+
```javascript
|
|
445
|
+
const logger = require("../logger");
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Tool implementation
|
|
449
|
+
* @param {Object} input - Tool input parameters
|
|
450
|
+
* @param {Object} context - Execution context
|
|
451
|
+
* @returns {Object} Tool result
|
|
452
|
+
*/
|
|
453
|
+
async function yourTool(input, context) {
|
|
454
|
+
try {
|
|
455
|
+
// Validate input
|
|
456
|
+
if (!input.requiredParam) {
|
|
457
|
+
throw new Error("requiredParam is required");
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Execute tool logic
|
|
461
|
+
const result = await doSomething(input.requiredParam);
|
|
462
|
+
|
|
463
|
+
// Return result
|
|
464
|
+
return {
|
|
465
|
+
success: true,
|
|
466
|
+
data: result,
|
|
467
|
+
};
|
|
468
|
+
} catch (error) {
|
|
469
|
+
logger.error({ error, input }, "Tool execution failed");
|
|
470
|
+
throw error;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
module.exports = {
|
|
475
|
+
yourTool,
|
|
476
|
+
};
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### 2. Register Tool
|
|
480
|
+
|
|
481
|
+
**File**: `src/tools/index.js`
|
|
482
|
+
|
|
483
|
+
```javascript
|
|
484
|
+
const { yourTool } = require("./your-tool");
|
|
485
|
+
|
|
486
|
+
const STANDARD_TOOLS = [
|
|
487
|
+
// ... existing tools
|
|
488
|
+
{
|
|
489
|
+
name: "your_tool",
|
|
490
|
+
description: "Description of what your tool does",
|
|
491
|
+
input_schema: {
|
|
492
|
+
type: "object",
|
|
493
|
+
properties: {
|
|
494
|
+
requiredParam: {
|
|
495
|
+
type: "string",
|
|
496
|
+
description: "Description of parameter",
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
required: ["requiredParam"],
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
];
|
|
503
|
+
|
|
504
|
+
// Add to tool execution mapping
|
|
505
|
+
async function executeTool(toolName, toolInput, context) {
|
|
506
|
+
switch (toolName) {
|
|
507
|
+
// ... existing cases
|
|
508
|
+
case "your_tool":
|
|
509
|
+
return await yourTool(toolInput, context);
|
|
510
|
+
default:
|
|
511
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### 3. Add Tests
|
|
517
|
+
|
|
518
|
+
**File**: `test/tools/your-tool.test.js`
|
|
519
|
+
|
|
520
|
+
```javascript
|
|
521
|
+
const assert = require("assert");
|
|
522
|
+
const { describe, it } = require("node:test");
|
|
523
|
+
const { yourTool } = require("../../src/tools/your-tool");
|
|
524
|
+
|
|
525
|
+
describe("Your Tool", () => {
|
|
526
|
+
it("should execute successfully with valid input", async () => {
|
|
527
|
+
const result = await yourTool(
|
|
528
|
+
{ requiredParam: "test" },
|
|
529
|
+
{ workspaceRoot: "/tmp" }
|
|
530
|
+
);
|
|
531
|
+
|
|
532
|
+
assert.strictEqual(result.success, true);
|
|
533
|
+
assert.ok(result.data);
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it("should throw error with invalid input", async () => {
|
|
537
|
+
await assert.rejects(
|
|
538
|
+
() => yourTool({}, {}),
|
|
539
|
+
/requiredParam is required/
|
|
540
|
+
);
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
## Community Guidelines
|
|
548
|
+
|
|
549
|
+
### Code of Conduct
|
|
550
|
+
|
|
551
|
+
- **Be respectful** and inclusive
|
|
552
|
+
- **Welcome newcomers** and help them contribute
|
|
553
|
+
- **Provide constructive feedback**
|
|
554
|
+
- **Focus on the code**, not the person
|
|
555
|
+
- **Assume good intentions**
|
|
556
|
+
|
|
557
|
+
### Getting Help
|
|
558
|
+
|
|
559
|
+
- **[GitHub Discussions](https://github.com/vishalveerareddy123/Lynkr/discussions)** - Ask questions
|
|
560
|
+
- **[Discord](https://discord.gg/qF7DDxrX)** - Real-time chat
|
|
561
|
+
- **[Issues](https://github.com/vishalveerareddy123/Lynkr/issues)** - Report bugs
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## License
|
|
566
|
+
|
|
567
|
+
By contributing to Lynkr, you agree that your contributions will be licensed under the Apache 2.0 License.
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
Thank you for contributing to Lynkr! 🎉
|