@qodo/sdk 0.4.0 → 0.6.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.
Files changed (57) hide show
  1. package/.claude/skills/qodo-agent/SKILL.md +656 -0
  2. package/.claude/skills/qodo-agent/assets/programmatic-agent.ts +317 -0
  3. package/.claude/skills/qodo-agent/references/builtin-tools.md +342 -0
  4. package/.claude/skills/qodo-agent/references/common-issues.md +457 -0
  5. package/dist/api/agent.d.ts +0 -1
  6. package/dist/api/agent.d.ts.map +1 -1
  7. package/dist/api/agent.js +5 -127
  8. package/dist/api/agent.js.map +1 -1
  9. package/dist/bin/install-skill.d.ts +14 -0
  10. package/dist/bin/install-skill.d.ts.map +1 -0
  11. package/dist/bin/install-skill.js +125 -0
  12. package/dist/bin/install-skill.js.map +1 -0
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/mcp/MCPManager.d.ts +0 -16
  18. package/dist/mcp/MCPManager.d.ts.map +1 -1
  19. package/dist/mcp/MCPManager.js +1 -42
  20. package/dist/mcp/MCPManager.js.map +1 -1
  21. package/dist/mcp/builtinServers.d.ts.map +1 -1
  22. package/dist/mcp/builtinServers.js +0 -12
  23. package/dist/mcp/builtinServers.js.map +1 -1
  24. package/dist/mcp/index.d.ts +0 -1
  25. package/dist/mcp/index.d.ts.map +1 -1
  26. package/dist/mcp/index.js +0 -1
  27. package/dist/mcp/index.js.map +1 -1
  28. package/dist/mcp/servers/filesystem.d.ts +0 -31
  29. package/dist/mcp/servers/filesystem.d.ts.map +1 -1
  30. package/dist/mcp/servers/filesystem.js +0 -222
  31. package/dist/mcp/servers/filesystem.js.map +1 -1
  32. package/dist/mcp/servers/shell.d.ts.map +1 -1
  33. package/dist/mcp/servers/shell.js +21 -105
  34. package/dist/mcp/servers/shell.js.map +1 -1
  35. package/dist/mcp/serversRegistry.d.ts +1 -1
  36. package/dist/mcp/serversRegistry.d.ts.map +1 -1
  37. package/dist/mcp/serversRegistry.js +3 -3
  38. package/dist/mcp/serversRegistry.js.map +1 -1
  39. package/dist/mcp/toolProcessor.d.ts.map +1 -1
  40. package/dist/mcp/toolProcessor.js +0 -43
  41. package/dist/mcp/toolProcessor.js.map +1 -1
  42. package/dist/sdk/QodoSDK.d.ts.map +1 -1
  43. package/dist/sdk/QodoSDK.js +0 -9
  44. package/dist/sdk/QodoSDK.js.map +1 -1
  45. package/dist/sdk/builders.d.ts +1 -1
  46. package/dist/sdk/builders.d.ts.map +1 -1
  47. package/dist/sdk/builders.js +1 -1
  48. package/dist/sdk/builders.js.map +1 -1
  49. package/dist/sdk/schemas.d.ts +1 -1
  50. package/dist/sdk/schemas.d.ts.map +1 -1
  51. package/dist/sdk/schemas.js +1 -1
  52. package/dist/sdk/schemas.js.map +1 -1
  53. package/package.json +9 -5
  54. package/dist/mcp/servers/gerrit.d.ts +0 -19
  55. package/dist/mcp/servers/gerrit.d.ts.map +0 -1
  56. package/dist/mcp/servers/gerrit.js +0 -515
  57. package/dist/mcp/servers/gerrit.js.map +0 -1
