├── .gitignore
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── libs.versions.toml
├── iosApp
├── iosApp
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ ├── app-icon-1024.png
│ │ │ └── Contents.json
│ │ └── AccentColor.colorset
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── KMMViewModel.swift
│ ├── iOSApp.swift
│ ├── Info.plist
│ └── ContentView.swift
├── Configuration
│ └── Config.xcconfig
└── iosApp.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── joreilly.xcuserdatad
│ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
│ └── xcuserdata
│ └── joreilly.xcuserdatad
│ └── xcschemes
│ ├── xcschememanagement.plist
│ └── iosApp.xcscheme
├── composeApp
├── src
│ ├── androidMain
│ │ ├── res
│ │ │ ├── values
│ │ │ │ └── strings.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ ├── kotlin
│ │ │ └── dev
│ │ │ │ └── johnoreilly
│ │ │ │ └── climatetrace
│ │ │ │ ├── theme
│ │ │ │ ├── Color.kt
│ │ │ │ ├── Type.kt
│ │ │ │ └── Theme.kt
│ │ │ │ ├── agent
│ │ │ │ └── ClimateTraceAgent.android.kt
│ │ │ │ ├── di
│ │ │ │ └── Koin.android.kt
│ │ │ │ └── MainActivity.kt
│ │ └── AndroidManifest.xml
│ ├── commonMain
│ │ └── kotlin
│ │ │ ├── dev
│ │ │ ├── johnoreilly
│ │ │ │ ├── climatetrace
│ │ │ │ │ ├── remote
│ │ │ │ │ │ ├── requests.http
│ │ │ │ │ │ ├── PopulationApi.kt
│ │ │ │ │ │ └── ClimateTraceApi.kt
│ │ │ │ │ ├── .DS_Store
│ │ │ │ │ ├── ui
│ │ │ │ │ │ ├── theme
│ │ │ │ │ │ │ ├── Type.kt
│ │ │ │ │ │ │ ├── Dimension.kt
│ │ │ │ │ │ │ ├── Color.kt
│ │ │ │ │ │ │ └── Theme.kt
│ │ │ │ │ │ ├── ChartNode.kt
│ │ │ │ │ │ ├── CountryEmissionsScreen.kt
│ │ │ │ │ │ ├── CountryListScreen.kt
│ │ │ │ │ │ ├── utils
│ │ │ │ │ │ │ └── ResizablePanel.kt
│ │ │ │ │ │ ├── SectorEmissionsPieChart.kt
│ │ │ │ │ │ ├── CountryAssetEmissionsInfoTreeMapChart.kt
│ │ │ │ │ │ ├── CountryInfoDetailedView.kt
│ │ │ │ │ │ └── ClimateTraceScreen.kt
│ │ │ │ │ ├── agent
│ │ │ │ │ │ ├── AgentProvider.kt
│ │ │ │ │ │ ├── ExitTool.kt
│ │ │ │ │ │ ├── ClimateTraceTool.kt
│ │ │ │ │ │ └── ClimateTraceAgentProvider.kt
│ │ │ │ │ ├── data
│ │ │ │ │ │ └── ClimateTraceRepository.kt
│ │ │ │ │ ├── viewmodel
│ │ │ │ │ │ ├── CountryListViewModel.kt
│ │ │ │ │ │ ├── CountryDetailsViewModel.kt
│ │ │ │ │ │ └── AgentViewModel.kt
│ │ │ │ │ └── di
│ │ │ │ │ │ └── Koin.kt
│ │ │ │ └── .DS_Store
│ │ │ └── .DS_Store
│ │ │ └── App.kt
│ ├── wasmJsMain
│ │ ├── resources
│ │ │ ├── styles.css
│ │ │ └── index.html
│ │ └── kotlin
│ │ │ ├── main.kt
│ │ │ └── dev
│ │ │ └── johnoreilly
│ │ │ └── climatetrace
│ │ │ ├── agent
│ │ │ └── ClimateTraceAgent.wasmJs.kt
│ │ │ └── di
│ │ │ └── Koin.wasmjs.kt
│ ├── jvmMain
│ │ └── kotlin
│ │ │ ├── dev
│ │ │ └── johnoreilly
│ │ │ │ └── climatetrace
│ │ │ │ ├── di
│ │ │ │ ├── Koin.jvm.kt
│ │ │ │ └── Koin.desktop.kt
│ │ │ │ └── agent
│ │ │ │ └── ClimateTraceAgent.jvm.kt
│ │ │ └── main.kt
│ ├── iosMain
│ │ └── kotlin
│ │ │ ├── dev
│ │ │ └── johnoreilly
│ │ │ │ └── climatetrace
│ │ │ │ ├── agent
│ │ │ │ └── ClimateTraceAgent.ios.kt
│ │ │ │ └── di
│ │ │ │ └── Koin.ios.kt
│ │ │ └── MainViewController.kt
│ └── commonTest
│ │ └── kotlin
│ │ └── dev
│ │ └── johnoreilly
│ │ └── climatetrace
│ │ └── screen
│ │ └── ClimateTraceTestsScreen.kt
└── build.gradle.kts
├── agents
├── src
│ └── main
│ │ └── kotlin
│ │ ├── main.kt
│ │ └── adk
│ │ ├── DevUiMain.kt
│ │ ├── ClimateTraceTool.kt
│ │ └── adk_agent.kt
└── build.gradle.kts
├── renovate.json
├── .devcontainer
└── devcontainer.json
├── .junie
└── guidelines.md
├── .github
└── workflows
│ ├── android.yml
│ ├── junie.yml
│ ├── ios.yml
│ └── build-and-publish-web.yml
├── settings.gradle.kts
├── gradle.properties
├── mcp-server
├── desktop-extension
│ └── manifest.json
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ └── McpServer.kt
├── gradlew.bat
├── README.md
├── gradlew
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | /local.properties
2 | **/.DS_Store
3 | **/build/
4 | .kotlin
5 | .gradle
6 | **/.idea/*
7 |
8 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/iosApp/iosApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
--------------------------------------------------------------------------------
/iosApp/Configuration/Config.xcconfig:
--------------------------------------------------------------------------------
1 | TEAM_ID=
2 | BUNDLE_ID=dev.johnoreilly.climatetrace.ClimateTraceKMP
3 | APP_NAME=ClimateTraceKMP
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ClimateTraceKMP
3 |
--------------------------------------------------------------------------------
/agents/src/main/kotlin/main.kt:
--------------------------------------------------------------------------------
1 | import dev.johnoreilly.climatetrace.di.initKoin
2 |
3 | val koin = initKoin(enableNetworkLogs = true).koin
4 |
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/johnoreilly/climatetrace/remote/requests.http:
--------------------------------------------------------------------------------
1 | GET https://api.climatetrace.org/v6/definitions/countries
2 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:base"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/commonMain/kotlin/dev/.DS_Store
--------------------------------------------------------------------------------
/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
--------------------------------------------------------------------------------
/iosApp/iosApp/KMMViewModel.swift:
--------------------------------------------------------------------------------
1 | import ComposeApp
2 | import KMPObservableViewModelCore
3 |
4 | extension Kmp_observableviewmodel_coreViewModel: ViewModel { }
5 |
--------------------------------------------------------------------------------
/composeApp/src/wasmJsMain/resources/styles.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | width: 100%;
3 | height: 100%;
4 | margin: 0;
5 | padding: 0;
6 | overflow: hidden;
7 | }
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/johnoreilly/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/commonMain/kotlin/dev/johnoreilly/.DS_Store
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/johnoreilly/climatetrace/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/composeApp/src/commonMain/kotlin/dev/johnoreilly/climatetrace/.DS_Store
--------------------------------------------------------------------------------
/agents/src/main/kotlin/adk/DevUiMain.kt:
--------------------------------------------------------------------------------
1 | package adk
2 |
3 | import adk.ClimateTraceAgent.Companion.initAgent
4 | import com.google.adk.web.AdkWebServer
5 |
6 | fun main() {
7 | AdkWebServer.start(initAgent())
8 | }
9 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
--------------------------------------------------------------------------------
/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/joreilly.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joreilly/ClimateTraceKMP/HEAD/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/joreilly.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/iosApp/iosApp/iOSApp.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import ComposeApp
3 |
4 | @main
5 | struct iOSApp: App {
6 |
7 | init() {
8 | Koin_iosKt.doInitKoin()
9 | }
10 |
11 | var body: some Scene {
12 | WindowGroup {
13 | ContentView()
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/composeApp/src/jvmMain/kotlin/dev/johnoreilly/climatetrace/di/Koin.jvm.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.di
2 |
3 | import io.ktor.client.engine.HttpClientEngine
4 | import io.ktor.client.engine.java.Java
5 |
6 | actual fun createHttpClientEngine(): HttpClientEngine {
7 | return Java.create()
8 | }
--------------------------------------------------------------------------------
/iosApp/iosApp.xcodeproj/project.xcworkspace/xcuserdata/joreilly.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/composeApp/src/wasmJsMain/kotlin/main.kt:
--------------------------------------------------------------------------------
1 | import androidx.compose.ui.ExperimentalComposeUiApi
2 | import androidx.compose.ui.window.CanvasBasedWindow
3 | import androidx.compose.ui.window.ComposeViewport
4 |
5 | @OptIn(ExperimentalComposeUiApi::class)
6 | fun main() {
7 | ComposeViewport(content = { App() })
8 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Java",
3 | "image": "mcr.microsoft.com/devcontainers/java:1-21",
4 | "features": {
5 | "ghcr.io/devcontainers/features/java:1": {
6 | "version": "none",
7 | "installMaven": "true",
8 | "mavenVersion": "3.8.6",
9 | "installGradle": "true"
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "app-icon-1024.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | }
9 | ],
10 | "info" : {
11 | "author" : "xcode",
12 | "version" : 1
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/johnoreilly/climatetrace/ui/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package com.example.ui.theme
2 |
3 | import androidx.compose.material3.Typography
4 | import androidx.compose.ui.text.TextStyle
5 | import androidx.compose.ui.text.font.FontFamily
6 | import androidx.compose.ui.text.font.FontWeight
7 | import androidx.compose.ui.unit.sp
8 |
9 | val AppTypography = Typography()
10 |
--------------------------------------------------------------------------------
/.junie/guidelines.md:
--------------------------------------------------------------------------------
1 | # Project Guidelines
2 |
3 | ## Project Structure
4 | This is a Kotlin Multiplatform project with Compose Multiplatform that includes:
5 | * `composeApp` - Shared Kotlin code with Compose UI
6 | * `iosApp` - iOS application
7 |
8 | ## Building the Project
9 | When building this project, Junie should use the following Gradle task:
10 | ```
11 | :composeApp:compileKotlinJvm
12 | ```
13 |
--------------------------------------------------------------------------------
/composeApp/src/androidMain/kotlin/dev/johnoreilly/climatetrace/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.wordmaster.androidApp.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val Purple80 = Color(0xFFD0BCFF)
6 | val PurpleGrey80 = Color(0xFFCCC2DC)
7 | val Pink80 = Color(0xFFEFB8C8)
8 |
9 | val Purple40 = Color(0xFF6650a4)
10 | val PurpleGrey40 = Color(0xFF625b71)
11 | val Pink40 = Color(0xFF7D5260)
--------------------------------------------------------------------------------
/composeApp/src/wasmJsMain/resources/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ClimateTraceKMP
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcodeproj/xcuserdata/joreilly.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | iosApp.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | name: Android CI
2 |
3 | on: pull_request
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: macos-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v5
12 | - name: set up JDK 21
13 | uses: actions/setup-java@v5
14 | with:
15 | distribution: 'zulu'
16 | java-version: 21
17 | - name: Build android app
18 | run: ./gradlew assembleDebug
19 | - name: Run Unit Tests
20 | run: ./gradlew :composeApp:jvmTest
21 |
22 |
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/johnoreilly/climatetrace/agent/AgentProvider.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.agent
2 |
3 | import ai.koog.agents.core.agent.AIAgent
4 |
5 | /**
6 | * Interface for agent factory
7 | */
8 | interface AgentProvider {
9 | val description: String
10 |
11 | suspend fun provideAgent(
12 | onToolCallEvent: suspend (String) -> Unit,
13 | onErrorEvent: suspend (String) -> Unit,
14 | onAssistantMessage: suspend (String) -> String
15 | ): AIAgent
16 | }
17 |
--------------------------------------------------------------------------------
/composeApp/src/iosMain/kotlin/dev/johnoreilly/climatetrace/agent/ClimateTraceAgent.ios.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.agent
2 |
3 | import ai.koog.prompt.executor.clients.google.GoogleModels
4 | import ai.koog.prompt.executor.llms.all.simpleGoogleAIExecutor
5 | import ai.koog.prompt.executor.model.PromptExecutor
6 | import dev.johnoreilly.climatetrace.BuildKonfig
7 |
8 | actual fun getLLModel() = GoogleModels.Gemini2_5Flash
9 |
10 | actual fun getPromptExecutor(): PromptExecutor {
11 | return simpleGoogleAIExecutor(BuildKonfig.GEMINI_API_KEY)
12 | }
--------------------------------------------------------------------------------
/iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "originHash" : "88d7673b251b3cbb9c40069df64b8e0aa1c4062dac38b066e5314b1847241136",
3 | "pins" : [
4 | {
5 | "identity" : "kmp-observableviewmodel",
6 | "kind" : "remoteSourceControl",
7 | "location" : "https://github.com/rickclephas/KMP-ObservableViewModel.git",
8 | "state" : {
9 | "revision" : "f18dcd23199915f7134db9ef5b0d4425bf4edb91",
10 | "version" : "1.0.0-BETA-1"
11 | }
12 | }
13 | ],
14 | "version" : 3
15 | }
16 |
--------------------------------------------------------------------------------
/composeApp/src/androidMain/kotlin/dev/johnoreilly/climatetrace/agent/ClimateTraceAgent.android.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.agent
2 |
3 | import ai.koog.prompt.executor.clients.google.GoogleModels
4 | import ai.koog.prompt.executor.llms.all.simpleGoogleAIExecutor
5 | import ai.koog.prompt.executor.model.PromptExecutor
6 | import dev.johnoreilly.climatetrace.BuildKonfig
7 |
8 | actual fun getLLModel() = GoogleModels.Gemini2_5Flash
9 |
10 | actual fun getPromptExecutor(): PromptExecutor {
11 | return simpleGoogleAIExecutor(BuildKonfig.GEMINI_API_KEY)
12 | }
--------------------------------------------------------------------------------
/composeApp/src/wasmJsMain/kotlin/dev/johnoreilly/climatetrace/agent/ClimateTraceAgent.wasmJs.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.agent
2 |
3 | import ai.koog.prompt.executor.clients.google.GoogleModels
4 | import ai.koog.prompt.executor.llms.all.simpleGoogleAIExecutor
5 | import ai.koog.prompt.executor.model.PromptExecutor
6 | import dev.johnoreilly.climatetrace.BuildKonfig
7 |
8 | actual fun getLLModel() = GoogleModels.Gemini2_5Flash
9 |
10 | actual fun getPromptExecutor(): PromptExecutor {
11 | return simpleGoogleAIExecutor(BuildKonfig.GEMINI_API_KEY)
12 | }
--------------------------------------------------------------------------------
/.github/workflows/junie.yml:
--------------------------------------------------------------------------------
1 | name: Junie
2 | run-name: Junie run ${{ inputs.run_id }}
3 |
4 | permissions:
5 | contents: write
6 |
7 | on:
8 | workflow_dispatch:
9 | inputs:
10 | run_id:
11 | description: "id of workflow process"
12 | required: true
13 | workflow_params:
14 | description: "stringified params"
15 | required: true
16 |
17 | jobs:
18 | call-workflow-passing-data:
19 | uses: jetbrains-junie/junie-workflows/.github/workflows/ej-issue.yml@main
20 | with:
21 | workflow_params: ${{ inputs.workflow_params }}
22 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google {
4 | content {
5 | includeGroupByRegex("com\\.android.*")
6 | includeGroupByRegex("com\\.google.*")
7 | includeGroupByRegex("androidx.*")
8 | }
9 | }
10 | mavenCentral()
11 | gradlePluginPortal()
12 | }
13 | }
14 | dependencyResolutionManagement {
15 | repositories {
16 | google()
17 | mavenCentral()
18 | }
19 | }
20 |
21 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
22 | rootProject.name = "ClimateTraceKMP"
23 | include(":composeApp")
24 | include(":mcp-server")
25 | include(":agents")
26 |
--------------------------------------------------------------------------------
/composeApp/src/wasmJsMain/kotlin/dev/johnoreilly/climatetrace/di/Koin.wasmjs.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.di
2 |
3 | import dev.johnoreilly.climatetrace.remote.Country
4 | import io.github.xxfast.kstore.KStore
5 | import io.github.xxfast.kstore.storage.storeOf
6 | import io.ktor.client.engine.HttpClientEngine
7 | import io.ktor.client.engine.js.Js
8 | import org.koin.core.module.Module
9 | import org.koin.dsl.module
10 |
11 | actual fun dataModule(): Module = module {
12 | single>> {
13 | storeOf(key = "countries", default = emptyList())
14 | }
15 | }
16 | actual fun createHttpClientEngine(): HttpClientEngine {
17 | return Js.create()
18 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | kotlin.code.style=official
2 | kotlin.incremental.wasm=true
3 | kotlin.native.toolchain.enabled=false
4 |
5 | #Gradle
6 | # Increase Gradle and Kotlin compiler daemon memory to avoid GC overhead OOMs during compilation
7 | org.gradle.jvmargs=-Xmx6144M -Xms2048M -XX:MaxMetaspaceSize=1024M -Dfile.encoding=UTF-8
8 | kotlin.daemon.jvmargs=-Xmx4096M -Xms1024M
9 |
10 |
11 | #Android
12 | android.nonTransitiveRClass=true
13 | android.useAndroidX=true
14 |
15 | #Compose
16 | org.jetbrains.compose.experimental.wasm.enabled=true
17 | org.jetbrains.compose.experimental.jscanvas.enabled=true
18 |
19 |
20 | #MPP
21 | kotlin.mpp.androidSourceSetLayoutVersion=2
22 | kotlin.mpp.enableCInteropCommonization=true
23 |
24 |
25 |
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/johnoreilly/climatetrace/remote/PopulationApi.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.remote
2 |
3 | import io.ktor.client.HttpClient
4 | import io.ktor.client.call.body
5 | import io.ktor.client.request.get
6 | import kotlinx.serialization.Serializable
7 |
8 | @Serializable
9 | data class CountryResponse(
10 | val population: Long
11 | )
12 |
13 | class PopulationApi(
14 | private val client: HttpClient,
15 | private val baseUrl: String = "https://restcountries.com/v3.1/alpha/"
16 |
17 | ) {
18 | suspend fun getPopulation(countryCode: String): Long {
19 | val response = client.get("$baseUrl$countryCode")
20 | val countries = response.body>()
21 | return countries.firstOrNull()?.population ?: 0L
22 | }
23 | }
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/johnoreilly/climatetrace/ui/ChartNode.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.ui
2 |
3 | import androidx.compose.runtime.Stable
4 | import androidx.compose.ui.graphics.Color
5 |
6 | @Stable
7 | sealed class ChartNode {
8 |
9 | abstract val name: String
10 | abstract val value: Double
11 | abstract val percentage: Double
12 |
13 | @Stable
14 | data class Leaf(
15 | override val name: String,
16 | override val value: Double,
17 | override val percentage: Double,
18 | val color: Color,
19 | ) : ChartNode()
20 |
21 | @Stable
22 | data class Section(
23 | override val name: String,
24 | override val value: Double,
25 | override val percentage: Double,
26 | val color: Color?,
27 | ) : ChartNode()
28 | }
--------------------------------------------------------------------------------
/.github/workflows/ios.yml:
--------------------------------------------------------------------------------
1 | name: iOS CI
2 |
3 | on: pull_request
4 |
5 | # Cancel any current or previous job from the same PR
6 | concurrency:
7 | group: ios-${{ github.head_ref }}
8 | cancel-in-progress: true
9 |
10 |
11 | jobs:
12 | build:
13 | runs-on: macos-latest
14 | steps:
15 | - uses: actions/checkout@v5
16 | - uses: actions/setup-java@v5
17 | with:
18 | distribution: 'zulu'
19 | java-version: 21
20 |
21 | - name: Set Xcode Version 16.4
22 | shell: bash
23 | run: |
24 | xcodes select 16.4
25 |
26 | - name: Build iOS app
27 | run: xcodebuild -allowProvisioningUpdates -allowProvisioningUpdates -workspace iosApp/iosApp.xcodeproj/project.xcworkspace -configuration Debug -scheme iosApp -sdk iphoneos -destination name='iPhone 16'
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/composeApp/src/commonMain/kotlin/dev/johnoreilly/climatetrace/agent/ExitTool.kt:
--------------------------------------------------------------------------------
1 | package dev.johnoreilly.climatetrace.agent
2 |
3 | import ai.koog.agents.core.tools.SimpleTool
4 | import ai.koog.agents.core.tools.annotations.LLMDescription
5 | import kotlinx.serialization.Serializable
6 |
7 | object ExitTool : SimpleTool() {
8 | @Serializable
9 | data class Args(
10 | @property:LLMDescription("The result of the agent session. Default is empty, if there's no particular result.")
11 | val result: String = ""
12 | )
13 |
14 | override val argsSerializer = Args.serializer()
15 | override val description: String =
16 | "Exit the agent session with the specified result. Call this tool to finish the conversation with the user."
17 |
18 | override suspend fun doExecute(args: Args): String = args.result
19 | }
20 |
--------------------------------------------------------------------------------
/agents/src/main/kotlin/adk/ClimateTraceTool.kt:
--------------------------------------------------------------------------------
1 | package adk
2 |
3 | import dev.johnoreilly.climatetrace.data.ClimateTraceRepository
4 | import io.reactivex.rxjava3.core.Single
5 | import koin
6 | import kotlinx.coroutines.rx3.rxSingle
7 |
8 | class ClimateTraceTool {
9 |
10 | companion object {
11 | val climateTraceRepository = koin.get()
12 |
13 | @JvmStatic
14 | fun getCountries(): Single