Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
194 commits
Select commit Hold shift + click to select a range
f3d8935
Test (#807)
aix-ahmet Jan 27, 2026
43d6183
ENG-2722 Fix code/value attribute handling for actions and removed au…
kadirpekel Jan 27, 2026
bebb927
Merge branch 'test' into development
aix-ahmet Jan 27, 2026
5a94cf1
removed limitations other than abort-critical (#811)
xainaz Jan 27, 2026
41285aa
Make model tool function, supplier, and version optional (#813)
xainaz Jan 28, 2026
11a53a8
fix: remove INFO severity from inspector
ahmetgunduz Jan 28, 2026
f63d1ff
ENG-2727-Change-the-inspector-payload-structure (#815)
aix-ahmet Jan 28, 2026
40042a1
feat(v2): Add Debugger meta-agent for agent response analysis (#814)
MaiaJP-AIXplain Jan 28, 2026
8ad7c97
ENG-2726 streaming support for v2 models (#816)
kadirpekel Jan 30, 2026
e62c1fb
ENG-2724 Added v2 apikey resource (#810)
kadirpekel Feb 3, 2026
bf38bd4
ENG-2725 Adjust run methods so that run uses the v2 endpoint and run_…
kadirpekel Feb 3, 2026
4cdf36a
Get-models-by-name (#674)
ahmetgunduz Feb 3, 2026
b004cd4
fix model completed
ahmetgunduz Feb 5, 2026
39a0448
Fix v2 imports from v1 modules that trigger env var validation (#819)
aix-ahmet Feb 5, 2026
d41cde0
Fix models api (#822)
aix-ahmet Feb 5, 2026
197c547
Merge branch 'test' into development
aix-ahmet Feb 5, 2026
698447e
remove duplicated code in v2/agent.py
aix-ahmet Feb 5, 2026
155b206
Development (#821)
ikxplain Feb 5, 2026
cda96cc
added rfc for test cleanup refactoring (#825)
aix-ahmet Feb 6, 2026
657ca4f
ci: add development branch to workflow triggers
aix-ahmet Feb 9, 2026
63897a8
undo ci
aix-ahmet Feb 9, 2026
987ec85
fix tests with available llm
aix-ahmet Feb 9, 2026
5bcbd2d
fix agent functional test and team agent functional test
aix-ahmet Feb 9, 2026
1db0f38
refactored test cleanup to use yield fixtures
aix-ahmet Feb 9, 2026
1539df1
removed finetune tests from development branch
aix-ahmet Feb 9, 2026
c71a3ab
Feature/fixture-based-test-cleanup (#826)
aix-ahmet Feb 9, 2026
a71e715
file parsing support in aiR and add functional test (#824)
basitanees Feb 9, 2026
6d61463
FIX: Bug 710 - Allowed Actions Not Set (#828)
aix-ahmet Feb 12, 2026
08c44b2
Development (#829)
ikxplain Feb 17, 2026
503e03e
fix agent exists bug on agent functional test
aix-ahmet Feb 18, 2026
8099123
fix agent exists bug on agent functional test cont'uned
aix-ahmet Feb 18, 2026
4c98777
fix tool exists bug on agent functional test
aix-ahmet Feb 18, 2026
fa8d549
fix llm not found bug on agent functional test
aix-ahmet Feb 18, 2026
14a9135
replace test agent name with uuid suffix in agent functional test
aix-ahmet Feb 18, 2026
4cefedf
remove _ from agent name in agent functional test
aix-ahmet Feb 18, 2026
1f11521
Merge branch 'main' into test
ikxplain Feb 23, 2026
95bbf09
Add score threshold option for searching in index (#683)
basitanees Feb 23, 2026
6ca8a98
Merge branch 'development' into test
aix-ahmet Feb 23, 2026
351c864
Test (#835)
aix-ahmet Feb 23, 2026
ffab69e
ENG-2794: Improve v2 streaming tool-calling handling and test coverag…
MaiaJP-AIXplain Feb 23, 2026
0ad819b
hotfix in toolcal with streamming (#836)
MaiaJP-AIXplain Feb 24, 2026
41dc526
V2 test failures (#839)
xainaz Feb 25, 2026
fb5b1dd
ENG-2804 Review of docstrings (#838)
kadirpekel Feb 25, 2026
36eda45
send dependencies if empty (#840)
xainaz Feb 25, 2026
6e84586
ENG-2808 Return connection URL when creating a Tool (#837)
kadirpekel Feb 25, 2026
a772743
check nested error message (#833)
xainaz Feb 25, 2026
86a2549
ENG-2783: reorg directory structure into dedicated v1/v2 folders (#831)
aix-ahmet Feb 25, 2026
3c9705e
fix python 3.12> compatibility and removed except from models
aix-ahmet Feb 25, 2026
85c5e2d
fix: response geneartion in v2
aix-ahmet Feb 25, 2026
14d58b9
feat: update default LLM from GPT-4o to GPT-5 Mini
aix-ahmet Feb 26, 2026
4b05fc7
Merge devtest (#843)
xainaz Mar 2, 2026
12148ce
Merge branch 'test' into development
aix-ahmet Mar 3, 2026
a571c51
ENG-2821 Addressed several api key management issues (#841)
kadirpekel Mar 3, 2026
1da7931
fix bug list action input (#846)
basitanees Mar 5, 2026
2920c68
Development (#842)
ikxplain Mar 5, 2026
9c38ae4
ENG-2831 using camelCase instead of Python's snake_case convention (#…
kadirpekel Mar 6, 2026
2d97a54
docs: refresh README positioning, diagrams, and v2 quickstart
nurhamdan1987 Mar 8, 2026
3ee3091
docs: refine README copy and update team-agent diagram
nurhamdan1987 Mar 8, 2026
bd08fb4
docs: mention built-in opt-in agent memory
nurhamdan1987 Mar 8, 2026
a77f20d
Merge branch 'main' into test with properly resolved conflicts
aix-ahmet Mar 9, 2026
6b7bbfc
Fix general asset tests: update model names, replace deleted model, s…
aix-ahmet Mar 9, 2026
fa8430c
Mark apikey create test as flaky due to transient 502 errors
aix-ahmet Mar 9, 2026
aad37a2
Fix failing functional tests: agent tool_steps iteration, v2 model te…
aix-ahmet Mar 9, 2026
5b4ca69
Merge branch 'main' into test
aix-ahmet Mar 9, 2026
e4f62c0
docs: refresh README for Agents SDK v2 (#849)
nurhamdan1987 Mar 10, 2026
b97b028
added tool type (#852)
xainaz Mar 10, 2026
c786e10
ENG-2852 GET /sdk/runs/{execution_id} returns 404 for valid agent exe…
kadirpekel Mar 10, 2026
ab1035e
ENG-2854 runtimewarning when saving an agent (#855)
kadirpekel Mar 10, 2026
57b70ae
ENG-2855 run_response_generation arg false by default (#856)
kadirpekel Mar 10, 2026
a8a9d16
Merge main into test, accepting main changes for conflicts
aix-ahmet Mar 11, 2026
1dedcbf
Test (#862)
aix-ahmet Mar 11, 2026
873fd64
Fix Function enum decoder: backend kebab-case IDs were silently rejec…
MaiaJP-AIXplain Mar 13, 2026
99dd844
Development (#867)
ikxplain Mar 16, 2026
6ab523d
problem 3 and 6 addressed (#865)
xainaz Mar 17, 2026
eacd131
ENG-2856 Unify action/input discovery API across Tool and Model (#857)
kadirpekel Mar 18, 2026
3291b51
ENG-2855 run_response_generation arg false by default (#868)
kadirpekel Mar 18, 2026
1dea6c2
ENG-2886 Fixed dataclass formation causing a bug (#870)
kadirpekel Mar 19, 2026
ac64b25
ENG-2880 Deprecate subagents param and replace with agents param (#871)
kadirpekel Mar 26, 2026
7df39c1
Readme refreshRefresh README positioning, examples, and AgenticOS arc…
nurhamdan1987 Mar 26, 2026
fc8c8af
fix: enable run_response_generation for Debugger meta-agent (#876)
MaiaJP-AIXplain Mar 26, 2026
53fc567
Add pre-commit CI workflow and fix two failing unit tests (#879)
aix-ahmet Mar 26, 2026
dd3317a
ENG-2836 Agent cloning introduced (#847)
kadirpekel Mar 26, 2026
3b6a63f
ENG-2847 fix the ActionInputsProxy to properly extract and coerce def…
kadirpekel Mar 26, 2026
f32e80f
Eng 2840 implement rlms (#869)
elsheikhams99 Mar 26, 2026
af6c341
ENG-2922: Add token usage and asset fields to model response (#881)
aix-ahmet Mar 27, 2026
632b214
each actions spec retrieved + attributes -> list (#883)
xainaz Mar 31, 2026
05c827c
ENG-2891 Tool saving foundation (#872)
kadirpekel Mar 31, 2026
8d29034
added available action (#887)
xainaz Mar 31, 2026
e83814c
Change default model for agents to GPT-5.4 (#888)
elsheikhams99 Apr 1, 2026
65d5520
Eng 2922 add token usage in llm calls in sdk (#884)
aix-ahmet Apr 1, 2026
a0ca7eb
ENG-2922 Token usage tracking in model responses and agent progress (…
aix-ahmet Apr 1, 2026
31eaddf
BUG-734 Fix OAuth tool deserialization crash and type mismatch (#891)
aix-ahmet Apr 6, 2026
fc9349c
fix single-action tool serialization and coverage (#898)
aix-ahmet Apr 6, 2026
12f38e3
Support URLs in RLMs context (#892)
elsheikhams99 Apr 7, 2026
adc66ca
docs: align root and docs README (#895)
nurhamdan1987 Apr 7, 2026
b0218f8
docs: add llms reference files (#893)
nurhamdan1987 Apr 7, 2026
8504c75
Main to Test (#899)
aix-ahmet Apr 7, 2026
fc38ae6
Merge origin/test into development
aix-ahmet Apr 7, 2026
7f0ce73
tests: restore GPT-5.4 default llm references
aix-ahmet Apr 7, 2026
23be558
Development (#901)
aix-ahmet Apr 7, 2026
12e1967
fix: support modern S3 presigned upload URLs
aix-ahmet Apr 7, 2026
8b1de63
remove not available cladue model
aix-ahmet Apr 7, 2026
bdf7c3b
update model to gpt 4o
aix-ahmet Apr 7, 2026
ddf3840
remove not available modedl
aix-ahmet Apr 7, 2026
89976a2
fix: align v2 attributes and functional fixtures with backend
aix-ahmet Apr 7, 2026
6d77e3f
Merge branch 'test' into development
aix-ahmet Apr 7, 2026
9bd9bfc
Development (#902)
aix-ahmet Apr 7, 2026
25dbeaa
Merge branch 'main' into test
aix-ahmet Apr 7, 2026
0b66545
chore: change the in/out token format
aix-ahmet Apr 7, 2026
c58c2f4
Update pyproject.toml (#909)
aix-ahmet Apr 9, 2026
317faa7
Eng 2969 (#910)
elsheikhams99 Apr 9, 2026
c8ef8de
Add support for pre-built inspectors (#913)
elsheikhams99 Apr 14, 2026
0631f7a
Development (#914)
ikxplain Apr 16, 2026
8d0792b
test: add Arabic v2 functional coverage (#906)
aix-ahmet Apr 17, 2026
6e94ab5
merge to test (#915)
hadi-aix Apr 24, 2026
444b435
Update AGENTS.md with behavioral rules for coding agents (#911)
nurhamdan1987 Apr 27, 2026
423942a
added datetime extracted (#873)
xainaz Apr 27, 2026
7ba7e8e
added mock link to test (#917)
xainaz May 4, 2026
b8517b4
Merge branch 'main' into test
elsheikhams99 May 5, 2026
20be0c7
fix(ENG-3044): force UTF-8 on SSE response in ModelResponseStreamer (…
MaiaJP-AIXplain May 6, 2026
b43d87a
Add hallucination guardrail (#916)
elsheikhams99 May 7, 2026
e05be93
Add agents with aixplain tools tests (#924)
elsheikhams99 May 11, 2026
a130638
initial changes for llms (#922)
xainaz May 22, 2026
94dd353
docs: refresh SDK README for SDK 2 (#938)
nurhamdan1987 Jun 1, 2026
5c27b31
main to test sync (#939)
aix-ahmet Jun 1, 2026
6b45ad2
Merge branch 'development' into test
aix-ahmet Jun 1, 2026
cec837e
Test to dev sync (#940)
aix-ahmet Jun 1, 2026
619fee3
feat: add parallel and rag modes to RLMs (#928)
elsheikhams99 Jun 2, 2026
f7e15d5
issue + tests added (#896)
xainaz Jun 2, 2026
a93ad3d
fix(v2): tolerate non-list details in ModelResult deserialization (#942)
aix-ahmet Jun 3, 2026
ee3b70f
fix(v2): V3-compat agent fixes — dict expected_output at run, json de…
aix-ahmet Jun 3, 2026
fe46dbc
fix(v2): dispatch prebuilt inspector payloads in Agent.__post_init__
aix-ahmet Jun 3, 2026
63ad1e5
Remove temperature parameter from worker run call (#945)
elsheikhams99 Jun 4, 2026
98d5e94
New feature for silent release - Agent benchmarking v0.1 (#946)
shreyasXplain Jun 5, 2026
5236df5
error codes changes (#934)
xainaz Jun 8, 2026
3e8c9a8
Merge branch 'test' into development
hadi-aix Jun 8, 2026
85c3750
merge to test (#948)
hadi-aix Jun 8, 2026
7fe6627
fix unit tests
aix-ahmet Jun 9, 2026
7ad13f4
fix(tests): replace removed/deprecated hardcoded asset IDs
aix-ahmet Jun 9, 2026
7ab1fe0
ci: trigger fresh test run
aix-ahmet Jun 9, 2026
a11d65f
test(general_assets): skip destructive test_model_deletion
aix-ahmet Jun 9, 2026
2fc1cfe
fix(sdk): harden against deleted models, dict polling responses, and …
aix-ahmet Jun 9, 2026
acb2b9e
fix(api_key): handle string model id in to_dict and _set_limit
aix-ahmet Jun 9, 2026
3ee24f8
Merge branch 'development' into test
aix-ahmet Jun 10, 2026
d003015
fix: remove incorrect object attribute access for dict response (#951)
shreyasXplain Jun 10, 2026
cd4cf5a
Fix/pipeline polling status (#955)
shreyasXplain Jun 10, 2026
024dba0
Merge branch 'main' into test
aix-ahmet Jun 11, 2026
3aa42df
fix: add trailing newlines to Arabic markdown files
aix-ahmet Jun 11, 2026
5df7b20
Development (#988)
aix-ahmet Jul 14, 2026
eb17443
Development (#990)
ikxplain Jul 17, 2026
7436793
Development (#992)
aix-ahmet Jul 21, 2026
ab93886
Development (#994)
aix-ahmet Jul 21, 2026
5664f4d
fix(ci): repair test-branch CI failures (run 29570846631) (#995)
aix-ahmet Jul 21, 2026
99e09c7
test(v2): align functional tests with current backend behavior (#996)
aix-ahmet Jul 21, 2026
edd8df7
test(v2): match Arabic inspector steps by the inspector's configured …
aix-ahmet Jul 21, 2026
640bed9
test: quiet the remaining non-backend CI failures (#998)
aix-ahmet Jul 21, 2026
0fb24b2
Merge remote-tracking branch 'origin/main' into test
aix-ahmet Jul 21, 2026
c296bb5
Merge to test 20260723 (#1002)
hadi-aix Jul 23, 2026
43f20a4
Merge to test 20260723 (#1004)
hadi-aix Jul 23, 2026
65865fd
Development (#1008)
aix-ahmet Jul 24, 2026
8a9d34f
Merge to test 20260723 (#1010)
hadi-aix Jul 24, 2026
66e2ae1
Merge branch 'main' into test
aix-ahmet Jul 27, 2026
3309ce8
Merge to test 20260730 (#1015)
hadi-aix Jul 30, 2026
b1cc941
Merge branch 'main' into test
ikxplain Jul 30, 2026
9ad943b
fix(model): restore session_id in _SDK_ONLY_PARAMS dropped by merge (…
aix-ahmet Jul 31, 2026
d226930
Merge to test 20260805 (#1024)
hadi-aix Aug 5, 2026
ec57bfc
Merge to test 20260805 (#1028)
hadi-aix Aug 5, 2026
47703cb
fix(tool): point DEFAULT_INTEGRATION_ID at Python Sandbox, not Slack …
aix-ahmet Aug 5, 2026
48dd2d8
fix(tool): send required function_name when connecting script tools (…
aix-ahmet Aug 5, 2026
cd05dad
fix(client): surface supplierError detail in APIError messages (#1032)
aix-ahmet Aug 5, 2026
35fa86b
Merge to test 20260807 (#1037)
hadi-aix Aug 7, 2026
7368956
Merge to test 20260807 (#1038)
hadi-aix Aug 7, 2026
b59443f
Merge to test 20260810 (#1039)
hadi-aix Aug 10, 2026
fa28e90
Merge to test 20260812 (#1049)
hadi-aix Aug 12, 2026
3073908
Merge to test 20260813 (#1052)
hadi-aix Aug 13, 2026
3799143
Merge to test 20260814 (#1054)
hadi-aix Aug 14, 2026
3d65305
Merge to test 20260824 (#1059)
hadi-aix Aug 24, 2026
e21d09d
Merge to test 20260825 (#1062)
hadi-aix Aug 25, 2026
f525377
Merge to test 20260826 (#1063)
hadi-aix Aug 27, 2026
65319bb
Merge to test 20260827 (#1064)
hadi-aix Aug 27, 2026
bb3a5d1
Merge to test 20260828 (#1067)
hadi-aix Aug 28, 2026
92e530b
Merge to test 20260829 (#1068)
hadi-aix Sep 5, 2026
9d6c942
Development (#1087)
aix-ahmet Sep 8, 2026
c1fa26e
Merge branch 'main' into test
aix-ahmet Sep 8, 2026
071bd9f
Merge to test 20260910 (#1092)
hadi-aix Sep 10, 2026
4d696ed
Merge to test 20260915 (#1131)
hadi-aix Sep 15, 2026
6194ea0
Merge main into test to resolve conflicts for production release 2026…
aix-ahmet Sep 16, 2026
a322b7d
Merge to test 20260916 (#1135)
hadi-aix Sep 18, 2026
89a7398
Merge to test 20260922 (#1141)
hadi-aix Sep 22, 2026
069e08c
Merge to test 20260924 (#1143)
hadi-aix Sep 24, 2026
4c2d959
Development to Test (#1148)
aix-ahmet Sep 29, 2026
e65d7b9
Development (#1149)
aix-ahmet Sep 30, 2026
c82d509
Merge to test 20261006 (#1165)
hadi-aix Oct 6, 2026
96e4d85
Merge to test 20261009 (#1173)
hadi-aix Oct 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 4 additions & 2 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ jobs:
python-version: '3.x'

- name: Install dependencies
# Pinned: the config relies on this version's renderer options.
run: |
pip install pydoc-markdown
pip install 'pydoc-markdown==4.8.2'

- name: Run pydoc-markdown
# PYTHONPATH=. lets the config import docs_rst_processor by dotted path.
run: |
pydoc-markdown pydoc-markdown.yml
PYTHONPATH=. pydoc-markdown pydoc-markdown.yml

- name: Create Pull Request if docs changed
uses: peter-evans/create-pull-request@v7
Expand Down
43 changes: 0 additions & 43 deletions .github/workflows/generator-drift.yaml

This file was deleted.

600 changes: 529 additions & 71 deletions .github/workflows/main.yaml

Large diffs are not rendered by default.

32 changes: 31 additions & 1 deletion .github/workflows/pre-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,43 @@ jobs:
python-version: "3.9"
cache: 'pip'

# The `gitleaks` pre-commit hook only sees the staged diff, so under
# `pre-commit run --all-files` below it scans nothing. This step is what
# actually satisfies "a secret scanner runs on every push" (ENG-3686): it
# walks the whole working tree, using the same rules and allowlists from
# .gitleaks.toml. Keep GITLEAKS_VERSION in step with the `rev` pinned for
# the hook in .pre-commit-config.yaml, and GITLEAKS_SHA256 in step with the
# linux_x64 line of that release's gitleaks_<version>_checksums.txt.
- name: Scan the full tree for secrets
env:
GITLEAKS_VERSION: "8.28.0"
GITLEAKS_SHA256: "a65b5253807a68ac0cafa4414031fd740aeb55f54fb7e55f386acb52e6a840eb"
run: |
set -euo pipefail
curl -sSfL -o /tmp/gitleaks.tar.gz \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
# Refuse to run a binary that is not the pinned release.
echo "${GITLEAKS_SHA256} /tmp/gitleaks.tar.gz" | sha256sum -c -
tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks
# `dir` (not `git`) so the scan covers the checked-out tree rather than
# a commit range; on a first push the range would be empty.
/tmp/gitleaks dir . --config .gitleaks.toml --redact --verbose --no-banner

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ".[test]"
pip install pre-commit coverage

# No TEAM_API_KEY (ENG-3683). The `pytest-check` hook runs `tests/unit`,
# which is credential-free by design (ENG-3431), so the key was only ever
# exposed to the third-party hook code this job also executes. If this job
# ever starts failing on a missing key, the regression is a unit test that
# has grown a backend dependency -- not this workflow.
- name: Run pre-commit hooks
env:
TEAM_API_KEY: ${{ secrets.TEAM_API_KEY }}
# The gitleaks hook is staged-diff only, so under --all-files it would
# build Go from source just to scan nothing. The step above already
# scans the whole tree.
SKIP: gitleaks
run: pre-commit run --all-files
166 changes: 157 additions & 9 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,144 @@ on:
permissions: {}

jobs:
# A tag could publish a wheel whose functional suites had never run against a
# live backend: this workflow gated only on `pytest tests/unit`, and `main.yaml`
# did not run on pull requests at all (ENG-3683). This job refuses to proceed
# unless every functional leg went green on the exact commit being released.
#
# Read-only, and deliberately not a `workflow_run` trigger: `workflow_run` fires
# when the *other* workflow finishes, which inverts the dependency (the test run
# would have to start the release) and cannot express "the run that already
# happened on this SHA".
functional-gate:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
# `gh api .../actions/runs` and `.../jobs`, which this workflow's deny-all
# default does not grant. Read only: this job decides, it never re-runs
# anything.
actions: read
steps:
- name: Checkout the tagged commit
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9"

- name: Require a green functional run on the tagged commit
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
# The commit the tag points at, not the tag name: a tag can be moved,
# and what was tested is a SHA.
SHA: ${{ github.sha }}
# Only used to recognise a manual dispatch of main.yaml on this tag.
TAG: ${{ github.ref_name }}
SERVER_URL: ${{ github.server_url }}
run: |
set -euo pipefail
python -m pip install --quiet --upgrade pip PyYAML

# The legs are read from the workflow file at the tagged commit rather
# than hardcoded here: a leg added in the same release would otherwise
# be quietly optional on the release that first ships it.
legs="$(python - <<'PY'
import yaml

with open(".github/workflows/main.yaml") as handle:
workflow = yaml.safe_load(handle)

for leg in workflow["jobs"]["functional"]["strategy"]["matrix"]["suite"]:
print(f"functional ({leg})")
PY
)"
test -n "$legs"

# Only runs that used the production backend and key count: a push to
# `main` (the normal flow), or a manual dispatch on this very tag (the
# recovery path below). main.yaml's IS_PROD is true for both. A push
# to `test`, a PR run or the nightly can sit on the same commit,
# but their legs passed against the test backend, and a release
# validated there proves nothing about what the wheel is published for
# (ENG-3683). The dispatch must be on this tag by name,
# not on any ref starting with "v": `version_2` is a branch, and a
# dispatch on a branch runs against the test backend.
#
# `head_branch` is a bare name, though, so a dispatch on a *branch*
# named exactly like this tag passes the filter too. Each run's jobs
# therefore have to include a successful `production-backend` job,
# which main.yaml runs only when IS_PROD is true; see `jobs_filter`.
#
# Every qualifying completed run, not just the latest: a first run that
# failed and a re-run of the failed legs together mean the commit is
# green, and only the union says so.
runs_filter='.workflow_runs[]
| select(.status == "completed")
| select((.event == "push" and .head_branch == "main")
or (.event == "workflow_dispatch" and .head_branch == $tag))
| .id'
runs="$(gh api --paginate \
"repos/$REPO/actions/workflows/main.yaml/runs?head_sha=$SHA&per_page=100" \
| jq -r --arg tag "$TAG" "$runs_filter")"

if [ -z "$runs" ]; then
echo "::error::no completed production run of main.yaml on $SHA."
echo "The functional matrix must have run against the production backend on the exact commit"
echo "being released: a push to main, or a manual dispatch on this tag. Runs from a push to"
echo "test, a PR or the nightly do not count -- they used the test backend."
echo "If this tag was pushed right after the merge, the main run may still be in progress:"
echo "wait for it to finish, then re-run this release."
echo "Otherwise: run main.yaml against the tag (Actions -> Run Tests -> Run workflow,"
echo "ref = $TAG), let it go green, then re-run this release."
exit 1
fi

# The names of a run's successful jobs, or nothing at all when its
# `production-backend` job did not succeed. Slurped, because
# `gh api --paginate` prints one JSON document per page.
jobs_filter='[.[].jobs[] | select(.conclusion == "success") | .name]
| if any(.[]; . == "production-backend") then .[] else empty end'
green="$(mktemp)"
for run in $runs; do
jobs="$(gh api --paginate "repos/$REPO/actions/runs/$run/jobs?per_page=100" | jq -rs "$jobs_filter")"
if [ -z "$jobs" ]; then
echo "::warning::run $run did not run against production (no successful production-backend job); not counted."
continue
fi
printf '%s\n' "$jobs" >> "$green"
done

missing=0
while IFS= read -r leg; do
if grep -Fxq "$leg" "$green"; then
echo "ok $leg"
else
echo "MISSING $leg"
missing=1
fi
done <<< "$legs"

if [ "$missing" -ne 0 ]; then
echo "::error::functional legs listed as MISSING above never succeeded on $SHA."
echo "Runs inspected (production runs only): $(echo "$runs" | tr '\n' ' ')"
echo "Re-run the failed legs of one of those runs, or dispatch main.yaml on $TAG, then"
echo "re-run this release."
echo "See $SERVER_URL/$REPO/actions/workflows/main.yaml"
exit 1
fi
echo "every functional leg is green on $SHA"

# Runs repository code (pip, build, pytest) and therefore holds NO id-token:
# a compromised build dependency must never share a process with the OIDC
# credential that can upload to PyPI.
build:
# Nothing is built for a commit the functional matrix has not passed.
needs: functional-gate
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
Expand Down Expand Up @@ -77,12 +211,15 @@ jobs:
print(f"tag {tag} matches declared version {declared}")
PY

# The whole unit suite, not just the packaging and CI guards. main.yaml is
# push-only and `required_status_checks.contexts` is still empty (this PR
# documents the flip but cannot make it), so nothing guarantees the tagged
# commit ever passed `unit-coverage`: `git tag v0.2.48 <any-commit> && git
# push --tags` would otherwise publish with the suite unrun. The suite is
# credential-free (ENG-3431), so it needs no secrets in this job.
# The whole unit suite, not just the packaging and CI guards.
# `required_status_checks.contexts` is still empty (docs/ci/required-checks.md
# documents the flip but a merge cannot make it), so nothing outside this
# workflow guarantees the tagged commit ever passed `unit-coverage`: `git tag
# v0.2.48 <any-commit> && git push --tags` would otherwise publish with the
# suite unrun. `functional-gate` above covers the functional matrix; this
# covers the unit suite, and unlike the gate it re-runs the tests here rather
# than trusting a recorded result. The suite is credential-free (ENG-3431),
# so it needs no secrets in this job.
#
# This covers the static half of the ENG-3543 packaging gate. The slow half
# (a .git-less export and a full module census) is main.yaml's
Expand All @@ -94,6 +231,10 @@ jobs:
# into a collection-time skip, a stray `-k` -- exits 0, and the release
# would proceed on a tree nothing had checked.
AIXPLAIN_REQUIRE_EXECUTED_TESTS: "1"
# The proportional floor from ENG-3684, matching main.yaml. The unit
# suite is credential-free, so anything much below this means tests are
# skipping themselves for reasons the release should not ship past.
AIXPLAIN_MIN_EXECUTED_RATIO: "0.8"
run: |
set -euo pipefail
pip install ".[test]"
Expand Down Expand Up @@ -126,16 +267,23 @@ jobs:
cd "$RUNNER_TEMP"
"$RUNNER_TEMP/venv/bin/python" - <<'PY'
import aixplain
import aixplain.base.parameters # noqa: F401 -> v1/base/, no __init__.py
import aixplain.v1.modules.model # noqa: F401
import aixplain.v2.core # noqa: F401
import aixplain.v2.api_key # noqa: F401
import aixplain.utils.url_safety # noqa: F401

assert "site-packages" in aixplain.__file__, (
f"imported the source tree, not the wheel: {aixplain.__file__}"
)
# v1 was removed in 0.3.0; a wheel that still resolves a legacy path
# would mean the removal did not reach the artifact.
try:
import aixplain.factories # noqa: F401
except ModuleNotFoundError as exc:
assert "aix.Agent" in str(exc), f"v1 error no longer names a v2 equivalent: {exc}"
else:
raise SystemExit("aixplain.factories still imports; v1 leaked into the wheel")
print("imported", aixplain.__file__)
PY
"$RUNNER_TEMP/venv/bin/aixplain" --help > /dev/null

- name: Upload the distribution for the publish job
uses: actions/upload-artifact@v4
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ brusk.yaml
pip-log.txt
pip-delete-this-directory.txt

# Local run-log scratch written by functional runs (distinct from tests/).
/test/

# Unit test / coverage reports
htmlcov/
.tox/
Expand Down
72 changes: 72 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Secret scanning for the aiXplain SDK (ENG-3686).
#
# Live platform keys were committed in plaintext in scratch files and sat in the
# tree for months. This config backs
# the `gitleaks` hook in .pre-commit-config.yaml and the full-tree scan in
# .github/workflows/pre-commit.yaml, which runs on every push.
#
# The allowlists below are deliberately narrow. Do NOT allowlist a whole test
# directory or file: the fixtures under tests/ are exactly where a real key gets
# pasted "just to try something". Allowlist the specific fake value, and say why.

title = "aiXplain SDK"

[extend]
# Gitleaks' curated rule set. It matches credential shapes (AWS keys, JWTs,
# GitHub tokens, high-entropy values next to an api_key-ish assignment) rather
# than raw entropy, so the repo's 24-hex MongoDB asset IDs are not flagged.
# detect-secrets was evaluated first and reported ~350 of them (ENG-3686).
useDefault = true

# The curated rules miss the shapes this repo actually leaked: a 64-hex platform
# key in `os.environ["TEAM_API_KEY"] = "..."`, in `{"Authorization": "Token ..."}`
# and passed straight to the client. A leaked assignment line went unreported;
# only saved notebook output tripped a default rule, so the same notebook saved
# without outputs would have passed. These two rules close
# that gap. tests/unit/test_secret_scanning.py checks both against those shapes.
#
# The text between the name and the key may hold hex letters (`_PROD`, `_DEV`,
# `_KEY`), so the rule only asks for a non-hex character right before the key,
# not for a separator free of a-f. A separator that had to avoid a-f missed
# `TEAM_API_KEY_PROD="<key>"` and `{"x-aixplain-key": "<key>"}`. Every name
# below ends in a non-hex letter, so a key written straight after one still has
# a boundary on its left.
[[rules]]
id = "aixplain-platform-key"
description = "aiXplain platform/team API key: 64 hex characters shortly after a credential name on the same line."
regex = '''(?i)(?:api[_-]?key|team[_-]?key|access[_-]?key|aixplain[_-]?key|token|secret|authorization)(?:[^\n]{0,40}?[^0-9a-f\n])?([0-9a-f]{64})(?:[^0-9a-f]|$)'''
secretGroup = 1
keywords = ["api_key", "api-key", "apikey", "team_key", "team-key", "access_key", "access-key", "aixplain_key", "aixplain-key", "token", "secret", "authorization"]

[[rules]]
id = "aixplain-client-positional-key"
description = "aiXplain platform API key passed positionally, as in `Aixplain(\"<key>\")`, where no credential name is on the line."
regex = '''(?i)\baixplain\(\s*["']([0-9a-f]{64})["']'''
secretGroup = 1
keywords = ["aixplain("]

[[allowlists]]
description = "Build artifacts, not reviewable source. `gitleaks dir .` walks the working tree, so a local run would otherwise re-report every secret-shaped literal frozen into a .pyc. All of these are gitignored and never reach a CI checkout."
paths = [
'''__pycache__/''',
'''\.pyc$''',
'''^\.venv/''',
'''^venv/''',
'''^uv\.lock$''',
]

[[allowlists]]
description = "Documentation placeholder. A literal instruction to the reader, never a live value."
regexes = [
'''^YOUR_API_KEY$''',
]

[[allowlists]]
description = "Hand-written fake credentials in unit tests, matched by exact value. Keep this list literal so a real key pasted next to them still trips the scanner."
regexes = [
'''^abcd1234efgh$''',
'''^wxyz5678uvst$''',
'''^valid_api_key_123$''',
# The planted key in tests/unit/test_secret_scanning.py, which must look like a real one to test the detector.
'''^deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef$''',
]
Loading
Loading