diff --git a/.gitattributes b/.gitattributes index 4257faf..c988d2b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,11 +1,15 @@ # # https://help.github.com/articles/dealing-with-line-endings/ # + +# Normalize line endings for all text files in the repository +* text=auto + # Linux start script should use lf -/gradlew text eol=lf binary +/gradlew text eol=lf # These are Windows script files and should use crlf -*.bat text eol=crlf binary +*.bat text eol=crlf # Binary files should be left untouched *.jar binary diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..c8bb664 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,31 @@ +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + # Wait a week after a release before proposing it, so a compromised or + # yanked version has time to be caught upstream. + cooldown: + default-days: 7 + groups: + github-actions: + patterns: + - "*" + + # gradle/libs.versions.toml, the settings.gradle.kts plugins, and the Gradle + # wrapper. Minor and patch updates share one PR; each major update gets its + # own, so a breaking release can be reviewed on its own. + - package-ecosystem: "gradle" + directory: "/" + schedule: + interval: "weekly" + cooldown: + default-days: 7 + open-pull-requests-limit: 10 + groups: + gradle-minor-and-patch: + update-types: + - "minor" + - "patch" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3e94a3..8ab6165 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,19 +18,21 @@ jobs: name: Build (JDK 21) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Set up JDK 21 - uses: actions/setup-java@v4 + uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: java-version: '21' distribution: temurin - name: Validate Gradle wrapper - uses: gradle/actions/wrapper-validation@v4 + uses: gradle/actions/wrapper-validation@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0 - name: Build run: ./gradlew build -x test --stacktrace diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b9c64a..d9646ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,42 @@ As of **1.2.0**, the template is versioned independently of the bundled the Vapi4k version it ships. Earlier entries (**1.7.0** and below) mirror the bundled Vapi4k library version. +## [1.2.2] - 2026-10-13 + +Maintenance release. Ships **Vapi4k 1.8.2**, **Ktor 3.6.0**, **Kotlin 2.4.21**, +and the **Gradle 9.8.1** wrapper. + +### Added +- Dependabot version updates (`.github/dependabot.yml`), weekly with a 7-day + cooldown before a new release is proposed: GitHub Actions in one grouped PR, + and the Gradle dependencies, plugins, and wrapper, with minor and patch + updates grouped and each major update in a PR of its own. +- `make versions-all` target that prints the dependency-updates plugin's full + report, including dependencies that are already up to date. + +### Changed +- Vapi4k upgraded to **1.8.2**; Ktor to **3.6.0**; Kotlin to **2.4.21**. +- Gradle wrapper upgraded to **9.8.1** (`gradlew.bat` regenerated). +- CI workflow actions upgraded to checkout **v7**, setup-java **v6**, and + gradle/actions **v6**. +- Gradle versions plugin upgraded to **0.66.0**, which adds the + `--output-formatter` option `make versions-all` relies on. +- `make versions` now lists only the dependencies with newer versions, plus any + that could not be checked, via an `outputFormatter` in `build.gradle.kts`. + Both `versions` targets run with `--no-parallel`. +- `CallCustomer.kt` uses `parseJson()` in place of `toJsonElement()`, which + Vapi4k 1.8.2 deprecates with its move to common-utils 5.x. +- `.gitattributes` normalizes line endings for all text files (`* text=auto`), + and `gradlew` / `*.bat` are no longer also marked `binary`, so they diff as + text. +- `CLAUDE.md` trimmed to the conventions the code does not already state. +- Documentation refreshed to match the shipped dependency versions + (`README.md`, `CLAUDE.md`, `llms.txt`). + +### Security +- The CI workflow pins every action to a commit SHA, and its checkout no + longer keeps the GitHub token in the workspace (`persist-credentials: false`). + ## [1.2.1] - 2026-08-01 Maintenance release. Ships **Vapi4k 1.8.1**, **Ktor 3.5.1**, **Kotlin 2.4.10**, @@ -136,7 +172,8 @@ Ships **Vapi4k 1.8.0**, **Ktor 3.5.1**, **Kotlin 2.4.0**, and the **Gradle ### Changed - Vapi4k pinned to **1.1.0**; Ktor upgraded to **3.0.1**; Kotlin **2.0.20**. -[1.2.1]: https://github.com/vapi4k/vapi4k-template/compare/e25364c...HEAD +[1.2.2]: https://github.com/vapi4k/vapi4k-template/compare/d49faf8...HEAD +[1.2.1]: https://github.com/vapi4k/vapi4k-template/compare/e25364c...d49faf8 [1.2.0-2026]: https://github.com/vapi4k/vapi4k-template/compare/8b86ea6...e25364c [1.7.0]: https://github.com/vapi4k/vapi4k-template/compare/c16fbbf...8b86ea6 [1.6.1]: https://github.com/vapi4k/vapi4k-template/compare/49dfb5f...1a3ec08 diff --git a/CLAUDE.md b/CLAUDE.md index f8c78aa..1da10fc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,43 +15,12 @@ java -jar build/libs/vapi4k-template.jar # Run the fat JAR ./gradlew dependencyUpdates # Check for dependency updates ``` -Makefile shortcuts: `make build`, `make jar`, `make run-jar`, `make build-docker`, `make run-docker`. - -## Architecture - -This is a ~220-line Kotlin template with three Vapi4k application types configured in a single Ktor server: - -**Application.kt** — Entry point (`fun main()`). Starts an embedded Ktor CIO server on port 8080 (or `PORT` env var). Installs the Vapi4k plugin with: - -- **Inbound call app** — responds to incoming calls (OpenAI GPT-4 Turbo + DeepGram Luna voice) -- **Outbound call app** (`/callCustomer`) — makes outbound calls (Anthropic Claude Opus 4 + ElevenLabs Paula voice) -- **Web app** (`/talkApp`) — browser-based talk button (Groq Llama3 70B + PlayHT Jack voice), serves UI at `GET /talk` - -Each app configures a model, voice provider, system message, and the `WeatherLookup` service tool. - -**Service Tools** — Defined as classes with `@ToolCall`-annotated methods and `@Param`-annotated parameters. -`WeatherLookup` demonstrates this pattern. The annotated method returns a String. - -**TalkPage.kt** — kotlinx.html DSL rendering the web talk page with `vapiTalkButton`. - -**CallCustomer.kt** — Standalone CLI entry point for triggering outbound calls via -`vapiApi().phone { outboundCall { ... } }`. +Makefile shortcuts: `make build`, `make jar`, `make run-jar`, `make build-docker`, `make run-docker`, +`make versions` (only outdated dependencies, via the `outputFormatter` in `build.gradle.kts`), and `make versions-all` +(the plugin's full report; `--output-formatter=plain` overrides that formatter). ## Key Conventions -- **Kotlin DSL-heavy**: Vapi4k configuration, Ktor routing, and HTML generation all use Kotlin DSL builders -- **Version catalog**: All dependency versions managed in `gradle/libs.versions.toml` -- **JVM 21**: Required by both `build.gradle.kts` (`jvmToolchain`) and `system.properties` (Heroku) -- **Code style**: ktlint / Kotlin official (`gradle.properties`) - -## Dependencies - -- **Kotlin** 2.4.10, **Ktor** 3.5.1, **Vapi4k** 1.8.1 -- Gradle with Kotlin DSL (version in `gradle/wrapper/gradle-wrapper.properties`) -- Two Vapi4k libraries: `vapi4k-core` (voice app framework) and `vapi4k-dbms` (persistence) -- All versions managed in `gradle/libs.versions.toml` — update versions there, not in `build.gradle.kts` - -## Deployment - -Supports Heroku (Procfile), Docker (Dockerfile with Alpine/JDK21), or standalone JAR. The Dockerfile runs as non-root -`vapi_user` with `-Xmx2048m`. +- **JVM 21**: pinned in *both* `build.gradle.kts` (`jvmToolchain`) and `system.properties` (Heroku). Changing one + without the other breaks Heroku deploys. +- **Version catalog**: update dependency versions in `gradle/libs.versions.toml`, not in `build.gradle.kts`. diff --git a/Makefile b/Makefile index 68548e0..8c7555d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: default help clean build jar run-jar refresh versions build-docker run-docker \ +.PHONY: default help clean build jar run-jar refresh versions versions-all build-docker run-docker \ push-docker release upgrade-wrapper \ _require-version _require-gradle-version _require-image @@ -30,8 +30,15 @@ run-jar: jar ## Build and run the fat JAR refresh: ## Refresh dependencies and check for updates ./gradlew --refresh-dependencies dependencyUpdates -versions: ## Check for available dependency updates - ./gradlew dependencyUpdates --no-configuration-cache +# dependencyUpdates is marked incompatible with the configuration cache (build.gradle.kts), so a run with the cache on +# builds an entry only to discard it, and says so. --no-configuration-cache skips the cache for this run instead. +# build.gradle.kts gives the task a formatter that lists only what is behind; versions-all names the plugin's own plain +# report, which also lists everything up to date. +versions: ## List the dependencies with newer versions, and any that could not be checked + ./gradlew dependencyUpdates --no-configuration-cache --no-parallel + +versions-all: ## The plugin's full dependency report, up-to-date dependencies included + ./gradlew dependencyUpdates --no-configuration-cache --no-parallel --output-formatter=plain build-docker: _require-version _require-image jar ## Build a single-arch Docker image tagged with the project version docker build -t $(IMAGE_NAME):$(VERSION) . diff --git a/README.md b/README.md index de45f02..563bd00 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Vapi4k Application Template -[![Kotlin version](https://img.shields.io/badge/kotlin-2.4.10-red?logo=kotlin)](http://kotlinlang.org) +[![Kotlin version](https://img.shields.io/badge/kotlin-2.4.21-red?logo=kotlin)](http://kotlinlang.org) [![ktlint](https://img.shields.io/badge/ktlint%20code--style-%E2%9D%A4-FF4081)](https://pinterest.github.io/ktlint/) This template is a starting point for creating a new [Vapi](https://vapi.ai) application using diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 941cdba..bf09111 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,36 +1,49 @@ -# Release Notes — v1.2.1 (2026-08-01) +# Release Notes — v1.2.2 (2026-10-13) The full version history is in [CHANGELOG.md](CHANGELOG.md). This file covers the most recent release only and is intended for use as the body of a GitHub release. -This is a maintenance release: dependency updates and documentation refreshes, -with no source or API changes. +This is a maintenance release: dependency and tooling updates, Dependabot, +a hardened CI workflow, and a one-line source change to follow a Vapi4k +deprecation. ## Highlights -- **Vapi4k 1.8.1** and **Kotlin 2.4.10** — upstream patch updates. Ktor stays - at **3.5.1** and the Gradle wrapper at **9.6.1**. -- **Gradle versions plugin 0.57.0.** The plugin has been relocated, so its id - changed from `com.github.ben-manes.versions` to - `io.github.ben-manes.versions`. `./gradlew dependencyUpdates` and - `make versions` behave the same. -- **Documentation refresh.** `README.md`, `CLAUDE.md`, and `llms.txt` now state - the shipped dependency versions. +- **Vapi4k 1.8.2**, **Ktor 3.6.0**, and **Kotlin 2.4.21** — the latest + upstream features and fixes. +- **Gradle 9.8.1 wrapper.** +- **Dependabot.** `.github/dependabot.yml` checks weekly and waits 7 days + after a release before proposing it. GitHub Actions updates arrive in one + grouped PR. Gradle dependencies, plugins, and the wrapper get one PR for all + minor and patch updates, and a PR of their own for each major update. +- **Newer, pinned CI actions.** `.github/workflows/ci.yml` moves to checkout + **v7**, setup-java **v6**, and gradle/actions **v6**, each pinned to a commit + SHA. The checkout no longer keeps the GitHub token in the workspace. +- **Shorter dependency reports.** `make versions` now lists only the + dependencies with newer versions, plus any that could not be checked. The new + `make versions-all` target prints the plugin's full report, up-to-date + dependencies included. The Gradle versions plugin moves to **0.66.0** to + support this. +- **`parseJson()` in `CallCustomer.kt`.** Vapi4k 1.8.2 moves to common-utils + 5.x, which deprecates `String.toJsonElement()` in favor of `parseJson()`. +- **Line-ending normalization.** `.gitattributes` now normalizes all text files, + keeping LF for `gradlew` and CRLF for `*.bat`. ## Upgrade notes -No source changes are required for a fork or downstream copy of this template. -To match this release: - -1. Pull the dependency versions from `gradle/libs.versions.toml` (Vapi4k - **1.8.1**, Ktor **3.5.1**, Kotlin **2.4.10**). -2. If you copied the versions-plugin declaration into your own build, update the - plugin id to `io.github.ben-manes.versions` — the old - `com.github.ben-manes.versions` id is no longer the published coordinate for - current releases. - -The Gradle wrapper is unchanged from 1.2.0 (**9.6.1**). +To bring a fork or downstream copy of this template up to this release: + +1. Upgrade the Gradle wrapper to **9.8.1** (`make upgrade-wrapper` or + `./gradlew wrapper --gradle-version 9.8.1`). +2. Pull the dependency versions from `gradle/libs.versions.toml` (Vapi4k + **1.8.2**, Ktor **3.6.0**, Kotlin **2.4.21**, versions plugin **0.66.0**). +3. Replace calls to `String.toJsonElement()` with `String.parseJson()` + (`import com.pambrose.common.json.parseJson`). The old function still + compiles but is deprecated. +4. To keep `make versions` short, copy the `outputFormatter` block from + `configureVersions()` in `build.gradle.kts`. Without it, both `versions` + targets print the full report. ## Build & run diff --git a/build.gradle.kts b/build.gradle.kts index b940877..52bf498 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -75,5 +75,23 @@ fun Project.configureVersions() { rejectVersionIf { isNonStable(candidate.version) && !isNonStable(currentVersion) } + + // Prints only what is behind, and what could not be checked. The plugin's own report, which + // `make versions-all` asks for with --output-formatter=plain, also lists every dependency + // already up to date. + outputFormatter { + val behind = outdated.dependencies.sortedBy { "${it.group}:${it.name}" } + if (behind.isEmpty()) println("All dependencies are up to date") + behind.forEach { d -> + val latest = with(d.available) { release ?: milestone ?: integration } + println(" - ${d.group}:${d.name} ${d.version} -> $latest") + } + unresolved.dependencies.sortedBy { "${it.group}:${it.name}" }.forEach { + println(" ? ${it.group}:${it.name}:${it.version} could not be checked") + } + if (gradle.current.isUpdateAvailable) { + println(" - Gradle ${gradle.running.version} -> ${gradle.current.version}") + } + } } } diff --git a/gradle.properties b/gradle.properties index 4d6c146..96e1836 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group = "com.myapp" -version=1.2.1 +version=1.2.2 kotlin.code.style=official org.gradle.configuration-cache=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bafc77d..f91bf0b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] -gradle-wrapper = "9.6.1" +gradle-wrapper = "9.8.1" jvm = "21" -kotlin = "2.4.10" -ktor = "3.5.1" -versions = "0.57.0" -vapi4k = "1.8.1" +kotlin = "2.4.21" +ktor = "3.6.0" +versions = "0.66.0" +vapi4k = "1.8.2" [libraries] vapi4k-core = { group = "com.vapi4k", name = "vapi4k-core", version.ref = "vapi4k" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index b1b8ef5..9fa7f28 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a9db115..2e7bb9f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 diff --git a/gradlew.bat b/gradlew.bat index 8508ef6..3185a43 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,82 +1,112 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem gradlew startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables, and ensure extensions are enabled -setlocal EnableExtensions - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -"%COMSPEC%" /c exit 1 - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -"%COMSPEC%" /c exit 1 - -:execute -@rem Setup the command line - - - -@rem Execute gradlew -@rem endlocal doesn't take effect until after the line is parsed and variables are expanded -@rem which allows us to clear the local environment before executing the java command -endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel - -:exitWithErrorLevel -@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts -"%COMSPEC%" /c exit %ERRORLEVEL% +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem gradlew startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +@rem Catch executions from older scripts and ensure they exit cleanly. +@rem This can be removed once we can be reasonably confident that few people +@rem will be migrating directly to this new wrapper. +goto afterSafetyNet +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +goto exitWithErrorLevel +:afterSafetyNet + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +1>&2 echo. +1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +1>&2 echo. +1>&2 echo Please set the JAVA_HOME variable in your environment to match the +1>&2 echo location of your Java installation. + +"%COMSPEC%" /c exit 1 +goto exitWithErrorLevel + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +1>&2 echo. +1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +1>&2 echo. +1>&2 echo Please set the JAVA_HOME variable in your environment to match the +1>&2 echo location of your Java installation. + +"%COMSPEC%" /c exit 1 +goto exitWithErrorLevel + +:execute +@rem Setup the command line + + + +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel + +@rem This label must not be changed. We rely on old scripts being able to jump to this point. +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/llms.txt b/llms.txt index c154492..e381386 100644 --- a/llms.txt +++ b/llms.txt @@ -21,9 +21,9 @@ Each app configures an AI model, a voice provider, a system message, and service ## Tech Stack -- **Language**: Kotlin 2.4.10 (JVM 21) -- **Web framework**: Ktor 3.5.1 with CIO engine -- **Voice AI**: Vapi4k 1.8.1 (`vapi4k-core` + `vapi4k-dbms`) via Maven Central +- **Language**: Kotlin 2.4.21 (JVM 21) +- **Web framework**: Ktor 3.6.0 with CIO engine +- **Voice AI**: Vapi4k 1.8.2 (`vapi4k-core` + `vapi4k-dbms`) via Maven Central - **Build**: Gradle with Kotlin DSL, version catalog (`gradle/libs.versions.toml`) - **HTML rendering**: kotlinx.html DSL - **Deployment**: Heroku (Procfile), Docker (Alpine + JDK 21), or standalone fat JAR @@ -43,6 +43,8 @@ Each app configures an AI model, a voice provider, a system message, and service ./gradlew buildFatJar # Create fat JAR ./gradlew runFatJar # Run the fat JAR ./gradlew dependencyUpdates # Check for dependency updates +make versions # List only the outdated dependencies +make versions-all # Full dependency report, up-to-date ones included ``` ## Documentation diff --git a/src/main/kotlin/com/myapp/CallCustomer.kt b/src/main/kotlin/com/myapp/CallCustomer.kt index 48c3e73..a22175d 100644 --- a/src/main/kotlin/com/myapp/CallCustomer.kt +++ b/src/main/kotlin/com/myapp/CallCustomer.kt @@ -1,6 +1,6 @@ package com.myapp -import com.pambrose.common.json.toJsonElement +import com.pambrose.common.json.parseJson import com.vapi4k.dsl.call.VapiApiImpl.Companion.vapiApi import io.ktor.client.statement.bodyAsText import kotlinx.coroutines.runBlocking @@ -18,6 +18,6 @@ fun main() { } println("Call status: ${callResp.status}") - println("Call response: ${callResp.bodyAsText().toJsonElement()}") + println("Call response: ${callResp.bodyAsText().parseJson()}") } } \ No newline at end of file