From 183554df9bf3be959d822e6142eae06a41441ea5 Mon Sep 17 00:00:00 2001 From: vinodvx <8429554+vinodvx@users.noreply.github.com> Date: Sat, 18 Jul 2026 23:13:49 -0700 Subject: [PATCH] chore: extract agctl module and switch to Task --- .github/PULL_REQUEST_TEMPLATE.md | 4 +- .github/workflows/ci.yml | 42 +++++- .github/workflows/release.yml | 2 +- .goreleaser.yaml | 19 +-- CONTRIBUTING.md | 31 ++-- Makefile | 119 ---------------- README.md | 4 +- RELEASING.md | 4 +- Taskfile.yml | 144 ++++++++++++++++++- cmd/README.md | 44 +++--- cmd/Taskfile.yml | 79 +++++++++++ cmd/config.go | 14 +- cmd/config.sample.yaml | 14 +- cmd/go.mod | 97 +++++++++++++ cmd/go.sum | 234 +++++++++++++++++++++++++++++++ cmd/main.go | 10 +- docs/getting-started/cli.mdx | 41 +++--- docs/testing/eval-harness.mdx | 4 +- eval-harness/README.md | 2 +- go.mod | 8 +- 20 files changed, 692 insertions(+), 224 deletions(-) delete mode 100644 Makefile create mode 100644 cmd/Taskfile.yml create mode 100644 cmd/go.mod create mode 100644 cmd/go.sum diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e6befb4..9206d3a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,9 +16,9 @@ ## Checklist -- [ ] I have run `make check` +- [ ] I have run `task check` - [ ] I have run `task examples:all` -- [ ] I have run `make tidy` if I added or removed dependencies +- [ ] I have run `task tidy` if I added or removed dependencies - [ ] Commit messages follow [conventional commits](https://www.conventionalcommits.org) (e.g. `feat:`, `fix:`, `docs:`) - [ ] I have added/updated tests for my changes - [ ] Documentation is updated if needed diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9b32c7..3fd8f09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ # - PR to main: full checks + Codecov upload # - workflow_dispatch: same + Codecov upload (on-demand coverage report) # - Push / merge to main: no workflow (already validated on the PR) -# (Secret scanning: run `make secrets-scan` locally.) +# (Secret scanning: run `task secrets-scan` locally.) name: CI on: @@ -11,7 +11,7 @@ on: workflow_dispatch: jobs: - ci: + sdk: runs-on: ubuntu-latest steps: - name: Checkout @@ -21,19 +21,23 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: go.mod + cache-dependency-path: go.sum # v2 is built with Go >= 1.26; v1.x binaries refuse modules targeting go 1.26+ - name: Install golangci-lint run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest + - name: Install Task + run: go install github.com/go-task/task/v3/cmd/task@latest + - name: Lint - run: make lint + run: task lint - name: Test - run: make test + run: task test - name: Code coverage - run: make test-coverage + run: task test-coverage - name: Upload coverage to Codecov if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' @@ -44,7 +48,31 @@ jobs: files: ./coverage.out - name: Build - run: make build + run: task build + + # agctl CLI is its own module (cmd/go.mod). Runs the same lint/test/build gates + # that used to be covered when cmd was part of the SDK module. + agctl: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: cmd/go.mod + cache-dependency-path: cmd/go.sum + + - name: Install golangci-lint + run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest + + - name: Install Task + run: go install github.com/go-task/task/v3/cmd/task@latest + + - name: Check (lint + test + build) + working-directory: cmd + run: task check eval-harness: runs-on: ubuntu-latest @@ -56,6 +84,7 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: go.mod + cache-dependency-path: go.sum - name: Set up Node.js uses: actions/setup-node@v4 @@ -90,6 +119,7 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: go.mod + cache-dependency-path: go.sum - name: Install Task run: go install github.com/go-task/task/v3/cmd/task@latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1a52428..bb4b211 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -# Release: GoReleaser builds agentctl for multiple platforms, creates GitHub Release +# Release: GoReleaser builds agctl for multiple platforms, creates GitHub Release # Trigger: push a tag (v0.0.1, v1.0.0, etc.) # See RELEASING.md for maintainer checklist name: Release diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 4115981..15ee8da 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,4 +1,4 @@ -# GoReleaser config — builds agentctl for multiple platforms, creates GitHub Release +# GoReleaser config — builds agctl for multiple platforms, creates GitHub Release # See https://goreleaser.com/customization/ version: 2 @@ -6,9 +6,12 @@ version: 2 project_name: agent-sdk-go builds: - - id: agentctl - main: ./cmd - binary: agentctl + # agctl is a separate Go module in ./cmd (its go.mod replaces the SDK with ../), + # so the build runs inside that directory. + - id: agctl + dir: ./cmd + main: . + binary: agctl ldflags: - -s -w - -X=main.version={{.Tag}} @@ -23,11 +26,11 @@ builds: - CGO_ENABLED=0 archives: - - id: agentctl - format: tar.gz + - id: agctl + formats: [tar.gz] format_overrides: - goos: windows - format: zip + formats: [zip] checksum: name_template: "checksums.txt" @@ -42,7 +45,7 @@ release: go get github.com/agenticenv/agent-sdk-go@{{ .Tag }} ``` - ### Install agentctl (CLI) + ### Install agctl (CLI) Download the archive for your platform from the **Assets** below (Linux, macOS, Windows — amd64 and arm64). Then extract and add to your `PATH`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eae5147..1d16cd9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,10 +9,11 @@ Before contributing, ensure you have: | Requirement | Version / Notes | |-------------|-----------------| | **Go** | **Minimum `go 1.26.0`** (see the `go` line in `go.mod`; use that version or newer). | +| **Task** | Task runner for all dev commands (`task build`, `task check`, `task lint`, ...). Install: `go install github.com/go-task/task/v3/cmd/task@latest` or see [taskfile.dev/installation](https://taskfile.dev/installation/) | | **Temporal server** | Required only for Temporal runtime examples, CLI, and Temporal-specific tests — see [Temporal setup](temporal-setup.md). Unit tests and in-process runtime examples run without it. | -| **golangci-lint** | Required for `make lint` — install **v2** with Go **≥** the `go` line in `go.mod`: `go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest` | -| **gofmt** | `make lint` runs `gofmt -s` check first; run `make fmt` to apply `gofmt -s -w` project-wide | -| **misspell** | `make spell` or `make lint` — typos via `misspell` | +| **golangci-lint** | Required for `task lint` — install **v2** with Go **≥** the `go` line in `go.mod`: `go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest` | +| **gofmt** | `task lint` runs `gofmt -s` check first; run `task fmt` to apply `gofmt -s -w` project-wide | +| **misspell** | `task spell` or `task lint` — typos via `misspell` | ## Temporal setup @@ -59,10 +60,10 @@ Keep your branch short and descriptive. Sync with `main` before opening a PR: `g ### 3. Run checks before a PR ```bash -make check +task check ``` -Runs `fmt-check`, spell check, `make lint`, `make test`, `make build`, and `make secrets-scan` — same core gates as the main CI job (coverage is CI-only; use `make test-coverage` locally if you want a report). `make test` includes eval-harness Go tests; the full Promptfoo/DeepEval suite runs in CI and via `make eval-harness` (see below). +Runs `fmt-check`, spell check, `task lint`, `task test`, `task build`, and `task secrets-scan` — same core gates as the main CI job (coverage is CI-only; use `task test-coverage` locally if you want a report). `task test` includes eval-harness Go tests; the full Promptfoo/DeepEval suite runs in CI and via `task eval-harness` (see below). Also run the full example suite on any code change to catch regressions unit tests may miss: @@ -75,17 +76,17 @@ Requires Task, Docker, and LLM credentials — see [examples/README.md](examples If you change **agent behavior** (e.g. `pkg/agent`, `pkg/memory`, telemetry, tools, runtime) or **`eval-harness/`**, run: ```bash -make eval-harness +task eval-harness ``` Behavioral regression tests use mock LLM/tools and assert on run output — SDK changes can break them even when eval-harness files are untouched. Requires Node.js and Python 3.10+ — see [eval-harness/README.md](eval-harness/README.md). CI runs this automatically on PRs (`eval-harness` job). -**CI runs automatically** on pull requests to `main` (open a PR or push updates to an existing PR to re-run checks). Pushes or merges to `main` do not trigger CI; use **workflow_dispatch** in GitHub Actions for an on-demand run. Run `make check` locally before opening a PR; CI must pass on the PR before merge. +**CI runs automatically** on pull requests to `main` (open a PR or push updates to an existing PR to re-run checks). Pushes or merges to `main` do not trigger CI; use **workflow_dispatch** in GitHub Actions for an on-demand run. Run `task check` locally before opening a PR; CI must pass on the PR before merge. To run only tests (e.g. while iterating): ```bash -make test +task test ``` Or a specific package: @@ -94,20 +95,20 @@ Or a specific package: go test ./pkg/agent/... -count=1 -v ``` -### 4. Run linters (included in `make check`) +### 4. Run linters (included in `task check`) ```bash -make lint +task lint ``` -This runs `gofmt -s` check, `misspell`, `go vet`, and `golangci-lint`. Use when debugging a lint failure without re-running the full `make check`. +This runs `gofmt -s` check, `misspell`, `go vet`, and `golangci-lint`. Use when debugging a lint failure without re-running the full `task check`. **golangci-lint vs Go version:** If you see `the Go language version used to build golangci-lint is lower than the targeted Go version`, your `golangci-lint` binary is too old for this module (Go 1.26+ requires **golangci-lint v2**). Reinstall: `go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest`, ensure `$(go env GOPATH)/bin` is on `PATH` ahead of any older install, then run `golangci-lint version` — it should report **v2.x** and a Go build **≥ 1.26**. ### 5. Generate coverage ```bash -make test-coverage +task test-coverage # Open coverage.html in a browser ``` @@ -172,15 +173,15 @@ Using the SDK and ran into issues, unclear docs, or confusing behavior? **Raise ## What Contributors Must Follow 1. **Code quality** - - Run `make check` before submitting a PR (format, spell, lint, test, build, secrets scan). PRs must pass. + - Run `task check` before submitting a PR (format, spell, lint, test, build, secrets scan). PRs must pass. - Run `task examples:all` before submitting a PR to verify nothing in the example suite breaks (any code change — not only example edits). Requires Task, Docker, and LLM credentials — see [examples/README.md](examples/README.md). - New examples that support batch runs must be added to **`taskfiles/examples.yml`** (see §6). - - Run `make tidy` before committing if you add or remove dependencies. + - Run `task tidy` before committing if you add or remove dependencies. 2. **Tests** - Add tests for new features and bug fixes. - Unit tests go in `*_test.go` files alongside the code. - - Agent behavior changes (`pkg/agent`, `pkg/memory`, telemetry, tools, runtime) or **`eval-harness/`** edits — run `make eval-harness` before submitting a PR. + - Agent behavior changes (`pkg/agent`, `pkg/memory`, telemetry, tools, runtime) or **`eval-harness/`** edits — run `task eval-harness` before submitting a PR. 3. **Commits** - Use [conventional commits](https://www.conventionalcommits.org) — these drive the release changelog: diff --git a/Makefile b/Makefile deleted file mode 100644 index cdd8d2c..0000000 --- a/Makefile +++ /dev/null @@ -1,119 +0,0 @@ -.PHONY: build install test lint tidy clean fmt fmt-check spell secrets-scan check eval-harness - -BIN_DIR := cmd/bin -BINARY := $(BIN_DIR)/agentctl -GOPATH_BIN := $(shell go env GOPATH)/bin -# Coverage merges via covdata; with GOTOOLCHAIN=auto the fetched toolchain can fail on -# packages with no tests ("go: no such tool covdata"). Pin to the exact toolchain line in go.mod -# (e.g. go1.26.0) — the bare language version (go1.26) is not a valid toolchain name. -# https://github.com/golang/go/issues/75031 -GO_TOOLCHAIN := $(shell awk '/^toolchain / { print $$2; exit }' go.mod) -GOTOOLCHAIN_COVERAGE := $(GO_TOOLCHAIN)+auto -# Embedded in agentctl -version (git describe, or "dev" outside a repo) -VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo dev) -LDFLAGS := -ldflags "-X main.version=$(VERSION)" - -# Build the cmd binary into cmd/bin (default: `make` with no target runs build) -build: - @echo "==> Building..." - @mkdir -p $(BIN_DIR) - go build $(LDFLAGS) -o $(BINARY) ./cmd - @echo "==> Build complete: $(BINARY)" - -# Install agentctl to $(GOPATH)/bin (run agentctl from anywhere if that dir is in PATH) -install: build - @mkdir -p $(GOPATH_BIN) - cp $(BINARY) $(GOPATH_BIN)/agentctl - @echo "Installed to $(GOPATH_BIN)/agentctl" - -# Run Go tests (pkg, internal, eval-harness runner) -test: - @echo "==> Running tests..." - go test ./pkg/... -count=1 - go test ./internal/... -count=1 - go test ./eval-harness/... -count=1 - @echo "==> Tests complete" - -# Promptfoo + DeepEval (same as CI eval-harness job). Requires Node.js and Python 3.10+. -eval-harness: - @echo "==> Running eval-harness (Promptfoo + DeepEval)..." - cd eval-harness/promptfoo && npx --yes promptfoo@latest eval -c config.yaml - cd eval-harness/deepeval && \ - (test -d .venv || python3 -m venv .venv) && \ - .venv/bin/pip install -q -r requirements.txt && \ - .venv/bin/pytest test_agent.py -v - @echo "==> Eval-harness complete" - -# Run before push: lint, test, build, and secrets scan (same core gates as CI; no auto-format). -# Coverage is CI-only (`make test-coverage` when you want the report). If fmt-check fails, run `make fmt`. -check: lint test build secrets-scan - @echo "==> All checks passed (ready to push)" - -# Run tests with coverage -test-coverage: - @echo "==> Running tests with coverage..." - GOTOOLCHAIN=$(GOTOOLCHAIN_COVERAGE) go test ./... -count=1 -coverprofile=coverage.out - @echo "==> Total coverage:" - @go tool cover -func=coverage.out | grep '^total:' - go tool cover -html=coverage.out -o coverage.html - @echo "==> Coverage report: coverage.html" - -# Format all Go files (gofmt with simplify; same as many style checks) -fmt: - @echo "==> gofmt -s -w" - gofmt -s -w . - @echo "==> Format complete" - -# Fail if any .go file needs gofmt -s (run `make fmt` to fix) -fmt-check: - @echo "==> Checking gofmt -s..." - @files=$$(gofmt -s -l .); \ - if [ -n "$$files" ]; then \ - echo "These files are not gofmt -s formatted. Run: make fmt"; \ - echo "$$files"; \ - exit 1; \ - fi - @echo "==> gofmt -s OK" - -# Typos in tracked source only (skips node_modules, .next, and other gitignored paths). -spell: - @echo "==> misspell" - @files=$$(git ls-files -z -- '*.go' '*.md' '*.yaml' '*.yml'); \ - if [ -z "$$files" ]; then \ - echo "No files to spell-check"; \ - else \ - printf '%s' "$$files" | xargs -0 go run github.com/client9/misspell/cmd/misspell@latest -error; \ - fi - -# Run linters (gofmt -s, misspell, go vet + golangci-lint). -# Use golangci-lint v2 when go.mod is 1.26+ — v1.x binaries error on newer language targets. -lint: fmt-check spell - @echo "==> Checking lints (go vet + golangci-lint)..." - go vet ./... - golangci-lint run ./... - @echo "==> Lint complete" - -# Tidy module dependencies -tidy: - @echo "==> Tidying module dependencies..." - go mod tidy - @echo "==> Tidy complete" - -# Remove built binaries and generated artifacts -clean: - @echo "==> Cleaning..." - rm -rf $(BIN_DIR) - rm -f coverage.out coverage.html - @echo "==> Clean complete" - -# Scan tracked files for leaked secrets (install: https://github.com/gitleaks/gitleaks#installing) -secrets-scan: - @echo "==> gitleaks detect" - @if command -v gitleaks >/dev/null 2>&1; then \ - gitleaks detect --source . --verbose --redact; \ - elif command -v docker >/dev/null 2>&1; then \ - docker run --rm -v "$$(pwd):/repo" -w /repo zricethezav/gitleaks:latest detect --source=/repo --verbose --redact; \ - else \ - echo "Install gitleaks or Docker."; \ - exit 1; \ - fi diff --git a/README.md b/README.md index e1489c6..01343a7 100644 --- a/README.md +++ b/README.md @@ -115,9 +115,9 @@ Evaluate agent quality with Promptfoo and DeepEval — locally or in CI. See [ev See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, workflow, and guidelines. Project policies: [SECURITY.md](SECURITY.md) · [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) -Quick commands: `make check` | `make test` | `make lint` | `make fmt` | `make tidy` | `make test-coverage` +Quick commands (requires [Task](https://taskfile.dev)): `task check` | `task test` | `task lint` | `task fmt` | `task tidy` | `task test-coverage` -Coverage reports (PR and default branch) are on **[Codecov](https://app.codecov.io/gh/agenticenv/agent-sdk-go)**. Run `make test-coverage` locally to produce `coverage.out` and `coverage.html`. +Coverage reports (PR and default branch) are on **[Codecov](https://app.codecov.io/gh/agenticenv/agent-sdk-go)**. Run `task test-coverage` locally to produce `coverage.out` and `coverage.html`. ## License diff --git a/RELEASING.md b/RELEASING.md index 86ee83f..b61a59c 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -10,13 +10,13 @@ Only users with **push access** to the repository can create tags and trigger re 1. **You create and push a tag** (e.g. `v0.0.1`, `v1.0.0`, `v2.0.3`) 2. **GitHub Actions runs** the Release workflow via [GoReleaser](https://goreleaser.com) -3. **Builds** `agentctl` for Linux, macOS, and Windows (amd64 and arm64 where supported), embedding **`agentctl -version`** as the git tag (`ldflags -X main.version={{.Tag}}` in `.goreleaser.yaml`) +3. **Builds** `agctl` (its own module in `cmd/`) for Linux, macOS, and Windows (amd64 and arm64 where supported), embedding **`agctl -version`** as the git tag (`ldflags -X main.version={{.Tag}}` in `.goreleaser.yaml`) 4. **Creates a GitHub Release** with archives (tar.gz / zip) and a checksums file ## Checklist before tagging - [ ] CI is green on `main` (lint, test, build pass — see [Actions](https://github.com/agenticenv/agent-sdk-go/actions)) -- [ ] `make lint` and `make test` pass locally (or rely on CI) +- [ ] `task lint` and `task test` pass locally (or rely on CI) - [ ] Commit messages follow [conventional commits](https://www.conventionalcommits.org) for categorized changelog (feat:, fix:, docs:, etc.) - [ ] Version follows [semver](https://semver.org): - **Patch** (0.0.1 → 0.0.2): bug fixes, no API changes diff --git a/Taskfile.yml b/Taskfile.yml index f5b9bdd..ede7a01 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -1,8 +1,14 @@ version: '3' +silent: true + dotenv: ['examples/.env'] includes: + # agctl CLI — its own module in ./cmd; namespaced as `task cmd:build`, `task cmd:check`, etc. + cmd: + taskfile: cmd/Taskfile.yml + dir: cmd examples: taskfile: taskfiles/examples.yml flatten: true @@ -10,10 +16,146 @@ includes: taskfile: taskfiles/reports.yml flatten: true +vars: + # Coverage merges via covdata; with GOTOOLCHAIN=auto the fetched toolchain can fail on + # packages with no tests ("go: no such tool covdata"). Pin to the exact toolchain line in + # go.mod (e.g. go1.26.0) — the bare language version (go1.26) is not a valid toolchain name. + # https://github.com/golang/go/issues/75031 + GO_TOOLCHAIN: + sh: awk '/^toolchain / { print $2; exit }' go.mod + GOTOOLCHAIN_COVERAGE: '{{.GO_TOOLCHAIN}}+auto' + tasks: # ── Default ─────────────────────────────────────────────── default: desc: Show available tasks cmds: - - task --list \ No newline at end of file + - task --list + + # ── SDK library: build / test / lint (migrated from the Makefile) ── + + # Compile all SDK library packages. The agctl CLI is a separate module in ./cmd — + # build/install it with `task cmd:build` (or `task cmd:install`). + build: + desc: Compile all SDK library packages + cmds: + - echo "==> Building SDK packages..." + - go build ./... + - echo "==> Build complete" + + test: + desc: Run Go tests (pkg, internal, eval-harness runner) + cmds: + - echo "==> Running tests..." + - go test ./pkg/... -count=1 + - go test ./internal/... -count=1 + - go test ./eval-harness/... -count=1 + - echo "==> Tests complete" + + test-coverage: + desc: Run tests with coverage; writes coverage.out and coverage.html + env: + GOTOOLCHAIN: '{{.GOTOOLCHAIN_COVERAGE}}' + cmds: + - echo "==> Running tests with coverage..." + - go test ./... -count=1 -coverprofile=coverage.out + - echo "==> Total coverage:" + - go tool cover -func=coverage.out | grep '^total:' + - go tool cover -html=coverage.out -o coverage.html + - 'echo "==> Coverage report: coverage.html"' + + fmt: + desc: Format all Go files (gofmt -s -w) + cmds: + - echo "==> gofmt -s -w" + - gofmt -s -w . + - echo "==> Format complete" + + fmt-check: + desc: Fail if any Go file needs gofmt -s (run `task fmt` to fix) + cmds: + - | + echo "==> Checking gofmt -s..." + files=$(gofmt -s -l .) + if [ -n "$files" ]; then + echo "These files are not gofmt -s formatted. Run: task fmt" + echo "$files" + exit 1 + fi + echo "==> gofmt -s OK" + + spell: + desc: Spell-check tracked source only (skips gitignored paths) + cmds: + - | + echo "==> misspell" + files=$(git ls-files -z -- '*.go' '*.md' '*.yaml' '*.yml') + if [ -z "$files" ]; then + echo "No files to spell-check" + else + printf '%s' "$files" | xargs -0 go run github.com/client9/misspell/cmd/misspell@latest -error + fi + + lint: + desc: Run linters (gofmt -s check, misspell, go vet + golangci-lint) + cmds: + - task: fmt-check + - task: spell + - echo "==> Checking lints (go vet + golangci-lint)..." + - go vet ./... + - golangci-lint run ./... + - echo "==> Lint complete" + + tidy: + desc: Tidy module dependencies + cmds: + - echo "==> Tidying module dependencies..." + - go mod tidy + - echo "==> Tidy complete" + + clean: + desc: Remove built binaries and coverage artifacts + cmds: + - echo "==> Cleaning..." + - rm -rf cmd/bin + - rm -f coverage.out coverage.html + - echo "==> Clean complete" + + secrets-scan: + desc: Scan tracked files for leaked secrets (gitleaks) + cmds: + - | + echo "==> gitleaks detect" + if command -v gitleaks >/dev/null 2>&1; then + gitleaks detect --source . --verbose --redact + elif command -v docker >/dev/null 2>&1; then + docker run --rm -v "$(pwd):/repo" -w /repo zricethezav/gitleaks:latest detect --source=/repo --verbose --redact + else + echo "Install gitleaks or Docker." + exit 1 + fi + + eval-harness: + desc: Promptfoo + DeepEval (same as CI eval-harness job). Requires Node.js and Python 3.10+. + cmds: + - echo "==> Running eval-harness (Promptfoo + DeepEval)..." + - cd eval-harness/promptfoo && npx --yes promptfoo@latest eval -c config.yaml + - | + cd eval-harness/deepeval && \ + (test -d .venv || python3 -m venv .venv) && \ + .venv/bin/pip install -q -r requirements.txt && \ + .venv/bin/pytest test_agent.py -v + - echo "==> Eval-harness complete" + + # Run before push: SDK lint/test/build + secrets scan + agctl (cmd) checks — all CI gates locally. + # Coverage is CI-only (`task test-coverage` when you want the report). If fmt-check fails, run `task fmt`. + check: + desc: All CI gates locally (SDK lint/test/build + secrets scan + agctl checks) + cmds: + - task: lint + - task: test + - task: build + - task: secrets-scan + - task: cmd:check + - echo "==> All checks passed (ready to push)" diff --git a/cmd/README.md b/cmd/README.md index eeda919..cd1cdcf 100644 --- a/cmd/README.md +++ b/cmd/README.md @@ -1,18 +1,18 @@ # CLI -The `agentctl` CLI uses **agent-sdk-go**, which runs agents on the **Temporal** runtime. A **running Temporal server** is required. See **[Temporal setup](../temporal-setup.md)** for Docker, Temporal CLI, ports, Cloud, and self-hosted options. +`agctl` is the interactive CLI for **agent-sdk-go**. It is its **own Go module** (`cmd/go.mod`) so the SDK library stays free of CLI-only dependencies. Its `go.mod` uses `replace github.com/agenticenv/agent-sdk-go => ../` to build against the SDK in this repo, so **run every command from the `cmd/` directory** (or use the installed binary). Interactive conversation mode. Type prompts, get responses. Type `exit`, `quit`, or `bye` to end. ## Configuration -1. **Copy the sample config** and add your values: +1. **Copy the sample config** and add your values (from `cmd/`): ```bash - cp cmd/config.sample.yaml cmd/config.yaml + cp config.sample.yaml config.yaml ``` -2. **Edit `cmd/config.yaml`** with your Temporal host, LLM provider, API key, and model. Optional **MCP** servers live under `mcp.servers` in `config.sample.yaml`: set `enabled: true` on entries you want (stdio subprocess or `streamable_http` URL); leave others `enabled: false`. +2. **Edit `config.yaml`** with your Temporal host, LLM provider, API key, and model. Optional **MCP** servers live under `mcp.servers` in `config.sample.yaml`: set `enabled: true` on entries you want (stdio subprocess or `streamable_http` URL); leave others `enabled: false`. 3. **Optional:** Use environment variables to override (keeps secrets out of the config file): @@ -20,7 +20,7 @@ Interactive conversation mode. Type prompts, get responses. Type `exit`, `quit`, export AGENT_LLM_APIKEY=sk-your-key export AGENT_LLM_PROVIDER=openai export AGENT_LLM_MODEL=gpt-4o - go run ./cmd + go run . ``` - **config.sample.yaml** — template (committed to repo) @@ -32,47 +32,45 @@ The CLI uses `temporal.host`, `temporal.port`, and `temporal.namespace` from `co ## Run +From the `cmd/` directory: + ```bash -go run ./cmd +task run +# or +go run . ``` Or with a custom config path: ```bash -go run ./cmd -config cmd/config.yaml +go run . -config /path/to/config.yaml ``` ## Build -From project root: - -```bash -make build -./cmd/bin/agentctl -``` - -Or build manually with an embedded version (matches `make build`, which uses `git describe`): +Uses [Task](https://taskfile.dev) (`Taskfile.yml` in this directory). From `cmd/`: ```bash -go build -ldflags "-X main.version=$(git describe --tags --always --dirty 2>/dev/null || echo dev)" -o cmd/bin/agentctl ./cmd +task build +./bin/agctl ``` -A plain `go build ./cmd` leaves the version as `dev` until you pass `-ldflags`. **Release binaries** from GitHub get the tag via GoReleaser (see `.goreleaser.yaml`, `-X main.version=`). +`task build` embeds the version via `git describe` (`-ldflags "-X main.version=..."`). A plain `go build .` leaves the version as `dev`. **Release binaries** from GitHub get the tag via GoReleaser (see `../.goreleaser.yaml`, which builds this module with `dir: ./cmd`). The `cmd/bin/` directory is gitignored. ## Install -Install `agentctl` to `$(go env GOPATH)/bin` so you can run it from anywhere (ensure that directory is in your PATH): +Install `agctl` to `$(go env GOPATH)/bin` so you can run it from anywhere (ensure that directory is in your PATH). From `cmd/`: ```bash -make install -agentctl -config cmd/config.yaml +task install +agctl -config config.yaml ``` ## Config file and env vars -Config is loaded from `cmd/config.yaml` (default). If the file does not exist, defaults plus env vars are used. +Config is loaded from `config.yaml` in the current directory (default; run from `cmd/`). Override with `-config `. If the file does not exist, defaults plus env vars are used. | Env var | Description | |---------|-------------| @@ -82,7 +80,7 @@ Config is loaded from `cmd/config.yaml` (default). If the file does not exist, d | `AGENT_LLM_MODEL` | e.g. `gpt-4o`, `claude-haiku-4-5`, `gemini-2.5-flash` | | `AGENT_LLM_BASEURL` | Optional; for OpenAI-compatible proxies | | `AGENT_LOGGER_LEVEL` | `error` (default), `warn`, `info`, `debug` | -| `AGENT_LOGGER_OUTPUT` | Log file path; default `cmd/logs/agent.log` | +| `AGENT_LOGGER_OUTPUT` | Log file path; default `cmd/logs/agctl.log` | | `AGENT_SHOW_LLM_USAGE` | When `true`, print accumulated session token usage on exit (`show_llm_usage` in config) | ### MCP (optional) @@ -95,6 +93,6 @@ When at least one server is enabled, the CLI registers **`WithMCPConfig`** and * The CLI shows only **user prompts and agent responses** on the console. Internal logs go to a file. -- **Default log file:** `cmd/logs/agent.log` (resolved from project root; gitignored) +- **Default log file:** `cmd/logs/agctl.log` (resolved from the module root; gitignored) - **Configure:** Set `logger.output` in `config.yaml` or `AGENT_LOGGER_OUTPUT` - **Directories:** `logs/` and `cmd/bin/` are gitignored diff --git a/cmd/Taskfile.yml b/cmd/Taskfile.yml new file mode 100644 index 0000000..7d5c046 --- /dev/null +++ b/cmd/Taskfile.yml @@ -0,0 +1,79 @@ +# Taskfile for the agctl CLI (its own Go module). +# Install Task: https://taskfile.dev/installation/ +# Run from the cmd/ directory: `task` (lists tasks), `task build`, `task run -- -config config.yaml`. +version: "3" + +silent: true + +vars: + BIN_DIR: bin + BINARY: bin/agctl + GOPATH_BIN: + sh: echo "$(go env GOPATH)/bin" + +tasks: + # Bare `task` (no args) lists available tasks instead of running a build. + default: + desc: List available tasks + cmds: + - task --list + + build: + # Local builds leave main.version at its default ("dev"); release builds are + # stamped with the git tag by GoReleaser (see ../.goreleaser.yaml). + desc: Build the agctl binary into cmd/bin (version = dev) + cmds: + - mkdir -p {{.BIN_DIR}} + - go build -o {{.BINARY}} . + - 'echo "==> Built {{.BINARY}} (dev)"' + + install: + desc: Install agctl to $(go env GOPATH)/bin + deps: [build] + cmds: + - cp {{.BINARY}} {{.GOPATH_BIN}}/agctl + - 'echo "==> Installed to {{.GOPATH_BIN}}/agctl"' + + run: + desc: 'Run agctl (pass flags after --, e.g. task run -- -config config.yaml)' + cmds: + - go run . {{.CLI_ARGS}} + + test: + desc: Run the cmd module tests + cmds: + - go test ./... -count=1 + + lint: + desc: Lint the cmd module (gofmt check, vet, golangci-lint) + cmds: + - test -z "$(gofmt -s -l .)" || (echo 'not gofmt -s formatted (run task fmt)' && exit 1) + - go vet ./... + - golangci-lint run ./... + + check: + desc: All cmd checks (lint + test + build) — mirrors the CI agctl job + cmds: + - task: lint + - task: test + - task: build + + fmt: + desc: Format Go files (gofmt -s) + cmds: + - gofmt -s -w . + + vet: + desc: go vet + cmds: + - go vet ./... + + tidy: + desc: Tidy module dependencies + cmds: + - go mod tidy + + clean: + desc: Remove built binaries + cmds: + - rm -rf {{.BIN_DIR}} diff --git a/cmd/config.go b/cmd/config.go index de01d5a..8a21646 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -216,7 +216,7 @@ type LLMConfig struct { type LoggerConfig struct { Level string `mapstructure:"level"` - Output string `mapstructure:"output"` // stdout | stderr | file path; default resolves to cmd/logs/agent.log + Output string `mapstructure:"output"` // stdout | stderr | file path; default resolves to cmd/logs/agctl.log Format string `mapstructure:"format"` // text | json (file/stdout/stderr) AddSource bool `mapstructure:"add_source"` // include file:line in each log line (slog source) TeeStderr bool `mapstructure:"tee_stderr"` // when output is a file, also copy to stderr (usually off so the REPL stays clean) @@ -227,7 +227,7 @@ type LoggerConfig struct { func LoadConfig(path string) (*Config, error) { v := viper.New() if path == "" { - path = "cmd/config.yaml" + path = "config.yaml" } v.SetConfigFile(path) v.SetConfigType("yaml") @@ -262,7 +262,7 @@ func LoadConfig(path string) (*Config, error) { v.SetDefault("llm.model", "gpt-4o") v.SetDefault("llm.baseURL", "") v.SetDefault("logger.level", "error") - v.SetDefault("logger.output", "logs/agent.log") + v.SetDefault("logger.output", "logs/agctl.log") v.SetDefault("logger.format", "json") v.SetDefault("logger.add_source", true) v.SetDefault("logger.tee_stderr", false) @@ -397,12 +397,12 @@ func getLogOutput(cfg *LoggerConfig) string { if cfg != nil && cfg.Output != "" { output = strings.TrimSpace(cfg.Output) } - if output == "" || output == "logs/agent.log" { - // Default: resolve to cmd/logs/agent.log so logs stay inside cmd/ regardless of cwd + if output == "" || output == "logs/agctl.log" { + // Default: resolve to /logs/agctl.log so logs stay inside cmd/ regardless of cwd if root := findProjectRoot(); root != "" { - output = filepath.Join(root, "cmd", "logs", "agent.log") + output = filepath.Join(root, "logs", "agctl.log") } else { - output = filepath.Join("cmd", "logs", "agent.log") + output = filepath.Join("logs", "agctl.log") } } return output diff --git a/cmd/config.sample.yaml b/cmd/config.sample.yaml index 3237ffa..27746e9 100644 --- a/cmd/config.sample.yaml +++ b/cmd/config.sample.yaml @@ -1,18 +1,18 @@ # agent-sdk-go CLI configuration sample # -# 1. Copy this file to config.yaml: -# cp cmd/config.sample.yaml cmd/config.yaml +# 1. Copy this file to config.yaml (run from the cmd/ directory): +# cp config.sample.yaml config.yaml # -# 2. Edit cmd/config.yaml with your values (API keys, Temporal host, etc.) -# 3. Run: go run ./cmd or ./cmd/bin/agentctl -config cmd/config.yaml +# 2. Edit config.yaml with your values (API keys, Temporal host, etc.) +# 3. Run: task run or go run . or ./bin/agctl -config config.yaml # # Environment variables with AGENT_ prefix override file values. -# Example: AGENT_LLM_APIKEY=sk-xxx AGENT_LLM_PROVIDER=openai go run ./cmd +# Example: AGENT_LLM_APIKEY=sk-xxx AGENT_LLM_PROVIDER=openai go run . # Runtime: local (default) or temporal. # local — runs entirely in-process; no Temporal server required. # temporal — durable execution via Temporal; requires a running Temporal server. -# Override per-run: AGENT_RUNTIME=temporal go run ./cmd +# Override per-run: AGENT_RUNTIME=temporal go run . runtime: local # Temporal connection (for durable agent execution) @@ -32,7 +32,7 @@ llm: # Logger: file by default (JSON + caller). Prompts/responses use fmt in main, not this logger. logger: level: info # error | warn | info | debug - output: logs/agent.log # file path | stdout | stderr + output: logs/agctl.log # file path | stdout | stderr format: json # json | text add_source: false tee_stderr: false diff --git a/cmd/go.mod b/cmd/go.mod new file mode 100644 index 0000000..cc84505 --- /dev/null +++ b/cmd/go.mod @@ -0,0 +1,97 @@ +module github.com/agenticenv/agent-sdk-go/cmd + +go 1.26 + +toolchain go1.26.0 + +replace github.com/agenticenv/agent-sdk-go => ../ + +require ( + github.com/agenticenv/agent-sdk-go v0.0.0-00010101000000-000000000000 + github.com/spf13/viper v1.21.0 + golang.org/x/oauth2 v0.35.0 +) + +require ( + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.18.1 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + github.com/a2aproject/a2a-go/v2 v2.2.1 // indirect + github.com/anthropics/anthropic-sdk-go v1.26.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/jsonschema-go v0.4.2 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect + github.com/googleapis/gax-go/v2 v2.17.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect + github.com/modelcontextprotocol/go-sdk v1.4.0 // indirect + github.com/nexus-rpc/sdk-go v0.6.0 // indirect + github.com/openai/openai-go/v3 v3.26.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/robfig/cron v1.2.0 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/segmentio/asm v1.1.3 // indirect + github.com/segmentio/encoding v0.5.4 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/stretchr/objx v0.5.3 // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tidwall/gjson v1.18.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + github.com/yosida95/uritemplate/v3 v3.0.2 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 // indirect + go.opentelemetry.io/otel/log v0.19.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/sdk v1.43.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/proto/otlp v1.10.0 // indirect + go.temporal.io/api v1.62.2 // indirect + go.temporal.io/sdk v1.41.0 // indirect + go.temporal.io/sdk/contrib/opentelemetry v0.7.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/crypto v0.49.0 // indirect + golang.org/x/mod v0.33.0 // indirect + golang.org/x/net v0.52.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.35.0 // indirect + golang.org/x/time v0.14.0 // indirect + google.golang.org/genai v1.51.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4 // indirect + google.golang.org/grpc v1.80.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/cmd/go.sum b/cmd/go.sum new file mode 100644 index 0000000..9763ae2 --- /dev/null +++ b/cmd/go.sum @@ -0,0 +1,234 @@ +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.18.1 h1:IwTEx92GFUo2pJ6Qea0EU3zYvKnTAeRCODxfA/G5UWs= +cloud.google.com/go/auth v0.18.1/go.mod h1:GfTYoS9G3CWpRA3Va9doKN9mjPGRS+v41jmZAhBzbrA= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +github.com/a2aproject/a2a-go/v2 v2.2.1 h1:NAfUoceWAStJ7FnF8TTfWuHejf9mzKgc9QmaKV1hyXw= +github.com/a2aproject/a2a-go/v2 v2.2.1/go.mod h1:mkZr8y2bUgAVQsjs/5fHK7xrRlAHDybMEyxWh2tKRC8= +github.com/anthropics/anthropic-sdk-go v1.26.0 h1:oUTzFaUpAevfuELAP1sjL6CQJ9HHAfT7CoSYSac11PY= +github.com/anthropics/anthropic-sdk-go v1.26.0/go.mod h1:qUKmaW+uuPB64iy1l+4kOSvaLqPXnHTTBKH6RVZ7q5Q= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= +github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8= +github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao= +github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8= +github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= +github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/modelcontextprotocol/go-sdk v1.4.0 h1:u0kr8lbJc1oBcawK7Df+/ajNMpIDFE41OEPxdeTLOn8= +github.com/modelcontextprotocol/go-sdk v1.4.0/go.mod h1:Nxc2n+n/GdCebUaqCOhTetptS17SXXNu9IfNTaLDi1E= +github.com/nexus-rpc/sdk-go v0.6.0 h1:QRgnP2zTbxEbiyWG/aXH8uSC5LV/Mg1fqb19jb4DBlo= +github.com/nexus-rpc/sdk-go v0.6.0/go.mod h1:FHdPfVQwRuJFZFTF0Y2GOAxCrbIBNrcPna9slkGKPYk= +github.com/openai/openai-go/v3 v3.26.0 h1:bRt6H/ozMNt/dDkN4gobnLqaEGrRGBzmbVs0xxJEnQE= +github.com/openai/openai-go/v3 v3.26.0/go.mod h1:cdufnVK14cWcT9qA1rRtrXx4FTRsgbDPW7Ia7SS5cZo= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= +github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc= +github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg= +github.com/segmentio/encoding v0.5.4 h1:OW1VRern8Nw6ITAtwSZ7Idrl3MXCFwXHPgqESYfvNt0= +github.com/segmentio/encoding v0.5.4/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= +github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 h1:hhPGP3zvvy1xWT9RTy970wlniSxFttBIsAK1gvMguJM= +go.opentelemetry.io/contrib/bridges/otelslog v0.18.0/go.mod h1:twJF7inoMza6kxMcF8JOdL3mPmtOZu7GEr34CUNE6Dg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 h1:Dn8rkudDzY6KV9dr/D/bTUuWgqDf9xe0rr4G2elrn0Y= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0/go.mod h1:gMk9F0xDgyN9M/3Ed5Y1wKcx/9mlU91NXY2SNq7RQuU= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0 h1:BEbF7ZBB6qQloV/Ub1+3NQoOUnVtcGkU3XX4Ws3GQfk= +go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= +go.temporal.io/api v1.62.2 h1:jFhIzlqNyJsJZTiCRQmTIMv6OTQ5BZ57z8gbgLGMaoo= +go.temporal.io/api v1.62.2/go.mod h1:iaxoP/9OXMJcQkETTECfwYq4cw/bj4nwov8b3ZLVnXM= +go.temporal.io/sdk v1.41.0 h1:c9tayCQJDM5ZQdrqjGmjqk5ejxUtsEScJGF94sAVYpM= +go.temporal.io/sdk v1.41.0/go.mod h1:/InXQT5guZ6AizYzpmzr5avQ/GMgq1ZObcKlKE2AhTc= +go.temporal.io/sdk/contrib/opentelemetry v0.7.0 h1:GSna1HP+1ibNXZ9xlVdQU2zFVqdt5VcdF0dzpeaYccQ= +go.temporal.io/sdk/contrib/opentelemetry v0.7.0/go.mod h1:oQJC6UIl3FbSYh4f2MlUAIYSE6FPw02X1Tw8/bOvfxg= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= +golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genai v1.51.0 h1:IZGuUqgfx40INv3hLFGCbOSGp0qFqm7LVmDghzNIYqg= +google.golang.org/genai v1.51.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk= +google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4 h1:yOzSCGPx+cp5VO7IxvZ9SBFF7j1tZVcNtlHR2iYKtVo= +google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4/go.mod h1:Q9HWtNeE7tM9npdIsEvqXj1QJIvVoeAV3rtXtS715Cw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4 h1:tEkOQcXgF6dH1G+MVKZrfpYvozGrzb91k6ha7jireSM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cmd/main.go b/cmd/main.go index cb431d0..97ac728 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -24,20 +24,20 @@ import ( "github.com/agenticenv/agent-sdk-go/pkg/tools/wikipedia" ) -// version is set at link time by GoReleaser (release) or Makefile (local build). +// version is set at link time by GoReleaser (release) or Taskfile (local build). // Plain `go run` / `go build` without -ldflags leaves the default "dev". var version = "dev" const ( exitPrompt = "Type 'exit', 'quit', or 'bye' to end the conversation." - convID = "interactive-agentctl" + convID = "interactive-agctl" ) func main() { var configPath string var showVersion bool - flag.StringVar(&configPath, "config", "cmd/config.yaml", "path to config file (env overrides file values)") - flag.StringVar(&configPath, "c", "cmd/config.yaml", "alias for -config") + flag.StringVar(&configPath, "config", "config.yaml", "path to config file (env overrides file values)") + flag.StringVar(&configPath, "c", "config.yaml", "alias for -config") flag.BoolVar(&showVersion, "version", false, "print version and exit") flag.BoolVar(&showVersion, "v", false, "alias for -version") flag.Parse() @@ -91,7 +91,7 @@ func main() { }() opts := []agent.Option{ - agent.WithName("agentctl"), + agent.WithName("agctl"), agent.WithSystemPrompt("You are a helpful assistant."), agent.WithLLMClient(llmClient), agent.WithStream(true), diff --git a/docs/getting-started/cli.mdx b/docs/getting-started/cli.mdx index eb485aa..1d81eed 100644 --- a/docs/getting-started/cli.mdx +++ b/docs/getting-started/cli.mdx @@ -1,15 +1,15 @@ --- title: "CLI" -description: "Run agents interactively from the terminal using agentctl with a YAML config file" +description: "Run agents interactively from the terminal using agctl with a YAML config file" --- -**`agentctl`** is the interactive REPL for Agent SDK for Go. Type prompts and receive agent responses. It uses the same SDK as your application code and supports both in-process and Temporal runtimes via a YAML config file. +**`agctl`** is the interactive REPL for Agent SDK for Go. Type prompts and receive agent responses. It uses the same SDK as your application code and supports both in-process and Temporal runtimes via a YAML config file. -**`agentctl` is not the Go library.** Install the SDK with `go get github.com/agenticenv/agent-sdk-go`. Install `agentctl` separately — download a release binary or build from source. +**`agctl` is not the Go library.** Install the SDK with `go get github.com/agenticenv/agent-sdk-go`. Install `agctl` separately — download a release binary or build from source. -## Install agentctl +## Install agctl ### Option 1 — Release binary (recommended) @@ -17,17 +17,19 @@ Pre-built binaries for Linux, macOS, and Windows (amd64 and arm64) are on [GitHu 1. Open the latest release 2. Download the archive for your platform from **Assets** -3. Extract and add `agentctl` to your `PATH` +3. Extract and add `agctl` to your `PATH` ### Option 2 — Build from source ```bash -make build -./cmd/bin/agentctl +# agctl is its own module in cmd/ (build with Task) +cd cmd +task build +./bin/agctl # Or install to $GOPATH/bin: -make install -agentctl -config cmd/config.yaml +task install +agctl -config config.yaml ``` ### Option 3 — Run without building (development) @@ -35,7 +37,8 @@ agentctl -config cmd/config.yaml From a cloned repository: ```bash -go run ./cmd +cd cmd +go run . ``` Compiles and runs on each invocation — useful during development. @@ -48,7 +51,7 @@ cp cmd/config.sample.yaml config.yaml # Edit config.yaml — set llm.apiKey or use AGENT_LLM_APIKEY # 2. Run the CLI -agentctl -config config.yaml +agctl -config config.yaml ``` If you use a release binary without cloning the repo, copy `config.sample.yaml` from the release assets into your working directory. @@ -65,7 +68,7 @@ Type prompts at the `>` prompt. Enter `exit`, `quit`, or `bye` to end the sessio Run with a custom path: ```bash -agentctl -config /path/to/config.yaml +agctl -config /path/to/config.yaml ``` ### Runtime selection @@ -80,7 +83,7 @@ Set `runtime` in `config.yaml`: Override per invocation: ```bash -AGENT_RUNTIME=temporal agentctl -config config.yaml +AGENT_RUNTIME=temporal agctl -config config.yaml ``` ### Minimal config.yaml @@ -102,7 +105,7 @@ temporal: logger: level: info - output: logs/agent.log + output: logs/agctl.log format: json ``` @@ -129,7 +132,7 @@ Environment variables override config file values. Prefer them for secrets. export AGENT_LLM_APIKEY=sk-your-key export AGENT_LLM_PROVIDER=openai export AGENT_LLM_MODEL=gpt-4o -agentctl -config config.yaml +agctl -config config.yaml ``` ## MCP servers (optional) @@ -166,9 +169,9 @@ Use this to measure cost across a full interactive session. `cached_prompt` refl ## SDK vs CLI -| | SDK (library) | CLI (`agentctl`) | +| | SDK (library) | CLI (`agctl`) | |---|---|---| -| **Install** | `go get github.com/agenticenv/agent-sdk-go@latest` | Download release binary or `make build` | +| **Install** | `go get github.com/agenticenv/agent-sdk-go@latest` | Download release binary or `cd cmd && task build` | | **Use** | Import `pkg/agent` in your Go application | Interactive REPL from the terminal | | **Config** | Go code — `NewAgent(...)` options | YAML file + env vars | @@ -176,9 +179,9 @@ Both are published from the same repository. Pin the SDK version in your `go.mod ## Logging -`agentctl` prints **only user prompts and agent responses** on the console. Internal SDK logs go to a file. +`agctl` prints **only user prompts and agent responses** on the console. Internal SDK logs go to a file. -- Default: `cmd/logs/agent.log` (gitignored) +- Default: `cmd/logs/agctl.log` (gitignored) - Override: `logger.output` in config or `AGENT_LOGGER_OUTPUT` ## Related diff --git a/docs/testing/eval-harness.mdx b/docs/testing/eval-harness.mdx index cd2a5ab..7a48ab5 100644 --- a/docs/testing/eval-harness.mdx +++ b/docs/testing/eval-harness.mdx @@ -43,10 +43,10 @@ go run ./eval-harness/runner -tools 2 go run ./eval-harness/runner -config eval-harness/runner/config.yaml ``` -Or use the Makefile shortcut: +Or use the Task shortcut: ```bash -make eval-harness +task eval-harness ``` CI runs PromptFoo and DeepEval on pull requests — see the `eval-harness` job in `.github/workflows/ci.yml`. diff --git a/eval-harness/README.md b/eval-harness/README.md index cb11fc3..7a40f1d 100644 --- a/eval-harness/README.md +++ b/eval-harness/README.md @@ -181,5 +181,5 @@ Four pytest tests in `test_agent.py`: - **Change agent behavior** — edit `eval-harness/runner/config.yaml` or `eval-harness/run_agent.sh`. - **Add tests** — extend `test_agent.py` with more telemetry asserts or DeepEval `LLMTestCase` fields. -> **Note:** CI runs both PromptFoo and DeepEval on PRs — see `.github/workflows/ci.yml` (`eval-harness` job). Locally: `make eval-harness` from the repo root. +> **Note:** CI runs both PromptFoo and DeepEval on PRs — see `.github/workflows/ci.yml` (`eval-harness` job). Locally: `task eval-harness` from the repo root. diff --git a/go.mod b/go.mod index d3a0b11..04f2bd5 100644 --- a/go.mod +++ b/go.mod @@ -14,13 +14,17 @@ require ( github.com/anthropics/anthropic-sdk-go v1.26.0 github.com/golang/mock v1.6.0 github.com/google/uuid v1.6.0 + github.com/jackc/pgx/v5 v5.9.2 github.com/joho/godotenv v1.5.1 github.com/modelcontextprotocol/go-sdk v1.4.0 github.com/nexus-rpc/sdk-go v0.6.0 github.com/openai/openai-go/v3 v3.26.0 + github.com/pgvector/pgvector-go v0.4.0 + github.com/pgvector/pgvector-go/pgx v0.4.0 github.com/redis/go-redis/v9 v9.18.0 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 + github.com/weaviate/weaviate v1.37.2 github.com/weaviate/weaviate-go-client/v5 v5.7.3 go.opentelemetry.io/contrib/bridges/otelslog v0.18.0 go.opentelemetry.io/otel v1.43.0 @@ -88,14 +92,11 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.9.2 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pgvector/pgvector-go v0.4.0 // indirect - github.com/pgvector/pgvector-go/pgx v0.4.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/robfig/cron v1.2.0 // indirect @@ -112,7 +113,6 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/weaviate/weaviate v1.37.2 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect github.com/yuin/gopher-lua v1.1.1 // indirect