Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
19 changes: 19 additions & 0 deletions .github/actions/setup-nix/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "Setup Nix"
description: "Install Nix and configure Cachix"
runs:
using: "composite"
steps:
- name: Install Nix
uses: cachix/install-nix-action@0b0e072294b088b73964f1d72dfdac0951439dbd # v31.8.4
with:
github_access_token: ${{ github.token }}

- name: Setup Cachix (numtide)
uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
with:
name: numtide
authToken: ""

- name: Load Nix development environment
shell: bash
run: nix develop --command true
54 changes: 54 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: CI

on:
push:
pull_request:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.13"]
include:
- python-version: "3.9"
sync-extras: "--all-extras --no-extra mcp"
- python-version: "3.10"
sync-extras: "--all-extras"
- python-version: "3.13"
sync-extras: "--all-extras"
env:
STACKONE_API_KEY: ${{ secrets.STACKONE_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Setup Nix
uses: ./.github/actions/setup-nix

- name: Install dependencies
run: nix develop --command uv sync ${{ matrix.sync-extras }}

- name: Run Lint
run: nix develop --command uv run ruff check .

- name: Run Mypy
run: |
if [[ "${{ matrix.python-version }}" == "3.9" ]]; then
nix develop --command uv run mypy stackone_ai --exclude stackone_ai/server.py
else
nix develop --command uv run mypy stackone_ai
fi

- name: Run Tests
run: nix develop --command uv run pytest
16 changes: 7 additions & 9 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Install uv
uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1
with:
python-version: "3.11"
enable-cache: true
- name: Setup Nix
uses: ./.github/actions/setup-nix

- name: Install all dependencies
run: uv sync --all-extras
run: nix develop --command uv sync --all-extras

- name: Build documentation
run: |
uv run scripts/build_docs.py
uv run mkdocs build
nix develop --command uv run scripts/build_docs.py
nix develop --command uv run mkdocs build

- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main'
Expand Down
42 changes: 0 additions & 42 deletions .github/workflows/lint.yml

This file was deleted.

33 changes: 33 additions & 0 deletions .github/workflows/nix-flake.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: "CI: Flake check"

on:
push:
paths:
- "flake.nix"
- "flake.lock"
- ".github/workflows/nix-flake.yml"
- ".github/actions/setup-nix/**"
pull_request:
paths:
- "flake.nix"
- "flake.lock"
- ".github/workflows/nix-flake.yml"
- ".github/actions/setup-nix/**"

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
# Check flake syntax and structure
flake-check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Setup Nix
uses: ./.github/actions/setup-nix

- name: Check flake
run: nix flake check --all-systems --show-trace
17 changes: 7 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,22 @@ jobs:
manifest-file: .release-please-manifest.json

# Only release to PyPI when a new release is created
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
if: ${{ steps.release.outputs.release_created }}

- name: Install uv
- name: Setup Nix
if: ${{ steps.release.outputs.release_created }}
uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1
with:
python-version: "3.11"
enable-cache: true
uses: ./.github/actions/setup-nix

- name: Update version in __init__.py
if: ${{ steps.release.outputs.release_created }}
run: |
uv run scripts/update_version.py
run: nix develop --command uv run scripts/update_version.py

- name: Build and publish package
if: ${{ steps.release.outputs.release_created }}
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
run: |
uv build
uv publish
nix develop --command uv build
nix develop --command uv publish
37 changes: 0 additions & 37 deletions .github/workflows/test.yml

This file was deleted.

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ site/
*.egg-info
dist/
build/

# Git hooks (managed by Nix)
.pre-commit-config.yaml
16 changes: 0 additions & 16 deletions .pre-commit-config.yaml

This file was deleted.

10 changes: 9 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ make install # Install dependencies and pre-commit hooks

# Code quality
make lint # Run ruff linting
make lint-fix # Auto-fix linting issues
make lint-fix # Auto-fix linting issues
make mypy # Run type checking

# Testing
Expand Down Expand Up @@ -64,17 +64,20 @@ make mcp-inspector # Run MCP server inspector for debugging
### OpenAPI Specifications

All tool definitions are generated from OpenAPI specs in `stackone_ai/oas/`:

- `core.json`, `ats.json`, `crm.json`, `documents.json`, `hris.json`, `iam.json`, `lms.json`, `marketing.json`

## Key Development Patterns

### Tool Filtering

```python
# Use glob patterns for tool selection
tools = StackOneToolSet(include_tools=["hris_*", "!hris_create_*"])
```

### Authentication

```python
# Uses environment variables or direct configuration
toolset = StackOneToolSet(
Expand All @@ -84,11 +87,13 @@ toolset = StackOneToolSet(
```

### Type Safety

- Full type annotations required (Python 3.11+)
- Strict mypy configuration
- Use generics for better IDE support

### Testing

- Snapshot testing for tool parsing (`tests/snapshots/`)
- Async tests use `pytest-asyncio`
- Example validation: See @./.cursor/rules/examples-standards
Expand All @@ -105,16 +110,19 @@ toolset = StackOneToolSet(
## Common Tasks

### Adding New SaaS Integration

1. Add OpenAPI spec to `stackone_ai/oas/`
2. Parser automatically converts to tool definitions
3. Test with `make test-tools`

### Modifying Tool Behavior

- Core execution logic in `StackOneTool.execute()` method
- HTTP configuration via `ExecuteConfig` class
- Response handling in `_process_response()`

### Updating Documentation

- Examples requirements: See @./.cursor/rules/examples-standards
- Run `make docs-serve` to preview changes
- MkDocs config in `mkdocs.yml`
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,30 @@ StackOne AI provides a unified interface for accessing various SaaS tools throug

## Installation

### Using Nix (Recommended for Development)

If you have [Nix](https://nixos.org/) installed with flakes enabled:

```bash
# Enter development environment (auto-installs dependencies and git hooks)
nix develop

# Format code
nix fmt

# Run checks
nix flake check
```

The Nix development environment includes:

- Python with uv package manager
- Automatic dependency installation
- Git hooks (treefmt + mypy) auto-configured
- Consistent environment across all platforms

### Using pip/uv

```bash
pip install 'stackone-ai[mcp]'

Expand Down Expand Up @@ -299,6 +323,7 @@ result = feedback_tool.call(
```

**Important**: The AI agent should always ask for user permission before submitting feedback:

- "Are you ok with sending feedback to StackOne? The LLM will take care of sending it."
- Only call the tool after the user explicitly agrees.

Expand Down Expand Up @@ -346,6 +371,7 @@ tools = toolset.fetch_tools(actions=["hris_*"], account_ids=["acc-123"])
```

Key differences:

- `fetch_tools()` uses keyword arguments for all filtering
- `account_id` becomes `account_ids` (list)
- Filter patterns go in the `actions` parameter (list)
Expand Down
Loading