solid_agent 0.0.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/CHANGELOG.md +68 -0
- data/LICENSE +21 -0
- data/README.md +321 -0
- data/Rakefile +32 -0
- data/docs/agent-md-spec.md +803 -0
- data/docs/parser-design.md +1369 -0
- data/docs/registry-api.md +882 -0
- data/examples/README.md +60 -0
- data/examples/manifests/changelog_writer.agent.md +81 -0
- data/examples/manifests/usage.rb +96 -0
- data/examples/memory_handoff/app/agents/researcher_agent.rb +36 -0
- data/examples/memory_handoff/app/agents/writer_agent.rb +41 -0
- data/examples/memory_handoff/usage.rb +45 -0
- data/examples/persistent_conversation/app/agents/support_agent.rb +59 -0
- data/examples/persistent_conversation/app/controllers/support_conversations_controller.rb +24 -0
- data/examples/persistent_conversation/app/views/agents/support/instructions.md.erb +8 -0
- data/examples/persistent_conversation/usage.rb +51 -0
- data/examples/reasoning/app/agents/analysis_agent.rb +52 -0
- data/examples/reasoning/usage.rb +52 -0
- data/examples/run_tracking/app/agents/report_agent.rb +30 -0
- data/examples/run_tracking/app/controllers/agent_runs_controller.rb +43 -0
- data/examples/run_tracking/app/jobs/document_analysis_job.rb +17 -0
- data/examples/run_tracking/app/services/document_analysis_run.rb +68 -0
- data/examples/run_tracking/usage.rb +85 -0
- data/examples/tool_streaming/app/agents/browser_agent.rb +65 -0
- data/examples/tool_streaming/app/channels/tool_status_channel.rb +24 -0
- data/examples/tool_streaming/app/views/browser_agent/tools/fetch_url.json.erb +15 -0
- data/examples/tool_streaming/usage.rb +47 -0
- data/lib/generators/solid_agent/agent/agent_generator.rb +95 -0
- data/lib/generators/solid_agent/agent/templates/action.text.erb +10 -0
- data/lib/generators/solid_agent/agent/templates/agent.rb.erb +93 -0
- data/lib/generators/solid_agent/context/context_generator.rb +124 -0
- data/lib/generators/solid_agent/context/templates/context_model.rb.erb +134 -0
- data/lib/generators/solid_agent/context/templates/create_context.rb.erb +32 -0
- data/lib/generators/solid_agent/context/templates/create_generations.rb.erb +46 -0
- data/lib/generators/solid_agent/context/templates/create_messages.rb.erb +37 -0
- data/lib/generators/solid_agent/context/templates/generation_model.rb.erb +51 -0
- data/lib/generators/solid_agent/context/templates/message_model.rb.erb +47 -0
- data/lib/generators/solid_agent/install/install_generator.rb +92 -0
- data/lib/generators/solid_agent/install/templates/agent_context.rb.erb +171 -0
- data/lib/generators/solid_agent/install/templates/agent_generation.rb.erb +76 -0
- data/lib/generators/solid_agent/install/templates/agent_memory.rb.erb +51 -0
- data/lib/generators/solid_agent/install/templates/agent_memory_entry.rb.erb +12 -0
- data/lib/generators/solid_agent/install/templates/agent_message.rb.erb +76 -0
- data/lib/generators/solid_agent/install/templates/agent_run.rb.erb +122 -0
- data/lib/generators/solid_agent/install/templates/create_agent_contexts.rb.erb +32 -0
- data/lib/generators/solid_agent/install/templates/create_agent_generations.rb.erb +51 -0
- data/lib/generators/solid_agent/install/templates/create_agent_memories.rb.erb +35 -0
- data/lib/generators/solid_agent/install/templates/create_agent_messages.rb.erb +38 -0
- data/lib/generators/solid_agent/install/templates/create_agent_runs.rb.erb +46 -0
- data/lib/generators/solid_agent/install/templates/initializer.rb.erb +51 -0
- data/lib/generators/solid_agent/manifest/manifest_generator.rb +209 -0
- data/lib/generators/solid_agent/manifest/templates/agent.md.erb +39 -0
- data/lib/generators/solid_agent/manifest/templates/prompt.erb +13 -0
- data/lib/generators/solid_agent/reasons/reasons_generator.rb +83 -0
- data/lib/generators/solid_agent/reasons/templates/add_reasoning_columns.rb.erb +12 -0
- data/lib/generators/solid_agent/tool/templates/tool.json.erb +19 -0
- data/lib/generators/solid_agent/tool/tool_generator.rb +117 -0
- data/lib/solid_agent/agent_manifest/agent_builder.rb +323 -0
- data/lib/solid_agent/agent_manifest/errors.rb +26 -0
- data/lib/solid_agent/agent_manifest/exporter_registry.rb +117 -0
- data/lib/solid_agent/agent_manifest/exporters/agent_md_exporter.rb +115 -0
- data/lib/solid_agent/agent_manifest/exporters/base_exporter.rb +152 -0
- data/lib/solid_agent/agent_manifest/exporters/crewai_exporter.rb +125 -0
- data/lib/solid_agent/agent_manifest/exporters/dotprompt_exporter.rb +92 -0
- data/lib/solid_agent/agent_manifest/input_schema.rb +154 -0
- data/lib/solid_agent/agent_manifest/manifest.rb +306 -0
- data/lib/solid_agent/agent_manifest/parser_registry.rb +185 -0
- data/lib/solid_agent/agent_manifest/parsers/agent_md_parser.rb +87 -0
- data/lib/solid_agent/agent_manifest/parsers/base_parser.rb +223 -0
- data/lib/solid_agent/agent_manifest/parsers/crewai_parser.rb +201 -0
- data/lib/solid_agent/agent_manifest/parsers/dotprompt_parser.rb +122 -0
- data/lib/solid_agent/agent_manifest/parsers/github_prompt_parser.rb +143 -0
- data/lib/solid_agent/agent_manifest/picoschema.rb +254 -0
- data/lib/solid_agent/agent_manifest/registry/auth.rb +103 -0
- data/lib/solid_agent/agent_manifest/registry/client.rb +384 -0
- data/lib/solid_agent/agent_manifest/resource.rb +103 -0
- data/lib/solid_agent/agent_manifest/tool.rb +160 -0
- data/lib/solid_agent/agent_manifest/validator.rb +368 -0
- data/lib/solid_agent/agent_manifest.rb +381 -0
- data/lib/solid_agent/engine.rb +16 -0
- data/lib/solid_agent/has_context.rb +670 -0
- data/lib/solid_agent/has_memory.rb +136 -0
- data/lib/solid_agent/has_reasons.rb +230 -0
- data/lib/solid_agent/has_tools.rb +257 -0
- data/lib/solid_agent/model_naming.rb +42 -0
- data/lib/solid_agent/model_pricing.rb +93 -0
- data/lib/solid_agent/reasonable/reason.rb +205 -0
- data/lib/solid_agent/reasonable.rb +181 -0
- data/lib/solid_agent/records/agent.rb +520 -0
- data/lib/solid_agent/records/agent_run.rb +520 -0
- data/lib/solid_agent/records/agent_template.rb +142 -0
- data/lib/solid_agent/records/agent_version.rb +141 -0
- data/lib/solid_agent/records/ownable.rb +130 -0
- data/lib/solid_agent/records.rb +152 -0
- data/lib/solid_agent/run_fingerprint.rb +51 -0
- data/lib/solid_agent/streams_tool_updates.rb +178 -0
- data/lib/solid_agent/tool_cache.rb +91 -0
- data/lib/solid_agent/version.rb +5 -0
- data/lib/solid_agent.rb +95 -0
- data/sig/solid_agent.rbs +4 -0
- metadata +174 -14
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "agent_manifest/errors"
|
|
4
|
+
require_relative "agent_manifest/manifest"
|
|
5
|
+
require_relative "agent_manifest/tool"
|
|
6
|
+
require_relative "agent_manifest/resource"
|
|
7
|
+
require_relative "agent_manifest/input_schema"
|
|
8
|
+
require_relative "agent_manifest/picoschema"
|
|
9
|
+
require_relative "agent_manifest/parser_registry"
|
|
10
|
+
require_relative "agent_manifest/parsers/base_parser"
|
|
11
|
+
require_relative "agent_manifest/parsers/agent_md_parser"
|
|
12
|
+
require_relative "agent_manifest/parsers/dotprompt_parser"
|
|
13
|
+
require_relative "agent_manifest/parsers/crewai_parser"
|
|
14
|
+
require_relative "agent_manifest/parsers/github_prompt_parser"
|
|
15
|
+
require_relative "agent_manifest/exporter_registry"
|
|
16
|
+
require_relative "agent_manifest/exporters/base_exporter"
|
|
17
|
+
require_relative "agent_manifest/exporters/agent_md_exporter"
|
|
18
|
+
require_relative "agent_manifest/exporters/dotprompt_exporter"
|
|
19
|
+
require_relative "agent_manifest/exporters/crewai_exporter"
|
|
20
|
+
require_relative "agent_manifest/validator"
|
|
21
|
+
require_relative "agent_manifest/agent_builder"
|
|
22
|
+
require_relative "agent_manifest/registry/auth"
|
|
23
|
+
require_relative "agent_manifest/registry/client"
|
|
24
|
+
|
|
25
|
+
require "digest"
|
|
26
|
+
require "json"
|
|
27
|
+
|
|
28
|
+
module SolidAgent
|
|
29
|
+
# AgentManifest provides a unified interface for working with agent definition files.
|
|
30
|
+
#
|
|
31
|
+
# Supports multiple formats:
|
|
32
|
+
# - `.agent.md` - Native format with full feature support
|
|
33
|
+
# - `.prompt` - Google Dotprompt format
|
|
34
|
+
# - `agents.yaml` - CrewAI format
|
|
35
|
+
# - `.prompt.md` - GitHub Copilot format
|
|
36
|
+
#
|
|
37
|
+
# @example Parse a manifest file
|
|
38
|
+
# manifest = SolidAgent::AgentManifest.parse("research_assistant.agent.md")
|
|
39
|
+
#
|
|
40
|
+
# @example Parse with auto-detection
|
|
41
|
+
# manifest = SolidAgent::AgentManifest.parse("agents.yaml")
|
|
42
|
+
#
|
|
43
|
+
# @example Export to different format
|
|
44
|
+
# content = SolidAgent::AgentManifest.export(manifest, :dotprompt)
|
|
45
|
+
#
|
|
46
|
+
# @example Convert between formats
|
|
47
|
+
# SolidAgent::AgentManifest.convert("agent.yaml", :agent_md, "agent.agent.md")
|
|
48
|
+
#
|
|
49
|
+
# @example Load as agent class
|
|
50
|
+
# klass = SolidAgent::AgentManifest.load_agent("research.agent.md")
|
|
51
|
+
# agent = klass.new
|
|
52
|
+
#
|
|
53
|
+
# @example Validate a manifest
|
|
54
|
+
# errors = SolidAgent::AgentManifest.validate("agent.agent.md")
|
|
55
|
+
#
|
|
56
|
+
# @example Load from any source
|
|
57
|
+
# manifest = SolidAgent::AgentManifest.load("https://example.com/agent.md")
|
|
58
|
+
# manifest = SolidAgent::AgentManifest.load({ name: "quick", model: "gpt-4o" })
|
|
59
|
+
#
|
|
60
|
+
module AgentManifest
|
|
61
|
+
class << self
|
|
62
|
+
# ============================================
|
|
63
|
+
# Unified Loading API
|
|
64
|
+
# ============================================
|
|
65
|
+
|
|
66
|
+
# Load manifest from any source with auto-detection
|
|
67
|
+
#
|
|
68
|
+
# @param source [String, Hash] File path, URL, JSON string, YAML string, or Hash
|
|
69
|
+
# @param format [Symbol] Force format (:agent_md, :json, :yaml, :dotprompt, :crewai)
|
|
70
|
+
# @return [Manifest] Parsed manifest
|
|
71
|
+
def load(source, format: nil)
|
|
72
|
+
case source
|
|
73
|
+
when Hash
|
|
74
|
+
from_hash(source)
|
|
75
|
+
when ->(s) { s.is_a?(String) && s.match?(%r{\Ahttps?://}) }
|
|
76
|
+
from_url(source, format: format)
|
|
77
|
+
when ->(s) { s.is_a?(String) && File.exist?(s) }
|
|
78
|
+
from_file(source, format: format)
|
|
79
|
+
when String
|
|
80
|
+
from_string(source, format: format || detect_string_format(source))
|
|
81
|
+
else
|
|
82
|
+
raise ArgumentError, "Unknown source type: #{source.class}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Load manifest from URL
|
|
87
|
+
#
|
|
88
|
+
# @param url [String] URL to fetch manifest from
|
|
89
|
+
# @param format [Symbol] Force format (auto-detected if nil)
|
|
90
|
+
# @return [Manifest] Parsed manifest
|
|
91
|
+
def from_url(url, format: nil)
|
|
92
|
+
require "net/http"
|
|
93
|
+
require "uri"
|
|
94
|
+
|
|
95
|
+
uri = URI.parse(url)
|
|
96
|
+
response = Net::HTTP.get_response(uri)
|
|
97
|
+
|
|
98
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
99
|
+
raise SolidAgent::LoadError, "Failed to fetch #{url}: #{response.code}"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
format ||= detect_format_from_url(url) || detect_format_from_content_type(response)
|
|
103
|
+
manifest = from_string(response.body, format: format)
|
|
104
|
+
manifest.source_path = url
|
|
105
|
+
manifest
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Load manifest from file
|
|
109
|
+
#
|
|
110
|
+
# @param path [String] Path to manifest file
|
|
111
|
+
# @param format [Symbol] Force format (auto-detected if nil)
|
|
112
|
+
# @return [Manifest] Parsed manifest
|
|
113
|
+
def from_file(path, format: nil)
|
|
114
|
+
parse(path, format: format)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Load manifest from string content
|
|
118
|
+
#
|
|
119
|
+
# @param content [String] Manifest content
|
|
120
|
+
# @param format [Symbol] Content format
|
|
121
|
+
# @return [Manifest] Parsed manifest
|
|
122
|
+
def from_string(content, format:)
|
|
123
|
+
parse_string(content, format: format)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Load manifest from JSON string
|
|
127
|
+
#
|
|
128
|
+
# @param json_string [String] JSON content
|
|
129
|
+
# @return [Manifest] Parsed manifest
|
|
130
|
+
def from_json(json_string)
|
|
131
|
+
from_hash(JSON.parse(json_string, symbolize_names: true))
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Load manifest from YAML string
|
|
135
|
+
#
|
|
136
|
+
# @param yaml_string [String] YAML content
|
|
137
|
+
# @return [Manifest] Parsed manifest
|
|
138
|
+
def from_yaml(yaml_string)
|
|
139
|
+
require "yaml"
|
|
140
|
+
from_hash(YAML.safe_load(yaml_string, symbolize_names: true, permitted_classes: [Symbol]))
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Load manifest from Hash
|
|
144
|
+
#
|
|
145
|
+
# @param hash [Hash] Manifest attributes
|
|
146
|
+
# @return [Manifest] Parsed manifest
|
|
147
|
+
def from_hash(hash)
|
|
148
|
+
Manifest.new(**hash.transform_keys(&:to_sym))
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Build agent class from manifest
|
|
152
|
+
#
|
|
153
|
+
# @param manifest [Manifest] Manifest to build from
|
|
154
|
+
# @param base_class [Class] Parent class
|
|
155
|
+
# @param class_name [String] Name to register constant as
|
|
156
|
+
# @return [Class] Generated agent class
|
|
157
|
+
def build(manifest, base_class: nil, class_name: nil)
|
|
158
|
+
AgentBuilder.build(manifest, base_class: base_class, class_name: class_name)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Build agent instance from manifest
|
|
162
|
+
#
|
|
163
|
+
# @param manifest [Manifest] Manifest to build from
|
|
164
|
+
# @param params [Hash] Parameters for the agent
|
|
165
|
+
# @return [Object] Agent instance
|
|
166
|
+
def build_instance(manifest, params: {}, **options)
|
|
167
|
+
AgentBuilder.build_instance(manifest, params: params, **options)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# ============================================
|
|
171
|
+
# Provenance & Checksums
|
|
172
|
+
# ============================================
|
|
173
|
+
|
|
174
|
+
# Generate checksum for any content
|
|
175
|
+
#
|
|
176
|
+
# @param content [String, Hash, Object] Content to checksum
|
|
177
|
+
# @return [String] MD5 hex digest
|
|
178
|
+
def checksum(content)
|
|
179
|
+
data = case content
|
|
180
|
+
when String then content
|
|
181
|
+
when Hash then content.to_json
|
|
182
|
+
else content.to_s
|
|
183
|
+
end
|
|
184
|
+
Digest::MD5.hexdigest(data)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Generate provenance record for a manifest
|
|
188
|
+
#
|
|
189
|
+
# @param manifest [Manifest] Manifest to generate provenance for
|
|
190
|
+
# @return [Hash] Provenance record with checksums
|
|
191
|
+
def provenance(manifest)
|
|
192
|
+
{
|
|
193
|
+
manifest_checksum: checksum(manifest.to_h),
|
|
194
|
+
instructions_checksum: manifest.instructions ? checksum(manifest.instructions) : nil,
|
|
195
|
+
model: manifest.model,
|
|
196
|
+
version: manifest.version,
|
|
197
|
+
source_path: manifest.source_path,
|
|
198
|
+
source_format: manifest.source_format,
|
|
199
|
+
generated_at: Time.now.iso8601,
|
|
200
|
+
tools: manifest.tools&.map { |t| { name: t.name, checksum: checksum(t.to_h) } }
|
|
201
|
+
}.compact
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# ============================================
|
|
205
|
+
# Original API (maintained for compatibility)
|
|
206
|
+
# ============================================
|
|
207
|
+
|
|
208
|
+
# Parse a manifest file
|
|
209
|
+
#
|
|
210
|
+
# @param path [String] Path to manifest file
|
|
211
|
+
# @param format [Symbol, nil] Force specific format (auto-detected if nil)
|
|
212
|
+
# @return [Manifest] Parsed manifest
|
|
213
|
+
# @raise [ParseError] if parsing fails
|
|
214
|
+
# @raise [UnknownFormatError] if format cannot be determined
|
|
215
|
+
def parse(path, format: nil)
|
|
216
|
+
ParserRegistry.parse(path, format: format)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Parse manifest content from a string
|
|
220
|
+
#
|
|
221
|
+
# @param content [String] Manifest content
|
|
222
|
+
# @param format [Symbol] Format of the content
|
|
223
|
+
# @return [Manifest] Parsed manifest
|
|
224
|
+
def parse_string(content, format:)
|
|
225
|
+
ParserRegistry.parse_string(content, format: format)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Export a manifest to a format string
|
|
229
|
+
#
|
|
230
|
+
# @param manifest [Manifest] Manifest to export
|
|
231
|
+
# @param format [Symbol] Target format (:agent_md, :dotprompt, :crewai)
|
|
232
|
+
# @param options [Hash] Format-specific options
|
|
233
|
+
# @return [String] Exported content
|
|
234
|
+
def export(manifest, format, **options)
|
|
235
|
+
ExporterRegistry.export(manifest, format, **options)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Export a manifest to a file
|
|
239
|
+
#
|
|
240
|
+
# @param manifest [Manifest] Manifest to export
|
|
241
|
+
# @param format [Symbol] Target format
|
|
242
|
+
# @param path [String] Output file path
|
|
243
|
+
# @param options [Hash] Format-specific options
|
|
244
|
+
# @return [String] The path written to
|
|
245
|
+
def export_to_file(manifest, format, path, **options)
|
|
246
|
+
ExporterRegistry.export_to_file(manifest, format, path, **options)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Convert a manifest file between formats
|
|
250
|
+
#
|
|
251
|
+
# @param input_path [String] Source file path
|
|
252
|
+
# @param output_format [Symbol] Target format
|
|
253
|
+
# @param output_path [String, nil] Output path (auto-generated if nil)
|
|
254
|
+
# @return [String] Output path
|
|
255
|
+
def convert(input_path, output_format, output_path = nil)
|
|
256
|
+
ExporterRegistry.convert(input_path, output_format, output_path)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Load an agent class from a manifest file
|
|
260
|
+
#
|
|
261
|
+
# @param path [String] Path to manifest file
|
|
262
|
+
# @param base_class [Class, nil] Base class to inherit from
|
|
263
|
+
# @param class_name [String, nil] Optional class name for registration
|
|
264
|
+
# @return [Class] The generated agent class
|
|
265
|
+
def load_agent(path, base_class: nil, class_name: nil)
|
|
266
|
+
manifest = parse(path)
|
|
267
|
+
AgentBuilder.build(manifest, base_class: base_class, class_name: class_name)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Load and instantiate an agent from a manifest file
|
|
271
|
+
#
|
|
272
|
+
# @param path [String] Path to manifest file
|
|
273
|
+
# @param params [Hash] Parameters to pass to the agent
|
|
274
|
+
# @param options [Hash] Options passed to build
|
|
275
|
+
# @return [Object] The instantiated agent
|
|
276
|
+
def load_agent_instance(path, params: {}, **options)
|
|
277
|
+
manifest = parse(path)
|
|
278
|
+
AgentBuilder.build_instance(manifest, params: params, **options)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Validate a manifest file or object
|
|
282
|
+
#
|
|
283
|
+
# @param path_or_manifest [String, Manifest] Path to file or Manifest object
|
|
284
|
+
# @param strict [Boolean] Enable strict validation
|
|
285
|
+
# @return [Array<String>] Array of error messages (empty if valid)
|
|
286
|
+
def validate(path_or_manifest, strict: false)
|
|
287
|
+
manifest = path_or_manifest.is_a?(String) ? parse(path_or_manifest) : path_or_manifest
|
|
288
|
+
Validator.validate(manifest, strict: strict)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# Check if a manifest is valid
|
|
292
|
+
#
|
|
293
|
+
# @param path_or_manifest [String, Manifest] Path to file or Manifest object
|
|
294
|
+
# @param strict [Boolean] Enable strict validation
|
|
295
|
+
# @return [Boolean]
|
|
296
|
+
def valid?(path_or_manifest, strict: false)
|
|
297
|
+
validate(path_or_manifest, strict: strict).empty?
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Validate and raise if invalid
|
|
301
|
+
#
|
|
302
|
+
# @param path_or_manifest [String, Manifest] Path to file or Manifest object
|
|
303
|
+
# @param strict [Boolean] Enable strict validation
|
|
304
|
+
# @raise [ValidationError] if invalid
|
|
305
|
+
# @return [Manifest] The validated manifest
|
|
306
|
+
def validate!(path_or_manifest, strict: false)
|
|
307
|
+
manifest = path_or_manifest.is_a?(String) ? parse(path_or_manifest) : path_or_manifest
|
|
308
|
+
Validator.validate!(manifest, strict: strict)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# List supported parser formats
|
|
312
|
+
#
|
|
313
|
+
# @return [Array<Symbol>]
|
|
314
|
+
def parser_formats
|
|
315
|
+
ParserRegistry.formats
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# List supported exporter formats
|
|
319
|
+
#
|
|
320
|
+
# @return [Array<Symbol>]
|
|
321
|
+
def exporter_formats
|
|
322
|
+
ExporterRegistry.formats
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Detect the format of a file
|
|
326
|
+
#
|
|
327
|
+
# @param path [String] Path to file
|
|
328
|
+
# @return [Symbol] Detected format
|
|
329
|
+
# @raise [UnknownFormatError] if format cannot be determined
|
|
330
|
+
def detect_format(path)
|
|
331
|
+
ParserRegistry.detect_format(path)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
private
|
|
335
|
+
|
|
336
|
+
# Detect format from string content
|
|
337
|
+
def detect_string_format(content)
|
|
338
|
+
content = content.strip
|
|
339
|
+
if content.start_with?("{") || content.start_with?("[")
|
|
340
|
+
:json
|
|
341
|
+
elsif content.start_with?("---")
|
|
342
|
+
# Could be YAML frontmatter (agent.md) or pure YAML
|
|
343
|
+
if content.match?(/\n---\s*\n/)
|
|
344
|
+
:agent_md
|
|
345
|
+
else
|
|
346
|
+
:yaml
|
|
347
|
+
end
|
|
348
|
+
elsif content.match?(/^\w+:\s/)
|
|
349
|
+
:yaml
|
|
350
|
+
elsif content.match?(/^#\s/)
|
|
351
|
+
:agent_md
|
|
352
|
+
else
|
|
353
|
+
:yaml
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# Detect format from URL path
|
|
358
|
+
def detect_format_from_url(url)
|
|
359
|
+
require "uri"
|
|
360
|
+
path = URI.parse(url).path
|
|
361
|
+
case File.extname(path)
|
|
362
|
+
when ".json" then :json
|
|
363
|
+
when ".yaml", ".yml" then :yaml
|
|
364
|
+
when ".md" then :agent_md
|
|
365
|
+
when ".prompt" then :dotprompt
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# Detect format from HTTP content-type
|
|
370
|
+
def detect_format_from_content_type(response)
|
|
371
|
+
content_type = response["content-type"].to_s
|
|
372
|
+
case content_type
|
|
373
|
+
when /json/ then :json
|
|
374
|
+
when /yaml/ then :yaml
|
|
375
|
+
when /markdown/ then :agent_md
|
|
376
|
+
else nil
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidAgent
|
|
4
|
+
class Engine < ::Rails::Engine
|
|
5
|
+
isolate_namespace SolidAgent
|
|
6
|
+
|
|
7
|
+
# Add generators to the Rails generator lookup path
|
|
8
|
+
config.generators do |g|
|
|
9
|
+
g.test_framework :minitest
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
initializer "solid_agent.load_generators" do
|
|
13
|
+
# Generators are automatically loaded from lib/generators
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|