@@ -0,0 +1,656 @@
1
+ ---
2
+ name: qodo-agent
3
+ description: Development companion for building AI-powered agents with @qodo/sdk. Use when working with QodoSDK, sdkAgent(), sdkCommand(), agent.toml, or any Qodo agent development tasks.
4
+ compatibility: Requires Node.js >= 18, npm, and zod package for schema definitions.
5
+ metadata:
6
+ author: qodo
7
+ version: "1.0"
8
+ ---
9
+
10
+ # Qodo SDK Development Companion
11
+
12
+ Use this skill when working with `@qodo/sdk` to build AI-powered agents. This skill helps you:
13
+
14
+ - **Create** agent configurations (TypeScript and TOML)
15
+ - **Scaffold** Zod schemas with proper patterns and descriptions
16
+ - **Extend** existing agents with new commands, tools, and capabilities
17
+ - **Debug** streaming events, schema validation, and tool execution issues
18
+ - **Refactor** between config formats and improve type safety
19
+
20
+ ## Quick Reference
21
+
22
+ ### Core Exports
23
+
24
+ | Export | Purpose |
25
+ |--------|---------|
26
+ | `QodoSDK` | Main SDK class - initialize and run agents |
27
+ | `sdkAgent()` | Build agent config programmatically |
28
+ | `sdkCommand()` | Build command config with Zod schemas |
29
+ | `sdkArgs()` | Convenience wrapper for `z.object()` |
30
+
31
+ ### Schema Helpers
32
+
33
+ | Export | Purpose |
34
+ |--------|---------|
35
+ | `zodOutputSchema()` | Convert Zod to JSON Schema for output |
36
+ | `zJsonValue()` | Flexible primitive type (string \| number \| boolean \| null) |
37
+ | `zJsonAny()` | Flexible any type (primitives + arrays + objects) |
38
+ | `zCoerce` | CLI-style input coercion (boolean, number, jsonArray, jsonObject) |
39
+ | `parseArgsWithSchema()` | Validate args with Zod, get typed result |
40
+ | `QodoSchemaError` | Schema validation error class |
41
+
42
+ ### Event Handling
43
+
44
+ | Export | Purpose |
45
+ |--------|---------|
46
+ | `SdkEventType` | Event type constants (Init, MessageDelta, Final, etc.) |
47
+ | `matchSdkEvent()` | Type-safe event router |
48
+
49
+ ### Clients
50
+
51
+ | Export | Purpose |
52
+ |--------|---------|
53
+ | `QodoInfoClient` | Backend info (models, capabilities) |
54
+ | `QodoSessionsClient` | Session history management |
55
+
56
+ ### Errors
57
+
58
+ | Export | Purpose |
59
+ |--------|---------|
60
+ | `QodoSchemaError` | Schema validation failures |
61
+ | `QodoAuthError` | Authentication failures |
62
+ | `QodoBackendBootstrapError` | Backend initialization failures |
63
+
64
+ ### Built-in Tools
65
+
66
+ Use these in `available_tools` to give your agent capabilities:
67
+
68
+ | Tool | Purpose | Common Use Cases |
69
+ |------|---------|------------------|
70
+ | `filesystem` | File operations | Read/write files, navigate directories, edit code |
71
+ | `git` | Version control | Check status, view diffs, commit changes |
72
+ | `ripgrep` | Code search | Find patterns, locate definitions, search codebase |
73
+ | `shell` | Run commands | Build tools, scripts, system commands |
74
+
75
+ **Example:**
76
+ ```typescript
77
+ sdkCommand({
78
+ name: 'analyze',
79
+ available_tools: ['filesystem', 'ripgrep'], // Read files + search
80
+ // ...
81
+ });
82
+ ```
83
+
84
+ **Common Combinations:**
85
+ - **Code analysis**: `['filesystem', 'ripgrep']`
86
+ - **Code review**: `['git', 'filesystem']`
87
+ - **Full development**: `['filesystem', 'git', 'ripgrep', 'shell']`
88
+
89
+ See [references/builtin-tools.md](references/builtin-tools.md) for detailed documentation on each tool.
90
+
91
+ ---
92
+
93
+ ## Critical Rules
94
+
95
+ ### For SDK Users (Building Apps)
96
+
97
+ 1. **Every output property needs `.describe()`**
98
+ ```typescript
99
+ // WRONG - will throw QodoSchemaError
100
+ const output = z.object({
101
+ summary: z.string(),
102
+ score: z.number(),
103
+ });
104
+
105
+ // CORRECT
106
+ const output = z.object({
107
+ summary: z.string().describe('Brief summary of the analysis'),
108
+ score: z.number().describe('Quality score from 0-100'),
109
+ });
110
+ ```
111
+
112
+ 2. **Never use `z.any()` in output schemas**
113
+ ```typescript
114
+ // WRONG - produces invalid JSON Schema
115
+ const output = z.object({
116
+ data: z.any().describe('The data'),
117
+ });
118
+
119
+ // CORRECT - use zJsonValue() or zJsonAny()
120
+ import { zJsonValue, zJsonAny } from '@qodo/sdk';
121
+
122
+ const output = z.object({
123
+ // For primitives only:
124
+ value: zJsonValue().describe('A primitive value'),
125
+ // For any JSON (including objects/arrays):
126
+ data: zJsonAny().describe('Any JSON data'),
127
+ });
128
+ ```
129
+
130
+ 3. **Always call `sdk.dispose()`**
131
+ ```typescript
132
+ const sdk = new QodoSDK({ ... });
133
+ try {
134
+ const result = await sdk.run('analyze', { args: { path: './src' } });
135
+ console.log(result.structured_output);
136
+ } finally {
137
+ await sdk.dispose(); // Cleanup MCP servers and connections
138
+ }
139
+ ```
140
+
141
+ 4. **Handle errors appropriately**
142
+ ```typescript
143
+ import { QodoSchemaError, QodoAuthError } from '@qodo/sdk';
144
+
145
+ try {
146
+ const result = await sdk.run('analyze');
147
+ } catch (e) {
148
+ if (e instanceof QodoSchemaError) {
149
+ console.error('Schema validation failed:', e.message);
150
+ } else if (e instanceof QodoAuthError) {
151
+ console.error('Authentication failed:', e.message);
152
+ } else {
153
+ throw e;
154
+ }
155
+ }
156
+ ```
157
+
158
+ ### For SDK Contributors (Modifying @qodo/sdk)
159
+
160
+ 1. **Never use `process.exit()`** - throw errors instead (library code)
161
+ 2. **Use `.js` extensions** in imports - ESM requirement
162
+ 3. **Export types separately** - TypeScript best practice
163
+
164
+ ---
165
+
166
+ ## Usage Patterns
167
+
168
+ ### Pattern 1: Simple Prompt (No Config)
169
+
170
+ ```typescript
171
+ import { QodoSDK } from '@qodo/sdk';
172
+
173
+ const sdk = new QodoSDK();
174
+ try {
175
+ const result = await sdk.prompt('Explain how async/await works in JavaScript');
176
+ console.log(result.final_output);
177
+ } finally {
178
+ await sdk.dispose();
179
+ }
180
+ ```
181
+
182
+ ### Pattern 2: Programmatic Agent with Zod
183
+
184
+ ```typescript
185
+ import { QodoSDK, sdkAgent, sdkCommand, sdkArgs, z } from '@qodo/sdk';
186
+ // Note: Import `z` from '@qodo/sdk' for guaranteed compatibility with SDK schema functions
187
+ // Alternatively, Zod 3 users can use: import { z } from 'zod';
188
+ // Zod 4 users should use: import { z } from 'zod/v3';
189
+
190
+ const agent = sdkAgent({
191
+ instructions: 'You are a code analysis assistant.',
192
+ commands: {
193
+ analyze: sdkCommand({
194
+ name: 'analyze',
195
+ description: 'Analyze code quality',
196
+ instructions: 'Analyze the code and provide a quality assessment.',
197
+ available_tools: ['filesystem', 'ripgrep'],
198
+ args: sdkArgs({
199
+ path: z.string().describe('Path to analyze'),
200
+ depth: z.number().optional().default(3).describe('Max directory depth'),
201
+ }),
202
+ output: z.object({
203
+ summary: z.string().describe('Overall assessment'),
204
+ issues: z.array(z.object({
205
+ file: z.string().describe('File path'),
206
+ line: z.number().describe('Line number'),
207
+ severity: z.enum(['low', 'medium', 'high']).describe('Issue severity'),
208
+ message: z.string().describe('Issue description'),
209
+ })).describe('List of issues found'),
210
+ score: z.number().describe('Quality score 0-100'),
211
+ }),
212
+ }),
213
+ },
214
+ });
215
+
216
+ const sdk = QodoSDK.fromAgent(agent);
217
+ try {
218
+ const result = await sdk.run('analyze', {
219
+ args: { path: './src', depth: 5 },
220
+ });
221
+ console.log('Score:', result.structured_output?.score);
222
+ console.log('Issues:', result.structured_output?.issues);
223
+ } finally {
224
+ await sdk.dispose();
225
+ }
226
+ ```
227
+
228
+ ### Pattern 3: TOML Configuration
229
+
230
+ Create `agent.toml`:
231
+ ```toml
232
+ version = "1.0"
233
+ instructions = "You are a helpful coding assistant."
234
+
235
+ [commands.review]
236
+ name = "review"
237
+ description = "Review code changes"
238
+ instructions = "Review the provided code changes and suggest improvements."
239
+ available_tools = ["filesystem", "git", "ripgrep"]
240
+
241
+ [commands.review.output_schema]
242
+ type = "json_schema"
243
+
244
+ [commands.review.output_schema.json_schema]
245
+ name = "review_output"
246
+ strict = true
247
+
248
+ [commands.review.output_schema.json_schema.schema]
249
+ type = "object"
250
+ required = ["summary", "suggestions"]
251
+
252
+ [commands.review.output_schema.json_schema.schema.properties.summary]
253
+ type = "string"
254
+ description = "Overall review summary"
255
+
256
+ [commands.review.output_schema.json_schema.schema.properties.suggestions]
257
+ type = "array"
258
+ description = "List of improvement suggestions"
259
+
260
+ [commands.review.output_schema.json_schema.schema.properties.suggestions.items]
261
+ type = "object"
262
+ required = ["file", "suggestion"]
263
+
264
+ [commands.review.output_schema.json_schema.schema.properties.suggestions.items.properties.file]
265
+ type = "string"
266
+ description = "File path"
267
+
268
+ [commands.review.output_schema.json_schema.schema.properties.suggestions.items.properties.suggestion]
269
+ type = "string"
270
+ description = "The suggestion"
271
+ ```
272
+
273
+ Then use it:
274
+ ```typescript
275
+ import { QodoSDK } from '@qodo/sdk';
276
+
277
+ const sdk = new QodoSDK({
278
+ agentFile: './agent.toml',
279
+ });
280
+ try {
281
+ const result = await sdk.run('review');
282
+ console.log(result.structured_output);
283
+ } finally {
284
+ await sdk.dispose();
285
+ }
286
+ ```
287
+
288
+ ### Pattern 4: Streaming Events
289
+
290
+ ```typescript
291
+ import { QodoSDK, SdkEventType, matchSdkEvent } from '@qodo/sdk';
292
+
293
+ const sdk = new QodoSDK();
294
+ try {
295
+ for await (const event of sdk.streamPrompt('Write a haiku about coding')) {
296
+ matchSdkEvent(event, {
297
+ [SdkEventType.MessageDelta]: (e) => {
298
+ process.stdout.write(e.data.delta);
299
+ },
300
+ [SdkEventType.ToolRequested]: (e) => {
301
+ console.log(`\nTool: ${e.data.server_name}.${e.data.tool_name}`);
302
+ },
303
+ [SdkEventType.ToolExecuted]: (e) => {
304
+ console.log(`Tool result: ${e.data.result.isError ? 'error' : 'success'}`);
305
+ },
306
+ [SdkEventType.Error]: (e) => {
307
+ console.error('Error:', e.data.message);
308
+ },
309
+ [SdkEventType.Final]: (e) => {
310
+ console.log('\n\nDone! Success:', e.data.success);
311
+ },
312
+ default: () => {}, // Ignore other events
313
+ });
314
+ }
315
+ } finally {
316
+ await sdk.dispose();
317
+ }
318
+ ```
319
+
320
+ ### Pattern 5: Custom Tool Approval
321
+
322
+ ```typescript
323
+ import { QodoSDK } from '@qodo/sdk';
324
+ import * as readline from 'readline';
325
+
326
+ const sdk = new QodoSDK({
327
+ autoApproveTools: false,
328
+ toolApproval: async ({ tool_name, server_name, tool_args }) => {
329
+ const rl = readline.createInterface({
330
+ input: process.stdin,
331
+ output: process.stdout,
332
+ });
333
+
334
+ return new Promise((resolve) => {
335
+ rl.question(
336
+ `Allow ${server_name}.${tool_name}(${JSON.stringify(tool_args)})? [y/N] `,
337
+ (answer) => {
338
+ rl.close();
339
+ resolve(answer.toLowerCase() === 'y');
340
+ }
341
+ );
342
+ });
343
+ },
344
+ });
345
+
346
+ try {
347
+ const result = await sdk.prompt('List files in current directory');
348
+ console.log(result.final_output);
349
+ } finally {
350
+ await sdk.dispose();
351
+ }
352
+ ```
353
+
354
+ ### Pattern 6: Session Continuity
355
+
356
+ ```typescript
357
+ import { QodoSDK } from '@qodo/sdk';
358
+
359
+ // First conversation
360
+ const sdk1 = new QodoSDK();
361
+ let sessionId: string;
362
+
363
+ try {
364
+ for await (const event of sdk1.streamPrompt('Remember: my favorite color is blue')) {
365
+ if (event.type === 'sdk.run.started') {
366
+ sessionId = event.data.session_id;
367
+ }
368
+ }
369
+ } finally {
370
+ await sdk1.dispose();
371
+ }
372
+
373
+ // Continue the conversation
374
+ const sdk2 = new QodoSDK().withSession(sessionId!);
375
+ try {
376
+ const result = await sdk2.prompt('What is my favorite color?');
377
+ console.log(result.final_output); // Should mention "blue"
378
+ } finally {
379
+ await sdk2.dispose();
380
+ }
381
+ ```
382
+
383
+ ### Pattern 7: Multi-Agent Orchestration
384
+
385
+ ```typescript
386
+ import { QodoSDK, sdkAgent, sdkCommand, sdkArgs, z } from '@qodo/sdk';
387
+
388
+ // Agent 1: Code analyzer
389
+ const analyzerAgent = sdkAgent({
390
+ instructions: 'You analyze code and identify issues.',
391
+ commands: {
392
+ analyze: sdkCommand({
393
+ name: 'analyze',
394
+ description: 'Analyze code',
395
+ available_tools: ['filesystem', 'ripgrep'],
396
+ output: z.object({
397
+ issues: z.array(z.string().describe('Issue description')).describe('Issues found'),
398
+ }),
399
+ }),
400
+ },
401
+ });
402
+
403
+ // Agent 2: Code fixer
404
+ const fixerAgent = sdkAgent({
405
+ instructions: 'You fix code issues.',
406
+ commands: {
407
+ fix: sdkCommand({
408
+ name: 'fix',
409
+ description: 'Fix code issues',
410
+ available_tools: ['filesystem'],
411
+ args: sdkArgs({
412
+ issues: z.array(z.string()).describe('Issues to fix'),
413
+ }),
414
+ output: z.object({
415
+ fixed: z.array(z.string().describe('Fixed issue')).describe('Issues that were fixed'),
416
+ }),
417
+ }),
418
+ },
419
+ });
420
+
421
+ // Orchestrate
422
+ const analyzer = QodoSDK.fromAgent(analyzerAgent);
423
+ const fixer = QodoSDK.fromAgent(fixerAgent);
424
+
425
+ try {
426
+ // Step 1: Analyze
427
+ const analysis = await analyzer.run('analyze');
428
+ const issues = analysis.structured_output?.issues || [];
429
+
430
+ // Step 2: Fix
431
+ if (issues.length > 0) {
432
+ const fixes = await fixer.run('fix', { args: { issues } });
433
+ console.log('Fixed:', fixes.structured_output?.fixed);
434
+ }
435
+ } finally {
436
+ await Promise.all([analyzer.dispose(), fixer.dispose()]);
437
+ }
438
+ ```
439
+
440
+ ---
441
+
442
+ ## Zod Schema Patterns
443
+
444
+ ### Basic Types with Descriptions
445
+
446
+ ```typescript
447
+ import { z } from '@qodo/sdk'; // Recommended for type compatibility
448
+
449
+ const output = z.object({
450
+ // Primitives
451
+ name: z.string().describe('The name'),
452
+ count: z.number().describe('Total count'),
453
+ enabled: z.boolean().describe('Whether enabled'),
454
+
455
+ // Optional fields
456
+ notes: z.string().optional().describe('Optional notes'),
457
+
458
+ // With defaults
459
+ priority: z.number().default(5).describe('Priority level 1-10'),
460
+
461
+ // Enums
462
+ status: z.enum(['pending', 'done', 'failed']).describe('Current status'),
463
+
464
+ // Arrays
465
+ tags: z.array(z.string().describe('Tag name')).describe('List of tags'),
466
+
467
+ // Nested objects
468
+ metadata: z.object({
469
+ created: z.string().describe('Creation date'),
470
+ author: z.string().describe('Author name'),
471
+ }).describe('Metadata information'),
472
+ });
473
+ ```
474
+
475
+ ### Flexible Types with zJsonValue and zJsonAny
476
+
477
+ ```typescript
478
+ import { z, zJsonValue, zJsonAny } from '@qodo/sdk';
479
+
480
+ const output = z.object({
481
+ // When you need a primitive but don't know which type
482
+ // Allows: string | number | boolean | null
483
+ dynamicValue: zJsonValue().describe('A dynamic primitive value'),
484
+
485
+ // When you need truly flexible data (including objects/arrays)
486
+ // Allows: primitives + arrays of primitives + objects with primitive values
487
+ rawData: zJsonAny().describe('Raw data in any JSON format'),
488
+
489
+ // Array of mixed primitives
490
+ mixedArray: z.array(zJsonValue()).describe('Array of mixed primitive values'),
491
+ });
492
+ ```
493
+
494
+ ### Coerced Input Types
495
+
496
+ ```typescript
497
+ import { z, zCoerce } from '@qodo/sdk';
498
+
499
+ // For CLI-style string inputs that need type conversion
500
+ const args = z.object({
501
+ // "true"/"false" strings -> boolean
502
+ verbose: zCoerce.boolean().describe('Enable verbose output'),
503
+
504
+ // "123" string -> number
505
+ limit: zCoerce.number().describe('Result limit'),
506
+
507
+ // '["a","b"]' string -> string[]
508
+ files: zCoerce.jsonArray(z.string()).describe('Files to process'),
509
+
510
+ // '{"key":"value"}' string -> object
511
+ config: zCoerce.jsonObject({ key: z.string() }).describe('Configuration'),
512
+ });
513
+ ```
514
+
515
+ ---
516
+
517
+ ## Event Types Reference
518
+
519
+ | Event Type | When Emitted | Key Data Fields |
520
+ |------------|--------------|-----------------|
521
+ | `sdk.init` | SDK initialized | `sdk_version`, `backend.base_url`, `model` |
522
+ | `sdk.run.started` | Run begins | `session_id`, `command`, `prompt_mode`, `cwd` |
523
+ | `sdk.message.delta` | Streaming text | `delta`, `message_id`, `role` |
524
+ | `sdk.message.full` | Full message update | `messages.langchain`, `messages.openai` |
525
+ | `sdk.progress` | Progress update | `title`, `status`, `percent` |
526
+ | `sdk.tool.requested` | Tool call requested | `tool_call_id`, `server_name`, `tool_name`, `tool_args`, `pending_approval` |
527
+ | `sdk.tool.approved` | Tool approved/denied | `tool_call_id`, `approved`, `reason` |
528
+ | `sdk.tool.executed` | Tool finished | `tool_call_id`, `result.isError`, `result.content` |
529
+ | `sdk.error` | Error occurred | `message`, `cause` |
530
+ | `sdk.final` | Run completed | `success`, `result.structured_output`, `result.final_output`, `messages` |
531
+
532
+ ---
533
+
534
+ ## QodoSDK Options Reference
535
+
536
+ ```typescript
537
+ interface QodoSDKOptions {
538
+ // Agent configuration (mutually exclusive)
539
+ agentFile?: string; // Path to agent.toml/yaml
540
+ agentContent?: string; // Raw TOML/YAML content
541
+ agentObject?: AIAssistantConfig; // Programmatic config
542
+
543
+ // MCP servers
544
+ mcpFile?: string; // Path to mcp.json
545
+ mcpServers?: Record<string, MCPConfig>; // Inline server configs
546
+
547
+ // Execution settings
548
+ model?: string; // Model override
549
+ projectPath?: string; // Working directory
550
+ additionalPaths?: string[]; // Extra accessible paths
551
+
552
+ // Tool handling
553
+ autoApproveTools?: boolean; // Auto-approve tools (default: true)
554
+ toolApproval?: (req) => Promise<boolean> | boolean; // Custom approval
555
+
556
+ // Session
557
+ contextSessionIds?: string[]; // Previous sessions for context
558
+
559
+ // Backend
560
+ backend?: { baseUrl?: string }; // Backend URL override
561
+
562
+ // Debugging
563
+ debug?: boolean; // Enable debug logging
564
+ logger?: QodoSDKLogger; // Custom logger
565
+
566
+ // Mode
567
+ interactiveMode?: boolean; // Enable interactive clarifications
568
+ }
569
+ ```
570
+
571
+ ---
572
+
573
+ ## Common Tasks
574
+
575
+ ### Adding a New Command to an Existing Agent
576
+
577
+ 1. Define the command with `sdkCommand()`:
578
+ ```typescript
579
+ const newCommand = sdkCommand({
580
+ name: 'newCommand',
581
+ description: 'What this command does',
582
+ instructions: 'Detailed instructions for the AI',
583
+ available_tools: ['filesystem', 'ripgrep'],
584
+ args: sdkArgs({
585
+ // Define your args
586
+ }),
587
+ output: z.object({
588
+ // Define your output with .describe() on every field
589
+ }),
590
+ });
591
+ ```
592
+
593
+ 2. Add to agent's commands:
594
+ ```typescript
595
+ const agent = sdkAgent({
596
+ commands: {
597
+ existingCommand,
598
+ newCommand, // Add here
599
+ },
600
+ });
601
+ ```
602
+
603
+ ### Converting TOML to Programmatic TypeScript
604
+
605
+ Read the TOML and translate each section:
606
+
607
+ ```typescript
608
+ // From TOML:
609
+ // [commands.analyze]
610
+ // name = "analyze"
611
+ // description = "Analyze code"
612
+ // available_tools = ["filesystem"]
613
+
614
+ // To TypeScript:
615
+ import { sdkCommand, sdkArgs, z } from '@qodo/sdk';
616
+
617
+ const analyze = sdkCommand({
618
+ name: 'analyze',
619
+ description: 'Analyze code',
620
+ available_tools: ['filesystem'],
621
+ args: sdkArgs({ /* from [commands.analyze.arguments] */ }),
622
+ output: z.object({ /* from [commands.analyze.output_schema] */ }),
623
+ });
624
+ ```
625
+
626
+ ### Debugging Schema Validation Errors
627
+
628
+ When you see `QodoSchemaError: output schema is missing description for: fieldName`:
629
+
630
+ 1. Find the field in your Zod schema
631
+ 2. Add `.describe('...')` to it
632
+ 3. Check nested objects - all properties need descriptions
633
+
634
+ ```typescript
635
+ // Before (error)
636
+ z.object({
637
+ items: z.array(z.object({
638
+ name: z.string(), // Missing description!
639
+ })),
640
+ })
641
+
642
+ // After (fixed)
643
+ z.object({
644
+ items: z.array(z.object({
645
+ name: z.string().describe('Item name'),
646
+ })).describe('List of items'),
647
+ })
648
+ ```
649
+
650
+ ---
651
+
652
+ ## Additional Resources
653
+
654
+ - [assets/programmatic-agent.ts](assets/programmatic-agent.ts) - Complete working TypeScript agent template
655
+ - [references/builtin-tools.md](references/builtin-tools.md) - Detailed guide to filesystem, git, ripgrep, and shell tools
656
+ - [references/common-issues.md](references/common-issues.md) - Troubleshooting guide for common problems