Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
6ffcca3
refactor!: remove client-side search from the Node SDK
willleeney Sep 15, 2026
083b90e
fix!: remove search leftovers the typecheck never saw
willleeney Sep 16, 2026
fe73783
feat(tool): preserve root schema keywords in toJsonSchema pass-through
willleeney Sep 29, 2026
18c3003
style: run oxfmt on formatted files
willleeney Sep 29, 2026
2bb8dbf
fix(toolsets): remove unused imports to pass oxlint
willleeney Sep 29, 2026
bdddc58
refactor!: remove SDK-side defender configuration
willleeney Sep 29, 2026
ed777cd
refactor!: remove the client-side feedback tool
willleeney Sep 29, 2026
e66ab64
fix(toolsets)!: stop model-supplied headers from switching tenant
willleeney Sep 29, 2026
527549d
refactor!: root every SDK error at StackOneError
willleeney Sep 29, 2026
dd3d5e3
fix(download): reduce Content-Disposition filenames to a safe basename
willleeney Sep 29, 2026
2eb93aa
refactor!: rebuild the toolset on the served MCP catalog
willleeney Sep 29, 2026
05bba04
feat: add search(), execute() and submitFeedback() with session ids
willleeney Sep 29, 2026
cf6501b
feat(tools): add executeOpenAIToolCalls()
willleeney Sep 29, 2026
17c589c
docs: document search/execute, feedback and the pass-through schema
willleeney Sep 29, 2026
9ec38c1
ci: run the sdk-conformance suite against the built SDK
willleeney Sep 29, 2026
cdb4b8e
refactor!: execute every tool over MCP tools/call
willleeney Sep 29, 2026
6d0f3b5
docs: describe MCP-only execution, dryRun and download links
willleeney Sep 29, 2026
7b14868
ci: pin sdk-conformance to the MCP-only suite
willleeney Sep 29, 2026
fd862c1
test: keep the search-and-execute example out of the root typecheck
willleeney Sep 29, 2026
c4b9ba7
test: type-check the search-and-execute example against source
willleeney Sep 30, 2026
92aa49d
fix(tools)!: forward only the header arguments a served schema declares
willleeney Sep 30, 2026
10975c8
fix(feedback): submit feedback with one tools/call on the first account
willleeney Sep 30, 2026
d44ec90
test(toolsets): pin getTool() to the first listed duplicate
willleeney Sep 30, 2026
406504d
refactor(errors): remove the unused describeApiFailure()
willleeney Sep 30, 2026
37e2efe
fix(toolsets): share one in-flight account discovery between concurre…
willleeney Sep 30, 2026
7d65495
fix(tools): serialise a tool result of undefined as "null"
willleeney Sep 30, 2026
3da22ec
feat(types): declare the fields a search hit carries
willleeney Sep 30, 2026
25812d1
docs: add a 2.x to 3.0 migration guide
willleeney Sep 30, 2026
d0876f0
ci: pin sdk-conformance to 9b5605a
willleeney Sep 30, 2026
988e54c
fix(toolsets): reject an empty account id
willleeney Oct 1, 2026
c3c4c71
fix(headers): declare no names for a closed or untyped headers object
willleeney Oct 1, 2026
bb220e0
fix(examples): print a non-numeric similarity score without throwing
willleeney Oct 1, 2026
7ec5d69
ci: re-check the PR title when a draft is marked ready
willleeney Oct 1, 2026
1269d28
fix(tools): reject NaN and Infinity arguments instead of sending them…
willleeney Oct 1, 2026
111701e
fix(toolsets): validate submitFeedback() sessionId as execute() does
willleeney Oct 1, 2026
95c3cb3
test: dispatch mock meta tools only in search_execute mode
willleeney Oct 1, 2026
aefce47
docs: match the README and migration guide to what the code does
willleeney Oct 1, 2026
64b3fe8
ci: pin sdk-conformance to 6a6991d
willleeney Oct 1, 2026
f953281
fix(toolsets): reject an empty accountId instead of widening to every…
willleeney Oct 1, 2026
faeed0b
refactor(toolsets): stop reading STACKONE_ACCOUNT_ID
willleeney Oct 1, 2026
460f495
feat: retry HTTP 429 responses and fail fan-outs on a persistent 429
willleeney Oct 1, 2026
fb2cadc
docs(readme): describe rate-limit retries
willleeney Oct 1, 2026
9f588c8
fix(retry): read only digits or an HTTP-date as Retry-After
willleeney Oct 1, 2026
dc9a755
ci: pin sdk-conformance to 9d5efab
willleeney Oct 1, 2026
05fa4fd
fix(retry): read Retry-After as a date only when it starts with a wee…
willleeney Oct 1, 2026
6639d19
fix(retry): return the 429 when a retry's wait would outlast the timeout
willleeney Oct 1, 2026
98254a7
test(mock): record each tools/call from the raw request body
willleeney Oct 1, 2026
609e3fc
fix(headers): keep a tool argument or header named __proto__
willleeney Oct 1, 2026
a8ea52f
feat(types): type execute() and submitFeedback() results as ActionResult
willleeney Oct 1, 2026
b80451e
docs: describe fetchTools() arguments and empty account ids as they n…
willleeney Oct 1, 2026
45917f1
fix(schema): keep a schema property named __proto__ when folding root…
willleeney Oct 1, 2026
b1427f7
fix(headers): drop non-object header arguments that aren't declared a…
willleeney Oct 1, 2026
04bcd7f
ci: pin sdk-conformance to 67103ca
willleeney Oct 1, 2026
dcd9c8a
fix(headers): treat array-typed headers field without object as ordinary
willleeney Oct 1, 2026
ba73216
feat(errors): add ToolArgumentsError
willleeney Oct 1, 2026
b6de5a0
fix(tool): throw ToolArgumentsError for malformed or unencodable argu…
willleeney Oct 1, 2026
486e052
fix(toolset): treat a null sessionId as not given
willleeney Oct 1, 2026
2be2c5f
fix(toolsets): treat an empty baseUrl or STACKONE_BASE_URL as unset, …
willleeney Oct 1, 2026
4de520f
fix(retry): read a Retry-After date strictly, as an RFC 9110 HTTP-dat…
willleeney Oct 2, 2026
56f8e2a
fix(headers): open a headers schema typed ["object", "null"], and tre…
willleeney Oct 2, 2026
bb21398
fix(tool): refuse a lone surrogate in tool arguments
willleeney Oct 2, 2026
259d0c9
fix(toolsets): treat accountIds: null as not given
willleeney Oct 2, 2026
222b668
fix: align error and warning messages with the Python SDK
willleeney Oct 2, 2026
ccf2318
feat(retry): warn when a 429 is not retried because the wait would pa…
willleeney Oct 2, 2026
3ce3c0d
fix(retry): read a Retry-After date as the shared vectors do
willleeney Oct 2, 2026
cc19db0
test: run the shared sdk-conformance vectors against the SDK
willleeney Oct 2, 2026
ebf1393
ci: fail when the vendored vectors differ from the pinned sdk-conform…
willleeney Oct 2, 2026
99b1516
Revert "fix(retry): read a Retry-After date as the shared vectors do"
willleeney Oct 2, 2026
b7c1647
test(vectors): sync the shared vectors to sdk-conformance daf1140
willleeney Oct 2, 2026
3405514
ci: pin sdk-conformance to daf1140
willleeney Oct 2, 2026
ea6984d
docs(migration): qualify the JSON-value and integer-precision rules
willleeney Oct 2, 2026
e7af56d
fix(tool): treat sparse array holes as undefined in argument validation
willleeney Oct 2, 2026
707ceba
fix(scripts): make sync-vectors.sh atomic and refuse a dirty source
willleeney Oct 2, 2026
59c6eec
test(fetch-retry): cover a leap second rolling into the next year
willleeney Oct 2, 2026
a41e548
test(vectors): sync the shared vectors to sdk-conformance 0906f4d
willleeney Oct 2, 2026
dbc296d
fix(headers): forward an ordinary headers field unchanged whatever it…
willleeney Oct 2, 2026
20d731f
ci: pin sdk-conformance to 0906f4d
willleeney Oct 2, 2026
a28f3a7
docs(migration): an ordinary headers field still passes the JSON-valu…
willleeney Oct 2, 2026
0faa7f5
test(vectors): sync the shared vectors to sdk-conformance dfdaca1
willleeney Oct 2, 2026
24174d0
ci: pin sdk-conformance to dfdaca1
willleeney Oct 2, 2026
7ff3452
test(vectors): sync the shared vectors to sdk-conformance ee0bb06
willleeney Oct 2, 2026
66dc25e
ci: pin sdk-conformance to ee0bb06
willleeney Oct 2, 2026
6dc31e5
test(vectors): fail on a vector file that no test grades
willleeney Oct 2, 2026
3f098d0
docs: pass STACKONE_ACCOUNT_ID || undefined in every snippet and example
willleeney Oct 2, 2026
ba3fa71
feat(toolsets): warn when STACKONE_ACCOUNT_ID is set but ignored
willleeney Oct 2, 2026
71206eb
fix(retry): report a timeout while retrying a 429 as the 429
willleeney Oct 2, 2026
e16e1fa
fix(toolsets): cache healthy accounts and keep each failure when ever…
willleeney Oct 2, 2026
6ab1ab7
feat(search): tag each hit with its account_id and apply topK to the …
willleeney Oct 2, 2026
3903b07
fix(execute): refuse an action whose connector is linked on more than…
willleeney Oct 2, 2026
7a41011
fix(tools): build every adapter from the first tool of each name
willleeney Oct 2, 2026
bde595a
feat(feedback): add actionRunId, and send feedback on the lowest acco…
willleeney Oct 2, 2026
c6625b0
test(mcp-client): pin image, audio and resource parts as plain JSON u…
willleeney Oct 2, 2026
53052d5
ci: run the full conformance suite against the Python SDK too
willleeney Oct 2, 2026
35b475a
test: clear STACKONE_ACCOUNT_ID for the test run
willleeney Oct 2, 2026
dd09e38
fix: adopt the review-round messages from sdk-conformance ec4dcfb
willleeney Oct 2, 2026
897bb9c
ci: pin sdk-conformance to ec4dcfb
willleeney Oct 2, 2026
9addab5
style: format the conformance job and a listing test
willleeney Oct 2, 2026
280df89
test(vectors): grade the 429-timeout messages
willleeney Oct 2, 2026
16eb697
ci: pin sdk-conformance to db6b908
willleeney Oct 2, 2026
7bcab06
fix(types): make SearchResult.account_id required
willleeney Oct 2, 2026
901f680
ci: pin the Python SDK checkout to a commit SHA
willleeney Oct 2, 2026
92dd680
docs: qualify account scope failure modes and pin accountIds in searc…
willleeney Oct 2, 2026
0b0ce6d
fix(toolsets): coalesce concurrent catalog listings and warn on empty…
willleeney Oct 2, 2026
53f4347
test: remove unreachable fallback paths in rate-limit-timeout vectors
willleeney Oct 2, 2026
d849a58
fix(mcp-client): reset the rate-limit flag per request, not per session
willleeney Oct 2, 2026
00da255
chore: sync vectors and pin sdk-conformance to c794e56
willleeney Oct 2, 2026
82fe558
ci: run conformance against stackone-ai-python 7e9b3ef
willleeney Oct 2, 2026
79c272e
feat(toolsets): send x-end-user-id for non-shared accounts
willleeney Oct 2, 2026
65dc469
chore: sync vectors and pin sdk-conformance to f46905f
willleeney Oct 2, 2026
4dd5df9
feat(toolsets): use the shared ignored-headers warning text
willleeney Oct 2, 2026
bb9dc14
chore(ci): pin sdk-conformance to 0d72282
willleeney Oct 2, 2026
334c840
test(vectors): sync to sdk-conformance 88c9400
willleeney Oct 2, 2026
8030159
ci: pin sdk-conformance to 88c9400
willleeney Oct 2, 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
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Required for all examples
STACKONE_API_KEY=your-stackone-api-key

