-
Notifications
You must be signed in to change notification settings - Fork 2
fix(core): resolve macOS issues in 1.4.0-alpha — deadlock, GhJSON validation, and JSON parsing #389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5cdbd0d
1a3ad3e
d55cda8
79ea04f
340fad3
8ad7faa
4984059
2568df6
aaabcda
cceab6b
7bf51ac
8fd16ad
2972d65
d2836c1
528c466
890b75b
a962b46
3d92b26
86acc9e
fed5a0b
ec32b57
9c4946b
80664eb
0399995
489954a
0582c82
31eefee
a39164e
ba28c4b
0ab3b1f
ce4a709
983196a
95afb73
c1a7538
8a78268
6c020e7
bc92c0d
8873c4d
4816104
be109dd
4d7a5eb
3af50f0
524068d
7d5a37d
c5212d3
48c2123
4b0f84c
269ad65
957ac2b
7779ddc
4f1c8ec
88ef34a
a6983c8
69b063f
2309fcb
3b900ee
3fc0e45
68afba9
a725248
2e69892
142203a
3e1ed60
8018997
4860607
eef55b2
a688972
5d05553
7fe175c
2f69992
2dc0564
4d9030d
5d8e25e
48f0c1d
2cb2188
4e45e8a
43311ac
a26d2ce
7934cff
39f48e3
9e217bd
3dffd0d
f31852c
180b11c
a4e053c
eadd85b
38a7af1
dcfada0
84bcda0
529e5ed
e039256
f84b7b8
4f721e5
e8897fe
89f2de4
35b5892
be4fcb8
b6fa354
43813c5
3c7d2ca
3cba90f
1846cc9
9407bbb
6048739
9056a55
d30a644
065a591
810d244
38ad0af
d229c66
936d393
0bea19b
b34bac8
6373dc3
83c3c2f
8b15661
e9e8224
febc4ac
ca87d14
2147923
1db4e7e
7ebf280
389aa1d
5ace30d
45609b2
cbeca74
d00bf17
8457aa6
0daef17
fb4c480
e027ea6
3c6ef0f
0cdab30
38edc7b
86b5d79
763b747
a42ee7c
d125055
42fa3ed
93bb67c
044ff19
787b565
564b22f
ee61671
dbac91a
74a6d83
3d67abc
6ec8197
4aa46fc
f306202
de68a72
04fae97
d4bdbfc
e6230db
cfa49ad
d259d02
411bdee
655f16c
384da92
42c992a
35ff95a
cf6b34f
a48ebfe
b1827db
97559b2
4addeb9
8cc8487
a11c12e
3a95074
ad3e54b
7dc06f2
7626b93
daad047
70ef054
5070e13
49f2463
36f88da
6136b96
c1f28de
10b855c
1fb025c
801eb35
35db35c
dea2e1f
5cc7687
11ba027
bc552e9
e2afdb7
cf281b6
7231305
a575798
656d822
4b698d3
9da03f9
359269a
01297c3
0e31f1e
808d652
7684e6b
7554094
f906100
98b1856
07987ef
31424dd
b4b4e38
f38b4a6
6286d23
1059100
b0b7c62
4c07f7a
9998648
f1ade57
c0d7ea3
c237d3b
f1e7534
683a11e
ea19eb8
afa9d1f
c0a5881
29b6649
2713ae2
9ad71ca
25c0bfb
c566478
a118924
046810c
b4d8a5d
dce8d56
8c9c0e1
86c5fa3
5442155
ee40b0f
f992350
8d634f7
5368d81
cd5f5a3
792de92
a4767e2
db23b0b
e5854ab
757b69d
94dea8e
2009ae1
226b201
93c2a4c
6a2c7a2
fb03c0d
abbc785
2e3ad18
c908008
6680525
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,7 @@ | |
| using Newtonsoft.Json; | ||
| using Newtonsoft.Json.Linq; | ||
| using SmartHopper.Core.Grasshopper.Utils.Constants; | ||
| using SmartHopper.Core.Grasshopper.Utils.Parsing; | ||
| using SmartHopper.Infrastructure.AICall.Core.Base; | ||
| using SmartHopper.Infrastructure.AICall.Core.Interactions; | ||
| using SmartHopper.Infrastructure.AICall.Core.Requests; | ||
|
|
@@ -215,7 +216,7 @@ private async Task<AIReturn> ExecuteAsync(AIToolCall toolCall) | |
|
|
||
| // Parse AI response and validate with retry loop | ||
| var response = result.Body.GetLastInteraction(AIAgent.Assistant).ToString(); | ||
| var responseJson = JObject.Parse(response); | ||
| var responseJson = SanitizeAndParseJson(response); | ||
|
|
||
| var language = responseJson["language"]?.ToString() ?? "python"; | ||
| var scriptCode = responseJson["script"]?.ToString() ?? string.Empty; | ||
|
|
@@ -266,7 +267,7 @@ private async Task<AIReturn> ExecuteAsync(AIToolCall toolCall) | |
|
|
||
| // Parse corrected response | ||
| response = correctionResult.Body.GetLastInteraction(AIAgent.Assistant).ToString(); | ||
| responseJson = JObject.Parse(response); | ||
| responseJson = SanitizeAndParseJson(response); | ||
|
|
||
| scriptCode = responseJson["script"]?.ToString() ?? string.Empty; | ||
| inputs = responseJson["inputs"] as JArray ?? new JArray(); | ||
|
|
@@ -364,6 +365,15 @@ private static string GetExtensionKey(string languageKey) | |
| }; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Sanitizes and parses an AI response as a JSON object. | ||
| /// Delegates to <see cref="AIResponseParser.SanitizeAndParseJson"/>. | ||
| /// </summary> | ||
| private static JObject SanitizeAndParseJson(string response) | ||
| { | ||
| return AIResponseParser.SanitizeAndParseJson(response); | ||
| } | ||
|
|
||
| private static string CreateComponentName(string languageKey) | ||
| { | ||
| return languageKey?.Trim().ToLowerInvariant() switch | ||
|
|
@@ -393,6 +403,7 @@ private static string CreateScriptGhJson( | |
| Name = CreateComponentName(languageKey), | ||
| NickName = nickname, | ||
| InstanceGuid = instanceGuid, | ||
| Id = instanceGuid.HasValue ? null : 1, | ||
|
||
| Pivot = pivot, | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -353,31 +353,48 @@ private void ProcessTransitionQueue() | |
| // Collect all transition results inside the lock in one pass | ||
| var pendingEvents = new List<(ComponentState oldState, ComponentState newState, bool isRejection, string rejectionMessage)>(); | ||
|
|
||
| while (this.pendingTransitions.Count > 0) | ||
| try | ||
| { | ||
| var request = this.pendingTransitions.Dequeue(); | ||
| var result = this.ExecuteTransitionCore(request); | ||
| if (result.HasValue) | ||
| while (this.pendingTransitions.Count > 0) | ||
| { | ||
| pendingEvents.Add(result.Value); | ||
| var request = this.pendingTransitions.Dequeue(); | ||
| var result = this.ExecuteTransitionCore(request); | ||
| if (result.HasValue) | ||
| { | ||
| pendingEvents.Add(result.Value); | ||
| } | ||
| } | ||
| } | ||
| finally | ||
| { | ||
| // Clear transitioning flag BEFORE releasing lock to prevent race conditions | ||
| this.isTransitioning = false; | ||
| } | ||
|
|
||
| // Clear transitioning flag BEFORE releasing lock to prevent race conditions | ||
| this.isTransitioning = false; | ||
|
|
||
| // Fire all events outside the lock | ||
| // Event handlers may call RequestTransition(), which will queue new transitions | ||
| // for the next ProcessTransitionQueue() call | ||
| foreach (var evt in pendingEvents) | ||
| // Fire all events TRULY outside the lock by temporarily releasing stateLock. | ||
| // This method is called from within lock(stateLock) in RequestTransition(), | ||
| // so we must explicitly exit/re-enter the monitor to prevent re-entrant | ||
| // deadlocks when event handlers call back into RequestTransition(). | ||
| if (pendingEvents.Count > 0) | ||
| { | ||
| if (evt.isRejection) | ||
| System.Threading.Monitor.Exit(this.stateLock); | ||
| try | ||
| { | ||
| this.TransitionRejected?.Invoke(evt.oldState, evt.newState, evt.rejectionMessage); | ||
| foreach (var evt in pendingEvents) | ||
| { | ||
| if (evt.isRejection) | ||
| { | ||
| this.TransitionRejected?.Invoke(evt.oldState, evt.newState, evt.rejectionMessage); | ||
| } | ||
| else | ||
| { | ||
| this.FireTransitionEvents(evt.oldState, evt.newState); | ||
| } | ||
| } | ||
| } | ||
| else | ||
| finally | ||
| { | ||
| this.FireTransitionEvents(evt.oldState, evt.newState); | ||
| System.Threading.Monitor.Enter(this.stateLock); | ||
| } | ||
|
Comment on lines
+380
to
398
|
||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.