Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions sdk_v2/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ include(cmake/Sanitizers.cmake)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(azure-storage-blobs-cpp CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(Microsoft.GSL CONFIG REQUIRED)
find_package(LibArchive REQUIRED)

if(FOUNDRY_LOCAL_BUILD_SERVICE)
Expand Down Expand Up @@ -557,7 +556,7 @@ target_include_directories(foundry_local_cpp
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(foundry_local_cpp INTERFACE foundry_local Microsoft.GSL::GSL)
target_link_libraries(foundry_local_cpp INTERFACE foundry_local)

# --------------------------------------------------------------------------
# Split debug symbols (Linux / macOS, RelWithDebInfo only)
Expand Down
15 changes: 6 additions & 9 deletions sdk_v2/cpp/docs/WrapperInterfacesDesign.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,19 @@ Driven by the interface decisions:
`std::unique_ptr<IModel>`. Null = not found.
- `Catalog::GetLatestVersion(const IModel&)` returns `std::unique_ptr<IModel>`.
- `Catalog::GetModels()` / `GetCachedModels()` / `GetLoadedModels()` return
`ModelList`. `ModelList::Models()` returns `gsl::span<const std::unique_ptr<IModel>>`.
`ModelList`. `ModelList::Models()` returns `std::vector<IModel*>`; the pointers
remain valid for the lifetime of the `ModelList`.
- `Session`, `ChatSession`, `AudioSession` constructors take `IModel&`.
- `IModel::SelectVariant(const IModel&)` and `Catalog::GetLatestVersion(const IModel&)`
internally use `static_cast<const Model&>(arg).native_handle()`. RTTI is not used;
the downcast is sound because `Model` is the only concrete `IModel` produced by
the SDK.

### 6. GSL dependency
### 6. Non-owning collections

`microsoft-gsl` is added as a vcpkg dependency.

- `gsl::span` is used in public API where a non-owning view of a contiguous range is
returned (e.g. `ModelList::Models()`, `InputOutputInfo::inputs`/`outputs`).
- `gsl::not_null` is allowed for internal class members. It is **not** used in public
API parameters or return types — references convey the same non-null contract more
idiomatically.
- Public collection APIs use standard-library types so consumers do not need extra header dependencies.
- `ModelList::Models()` projects its internally owned models as non-owning `IModel*` values. It does not
expose the `std::unique_ptr` storage used to manage their lifetimes.

### 7. Removed types

Expand Down
3 changes: 1 addition & 2 deletions sdk_v2/cpp/include/foundry_local/foundry_local_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <gsl/span>
#include <memory>
#include <mutex>
#include <optional>
Expand Down Expand Up @@ -745,7 +744,7 @@ class ModelList {
ModelList(const ModelList&) = delete;
ModelList& operator=(const ModelList&) = delete;

gsl::span<const std::unique_ptr<IModel>> Models() const noexcept;
std::vector<IModel*> Models() const;
size_t size() const noexcept;
auto begin() const noexcept { return models_.begin(); }
auto end() const noexcept { return models_.end(); }
Expand Down
10 changes: 8 additions & 2 deletions sdk_v2/cpp/include/foundry_local/foundry_local_cpp.inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,14 @@ inline ModelList::ModelList(flModelList& model_list)
}
}

inline gsl::span<const std::unique_ptr<IModel>> ModelList::Models() const noexcept {
return {models_.data(), models_.size()};
inline std::vector<IModel*> ModelList::Models() const {
std::vector<IModel*> models;
models.reserve(models_.size());
for (const auto& model : models_) {
models.push_back(model.get());
}

return models;
}

inline size_t ModelList::size() const noexcept {
Expand Down
8 changes: 3 additions & 5 deletions sdk_v2/cpp/test/sdk_api/catalog_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@
// Licensed under the MIT License.
// Catalog-focused SDK integration tests using only the public C++ API.

#include <gsl/span>
#include <memory>
#include <type_traits>

#include "model_fixture.h"

namespace {

const foundry_local::IModel* FindModelByAlias(
gsl::span<const std::unique_ptr<foundry_local::IModel>> models,
std::string_view alias) {
const foundry_local::IModel* FindModelByAlias(const std::vector<foundry_local::IModel*>& models,
std::string_view alias) {
for (const auto& model : models) {
if (model->GetInfo().Alias() == alias) {
return model.get();
return model;
}
}

Expand Down
1 change: 0 additions & 1 deletion sdk_v2/cpp/vcpkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"features": ["curl"],
"platform": "!windows | uwp"
},
"ms-gsl",
"zlib",
"nlohmann-json",
"spdlog"
Expand Down
2 changes: 1 addition & 1 deletion sdk_v2/js/native/src/catalog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Napi::Value WrapModelList(Napi::Env env, foundry_local::ModelList ml,
Napi::Array arr = Napi::Array::New(env, models.size());
for (size_t i = 0; i < models.size(); ++i) {
ModelCtorToken token;
token.impl = models[i].get();
token.impl = models[i];
token.keepalive = list;
token.manager = Napi::Reference<Napi::Object>::New(manager.Value(), 1);
arr.Set(static_cast<uint32_t>(i), Model::NewInstance(env, std::move(token)));
Expand Down
2 changes: 1 addition & 1 deletion sdk_v2/js/native/src/model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Napi::Array WrapModelList(Napi::Env env, std::shared_ptr<foundry_local::ModelLis
Napi::Array arr = Napi::Array::New(env, models.size());
for (size_t i = 0; i < models.size(); ++i) {
ModelCtorToken token;
token.impl = models[i].get();
token.impl = models[i];
token.keepalive = list; // shared_ptr copy keeps the ModelList alive
// Cloning the manager ObjectReference per Model so each entry pins it.
token.manager = Napi::Reference<Napi::Object>::New(manager.Value(), 1);
Expand Down
Loading