@plazmodium/odin 0.3.2-beta → 0.3.4-beta

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 (73) hide show
  1. package/README.md +82 -11
  2. package/builtin/ODIN.md +1045 -0
  3. package/builtin/agent-definitions/README.md +170 -0
  4. package/builtin/agent-definitions/_shared-context.md +377 -0
  5. package/builtin/agent-definitions/architect.md +627 -0
  6. package/builtin/agent-definitions/builder.md +716 -0
  7. package/builtin/agent-definitions/discovery.md +293 -0
  8. package/builtin/agent-definitions/documenter.md +238 -0
  9. package/builtin/agent-definitions/guardian.md +1049 -0
  10. package/builtin/agent-definitions/integrator.md +363 -0
  11. package/builtin/agent-definitions/planning.md +236 -0
  12. package/builtin/agent-definitions/product.md +405 -0
  13. package/builtin/agent-definitions/release.md +430 -0
  14. package/builtin/agent-definitions/reviewer.md +447 -0
  15. package/builtin/agent-definitions/watcher.md +402 -0
  16. package/builtin/skills/api/graphql/SKILL.md +548 -0
  17. package/builtin/skills/api/grpc/SKILL.md +554 -0
  18. package/builtin/skills/api/rest-api/SKILL.md +469 -0
  19. package/builtin/skills/api/trpc/SKILL.md +503 -0
  20. package/builtin/skills/architecture/clean-architecture/SKILL.md +141 -0
  21. package/builtin/skills/architecture/domain-driven-design/SKILL.md +129 -0
  22. package/builtin/skills/architecture/event-driven/SKILL.md +145 -0
  23. package/builtin/skills/architecture/microservices/SKILL.md +143 -0
  24. package/builtin/skills/architecture/tla-precheck/SKILL.md +171 -0
  25. package/builtin/skills/backend/golang-gin/SKILL.md +141 -0
  26. package/builtin/skills/backend/nodejs-express/SKILL.md +277 -0
  27. package/builtin/skills/backend/nodejs-fastify/SKILL.md +152 -0
  28. package/builtin/skills/backend/python-django/SKILL.md +128 -0
  29. package/builtin/skills/backend/python-fastapi/SKILL.md +140 -0
  30. package/builtin/skills/database/mongodb/SKILL.md +132 -0
  31. package/builtin/skills/database/postgresql/SKILL.md +120 -0
  32. package/builtin/skills/database/prisma-orm/SKILL.md +366 -0
  33. package/builtin/skills/database/redis/SKILL.md +140 -0
  34. package/builtin/skills/database/supabase/SKILL.md +416 -0
  35. package/builtin/skills/devops/aws/SKILL.md +382 -0
  36. package/builtin/skills/devops/docker/SKILL.md +359 -0
  37. package/builtin/skills/devops/github-actions/SKILL.md +435 -0
  38. package/builtin/skills/devops/kubernetes/SKILL.md +459 -0
  39. package/builtin/skills/devops/terraform/SKILL.md +453 -0
  40. package/builtin/skills/frontend/alpine-dev/SKILL.md +27 -0
  41. package/builtin/skills/frontend/angular-dev/SKILL.md +28 -0
  42. package/builtin/skills/frontend/astro-dev/SKILL.md +28 -0
  43. package/builtin/skills/frontend/htmx-dev/SKILL.md +28 -0
  44. package/builtin/skills/frontend/nextjs-dev/SKILL.md +470 -0
  45. package/builtin/skills/frontend/react-patterns/SKILL.md +166 -0
  46. package/builtin/skills/frontend/svelte-dev/SKILL.md +28 -0
  47. package/builtin/skills/frontend/tailwindcss/SKILL.md +131 -0
  48. package/builtin/skills/frontend/vuejs-dev/SKILL.md +28 -0
  49. package/builtin/skills/generic-dev/SKILL.md +307 -0
  50. package/builtin/skills/testing/cypress/SKILL.md +372 -0
  51. package/builtin/skills/testing/jest/SKILL.md +176 -0
  52. package/builtin/skills/testing/playwright/SKILL.md +341 -0
  53. package/builtin/skills/testing/unit-tests-eval-sdd/SKILL.md +73 -0
  54. package/builtin/skills/testing/unit-tests-sdd/SKILL.md +83 -0
  55. package/builtin/skills/testing/vitest/SKILL.md +249 -0
  56. package/dist/adapters/skills/filesystem.d.ts.map +1 -1
  57. package/dist/adapters/skills/filesystem.js +2 -18
  58. package/dist/adapters/skills/filesystem.js.map +1 -1
  59. package/dist/builtin-assets.d.ts +8 -0
  60. package/dist/builtin-assets.d.ts.map +1 -0
  61. package/dist/builtin-assets.js +90 -0
  62. package/dist/builtin-assets.js.map +1 -0
  63. package/dist/init.js +69 -11
  64. package/dist/init.js.map +1 -1
  65. package/dist/schemas.d.ts +1 -1
  66. package/dist/server.js +1 -1
  67. package/dist/server.js.map +1 -1
  68. package/dist/tools/prepare-phase-context.d.ts.map +1 -1
  69. package/dist/tools/prepare-phase-context.js +5 -0
  70. package/dist/tools/prepare-phase-context.js.map +1 -1
  71. package/dist/types.d.ts +3 -0
  72. package/dist/types.d.ts.map +1 -1
  73. package/package.json +5 -3
