tavus-cli 0.3.3__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/.github/workflows/ci.yml +3 -0
  2. tavus_cli-0.4.0/.github/workflows/deploy-cloudflare-worker.yml +102 -0
  3. tavus_cli-0.4.0/.github/workflows/pypi-cli.yml +382 -0
  4. tavus_cli-0.4.0/.github/workflows/tail-cloudflare-worker.yml +52 -0
  5. tavus_cli-0.4.0/.github/workflows/validate-staging-deployment.yml +87 -0
  6. tavus_cli-0.4.0/.release-please-manifest.json +3 -0
  7. tavus_cli-0.4.0/CHANGELOG.md +33 -0
  8. tavus_cli-0.4.0/PKG-INFO +334 -0
  9. tavus_cli-0.4.0/README.md +312 -0
  10. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/docs/gemini-enterprise/README.md +3 -3
  11. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/docs/usage-observability.md +1 -1
  12. tavus_cli-0.4.0/packages/tavus/README.md +14 -0
  13. tavus_cli-0.4.0/packages/tavus/pyproject.toml +20 -0
  14. tavus_cli-0.4.0/packages/tavus-mcp/README.md +17 -0
  15. tavus_cli-0.4.0/packages/tavus-mcp/pyproject.toml +20 -0
  16. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/pyproject.toml +1 -1
  17. tavus_cli-0.4.0/release-please-config.json +57 -0
  18. tavus_cli-0.4.0/scripts/__init__.py +1 -0
  19. tavus_cli-0.4.0/scripts/check_release_versions.py +101 -0
  20. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/skills/tavus-agentic-pals/SKILL.md +83 -21
  21. tavus_cli-0.4.0/skills/tavus-agentic-pals/references/build-and-verify.md +85 -0
  22. tavus_cli-0.4.0/skills/tavus-agentic-pals/references/builder-workflow.md +102 -0
  23. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/skills/tavus-agentic-pals/references/chat-mode.md +12 -12
  24. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/skills/tavus-agentic-pals/references/examples.md +1 -2
  25. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/__init__.py +1 -1
  26. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/server.py +3 -3
  27. tavus_cli-0.4.0/tests/unit/test_release_versions.py +70 -0
  28. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/uv.lock +1 -1
  29. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/package-lock.json +2 -2
  30. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/package.json +1 -1
  31. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/src/oauth.ts +78 -17
  32. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/src/tavus.ts +456 -19
  33. tavus_cli-0.4.0/workers/tavus-mcp/src/version.ts +1 -0
  34. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/test/tavus.test.ts +244 -8
  35. tavus_cli-0.3.3/.github/workflows/deploy-cloudflare-worker.yml +0 -71
  36. tavus_cli-0.3.3/.github/workflows/pypi-cli.yml +0 -39
  37. tavus_cli-0.3.3/PKG-INFO +0 -288
  38. tavus_cli-0.3.3/README.md +0 -266
  39. tavus_cli-0.3.3/skills/tavus-agentic-pals/references/build-and-verify.md +0 -72
  40. tavus_cli-0.3.3/skills/tavus-agentic-pals/references/builder-workflow.md +0 -74
  41. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/.env.example +0 -0
  42. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/.github/workflows/pr-reviews.yml +0 -0
  43. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/.gitignore +0 -0
  44. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/AGENTS.md +0 -0
  45. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/docs/gemini-enterprise/listing.md +0 -0
  46. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/docs/gemini-enterprise/test-queries.md +0 -0
  47. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/skills/tavus-agentic-pals/agents/openai.yaml +0 -0
  48. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/cli/__init__.py +0 -0
  49. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/cli/main.py +0 -0
  50. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/__init__.py +0 -0
  51. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/auth/__init__.py +0 -0
  52. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/auth/keyring_store.py +0 -0
  53. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/auth/oauth.py +0 -0
  54. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/auth/session.py +0 -0
  55. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/client/__init__.py +0 -0
  56. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/client/http.py +0 -0
  57. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/daily_transport.py +0 -0
  58. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/env.py +0 -0
  59. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/errors.py +0 -0
  60. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/pal_urls.py +0 -0
  61. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/patch.py +0 -0
  62. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/__init__.py +0 -0
  63. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/build_and_verify.py +0 -0
  64. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/capabilities.py +0 -0
  65. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/carrier_builder.py +0 -0
  66. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/knowledge.py +0 -0
  67. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/options.py +0 -0
  68. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/quickstart.py +0 -0
  69. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/scaffold_embed.py +0 -0
  70. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/templates.py +0 -0
  71. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/recipes/tool_reuse.py +0 -0
  72. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/schemas/__init__.py +0 -0
  73. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/schemas/file_manifest.py +0 -0
  74. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/schemas/guardrail.py +0 -0
  75. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/schemas/objective.py +0 -0
  76. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/schemas/pal.py +0 -0
  77. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/schemas/pronunciation.py +0 -0
  78. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/src/tavus_mcp/sdk/schemas/tool.py +0 -0
  79. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/conftest.py +0 -0
  80. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/integration/test_cli.py +0 -0
  81. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/integration/test_client.py +0 -0
  82. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/integration/test_mcp_server.py +0 -0
  83. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/integration/test_oauth.py +0 -0
  84. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_auth.py +0 -0
  85. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_build_and_verify.py +0 -0
  86. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_builder.py +0 -0
  87. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_capabilities.py +0 -0
  88. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_daily_transport.py +0 -0
  89. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_env.py +0 -0
  90. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_guardrail_schema.py +0 -0
  91. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_objective_schema.py +0 -0
  92. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_pal_schema.py +0 -0
  93. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_patch.py +0 -0
  94. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_pronunciation_schema.py +0 -0
  95. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_scaffold_embed.py +0 -0
  96. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_tool_reuse.py +0 -0
  97. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/tests/unit/test_tool_schema.py +0 -0
  98. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/.dev.vars.example +0 -0
  99. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/src/index.ts +0 -0
  100. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/src/oauth-grant.ts +0 -0
  101. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/test/parity.test.ts +0 -0
  102. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/tsconfig.json +0 -0
  103. {tavus_cli-0.3.3 → tavus_cli-0.4.0}/workers/tavus-mcp/wrangler.jsonc +0 -0
