Conversation
nenad1002
commented
Mar 23, 2026
- pipeline support missing, will come in future
- ARM support will come soon
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR introduces an initial C++ SDK under sdk/cpp/, including the core API surface (manager/catalog/model/client), a CMake-based build, unit tests, and sample usage.
Changes:
- Add C++ SDK public headers and a Windows (WIL-based) implementation.
- Add CMake project/presets plus formatting configuration for the C++ SDK.
- Add GTest unit tests and JSON testdata fixtures covering parsing, catalog/model behavior, and client requests.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/cpp/CMakeLists.txt | Defines the C++ SDK library, sample, and unit tests; Windows-only guard and dependencies. |
| sdk/cpp/CMakePresets.json | Adds configure/build/test presets for building the C++ SDK. |
| sdk/cpp/.clang-format | Establishes C++ formatting rules for the SDK. |
| sdk/cpp/include/foundry_local.h | Public C++ SDK API surface (manager, catalog, model/variant, chat/audio clients, types). |
| sdk/cpp/include/configuration.h | Configuration types/validation for initializing Foundry Local from C++. |
| sdk/cpp/include/core_interop_request.h | Helper for building JSON-wrapped core requests with Params. |
| sdk/cpp/include/flcore_native.h | Native ABI struct/function-pointer definitions for calling the core DLL. |
| sdk/cpp/include/foundry_local_exception.h | SDK exception type with optional logging. |
| sdk/cpp/include/foundry_local_internal_core.h | Internal core interface abstraction used by SDK types/tests. |
| sdk/cpp/include/logger.h | Logger interface + NullLogger implementation. |
| sdk/cpp/include/log_level.h | LogLevel enum and string conversion helper. |
| sdk/cpp/include/parser.h | JSON (de)serialization helpers for model info, chat, tool calling, etc. |
| sdk/cpp/src/foundry_local.cpp | Main SDK implementation: DLL loading, manager/catalog/model/clients, streaming callbacks. |
| sdk/cpp/sample/main.cpp | Example app demonstrating catalog browsing, chat (streaming/non), audio, tool calling, and variant selection. |
| sdk/cpp/test/mock_core.h | Mock/file-backed core implementations + file reading helper for tests. |
| sdk/cpp/test/mock_object_factory.h | Test factory enabling construction of private-constructor SDK types. |
| sdk/cpp/test/parser_and_types_test.cpp | Unit tests for parsing/serialization utilities and small type behaviors. |
| sdk/cpp/test/model_variant_test.cpp | Unit tests for ModelVariant and Model behaviors (load/cache/download/path/selection). |
| sdk/cpp/test/client_test.cpp | Unit tests for ChatClient/AudioClient request formatting and streaming. |
| sdk/cpp/test/catalog_test.cpp | Unit tests for Catalog grouping/filtering/caching and file-based fixtures. |
| sdk/cpp/test/testdata/empty_models_list.json | Fixture: empty model list. |
| sdk/cpp/test/testdata/malformed_models_list.json | Fixture: malformed JSON for error-path testing. |
| sdk/cpp/test/testdata/missing_name_field_models_list.json | Fixture: missing required fields for validation/error tests. |
| sdk/cpp/test/testdata/mixed_openai_and_local.json | Fixture: mix of OpenAI-prefixed and local models for filtering tests. |
| sdk/cpp/test/testdata/real_models_list.json | Fixture: richer realistic model entries with optional fields/runtime/template. |
| sdk/cpp/test/testdata/single_cached_model.json | Fixture: one cached model entry for subset tests. |
| sdk/cpp/test/testdata/three_variants_one_model.json | Fixture: multiple variants under one alias for grouping tests. |
| sdk/cpp/test/testdata/valid_cached_models.json | Fixture: cached model IDs list. |
| sdk/cpp/test/testdata/valid_loaded_models.json | Fixture: loaded model IDs list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| #include "logger.h" | ||
|
|
||
| namespace FoundryLocal { |
There was a problem hiding this comment.
nit: should we follow the ORT conventions for naming etc. for consistency? If so namespace would be foundry_local
| FetchContent_Declare( | ||
| nlohmann_json | ||
| GIT_REPOSITORY https://github.com/nlohmann/json.git | ||
| GIT_TAG v3.12.0 | ||
| ) | ||
| FetchContent_MakeAvailable(nlohmann_json) |
There was a problem hiding this comment.
Is using FetchContent allowed by security rules or do we need to use vcpkg? I have a working vcpkg based setup in my WIP branch if you need to copy from somewhere.
| # ----------------------------- | ||
| FetchContent_Declare( | ||
| wil_src | ||
| GIT_REPOSITORY https://github.com/microsoft/wil.git |
There was a problem hiding this comment.
Is the SDK Windows only or it builds/runs on other platforms?
| add_library(CppSdk STATIC | ||
| src/foundry_local.cpp | ||
| # Add more .cpp files as you migrate: | ||
| # src/parser.cpp | ||
| # src/dllmain.cpp | ||
| # src/pch.cpp | ||
| ) |
There was a problem hiding this comment.
Should we build a shared library as well or there's no requirement for that currently?
| } | ||
| }, | ||
| { | ||
| "name": "x86-debug", |
There was a problem hiding this comment.
Do we care about x86? We don't have FL Core builds of that do we?
| for (const auto& v : it->second.variants_) { | ||
| modelIdToModelVariant_[v.GetInfo().name] = &v; | ||
| } |
There was a problem hiding this comment.
Do we need to iterate all variants here or just add the current one?
If we're adding to modelIdToModelVariant should it be using v.GetId() rather than the name? id == name:version and should be unique.
| return CollectVariantsByIds(modelIdToModelVariant_, GetLoadedModelsInternal(core_, *logger_)); | ||
| } | ||
|
|
||
| std::vector<const ModelVariant*> Catalog::GetCachedModels() const { | ||
| return CollectVariantsByIds(modelIdToModelVariant_, GetCachedModelsInternal(core_, *logger_)); |
There was a problem hiding this comment.
Not quite understanding this. The loaded and cached model getters should return model ids which we should be able to directly looked up in the model id to variant map.
| FoundryLocalManager::FoundryLocalManager(FoundryLocalManager&& other) noexcept | ||
| : config_(std::move(other.config_)), | ||
| core_(std::move(other.core_)), | ||
| catalog_(std::move(other.catalog_)), | ||
| logger_(other.OwnsLogger() ? &defaultLogger_ : other.logger_), | ||
| urls_(std::move(other.urls_)) { | ||
| other.logger_ = &other.defaultLogger_; | ||
| } | ||
|
|
||
| FoundryLocalManager& FoundryLocalManager::operator=(FoundryLocalManager&& other) noexcept { | ||
| if (this != &other) { | ||
| config_ = std::move(other.config_); | ||
| core_ = std::move(other.core_); | ||
| catalog_ = std::move(other.catalog_); | ||
| logger_ = other.OwnsLogger() ? &defaultLogger_ : other.logger_; | ||
| urls_ = std::move(other.urls_); | ||
| other.logger_ = &other.defaultLogger_; | ||
| } | ||
| return *this; | ||
| } |
| core_->call(initReq.Command(), *logger_, &initJson); | ||
|
|
||
| if (config_.model_cache_dir) { | ||
| std::string current = core_->call("get_cache_directory", *logger_); |
There was a problem hiding this comment.
We should be able to provide the cache dir in the call to initialize. I believe there's logic in Core to create the directory if it doesn't exist as well.
|
|
||
| using Factory = MockObjectFactory; | ||
|
|
||
| class ChatClientTest : public ::testing::Test { |
There was a problem hiding this comment.
Do we have e2e or functional tests that exercise the public API overall (not just the chat client) with minimal mocking similar to the C# SDK?
I thought we setup some test data so that we can avoid the model download when running in the CI, although we should have a test that downloads a model if not already cached when run locally as a sanity check (C# has a 'SkipInCI' attribute so we might need something similar).
Should be fine to hit the catalog for the latest model list.