Skip to content

feat: the agent tool vocabulary #7

feat: the agent tool vocabulary

feat: the agent tool vocabulary #7

Workflow file for this run

name: CI
on:
push:
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
# Lint levels live in `[workspace.lints]` in the root Cargo.toml so local and
# CI runs agree; don't add a blanket RUSTFLAGS here.
CARGO_TERM_COLOR: always
jobs:
rust:
name: Rust
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
# This job executes repository code (cargo build/test); don't persist
# the token in git config.
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov
- uses: Swatinem/rust-cache@v2
- name: Check formatting
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Build
run: cargo build --all-targets --all-features
- name: Test
run: cargo test --all-features
- name: Test default features
run: cargo test
# This crate is the vocabulary both an agent harness and a host
# application link against, so its dependency list is a promise to both.
# That promise is invisible in a diff, because a forbidden dependency
# arrives transitively through a feature someone enabled one crate away —
# so it is asserted rather than documented.
#
# `tinyagents` is on the list for a structural reason, not a size one: it
# depends on *this* crate. An edge back would be a cycle, and the
# `context` module's erasure trait exists precisely to make one
# unnecessary. Everything else on the list is weight a tool author should
# not have to compile to write a tool.
#
# The FORWARD form is required. `cargo tree -i <crate> -p tinytools`
# discards the `-p` scope, prints the whole-workspace inverse tree, and
# exits 0 looking clean even when this crate is the one at fault.
- name: Assert the vocabulary crate stays dependency-light
run: |
set -euo pipefail
# Compare crate NAMES only. `cargo tree` prints each package as
# `name vX.Y.Z (/path/to/checkout)`, and a consumer may vendor this
# repository *underneath* one of the forbidden crates — tinyagents
# does exactly that — so grepping the raw line matches the path and
# reports a dependency that is not there. Cut the version and path off
# first.
package_names="$(cargo tree -p tinytools -e normal,build --prefix none \
| awk '{print $1}' | sort -u)"
# `grep -E` exits 1 on "no match", which is the success case here, so
# it cannot share a `set -e` pipeline with the commands that produced
# its input: that would abort the script on the very outcome we want.
# Capture its exit status explicitly and only tolerate exactly 1;
# anything else (a real grep failure, or a non-1 pipeline failure from
# cargo tree/awk/sort surfaced through `pipefail`) still fails the job.
forbidden=""
set +e
forbidden="$(printf '%s\n' "$package_names" \
| grep -Exi 'tinyagents|tinybus|tokio|reqwest|ureq|hyper|rusqlite|git2')"
grep_status=$?
set -e
if [ "$grep_status" -ne 0 ] && [ "$grep_status" -ne 1 ]; then
echo "dependency scan failed (grep exit $grep_status)" >&2
exit "$grep_status"
fi
if [ -n "$forbidden" ]; then
echo "tinytools pulled in a dependency its manifest forbids:" >&2
echo "$forbidden" >&2
echo >&2
echo "This crate is what a harness and a host both compile against." >&2
echo "It must stay free of agent harnesses, transports, async" >&2
echo "runtimes, HTTP clients and native libraries." >&2
exit 1
fi
- name: Require 90% line coverage in every source file
run: .github/scripts/check-file-coverage.sh 90 coverage.json
- name: Upload coverage report
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: coverage-json
path: coverage.json
if-no-files-found: ignore
docs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Build documentation
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --no-deps --all-features
msrv:
name: Minimum supported Rust version
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
# `rust-version` is inherited from `[workspace.package]`, so every member
# reports the same value. Read it off the package the module ships as
# rather than off `packages[0]`, whose order cargo does not promise.
- name: Read rust-version from Cargo.toml
id: msrv
run: |
set -euo pipefail
msrv="$(cargo metadata --format-version 1 --no-deps \
| jq -r '.packages[] | select(.name == "tinytools") | .rust_version')"
if [[ -z "$msrv" || "$msrv" == "null" ]]; then
echo "workspace.package.rust-version is not set in Cargo.toml" >&2
exit 1
fi
echo "version=$msrv" >> "$GITHUB_OUTPUT"
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ steps.msrv.outputs.version }}
- uses: Swatinem/rust-cache@v2
- name: Build with the declared MSRV
run: cargo build --all-targets --all-features
supply-chain:
name: Supply chain
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Check advisories, licenses, bans, and sources
uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check all