orchid-api 0.2.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 (36) hide show
  1. orchid_api-0.2.0/.editorconfig +22 -0
  2. orchid_api-0.2.0/.github/workflows/ci.yml +157 -0
  3. orchid_api-0.2.0/.gitignore +42 -0
  4. orchid_api-0.2.0/.gitlint +15 -0
  5. orchid_api-0.2.0/.pre-commit-config.yaml +16 -0
  6. orchid_api-0.2.0/AGENTS.md +110 -0
  7. orchid_api-0.2.0/CLAUDE.md +1 -0
  8. orchid_api-0.2.0/CONTRIBUTING.md +83 -0
  9. orchid_api-0.2.0/Dockerfile +40 -0
  10. orchid_api-0.2.0/LICENSE +21 -0
  11. orchid_api-0.2.0/PKG-INFO +22 -0
  12. orchid_api-0.2.0/README.md +136 -0
  13. orchid_api-0.2.0/icon.svg +12 -0
  14. orchid_api-0.2.0/orchid_api/__init__.py +1 -0
  15. orchid_api-0.2.0/orchid_api/auth.py +54 -0
  16. orchid_api-0.2.0/orchid_api/context.py +32 -0
  17. orchid_api-0.2.0/orchid_api/main.py +149 -0
  18. orchid_api-0.2.0/orchid_api/models.py +82 -0
  19. orchid_api-0.2.0/orchid_api/routers/__init__.py +1 -0
  20. orchid_api-0.2.0/orchid_api/routers/chats.py +85 -0
  21. orchid_api-0.2.0/orchid_api/routers/legacy.py +93 -0
  22. orchid_api-0.2.0/orchid_api/routers/messages.py +238 -0
  23. orchid_api-0.2.0/orchid_api/routers/sharing.py +82 -0
  24. orchid_api-0.2.0/orchid_api/settings.py +168 -0
  25. orchid_api-0.2.0/orchid_api/tracing.py +45 -0
  26. orchid_api-0.2.0/pyproject.toml +63 -0
  27. orchid_api-0.2.0/tests/conftest.py +58 -0
  28. orchid_api-0.2.0/tests/test_auth.py +135 -0
  29. orchid_api-0.2.0/tests/test_context.py +33 -0
  30. orchid_api-0.2.0/tests/test_models.py +132 -0
  31. orchid_api-0.2.0/tests/test_routers_chats.py +130 -0
  32. orchid_api-0.2.0/tests/test_routers_legacy.py +105 -0
  33. orchid_api-0.2.0/tests/test_routers_messages.py +201 -0
  34. orchid_api-0.2.0/tests/test_routers_sharing.py +99 -0
  35. orchid_api-0.2.0/tests/test_settings.py +118 -0
  36. orchid_api-0.2.0/tests/test_tracing.py +36 -0
