swarm_sdk 2.2.0 → 2.3.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/lib/swarm_sdk/agent/builder.rb +58 -0
- data/lib/swarm_sdk/agent/chat.rb +527 -1059
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/context_tracker.rb +9 -88
- data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +204 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/hook_integration.rb +111 -44
- data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +78 -0
- data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +233 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/logging_helpers.rb +1 -1
- data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +83 -0
- data/lib/swarm_sdk/agent/{chat → chat_helpers}/system_reminder_injector.rb +12 -12
- data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +79 -0
- data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +98 -0
- data/lib/swarm_sdk/agent/context.rb +2 -2
- data/lib/swarm_sdk/agent/definition.rb +66 -154
- data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +4 -2
- data/lib/swarm_sdk/agent/system_prompt_builder.rb +161 -0
- data/lib/swarm_sdk/builders/base_builder.rb +409 -0
- data/lib/swarm_sdk/concerns/cleanupable.rb +39 -0
- data/lib/swarm_sdk/concerns/snapshotable.rb +67 -0
- data/lib/swarm_sdk/concerns/validatable.rb +55 -0
- data/lib/swarm_sdk/configuration/parser.rb +353 -0
- data/lib/swarm_sdk/configuration/translator.rb +255 -0
- data/lib/swarm_sdk/configuration.rb +65 -543
- data/lib/swarm_sdk/context_compactor/token_counter.rb +3 -3
- data/lib/swarm_sdk/context_compactor.rb +6 -11
- data/lib/swarm_sdk/context_management/builder.rb +128 -0
- data/lib/swarm_sdk/context_management/context.rb +328 -0
- data/lib/swarm_sdk/defaults.rb +196 -0
- data/lib/swarm_sdk/events_to_messages.rb +18 -0
- data/lib/swarm_sdk/hooks/shell_executor.rb +2 -1
- data/lib/swarm_sdk/log_collector.rb +179 -29
- data/lib/swarm_sdk/log_stream.rb +29 -0
- data/lib/swarm_sdk/node_context.rb +1 -1
- data/lib/swarm_sdk/observer/builder.rb +81 -0
- data/lib/swarm_sdk/observer/config.rb +45 -0
- data/lib/swarm_sdk/observer/manager.rb +236 -0
- data/lib/swarm_sdk/patterns/agent_observer.rb +160 -0
- data/lib/swarm_sdk/plugin.rb +93 -3
- data/lib/swarm_sdk/snapshot.rb +6 -6
- data/lib/swarm_sdk/snapshot_from_events.rb +13 -2
- data/lib/swarm_sdk/state_restorer.rb +136 -151
- data/lib/swarm_sdk/state_snapshot.rb +65 -100
- data/lib/swarm_sdk/swarm/agent_initializer.rb +180 -136
- data/lib/swarm_sdk/swarm/builder.rb +44 -578
- data/lib/swarm_sdk/swarm/executor.rb +213 -0
- data/lib/swarm_sdk/swarm/hook_triggers.rb +150 -0
- data/lib/swarm_sdk/swarm/logging_callbacks.rb +340 -0
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +7 -4
- data/lib/swarm_sdk/swarm/tool_configurator.rb +42 -138
- data/lib/swarm_sdk/swarm.rb +137 -679
- data/lib/swarm_sdk/tools/bash.rb +11 -3
- data/lib/swarm_sdk/tools/delegate.rb +61 -43
- data/lib/swarm_sdk/tools/edit.rb +8 -13
- data/lib/swarm_sdk/tools/glob.rb +9 -1
- data/lib/swarm_sdk/tools/grep.rb +7 -0
- data/lib/swarm_sdk/tools/multi_edit.rb +15 -11
- data/lib/swarm_sdk/tools/path_resolver.rb +51 -2
- data/lib/swarm_sdk/tools/read.rb +11 -13
- data/lib/swarm_sdk/tools/registry.rb +122 -10
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +8 -5
- data/lib/swarm_sdk/tools/stores/storage.rb +0 -6
- data/lib/swarm_sdk/tools/todo_write.rb +7 -0
- data/lib/swarm_sdk/tools/web_fetch.rb +3 -2
- data/lib/swarm_sdk/tools/write.rb +8 -13
- data/lib/swarm_sdk/version.rb +1 -1
- data/lib/swarm_sdk/{node → workflow}/agent_config.rb +1 -1
- data/lib/swarm_sdk/workflow/builder.rb +143 -0
- data/lib/swarm_sdk/workflow/executor.rb +497 -0
- data/lib/swarm_sdk/{node/builder.rb → workflow/node_builder.rb} +3 -3
- data/lib/swarm_sdk/{node → workflow}/transformer_executor.rb +3 -2
- data/lib/swarm_sdk/{node_orchestrator.rb → workflow.rb} +152 -456
- data/lib/swarm_sdk.rb +33 -3
- metadata +67 -15
- data/lib/swarm_sdk/providers/openai_with_responses.rb +0 -589
|
@@ -18,11 +18,6 @@ module SwarmSDK
|
|
|
18
18
|
# system_prompt: "You build APIs"
|
|
19
19
|
# })
|
|
20
20
|
class Definition
|
|
21
|
-
DEFAULT_MODEL = "gpt-5"
|
|
22
|
-
DEFAULT_PROVIDER = "openai"
|
|
23
|
-
DEFAULT_TIMEOUT = 300 # 5 minutes - reasoning models can take a while
|
|
24
|
-
BASE_SYSTEM_PROMPT_PATH = File.expand_path("../prompts/base_system_prompt.md.erb", __dir__)
|
|
25
|
-
|
|
26
21
|
attr_reader :name,
|
|
27
22
|
:description,
|
|
28
23
|
:model,
|
|
@@ -44,7 +39,7 @@ module SwarmSDK
|
|
|
44
39
|
:agent_permissions,
|
|
45
40
|
:assume_model_exists,
|
|
46
41
|
:hooks,
|
|
47
|
-
:
|
|
42
|
+
:plugin_configs,
|
|
48
43
|
:shared_across_delegations
|
|
49
44
|
|
|
50
45
|
attr_accessor :bypass_permissions, :max_concurrent_tools
|
|
@@ -72,14 +67,14 @@ module SwarmSDK
|
|
|
72
67
|
end
|
|
73
68
|
|
|
74
69
|
@description = config[:description]
|
|
75
|
-
@model = config[:model] ||
|
|
76
|
-
@provider = config[:provider] ||
|
|
70
|
+
@model = config[:model] || Defaults::Agent::MODEL
|
|
71
|
+
@provider = config[:provider] || Defaults::Agent::PROVIDER
|
|
77
72
|
@base_url = config[:base_url]
|
|
78
73
|
@api_version = config[:api_version]
|
|
79
74
|
@context_window = config[:context_window] # Explicit context window override
|
|
80
75
|
@parameters = config[:parameters] || {}
|
|
81
76
|
@headers = Utils.stringify_keys(config[:headers] || {})
|
|
82
|
-
@timeout = config[:timeout] ||
|
|
77
|
+
@timeout = config[:timeout] || Defaults::Timeouts::AGENT_REQUEST_SECONDS
|
|
83
78
|
@bypass_permissions = config[:bypass_permissions] || false
|
|
84
79
|
@max_concurrent_tools = config[:max_concurrent_tools]
|
|
85
80
|
# Always assume model exists - SwarmSDK validates models separately using models.json
|
|
@@ -100,9 +95,9 @@ module SwarmSDK
|
|
|
100
95
|
# Parse directory first so it can be used in system prompt rendering
|
|
101
96
|
@directory = parse_directory(config[:directory])
|
|
102
97
|
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
@
|
|
98
|
+
# Extract plugin configurations (generic bucket for all plugin-specific keys)
|
|
99
|
+
# This allows plugins to store their config without SDK knowing about them
|
|
100
|
+
@plugin_configs = extract_plugin_configs(config)
|
|
106
101
|
|
|
107
102
|
# Delegation isolation mode (default: false = isolated instances per delegation)
|
|
108
103
|
@shared_across_delegations = config[:shared_across_delegations] || false
|
|
@@ -132,40 +127,20 @@ module SwarmSDK
|
|
|
132
127
|
validate!
|
|
133
128
|
end
|
|
134
129
|
|
|
135
|
-
#
|
|
130
|
+
# Get plugin-specific configuration
|
|
136
131
|
#
|
|
137
|
-
#
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
# Hash (from YAML) - check for directory key
|
|
145
|
-
if @memory.is_a?(Hash)
|
|
146
|
-
directory = @memory[:directory] || @memory["directory"]
|
|
147
|
-
return !directory.nil? && !directory.to_s.strip.empty?
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
false
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
# Parse memory configuration from Hash or MemoryConfig object
|
|
132
|
+
# Plugins store their configuration in the generic plugin_configs hash.
|
|
133
|
+
# This allows SDK to remain plugin-agnostic while plugins can store
|
|
134
|
+
# arbitrary configuration.
|
|
135
|
+
#
|
|
136
|
+
# @param plugin_name [Symbol] Plugin name (e.g., :memory)
|
|
137
|
+
# @return [Object, nil] Plugin configuration or nil if not present
|
|
154
138
|
#
|
|
155
|
-
# @
|
|
156
|
-
#
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
# If it's a MemoryConfig object (duck typing - has directory, adapter, mode methods)
|
|
161
|
-
# return as-is. This could be SwarmMemory::DSL::MemoryConfig or any compatible object.
|
|
162
|
-
return memory_config if memory_config.respond_to?(:directory) &&
|
|
163
|
-
memory_config.respond_to?(:adapter) &&
|
|
164
|
-
memory_config.respond_to?(:enabled?)
|
|
165
|
-
|
|
166
|
-
# If it's a hash (from YAML), keep it as a hash
|
|
167
|
-
# Plugin will create storage adapter based on the hash values
|
|
168
|
-
memory_config
|
|
139
|
+
# @example
|
|
140
|
+
# agent_definition.plugin_config(:memory)
|
|
141
|
+
# # => { directory: "tmp/memory", mode: :researcher }
|
|
142
|
+
def plugin_config(plugin_name)
|
|
143
|
+
@plugin_configs[plugin_name.to_sym] || @plugin_configs[plugin_name.to_s]
|
|
169
144
|
end
|
|
170
145
|
|
|
171
146
|
def to_h
|
|
@@ -285,122 +260,59 @@ module SwarmSDK
|
|
|
285
260
|
end
|
|
286
261
|
|
|
287
262
|
def build_full_system_prompt(custom_prompt)
|
|
288
|
-
#
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
end
|
|
298
|
-
elsif default_tools_enabled?
|
|
299
|
-
# Non-coding agent: optionally include TODO/Scratchpad sections if default tools available
|
|
300
|
-
non_coding_base = render_non_coding_base_prompt
|
|
301
|
-
|
|
302
|
-
if custom_prompt && !custom_prompt.strip.empty?
|
|
303
|
-
# Prepend TODO/Scratchpad info before custom prompt
|
|
304
|
-
"#{non_coding_base}\n\n#{custom_prompt}"
|
|
305
|
-
else
|
|
306
|
-
# No custom prompt: just return TODO/Scratchpad info
|
|
307
|
-
non_coding_base
|
|
308
|
-
end
|
|
309
|
-
else
|
|
310
|
-
# No default tools: return only custom prompt
|
|
311
|
-
(custom_prompt || "").to_s
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
# Append plugin contributions to system prompt
|
|
315
|
-
plugin_contributions = collect_plugin_prompt_contributions
|
|
316
|
-
if plugin_contributions.any?
|
|
317
|
-
combined_contributions = plugin_contributions.join("\n\n")
|
|
318
|
-
prompt = if prompt && !prompt.strip.empty?
|
|
319
|
-
"#{prompt}\n\n#{combined_contributions}"
|
|
320
|
-
else
|
|
321
|
-
combined_contributions
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
prompt
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
# Check if default tools are enabled (i.e., not disabled)
|
|
329
|
-
#
|
|
330
|
-
# @return [Boolean] True if default tools should be included
|
|
331
|
-
def default_tools_enabled?
|
|
332
|
-
@disable_default_tools != true
|
|
263
|
+
# Delegate to SystemPromptBuilder for all prompt construction logic
|
|
264
|
+
# This keeps Definition focused on data storage while extracting complex logic
|
|
265
|
+
SystemPromptBuilder.build(
|
|
266
|
+
custom_prompt: custom_prompt,
|
|
267
|
+
coding_agent: @coding_agent,
|
|
268
|
+
disable_default_tools: @disable_default_tools,
|
|
269
|
+
directory: @directory,
|
|
270
|
+
definition: self,
|
|
271
|
+
)
|
|
333
272
|
end
|
|
334
273
|
|
|
335
|
-
def
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
os_version = begin
|
|
339
|
-
%x(uname -sr 2>/dev/null).strip
|
|
340
|
-
rescue
|
|
341
|
-
RUBY_PLATFORM
|
|
342
|
-
end
|
|
343
|
-
date = Time.now.strftime("%Y-%m-%d")
|
|
344
|
-
|
|
345
|
-
template_content = File.read(BASE_SYSTEM_PROMPT_PATH)
|
|
346
|
-
ERB.new(template_content).result(binding)
|
|
274
|
+
def parse_directory(directory_config)
|
|
275
|
+
directory_config ||= "."
|
|
276
|
+
File.expand_path(directory_config.to_s)
|
|
347
277
|
end
|
|
348
278
|
|
|
349
|
-
#
|
|
279
|
+
# Extract plugin-specific configuration keys from the config hash
|
|
350
280
|
#
|
|
351
|
-
#
|
|
352
|
-
#
|
|
281
|
+
# Standard SDK keys are filtered out, leaving only plugin-specific keys.
|
|
282
|
+
# This allows plugins to add their own configuration without SDK modifications.
|
|
353
283
|
#
|
|
354
|
-
# @
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
<today-date>
|
|
388
|
-
#{date}
|
|
389
|
-
#</today-date>
|
|
390
|
-
|
|
391
|
-
# Current Environment
|
|
392
|
-
|
|
393
|
-
<env>
|
|
394
|
-
Working directory: #{cwd}
|
|
395
|
-
Platform: #{platform}
|
|
396
|
-
OS Version: #{os_version}
|
|
397
|
-
</env>
|
|
398
|
-
PROMPT
|
|
399
|
-
end
|
|
400
|
-
|
|
401
|
-
def parse_directory(directory_config)
|
|
402
|
-
directory_config ||= "."
|
|
403
|
-
File.expand_path(directory_config.to_s)
|
|
284
|
+
# @param config [Hash] Full agent configuration
|
|
285
|
+
# @return [Hash] Plugin-specific configuration (keys not recognized by SDK)
|
|
286
|
+
def extract_plugin_configs(config)
|
|
287
|
+
standard_keys = [
|
|
288
|
+
:name,
|
|
289
|
+
:description,
|
|
290
|
+
:model,
|
|
291
|
+
:provider,
|
|
292
|
+
:base_url,
|
|
293
|
+
:api_version,
|
|
294
|
+
:context_window,
|
|
295
|
+
:parameters,
|
|
296
|
+
:headers,
|
|
297
|
+
:timeout,
|
|
298
|
+
:bypass_permissions,
|
|
299
|
+
:max_concurrent_tools,
|
|
300
|
+
:assume_model_exists,
|
|
301
|
+
:disable_default_tools,
|
|
302
|
+
:coding_agent,
|
|
303
|
+
:directory,
|
|
304
|
+
:system_prompt,
|
|
305
|
+
:tools,
|
|
306
|
+
:delegates_to,
|
|
307
|
+
:mcp_servers,
|
|
308
|
+
:hooks,
|
|
309
|
+
:default_permissions,
|
|
310
|
+
:permissions,
|
|
311
|
+
:shared_across_delegations,
|
|
312
|
+
:directories,
|
|
313
|
+
]
|
|
314
|
+
|
|
315
|
+
config.reject { |k, _| standard_keys.include?(k.to_sym) }
|
|
404
316
|
end
|
|
405
317
|
|
|
406
318
|
# Parse tools configuration with permissions support
|
|
@@ -64,7 +64,8 @@ module SwarmSDK
|
|
|
64
64
|
@on_request.call(request_data)
|
|
65
65
|
rescue StandardError => e
|
|
66
66
|
# Don't let logging errors break the request
|
|
67
|
-
|
|
67
|
+
LogStream.emit_error(e, source: "llm_instrumentation_middleware", context: "emit_request_event", provider: @provider_name)
|
|
68
|
+
RubyLLM.logger.debug("LLM instrumentation request error: #{e.message}")
|
|
68
69
|
end
|
|
69
70
|
|
|
70
71
|
# Emit response event
|
|
@@ -97,7 +98,8 @@ module SwarmSDK
|
|
|
97
98
|
@on_response.call(response_data)
|
|
98
99
|
rescue StandardError => e
|
|
99
100
|
# Don't let logging errors break the response
|
|
100
|
-
|
|
101
|
+
LogStream.emit_error(e, source: "llm_instrumentation_middleware", context: "emit_response_event", provider: @provider_name)
|
|
102
|
+
RubyLLM.logger.debug("LLM instrumentation response error: #{e.message}")
|
|
101
103
|
end
|
|
102
104
|
|
|
103
105
|
# Sanitize headers by removing sensitive data
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SwarmSDK
|
|
4
|
+
module Agent
|
|
5
|
+
# Builds system prompts for agents
|
|
6
|
+
#
|
|
7
|
+
# This class encapsulates all system prompt construction logic, including:
|
|
8
|
+
# - Base system prompt rendering (for coding agents)
|
|
9
|
+
# - Non-coding base prompt rendering
|
|
10
|
+
# - Plugin prompt contribution collection
|
|
11
|
+
# - Combining base and custom prompts
|
|
12
|
+
#
|
|
13
|
+
# ## Safety Note for SwarmMemory Integration
|
|
14
|
+
#
|
|
15
|
+
# This is an INTERNAL helper that receives Definition attributes as input.
|
|
16
|
+
# Definition remains the single source of truth with all instance variables.
|
|
17
|
+
# SwarmMemory uses `agent_definition.instance_eval { binding }` for ERB templating,
|
|
18
|
+
# which requires all properties to be on Definition object. This helper is safe
|
|
19
|
+
# because it doesn't affect Definition's structure - it only extracts logic.
|
|
20
|
+
class SystemPromptBuilder
|
|
21
|
+
BASE_SYSTEM_PROMPT_PATH = File.expand_path("../prompts/base_system_prompt.md.erb", __dir__)
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
# Build the complete system prompt for an agent
|
|
25
|
+
#
|
|
26
|
+
# @param custom_prompt [String, nil] Custom system prompt from configuration
|
|
27
|
+
# @param coding_agent [Boolean] Whether agent is configured for coding tasks
|
|
28
|
+
# @param disable_default_tools [Boolean, Array, nil] Default tools disable configuration
|
|
29
|
+
# @param directory [String] Agent's working directory
|
|
30
|
+
# @param definition [Definition] Full definition for plugin contributions
|
|
31
|
+
# @return [String] Complete system prompt
|
|
32
|
+
def build(custom_prompt:, coding_agent:, disable_default_tools:, directory:, definition:)
|
|
33
|
+
new(
|
|
34
|
+
custom_prompt: custom_prompt,
|
|
35
|
+
coding_agent: coding_agent,
|
|
36
|
+
disable_default_tools: disable_default_tools,
|
|
37
|
+
directory: directory,
|
|
38
|
+
definition: definition,
|
|
39
|
+
).build
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def initialize(custom_prompt:, coding_agent:, disable_default_tools:, directory:, definition:)
|
|
44
|
+
@custom_prompt = custom_prompt
|
|
45
|
+
@coding_agent = coding_agent
|
|
46
|
+
@disable_default_tools = disable_default_tools
|
|
47
|
+
@directory = directory
|
|
48
|
+
@definition = definition
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def build
|
|
52
|
+
prompt = base_prompt_section
|
|
53
|
+
prompt = append_plugin_contributions(prompt)
|
|
54
|
+
prompt
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def base_prompt_section
|
|
60
|
+
if @coding_agent
|
|
61
|
+
build_coding_agent_prompt
|
|
62
|
+
elsif default_tools_enabled?
|
|
63
|
+
build_non_coding_agent_prompt
|
|
64
|
+
else
|
|
65
|
+
(@custom_prompt || "").to_s
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def build_coding_agent_prompt
|
|
70
|
+
rendered_base = render_base_system_prompt
|
|
71
|
+
|
|
72
|
+
if @custom_prompt && !@custom_prompt.strip.empty?
|
|
73
|
+
"#{rendered_base}\n\n#{@custom_prompt}"
|
|
74
|
+
else
|
|
75
|
+
rendered_base
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def build_non_coding_agent_prompt
|
|
80
|
+
non_coding_base = render_non_coding_base_prompt
|
|
81
|
+
|
|
82
|
+
if @custom_prompt && !@custom_prompt.strip.empty?
|
|
83
|
+
"#{non_coding_base}\n\n#{@custom_prompt}"
|
|
84
|
+
else
|
|
85
|
+
non_coding_base
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def default_tools_enabled?
|
|
90
|
+
@disable_default_tools != true
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def render_base_system_prompt
|
|
94
|
+
cwd = @directory || Dir.pwd
|
|
95
|
+
platform = RUBY_PLATFORM
|
|
96
|
+
os_version = begin
|
|
97
|
+
%x(uname -sr 2>/dev/null).strip
|
|
98
|
+
rescue
|
|
99
|
+
RUBY_PLATFORM
|
|
100
|
+
end
|
|
101
|
+
date = Time.now.strftime("%Y-%m-%d")
|
|
102
|
+
|
|
103
|
+
template_content = File.read(BASE_SYSTEM_PROMPT_PATH)
|
|
104
|
+
ERB.new(template_content).result(binding)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def render_non_coding_base_prompt
|
|
108
|
+
cwd = @directory || Dir.pwd
|
|
109
|
+
platform = RUBY_PLATFORM
|
|
110
|
+
os_version = begin
|
|
111
|
+
%x(uname -sr 2>/dev/null).strip
|
|
112
|
+
rescue
|
|
113
|
+
RUBY_PLATFORM
|
|
114
|
+
end
|
|
115
|
+
date = Time.now.strftime("%Y-%m-%d")
|
|
116
|
+
|
|
117
|
+
<<~PROMPT.strip
|
|
118
|
+
# Today's date
|
|
119
|
+
|
|
120
|
+
<today-date>
|
|
121
|
+
#{date}
|
|
122
|
+
#</today-date>
|
|
123
|
+
|
|
124
|
+
# Current Environment
|
|
125
|
+
|
|
126
|
+
<env>
|
|
127
|
+
Working directory: #{cwd}
|
|
128
|
+
Platform: #{platform}
|
|
129
|
+
OS Version: #{os_version}
|
|
130
|
+
</env>
|
|
131
|
+
PROMPT
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def append_plugin_contributions(prompt)
|
|
135
|
+
contributions = collect_plugin_prompt_contributions
|
|
136
|
+
return prompt if contributions.empty?
|
|
137
|
+
|
|
138
|
+
combined_contributions = contributions.join("\n\n")
|
|
139
|
+
|
|
140
|
+
if prompt && !prompt.strip.empty?
|
|
141
|
+
"#{prompt}\n\n#{combined_contributions}"
|
|
142
|
+
else
|
|
143
|
+
combined_contributions
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def collect_plugin_prompt_contributions
|
|
148
|
+
contributions = []
|
|
149
|
+
|
|
150
|
+
PluginRegistry.all.each do |plugin|
|
|
151
|
+
next unless plugin.storage_enabled?(@definition)
|
|
152
|
+
|
|
153
|
+
contribution = plugin.system_prompt_contribution(agent_definition: @definition, storage: nil)
|
|
154
|
+
contributions << contribution if contribution && !contribution.strip.empty?
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
contributions
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|