Skip to content

Add multiplatform SystemConfigReader interface with JVM-specific implementation#1228

Closed
kpavlov wants to merge 1 commit intodevelopfrom
kpavlov/system-config-reader
Closed

Add multiplatform SystemConfigReader interface with JVM-specific implementation#1228
kpavlov wants to merge 1 commit intodevelopfrom
kpavlov/system-config-reader

Conversation

@kpavlov
Copy link
Copy Markdown
Contributor

@kpavlov kpavlov commented Dec 5, 2025

Add multiplatform system configuration and secrets readers with JVM-specific implementation

Introduce SystemConfigReader and SystemSecretsReader interfaces to standardize access to configuration values and secrets across different platforms. This change utilizes the expect/actual mechanism to define common contracts with specific platform implementations.

  • Implement fully functional readers for the JVM target: the configuration reader resolves values from environment variables and system properties (supports name normalization), while the secrets reader strictly uses environment variables for security.
  • Add stub implementations for Android, Apple, JS, and WasmJS platforms that currently throw a NotImplementedError when accessed.
  • Define the common interfaces and factory functions to allow retrieval of configuration strings and secrets.

Motivation and Context

Should be used in Debugger Config and LLM Clients

See also #1231

Breaking Changes

No

Type of the changes

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tests improvement
  • Refactoring

Checklist

  • The pull request has a description of the proposed change
  • I read the Contributing Guidelines before opening the pull request
  • The pull request uses develop as the base branch
  • Tests for the changes have been added
  • All new and existing tests passed
Additional steps for pull requests adding a new feature
  • An issue describing the proposed change exists
  • The pull request includes a link to the issue
  • The change was discussed and approved in the issue
  • Docs have been added / updated

