Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2f479a5
feat(sdk): add runExperiment and score
ephraimduncan Oct 29, 2026
e44cf60
fix(sdk): keep each min score and print scores as the python sdk does
ephraimduncan Oct 29, 2026
b8dc041
feat(sdk-python): add run_experiment and score
ephraimduncan Oct 29, 2026
968a45e
feat(sdk): add the experiment action for pull requests
ephraimduncan Oct 29, 2026
473a529
docs(sdk): document experiments, scores, and the experiment action
ephraimduncan Oct 29, 2026
1d8ee43
fix(sdk): complete the experiment after a run stops
ephraimduncan Oct 30, 2026
bf7844f
fix(sdk-python): complete the experiment after a run stops
ephraimduncan Oct 30, 2026
ae0ed55
fix(sdk): use the tsx of the project and change only our comment
ephraimduncan Oct 30, 2026
fad2f00
docs(sdk): tell how a stopped experiment run completes
ephraimduncan Oct 30, 2026
85fa4f1
docs(sdk): give api.telemetry.dev as the default base url
ephraimduncan Oct 30, 2026
339eb0c
feat(sdk): record the prompt on model calls outside withPrompt
ephraimduncan Oct 29, 2026
ae47605
fix(sdk): find the prompt by message identity, not by text
ephraimduncan Oct 29, 2026
a6b98fe
fix(sdk): name the newest compile, not the last tagged message
ephraimduncan Oct 29, 2026
3bc6f53
fix(sdk): keep the variables of recent compiles only
ephraimduncan Oct 29, 2026
abb8d10
fix(sdk): give the base url to getPrompt in the prompt tests
ephraimduncan Oct 29, 2026
f6aa1c1
fix(sdk): keep the variables of the last two chat turns
ephraimduncan Oct 29, 2026
1b09916
fix(sdk): keep compiled variables for 5 minutes, not two turns
ephraimduncan Oct 30, 2026
b2a0e09
fix(sdk): measure the variables time of compiled messages in elapsed …
ephraimduncan Oct 30, 2026
0c2f2b6
docs(sdk): tell that a call with no compiled message records its input
ephraimduncan Oct 30, 2026
789c94b
fix(cli): break the sign-in lock only when its holder has exited
aikins01 Oct 30, 2026
1195b11
docs(sdk): name the read prompts access of the prompt api key (#103)
ephraimduncan Oct 30, 2026
c6b599e
fix(sdk-python): fetch prompts again in a forked process (#105)
ephraimduncan Oct 30, 2026
fe00efa
Merge pull request #121 from telemetry-dev/feat/evals
ephraimduncan Oct 30, 2026
fa549cd
Merge remote-tracking branch 'origin/main' into feat/sdk/prompt-outsi…
ephraimduncan Oct 30, 2026
6435fb6
Merge pull request #112 from telemetry-dev/feat/sdk/prompt-outside-scope
ephraimduncan Oct 30, 2026
ee91484
chore: release main (#125)
aikins01 Oct 30, 2026
dcad14b
feat(cli): report errors as one JSON line with a stable code under --…
aikins01 Oct 30, 2026
02f63f5
feat(cli): summarize a trace's failures and repeated calls, and sugge…
aikins01 Oct 30, 2026
56b7ba4
test(cli): give each cli test 30 seconds, since each one starts the c…
aikins01 Oct 30, 2026
88a2e0d
ci(release): release the experiment action with a major tag (#126)
ephraimduncan Oct 30, 2026
c935591
chore: ignore the experiment action changelog in the formatter (#132)
ephraimduncan Oct 30, 2026
aa5b7e2
chore: release main (#129)
aikins01 Oct 30, 2026
505309b
feat(cli): add --json to login and logout (#131)
aikins01 Oct 30, 2026
b639de9
feat(cli): map telemetry.dev's tool error codes to cli error codes (#…
aikins01 Oct 30, 2026
511a491
chore: release main (#133)
aikins01 Oct 30, 2026
4a54d8c
Merge branch 'main' into fix/cli/session-lock-owner
aikins01 Oct 30, 2026
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
74 changes: 71 additions & 3 deletions .github/scripts/release_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ mv "$repo/release-please-config.json.next" "$repo/release-please-config.json"
run_push_discovery false '["packages/mcp"]'
grep -Fxq 'npm=["packages/otel","packages/mcp"]' "$tmp/output"
git -C "$repo" checkout --quiet -- release-please-config.json
jq '.packages["actions/experiment"] = {"component": "experiment-action", "release-type": "simple"}' \
"$repo/release-please-config.json" > "$repo/release-please-config.json.next"
mv "$repo/release-please-config.json.next" "$repo/release-please-config.json"
jq '.["actions/experiment"] = "1.0.0"' "$repo/.release-please-manifest.json" > "$repo/.release-please-manifest.json.next"
mv "$repo/.release-please-manifest.json.next" "$repo/.release-please-manifest.json"
git -C "$repo" tag experiment-action-v1.0.0
for released in '["actions/experiment","packages/mcp"]' '[]'; do
run_push_discovery false "$released"
grep -Fxq 'npm=["packages/otel","packages/mcp"]' "$tmp/output"
grep -Fxq 'python=["sdks/python"]' "$tmp/output"
done
git -C "$repo" tag --delete experiment-action-v1.0.0 > /dev/null
git -C "$repo" checkout --quiet -- release-please-config.json .release-please-manifest.json
expect_failure "Expected 2 configured packages for released paths, found 1" \
run_push_discovery false '["packages/mcp","packages/unknown"]'
expect_failure "Release otel-v0.1.0 is still a draft" run_push_discovery true '["packages/otel"]'
Expand All @@ -161,6 +174,60 @@ git -C "$repo" commit --quiet --allow-empty -m after-batch
expect_failure "Release tag, event, and checkout commits do not match" \
run_push_discovery false '["packages/otel"]' "$(git -C "$repo" rev-parse HEAD)"

action_repo="$tmp/action-repo"
git init --quiet --initial-branch=main "$action_repo"
git -C "$action_repo" config user.name "Release Test"
git -C "$action_repo" config user.email "release-test@example.invalid"
action_commit() {
printf '%s\n' "$1" > "$action_repo/.release-please-manifest.json"
git -C "$action_repo" add .release-please-manifest.json
git -C "$action_repo" commit --quiet -m "$1"
git -C "$action_repo" rev-parse HEAD
}
unreleased_sha=$(action_commit '{}')
v1_0_0_sha=$(action_commit '{"actions/experiment":"1.0.0"}')
git -C "$action_repo" tag experiment-action-v1.0.0
other_release_sha=$(action_commit '{"actions/experiment":"1.0.0","packages/mcp":"0.1.2"}')
v1_0_1_sha=$(action_commit '{"actions/experiment":"1.0.1"}')
git -C "$action_repo" tag experiment-action-v1.0.1
v2_0_0_sha=$(action_commit '{"actions/experiment":"2.0.0"}')
git -C "$action_repo" tag experiment-action-v2.0.0
mkdir -p "$tmp/tag-bin"
cat > "$tmp/tag-bin/gh" <<'SH'
#!/usr/bin/env bash
printf '%s\n' "$*" >> "$GH_LOG"
SH
chmod +x "$tmp/tag-bin/gh"
extract_run tag-experiment-action > "$tmp/tag-action.sh"
run_tag_action() {
(
cd "$action_repo"
git switch --quiet --detach "$1"
rm -f "$tmp/gh-log"
PATH="$tmp/tag-bin:$PATH" GH_LOG="$tmp/gh-log" GITHUB_REPOSITORY=telemetry-dev/telemetry GITHUB_SHA="$1" \
bash -eo pipefail "$tmp/tag-action.sh"
)
}
expect_gh_call() {
[[ $(wc -l < "$tmp/gh-log") -eq 1 ]]
grep -Fxq "$1" "$tmp/gh-log"
}
for sha in "$unreleased_sha" "$other_release_sha"; do
run_tag_action "$sha"
[[ ! -e "$tmp/gh-log" ]]
done
run_tag_action "$v1_0_0_sha"
expect_gh_call "api --method POST repos/telemetry-dev/telemetry/git/refs -f ref=refs/tags/experiment-action-v1 -f sha=$v1_0_0_sha"
git -C "$action_repo" tag experiment-action-v1 "$v1_0_0_sha"
run_tag_action "$v1_0_1_sha"
expect_gh_call "api --method PATCH repos/telemetry-dev/telemetry/git/refs/tags/experiment-action-v1 -f sha=$v1_0_1_sha -F force=true"
git -C "$action_repo" tag --force experiment-action-v1 "$v1_0_1_sha" > /dev/null
# A rerun of an earlier release must not move the major tag back.
run_tag_action "$v1_0_0_sha"
[[ ! -e "$tmp/gh-log" ]]
run_tag_action "$v2_0_0_sha"
expect_gh_call "api --method POST repos/telemetry-dev/telemetry/git/refs -f ref=refs/tags/experiment-action-v2 -f sha=$v2_0_0_sha"

release_tree=$(git -C "$repo" show --no-patch --format=%T "$release_sha")
unrelated_sha=$(printf 'unrelated\n' | git -C "$repo" commit-tree "$release_tree")
git -C "$repo" switch --quiet --detach "$unrelated_sha"
Expand Down Expand Up @@ -415,7 +482,8 @@ workflow_pnpm=$(
' "$root/.github/workflows/release.yml"
)
[[ "$workflow_pnpm" == "$package_pnpm" ]]
[[ $(grep -Ec '^[[:space:]]*concurrency:' "$root/.github/workflows/release.yml") -eq 2 ]]
[[ $(grep -Ec '^[[:space:]]*concurrency:' "$root/.github/workflows/release.yml") -eq 3 ]]
grep -Fxq " group: tag-experiment-action" "$root/.github/workflows/release.yml"
grep -Fxq " group: release-\${{ inputs.release_tag || github.sha }}" \
"$root/.github/workflows/release.yml"
grep -Fxq " group: release-please-\${{ github.ref }}" \
Expand Down Expand Up @@ -455,13 +523,13 @@ for path, package in packages.items():
manifest = json.loads((root / path / "package.json").read_text())
paths[manifest["name"]] = path
dependencies[path] = [*manifest.get("dependencies", {}), *manifest.get("peerDependencies", {})]
else:
elif package["release-type"] == "python":
project = tomllib.loads((root / path / "pyproject.toml").read_text())["project"]
paths[normalize(project["name"])] = path
dependencies[path] = [
normalize(re.match(r"[A-Za-z0-9._-]+", requirement)[0]) for requirement in project.get("dependencies", [])
]
for path in order:
for path in dependencies:
for dependency in dependencies[path]:
dependency_path = paths.get(dependency)
if dependency_path and order.index(dependency_path) > order.index(path):
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
with:
persist-credentials: false
- run: bash .github/scripts/release_test.sh
- run: shellcheck .github/scripts/*.sh
- run: shellcheck .github/scripts/*.sh actions/experiment/*.sh

typescript:
runs-on: ubuntu-latest
Expand Down
38 changes: 38 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ jobs:
case "$release_type" in
node) npm+=("$path") ;;
python) python+=("$path") ;;
# The experiment action has no package: the tag-experiment-action job moves its major tag.
simple) continue ;;
*)
echo "Unsupported release type for $path: $release_type" >&2
exit 1
Expand Down Expand Up @@ -289,3 +291,39 @@ jobs:
.github/scripts/verify-python-release-dependencies.sh "$wheel"
uv publish --trusted-publishing always --check-url https://pypi.org/simple "python/$package"/*
done < python/publish-order.txt

tag-experiment-action:
needs: release-please
concurrency:
group: tag-experiment-action
cancel-in-progress: false
# The default queue cancels a waiting job when another push arrives, and that release then keeps the old major tag.
queue: max
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
fetch-depth: 0
persist-credentials: false
ref: ${{ github.sha }}
- env:
GH_TOKEN: ${{ github.token }}
run: |
version=$(jq -r '.["actions/experiment"] // empty' .release-please-manifest.json)
# A rerun after release-please failed partway gets no outputs for the release, so its tag selects it.
if [[ -z "$version" || "$(git rev-parse -q --verify "refs/tags/experiment-action-v$version^{commit}" || true)" != "$GITHUB_SHA" ]]; then
exit 0
fi

# Workflows use the major tag, which moves to each release of its major version, but never back.
major="experiment-action-v${version%%.*}"
current=$(git rev-parse -q --verify "refs/tags/$major^{commit}" || true)
if [[ -z "$current" ]]; then
gh api --method POST "repos/$GITHUB_REPOSITORY/git/refs" -f "ref=refs/tags/$major" -f "sha=$GITHUB_SHA"
elif git merge-base --is-ancestor "$current" "$GITHUB_SHA"; then
gh api --method PATCH "repos/$GITHUB_REPOSITORY/git/refs/tags/$major" -f "sha=$GITHUB_SHA" -F force=true
else
echo "$major is at a release after experiment-action-v$version"
fi
41 changes: 21 additions & 20 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
{
"packages/otel": "0.2.0",
"packages/sdk": "0.2.1",
"packages/sdk": "0.2.2",
"packages/ai": "0.2.0",
"packages/anthropic": "0.2.1",
"packages/bedrock": "0.2.1",
"packages/cursor": "0.2.1",
"packages/eve": "0.2.1",
"packages/google-genai": "0.2.1",
"packages/mcp": "0.2.1",
"packages/omp": "0.2.1",
"packages/openai": "0.2.1",
"packages/opencode": "0.2.1",
"packages/openrouter": "0.2.1",
"packages/pi": "0.2.1",
"packages/anthropic": "0.2.2",
"packages/bedrock": "0.2.2",
"packages/cursor": "0.2.2",
"packages/eve": "0.2.2",
"packages/google-genai": "0.2.2",
"packages/mcp": "0.2.2",
"packages/omp": "0.2.2",
"packages/openai": "0.2.2",
"packages/opencode": "0.2.2",
"packages/openrouter": "0.2.2",
"packages/pi": "0.2.2",
"packages/tanstack-ai": "0.2.0",
"sdks/python": "0.3.1",
"sdks/python-anthropic": "0.2.1",
"sdks/python-bedrock": "0.2.1",
"sdks/python-google-genai": "0.2.1",
"sdks/python-litellm": "0.2.1",
"sdks/python-openai": "0.2.1",
"sdks/python-openrouter": "0.2.1",
"packages/cli": "0.1.0"
"sdks/python": "0.3.2",
"sdks/python-anthropic": "0.2.2",
"sdks/python-bedrock": "0.2.2",
"sdks/python-google-genai": "0.2.2",
"sdks/python-litellm": "0.2.2",
"sdks/python-openai": "0.2.2",
"sdks/python-openrouter": "0.2.2",
"packages/cli": "0.1.2",
"actions/experiment": "1.0.0"
}
13 changes: 13 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,16 @@ Each registry's publish job stops at the first package that fails, so the packag
To retry an existing published release, run the `Release` workflow from `main` and set `release_tag` to that release's full tag. This is a real publication attempt, not a dry run. The tag must be an ancestor of the selected `main` commit. Every configured SDK directory, shared build scripts, lockfiles, release configuration, and root build configuration must be unchanged from the tag; only `packageManager` may differ within root `package.json`. Workflow-only recovery changes are allowed. Source-changing fixes need a new release, not a retry of an old version.

Artifact names and versions are checked before upload. npm retries skip an existing version only when its SHA-512 integrity matches the local tarball, and publication waits about 10 minutes for published `@telemetry-dev/*` dependencies and peer dependencies to satisfy their declared ranges. Python publication likewise waits about 10 minutes for each wheel's dependencies to resolve on PyPI. PyPI retries use `uv publish --check-url` to check existing distributions. An integrity mismatch must be investigated, not bypassed or overwritten.

## Experiment action

The experiment action in `actions/experiment` has no package. Release Please gives it releases such as `experiment-action-v1.0.0`. The `tag-experiment-action` job of the `Release` workflow then moves the major tag, `experiment-action-v1`, to the release commit. The README of the action and the experiment page of telemetry.dev tell users to use the major tag. The job moves a major tag only forward on `main`, so a rerun of an earlier release does not move it back.

A change that can break a workflow, for example a removed input or a changed output, must have a `feat!:` or `fix!:` commit. Release Please then gives the action a new major version, and `experiment-action-v1` stays at the last 1.x release. A `release_tag` retry does not apply to the action. If the job fails, re-run the failed job of the release run.

The job uses `GITHUB_TOKEN`, which cannot have the `workflows` permission. Thus GitHub rejects the tag when no branch head has the same `.github/workflows` files as the release commit. If a merge changed a workflow before the job ran, move the tag with your own credentials:

```sh
git fetch origin --tags
git push --force origin 'experiment-action-v1.0.1^{commit}:refs/tags/experiment-action-v1'
```
14 changes: 14 additions & 0 deletions actions/experiment/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Changelog

## 1.0.0 (2026-10-30)


### Features

* **sdk:** add the experiment action for pull requests ([968a45e](https://github.com/telemetry-dev/telemetry/commit/968a45e0eeff183d2409c0336c6328ac07a2e36d))
* **sdk:** run experiments on datasets and send scores ([fe00efa](https://github.com/telemetry-dev/telemetry/commit/fe00efa1326797f8fda647d665b388621a961d39))


### Bug Fixes

* **sdk:** use the tsx of the project and change only our comment ([ae0ed55](https://github.com/telemetry-dev/telemetry/commit/ae0ed556f68d1952cbe33ca8f93f29a429fab5a4))
Loading
Loading