Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -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
31 changes: 31 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -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"
10 changes: 6 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
39 changes: 38 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**,
Expand Down Expand Up @@ -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
Expand Down
43 changes: 6 additions & 37 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
13 changes: 10 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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) .
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
57 changes: 35 additions & 22 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
18 changes: 18 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
}
}
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group = "com.myapp"
version=1.2.1
version=1.2.2

kotlin.code.style=official
org.gradle.configuration-cache=true
Expand Down
10 changes: 5 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -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" }
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Loading
Loading