Skip to content

Commit c1ecdad

Browse files
author
wisedev
committed
fix: improved local tool handling
1 parent f243f36 commit c1ecdad

File tree

2 files changed

+119
-14
lines changed

2 files changed

+119
-14
lines changed

src/MaIN.Core/.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>MaIN.NET</id>
5-
<version>0.9.1</version>
5+
<version>0.9.2</version>
66
<authors>Wisedev</authors>
77
<owners>Wisedev</owners>
88
<icon>favicon.png</icon>

src/MaIN.Services/Services/LLMService/Utils/ToolCallsHelper.cs

Lines changed: 118 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Text.Json;
22
using System.Text.Json.Serialization;
3+
using System.Text.RegularExpressions;
34
using MaIN.Domain.Entities.Tools;
45

56
namespace MaIN.Services.Services.LLMService.Utils;
@@ -36,26 +37,130 @@ public static ToolParseResult ParseToolCalls(string response)
3637
}
3738
}
3839

39-
private static string? ExtractJsonContent(string text)
40+
private static string? ExtractJsonContent(string text)
41+
{
42+
if (string.IsNullOrWhiteSpace(text))
43+
return null;
44+
45+
text = text.Trim();
46+
47+
var jsonFromCodeBlock = ExtractFromCodeBlock(text);
48+
if (jsonFromCodeBlock != null)
49+
return jsonFromCodeBlock;
50+
51+
return FindBalancedJson(text);
52+
}
53+
54+
private static string? ExtractFromCodeBlock(string text)
55+
{
56+
var patterns = new[]
4057
{
41-
text = text.Trim();
58+
@"```json\s*([\s\S]*?)\s*```",
59+
@"```\s*([\s\S]*?)\s*```"
60+
};
4261

43-
var firstBrace = text.IndexOf('{');
44-
var firstBracket = text.IndexOf('[');
45-
var startIndex = (firstBrace >= 0 && firstBracket >= 0)
46-
? Math.Min(firstBrace, firstBracket)
47-
: Math.Max(firstBrace, firstBracket);
62+
foreach (var pattern in patterns)
63+
{
64+
var match = Regex.Match(text, pattern);
65+
if (match.Success)
66+
{
67+
var content = match.Groups[1].Value.Trim();
68+
69+
content = Regex.Replace(content, @"^<[^>]+>\s*", "");
70+
content = Regex.Replace(content, @"\s*<[^>]+>$", "");
71+
content = content.Trim();
72+
73+
if (content.StartsWith("{") || content.StartsWith("["))
74+
{
75+
var balanced = FindBalancedJson(content);
76+
if (balanced != null)
77+
return balanced;
78+
}
79+
}
80+
}
4881

49-
var lastBrace = text.LastIndexOf('}');
50-
var lastBracket = text.LastIndexOf(']');
51-
var endIndex = Math.Max(lastBrace, lastBracket);
82+
return null;
83+
}
5284

53-
if (startIndex >= 0 && endIndex > startIndex)
54-
return text.Substring(startIndex, endIndex - startIndex + 1);
85+
private static string? FindBalancedJson(string text)
86+
{
87+
// Try to find a balanced JSON object or array
88+
for (int i = 0; i < text.Length; i++)
89+
{
90+
if (text[i] == '{')
91+
{
92+
var json = ExtractBalanced(text, i, '{', '}');
93+
if (json != null && IsValidJsonStart(json))
94+
return json;
95+
}
96+
else if (text[i] == '[')
97+
{
98+
var json = ExtractBalanced(text, i, '[', ']');
99+
if (json != null && IsValidJsonStart(json))
100+
return json;
101+
}
102+
}
55103

56-
return null;
104+
return null;
105+
}
106+
107+
private static string? ExtractBalanced(string text, int startIndex, char openChar, char closeChar)
108+
{
109+
int depth = 0;
110+
bool inString = false;
111+
bool escaped = false;
112+
113+
for (int i = startIndex; i < text.Length; i++)
114+
{
115+
char c = text[i];
116+
117+
if (escaped)
118+
{
119+
escaped = false;
120+
continue;
121+
}
122+
123+
if (c == '\\')
124+
{
125+
escaped = true;
126+
continue;
127+
}
128+
129+
if (c == '"' && !inString)
130+
{
131+
inString = true;
132+
}
133+
else if (c == '"' && inString)
134+
{
135+
inString = false;
136+
}
137+
else if (!inString)
138+
{
139+
if (c == openChar)
140+
{
141+
depth++;
142+
}
143+
else if (c == closeChar)
144+
{
145+
depth--;
146+
if (depth == 0)
147+
{
148+
return text.Substring(startIndex, i - startIndex + 1);
149+
}
150+
}
151+
}
57152
}
58153

154+
return null;
155+
}
156+
157+
private static bool IsValidJsonStart(string json)
158+
{
159+
json = json.Trim();
160+
return (json.StartsWith("{") && json.EndsWith("}")) ||
161+
(json.StartsWith("[") && json.EndsWith("]"));
162+
}
163+
59164
private static List<ToolCall> NormalizeToolCalls(List<ToolCall>? calls)
60165
{
61166
if (calls is null)

0 commit comments

Comments
 (0)