├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── arc-scripting
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ │ └── kotlin
│ │ │ │ └── script
│ │ │ │ └── templates
│ │ │ │ ├── org.eclipse.lmos.arc.scripting.agents.ScriptDeps.classname
│ │ │ │ └── org.eclipse.lmos.arc.scripting.functions.ScriptDeps.classname
│ │ └── kotlin
│ │ │ ├── Exceptions.kt
│ │ │ ├── agents
│ │ │ ├── CompiledAgentLoader.kt
│ │ │ └── Events.kt
│ │ │ └── functions
│ │ │ ├── Events.kt
│ │ │ └── ScriptDef.kt
│ └── test
│ │ ├── resources
│ │ ├── knowledge-source.txt
│ │ ├── weather.functions.kts
│ │ ├── weather.agent.kts
│ │ └── kb-summarizer.agent.kts
│ │ └── kotlin
│ │ ├── Testing.kt
│ │ ├── agents
│ │ └── ScriptingAgentLoaderTest.kt
│ │ ├── functions
│ │ └── ScriptingLLMFunctionLoaderTest.kt
│ │ └── FunctionsTest.kt
└── build.gradle.kts
├── arc-readers
├── src
│ ├── test
│ │ ├── resources
│ │ │ ├── test.pdf
│ │ │ ├── test.pdf.license
│ │ │ └── test.html
│ │ └── kotlin
│ │ │ └── HtmlReaderTest.kt
│ └── main
│ │ └── kotlin
│ │ └── PdfReader.kt
└── build.gradle.kts
├── arc-mcp
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ │ └── services
│ │ │ │ └── org.eclipse.lmos.arc.agents.functions.LLMFunctionLoader
│ │ └── kotlin
│ │ │ ├── Adapter.kt
│ │ │ └── McpToolsByEnvironment.kt
│ └── test
│ │ ├── resources
│ │ └── application.yml
│ │ └── kotlin
│ │ ├── TestBase.kt
│ │ └── McpPromptRetrieverTest.kt
├── README.md
└── build.gradle.kts
├── arc-view-spring-boot-starter
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── chat
│ │ │ │ ├── version.json
│ │ │ │ ├── favicon.png
│ │ │ │ ├── icons
│ │ │ │ │ └── Icon-192.png
│ │ │ │ ├── canvaskit
│ │ │ │ │ ├── skwasm.wasm
│ │ │ │ │ ├── canvaskit.wasm
│ │ │ │ │ ├── skwasm_heavy.wasm
│ │ │ │ │ └── chromium
│ │ │ │ │ │ └── canvaskit.wasm
│ │ │ │ ├── assets
│ │ │ │ │ ├── fonts
│ │ │ │ │ │ ├── MaterialIcons-Regular.otf
│ │ │ │ │ │ └── static
│ │ │ │ │ │ │ └── RobotoMono-Regular.ttf
│ │ │ │ │ ├── FontManifest.json
│ │ │ │ │ ├── AssetManifest.json
│ │ │ │ │ ├── AssetManifest.bin
│ │ │ │ │ ├── AssetManifest.bin.json
│ │ │ │ │ └── assets
│ │ │ │ │ │ └── config
│ │ │ │ │ │ └── app-config.yaml
│ │ │ │ └── manifest.json
│ │ │ └── META-INF
│ │ │ │ └── spring
│ │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ │ └── kotlin
│ │ │ ├── ArcViewAutoConfiguration.kt
│ │ │ └── inbound
│ │ │ └── UseCaseParser.kt
│ └── test
│ │ └── kotlin
│ │ └── TestApplication.kt
└── build.gradle.kts
├── arc-azure-client
├── src
│ └── main
│ │ └── resources
│ │ └── META-INF
│ │ └── services
│ │ └── org.eclipse.lmos.arc.agents.llm.CompleterLoaderService
└── build.gradle.kts
├── arc-agents
├── src
│ ├── test
│ │ ├── resources
│ │ │ └── test.txt
│ │ └── kotlin
│ │ │ ├── dsl
│ │ │ ├── Filters.kt
│ │ │ ├── extensions
│ │ │ │ └── TemplateTest.kt
│ │ │ └── AgentSystemPromptTest.kt
│ │ │ ├── functions
│ │ │ └── JsonsTest.kt
│ │ │ └── DSLAgentsTest.kt
│ └── main
│ │ └── kotlin
│ │ ├── User.kt
│ │ ├── events
│ │ ├── EventListener.kt
│ │ ├── LoggingEventHandler.kt
│ │ ├── Events.kt
│ │ └── MessagePublisher.kt
│ │ ├── dsl
│ │ ├── Tools.kt
│ │ ├── extensions
│ │ │ ├── Trace.kt
│ │ │ ├── Logging.kt
│ │ │ ├── Times.kt
│ │ │ ├── Template.kt
│ │ │ ├── Events.kt
│ │ │ ├── Data.kt
│ │ │ └── Extract.kt
│ │ ├── AgentBuilder.kt
│ │ └── AgentFactory.kt
│ │ ├── ConversationAgent.kt
│ │ ├── llm
│ │ ├── TextCompleterProvider.kt
│ │ ├── Simularity.kt
│ │ ├── AIClientConfig.kt
│ │ ├── ChatCompleterProvider.kt
│ │ ├── ChatCompleter.kt
│ │ ├── LLMEvents.kt
│ │ └── ChatCompletionSettings.kt
│ │ ├── agent
│ │ ├── Skill.kt
│ │ ├── UseCaseExtractor.kt
│ │ ├── Extensions.kt
│ │ └── AgentChain.kt
│ │ ├── functions
│ │ ├── FunctionWithContext.kt
│ │ ├── ListenableFunction.kt
│ │ ├── FunctionEvents.kt
│ │ └── TraceableLLMFunction.kt
│ │ ├── tracing
│ │ └── GenerateResponseTagger.kt
│ │ ├── LogContext.kt
│ │ ├── router
│ │ └── RouterEvents.kt
│ │ ├── AgentEvents.kt
│ │ └── features
│ │ └── FeatureFlags.kt
└── build.gradle.kts
├── arc-api
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ ├── RequestEnd.kt
│ ├── AnonymizationEntity.kt
│ ├── RequestEnvelope.kt
│ ├── Message.kt
│ ├── AgentRequest.kt
│ └── Helpers.kt
├── adl-kotlin-runner
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── services
│ │ │ └── org.eclipse.lmos.arc.assistants.support.usecases.code.CodeBlockRunner
│ │ └── kotlin
│ │ ├── ScriptConfiguration.kt
│ │ └── extensions
│ │ ├── Time.kt
│ │ └── Http.kt
└── build.gradle.kts
├── CODEOWNERS
├── arc-openai-realtime-client
├── README.md
├── src
│ ├── test
│ │ └── resources
│ │ │ └── application.yml
│ └── main
│ │ └── kotlin
│ │ ├── WavData.kt
│ │ ├── FunctionToSchema.kt
│ │ └── sound
│ │ └── Pcm16ToWav.kt
└── build.gradle.kts
├── arc-result
└── build.gradle.kts
├── arc-gen
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ ├── Agents.kt
│ └── Functions.kt
├── arc-graphql-spring-boot-starter
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── arc.properties
│ │ │ └── META-INF
│ │ │ │ └── spring
│ │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ │ └── kotlin
│ │ │ ├── ErrorHandler.kt
│ │ │ ├── AgentResolver.kt
│ │ │ ├── inbound
│ │ │ ├── EventSerializer.kt
│ │ │ ├── ContextExtractor.kt
│ │ │ ├── AgentQuery.kt
│ │ │ ├── AccessControlHeaders.kt
│ │ │ └── ToolQuery.kt
│ │ │ ├── context
│ │ │ ├── AnonymizationEntities.kt
│ │ │ └── ContextProvider.kt
│ │ │ ├── Logging.kt
│ │ │ └── EventsConfiguration.kt
│ └── test
│ │ ├── resources
│ │ └── application.yml
│ │ └── kotlin
│ │ ├── NoFeatureTest.kt
│ │ ├── AgentSubscriptionTest.kt
│ │ └── AgentEventsSubscriptionTest.kt
└── build.gradle.kts
├── .editorconfig
├── arc-streaming-spring-boot-starter
├── README.md
├── src
│ ├── main
│ │ └── resources
│ │ │ └── META-INF
│ │ │ └── spring
│ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ └── test
│ │ ├── resources
│ │ └── application.yml
│ │ └── kotlin
│ │ └── TestApplication.kt
└── build.gradle.kts
├── arc-spring-boot-starter
└── src
│ ├── main
│ ├── resources
│ │ └── META-INF
│ │ │ └── spring
│ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ └── kotlin
│ │ ├── AIConfig.kt
│ │ ├── MetricConfiguration.kt
│ │ └── Agents.kt
│ └── test
│ ├── kotlin
│ ├── clients
│ │ ├── TestApplication.kt
│ │ └── ClientsTest.kt
│ ├── TestEvent.kt
│ ├── gen
│ │ └── Agents.kt
│ ├── GenAgentTest.kt
│ └── AgentBeansTest.kt
│ └── resources
│ ├── agents
│ ├── subfolder
│ │ ├── travel.functions.kts
│ │ └── travel.agent.kts
│ ├── weather.functions.kts
│ └── weather.agent.kts
│ └── application.yml
├── arc-agent-client
├── src
│ ├── test
│ │ └── resources
│ │ │ └── application.yml
│ └── main
│ │ └── kotlin
│ │ ├── graphql
│ │ └── AgentSubscription.kt
│ │ └── AgentClient.kt
└── build.gradle.kts
├── arc-memory-mongo-spring-boot-starter
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ │ └── spring
│ │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ │ └── kotlin
│ │ │ ├── MemoryAutoConfiguration.kt
│ │ │ ├── MemoryRepository.kt
│ │ │ └── IndexCreator.kt
│ └── test
│ │ └── kotlin
│ │ ├── TestApplication.kt
│ │ └── TestBase.kt
└── build.gradle.kts
├── arc-openai-api-spring-boot-starter
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ │ └── spring
│ │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ │ └── kotlin
│ │ │ └── ArcOpenAIApiAutoConfiguration.kt
│ └── test
│ │ ├── kotlin
│ │ ├── TestEvent.kt
│ │ └── OpenAIApiTest.kt
│ │ └── resources
│ │ └── application.yml
└── build.gradle.kts
├── arc-runner
├── src
│ ├── main
│ │ └── kotlin
│ │ │ ├── server
│ │ │ └── Config.kt
│ │ │ ├── List.kt
│ │ │ ├── View.kt
│ │ │ ├── Install.kt
│ │ │ └── Set.kt
│ └── test
│ │ └── kotlin
│ │ └── RunTest.kt
├── arcPre.java
├── arc.java
└── weather.agent.kts
├── arc-assistants
├── build.gradle.kts
└── src
│ ├── test
│ ├── resources
│ │ ├── use_cases_steps.md
│ │ ├── use_cases_out.md
│ │ ├── use_cases_mobile.md
│ │ ├── use_cases.md
│ │ ├── use_cases_conditionals.md
│ │ └── use_cases_errors.md
│ └── kotlin
│ │ ├── filters
│ │ └── ReturnUseCaseIdFilterTest.kt
│ │ ├── LLMHackingDetectorTest.kt
│ │ ├── CustomerSupportAgentTest.kt
│ │ ├── usecases
│ │ ├── VersionExtractorTest.kt
│ │ └── ConditionalTest.kt
│ │ └── AlternativeSolutionFilterTest.kt
│ └── main
│ └── kotlin
│ ├── usecases
│ ├── VersionExtractor.kt
│ ├── validation
│ │ ├── UseCaseSyntaxError.kt
│ │ └── Validator.kt
│ ├── features
│ │ ├── Events.kt
│ │ └── Prompts.kt
│ └── UseCaseIdExtractor.kt
│ ├── events
│ └── UseCaseEvents.kt
│ ├── extensions
│ ├── LoadedUseCases.kt
│ └── UseCaseLoader.kt
│ ├── ConversationClassifications.kt
│ └── filters
│ ├── UnresolvedDetector.kt
│ └── ReturnUseCaseIdFilter.kt
├── arc-langchain4j-client
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── services
│ │ │ └── org.eclipse.lmos.arc.agents.llm.CompleterLoaderService
│ │ └── kotlin
│ │ ├── loaders
│ │ ├── OllamaClientLoader.kt
│ │ ├── GeminiClientLoader.kt
│ │ ├── GroqClientLoader.kt
│ │ └── BedrockClientLoader.kt
│ │ └── builders
│ │ ├── OllamaBuilder.kt
│ │ └── GroqBuilder.kt
└── build.gradle.kts
├── .github
├── workflows
│ ├── ci.yml
│ ├── ci-main.yml
│ └── release.yml
└── dependabot.yml
├── arc-memory-redis
├── src
│ ├── main
│ │ └── kotlin
│ │ │ └── MemoryEntry.kt
│ └── test
│ │ └── kotlin
│ │ └── TestBase.kt
└── build.gradle.kts
├── examples
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── log4j.properties
│ │ └── kotlin
│ │ │ └── AgentScriptServer.kt
│ └── test
│ │ └── kotlin
│ │ └── McpApplication.kt
├── build.gradle.kts
├── README.md
└── agents
│ └── assistant.agent.kts
├── arc-openai-client
├── src
│ ├── main
│ │ └── kotlin
│ │ │ └── OpenAINativeClientConfig.kt
│ └── test
│ │ └── kotlin
│ │ └── OpenAINativeClientConfigTest.kt
└── build.gradle.kts
├── gradle.properties
├── adl-server
├── src
│ └── main
│ │ └── kotlin
│ │ ├── inbound
│ │ ├── AdlQuery.kt
│ │ └── AdlCompilerMutation.kt
│ │ └── EnvConfig.kt
└── build.gradle.kts
├── arc-gradle-plugin
└── src
│ └── main
│ └── resources
│ ├── FunctionTemplate.kt.txt
│ └── AgentTemplate.kt.txt
├── arc-server
├── src
│ └── main
│ │ └── kotlin
│ │ ├── EnvConfig.kt
│ │ └── Skills.kt
└── build.gradle.kts
├── settings.gradle.kts
└── .gitignore
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/arc-scripting/src/main/resources/META-INF/kotlin/script/templates/org.eclipse.lmos.arc.scripting.agents.ScriptDeps.classname:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/arc-scripting/src/main/resources/META-INF/kotlin/script/templates/org.eclipse.lmos.arc.scripting.functions.ScriptDeps.classname:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/arc-readers/src/test/resources/test.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-readers/src/test/resources/test.pdf
--------------------------------------------------------------------------------
/arc-mcp/src/main/resources/META-INF/services/org.eclipse.lmos.arc.agents.functions.LLMFunctionLoader:
--------------------------------------------------------------------------------
1 | org.eclipse.lmos.arc.mcp.McpToolsByEnvironment
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/version.json:
--------------------------------------------------------------------------------
1 | {"app_name":"arc_view","version":"0.2.0","build_number":"1","package_name":"arc_view"}
--------------------------------------------------------------------------------
/arc-readers/src/test/resources/test.pdf.license:
--------------------------------------------------------------------------------
1 | SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 |
3 | SPDX-License-Identifier: Apache-2.0
4 |
--------------------------------------------------------------------------------
/arc-azure-client/src/main/resources/META-INF/services/org.eclipse.lmos.arc.agents.llm.CompleterLoaderService:
--------------------------------------------------------------------------------
1 | org.eclipse.lmos.arc.client.azure.AzureClientLoader
--------------------------------------------------------------------------------
/arc-agents/src/test/resources/test.txt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | ARC is fun!
--------------------------------------------------------------------------------
/arc-api/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | }
7 |
--------------------------------------------------------------------------------
/adl-kotlin-runner/src/main/resources/META-INF/services/org.eclipse.lmos.arc.assistants.support.usecases.code.CodeBlockRunner:
--------------------------------------------------------------------------------
1 | org.eclipse.lmos.arc.kotlin.runner.KotlinCodeBlockRunner
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-view-spring-boot-starter/src/main/resources/chat/favicon.png
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # This file helps GitHub doing automatic review requests for new PRs.
2 |
3 | # Assign all PRs to the most suitable committer:
4 | /.github/ @pschwager
5 | * @patwlan
6 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-view-spring-boot-starter/src/main/resources/chat/icons/Icon-192.png
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/canvaskit/skwasm.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-view-spring-boot-starter/src/main/resources/chat/canvaskit/skwasm.wasm
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/canvaskit/canvaskit.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-view-spring-boot-starter/src/main/resources/chat/canvaskit/canvaskit.wasm
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/canvaskit/skwasm_heavy.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-view-spring-boot-starter/src/main/resources/chat/canvaskit/skwasm_heavy.wasm
--------------------------------------------------------------------------------
/arc-scripting/src/test/resources/knowledge-source.txt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | This is a file to test init block of arc agents.
--------------------------------------------------------------------------------
/arc-openai-realtime-client/README.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | Work in progress. Mainly used for testing the new OpenAI RealTime API.
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/canvaskit/chromium/canvaskit.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-view-spring-boot-starter/src/main/resources/chat/canvaskit/chromium/canvaskit.wasm
--------------------------------------------------------------------------------
/arc-readers/src/test/resources/test.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
This is a test!
9 |
--------------------------------------------------------------------------------
/arc-result/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | // Logging
7 | implementation(libs.slf4j.api)
8 | }
9 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/assets/fonts/MaterialIcons-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-view-spring-boot-starter/src/main/resources/chat/assets/fonts/MaterialIcons-Regular.otf
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/assets/fonts/static/RobotoMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eclipse-lmos/arc/HEAD/arc-view-spring-boot-starter/src/main/resources/chat/assets/fonts/static/RobotoMono-Regular.ttf
--------------------------------------------------------------------------------
/arc-agents/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | api(project(":arc-result"))
7 | implementation(libs.slf4j.api)
8 | }
9 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/assets/FontManifest.json:
--------------------------------------------------------------------------------
1 | [{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"RobotoMono","fonts":[{"weight":700,"asset":"fonts/static/RobotoMono-Regular.ttf"}]}]
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
--------------------------------------------------------------------------------
/arc-gen/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-result"))
7 | implementation(project(":arc-agents"))
8 | }
9 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/resources/arc.properties:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 |
6 | graphql.packages=org.eclipse.lmos.arc.api,org.eclipse.lmos.arc.graphql.inbound
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: CC0-1.0
4 |
5 | [*.{kt,kts}]
6 | ktlint_code_style = intellij_idea
7 | ktlint_standard_filename = disabled
8 | ktlint_standard_no-wildcard-imports = disabled
9 |
--------------------------------------------------------------------------------
/arc-streaming-spring-boot-starter/README.md:
--------------------------------------------------------------------------------
1 |
6 | # Arc Streaming Spring Boot Starter
7 |
8 | Work in progress. Mainly used for testing the new OpenAI RealTime API.
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | org.eclipse.lmos.arc.spring.ArcAutoConfiguration
5 |
--------------------------------------------------------------------------------
/arc-agent-client/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | server:
6 | port: 8083
7 |
8 | logging:
9 | level:
10 | root: WARN
11 | org.eclipse.lmos.arc: DEBUG
12 |
--------------------------------------------------------------------------------
/arc-openai-realtime-client/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | server:
6 | port: 8080
7 |
8 | logging:
9 | level:
10 | root: DEBUG
11 | org.eclipse.lmos.arc: DEBUG
12 |
--------------------------------------------------------------------------------
/arc-streaming-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | org.eclipse.lmos.arc.ws.AgentStreamingAutoConfiguration
5 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | org.eclipse.lmos.arc.view.ArcViewAutoConfiguration
5 |
--------------------------------------------------------------------------------
/arc-api/src/main/kotlin/RequestEnd.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.api
6 |
7 | /**
8 | * Indicates the end of a request.
9 | */
10 | const val REQUEST_END = ""
11 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | org.eclipse.lmos.arc.graphql.AgentGraphQLAutoConfiguration
5 |
--------------------------------------------------------------------------------
/arc-memory-mongo-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | org.eclipse.lmos.arc.memory.mongo.MemoryAutoConfiguration
5 |
--------------------------------------------------------------------------------
/arc-openai-api-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | org.eclipse.lmos.arc.openai.api.ArcOpenAIApiAutoConfiguration
5 |
--------------------------------------------------------------------------------
/arc-mcp/README.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | # MCP - Model Context Protocol (WIP)
8 |
9 | This projects enables the integration of MCP (Model Context Protocol) resources, such as Tools and Prompts, into the Arc
10 | Framework.
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/User.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents
6 |
7 | import kotlinx.serialization.Serializable
8 |
9 | /**
10 | * A user.
11 | */
12 | @Serializable
13 | class User(val id: String)
14 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/assets/AssetManifest.json:
--------------------------------------------------------------------------------
1 | {"LICENSES/Apache-2.0.txt":["LICENSES/Apache-2.0.txt"],"assets/config/app-config.yaml":["assets/config/app-config.yaml"],"assets/lmos.svg":["assets/lmos.svg"],"fonts/LICENSE.txt":["fonts/LICENSE.txt"],"fonts/static/RobotoMono-Regular.ttf":["fonts/static/RobotoMono-Regular.ttf"]}
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/events/EventListener.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.events
6 |
7 | /**
8 | * EventHandler interface.
9 | */
10 | interface EventHandler {
11 | fun onEvent(event: T)
12 | }
13 |
--------------------------------------------------------------------------------
/arc-runner/src/main/kotlin/server/Config.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.runner.server
6 |
7 | import java.io.File
8 |
9 | data class AppConfig(
10 | val clientConfig: AIClientConfig,
11 | val scriptFolder: File,
12 | )
13 |
--------------------------------------------------------------------------------
/arc-assistants/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | api(project(":arc-result"))
7 | api(project(":arc-agents"))
8 | implementation("org.slf4j:slf4j-api:2.0.17")
9 |
10 | testImplementation(project(":adl-kotlin-runner"))
11 | }
12 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/test/kotlin/TestApplication.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.view
6 |
7 | import org.springframework.boot.autoconfigure.SpringBootApplication
8 |
9 | @SpringBootApplication
10 | open class TestApplication
11 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/kotlin/clients/TestApplication.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.clients
6 |
7 | import org.springframework.boot.autoconfigure.SpringBootApplication
8 |
9 | @SpringBootApplication
10 | open class TestApplication
11 |
--------------------------------------------------------------------------------
/arc-api/src/main/kotlin/AnonymizationEntity.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.api
6 |
7 | import kotlinx.serialization.Serializable
8 |
9 | @Serializable
10 | data class AnonymizationEntity(val type: String, val value: String, val replacement: String)
11 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | logging:
6 | level:
7 | root: INFO
8 | org.eclipse.lmos.ai: DEBUG
9 |
10 | server:
11 | port: 8080
12 |
13 | arc:
14 | subscriptions:
15 | events:
16 | enable: true
--------------------------------------------------------------------------------
/arc-langchain4j-client/src/main/resources/META-INF/services/org.eclipse.lmos.arc.agents.llm.CompleterLoaderService:
--------------------------------------------------------------------------------
1 | org.eclipse.lmos.arc.client.langchain4j.loaders.OllamaClientLoader
2 | org.eclipse.lmos.arc.client.langchain4j.loaders.GeminiClientLoader
3 | org.eclipse.lmos.arc.client.langchain4j.loaders.GroqClientLoader
4 | org.eclipse.lmos.arc.client.langchain4j.loaders.BedrockClientLoader
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/assets/AssetManifest.bin:
--------------------------------------------------------------------------------
1 |
LICENSES/Apache-2.0.txt
assetLICENSES/Apache-2.0.txtassets/config/app-config.yaml
assetassets/config/app-config.yamlassets/lmos.svg
assetassets/lmos.svgfonts/LICENSE.txt
assetfonts/LICENSE.txt#fonts/static/RobotoMono-Regular.ttf
asset#fonts/static/RobotoMono-Regular.ttf
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | name: CI
6 |
7 | on:
8 | push:
9 | branches-ignore:
10 | - 'main'
11 | pull_request:
12 |
13 | jobs:
14 | CI:
15 | uses: eclipse-lmos/.github/.github/workflows/gradle-ci.yml@main
16 | permissions:
17 | contents: read
18 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/Tools.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl
6 |
7 | /**
8 | * Magic value for the tools field to include all tools that are available.
9 | */
10 | object AllTools : List by listOf("*") {
11 | val symbol get() = first()
12 | }
13 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/ConversationAgent.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents
5 |
6 | import org.eclipse.lmos.arc.agents.conversation.Conversation
7 |
8 | /**
9 | * A conversational agent interface.
10 | */
11 | interface ConversationAgent : Agent
12 |
--------------------------------------------------------------------------------
/arc-gen/src/main/kotlin/Agents.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | @file:Suppress("ktlint")
5 |
6 | package org.eclipse.lmos.arc.agents.gen
7 |
8 | import org.eclipse.lmos.arc.agents.dsl.AgentDefinitionContext
9 |
10 | class Agents {
11 |
12 | fun build(context: AgentDefinitionContext) {
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/arc-memory-redis/src/main/kotlin/MemoryEntry.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.memory.redis
6 |
7 | /**
8 | * Entry in memory.
9 | */
10 | data class MemoryEntry(val value: T)
11 |
12 | data class MemoryKey(val owner: String, val key: String, val sessionId: String? = null)
13 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/resources/agents/subfolder/travel.functions.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
3 | * //
4 | * // SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | function(
8 | name = "get_travel_info",
9 | description = "Returns travel information",
10 | ) {
11 | """
12 | There are many hotels available.
13 | """
14 | }
--------------------------------------------------------------------------------
/arc-assistants/src/test/resources/use_cases_steps.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | ### UseCase: usecase1
8 | #### Description
9 | The description of the use case 1.
10 |
11 | #### Solution
12 | No step
13 | Step1
14 | Step2
15 |
16 | Step3
17 | >
18 | Step4
19 |
20 | ----
21 |
--------------------------------------------------------------------------------
/arc-gen/src/main/kotlin/Functions.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | @file:Suppress("ktlint")
5 |
6 | package org.eclipse.lmos.arc.agents.gen
7 |
8 | import org.eclipse.lmos.arc.agents.dsl.FunctionDefinitionContext
9 |
10 | class Functions {
11 |
12 | fun build(context: FunctionDefinitionContext) {
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | version: 2
6 | updates:
7 | - package-ecosystem: "gradle"
8 | directory: "/"
9 | open-pull-requests-limit: 10
10 | schedule:
11 | interval: "daily"
12 | - package-ecosystem: "github-actions"
13 | directory: "/"
14 | schedule:
15 | interval: "daily"
--------------------------------------------------------------------------------
/arc-scripting/src/test/kotlin/Testing.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.scripting
6 |
7 | /**
8 | * Reads a script from the resource folder.
9 | */
10 | fun readScript(name: String) = Thread.currentThread().contextClassLoader.getResourceAsStream(name).use {
11 | String(it!!.readAllBytes())
12 | }
13 |
--------------------------------------------------------------------------------
/arc-runner/src/test/kotlin/RunTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.runner
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.junit.jupiter.api.Test
9 |
10 | class RunTest {
11 |
12 | @Test
13 | fun `test run command`(): Unit = runBlocking {
14 | // RunArc().run()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/arc-scripting/src/main/kotlin/Exceptions.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.scripting
6 |
7 | /**
8 | * Thrown when a script fails to execute. This can be due to syntax errors or runtime exceptions.
9 | */
10 | class ScriptFailedException(reason: String) : Exception("Failed to execute script! Reason:[$reason]")
11 |
--------------------------------------------------------------------------------
/arc-api/src/main/kotlin/RequestEnvelope.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.api
6 |
7 | import kotlinx.serialization.Serializable
8 |
9 | /**
10 | * Combines the agent name and the request into a single data type.
11 | */
12 | @Serializable
13 | data class RequestEnvelope(val agentName: String?, val payload: AgentRequest)
14 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/usecases/VersionExtractor.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.usecases
6 |
7 | fun extractVersion(message: String): String? {
8 | val versionRegex = "".toRegex(RegexOption.IGNORE_CASE)
9 | return versionRegex.find(message)?.groupValues?.elementAtOrNull(1)?.trim()
10 | }
11 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/ErrorHandler.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.AssistantMessage
8 | import org.eclipse.lmos.arc.core.Result
9 |
10 | interface ErrorHandler {
11 |
12 | fun handleError(e: Exception): Result
13 | }
14 |
--------------------------------------------------------------------------------
/arc-readers/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-result"))
7 | implementation(project(":arc-agents"))
8 |
9 | // Logging
10 | implementation(libs.slf4j.api)
11 |
12 | // jsoup
13 | implementation("org.jsoup:jsoup:1.21.1")
14 | implementation("org.apache.pdfbox:pdfbox:3.0.6")
15 | }
16 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/resources/agents/subfolder/travel.agent.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | agent {
6 | name = "travel-agent"
7 | description = "Agent that helps customer with their travel plans."
8 | systemPrompt = {
9 | """
10 | You are a travel agent. You help customers with their travel plans.
11 | """
12 | }
13 | }
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/kotlin/TestEvent.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.spring
6 |
7 | import org.eclipse.lmos.arc.agents.events.BaseEvent
8 | import org.eclipse.lmos.arc.agents.events.Event
9 | import java.time.Instant
10 |
11 | class TestEvent : Event by BaseEvent() {
12 | override val timestamp: Instant = Instant.now()
13 | }
14 |
--------------------------------------------------------------------------------
/arc-openai-api-spring-boot-starter/src/test/kotlin/TestEvent.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.spring
6 |
7 | import org.eclipse.lmos.arc.agents.events.BaseEvent
8 | import org.eclipse.lmos.arc.agents.events.Event
9 | import java.time.Instant
10 |
11 | class TestEvent : Event by BaseEvent() {
12 | override val timestamp: Instant = Instant.now()
13 | }
14 |
--------------------------------------------------------------------------------
/arc-scripting/src/main/kotlin/agents/CompiledAgentLoader.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.scripting.agents
6 |
7 | import org.eclipse.lmos.arc.agents.dsl.AgentDefinitionContext
8 |
9 | /**
10 | * Interface for loading compiled agents.
11 | */
12 | interface CompiledAgentLoader {
13 |
14 | fun load(agentDefinitionContext: AgentDefinitionContext)
15 | }
16 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/assets/AssetManifest.bin.json:
--------------------------------------------------------------------------------
1 | "DQUHF0xJQ0VOU0VTL0FwYWNoZS0yLjAudHh0DAENAQcFYXNzZXQHF0xJQ0VOU0VTL0FwYWNoZS0yLjAudHh0Bx1hc3NldHMvY29uZmlnL2FwcC1jb25maWcueWFtbAwBDQEHBWFzc2V0Bx1hc3NldHMvY29uZmlnL2FwcC1jb25maWcueWFtbAcPYXNzZXRzL2xtb3Muc3ZnDAENAQcFYXNzZXQHD2Fzc2V0cy9sbW9zLnN2ZwcRZm9udHMvTElDRU5TRS50eHQMAQ0BBwVhc3NldAcRZm9udHMvTElDRU5TRS50eHQHI2ZvbnRzL3N0YXRpYy9Sb2JvdG9Nb25vLVJlZ3VsYXIudHRmDAENAQcFYXNzZXQHI2ZvbnRzL3N0YXRpYy9Sb2JvdG9Nb25vLVJlZ3VsYXIudHRm"
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/llm/TextCompleterProvider.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.llm
6 |
7 | /**
8 | * Provides TextEmbedder based on their model name.
9 | * TextEmbedderProviders must provide a default TextEmbedder if no model is explicitly defined.
10 | */
11 | fun interface TextEmbedderProvider {
12 |
13 | fun provideByModel(model: String?): TextEmbedder
14 | }
15 |
--------------------------------------------------------------------------------
/examples/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | # Root Logger
5 | log4j.rootLogger=INFO, stdout
6 |
7 | # Direct log messages to stdout
8 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
9 | log4j.appender.stdout.Target=System.out
10 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
11 | log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
--------------------------------------------------------------------------------
/arc-mcp/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | spring:
6 | jackson:
7 | default-property-inclusion: NON_NULL
8 | main:
9 | banner-mode: off
10 | web-application-type: reactive
11 | reactor:
12 | context-propagation: auto
13 | threads:
14 | virtual:
15 | enabled: true
16 |
17 | server:
18 | shutdown: immediate
19 |
20 | arc:
21 | mcp:
22 | tools:
23 | expose: true
--------------------------------------------------------------------------------
/arc-openai-client/src/main/kotlin/OpenAINativeClientConfig.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.client.openai
6 |
7 | data class OpenAINativeClientConfig(
8 | val modelName: String,
9 | val url: String,
10 | val apiKey: String,
11 | ) {
12 |
13 | override fun toString(): String {
14 | return "OpenAINativeClientConfig(modelName=$modelName, url=$url, apiKey=***)"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/adl-kotlin-runner/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-assistants"))
7 | implementation(project(":arc-result"))
8 | implementation("org.jetbrains.kotlin:kotlin-scripting-common")
9 | implementation("org.jetbrains.kotlin:kotlin-scripting-jvm")
10 | implementation("org.jetbrains.kotlin:kotlin-scripting-jvm-host")
11 | implementation(libs.slf4j.api)
12 | }
13 |
--------------------------------------------------------------------------------
/arc-openai-realtime-client/src/main/kotlin/WavData.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agent.client.ws
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.BinaryData
8 | import org.eclipse.lmos.arc.agents.conversation.DataStream
9 |
10 | /**
11 | * Creates a [BinaryData] object with the given wav audio data.
12 | */
13 | fun wavData(audio: DataStream) = BinaryData(mimeType = "audio/wav", stream = audio)
14 |
--------------------------------------------------------------------------------
/arc-scripting/src/main/kotlin/agents/Events.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.scripting.agents
6 |
7 | import org.eclipse.lmos.arc.agents.events.BaseEvent
8 | import org.eclipse.lmos.arc.agents.events.Event
9 |
10 | /**
11 | * Events published when an agent is loaded.
12 | */
13 | data class AgentLoadedEvent(
14 | val name: String,
15 | val errorMessage: String? = null,
16 | ) : Event by BaseEvent()
17 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | ##
3 | ## SPDX-License-Identifier: Apache-2.0
4 |
5 | kotlin.code.style=official
6 | org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx6096M
7 | org.gradle.caching=true
8 | org.gradle.daemon=true
9 | org.gradle.parallel=false
10 | org.gradle.dependency.verification=lenient
11 | # Experimental
12 | #org.gradle.configuration-cache=true
13 | #org.gradle.configuration-cache.problems=warn
14 | org.gradle.configureondemand=true
15 | version=0.208.0-SNAPSHOT
16 |
--------------------------------------------------------------------------------
/arc-scripting/src/main/kotlin/functions/Events.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.scripting.functions
6 |
7 | import org.eclipse.lmos.arc.agents.events.BaseEvent
8 | import org.eclipse.lmos.arc.agents.events.Event
9 |
10 | /**
11 | * Events published when a function is loaded.
12 | */
13 | data class FunctionLoadedEvent(
14 | val name: String,
15 | val errorMessage: String? = null,
16 | ) : Event by BaseEvent()
17 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/kotlin/gen/Agents.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | @file:Suppress("ktlint")
5 |
6 | package org.eclipse.lmos.arc.agents.gen
7 |
8 | import org.eclipse.lmos.arc.agents.dsl.AgentDefinitionContext
9 |
10 | class Agents {
11 |
12 | fun build(context: AgentDefinitionContext) {
13 | with(context) {
14 | agent {
15 | name = "weather-gen"
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/usecases/validation/UseCaseSyntaxError.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.assistants.support.usecases.validation
5 |
6 | import kotlinx.serialization.Serializable
7 |
8 | @Serializable
9 | data class UseCaseSyntaxError(
10 | override val code: String = "SYNTAX_ERROR",
11 | override val useCases: List = emptyList(),
12 | override val message: String,
13 | ) : UseCaseValidationError
14 |
--------------------------------------------------------------------------------
/arc-openai-client/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-result"))
7 | implementation(project(":arc-agents"))
8 |
9 | // Logging
10 | implementation("org.slf4j:slf4j-api:2.0.17")
11 | implementation("com.squareup.okhttp3:okhttp:5.3.2")
12 | implementation("com.squareup.okhttp3:logging-interceptor:5.3.2")
13 |
14 | // OpenAISDK
15 | api("com.openai:openai-java:0.34.1")
16 | }
17 |
--------------------------------------------------------------------------------
/adl-server/src/main/kotlin/inbound/AdlQuery.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.adl.server.inbound
6 |
7 | import com.expediagroup.graphql.generator.annotations.GraphQLDescription
8 | import com.expediagroup.graphql.server.operations.Query
9 |
10 | class AdlQuery : Query {
11 |
12 | @GraphQLDescription("Returns the supported version of the ALD.")
13 | fun version(adlCode: AdlSource): String {
14 | return "!.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/AgentResolver.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql
6 |
7 | import org.eclipse.lmos.arc.agents.Agent
8 | import org.eclipse.lmos.arc.api.AgentRequest
9 |
10 | /**
11 | * Resolves the agent for the given request.
12 | * Returns null if no agent is found.
13 | */
14 | interface AgentResolver {
15 |
16 | fun resolveAgent(agentName: String? = null, request: AgentRequest): Agent<*, *>?
17 | }
18 |
--------------------------------------------------------------------------------
/arc-memory-redis/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | api(project(":arc-result"))
7 | api(project(":arc-agents"))
8 |
9 | implementation(libs.redis.lettuce)
10 | implementation(libs.slf4j.api)
11 | implementation(libs.jackson.kotlin)
12 | implementation(libs.jackson.databind)
13 |
14 | testImplementation("com.redis:testcontainers-redis:2.2.4")
15 | testImplementation("org.testcontainers:junit-jupiter:1.20.4")
16 | }
17 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/agent/Skill.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.agent
5 |
6 | /**
7 | * Represents a skill that an agent can perform.
8 | */
9 | data class Skill(
10 | val id: String,
11 | val name: String,
12 | val description: String? = null,
13 | val tags: List? = null,
14 | val examples: List? = null,
15 | val inputModes: List? = null,
16 | val outputModes: List? = null,
17 | )
18 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/usecases/validation/Validator.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.assistants.support.usecases.validation
5 |
6 | import org.eclipse.lmos.arc.assistants.support.usecases.UseCase
7 |
8 | interface UseCaseValidator {
9 |
10 | fun validate(useCases: List): UseCaseValidationError?
11 | }
12 |
13 | sealed interface UseCaseValidationError {
14 | val message: String
15 | val code: String
16 | val useCases: List
17 | }
18 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-assistants"))
7 | implementation("org.springframework.boot:spring-boot-autoconfigure:3.4.4")
8 | implementation("org.springframework.boot:spring-boot-configuration-processor:3.4.4")
9 | implementation("org.springframework.boot:spring-boot-starter-webflux:3.5.0")
10 |
11 | testImplementation("org.springframework.boot:spring-boot-starter-test:3.5.0")
12 | }
13 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/functions/FunctionWithContext.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.functions
6 |
7 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
8 |
9 | /**
10 | * Tags a function that requires a DSLContext to be executed.
11 | */
12 | interface FunctionWithContext {
13 |
14 | /**
15 | * Returns a new instance of the function that executes with the given context.
16 | */
17 | fun withContext(context: DSLContext): LLMFunction
18 | }
19 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/events/LoggingEventHandler.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.events
6 |
7 | import org.slf4j.LoggerFactory
8 |
9 | /**
10 | * Handles events generated by Agents.
11 | * Mainly used for logging purposes.
12 | */
13 | class LoggingEventHandler : EventHandler {
14 |
15 | private val log = LoggerFactory.getLogger(javaClass)
16 |
17 | override fun onEvent(event: Event) {
18 | log.debug("Event published: $event")
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/arc-mcp/src/test/kotlin/TestBase.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.mcp
5 |
6 | import org.junit.jupiter.api.TestInstance
7 | import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
8 | import org.springframework.boot.test.context.SpringBootTest
9 | import org.springframework.test.context.ActiveProfiles
10 |
11 | @SpringBootTest(
12 | webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
13 | )
14 | @ActiveProfiles("test")
15 | @TestInstance(PER_CLASS)
16 | open class TestBase
17 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/events/UseCaseEvents.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.events
6 |
7 | import org.eclipse.lmos.arc.agents.events.BaseEvent
8 | import org.eclipse.lmos.arc.agents.events.Event
9 |
10 | /**
11 | * Emitted when a use case was triggered.
12 | */
13 | data class UseCaseEvent(
14 | val name: String,
15 | val step: String? = null,
16 | val version: String? = null,
17 | val description: String? = null,
18 | ) : Event by BaseEvent()
19 |
--------------------------------------------------------------------------------
/arc-gradle-plugin/src/main/resources/FunctionTemplate.kt.txt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | @file:Suppress("ktlint")
5 | package org.eclipse.lmos.arc.agents.gen
6 |
7 | //@@IMPORTS@@
8 | import org.eclipse.lmos.arc.agents.dsl.*
9 | import org.eclipse.lmos.arc.agents.dsl.extensions.*
10 | import org.eclipse.lmos.arc.core.*
11 |
12 | class Functions {
13 |
14 | fun build(context: FunctionDefinitionContext) {
15 | with(context) {
16 | //@@CODE@@
17 | }
18 | }
19 |
20 | //@@OUTER_CODE@@
21 | }
22 |
--------------------------------------------------------------------------------
/arc-openai-realtime-client/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-result"))
7 | implementation(project(":arc-agents"))
8 |
9 | implementation(libs.ktor.client.websockets)
10 | implementation(libs.ktor.client.cio.jvm)
11 | implementation(libs.ktor.serialization.kotlinx.json)
12 | implementation(libs.ktor.client.core)
13 |
14 | testImplementation(libs.spring.boot.starter.test)
15 | testImplementation(libs.spring.boot.starter)
16 | }
17 |
--------------------------------------------------------------------------------
/arc-streaming-spring-boot-starter/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | spring:
6 | jackson:
7 | default-property-inclusion: NON_NULL
8 | main:
9 | banner-mode: off
10 | web-application-type: reactive
11 | reactor:
12 | context-propagation: auto
13 | graphql:
14 | graphiql:
15 | enabled: true
16 |
17 | logging:
18 | level:
19 | root: INFO
20 | org.eclipse.lmos.arc: DEBUG
21 |
22 | server:
23 | port: 8080
24 |
25 | arc:
26 | subscriptions:
27 | events:
28 | enable: true
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/tracing/GenerateResponseTagger.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.tracing
5 |
6 | import org.eclipse.lmos.arc.agents.conversation.AssistantMessage
7 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
8 |
9 | /**
10 | * Interface for adding tags to the "generated response" span.
11 | * Simple add any implementation to the context of the agent.
12 | */
13 | interface GenerateResponseTagger {
14 |
15 | fun tag(tags: Tags, outputMessage: AssistantMessage, dslContext: DSLContext)
16 | }
17 |
--------------------------------------------------------------------------------
/arc-azure-client/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | plugins {
6 | id("sh.ondr.koja") version "0.4.6"
7 | }
8 |
9 | dependencies {
10 | implementation(project(":arc-result"))
11 | implementation(project(":arc-agents"))
12 |
13 | // Logging
14 | implementation(libs.slf4j.api)
15 |
16 | // Azure
17 | api("com.azure:azure-ai-openai:1.0.0-beta.16")
18 | api("com.azure:azure-core-tracing-opentelemetry:1.0.0-beta.56")
19 | implementation("com.azure:azure-identity:1.15.4")
20 |
21 | // Tests
22 | testImplementation(libs.slf4j.jdk14)
23 | }
24 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/extensions/Trace.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl.extensions
6 |
7 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
8 | import org.eclipse.lmos.arc.agents.dsl.getOptional
9 | import org.eclipse.lmos.arc.agents.tracing.AgentTracer
10 | import org.eclipse.lmos.arc.agents.tracing.DefaultAgentTracer
11 |
12 | /**
13 | * Returns the AgentTracer from the context or a default implementation.
14 | */
15 | suspend fun DSLContext.tracer(): AgentTracer {
16 | return getOptional() ?: DefaultAgentTracer()
17 | }
18 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/resources/use_cases_out.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | ### UseCase: usecase1
8 | #### Description
9 | The description of the use case 1.
10 |
11 | #### Steps
12 | - Step one of the use case 1.
13 |
14 | #### Solution
15 | Solution
16 |
17 | ----
18 |
19 | ### UseCase: usecase2
20 | #### Description
21 | The description of the use case 2.
22 |
23 | #### Solution
24 | Primary Solution
25 |
26 | ----
27 |
28 | ### UseCase: usecase3
29 | #### Description
30 | The description of the use case 3.
31 |
32 | #### Solution
33 | Solution for use case 3
34 |
35 | ----
36 |
--------------------------------------------------------------------------------
/arc-agents/src/test/kotlin/dsl/Filters.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
8 |
9 | class NumberFilter : AgentFilter {
10 | override suspend fun filter(m: ConversationMessage): ConversationMessage {
11 | return m.update(m.content.replace("1234", "NUMBER"))
12 | }
13 | }
14 |
15 | class DateFilter : AgentFilter {
16 | override suspend fun filter(m: ConversationMessage): ConversationMessage {
17 | return m.update(m.content.replace("01.01.2024", "DATE"))
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/arc-mcp/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-result"))
7 | implementation(project(":arc-agents"))
8 |
9 | // Logging
10 | implementation("org.slf4j:slf4j-api:2.0.17")
11 |
12 | // MCP
13 | implementation(libs.mcp.sdk)
14 |
15 | // Test
16 | testImplementation(project(":arc-spring-boot-starter"))
17 | testImplementation(libs.spring.ai.starter.mcp.server.webflux)
18 | testImplementation(libs.spring.boot.starter.webflux)
19 | testImplementation("org.springframework.boot:spring-boot-starter-test:3.5.0")
20 | }
21 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/extensions/LoadedUseCases.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.extensions
6 |
7 | import org.eclipse.lmos.arc.assistants.support.usecases.UseCase
8 |
9 | /**
10 | * Local variables stored by the Use Case extensions.
11 | */
12 | data class LoadedUseCases(
13 | val name: String,
14 | val useCases: List,
15 | val usedUseCases: List,
16 | val processedUseCases: String,
17 | val processedUseCaseMap: Map,
18 | val currentStep: String? = null,
19 | val currentUseCaseId: String? = null,
20 | )
21 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/LogContext.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents
6 |
7 | import kotlinx.coroutines.slf4j.MDCContext
8 | import kotlinx.coroutines.withContext
9 | import org.slf4j.MDC
10 |
11 | /**
12 | * Add values to the log context.
13 | */
14 | suspend fun withLogContext(
15 | map: Map,
16 | block: suspend kotlinx.coroutines.CoroutineScope.() -> T,
17 | ): T {
18 | return withContext(MDCContext(logContext() + map), block)
19 | }
20 |
21 | /**
22 | * Returns the current log context.
23 | */
24 | fun logContext() = MDC.getCopyOfContextMap() ?: emptyMap()
25 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/resources/use_cases_mobile.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | ### UseCase: usecase1
8 | #### Description
9 | The description of the use case 1.
10 |
11 | #### Steps
12 | - Step one of the use case 1.
13 |
14 | #### Solution
15 | Solution
16 |
17 | ----
18 |
19 | ### UseCase: usecase2
20 | #### Description
21 | The description of the use case 2.
22 |
23 | #### Solution
24 | Primary Solution
25 |
26 | ----
27 |
28 | ### UseCase: usecase3
29 | #### Description
30 | The description of the use case 3.
31 |
32 | #### Solution
33 | Solution for use case 3
34 | The mobile solution for use case 3
35 |
36 | ----
37 |
--------------------------------------------------------------------------------
/arc-openai-api-spring-boot-starter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | api(project(":arc-result"))
7 | api(project(":arc-agents"))
8 | api(project(":arc-api"))
9 | implementation(libs.spring.boot.starter)
10 | implementation(libs.spring.boot.autoconfigure)
11 | implementation(libs.spring.boot.configuration.processor)
12 | implementation(libs.spring.boot.starter.webflux)
13 |
14 | // Tests
15 | testImplementation(project(":arc-spring-boot-starter"))
16 | testImplementation(libs.spring.boot.starter.test)
17 | testImplementation("dev.langchain4j:langchain4j-open-ai:1.0.1")
18 | }
19 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Arc View",
3 | "short_name": "arc_view",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "The Arc Chat UI.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-192.png",
19 | "sizes": "192x192",
20 | "type": "image/png",
21 | "purpose": "maskable"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/test/kotlin/NoFeatureTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql
6 |
7 | import features.FeatureAgentResolver
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.junit.jupiter.api.Test
10 | import org.springframework.beans.factory.annotation.Autowired
11 | import org.springframework.boot.test.context.SpringBootTest
12 |
13 | @SpringBootTest
14 | class NoFeatureTest {
15 |
16 | @Autowired
17 | var agentResolver: FeatureAgentResolver? = null
18 |
19 | @Test
20 | fun `test FeatureAgentResolver is not defined`() {
21 | assertThat(agentResolver).isNull()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/arc-runner/src/main/kotlin/List.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.runner
6 |
7 | import picocli.CommandLine.Command
8 |
9 | @Command(
10 | name = "list",
11 | mixinStandardHelpOptions = true,
12 | description = ["Lists the Agents that are installed in HOME."],
13 | )
14 | class ListAgents : Runnable {
15 |
16 | override fun run() {
17 | println("The following Agents are installed:")
18 | home().listFiles()?.forEach { file ->
19 | if (file.getName().endsWith(".agent.kts")) {
20 | println("- " + file.getName().replace(".agent.kts", ""))
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/arc-scripting/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-result"))
7 | implementation(project(":arc-agents"))
8 |
9 | // Logging
10 | implementation("org.slf4j:slf4j-api:2.0.17")
11 |
12 | // Kotlin Scripting
13 | implementation("org.jetbrains.kotlin:kotlin-scripting-common:2.2.21")
14 | implementation("org.jetbrains.kotlin:kotlin-scripting-jvm:2.2.21")
15 | implementation("org.jetbrains.kotlin:kotlin-scripting-jvm-host:2.2.21")
16 | // implementation("org.jetbrains.kotlin:kotlin-scripting-dependencies")
17 | // implementation("org.jetbrains.kotlin:kotlin-scripting-dependencies-maven")
18 | }
19 |
--------------------------------------------------------------------------------
/arc-scripting/src/test/resources/weather.functions.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
3 | * //
4 | * // SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * My weather function.
9 | */
10 | function(
11 | name = "get_weather",
12 | description = "Returns real-time weather information for any location",
13 | params = types(string("location", "a city to obtain the weather for."))
14 | ) { (location) ->
15 | """
16 | The weather is good in $location. It is 20 degrees celsius.
17 | """
18 | }
19 |
20 | function(
21 | name = "get_forecast",
22 | description = "Returns real-time weather forecast",
23 | ) { """
24 | The next 4 days will be full of sun!
25 | """
26 | }
27 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/inbound/EventSerializer.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.graphql.inbound
5 |
6 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
7 | import com.fasterxml.jackson.module.kotlin.KotlinFeature.UseJavaDurationConversion
8 | import com.fasterxml.jackson.module.kotlin.jacksonMapperBuilder
9 | import org.eclipse.lmos.arc.agents.events.Event
10 |
11 | private val eventObjectMapper = jacksonMapperBuilder {
12 | enable(UseJavaDurationConversion)
13 | }.addModule(JavaTimeModule()).build()
14 |
15 | /**
16 | * Serialize an Event to JSON.
17 | */
18 | fun Event.toJson(): String = eventObjectMapper.writeValueAsString(this)
19 |
--------------------------------------------------------------------------------
/arc-openai-client/src/test/kotlin/OpenAINativeClientConfigTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.client.openai
6 |
7 | import org.junit.jupiter.api.Assertions.assertEquals
8 | import org.junit.jupiter.api.Test
9 |
10 | class OpenAINativeClientConfigTest {
11 |
12 | @Test
13 | fun testToString() {
14 | val config = OpenAINativeClientConfig(
15 | modelName = "test-model",
16 | url = "http://test-url",
17 | apiKey = "test-api-key",
18 | )
19 | val expected = "OpenAINativeClientConfig(modelName=test-model, url=http://test-url, apiKey=***)"
20 | assertEquals(expected, config.toString())
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/resources/agents/weather.functions.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
3 | * //
4 | * // SPDX-License-Identifier: Apache-2.0
5 | */
6 |
7 | /**
8 | * My weather function.
9 | */
10 | function(
11 | name = "get_weather",
12 | description = "Returns real-time weather information for any location",
13 | params = types(string("location", "a city to obtain the weather for."))
14 | ) { (location) ->
15 | """
16 | The weather is good in $location. It is 20 degrees celsius.
17 | """
18 | }
19 |
20 | function(
21 | name = "get_forecast",
22 | description = "Returns real-time weather forecast",
23 | ) { """
24 | The next 4 days will be full of sun!
25 | """
26 | }
27 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/usecases/features/Events.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.assistants.support.usecases.features
5 |
6 | import org.eclipse.lmos.arc.agents.events.BaseEvent
7 | import org.eclipse.lmos.arc.agents.events.Event
8 | import org.eclipse.lmos.arc.assistants.support.usecases.FlowOption
9 | import org.eclipse.lmos.arc.assistants.support.usecases.FlowOptions
10 | import java.time.Instant
11 |
12 | data class FlowOptionEvent(
13 | val useCaseId: String,
14 | val matchedOption: FlowOption,
15 | val flowOptions: FlowOptions,
16 | val referenceUseCase: String? = null,
17 | override val timestamp: Instant = Instant.now(),
18 | ) : Event by BaseEvent()
19 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/main/kotlin/AIConfig.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.spring
6 |
7 | import org.springframework.boot.context.properties.ConfigurationProperties
8 |
9 | /**
10 | * Simple setup for loading configuration properties.
11 | */
12 | @ConfigurationProperties(prefix = "arc.ai")
13 | data class AIConfig(val clients: List)
14 |
15 | data class AIClientConfig(
16 | val id: String,
17 | val client: String,
18 | val modelName: String,
19 | val url: String? = null,
20 | val apiKey: String? = null,
21 | val accessKey: String? = null,
22 | val accessSecret: String? = null,
23 | val toolSupported: Boolean = false,
24 | )
25 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/router/RouterEvents.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.router
6 |
7 | import org.eclipse.lmos.arc.agents.events.BaseEvent
8 | import org.eclipse.lmos.arc.agents.events.Event
9 | import java.time.Instant
10 | import kotlin.time.Duration
11 |
12 | /**
13 | * Events published by the LLM clients.
14 | */
15 |
16 | data class RouterReadyEvent(
17 | override val timestamp: Instant = Instant.now(),
18 | ) : Event by BaseEvent()
19 |
20 | data class RouterRoutedEvent(
21 | val request: String,
22 | val destination: Destination?,
23 | val duration: Duration,
24 | override val timestamp: Instant = Instant.now(),
25 | ) : Event by BaseEvent()
26 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | arc:
5 | scripts:
6 | folder: src/test/resources/agents
7 | hotReload:
8 | enable: true
9 | delay: PT1S
10 | router:
11 | enable: true
12 | model: "llama3:8b"
13 | ai:
14 | clients:
15 | - id: GPT-4o
16 | client: azure
17 | url: https://openai.azure.com/
18 | modelName: gpt-4o
19 | - id: llama3.3
20 | modelName: llama3.3
21 | client: ollama
22 | - id: GPT-4o-mini
23 | modelName: gpt-4o-mini
24 | api-key: 12345
25 | client: openai
26 |
27 | logging:
28 | level:
29 | root: WARN
30 | org.eclipse.lmos.ai: DEBUG
31 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/resources/chat/assets/assets/config/app-config.yaml:
--------------------------------------------------------------------------------
1 | #
2 | # SPDX-FileCopyrightText: 2024 Deutsche Telekom AG
3 | #
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 | storage:
7 | type: "default" # type could be default or secure
8 |
9 | openid:
10 | enabled: true
11 | type: keycloak
12 | credential:
13 | issuerBaseUrl: ${ARC_VIEW_ISSUER_BASE_URL}
14 | client_id: ${ARC_VIEW_OIDC_CLIENT_ID}
15 | client_secret: ${ARC_VIEW_OIDC_CLIENT_SECRET}
16 | redirect_base_url: ${ARC_VIEW_REDIRECT_BASE_URL} #this property will be used form macos(desktop) or desktop application
17 | call_back_path: "/callback"
18 | scopes:
19 | - "openid"
20 | - "profile"
21 | - "email"
22 | redirect_deeplink_url: "com.example.app://callback"
23 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/extensions/Logging.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl.extensions
6 |
7 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
8 | import org.slf4j.LoggerFactory
9 |
10 | /**
11 | * Extensions for logging
12 | */
13 | private val log = LoggerFactory.getLogger("ArcDSL")
14 |
15 | fun DSLContext.debug(message: String) {
16 | log.debug(message)
17 | }
18 |
19 | fun DSLContext.info(message: String) {
20 | log.info(message)
21 | }
22 |
23 | fun DSLContext.warn(message: String, ex: Exception? = null) {
24 | log.warn(message, ex)
25 | }
26 |
27 | fun DSLContext.error(message: String, ex: Exception? = null) {
28 | log.error(message, ex)
29 | }
30 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/events/Events.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.events
6 |
7 | import org.slf4j.MDC
8 | import java.time.Instant
9 |
10 | /**
11 | * Interface for all event types.
12 | */
13 | interface Event {
14 | val timestamp: Instant
15 | val context: Map
16 | }
17 |
18 | /**
19 | * Base class for events.
20 | * Can be used in combination with the 'by' keyword to implement the [Event] interface.
21 | * Example, class MyEvent : Event by BaseEvent()
22 | */
23 | class BaseEvent(
24 | override val timestamp: Instant = Instant.now(),
25 | override val context: Map = MDC.getCopyOfContextMap() ?: emptyMap(),
26 | ) : Event
27 |
--------------------------------------------------------------------------------
/arc-memory-mongo-spring-boot-starter/src/test/kotlin/TestApplication.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.memory.mongo
6 |
7 | import org.springframework.boot.autoconfigure.SpringBootApplication
8 | import org.springframework.boot.testcontainers.service.connection.ServiceConnection
9 | import org.springframework.context.annotation.Bean
10 | import org.testcontainers.containers.MongoDBContainer
11 | import org.testcontainers.utility.DockerImageName.parse
12 |
13 | @SpringBootApplication(proxyBeanMethods = false)
14 | open class TestApplication {
15 |
16 | @Bean
17 | @ServiceConnection
18 | fun mongoContainer() =
19 | MongoDBContainer(parse("mongo:7")).withReuse(true)
20 | }
21 |
--------------------------------------------------------------------------------
/arc-openai-api-spring-boot-starter/src/test/resources/application.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | server:
6 | port: 8080
7 |
8 | arc:
9 | scripts:
10 | enabled: false
11 | folder: src/test/resources/agents
12 | hotReload:
13 | enable: false
14 | delay: PT1S
15 | ai:
16 | clients:
17 | - id: GPT-4o
18 | client: azure
19 | url: https://openai.azure.com/
20 | modelName: gpt-4o
21 | - id: llama3.3
22 | modelName: llama3.3
23 | client: ollama
24 | - id: GPT-4o-mini
25 | modelName: gpt-4o-mini
26 | api-key: 12345
27 | client: openai
28 |
29 | logging:
30 | level:
31 | root: WARN
32 | org.eclipse.lmos.ai: DEBUG
33 |
--------------------------------------------------------------------------------
/.github/workflows/ci-main.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | name: CI
6 |
7 | on:
8 | push:
9 | branches: [ main ]
10 |
11 | jobs:
12 | CI:
13 | uses: eclipse-lmos/.github/.github/workflows/gradle-ci-main.yml@main
14 | permissions:
15 | contents: write
16 | packages: write
17 | secrets:
18 | oss-username: ${{ secrets.CENTRAL_SONATYPE_TOKEN_USERNAME }}
19 | oss-password: ${{ secrets.CENTRAL_SONATYPE_TOKEN_PASSWORD }}
20 | signing-key-id: ${{ secrets.GPG_SUBKEY_ID }}
21 | signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
22 | signing-key-password: ${{ secrets.GPG_PASSPHRASE }}
23 | registry-username: ${{ github.actor }}
24 | registry-password: ${{ secrets.GITHUB_TOKEN }}
25 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/inbound/ContextExtractor.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql.inbound
6 |
7 | import org.eclipse.lmos.arc.agents.agent.AgentChain
8 | import org.eclipse.lmos.arc.api.AgentRequest
9 |
10 | /**
11 | * Extract context beans that are encoded in the AgentRequest.
12 | */
13 | fun extractContext(request: AgentRequest): Set {
14 | return buildSet {
15 | /**
16 | * Extract an AgentChain from the request.
17 | */
18 | request.systemContext.firstOrNull { it.key == "agent_chain" }?.let { item ->
19 | add(AgentChain(item.value.split(",").map { it.trim() }.filter { it.isNotBlank() }))
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/functions/ListenableFunction.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.functions
6 |
7 | import org.eclipse.lmos.arc.core.Result
8 | import org.eclipse.lmos.arc.core.Success
9 |
10 | /**
11 | * A function decorator that listens for the result of the function
12 | * and calls a listener function with the result.
13 | */
14 | class ListenableFunction(
15 | private val fn: LLMFunction,
16 | private val listener: suspend (String) -> Unit,
17 | ) :
18 | LLMFunction by fn {
19 |
20 | override suspend fun execute(input: Map): Result {
21 | return fn.execute(input).also { if (it is Success) listener(it.value) }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/events/MessagePublisher.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.events
6 |
7 | import kotlinx.coroutines.channels.Channel
8 | import org.eclipse.lmos.arc.agents.conversation.AssistantMessage
9 |
10 | /**
11 | * Publishes a message that is returned to the client.
12 | */
13 | fun interface MessagePublisher {
14 | suspend fun publish(message: AssistantMessage)
15 | }
16 |
17 | fun interface MessageChannel {
18 | fun publish(message: AssistantMessage)
19 | }
20 |
21 | class MessagePublisherChannel(val channel: Channel) : MessagePublisher {
22 |
23 | override suspend fun publish(message: AssistantMessage) {
24 | channel.trySend(message)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/kotlin/ArcViewAutoConfiguration.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.view
6 |
7 | import org.springframework.boot.autoconfigure.AutoConfiguration
8 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
9 | import org.springframework.context.annotation.Bean
10 | import org.springframework.core.io.ClassPathResource
11 | import org.springframework.web.reactive.function.server.RouterFunctions
12 |
13 | @AutoConfiguration
14 | open class ArcViewAutoConfiguration {
15 |
16 | @Bean
17 | @ConditionalOnProperty("arc.chat.ui.enabled", havingValue = "true")
18 | fun chatResourceRouter() = RouterFunctions.resources("/chat/**", ClassPathResource("chat/"))
19 | }
20 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/test/kotlin/AgentSubscriptionTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.graphql.inbound.AgentSubscription
10 | import org.junit.jupiter.api.Test
11 | import org.springframework.beans.factory.annotation.Autowired
12 | import org.springframework.boot.test.context.SpringBootTest
13 |
14 | @SpringBootTest
15 | class AgentSubscriptionTest {
16 |
17 | @Autowired
18 | lateinit var agentSubscription: AgentSubscription
19 |
20 | @Test
21 | fun `test agentSubscription is defined`(): Unit = runBlocking {
22 | assertThat(agentSubscription).isNotNull
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/main/kotlin/MetricConfiguration.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.spring
6 |
7 | import io.micrometer.core.instrument.MeterRegistry
8 | import io.micrometer.core.instrument.simple.SimpleMeterRegistry
9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
11 | import org.springframework.context.annotation.Bean
12 |
13 | @ConditionalOnClass(MeterRegistry::class)
14 | class MetricConfiguration {
15 |
16 | @Bean
17 | fun metricsHandler(meterRegistry: MeterRegistry) = MetricsHandler(meterRegistry)
18 |
19 | @Bean
20 | @ConditionalOnMissingBean
21 | fun meterRegistry() = SimpleMeterRegistry()
22 | }
23 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 |
7 | implementation(project(":arc-agents"))
8 | implementation(project(":arc-result"))
9 | implementation(project(":arc-api"))
10 |
11 | // Graphql
12 | implementation(libs.graphql.kotlin.spring)
13 | implementation(libs.openfeature.sdk)
14 |
15 | // Spring
16 | implementation(libs.spring.boot.starter.webflux)
17 | implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.1")
18 | implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.19.2")
19 |
20 | // Test
21 | testImplementation(project(":arc-spring-boot-starter"))
22 | testImplementation("org.springframework.boot:spring-boot-starter-test:3.5.0")
23 | }
24 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/inbound/AgentQuery.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql.inbound
6 |
7 | import com.expediagroup.graphql.generator.annotations.GraphQLDescription
8 | import com.expediagroup.graphql.server.operations.Query
9 | import kotlinx.serialization.Serializable
10 | import org.eclipse.lmos.arc.agents.AgentProvider
11 |
12 | /**
13 | * Returns the list of available Agents.
14 | */
15 | class AgentQuery(private val agentProvider: AgentProvider) : Query {
16 |
17 | @GraphQLDescription("Returns the list of available Agents.")
18 | fun agent(): Agents {
19 | return Agents(agentProvider.getAgents().map { it.name })
20 | }
21 | }
22 |
23 | @Serializable
24 | data class Agents(val names: List)
25 |
--------------------------------------------------------------------------------
/arc-openai-realtime-client/src/main/kotlin/FunctionToSchema.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agent.client.ws
6 |
7 | import kotlinx.serialization.json.JsonObject
8 | import kotlinx.serialization.json.JsonPrimitive
9 | import kotlinx.serialization.json.buildJsonObject
10 | import org.eclipse.lmos.arc.agents.functions.LLMFunction
11 | import org.eclipse.lmos.arc.agents.functions.toJson
12 |
13 | /**
14 | * Converts an LLMFunction to a JSON Schema.
15 | */
16 | fun LLMFunction.toJsonSchema(): JsonObject {
17 | return buildJsonObject {
18 | put("type", JsonPrimitive("function"))
19 | put("name", JsonPrimitive(name))
20 | put("description", JsonPrimitive(description))
21 | put("parameters", parameters.toJson())
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/arc-memory-mongo-spring-boot-starter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | api(project(":arc-result"))
7 | api(project(":arc-agents"))
8 |
9 | implementation(libs.spring.boot.autoconfigure)
10 | implementation(libs.spring.boot.configuration.processor)
11 | implementation("org.springframework.boot:spring-boot-starter-data-mongodb-reactive:4.0.0")
12 |
13 | testImplementation("org.springframework.boot:spring-boot-testcontainers:4.0.0")
14 | testImplementation("org.springframework.boot:spring-boot-starter-test:4.0.0")
15 | testImplementation("org.springframework.boot:spring-boot-starter:4.0.0")
16 | testImplementation("org.testcontainers:mongodb:1.21.3")
17 | testImplementation("org.testcontainers:junit-jupiter:1.15.1")
18 | }
19 |
--------------------------------------------------------------------------------
/arc-scripting/src/test/resources/weather.agent.kts:
--------------------------------------------------------------------------------
1 |
2 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
3 | //
4 | // SPDX-License-Identifier: Apache-2.0
5 |
6 |
7 | agent {
8 | name = "weather"
9 | description = "Agent that provides weather data."
10 | systemPrompt = {
11 | """
12 | You are a professional weather service.
13 | You have access to real-time weather data with the get_weather function.
14 | Keep your answer short and concise.
15 | All you require is the location.
16 | if you cannot help the user, simply reply "I cant help you"
17 | """
18 | }
19 | filterInput {
20 | "A transformed question" replaces "A question"
21 | -"Bad Word"
22 | -"Malware.*".toRegex()
23 | }
24 | filterOutput {
25 | -"Bad Word"
26 | -"Malware.*".toRegex()
27 | }
28 | }
--------------------------------------------------------------------------------
/adl-kotlin-runner/src/main/kotlin/ScriptConfiguration.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.kotlin.runner
6 |
7 | import kotlin.script.experimental.api.*
8 | import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
9 | import kotlin.script.experimental.jvm.jvm
10 | import kotlin.script.experimental.jvm.jvmTarget
11 |
12 | object ScriptConfiguration : ScriptCompilationConfiguration(
13 | {
14 | defaultImports(
15 | "org.eclipse.lmos.arc.kotlin.runner.extensions.*",
16 | )
17 |
18 | ide {
19 | acceptedLocations(ScriptAcceptedLocation.Everywhere)
20 | }
21 |
22 | jvm {
23 | jvmTarget("21")
24 | dependenciesFromCurrentContext(wholeClasspath = true)
25 | }
26 | },
27 | )
28 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/llm/Simularity.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.llm
6 |
7 | import kotlin.math.sqrt
8 |
9 | /**
10 | * Calculates the cosine similarity between two vectors.
11 | * The result will range from -1.0 to 1.0. With 1.0 meaning the vectors are practically identical.
12 | */
13 | fun similarity(vec1: List, vec2: List): Double {
14 | require(vec1.size == vec2.size) { "Vector sizes must be equal!" }
15 | val dotProduct = vec1.zip(vec2) { a, b -> a * b }.sum()
16 | val magnitude1 = sqrt(vec1.sumOf { it * it })
17 | val magnitude2 = sqrt(vec2.sumOf { it * it })
18 | return if (magnitude1 == 0.0 || magnitude2 == 0.0) {
19 | 0.0
20 | } else {
21 | dotProduct / (magnitude1 * magnitude2)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/arc-runner/arcPre.java:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | //usr/bin/env jbang "$0" "$@" ; exit $?
6 | //JAVA 21
7 |
8 | //COMPILE_OPTIONS -Xlint:-options
9 |
10 | //DEPS org.eclipse.lmos:arc-runner:0.117.0
11 | //DEPS org.slf4j:slf4j-api:2.0.16
12 | //DEPS com.azure:azure-core-tracing-opentelemetry:1.0.0-beta.52
13 | //DEPS com.fasterxml.jackson.core:jackson-databind:2.17.2
14 | //DEPS io.projectreactor:reactor-core:3.4.41
15 |
16 | package arc.runner;
17 |
18 | import org.eclipse.lmos.arc.runner.Arc;
19 | import picocli.CommandLine;
20 |
21 | /* ktlint-disable */
22 | public class arcPre {
23 |
24 | public static void main(String[] args) {
25 | var exitCode = new CommandLine(new Arc()).execute(args);
26 | // System.exit(exitCode); kills the server
27 | }
28 | }
29 | /* ktlint-enable */
30 |
--------------------------------------------------------------------------------
/adl-kotlin-runner/src/main/kotlin/extensions/Time.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.kotlin.runner.extensions
6 | import java.time.ZoneId
7 | import java.time.ZonedDateTime
8 | import java.time.format.DateTimeFormatter
9 |
10 | /**
11 | * Extensions to provide the LLM with the current time.
12 | */
13 | fun time(zoneId: String? = null) = formatDateTime("HH:mm", zoneId)
14 | fun date(zoneId: String? = null) = formatDateTime("dd.MM", zoneId)
15 | fun year(zoneId: String? = null) = formatDateTime("yyyy", zoneId)
16 |
17 | fun formatDateTime(pattern: String, zoneId: String? = null): String {
18 | val formatter = DateTimeFormatter.ofPattern(pattern)
19 | val time = zoneId?.let { ZonedDateTime.now(ZoneId.of(it)) } ?: ZonedDateTime.now()
20 | return formatter.format(time)
21 | }
22 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/agent/UseCaseExtractor.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.agent
5 |
6 | /**
7 | * Regex to extract Use Case ID from text.
8 | */
9 | private val idRegex = "".toRegex(RegexOption.IGNORE_CASE)
10 |
11 | /**
12 | * Extracts the Use Case ID from the given message.
13 | * For example, " some output"
14 | * @receiver the message string to extract the Use Case ID from.
15 | * @return a Pair containing the extracted Use Case ID (or null if not found) and the cleaned message without the Use Case ID.
16 | */
17 | fun String.extractId(): Pair {
18 | val id = idRegex.find(this)?.groupValues?.elementAtOrNull(1)?.trim()
19 | val cleanedMessage = replace(idRegex, "").trim()
20 | return id to cleanedMessage
21 | }
22 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/extensions/Times.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl.extensions
6 |
7 | import java.time.ZoneId
8 | import java.time.ZonedDateTime
9 | import java.time.format.DateTimeFormatter
10 |
11 | /**
12 | * Extensions to provide the LLM with the current time.
13 | */
14 | fun time(zoneId: String? = null) = formatDateTime("HH:mm", zoneId)
15 | fun date(zoneId: String? = null) = formatDateTime("dd.MM", zoneId)
16 | fun year(zoneId: String? = null) = formatDateTime("yyyy", zoneId)
17 |
18 | fun formatDateTime(pattern: String, zoneId: String? = null): String {
19 | val formatter = DateTimeFormatter.ofPattern(pattern)
20 | val time = zoneId?.let { ZonedDateTime.now(ZoneId.of(it)) } ?: ZonedDateTime.now()
21 | return formatter.format(time)
22 | }
23 |
--------------------------------------------------------------------------------
/examples/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-agents"))
7 | implementation(project(":arc-azure-client"))
8 | implementation(project(":arc-server"))
9 | implementation(project(":arc-mcp"))
10 | implementation(project(":arc-scripting"))
11 | implementation(project(":arc-langchain4j-client"))
12 | implementation("dev.langchain4j:langchain4j-ollama:1.8.0")
13 |
14 | // Test
15 | testImplementation("org.springframework.ai:spring-ai-mcp-server-webflux-spring-boot-starter:1.0.0-M6")
16 | testImplementation("org.springframework.boot:spring-boot-starter-webflux:3.4.3")
17 | testImplementation(project(":arc-graphql-spring-boot-starter"))
18 | testImplementation("com.expediagroup:graphql-kotlin-spring-server:8.8.1")
19 | }
20 |
--------------------------------------------------------------------------------
/arc-langchain4j-client/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-result"))
7 | implementation(project(":arc-agents"))
8 |
9 | // Logging
10 | implementation("org.slf4j:slf4j-api:2.0.17")
11 |
12 | // LangChain4J
13 | val langchain4jVersion = "1.8.0"
14 | compileOnly("dev.langchain4j:langchain4j-core:$langchain4jVersion")
15 | compileOnly("dev.langchain4j:langchain4j-bedrock:$langchain4jVersion")
16 | compileOnly("dev.langchain4j:langchain4j-google-ai-gemini:$langchain4jVersion")
17 | compileOnly("dev.langchain4j:langchain4j-ollama:$langchain4jVersion")
18 | compileOnly("dev.langchain4j:langchain4j-open-ai:$langchain4jVersion")
19 |
20 | testImplementation("dev.langchain4j:langchain4j-bedrock:$langchain4jVersion")
21 | }
22 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/resources/use_cases.md:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | ### UseCase: usecase1
10 | #### Description
11 | The description of the use case 1.
12 |
13 | #### Steps
14 | - Step one of the use case 1.
15 |
16 | #### Solution
17 | Solution
18 |
19 | ----
20 |
21 | ### UseCase: usecase2 (2)
22 | #### Description
23 | The description of the use case 2.
24 |
25 | #### Solution
26 | Primary Solution
27 |
28 | #### Alternative Solution
29 | Alternative solution
30 | The web solution for use case 2
31 |
32 | #### Fallback Solution
33 | - Fallback soultion!
34 |
35 | ----
36 |
37 | ### UseCase: usecase3
38 | #### Description
39 | The description of the use case 3.
40 |
41 | #### Solution
42 | Solution for use case 3
43 | The mobile solution for use case 3
44 |
45 | ----
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/test/kotlin/AgentEventsSubscriptionTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.graphql.inbound.EventSubscription
10 | import org.junit.jupiter.api.Test
11 | import org.springframework.beans.factory.annotation.Autowired
12 | import org.springframework.boot.test.context.SpringBootTest
13 |
14 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
15 | class AgentEventsSubscriptionTest {
16 |
17 | @Autowired
18 | lateinit var eventSubscription: EventSubscription
19 |
20 | @Test
21 | fun `test eventSubscription is defined`(): Unit = runBlocking {
22 | assertThat(eventSubscription).isNotNull
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/arc-scripting/src/test/kotlin/agents/ScriptingAgentLoaderTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.scripting.agents
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.scripting.TestBase
10 | import org.eclipse.lmos.arc.scripting.readScript
11 | import org.junit.jupiter.api.Test
12 | import java.io.File
13 |
14 | class ScriptingAgentLoaderTest : TestBase() {
15 |
16 | @Test
17 | fun `test loading scripting agent from file`(): Unit = runBlocking {
18 | val scriptFile = File(scripts, "weather.agent.kts").also {
19 | it.writeText(readScript("weather.agent.kts"))
20 | }
21 | scriptingAgentLoader.loadAgents(scriptFile)
22 | assertThat(scriptingAgentLoader.getAgents()).hasSize(1)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/arc-openai-api-spring-boot-starter/src/main/kotlin/ArcOpenAIApiAutoConfiguration.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.openai.api
6 |
7 | import org.eclipse.lmos.arc.agents.AgentProvider
8 | import org.eclipse.lmos.arc.agents.events.*
9 | import org.eclipse.lmos.arc.openai.api.inbound.OpenAIController
10 | import org.springframework.beans.factory.annotation.Value
11 | import org.springframework.boot.autoconfigure.AutoConfiguration
12 | import org.springframework.context.annotation.Bean
13 |
14 | @AutoConfiguration
15 | open class ArcOpenAIApiAutoConfiguration {
16 |
17 | @Bean
18 | fun openAIController(
19 | @Value("\${arc.openai.endpoint.key:}") key: String?,
20 | agentProvider: AgentProvider,
21 | ): OpenAIController = OpenAIController(agentProvider, key.takeIf { it?.isNotEmpty() == true })
22 | }
23 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/resources/agents/weather.agent.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | agent {
6 | name = "weather"
7 | description = "Agent that provides weather data. Handles all weather related query"
8 | systemPrompt = {
9 | """
10 | You are a professional weather service. You provide weather data to your users.
11 | You have access to real-time weather data with the get_weather function.
12 | Use 'unknown' if the location is not provided.
13 | Always state the location used in the response.
14 |
15 | # Instructions
16 | - Keep your answer short and concise.
17 | - If you cannot help the user, simply reply "I cant help you"
18 | - Use the "store_preference" function, to store the weather location."
19 | """
20 | }
21 | tools = listOf("get_weather")
22 | }
--------------------------------------------------------------------------------
/arc-gradle-plugin/src/main/resources/AgentTemplate.kt.txt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | @file:Suppress("ktlint")
5 | package org.eclipse.lmos.arc.agents.gen
6 |
7 | //@@IMPORTS@@
8 | import org.eclipse.lmos.arc.agents.dsl.get
9 | import org.eclipse.lmos.arc.agents.dsl.*
10 | import org.eclipse.lmos.arc.core.*
11 | import org.eclipse.lmos.arc.agents.conversation.UserMessage
12 | import org.eclipse.lmos.arc.agents.conversation.latest
13 | import org.eclipse.lmos.arc.agents.dsl.extensions.*
14 | import org.eclipse.lmos.arc.agents.llm.ChatCompletionSettings
15 | import org.eclipse.lmos.arc.agents.llm.OutputFormat
16 | import org.eclipse.lmos.arc.assistants.support.filters.*
17 |
18 | class Agents {
19 |
20 | fun build(context: AgentDefinitionContext) {
21 | with(context) {
22 | //@@CODE@@
23 | }
24 | }
25 |
26 | //@@OUTER_CODE@@
27 | }
28 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/kotlin/filters/ReturnUseCaseIdFilterTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.filters
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.agents.dsl.AgentOutputFilter
10 | import org.eclipse.lmos.arc.agents.dsl.withDSLContext
11 | import org.eclipse.lmos.arc.assistants.support.TestBase
12 | import org.junit.jupiter.api.Test
13 |
14 | class ReturnUseCaseIdFilterTest : TestBase() {
15 |
16 | @Test
17 | fun `test ReturnUseCaseIdFilter implements AgentFilter`() = runBlocking {
18 | // Verify that ReturnUseCaseIdFilter implements AgentFilter
19 | withDSLContext {
20 | assertThat(ReturnUseCaseIdFilter::class.java).isAssignableTo(AgentOutputFilter::class.java)
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/resources/use_cases_conditionals.md:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | ### UseCase: usecase1
10 | #### Description
11 | The description of the use case 1.
12 |
13 | #### Steps
14 | - Step off
15 | - Step on>
16 |
17 | #### Solution
18 | Solution>
19 |
20 | ----
21 |
22 | ### UseCase: usecase2
23 | #### Description
24 | The description of the use case 2.
25 |
26 | #### Solution
27 | Primary 1
28 | Primary 2>
29 | end
30 |
31 | #### Alternative Solution
32 | Alternative solution
33 | The web solution for use case 2
34 | ----
35 |
36 | ### UseCase: usecase3
37 | #### Description
38 | The description of the use case 3.
39 | Second description.
40 |
41 | #### Solution
42 | Solution for use case 3
43 | The mobile solution for use case 3
44 |
45 | Off solution
46 | >
47 |
48 | ----
--------------------------------------------------------------------------------
/arc-agent-client/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(libs.ktor.client.websockets)
7 | implementation(libs.ktor.client.cio.jvm)
8 | implementation(libs.ktor.serialization.kotlinx.json)
9 | implementation(libs.ktor.client.core)
10 | implementation(libs.ktor.client.otel)
11 | implementation("io.opentelemetry:opentelemetry-exporter-otlp:1.56.0")
12 | implementation("io.opentelemetry:opentelemetry-sdk:1.56.0")
13 |
14 | api(project(":arc-api"))
15 |
16 | testImplementation(project(":arc-result"))
17 | testImplementation(project(":arc-agents"))
18 | testImplementation(project(":arc-graphql-spring-boot-starter"))
19 | testImplementation(project(":arc-spring-boot-starter"))
20 | testImplementation(libs.spring.boot.starter.test)
21 | testImplementation(libs.spring.boot.starter)
22 | }
23 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/context/AnonymizationEntities.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql.context
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.AnonymizationEntity
8 | import java.util.concurrent.atomic.AtomicReference
9 |
10 | /**
11 | * Holds a list of anonymized entities.
12 | */
13 | class AnonymizationEntities(anonymizationEntities: List) {
14 | private val _entities = AtomicReference(anonymizationEntities)
15 | var entities: List
16 | get() = _entities.get()
17 | set(value) {
18 | _entities.set(value)
19 | }
20 |
21 | fun hasReplacementToken(replacement: String) = entities.any { it.replacement == replacement }
22 |
23 | fun getReplacementFor(name: String) = entities.firstOrNull { it.value == name }
24 | }
25 |
--------------------------------------------------------------------------------
/arc-agent-client/src/main/kotlin/graphql/AgentSubscription.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agent.client.graphql
6 |
7 | /**
8 | * GraphQL subscription for Agent messages.
9 | */
10 | internal const val AGENT_SUBSCRIPTION = """
11 | subscription(${'$'}request: AgentRequestInput!, ${'$'}agentName: String) {
12 | agent(agentName: ${'$'}agentName, request: ${'$'}request) {
13 | status,
14 | type,
15 | responseTime,
16 | toolCalls {
17 | name,
18 | arguments,
19 | },
20 | context {
21 | key,
22 | value,
23 | },
24 | anonymizationEntities {
25 | type,
26 | value,
27 | replacement,
28 | },
29 | messages {
30 | content
31 | format,
32 | role,
33 | }
34 | }
35 | }
36 | """
37 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/kotlin/LLMHackingDetectorTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.agents.dsl.AgentInputFilter
10 | import org.eclipse.lmos.arc.agents.dsl.withDSLContext
11 | import org.eclipse.lmos.arc.assistants.support.filters.LLMHackingDetector
12 | import org.junit.jupiter.api.Test
13 |
14 | class LLMHackingDetectorTest : TestBase() {
15 |
16 | @Test
17 | fun `test LLMHackingDetector implements AgentFilter`() = runBlocking {
18 | // Verify that LLMHackingDetector implements AgentFilter
19 | withDSLContext {
20 | val detector = LLMHackingDetector()
21 | assertThat(detector).isInstanceOf(AgentInputFilter::class.java)
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/Logging.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql
6 |
7 | import kotlinx.coroutines.slf4j.MDCContext
8 | import kotlinx.coroutines.withContext
9 | import org.eclipse.lmos.arc.api.AgentRequest
10 | import org.slf4j.MDC
11 |
12 | suspend fun withLogContext(
13 | agent: String,
14 | request: AgentRequest,
15 | block: suspend kotlinx.coroutines.CoroutineScope.() -> T,
16 | ): T {
17 | val current = MDC.getCopyOfContextMap() ?: emptyMap()
18 | val extraContext = mapOf(
19 | "agent" to agent,
20 | "conversationId" to request.conversationContext.conversationId,
21 | "turnId" to (request.conversationContext.turnId ?: "-1"),
22 | ) + request.systemContext.associate { it.key to it.value }
23 | return withContext(MDCContext(current + extraContext), block)
24 | }
25 |
--------------------------------------------------------------------------------
/arc-runner/arc.java:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | //usr/bin/env jbang "$0" "$@" ; exit $?
6 | //JAVA 21
7 |
8 | //COMPILE_OPTIONS -Xlint:-options
9 |
10 | //REPOS mavencentral,snapshots=https://oss.sonatype.org/content/repositories/snapshots/
11 | //DEPS org.eclipse.lmos:arc-runner:0.122.0-SNAPSHOT
12 | //DEPS org.slf4j:slf4j-api:2.0.16
13 | //DEPS com.fasterxml.jackson.core:jackson-databind:2.17.2
14 | //DEPS io.projectreactor:reactor-core:3.6.9
15 | //DEPS io.ktor:ktor-server-core-jvm:3.0.3
16 |
17 | package arc.runner;
18 |
19 | import org.eclipse.lmos.arc.runner.Arc;
20 | import picocli.CommandLine;
21 |
22 | /* ktlint-disable */
23 | public class arc {
24 |
25 | public static void main(String[] args) {
26 | var exitCode = new CommandLine(new Arc()).execute(args);
27 | // System.exit(exitCode); kills the server
28 | }
29 | }
30 | /* ktlint-enable */
31 |
--------------------------------------------------------------------------------
/arc-scripting/src/test/kotlin/functions/ScriptingLLMFunctionLoaderTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.scripting.functions
5 |
6 | import kotlinx.coroutines.runBlocking
7 | import org.assertj.core.api.Assertions.assertThat
8 | import org.eclipse.lmos.arc.scripting.TestBase
9 | import org.eclipse.lmos.arc.scripting.readScript
10 | import org.junit.jupiter.api.Test
11 | import java.io.File
12 |
13 | class ScriptingLLMFunctionLoaderTest : TestBase() {
14 |
15 | @Test
16 | fun `test loading scripting functions from file`(): Unit = runBlocking {
17 | val scriptFile = File(scripts, "weather.functions.kts").also {
18 | it.writeText(readScript("weather.functions.kts"))
19 | }
20 | scriptingLLMFunctionLoader.loadFunctions(scriptFile)
21 | assertThat(scriptingLLMFunctionLoader.load(null)).hasSize(2)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/kotlin/GenAgentTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.spring
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.agents.AgentProvider
10 | import org.eclipse.lmos.arc.agents.getAgentByName
11 | import org.junit.jupiter.api.Test
12 | import org.springframework.beans.factory.annotation.Autowired
13 | import org.springframework.boot.test.context.SpringBootTest
14 |
15 | @SpringBootTest(
16 | properties = [
17 | "arc.scripts.enabled=false",
18 | ],
19 | )
20 | class GenAgentTest {
21 |
22 | @Autowired
23 | lateinit var agentProvider: AgentProvider
24 |
25 | @Test
26 | fun `test gen agent is loaded`(): Unit = runBlocking {
27 | assertThat(agentProvider.getAgentByName("weather-gen")).isNotNull
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/arc-streaming-spring-boot-starter/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 |
7 | implementation(project(":arc-agents"))
8 | implementation(project(":arc-result"))
9 | implementation(project(":arc-api"))
10 | implementation(project(":arc-graphql-spring-boot-starter"))
11 |
12 | // Spring
13 | implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.1")
14 | implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.19.2")
15 | implementation(libs.spring.boot.starter.webflux)
16 | implementation(libs.spring.boot.starter.websocket)
17 |
18 | // Test
19 | testImplementation(project(":arc-spring-boot-starter"))
20 | testImplementation(project(":arc-agent-client"))
21 | testImplementation(project(":arc-openai-realtime-client"))
22 | testImplementation(libs.spring.boot.starter.test)
23 | }
24 |
--------------------------------------------------------------------------------
/arc-runner/src/main/kotlin/View.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.runner
6 |
7 | import picocli.CommandLine.Command
8 | import picocli.CommandLine.Parameters
9 | import java.awt.Desktop
10 | import java.net.URI
11 |
12 | @Command(
13 | name = "view",
14 | description = ["Opens the Arc View in the browser."],
15 | )
16 | open class OpenView : Runnable {
17 |
18 | @Parameters(
19 | index = "0",
20 | description = ["The port the Agent server is running on. Defaults to 8080."],
21 | defaultValue = "8080",
22 | )
23 | private var port: String = "8080"
24 |
25 | override fun run() {
26 | println("Opening Arc View...")
27 | try {
28 | Desktop.getDesktop().browse(URI("http://localhost:$port/chat#/chat"))
29 | } catch (e: Exception) {
30 | e.printStackTrace()
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | name: Release
6 |
7 | on:
8 | workflow_dispatch:
9 | inputs:
10 | release-type:
11 | type: choice
12 | description: What do you want to release?
13 | options:
14 | - Milestone
15 | - Release
16 |
17 | jobs:
18 | CI:
19 | uses: eclipse-lmos/.github/.github/workflows/gradle-release.yml@main
20 | permissions:
21 | contents: write
22 | packages: write
23 | secrets:
24 | oss-username: ${{ secrets.CENTRAL_SONATYPE_TOKEN_USERNAME }}
25 | oss-password: ${{ secrets.CENTRAL_SONATYPE_TOKEN_PASSWORD }}
26 | bot-token: ${{ secrets.LMOS_BOT_TOKEN }}
27 | signing-key-id: ${{ secrets.GPG_SUBKEY_ID }}
28 | signing-key: ${{ secrets.GPG_PRIVATE_KEY }}
29 | signing-key-password: ${{ secrets.GPG_PASSPHRASE }}
30 | with:
31 | release-type: ${{ github.event.inputs.release-type }}
--------------------------------------------------------------------------------
/arc-agent-client/src/main/kotlin/AgentClient.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agent.client
6 |
7 | import kotlinx.coroutines.flow.Flow
8 | import org.eclipse.lmos.arc.api.AgentRequest
9 | import org.eclipse.lmos.arc.api.AgentResult
10 |
11 | /**
12 | * Client for communicating with the Agents.
13 | */
14 | interface AgentClient {
15 |
16 | /**
17 | * Calls the agent with the given request.
18 | * If an url is not provided, the client will use the default url.
19 | * If an agent name is not provided, the server will use the default agent.
20 | */
21 | suspend fun callAgent(agentRequest: AgentRequest, agentName: String? = null, url: String? = null, requestHeaders: Map = emptyMap()): Flow
22 | }
23 |
24 | /**
25 | * Exception thrown when an error occurs during agent communication.
26 | */
27 | class AgentException(message: String) : Exception(message)
28 |
--------------------------------------------------------------------------------
/adl-server/src/main/kotlin/EnvConfig.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.adl.server
5 |
6 | /**
7 | * Configuration object that provides access to environment-based settings for the ARC server.
8 | * This object reads configuration values from environment variables and provides default values
9 | * when the environment variables are not set.
10 | */
11 | object EnvConfig {
12 | /**
13 | * Indicates whether the server is running in development mode.
14 | *
15 | * Environment variable: ARC_DEV_MODE
16 | * Default value: false
17 | */
18 | val isDevMode get() = System.getenv("ARC_DEV_MODE")?.toBoolean() ?: false
19 |
20 | /**
21 | * The port on which the server should listen for incoming connections.
22 | *
23 | * Environment variable: ARC_SERVER_PORT
24 | * Default value: 8080
25 | */
26 | val serverPort get() = System.getenv("ADL_SERVER_PORT")?.toInt() ?: 8080
27 | }
28 |
--------------------------------------------------------------------------------
/arc-api/src/main/kotlin/Message.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.api
6 |
7 | import kotlinx.serialization.Serializable
8 |
9 | @Serializable
10 | data class Message(
11 | val role: String,
12 | val content: String,
13 | val format: String = "text",
14 | val turnId: String? = null,
15 | val binaryData: List? = null,
16 | )
17 |
18 | /**
19 | * Presents binary data in a message. The data can be encoded as base64 directly in this object or
20 | * this object may contain a source from where the data can be read, for example, a http address.
21 | */
22 | @Serializable
23 | class BinaryData(val mimeType: String, val dataAsBase64: String? = null, val source: String? = null)
24 |
25 | /**
26 | * Indicates that the binary data is being streamed to the receiver server from the client.
27 | * This is used as a source in the [BinaryData] object.
28 | */
29 | const val STREAM_SOURCE = "STREAM_SOURCE"
30 |
--------------------------------------------------------------------------------
/arc-server/src/main/kotlin/EnvConfig.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.server.ktor
5 |
6 | /**
7 | * Configuration object that provides access to environment-based settings for the ARC server.
8 | * This object reads configuration values from environment variables and provides default values
9 | * when the environment variables are not set.
10 | */
11 | object EnvConfig {
12 | /**
13 | * Indicates whether the server is running in development mode.
14 | *
15 | * Environment variable: ARC_DEV_MODE
16 | * Default value: false
17 | */
18 | val isDevMode get() = System.getenv("ARC_DEV_MODE")?.toBoolean() ?: false
19 |
20 | /**
21 | * The port on which the server should listen for incoming connections.
22 | *
23 | * Environment variable: ARC_SERVER_PORT
24 | * Default value: 8080
25 | */
26 | val serverPort get() = System.getenv("ARC_SERVER_PORT")?.toInt() ?: 8080
27 | }
28 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | rootProject.name = "arc"
6 |
7 | include("arc-scripting")
8 | include("arc-azure-client")
9 | include("arc-readers")
10 | include("arc-result")
11 | include("arc-agents")
12 | include("arc-spring-boot-starter")
13 | include("arc-memory-mongo-spring-boot-starter")
14 | include("arc-api")
15 | include("arc-agent-client")
16 | include("arc-graphql-spring-boot-starter")
17 | // include("arc-runner")
18 | include("arc-view-spring-boot-starter")
19 | include("arc-assistants")
20 | include("arc-langchain4j-client")
21 | include("arc-gradle-plugin")
22 | include("arc-gen")
23 | include("arc-openai-client")
24 | include("arc-streaming-spring-boot-starter")
25 | include("arc-openai-realtime-client")
26 | include("arc-openai-api-spring-boot-starter")
27 | include("arc-memory-redis")
28 | include("arc-mcp")
29 | include("arc-server")
30 | include("adl-kotlin-runner")
31 | include("adl-server")
32 | include("examples")
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | #
3 | # SPDX-License-Identifier: CC0-1.0
4 |
5 | .gradle
6 | build/
7 | !gradle/wrapper/gradle-wrapper.jar
8 | !**/src/main/**/build/
9 | !**/src/test/**/build/
10 |
11 | ### IntelliJ IDEA ###
12 | .idea/modules.xml
13 | .idea/jarRepositories.xml
14 | .idea/compiler.xml
15 | .idea/libraries/
16 | .idea
17 | *.iws
18 | *.iml
19 | *.ipr
20 | *.xml
21 | out/
22 | !**/src/main/**/out/
23 | !**/src/test/**/out/
24 |
25 | ### Eclipse ###
26 | .apt_generated
27 | .classpath
28 | .factorypath
29 | .project
30 | .settings
31 | .springBeans
32 | .sts4-cache
33 | bin/
34 | !**/src/main/**/bin/
35 | !**/src/test/**/bin/
36 |
37 | ### NetBeans ###
38 | /nbproject/private/
39 | /nbbuild/
40 | /dist/
41 | /nbdist/
42 | /.nb-gradle/
43 |
44 | ### VS Code ###
45 | .vscode/
46 |
47 | ### Mac OS ###
48 | .DS_Store
49 |
50 | ### Secrets ###
51 | **/application-secret.yml
52 |
53 | .kotlin
54 | /docs/node_modules/
55 | /docs/.docusaurus/
56 | /docs-src/node_modules/
57 | /docs-src/.docusaurus/
58 | .idea/
--------------------------------------------------------------------------------
/arc-agents/src/test/kotlin/dsl/extensions/TemplateTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl.extensions
6 |
7 | import org.assertj.core.api.Assertions.assertThat
8 | import org.eclipse.lmos.arc.agents.TestBase
9 | import org.junit.jupiter.api.Test
10 |
11 | class TemplateTest : TestBase() {
12 |
13 | @Test
14 | fun `test then extension`() {
15 | val predicate = true
16 | val result = """
17 | Hello${predicate then ", World!"}
18 | """.trim()
19 | assertThat(result).isEqualTo("Hello, World!")
20 | }
21 |
22 | @Test
23 | fun `test markdown extension`() {
24 | val result = listOf("one", "two", "three").markdown()
25 | assertThat(result).isEqualTo("- one\n- two\n- three\n")
26 | }
27 |
28 | @Test
29 | fun `test newline extension`() {
30 | val result = "Hello".newline()
31 | assertThat(result).isEqualTo("Hello\n")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/kotlin/clients/ClientsTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.clients
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.agents.llm.ChatCompleterProvider
10 | import org.junit.jupiter.api.Test
11 | import org.springframework.beans.factory.annotation.Autowired
12 | import org.springframework.boot.test.context.SpringBootTest
13 |
14 | @SpringBootTest
15 | class ClientsTest {
16 |
17 | @Autowired
18 | lateinit var chatCompleterProvider: ChatCompleterProvider
19 |
20 | @Test
21 | fun `test chatCompleterProvider has loaded all expected clients`(): Unit = runBlocking {
22 | assertThat(chatCompleterProvider.provideByModel("GPT-4o")).isNotNull
23 | assertThat(chatCompleterProvider.provideByModel("llama3.3")).isNotNull
24 | assertThat(chatCompleterProvider.provideByModel("GPT-4o-mini")).isNotNull
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/arc-scripting/src/test/kotlin/FunctionsTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.scripting
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.agents.dsl.BasicFunctionDefinitionContext
10 | import org.junit.jupiter.api.Test
11 |
12 | class FunctionsTest : TestBase() {
13 |
14 | @Test
15 | fun `test script`(): Unit = runBlocking {
16 | val context = BasicFunctionDefinitionContext(testBeanProvider)
17 | functionEngine.eval(
18 | """
19 | function(
20 | name = "get_weather",
21 | description = "the weather service",
22 | params = types(string("location","the location"))
23 | ) {
24 | "the weather is weather in location!"
25 | }
26 | """,
27 | context,
28 | )
29 | assertThat(context.functions).hasSize(1)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/AgentEvents.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.Conversation
8 | import org.eclipse.lmos.arc.agents.events.BaseEvent
9 | import org.eclipse.lmos.arc.agents.events.Event
10 | import org.eclipse.lmos.arc.core.Result
11 | import kotlin.time.Duration
12 |
13 | /**
14 | * Collection of events that can be published by Agents.
15 | */
16 | sealed class AgentEvent : Event by BaseEvent() {
17 | abstract val agent: Agent<*, *>
18 | }
19 |
20 | data class AgentFinishedEvent(
21 | override val agent: Agent<*, *>,
22 | val model: String?,
23 | val input: Conversation,
24 | val output: Result,
25 | val duration: Duration,
26 | val flowBreak: Boolean = false,
27 | val tools: Set = emptySet(),
28 | ) : AgentEvent()
29 |
30 | data class AgentStartedEvent(
31 | override val agent: Agent<*, *>,
32 | ) : AgentEvent()
33 |
--------------------------------------------------------------------------------
/arc-openai-api-spring-boot-starter/src/test/kotlin/OpenAIApiTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.spring
6 |
7 | import dev.langchain4j.model.openai.OpenAiChatModel
8 | import kotlinx.coroutines.runBlocking
9 | import org.assertj.core.api.Assertions.assertThat
10 | import org.junit.jupiter.api.Test
11 | import org.springframework.boot.test.context.SpringBootTest
12 |
13 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
14 | class OpenAIApiTest {
15 |
16 | @Test
17 | fun `test OpenAI API configuration`(): Unit = runBlocking {
18 | val model = OpenAiChatModel.builder()
19 | .baseUrl("http://localhost:8080/openai/v1/")
20 | .apiKey("your-api-key")
21 | .modelName("gpt-4o-mini")
22 | .build()
23 |
24 | model.chat("Hello").let { response ->
25 | println("Response: $response")
26 | assertThat(response).isEqualTo("Hello from Bot!")
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/context/ContextProvider.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql.context
6 |
7 | import org.eclipse.lmos.arc.agents.dsl.extensions.SystemContext
8 | import org.eclipse.lmos.arc.agents.dsl.extensions.SystemContextProvider
9 | import org.eclipse.lmos.arc.agents.dsl.extensions.UserProfile
10 | import org.eclipse.lmos.arc.agents.dsl.extensions.UserProfileProvider
11 | import org.eclipse.lmos.arc.api.AgentRequest
12 |
13 | /**
14 | * Provides the system context and user profile to the context of the DSL.
15 | */
16 | data class ContextProvider(val request: AgentRequest) : SystemContextProvider, UserProfileProvider {
17 |
18 | override fun provideSystem(): SystemContext {
19 | return SystemContext(request.systemContext.associate { it.key to it.value })
20 | }
21 |
22 | override fun provideProfile(): UserProfile {
23 | return UserProfile(request.userContext.profile.associate { it.key to it.value })
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/resources/use_cases_errors.md:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | ### UseCase: usecase1
10 |
11 | #### Description
12 |
13 | The description of the use case 1.
14 |
15 | #### Steps
16 |
17 | - Step one of the use case 1.
18 |
19 | #### Solution
20 |
21 | Solution
22 |
23 | #### Examples
24 | - Example 1
25 | - Example 2
26 |
27 | ----
28 |
29 | ### UseCase: usecase1 (2)
30 |
31 | #### Description
32 |
33 | The description of the use case 2.
34 |
35 | #### Solution
36 |
37 | Primary Solution
38 |
39 | #### Alternative Solution
40 |
41 | Alternative solution
42 | The web solution for use case 2
43 |
44 | #### Fallback Solution
45 |
46 | - Fallback soultion!
47 |
48 | ----
49 |
50 | ### UseCase: usecase3
51 |
52 | #### Description
53 |
54 | The description of the use case 3.
55 |
56 | #### Solution
57 |
58 | Solution for use case 3
59 | The mobile solution for use case 3
60 |
61 | #### Examples
62 | - Example 1
63 | - Example 2
64 |
65 | ----
--------------------------------------------------------------------------------
/arc-memory-mongo-spring-boot-starter/src/main/kotlin/MemoryAutoConfiguration.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.memory.mongo
6 |
7 | import org.springframework.beans.factory.annotation.Value
8 | import org.springframework.boot.autoconfigure.AutoConfiguration
9 | import org.springframework.context.annotation.Bean
10 | import org.springframework.data.mongodb.core.ReactiveMongoTemplate
11 | import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories
12 | import java.time.Duration
13 |
14 | @AutoConfiguration
15 | @EnableReactiveMongoRepositories(basePackageClasses = [MemoryRepository::class])
16 | class MemoryAutoConfiguration {
17 |
18 | @Bean
19 | fun indexCreator(mongoTemplate: ReactiveMongoTemplate) = IndexCreator(mongoTemplate)
20 |
21 | @Bean
22 | fun memory(
23 | memoryRepository: MemoryRepository,
24 | @Value("\${arc.memory.short-term-ttl:PT3H}") shortTermTTL: Duration,
25 | ) = MongoMemory(memoryRepository, shortTermTTL)
26 | }
27 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/features/FeatureFlags.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.features
5 |
6 | /**
7 | * Interface for managing feature flags in the application.
8 | */
9 | interface FeatureFlags {
10 |
11 | /**
12 | * Returns the value of a feature as a String.
13 | */
14 | fun getFeature(feature: String, default: String, param: Map = emptyMap()): String
15 |
16 | /**
17 | * Returns the value of a feature as an Int.
18 | */
19 | fun getFeatureInt(feature: String, default: Int = -1, param: Map = emptyMap()): Int
20 |
21 | /**
22 | * Returns the value of a feature as a Double.
23 | */
24 | fun getFeatureDouble(feature: String, default: Double = -1.0, param: Map = emptyMap()): Double
25 |
26 | /**
27 | * Returns the value of a feature as a Boolean.
28 | */
29 | fun getFeatureBoolean(feature: String, default: Boolean = false, param: Map = emptyMap()): Boolean
30 | }
31 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/main/kotlin/Agents.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.spring
6 |
7 | import org.eclipse.lmos.arc.agents.Agent
8 | import org.eclipse.lmos.arc.agents.dsl.AgentDefinition
9 | import org.eclipse.lmos.arc.agents.dsl.AgentFactory
10 | import org.eclipse.lmos.arc.agents.dsl.BasicAgentDefinitionContext
11 |
12 | /**
13 | * A factory for creating agents using the Arc Agent DSL.
14 | * Mainly used for creating Agents inside of Configuration classes.
15 | *
16 | * For example:
17 | * @Bean
18 | * fun myAgent(agent: Agents) = agent {
19 | * name = "My Agent"
20 | * systemPrompt = { "you are a helpful agent that tell funny jokes." }
21 | * }
22 | */
23 | class Agents(private val agentFactory: AgentFactory<*>) {
24 |
25 | operator fun invoke(agentDefinition: AgentDefinition.() -> Unit): Agent<*, *> {
26 | val context = BasicAgentDefinitionContext(agentFactory)
27 | context.agent { agentDefinition() }
28 | return context.agents.first()
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/arc-view-spring-boot-starter/src/main/kotlin/inbound/UseCaseParser.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.view.inbound
6 |
7 | import org.eclipse.lmos.arc.assistants.support.usecases.validation.UseCaseToJson
8 | import org.springframework.http.ResponseEntity
9 | import org.springframework.stereotype.Controller
10 | import org.springframework.web.bind.annotation.PostMapping
11 | import org.springframework.web.bind.annotation.RequestBody
12 | import org.springframework.web.bind.annotation.RequestMapping
13 |
14 | /**
15 | * Controller to receive use cases as plain markdown text and return them as JSON.
16 | */
17 | @Controller
18 | @RequestMapping("/arc/usecases")
19 | class UseCaseParser {
20 |
21 | private val json = UseCaseToJson()
22 |
23 | @PostMapping(consumes = ["text/plain"], produces = ["application/json"])
24 | fun receiveUseCases(@RequestBody data: String): ResponseEntity {
25 | val parsed = json.convert(data)
26 | return ResponseEntity.ok(parsed)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/extensions/Template.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl.extensions
6 |
7 | /**
8 | * Extensions to make using kotlin string templating easier.
9 | */
10 |
11 | /**
12 | * Returns the string if the predicate is true.
13 | * For example,
14 | * """ Some string template ${someVariableThatResultToTrue then "Hello"} """
15 | * will return "Some string template Hello".
16 | * This is simply a shorthand for
17 | * """ Some string template ${if(someVariableThatResultToTrue) "Hello" else "" } """.
18 | */
19 | infix fun Any?.then(out: String) = if (this == true) out else ""
20 |
21 | /**
22 | * Adds a newline character to the end of the string.
23 | **/
24 | fun String.newline() = this + "\n"
25 |
26 | /**
27 | * Prints a list of strings as a markdown list.
28 | * Example:
29 | * listOf("one", "two", "three").printAsList()
30 | * will return
31 | * - one
32 | * - two
33 | * - three
34 | */
35 | fun List.markdown() = this.joinToString("") { "- $it".newline() }
36 |
--------------------------------------------------------------------------------
/arc-api/src/main/kotlin/AgentRequest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.api
6 |
7 | import kotlinx.serialization.Serializable
8 |
9 | /**
10 | * AgentRequest
11 | */
12 | @Serializable
13 | data class AgentRequest(
14 | val messages: List,
15 | val conversationContext: ConversationContext,
16 | val systemContext: List,
17 | val userContext: UserContext,
18 | )
19 |
20 | @Serializable
21 | data class UserContext(
22 | val userId: String? = null,
23 | val userToken: String? = null,
24 | val profile: List,
25 | )
26 |
27 | @Serializable
28 | data class ConversationContext(
29 | val conversationId: String,
30 | val turnId: String? = null,
31 | val anonymizationEntities: List? = null,
32 | )
33 |
34 | @Serializable
35 | data class ProfileEntry(
36 | val key: String,
37 | val value: String,
38 | )
39 |
40 | @Serializable
41 | data class SystemContextEntry(
42 | val key: String,
43 | val value: String,
44 | )
45 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/ConversationClassifications.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.ConversationClassification
8 |
9 | /**
10 | * A classification to indicate that the agent was unavailable to resolve the user's request.
11 | */
12 | object Unresolved : ConversationClassification {
13 | override fun toString() = "UNRESOLVED"
14 | }
15 |
16 | /**
17 | * A classification to indicate that the agent has handed over the conversation to a human agent.
18 | * This can be because the user explicitly asked for a human agent or because the agent detected
19 | * that it cannot resolve the user's request.
20 | */
21 | object AgentHandover : ConversationClassification {
22 | override fun toString() = "AGENT_HANDOVER"
23 | }
24 |
25 | /**
26 | * A classification to indicate that the agent hallucinated.
27 | */
28 | object HallucinationDetected : ConversationClassification {
29 | override fun toString() = "HALLUCINATION_DETECTED"
30 | }
31 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/agent/Extensions.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.agent
5 |
6 | import org.eclipse.lmos.arc.agents.AgentFailedException
7 | import org.eclipse.lmos.arc.agents.ConversationAgent
8 | import org.eclipse.lmos.arc.agents.User
9 | import org.eclipse.lmos.arc.agents.conversation.AssistantMessage
10 | import org.eclipse.lmos.arc.agents.conversation.latest
11 | import org.eclipse.lmos.arc.agents.conversation.toConversation
12 | import org.eclipse.lmos.arc.core.map
13 | import org.eclipse.lmos.arc.core.result
14 |
15 | /**
16 | * Helper function to "ask" the agent a question.
17 | *
18 | * @param question The question to ask the agent.
19 | * @param user Optional user context for the conversation.
20 | * @return A Result containing the conversation or an AgentFailedException.
21 | */
22 | suspend fun ConversationAgent.ask(question: String, user: User? = null) = result {
23 | return execute(question.toConversation(user)).map { it.latest()?.content ?: "" }
24 | }
25 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/agent/AgentChain.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.agent
5 |
6 | /**
7 | * Represents a list of agents that should be executed one after the other
8 | * with the output of the previous agent being the input of the next agent.
9 | */
10 | data class AgentChain(val agents: List, val agentOnFailure: String? = null) {
11 |
12 | init {
13 | require(agents.isNotEmpty()) { "Agent chain must contain at least one agent." }
14 | }
15 |
16 | /**
17 | * Returns the next agent in the chain.
18 | * If the current agent is the last one in the chain, it returns null.
19 | * If the current agent is not found in the chain, it returns null.
20 | */
21 | fun nextAgent(currentAgent: String): String? {
22 | val currentIndex = agents.indexOf(currentAgent)
23 | if (currentIndex == -1) return null
24 | return if (currentIndex < agents.size - 1) {
25 | agents[currentIndex + 1]
26 | } else {
27 | null
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/AgentBuilder.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl
6 |
7 | import org.eclipse.lmos.arc.agents.Agent
8 | import org.eclipse.lmos.arc.agents.functions.LLMFunction
9 |
10 | /**
11 | * Handy function to builds agents using the given [agentFactory] and [builder].
12 | * @return the list of agents created.
13 | */
14 | fun buildAgents(agentFactory: AgentFactory<*>, builder: AgentDefinitionContext.() -> Unit): List> {
15 | val context = BasicAgentDefinitionContext(agentFactory)
16 | with(context) {
17 | builder()
18 | }
19 | return context.agents.toList()
20 | }
21 |
22 | /**
23 | * Handy function to builds agent functions.
24 | * @return the list of functions created.
25 | */
26 | fun buildFunctions(beanProvider: BeanProvider, builder: BasicFunctionDefinitionContext.() -> Unit): List {
27 | val context = BasicFunctionDefinitionContext(beanProvider)
28 | with(context) {
29 | builder()
30 | }
31 | return context.functions.toList()
32 | }
33 |
--------------------------------------------------------------------------------
/arc-langchain4j-client/src/main/kotlin/loaders/OllamaClientLoader.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.client.langchain4j.loaders
5 |
6 | import org.eclipse.lmos.arc.agents.events.EventPublisher
7 | import org.eclipse.lmos.arc.agents.llm.AIClientConfig
8 | import org.eclipse.lmos.arc.agents.llm.ANY_MODEL
9 | import org.eclipse.lmos.arc.agents.tracing.AgentTracer
10 | import org.eclipse.lmos.arc.client.langchain4j.LangChainClient
11 | import org.eclipse.lmos.arc.client.langchain4j.builders.ollamaBuilder
12 |
13 | class OllamaClientLoader : ClientLoader(
14 | name = "OLLAMA",
15 | dependOnClass = "dev.langchain4j.model.ollama.OllamaChatModel",
16 | clientNames = setOf("ollama"),
17 | ) {
18 |
19 | override fun loadClient(
20 | config: AIClientConfig,
21 | tracer: AgentTracer?,
22 | eventPublisher: EventPublisher?,
23 | ) = buildMap {
24 | val client = LangChainClient(config, ollamaBuilder(), eventPublisher, tracer)
25 | put(config.modelAlias ?: config.modelName ?: ANY_MODEL, client)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/arc-readers/src/main/kotlin/PdfReader.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl.extensions
6 |
7 | import org.apache.pdfbox.Loader
8 | import org.apache.pdfbox.text.PDFTextStripper
9 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
10 | import org.eclipse.lmos.arc.core.closeWith
11 | import org.eclipse.lmos.arc.core.failWith
12 | import org.eclipse.lmos.arc.core.result
13 | import java.net.URI
14 |
15 | /**
16 | * Extensions for reading PDF files.
17 | * @param uriString The URI of the PDF file.
18 | */
19 | fun DSLContext.pdf(uriString: String) = result {
20 | try {
21 | val inputStream = URI(uriString).toURL().openStream() closeWith { it.close() }
22 | val document = Loader.loadPDF(inputStream.readAllBytes()) closeWith { it.close() }
23 | PDFTextStripper().getText(document)
24 | } catch (ex: Exception) {
25 | failWith { ReadPdfException(uriString, ex) }
26 | }
27 | }
28 |
29 | class ReadPdfException(url: String, cause: Exception) : Exception("Failed to read PDF at $url", cause)
30 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/functions/FunctionEvents.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.functions
6 |
7 | import org.eclipse.lmos.arc.agents.ArcException
8 | import org.eclipse.lmos.arc.agents.events.BaseEvent
9 | import org.eclipse.lmos.arc.agents.events.Event
10 | import org.eclipse.lmos.arc.core.Result
11 | import java.time.Instant
12 | import kotlin.time.Duration
13 |
14 | /**
15 | * Events published by the LLM clients when calling functions.
16 | */
17 |
18 | data class LLMFunctionStartedEvent(
19 | val name: String,
20 | val param: Map,
21 | override val timestamp: Instant = Instant.now(),
22 | ) : Event by BaseEvent()
23 |
24 | data class LLMFunctionCalledEvent(
25 | val name: String,
26 | val param: Map,
27 | val result: Result,
28 | val duration: Duration,
29 | override val timestamp: Instant = Instant.now(),
30 | val version: String? = null,
31 | val description: String? = null,
32 | val outputDescription: String? = null,
33 | ) : Event by BaseEvent()
34 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/llm/AIClientConfig.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.llm
5 |
6 | data class AIClientConfig(
7 | val modelAlias: String? = null,
8 | val client: String,
9 | val modelName: String? = null,
10 | val endpoint: String? = null,
11 | val apiKey: String? = null,
12 | val accessKey: String? = null,
13 | val accessSecret: String? = null,
14 | val region: String? = null,
15 | ) {
16 |
17 | init {
18 | if (modelAlias != null && modelName == null) {
19 | error("ModelName must be provided if modelAlias is set!")
20 | }
21 | }
22 |
23 | override fun toString(): String {
24 | val apiKeyMasked = apiKey?.let { "****" } ?: "null"
25 | val accessKeyMasked = accessKey?.let { "****" } ?: "null"
26 | val accessSecretMasked = accessSecret?.let { "****" } ?: "null"
27 | return "AIClientConfig(id=$modelAlias, client=$client, modelName=$modelName, endpoint=$endpoint, apiKey=$apiKeyMasked, accessKey=$accessKeyMasked, accessSecret=$accessSecretMasked)"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/arc-scripting/src/test/resources/kb-summarizer.agent.kts:
--------------------------------------------------------------------------------
1 | import java.io.File
2 |
3 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
4 | //
5 | // SPDX-License-Identifier: Apache-2.0
6 |
7 |
8 | agent {
9 | name = "kb-summarizer"
10 | description = "Agent that provides weather data."
11 | var knowledgeSource = ""
12 | var numberOfTimesFileLoaded = 0
13 | init = {
14 | knowledgeSource = File("src/test/resources/knowledge-source.txt").readText()
15 | numberOfTimesFileLoaded++
16 | }
17 | systemPrompt = {
18 | """
19 | You are a professional document summarizer.
20 | You have access to the knowledge file. The knowledge content is as follows:
21 | $knowledgeSource
22 | Keep your answer short and concise.
23 | if you cannot help the user, simply reply "I cant help you"
24 | Number of times file loaded = $numberOfTimesFileLoaded
25 | """
26 | }
27 | filterInput {
28 | "A transformed question" replaces "A question"
29 | -"Bad Word"
30 | -"Malware.*".toRegex()
31 | }
32 | filterOutput {
33 | -"Bad Word"
34 | -"Malware.*".toRegex()
35 | }
36 | }
--------------------------------------------------------------------------------
/arc-memory-mongo-spring-boot-starter/src/test/kotlin/TestBase.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.memory.mongo
5 |
6 | import org.junit.jupiter.api.AfterEach
7 | import org.junit.jupiter.api.TestInstance
8 | import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
9 | import org.springframework.beans.factory.annotation.Autowired
10 | import org.springframework.boot.test.context.SpringBootTest
11 | import org.springframework.data.mongodb.core.ReactiveMongoTemplate
12 | import org.springframework.test.context.ActiveProfiles
13 |
14 | @SpringBootTest(
15 | properties = ["arc.memory.short-term-ttl=PT3S"],
16 | )
17 | @ActiveProfiles("test")
18 | @TestInstance(PER_CLASS)
19 | open class TestBase {
20 |
21 | @Autowired
22 | lateinit var memory: MongoMemory
23 |
24 | @Autowired
25 | lateinit var mongoTemplate: ReactiveMongoTemplate
26 |
27 | @AfterEach
28 | fun setup() {
29 | mongoTemplate.collectionNames.map {
30 | mongoTemplate.dropCollection(it)
31 | }.blockFirst()
32 | }
33 | }
34 |
35 | data class TestValue(val nr: Int, val value: String)
36 |
--------------------------------------------------------------------------------
/arc-server/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | dependencies {
6 | implementation(project(":arc-agents"))
7 | implementation(project(":arc-graphql-spring-boot-starter"))
8 | implementation(project(":arc-view-spring-boot-starter"))
9 |
10 | implementation(libs.ktor.server.core)
11 | implementation(libs.ktor.server.cio)
12 | implementation(libs.ktor.server.websockets)
13 | implementation(libs.ktor.server.static)
14 | implementation(libs.graphql.kotlin.ktor)
15 |
16 | // OpenTelemetry dependencies
17 | implementation(platform("io.opentelemetry:opentelemetry-bom:1.55.0"))
18 | implementation("io.opentelemetry:opentelemetry-extension-kotlin")
19 | implementation("io.opentelemetry:opentelemetry-context")
20 | implementation("io.opentelemetry:opentelemetry-api")
21 | implementation("io.opentelemetry:opentelemetry-sdk")
22 | implementation("io.opentelemetry:opentelemetry-exporter-otlp")
23 | implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
24 | implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi")
25 | }
26 |
--------------------------------------------------------------------------------
/arc-memory-redis/src/test/kotlin/TestBase.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.memory.redis
5 |
6 | import com.redis.testcontainers.RedisContainer
7 | import io.lettuce.core.RedisClient
8 | import org.testcontainers.junit.jupiter.Container
9 | import org.testcontainers.junit.jupiter.Testcontainers
10 | import org.testcontainers.utility.DockerImageName
11 | import java.time.Duration
12 |
13 | @Testcontainers
14 | open class TestBase {
15 |
16 | companion object {
17 | private val redisImage: DockerImageName = DockerImageName.parse("redis:7.0.12")
18 |
19 | @Container
20 | private val redisContainer = RedisContainer(redisImage).withExposedPorts(6379).also { it.start() }
21 | }
22 |
23 | val memory = RedisMemory(shortTermTTL = Duration.ofSeconds(2), redisClient = createRedisClient())
24 |
25 | private fun createRedisClient(): RedisClient {
26 | val port = redisContainer.getMappedPort(6379)
27 | val redisURI = "redis://localhost:$port"
28 | return RedisClient.create(redisURI)
29 | }
30 | }
31 |
32 | data class TestValue(val nr: Int, val value: String)
33 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/usecases/UseCaseIdExtractor.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.usecases
6 |
7 | typealias UseCaseId = String
8 |
9 | /**
10 | * Extract the use case id from the assistant message.
11 | * For example, ""
12 | */
13 | private val useCaseIdRegex = "".toRegex(RegexOption.IGNORE_CASE)
14 |
15 | fun extractUseCaseId(message: String): Pair {
16 | val id = useCaseIdRegex.find(message)?.groupValues?.elementAtOrNull(1)?.trim()
17 | val cleanedMessage = message.replace(useCaseIdRegex, "").trim()
18 | return cleanedMessage to id
19 | }
20 |
21 | /**
22 | * Extract the use case step id from the assistant message.
23 | * For example, ""
24 | */
25 | private val useCaseStepIdRegex = "".toRegex()
26 |
27 | fun extractUseCaseStepId(message: String): Pair {
28 | val id = useCaseStepIdRegex.find(message)?.groupValues?.elementAtOrNull(1)
29 | val cleanedMessage = message.replace(useCaseStepIdRegex, "").replace("", "").trim()
30 | return cleanedMessage to id
31 | }
32 |
--------------------------------------------------------------------------------
/examples/src/main/kotlin/AgentScriptServer.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.examples.script
5 |
6 | import kotlinx.coroutines.runBlocking
7 | import org.eclipse.lmos.arc.scripting.hotReloadAgents
8 | import org.eclipse.lmos.arc.server.ktor.serve
9 | import java.io.File
10 |
11 | /**
12 | * Demonstrates how run Agents that are defined in Kotlin script files.
13 | *
14 | * Changes to the script files will be automatically detected and reloaded.
15 | * New Agents can also be added to the folder without restarting the server.
16 | *
17 | * Setup:
18 | * - Set the OpenAI API key as a System property or environment variable.
19 | *
20 | * Dependencies:
21 | * - implementation(project(":arc-agents"))
22 | * - implementation(project(":arc-azure-client"))
23 | * - implementation(project(":arc-server"))
24 | * - implementation(project(":arc-scripting"))
25 | */
26 | fun main(): Unit = runBlocking {
27 | // Set the OpenAI API as a System property or environment variable.
28 | // System.setProperty("OPENAI_API_KEY", "****")
29 |
30 | hotReloadAgents(File("examples/agents")).serve(devMode = true)
31 | }
32 |
--------------------------------------------------------------------------------
/arc-langchain4j-client/src/main/kotlin/loaders/GeminiClientLoader.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.client.langchain4j.loaders
5 |
6 | import org.eclipse.lmos.arc.agents.events.EventPublisher
7 | import org.eclipse.lmos.arc.agents.llm.AIClientConfig
8 | import org.eclipse.lmos.arc.agents.llm.ANY_MODEL
9 | import org.eclipse.lmos.arc.agents.tracing.AgentTracer
10 | import org.eclipse.lmos.arc.client.langchain4j.LangChainClient
11 | import org.eclipse.lmos.arc.client.langchain4j.builders.geminiBuilder
12 |
13 | class GeminiClientLoader : ClientLoader(
14 | name = "GEMINI",
15 | dependOnClass = "dev.langchain4j.model.googleai.GoogleAiGeminiChatModel",
16 | clientNames = setOf("gemini"),
17 | ) {
18 |
19 | override fun loadClient(
20 | config: AIClientConfig,
21 | tracer: AgentTracer?,
22 | eventPublisher: EventPublisher?,
23 | ) = buildMap {
24 | config.apiKey ?: error("API key is required for Gemini!")
25 | val client = LangChainClient(config, geminiBuilder(), eventPublisher, tracer)
26 | put(config.modelAlias ?: config.modelName ?: ANY_MODEL, client)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/arc-memory-mongo-spring-boot-starter/src/main/kotlin/MemoryRepository.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.memory.mongo
6 |
7 | import org.springframework.data.annotation.Id
8 | import org.springframework.data.mongodb.core.index.Indexed
9 | import org.springframework.data.mongodb.core.mapping.Document
10 | import org.springframework.data.repository.kotlin.CoroutineCrudRepository
11 | import java.io.Serializable
12 | import java.time.Instant
13 |
14 | /**
15 | * Repository for the memory.
16 | */
17 | interface MemoryRepository : CoroutineCrudRepository
18 |
19 | /**
20 | * Entry in memory.
21 | */
22 | @Document
23 | data class MemoryEntry(
24 | val owner: String,
25 | val key: String,
26 | val value: Any,
27 | val sessionId: String? = null,
28 | @Indexed(expireAfter = "0s") val deletionDate: Instant? = null,
29 | @Id val id: MemoryKey = MemoryKey(owner, key, sessionId),
30 | val creationDate: Instant = Instant.now(),
31 | )
32 |
33 | /**
34 | * Key for a [MemoryEntry].
35 | */
36 | data class MemoryKey(val owner: String, val key: String, val sessionId: String? = null) : Serializable
37 |
--------------------------------------------------------------------------------
/arc-langchain4j-client/src/main/kotlin/builders/OllamaBuilder.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.client.langchain4j.builders
6 |
7 | import dev.langchain4j.model.chat.ChatModel
8 | import dev.langchain4j.model.ollama.OllamaChatModel
9 | import org.eclipse.lmos.arc.agents.llm.AIClientConfig
10 | import org.eclipse.lmos.arc.agents.llm.ChatCompletionSettings
11 |
12 | /**
13 | * Builds an ollama client.
14 | */
15 | fun ollamaBuilder(): (AIClientConfig, ChatCompletionSettings?) -> ChatModel {
16 | return { config, settings ->
17 | OllamaChatModel
18 | .builder()
19 | .baseUrl(config.endpoint ?: "http://localhost:11434")
20 | .modelName(config.modelName ?: settings?.model ?: settings?.deploymentName)
21 | .apply {
22 | if (settings != null) {
23 | settings.topP?.let { topP(it) }
24 | settings.temperature?.let { temperature(it) }
25 | settings.seed?.let { seed(it.toInt()) }
26 | settings.topK?.let { topK(it) }
27 | }
28 | }
29 | .build()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/arc-api/src/main/kotlin/Helpers.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.api
6 |
7 | /**
8 | * Short-hand function to create an agent request with a single user message.
9 | */
10 | fun agentRequest(content: String, conversationId: String, vararg binaryData: BinaryData, turnId: String? = null) =
11 | AgentRequest(
12 | messages = listOf(
13 | Message(
14 | "user",
15 | content,
16 | turnId = turnId,
17 | binaryData = binaryData.toList(),
18 | ),
19 | ),
20 | conversationContext = ConversationContext(conversationId, turnId),
21 | systemContext = emptyList(),
22 | userContext = UserContext(profile = emptyList()),
23 | )
24 |
25 | /**
26 | * Short-hand functions to create a messages.
27 | */
28 | fun userMessage(content: String, turnId: String? = null) = Message("user", content, turnId = turnId)
29 |
30 | fun assistantMessage(content: String, turnId: String? = null, binaryData: List? = null) = Message(
31 | "assistant",
32 | content,
33 | turnId = turnId,
34 | binaryData = binaryData,
35 | )
36 |
--------------------------------------------------------------------------------
/arc-memory-mongo-spring-boot-starter/src/main/kotlin/IndexCreator.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.memory.mongo
6 |
7 | import org.springframework.context.event.ContextRefreshedEvent
8 | import org.springframework.context.event.EventListener
9 | import org.springframework.data.mongodb.core.ReactiveMongoTemplate
10 | import org.springframework.data.mongodb.core.index.IndexDefinition
11 | import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver
12 |
13 | /**
14 | * Creates indices for the [MemoryEntry] collection.
15 | */
16 | class IndexCreator(private val mongoTemplate: ReactiveMongoTemplate) {
17 |
18 | @EventListener(ContextRefreshedEvent::class)
19 | fun initIndicesAfterStartup() {
20 | val mappingContext = mongoTemplate.converter.mappingContext
21 | val resolver = MongoPersistentEntityIndexResolver(mappingContext)
22 | val indexOps = mongoTemplate.indexOps(MemoryEntry::class.java)
23 | resolver.resolveIndexFor(MemoryEntry::class.java).forEach { indexDefinition: IndexDefinition? ->
24 | indexDefinition?.let { indexOps.ensureIndex(it).block() }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/arc-langchain4j-client/src/main/kotlin/builders/GroqBuilder.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.client.langchain4j.builders
6 |
7 | import dev.langchain4j.model.chat.ChatModel
8 | import dev.langchain4j.model.openai.OpenAiChatModel
9 | import org.eclipse.lmos.arc.agents.llm.AIClientConfig
10 | import org.eclipse.lmos.arc.agents.llm.ChatCompletionSettings
11 |
12 | /**
13 | * Builds a groq client.
14 | */
15 | fun groqBuilder(): (AIClientConfig, ChatCompletionSettings?) -> ChatModel {
16 | return { config, settings ->
17 | OpenAiChatModel
18 | .builder()
19 | .baseUrl(config.endpoint ?: "https://api.groq.com/openai/v1")
20 | .modelName(config.modelName ?: settings?.model ?: settings?.deploymentName)
21 | .apiKey(config.apiKey ?: error("API key is required for Groq!"))
22 | .apply {
23 | if (settings != null) {
24 | settings.topP?.let { topP(it) }
25 | settings.temperature?.let { temperature(it) }
26 | settings.seed?.let { seed(it.toInt()) }
27 | }
28 | }
29 | .build()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/adl-server/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | plugins {
6 | alias(libs.plugins.ktor)
7 | }
8 |
9 | application {
10 | mainClass = "org.eclipse.lmos.adl.server.AdlServerKt"
11 | }
12 |
13 | dependencies {
14 | implementation(project(":arc-assistants"))
15 | implementation(project(":adl-kotlin-runner"))
16 |
17 | implementation(libs.ktor.server.core)
18 | implementation(libs.ktor.server.cio)
19 | implementation(libs.ktor.server.websockets)
20 | implementation(libs.ktor.server.static)
21 | implementation(libs.graphql.kotlin.ktor)
22 |
23 | // OpenTelemetry dependencies
24 | implementation(platform("io.opentelemetry:opentelemetry-bom:1.55.0"))
25 | implementation("io.opentelemetry:opentelemetry-extension-kotlin")
26 | implementation("io.opentelemetry:opentelemetry-context")
27 | implementation("io.opentelemetry:opentelemetry-api")
28 | implementation("io.opentelemetry:opentelemetry-sdk")
29 | implementation("io.opentelemetry:opentelemetry-exporter-otlp")
30 | implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
31 | implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi")
32 | }
33 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Arc Examples
2 |
3 | This directory contains example applications demonstrating various features and capabilities of the Arc framework.
4 |
5 | ## Examples
6 |
7 | ### Main Examples
8 |
9 | 1. **AgentServer.kt**
10 | - Demonstrates how to run an Agent server with a web interface
11 | - Creates a simple weather assistant using GPT-4o
12 | - Web interface accessible at http://localhost:8080/chat/index.html#/chat
13 |
14 | 2. **AgentScriptServer.kt**
15 | - Demonstrates how to run Agents defined in Kotlin script files.
16 | - Uses hot reloading for agents from the "examples/agents" directory.
17 | - Web interface accessible at http://localhost:8080/chat/index.html#/chat
18 |
19 | 3. **McpAgent.kt**
20 | - Demonstrates how to connect an Agent to tools hosted on an MCP (Model Control Protocol) server.
21 | - Uses the "getBooks" tool from the MCP server
22 | - Requires McpApplication to be running
23 |
24 | 4. **OllamaAgent.kt**
25 | - Demonstrates how to connect an Agent to the Ollama server (a local LLM server)
26 |
27 | 5. **OpenAIAgent.kt**
28 | - Demonstrates how to connect an Agent to the OpenAI API.
29 |
30 | 6. **ContextAgent.kt**
31 | - Demonstrates how to provide Agents with access to external beans / components.
32 |
33 |
34 |
--------------------------------------------------------------------------------
/arc-langchain4j-client/src/main/kotlin/loaders/GroqClientLoader.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.client.langchain4j.loaders
5 |
6 | import org.eclipse.lmos.arc.agents.events.EventPublisher
7 | import org.eclipse.lmos.arc.agents.llm.AIClientConfig
8 | import org.eclipse.lmos.arc.agents.llm.ANY_MODEL
9 | import org.eclipse.lmos.arc.agents.tracing.AgentTracer
10 | import org.eclipse.lmos.arc.client.langchain4j.LangChainClient
11 | import org.eclipse.lmos.arc.client.langchain4j.builders.groqBuilder
12 |
13 | class GroqClientLoader : ClientLoader(
14 | name = "GROQ",
15 | dependOnClass = "dev.langchain4j.model.openai.OpenAiChatModel",
16 | clientNames = setOf("groq"),
17 | ) {
18 |
19 | override fun loadClient(
20 | config: AIClientConfig,
21 | tracer: AgentTracer?,
22 | eventPublisher: EventPublisher?,
23 | ) = buildMap {
24 | config.apiKey ?: error("API key is required for Groq!")
25 | config.endpoint ?: error("Model endpoint is required for Groq!")
26 | val client = LangChainClient(config, groqBuilder(), eventPublisher, tracer)
27 | put(config.modelAlias ?: config.modelName ?: ANY_MODEL, client)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/filters/UnresolvedDetector.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.filters
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
8 | import org.eclipse.lmos.arc.agents.dsl.AgentOutputFilter
9 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
10 | import org.eclipse.lmos.arc.agents.dsl.OutputFilterContext
11 | import org.eclipse.lmos.arc.agents.dsl.extensions.breakWith
12 | import org.eclipse.lmos.arc.assistants.support.Unresolved
13 |
14 | class UnresolvedDetector(private val fallbackReply: DSLContext.() -> String) : AgentOutputFilter {
15 |
16 | override suspend fun filter(message: ConversationMessage, context: OutputFilterContext): ConversationMessage {
17 | with(context) {
18 | if (message.content.contains("NO_ANSWER") || message.content.trim().isEmpty()) {
19 | breakWith(fallbackReply.invoke(context), classification = Unresolved)
20 | }
21 | if (message.content.contains(Unresolved.toString())) {
22 | breakWith(fallbackReply.invoke(context), classification = Unresolved)
23 | }
24 | }
25 | return message
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/usecases/features/Prompts.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.usecases.features
6 |
7 | val optionsAnalyserPrompt = """
8 | You are an assistant that analyzes user input and matches it to a list of possible options.
9 |
10 | ### Rules:
11 | - Your task is to choose exactly one option from the list of options that best matches the users intent.
12 | - If the user input does not match any option, you must return: NO_MATCH
13 | - Do not explain your reasoning or provide extra commentary. Only return the chosen option (or NO_MATCH).
14 | - Match the user intent even if the language is different than the options.
15 |
16 | ### Examples:
17 | User input: "sure"
18 | Options:
19 | - yes
20 | - no
21 | Correct output: yes
22 |
23 | User input: "makes sense"
24 | Options:
25 | - yes
26 | - no
27 | Correct output: yes
28 |
29 | User input: "blue"
30 | Options:
31 | - user choose color
32 | - other
33 | Correct output: user choose color
34 |
35 | User input: "i dont know"
36 | Options:
37 | - user choose color
38 | - other
39 | Correct output: other
40 |
41 | """.trimIndent()
42 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/kotlin/CustomerSupportAgentTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.junit.jupiter.api.Test
10 |
11 | class CustomerSupportAgentTest : TestBase() {
12 |
13 | @Test
14 | fun `test assistant creation`(): Unit = runBlocking {
15 | val assistant = assistantContext {
16 | customerSupportAgent {
17 | name = "Customer Support"
18 | companyName = "Deutsche Telekom"
19 | knowledge {
20 | """
21 | - I can help you with your phone
22 | - I can help you with your internet
23 | """
24 | }
25 | examples {
26 | """
27 | - I have a problem with my phone
28 | - I need help with my internet
29 | - I want to cancel my contract
30 | """
31 | }
32 | }
33 | }
34 |
35 | assertThat(assistant.name).isEqualTo("Customer Support")
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/arc-spring-boot-starter/src/test/kotlin/AgentBeansTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.spring
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.assertj.core.api.Assertions.assertThatNoException
10 | import org.eclipse.lmos.arc.agents.AgentProvider
11 | import org.eclipse.lmos.arc.agents.functions.LLMFunctionProvider
12 | import org.eclipse.lmos.arc.agents.getAgentByName
13 | import org.junit.jupiter.api.Test
14 | import org.springframework.beans.factory.annotation.Autowired
15 | import org.springframework.boot.test.context.SpringBootTest
16 |
17 | @SpringBootTest
18 | class AgentBeansTest {
19 |
20 | @Autowired
21 | lateinit var agentProvider: AgentProvider
22 |
23 | @Autowired
24 | lateinit var functionProvider: LLMFunctionProvider
25 |
26 | @Test
27 | fun `test agent defined as bean`(): Unit = runBlocking {
28 | assertThat(agentProvider.getAgentByName("agentBean")).isNotNull
29 | }
30 |
31 | @Test
32 | fun `test function defined as bean`(): Unit = runBlocking {
33 | assertThatNoException().isThrownBy { runBlocking { (functionProvider.provide("get_weather_bean")) } }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/functions/TraceableLLMFunction.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.functions
6 |
7 | import org.eclipse.lmos.arc.agents.tracing.AgentTracer
8 | import org.eclipse.lmos.arc.core.Result
9 | import org.eclipse.lmos.arc.core.getOrNull
10 | import org.eclipse.lmos.arc.core.onFailure
11 |
12 | class TraceableLLMFunction(private val tracer: AgentTracer, private val function: LLMFunction) :
13 | LLMFunction by function {
14 |
15 | override suspend fun execute(input: Map): Result {
16 | return tracer.withSpan(
17 | "tool $name",
18 | mapOf(
19 | "name" to name,
20 | "parameters" to parameters.toString(),
21 | "description" to description,
22 | "sensitive" to isSensitive.toString(),
23 | ),
24 | ) { tags, _ ->
25 | function.execute(input).also { result ->
26 | tags.tag("input", input.toString())
27 | result.getOrNull()?.let { tags.tag("result", it) }
28 | result.onFailure { tags.tag("error", it.message ?: "unknown error") }
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/inbound/AccessControlHeaders.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql.inbound
6 |
7 | import org.slf4j.LoggerFactory
8 | import org.springframework.web.server.ServerWebExchange
9 | import org.springframework.web.server.WebFilter
10 | import org.springframework.web.server.WebFilterChain
11 | import reactor.core.publisher.Mono
12 |
13 | /**
14 | * Adds CORs and other headers for running the agent.
15 | */
16 | class AccessControlHeaders(
17 | private val allowOrigin: String,
18 | private val allowMethods: String,
19 | private val allowHeaders: String,
20 | ) : WebFilter {
21 |
22 | private val log = LoggerFactory.getLogger(this.javaClass)
23 |
24 | override fun filter(serverWebExchange: ServerWebExchange, webFilterChain: WebFilterChain): Mono {
25 | log.debug("Adding CORs headers")
26 | serverWebExchange.response.headers.add("Access-Control-Allow-Origin", allowOrigin)
27 | serverWebExchange.response.headers.add("Access-Control-Allow-Methods", allowMethods)
28 | serverWebExchange.response.headers.add("Access-Control-Allow-Headers", allowHeaders)
29 | return webFilterChain.filter(serverWebExchange)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/arc-mcp/src/test/kotlin/McpPromptRetrieverTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.mcp
5 |
6 | import kotlinx.coroutines.runBlocking
7 | import org.assertj.core.api.Assertions.assertThat
8 | import org.eclipse.lmos.arc.agents.dsl.extensions.NoPromptFoundException
9 | import org.eclipse.lmos.arc.core.Failure
10 | import org.eclipse.lmos.arc.core.getOrThrow
11 | import org.junit.jupiter.api.Test
12 | import org.springframework.boot.test.web.server.LocalServerPort
13 | import java.util.*
14 |
15 | class McpPromptRetrieverTest : TestBase() {
16 |
17 | @LocalServerPort
18 | private var port: Int = 0
19 |
20 | @Test
21 | fun `test prompt retriever`(): Unit = runBlocking {
22 | val prompt = McpPromptRetriever("http://localhost:$port").fetchPromptText("greeting", emptyMap())
23 | prompt.getOrThrow().let {
24 | assertThat(it).isEqualTo("Hello friend! How can I assist you today?")
25 | }
26 | }
27 |
28 | @Test
29 | fun `test for NoPromptFoundException`(): Unit = runBlocking {
30 | val result = McpPromptRetriever("http://localhost:$port").fetchPromptText("no-prompt", emptyMap()) as Failure
31 | assertThat(result.reason is NoPromptFoundException).isTrue()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/extensions/Events.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl.extensions
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.AssistantMessage
8 | import org.eclipse.lmos.arc.agents.conversation.Conversation
9 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
10 | import org.eclipse.lmos.arc.agents.dsl.get
11 | import org.eclipse.lmos.arc.agents.dsl.getOptional
12 | import org.eclipse.lmos.arc.agents.events.Event
13 | import org.eclipse.lmos.arc.agents.events.EventPublisher
14 | import org.eclipse.lmos.arc.agents.events.MessagePublisher
15 |
16 | /**
17 | * Extensions for eventing.
18 | */
19 | suspend fun DSLContext.emit(event: Event) {
20 | getOptional()?.publish(event)
21 | }
22 |
23 | /**
24 | * Emits a message to the client.
25 | *
26 | * @last If true, indicates that this is the last message in the conversation turn.
27 | */
28 | suspend fun DSLContext.emitMessage(msg: String, last: Boolean = false) {
29 | val currentTurnId = get().currentTurnId
30 | emitMessage(AssistantMessage(msg, turnId = currentTurnId, last = last))
31 | }
32 |
33 | suspend fun DSLContext.emitMessage(msg: AssistantMessage) {
34 | get().publish(msg)
35 | }
36 |
--------------------------------------------------------------------------------
/arc-readers/src/test/kotlin/HtmlReaderTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | import kotlinx.coroutines.runBlocking
6 | import org.assertj.core.api.Assertions.assertThat
7 | import org.eclipse.lmos.arc.agents.dsl.BasicDSLContext
8 | import org.eclipse.lmos.arc.agents.dsl.BeanProvider
9 | import org.eclipse.lmos.arc.agents.dsl.extensions.htmlDocument
10 | import org.eclipse.lmos.arc.core.getOrThrow
11 | import org.junit.jupiter.api.Test
12 | import java.io.File
13 | import kotlin.reflect.KClass
14 |
15 | class HtmlReaderTest {
16 |
17 | @Test
18 | fun `test reading a html file`(): Unit = runBlocking {
19 | val result = File("src/test/resources/test.html").readText().htmlDocument().getOrThrow()
20 | assertThat(result.text().trim()).isEqualTo("This is a test!")
21 | }
22 |
23 | @Test
24 | fun `test reading a html document`(): Unit = runBlocking {
25 | val result = File("src/test/resources/test.html").readText().htmlDocument().getOrThrow()
26 | assertThat(result.select("p").text()).isEqualTo("test!")
27 | }
28 |
29 | private fun dslContext() = BasicDSLContext(object : BeanProvider {
30 | override suspend fun provide(bean: KClass): T {
31 | error("err")
32 | }
33 | })
34 | }
35 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/llm/ChatCompleterProvider.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.llm
6 |
7 | /**
8 | * Indicates that the ChatCompleter can be used for multiple models.
9 | */
10 | const val ANY_MODEL = "*"
11 |
12 | /**
13 | * Provides ChatCompleter based on their model name.
14 | * ChatCompleterProviders must provide a default ChatCompleter if no model is explicitly defined.
15 | */
16 | fun interface ChatCompleterProvider {
17 |
18 | fun provideByModel(model: String?): ChatCompleter
19 | }
20 |
21 | /**
22 | * Provides an implementation of ChatCompleterProvider that is backed by a map of ChatCompleters.
23 | */
24 | class MapChatCompleterProvider(private val map: Map) : ChatCompleterProvider {
25 |
26 | override fun provideByModel(model: String?): ChatCompleter {
27 | return model?.let {
28 | map[model] ?: map[ANY_MODEL] ?: error("Cannot find a ChatCompleter for $model! ChatCompleters:[$map]")
29 | } ?: map[ANY_MODEL] ?: map.values.first()
30 | }
31 |
32 | override fun toString(): String {
33 | return "MapChatCompleterProvider(map=$map)"
34 | }
35 | }
36 |
37 | fun Map.toChatCompleterProvider() = MapChatCompleterProvider(this)
38 |
--------------------------------------------------------------------------------
/examples/agents/assistant.agent.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | agent {
6 | name = "assistant-agent"
7 | description = "A helpful assistant that can provide information and answer questions."
8 | model { "gpt-4o" }
9 | tools = AllTools
10 | prompt {
11 | val customerName = userProfile("name", "")
12 |
13 | """
14 | # Goal
15 | You are a helpful assistant that can provide information and answer customer questions.
16 | You answer in a helpful and professional manner.
17 |
18 | ### Instructions
19 | ${(customerName.isNotEmpty()) then "- Always greet the customer with their name, $customerName"}
20 | - Only answer the customer question in a concise and short way.
21 | - Only provide information the user has explicitly asked for.
22 | - Use the "Knowledge" section to answer customers queries.
23 | - If the customer's question is on a topic not described in the "Knowledge" section nor llm functions, reply that you cannot help with that issue.
24 |
25 | ### Knowledge
26 | **Customer would like to know about Arc.**
27 | - Read the content from https://eclipse.dev/lmos/arc/ and provide the answer.
28 |
29 | """
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/llm/ChatCompleter.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.llm
6 |
7 | import org.eclipse.lmos.arc.agents.ArcException
8 | import org.eclipse.lmos.arc.agents.conversation.AssistantMessage
9 | import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
10 | import org.eclipse.lmos.arc.agents.conversation.UserMessage
11 | import org.eclipse.lmos.arc.agents.events.EventPublisher
12 | import org.eclipse.lmos.arc.agents.functions.LLMFunction
13 | import org.eclipse.lmos.arc.core.Result
14 |
15 | /**
16 | * ChatCompleters can take a conversation and adds a new message to the conversation.
17 | * They are usually connect to a LLM Model, such as, ChatGPT or Gemini.
18 | */
19 | interface ChatCompleter {
20 | suspend fun complete(
21 | messages: List,
22 | functions: List? = null,
23 | settings: ChatCompletionSettings? = null,
24 | eventPublisher: EventPublisher? = null,
25 | ): Result
26 | }
27 |
28 | suspend fun ChatCompleter.complete(
29 | userMessage: String,
30 | functions: List? = null,
31 | settings: ChatCompletionSettings? = null,
32 | ) = complete(listOf(UserMessage(userMessage)), functions, settings)
33 |
--------------------------------------------------------------------------------
/adl-kotlin-runner/src/main/kotlin/extensions/Http.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.kotlin.runner.extensions
5 |
6 | import kotlinx.coroutines.future.await
7 | import java.net.URI
8 | import java.net.http.HttpClient
9 | import java.net.http.HttpRequest
10 | import java.net.http.HttpRequest.BodyPublishers
11 | import java.net.http.HttpResponse
12 |
13 | /**
14 | * Performs a HTTP GET request.
15 | */
16 | suspend fun httpGet(url: String, headers: Map = emptyMap()): String {
17 | val request = HttpRequest.newBuilder().uri(URI(url)).apply {
18 | headers.forEach { (k, v) -> setHeader(k, v) }
19 | }.GET().build()
20 | val response = HttpClient.newHttpClient().sendAsync(request, HttpResponse.BodyHandlers.ofString()).await()
21 | return response.body()
22 | }
23 |
24 | /**
25 | * Performs a HTTP POST request.
26 | */
27 | suspend fun httpPost(url: String, body: String, headers: Map = emptyMap()): String {
28 | val request = HttpRequest.newBuilder().uri(URI(url)).apply {
29 | headers.forEach { (k, v) -> setHeader(k, v) }
30 | }.POST(BodyPublishers.ofString(body)).build()
31 | val response = HttpClient.newHttpClient().sendAsync(request, HttpResponse.BodyHandlers.ofString()).await()
32 | return response.body()
33 | }
34 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/extensions/UseCaseLoader.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.extensions
6 |
7 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
8 | import org.eclipse.lmos.arc.assistants.support.usecases.UseCase
9 |
10 | /**
11 | * Interface for loading use cases by name and context.
12 | *
13 | * Implementations of this interface are responsible for retrieving a list of [UseCase]s
14 | * based on a given name (e.g., a file, resource, or identifier) and the current [DSLContext].
15 | * This allows for flexible loading strategies, such as from local files, remote sources,
16 | * or custom repositories, depending on the application's needs.
17 | *
18 | * @see UseCase for the use case data structure
19 | * @see DSLContext for the context in which the loader operates
20 | */
21 | interface UseCaseLoader {
22 | /**
23 | * Loads use cases for the given name and context.
24 | *
25 | * @param name The identifier or resource name for the use cases to load.
26 | * @param context The DSLContext providing additional context for loading.
27 | * @return A list of loaded [UseCase]s or null, if use cases could not be loaded.
28 | */
29 | suspend fun loadUseCases(name: String, context: DSLContext): List?
30 | }
31 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/llm/LLMEvents.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.llm
6 |
7 | import org.eclipse.lmos.arc.agents.ArcException
8 | import org.eclipse.lmos.arc.agents.conversation.AssistantMessage
9 | import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
10 | import org.eclipse.lmos.arc.agents.events.BaseEvent
11 | import org.eclipse.lmos.arc.agents.events.Event
12 | import org.eclipse.lmos.arc.agents.functions.LLMFunction
13 | import org.eclipse.lmos.arc.core.Result
14 | import kotlin.time.Duration
15 |
16 | /**
17 | * Events published by the LLM clients.
18 | */
19 |
20 | data class LLMStartedEvent(val model: String) : Event by BaseEvent()
21 |
22 | data class LLMFinishedEvent(
23 | val result: Result,
24 | val messages: List,
25 | val functions: List?,
26 | val model: String,
27 | // TODO:: openAI SDK support Long For totalTokens, promptTokens, completionTokens. Revisit this
28 | val totalTokens: Int,
29 | val promptTokens: Int,
30 | val completionTokens: Int,
31 | val functionCallCount: Int,
32 | val duration: Duration,
33 | val settings: ChatCompletionSettings? = null,
34 | val finishReasons: List? = null,
35 | ) : Event by BaseEvent()
36 |
--------------------------------------------------------------------------------
/arc-langchain4j-client/src/main/kotlin/loaders/BedrockClientLoader.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.client.langchain4j.loaders
5 |
6 | import org.eclipse.lmos.arc.agents.events.EventPublisher
7 | import org.eclipse.lmos.arc.agents.llm.AIClientConfig
8 | import org.eclipse.lmos.arc.agents.llm.ANY_MODEL
9 | import org.eclipse.lmos.arc.agents.tracing.AgentTracer
10 | import org.eclipse.lmos.arc.client.langchain4j.LangChainClient
11 | import org.eclipse.lmos.arc.client.langchain4j.builders.bedrockBuilder
12 |
13 | class BedrockClientLoader : ClientLoader(
14 | name = "BEDROCK",
15 | dependOnClass = "dev.langchain4j.model.bedrock.BedrockAnthropicMessageChatModel",
16 | clientNames = setOf("bedrock"),
17 | ) {
18 |
19 | override fun loadClient(
20 | config: AIClientConfig,
21 | tracer: AgentTracer?,
22 | eventPublisher: EventPublisher?,
23 | ) = buildMap {
24 | config.accessKey ?: error("AccessKey is required for bedrock!")
25 | config.accessSecret ?: error("AccessSecret is required for bedrock!")
26 | config.endpoint ?: error("Endpoint is required for bedrock!")
27 | val client = LangChainClient(config, bedrockBuilder(), eventPublisher, tracer)
28 | put(config.modelAlias ?: config.modelName ?: ANY_MODEL, client)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/arc-assistants/src/main/kotlin/filters/ReturnUseCaseIdFilter.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.assistants.support.filters
5 |
6 | import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
7 | import org.eclipse.lmos.arc.agents.dsl.AgentOutputFilter
8 | import org.eclipse.lmos.arc.agents.dsl.OutputFilterContext
9 | import org.eclipse.lmos.arc.agents.dsl.extensions.getCurrentUseCases
10 | import org.eclipse.lmos.arc.agents.dsl.extensions.system
11 | import org.slf4j.LoggerFactory
12 |
13 | /**
14 | * Returns the use case id if the system property "returnUseCaseId" is set to true.
15 | * This will only work for Agents that use the useCase function.
16 | */
17 | class ReturnUseCaseIdFilter : AgentOutputFilter {
18 | private val log = LoggerFactory.getLogger(javaClass)
19 |
20 | override suspend fun filter(message: ConversationMessage, context: OutputFilterContext): ConversationMessage {
21 | with(context) {
22 | if (system("returnUseCaseId", "false") == "true") {
23 | getCurrentUseCases()?.currentUseCaseId?.let {
24 | log.debug("Returning use case id: $it")
25 | return message.update("${message.content}")
26 | }
27 | }
28 | }
29 | return message
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/inbound/ToolQuery.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql.inbound
6 |
7 | import com.expediagroup.graphql.generator.annotations.GraphQLDescription
8 | import com.expediagroup.graphql.server.operations.Query
9 | import kotlinx.serialization.Serializable
10 | import org.eclipse.lmos.arc.agents.functions.LLMFunctionProvider
11 | import org.eclipse.lmos.arc.agents.functions.toJson
12 |
13 | /**
14 | * Returns the list of available tools (functions) provided by the LLMFunctionProvider.
15 | */
16 | class ToolQuery(private val functionProvider: LLMFunctionProvider) : Query {
17 |
18 | @GraphQLDescription("Returns the list of available tools.")
19 | suspend fun tool(): Tools {
20 | return Tools(
21 | functionProvider.provideAll().map { function ->
22 | Tool(
23 | name = function.name,
24 | description = function.description,
25 | parameters = function.parameters.toJson().toString(),
26 | )
27 | },
28 | )
29 | }
30 | }
31 |
32 | @Serializable
33 | data class Tools(
34 | val tools: List,
35 | )
36 |
37 | @Serializable
38 | data class Tool(
39 | val name: String,
40 | val description: String,
41 | val parameters: String,
42 | )
43 |
--------------------------------------------------------------------------------
/arc-runner/src/main/kotlin/Install.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | @file:Suppress("ktlint")
6 |
7 | package org.eclipse.lmos.arc.runner
8 |
9 | import picocli.CommandLine.Command
10 | import picocli.CommandLine.Parameters
11 | import java.io.File
12 | import java.net.URL
13 | import java.nio.file.Files
14 | import java.nio.file.StandardCopyOption
15 |
16 | @Command(
17 | name = "install",
18 | mixinStandardHelpOptions = true,
19 | description = ["Installs a Agents."],
20 | )
21 | class InstallAgent : Runnable {
22 |
23 | @Parameters(
24 | index = "0",
25 | description = ["The name of the Agent to install."],
26 | )
27 | private var agent: String = ""
28 |
29 | override fun run() {
30 | if (agent.isEmpty()) {
31 | println("Invalid Agent name.")
32 | return
33 | }
34 | if (agent.contains(".") || agent.contains("/")) {
35 | println("Invalid Agent name. Please provide a valid Agent name without '.' or '/'...")
36 | return
37 | }
38 | println("Installing Arc Runner...")
39 | val fullName = "$agent.agent.kts"
40 | val `in` = URL("https://raw.githubusercontent.com/eclipse-lmos/arc/main/arc-runner/$fullName").openStream()
41 | Files.copy(`in`, File(home(), fullName).toPath(), StandardCopyOption.REPLACE_EXISTING)
42 | }
43 | }
--------------------------------------------------------------------------------
/arc-runner/src/main/kotlin/Set.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.runner
6 |
7 | import picocli.CommandLine.Command
8 | import picocli.CommandLine.Parameters
9 |
10 | @Command(
11 | name = "set",
12 | mixinStandardHelpOptions = true,
13 | description = ["Sets a property for the runner. The following properties are supported: ARC_AI_KEY, ARC_AI_URL, ARC_MODEL, ARC_CLIENT."],
14 | )
15 | open class SetProperty : Runnable {
16 |
17 | @Parameters(
18 | index = "0",
19 | description = ["The name of the property to set."],
20 | )
21 | private var name: String = ""
22 |
23 | @Parameters(
24 | index = "1",
25 | description = ["The value of the property to set."],
26 | )
27 | private var value: String = ""
28 |
29 | private val propertyNames: Set = setOf("ARC_AI_KEY", "ARC_AI_URL", "ARC_MODEL", "ARC_CLIENT")
30 |
31 | override fun run() {
32 | if (!propertyNames.contains(name)) {
33 | println("Invalid property name. Please provide a valid property name: $propertyNames")
34 | }
35 | if (value.isEmpty()) {
36 | println("Invalid property value. Property value cannot be empty.")
37 | }
38 | val properties = loadProperties()
39 | properties[name] = value
40 | properties.storeInHome()
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/arc-agents/src/test/kotlin/functions/JsonsTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.functions
6 |
7 | import org.assertj.core.api.Assertions.assertThat
8 | import org.eclipse.lmos.arc.agents.TestBase
9 | import org.eclipse.lmos.arc.core.Failure
10 | import org.eclipse.lmos.arc.core.getOrThrow
11 | import org.junit.jupiter.api.Test
12 |
13 | class JsonsTest : TestBase() {
14 |
15 | @Test
16 | fun `test convertToJsonMap`() {
17 | val jsonMap = """
18 | {
19 | "name": "Bard",
20 | "array": [1,2],
21 | "number": 3,
22 | "object": { "key": "value" }
23 | }
24 | """.convertToJsonMap().getOrThrow()
25 | assertThat(jsonMap["name"]).isEqualTo("Bard")
26 | assertThat(jsonMap["array"] as List).contains(1, 2)
27 | assertThat(jsonMap["number"] as Int).isEqualTo(3)
28 | assertThat(jsonMap["object"] as Map).containsEntry("key", "value")
29 | }
30 |
31 | @Test
32 | fun `test convertToJsonMap fails`() {
33 | val result = """
34 | {
35 | "name": "B
36 | """.convertToJsonMap()
37 | assertThat(result).isInstanceOf(Failure::class.java)
38 | assertThat((result as Failure).reason).isInstanceOf(InvalidJsonException::class.java)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/arc-graphql-spring-boot-starter/src/main/kotlin/EventsConfiguration.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.graphql
6 |
7 | import org.eclipse.lmos.arc.graphql.inbound.EventSubscription
8 | import org.eclipse.lmos.arc.graphql.inbound.EventSubscriptionHolder
9 | import org.springframework.boot.autoconfigure.condition.AnyNestedCondition
10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
11 | import org.springframework.context.annotation.Bean
12 | import org.springframework.context.annotation.Conditional
13 | import org.springframework.context.annotation.Configuration
14 | import org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase
15 |
16 | @Configuration(proxyBeanMethods = false)
17 | @Conditional(DevModeOrEnabled::class)
18 | open class EventsConfiguration {
19 |
20 | @Bean
21 | fun eventSubscriptionHolder() = EventSubscriptionHolder()
22 |
23 | @Bean
24 | fun eventSubscription(eventSubscriptionHolder: EventSubscriptionHolder) = EventSubscription(eventSubscriptionHolder)
25 | }
26 |
27 | class DevModeOrEnabled : AnyNestedCondition(ConfigurationPhase.PARSE_CONFIGURATION) {
28 | @ConditionalOnProperty("arc.chat.ui.enabled", havingValue = "true")
29 | class UIEnabled
30 |
31 | @ConditionalOnProperty("arc.subscriptions.events.enable", havingValue = "true")
32 | class Enable
33 | }
34 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/extensions/Data.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.agents.dsl
5 |
6 | import org.eclipse.lmos.arc.agents.events.BaseEvent
7 | import org.eclipse.lmos.arc.agents.events.Event
8 | import org.eclipse.lmos.arc.agents.events.EventPublisher
9 |
10 | /**
11 | * Local variable where the LLM data is stored.
12 | */
13 | private const val LOCAL_LLM_DATA = "LOCAL_LLM_DATA"
14 |
15 | /**
16 | * The piece of data that is feed to the LLM.
17 | */
18 | data class Data(val name: String, val data: String)
19 |
20 | /**
21 | * Gets and sets the current data sources.
22 | */
23 | fun DSLContext.getData(): List? = getLocal(LOCAL_LLM_DATA) as? List?
24 | suspend fun DSLContext.addData(data: Data) {
25 | val dataList = getLocal(LOCAL_LLM_DATA) as? List? ?: emptyList()
26 | setLocal(LOCAL_LLM_DATA, dataList + data)
27 | getOptional()?.publish(DataAddedEvent(data.name, data.data))
28 | }
29 |
30 | /**
31 | * Get system prompt
32 | */
33 | fun DSLContext.getSystemPrompt(): Data? = getData()?.firstOrNull { it.name == "systemPrompt" }
34 | suspend fun DSLContext.setSystemPrompt(prompt: String) {
35 | addData(Data("systemPrompt", prompt))
36 | }
37 |
38 | /**
39 | * Event that is published when new data is added.
40 | */
41 | data class DataAddedEvent(val name: String, val data: String) : Event by BaseEvent()
42 |
--------------------------------------------------------------------------------
/arc-server/src/main/kotlin/Skills.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.server.ktor
5 |
6 | import kotlinx.serialization.Serializable
7 |
8 | @Serializable
9 | data class AgentCard(
10 | val name: String,
11 | val description: String,
12 | val url: String,
13 | val provider: Provider? = null,
14 | val version: String,
15 | val documentationUrl: String? = null,
16 | val capabilities: Capabilities,
17 | val authentication: Authentication? = null,
18 | val defaultInputModes: List,
19 | val defaultOutputModes: List,
20 | val skills: List,
21 | )
22 |
23 | @Serializable
24 | data class Authentication(
25 | val schemes: List,
26 | val credentials: String? = null,
27 | )
28 |
29 | @Serializable
30 | data class Capabilities(
31 | val streaming: Boolean = false,
32 | val pushNotifications: Boolean = false,
33 | val stateTransitionHistory: Boolean = false,
34 | )
35 |
36 | @Serializable
37 | data class Skill(
38 | val id: String,
39 | val name: String,
40 | val description: String? = null,
41 | val tags: List? = null,
42 | val examples: List? = null,
43 | val inputModes: List? = null,
44 | val outputModes: List? = null,
45 | )
46 |
47 | @Serializable
48 | data class Provider(
49 | val organization: String,
50 | val url: String,
51 | )
52 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/kotlin/usecases/VersionExtractorTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.usecases
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.agents.dsl.extensions.local
10 | import org.eclipse.lmos.arc.agents.dsl.withDSLContext
11 | import org.junit.jupiter.api.Test
12 |
13 | class VersionExtractorTest {
14 |
15 | @Test
16 | fun `test use case version id extraction from use cases`(): Unit = runBlocking {
17 | withDSLContext {
18 | val useCases = local("use_cases.md")!!.toUseCases()
19 | assertThat(useCases[1].version).isEqualTo("1.0.0")
20 | }
21 | }
22 |
23 | @Test
24 | fun `test use case version id extraction`() {
25 | val version = extractVersion("This is a use case ")
26 | assertThat(version).isEqualTo("1.0.0")
27 | }
28 |
29 | @Test
30 | fun `test use case version id extraction - case sensitive`() {
31 | val version = extractVersion("This is a use case ")
32 | assertThat(version).isEqualTo("1.0.0")
33 | }
34 |
35 | @Test
36 | fun `test use case version id extraction - empty strings`() {
37 | val version = extractVersion("This is a use case ")
38 | assertThat(version).isEqualTo("1.0.0")
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/arc-mcp/src/main/kotlin/Adapter.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.mcp
5 |
6 | import io.modelcontextprotocol.spec.McpSchema.Tool
7 | import org.eclipse.lmos.arc.agents.functions.ParameterSchema
8 | import org.eclipse.lmos.arc.agents.functions.ParametersSchema
9 |
10 | /**
11 | * Converts a [Tool] JsonSchema to a [ParametersSchema].
12 | */
13 | fun parameters(tool: Tool): ParametersSchema {
14 | return ParametersSchema(
15 | required = tool.inputSchema.required,
16 | type = tool.inputSchema.type,
17 | properties = tool.inputSchema.properties.mapValues { (_, v) ->
18 | val type = v as Map
19 | mapProperties(type)
20 | },
21 | )
22 | }
23 |
24 | private fun mapProperties(type: Map): ParameterSchema {
25 | return ParameterSchema(
26 | type = type["type"] as String,
27 | description = type["description"] as String?,
28 | name = type["name"] as String?,
29 | required = type["required"] as List?,
30 | items = (type["items"] as Map?)?.let { ParameterSchema(type = it["type"].toString()) },
31 | enum = (type["enum"] as List?)?.map { it.toString() },
32 | properties = (type["properties"] as Map?)?.mapValues { (_, v) ->
33 | val type = v as Map
34 | mapProperties(type)
35 | },
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/arc-openai-realtime-client/src/main/kotlin/sound/Pcm16ToWav.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agent.client.ws.sound
6 |
7 | import java.io.ByteArrayOutputStream
8 | import java.nio.ByteBuffer
9 | import java.nio.ByteOrder
10 |
11 | /**
12 | * Converts PCM data to a WAV file.
13 | */
14 | fun pcm16ToWav(pcmData: ByteArray, sampleRate: Int = 24000, channels: Int = 1): ByteArray {
15 | val byteRate = sampleRate * channels * 2 // Bytes per second
16 | val blockAlign = channels * 2 // Bytes per sample
17 | val chunkSize = 36 + pcmData.size // Chunk size, including header
18 |
19 | val header = ByteBuffer.allocate(44)
20 | header.order(ByteOrder.LITTLE_ENDIAN)
21 | header.put("RIFF".toByteArray())
22 | header.putInt(chunkSize)
23 | header.put("WAVE".toByteArray())
24 | header.put("fmt ".toByteArray())
25 | header.putInt(16) // Format chunk size
26 | header.putShort(1.toShort()) // Audio format (1 = PCM)
27 | header.putShort(channels.toShort())
28 | header.putInt(sampleRate)
29 | header.putInt(byteRate)
30 | header.putShort(blockAlign.toShort())
31 | header.putShort(16.toShort()) // Bits per sample
32 | header.put("data".toByteArray())
33 | header.putInt(pcmData.size)
34 |
35 | val outputFile = ByteArrayOutputStream()
36 | outputFile.write(header.array())
37 | outputFile.write(pcmData)
38 | return outputFile.toByteArray()
39 | }
40 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/AgentFactory.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl
6 |
7 | import org.eclipse.lmos.arc.agents.Agent
8 | import org.eclipse.lmos.arc.agents.ChatAgent
9 |
10 | /**
11 | * Factory for creating agents from Agent Definitions.
12 | */
13 | fun interface AgentFactory> {
14 | fun createAgent(agentDefinition: AgentDefinition): T
15 | }
16 |
17 | /**
18 | * Default implementation of [AgentFactory] that create [ChatAgent] instances from [AgentDefinition]s.
19 | */
20 | class ChatAgentFactory(private val beanProvider: BeanProvider) : AgentFactory {
21 |
22 | override fun createAgent(agentDefinition: AgentDefinition): ChatAgent {
23 | return ChatAgent(
24 | name = agentDefinition.name,
25 | description = agentDefinition.description,
26 | version = agentDefinition.version,
27 | activateOnFeatures = agentDefinition.activateOnFeatures,
28 | skills = agentDefinition.skills,
29 | model = agentDefinition.model,
30 | agentDefinition.settings,
31 | beanProvider,
32 | agentDefinition.systemPrompt,
33 | agentDefinition.toolsProvider,
34 | agentDefinition.outputFilter,
35 | agentDefinition.inputFilter,
36 | agentDefinition.onFail,
37 | agentDefinition.init,
38 | )
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/arc-scripting/src/main/kotlin/functions/ScriptDef.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.scripting.functions
6 |
7 | import org.eclipse.lmos.arc.agents.dsl.FunctionDefinitionContext
8 | import kotlin.script.experimental.annotations.KotlinScript
9 | import kotlin.script.experimental.api.*
10 | import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
11 | import kotlin.script.experimental.jvm.jvm
12 | import kotlin.script.experimental.jvm.jvmTarget
13 |
14 | /**
15 | * Configure Script Execution.
16 | */
17 | @KotlinScript(
18 | fileExtension = "functions.kts",
19 | compilationConfiguration = ScriptConfiguration::class,
20 | )
21 | abstract class ScriptDeps
22 |
23 | object ScriptConfiguration : ScriptCompilationConfiguration(
24 | {
25 | implicitReceivers(FunctionDefinitionContext::class)
26 |
27 | compilerOptions("-Xcontext-parameters")
28 |
29 | defaultImports(
30 | "org.eclipse.lmos.arc.agents.dsl.get",
31 | "org.eclipse.lmos.arc.agents.dsl.*",
32 | "org.eclipse.lmos.arc.core.*",
33 | "org.eclipse.lmos.arc.agents.dsl.extensions.*",
34 | )
35 |
36 | ide {
37 |
38 | acceptedLocations(ScriptAcceptedLocation.Everywhere)
39 | }
40 |
41 | jvm {
42 | jvmTarget("21")
43 | dependenciesFromCurrentContext(wholeClasspath = true)
44 | }
45 | },
46 | )
47 |
--------------------------------------------------------------------------------
/arc-agents/src/test/kotlin/DSLAgentsTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.junit.jupiter.api.Test
10 |
11 | class DSLAgentsTest : TestBase() {
12 |
13 | @Test
14 | fun `test loading agents`() {
15 | val agentBuilder = DSLAgents.init(chatCompleterProvider)
16 | agentBuilder.define {
17 | agent {
18 | name = "agent"
19 | description = "agent description"
20 | systemPrompt = { "does stuff" }
21 | }
22 | }
23 | val result = agentBuilder.getAgents()
24 | assertThat(result).hasSize(1)
25 | assertThat(result[0].name).isEqualTo("agent")
26 | }
27 |
28 | @Test
29 | fun `test loading functions`(): Unit = runBlocking {
30 | val agentBuilder = DSLAgents.init(chatCompleterProvider)
31 | agentBuilder.defineFunctions {
32 | function(
33 | name = "get_weather",
34 | description = "the weather service",
35 | params = types(string("location", "the location")),
36 | ) {
37 | "result"
38 | }
39 | }
40 | val result = agentBuilder.provideAll()
41 | assertThat(result).hasSize(1)
42 | assertThat(result[0].name).isEqualTo("get_weather")
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/examples/src/test/kotlin/McpApplication.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.examples.mcp
6 |
7 | import com.expediagroup.graphql.server.spring.GraphQLAutoConfiguration
8 | import org.eclipse.lmos.arc.graphql.AgentGraphQLAutoConfiguration
9 | import org.springframework.ai.tool.ToolCallbackProvider
10 | import org.springframework.ai.tool.annotation.Tool
11 | import org.springframework.ai.tool.method.MethodToolCallbackProvider
12 | import org.springframework.boot.autoconfigure.SpringBootApplication
13 | import org.springframework.boot.runApplication
14 | import org.springframework.context.annotation.Bean
15 | import org.springframework.stereotype.Service
16 |
17 | @SpringBootApplication(
18 | exclude = [
19 | AgentGraphQLAutoConfiguration::class,
20 | GraphQLAutoConfiguration::class,
21 | ],
22 | )
23 | open class McpApplication {
24 |
25 | @Bean
26 | open fun tools(bookService: BookService): ToolCallbackProvider {
27 | return MethodToolCallbackProvider.builder().toolObjects(bookService).build()
28 | }
29 | }
30 |
31 | @Service
32 | open class BookService {
33 |
34 | @Tool(description = "Gets a list of available books")
35 | open fun getBooks(): List {
36 | return listOf(Book("Spring Boot"), Book("Kotlin"))
37 | }
38 | }
39 |
40 | data class Book(val name: String)
41 |
42 | fun main(args: Array) {
43 | runApplication(*args)
44 | }
45 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/kotlin/usecases/ConditionalTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support.usecases
6 |
7 | import org.assertj.core.api.Assertions.assertThat
8 | import org.junit.jupiter.api.Test
9 |
10 | class ConditionalTest {
11 |
12 | @Test
13 | fun `matches returns true when no conditions`() {
14 | val conditional = Conditional(text = "Test")
15 | assertThat(conditional.matches(emptySet())).isTrue
16 | assertThat(conditional.matches(setOf("any"))).isTrue
17 | }
18 |
19 | @Test
20 | fun `matches returns true if all conditions are present`() {
21 | val conditional = Conditional(text = "Test", conditions = setOf("foo", "bar"))
22 | assertThat(conditional.matches(setOf("foo", "bar", "baz"))).isTrue
23 | }
24 |
25 | @Test
26 | fun `matches returns false if any condition is missing`() {
27 | val conditional = Conditional(text = "Test", conditions = setOf("foo", "bar"))
28 | assertThat(conditional.matches(setOf("foo"))).isFalse
29 | assertThat(conditional.matches(emptySet())).isFalse
30 | }
31 |
32 | @Test
33 | fun `plus operator concatenates text`() {
34 | val conditional = Conditional(text = "Hello")
35 | val result = conditional + " World"
36 | assertThat(result.text).isEqualTo("Hello World")
37 | assertThat(result.conditions).isEqualTo(conditional.conditions)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/arc-mcp/src/main/kotlin/McpToolsByEnvironment.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 | package org.eclipse.lmos.arc.mcp
5 |
6 | import org.eclipse.lmos.arc.agents.functions.LLMFunction
7 | import org.eclipse.lmos.arc.agents.functions.LLMFunctionLoader
8 | import org.eclipse.lmos.arc.agents.functions.ToolLoaderContext
9 | import org.slf4j.LoggerFactory
10 | import java.lang.System.getProperty
11 | import java.lang.System.getenv
12 | import java.time.Duration
13 |
14 | /**
15 | * Loads instances of [McpTools] from environment variables.
16 | * This class is set up to be discovered by the [LLMFunctionServiceLoader].
17 | */
18 | class McpToolsByEnvironment : LLMFunctionLoader {
19 |
20 | private val log = LoggerFactory.getLogger(javaClass)
21 |
22 | private val tools: List by lazy {
23 | val urls = getEnvironmentValue("ARC_MCP_TOOLS_URLS")?.split(",") ?: return@lazy emptyList()
24 | val cacheDuration = getEnvironmentValue("ARC_MCP_TOOLS_CACHE_DURATION")?.let { Duration.parse(it) }
25 | log.info("Loading MCP tools from URLs: $urls")
26 | urls.map { url ->
27 | McpTools(url.trim(), cacheDuration)
28 | }
29 | }
30 |
31 | override suspend fun load(context: ToolLoaderContext?): List {
32 | return tools.flatMap { it.load(context) }
33 | }
34 |
35 | private fun getEnvironmentValue(name: String): String? {
36 | return getProperty(name) ?: getenv(name)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/arc-streaming-spring-boot-starter/src/test/kotlin/TestApplication.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.ws
6 |
7 | import org.eclipse.lmos.arc.agent.client.ws.OpenAIRealtimeClient
8 | import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
9 | import org.eclipse.lmos.arc.agents.llm.ChatCompleterProvider
10 | import org.eclipse.lmos.arc.spring.Agents
11 | import org.springframework.boot.autoconfigure.SpringBootApplication
12 | import org.springframework.context.annotation.Bean
13 | import java.io.File
14 | import java.io.StringReader
15 | import java.util.*
16 | import java.util.concurrent.atomic.AtomicReference
17 |
18 | @SpringBootApplication
19 | open class TestApplication {
20 |
21 | val key = File(System.getProperty("user.home"), ".arc/arc.properties").readText().let {
22 | Properties().apply { load(StringReader(it)) }.getProperty("ARC_AI_KEY")
23 | }
24 |
25 | @Bean
26 | open fun myAgent(agent: Agents) = agent {
27 | name = "agent"
28 | filterInput {
29 | lastInputMessage.set(inputMessage)
30 | }
31 | prompt { "you are a helpful agent that tell funny jokes." }
32 | }
33 |
34 | @Bean
35 | open fun chatCompleterProvider() = ChatCompleterProvider {
36 | OpenAIRealtimeClient("wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2024-10-01", key)
37 | }
38 | }
39 |
40 | val lastInputMessage = AtomicReference()
41 |
--------------------------------------------------------------------------------
/adl-server/src/main/kotlin/inbound/AdlCompilerMutation.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.adl.server.inbound
6 |
7 | import com.expediagroup.graphql.generator.annotations.GraphQLDescription
8 | import com.expediagroup.graphql.server.operations.Mutation
9 | import org.eclipse.lmos.arc.assistants.support.usecases.UseCase
10 | import org.eclipse.lmos.arc.assistants.support.usecases.formatToString
11 | import org.eclipse.lmos.arc.assistants.support.usecases.toUseCases
12 |
13 | /**
14 | * GraphQL query for compiling ADL code.
15 | * Takes ADL code as input (string) and returns compiled output as a formatted string.
16 | */
17 | class AdlCompilerMutation : Mutation {
18 |
19 | /**
20 | * Compiles the given ADL code and returns the formatted output.
21 | * @param adl The ADL code to compile.
22 | * @return An object containing the compiled output as a string in the field 'compiledOutput'.
23 | */
24 | @GraphQLDescription("Compiles the given ADL code.")
25 | suspend fun compile(adl: String, conditionals: List = emptyList()): CompileResult {
26 | val useCases: List = adl.toUseCases()
27 | val compiledOutput = useCases.formatToString(conditions = conditionals.toSet())
28 | return CompileResult(compiledOutput)
29 | }
30 | }
31 |
32 | /**
33 | * Data class for the compile result.
34 | */
35 | data class CompileResult(val compiledOutput: String)
36 |
37 | data class AdlSource(val adl: String)
38 |
--------------------------------------------------------------------------------
/arc-assistants/src/test/kotlin/AlternativeSolutionFilterTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.assistants.support
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.agents.dsl.extensions.local
10 | import org.eclipse.lmos.arc.agents.dsl.withDSLContext
11 | import org.eclipse.lmos.arc.assistants.support.usecases.formatToString
12 | import org.eclipse.lmos.arc.assistants.support.usecases.toUseCases
13 | import org.junit.jupiter.api.Test
14 |
15 | class AlternativeSolutionFilterTest : TestBase() {
16 |
17 | @Test
18 | fun `test alternative solution filter`(): Unit = runBlocking {
19 | withDSLContext {
20 | val useCases = local("use_cases.md")!!.toUseCases()
21 | val parsedUseCases = useCases.formatToString()
22 | assertThat(parsedUseCases).doesNotContain("alternative")
23 | assertThat(parsedUseCases).contains("usecase1", "usecase2", "usecase3")
24 | }
25 | }
26 |
27 | @Test
28 | fun `test alternative solution filter with alternatives`(): Unit = runBlocking {
29 | withDSLContext {
30 | val useCases = local("use_cases.md")!!.toUseCases()
31 | val parsedUseCases = useCases.formatToString(setOf("usecase2"))
32 | assertThat(parsedUseCases).doesNotContain("Primary Solution")
33 | assertThat(parsedUseCases).contains("Alternative solution")
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/llm/ChatCompletionSettings.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.llm
6 |
7 | import kotlin.reflect.KClass
8 |
9 | data class ChatCompletionSettings(
10 | val temperature: Double? = null,
11 | val maxTokens: Int? = null,
12 | val topP: Double? = null,
13 | val topK: Int? = null,
14 | val n: Int? = null,
15 | val seed: Long? = null,
16 | val format: OutputFormat? = null,
17 | val model: String? = null,
18 | val deploymentName: String? = null,
19 | val outputSchema: OutputSchema? = null,
20 | ) {
21 | fun deploymentNameOrModel(): String? {
22 | return deploymentName ?: model
23 | }
24 | }
25 |
26 | enum class OutputFormat {
27 | TEXT,
28 | JSON,
29 | }
30 |
31 | data class OutputSchema(
32 | val name: String,
33 | val description: String,
34 | val type: KClass<*>,
35 | )
36 |
37 | /**
38 | * Assigns the deployment or model name to the settings.
39 | * If the settings are null, a new instance is created with the provided deployment name.
40 | *
41 | * @param deploymentOrModelName The deployment or model Name to assign.
42 | * @return The updated settings.
43 | */
44 | fun ChatCompletionSettings?.assignDeploymentNameOrModel(deploymentOrModelName: String?): ChatCompletionSettings? {
45 | if (this == null) return ChatCompletionSettings(deploymentName = deploymentOrModelName)
46 | if (this.deploymentName == null) return copy(deploymentName = deploymentOrModelName)
47 | return this
48 | }
49 |
--------------------------------------------------------------------------------
/arc-runner/weather.agent.kts:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | agent {
6 | name = "weather-agent"
7 | model = { "GPT-4o" }
8 | description = "A helpful assistant that can provide information about the weather."
9 | systemPrompt = {
10 | """
11 | # Goal
12 | You are a helpful assistant that provides weather information.
13 | You answer in a helpful and professional manner.
14 |
15 | ### Instructions
16 | - Only answer the customer question in a concise and short way.
17 | - Only provide information the user has explicitly asked for.
18 | - Use the "Weather" section to answer customers queries.
19 | - If the customer's question is on a topic not described in the "Knowledge" section, reply that you cannot help with that issue.
20 |
21 | ### Weather
22 | {
23 | "location": "Berlin",
24 | "weather": "Sunny with a temperature high of 30 degress",
25 | },
26 | {
27 | "location": "London",
28 | "weather": "21 degress",
29 | },
30 | {
31 | "location": "Paris",
32 | "weather": "36 degress",
33 | },
34 | {
35 | "location": "Madrid",
36 | "weather": "39 degress",
37 | },
38 | {
39 | "location": "Athens",
40 | "weather": "33 degress",
41 | },
42 | {
43 | "location": "New York",
44 | "weather": "26 degress",
45 | }
46 | """
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/arc-agents/src/test/kotlin/dsl/AgentSystemPromptTest.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl
6 |
7 | import kotlinx.coroutines.runBlocking
8 | import org.assertj.core.api.Assertions.assertThat
9 | import org.eclipse.lmos.arc.agents.ChatAgent
10 | import org.eclipse.lmos.arc.agents.TestBase
11 | import org.junit.jupiter.api.Test
12 |
13 | class AgentSystemPromptTest : TestBase() {
14 |
15 | @Test
16 | fun `test SystemPrompt output`(): Unit = runBlocking {
17 | val agent = agent {
18 | name = ""
19 | description = ""
20 | systemPrompt = {
21 | +"""first"""
22 | if (false) +"error"
23 | if (true) +"second"
24 | """third"""
25 | }
26 | }
27 | val (input, _) = executeAgent(agent as ChatAgent, "bad stuff here")
28 | assertThat(input.first().content).isEqualTo("firstsecondthird")
29 | }
30 |
31 | @Test
32 | fun `test SystemPrompt has access to context beans`(): Unit = runBlocking {
33 | val testString = "testString"
34 | val agent = agent {
35 | name = ""
36 | description = ""
37 | systemPrompt = {
38 | get()
39 | }
40 | }
41 | testBeanProvider.setContext(setOf(testString)) {
42 | val (input, _) = executeAgent(agent as ChatAgent, "bad stuff here")
43 | assertThat(input.first().content).isEqualTo("testString")
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/arc-agents/src/main/kotlin/dsl/extensions/Extract.kt:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: 2025 Deutsche Telekom AG and others
2 | //
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | package org.eclipse.lmos.arc.agents.dsl.extensions
6 |
7 | import org.eclipse.lmos.arc.agents.conversation.ConversationMessage
8 | import org.eclipse.lmos.arc.agents.dsl.DSLContext
9 | import org.eclipse.lmos.arc.agents.dsl.InputFilterContext
10 | import org.eclipse.lmos.arc.agents.dsl.OutputFilterContext
11 |
12 | /**
13 | * Extensions for extracting data from messages.
14 | */
15 |
16 | /**
17 | * Extracts email addresses from a message.
18 | */
19 | val EMAIL_PATTERN =
20 | Regex("""([a-zA-Z0-9.!#${'$'}%&'*+/=?^_`{|}~-]+)@([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,62}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}""")
21 |
22 | fun DSLContext.extractEmail(message: ConversationMessage): List {
23 | return EMAIL_PATTERN.findAll(message.content).map { it.value }.toList()
24 | }
25 |
26 | /**
27 | * Extracts urls from a message.
28 | */
29 | val URL_PATTERN =
30 | Regex("""(https|http)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]""")
31 |
32 | fun DSLContext.extractUrl(message: ConversationMessage): List {
33 | return URL_PATTERN.findAll(message.content).map { it.value }.toList()
34 | }
35 |
36 | /**
37 | * Extracts patterns from input or output.
38 | */
39 | fun OutputFilterContext.extract(pattern: Regex): List {
40 | return pattern.findAll(outputMessage.content).map { it.value }.toList()
41 | }
42 | fun InputFilterContext.extract(pattern: Regex): List {
43 | return pattern.findAll(inputMessage.content).map { it.value }.toList()
44 | }
45 |
--------------------------------------------------------------------------------