agentic 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/.agentic.yml +2 -0
- data/.architecture/decisions/ArchitecturalFeatureBuilder.md +136 -0
- data/.architecture/decisions/ArchitectureConsiderations.md +200 -0
- data/.architecture/decisions/adr_001_observer_pattern_implementation.md +196 -0
- data/.architecture/decisions/adr_002_plan_orchestrator.md +320 -0
- data/.architecture/decisions/adr_003_plan_orchestrator_interface.md +179 -0
- data/.architecture/decisions/adrs/ADR-001-dependency-management.md +147 -0
- data/.architecture/decisions/adrs/ADR-002-system-boundaries.md +162 -0
- data/.architecture/decisions/adrs/ADR-003-content-safety.md +158 -0
- data/.architecture/decisions/adrs/ADR-004-agent-permissions.md +161 -0
- data/.architecture/decisions/adrs/ADR-005-adaptation-engine.md +127 -0
- data/.architecture/decisions/adrs/ADR-006-extension-system.md +273 -0
- data/.architecture/decisions/adrs/ADR-007-learning-system.md +156 -0
- data/.architecture/decisions/adrs/ADR-008-prompt-generation.md +325 -0
- data/.architecture/decisions/adrs/ADR-009-task-failure-handling.md +353 -0
- data/.architecture/decisions/adrs/ADR-010-task-input-handling.md +251 -0
- data/.architecture/decisions/adrs/ADR-011-task-observable-pattern.md +391 -0
- data/.architecture/decisions/adrs/ADR-012-task-output-handling.md +205 -0
- data/.architecture/decisions/adrs/ADR-013-architecture-alignment.md +211 -0
- data/.architecture/decisions/adrs/ADR-014-agent-capability-registry.md +80 -0
- data/.architecture/decisions/adrs/ADR-015-persistent-agent-store.md +100 -0
- data/.architecture/decisions/adrs/ADR-016-agent-assembly-engine.md +117 -0
- data/.architecture/decisions/adrs/ADR-017-streaming-observability.md +171 -0
- data/.architecture/decisions/capability_tools_distinction.md +150 -0
- data/.architecture/decisions/cli_command_structure.md +61 -0
- data/.architecture/implementation/agent_self_assembly_implementation.md +267 -0
- data/.architecture/implementation/agent_self_assembly_summary.md +138 -0
- data/.architecture/members.yml +187 -0
- data/.architecture/planning/self_implementation_exercise.md +295 -0
- data/.architecture/planning/session_compaction_rule.md +43 -0
- data/.architecture/planning/streaming_observability_feature.md +223 -0
- data/.architecture/principles.md +151 -0
- data/.architecture/recalibration/0-2-0.md +92 -0
- data/.architecture/recalibration/agent_self_assembly.md +238 -0
- data/.architecture/recalibration/cli_command_structure.md +91 -0
- data/.architecture/recalibration/implementation_roadmap_0-2-0.md +301 -0
- data/.architecture/recalibration/progress_tracking_0-2-0.md +114 -0
- data/.architecture/recalibration_process.md +127 -0
- data/.architecture/reviews/0-2-0.md +181 -0
- data/.architecture/reviews/cli_command_duplication.md +98 -0
- data/.architecture/templates/adr.md +105 -0
- data/.architecture/templates/implementation_roadmap.md +125 -0
- data/.architecture/templates/progress_tracking.md +89 -0
- data/.architecture/templates/recalibration_plan.md +70 -0
- data/.architecture/templates/version_comparison.md +124 -0
- data/.claude/settings.local.json +13 -0
- data/.claude-sessions/001-task-class-architecture-implementation.md +129 -0
- data/.claude-sessions/002-plan-orchestrator-interface-review.md +105 -0
- data/.claude-sessions/architecture-governance-implementation.md +37 -0
- data/.claude-sessions/architecture-review-session.md +27 -0
- data/ArchitecturalFeatureBuilder.md +136 -0
- data/ArchitectureConsiderations.md +229 -0
- data/CHANGELOG.md +57 -2
- data/CLAUDE.md +111 -0
- data/CONTRIBUTING.md +286 -0
- data/MAINTAINING.md +301 -0
- data/README.md +582 -28
- data/docs/agent_capabilities_api.md +259 -0
- data/docs/artifact_extension_points.md +757 -0
- data/docs/artifact_generation_architecture.md +323 -0
- data/docs/artifact_implementation_plan.md +596 -0
- data/docs/artifact_integration_points.md +345 -0
- data/docs/artifact_verification_strategies.md +581 -0
- data/docs/streaming_observability_architecture.md +510 -0
- data/exe/agentic +6 -1
- data/lefthook.yml +5 -0
- data/lib/agentic/adaptation_engine.rb +124 -0
- data/lib/agentic/agent.rb +181 -4
- data/lib/agentic/agent_assembly_engine.rb +442 -0
- data/lib/agentic/agent_capability_registry.rb +260 -0
- data/lib/agentic/agent_config.rb +63 -0
- data/lib/agentic/agent_specification.rb +46 -0
- data/lib/agentic/capabilities/examples.rb +530 -0
- data/lib/agentic/capabilities.rb +14 -0
- data/lib/agentic/capability_provider.rb +146 -0
- data/lib/agentic/capability_specification.rb +118 -0
- data/lib/agentic/cli/agent.rb +31 -0
- data/lib/agentic/cli/capabilities.rb +191 -0
- data/lib/agentic/cli/config.rb +134 -0
- data/lib/agentic/cli/execution_observer.rb +796 -0
- data/lib/agentic/cli.rb +1068 -0
- data/lib/agentic/default_agent_provider.rb +35 -0
- data/lib/agentic/errors/llm_error.rb +184 -0
- data/lib/agentic/execution_plan.rb +53 -0
- data/lib/agentic/execution_result.rb +91 -0
- data/lib/agentic/expected_answer_format.rb +46 -0
- data/lib/agentic/extension/domain_adapter.rb +109 -0
- data/lib/agentic/extension/plugin_manager.rb +163 -0
- data/lib/agentic/extension/protocol_handler.rb +116 -0
- data/lib/agentic/extension.rb +45 -0
- data/lib/agentic/factory_methods.rb +9 -1
- data/lib/agentic/generation_stats.rb +61 -0
- data/lib/agentic/learning/README.md +84 -0
- data/lib/agentic/learning/capability_optimizer.rb +613 -0
- data/lib/agentic/learning/execution_history_store.rb +251 -0
- data/lib/agentic/learning/pattern_recognizer.rb +500 -0
- data/lib/agentic/learning/strategy_optimizer.rb +706 -0
- data/lib/agentic/learning.rb +131 -0
- data/lib/agentic/llm_assisted_composition_strategy.rb +188 -0
- data/lib/agentic/llm_client.rb +215 -15
- data/lib/agentic/llm_config.rb +65 -1
- data/lib/agentic/llm_response.rb +163 -0
- data/lib/agentic/logger.rb +1 -1
- data/lib/agentic/observable.rb +51 -0
- data/lib/agentic/persistent_agent_store.rb +385 -0
- data/lib/agentic/plan_execution_result.rb +129 -0
- data/lib/agentic/plan_orchestrator.rb +464 -0
- data/lib/agentic/plan_orchestrator_config.rb +57 -0
- data/lib/agentic/retry_config.rb +63 -0
- data/lib/agentic/retry_handler.rb +125 -0
- data/lib/agentic/structured_outputs.rb +1 -1
- data/lib/agentic/task.rb +193 -0
- data/lib/agentic/task_definition.rb +39 -0
- data/lib/agentic/task_execution_result.rb +92 -0
- data/lib/agentic/task_failure.rb +66 -0
- data/lib/agentic/task_output_schemas.rb +112 -0
- data/lib/agentic/task_planner.rb +54 -19
- data/lib/agentic/task_result.rb +48 -0
- data/lib/agentic/ui.rb +244 -0
- data/lib/agentic/verification/critic_framework.rb +116 -0
- data/lib/agentic/verification/llm_verification_strategy.rb +60 -0
- data/lib/agentic/verification/schema_verification_strategy.rb +47 -0
- data/lib/agentic/verification/verification_hub.rb +62 -0
- data/lib/agentic/verification/verification_result.rb +50 -0
- data/lib/agentic/verification/verification_strategy.rb +26 -0
- data/lib/agentic/version.rb +1 -1
- data/lib/agentic.rb +74 -2
- data/plugins/README.md +41 -0
- metadata +245 -6
@@ -0,0 +1,757 @@
|
|
1
|
+
# Artifact Generation Extension Points
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
The artifact generation system is designed with extensibility as a core principle. This document outlines the extension points that allow developers to add new artifact types, generators, verification strategies, and domain-specific templates while maintaining system consistency and quality.
|
6
|
+
|
7
|
+
## Extension Architecture
|
8
|
+
|
9
|
+
Following the established Agentic extension patterns, the artifact system provides these extension points:
|
10
|
+
|
11
|
+
1. **ArtifactTypeProvider**: Register new artifact types and their specifications
|
12
|
+
2. **ArtifactGenerator**: Custom generation strategies for specific artifact types
|
13
|
+
3. **WorkspaceTemplate**: Predefined project structures and scaffolding
|
14
|
+
4. **VerificationStrategy**: Custom validation approaches for artifact types
|
15
|
+
5. **DomainAdapter**: Domain-specific artifact generation behaviors
|
16
|
+
|
17
|
+
## Core Extension Interfaces
|
18
|
+
|
19
|
+
### 1. ArtifactTypeProvider Interface
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
module Agentic
|
23
|
+
module Extension
|
24
|
+
# Base interface for artifact type providers
|
25
|
+
# Providers define new types of artifacts that can be generated
|
26
|
+
class ArtifactTypeProvider
|
27
|
+
# @return [String] Unique identifier for the artifact type
|
28
|
+
attr_reader :type_name
|
29
|
+
|
30
|
+
# @return [String] Human-readable description
|
31
|
+
attr_reader :description
|
32
|
+
|
33
|
+
# @return [Hash] Configuration options for this type
|
34
|
+
attr_reader :config
|
35
|
+
|
36
|
+
# Initialize a new artifact type provider
|
37
|
+
# @param type_name [String] Unique identifier for the artifact type
|
38
|
+
# @param description [String] Human-readable description
|
39
|
+
# @param config [Hash] Configuration options
|
40
|
+
def initialize(type_name, description, config = {})
|
41
|
+
@type_name = type_name
|
42
|
+
@description = description
|
43
|
+
@config = config
|
44
|
+
end
|
45
|
+
|
46
|
+
# Define the specification for this artifact type
|
47
|
+
# @return [ArtifactSpecification] The artifact specification
|
48
|
+
def specification
|
49
|
+
raise NotImplementedError, "Subclasses must implement specification"
|
50
|
+
end
|
51
|
+
|
52
|
+
# Create a generator for this artifact type
|
53
|
+
# @param context [Hash] Generation context (task, agent, etc.)
|
54
|
+
# @return [ArtifactGenerator] The generator instance
|
55
|
+
def create_generator(context = {})
|
56
|
+
raise NotImplementedError, "Subclasses must implement create_generator"
|
57
|
+
end
|
58
|
+
|
59
|
+
# Create a verification strategy for this artifact type
|
60
|
+
# @param config [Hash] Verification configuration
|
61
|
+
# @return [VerificationStrategy] The verification strategy
|
62
|
+
def create_verifier(config = {})
|
63
|
+
raise NotImplementedError, "Subclasses must implement create_verifier"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Check if this provider can handle a specific requirement
|
67
|
+
# @param requirement [Hash] The artifact requirement
|
68
|
+
# @return [Boolean] True if this provider can handle the requirement
|
69
|
+
def can_handle?(requirement)
|
70
|
+
requirement[:type] == @type_name ||
|
71
|
+
(requirement[:file_extension] &&
|
72
|
+
specification.supported_extensions.include?(requirement[:file_extension]))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
### 2. ArtifactGenerator Interface
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
module Agentic
|
83
|
+
module Extension
|
84
|
+
# Base interface for artifact generators
|
85
|
+
# Generators handle the actual content creation for specific artifact types
|
86
|
+
class ArtifactGenerator
|
87
|
+
# @return [ArtifactSpecification] The artifact specification this generator handles
|
88
|
+
attr_reader :specification
|
89
|
+
|
90
|
+
# @return [Hash] Configuration options for generation
|
91
|
+
attr_reader :config
|
92
|
+
|
93
|
+
# Initialize a new artifact generator
|
94
|
+
# @param specification [ArtifactSpecification] The artifact specification
|
95
|
+
# @param config [Hash] Configuration options
|
96
|
+
def initialize(specification, config = {})
|
97
|
+
@specification = specification
|
98
|
+
@config = config
|
99
|
+
end
|
100
|
+
|
101
|
+
# Generate content for an artifact
|
102
|
+
# @param input [Hash] Input data for generation (task description, requirements, etc.)
|
103
|
+
# @param context [Hash] Generation context (agent, workspace, etc.)
|
104
|
+
# @return [String] The generated content
|
105
|
+
def generate_content(input, context = {})
|
106
|
+
raise NotImplementedError, "Subclasses must implement generate_content"
|
107
|
+
end
|
108
|
+
|
109
|
+
# Determine the output filename for the artifact
|
110
|
+
# @param input [Hash] Input data
|
111
|
+
# @param context [Hash] Generation context
|
112
|
+
# @return [String] The filename (without path)
|
113
|
+
def determine_filename(input, context = {})
|
114
|
+
base_name = extract_name_from_input(input) || "artifact"
|
115
|
+
"#{base_name}#{@specification.default_extension}"
|
116
|
+
end
|
117
|
+
|
118
|
+
# Post-process generated content (formatting, cleanup, etc.)
|
119
|
+
# @param content [String] The raw generated content
|
120
|
+
# @param context [Hash] Processing context
|
121
|
+
# @return [String] The processed content
|
122
|
+
def post_process(content, context = {})
|
123
|
+
content # Default: no post-processing
|
124
|
+
end
|
125
|
+
|
126
|
+
# Validate generation requirements before attempting generation
|
127
|
+
# @param input [Hash] Input data
|
128
|
+
# @return [Array<String>] Array of validation errors (empty if valid)
|
129
|
+
def validate_requirements(input)
|
130
|
+
[] # Default: no validation errors
|
131
|
+
end
|
132
|
+
|
133
|
+
protected
|
134
|
+
|
135
|
+
# Extract a meaningful name from input data
|
136
|
+
# @param input [Hash] Input data
|
137
|
+
# @return [String, nil] Extracted name or nil
|
138
|
+
def extract_name_from_input(input)
|
139
|
+
input[:name] ||
|
140
|
+
input[:class_name] ||
|
141
|
+
input[:function_name] ||
|
142
|
+
extract_from_description(input[:description])
|
143
|
+
end
|
144
|
+
|
145
|
+
# Extract name from description text
|
146
|
+
# @param description [String] Description text
|
147
|
+
# @return [String, nil] Extracted name or nil
|
148
|
+
def extract_from_description(description)
|
149
|
+
return nil unless description
|
150
|
+
|
151
|
+
# Look for patterns like "Create a UserService class"
|
152
|
+
if match = description.match(/create\s+(?:a\s+)?(\w+)/i)
|
153
|
+
match[1].downcase
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
### 3. WorkspaceTemplate Interface
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
module Agentic
|
165
|
+
module Extension
|
166
|
+
# Base interface for workspace templates
|
167
|
+
# Templates define project structures and provide scaffolding
|
168
|
+
class WorkspaceTemplate
|
169
|
+
# @return [String] Unique identifier for the template
|
170
|
+
attr_reader :name
|
171
|
+
|
172
|
+
# @return [String] Human-readable description
|
173
|
+
attr_reader :description
|
174
|
+
|
175
|
+
# @return [Hash] Template configuration
|
176
|
+
attr_reader :config
|
177
|
+
|
178
|
+
# Initialize a new workspace template
|
179
|
+
# @param name [String] Unique identifier
|
180
|
+
# @param description [String] Human-readable description
|
181
|
+
# @param config [Hash] Template configuration
|
182
|
+
def initialize(name, description, config = {})
|
183
|
+
@name = name
|
184
|
+
@description = description
|
185
|
+
@config = config
|
186
|
+
end
|
187
|
+
|
188
|
+
# Define the directory structure for this template
|
189
|
+
# @return [Hash] Directory structure definition
|
190
|
+
def directory_structure
|
191
|
+
raise NotImplementedError, "Subclasses must implement directory_structure"
|
192
|
+
end
|
193
|
+
|
194
|
+
# Get template files (scaffolding, boilerplate, etc.)
|
195
|
+
# @return [Hash] Map of relative paths to file contents
|
196
|
+
def template_files
|
197
|
+
{}
|
198
|
+
end
|
199
|
+
|
200
|
+
# Get artifact specifications for this template
|
201
|
+
# @return [Array<ArtifactSpecification>] Required artifacts
|
202
|
+
def artifact_specifications
|
203
|
+
[]
|
204
|
+
end
|
205
|
+
|
206
|
+
# Apply template to a workspace directory
|
207
|
+
# @param workspace_path [String] Path to workspace directory
|
208
|
+
# @param context [Hash] Template application context
|
209
|
+
# @return [Hash] Metadata about applied template
|
210
|
+
def apply_to_workspace(workspace_path, context = {})
|
211
|
+
create_directory_structure(workspace_path)
|
212
|
+
create_template_files(workspace_path, context)
|
213
|
+
|
214
|
+
{
|
215
|
+
template: @name,
|
216
|
+
applied_at: Time.now,
|
217
|
+
directories_created: count_directories_created(workspace_path),
|
218
|
+
files_created: count_files_created(workspace_path)
|
219
|
+
}
|
220
|
+
end
|
221
|
+
|
222
|
+
# Check if this template is suitable for given requirements
|
223
|
+
# @param requirements [Hash] Project requirements
|
224
|
+
# @return [Boolean] True if template is suitable
|
225
|
+
def suitable_for?(requirements)
|
226
|
+
return false unless requirements[:project_type]
|
227
|
+
|
228
|
+
supported_types = @config[:supported_project_types] || []
|
229
|
+
supported_types.include?(requirements[:project_type])
|
230
|
+
end
|
231
|
+
|
232
|
+
protected
|
233
|
+
|
234
|
+
# Create directory structure in workspace
|
235
|
+
# @param workspace_path [String] Workspace directory path
|
236
|
+
def create_directory_structure(workspace_path)
|
237
|
+
structure = directory_structure
|
238
|
+
create_directories_recursive(workspace_path, structure)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Create template files in workspace
|
242
|
+
# @param workspace_path [String] Workspace directory path
|
243
|
+
# @param context [Hash] Template context for file processing
|
244
|
+
def create_template_files(workspace_path, context)
|
245
|
+
template_files.each do |relative_path, content|
|
246
|
+
full_path = File.join(workspace_path, relative_path)
|
247
|
+
processed_content = process_template_content(content, context)
|
248
|
+
|
249
|
+
FileUtils.mkdir_p(File.dirname(full_path))
|
250
|
+
File.write(full_path, processed_content)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
# Process template content with context variables
|
255
|
+
# @param content [String] Template content
|
256
|
+
# @param context [Hash] Context variables
|
257
|
+
# @return [String] Processed content
|
258
|
+
def process_template_content(content, context)
|
259
|
+
# Simple template variable substitution
|
260
|
+
# In a real implementation, this would use a proper template engine
|
261
|
+
result = content.dup
|
262
|
+
context.each do |key, value|
|
263
|
+
result.gsub!("{{#{key}}}", value.to_s)
|
264
|
+
end
|
265
|
+
result
|
266
|
+
end
|
267
|
+
|
268
|
+
# Create directories recursively
|
269
|
+
# @param base_path [String] Base directory path
|
270
|
+
# @param structure [Hash] Directory structure hash
|
271
|
+
def create_directories_recursive(base_path, structure)
|
272
|
+
structure.each do |dir_name, sub_structure|
|
273
|
+
dir_path = File.join(base_path, dir_name.to_s)
|
274
|
+
FileUtils.mkdir_p(dir_path)
|
275
|
+
|
276
|
+
if sub_structure.is_a?(Hash)
|
277
|
+
create_directories_recursive(dir_path, sub_structure)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
```
|
285
|
+
|
286
|
+
## Built-in Extension Implementations
|
287
|
+
|
288
|
+
### 1. Ruby Source Code Provider
|
289
|
+
|
290
|
+
```ruby
|
291
|
+
class RubySourceProvider < ArtifactTypeProvider
|
292
|
+
def initialize
|
293
|
+
super("ruby_source", "Ruby source code files", {
|
294
|
+
supported_extensions: [".rb"],
|
295
|
+
requires_syntax_check: true,
|
296
|
+
supports_testing: true
|
297
|
+
})
|
298
|
+
end
|
299
|
+
|
300
|
+
def specification
|
301
|
+
@specification ||= ArtifactSpecification.new(
|
302
|
+
type: @type_name,
|
303
|
+
default_extension: ".rb",
|
304
|
+
supported_extensions: [".rb"],
|
305
|
+
validation_rules: [
|
306
|
+
"syntax_check",
|
307
|
+
"rubocop_compliance",
|
308
|
+
"yard_documentation"
|
309
|
+
],
|
310
|
+
dependencies: [],
|
311
|
+
metadata: {
|
312
|
+
language: "ruby",
|
313
|
+
paradigm: "object_oriented",
|
314
|
+
runtime: "ruby"
|
315
|
+
}
|
316
|
+
)
|
317
|
+
end
|
318
|
+
|
319
|
+
def create_generator(context = {})
|
320
|
+
RubySourceGenerator.new(specification, context)
|
321
|
+
end
|
322
|
+
|
323
|
+
def create_verifier(config = {})
|
324
|
+
RubySourceVerificationStrategy.new(config)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
class RubySourceGenerator < ArtifactGenerator
|
329
|
+
def generate_content(input, context = {})
|
330
|
+
agent = context[:agent]
|
331
|
+
prompt = build_ruby_generation_prompt(input)
|
332
|
+
|
333
|
+
response = agent.execute_prompt(prompt)
|
334
|
+
extract_code_from_response(response)
|
335
|
+
end
|
336
|
+
|
337
|
+
def determine_filename(input, context = {})
|
338
|
+
if input[:class_name]
|
339
|
+
"#{input[:class_name].downcase}.rb"
|
340
|
+
elsif input[:module_name]
|
341
|
+
"#{input[:module_name].downcase}.rb"
|
342
|
+
else
|
343
|
+
super
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
def post_process(content, context = {})
|
348
|
+
# Apply RuboCop auto-corrections if available
|
349
|
+
if system('which rubocop > /dev/null 2>&1')
|
350
|
+
apply_rubocop_autocorrect(content)
|
351
|
+
else
|
352
|
+
content
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def validate_requirements(input)
|
357
|
+
errors = []
|
358
|
+
errors << "Missing description" unless input[:description]
|
359
|
+
errors << "No clear class or module intent" unless has_clear_intent?(input)
|
360
|
+
errors
|
361
|
+
end
|
362
|
+
|
363
|
+
private
|
364
|
+
|
365
|
+
def build_ruby_generation_prompt(input)
|
366
|
+
<<~PROMPT
|
367
|
+
Generate Ruby code based on the following requirements:
|
368
|
+
|
369
|
+
Description: #{input[:description]}
|
370
|
+
#{"Class Name: #{input[:class_name]}" if input[:class_name]}
|
371
|
+
#{"Module Name: #{input[:module_name]}" if input[:module_name]}
|
372
|
+
#{"Include Tests: Yes" if input[:include_tests]}
|
373
|
+
|
374
|
+
Requirements:
|
375
|
+
- Follow Ruby style guide conventions
|
376
|
+
- Include appropriate documentation
|
377
|
+
- Use meaningful variable and method names
|
378
|
+
- Include error handling where appropriate
|
379
|
+
|
380
|
+
Return only the Ruby code, properly formatted.
|
381
|
+
PROMPT
|
382
|
+
end
|
383
|
+
|
384
|
+
def extract_code_from_response(response)
|
385
|
+
# Extract code from markdown code blocks or plain text
|
386
|
+
if response.include?("```ruby")
|
387
|
+
response[/```ruby\n(.*?)```/m, 1]
|
388
|
+
elsif response.include?("```")
|
389
|
+
response[/```\n(.*?)```/m, 1]
|
390
|
+
else
|
391
|
+
response
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def has_clear_intent?(input)
|
396
|
+
description = input[:description]&.downcase
|
397
|
+
return false unless description
|
398
|
+
|
399
|
+
ruby_keywords = %w[class module method function def initialize]
|
400
|
+
ruby_keywords.any? { |keyword| description.include?(keyword) }
|
401
|
+
end
|
402
|
+
end
|
403
|
+
```
|
404
|
+
|
405
|
+
### 2. React Application Template
|
406
|
+
|
407
|
+
```ruby
|
408
|
+
class ReactAppTemplate < WorkspaceTemplate
|
409
|
+
def initialize
|
410
|
+
super("react_app", "React web application", {
|
411
|
+
supported_project_types: ["web_app", "spa", "react_app"],
|
412
|
+
requires_node: true,
|
413
|
+
package_manager: "npm"
|
414
|
+
})
|
415
|
+
end
|
416
|
+
|
417
|
+
def directory_structure
|
418
|
+
{
|
419
|
+
src: {
|
420
|
+
components: {},
|
421
|
+
hooks: {},
|
422
|
+
utils: {},
|
423
|
+
styles: {}
|
424
|
+
},
|
425
|
+
public: {},
|
426
|
+
tests: {
|
427
|
+
components: {},
|
428
|
+
integration: {}
|
429
|
+
},
|
430
|
+
docs: {}
|
431
|
+
}
|
432
|
+
end
|
433
|
+
|
434
|
+
def template_files
|
435
|
+
{
|
436
|
+
"package.json" => package_json_template,
|
437
|
+
"src/App.js" => app_component_template,
|
438
|
+
"src/index.js" => index_template,
|
439
|
+
"public/index.html" => html_template,
|
440
|
+
"README.md" => readme_template,
|
441
|
+
".gitignore" => gitignore_template
|
442
|
+
}
|
443
|
+
end
|
444
|
+
|
445
|
+
def artifact_specifications
|
446
|
+
[
|
447
|
+
ArtifactSpecification.new(
|
448
|
+
type: "react_component",
|
449
|
+
default_extension: ".js",
|
450
|
+
supported_extensions: [".js", ".jsx", ".ts", ".tsx"]
|
451
|
+
),
|
452
|
+
ArtifactSpecification.new(
|
453
|
+
type: "css_styles",
|
454
|
+
default_extension: ".css",
|
455
|
+
supported_extensions: [".css", ".scss", ".less"]
|
456
|
+
)
|
457
|
+
]
|
458
|
+
end
|
459
|
+
|
460
|
+
private
|
461
|
+
|
462
|
+
def package_json_template
|
463
|
+
<<~JSON
|
464
|
+
{
|
465
|
+
"name": "{{project_name}}",
|
466
|
+
"version": "1.0.0",
|
467
|
+
"description": "{{project_description}}",
|
468
|
+
"main": "src/index.js",
|
469
|
+
"scripts": {
|
470
|
+
"start": "react-scripts start",
|
471
|
+
"build": "react-scripts build",
|
472
|
+
"test": "react-scripts test",
|
473
|
+
"eject": "react-scripts eject"
|
474
|
+
},
|
475
|
+
"dependencies": {
|
476
|
+
"react": "^18.2.0",
|
477
|
+
"react-dom": "^18.2.0",
|
478
|
+
"react-scripts": "5.0.1"
|
479
|
+
},
|
480
|
+
"devDependencies": {
|
481
|
+
"@testing-library/jest-dom": "^5.16.4",
|
482
|
+
"@testing-library/react": "^13.3.0",
|
483
|
+
"@testing-library/user-event": "^13.5.0"
|
484
|
+
}
|
485
|
+
}
|
486
|
+
JSON
|
487
|
+
end
|
488
|
+
|
489
|
+
def app_component_template
|
490
|
+
<<~JAVASCRIPT
|
491
|
+
import React from 'react';
|
492
|
+
import './App.css';
|
493
|
+
|
494
|
+
function App() {
|
495
|
+
return (
|
496
|
+
<div className="App">
|
497
|
+
<header className="App-header">
|
498
|
+
<h1>{{project_name}}</h1>
|
499
|
+
<p>{{project_description}}</p>
|
500
|
+
</header>
|
501
|
+
</div>
|
502
|
+
);
|
503
|
+
}
|
504
|
+
|
505
|
+
export default App;
|
506
|
+
JAVASCRIPT
|
507
|
+
end
|
508
|
+
|
509
|
+
def readme_template
|
510
|
+
<<~MARKDOWN
|
511
|
+
# {{project_name}}
|
512
|
+
|
513
|
+
{{project_description}}
|
514
|
+
|
515
|
+
## Getting Started
|
516
|
+
|
517
|
+
This project was created with Create React App.
|
518
|
+
|
519
|
+
### Available Scripts
|
520
|
+
|
521
|
+
- `npm start` - Runs the app in development mode
|
522
|
+
- `npm test` - Launches the test runner
|
523
|
+
- `npm run build` - Builds the app for production
|
524
|
+
|
525
|
+
## Features
|
526
|
+
|
527
|
+
- Modern React with hooks
|
528
|
+
- Component-based architecture
|
529
|
+
- Responsive design
|
530
|
+
- Testing setup included
|
531
|
+
|
532
|
+
MARKDOWN
|
533
|
+
end
|
534
|
+
end
|
535
|
+
```
|
536
|
+
|
537
|
+
### 3. JSON Configuration Provider
|
538
|
+
|
539
|
+
```ruby
|
540
|
+
class JsonConfigProvider < ArtifactTypeProvider
|
541
|
+
def initialize
|
542
|
+
super("json_config", "JSON configuration files", {
|
543
|
+
supported_extensions: [".json"],
|
544
|
+
requires_schema_validation: true,
|
545
|
+
supports_comments: false
|
546
|
+
})
|
547
|
+
end
|
548
|
+
|
549
|
+
def specification
|
550
|
+
@specification ||= ArtifactSpecification.new(
|
551
|
+
type: @type_name,
|
552
|
+
default_extension: ".json",
|
553
|
+
supported_extensions: [".json"],
|
554
|
+
validation_rules: [
|
555
|
+
"json_syntax_check",
|
556
|
+
"schema_validation",
|
557
|
+
"required_fields_check"
|
558
|
+
],
|
559
|
+
dependencies: [],
|
560
|
+
metadata: {
|
561
|
+
format: "json",
|
562
|
+
structured: true,
|
563
|
+
human_readable: true
|
564
|
+
}
|
565
|
+
)
|
566
|
+
end
|
567
|
+
|
568
|
+
def create_generator(context = {})
|
569
|
+
JsonConfigGenerator.new(specification, context)
|
570
|
+
end
|
571
|
+
|
572
|
+
def create_verifier(config = {})
|
573
|
+
JsonConfigVerificationStrategy.new(config)
|
574
|
+
end
|
575
|
+
end
|
576
|
+
```
|
577
|
+
|
578
|
+
## Extension Registration System
|
579
|
+
|
580
|
+
### ArtifactTypeRegistry
|
581
|
+
|
582
|
+
```ruby
|
583
|
+
module Agentic
|
584
|
+
# Registry for artifact type providers and extensions
|
585
|
+
class ArtifactTypeRegistry
|
586
|
+
include Singleton
|
587
|
+
|
588
|
+
def initialize
|
589
|
+
@providers = {}
|
590
|
+
@templates = {}
|
591
|
+
@domain_adapters = {}
|
592
|
+
register_builtin_providers
|
593
|
+
end
|
594
|
+
|
595
|
+
# Register an artifact type provider
|
596
|
+
# @param provider [ArtifactTypeProvider] The provider to register
|
597
|
+
def register_provider(provider)
|
598
|
+
@providers[provider.type_name] = provider
|
599
|
+
Agentic.logger.info("Registered artifact type provider: #{provider.type_name}")
|
600
|
+
end
|
601
|
+
|
602
|
+
# Register a workspace template
|
603
|
+
# @param template [WorkspaceTemplate] The template to register
|
604
|
+
def register_template(template)
|
605
|
+
@templates[template.name] = template
|
606
|
+
Agentic.logger.info("Registered workspace template: #{template.name}")
|
607
|
+
end
|
608
|
+
|
609
|
+
# Register a domain adapter
|
610
|
+
# @param domain [String] Domain identifier
|
611
|
+
# @param adapter [DomainAdapter] The domain adapter
|
612
|
+
def register_domain_adapter(domain, adapter)
|
613
|
+
@domain_adapters[domain] = adapter
|
614
|
+
Agentic.logger.info("Registered domain adapter: #{domain}")
|
615
|
+
end
|
616
|
+
|
617
|
+
# Get provider for artifact type
|
618
|
+
# @param type_name [String] The artifact type name
|
619
|
+
# @return [ArtifactTypeProvider, nil] The provider or nil
|
620
|
+
def get_provider(type_name)
|
621
|
+
@providers[type_name]
|
622
|
+
end
|
623
|
+
|
624
|
+
# Get template by name
|
625
|
+
# @param template_name [String] The template name
|
626
|
+
# @return [WorkspaceTemplate, nil] The template or nil
|
627
|
+
def get_template(template_name)
|
628
|
+
@templates[template_name]
|
629
|
+
end
|
630
|
+
|
631
|
+
# Find suitable template for requirements
|
632
|
+
# @param requirements [Hash] Project requirements
|
633
|
+
# @return [WorkspaceTemplate, nil] Suitable template or nil
|
634
|
+
def find_template(requirements)
|
635
|
+
@templates.values.find { |template| template.suitable_for?(requirements) }
|
636
|
+
end
|
637
|
+
|
638
|
+
# Get domain adapter
|
639
|
+
# @param domain [String] Domain identifier
|
640
|
+
# @return [DomainAdapter, nil] The adapter or nil
|
641
|
+
def get_domain_adapter(domain)
|
642
|
+
@domain_adapters[domain]
|
643
|
+
end
|
644
|
+
|
645
|
+
# List all registered providers
|
646
|
+
# @return [Hash] Map of type names to providers
|
647
|
+
def list_providers
|
648
|
+
@providers.dup
|
649
|
+
end
|
650
|
+
|
651
|
+
# List all registered templates
|
652
|
+
# @return [Hash] Map of template names to templates
|
653
|
+
def list_templates
|
654
|
+
@templates.dup
|
655
|
+
end
|
656
|
+
|
657
|
+
private
|
658
|
+
|
659
|
+
def register_builtin_providers
|
660
|
+
register_provider(RubySourceProvider.new)
|
661
|
+
register_provider(JsonConfigProvider.new)
|
662
|
+
register_provider(JavaScriptSourceProvider.new)
|
663
|
+
register_provider(PythonSourceProvider.new)
|
664
|
+
register_provider(MarkdownDocProvider.new)
|
665
|
+
|
666
|
+
register_template(ReactAppTemplate.new)
|
667
|
+
register_template(RubyGemTemplate.new)
|
668
|
+
register_template(NodeJsAppTemplate.new)
|
669
|
+
register_template(PythonPackageTemplate.new)
|
670
|
+
end
|
671
|
+
end
|
672
|
+
end
|
673
|
+
```
|
674
|
+
|
675
|
+
## Plugin Discovery and Auto-Registration
|
676
|
+
|
677
|
+
```ruby
|
678
|
+
# Example plugin file: plugins/custom_artifact_types.rb
|
679
|
+
module CustomArtifactTypes
|
680
|
+
# Plugin initialization hook
|
681
|
+
def self.initialize_plugin
|
682
|
+
registry = Agentic::ArtifactTypeRegistry.instance
|
683
|
+
|
684
|
+
# Register custom providers
|
685
|
+
registry.register_provider(DockerfileProvider.new)
|
686
|
+
registry.register_provider(KubernetesManifestProvider.new)
|
687
|
+
|
688
|
+
# Register custom templates
|
689
|
+
registry.register_template(MicroserviceTemplate.new)
|
690
|
+
registry.register_template(DockerizedAppTemplate.new)
|
691
|
+
end
|
692
|
+
|
693
|
+
# Plugin entry point
|
694
|
+
def self.call(event, data)
|
695
|
+
case event
|
696
|
+
when :before_artifact_generation
|
697
|
+
apply_custom_preprocessing(data)
|
698
|
+
when :after_artifact_generation
|
699
|
+
apply_custom_postprocessing(data)
|
700
|
+
end
|
701
|
+
end
|
702
|
+
end
|
703
|
+
|
704
|
+
# Auto-register the plugin
|
705
|
+
Agentic::Extension::PluginManager.instance.register!(
|
706
|
+
"custom_artifact_types",
|
707
|
+
CustomArtifactTypes,
|
708
|
+
{
|
709
|
+
version: "1.0.0",
|
710
|
+
description: "Custom artifact types for containerized applications",
|
711
|
+
author: "Your Name"
|
712
|
+
}
|
713
|
+
)
|
714
|
+
```
|
715
|
+
|
716
|
+
## Domain-Specific Artifact Adaptation
|
717
|
+
|
718
|
+
```ruby
|
719
|
+
# Healthcare domain adapter for artifact generation
|
720
|
+
class HealthcareArtifactAdapter < Agentic::Extension::DomainAdapter
|
721
|
+
def initialize
|
722
|
+
super("healthcare", {
|
723
|
+
compliance_frameworks: ["HIPAA", "FDA"],
|
724
|
+
required_documentation: ["privacy_policy", "security_audit"],
|
725
|
+
code_standards: ["secure_coding", "data_encryption"]
|
726
|
+
})
|
727
|
+
|
728
|
+
register_artifact_adapters
|
729
|
+
end
|
730
|
+
|
731
|
+
private
|
732
|
+
|
733
|
+
def register_artifact_adapters
|
734
|
+
# Adapt Ruby code generation for healthcare compliance
|
735
|
+
register_adapter(:ruby_source, lambda do |generator, context|
|
736
|
+
generator.add_compliance_requirements([
|
737
|
+
"data_encryption",
|
738
|
+
"audit_logging",
|
739
|
+
"access_controls"
|
740
|
+
])
|
741
|
+
generator
|
742
|
+
end)
|
743
|
+
|
744
|
+
# Adapt configuration generation for HIPAA compliance
|
745
|
+
register_adapter(:json_config, lambda do |generator, context|
|
746
|
+
generator.add_required_fields([
|
747
|
+
"encryption_settings",
|
748
|
+
"audit_configuration",
|
749
|
+
"access_policies"
|
750
|
+
])
|
751
|
+
generator
|
752
|
+
end)
|
753
|
+
end
|
754
|
+
end
|
755
|
+
```
|
756
|
+
|
757
|
+
This extension system provides comprehensive customization capabilities while maintaining consistency with the existing Agentic architecture. Developers can easily add new artifact types, generation strategies, workspace templates, and domain-specific behaviors through well-defined interfaces and automatic discovery mechanisms.
|