# Optional: the examples read this and pass it as accountId (the SDK itself never reads it).
# Without it, the SDK uses every active account linked to the API key
STACKONE_ACCOUNT_ID=your-account-id

# Required for OpenAI examples (openai-integration, openai-responses-integration, search-tools)
# Required for OpenAI examples (openai-integration, openai-responses-integration, ai-sdk-integration)
OPENAI_API_KEY=your-openai-api-key

# Required for Anthropic examples (anthropic-integration, claude-agent-sdk-integration)
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/check-title.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- reopened
- edited
- synchronize
- ready_for_review

permissions:
pull-requests: read
Expand Down
130 changes: 130 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,136 @@ jobs:
- name: Run Tests
run: pnpm exec vitest run --project root

# Enforces the wire contract shared with the Python SDK (StackOneHQ/sdk-conformance).
# StackOneHQ/sdk-conformance is private and requires CONFORMANCE_REPO_TOKEN.
# Fork PRs and Dependabot runs cannot access this secret and skip this gate;
# internal branches and PRs require the secret and fail if it is absent or expired.
check-secret:
runs-on: ubuntu-latest
outputs:
can-skip: ${{ steps.check.outputs.can-skip }}
steps:
- id: check
env:
TOKEN: ${{ secrets.CONFORMANCE_REPO_TOKEN }}
IS_FORK: ${{ github.event.pull_request.head.repo.fork == true }}
IS_DEPENDABOT: ${{ github.actor == 'dependabot[bot]' }}
run: |
if [ -z "$TOKEN" ] && { [ "$IS_FORK" = "true" ] || [ "$IS_DEPENDABOT" = "true" ]; }; then
echo "can-skip=true" >> "$GITHUB_OUTPUT"
else
echo "can-skip=false" >> "$GITHUB_OUTPUT"
fi