@kpavlov kpavlov added the enhancement New feature or request label Dec 5, 2025
@kpavlov kpavlov marked this pull request as ready for review December 5, 2025 12:32
Comment thread utils/src/androidMain/kotlin/ai/koog/utils/system/SystemConfigReader.android.kt Outdated
Comment thread utils/src/androidMain/kotlin/ai/koog/utils/system/SystemConfigReader.android.kt Outdated
Comment thread utils/src/appleMain/kotlin/ai/koog/utils/system/SystemConfigReader.apple.kt Outdated
Comment thread utils/src/jvmMain/kotlin/ai/koog/utils/system/SystemConfigReader.jvm.kt Outdated
*/
override fun get(name: String): String? {
return cache.computeIfAbsent(name) {
System.getenv(name) ?: System.getProperty(name.lowercase().replace('_', '.'))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Custom logic with lowercase and replace doesn't look straightforward and can lead to confusion. Let's use name as it is everywhere

Copy link
Copy Markdown
Contributor Author

@kpavlov kpavlov Dec 5, 2025

Choose a reason for hiding this comment

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

I’m not sure about that. It’s a pretty standard way/convention to handle things by using CONFIG_PROP as an environment variable and config.prop as a system property. Debugger is using the same pattern as well

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It's fine that it's an established patter, the main concern here is that your input gets modified unexpectedly. So e.g. if I pass org.my_propery, it would be transformed to org.my.property and the function will return null. And it can be confusing if I know that the property is there

Copy link
Copy Markdown
Contributor Author

@kpavlov kpavlov Dec 5, 2025

Choose a reason for hiding this comment

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

@EugeneTheDev, how should we handle this? Should we only normalize the name if it’s in UPPER_CASE_WITH_UNDERSCORES?
Is the current setup working well enough?

I suggest keeping this implementation, and users can implement their own config reader

Copy link
Copy Markdown
Collaborator

@EugeneTheDev EugeneTheDev Dec 5, 2025

Choose a reason for hiding this comment

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

Do you think it should be reader's concern? IMHO we should keep reader as simple as possible - only read what is asked. And if the application allows several configuration options, like in your Spring example with env MY_PROPERTY and system my.property, it should be application's concern, and I would expect the usage site to implement something as follows:

val myProperty = reader.getConfigVariable("MY_PROPERTY")
    ?: reader.getConfigVariable("my.property")
    ?: throw NoSuchElementException("Can't find myProperty")
    

Copy link
Copy Markdown
Contributor Author

@kpavlov kpavlov Dec 5, 2025

Choose a reason for hiding this comment

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

This wouldn't work as convention over configuration then.
This behavior is only applicable to JVM. For other platforms there should not be such convention.
@Ololoshechkin, what do you think?

Comment thread utils/src/wasmJsMain/kotlin/ai/koog/utils/system/SystemConfigReader.wasmJs.kt Outdated
Comment thread utils/src/jvmMain/kotlin/ai/koog/utils/system/SystemConfigReader.jvm.kt Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Dec 5, 2025

Qodana for JVM

1175 new problems were found

Inspection name Severity Problems
Check Kotlin and Java source code coverage 🔶 Warning 1159
Missing KDoc for public API declaration 🔶 Warning 16
@@ Code coverage @@
+ 72% total lines covered
16818 lines analyzed, 12198 lines covered
# Calculated according to the filters of your coverage tool

☁️ View the detailed Qodana report

Contact Qodana team

Contact us at qodana-support@jetbrains.com

@kpavlov kpavlov force-pushed the kpavlov/system-config-reader branch 2 times, most recently from f739f23 to 90d46a7 Compare December 5, 2025 16:23
@kpavlov kpavlov requested a review from Ololoshechkin December 5, 2025 16:24
Introduce `SystemConfigReader` and `SystemSecretsReader` interfaces to standardize access to configuration values and secrets across different platforms. This change utilizes the `expect`/`actual` mechanism to define common contracts with specific platform implementations.

*   Implement fully functional readers for the JVM target: the configuration reader resolves values from environment variables and system properties (supports name normalization), while the secrets reader strictly uses environment variables for security.
*   Add stub implementations for Android, Apple, JS, and WasmJS platforms that currently throw a `NotImplementedError` when accessed.
*   Define the common interfaces and factory functions to allow retrieval of configuration strings and secrets.
@kpavlov kpavlov force-pushed the kpavlov/system-config-reader branch from 90d46a7 to 72149ef Compare December 5, 2025 16:34
@kpavlov kpavlov requested a review from EugeneTheDev December 5, 2025 16:54
kpavlov added a commit that referenced this pull request Dec 5, 2025
# Add multiplatform system configuration and secrets readers with
JVM-specific implementation

Introduce `SystemConfigReader` and `SystemSecretsReader` interfaces to
standardize access to configuration values and secrets across different
platforms. This change utilizes the `expect`/`actual` mechanism to
define common contracts with specific platform implementations.

* Implement fully functional readers for the JVM target: the
configuration reader resolves values from environment variables and
system properties (supports name normalization), while the secrets
reader strictly uses environment variables for security.
* Add stub implementations for Android, Apple, JS, and WasmJS platforms
that currently throw a `NotImplementedError` when accessed.
* Define the common interfaces and factory functions to allow retrieval
of configuration strings and secrets.
* Add `UserDefaultsSystemConfigReader` backed by Apple's NSUserDefaults
for retrieving configuration properties. Update `systemConfigReader` to
use this implementation and introduce comprehensive unit tests to ensure
correctness.

## Motivation and Context
Should be used in Debugger Config and LLM Clients

See also #1228 

## Breaking Changes
No

---

#### Type of the changes
- [x] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Tests improvement
- [ ] Refactoring

#### Checklist
- [x] The pull request has a description of the proposed change
- [x] I read the [Contributing
Guidelines](https://github.com/JetBrains/koog/blob/main/CONTRIBUTING.md)
before opening the pull request
- [x] The pull request uses **`develop`** as the base branch
- [x] Tests for the changes have been added
- [x] All new and existing tests passed

##### Additional steps for pull requests adding a new feature
- [ ] An issue describing the proposed change exists
- [ ] The pull request includes a link to the issue
- [ ] The change was discussed and approved in the issue
- [ ] Docs have been added / updated
@kpavlov
Copy link
Copy Markdown
Contributor Author

kpavlov commented Dec 5, 2025

Merged as a part of #1231

@kpavlov kpavlov closed this Dec 5, 2025
@kpavlov kpavlov deleted the kpavlov/system-config-reader branch December 5, 2025 18:08
vova-jb pushed a commit that referenced this pull request Jan 27, 2026
# Add multiplatform system configuration and secrets readers with
JVM-specific implementation

Introduce `SystemConfigReader` and `SystemSecretsReader` interfaces to
standardize access to configuration values and secrets across different
platforms. This change utilizes the `expect`/`actual` mechanism to
define common contracts with specific platform implementations.

* Implement fully functional readers for the JVM target: the
configuration reader resolves values from environment variables and
system properties (supports name normalization), while the secrets
reader strictly uses environment variables for security.
* Add stub implementations for Android, Apple, JS, and WasmJS platforms
that currently throw a `NotImplementedError` when accessed.
* Define the common interfaces and factory functions to allow retrieval
of configuration strings and secrets.
* Add `UserDefaultsSystemConfigReader` backed by Apple's NSUserDefaults
for retrieving configuration properties. Update `systemConfigReader` to
use this implementation and introduce comprehensive unit tests to ensure
correctness.

## Motivation and Context
Should be used in Debugger Config and LLM Clients

See also #1228 

## Breaking Changes
No

---

#### Type of the changes
- [x] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Tests improvement
- [ ] Refactoring

#### Checklist
- [x] The pull request has a description of the proposed change
- [x] I read the [Contributing
Guidelines](https://github.com/JetBrains/koog/blob/main/CONTRIBUTING.md)
before opening the pull request
- [x] The pull request uses **`develop`** as the base branch
- [x] Tests for the changes have been added
- [x] All new and existing tests passed

##### Additional steps for pull requests adding a new feature
- [ ] An issue describing the proposed change exists
- [ ] The pull request includes a link to the issue
- [ ] The change was discussed and approved in the issue
- [ ] Docs have been added / updated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants