ai-eng-system 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/dist/.claude-plugin/agents/agent-creator.md +206 -0
- package/dist/.claude-plugin/agents/ai_engineer.md +187 -0
- package/dist/.claude-plugin/agents/api_builder_enhanced.md +82 -0
- package/dist/.claude-plugin/agents/architect-advisor.md +88 -0
- package/dist/.claude-plugin/agents/backend_architect.md +88 -0
- package/dist/.claude-plugin/agents/code_reviewer.md +208 -0
- package/dist/.claude-plugin/agents/command-creator.md +331 -0
- package/dist/.claude-plugin/agents/cost_optimizer.md +284 -0
- package/dist/.claude-plugin/agents/database_optimizer.md +175 -0
- package/dist/.claude-plugin/agents/deployment_engineer.md +186 -0
- package/dist/.claude-plugin/agents/docs-writer.md +99 -0
- package/dist/.claude-plugin/agents/documentation_specialist.md +212 -0
- package/dist/.claude-plugin/agents/frontend-reviewer.md +51 -0
- package/dist/.claude-plugin/agents/full_stack_developer.md +391 -0
- package/dist/.claude-plugin/agents/infrastructure_builder.md +77 -0
- package/dist/.claude-plugin/agents/java-pro.md +182 -0
- package/dist/.claude-plugin/agents/ml_engineer.md +176 -0
- package/dist/.claude-plugin/agents/monitoring_expert.md +79 -0
- package/dist/.claude-plugin/agents/performance_engineer.md +193 -0
- package/dist/.claude-plugin/agents/plugin-validator.md +378 -0
- package/dist/.claude-plugin/agents/prompt-optimizer.md +63 -0
- package/dist/.claude-plugin/agents/security_scanner.md +332 -0
- package/dist/.claude-plugin/agents/seo-specialist.md +73 -0
- package/dist/.claude-plugin/agents/skill-creator.md +311 -0
- package/dist/.claude-plugin/agents/test-docs-writer-2.md +46 -0
- package/dist/.claude-plugin/agents/test-docs-writer-usage.md +40 -0
- package/dist/.claude-plugin/agents/test-docs-writer.md +98 -0
- package/dist/.claude-plugin/agents/test_generator.md +260 -0
- package/dist/.claude-plugin/agents/tool-creator.md +474 -0
- package/dist/.claude-plugin/commands/compound.md +26 -0
- package/dist/.claude-plugin/commands/context.md +318 -0
- package/dist/.claude-plugin/commands/create-agent.md +48 -0
- package/dist/.claude-plugin/commands/create-command.md +48 -0
- package/dist/.claude-plugin/commands/create-plugin.md +400 -0
- package/dist/.claude-plugin/commands/create-skill.md +48 -0
- package/dist/.claude-plugin/commands/create-tool.md +53 -0
- package/dist/.claude-plugin/commands/deploy.md +35 -0
- package/dist/.claude-plugin/commands/optimize.md +79 -0
- package/dist/.claude-plugin/commands/plan.md +215 -0
- package/dist/.claude-plugin/commands/recursive-init.md +217 -0
- package/dist/.claude-plugin/commands/research.md +199 -0
- package/dist/.claude-plugin/commands/review.md +73 -0
- package/dist/.claude-plugin/commands/seo.md +40 -0
- package/dist/.claude-plugin/commands/work.md +460 -0
- package/dist/.claude-plugin/hooks.json +15 -0
- package/dist/.claude-plugin/marketplace.json +54 -0
- package/dist/.claude-plugin/plugin.json +24 -0
- package/dist/.claude-plugin/skills/AGENTS.md +37 -0
- package/dist/.claude-plugin/skills/devops/coolify-deploy/SKILL.md +8 -0
- package/dist/.claude-plugin/skills/devops/git-worktree/SKILL.md +11 -0
- package/dist/.claude-plugin/skills/plugin-dev/SKILL.md +322 -0
- package/dist/.claude-plugin/skills/plugin-dev/references/agent-format.md +248 -0
- package/dist/.claude-plugin/skills/plugin-dev/references/claude-code-plugins.md +372 -0
- package/dist/.claude-plugin/skills/plugin-dev/references/command-format.md +312 -0
- package/dist/.claude-plugin/skills/plugin-dev/references/opencode-plugins.md +406 -0
- package/dist/.claude-plugin/skills/plugin-dev/references/opencode-tools.md +470 -0
- package/dist/.claude-plugin/skills/plugin-dev/references/skill-format.md +328 -0
- package/dist/.claude-plugin/skills/prompting/incentive-prompting/SKILL.md +162 -0
- package/dist/.claude-plugin/skills/research/comprehensive-research/SKILL.md +343 -0
- package/dist/.opencode/agent/ai-eng/ai-innovation/ai_engineer.md +186 -0
- package/dist/.opencode/agent/ai-eng/ai-innovation/ml_engineer.md +175 -0
- package/dist/.opencode/agent/ai-eng/ai-innovation/prompt-optimizer.md +62 -0
- package/dist/.opencode/agent/ai-eng/business-analytics/seo-specialist.md +72 -0
- package/dist/.opencode/agent/ai-eng/development/api_builder_enhanced.md +81 -0
- package/dist/.opencode/agent/ai-eng/development/architect-advisor.md +87 -0
- package/dist/.opencode/agent/ai-eng/development/backend_architect.md +87 -0
- package/dist/.opencode/agent/ai-eng/development/database_optimizer.md +174 -0
- package/dist/.opencode/agent/ai-eng/development/docs-writer.md +98 -0
- package/dist/.opencode/agent/ai-eng/development/documentation_specialist.md +211 -0
- package/dist/.opencode/agent/ai-eng/development/frontend-reviewer.md +50 -0
- package/dist/.opencode/agent/ai-eng/development/full_stack_developer.md +390 -0
- package/dist/.opencode/agent/ai-eng/development/java-pro.md +181 -0
- package/dist/.opencode/agent/ai-eng/development/test-docs-writer-2.md +45 -0
- package/dist/.opencode/agent/ai-eng/development/test-docs-writer-usage.md +39 -0
- package/dist/.opencode/agent/ai-eng/development/test-docs-writer.md +97 -0
- package/dist/.opencode/agent/ai-eng/meta/agent-creator.md +208 -0
- package/dist/.opencode/agent/ai-eng/meta/command-creator.md +333 -0
- package/dist/.opencode/agent/ai-eng/meta/skill-creator.md +313 -0
- package/dist/.opencode/agent/ai-eng/meta/tool-creator.md +476 -0
- package/dist/.opencode/agent/ai-eng/operations/cost_optimizer.md +283 -0
- package/dist/.opencode/agent/ai-eng/operations/deployment_engineer.md +185 -0
- package/dist/.opencode/agent/ai-eng/operations/infrastructure_builder.md +76 -0
- package/dist/.opencode/agent/ai-eng/operations/monitoring_expert.md +78 -0
- package/dist/.opencode/agent/ai-eng/quality-testing/code_reviewer.md +207 -0
- package/dist/.opencode/agent/ai-eng/quality-testing/performance_engineer.md +192 -0
- package/dist/.opencode/agent/ai-eng/quality-testing/plugin-validator.md +380 -0
- package/dist/.opencode/agent/ai-eng/quality-testing/security_scanner.md +331 -0
- package/dist/.opencode/agent/ai-eng/quality-testing/test_generator.md +259 -0
- package/dist/.opencode/command/ai-eng/compound.md +26 -0
- package/dist/.opencode/command/ai-eng/context.md +318 -0
- package/dist/.opencode/command/ai-eng/create-agent.md +48 -0
- package/dist/.opencode/command/ai-eng/create-command.md +48 -0
- package/dist/.opencode/command/ai-eng/create-plugin.md +400 -0
- package/dist/.opencode/command/ai-eng/create-skill.md +48 -0
- package/dist/.opencode/command/ai-eng/create-tool.md +53 -0
- package/dist/.opencode/command/ai-eng/deploy.md +35 -0
- package/dist/.opencode/command/ai-eng/optimize.md +79 -0
- package/dist/.opencode/command/ai-eng/plan.md +215 -0
- package/dist/.opencode/command/ai-eng/recursive-init.md +217 -0
- package/dist/.opencode/command/ai-eng/research.md +199 -0
- package/dist/.opencode/command/ai-eng/review.md +73 -0
- package/dist/.opencode/command/ai-eng/seo.md +40 -0
- package/dist/.opencode/command/ai-eng/work.md +460 -0
- package/dist/.opencode/opencode.jsonc +8 -0
- package/dist/.opencode/plugin/ai-eng-system.ts +10 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +13 -0
- package/dist/skills/AGENTS.md +37 -0
- package/dist/skills/devops/coolify-deploy/SKILL.md +8 -0
- package/dist/skills/devops/git-worktree/SKILL.md +11 -0
- package/dist/skills/plugin-dev/SKILL.md +322 -0
- package/dist/skills/plugin-dev/references/agent-format.md +248 -0
- package/dist/skills/plugin-dev/references/claude-code-plugins.md +372 -0
- package/dist/skills/plugin-dev/references/command-format.md +312 -0
- package/dist/skills/plugin-dev/references/opencode-plugins.md +406 -0
- package/dist/skills/plugin-dev/references/opencode-tools.md +470 -0
- package/dist/skills/plugin-dev/references/skill-format.md +328 -0
- package/dist/skills/prompting/incentive-prompting/SKILL.md +162 -0
- package/dist/skills/research/comprehensive-research/SKILL.md +343 -0
- package/package.json +73 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
# OpenCode Custom Tools Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
OpenCode supports custom tools through TypeScript files using the `tool()` helper from `@opencode-ai/plugin`. This is a powerful feature unique to OpenCode that allows extending functionality with executable code.
|
|
6
|
+
|
|
7
|
+
## Tool Format
|
|
8
|
+
|
|
9
|
+
### Basic Structure
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { tool } from "@opencode-ai/plugin"
|
|
13
|
+
|
|
14
|
+
export default tool({
|
|
15
|
+
description: "Tool description",
|
|
16
|
+
args: {
|
|
17
|
+
param1: tool.schema.string().describe("Parameter description"),
|
|
18
|
+
param2: tool.schema.number().describe("Number parameter"),
|
|
19
|
+
},
|
|
20
|
+
async execute(args, context) {
|
|
21
|
+
// Tool implementation
|
|
22
|
+
return result
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Multiple Tools
|
|
28
|
+
|
|
29
|
+
Export multiple tools from one file:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { tool } from "@opencode-ai/plugin"
|
|
33
|
+
|
|
34
|
+
export const add = tool({
|
|
35
|
+
description: "Add two numbers",
|
|
36
|
+
args: {
|
|
37
|
+
a: tool.schema.number().describe("First number"),
|
|
38
|
+
b: tool.schema.number().describe("Second number"),
|
|
39
|
+
},
|
|
40
|
+
async execute(args) {
|
|
41
|
+
return args.a + args.b
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
export const multiply = tool({
|
|
46
|
+
description: "Multiply two numbers",
|
|
47
|
+
args: {
|
|
48
|
+
a: tool.schema.number().describe("First number"),
|
|
49
|
+
b: tool.schema.number().describe("Second number"),
|
|
50
|
+
},
|
|
51
|
+
async execute(args) {
|
|
52
|
+
return args.a * args.b
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// Creates: math_add and math_multiply tools
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Schema Validation
|
|
60
|
+
|
|
61
|
+
### Zod Integration
|
|
62
|
+
|
|
63
|
+
OpenCode uses Zod for runtime validation:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { tool } from "@opencode-ai/plugin"
|
|
67
|
+
import { z } from "zod"
|
|
68
|
+
|
|
69
|
+
export default tool({
|
|
70
|
+
description: "Create user with validation",
|
|
71
|
+
args: {
|
|
72
|
+
email: z.string().email().describe("Valid email address"),
|
|
73
|
+
age: z.number().min(18).describe("User age (18+)"),
|
|
74
|
+
name: z.string().min(2).describe("Full name (min 2 chars)"),
|
|
75
|
+
},
|
|
76
|
+
async execute(args, context) {
|
|
77
|
+
// Zod validates args before execution
|
|
78
|
+
return `User: ${args.name}, Age: ${args.age}, Email: ${args.email}`
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Advanced Schemas
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { tool } from "@opencode-ai/plugin"
|
|
87
|
+
import { z } from "zod"
|
|
88
|
+
|
|
89
|
+
export default tool({
|
|
90
|
+
description: "Complex configuration tool",
|
|
91
|
+
args: {
|
|
92
|
+
config: z.object({
|
|
93
|
+
database: z.object({
|
|
94
|
+
host: z.string().describe("Database host"),
|
|
95
|
+
port: z.number().min(1).max(65535).describe("Database port"),
|
|
96
|
+
ssl: z.boolean().describe("Use SSL connection"),
|
|
97
|
+
}),
|
|
98
|
+
features: z.array(z.enum(["analytics", "logging", "caching"])).describe("Enabled features"),
|
|
99
|
+
}),
|
|
100
|
+
options: z.record(z.string(), z.any()).describe("Additional options"),
|
|
101
|
+
},
|
|
102
|
+
async execute(args, context) {
|
|
103
|
+
// Complex nested validation
|
|
104
|
+
return `Config: ${JSON.stringify(args.config)}`
|
|
105
|
+
},
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Context Access
|
|
110
|
+
|
|
111
|
+
### Available Context
|
|
112
|
+
|
|
113
|
+
Tools receive context about the current session:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
async execute(args, context) {
|
|
117
|
+
const { agent, sessionID, messageID } = context
|
|
118
|
+
|
|
119
|
+
console.log(`Running in ${agent} context`)
|
|
120
|
+
console.log(`Session: ${sessionID}`)
|
|
121
|
+
console.log(`Message: ${messageID}`)
|
|
122
|
+
|
|
123
|
+
// Tool implementation
|
|
124
|
+
return result
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Context Properties
|
|
129
|
+
|
|
130
|
+
| Property | Type | Description |
|
|
131
|
+
|----------|-------|-------------|
|
|
132
|
+
| **agent** | string | Current agent name |
|
|
133
|
+
| **sessionID** | string | Current session identifier |
|
|
134
|
+
| **messageID** | string | Current message identifier |
|
|
135
|
+
|
|
136
|
+
## Tool Categories
|
|
137
|
+
|
|
138
|
+
### File Operations
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
export default tool({
|
|
142
|
+
description: "Read and parse configuration file",
|
|
143
|
+
args: {
|
|
144
|
+
filePath: tool.schema.string().describe("Path to config file"),
|
|
145
|
+
},
|
|
146
|
+
async execute(args, context) {
|
|
147
|
+
const content = await Bun.file(args.filePath).text()
|
|
148
|
+
const config = JSON.parse(content)
|
|
149
|
+
return config
|
|
150
|
+
},
|
|
151
|
+
})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### System Integration
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
export default tool({
|
|
158
|
+
description: "Execute system command safely",
|
|
159
|
+
args: {
|
|
160
|
+
command: tool.schema.string().describe("Command to execute"),
|
|
161
|
+
args: tool.schema.array(tool.schema.string()).describe("Command arguments"),
|
|
162
|
+
},
|
|
163
|
+
async execute(args, context) {
|
|
164
|
+
// Safe command execution
|
|
165
|
+
const allowedCommands = ['git', 'npm', 'ls']
|
|
166
|
+
if (!allowedCommands.includes(args.command)) {
|
|
167
|
+
throw new Error(`Command not allowed: ${args.command}`)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const result = await Bun.$([args.command, ...args.args]).text()
|
|
171
|
+
return result.trim()
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### External API
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
export default tool({
|
|
180
|
+
description: "Query external API",
|
|
181
|
+
args: {
|
|
182
|
+
endpoint: tool.schema.string().describe("API endpoint"),
|
|
183
|
+
query: tool.schema.string().describe("Query parameters"),
|
|
184
|
+
},
|
|
185
|
+
async execute(args, context) {
|
|
186
|
+
const url = `https://api.example.com/${args.endpoint}`
|
|
187
|
+
const response = await fetch(url, {
|
|
188
|
+
method: 'POST',
|
|
189
|
+
body: JSON.stringify({ query: args.query }),
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
if (!response.ok) {
|
|
193
|
+
throw new Error(`API request failed: ${response.status}`)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const data = await response.json()
|
|
197
|
+
return data
|
|
198
|
+
},
|
|
199
|
+
})
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Database Operations
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
export default tool({
|
|
206
|
+
description: "Execute database query",
|
|
207
|
+
args: {
|
|
208
|
+
sql: tool.schema.string().describe("SQL query to execute"),
|
|
209
|
+
},
|
|
210
|
+
async execute(args, context) {
|
|
211
|
+
// Database connection and query execution
|
|
212
|
+
const result = await Bun.$`psql $DATABASE_URL -c "${args.sql}"`.text()
|
|
213
|
+
return result
|
|
214
|
+
},
|
|
215
|
+
})
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Best Practices
|
|
219
|
+
|
|
220
|
+
### Error Handling
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
export default tool({
|
|
224
|
+
description: "Robust file operations",
|
|
225
|
+
args: {
|
|
226
|
+
path: tool.schema.string().describe("File path"),
|
|
227
|
+
},
|
|
228
|
+
async execute(args, context) {
|
|
229
|
+
try {
|
|
230
|
+
const content = await Bun.file(args.path).text()
|
|
231
|
+
return { success: true, content }
|
|
232
|
+
} catch (error) {
|
|
233
|
+
return {
|
|
234
|
+
success: false,
|
|
235
|
+
error: error.message,
|
|
236
|
+
code: 'FILE_READ_ERROR'
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
})
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Input Validation
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
export default tool({
|
|
247
|
+
description: "Secure file creation",
|
|
248
|
+
args: {
|
|
249
|
+
filename: tool.schema.string()
|
|
250
|
+
.regex(/^[a-zA-Z0-9._-]+$/)
|
|
251
|
+
.describe("Valid filename"),
|
|
252
|
+
content: tool.schema.string().min(1).describe("File content"),
|
|
253
|
+
},
|
|
254
|
+
async execute(args, context) {
|
|
255
|
+
// Sanitize filename
|
|
256
|
+
const safeFilename = args.filename.replace(/[^a-zA-Z0-9._-]/g, '_')
|
|
257
|
+
|
|
258
|
+
// Validate content
|
|
259
|
+
if (args.content.length > 10000) {
|
|
260
|
+
throw new Error("Content too long (max 10k chars)")
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
await Bun.write(`${safeFilename}.txt`, args.content)
|
|
264
|
+
return `Created: ${safeFilename}.txt`
|
|
265
|
+
},
|
|
266
|
+
})
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Security
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
export default tool({
|
|
273
|
+
description: "Secure credential management",
|
|
274
|
+
args: {
|
|
275
|
+
service: tool.schema.string().describe("Service name"),
|
|
276
|
+
},
|
|
277
|
+
async execute(args, context) {
|
|
278
|
+
// Never log credentials
|
|
279
|
+
const credential = process.env[`${args.service.toUpperCase()}_API_KEY`]
|
|
280
|
+
|
|
281
|
+
if (!credential) {
|
|
282
|
+
throw new Error(`Credential not found for ${args.service}`)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Use credential without exposing it
|
|
286
|
+
const result = await fetch(`https://api.${args.service}.com/verify`, {
|
|
287
|
+
headers: { 'Authorization': `Bearer ${credential}` }
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
return { service: args.service, status: 'verified' }
|
|
291
|
+
},
|
|
292
|
+
})
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Integration with Plugin-Dev
|
|
296
|
+
|
|
297
|
+
### Tool Creator Agent
|
|
298
|
+
|
|
299
|
+
The `ai-eng/tool-creator` agent helps create custom tools:
|
|
300
|
+
|
|
301
|
+
```yaml
|
|
302
|
+
---
|
|
303
|
+
name: tool-creator
|
|
304
|
+
description: Use this agent when user asks to "create a tool", "build a custom tool", "make a tool that...", or needs TypeScript tool development assistance.
|
|
305
|
+
mode: subagent
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
You are a TypeScript tool development expert...
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Tool Generation Workflow
|
|
312
|
+
|
|
313
|
+
1. **Requirements Analysis**: Understand tool purpose
|
|
314
|
+
2. **Schema Design**: Create Zod validation
|
|
315
|
+
3. **Implementation**: Write TypeScript code
|
|
316
|
+
4. **Testing**: Verify tool functionality
|
|
317
|
+
5. **Documentation**: Add usage examples
|
|
318
|
+
|
|
319
|
+
## Tool Locations
|
|
320
|
+
|
|
321
|
+
### Project-Local
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
.opencode/tool/
|
|
325
|
+
├── my-tool.ts
|
|
326
|
+
├── database-query.ts
|
|
327
|
+
└── api-client.ts
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Global
|
|
331
|
+
|
|
332
|
+
```
|
|
333
|
+
~/.config/opencode/tool/
|
|
334
|
+
├── git-helper.ts
|
|
335
|
+
├── file-operations.ts
|
|
336
|
+
└── system-integration.ts
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Advanced Features
|
|
340
|
+
|
|
341
|
+
### Async Operations
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
export default tool({
|
|
345
|
+
description: "Async file processing",
|
|
346
|
+
args: {
|
|
347
|
+
files: tool.schema.array(tool.schema.string()).describe("Files to process"),
|
|
348
|
+
},
|
|
349
|
+
async execute(args, context) {
|
|
350
|
+
const results = []
|
|
351
|
+
|
|
352
|
+
for (const file of args.files) {
|
|
353
|
+
const content = await Bun.file(file).text()
|
|
354
|
+
const processed = await processContent(content)
|
|
355
|
+
results.push({ file, processed })
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return results
|
|
359
|
+
},
|
|
360
|
+
})
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Streaming Results
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
export default tool({
|
|
367
|
+
description: "Stream large dataset",
|
|
368
|
+
args: {
|
|
369
|
+
source: tool.schema.string().describe("Data source URL"),
|
|
370
|
+
},
|
|
371
|
+
async execute(args, context) {
|
|
372
|
+
const response = await fetch(args.source)
|
|
373
|
+
|
|
374
|
+
// Stream processing for large data
|
|
375
|
+
const reader = response.body?.getReader()
|
|
376
|
+
if (!reader) return
|
|
377
|
+
|
|
378
|
+
let processed = 0
|
|
379
|
+
while (true) {
|
|
380
|
+
const { done, value } = await reader.read()
|
|
381
|
+
if (done) break
|
|
382
|
+
|
|
383
|
+
// Process chunk
|
|
384
|
+
processed += value.length
|
|
385
|
+
|
|
386
|
+
// Yield progress
|
|
387
|
+
yield { processed, total: response.headers.get('content-length') }
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
})
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Configuration Management
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
export default tool({
|
|
397
|
+
description: "Manage tool configuration",
|
|
398
|
+
args: {
|
|
399
|
+
action: tool.schema.enum(['get', 'set', 'list']).describe("Configuration action"),
|
|
400
|
+
key: tool.schema.string().describe("Configuration key"),
|
|
401
|
+
value: tool.schema.any().describe("Configuration value"),
|
|
402
|
+
},
|
|
403
|
+
async execute(args, context) {
|
|
404
|
+
const configPath = '.tool-config.json'
|
|
405
|
+
|
|
406
|
+
switch (args.action) {
|
|
407
|
+
case 'get':
|
|
408
|
+
const config = JSON.parse(await Bun.file(configPath).text())
|
|
409
|
+
return config[args.key] || null
|
|
410
|
+
|
|
411
|
+
case 'set':
|
|
412
|
+
const config = JSON.parse(await Bun.file(configPath).text())
|
|
413
|
+
config[args.key] = args.value
|
|
414
|
+
await Bun.write(configPath, JSON.stringify(config, null, 2))
|
|
415
|
+
return `Set ${args.key} = ${args.value}`
|
|
416
|
+
|
|
417
|
+
case 'list':
|
|
418
|
+
const config = JSON.parse(await Bun.file(configPath).text())
|
|
419
|
+
return config
|
|
420
|
+
|
|
421
|
+
default:
|
|
422
|
+
throw new Error(`Invalid action: ${args.action}`)
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
})
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## Testing
|
|
429
|
+
|
|
430
|
+
### Unit Testing
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
import { describe, it, expect } from 'bun:test'
|
|
434
|
+
import myTool from './my-tool'
|
|
435
|
+
|
|
436
|
+
describe('myTool', () => {
|
|
437
|
+
it('should validate input correctly', async () => {
|
|
438
|
+
const result = await myTool.execute({
|
|
439
|
+
param: 'valid-input'
|
|
440
|
+
}, {})
|
|
441
|
+
|
|
442
|
+
expect(result).toContain('success')
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
it('should reject invalid input', async () => {
|
|
446
|
+
await expect(async () =>
|
|
447
|
+
myTool.execute({ param: 'invalid-input' }, {})
|
|
448
|
+
).toThrow('Invalid input')
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Integration Testing
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
// Test tool in OpenCode context
|
|
457
|
+
import myTool from './my-tool'
|
|
458
|
+
|
|
459
|
+
// Mock OpenCode context
|
|
460
|
+
const mockContext = {
|
|
461
|
+
agent: 'test',
|
|
462
|
+
sessionID: 'test-session',
|
|
463
|
+
messageID: 'test-message'
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const result = await myTool.execute({ param: 'test' }, mockContext)
|
|
467
|
+
console.log('Tool result:', result)
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Custom tools provide a powerful way to extend OpenCode with domain-specific functionality while maintaining type safety and validation.
|