# Runs the full suite, both SDKs side by side, so a change here that the Python SDK does not
# match fails here rather than drifting.
conformance:
needs: check-secret
if: needs.check-secret.outputs.can-skip != 'true'
runs-on: ubuntu-latest
env:
# Pinned to a commit rather than the branch while StackOneHQ/stackone-ai-python#210 is
# open, so this only moves when we bump it deliberately. Switch to a main commit once it
# merges.
PYTHON_SDK_REF: 7e9b3efd1101eb953813486b789c57bd0645ad0e
steps:
- name: Check conformance token is configured
env:
TOKEN: ${{ secrets.CONFORMANCE_REPO_TOKEN }}
run: |
if [ -z "$TOKEN" ]; then
echo "::error::CONFORMANCE_REPO_TOKEN is not set or has expired."
exit 1
fi

- name: Checkout SDK
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
path: sdk

- name: Checkout conformance suite
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: StackOneHQ/sdk-conformance
ref: 88c9400516f9842ca81dccce747f5d3e66e1fb0a
token: ${{ secrets.CONFORMANCE_REPO_TOKEN }}
path: sdk-conformance
persist-credentials: false

# Public, so no token.
- name: Checkout Python SDK
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: StackOneHQ/stackone-ai-python
ref: ${{ env.PYTHON_SDK_REF }}
path: stackone-ai-python
persist-credentials: false