@@ -5,6 +5,7 @@ on:
5
5
  push:
6
6
  branches:
7
7
  - main
8
+ workflow_dispatch:
8
9
 
9
10
  concurrency:
10
11
  group: ci-${{ github.ref }}
@@ -25,6 +26,8 @@ jobs:
25
26
  python-version: ${{ matrix.python-version }}
26
27
  - name: Install uv
27
28
  run: pip install uv
29
+ - name: Check release versions before dependency sync
30
+ run: python scripts/check_release_versions.py
28
31
  - name: Install dependencies
29
32
  run: uv sync --extra dev
30
33
  - name: Ruff
@@ -0,0 +1,102 @@
1
+ name: Deploy Tavus MCP Worker to a lower environment
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ environment:
7
+ description: Lower environment to deploy
8
+ required: true
9
+ default: stg
10
+ type: choice
11
+ options:
12
+ - test
13
+ - stg
14
+ push:
15
+ branches:
16
+ - main
17
+
18
+ permissions:
19
+ contents: read
20
+ deployments: read
21
+ pull-requests: read
22
+
23
+ concurrency:
24
+ group: deploy-tavus-mcp-worker-${{ github.event_name == 'workflow_dispatch' && inputs.environment || 'stg' }}
25
+ cancel-in-progress: true
26
+
27
+ jobs:
28
+ deploy:
29
+ name: Deploy Worker to ${{ github.event_name == 'workflow_dispatch' && inputs.environment || 'stg' }}
30
+ # A release commit is the small version/changelog delta on top of the code
31
+ # already proven in staging. The release workflow promotes that exact tag.
32
+ if: >-
33
+ github.event_name == 'workflow_dispatch' ||
34
+ !startsWith(github.event.head_commit.message, 'chore(main): release')
35
+ runs-on: ubuntu-latest
36
+ timeout-minutes: 15
37
+ environment: ${{ github.event_name == 'workflow_dispatch' && inputs.environment || 'stg' }}
38
+ env:
39
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
40
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
41
+ CLOUDFLARE_ENV: ${{ github.event_name == 'workflow_dispatch' && inputs.environment || 'stg' }}
42
+ MCP_BASE_URL: https://mcp.tavus-preview.io
43
+ defaults:
44
+ run:
45
+ working-directory: workers/tavus-mcp
46
+
47
+ steps:
48
+ - name: Checkout
49
+ uses: actions/checkout@v4
50
+
51
+ - name: Set up Node.js
52
+ uses: actions/setup-node@v4
53
+ with:
54
+ node-version: 24
55
+ cache: npm
56
+ cache-dependency-path: workers/tavus-mcp/package-lock.json
57
+
58
+ - name: Validate deployment secrets
59
+ run: |
60
+ if [ -z "${CLOUDFLARE_API_TOKEN:-}" ]; then
61
+ echo "::error::Missing CLOUDFLARE_API_TOKEN for '$CLOUDFLARE_ENV'."
62
+ exit 1
63
+ fi
64
+ if [ -z "${CLOUDFLARE_ACCOUNT_ID:-}" ]; then
65
+ echo "::error::Missing CLOUDFLARE_ACCOUNT_ID for '$CLOUDFLARE_ENV'."
66
+ exit 1
67
+ fi
68
+
69
+ - name: Install dependencies
70
+ run: npm ci
71
+
72
+ - name: Type-check
73
+ run: npm run build
74
+
75
+ - name: Test
76
+ run: npm test
77
+
78
+ - name: Deploy Worker
79
+ run: npx wrangler deploy --env "$CLOUDFLARE_ENV"
80
+
81
+ - name: Smoke-test hosted OAuth and MCP routes
82
+ if: env.CLOUDFLARE_ENV == 'stg'
83
+ run: |
84
+ curl --fail --silent --show-error \
85
+ "$MCP_BASE_URL/.well-known/oauth-protected-resource/mcp" >/dev/null
86
+ curl --fail --silent --show-error \
87
+ "$MCP_BASE_URL/.well-known/oauth-authorization-server" >/dev/null
88
+ STATUS=$(curl --silent --output /tmp/tavus-mcp-response \
89
+ --write-out '%{http_code}' "$MCP_BASE_URL/mcp")
90
+ if [ "$STATUS" != "401" ]; then
91
+ echo "::error::$MCP_BASE_URL/mcp returned $STATUS; expected 401 without credentials."
92
+ cat /tmp/tavus-mcp-response
93
+ exit 1
94
+ fi
95
+
96
+ - name: Refresh Slack deployment tabs
97
+ if: always() && env.CLOUDFLARE_ENV == 'stg'
98
+ continue-on-error: true
99
+ uses: Tavus-Engineering/pr-changelog-action/status@main
100
+ with:
101
+ slack-bot-token: ${{ secrets.CVI_BOT_SLACK_TOKEN }}
102
+ github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,382 @@
1
+ name: Release Tavus MCP
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+ inputs:
9
+ tag:
10
+ description: Existing GitHub release tag to retry, such as v0.3.4
11
+ required: true
12
+ type: string
13
+
14
+ permissions:
15
+ actions: write
16
+ contents: write
17
+ deployments: read
18
+ id-token: write
19
+ issues: write
20
+ pull-requests: write
21
+
22
+ concurrency:
23
+ group: release-tavus-mcp
24
+ cancel-in-progress: false
25
+
26
+ jobs:
27
+ release-please:
28
+ if: github.event_name == 'push'
29
+ runs-on: ubuntu-latest
30
+ outputs:
31
+ release_created: ${{ steps.release.outputs.release_created }}
32
+ tag_name: ${{ steps.release.outputs.tag_name }}
33
+ steps:
34
+ - name: Open or publish the release
35
+ id: release
36
+ uses: googleapis/release-please-action@v4.4.1
37
+ with:
38
+ token: ${{ github.token }}
39
+ config-file: release-please-config.json
40
+ manifest-file: .release-please-manifest.json
41
+
42
+ # release-please's generic TOML updater cannot target one package in
43
+ # uv.lock's [[package]] array. Re-lock the generated release branch so
44
+ # the local tavus-cli package matches pyproject.toml before CI runs.
45
+ - name: Checkout the release pull request
46
+ if: steps.release.outputs.prs_created == 'true'
47
+ uses: actions/checkout@v4
48
+ with:
49
+ ref: ${{ fromJSON(steps.release.outputs.pr).headBranchName }}
50
+ fetch-depth: 0
51
+
52
+ - name: Set up Python for the release lockfile
53
+ if: steps.release.outputs.prs_created == 'true'
54
+ uses: actions/setup-python@v5
55
+ with:
56
+ python-version: '3.11'
57
+
58
+ - name: Install uv for the release lockfile
59
+ if: steps.release.outputs.prs_created == 'true'
60
+ run: pip install uv
61
+
62
+ - name: Refresh the release lockfile
63
+ if: steps.release.outputs.prs_created == 'true'
64
+ run: |
65
+ set -euo pipefail
66
+ uv lock
67
+ if git diff --quiet -- uv.lock; then
68
+ echo "uv.lock already matches the release version."
69
+ exit 0
70
+ fi
71
+ git config user.name "github-actions[bot]"
72
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
73
+ git add uv.lock
74
+ git commit -m "chore: refresh the release lockfile"
75
+ git push
76
+
77
+ # Pull requests created with GITHUB_TOKEN do not emit pull_request
78
+ # events. Dispatch both checks against the generated branch so its head
79
+ # still gets the normal CI and exact-staging evidence.
80
+ - name: Run checks for the release pull request
81
+ if: steps.release.outputs.prs_created == 'true'
82
+ env:
83
+ GH_TOKEN: ${{ github.token }}
84
+ RELEASE_PR: ${{ steps.release.outputs.pr }}
85
+ run: |
86
+ set -euo pipefail
87
+ BRANCH=$(jq -r '.headBranchName // empty' <<<"$RELEASE_PR")
88
+ NUMBER=$(jq -r '.number // empty' <<<"$RELEASE_PR")
89
+ if [[ ! "$BRANCH" =~ ^release-please ]]; then
90
+ echo "::error::Unexpected release pull request branch '$BRANCH'."
91
+ exit 1
92
+ fi
93
+ echo "Dispatching checks for release pull request #$NUMBER on $BRANCH."
94
+ gh workflow run ci.yml --repo "${{ github.repository }}" --ref "$BRANCH"
95
+ gh workflow run validate-staging-deployment.yml \
96
+ --repo "${{ github.repository }}" \
97
+ --ref "$BRANCH" \
98
+ -f main_sha="${{ github.sha }}"
99
+
100
+ - name: Refresh Slack deployment tabs
101
+ continue-on-error: true
102
+ uses: Tavus-Engineering/pr-changelog-action/status@main
103
+ with:
104
+ slack-bot-token: ${{ secrets.CVI_BOT_SLACK_TOKEN }}
105
+ github-token: ${{ secrets.GITHUB_TOKEN }}
106
+
107
+ preflight:
108
+ name: Validate and build the exact release tag
109
+ needs: release-please
110
+ if: >-
111
+ always() &&
112
+ (github.event_name == 'workflow_dispatch' ||
113
+ needs.release-please.outputs.release_created == 'true')
114
+ runs-on: ubuntu-latest
115
+ timeout-minutes: 20
116
+ env:
117
+ RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || needs.release-please.outputs.tag_name }}
118
+ GH_TOKEN: ${{ github.token }}
119
+ outputs:
120
+ release_tag: ${{ steps.release.outputs.release_tag }}
121
+ release_version: ${{ steps.release.outputs.release_version }}
122
+ release_sha: ${{ steps.release.outputs.release_sha }}
123
+ steps:
124
+ - name: Checkout the release tag
125
+ uses: actions/checkout@v4
126
+ with:
127
+ ref: ${{ env.RELEASE_TAG }}
128
+ fetch-depth: 0
129
+
130
+ - name: Resolve and validate the release
131
+ id: release
132
+ run: |
133
+ set -euo pipefail
134
+ if [ -z "$RELEASE_TAG" ] || [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
135
+ echo "::error::Release tag '$RELEASE_TAG' must look like v0.3.4."
136
+ exit 1
137
+ fi
138
+ gh release view "$RELEASE_TAG" --repo "${{ github.repository }}" >/dev/null
139
+
140
+ RELEASE_SHA=$(git rev-parse HEAD)
141
+ TAG_SHA=$(git rev-list -n 1 "$RELEASE_TAG")
142
+ if [ "$RELEASE_SHA" != "$TAG_SHA" ]; then
143
+ echo "::error::$RELEASE_TAG points to $TAG_SHA, but checkout is $RELEASE_SHA."
144
+ exit 1
145
+ fi
146
+
147
+ VERSION=${RELEASE_TAG#v}
148
+ python scripts/check_release_versions.py --expected "$VERSION"
149
+
150
+ PARENT_SHA=$(git rev-parse "$RELEASE_SHA^")
151
+ UNEXPECTED=$(git diff --name-only "$PARENT_SHA" "$RELEASE_SHA" | grep -Ev \
152
+ '^(\.release-please-manifest\.json|CHANGELOG\.md|pyproject\.toml|uv\.lock|src/tavus_mcp/__init__\.py|workers/tavus-mcp/package\.json|workers/tavus-mcp/package-lock\.json|workers/tavus-mcp/src/version\.ts|packages/tavus/pyproject\.toml|packages/tavus-mcp/pyproject\.toml)$' || true)
153
+ if [ -n "$UNEXPECTED" ]; then
154
+ echo "::error::The release commit contains files that were not staged:"
155
+ echo "$UNEXPECTED"
156
+ exit 1
157
+ fi
158
+
159
+ DEPLOYMENTS=$(gh api "/repos/${{ github.repository }}/deployments?environment=stg&sha=$PARENT_SHA&per_page=20")
160
+ STAGED=false
161
+ while read -r DEPLOYMENT_ID; do
162
+ if gh api "/repos/${{ github.repository }}/deployments/$DEPLOYMENT_ID/statuses?per_page=20" \
163
+ --jq 'any(.[]; .state == "success")' | grep -qx true; then
164
+ STAGED=true
165
+ break
166
+ fi
167
+ done < <(jq -r '.[].id' <<<"$DEPLOYMENTS")
168
+ if [ "$STAGED" != true ]; then
169
+ echo "::error::Release parent $PARENT_SHA has no successful stg deployment."
170
+ exit 1
171
+ fi
172
+
173
+ echo "release_tag=$RELEASE_TAG" >>"$GITHUB_OUTPUT"
174
+ echo "release_version=$VERSION" >>"$GITHUB_OUTPUT"
175
+ echo "release_sha=$RELEASE_SHA" >>"$GITHUB_OUTPUT"
176
+ echo "Release $RELEASE_TAG promotes staged parent $PARENT_SHA."
177
+
178
+ - name: Set up Python
179
+ uses: actions/setup-python@v5
180
+ with:
181
+ python-version: '3.11'
182
+
183
+ - name: Install uv
184
+ run: pip install uv
185
+
186
+ - name: Install Python dependencies
187
+ run: uv sync --extra dev
188
+
189
+ - name: Ruff
190
+ run: uv run ruff check .
191
+
192
+ - name: Pytest
193
+ env:
194
+ COLUMNS: '200'
195
+ run: uv run pytest -q
196
+
197
+ - name: Build Python distributions
198
+ run: |
199
+ uv build
200
+ uv build packages/tavus --out-dir dist
201
+ uv build packages/tavus-mcp --out-dir dist
202
+
203
+ - name: Set up Node.js
204
+ uses: actions/setup-node@v4
205
+ with:
206
+ node-version: 24
207
+ cache: npm
208
+ cache-dependency-path: workers/tavus-mcp/package-lock.json
209
+
210
+ - name: Install Worker dependencies
211
+ working-directory: workers/tavus-mcp
212
+ run: npm ci
213
+
214
+ - name: Type-check Worker
215
+ working-directory: workers/tavus-mcp
216
+ run: npm run build
217
+
218
+ - name: Test Worker
219
+ working-directory: workers/tavus-mcp
220
+ run: npm test
221
+
222
+ - name: Upload Python distributions
223
+ uses: actions/upload-artifact@v4
224
+ with:
225
+ name: tavus-cli-${{ steps.release.outputs.release_version }}
226
+ path: dist/*
227
+ if-no-files-found: error
228
+ retention-days: 7
229
+
230
+ update-pending-board:
231
+ name: Show the production approval in Slack
232
+ needs: preflight
233
+ runs-on: ubuntu-latest
234
+ timeout-minutes: 7
235
+ steps:
236
+ - name: Wait for the production job to request approval
237
+ env:
238
+ GH_TOKEN: ${{ github.token }}
239
+ run: |
240
+ for ATTEMPT in $(seq 1 20); do
241
+ DEPLOYMENTS=$(gh api "/repos/${{ github.repository }}/deployments?environment=prod&sha=${{ needs.preflight.outputs.release_sha }}&per_page=10" || true)
242
+ while read -r DEPLOYMENT_ID; do
243
+ STATE=$(gh api "/repos/${{ github.repository }}/deployments/$DEPLOYMENT_ID/statuses?per_page=1" --jq '.[0].state // ""' || true)
244
+ if [ "$STATE" = "waiting" ]; then
245
+ echo "Production is waiting for approval."
246
+ exit 0
247
+ fi
248
+ if [ -n "$STATE" ]; then
249
+ echo "Production already moved to '$STATE'; refreshing the tabs now."
250
+ exit 0
251
+ fi
252
+ done < <(jq -r '.[].id' <<<"${DEPLOYMENTS:-[]}" 2>/dev/null || true)
253
+ sleep 15
254
+ done
255
+ echo "::warning::Production approval did not appear before the Slack refresh."
256
+
257
+ - name: Refresh Slack deployment tabs
258
+ continue-on-error: true
259
+ uses: Tavus-Engineering/pr-changelog-action/status@main
260
+ with:
261
+ slack-bot-token: ${{ secrets.CVI_BOT_SLACK_TOKEN }}
262
+ github-token: ${{ secrets.GITHUB_TOKEN }}
263
+
264
+ production:
265
+ name: Deploy Worker and publish CLI
266
+ needs: preflight
267
+ runs-on: ubuntu-latest
268
+ timeout-minutes: 20
269
+ environment: prod
270
+ env:
271
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
272
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
273
+ steps:
274
+ - name: Checkout the exact release tag
275
+ uses: actions/checkout@v4
276
+ with:
277
+ ref: ${{ needs.preflight.outputs.release_tag }}
278
+
279
+ - name: Set up Node.js
280
+ uses: actions/setup-node@v4
281
+ with:
282
+ node-version: 24
283
+ cache: npm
284
+ cache-dependency-path: workers/tavus-mcp/package-lock.json
285
+
286
+ - name: Install Worker dependencies
287
+ working-directory: workers/tavus-mcp
288
+ run: npm ci
289
+
290
+ - name: Deploy the hosted Worker
291
+ working-directory: workers/tavus-mcp
292
+ run: npx wrangler deploy --env prod
293
+
294
+ - name: Smoke-test production OAuth and MCP routes
295
+ run: |
296
+ curl --fail --silent --show-error \
297
+ https://mcp.tavus.io/.well-known/oauth-protected-resource/mcp >/dev/null
298
+ curl --fail --silent --show-error \
299
+ https://mcp.tavus.io/.well-known/oauth-authorization-server >/dev/null
300
+ STATUS=$(curl --silent --output /tmp/tavus-mcp-response \
301
+ --write-out '%{http_code}' https://mcp.tavus.io/mcp)
302
+ if [ "$STATUS" != "401" ]; then
303
+ echo "::error::https://mcp.tavus.io/mcp returned $STATUS; expected 401 without credentials."
304
+ cat /tmp/tavus-mcp-response
305
+ exit 1
306
+ fi
307
+
308
+ - name: Set up Python
309
+ uses: actions/setup-python@v5
310
+ with:
311
+ python-version: '3.11'
312
+
313
+ - name: Install uv
314
+ run: pip install uv
315
+
316
+ - name: Download Python distributions
317
+ uses: actions/download-artifact@v4
318
+ with:
319
+ name: tavus-cli-${{ needs.preflight.outputs.release_version }}
320
+ path: dist
321
+
322
+ - name: Publish Tavus CLI and its alias packages to PyPI
323
+ run: uv publish --trusted-publishing always --check-url https://pypi.org/simple/ dist/*
324
+
325
+ notify-cvi-automations:
326
+ name: 'Notify #cvi-automations (prod deploy)'
327
+ needs: [preflight, production]
328
+ if: ${{ always() && !cancelled() && needs.preflight.result == 'success' }}
329
+ runs-on: ubuntu-latest
330
+ # A Slack or mention-resolution failure must not change the deploy result.
331
+ continue-on-error: true
332
+ timeout-minutes: 5
333
+ steps:
334
+ - name: Resolve release author mentions
335
+ id: mentions
336
+ continue-on-error: true
337
+ timeout-minutes: 2
338
+ uses: Tavus-Engineering/pr-changelog-action/release-mentions@main
339
+ with:
340
+ github-token: ${{ secrets.GITHUB_TOKEN }}
341
+ deploy-tag: ${{ needs.preflight.outputs.release_tag }}
342
+ environment: prod
343
+
344
+ - name: 'Post outcome to #cvi-automations'
345
+ env:
346
+ SLACK_BOT_TOKEN: ${{ secrets.CVI_BOT_SLACK_TOKEN }}
347
+ MENTIONS: ${{ steps.mentions.outputs.mentions }}
348
+ DEPLOY_RESULT: ${{ needs.production.result }}
349
+ RELEASE_TAG: ${{ needs.preflight.outputs.release_tag }}
350
+ RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
351
+ run: |
352
+ set -euo pipefail
353
+ AUTHOR_TAGS="${MENTIONS:+${MENTIONS} }"
354
+ CVI_TEAM="<!subteam^S08HUM36HMZ>"
355
+ if [ "$DEPLOY_RESULT" = "success" ]; then
356
+ TEXT=":white_check_mark: ${AUTHOR_TAGS}Tavus MCP <${RUN_URL}|${RELEASE_TAG}> is live in production."
357
+ else
358
+ TEXT=":x: ${CVI_TEAM} Tavus MCP production deploy failed — <${RUN_URL}|run>."
359
+ fi
360
+
361
+ RESPONSE=$(curl --fail-with-body --silent --show-error \
362
+ --connect-timeout 5 --max-time 30 \
363
+ -X POST https://slack.com/api/chat.postMessage \
364
+ -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
365
+ -H "Content-Type: application/json; charset=utf-8" \
366
+ --data "$(jq -n --arg channel "C0B9S5Y556V" --arg text "$TEXT" \
367
+ '{channel:$channel, text:$text, unfurl_links:false}')")
368
+ echo "$RESPONSE" | jq .
369
+ echo "$RESPONSE" | jq -e '.ok == true' >/dev/null
370
+
371
+ update-final-board:
372
+ name: Refresh Slack after production
373
+ needs: [preflight, update-pending-board, production]
374
+ if: always() && needs.preflight.result == 'success'
375
+ runs-on: ubuntu-latest
376
+ steps:
377
+ - name: Refresh Slack deployment tabs
378
+ continue-on-error: true
379
+ uses: Tavus-Engineering/pr-changelog-action/status@main
380
+ with:
381
+ slack-bot-token: ${{ secrets.CVI_BOT_SLACK_TOKEN }}
382
+ github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,52 @@
1
+ name: Tail Tavus MCP Worker
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ environment:
7
+ description: Cloudflare Worker environment to tail
8
+ required: true
9
+ default: prod
10
+ type: choice
11
+ options:
12
+ - test
13
+ - stg
14
+ - prod
15
+ seconds:
16
+ description: How long to stream logs before exiting
17
+ required: true
18
+ default: "120"
19
+ type: string
20
+
21
+ permissions:
22
+ contents: read
23
+
24
+ jobs:
25
+ tail:
26
+ runs-on: ubuntu-latest
27
+ environment: ${{ inputs.environment }}
28
+ env:
29
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
30
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
31
+ defaults:
32
+ run:
33
+ working-directory: workers/tavus-mcp
34
+
35
+ steps:
36
+ - name: Checkout
37
+ uses: actions/checkout@v4
38
+
39
+ - name: Setup Node.js
40
+ uses: actions/setup-node@v4
41
+ with:
42
+ node-version: 24
43
+ cache: npm
44
+ cache-dependency-path: workers/tavus-mcp/package-lock.json
45
+
46
+ - name: Install dependencies
47
+ run: npm ci
48
+
49
+ - name: Tail Worker logs
50
+ # timeout exits 124 when the window closes; that is the expected success path.
51
+ run: |
52
+ timeout "${{ inputs.seconds }}" npx wrangler tail --env "${{ inputs.environment }}" --format json || [ $? -eq 124 ]
@@ -0,0 +1,87 @@
1
+ name: Validate staging deployment
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main]
6
+ paths: [CHANGELOG.md]
7
+ workflow_dispatch:
8
+ inputs:
9
+ main_sha:
10
+ description: Exact main commit that the release pull request promotes
11
+ required: true
12
+ type: string
13
+
14
+ permissions:
15
+ actions: read
16
+ contents: read
17
+
18
+ concurrency:
19
+ group: validate-staging-${{ github.event.pull_request.number || github.run_id }}
20
+ cancel-in-progress: true
21
+
22
+ jobs:
23
+ validate-staging:
24
+ name: Validate the current main commit in staging
25
+ if: >-
26
+ github.event_name == 'workflow_dispatch' ||
27
+ startsWith(github.head_ref, 'release-please')
28
+ runs-on: ubuntu-latest
29
+ timeout-minutes: 30
30
+ steps:
31
+ - name: Wait for the exact staging deployment
32
+ env:
33
+ GH_TOKEN: ${{ github.token }}
34
+ EXPECTED_MAIN_SHA: ${{ github.event_name == 'workflow_dispatch' && inputs.main_sha || '' }}
35
+ run: |
36
+ while :; do
37
+ MAIN_TIP=$EXPECTED_MAIN_SHA
38
+ if [ -z "$MAIN_TIP" ]; then
39
+ MAIN_TIP=$(gh api "/repos/${{ github.repository }}/commits/main" \
40
+ --jq '.sha' || true)
41
+ fi
42
+ if [ -z "$MAIN_TIP" ]; then
43
+ echo "Could not resolve main; retrying."
44
+ sleep 30
45
+ continue
46
+ fi
47
+
48
+ RUN=$(gh api \
49
+ "/repos/${{ github.repository }}/actions/workflows/deploy-cloudflare-worker.yml/runs?branch=main&head_sha=$MAIN_TIP&event=push&per_page=1" \
50
+ --jq '.workflow_runs[0]' || true)
51
+ if [ -z "$RUN" ] || [ "$RUN" = "null" ]; then
52
+ echo "No staging run for $MAIN_TIP yet; waiting."
53
+ sleep 30
54
+ continue
55
+ fi
56
+
57
+ STATUS=$(jq -r '.status' <<<"$RUN")
58
+ CONCLUSION=$(jq -r '.conclusion' <<<"$RUN")
59
+ RUN_ID=$(jq -r '.id' <<<"$RUN")
60
+ URL=$(jq -r '.html_url' <<<"$RUN")
61
+ if [ "$STATUS" != "completed" ]; then
62
+ echo "Staging run for $MAIN_TIP is $STATUS; waiting. $URL"
63
+ sleep 30
64
+ continue
65
+ fi
66
+
67
+ if [ "$CONCLUSION" != "success" ]; then
68
+ echo "::error::Staging run for $MAIN_TIP concluded '$CONCLUSION'."
69
+ echo "View the run: $URL"
70
+ exit 1
71
+ fi
72
+
73
+ DEPLOY_JOB=$(gh api "/repos/${{ github.repository }}/actions/runs/$RUN_ID/jobs?per_page=100" \
74
+ --jq 'first(.jobs[] | select(.name == "Deploy Worker to stg")) // empty')
75
+ if [ -z "$DEPLOY_JOB" ]; then
76
+ echo "::error::Run $RUN_ID has no 'Deploy Worker to stg' job."
77
+ exit 1
78
+ fi
79
+ if [ "$(jq -r '.conclusion' <<<"$DEPLOY_JOB")" != "success" ]; then
80
+ echo "::error::The staging deploy job did not succeed."
81
+ echo "View the run: $URL"
82
+ exit 1
83
+ fi
84
+
85
+ echo "Staging deployed current main commit $MAIN_TIP successfully."
86
+ break
87
+ done
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.4.0"
3
+ }
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ ## [0.4.0](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.3.4...v0.4.0) (2026-08-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * notify cvi-automations after MCP deploys ([#41](https://github.com/Tavus-Engineering/tavus-mcp/issues/41)) ([169d092](https://github.com/Tavus-Engineering/tavus-mcp/commit/169d092b6b9241256316e3d8f6a0a633319b70ef))
9
+ * publish tavus and tavus-mcp alias packages ([2c781a0](https://github.com/Tavus-Engineering/tavus-mcp/commit/2c781a059b1ef06acd2d4293239e41d568c4f0ce))
10
+
11
+ ## [0.3.4](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.3.3...v0.3.4) (2026-08-25)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * automate Tavus MCP releases ([#34](https://github.com/Tavus-Engineering/tavus-mcp/issues/34)) ([a76cfc5](https://github.com/Tavus-Engineering/tavus-mcp/commit/a76cfc5938e4fabc730e0109649e0dea63f966b6))
17
+ * keep the Python package version in releases ([#38](https://github.com/Tavus-Engineering/tavus-mcp/issues/38)) ([85d8809](https://github.com/Tavus-Engineering/tavus-mcp/commit/85d8809fcc707b71c9daedcb4ed5f2faac4f5334))
18
+ * regenerate the release lockfile before CI ([#39](https://github.com/Tavus-Engineering/tavus-mcp/issues/39)) ([f0afd76](https://github.com/Tavus-Engineering/tavus-mcp/commit/f0afd760926132c3d5cb3c29d4afd8d261ba3306))
19
+
20
+
21
+ ### Documentation
22
+
23
+ * rewrite the README around the current CLI and MCP surfaces ([252a808](https://github.com/Tavus-Engineering/tavus-mcp/commit/252a808b22406239dfe8c552b9c7338ca29a539e))
24
+
25
+
26
+ ### Continuous Integration
27
+
28
+ * run release checks without an app secret ([#35](https://github.com/Tavus-Engineering/tavus-mcp/issues/35)) ([9bee88a](https://github.com/Tavus-Engineering/tavus-mcp/commit/9bee88ad3b62c448a53e27ea7381aeca42d4dd2b))
29
+ * target the repository for release check dispatch ([#37](https://github.com/Tavus-Engineering/tavus-mcp/issues/37)) ([1cb9d8e](https://github.com/Tavus-Engineering/tavus-mcp/commit/1cb9d8e8cde12e3bd8a1b6b5fcd7768470264e1c))
30
+
31
+ ## Changelog
32
+
33
+ Release notes for Tavus CLI and the hosted Tavus MCP Worker appear here.