language-operator 0.1.30 → 0.1.31

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/Gemfile.lock +1 -1
  4. data/Makefile +7 -2
  5. data/Rakefile +29 -0
  6. data/docs/dsl/SCHEMA_VERSION.md +250 -0
  7. data/docs/dsl/agent-reference.md +13 -0
  8. data/lib/language_operator/agent/safety/safe_executor.rb +12 -0
  9. data/lib/language_operator/cli/commands/agent.rb +54 -101
  10. data/lib/language_operator/cli/commands/cluster.rb +37 -1
  11. data/lib/language_operator/cli/commands/persona.rb +2 -5
  12. data/lib/language_operator/cli/commands/status.rb +5 -18
  13. data/lib/language_operator/cli/commands/system.rb +772 -0
  14. data/lib/language_operator/cli/formatters/code_formatter.rb +3 -7
  15. data/lib/language_operator/cli/formatters/log_formatter.rb +3 -5
  16. data/lib/language_operator/cli/formatters/progress_formatter.rb +3 -7
  17. data/lib/language_operator/cli/formatters/status_formatter.rb +37 -0
  18. data/lib/language_operator/cli/formatters/table_formatter.rb +10 -26
  19. data/lib/language_operator/cli/helpers/pastel_helper.rb +24 -0
  20. data/lib/language_operator/cli/main.rb +4 -0
  21. data/lib/language_operator/dsl/schema.rb +1102 -0
  22. data/lib/language_operator/dsl.rb +1 -0
  23. data/lib/language_operator/logger.rb +4 -4
  24. data/lib/language_operator/templates/README.md +23 -0
  25. data/lib/language_operator/templates/examples/agent_synthesis.tmpl +115 -0
  26. data/lib/language_operator/templates/examples/persona_distillation.tmpl +19 -0
  27. data/lib/language_operator/templates/schema/.gitkeep +0 -0
  28. data/lib/language_operator/templates/schema/CHANGELOG.md +93 -0
  29. data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +306 -0
  30. data/lib/language_operator/templates/schema/agent_dsl_schema.json +452 -0
  31. data/lib/language_operator/version.rb +1 -1
  32. data/requirements/tasks/iterate.md +2 -2
  33. metadata +13 -9
  34. data/examples/README.md +0 -569
  35. data/examples/agent_example.rb +0 -86
  36. data/examples/chat_endpoint_agent.rb +0 -118
  37. data/examples/github_webhook_agent.rb +0 -171
  38. data/examples/mcp_agent.rb +0 -158
  39. data/examples/oauth_callback_agent.rb +0 -296
  40. data/examples/stripe_webhook_agent.rb +0 -219
  41. data/examples/webhook_agent.rb +0 -80
