matimo 0.1.0-alpha.1 → 0.1.0-alpha.3
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 +83 -28
- package/dist/core/schema.d.ts +1 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +8 -3
- package/dist/core/schema.js.map +1 -1
- package/dist/core/tool-loader.d.ts.map +1 -1
- package/dist/core/tool-loader.js +15 -4
- package/dist/core/tool-loader.js.map +1 -1
- package/dist/core/tool-registry.d.ts.map +1 -1
- package/dist/core/tool-registry.js +5 -1
- package/dist/core/tool-registry.js.map +1 -1
- package/dist/decorators/tool-decorator.d.ts.map +1 -1
- package/dist/decorators/tool-decorator.js +7 -4
- package/dist/decorators/tool-decorator.js.map +1 -1
- package/dist/encodings/parameter-encoding.d.ts.map +1 -1
- package/dist/encodings/parameter-encoding.js +9 -2
- package/dist/encodings/parameter-encoding.js.map +1 -1
- package/dist/executors/command-executor.d.ts.map +1 -1
- package/dist/executors/command-executor.js +5 -1
- package/dist/executors/command-executor.js.map +1 -1
- package/dist/executors/http-executor.d.ts.map +1 -1
- package/dist/executors/http-executor.js +5 -1
- package/dist/executors/http-executor.js.map +1 -1
- package/package.json +4 -4
- package/tools/calculator/calculator.ts +78 -0
- package/tools/calculator/definition.yaml +71 -0
- package/tools/echo-tool/definition.yaml +35 -0
- package/tools/examples/calculator.yaml +54 -0
- package/tools/examples/echo-tool.yaml +35 -0
- package/tools/examples/http-client.yaml +66 -0
- package/tools/github/definition.yaml +41 -0
- package/tools/gmail/README.md +1189 -0
- package/tools/gmail/create-draft/definition.yaml +99 -0
- package/tools/gmail/definition.yaml +49 -0
- package/tools/gmail/delete-message/definition.yaml +42 -0
- package/tools/gmail/get-message/definition.yaml +89 -0
- package/tools/gmail/list-messages/definition.yaml +84 -0
- package/tools/gmail/send-email/definition.yaml +95 -0
- package/tools/http-client/definition.yaml +73 -0
- package/tools/slack/README.md +200 -0
- package/tools/slack/assets/icon.svg +9 -0
- package/tools/slack/assets/logo-dark.svg +14 -0
- package/tools/slack/assets/logo-light.svg +14 -0
- package/tools/slack/assets/logo.svg +14 -0
- package/tools/slack/definition.yaml +54 -0
- package/tools/slack/get-user/definition.yaml +31 -0
- package/tools/slack/list-channels/definition.yaml +46 -0
- package/tools/slack/send-message/definition.yaml +30 -0
- package/tools/slack/slack_add_reaction/definition.yaml +45 -0
- package/tools/slack/slack_create_channel/definition.yaml +41 -0
- package/tools/slack/slack_get_channel_history/definition.yaml +58 -0
- package/tools/slack/slack_get_reactions/definition.yaml +36 -0
- package/tools/slack/slack_get_thread_replies/definition.yaml +45 -0
- package/tools/slack/slack_get_user_info/definition.yaml +32 -0
- package/tools/slack/slack_join_channel/definition.yaml +35 -0
- package/tools/slack/slack_reply_to_message/definition.yaml +49 -0
- package/tools/slack/slack_search_messages/definition.yaml +46 -0
- package/tools/slack/slack_send_channel_message/definition.yaml +34 -0
- package/tools/slack/slack_send_dm/definition.yaml +37 -0
- package/tools/slack/slack_set_channel_topic/definition.yaml +40 -0
- package/tools/slack/slack_upload_file/definition.yaml +152 -0
- package/docs/Gemfile +0 -5
- package/docs/RELEASES.md +0 -69
- package/docs/ROADMAP.md +0 -138
- package/docs/_config.yml +0 -27
- package/docs/api-reference/ERRORS.md +0 -445
- package/docs/api-reference/SDK.md +0 -582
- package/docs/api-reference/TYPES.md +0 -415
- package/docs/architecture/OAUTH.md +0 -1366
- package/docs/architecture/OVERVIEW.md +0 -564
- package/docs/assets/logo.png +0 -0
- package/docs/community/COMMIT_GUIDELINES.md +0 -552
- package/docs/framework-integrations/LANGCHAIN.md +0 -286
- package/docs/getting-started/QUICK_START.md +0 -211
- package/docs/getting-started/YOUR_FIRST_TOOL.md +0 -217
- package/docs/getting-started/installation.md +0 -124
- package/docs/index.md +0 -288
- package/docs/tool-development/DECORATOR_GUIDE.md +0 -633
- package/docs/tool-development/OAUTH_LINK.md +0 -5
- package/docs/tool-development/PROVIDER_CONFIGURATION.md +0 -458
- package/docs/tool-development/TESTING.md +0 -412
- package/docs/tool-development/TOOL_SPECIFICATION.md +0 -793
- package/docs/tool-development/YAML_TOOLS.md +0 -65
- package/docs/troubleshooting/FAQ.md +0 -391
- package/docs/user-guide/AUTHENTICATION.md +0 -255
- package/docs/user-guide/DEVELOPMENT_STANDARDS.md +0 -698
- package/docs/user-guide/SDK_PATTERNS.md +0 -316
- package/docs/user-guide/TOOL_DISCOVERY.md +0 -209
|
@@ -1,698 +0,0 @@
|
|
|
1
|
-
# Development Standards — Code Quality Rules
|
|
2
|
-
|
|
3
|
-
Code quality standards and best practices for Matimo.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
- [TypeScript Standards](#typescript-standards)
|
|
8
|
-
- [Naming Conventions](#naming-conventions)
|
|
9
|
-
- [Error Handling](#error-handling)
|
|
10
|
-
- [Testing Standards](#testing-standards)
|
|
11
|
-
- [Documentation Standards](#documentation-standards)
|
|
12
|
-
- [Security Standards](#security-standards)
|
|
13
|
-
- [Logging Standards](#logging-standards)
|
|
14
|
-
- [Performance Standards](#performance-standards)
|
|
15
|
-
- [Quality Metrics](#quality-metrics)
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## TypeScript Standards
|
|
20
|
-
|
|
21
|
-
### Strict Mode (Required)
|
|
22
|
-
|
|
23
|
-
All code must compile in TypeScript strict mode.
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
// tsconfig.json
|
|
27
|
-
{
|
|
28
|
-
"compilerOptions": {
|
|
29
|
-
"strict": true,
|
|
30
|
-
"noImplicitAny": true,
|
|
31
|
-
"noImplicitThis": true,
|
|
32
|
-
"strictNullChecks": true,
|
|
33
|
-
"strictFunctionTypes": true,
|
|
34
|
-
"strictBindCallApply": true,
|
|
35
|
-
"strictPropertyInitialization": true,
|
|
36
|
-
"noImplicitReturns": true
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Type Safety
|
|
42
|
-
|
|
43
|
-
**DO:**
|
|
44
|
-
```typescript
|
|
45
|
-
// Explicit types everywhere
|
|
46
|
-
function loadTool(path: string): ToolDefinition {
|
|
47
|
-
// implementation
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Use interface for contracts
|
|
51
|
-
interface ToolDefinition {
|
|
52
|
-
name: string;
|
|
53
|
-
execute(params: Record<string, unknown>): Promise<Result>;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Use union types for variants
|
|
57
|
-
type ExecutionType = 'command' | 'http' | 'script';
|
|
58
|
-
|
|
59
|
-
// Use const assertions for immutable data
|
|
60
|
-
const EXECUTION_TYPES = ['command', 'http', 'script'] as const;
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
**DON'T:**
|
|
64
|
-
```typescript
|
|
65
|
-
// No implicit any
|
|
66
|
-
function loadTool(path) { }
|
|
67
|
-
|
|
68
|
-
// No any types
|
|
69
|
-
function execute(tool: any, params: any): any { }
|
|
70
|
-
|
|
71
|
-
// No untyped variables
|
|
72
|
-
let result;
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Export Types
|
|
76
|
-
|
|
77
|
-
Export types alongside implementations:
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
// ✅ DO: Export types with implementation
|
|
81
|
-
export interface ToolDefinition {
|
|
82
|
-
name: string;
|
|
83
|
-
// ...
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export class ToolLoader {
|
|
87
|
-
loadToolFromFile(path: string): ToolDefinition { }
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// ❌ DON'T: Types only in comments
|
|
91
|
-
// ToolDefinition = { name: string, ... }
|
|
92
|
-
class ToolLoader { }
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## Naming Conventions
|
|
98
|
-
|
|
99
|
-
### Files
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
// kebab-case for files
|
|
103
|
-
tool-loader.ts
|
|
104
|
-
command-executor.ts
|
|
105
|
-
error-codes.ts
|
|
106
|
-
matimo-error.ts
|
|
107
|
-
|
|
108
|
-
// Descriptive names
|
|
109
|
-
// ✓ command-executor.ts
|
|
110
|
-
// ✗ executor.ts
|
|
111
|
-
// ✗ cmd-exec.ts
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Classes & Types
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
// PascalCase for classes
|
|
118
|
-
class ToolLoader { }
|
|
119
|
-
class CommandExecutor { }
|
|
120
|
-
class MatimoError extends Error { }
|
|
121
|
-
|
|
122
|
-
// PascalCase for types/interfaces
|
|
123
|
-
interface ToolDefinition { }
|
|
124
|
-
interface ExecutionConfig { }
|
|
125
|
-
type ExecutionType = 'command' | 'http' | 'script';
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### Functions & Variables
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
// camelCase for functions and variables
|
|
132
|
-
function loadTool() { }
|
|
133
|
-
const toolRegistry = new Map();
|
|
134
|
-
let executionCount = 0;
|
|
135
|
-
|
|
136
|
-
// Descriptive names
|
|
137
|
-
// ✓ loadToolFromFile()
|
|
138
|
-
// ✓ validateToolParameters()
|
|
139
|
-
// ✗ load()
|
|
140
|
-
// ✗ validate()
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Constants
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
// UPPER_SNAKE_CASE for constants
|
|
147
|
-
const MAX_RETRIES = 3;
|
|
148
|
-
const DEFAULT_TIMEOUT = 5000;
|
|
149
|
-
const SUPPORTED_TYPES = ['command', 'http', 'script'];
|
|
150
|
-
|
|
151
|
-
// Constants should be immutable
|
|
152
|
-
const readonly EXECUTION_TYPES = ['command', 'http'] as const;
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## Error Handling
|
|
158
|
-
|
|
159
|
-
### Use Structured Errors
|
|
160
|
-
|
|
161
|
-
```typescript
|
|
162
|
-
// Define standard error codes
|
|
163
|
-
export enum ErrorCode {
|
|
164
|
-
INVALID_SCHEMA = 'INVALID_SCHEMA',
|
|
165
|
-
EXECUTION_FAILED = 'EXECUTION_FAILED',
|
|
166
|
-
AUTH_FAILED = 'AUTH_FAILED',
|
|
167
|
-
TOOL_NOT_FOUND = 'TOOL_NOT_FOUND',
|
|
168
|
-
FILE_NOT_FOUND = 'FILE_NOT_FOUND',
|
|
169
|
-
VALIDATION_FAILED = 'VALIDATION_FAILED'
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Use structured error class
|
|
173
|
-
export class MatimoError extends Error {
|
|
174
|
-
constructor(
|
|
175
|
-
message: string,
|
|
176
|
-
public code: ErrorCode,
|
|
177
|
-
public context?: Record<string, unknown>
|
|
178
|
-
) {
|
|
179
|
-
super(message);
|
|
180
|
-
this.name = 'MatimoError';
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Throw with context
|
|
185
|
-
throw new MatimoError(
|
|
186
|
-
'Tool execution failed',
|
|
187
|
-
ErrorCode.EXECUTION_FAILED,
|
|
188
|
-
{
|
|
189
|
-
toolName: tool.name,
|
|
190
|
-
reason: 'timeout',
|
|
191
|
-
duration: 30000
|
|
192
|
-
}
|
|
193
|
-
);
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Error Message Guidelines
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
// ✅ DO: Clear, actionable messages
|
|
200
|
-
throw new MatimoError(
|
|
201
|
-
'Tool validation failed: missing required parameter "repo"',
|
|
202
|
-
ErrorCode.VALIDATION_FAILED
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
// ✅ DO: Include context
|
|
206
|
-
throw new MatimoError(
|
|
207
|
-
'HTTP request failed',
|
|
208
|
-
ErrorCode.EXECUTION_FAILED,
|
|
209
|
-
{ status: 500, endpoint: '/api/issues' }
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
// ❌ DON'T: Generic errors
|
|
213
|
-
throw new Error('Something went wrong');
|
|
214
|
-
|
|
215
|
-
// ❌ DON'T: Include sensitive data
|
|
216
|
-
throw new Error(`Failed with token: ${apiKey}`);
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Error Handling Pattern
|
|
220
|
-
|
|
221
|
-
```typescript
|
|
222
|
-
try {
|
|
223
|
-
const result = await executor.execute(tool, params);
|
|
224
|
-
return result;
|
|
225
|
-
} catch (error) {
|
|
226
|
-
if (error instanceof MatimoError) {
|
|
227
|
-
logger.error('Execution failed', {
|
|
228
|
-
code: error.code,
|
|
229
|
-
message: error.message,
|
|
230
|
-
context: error.context
|
|
231
|
-
});
|
|
232
|
-
throw error;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Convert unknown errors
|
|
236
|
-
throw new MatimoError(
|
|
237
|
-
'Unknown error during execution',
|
|
238
|
-
ErrorCode.EXECUTION_FAILED,
|
|
239
|
-
{ originalError: error.message }
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
## Testing Standards
|
|
247
|
-
|
|
248
|
-
### Test File Organization
|
|
249
|
-
|
|
250
|
-
```typescript
|
|
251
|
-
// test/unit/tool-loader.test.ts
|
|
252
|
-
describe('ToolLoader', () => {
|
|
253
|
-
describe('loadToolFromFile', () => {
|
|
254
|
-
it('should load valid YAML tool definition', () => {
|
|
255
|
-
// Arrange
|
|
256
|
-
const filePath = './fixtures/calculator.yaml';
|
|
257
|
-
|
|
258
|
-
// Act
|
|
259
|
-
const tool = loader.loadToolFromFile(filePath);
|
|
260
|
-
|
|
261
|
-
// Assert
|
|
262
|
-
expect(tool.name).toBe('calculator');
|
|
263
|
-
expect(tool.parameters).toBeDefined();
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it('should throw FileNotFoundError when file does not exist', () => {
|
|
267
|
-
// Arrange
|
|
268
|
-
const filePath = './fixtures/nonexistent.yaml';
|
|
269
|
-
|
|
270
|
-
// Act & Assert
|
|
271
|
-
expect(() => {
|
|
272
|
-
loader.loadToolFromFile(filePath);
|
|
273
|
-
}).toThrow(FileNotFoundError);
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
});
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
### Test Naming
|
|
280
|
-
|
|
281
|
-
```typescript
|
|
282
|
-
// ✅ DO: Descriptive test names
|
|
283
|
-
it('should load valid YAML tool definition');
|
|
284
|
-
it('should throw FileNotFoundError when file does not exist');
|
|
285
|
-
it('should validate parameters against schema');
|
|
286
|
-
it('should handle missing required parameters');
|
|
287
|
-
it('should retry on temporary failure');
|
|
288
|
-
|
|
289
|
-
// ❌ DON'T: Vague test names
|
|
290
|
-
it('should work');
|
|
291
|
-
it('tests loading');
|
|
292
|
-
it('handles errors');
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Test Coverage
|
|
296
|
-
|
|
297
|
-
**Minimum targets:**
|
|
298
|
-
- Overall: **80%+**
|
|
299
|
-
- Critical paths: **90%+**
|
|
300
|
-
- Branch coverage: All if/else paths tested
|
|
301
|
-
- Edge cases: Empty inputs, null values, max values
|
|
302
|
-
|
|
303
|
-
```bash
|
|
304
|
-
# Check coverage
|
|
305
|
-
pnpm test:coverage
|
|
306
|
-
|
|
307
|
-
# Expected:
|
|
308
|
-
# Statements : 80%+
|
|
309
|
-
# Branches : 75%+
|
|
310
|
-
# Functions : 80%+
|
|
311
|
-
# Lines : 80%+
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### Mocking & Fixtures
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
// ✅ DO: Use fixtures for test data
|
|
318
|
-
const validTool = loadYaml('./fixtures/calculator.yaml');
|
|
319
|
-
|
|
320
|
-
// ✅ DO: Mock external dependencies
|
|
321
|
-
const mockAPI = jest.spyOn(axios, 'get')
|
|
322
|
-
.mockResolvedValue({ data: { id: 1 } });
|
|
323
|
-
|
|
324
|
-
// ✅ DO: Clean up mocks
|
|
325
|
-
afterEach(() => {
|
|
326
|
-
jest.clearAllMocks();
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
// ✅ DO: Use AAA pattern
|
|
330
|
-
it('should execute tool', () => {
|
|
331
|
-
// Arrange
|
|
332
|
-
const tool = loadTool('calculator');
|
|
333
|
-
|
|
334
|
-
// Act
|
|
335
|
-
const result = executor.execute(tool, { a: 1, b: 2 });
|
|
336
|
-
|
|
337
|
-
// Assert
|
|
338
|
-
expect(result.output.result).toBe(3);
|
|
339
|
-
});
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
---
|
|
343
|
-
|
|
344
|
-
## Documentation Standards
|
|
345
|
-
|
|
346
|
-
### JSDoc Comments
|
|
347
|
-
|
|
348
|
-
```typescript
|
|
349
|
-
// ✅ DO: JSDoc for all public APIs
|
|
350
|
-
/**
|
|
351
|
-
* Load a tool definition from a YAML/JSON file.
|
|
352
|
-
*
|
|
353
|
-
* @param path - Path to tool definition file
|
|
354
|
-
* @returns Loaded and validated tool definition
|
|
355
|
-
* @throws {FileNotFoundError} If file doesn't exist
|
|
356
|
-
* @throws {SchemaValidationError} If tool schema invalid
|
|
357
|
-
*
|
|
358
|
-
* @example
|
|
359
|
-
* const tool = loader.loadToolFromFile('./tools/calculator.yaml');
|
|
360
|
-
*/
|
|
361
|
-
export function loadToolFromFile(path: string): ToolDefinition {
|
|
362
|
-
// implementation
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// ❌ DON'T: Missing or vague documentation
|
|
366
|
-
function load(p) { }
|
|
367
|
-
|
|
368
|
-
// ❌ DON'T: Obvious comments
|
|
369
|
-
// Increment i
|
|
370
|
-
i++;
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### Code Comments
|
|
374
|
-
|
|
375
|
-
Comments should explain **WHY**, not **WHAT**.
|
|
376
|
-
|
|
377
|
-
```typescript
|
|
378
|
-
// ✅ DO: Explain why
|
|
379
|
-
// We retry exponentially because the API has rate limits
|
|
380
|
-
// and temporary network issues are common
|
|
381
|
-
const delay = initialDelay * Math.pow(2, retries);
|
|
382
|
-
|
|
383
|
-
// ✅ DO: Document non-obvious logic
|
|
384
|
-
// Skip first item because it's always metadata
|
|
385
|
-
for (let i = 1; i < items.length; i++) {
|
|
386
|
-
// process item
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// ❌ DON'T: Describe what the code does
|
|
390
|
-
// Calculate exponential backoff
|
|
391
|
-
const delay = initialDelay * Math.pow(2, retries);
|
|
392
|
-
|
|
393
|
-
// ❌ DON'T: Obvious comments
|
|
394
|
-
// Get the first item
|
|
395
|
-
const first = items[0];
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
### README Structure
|
|
399
|
-
|
|
400
|
-
```markdown
|
|
401
|
-
# Tool Name
|
|
402
|
-
|
|
403
|
-
Brief description (1 sentence)
|
|
404
|
-
|
|
405
|
-
## Features
|
|
406
|
-
- Feature 1
|
|
407
|
-
- Feature 2
|
|
408
|
-
|
|
409
|
-
## Installation
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
## Installation
|
|
413
|
-
|
|
414
|
-
Step-by-step setup instructions
|
|
415
|
-
|
|
416
|
-
## Usage
|
|
417
|
-
|
|
418
|
-
Code examples
|
|
419
|
-
|
|
420
|
-
## API Reference
|
|
421
|
-
|
|
422
|
-
Methods and options
|
|
423
|
-
|
|
424
|
-
## Troubleshooting
|
|
425
|
-
|
|
426
|
-
Common issues and solutions
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
---
|
|
430
|
-
|
|
431
|
-
## Security Standards
|
|
432
|
-
|
|
433
|
-
### Input Validation
|
|
434
|
-
|
|
435
|
-
```typescript
|
|
436
|
-
// ✅ DO: Validate all inputs
|
|
437
|
-
const validated = toolSchema.parameters.parse(params);
|
|
438
|
-
const result = await executor.execute(tool, validated);
|
|
439
|
-
|
|
440
|
-
// ✅ DO: Use Zod for schema validation
|
|
441
|
-
import { z } from 'zod';
|
|
442
|
-
|
|
443
|
-
const paramSchema = z.object({
|
|
444
|
-
repo: z.string().regex(/^[^/]+\/[^/]+$/),
|
|
445
|
-
issue: z.number().min(1)
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
const validated = paramSchema.parse(params);
|
|
449
|
-
|
|
450
|
-
// ❌ DON'T: Trust user input
|
|
451
|
-
const command = `git clone ${userUrl}`; // Dangerous!
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
### Secret Management
|
|
455
|
-
|
|
456
|
-
```typescript
|
|
457
|
-
// ✅ DO: Use environment variables with MATIMO_ prefix
|
|
458
|
-
const apiKey = process.env.MATIMO_SLACK_API_KEY;
|
|
459
|
-
if (!apiKey) {
|
|
460
|
-
throw new MatimoError('Missing Slack API key', ErrorCode.AUTH_FAILED);
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// ✅ DO: Validate secrets exist before use
|
|
464
|
-
const token = process.env.MATIMO_GITHUB_TOKEN;
|
|
465
|
-
if (!token || token.length === 0) {
|
|
466
|
-
throw new MatimoError('Invalid GitHub token', ErrorCode.AUTH_FAILED);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
// ❌ DON'T: Hardcode secrets
|
|
470
|
-
const API_KEY = 'sk_live_abc123xyz789'; // NEVER!
|
|
471
|
-
|
|
472
|
-
// ❌ DON'T: Log secrets
|
|
473
|
-
logger.info('Token retrieved:', apiKey); // WRONG!
|
|
474
|
-
logger.info('Token retrieved'); // OK
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
### Output Escaping
|
|
478
|
-
|
|
479
|
-
```typescript
|
|
480
|
-
// ✅ DO: Escape shell commands
|
|
481
|
-
import { shellEscape } from 'shell-escape';
|
|
482
|
-
const escaped = shellEscape([command, ...args]);
|
|
483
|
-
|
|
484
|
-
// ✅ DO: Sanitize error messages
|
|
485
|
-
const sanitized = error.message.replace(apiKey, '[REDACTED]');
|
|
486
|
-
|
|
487
|
-
// ❌ DON'T: Include secrets in error messages
|
|
488
|
-
throw new Error(`Failed with key: ${apiKey}`);
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
---
|
|
492
|
-
|
|
493
|
-
## Logging Standards
|
|
494
|
-
|
|
495
|
-
### Structured Logging
|
|
496
|
-
|
|
497
|
-
```typescript
|
|
498
|
-
// ✅ DO: Use structured logging
|
|
499
|
-
logger.info('tool_execution', {
|
|
500
|
-
traceId: context.traceId,
|
|
501
|
-
toolName: tool.name,
|
|
502
|
-
parameters: sanitized(params),
|
|
503
|
-
duration: executionTime,
|
|
504
|
-
status: 'success' | 'failed'
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
// ✅ DO: Include trace IDs
|
|
508
|
-
logger.error('execution_failed', {
|
|
509
|
-
traceId: context.traceId,
|
|
510
|
-
toolName: tool.name,
|
|
511
|
-
error: error.message
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
// ❌ DON'T: Unstructured logging
|
|
515
|
-
console.log('Tool loaded');
|
|
516
|
-
logger.info('tool loaded: ' + toolName);
|
|
517
|
-
|
|
518
|
-
// ❌ DON'T: Log secrets
|
|
519
|
-
logger.info('Token: ' + apiKey);
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
### Log Levels
|
|
523
|
-
|
|
524
|
-
```typescript
|
|
525
|
-
logger.debug('Parsing tool definition'); // Detailed info
|
|
526
|
-
logger.info('Tool loaded successfully'); // Informational
|
|
527
|
-
logger.warn('Tool schema drift detected'); // Warning
|
|
528
|
-
logger.error('Tool execution failed', error); // Error
|
|
529
|
-
|
|
530
|
-
// ❌ DON'T: Use console.log in production
|
|
531
|
-
console.log('Debug info');
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
---
|
|
535
|
-
|
|
536
|
-
## Performance Standards
|
|
537
|
-
|
|
538
|
-
### Execution Time Targets
|
|
539
|
-
|
|
540
|
-
```
|
|
541
|
-
Simple tools (echo, time): <100ms
|
|
542
|
-
API tools (GitHub, Slack): <2 seconds
|
|
543
|
-
Data processing (CSV, JSON): <1 second
|
|
544
|
-
Heavy computation: <10 seconds
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
### Memory Targets
|
|
548
|
-
|
|
549
|
-
```
|
|
550
|
-
Tool loading: <10MB
|
|
551
|
-
Tool execution: <50MB
|
|
552
|
-
Registry loading: <20MB
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
### Throughput Targets
|
|
556
|
-
|
|
557
|
-
```
|
|
558
|
-
Tools loaded: 1000+ in <1 second
|
|
559
|
-
Concurrent executions: 100+
|
|
560
|
-
Requests/second: 1000+
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
---
|
|
564
|
-
|
|
565
|
-
## Quality Metrics
|
|
566
|
-
|
|
567
|
-
### Code Quality Checklist
|
|
568
|
-
|
|
569
|
-
```typescript
|
|
570
|
-
// ✅ Types
|
|
571
|
-
- Strict TypeScript mode enabled
|
|
572
|
-
- No `any` types used
|
|
573
|
-
- All functions have type signatures
|
|
574
|
-
- Return types explicitly declared
|
|
575
|
-
|
|
576
|
-
// ✅ Testing
|
|
577
|
-
- 80%+ test coverage
|
|
578
|
-
- Unit tests for all modules
|
|
579
|
-
- Integration tests for critical paths
|
|
580
|
-
- Edge cases tested
|
|
581
|
-
|
|
582
|
-
// ✅ Documentation
|
|
583
|
-
- JSDoc comments on all public APIs
|
|
584
|
-
- README with examples
|
|
585
|
-
- Code comments explaining WHY
|
|
586
|
-
- Type definitions exported
|
|
587
|
-
|
|
588
|
-
// ✅ Error Handling
|
|
589
|
-
- All errors use MatimoError
|
|
590
|
-
- Errors include codes and context
|
|
591
|
-
- No generic Error throws
|
|
592
|
-
- Error messages are clear
|
|
593
|
-
|
|
594
|
-
// ✅ Security
|
|
595
|
-
- No hardcoded secrets
|
|
596
|
-
- All inputs validated
|
|
597
|
-
- Sensitive data never logged
|
|
598
|
-
- Shell commands properly escaped
|
|
599
|
-
|
|
600
|
-
// ✅ Performance
|
|
601
|
-
- Tool loading <10MB
|
|
602
|
-
- Execution meets time targets
|
|
603
|
-
- No memory leaks
|
|
604
|
-
- Concurrent operations supported
|
|
605
|
-
```
|
|
606
|
-
|
|
607
|
-
### Build Verification
|
|
608
|
-
|
|
609
|
-
```bash
|
|
610
|
-
# Check TypeScript
|
|
611
|
-
pnpm build
|
|
612
|
-
# Expected: No errors
|
|
613
|
-
|
|
614
|
-
# Check linting
|
|
615
|
-
pnpm lint
|
|
616
|
-
# Expected: 0 errors, 0 warnings
|
|
617
|
-
|
|
618
|
-
# Check tests
|
|
619
|
-
pnpm test
|
|
620
|
-
# Expected: All tests passing
|
|
621
|
-
|
|
622
|
-
# Check coverage
|
|
623
|
-
pnpm test:coverage
|
|
624
|
-
# Expected: 80%+ coverage
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
---
|
|
628
|
-
|
|
629
|
-
## Development Workflow
|
|
630
|
-
|
|
631
|
-
### Before Committing
|
|
632
|
-
|
|
633
|
-
1. **Format code:** `pnpm format`
|
|
634
|
-
2. **Check types:** `pnpm build`
|
|
635
|
-
3. **Lint:** `pnpm lint`
|
|
636
|
-
4. **Test:** `pnpm test`
|
|
637
|
-
5. **Coverage:** `pnpm test:coverage` (verify 80%+)
|
|
638
|
-
|
|
639
|
-
### Pre-Merge Checklist
|
|
640
|
-
|
|
641
|
-
- [ ] All tests passing
|
|
642
|
-
- [ ] Coverage 80%+
|
|
643
|
-
- [ ] No TypeScript errors
|
|
644
|
-
- [ ] No ESLint warnings
|
|
645
|
-
- [ ] Code formatted with Prettier
|
|
646
|
-
- [ ] Commit messages follow guidelines
|
|
647
|
-
- [ ] Documentation updated
|
|
648
|
-
- [ ] PR reviewed and approved
|
|
649
|
-
|
|
650
|
-
---
|
|
651
|
-
|
|
652
|
-
## Common Anti-Patterns
|
|
653
|
-
|
|
654
|
-
```typescript
|
|
655
|
-
// ❌ DON'T: Use any types
|
|
656
|
-
function execute(tool: any, params: any): any { }
|
|
657
|
-
|
|
658
|
-
// ✅ DO: Use proper types
|
|
659
|
-
function execute(
|
|
660
|
-
tool: ToolDefinition,
|
|
661
|
-
params: Record<string, unknown>
|
|
662
|
-
): Promise<ExecutionResult> { }
|
|
663
|
-
|
|
664
|
-
// ❌ DON'T: Generic error handling
|
|
665
|
-
catch (error) {
|
|
666
|
-
throw new Error('Failed');
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
// ✅ DO: Structured error handling
|
|
670
|
-
catch (error) {
|
|
671
|
-
throw new MatimoError(
|
|
672
|
-
'Tool execution failed',
|
|
673
|
-
ErrorCode.EXECUTION_FAILED,
|
|
674
|
-
{ toolName, reason: error.message }
|
|
675
|
-
);
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
// ❌ DON'T: Log secrets
|
|
679
|
-
logger.info('Authenticated with key:', apiKey);
|
|
680
|
-
|
|
681
|
-
// ✅ DO: Redact sensitive data
|
|
682
|
-
logger.info('Authentication successful', { hasKey: !!apiKey });
|
|
683
|
-
|
|
684
|
-
// ❌ DON'T: Skip validation
|
|
685
|
-
const result = userInput.trim();
|
|
686
|
-
|
|
687
|
-
// ✅ DO: Validate all inputs
|
|
688
|
-
const validated = schema.parse(userInput);
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
---
|
|
692
|
-
|
|
693
|
-
## See Also
|
|
694
|
-
|
|
695
|
-
- [CONTRIBUTING.md](../CONTRIBUTING.md) — Contribution guide
|
|
696
|
-
- [COMMIT_GUIDELINES.md](../community/COMMIT_GUIDELINES.md) — Commit standards
|
|
697
|
-
- [QUICK_START.md](../getting-started/QUICK_START.md) — Get started
|
|
698
|
-
- [API_REFERENCE.md](../api-reference/SDK.md) — SDK documentation
|