@botlearn/code-gen 0.1.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.
@@ -0,0 +1,344 @@
1
+ ---
2
+ domain: code-gen
3
+ topic: design-patterns-and-language-idioms
4
+ priority: high
5
+ ttl: 30d
6
+ ---
7
+
8
+ # Code Generation — Design Patterns, Async Patterns & Error Handling
9
+
10
+ ## Creational Design Patterns
11
+
12
+ ### Factory Pattern
13
+ - Use when object creation logic is complex or depends on runtime conditions
14
+ - Encapsulate construction behind a factory function or class method
15
+ - Return interface types rather than concrete implementations
16
+ ```typescript
17
+ interface Logger { log(msg: string): void; }
18
+ function createLogger(type: "console" | "file" | "remote"): Logger {
19
+ switch (type) {
20
+ case "console": return new ConsoleLogger();
21
+ case "file": return new FileLogger();
22
+ case "remote": return new RemoteLogger();
23
+ default: throw new InvalidLoggerTypeError(type);
24
+ }
25
+ }
26
+ ```
27
+
28
+ ### Builder Pattern
29
+ - Use for constructing complex objects with many optional parameters
30
+ - Prefer over constructors with 4+ parameters
31
+ - Chain methods and return `this` for fluent API
32
+ ```typescript
33
+ const query = new QueryBuilder()
34
+ .select("name", "email")
35
+ .from("users")
36
+ .where("active", true)
37
+ .orderBy("created_at", "desc")
38
+ .limit(50)
39
+ .build();
40
+ ```
41
+
42
+ ### Singleton / Module Pattern
43
+ - Use for shared resources: database connections, configuration, caches
44
+ - In modern JS/TS: prefer module-level instances over class-based singletons
45
+ - Always make singletons injectable for testability
46
+ ```typescript
47
+ // Module singleton (preferred)
48
+ const config = loadConfig();
49
+ export { config };
50
+
51
+ // Injectable singleton (testable)
52
+ let instance: DbPool | null = null;
53
+ export function getPool(factory = createPool): DbPool {
54
+ if (!instance) instance = factory();
55
+ return instance;
56
+ }
57
+ ```
58
+
59
+ ## Structural Design Patterns
60
+
61
+ ### Adapter Pattern
62
+ - Use to wrap third-party libraries behind your own interface
63
+ - Isolates vendor lock-in; makes swapping implementations easy
64
+ ```typescript
65
+ interface StorageAdapter {
66
+ get(key: string): Promise<string | null>;
67
+ set(key: string, value: string, ttl?: number): Promise<void>;
68
+ delete(key: string): Promise<void>;
69
+ }
70
+ // RedisAdapter, MemcachedAdapter, InMemoryAdapter all implement StorageAdapter
71
+ ```
72
+
73
+ ### Repository Pattern
74
+ - Abstract data access behind a repository interface
75
+ - Keep business logic free from database query details
76
+ ```typescript
77
+ interface UserRepository {
78
+ findById(id: string): Promise<User | null>;
79
+ findByEmail(email: string): Promise<User | null>;
80
+ create(data: CreateUserDTO): Promise<User>;
81
+ update(id: string, data: UpdateUserDTO): Promise<User>;
82
+ delete(id: string): Promise<void>;
83
+ }
84
+ ```
85
+
86
+ ### Middleware / Pipeline Pattern
87
+ - Chain processing steps for request handling, data transformation, or validation
88
+ - Each middleware receives context and a `next` function
89
+ ```typescript
90
+ type Middleware<T> = (ctx: T, next: () => Promise<void>) => Promise<void>;
91
+
92
+ function compose<T>(middlewares: Middleware<T>[]): Middleware<T> {
93
+ return (ctx, next) => {
94
+ let index = -1;
95
+ function dispatch(i: number): Promise<void> {
96
+ if (i <= index) return Promise.reject(new Error("next() called multiple times"));
97
+ index = i;
98
+ const fn = i === middlewares.length ? next : middlewares[i];
99
+ return fn(ctx, () => dispatch(i + 1));
100
+ }
101
+ return dispatch(0);
102
+ };
103
+ }
104
+ ```
105
+
106
+ ## Behavioral Design Patterns
107
+
108
+ ### Strategy Pattern
109
+ - Use when an algorithm needs to vary at runtime
110
+ - Define a common interface; inject the desired strategy
111
+ ```typescript
112
+ interface CompressionStrategy {
113
+ compress(data: Buffer): Promise<Buffer>;
114
+ decompress(data: Buffer): Promise<Buffer>;
115
+ }
116
+ // GzipStrategy, BrotliStrategy, LZ4Strategy all implement CompressionStrategy
117
+ ```
118
+
119
+ ### Observer / Event Emitter Pattern
120
+ - Use for decoupled communication between components
121
+ - Prefer typed event maps over string-based events
122
+ ```typescript
123
+ type EventMap = {
124
+ "user:created": { id: string; email: string };
125
+ "user:deleted": { id: string };
126
+ "order:completed": { orderId: string; total: number };
127
+ };
128
+
129
+ interface TypedEmitter<T extends Record<string, unknown>> {
130
+ on<K extends keyof T>(event: K, handler: (data: T[K]) => void): void;
131
+ emit<K extends keyof T>(event: K, data: T[K]): void;
132
+ }
133
+ ```
134
+
135
+ ## Async Patterns
136
+
137
+ ### Promise Composition
138
+ ```typescript
139
+ // Parallel execution — use when tasks are independent
140
+ const [users, orders, products] = await Promise.all([
141
+ fetchUsers(),
142
+ fetchOrders(),
143
+ fetchProducts(),
144
+ ]);
145
+
146
+ // Settled — use when you need results even if some fail
147
+ const results = await Promise.allSettled([
148
+ riskyOperation1(),
149
+ riskyOperation2(),
150
+ ]);
151
+ const successes = results.filter(r => r.status === "fulfilled");
152
+ const failures = results.filter(r => r.status === "rejected");
153
+ ```
154
+
155
+ ### Retry with Exponential Backoff
156
+ ```typescript
157
+ async function withRetry<T>(
158
+ fn: () => Promise<T>,
159
+ options: { maxRetries: number; baseDelay: number; maxDelay: number }
160
+ ): Promise<T> {
161
+ for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
162
+ try {
163
+ return await fn();
164
+ } catch (error) {
165
+ if (attempt === options.maxRetries) throw error;
166
+ const delay = Math.min(
167
+ options.baseDelay * Math.pow(2, attempt) + Math.random() * 100,
168
+ options.maxDelay
169
+ );
170
+ await new Promise(resolve => setTimeout(resolve, delay));
171
+ }
172
+ }
173
+ throw new Error("Unreachable");
174
+ }
175
+ ```
176
+
177
+ ### Async Iterator / Stream Processing
178
+ ```typescript
179
+ async function* paginate<T>(
180
+ fetchPage: (cursor: string | null) => Promise<{ data: T[]; nextCursor: string | null }>
181
+ ): AsyncGenerator<T> {
182
+ let cursor: string | null = null;
183
+ do {
184
+ const { data, nextCursor } = await fetchPage(cursor);
185
+ for (const item of data) yield item;
186
+ cursor = nextCursor;
187
+ } while (cursor !== null);
188
+ }
189
+ ```
190
+
191
+ ### Circuit Breaker
192
+ ```typescript
193
+ class CircuitBreaker {
194
+ private failures = 0;
195
+ private lastFailureTime = 0;
196
+ private state: "closed" | "open" | "half-open" = "closed";
197
+
198
+ constructor(
199
+ private readonly threshold: number,
200
+ private readonly resetTimeoutMs: number
201
+ ) {}
202
+
203
+ async execute<T>(fn: () => Promise<T>): Promise<T> {
204
+ if (this.state === "open") {
205
+ if (Date.now() - this.lastFailureTime > this.resetTimeoutMs) {
206
+ this.state = "half-open";
207
+ } else {
208
+ throw new CircuitOpenError("Circuit breaker is open");
209
+ }
210
+ }
211
+ try {
212
+ const result = await fn();
213
+ this.onSuccess();
214
+ return result;
215
+ } catch (error) {
216
+ this.onFailure();
217
+ throw error;
218
+ }
219
+ }
220
+
221
+ private onSuccess(): void {
222
+ this.failures = 0;
223
+ this.state = "closed";
224
+ }
225
+
226
+ private onFailure(): void {
227
+ this.failures++;
228
+ this.lastFailureTime = Date.now();
229
+ if (this.failures >= this.threshold) this.state = "open";
230
+ }
231
+ }
232
+ ```
233
+
234
+ ## Error Handling Patterns
235
+
236
+ ### Custom Error Hierarchy
237
+ ```typescript
238
+ class AppError extends Error {
239
+ constructor(
240
+ message: string,
241
+ public readonly code: string,
242
+ public readonly statusCode: number = 500,
243
+ public readonly isOperational: boolean = true,
244
+ public readonly cause?: Error
245
+ ) {
246
+ super(message);
247
+ this.name = this.constructor.name;
248
+ Error.captureStackTrace(this, this.constructor);
249
+ }
250
+ }
251
+
252
+ class ValidationError extends AppError {
253
+ constructor(message: string, public readonly fields: Record<string, string[]>) {
254
+ super(message, "VALIDATION_ERROR", 400);
255
+ }
256
+ }
257
+
258
+ class NotFoundError extends AppError {
259
+ constructor(resource: string, id: string) {
260
+ super(`${resource} with id '${id}' not found`, "NOT_FOUND", 404);
261
+ }
262
+ }
263
+
264
+ class ExternalServiceError extends AppError {
265
+ constructor(service: string, cause: Error) {
266
+ super(`External service '${service}' failed: ${cause.message}`, "EXTERNAL_SERVICE_ERROR", 502, true, cause);
267
+ }
268
+ }
269
+ ```
270
+
271
+ ### Result Type (Rust-inspired)
272
+ ```typescript
273
+ type Result<T, E = Error> =
274
+ | { ok: true; value: T }
275
+ | { ok: false; error: E };
276
+
277
+ function ok<T>(value: T): Result<T, never> {
278
+ return { ok: true, value };
279
+ }
280
+
281
+ function err<E>(error: E): Result<never, E> {
282
+ return { ok: false, error };
283
+ }
284
+
285
+ // Usage: eliminates try/catch proliferation
286
+ async function parseConfig(path: string): Promise<Result<Config, ConfigError>> {
287
+ const raw = await readFile(path);
288
+ if (!raw) return err(new ConfigError("File not found"));
289
+ const parsed = JSON.parse(raw);
290
+ const validated = configSchema.safeParse(parsed);
291
+ if (!validated.success) return err(new ConfigError(validated.error.message));
292
+ return ok(validated.data);
293
+ }
294
+ ```
295
+
296
+ ### Graceful Degradation
297
+ ```typescript
298
+ async function getUserProfile(userId: string): Promise<UserProfile> {
299
+ const user = await userRepo.findById(userId); // Required — throw on failure
300
+ if (!user) throw new NotFoundError("User", userId);
301
+
302
+ // Optional enrichment — degrade gracefully
303
+ const [avatar, preferences] = await Promise.allSettled([
304
+ avatarService.getAvatar(userId),
305
+ preferencesService.getPreferences(userId),
306
+ ]);
307
+
308
+ return {
309
+ ...user,
310
+ avatar: avatar.status === "fulfilled" ? avatar.value : DEFAULT_AVATAR,
311
+ preferences: preferences.status === "fulfilled" ? preferences.value : DEFAULT_PREFERENCES,
312
+ };
313
+ }
314
+ ```
315
+
316
+ ## Language-Specific Idioms
317
+
318
+ ### TypeScript
319
+ - Use `unknown` instead of `any` for type-safe narrowing
320
+ - Prefer `interface` for object shapes; `type` for unions, intersections, and mapped types
321
+ - Use discriminated unions for state modeling
322
+ - Leverage `as const` for literal types and exhaustive checks
323
+ - Use branded types for domain identifiers (`type UserId = string & { __brand: "UserId" }`)
324
+
325
+ ### Python
326
+ - Use dataclasses or Pydantic models for structured data
327
+ - Use context managers (`with` statement) for resource management
328
+ - Prefer `pathlib.Path` over string-based file operations
329
+ - Use type hints with `TypeVar`, `Generic`, `Protocol` for generic code
330
+ - Use `enum.Enum` for fixed sets of values; `@dataclass(frozen=True)` for value objects
331
+
332
+ ### Go
333
+ - Return `(result, error)` tuples; check errors immediately
334
+ - Use `context.Context` for cancellation and timeout propagation
335
+ - Prefer composition over inheritance via struct embedding
336
+ - Use interfaces implicitly (no `implements` keyword)
337
+ - Use `defer` for cleanup; `sync.WaitGroup` for goroutine coordination
338
+
339
+ ### Rust
340
+ - Leverage the ownership system; prefer `&str` over `String` in function signatures
341
+ - Use `Result<T, E>` and the `?` operator for error propagation
342
+ - Use `enum` for algebraic data types and state machines
343
+ - Implement `From<OtherError>` for custom error types to enable `?`
344
+ - Use `Iterator` trait methods instead of manual loops
package/manifest.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@botlearn/code-gen",
3
+ "version": "0.1.0",
4
+ "description": "Complete code generation with proper architecture, error handling, type safety, and test accompaniment for OpenClaw Agent",
5
+ "category": "programming-assistance",
6
+ "author": "BotLearn",
7
+ "benchmarkDimension": "code-generation",
8
+ "expectedImprovement": 50,
9
+ "dependencies": {},
10
+ "compatibility": {
11
+ "openclaw": ">=0.5.0"
12
+ },
13
+ "files": {
14
+ "skill": "skill.md",
15
+ "knowledge": [
16
+ "knowledge/domain.md",
17
+ "knowledge/best-practices.md",
18
+ "knowledge/anti-patterns.md"
19
+ ],
20
+ "strategies": [
21
+ "strategies/main.md"
22
+ ],
23
+ "smokeTest": "tests/smoke.json",
24
+ "benchmark": "tests/benchmark.json"
25
+ }
26
+ }
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@botlearn/code-gen",
3
+ "version": "0.1.0",
4
+ "description": "Complete code generation with proper architecture, error handling, type safety, and test accompaniment for OpenClaw Agent",
5
+ "type": "module",
6
+ "main": "manifest.json",
7
+ "files": [
8
+ "manifest.json",
9
+ "skill.md",
10
+ "knowledge/",
11
+ "strategies/",
12
+ "tests/",
13
+ "README.md"
14
+ ],
15
+ "keywords": [
16
+ "botlearn",
17
+ "openclaw",
18
+ "skill",
19
+ "programming-assistance"
20
+ ],
21
+ "author": "BotLearn",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/readai-team/botlearn-awesome-skills.git",
26
+ "directory": "packages/skills/code-gen"
27
+ },
28
+ "homepage": "https://github.com/readai-team/botlearn-awesome-skills/tree/main/packages/skills/code-gen",
29
+ "bugs": {
30
+ "url": "https://github.com/readai-team/botlearn-awesome-skills/issues"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ }
35
+ }
package/skill.md ADDED
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: code-gen
3
+ role: Code Generation Specialist
4
+ version: 1.0.0
5
+ triggers:
6
+ - "write code"
7
+ - "generate function"
8
+ - "create API"
9
+ - "implement feature"
10
+ - "code this"
11
+ ---
12
+
13
+ # Role
14
+
15
+ You are a Code Generation Specialist. When activated, you produce complete, production-ready code with proper architecture, comprehensive error handling, strong type safety, and accompanying tests. You transform high-level requirements into well-structured implementations that follow language idioms, framework conventions, and established design patterns.
16
+
17
+ # Capabilities
18
+
19
+ 1. Analyze requirements to determine optimal architecture, language features, and design patterns before writing any code
20
+ 2. Generate complete implementations with proper module structure, interface definitions, error handling, and input validation
21
+ 3. Apply language-specific idioms and framework conventions (e.g., Pythonic patterns, idiomatic Go, modern TypeScript, Rust ownership)
22
+ 4. Produce typed interfaces and data models that enforce correctness at compile time and document intent
23
+ 5. Generate accompanying unit tests, integration tests, and usage examples alongside the implementation
24
+ 6. Implement comprehensive error handling with custom error types, recovery strategies, and meaningful error messages
25
+
26
+ # Constraints
27
+
28
+ 1. Never generate code without first analyzing requirements and choosing an appropriate architecture
29
+ 2. Never omit error handling — every external interaction (I/O, network, parsing, user input) must have explicit error handling
30
+ 3. Never produce untyped code when the language supports a type system — always define interfaces, types, or schemas
31
+ 4. Never skip input validation — all public function parameters must be validated at the boundary
32
+ 5. Never generate code without at least one accompanying test or usage example
33
+ 6. Never use `any` type (TypeScript), bare `except` (Python), or equivalent type-erasure patterns unless explicitly justified
34
+
35
+ # Activation
36
+
37
+ WHEN the user requests code generation or implementation:
38
+ 1. Analyze the requirement to identify scope, constraints, target language, and quality expectations
39
+ 2. Select architecture and design patterns following strategies/main.md
40
+ 3. Apply language idioms and framework conventions from knowledge/domain.md
41
+ 4. Implement with type safety and error handling per knowledge/best-practices.md
42
+ 5. Verify against knowledge/anti-patterns.md to avoid common code generation mistakes
43
+ 6. Output complete implementation with types, error handling, tests, and usage documentation
@@ -0,0 +1,114 @@
1
+ ---
2
+ strategy: code-gen
3
+ version: 1.0.0
4
+ steps: 6
5
+ ---
6
+
7
+ # Code Generation Strategy
8
+
9
+ ## Step 1: Requirement Analysis
10
+ - Parse the user's request to identify: **target language**, **framework/runtime**, **functional requirements**, **non-functional requirements** (performance, scale, security)
11
+ - Classify the task type: utility function / API endpoint / data model / CLI tool / state machine / full-stack feature / library/SDK
12
+ - Identify input/output contract: what data comes in, what data goes out, what types are involved
13
+ - Determine the scope boundary: what this code is responsible for vs. what it delegates
14
+ - IF requirements are ambiguous THEN ask one focused clarifying question before proceeding
15
+ - Extract constraints: target runtime (Node.js, browser, serverless), dependencies allowed, coding standards, existing codebase conventions
16
+
17
+ ## Step 2: Architecture Decision
18
+ - SELECT architecture pattern based on task type and complexity:
19
+ - Simple utility → Pure function with types and validation
20
+ - API endpoint → Controller + Service + Repository layers with DTO types
21
+ - Data pipeline → Pipeline/middleware pattern with typed stages
22
+ - State management → State machine with discriminated union states and typed transitions
23
+ - CLI tool → Command pattern with argument parsing, validation, and help generation
24
+ - Library/SDK → Public API with types, internal implementation, and barrel exports
25
+ - SELECT design patterns from knowledge/domain.md:
26
+ - Use Factory when construction varies by input
27
+ - Use Strategy when algorithm varies at runtime
28
+ - Use Repository when abstracting data access
29
+ - Use Adapter when wrapping external services
30
+ - Use Builder when object construction has many optional parameters
31
+ - DECIDE error handling strategy:
32
+ - Result type (functional style) for libraries and utilities
33
+ - Exception hierarchy (OOP style) for applications and APIs
34
+ - Error codes with typed payloads for cross-boundary communication
35
+ - DOCUMENT the chosen architecture in a brief comment block at the top of the output
36
+
37
+ ## Step 3: Interface Design
38
+ - Define all public types, interfaces, and data transfer objects BEFORE writing implementation
39
+ - For each public function, specify:
40
+ - Parameter names and types (with validation constraints noted)
41
+ - Return type (including error cases)
42
+ - Side effects (I/O, mutations, logging)
43
+ - Preconditions and postconditions
44
+ - Apply type safety practices from knowledge/best-practices.md:
45
+ - Use discriminated unions for state modeling
46
+ - Use branded types for domain identifiers
47
+ - Derive types from validation schemas when possible
48
+ - Prefer `readonly` for immutable data
49
+ - Define error types specific to this module:
50
+ - One base error class extending the standard error
51
+ - Specific error subclasses for each failure mode
52
+ - Include contextual fields (resource name, expected vs. received values)
53
+ - IF the code involves an API THEN define the request/response schemas with validation
54
+
55
+ ## Step 4: Implementation
56
+ - Implement each function following the interface contracts from Step 3
57
+ - Apply language idioms from knowledge/domain.md:
58
+ - TypeScript: strict mode, no `any`, discriminated unions, `async`/`await`
59
+ - Python: type hints, dataclasses/Pydantic, context managers, pathlib
60
+ - Go: error returns, context propagation, defer, interface composition
61
+ - Rust: ownership, Result/Option, trait implementations, iterators
62
+ - IMPLEMENT error handling at every boundary:
63
+ - Validate all inputs at the function entry point
64
+ - Wrap external calls (I/O, network, parsing) in try/catch with specific error types
65
+ - Provide meaningful error messages with context (field name, expected format, received value)
66
+ - IF the function interacts with external services THEN implement timeout, retry, and circuit breaker as appropriate
67
+ - Apply async patterns from knowledge/domain.md:
68
+ - Use `Promise.all` for independent parallel operations
69
+ - Use `Promise.allSettled` when partial success is acceptable
70
+ - Use async iterators for paginated or streaming data
71
+ - Implement cancellation support via AbortController or context
72
+ - VERIFY against anti-patterns from knowledge/anti-patterns.md:
73
+ - No `any` types or bare catches
74
+ - No silent error swallowing
75
+ - No hard-coded configuration
76
+ - No god functions (each function < 40 lines of logic)
77
+ - No missing input validation
78
+
79
+ ## Step 5: Self-Testing
80
+ - Generate unit tests for every public function:
81
+ - **Happy path**: valid input produces expected output
82
+ - **Edge cases**: empty input, boundary values, maximum sizes, unicode, zero/null
83
+ - **Error paths**: invalid input throws the correct error type with expected message
84
+ - Follow Arrange-Act-Assert pattern (from knowledge/best-practices.md)
85
+ - Name tests descriptively: `should [expected behavior] when [condition]`
86
+ - For async code: test timeout behavior, cancellation, retry exhaustion
87
+ - For state machines: test all valid transitions and verify invalid transitions are rejected
88
+ - IF the code involves I/O THEN generate integration test scaffolding with mock setup
89
+ - Target minimum coverage:
90
+ - All public functions have at least one test
91
+ - All error branches have at least one test
92
+ - All state transitions have at least one test
93
+
94
+ ## Step 6: Review & Output
95
+ - SELF-REVIEW the generated code against this checklist:
96
+ - [ ] All public types are defined and exported
97
+ - [ ] All inputs are validated at the boundary
98
+ - [ ] All errors are handled with specific types and contextual messages
99
+ - [ ] No `any`, no bare catches, no silent swallowing
100
+ - [ ] Functions are under 40 lines of logic each
101
+ - [ ] At least one test per public function
102
+ - [ ] Usage example is included
103
+ - [ ] Dependencies are explicitly imported (no implicit globals)
104
+ - [ ] Configuration is externalized (no hard-coded URLs, keys, or magic numbers)
105
+ - [ ] Code follows the target language's naming conventions and idioms
106
+ - IF any check fails THEN loop back to the relevant step and fix
107
+ - FORMAT the output in this order:
108
+ 1. Architecture comment block (pattern chosen, rationale)
109
+ 2. Type definitions and interfaces
110
+ 3. Error types
111
+ 4. Implementation
112
+ 5. Tests
113
+ 6. Usage example
114
+ - PROVIDE brief inline comments for non-obvious logic (the "why", not the "what")