Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1937 commits
Select commit Hold shift + click to select a range
5cdbd0d
chore: prepare release 1.1.0-alpha with version update and code style…
actions-user Nov 23, 2025
1a3ad3e
chore: prepare release 1.1.0-alpha with version update and code style…
marc-romu Nov 23, 2025
d55cda8
release/1.1.0-alpha (#348)
marc-romu Nov 23, 2025
79ea04f
refactor(ci): simplify release workflow by removing intermediate envi…
marc-romu Nov 23, 2025
340fad3
main to dev update (#350)
marc-romu Nov 23, 2025
8ad7faa
chore(yak): update manifest with Rhino 8.24 requirement and expanded …
marc-romu Nov 23, 2025
4984059
chore: bump version to 1.2.0-dev.251124 and update README badges to r…
marc-romu Nov 24, 2025
2568df6
chore: bump version to 1.1.1-dev.251124 and update README badges to r…
marc-romu Nov 24, 2025
aaabcda
chore(providers-anthropic): add claude dated models and update default
marc-romu Nov 24, 2025
cceab6b
chore(providers-mistralai): remove duplicate mistral-small model entry
marc-romu Nov 24, 2025
7bf51ac
chore(providers-openai): add GPT-5.1 series models and adjust rankings
marc-romu Nov 24, 2025
8fd16ad
chore(providers-anthropic): add structured-outputs beta support and r…
marc-romu Nov 24, 2025
2972d65
chore(providers-anthropic): add missing AIModels namespace import
marc-romu Nov 24, 2025
d2836c1
chore(providers-anthropic): simplify json_schema output_format struct…
marc-romu Nov 24, 2025
528c466
fix(providers): refresh Anthropic/OpenAI model registries and default…
marc-romu Nov 24, 2025
890b75b
chore: prepare release 1.1.1-alpha with version update and code style…
actions-user Nov 24, 2025
a962b46
chore: prepare release 1.1.1-alpha with version update and code style…
marc-romu Nov 24, 2025
3d92b26
release/1.1.1-alpha (#353)
marc-romu Nov 24, 2025
86acc9e
feat: expand keyword tags for better discoverability
marc-romu Nov 24, 2025
fed5a0b
Merge branch 'dev' of https://github.com/architects-toolkit/SmartHopp…
marc-romu Nov 24, 2025
ec32b57
chore(yak): refine package description and update project URL
marc-romu Nov 24, 2025
9c4946b
chore: bump development version to 1.2.0-dev.251129
marc-romu Nov 29, 2025
80664eb
feat(ai): enable Scripting tools
marc-romu Nov 29, 2025
0399995
feat(ui): combine Select button and AI provider badges in stateful co…
marc-romu Nov 29, 2025
489954a
feat(script-tools): split script generator into GhJSON tools and simp…
marc-romu Nov 29, 2025
0582c82
feat(ghjson): default ShowStandardOutput to true for script component…
marc-romu Nov 29, 2025
31eefee
refactor(script-tools): add summary output and improve error messagin…
marc-romu Nov 29, 2025
a39164e
feat(script-tools): add batch processing support to AI Script Generat…
marc-romu Nov 29, 2025
ba28c4b
feat(grasshopper): add component replacement mode to GhPutComponents
marc-romu Nov 29, 2025
0ab3b1f
feat(ui): add dialog-to-canvas visual linking system
marc-romu Nov 29, 2025
ce4a709
refactor(ui): cache selected object bounds during hover to prevent vi…
marc-romu Nov 29, 2025
983196a
feat(ui): add per-component replacement prompts and canvas centering …
marc-romu Nov 29, 2025
95afb73
feat(gh_put): add connection preservation during component replacemen…
marc-romu Nov 29, 2025
c1a7538
feat(ghjson): add GhJSON document merging with gh_merge tool and GhMe…
marc-romu Nov 29, 2025
8a78268
feat(anthropic): add claude-opus-4-5 model and rebalance model rankings
marc-romu Nov 29, 2025
6c020e7
fix(gh_put): prevent infinite loop and expired object errors during c…
marc-romu Nov 29, 2025
bc92c0d
feat(security): add assembly signature verification to AIToolManager.…
marc-romu Nov 29, 2025
8873c4d
feat(security): remove development mode bypasses from assembly signat…
marc-romu Nov 29, 2025
4816104
feat(signing): expand authenticode signing to all SmartHopper assemblies
marc-romu Nov 29, 2025
be109dd
feat(security): add assembly signature verification to AIToolManager.…
marc-romu Nov 29, 2025
4d7a5eb
revert tool manager security
marc-romu Nov 29, 2025
3af50f0
Merge branch 'feature/1.2.0-script-tools' of https://github.com/archi…
marc-romu Nov 29, 2025
524068d
revert tool manager
marc-romu Nov 29, 2025
7d5a37d
refactor(gh_put): convert GhPutComponents to async StatefulAsyncCompo…
marc-romu Nov 29, 2025
c5212d3
fix(script_generate): add nickname to required fields in tool schema
marc-romu Nov 29, 2025
48c2123
feat(components): skip metrics validation for local tool calls
marc-romu Nov 29, 2025
4b0f84c
feat(ui): add connector lines from selection center to Select button …
marc-romu Nov 29, 2025
269ad65
refactor(ui): extract selection rendering logic to SelectingComponent…
marc-romu Nov 29, 2025
957ac2b
refactor(components): add automatic pruning of deleted objects from s…
marc-romu Nov 30, 2025
7779ddc
feat(resources): add ghmerge icon and update ghget/ghput icons
marc-romu Nov 30, 2025
4f1c8ec
refactor(gh_merge): add missing Resources import for icon property
marc-romu Nov 30, 2025
88ef34a
feat(resources): mcneelpost and script component icons by outlined ones
marc-romu Nov 30, 2025
a6983c8
feat(script_edit): add nickname to required fields in tool schema to …
marc-romu Nov 30, 2025
69b063f
feat(openrouter): add structured output support and populate finish_r…
marc-romu Nov 30, 2025
2309fcb
feat(gh_get): add category filter parameter to filter components by G…
marc-romu Nov 30, 2025
3b900ee
refactor(script_edit): remove unused script_fix tool
marc-romu Nov 30, 2025
3fc0e45
feat(gh_get): extend category filtering from components to all docume…
marc-romu Nov 30, 2025
68afba9
refactor(script_parameter_modifier): change tool category from "Scrip…
marc-romu Nov 30, 2025
a725248
refactor(canvas_button): strengthen scripting tool usage instructions…
marc-romu Nov 30, 2025
2e69892
feat(metrics): aggregate turn metrics in chat UI and fix tool result …
marc-romu Nov 30, 2025
142203a
feat(script_edit): add script_edit_and_replace_on_canvas wrapper tool…
marc-romu Nov 30, 2025
3e1ed60
feat(script_tools): add comprehensive parameter modifier support to s…
marc-romu Dec 3, 2025
8018997
feat(web_chat): make WebChatDialog an owned tool window that follows …
marc-romu Dec 3, 2025
4860607
refactor(script_tools): change script_edit_and_replace_on_canvas to u…
marc-romu Dec 3, 2025
eef55b2
refactor(canvas_button): add scripting workflow guidelines to avoid u…
marc-romu Dec 3, 2025
a688972
chore(version): bump version to 1.2.0-dev.251203
marc-romu Dec 3, 2025
5d05553
refactor(changelog): consolidate v1.2.0 release notes
marc-romu Dec 3, 2025
7fe175c
chore(issue_template): update SmartHopper version placeholder to 1.2.…
marc-romu Dec 3, 2025
2f69992
refactor(infrastructure): remove trailing whitespace from XML comment
marc-romu Dec 3, 2025
2dc0564
refactor: simplify code with LINQ expressions and improve code quality
marc-romu Dec 3, 2025
4d9030d
feat(script-tools): add GhJSON-based script tools, merge workflows, a…
marc-romu Dec 3, 2025
5d8e25e
feat(script_tools): add script code validation with automatic self-co…
marc-romu Dec 5, 2025
48f0c1d
feat(script_tools): add language-specific guidance to script_review a…
marc-romu Dec 6, 2025
2cb2188
feat(model_compatibility): add "Not Recommended" badge for models dis…
marc-romu Dec 6, 2025
4e45e8a
feat(model_compatibility): mark deprecated models and add script tool…
marc-romu Dec 6, 2025
43311ac
refactor(mistral_provider): reorder capability flags for consistency …
marc-romu Dec 6, 2025
a26d2ce
refactor(script_tools): add validation for non-Python shebang directi…
marc-romu Dec 6, 2025
7934cff
docs(DEV.md): update component and AI tool naming, add code formattin…
marc-romu Dec 6, 2025
39f48e3
refactor(openrouter): make openai/gpt-5-mini default for Text2Json
marc-romu Dec 6, 2025
9e217bd
docs(CONTRIBUTING.md): add Update-InternalsVisibleTo.ps1 step to loca…
marc-romu Dec 6, 2025
3dffd0d
docs: expand architecture and model capabilities documentation with b…
marc-romu Dec 6, 2025
f31852c
Merge branch 'feat/1.2.0-scripting-improvments' of https://github.com…
marc-romu Dec 6, 2025
180b11c
refactor(build): move signing scripts to tools/ directory and add uni…
marc-romu Dec 6, 2025
a4e053c
style: remove trailing whitespace across test and core files
marc-romu Dec 6, 2025
eadd85b
refactor(signing): default to solution root for signing.snk and signi…
marc-romu Dec 6, 2025
38a7af1
ci(release): replace SmartHopperPublicKey with placeholder in release…
marc-romu Dec 6, 2025
dcfada0
docs(README.md): update version badge to 1.2.0-dev.251206, reorder fe…
marc-romu Dec 6, 2025
84bcda0
chore: remove Using Directives Check from PR validation workflow, doc…
marc-romu Dec 6, 2025
529e5ed
refactor(signing): convert password parameters to SecureString and ad…
marc-romu Dec 6, 2025
e039256
feat(scripting): enhance script tools, model compatibility, and docs …
marc-romu Dec 6, 2025
f84b7b8
docs
marc-romu Dec 6, 2025
4f721e5
chore: prepare release 1.2.0-alpha with version update and code style…
actions-user Dec 6, 2025
e8897fe
chore: prepare release 1.2.0-alpha with version update and code style…
marc-romu Dec 6, 2025
89f2de4
chore: windsurf workflows
marc-romu Dec 6, 2025
35b5892
release/1.2.0-alpha (#357)
marc-romu Dec 6, 2025
be4fcb8
chore(yak): remove unaccepted 'c#' keyword
marc-romu Dec 6, 2025
b6fa354
chore: update version to 1.2.1-dev.251207 and enhance script generati…
marc-romu Dec 7, 2025
43813c5
fix(dialogs): center StyledMessageDialog on screen containing owner w…
marc-romu Dec 7, 2025
3c7d2ca
feat(tools): add runtime data extraction to gh_get tools and fix scri…
marc-romu Dec 7, 2025
3cba90f
fix(chat): ensure unique TurnIds for user messages and preserve TurnI…
marc-romu Dec 7, 2025
1846cc9
feat(tools): add runtime data getters and script canvas placement wra…
marc-romu Dec 7, 2025
9407bbb
chore: prepare release 1.2.1-alpha with version update and code style…
actions-user Dec 7, 2025
6048739
chore: prepare release 1.2.1-alpha with version update and code style…
marc-romu Dec 7, 2025
9056a55
release/1.2.1-alpha (#361)
marc-romu Dec 7, 2025
d30a644
Fix: reduce WebChat freezes during drag/resize
marc-romu Dec 22, 2025
065a591
chore: update SmartHopperPublicKey with dev public key value
marc-romu Dec 22, 2025
810d244
chore: update bug report template placeholders to reflect current ver…
marc-romu Dec 22, 2025
38ad0af
Fix: prevent WebChat UI freezes during streaming
marc-romu Dec 22, 2025
d229c66
perf(chat): optimize DOM updates with keyed queue and conditional deb…
marc-romu Dec 23, 2025
936d393
perf(chat): optimize message rendering with template caching, LRU dif…
marc-romu Dec 23, 2025
0bea19b
perf(chat): remove unused stream animation code and fix body filter p…
marc-romu Dec 23, 2025
b34bac8
feat(chat): add instruction_get tool to reduce system prompt size and…
marc-romu Dec 23, 2025
6373dc3
fix(tools): improve instruction_get reliability and add required para…
marc-romu Dec 23, 2025
83c3c2f
refactor(chat): extract shared streaming logic and optimize provider …
marc-romu Dec 24, 2025
8b15661
docs(changelog)
marc-romu Dec 24, 2025
e9e8224
refactor(chat): improve error logging and code formatting in WebChat …
marc-romu Dec 24, 2025
febc4ac
perf(chat): improve WebChat stability and streaming performance (#362)
marc-romu Dec 24, 2025
ca87d14
docs: fix version badge
marc-romu Dec 24, 2025
2147923
Merge branch 'dev' of https://github.com/architects-toolkit/SmartHopp…
marc-romu Dec 24, 2025
1db4e7e
perf(component-base): refactored component base for stability
marc-romu Dec 24, 2025
7ebf280
perf(providers): add reasoning support for tool calls across all prov…
marc-romu Dec 24, 2025
389aa1d
feat(component-base): new state manager to improve component state st…
marc-romu Dec 25, 2025
5ace30d
refactor(components): remove "Done :)" messages and prevent clearing …
marc-romu Dec 25, 2025
45609b2
refactor(component-base): add post-solve guard to prevent premature o…
marc-romu Dec 25, 2025
cbeca74
feat(ghjson): add panel color and bounds serialization support
marc-romu Dec 26, 2025
d00bf17
style: remove trailing blank lines and fix copyright inconsistencies
marc-romu Dec 26, 2025
8457aa6
fix(header-fixer): strip BOM when comparing and updating file headers
marc-romu Dec 26, 2025
0daef17
style(docs): remove trailing whitespace in GhJSON index
marc-romu Dec 26, 2025
fb4c480
fix(component-base): improve debounce timer cancellation checks to pr…
marc-romu Dec 27, 2025
e027ea6
refactor: simplify conditional expressions and improve code clarity
marc-romu Dec 27, 2025
3c6ef0f
fix(component-base): stabilize stateful component base with a new Sta…
marc-romu Dec 27, 2025
0cdab30
chore: update development version date to 1.2.2-dev.251227
actions-user Dec 27, 2025
38edc7b
chore: update development version date to 1.2.2-dev.251227 (#365)
marc-romu Dec 27, 2025
86b5d79
chore: prepare release 1.2.2-alpha with version update and code style…
actions-user Dec 27, 2025
763b747
chore: prepare release 1.2.2-alpha with version update and code style…
marc-romu Dec 27, 2025
a42ee7c
release/1.2.2-alpha (#367)
marc-romu Dec 27, 2025
d125055
docs: add DeepWiki badge to README
marc-romu Jan 3, 2026
42fa3ed
feat: new context limit management features in conversation session a…
marc-romu Jan 5, 2026
93bb67c
feat: change conversation summaries to use AIAgent.Summary role with …
marc-romu Jan 5, 2026
044ff19
feat: add Optimized serialization context to exclude persistent/volat…
marc-romu Jan 5, 2026
787b565
feat: new LastEffectiveTotalTokens field in AIMetrics to properly cal…
marc-romu Jan 10, 2026
564b22f
feat: add ContextLimit property to all AI model capabilities across p…
marc-romu Jan 10, 2026
ee61671
feat: add debug Update button to refresh chat view from conversation …
marc-romu Jan 10, 2026
dbac91a
chore: remove trailing whitespace in AIBody.cs
marc-romu Jan 10, 2026
74a6d83
chore: changelog update
marc-romu Jan 10, 2026
3d67abc
feat(chat): add context limit management and debug improvements (#368)
marc-romu Jan 10, 2026
6ec8197
docs: update version badge for dev
actions-user Jan 10, 2026
4aa46fc
docs: update version badge for dev to 1.2.3-dev.260110 (#369)
marc-romu Jan 10, 2026
f306202
chore: prepare release 1.2.3-alpha with version update and code style…
actions-user Jan 11, 2026
de68a72
chore: prepare release 1.2.3-alpha with version update and code style…
marc-romu Jan 11, 2026
04fae97
docs: reorder README badges and update DeconstructMetrics component GUID
marc-romu Jan 11, 2026
d4bdbfc
ci: allow release branch names as valid PR titles in validation workflow
marc-romu Jan 11, 2026
e6230db
release/1.2.3-alpha (#371)
marc-romu Jan 11, 2026
cfa49ad
fix: add missing context_usage_percent property to AIStatefulAsyncCom…
marc-romu Jan 11, 2026
d259d02
chore: prepare release 1.2.4-alpha with version update and code style…
actions-user Jan 11, 2026
411bdee
chore: prepare release 1.2.4-alpha with version update and code style…
marc-romu Jan 11, 2026
655f16c
release/1.2.4-alpha (#373)
marc-romu Jan 11, 2026
384da92
refactor: updated license header and automated updates via github wor…
marc-romu Jan 11, 2026
42c992a
refactor: externalized ghjson libraries and fix in update-licensehead…
marc-romu Jan 11, 2026
35ff95a
refactor: migrate to ghjson-dotnet library and update component seria…
marc-romu Jan 11, 2026
cf6b34f
refactor: disable persistent data serialization in gh_get and remove …
marc-romu Jan 11, 2026
a48ebfe
refactor: migrate script component utilities to ghjson-dotnet library…
marc-romu Jan 11, 2026
b1827db
style: normalize license header whitespace across test component files
marc-romu Jan 11, 2026
97559b2
Merge branch 'dev' of https://github.com/architects-toolkit/SmartHopp…
marc-romu Jan 11, 2026
4addeb9
Merge branch 'dev' of https://github.com/architects-toolkit/SmartHopp…
marc-romu Jan 11, 2026
8cc8487
refactor: GhJSON externalization to ghjson-dotnet package
marc-romu Jan 11, 2026
a11c12e
refactor: rename ScriptComponentHelper to ScriptParameterSettingsPars…
marc-romu Jan 11, 2026
3a95074
refactor: bump version to 1.3.0-dev and enhance script component para…
marc-romu Jan 11, 2026
ad3e54b
refactor: migrate AI tools to use ghjson-dotnet façade APIs exclusively
marc-romu Jan 12, 2026
7dc06f2
refactor: delegate canvas operations to ghjson-dotnet façade methods …
marc-romu Jan 12, 2026
7626b93
refactor: add JSON schema validation and System.Text.Json dependencie…
marc-romu Jan 12, 2026
daad047
refactor: enable CopyLocalLockFileAssemblies and normalize FilterPars…
marc-romu Jan 12, 2026
70ef054
refactor: migrate AI tools to direct Grasshopper API and update ghjso…
marc-romu Feb 7, 2026
5070e13
chore: bump version to 1.3.0-dev.260207 and normalize GhJsonExtension…
marc-romu Feb 7, 2026
49f2463
refactor: migrate gh_get to use ghjson-dotnet CanvasSelector and remo…
marc-romu Feb 7, 2026
36f88da
fix: restore filter pipeline, connection depth expansion, and externa…
marc-romu Feb 7, 2026
6136b96
chore: update LGPL license header format to use URL instead of postal…
marc-romu Feb 7, 2026
c1f28de
refactor: replace manual offset calculation with AutoOffset flag in g…
marc-romu Feb 7, 2026
10b855c
refactor: change ISelectingComponent to use IGH_DocumentObject instea…
marc-romu Feb 7, 2026
1fb025c
refactor: remove legacy references and unused code from AICall infras…
marc-romu Feb 8, 2026
801eb35
chore: update ready_to_use badge status from NO to YES in README.md
marc-romu Feb 8, 2026
35db35c
chore: update changelog
marc-romu Feb 8, 2026
dea2e1f
refactor: normalize gh_put.cs file encoding from ASCII to UTF-8 with BOM
marc-romu Feb 8, 2026
5cc7687
refactor: remove header-fixer GitHub action and simplify code style w…
marc-romu Feb 8, 2026
11ba027
refactor: replace ghjson-dotnet project references with NuGet package…
marc-romu Feb 8, 2026
bc552e9
fix: correct regex escaping in line ending normalization for license …
marc-romu Feb 8, 2026
e2afdb7
refactor(ghjson): externalize GhJSON libraries to ghjson-dotnet packa…
marc-romu Feb 8, 2026
cf281b6
chore: update development version date to 1.3.0-dev.260208
actions-user Feb 8, 2026
7231305
chore: update development version date to 1.3.0-dev.260208 (#375)
marc-romu Feb 8, 2026
a575798
chore: add automated copyright year update workflow and centralize me…
marc-romu Feb 8, 2026
656d822
chore: remove redundant XML declarations from project files and impro…
marc-romu Feb 8, 2026
4b698d3
chore: add automated copyright year update workflow and centralize me…
marc-romu Feb 8, 2026
9da03f9
chore: bump version to 1.2.4 stable release
marc-romu Feb 8, 2026
359269a
chore: bump version to 1.2.4 stable release (#377)
marc-romu Feb 8, 2026
01297c3
chore: update CHANGELOG.md with version 1.2.4 release date
marc-romu Feb 8, 2026
0e31f1e
chore: Updated yak-package manifest description to emphasize open sou…
marc-romu Feb 8, 2026
808d652
docs: update DEV.md with component categories, tool categorization, a…
marc-romu Feb 8, 2026
7684e6b
docs: reorganize DEV.md component and AI tool tables by category for …
marc-romu Feb 8, 2026
7554094
chore: add manifest text validation and auto-update workflows for ver…
marc-romu Feb 8, 2026
f906100
chore: update copyright year to 2026 and conditionally show warning i…
marc-romu Feb 8, 2026
98b1856
chore: replace runtime version retrieval with compile-time constant i…
marc-romu Feb 8, 2026
07987ef
chore: replace compile-time version constant with runtime assembly at…
marc-romu Feb 8, 2026
31424dd
Merge branch 'main' into dev
marc-romu Feb 8, 2026
b4b4e38
chore: prepare CHANGELOG and manifest for 1.3.0-alpha release
marc-romu Feb 8, 2026
f38b4a6
chore: fix grep syntax in pr-manifest-validation.yml by adding explic…
marc-romu Feb 8, 2026
6286d23
refactor(ghjson): externalize GhJSON libraries to ghjson-dotnet NuGet…
marc-romu Feb 8, 2026
1059100
chore: prepare release 1.3.0-alpha with version update and code style…
actions-user Feb 8, 2026
b0b7c62
chore: prepare release 1.3.0-alpha with version update and code style…
marc-romu Feb 8, 2026
4c07f7a
release/1.3.0-alpha (#381)
marc-romu Feb 8, 2026
9998648
fix(core): add macOS/Linux compatibility for provider loading and URL…
nofcfy-fanqi Feb 13, 2026
f1ade57
chore: restrict pr-milestone workflow to specific branches and exclud…
marc-romu Feb 15, 2026
c0d7ea3
fix(core): add macOS compatibility for provider loading and URL handl…
marc-romu Feb 15, 2026
c237d3b
chore: bump version to 1.4.0-dev.260215 and update issue template pla…
marc-romu Feb 15, 2026
f1e7534
chore: refactor ComponentStateManager event firing to prevent macOS d…
marc-romu Feb 15, 2026
683a11e
fix(settings): initialize new installations with encryption version 2…
marc-romu Feb 15, 2026
ea19eb8
refactor(dialogs): refactored StyledMessageDialog sizing calculations
marc-romu Feb 15, 2026
afa9d1f
fix(ui): prevent WebChatDialog crash on macOS by using null baseUri f…
marc-romu Feb 15, 2026
c0a5881
feat(ui): add VersionHelper utility and enhance About dialog with aut…
marc-romu Feb 15, 2026
29b6649
feat(security): add SHA-256 hash verification system for AI provider …
marc-romu Feb 15, 2026
2713ae2
refactor(menu): remove unused VersionHelper import from AboutMenuItem
marc-romu Feb 15, 2026
9ad71ca
feat(ci): add reusable GitHub Actions for build, hash calculation, an…
marc-romu Feb 15, 2026
25c0bfb
feat(security): add comprehensive input validation and sanitization t…
marc-romu Feb 15, 2026
c566478
refactor(ci): rename test workflows to user workflows and update desc…
marc-romu Feb 15, 2026
a118924
chore(deps): remove commented-out Grasshopper package reference from …
marc-romu Feb 15, 2026
046810c
style: apply consistent code formatting and whitespace cleanup across…
marc-romu Feb 15, 2026
b4d8a5d
refactor(security): improve platform name validation regex to better …
marc-romu Feb 15, 2026
dce8d56
refactor(security): simplify platform name validation to use allowlis…
marc-romu Feb 15, 2026
8c9c0e1
refactor(security): simplify platform name validation in calculate-pr…
marc-romu Feb 15, 2026
86c5fa3
refactor(actions): standardize output names to uppercase in calculate…
marc-romu Feb 15, 2026
5442155
refactor(ci): remove PR comment steps from validation workflows
marc-romu Feb 15, 2026
ee40b0f
refactor(ci): improve hash file conflict detection in PR build valida…
marc-romu Feb 15, 2026
f992350
feat(security): add SHA-256 provider verification and macOS compatibi…
marc-romu Feb 15, 2026
8d634f7
chore: prepare release 1.4.0-alpha with version update and code style…
actions-user Feb 15, 2026
5368d81
chore: prepare release 1.4.0-alpha with version update and code style…
marc-romu Feb 15, 2026
cd5f5a3
release/1.4.0-alpha (#385)
marc-romu Feb 15, 2026
792de92
feat(ci): add GitHub Pages publishing for provider hash manifests
marc-romu Feb 15, 2026
a4767e2
Merge branch 'main' of https://github.com/architects-toolkit/SmartHopper
marc-romu Feb 15, 2026
db23b0b
refactor(ci): remove duplicate hash manifest publishing steps from re…
marc-romu Feb 15, 2026
e5854ab
refactor(actions): cache hash file before git operations in publish-t…
marc-romu Feb 15, 2026
757b69d
refactor(ci): split GitHub Pages publishing into separate generation …
marc-romu Feb 15, 2026
94dea8e
refactor(ci): replace GitHub API with versions manifest for GitHub Pa…
marc-romu Feb 15, 2026
2009ae1
refactor(ci): commit hash files to repository and deploy Pages on PR …
marc-romu Feb 15, 2026
226b201
fix(ci): consolidate multi-line PR body into single PowerShell variab…
marc-romu Feb 15, 2026
93c2a4c
fix(ci): add pull-requests permission and improve error handling for …
marc-romu Feb 15, 2026
6a2c7a2
chore: add provider hash manifest for 1.4.0-alpha (#386)
github-actions[bot] Feb 15, 2026
fb03c0d
fix(ci): fetch full git history for version determination in Pages de…
marc-romu Feb 15, 2026
abbc785
refactor(ci): simplify GitHub Pages generation to process all hash fi…
marc-romu Feb 15, 2026
2e3ad18
fix(core): resolve macOS issues in 1.4.0-alpha — deadlock, GhJSON val…
nofcfy-fanqi Feb 16, 2026
c908008
fix: address review feedback — extract shared JSON parser, remove dea…
nofcfy-fanqi Feb 19, 2026
6680525
Merge branch '263-compatibility-with-mac' into fix/macos-compat-1.4-pr
marc-romu Mar 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- fix(core): fire `ComponentStateManager` transition events outside `stateLock` using `Monitor.Exit`/`Monitor.Enter` to prevent deadlocks from re-entrant lock acquisition on macOS (adapted to 1.4.0 code structure)
- fix(infrastructure): skip SHA-256 hash verification on non-Windows platforms where source-built assemblies produce different hashes than official releases
- fix(tools): set GhJSON component `Id = 1` when `InstanceGuid` is null in `script_generate` and `script_edit` to satisfy GhJSON.Core validation requiring at least one identifier
- fix(tools): add `SanitizeAndParseJson` to handle AI responses wrapped in markdown code blocks or non-JSON formatting in `script_generate` and `script_edit`
- fix(infrastructure): improve `AIProvider.CallApi()` error messages for non-JSON API responses (e.g., HTML error pages from proxies)

## [1.4.0-alpha] - 2026-02-15

Many thanks to [nofcfy-fanqi](https://github.com/nofcfy-fanqi) and [nof2504](https://github.com/nof2504) for the contributions to this release.
Expand Down
16 changes: 14 additions & 2 deletions src/SmartHopper.Core.Grasshopper/AITools/script_edit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
using GhJSON.Core;
using GhJSON.Core.SchemaModels;
using GhJSON.Core.Serialization;
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;
Expand Down Expand Up @@ -242,7 +244,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 newScriptCode = responseJson["script"]?.ToString() ?? string.Empty;
var newInputs = responseJson["inputs"] as JArray ?? new JArray();
Expand Down Expand Up @@ -289,7 +291,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);

newScriptCode = responseJson["script"]?.ToString() ?? string.Empty;
newInputs = responseJson["inputs"] as JArray ?? new JArray();
Expand Down Expand Up @@ -397,6 +399,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 CreateScriptGhJson(
string languageKey,
string scriptCode,
Expand All @@ -421,6 +432,7 @@ private static string CreateScriptGhJson(
},
NickName = nickname,
InstanceGuid = instanceGuid,
Id = instanceGuid.HasValue ? null : 1,
Comment thread
marc-romu marked this conversation as resolved.
Pivot = pivot,
};

Expand Down
15 changes: 13 additions & 2 deletions src/SmartHopper.Core.Grasshopper/AITools/script_generate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -393,6 +403,7 @@ private static string CreateScriptGhJson(
Name = CreateComponentName(languageKey),
NickName = nickname,
InstanceGuid = instanceGuid,
Id = instanceGuid.HasValue ? null : 1,
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type mismatch: Setting Id = 1 when creating a GhJSON component may be incorrect. According to GhJSON.Core conventions, Id is typically used as a sequential document-level identifier (1, 2, 3, etc.) when components don't have GUIDs, not as a constant fallback value. Using a hardcoded 1 for all generated components without GUIDs could cause issues if multiple components are created in the same document.

However, since this code creates single-component documents (line 479-481 shows AddComponent(component) with a single component), using Id = 1 is acceptable for this specific use case. If this function is ever used to create multi-component documents, the Id logic will need to be updated to use sequential IDs.

Copilot uses AI. Check for mistakes.
Pivot = pivot,
};

Expand Down
141 changes: 141 additions & 0 deletions src/SmartHopper.Core.Grasshopper/Utils/Parsing/AIResponseParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* along with this library; if not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
Expand Down Expand Up @@ -545,5 +546,145 @@ public static string NormalizeJsonArrayString(List<string> values)
}

#endregion

#region JSON Object Parsing

/// <summary>
/// Attempts to extract and parse a JSON object from an AI response that may contain
/// markdown formatting, HTML tags, or other non-JSON wrapping.
/// Uses brace-depth tracking to correctly extract the first complete JSON object.
/// </summary>
/// <param name="response">Raw response from the AI.</param>
/// <returns>Parsed <see cref="JObject"/>.</returns>
/// <exception cref="JsonException">Thrown when the response cannot be parsed as JSON.</exception>
public static JObject SanitizeAndParseJson(string response)
{
if (string.IsNullOrWhiteSpace(response))
{
throw new JsonException("AI response is empty.");
}

// Try direct parse first
try
{
return JObject.Parse(response);
}
catch (JsonException)
{
// Continue with sanitization attempts
}

// Try extracting JSON from markdown code blocks (```json ... ``` or ``` ... ```)
var trimmed = response.Trim();
var match = MarkdownCodeBlockRegex().Match(trimmed);
if (match.Success)
{
try
{
return JObject.Parse(match.Groups[1].Value.Trim());
}
catch (JsonException)
{
// Continue
}
}

// Try extracting the first complete JSON object by tracking brace depth
var jsonCandidate = ExtractFirstJsonObject(trimmed);
if (!string.IsNullOrEmpty(jsonCandidate))
{
try
{
return JObject.Parse(jsonCandidate);
}
catch (JsonException)
{
// Continue
}
}

// All attempts failed - provide a descriptive error
var preview = response.Length > 200 ? response.Substring(0, 200) + "..." : response;
if (trimmed.StartsWith("<", StringComparison.Ordinal))
{
throw new JsonException(
$"AI returned HTML/XML instead of JSON. This may indicate a provider error. Preview: {preview}");
}

throw new JsonException($"AI response is not valid JSON. Preview: {preview}");
}

/// <summary>
/// Extracts the first complete JSON object from a string by tracking brace depth,
/// correctly handling nested objects and string literals.
/// </summary>
/// <param name="text">The text to search for a JSON object.</param>
/// <returns>The first complete JSON object string, or null if none found.</returns>
private static string ExtractFirstJsonObject(string text)
{
if (string.IsNullOrEmpty(text))
{
return null;
}

bool inString = false;
bool escape = false;
int depth = 0;
int startIndex = -1;

for (int i = 0; i < text.Length; i++)
{
char c = text[i];

if (escape)
{
escape = false;
continue;
}

if (c == '\\')
{
if (inString)
{
escape = true;
}

continue;
}

if (c == '"')
{
inString = !inString;
continue;
}

if (inString)
{
continue;
}

if (c == '{')
{
if (depth == 0)
{
startIndex = i;
}

depth++;
}
else if (c == '}' && depth > 0)
{
depth--;
if (depth == 0 && startIndex >= 0)
{
return text.Substring(startIndex, i - startIndex + 1);
}
}
}

return null;
}

#endregion
}
}
49 changes: 33 additions & 16 deletions src/SmartHopper.Core/ComponentBase/ComponentStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential thread safety issue: After releasing the lock via Monitor.Exit() at line 380, if another thread calls RequestTransition() before this thread re-acquires the lock at line 397, that other thread could observe isTransitioning = false (set at line 371) and start its own ProcessTransitionQueue() execution. This could lead to concurrent processing of the transition queue from multiple threads.

The pattern assumes the calling thread still "owns" the lock semantically even after Monitor.Exit(), but that's not guaranteed. Consider one of these approaches:

  1. Set a separate flag before releasing the lock to indicate events are being fired
  2. Use a recursive lock pattern instead of Monitor.Exit/Enter
  3. Accept that new transitions will be queued and processed by the next ProcessTransitionQueue call

The current implementation may work in practice if event handlers typically don't trigger transitions from other threads, but the race condition exists.

Copilot uses AI. Check for mistakes.
}
}
Expand Down
14 changes: 13 additions & 1 deletion src/SmartHopper.Infrastructure/AIProviders/AIProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,19 @@ private async Task<IAIReturn> CallApi(AIRequestCall request)
catch (Exception ex)
{
Debug.WriteLine($"[{this.Name}] Call - Failed to parse JSON response: {ex.Message}");
throw;

// Provide a more useful error when the API returns non-JSON content (e.g., HTML error pages)
var preview = content?.Length > 200 ? content.Substring(0, 200) + "..." : content;
if (!string.IsNullOrEmpty(content) && content.TrimStart().StartsWith("<", StringComparison.Ordinal))
{
throw new Exception(
$"The {this.Name} API returned an HTML response instead of JSON. " +
$"This usually indicates a server error, proxy issue, or Cloudflare challenge. " +
$"Response preview: {preview}");
}

throw new Exception(
$"The {this.Name} API returned invalid JSON. Response preview: {preview}", ex);
}

var aiReturn = new AIReturn();
Expand Down
Loading