@@ -0,0 +1,554 @@
1
+ ---
2
+ name: grpc
3
+ description: gRPC expertise for building high-performance RPC services. Covers Protocol Buffers, service definitions, streaming, and client/server implementation in multiple languages.
4
+ category: api
5
+ compatible_with:
6
+ - golang-gin
7
+ - python-fastapi
8
+ - microservices
9
+ ---
10
+
11
+ # gRPC High-Performance RPC
12
+
13
+ ## Instructions
14
+
15
+ 1. **Assess the use case**: gRPC excels at microservices, real-time streaming, and polyglot environments.
16
+ 2. **Follow gRPC conventions**:
17
+ - Define services in .proto files
18
+ - Use Protocol Buffers for serialization
19
+ - Implement proper error handling with status codes
20
+ - Consider streaming patterns
21
+ 3. **Provide complete examples**: Include proto definitions, server, and client code.
22
+ 4. **Guide on best practices**: Error handling, deadlines, load balancing.
23
+
24
+ ## Protocol Buffers
25
+
26
+ ### Basic Service Definition
27
+
28
+ ```protobuf
29
+ // user.proto
30
+ syntax = "proto3";
31
+
32
+ package user.v1;
33
+
34
+ option go_package = "github.com/myorg/myapp/gen/user/v1";
35
+
36
+ import "google/protobuf/timestamp.proto";
37
+ import "google/protobuf/empty.proto";
38
+
39
+ // User service definition
40
+ service UserService {
41
+ // Unary RPC
42
+ rpc GetUser(GetUserRequest) returns (User);
43
+ rpc CreateUser(CreateUserRequest) returns (User);
44
+ rpc UpdateUser(UpdateUserRequest) returns (User);
45
+ rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty);
46
+
47
+ // Server streaming
48
+ rpc ListUsers(ListUsersRequest) returns (stream User);
49
+
50
+ // Client streaming
51
+ rpc BatchCreateUsers(stream CreateUserRequest) returns (BatchCreateResponse);
52
+
53
+ // Bidirectional streaming
54
+ rpc Chat(stream ChatMessage) returns (stream ChatMessage);
55
+ }
56
+
57
+ // Messages
58
+ message User {
59
+ string id = 1;
60
+ string email = 2;
61
+ string name = 3;
62
+ Role role = 4;
63
+ google.protobuf.Timestamp created_at = 5;
64
+ google.protobuf.Timestamp updated_at = 6;
65
+ }
66
+
67
+ message GetUserRequest {
68
+ string id = 1;
69
+ }
70
+
71
+ message CreateUserRequest {
72
+ string email = 1;
73
+ string name = 2;
74
+ string password = 3;
75
+ Role role = 4;
76
+ }
77
+
78
+ message UpdateUserRequest {
79
+ string id = 1;
80
+ optional string email = 2;
81
+ optional string name = 3;
82
+ }
83
+
84
+ message DeleteUserRequest {
85
+ string id = 1;
86
+ }
87
+
88
+ message ListUsersRequest {
89
+ int32 page_size = 1;
90
+ string page_token = 2;
91
+ UserFilter filter = 3;
92
+ }
93
+
94
+ message UserFilter {
95
+ optional Role role = 1;
96
+ optional string search = 2;
97
+ }
98
+
99
+ message BatchCreateResponse {
100
+ int32 created_count = 1;
101
+ repeated string user_ids = 2;
102
+ }
103
+
104
+ message ChatMessage {
105
+ string user_id = 1;
106
+ string content = 2;
107
+ google.protobuf.Timestamp timestamp = 3;
108
+ }
109
+
110
+ enum Role {
111
+ ROLE_UNSPECIFIED = 0;
112
+ ROLE_USER = 1;
113
+ ROLE_ADMIN = 2;
114
+ ROLE_MODERATOR = 3;
115
+ }
116
+ ```
117
+
118
+ ### Field Rules
119
+
120
+ ```protobuf
121
+ message Example {
122
+ // Scalar types
123
+ string name = 1;
124
+ int32 age = 2;
125
+ int64 id = 3;
126
+ bool active = 4;
127
+ double price = 5;
128
+ bytes data = 6;
129
+
130
+ // Optional (explicit presence)
131
+ optional string nickname = 7;
132
+
133
+ // Repeated (arrays)
134
+ repeated string tags = 8;
135
+
136
+ // Maps
137
+ map<string, string> metadata = 9;
138
+
139
+ // Nested message
140
+ Address address = 10;
141
+
142
+ // Oneof (union type)
143
+ oneof contact {
144
+ string phone = 11;
145
+ string email = 12;
146
+ }
147
+ }
148
+
149
+ message Address {
150
+ string street = 1;
151
+ string city = 2;
152
+ string country = 3;
153
+ }
154
+ ```
155
+
156
+ ## Server Implementation
157
+
158
+ ### Go Server
159
+
160
+ ```go
161
+ // server/main.go
162
+ package main
163
+
164
+ import (
165
+ "context"
166
+ "log"
167
+ "net"
168
+
169
+ "google.golang.org/grpc"
170
+ "google.golang.org/grpc/codes"
171
+ "google.golang.org/grpc/status"
172
+
173
+ pb "github.com/myorg/myapp/gen/user/v1"
174
+ )
175
+
176
+ type userServer struct {
177
+ pb.UnimplementedUserServiceServer
178
+ db *database
179
+ }
180
+
181
+ func (s *userServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.User, error) {
182
+ user, err := s.db.FindUser(req.Id)
183
+ if err != nil {
184
+ return nil, status.Errorf(codes.NotFound, "user not found: %v", err)
185
+ }
186
+ return user, nil
187
+ }
188
+
189
+ func (s *userServer) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.User, error) {
190
+ // Validation
191
+ if req.Email == "" {
192
+ return nil, status.Error(codes.InvalidArgument, "email is required")
193
+ }
194
+
195
+ user, err := s.db.CreateUser(req)
196
+ if err != nil {
197
+ return nil, status.Errorf(codes.Internal, "failed to create user: %v", err)
198
+ }
199
+ return user, nil
200
+ }
201
+
202
+ // Server streaming
203
+ func (s *userServer) ListUsers(req *pb.ListUsersRequest, stream pb.UserService_ListUsersServer) error {
204
+ users, err := s.db.ListUsers(req.Filter)
205
+ if err != nil {
206
+ return status.Errorf(codes.Internal, "failed to list users: %v", err)
207
+ }
208
+
209
+ for _, user := range users {
210
+ if err := stream.Send(user); err != nil {
211
+ return err
212
+ }
213
+ }
214
+ return nil
215
+ }
216
+
217
+ // Bidirectional streaming
218
+ func (s *userServer) Chat(stream pb.UserService_ChatServer) error {
219
+ for {
220
+ msg, err := stream.Recv()
221
+ if err == io.EOF {
222
+ return nil
223
+ }
224
+ if err != nil {
225
+ return err
226
+ }
227
+
228
+ // Echo back
229
+ response := &pb.ChatMessage{
230
+ UserId: "server",
231
+ Content: "Received: " + msg.Content,
232
+ Timestamp: timestamppb.Now(),
233
+ }
234
+ if err := stream.Send(response); err != nil {
235
+ return err
236
+ }
237
+ }
238
+ }
239
+
240
+ func main() {
241
+ lis, err := net.Listen("tcp", ":50051")
242
+ if err != nil {
243
+ log.Fatalf("failed to listen: %v", err)
244
+ }
245
+
246
+ grpcServer := grpc.NewServer(
247
+ grpc.UnaryInterceptor(loggingInterceptor),
248
+ )
249
+
250
+ pb.RegisterUserServiceServer(grpcServer, &userServer{db: newDatabase()})
251
+
252
+ log.Println("Server listening on :50051")
253
+ if err := grpcServer.Serve(lis); err != nil {
254
+ log.Fatalf("failed to serve: %v", err)
255
+ }
256
+ }
257
+ ```
258
+
259
+ ### Node.js Server
260
+
261
+ ```typescript
262
+ // server.ts
263
+ import * as grpc from '@grpc/grpc-js';
264
+ import * as protoLoader from '@grpc/proto-loader';
265
+
266
+ const packageDefinition = protoLoader.loadSync('./user.proto', {
267
+ keepCase: true,
268
+ longs: String,
269
+ enums: String,
270
+ defaults: true,
271
+ oneofs: true,
272
+ });
273
+
274
+ const proto = grpc.loadPackageDefinition(packageDefinition) as any;
275
+
276
+ const userService: grpc.UntypedServiceImplementation = {
277
+ getUser: async (call, callback) => {
278
+ try {
279
+ const user = await db.findUser(call.request.id);
280
+ if (!user) {
281
+ callback({
282
+ code: grpc.status.NOT_FOUND,
283
+ message: 'User not found',
284
+ });
285
+ return;
286
+ }
287
+ callback(null, user);
288
+ } catch (err) {
289
+ callback({
290
+ code: grpc.status.INTERNAL,
291
+ message: 'Internal error',
292
+ });
293
+ }
294
+ },
295
+
296
+ listUsers: async (call) => {
297
+ const users = await db.listUsers(call.request.filter);
298
+ for (const user of users) {
299
+ call.write(user);
300
+ }
301
+ call.end();
302
+ },
303
+ };
304
+
305
+ const server = new grpc.Server();
306
+ server.addService(proto.user.v1.UserService.service, userService);
307
+
308
+ server.bindAsync(
309
+ '0.0.0.0:50051',
310
+ grpc.ServerCredentials.createInsecure(),
311
+ (err, port) => {
312
+ if (err) {
313
+ console.error(err);
314
+ return;
315
+ }
316
+ console.log(`Server running on port ${port}`);
317
+ }
318
+ );
319
+ ```
320
+
321
+ ## Client Implementation
322
+
323
+ ### Go Client
324
+
325
+ ```go
326
+ // client/main.go
327
+ package main
328
+
329
+ import (
330
+ "context"
331
+ "io"
332
+ "log"
333
+ "time"
334
+
335
+ "google.golang.org/grpc"
336
+ "google.golang.org/grpc/credentials/insecure"
337
+
338
+ pb "github.com/myorg/myapp/gen/user/v1"
339
+ )
340
+
341
+ func main() {
342
+ conn, err := grpc.Dial(
343
+ "localhost:50051",
344
+ grpc.WithTransportCredentials(insecure.NewCredentials()),
345
+ )
346
+ if err != nil {
347
+ log.Fatalf("failed to connect: %v", err)
348
+ }
349
+ defer conn.Close()
350
+
351
+ client := pb.NewUserServiceClient(conn)
352
+
353
+ // Unary call with deadline
354
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
355
+ defer cancel()
356
+
357
+ user, err := client.GetUser(ctx, &pb.GetUserRequest{Id: "123"})
358
+ if err != nil {
359
+ log.Fatalf("GetUser failed: %v", err)
360
+ }
361
+ log.Printf("User: %v", user)
362
+
363
+ // Server streaming
364
+ stream, err := client.ListUsers(ctx, &pb.ListUsersRequest{PageSize: 10})
365
+ if err != nil {
366
+ log.Fatalf("ListUsers failed: %v", err)
367
+ }
368
+
369
+ for {
370
+ user, err := stream.Recv()
371
+ if err == io.EOF {
372
+ break
373
+ }
374
+ if err != nil {
375
+ log.Fatalf("stream error: %v", err)
376
+ }
377
+ log.Printf("Received user: %v", user)
378
+ }
379
+ }
380
+ ```
381
+
382
+ ### TypeScript Client
383
+
384
+ ```typescript
385
+ // client.ts
386
+ import * as grpc from '@grpc/grpc-js';
387
+ import * as protoLoader from '@grpc/proto-loader';
388
+
389
+ const packageDefinition = protoLoader.loadSync('./user.proto');
390
+ const proto = grpc.loadPackageDefinition(packageDefinition) as any;
391
+
392
+ const client = new proto.user.v1.UserService(
393
+ 'localhost:50051',
394
+ grpc.credentials.createInsecure()
395
+ );
396
+
397
+ // Unary call
398
+ client.getUser({ id: '123' }, (err: any, response: any) => {
399
+ if (err) {
400
+ console.error('Error:', err);
401
+ return;
402
+ }
403
+ console.log('User:', response);
404
+ });
405
+
406
+ // Server streaming
407
+ const stream = client.listUsers({ page_size: 10 });
408
+ stream.on('data', (user: any) => {
409
+ console.log('Received user:', user);
410
+ });
411
+ stream.on('end', () => {
412
+ console.log('Stream ended');
413
+ });
414
+ stream.on('error', (err: any) => {
415
+ console.error('Stream error:', err);
416
+ });
417
+
418
+ // Promisified client
419
+ function getUser(id: string): Promise<User> {
420
+ return new Promise((resolve, reject) => {
421
+ client.getUser({ id }, (err: any, response: any) => {
422
+ if (err) reject(err);
423
+ else resolve(response);
424
+ });
425
+ });
426
+ }
427
+ ```
428
+
429
+ ## Error Handling
430
+
431
+ ### Status Codes
432
+
433
+ | Code | Name | Use Case |
434
+ |------|------|----------|
435
+ | 0 | OK | Success |
436
+ | 1 | CANCELLED | Client cancelled |
437
+ | 2 | UNKNOWN | Unknown error |
438
+ | 3 | INVALID_ARGUMENT | Bad request |
439
+ | 4 | DEADLINE_EXCEEDED | Timeout |
440
+ | 5 | NOT_FOUND | Resource not found |
441
+ | 6 | ALREADY_EXISTS | Resource exists |
442
+ | 7 | PERMISSION_DENIED | Not authorized |
443
+ | 8 | RESOURCE_EXHAUSTED | Rate limited |
444
+ | 9 | FAILED_PRECONDITION | Invalid state |
445
+ | 10 | ABORTED | Conflict |
446
+ | 11 | OUT_OF_RANGE | Invalid range |
447
+ | 12 | UNIMPLEMENTED | Not implemented |
448
+ | 13 | INTERNAL | Server error |
449
+ | 14 | UNAVAILABLE | Service unavailable |
450
+ | 16 | UNAUTHENTICATED | Not authenticated |
451
+
452
+ ### Error Details
453
+
454
+ ```go
455
+ import (
456
+ "google.golang.org/genproto/googleapis/rpc/errdetails"
457
+ "google.golang.org/grpc/status"
458
+ )
459
+
460
+ func validateRequest(req *pb.CreateUserRequest) error {
461
+ var violations []*errdetails.BadRequest_FieldViolation
462
+
463
+ if req.Email == "" {
464
+ violations = append(violations, &errdetails.BadRequest_FieldViolation{
465
+ Field: "email",
466
+ Description: "Email is required",
467
+ })
468
+ }
469
+
470
+ if len(violations) > 0 {
471
+ st := status.New(codes.InvalidArgument, "validation failed")
472
+ br := &errdetails.BadRequest{FieldViolations: violations}
473
+ st, _ = st.WithDetails(br)
474
+ return st.Err()
475
+ }
476
+
477
+ return nil
478
+ }
479
+ ```
480
+
481
+ ## Interceptors (Middleware)
482
+
483
+ ```go
484
+ // Unary interceptor
485
+ func loggingInterceptor(
486
+ ctx context.Context,
487
+ req interface{},
488
+ info *grpc.UnaryServerInfo,
489
+ handler grpc.UnaryHandler,
490
+ ) (interface{}, error) {
491
+ start := time.Now()
492
+
493
+ resp, err := handler(ctx, req)
494
+
495
+ log.Printf("method=%s duration=%s error=%v",
496
+ info.FullMethod,
497
+ time.Since(start),
498
+ err,
499
+ )
500
+
501
+ return resp, err
502
+ }
503
+
504
+ // Auth interceptor
505
+ func authInterceptor(
506
+ ctx context.Context,
507
+ req interface{},
508
+ info *grpc.UnaryServerInfo,
509
+ handler grpc.UnaryHandler,
510
+ ) (interface{}, error) {
511
+ md, ok := metadata.FromIncomingContext(ctx)
512
+ if !ok {
513
+ return nil, status.Error(codes.Unauthenticated, "no metadata")
514
+ }
515
+
516
+ tokens := md.Get("authorization")
517
+ if len(tokens) == 0 {
518
+ return nil, status.Error(codes.Unauthenticated, "no token")
519
+ }
520
+
521
+ user, err := validateToken(tokens[0])
522
+ if err != nil {
523
+ return nil, status.Error(codes.Unauthenticated, "invalid token")
524
+ }
525
+
526
+ ctx = context.WithValue(ctx, userKey, user)
527
+ return handler(ctx, req)
528
+ }
529
+
530
+ // Chain interceptors
531
+ server := grpc.NewServer(
532
+ grpc.ChainUnaryInterceptor(
533
+ loggingInterceptor,
534
+ authInterceptor,
535
+ ),
536
+ )
537
+ ```
538
+
539
+ ## Best Practices
540
+
541
+ - **Use deadlines** - Always set timeouts on client calls
542
+ - **Handle streaming errors** - Check for EOF and errors in loops
543
+ - **Use interceptors** - For cross-cutting concerns (logging, auth, tracing)
544
+ - **Version your APIs** - Include version in package name
545
+ - **Document with comments** - Proto comments become documentation
546
+ - **Use well-known types** - google.protobuf.Timestamp, Empty, etc.
547
+ - **Implement health checks** - Use grpc-health-probe
548
+ - **Enable reflection** - For debugging with grpcurl
549
+
550
+ ## References
551
+
552
+ - gRPC Documentation: https://grpc.io/docs/
553
+ - Protocol Buffers: https://protobuf.dev/
554
+ - gRPC Status Codes: https://grpc.io/docs/guides/status-codes/