@@ -0,0 +1,22 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ trim_trailing_whitespace = true
7
+ charset = utf-8
8
+
9
+ [*.py]
10
+ indent_style = space
11
+ indent_size = 4
12
+ max_line_length = 120
13
+
14
+ [*.{yml,yaml,json,toml}]
15
+ indent_style = space
16
+ indent_size = 2
17
+
18
+ [Makefile]
19
+ indent_style = tab
20
+
21
+ [*.md]
22
+ trim_trailing_whitespace = false
@@ -0,0 +1,157 @@
1
+ # orchid-api (FastAPI server) — CI + Semantic Release
2
+
3
+ name: CI
4
+
5
+ on:
6
+ pull_request:
7
+ branches: [main]
8
+ push:
9
+ branches: [main]
10
+
11
+ jobs:
12
+ # ── Lint ────────────────────────────────────────────────────
13
+
14
+ ruff:
15
+ name: Ruff lint & format
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.13"
22
+ - run: pip install ruff
23
+ - run: ruff check orchid_api/
24
+ - run: ruff format --check orchid_api/
25
+
26
+ commit-lint:
27
+ name: Commit message check
28
+ if: github.event_name == 'pull_request'
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ with:
33
+ fetch-depth: 0
34
+ - uses: actions/setup-python@v5
35
+ with:
36
+ python-version: "3.13"
37
+ - run: pip install gitlint
38
+ - run: gitlint --commits "${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}"
39
+
40
+ # ── Test ────────────────────────────────────────────────────
41
+
42
+ test:
43
+ name: Tests + coverage
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+ - uses: actions/setup-python@v5
48
+ with:
49
+ python-version: "3.13"
50
+ cache: pip
51
+ cache-dependency-path: pyproject.toml
52
+ - run: pip install -e ".[dev]" pytest-cov
53
+ - name: Run tests
54
+ run: |
55
+ pytest tests/ \
56
+ --cov=orchid_api \
57
+ --cov-report=term-missing \
58
+ --cov-report=xml:coverage.xml \
59
+ --junitxml=report.xml \
60
+ -x
61
+ - name: Upload coverage
62
+ if: always()
63
+ uses: actions/upload-artifact@v4
64
+ with:
65
+ name: coverage
66
+ path: coverage.xml
67
+ if-no-files-found: ignore
68
+ - name: Upload test report
69
+ if: always()
70
+ uses: actions/upload-artifact@v4
71
+ with:
72
+ name: test-report
73
+ path: report.xml
74
+ if-no-files-found: ignore
75
+ - name: Coverage summary
76
+ if: hashFiles('coverage.xml') != ''
77
+ uses: irongut/CodeCoverageSummary@v1.3.0
78
+ with:
79
+ filename: "**/coverage.xml"
80
+ format: markdown
81
+ output: both
82
+ badge: true
83
+ fail_below_min: false
84
+ thresholds: "50 75"
85
+ - name: Add coverage PR comment
86
+ if: github.event_name == 'pull_request' && hashFiles('code-coverage-results.md') != ''
87
+ uses: marocchino/sticky-pull-request-comment@v2
88
+ with:
89
+ header: coverage
90
+ path: code-coverage-results.md
91
+
92
+ # ── Build ───────────────────────────────────────────────────
93
+
94
+ build:
95
+ name: Build wheel
96
+ runs-on: ubuntu-latest
97
+ needs: [ruff, test]
98
+ steps:
99
+ - uses: actions/checkout@v4
100
+ - uses: actions/setup-python@v5
101
+ with:
102
+ python-version: "3.13"
103
+ - run: pip install build
104
+ - run: python -m build
105
+ - uses: actions/upload-artifact@v4
106
+ with:
107
+ name: dist
108
+ path: dist/
109
+ retention-days: 7
110
+
111
+ # ── Release (semantic-release on main push) ─────────────────
112
+
113
+ release:
114
+ name: Semantic release
115
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
116
+ runs-on: ubuntu-latest
117
+ needs: [ruff, test, build]
118
+ permissions:
119
+ contents: write
120
+ id-token: write # required for PyPI trusted publishing
121
+ steps:
122
+ - uses: actions/checkout@v4
123
+ with:
124
+ fetch-depth: 0
125
+ token: ${{ secrets.GITHUB_TOKEN }}
126
+ - uses: actions/setup-python@v5
127
+ with:
128
+ python-version: "3.13"
129
+ - run: pip install python-semantic-release build
130
+ - name: Configure git
131
+ run: |
132
+ git config user.name "github-actions[bot]"
133
+ git config user.email "github-actions[bot]@users.noreply.github.com"
134
+ - name: Bump version & tag
135
+ id: version
136
+ env:
137
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
138
+ run: |
139
+ OUTPUT=$(semantic-release version --push --tag --commit 2>&1) || true
140
+ echo "$OUTPUT"
141
+ if echo "$OUTPUT" | grep -q "no release will be made"; then
142
+ echo "released=false" >> "$GITHUB_OUTPUT"
143
+ else
144
+ echo "released=true" >> "$GITHUB_OUTPUT"
145
+ fi
146
+ - name: Build distribution
147
+ if: steps.version.outputs.released == 'true'
148
+ run: python -m build
149
+ - name: Publish GitHub Release
150
+ if: steps.version.outputs.released == 'true'
151
+ env:
152
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
153
+ run: semantic-release publish
154
+ # 4. Publish to PyPI via trusted publishing (OIDC)
155
+ - name: Publish to PyPI
156
+ if: steps.version.outputs.released == 'true'
157
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,42 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ *.egg
7
+ dist/
8
+ build/
9
+ *.whl
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ ENV/
15
+
16
+ # IDE
17
+ .idea/
18
+ .vscode/
19
+ *.swp
20
+ *.swo
21
+ *~
22
+
23
+ # Ruff
24
+ .ruff_cache/
25
+
26
+ # pytest
27
+ .pytest_cache/
28
+ htmlcov/
29
+ .coverage
30
+ coverage.xml
31
+
32
+ # Environment
33
+ .env
34
+ .env.local
35
+ .env.*.local
36
+
37
+ # OS
38
+ .DS_Store
39
+ Thumbs.db
40
+
41
+ # mypy
42
+ .mypy_cache/
@@ -0,0 +1,15 @@
1
+ # Gitlint — enforce Conventional Commits for semantic-release
2
+ # https://jorisroovers.com/gitlint/
3
+
4
+ [general]
5
+ contrib = contrib-title-conventional-commits
6
+ ignore = merge-commit,revert-commit
7
+
8
+ [title-max-length]
9
+ line-length = 72
10
+
11
+ [body-max-line-length]
12
+ line-length = 120
13
+
14
+ [contrib-title-conventional-commits]
15
+ types = feat,fix,perf,refactor,docs,style,test,build,ci,chore
@@ -0,0 +1,16 @@
1
+ # Pre-commit hooks — run automatically before each commit
2
+ # Install: pip install pre-commit && pre-commit install
3
+ # Manual: pre-commit run --all-files
4
+
5
+ repos:
6
+ - repo: https://github.com/astral-sh/ruff-pre-commit
7
+ rev: v0.9.10
8
+ hooks:
9
+ - id: ruff
10
+ args: [--fix, --exit-non-zero-on-fix]
11
+ - id: ruff-format
12
+
13
+ - repo: https://github.com/jorisroovers/gitlint
14
+ rev: v0.19.1
15
+ hooks:
16
+ - id: gitlint
@@ -0,0 +1,110 @@
1
+ # orchid-api — AI Context
2
+
3
+ ## What This Package Is
4
+
5
+ **orchid-api** is the FastAPI server for the Orchid multi-agent AI framework. It imports `orchid` (the library) as a dependency and exposes HTTP endpoints for chat management, message handling, document uploads, and RAG sharing. It does NOT contain agent logic, graph building, or persistence implementations — those live in `orchid/`.
6
+
7
+ ## Package Structure
8
+
9
+ ```
10
+ orchid-api/
11
+ orchid_api/
12
+ main.py FastAPI app + lifespan (graph build, storage init, tracing)
13
+ settings.py Pydantic BaseSettings + YAML overlay via _apply_yaml_config()
14
+ context.py AppContext dataclass (singleton, populated at startup)
15
+ auth.py Bearer token -> AuthContext via pluggable IdentityResolver (ADR-010)
16
+ models.py Pydantic response models
17
+ tracing.py LangSmith setup
18
+ routers/
19
+ chats.py CRUD: create, list, delete chat sessions
20
+ messages.py Send messages + document upload (multipart/form-data)
21
+ sharing.py Promote chat RAG data to user-common scope
22
+ legacy.py Legacy single-shot /chat endpoint (JSON body)
23
+ Dockerfile
24
+ pyproject.toml
25
+ ```
26
+
27
+ ## Key Dependencies
28
+
29
+ | Package | Role |
30
+ |---------|------|
31
+ | `orchid` | Core framework (agents, graph, RAG, persistence) |
32
+ | `fastapi` | HTTP framework |
33
+ | `uvicorn` | ASGI server |
34
+ | `httpx` | Async HTTP client (for identity resolution) |
35
+ | `pydantic-settings` | Environment + YAML config |
36
+ | `python-multipart` | File upload support |
37
+ | `langchain-core` | LangGraph message types |
38
+
39
+ ## Architecture Rules (Apply When Editing This Package)
40
+
41
+ 1. **This is a thin HTTP layer.** Business logic belongs in `orchid/`, not here. Routers call `orchid` APIs and return responses.
42
+
43
+ 2. **Identity resolution happens ONCE in `auth.py`.** The `get_auth_context` dependency resolves the Bearer token into `AuthContext`. No other code initiates OAuth flows (ADR-010).
44
+
45
+ 3. **`AppContext` replaces globals.** All runtime state (runtime, graph, chat_repo, http_client, identity_resolver) lives in `context.py:app_ctx`. The `runtime` field is an `OrchidRuntime` instance that owns the reader, LLM service, and MCP client factory. Routers access it via `from ..context import app_ctx`.
46
+
47
+ 4. **Routers are split by domain (SRP).** `chats.py` = CRUD, `messages.py` = send + upload, `sharing.py` = share, `legacy.py` = backward compat. New endpoints go in the appropriate router, never in `main.py`.
48
+
49
+ 5. **No agent or framework code here.** No `BaseAgent` subclasses, no graph wiring, no RAG logic. Those belong in `orchid/` or consumer projects.
50
+
51
+ 6. **Settings priority:** env vars > `orchid.yml` > hardcoded defaults. The `_YAML_TO_ENV` mapping in `settings.py` translates nested YAML keys to flat env vars.
52
+
53
+ 7. **Don't persist augmented prompts.** Save the original user message to chat history, NOT the version with prepended file content or RAG context.
54
+
55
+ ## Configuration (Settings)
56
+
57
+ All settings are env vars, optionally populated from `orchid.yml` via `ORCHID_CONFIG`:
58
+
59
+ | Setting | Default | Purpose |
60
+ |---------|---------|---------|
61
+ | `LITELLM_MODEL` | `ollama/llama3.2` | LLM model identifier |
62
+ | `AGENTS_CONFIG_PATH` | `agents.yaml` | Path to agent YAML config |
63
+ | `VECTOR_BACKEND` | `qdrant` | Vector store backend |
64
+ | `QDRANT_URL` | `http://qdrant:6333` | Qdrant connection URL |
65
+ | `EMBEDDING_MODEL` | `text-embedding-3-small` | Embedding model |
66
+ | `CHAT_STORAGE_CLASS` | `orchid_ai.persistence.sqlite.SQLiteChatStorage` | Storage backend class |
67
+ | `CHAT_DB_DSN` | `~/.orchid/chats.db` | Database connection string |
68
+ | `DEV_AUTH_BYPASS` | `false` | Skip auth (dev only) |
69
+ | `IDENTITY_RESOLVER_CLASS` | `""` | Dotted path to IdentityResolver |
70
+ | `STARTUP_HOOK` | `""` | Async function called at startup |
71
+
72
+ ## Running
73
+
74
+ ```bash
75
+ # Standalone (no Docker):
76
+ pip install orchid-ai orchid-api
77
+ ORCHID_CONFIG=orchid.yml uvicorn orchid_api.main:app --port 8000
78
+
79
+ # Docker:
80
+ docker build -t orchid-api .
81
+ docker run -p 8000:8000 -v ./orchid.yml:/app/orchid.yml orchid-api
82
+ ```
83
+
84
+ ## Endpoints
85
+
86
+ | Method | Path | Router | Purpose |
87
+ |--------|------|--------|---------|
88
+ | POST | `/chats` | chats | Create chat session |
89
+ | GET | `/chats` | chats | List user's chats |
90
+ | DELETE | `/chats/{id}` | chats | Delete chat |
91
+ | GET | `/chats/{id}/messages` | messages | Load chat history |
92
+ | POST | `/chats/{id}/messages` | messages | Send message (multipart) |
93
+ | POST | `/chats/{id}/upload` | messages | Upload documents for chat RAG |
94
+ | POST | `/chats/{id}/share` | sharing | Promote chat RAG to user scope |
95
+ | POST | `/chat` | legacy | Single-shot (no persistence) |
96
+ | GET | `/health` | main | Readiness check |
97
+
98
+ ## Code Style
99
+
100
+ - Python 3.11+, Ruff, line length 120
101
+ - `from __future__ import annotations` in every file
102
+ - Imports: `from orchid_ai.xxx` (never `from src.xxx`)
103
+ - No vendor-specific code — platform integrations belong in consumer projects
104
+
105
+ ## Common Pitfalls
106
+
107
+ - `POST /chats/{id}/messages` uses `multipart/form-data`, not JSON. The legacy `POST /chat` uses JSON.
108
+ - CORS allows `localhost:3000` and `frontend:3000` — add new origins in `main.py` if needed.
109
+ - The `lifespan()` function builds the graph at startup. Changes to agent config require a restart.
110
+ - Embedding dimension mismatch (768 vs 1536 vs 3072) causes silent retrieval failures. Switching models requires re-indexing.
@@ -0,0 +1 @@
1
+ AGENTS.md
@@ -0,0 +1,83 @@
1
+ # Contributing to orchid-api
2
+
3
+ ## Development Setup
4
+
5
+ ```bash
6
+ cd orchid-api
7
+ python -m venv .venv
8
+ source .venv/bin/activate
9
+ pip install -e ../orchid -e ".[dev]"
10
+ pre-commit install
11
+ ```
12
+
13
+ The last command installs git hooks that **automatically run ruff (lint + format) and gitlint (commit message check) before every commit**.
14
+
15
+ ## Commit Message Convention
16
+
17
+ This project uses **[Conventional Commits](https://www.conventionalcommits.org/)** to enable automatic semantic versioning. Every commit message must follow this format:
18
+
19
+ ```
20
+ <type>(<scope>): <description>
21
+
22
+ [optional body]
23
+
24
+ [optional footer(s)]
25
+ ```
26
+
27
+ ### Types
28
+
29
+ | Type | Description | Version Bump |
30
+ |------|-------------|-------------|
31
+ | `feat` | New feature | **minor** (0.X.0) |
32
+ | `fix` | Bug fix | **patch** (0.0.X) |
33
+ | `perf` | Performance improvement | **patch** (0.0.X) |
34
+ | `refactor` | Code refactor (no feature/fix) | none |
35
+ | `docs` | Documentation only | none |
36
+ | `style` | Formatting, whitespace | none |
37
+ | `test` | Adding/updating tests | none |
38
+ | `build` | Build system, dependencies | none |
39
+ | `ci` | CI/CD configuration | none |
40
+ | `chore` | Maintenance tasks | none |
41
+
42
+ ### Breaking Changes
43
+
44
+ Append `!` after the type or add `BREAKING CHANGE:` in the footer for a **major** bump:
45
+
46
+ ```
47
+ feat!: change /chats/{id}/messages response format
48
+ ```
49
+
50
+ ### Examples
51
+
52
+ ```
53
+ feat(routers): add pagination to GET /chats endpoint
54
+ fix(auth): handle expired bearer tokens gracefully
55
+ docs: update API endpoint table in README
56
+ test(sharing): add tests for scope promotion endpoint
57
+ ci: add coverage reporting to GitLab pipeline
58
+ ```
59
+
60
+ ### Validation
61
+
62
+ Commit messages are validated in CI via [gitlint](https://jorisroovers.com/gitlint/). To check locally:
63
+
64
+ ```bash
65
+ pip install gitlint
66
+ gitlint
67
+ ```
68
+
69
+ ## Running Tests
70
+
71
+ ```bash
72
+ pytest tests/ -x # all tests
73
+ pytest tests/ --cov=orchid_api # with coverage
74
+ ruff check orchid_api/ # lint
75
+ ruff format orchid_api/ # format
76
+ ```
77
+
78
+ ## Merge Requests
79
+
80
+ 1. Create a feature branch from `main`
81
+ 2. Use conventional commit messages
82
+ 3. Ensure tests pass and linting is clean
83
+ 4. Keep MRs focused -- one feature or fix per MR
@@ -0,0 +1,40 @@
1
+ # orchid-api — FastAPI + LangGraph agent backend
2
+ #
3
+ # Build context: orchid-api/
4
+ # docker build -t orchid-api .
5
+ #
6
+ # Multi-stage: install deps → slim runtime
7
+
8
+ # ── Stage 1: build & install ───────────────────────────────────
9
+ FROM python:3.13-slim AS builder
10
+
11
+ WORKDIR /app
12
+
13
+ # System deps for building wheels
14
+ RUN apt-get update && apt-get install -y --no-install-recommends gcc && rm -rf /var/lib/apt/lists/*
15
+
16
+ # Install orchid-api (pulls orchid from PyPI as a dependency)
17
+ COPY pyproject.toml pyproject.toml
18
+ COPY orchid_api orchid_api
19
+ RUN pip install --no-cache-dir --prefix=/install .
20
+
21
+ # ── Stage 2: runtime ──────────────────────────────────────────
22
+ FROM python:3.13-slim
23
+
24
+ WORKDIR /app
25
+
26
+ # Copy installed packages from builder
27
+ COPY --from=builder /install /usr/local
28
+
29
+ # Copy application source
30
+ COPY orchid_api orchid_api
31
+
32
+ ENV PYTHONDONTWRITEBYTECODE=1
33
+ ENV PYTHONUNBUFFERED=1
34
+
35
+ EXPOSE 8000
36
+
37
+ HEALTHCHECK --interval=15s --timeout=3s --start-period=10s \
38
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
39
+
40
+ CMD ["uvicorn", "orchid_api.main:app", "--host", "0.0.0.0", "--port", "8000"]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Orchid Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,22 @@
1
+ Metadata-Version: 2.4
2
+ Name: orchid-api
3
+ Version: 0.2.0
4
+ Summary: Orchid API — FastAPI server for the Orchid agent framework
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: fastapi>=0.115.0
8
+ Requires-Dist: httpx>=0.28.0
9
+ Requires-Dist: langchain-core>=0.3.0
10
+ Requires-Dist: orchid-ai>=1.1.0
11
+ Requires-Dist: pydantic-settings>=2.7.0
12
+ Requires-Dist: pydantic>=2.10.0
13
+ Requires-Dist: python-multipart>=0.0.9
14
+ Requires-Dist: pyyaml>=6.0
15
+ Requires-Dist: uvicorn[standard]>=0.34.0
16
+ Provides-Extra: dev
17
+ Requires-Dist: gitlint>=0.19.0; extra == 'dev'
18
+ Requires-Dist: pre-commit>=4.0; extra == 'dev'
19
+ Requires-Dist: pytest-asyncio>=0.25.0; extra == 'dev'
20
+ Requires-Dist: pytest-cov>=6.0; extra == 'dev'
21
+ Requires-Dist: pytest>=8.0; extra == 'dev'
22
+ Requires-Dist: ruff>=0.9.0; extra == 'dev'
@@ -0,0 +1,136 @@
1
+ <p align="center">
2
+ <img src="icon.svg" alt="Orchid" width="80" />
3
+ </p>
4
+
5
+ <h1 align="center">Orchid API</h1>
6
+
7
+ FastAPI server for the [Orchid](../orchid) multi-agent AI framework.
8
+
9
+ Provides HTTP endpoints for chat management, message handling, document uploads, and RAG sharing. This is a thin HTTP layer -- all agent logic, graph building, and persistence live in the `orchid` library.
10
+
11
+ ## Features
12
+
13
+ - Multi-chat session management (create, list, delete)
14
+ - Streaming message send with agent graph invocation
15
+ - File upload with document parsing and chat-scoped RAG
16
+ - Chat sharing (promote RAG data to user scope)
17
+ - Pluggable identity resolution (Bearer token -> AuthContext)
18
+ - LangSmith tracing integration
19
+ - CORS support for frontend clients
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ pip install orchid-api
25
+ ```
26
+
27
+ Requires the `orchid` library:
28
+
29
+ ```bash
30
+ pip install orchid-ai orchid-api
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ```bash
36
+ # With orchid.yml config:
37
+ ORCHID_CONFIG=path/to/orchid.yml uvicorn orchid_api.main:app --port 8000
38
+
39
+ # Health check:
40
+ curl http://localhost:8000/health
41
+ ```
42
+
43
+ ## Endpoints
44
+
45
+ | Method | Path | Content-Type | Purpose |
46
+ |--------|------|-------------|---------|
47
+ | `POST` | `/chats` | JSON | Create a chat session |
48
+ | `GET` | `/chats` | -- | List user's chat sessions |
49
+ | `DELETE` | `/chats/{id}` | -- | Delete a chat session |
50
+ | `GET` | `/chats/{id}/messages` | -- | Load chat message history |
51
+ | `POST` | `/chats/{id}/messages` | **multipart/form-data** | Send a message (with optional files) |
52
+ | `POST` | `/chats/{id}/upload` | multipart/form-data | Upload documents for chat RAG |
53
+ | `POST` | `/chats/{id}/share` | -- | Promote chat RAG data to user scope |
54
+ | `POST` | `/chat` | JSON | Legacy single-shot (no persistence) |
55
+ | `GET` | `/health` | -- | Readiness check |
56
+
57
+ ## Architecture
58
+
59
+ ```
60
+ orchid_api/
61
+ main.py FastAPI app + lifespan (graph build, storage init, tracing)
62
+ settings.py Pydantic BaseSettings + YAML overlay
63
+ context.py AppContext dataclass (singleton, populated at startup)
64
+ auth.py Bearer token -> AuthContext via pluggable IdentityResolver
65
+ models.py Pydantic response models
66
+ tracing.py LangSmith setup
67
+ routers/
68
+ chats.py CRUD: create, list, delete chat sessions
69
+ messages.py Send messages + document upload (multipart/form-data)
70
+ sharing.py Promote chat RAG data to user-common scope
71
+ legacy.py Legacy single-shot /chat endpoint (JSON body)
72
+ ```
73
+
74
+ ## Configuration
75
+
76
+ All settings are environment variables, optionally populated from `orchid.yml` via `ORCHID_CONFIG`:
77
+
78
+ | Setting | Default | Purpose |
79
+ |---------|---------|---------|
80
+ | `LITELLM_MODEL` | `ollama/llama3.2` | LLM model identifier |
81
+ | `AGENTS_CONFIG_PATH` | `agents.yaml` | Path to agent YAML config |
82
+ | `VECTOR_BACKEND` | `qdrant` | Vector store backend (`qdrant` or `null`) |
83
+ | `QDRANT_URL` | `http://qdrant:6333` | Qdrant connection URL |
84
+ | `EMBEDDING_MODEL` | `text-embedding-3-small` | Embedding model |
85
+ | `CHAT_STORAGE_CLASS` | `orchid_ai.persistence.sqlite.SQLiteChatStorage` | Storage backend class |
86
+ | `CHAT_DB_DSN` | `~/.orchid/chats.db` | Database connection string |
87
+ | `DEV_AUTH_BYPASS` | `false` | Skip auth (dev only) |
88
+ | `IDENTITY_RESOLVER_CLASS` | -- | Dotted path to IdentityResolver subclass |
89
+ | `STARTUP_HOOK` | -- | Async function called at startup |
90
+ | `LANGSMITH_TRACING` | `false` | Enable LangSmith tracing |
91
+ | `LANGSMITH_API_KEY` | -- | LangSmith API key |
92
+
93
+ **Priority:** env vars > `orchid.yml` > hardcoded defaults.
94
+
95
+ ## Docker
96
+
97
+ ```dockerfile
98
+ # Build (from parent directory):
99
+ docker build -f orchid-api/Dockerfile -t orchid-api .
100
+
101
+ # Run:
102
+ docker run -p 8000:8000 -e ORCHID_CONFIG=/app/config/orchid.yml orchid-api
103
+ ```
104
+
105
+ Or with docker-compose:
106
+
107
+ ```bash
108
+ docker compose -f docker-compose.demo.yml up --build # SQLite
109
+ docker compose -f docker-compose.local.yml up --build # PostgreSQL + Qdrant
110
+ ```
111
+
112
+ ## Development
113
+
114
+ ```bash
115
+ pip install -e ".[dev]"
116
+ ORCHID_CONFIG=orchid.yml uvicorn orchid_api.main:app --reload --port 8000
117
+ ```
118
+
119
+ ## Testing
120
+
121
+ ```bash
122
+ pip install -e ".[dev]"
123
+ pytest tests/ -x
124
+ ruff check orchid_api/
125
+ ```
126
+
127
+ ## Code Style
128
+
129
+ - Python 3.11+, Ruff, line length 120
130
+ - `from __future__ import annotations` in every file
131
+ - Routers split by domain (SRP): chats, messages, sharing, legacy
132
+ - All runtime state in `AppContext` -- no module-level globals
133
+
134
+ ## License
135
+
136
+ MIT -- see [LICENSE](LICENSE).
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 24 24" fill="none">
2
+ <rect width="24" height="24" rx="5" fill="#0D0B11"/>
3
+ <!-- Glow -->
4
+ <circle cx="12" cy="12" r="8" fill="#B06AB3" opacity="0.12"/>
5
+ <!-- Orchid petals -->
6
+ <path d="M12 2C10.5 5 9.5 7.5 12 11C14.5 7.5 13.5 5 12 2Z" fill="#D490D7"/>
7
+ <path d="M4 8C6.5 7.5 9 8 11 11C7.5 11.5 5.5 10.5 4 8Z" fill="#C87ECB" opacity="0.9"/>
8
+ <path d="M20 8C17.5 7.5 15 8 13 11C16.5 11.5 18.5 10.5 20 8Z" fill="#C87ECB" opacity="0.9"/>
9
+ <path d="M6 18C7.5 15.5 9.5 13.5 12 13C9 14.5 7 16 6 18Z" fill="#B06AB3" opacity="0.85"/>
10
+ <path d="M18 18C16.5 15.5 14.5 13.5 12 13C15 14.5 17 16 18 18Z" fill="#B06AB3" opacity="0.85"/>
11
+ <circle cx="12" cy="11.5" r="1.5" fill="#FFFFFF"/>
12
+ </svg>
@@ -0,0 +1 @@
1
+ # Orchid API — FastAPI server