smart_agent 0.2.8 → 0.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/smart_agent/agent.rb +56 -33
- data/lib/smart_agent/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dffe825327912ea1a49ffba0cc2630a7e0078edbd9e2ac14b587b983c54ff7cd
|
|
4
|
+
data.tar.gz: e8efe4bb5e25e2f5b933b6c74dce6aa05249f5ef09967ee4e4d86abdd94611f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f6f921ece654b0352aef2dc0a215231d17a367dc4129969a5ec58b22e98d4d06f0ed6c72392b2a1d9f9d103989db119647e6e154d7e8f6d79deea61e7cd22c48
|
|
7
|
+
data.tar.gz: 9efad024502c4024b1f866a63b768b73d2529910de4f2cbb5c69e0a45b11ed5be7624c0abb08942fbdb28afabfdc8249626a690126808862b3d0d72427da690f
|
data/lib/smart_agent/agent.rb
CHANGED
|
@@ -72,6 +72,8 @@ module SmartAgent
|
|
|
72
72
|
def call_worker(name, params, with_tools: true, with_history: false)
|
|
73
73
|
SmartAgent.logger.info("Call Worker name is: #{name}")
|
|
74
74
|
SmartAgent.logger.info("Call Worker params is: #{params}")
|
|
75
|
+
# 记录 session_id,call_tools 写工具结果时需要按 session 路由(HistoryManager 启用时)
|
|
76
|
+
@session_id = params[:session_id]
|
|
75
77
|
if with_tools
|
|
76
78
|
simple_tools = []
|
|
77
79
|
if @agent.tools
|
|
@@ -107,46 +109,47 @@ module SmartAgent
|
|
|
107
109
|
end
|
|
108
110
|
|
|
109
111
|
def safe_parse(input)
|
|
110
|
-
|
|
111
|
-
original_input = input.dup
|
|
112
|
+
return input unless input.is_a?(String)
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if cleaned.start_with?('"') && cleaned.end_with?('"')
|
|
118
|
-
cleaned = cleaned[1...-1]
|
|
114
|
+
begin
|
|
115
|
+
return JSON.parse(input)
|
|
116
|
+
rescue JSON::ParserError
|
|
117
|
+
nil
|
|
119
118
|
end
|
|
120
119
|
|
|
121
|
-
|
|
122
|
-
#
|
|
123
|
-
cleaned = cleaned
|
|
124
|
-
.gsub(/\\"/, '"') # 反转义引号
|
|
125
|
-
.gsub(/\\\\/, '\\') # 反转义反斜杠
|
|
126
|
-
# 不反转义\n, \t, \r等,因为它们是JSON合法的转义序列
|
|
127
|
-
|
|
128
|
-
# 步骤4: 尝试解析
|
|
129
|
-
begin
|
|
130
|
-
return JSON.parse(cleaned)
|
|
131
|
-
rescue JSON::ParserError => e
|
|
132
|
-
# 如果清理后失败,尝试原始输入
|
|
120
|
+
stripped = input.strip
|
|
121
|
+
if stripped.start_with?('"') && stripped.end_with?('"') # 双重编码: "{\"command\":\"ls\"}"
|
|
133
122
|
begin
|
|
134
|
-
|
|
123
|
+
inner = JSON.parse(stripped)
|
|
124
|
+
return JSON.parse(inner) if inner.is_a?(String)
|
|
135
125
|
rescue JSON::ParserError
|
|
136
|
-
|
|
137
|
-
puts "Original: #{original_input}"
|
|
138
|
-
puts "Cleaned: #{cleaned}"
|
|
139
|
-
# 返回原始字符串以便后续处理
|
|
140
|
-
return original_input
|
|
126
|
+
nil
|
|
141
127
|
end
|
|
142
128
|
end
|
|
143
|
-
end
|
|
144
129
|
|
|
145
|
-
|
|
130
|
+
begin
|
|
131
|
+
JSON.parse(stripped.gsub(/\\"/, '"')) # 只做引号级清理,不碰反斜杠
|
|
132
|
+
rescue JSON::ParserError => e
|
|
133
|
+
SmartAgent.logger&.warn("safe_parse failed: #{e.class}: #{e.message} input=#{input[0, 200].inspect}")
|
|
134
|
+
input
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def call_tools(result, calls: nil)
|
|
146
139
|
@agent.processor(:tool).call({ :status => :start }) if @agent.processor(:tool)
|
|
147
140
|
SmartAgent.logger.info("call tools: " + result.to_s)
|
|
148
141
|
results = []
|
|
149
|
-
|
|
142
|
+
completed_calls = []
|
|
143
|
+
completed_messages = []
|
|
144
|
+
# DeepSeek thinking 模式要求带 tool_calls 的 assistant 消息回传 reasoning_content,否则 400
|
|
145
|
+
reasoning = begin
|
|
146
|
+
result.response.dig("choices", 0, "message", "reasoning_content")
|
|
147
|
+
rescue StandardError
|
|
148
|
+
nil
|
|
149
|
+
end
|
|
150
|
+
# 调用方可传入 calls: 覆盖本次要执行的工具调用集合(如截断 / DSML 兑底解析后的结果)
|
|
151
|
+
source = calls || result.call_tools
|
|
152
|
+
(source || []).each do |tool|
|
|
150
153
|
tool_call_id = tool["id"]
|
|
151
154
|
tool_name = tool["function"]["name"].to_sym
|
|
152
155
|
params = safe_parse(tool["function"]["arguments"])
|
|
@@ -154,8 +157,8 @@ module SmartAgent
|
|
|
154
157
|
tool_result = Tool.find_tool(tool_name).call(params, @agent)
|
|
155
158
|
if tool_result
|
|
156
159
|
@agent.processor(:tool).call({ :content => tool_result }) if @agent.processor(:tool)
|
|
157
|
-
|
|
158
|
-
|
|
160
|
+
completed_calls << tool
|
|
161
|
+
completed_messages << { "role" => "tool", "tool_call_id" => tool_call_id, "content" => tool_result.to_s.force_encoding("UTF-8") }
|
|
159
162
|
results << tool_result
|
|
160
163
|
end
|
|
161
164
|
end
|
|
@@ -163,8 +166,8 @@ module SmartAgent
|
|
|
163
166
|
tool_result = MCPClient.new(server_name).call(tool_name, params, @agent)
|
|
164
167
|
if tool_result
|
|
165
168
|
@agent.processor(:tool).call({ :content => tool_result }) if @agent.processor(:tool)
|
|
166
|
-
|
|
167
|
-
|
|
169
|
+
completed_calls << tool
|
|
170
|
+
completed_messages << { "role" => "tool", "tool_call_id" => tool_call_id, "content" => tool_result.to_s }
|
|
168
171
|
results << tool_result
|
|
169
172
|
end
|
|
170
173
|
end
|
|
@@ -172,6 +175,26 @@ module SmartAgent
|
|
|
172
175
|
end
|
|
173
176
|
@agent.processor(:tool).call({ :status => :end }) if @agent.processor(:tool)
|
|
174
177
|
return results
|
|
178
|
+
ensure
|
|
179
|
+
# 每轮写一条 assistant 消息(含全部 tool_calls),而不是每个工具各写一条,
|
|
180
|
+
# 避免交错产生 assistant/tool/assistant/tool 序列;被中断时也保留已完成部分。
|
|
181
|
+
if completed_calls && completed_calls.any?
|
|
182
|
+
message = { "role" => "assistant", "content" => "", "tool_calls" => completed_calls }
|
|
183
|
+
message["reasoning_content"] = reasoning if reasoning
|
|
184
|
+
append_history_message(message)
|
|
185
|
+
completed_messages.each { |m| append_history_message(m) }
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# 写历史:HistoryManager 可用时按 session 路由(否则工具结果写全局、读 session 会失忆),
|
|
190
|
+
# 不可用时回退到全局数组(与旧行为一致)。
|
|
191
|
+
def append_history_message(message)
|
|
192
|
+
engine = SmartAgent.prompt_engine
|
|
193
|
+
if engine.respond_to?(:history_manager) && engine.history_manager && @session_id
|
|
194
|
+
engine.history_manager.add_message(@session_id, message)
|
|
195
|
+
elsif engine.respond_to?(:history_messages)
|
|
196
|
+
engine.history_messages << message
|
|
197
|
+
end
|
|
175
198
|
end
|
|
176
199
|
|
|
177
200
|
def call_tool(name, params = {})
|
data/lib/smart_agent/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: smart_agent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Zhuang Biaowei
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.5.
|
|
18
|
+
version: 0.5.4
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.5.
|
|
25
|
+
version: 0.5.4
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: mcp-sdk.rb
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -85,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
85
85
|
- !ruby/object:Gem::Version
|
|
86
86
|
version: '0'
|
|
87
87
|
requirements: []
|
|
88
|
-
rubygems_version: 4.0.
|
|
88
|
+
rubygems_version: 4.0.16
|
|
89
89
|
specification_version: 4
|
|
90
90
|
summary: Intelligent agent framework with DSL and MCP integration
|
|
91
91
|
test_files: []
|