@@ -0,0 +1,1102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../version'
4
+
5
+ module LanguageOperator
6
+ module Dsl
7
+ # JSON Schema generator for the Agent DSL
8
+ #
9
+ # Generates a JSON Schema v7 representation of the Language Operator Agent DSL.
10
+ # This schema documents all available DSL methods, their parameters, validation
11
+ # patterns, and structure.
12
+ #
13
+ # Used for:
14
+ # - Template validation
15
+ # - Documentation generation
16
+ # - IDE autocomplete/IntelliSense
17
+ # - CLI introspection commands
18
+ #
19
+ # @example Generate schema
20
+ # schema = LanguageOperator::Dsl::Schema.to_json_schema
21
+ # File.write('schema.json', JSON.pretty_generate(schema))
22
+ # rubocop:disable Metrics/ClassLength
23
+ class Schema
24
+ # Generate complete JSON Schema v7 representation
25
+ #
26
+ # @return [Hash] JSON Schema draft-07 compliant schema
27
+ def self.to_json_schema
28
+ {
29
+ '$schema': 'http://json-schema.org/draft-07/schema#',
30
+ '$id': 'https://github.com/language-operator/language-operator-gem/schema/agent-dsl.json',
31
+ title: 'Language Operator Agent DSL',
32
+ description: 'Schema for defining autonomous AI agents using the Language Operator DSL',
33
+ version: LanguageOperator::VERSION,
34
+ type: 'object',
35
+ properties: agent_properties,
36
+ required: %w[name],
37
+ definitions: all_definitions
38
+ }
39
+ end
40
+
41
+ # Generate OpenAPI 3.0 specification for agent HTTP endpoints
42
+ #
43
+ # Generates an OpenAPI 3.0.3 spec documenting the HTTP API exposed by
44
+ # reactive agents. This includes chat endpoints, webhooks, and health checks.
45
+ #
46
+ # @return [Hash] OpenAPI 3.0.3 compliant specification
47
+ # @example Generate OpenAPI spec
48
+ # spec = LanguageOperator::Dsl::Schema.to_openapi
49
+ # File.write('openapi.json', JSON.pretty_generate(spec))
50
+ def self.to_openapi
51
+ {
52
+ openapi: '3.0.3',
53
+ info: openapi_info,
54
+ servers: openapi_servers,
55
+ paths: openapi_paths,
56
+ components: openapi_components
57
+ }
58
+ end
59
+
60
+ # Returns the schema version
61
+ #
62
+ # The schema version is directly linked to the gem version and follows semantic
63
+ # versioning. Schema changes follow these rules:
64
+ # - MAJOR: Breaking changes to DSL structure or behavior
65
+ # - MINOR: New features, backward-compatible additions
66
+ # - PATCH: Bug fixes, documentation improvements
67
+ #
68
+ # @return [String] Current schema version (e.g., "0.1.30")
69
+ # @example
70
+ # LanguageOperator::Dsl::Schema.version
71
+ # # => "0.1.30"
72
+ def self.version
73
+ LanguageOperator::VERSION
74
+ end
75
+
76
+ # Returns array of safe agent DSL methods allowed in agent definitions
77
+ #
78
+ # Reads from Agent::Safety::ASTValidator::SAFE_AGENT_METHODS constant.
79
+ # These methods are validated as safe for use in synthesized agent code.
80
+ #
81
+ # Includes methods for:
82
+ # - Agent metadata (description, persona, objectives)
83
+ # - Execution modes (mode, schedule)
84
+ # - Workflows (workflow, step, depends_on, prompt)
85
+ # - Constraints (budget, max_requests, rate_limit, content_filter)
86
+ # - Output destinations (output)
87
+ # - Endpoints (webhook, as_mcp_server, as_chat_endpoint)
88
+ #
89
+ # @return [Array<String>] Sorted array of safe agent method names
90
+ # @example
91
+ # LanguageOperator::Dsl::Schema.safe_agent_methods
92
+ # # => ["agent", "as_chat_endpoint", "as_mcp_server", "budget", ...]
93
+ def self.safe_agent_methods
94
+ require_relative '../agent/safety/ast_validator'
95
+ Agent::Safety::ASTValidator::SAFE_AGENT_METHODS.sort
96
+ end
97
+
98
+ # Returns array of safe tool DSL methods allowed in tool definitions
99
+ #
100
+ # Reads from Agent::Safety::ASTValidator::SAFE_TOOL_METHODS constant.
101
+ # These methods are validated as safe for use in synthesized tool code.
102
+ #
103
+ # Includes methods for:
104
+ # - Tool definition (tool, description)
105
+ # - Parameters (parameter, type, required, default)
106
+ # - Execution (execute)
107
+ #
108
+ # @return [Array<String>] Sorted array of safe tool method names
109
+ # @example
110
+ # LanguageOperator::Dsl::Schema.safe_tool_methods
111
+ # # => ["default", "description", "execute", "parameter", "required", "tool", "type"]
112
+ def self.safe_tool_methods
113
+ require_relative '../agent/safety/ast_validator'
114
+ Agent::Safety::ASTValidator::SAFE_TOOL_METHODS.sort
115
+ end
116
+
117
+ # Returns array of safe helper methods available in execute blocks
118
+ #
119
+ # Reads from Agent::Safety::ASTValidator::SAFE_HELPER_METHODS constant.
120
+ # These helper methods are validated as safe for use in tool execute blocks.
121
+ #
122
+ # Includes helpers for:
123
+ # - HTTP requests (HTTP.*)
124
+ # - Shell commands (Shell.run)
125
+ # - Validation (validate_url, validate_phone, validate_email)
126
+ # - Environment variables (env_required, env_get)
127
+ # - Utilities (truncate, parse_csv)
128
+ # - Response formatting (error, success)
129
+ #
130
+ # @return [Array<String>] Sorted array of safe helper method names
131
+ # @example
132
+ # LanguageOperator::Dsl::Schema.safe_helper_methods
133
+ # # => ["HTTP", "Shell", "env_get", "env_required", "error", ...]
134
+ def self.safe_helper_methods
135
+ require_relative '../agent/safety/ast_validator'
136
+ Agent::Safety::ASTValidator::SAFE_HELPER_METHODS.sort
137
+ end
138
+
139
+ # Agent top-level properties
140
+ #
141
+ # @return [Hash] Schema properties for agent definition
142
+ def self.agent_properties
143
+ {
144
+ name: {
145
+ type: 'string',
146
+ description: 'Unique agent identifier (lowercase, alphanumeric, hyphens)',
147
+ pattern: '^[a-z0-9-]+$',
148
+ minLength: 1,
149
+ maxLength: 63
150
+ },
151
+ description: {
152
+ type: 'string',
153
+ description: 'Human-readable description of agent purpose'
154
+ },
155
+ persona: {
156
+ type: 'string',
157
+ description: 'System prompt or persona defining agent behavior and expertise'
158
+ },
159
+ schedule: {
160
+ type: 'string',
161
+ description: 'Cron expression for scheduled execution (sets mode to :scheduled)',
162
+ pattern: '^\s*(\S+\s+){4}\S+\s*$'
163
+ },
164
+ mode: {
165
+ type: 'string',
166
+ description: 'Execution mode for the agent',
167
+ enum: %w[autonomous scheduled reactive]
168
+ },
169
+ objectives: {
170
+ type: 'array',
171
+ description: 'List of goals the agent should achieve',
172
+ items: {
173
+ type: 'string'
174
+ },
175
+ minItems: 0
176
+ },
177
+ workflow: {
178
+ '$ref': '#/definitions/WorkflowDefinition'
179
+ },
180
+ constraints: {
181
+ '$ref': '#/definitions/ConstraintsDefinition'
182
+ },
183
+ output: {
184
+ '$ref': '#/definitions/OutputDefinition'
185
+ },
186
+ webhooks: {
187
+ type: 'array',
188
+ description: 'Webhook endpoints for reactive agents',
189
+ items: {
190
+ '$ref': '#/definitions/WebhookDefinition'
191
+ }
192
+ },
193
+ mcp_server: {
194
+ '$ref': '#/definitions/McpServerDefinition'
195
+ },
196
+ chat_endpoint: {
197
+ '$ref': '#/definitions/ChatEndpointDefinition'
198
+ }
199
+ }
200
+ end
201
+
202
+ # All nested definition schemas
203
+ #
204
+ # @return [Hash] Schema definitions for nested types
205
+ def self.all_definitions
206
+ {
207
+ WorkflowDefinition: workflow_definition_schema,
208
+ StepDefinition: step_definition_schema,
209
+ ConstraintsDefinition: constraints_definition_schema,
210
+ OutputDefinition: output_definition_schema,
211
+ WebhookDefinition: webhook_definition_schema,
212
+ WebhookAuthentication: webhook_authentication_schema,
213
+ McpServerDefinition: mcp_server_definition_schema,
214
+ ChatEndpointDefinition: chat_endpoint_definition_schema,
215
+ ToolDefinition: tool_definition_schema,
216
+ ParameterDefinition: parameter_definition_schema
217
+ }
218
+ end
219
+
220
+ # Workflow definition schema
221
+ #
222
+ # @return [Hash] Schema for workflow definitions
223
+ def self.workflow_definition_schema
224
+ {
225
+ type: 'object',
226
+ description: 'Multi-step workflow with dependencies',
227
+ properties: {
228
+ steps: {
229
+ type: 'array',
230
+ description: 'Ordered list of workflow steps',
231
+ items: {
232
+ '$ref': '#/definitions/StepDefinition'
233
+ }
234
+ }
235
+ }
236
+ }
237
+ end
238
+
239
+ # Step definition schema
240
+ #
241
+ # @return [Hash] Schema for workflow steps
242
+ def self.step_definition_schema
243
+ {
244
+ type: 'object',
245
+ description: 'Individual workflow step',
246
+ properties: {
247
+ name: {
248
+ type: 'string',
249
+ description: 'Step identifier (symbol or string)'
250
+ },
251
+ tool: {
252
+ type: 'string',
253
+ description: 'Tool name to execute in this step'
254
+ },
255
+ params: {
256
+ type: 'object',
257
+ description: 'Parameters to pass to the tool',
258
+ additionalProperties: true
259
+ },
260
+ depends_on: {
261
+ oneOf: [
262
+ { type: 'string' },
263
+ {
264
+ type: 'array',
265
+ items: { type: 'string' }
266
+ }
267
+ ],
268
+ description: 'Step dependencies (must complete before this step)'
269
+ },
270
+ prompt: {
271
+ type: 'string',
272
+ description: 'LLM prompt template for this step'
273
+ }
274
+ },
275
+ required: %w[name]
276
+ }
277
+ end
278
+
279
+ # Constraints definition schema
280
+ #
281
+ # @return [Hash] Schema for constraint definitions
282
+ def self.constraints_definition_schema
283
+ {
284
+ type: 'object',
285
+ description: 'Execution constraints and limits',
286
+ properties: {
287
+ max_iterations: {
288
+ type: 'integer',
289
+ description: 'Maximum number of execution iterations',
290
+ minimum: 1
291
+ },
292
+ timeout: {
293
+ type: 'string',
294
+ description: 'Execution timeout (e.g., "30s", "5m", "1h")',
295
+ pattern: '^\d+[smh]$'
296
+ },
297
+ memory: {
298
+ type: 'string',
299
+ description: 'Memory limit (e.g., "512Mi", "1Gi")'
300
+ },
301
+ rate_limit: {
302
+ type: 'integer',
303
+ description: 'Maximum requests per time period',
304
+ minimum: 1
305
+ },
306
+ daily_budget: {
307
+ type: 'number',
308
+ description: 'Maximum daily cost in USD',
309
+ minimum: 0
310
+ },
311
+ hourly_budget: {
312
+ type: 'number',
313
+ description: 'Maximum hourly cost in USD',
314
+ minimum: 0
315
+ },
316
+ token_budget: {
317
+ type: 'integer',
318
+ description: 'Maximum total tokens allowed',
319
+ minimum: 1
320
+ },
321
+ requests_per_minute: {
322
+ type: 'integer',
323
+ description: 'Maximum requests per minute',
324
+ minimum: 1
325
+ },
326
+ requests_per_hour: {
327
+ type: 'integer',
328
+ description: 'Maximum requests per hour',
329
+ minimum: 1
330
+ },
331
+ requests_per_day: {
332
+ type: 'integer',
333
+ description: 'Maximum requests per day',
334
+ minimum: 1
335
+ },
336
+ blocked_patterns: {
337
+ type: 'array',
338
+ description: 'Content patterns to block',
339
+ items: { type: 'string' }
340
+ },
341
+ blocked_topics: {
342
+ type: 'array',
343
+ description: 'Topics to avoid',
344
+ items: { type: 'string' }
345
+ }
346
+ }
347
+ }
348
+ end
349
+
350
+ # Output definition schema
351
+ #
352
+ # @return [Hash] Schema for output configuration
353
+ def self.output_definition_schema
354
+ {
355
+ type: 'object',
356
+ description: 'Output destination configuration',
357
+ properties: {
358
+ workspace: {
359
+ type: 'string',
360
+ description: 'Workspace directory path for file outputs'
361
+ },
362
+ slack: {
363
+ type: 'object',
364
+ description: 'Slack integration configuration',
365
+ properties: {
366
+ channel: {
367
+ type: 'string',
368
+ description: 'Slack channel name or ID'
369
+ }
370
+ },
371
+ required: %w[channel]
372
+ },
373
+ email: {
374
+ type: 'object',
375
+ description: 'Email notification configuration',
376
+ properties: {
377
+ to: {
378
+ type: 'string',
379
+ description: 'Email recipient address',
380
+ format: 'email'
381
+ }
382
+ },
383
+ required: %w[to]
384
+ }
385
+ }
386
+ }
387
+ end
388
+
389
+ # Webhook definition schema
390
+ #
391
+ # @return [Hash] Schema for webhook definitions
392
+ def self.webhook_definition_schema
393
+ {
394
+ type: 'object',
395
+ description: 'Webhook endpoint configuration',
396
+ properties: {
397
+ path: {
398
+ type: 'string',
399
+ description: 'URL path for webhook endpoint',
400
+ pattern: '^/'
401
+ },
402
+ method: {
403
+ type: 'string',
404
+ description: 'HTTP method',
405
+ enum: %w[get post put delete patch],
406
+ default: 'post'
407
+ },
408
+ authentication: {
409
+ '$ref': '#/definitions/WebhookAuthentication'
410
+ },
411
+ validations: {
412
+ type: 'array',
413
+ description: 'Request validation rules',
414
+ items: {
415
+ type: 'object',
416
+ properties: {
417
+ type: {
418
+ type: 'string',
419
+ enum: %w[headers content_type custom]
420
+ }
421
+ }
422
+ }
423
+ }
424
+ },
425
+ required: %w[path]
426
+ }
427
+ end
428
+
429
+ # Webhook authentication schema
430
+ #
431
+ # @return [Hash] Schema for webhook authentication
432
+ def self.webhook_authentication_schema
433
+ {
434
+ type: 'object',
435
+ description: 'Webhook authentication configuration',
436
+ properties: {
437
+ type: {
438
+ type: 'string',
439
+ description: 'Authentication type',
440
+ enum: %w[hmac api_key bearer custom]
441
+ },
442
+ secret: {
443
+ type: 'string',
444
+ description: 'Secret key for authentication'
445
+ },
446
+ header: {
447
+ type: 'string',
448
+ description: 'Header name containing signature/token'
449
+ },
450
+ algorithm: {
451
+ type: 'string',
452
+ description: 'HMAC algorithm',
453
+ enum: %w[sha1 sha256 sha512]
454
+ },
455
+ prefix: {
456
+ type: 'string',
457
+ description: 'Signature prefix (e.g., "sha256=")'
458
+ }
459
+ }
460
+ }
461
+ end
462
+
463
+ # MCP server definition schema
464
+ #
465
+ # @return [Hash] Schema for MCP server definitions
466
+ def self.mcp_server_definition_schema
467
+ {
468
+ type: 'object',
469
+ description: 'MCP (Model Context Protocol) server configuration',
470
+ properties: {
471
+ name: {
472
+ type: 'string',
473
+ description: 'MCP server name'
474
+ },
475
+ tools: {
476
+ type: 'object',
477
+ description: 'Tools exposed via MCP',
478
+ additionalProperties: {
479
+ '$ref': '#/definitions/ToolDefinition'
480
+ }
481
+ }
482
+ }
483
+ }
484
+ end
485
+
486
+ # Chat endpoint definition schema
487
+ #
488
+ # @return [Hash] Schema for chat endpoint definitions
489
+ def self.chat_endpoint_definition_schema
490
+ {
491
+ type: 'object',
492
+ description: 'OpenAI-compatible chat endpoint configuration',
493
+ properties: {
494
+ system_prompt: {
495
+ type: 'string',
496
+ description: 'System prompt for chat mode'
497
+ },
498
+ temperature: {
499
+ type: 'number',
500
+ description: 'Sampling temperature (0.0-2.0)',
501
+ minimum: 0.0,
502
+ maximum: 2.0,
503
+ default: 0.7
504
+ },
505
+ max_tokens: {
506
+ type: 'integer',
507
+ description: 'Maximum tokens in response',
508
+ minimum: 1,
509
+ default: 2000
510
+ },
511
+ model_name: {
512
+ type: 'string',
513
+ description: 'Model name exposed in API'
514
+ },
515
+ top_p: {
516
+ type: 'number',
517
+ description: 'Nucleus sampling parameter (0.0-1.0)',
518
+ minimum: 0.0,
519
+ maximum: 1.0,
520
+ default: 1.0
521
+ },
522
+ frequency_penalty: {
523
+ type: 'number',
524
+ description: 'Frequency penalty (-2.0 to 2.0)',
525
+ minimum: -2.0,
526
+ maximum: 2.0,
527
+ default: 0.0
528
+ },
529
+ presence_penalty: {
530
+ type: 'number',
531
+ description: 'Presence penalty (-2.0 to 2.0)',
532
+ minimum: -2.0,
533
+ maximum: 2.0,
534
+ default: 0.0
535
+ },
536
+ stop_sequences: {
537
+ type: 'array',
538
+ description: 'Sequences that stop generation',
539
+ items: { type: 'string' }
540
+ }
541
+ }
542
+ }
543
+ end
544
+
545
+ # Tool definition schema
546
+ #
547
+ # @return [Hash] Schema for tool definitions
548
+ def self.tool_definition_schema
549
+ {
550
+ type: 'object',
551
+ description: 'MCP tool definition',
552
+ properties: {
553
+ name: {
554
+ type: 'string',
555
+ description: 'Tool name (lowercase, alphanumeric, underscores)',
556
+ pattern: '^[a-z0-9_]+$'
557
+ },
558
+ description: {
559
+ type: 'string',
560
+ description: 'Human-readable tool description'
561
+ },
562
+ parameters: {
563
+ type: 'object',
564
+ description: 'Tool parameters',
565
+ additionalProperties: {
566
+ '$ref': '#/definitions/ParameterDefinition'
567
+ }
568
+ }
569
+ },
570
+ required: %w[name description]
571
+ }
572
+ end
573
+
574
+ # Parameter definition schema
575
+ #
576
+ # @return [Hash] Schema for parameter definitions
577
+ def self.parameter_definition_schema
578
+ {
579
+ type: 'object',
580
+ description: 'Tool parameter definition',
581
+ properties: {
582
+ type: {
583
+ type: 'string',
584
+ description: 'Parameter type',
585
+ enum: %w[string number integer boolean array object]
586
+ },
587
+ description: {
588
+ type: 'string',
589
+ description: 'Parameter description'
590
+ },
591
+ required: {
592
+ type: 'boolean',
593
+ description: 'Whether parameter is required',
594
+ default: false
595
+ },
596
+ default: {
597
+ description: 'Default value if not provided'
598
+ },
599
+ enum: {
600
+ type: 'array',
601
+ description: 'Allowed values',
602
+ items: {}
603
+ }
604
+ },
605
+ required: %w[type]
606
+ }
607
+ end
608
+
609
+ # OpenAPI info section
610
+ #
611
+ # @return [Hash] OpenAPI info object
612
+ def self.openapi_info
613
+ {
614
+ title: 'Language Operator Agent API',
615
+ version: LanguageOperator::VERSION,
616
+ description: 'HTTP API endpoints exposed by Language Operator reactive agents',
617
+ contact: {
618
+ name: 'Language Operator',
619
+ url: 'https://github.com/language-operator/language-operator-gem'
620
+ },
621
+ license: {
622
+ name: 'FSL-1.1-Apache-2.0',
623
+ url: 'https://github.com/language-operator/language-operator-gem/blob/main/LICENSE'
624
+ }
625
+ }
626
+ end
627
+
628
+ # OpenAPI servers section
629
+ #
630
+ # @return [Array<Hash>] OpenAPI server objects
631
+ def self.openapi_servers
632
+ [
633
+ {
634
+ url: 'http://localhost:8080',
635
+ description: 'Local development server'
636
+ }
637
+ ]
638
+ end
639
+
640
+ # OpenAPI paths section - documents all HTTP endpoints
641
+ #
642
+ # @return [Hash] OpenAPI paths object
643
+ def self.openapi_paths
644
+ {
645
+ '/health' => health_endpoint_spec,
646
+ '/ready' => ready_endpoint_spec,
647
+ '/v1/chat/completions' => chat_completions_endpoint_spec,
648
+ '/v1/models' => models_endpoint_spec
649
+ }
650
+ end
651
+
652
+ # OpenAPI components section - reusable schemas
653
+ #
654
+ # @return [Hash] OpenAPI components object
655
+ def self.openapi_components
656
+ {
657
+ schemas: {
658
+ ChatCompletionRequest: chat_completion_request_schema,
659
+ ChatCompletionResponse: chat_completion_response_schema,
660
+ ChatMessage: chat_message_schema,
661
+ ChatChoice: chat_choice_schema,
662
+ ChatUsage: chat_usage_schema,
663
+ ModelList: model_list_schema,
664
+ Model: model_schema,
665
+ HealthResponse: health_response_schema,
666
+ ErrorResponse: error_response_schema
667
+ }
668
+ }
669
+ end
670
+
671
+ # Health check endpoint spec
672
+ #
673
+ # @return [Hash] OpenAPI path item
674
+ def self.health_endpoint_spec
675
+ {
676
+ get: {
677
+ summary: 'Health check',
678
+ description: 'Returns the health status of the agent',
679
+ operationId: 'getHealth',
680
+ tags: ['Health'],
681
+ responses: {
682
+ '200': {
683
+ description: 'Agent is healthy',
684
+ content: {
685
+ 'application/json': {
686
+ schema: {
687
+ '$ref': '#/components/schemas/HealthResponse'
688
+ }
689
+ }
690
+ }
691
+ }
692
+ }
693
+ }
694
+ }
695
+ end
696
+
697
+ # Readiness check endpoint spec
698
+ #
699
+ # @return [Hash] OpenAPI path item
700
+ def self.ready_endpoint_spec
701
+ {
702
+ get: {
703
+ summary: 'Readiness check',
704
+ description: 'Returns whether the agent is ready to accept requests',
705
+ operationId: 'getReady',
706
+ tags: ['Health'],
707
+ responses: {
708
+ '200': {
709
+ description: 'Agent is ready',
710
+ content: {
711
+ 'application/json': {
712
+ schema: {
713
+ '$ref': '#/components/schemas/HealthResponse'
714
+ }
715
+ }
716
+ }
717
+ },
718
+ '503': {
719
+ description: 'Agent is not ready',
720
+ content: {
721
+ 'application/json': {
722
+ schema: {
723
+ '$ref': '#/components/schemas/ErrorResponse'
724
+ }
725
+ }
726
+ }
727
+ }
728
+ }
729
+ }
730
+ }
731
+ end
732
+
733
+ # Chat completions endpoint spec (OpenAI-compatible)
734
+ #
735
+ # @return [Hash] OpenAPI path item
736
+ def self.chat_completions_endpoint_spec
737
+ {
738
+ post: {
739
+ summary: 'Create chat completion',
740
+ description: 'Creates a chat completion response (OpenAI-compatible endpoint)',
741
+ operationId: 'createChatCompletion',
742
+ tags: ['Chat'],
743
+ requestBody: {
744
+ required: true,
745
+ content: {
746
+ 'application/json': {
747
+ schema: {
748
+ '$ref': '#/components/schemas/ChatCompletionRequest'
749
+ }
750
+ }
751
+ }
752
+ },
753
+ responses: {
754
+ '200': {
755
+ description: 'Successful chat completion response',
756
+ content: {
757
+ 'application/json': {
758
+ schema: {
759
+ '$ref': '#/components/schemas/ChatCompletionResponse'
760
+ }
761
+ },
762
+ 'text/event-stream': {
763
+ description: 'Server-sent events stream (when stream=true)',
764
+ schema: {
765
+ type: 'string'
766
+ }
767
+ }
768
+ }
769
+ },
770
+ '400': {
771
+ description: 'Invalid request',
772
+ content: {
773
+ 'application/json': {
774
+ schema: {
775
+ '$ref': '#/components/schemas/ErrorResponse'
776
+ }
777
+ }
778
+ }
779
+ }
780
+ }
781
+ }
782
+ }
783
+ end
784
+
785
+ # Models list endpoint spec (OpenAI-compatible)
786
+ #
787
+ # @return [Hash] OpenAPI path item
788
+ def self.models_endpoint_spec
789
+ {
790
+ get: {
791
+ summary: 'List models',
792
+ description: 'Lists available models (OpenAI-compatible endpoint)',
793
+ operationId: 'listModels',
794
+ tags: ['Models'],
795
+ responses: {
796
+ '200': {
797
+ description: 'List of available models',
798
+ content: {
799
+ 'application/json': {
800
+ schema: {
801
+ '$ref': '#/components/schemas/ModelList'
802
+ }
803
+ }
804
+ }
805
+ }
806
+ }
807
+ }
808
+ }
809
+ end
810
+
811
+ # Chat completion request schema
812
+ #
813
+ # @return [Hash] OpenAPI schema object
814
+ def self.chat_completion_request_schema
815
+ {
816
+ type: 'object',
817
+ required: %w[model messages],
818
+ properties: {
819
+ model: {
820
+ type: 'string',
821
+ description: 'Model name to use for completion'
822
+ },
823
+ messages: {
824
+ type: 'array',
825
+ description: 'List of messages in the conversation',
826
+ items: {
827
+ '$ref': '#/components/schemas/ChatMessage'
828
+ }
829
+ },
830
+ temperature: {
831
+ type: 'number',
832
+ description: 'Sampling temperature (0.0-2.0)',
833
+ minimum: 0.0,
834
+ maximum: 2.0,
835
+ default: 0.7
836
+ },
837
+ max_tokens: {
838
+ type: 'integer',
839
+ description: 'Maximum tokens in response',
840
+ minimum: 1,
841
+ default: 2000
842
+ },
843
+ stream: {
844
+ type: 'boolean',
845
+ description: 'Stream responses as server-sent events',
846
+ default: false
847
+ },
848
+ top_p: {
849
+ type: 'number',
850
+ description: 'Nucleus sampling parameter',
851
+ minimum: 0.0,
852
+ maximum: 1.0,
853
+ default: 1.0
854
+ },
855
+ frequency_penalty: {
856
+ type: 'number',
857
+ description: 'Frequency penalty (-2.0 to 2.0)',
858
+ minimum: -2.0,
859
+ maximum: 2.0,
860
+ default: 0.0
861
+ },
862
+ presence_penalty: {
863
+ type: 'number',
864
+ description: 'Presence penalty (-2.0 to 2.0)',
865
+ minimum: -2.0,
866
+ maximum: 2.0,
867
+ default: 0.0
868
+ },
869
+ stop: {
870
+ oneOf: [
871
+ { type: 'string' },
872
+ {
873
+ type: 'array',
874
+ items: { type: 'string' }
875
+ }
876
+ ],
877
+ description: 'Stop sequences for generation'
878
+ }
879
+ }
880
+ }
881
+ end
882
+
883
+ # Chat completion response schema
884
+ #
885
+ # @return [Hash] OpenAPI schema object
886
+ def self.chat_completion_response_schema
887
+ {
888
+ type: 'object',
889
+ required: %w[id object created model choices],
890
+ properties: {
891
+ id: {
892
+ type: 'string',
893
+ description: 'Unique identifier for the completion'
894
+ },
895
+ object: {
896
+ type: 'string',
897
+ description: 'Object type (always "chat.completion")',
898
+ enum: ['chat.completion']
899
+ },
900
+ created: {
901
+ type: 'integer',
902
+ description: 'Unix timestamp of creation'
903
+ },
904
+ model: {
905
+ type: 'string',
906
+ description: 'Model used for completion'
907
+ },
908
+ choices: {
909
+ type: 'array',
910
+ description: 'List of completion choices',
911
+ items: {
912
+ '$ref': '#/components/schemas/ChatChoice'
913
+ }
914
+ },
915
+ usage: {
916
+ '$ref': '#/components/schemas/ChatUsage'
917
+ }
918
+ }
919
+ }
920
+ end
921
+
922
+ # Chat message schema
923
+ #
924
+ # @return [Hash] OpenAPI schema object
925
+ def self.chat_message_schema
926
+ {
927
+ type: 'object',
928
+ required: %w[role content],
929
+ properties: {
930
+ role: {
931
+ type: 'string',
932
+ description: 'Message role',
933
+ enum: %w[system user assistant]
934
+ },
935
+ content: {
936
+ type: 'string',
937
+ description: 'Message content'
938
+ },
939
+ name: {
940
+ type: 'string',
941
+ description: 'Optional name of the message author'
942
+ }
943
+ }
944
+ }
945
+ end
946
+
947
+ # Chat choice schema
948
+ #
949
+ # @return [Hash] OpenAPI schema object
950
+ def self.chat_choice_schema
951
+ {
952
+ type: 'object',
953
+ required: %w[index message finish_reason],
954
+ properties: {
955
+ index: {
956
+ type: 'integer',
957
+ description: 'Choice index'
958
+ },
959
+ message: {
960
+ '$ref': '#/components/schemas/ChatMessage'
961
+ },
962
+ finish_reason: {
963
+ type: 'string',
964
+ description: 'Reason for completion finish',
965
+ enum: %w[stop length content_filter null]
966
+ }
967
+ }
968
+ }
969
+ end
970
+
971
+ # Chat usage schema
972
+ #
973
+ # @return [Hash] OpenAPI schema object
974
+ def self.chat_usage_schema
975
+ {
976
+ type: 'object',
977
+ required: %w[prompt_tokens completion_tokens total_tokens],
978
+ properties: {
979
+ prompt_tokens: {
980
+ type: 'integer',
981
+ description: 'Tokens in the prompt'
982
+ },
983
+ completion_tokens: {
984
+ type: 'integer',
985
+ description: 'Tokens in the completion'
986
+ },
987
+ total_tokens: {
988
+ type: 'integer',
989
+ description: 'Total tokens used'
990
+ }
991
+ }
992
+ }
993
+ end
994
+
995
+ # Model list schema
996
+ #
997
+ # @return [Hash] OpenAPI schema object
998
+ def self.model_list_schema
999
+ {
1000
+ type: 'object',
1001
+ required: %w[object data],
1002
+ properties: {
1003
+ object: {
1004
+ type: 'string',
1005
+ description: 'Object type (always "list")',
1006
+ enum: ['list']
1007
+ },
1008
+ data: {
1009
+ type: 'array',
1010
+ description: 'List of available models',
1011
+ items: {
1012
+ '$ref': '#/components/schemas/Model'
1013
+ }
1014
+ }
1015
+ }
1016
+ }
1017
+ end
1018
+
1019
+ # Model schema
1020
+ #
1021
+ # @return [Hash] OpenAPI schema object
1022
+ def self.model_schema
1023
+ {
1024
+ type: 'object',
1025
+ required: %w[id object],
1026
+ properties: {
1027
+ id: {
1028
+ type: 'string',
1029
+ description: 'Model identifier'
1030
+ },
1031
+ object: {
1032
+ type: 'string',
1033
+ description: 'Object type (always "model")',
1034
+ enum: ['model']
1035
+ },
1036
+ created: {
1037
+ type: 'integer',
1038
+ description: 'Unix timestamp of model creation'
1039
+ },
1040
+ owned_by: {
1041
+ type: 'string',
1042
+ description: 'Organization that owns the model'
1043
+ }
1044
+ }
1045
+ }
1046
+ end
1047
+
1048
+ # Health response schema
1049
+ #
1050
+ # @return [Hash] OpenAPI schema object
1051
+ def self.health_response_schema
1052
+ {
1053
+ type: 'object',
1054
+ required: %w[status],
1055
+ properties: {
1056
+ status: {
1057
+ type: 'string',
1058
+ description: 'Health status',
1059
+ enum: %w[ok ready]
1060
+ },
1061
+ timestamp: {
1062
+ type: 'string',
1063
+ format: 'date-time',
1064
+ description: 'Timestamp of health check'
1065
+ }
1066
+ }
1067
+ }
1068
+ end
1069
+
1070
+ # Error response schema
1071
+ #
1072
+ # @return [Hash] OpenAPI schema object
1073
+ def self.error_response_schema
1074
+ {
1075
+ type: 'object',
1076
+ required: %w[error],
1077
+ properties: {
1078
+ error: {
1079
+ type: 'object',
1080
+ required: %w[message type],
1081
+ properties: {
1082
+ message: {
1083
+ type: 'string',
1084
+ description: 'Error message'
1085
+ },
1086
+ type: {
1087
+ type: 'string',
1088
+ description: 'Error type'
1089
+ },
1090
+ code: {
1091
+ type: 'string',
1092
+ description: 'Error code'
1093
+ }
1094
+ }
1095
+ }
1096
+ }
1097
+ }
1098
+ end
1099
+ end
1100
+ # rubocop:enable Metrics/ClassLength
1101
+ end
1102
+ end