swarm_sdk 2.0.3 → 2.0.5
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 +41 -0
- data/lib/swarm_sdk/agent/chat/logging_helpers.rb +22 -5
- data/lib/swarm_sdk/agent/definition.rb +52 -6
- data/lib/swarm_sdk/configuration.rb +3 -1
- data/lib/swarm_sdk/prompts/memory.md.erb +480 -0
- data/lib/swarm_sdk/swarm/agent_initializer.rb +16 -3
- data/lib/swarm_sdk/swarm/builder.rb +9 -1
- data/lib/swarm_sdk/swarm/tool_configurator.rb +73 -23
- data/lib/swarm_sdk/swarm.rb +51 -7
- data/lib/swarm_sdk/tools/document_converters/html_converter.rb +101 -0
- data/lib/swarm_sdk/tools/memory/memory_delete.rb +64 -0
- data/lib/swarm_sdk/tools/memory/memory_edit.rb +145 -0
- data/lib/swarm_sdk/tools/memory/memory_glob.rb +94 -0
- data/lib/swarm_sdk/tools/memory/memory_grep.rb +147 -0
- data/lib/swarm_sdk/tools/memory/memory_multi_edit.rb +228 -0
- data/lib/swarm_sdk/tools/memory/memory_read.rb +82 -0
- data/lib/swarm_sdk/tools/memory/memory_write.rb +90 -0
- data/lib/swarm_sdk/tools/registry.rb +11 -3
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +96 -0
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +76 -0
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +91 -0
- data/lib/swarm_sdk/tools/stores/memory_storage.rb +300 -0
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +224 -0
- data/lib/swarm_sdk/tools/stores/storage.rb +148 -0
- data/lib/swarm_sdk/tools/stores/storage_read_tracker.rb +61 -0
- data/lib/swarm_sdk/tools/web_fetch.rb +261 -0
- data/lib/swarm_sdk/version.rb +1 -1
- data/lib/swarm_sdk.rb +39 -0
- metadata +18 -5
- data/lib/swarm_sdk/tools/scratchpad_list.rb +0 -88
- data/lib/swarm_sdk/tools/scratchpad_read.rb +0 -59
- data/lib/swarm_sdk/tools/scratchpad_write.rb +0 -88
- data/lib/swarm_sdk/tools/stores/scratchpad.rb +0 -153
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2b0a4dbb64785b7fc12ad6a461acfb4502135cbf06a86f08de6ae7b2df05e21
|
4
|
+
data.tar.gz: c118e7fb996b6ce679d1feb80e359f246ca5741d4d2ae1dbbece537796502b0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fe12e5956c41623e43b0f7b69d8bce442052c180aaf89e787b1163836f013a45435a8147ce749eaaf2809799cb0c17f3ac2942ed5fdff048805d8ab21d1924d
|
7
|
+
data.tar.gz: 526374b16146e8721c2b1a7370bf58843fa7bd03b36b5f1cd6a5a23e263446171005dec50ce5ec979d6aa42f5a07886f27f09939aacd76c45c922478782624bb
|
@@ -2,6 +2,32 @@
|
|
2
2
|
|
3
3
|
module SwarmSDK
|
4
4
|
module Agent
|
5
|
+
# Configuration for agent memory
|
6
|
+
class MemoryConfig
|
7
|
+
def initialize
|
8
|
+
@adapter = :filesystem # Default adapter
|
9
|
+
@directory = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
# DSL method to set/get adapter
|
13
|
+
def adapter(value = nil)
|
14
|
+
return @adapter if value.nil?
|
15
|
+
|
16
|
+
@adapter = value.to_sym
|
17
|
+
end
|
18
|
+
|
19
|
+
# DSL method to set/get directory
|
20
|
+
def directory(value = nil)
|
21
|
+
return @directory if value.nil?
|
22
|
+
|
23
|
+
@directory = value
|
24
|
+
end
|
25
|
+
|
26
|
+
def enabled?
|
27
|
+
!@directory.nil?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
5
31
|
# Builder provides fluent API for configuring agents
|
6
32
|
#
|
7
33
|
# This class offers a Ruby DSL for defining agents with a clean, readable syntax.
|
@@ -51,6 +77,7 @@ module SwarmSDK
|
|
51
77
|
@hooks = []
|
52
78
|
@permissions_config = {}
|
53
79
|
@default_permissions = {} # Set by SwarmBuilder from all_agents
|
80
|
+
@memory_config = nil
|
54
81
|
end
|
55
82
|
|
56
83
|
# Set/get agent model
|
@@ -218,6 +245,19 @@ module SwarmSDK
|
|
218
245
|
@directory = dir
|
219
246
|
end
|
220
247
|
|
248
|
+
# Configure persistent memory for this agent
|
249
|
+
#
|
250
|
+
# @example
|
251
|
+
# memory do
|
252
|
+
# adapter :filesystem # default
|
253
|
+
# directory ".swarm/agent-memory"
|
254
|
+
# end
|
255
|
+
def memory(&block)
|
256
|
+
@memory_config = MemoryConfig.new
|
257
|
+
@memory_config.instance_eval(&block) if block_given?
|
258
|
+
@memory_config
|
259
|
+
end
|
260
|
+
|
221
261
|
# Set delegation targets
|
222
262
|
def delegates_to(*agent_names)
|
223
263
|
@delegates_to.concat(agent_names)
|
@@ -359,6 +399,7 @@ module SwarmSDK
|
|
359
399
|
agent_config[:assume_model_exists] = @assume_model_exists unless @assume_model_exists.nil?
|
360
400
|
agent_config[:permissions] = @permissions_config if @permissions_config.any?
|
361
401
|
agent_config[:default_permissions] = @default_permissions if @default_permissions.any?
|
402
|
+
agent_config[:memory] = @memory_config if @memory_config
|
362
403
|
|
363
404
|
# Convert DSL hooks to HookDefinition format
|
364
405
|
agent_config[:hooks] = convert_hooks_to_definitions if @hooks.any?
|
@@ -70,20 +70,37 @@ module SwarmSDK
|
|
70
70
|
def calculate_cost(message)
|
71
71
|
return zero_cost unless message.input_tokens && message.output_tokens
|
72
72
|
|
73
|
-
|
73
|
+
# Use SwarmSDK's model registry (not RubyLLM's) for up-to-date pricing
|
74
|
+
model_info = SwarmSDK::Models.find(message.model_id)
|
74
75
|
return zero_cost unless model_info
|
75
76
|
|
76
|
-
#
|
77
|
-
|
78
|
-
|
77
|
+
# Extract pricing from SwarmSDK's models.json structure
|
78
|
+
pricing = model_info["pricing"] || model_info[:pricing]
|
79
|
+
return zero_cost unless pricing
|
80
|
+
|
81
|
+
text_pricing = pricing["text_tokens"] || pricing[:text_tokens]
|
82
|
+
return zero_cost unless text_pricing
|
83
|
+
|
84
|
+
standard_pricing = text_pricing["standard"] || text_pricing[:standard]
|
85
|
+
return zero_cost unless standard_pricing
|
86
|
+
|
87
|
+
input_price = standard_pricing["input_per_million"] || standard_pricing[:input_per_million]
|
88
|
+
output_price = standard_pricing["output_per_million"] || standard_pricing[:output_per_million]
|
89
|
+
|
90
|
+
return zero_cost unless input_price && output_price
|
91
|
+
|
92
|
+
# Calculate costs (prices are per million tokens in USD)
|
93
|
+
input_cost = (message.input_tokens / 1_000_000.0) * input_price
|
94
|
+
output_cost = (message.output_tokens / 1_000_000.0) * output_price
|
79
95
|
|
80
96
|
{
|
81
97
|
input_cost: input_cost,
|
82
98
|
output_cost: output_cost,
|
83
99
|
total_cost: input_cost + output_cost,
|
84
100
|
}
|
85
|
-
rescue StandardError
|
101
|
+
rescue StandardError => e
|
86
102
|
# Model not found in registry or pricing not available
|
103
|
+
RubyLLM.logger.debug("Cost calculation failed for #{message.model_id}: #{e.message}")
|
87
104
|
zero_cost
|
88
105
|
end
|
89
106
|
|
@@ -43,7 +43,8 @@ module SwarmSDK
|
|
43
43
|
:default_permissions,
|
44
44
|
:agent_permissions,
|
45
45
|
:assume_model_exists,
|
46
|
-
:hooks
|
46
|
+
:hooks,
|
47
|
+
:memory
|
47
48
|
|
48
49
|
attr_accessor :bypass_permissions, :max_concurrent_tools
|
49
50
|
|
@@ -91,7 +92,11 @@ module SwarmSDK
|
|
91
92
|
# Parse directory first so it can be used in system prompt rendering
|
92
93
|
@directory = parse_directory(config[:directory])
|
93
94
|
|
94
|
-
#
|
95
|
+
# Parse memory configuration BEFORE building system prompt
|
96
|
+
# (memory prompt needs to be appended if memory is enabled)
|
97
|
+
@memory = parse_memory_config(config[:memory])
|
98
|
+
|
99
|
+
# Build system prompt after directory and memory are set
|
95
100
|
@system_prompt = build_full_system_prompt(config[:system_prompt])
|
96
101
|
|
97
102
|
# Parse tools with permissions support
|
@@ -116,6 +121,30 @@ module SwarmSDK
|
|
116
121
|
validate!
|
117
122
|
end
|
118
123
|
|
124
|
+
# Check if memory is enabled for this agent
|
125
|
+
#
|
126
|
+
# @return [Boolean]
|
127
|
+
def memory_enabled?
|
128
|
+
@memory&.respond_to?(:enabled?) && @memory.enabled?
|
129
|
+
end
|
130
|
+
|
131
|
+
# Parse memory configuration from Hash or MemoryConfig object
|
132
|
+
#
|
133
|
+
# @param memory_config [Hash, Agent::MemoryConfig, nil] Memory configuration
|
134
|
+
# @return [Agent::MemoryConfig, nil]
|
135
|
+
def parse_memory_config(memory_config)
|
136
|
+
return if memory_config.nil?
|
137
|
+
return memory_config if memory_config.is_a?(Agent::MemoryConfig)
|
138
|
+
|
139
|
+
# Convert hash (from YAML) to MemoryConfig object
|
140
|
+
config = Agent::MemoryConfig.new
|
141
|
+
adapter_value = memory_config[:adapter] || memory_config["adapter"] || :filesystem
|
142
|
+
config.adapter(adapter_value.to_sym)
|
143
|
+
directory_value = memory_config[:directory] || memory_config["directory"]
|
144
|
+
config.directory(directory_value) if directory_value
|
145
|
+
config
|
146
|
+
end
|
147
|
+
|
119
148
|
def to_h
|
120
149
|
{
|
121
150
|
name: @name,
|
@@ -216,9 +245,8 @@ module SwarmSDK
|
|
216
245
|
end
|
217
246
|
|
218
247
|
def build_full_system_prompt(custom_prompt)
|
219
|
-
#
|
220
|
-
|
221
|
-
if @coding_agent
|
248
|
+
# Build the base prompt based on coding_agent setting
|
249
|
+
prompt = if @coding_agent
|
222
250
|
# Coding agent: include full base prompt
|
223
251
|
rendered_base = render_base_system_prompt
|
224
252
|
|
@@ -238,11 +266,22 @@ module SwarmSDK
|
|
238
266
|
# No custom prompt: just return TODO/Scratchpad info
|
239
267
|
non_coding_base
|
240
268
|
end
|
241
|
-
# Default tools available: include TODO/Scratchpad instructions
|
242
269
|
else
|
243
270
|
# No default tools: return only custom prompt
|
244
271
|
(custom_prompt || "").to_s
|
245
272
|
end
|
273
|
+
|
274
|
+
# Append memory instructions if memory is enabled
|
275
|
+
if memory_enabled?
|
276
|
+
memory_prompt = render_memory_prompt
|
277
|
+
prompt = if prompt && !prompt.strip.empty?
|
278
|
+
"#{prompt}\n\n#{memory_prompt}"
|
279
|
+
else
|
280
|
+
memory_prompt
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
prompt
|
246
285
|
end
|
247
286
|
|
248
287
|
# Check if default tools are enabled (i.e., not disabled)
|
@@ -266,6 +305,13 @@ module SwarmSDK
|
|
266
305
|
ERB.new(template_content).result(binding)
|
267
306
|
end
|
268
307
|
|
308
|
+
def render_memory_prompt
|
309
|
+
# Load and render the memory system prompt
|
310
|
+
memory_prompt_path = File.expand_path("../prompts/memory.md.erb", __dir__)
|
311
|
+
template_content = File.read(memory_prompt_path)
|
312
|
+
ERB.new(template_content).result(binding)
|
313
|
+
end
|
314
|
+
|
269
315
|
def render_non_coding_base_prompt
|
270
316
|
# Simplified base prompt for non-coding agents
|
271
317
|
# Includes environment info, TODO, and Scratchpad tool information
|
@@ -4,7 +4,7 @@ module SwarmSDK
|
|
4
4
|
class Configuration
|
5
5
|
ENV_VAR_WITH_DEFAULT_PATTERN = /\$\{([^:}]+)(:=([^}]*))?\}/
|
6
6
|
|
7
|
-
attr_reader :config_path, :swarm_name, :lead_agent, :agents, :all_agents_config, :swarm_hooks, :all_agents_hooks
|
7
|
+
attr_reader :config_path, :swarm_name, :lead_agent, :agents, :all_agents_config, :swarm_hooks, :all_agents_hooks, :scratchpad_enabled
|
8
8
|
|
9
9
|
class << self
|
10
10
|
def load(path)
|
@@ -62,6 +62,7 @@ module SwarmSDK
|
|
62
62
|
name: @swarm_name,
|
63
63
|
global_concurrency: Swarm::DEFAULT_GLOBAL_CONCURRENCY,
|
64
64
|
default_local_concurrency: Swarm::DEFAULT_LOCAL_CONCURRENCY,
|
65
|
+
scratchpad_enabled: @scratchpad_enabled,
|
65
66
|
)
|
66
67
|
|
67
68
|
# Add all agents - pass definitions directly
|
@@ -146,6 +147,7 @@ module SwarmSDK
|
|
146
147
|
|
147
148
|
@swarm_name = swarm[:name]
|
148
149
|
@lead_agent = swarm[:lead].to_sym # Convert to symbol for consistency
|
150
|
+
@scratchpad_enabled = swarm[:use_scratchpad].nil? ? true : swarm[:use_scratchpad] # Default: enabled
|
149
151
|
end
|
150
152
|
|
151
153
|
def load_agents
|