├── 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 | --------------------------------------------------------------------------------