# tests/vectors is a copy of the suite's vectors/ (scripts/sync-vectors.sh), which the unit
# tests run. An edit to the copy, or a pin moved without a re-copy, fails here.
- name: Vendored vectors match the pinned sdk-conformance
run: diff -r sdk/tests/vectors sdk-conformance/vectors

- name: Setup pnpm
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 10.26.0
package_json_file: sdk-conformance/package.json

# 24, not 22: the SDK's devEngines pins Node ^24.11.0, and the suite runs on it too.
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24

- name: Install SDK dependencies
working-directory: sdk
run: pnpm install --frozen-lockfile

# The runner imports the built dist, not src, so the harness grades the
# publishable artifact. It refuses a dist older than src.
- name: Build SDK
working-directory: sdk
run: pnpm run build

- name: Setup uv
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
python-version: '3.13'

- name: Install Python SDK dependencies
working-directory: stackone-ai-python
run: uv sync --all-extras --locked

- name: Install conformance dependencies
working-directory: sdk-conformance
run: pnpm install --frozen-lockfile

- name: Run conformance suite
working-directory: sdk-conformance
env:
NODE_SDK_DIST: ${{ github.workspace }}/sdk/dist/index.mjs
PYTHON_SDK_DIR: ${{ github.workspace }}/stackone-ai-python
run: pnpm test -- --strict-schema

# Make this the one required status check. Individually required checks go
# missing when a job is renamed or a matrix entry is added, and nothing notices.
ci-ok:
if: always()
needs: [check-secret, gitleaks, lint, build-and-test, ai-peer-range, conformance]
runs-on: ubuntu-latest
steps:
- name: Require every job to have passed
run: |
if [ "${{ needs.gitleaks.result != 'success' || needs.lint.result != 'success' || needs.build-and-test.result != 'success' || needs.ai-peer-range.result != 'success' }}" = "true" ]; then
echo "::error::A required job did not pass (gitleaks: ${{ needs.gitleaks.result }}, lint: ${{ needs.lint.result }}, build-and-test: ${{ needs.build-and-test.result }}, ai-peer-range: ${{ needs.ai-peer-range.result }})"
exit 1
fi
if [ "${{ needs.conformance.result != 'success' && needs.check-secret.outputs.can-skip != 'true' }}" = "true" ]; then
echo "::error::Conformance check did not pass (result: ${{ needs.conformance.result }})"
exit 1
fi

coverage:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
Expand Down
3 changes: 2 additions & 1 deletion .oxfmtrc.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"useTabs": true,
"semi": true,
"singleQuote": true,
"ignorePatterns": [".claude/settings.local.json", "CHANGELOG.md"],
// tests/vectors is vendored byte for byte from sdk-conformance: CI diffs it against the source.
"ignorePatterns": [".claude/settings.local.json", "CHANGELOG.md", "tests/vectors/**"],
}
7 changes: 3 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Available Skills

| Skill | Usage | Description |
| --------------------- | --------------------------- | -------------------------------------------------- |
| **orama-integration** | N/A | Integrating with Orama search/indexing |
| **release-please** | `/release-please <version>` | Trigger a release-please PR for a specific version |
| Skill | Usage | Description |
| ------------------ | --------------------------- | -------------------------------------------------- |
| **release-please** | `/release-please <version>` | Trigger a release-please PR for a specific version |
Loading
Loading