amigo_sdk 0.10.0__tar.gz → 0.12.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.

Potentially problematic release.


This version of amigo_sdk might be problematic. Click here for more details.

Files changed (46) hide show
  1. amigo_sdk-0.12.0/CONTRIBUTING.md +137 -0
  2. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/PKG-INFO +83 -3
  3. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/README.md +82 -2
  4. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/scripts/gen_models.py +1 -0
  5. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/specs/openapi-baseline.json +1 -1
  6. amigo_sdk-0.12.0/src/amigo_sdk/__init__.py +4 -0
  7. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/generated/model.py +291 -428
  8. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/http_client.py +6 -5
  9. amigo_sdk-0.12.0/src/amigo_sdk/models.py +1 -0
  10. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/resources/conversation.py +5 -4
  11. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/integration/test_conversation_integration.py +20 -25
  12. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/resources/test_conversation.py +7 -4
  13. amigo_sdk-0.10.0/CONTRIBUTING.md +0 -77
  14. amigo_sdk-0.10.0/src/amigo_sdk/__init__.py +0 -8
  15. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/.github/workflows/auto-release.yml +0 -0
  16. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/.github/workflows/release.yml +0 -0
  17. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/.github/workflows/test.yml +0 -0
  18. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/.gitignore +0 -0
  19. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/LICENSE +0 -0
  20. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/pyproject.toml +0 -0
  21. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/scripts/__init__.py +0 -0
  22. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/scripts/aliases.json +0 -0
  23. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/scripts/check.py +0 -0
  24. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/_retry_utils.py +0 -0
  25. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/auth.py +0 -0
  26. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/config.py +0 -0
  27. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/errors.py +0 -0
  28. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/resources/organization.py +0 -0
  29. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/resources/service.py +0 -0
  30. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/resources/user.py +0 -0
  31. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/src/amigo_sdk/sdk_client.py +0 -0
  32. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/__init__.py +0 -0
  33. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/conftest.py +0 -0
  34. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/integration/test_organization_integration.py +0 -0
  35. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/integration/test_user_integration.py +0 -0
  36. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/resources/__init__.py +0 -0
  37. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/resources/helpers.py +0 -0
  38. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/resources/test_organization.py +0 -0
  39. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/resources/test_service.py +0 -0
  40. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/resources/test_user.py +0 -0
  41. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/test_auth.py +0 -0
  42. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/test_config.py +0 -0
  43. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/test_errors.py +0 -0
  44. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/test_http_client.py +0 -0
  45. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/test_retry_utils.py +0 -0
  46. {amigo_sdk-0.10.0 → amigo_sdk-0.12.0}/tests/test_sdk_client.py +0 -0
@@ -0,0 +1,137 @@
1
+ # Contributing Guide
2
+
3
+ ## Quick Setup
4
+
5
+ ```bash
6
+ # Create and activate virtual environment
7
+ python -m venv .venv
8
+ source .venv/bin/activate
9
+
10
+ # Install the project in development mode
11
+ pip install -e ".[dev]"
12
+ ```
13
+
14
+ ## Development Commands
15
+
16
+ ```bash
17
+ check # Run all checks (format, lint, tests)
18
+ check --fix # Auto-fix issues and run all checks
19
+ check --fast # Format + lint only (skip tests)
20
+
21
+ gen-models # Generate models from API spec
22
+ ```
23
+
24
+ ## Workflow
25
+
26
+ 1. **Before committing:** Run `check --fix` to auto-fix issues
27
+ 2. **During development:** Use `check --fast` for quick validation
28
+ 3. **Update models:** Run `gen-models` when API changes
29
+
30
+ ## Release Process
31
+
32
+ ### GitHub Actions Release
33
+
34
+ 1. Go to the **Actions** tab in GitHub
35
+ 2. Select the **Release** workflow
36
+ 3. Click **Run workflow** and choose:
37
+ - **Version type**: `patch` (default), `minor`, or `major`
38
+ - **Dry run**: Test the release process without publishing
39
+
40
+ The workflow will automatically:
41
+
42
+ - ✅ Run all tests, linting, and formatting checks (reuses existing test workflow)
43
+ - 🔄 Generate fresh models from the API spec
44
+ - 📈 Increment the version using Hatch
45
+ - 📦 Build the package
46
+ - 🚀 Upload to PyPI
47
+ - 🏷️ Create a Git tag and GitHub release
48
+ - 📋 Provide detailed summary with links
49
+
50
+ ### Required Repository Secrets
51
+
52
+ Configure these secrets in your GitHub repository settings:
53
+
54
+ - `PYPI_API_TOKEN`: Token for https://pypi.org/ (production releases)
55
+ - `CODECOV_TOKEN`: Token for Codecov uploads (used by CI test workflow)
56
+ - `RELEASE_BOT_APP_ID`: GitHub App ID used to create tags/releases
57
+ - `RELEASE_BOT_PRIVATE_KEY`: GitHub App private key (PEM) for the release bot
58
+
59
+ ### Getting API Tokens
60
+
61
+ 1. **PyPI**: Go to https://pypi.org/manage/account/token/
62
+ 2. Create a token with upload permissions
63
+ 3. Add the token to your repository secrets
64
+
65
+ ## Auto-Release (OpenAPI changes)
66
+
67
+ When the backend OpenAPI spec changes, the SDK can auto-release a new version.
68
+
69
+ - Trigger: a `repository_dispatch` event with type `openapi-updated`
70
+ - Detect job: fetches the provided `spec_url` (or defaults to `https://api.amigo.ai/v1/openapi.json`), normalizes and compares against `specs/openapi-baseline.json`
71
+ - If changed: invokes the release workflow with `version_type=minor` and passes `spec_url` (supports `dry_run`)
72
+ - Release workflow: regenerates models, bumps version, builds, publishes to PyPI, pushes tag, and creates a GitHub release
73
+
74
+ Manual trigger example (repository_dispatch):
75
+
76
+ ```bash
77
+ curl -X POST \
78
+ -H "Accept: application/vnd.github+json" \
79
+ -H "Authorization: Bearer $GH_TOKEN" \
80
+ https://api.github.com/repos/<OWNER>/<REPO>/dispatches \
81
+ -d '{
82
+ "event_type": "openapi-updated",
83
+ "client_payload": {
84
+ "spec_url": "https://api.amigo.ai/v1/openapi.json",
85
+ "dry_run": true
86
+ }
87
+ }'
88
+ ```
89
+
90
+ Notes:
91
+
92
+ - The baseline file `specs/openapi-baseline.json` is created on first run and updated as part of the release workflow.
93
+ - Ensure the secrets listed above are configured so the workflow can push tags, create releases, and publish to PyPI.
94
+
95
+ ### Manual trigger using GitHub CLI (gh)
96
+
97
+ Requires `gh` authenticated with a token that can dispatch events on the SDK repos.
98
+
99
+ ```bash
100
+ # Values that mirror the workflow
101
+ OWNER="amigo-ai"
102
+ BACKEND_REPO="$OWNER/backend"
103
+ COMMIT_SHA="$(git rev-parse HEAD 2>/dev/null || echo manual-test)"
104
+ RUN_ID="$(date +%s)" # stand-in for GitHub Actions run_id
105
+
106
+ for repo in amigo-typescript-sdk amigo-python-sdk; do
107
+ echo "Notifying $repo..."
108
+ gh api "repos/$OWNER/$repo/dispatches" \
109
+ --method POST \
110
+ --header 'Accept: application/vnd.github+json' \
111
+ --input - <<EOF || echo "⚠️ Failed to notify $repo"
112
+ {
113
+ "event_type": "openapi-updated",
114
+ "client_payload": {
115
+ "spec_url": "https://api.amigo.ai/v1/openapi.json",
116
+ "commit_sha": "$COMMIT_SHA",
117
+ "backend_repo": "$BACKEND_REPO",
118
+ "backend_run_id": "$RUN_ID"
119
+ }
120
+ }
121
+ EOF
122
+ done
123
+ ```
124
+
125
+ ## IDE Setup (VS Code)
126
+
127
+ Install extensions:
128
+
129
+ - [Ruff](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff)
130
+ - [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
131
+
132
+ ## Troubleshooting
133
+
134
+ - **Command not found:** Activate virtual environment with `source .venv/bin/activate`
135
+ - **Linting failures:** Run `check --fix` to auto-fix issues
136
+ - **Model import errors:** Run `gen-models` to regenerate models
137
+ - **Release failures:** Check API tokens are configured in repository secrets and try a dry run first
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amigo_sdk
3
- Version: 0.10.0
3
+ Version: 0.12.0
4
4
  Summary: Amigo AI Python SDK
5
5
  Author: Amigo AI
6
6
  License-File: LICENSE
@@ -50,7 +50,7 @@ This SDK auto-generates its types from the latest [Amigo OpenAPI schema](https:/
50
50
 
51
51
  ```python
52
52
  from amigo_sdk import AmigoClient
53
- from amigo_sdk.generated.model import GetConversationsParametersQuery
53
+ from amigo_sdk.models import GetConversationsParametersQuery
54
54
 
55
55
  # Initialize and use the client synchronously
56
56
  with AmigoClient(
@@ -65,9 +65,38 @@ with AmigoClient(
65
65
  print("Conversations:", conversations)
66
66
  ```
67
67
 
68
+ ## Quick Start (async)
69
+
70
+ ```python
71
+ import asyncio
72
+
73
+ from amigo_sdk import AsyncAmigoClient
74
+ from amigo_sdk.models import GetConversationsParametersQuery
75
+
76
+
77
+ async def main():
78
+ async with AsyncAmigoClient(
79
+ api_key="your-api-key",
80
+ api_key_id="your-api-key-id",
81
+ user_id="user-id",
82
+ organization_id="your-organization-id",
83
+ ) as client:
84
+ conversations = await client.conversation.get_conversations(
85
+ GetConversationsParametersQuery(limit=10, sort_by=["-created_at"])
86
+ )
87
+ print("Conversations:", conversations)
88
+
89
+
90
+ asyncio.run(main())
91
+ ```
92
+
68
93
  ## Examples
69
94
 
70
- For more SDK usage examples see checkout the [examples/](examples/README.md) folder.
95
+ For more SDK usage examples see the [examples overview](examples/README.md). Direct links:
96
+
97
+ - **Conversation (sync)**: [examples/conversation/conversation.py](examples/conversation/conversation.py)
98
+ - **Conversation (async)**: [examples/conversation/conversation_async.py](examples/conversation/conversation_async.py)
99
+ - **User management (sync)**: [examples/user/user-management.py](examples/user/user-management.py)
71
100
 
72
101
  ## Configuration
73
102
 
@@ -133,6 +162,43 @@ The SDK provides access to the following resources:
133
162
  - **Conversation**: Manage conversations
134
163
  - **User**: Manage users
135
164
 
165
+ ## Generated types
166
+
167
+ The SDK ships with Pydantic models generated from the latest OpenAPI schema.
168
+
169
+ - **Importing types**: Import directly from `amigo_sdk.models`
170
+
171
+ ```python
172
+ from amigo_sdk.models import (
173
+ GetConversationsParametersQuery,
174
+ ConversationCreateConversationRequest,
175
+ GetUsersParametersQuery,
176
+ )
177
+ ```
178
+
179
+ - **Using types when calling SDK functions**: Pass request/query models to resource methods.
180
+
181
+ ```python
182
+ from amigo_sdk import AmigoClient
183
+ from amigo_sdk.models import GetConversationsParametersQuery
184
+
185
+ with AmigoClient() as client:
186
+ conversations = client.conversation.get_conversations(
187
+ GetConversationsParametersQuery(limit=20, sort_by=["-created_at"])
188
+ )
189
+ ```
190
+
191
+ - **Parsing returned objects**: Responses are Pydantic models. Access fields directly or convert to dict/JSON.
192
+
193
+ ```python
194
+ # Access fields
195
+ first = conversations.conversations[0]
196
+ print(first.id, first.created_at)
197
+
198
+ # Convert to plain dict for logging/serialization
199
+ print(first.model_dump(mode="json"))
200
+ ```
201
+
136
202
  ## Error Handling
137
203
 
138
204
  The SDK provides typed error handling:
@@ -162,6 +228,20 @@ except Exception as error:
162
228
  print("Unexpected error:", error)
163
229
  ```
164
230
 
231
+ ## Retries
232
+
233
+ The HTTP client includes sensible, configurable retries:
234
+
235
+ - **Defaults**:
236
+
237
+ - max attempts: 3
238
+ - backoff base: 0.25s (exponential with full jitter)
239
+ - max delay per attempt: 30s
240
+ - retry on status: {408, 429, 500, 502, 503, 504}
241
+ - retry on methods: {"GET"}
242
+ - special-case: POST is retried on 429 when `Retry-After` is present
243
+ - 401 triggers a one-time token refresh and immediate retry
244
+
165
245
  ## Development
166
246
 
167
247
  For detailed development setup, testing, and contribution guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
@@ -28,7 +28,7 @@ This SDK auto-generates its types from the latest [Amigo OpenAPI schema](https:/
28
28
 
29
29
  ```python
30
30
  from amigo_sdk import AmigoClient
31
- from amigo_sdk.generated.model import GetConversationsParametersQuery
31
+ from amigo_sdk.models import GetConversationsParametersQuery
32
32
 
33
33
  # Initialize and use the client synchronously
34
34
  with AmigoClient(
@@ -43,9 +43,38 @@ with AmigoClient(
43
43
  print("Conversations:", conversations)
44
44
  ```
45
45
 
46
+ ## Quick Start (async)
47
+
48
+ ```python
49
+ import asyncio
50
+
51
+ from amigo_sdk import AsyncAmigoClient
52
+ from amigo_sdk.models import GetConversationsParametersQuery
53
+
54
+
55
+ async def main():
56
+ async with AsyncAmigoClient(
57
+ api_key="your-api-key",
58
+ api_key_id="your-api-key-id",
59
+ user_id="user-id",
60
+ organization_id="your-organization-id",
61
+ ) as client:
62
+ conversations = await client.conversation.get_conversations(
63
+ GetConversationsParametersQuery(limit=10, sort_by=["-created_at"])
64
+ )
65
+ print("Conversations:", conversations)
66
+
67
+
68
+ asyncio.run(main())
69
+ ```
70
+
46
71
  ## Examples
47
72
 
48
- For more SDK usage examples see checkout the [examples/](examples/README.md) folder.
73
+ For more SDK usage examples see the [examples overview](examples/README.md). Direct links:
74
+
75
+ - **Conversation (sync)**: [examples/conversation/conversation.py](examples/conversation/conversation.py)
76
+ - **Conversation (async)**: [examples/conversation/conversation_async.py](examples/conversation/conversation_async.py)
77
+ - **User management (sync)**: [examples/user/user-management.py](examples/user/user-management.py)
49
78
 
50
79
  ## Configuration
51
80
 
@@ -111,6 +140,43 @@ The SDK provides access to the following resources:
111
140
  - **Conversation**: Manage conversations
112
141
  - **User**: Manage users
113
142
 
143
+ ## Generated types
144
+
145
+ The SDK ships with Pydantic models generated from the latest OpenAPI schema.
146
+
147
+ - **Importing types**: Import directly from `amigo_sdk.models`
148
+
149
+ ```python
150
+ from amigo_sdk.models import (
151
+ GetConversationsParametersQuery,
152
+ ConversationCreateConversationRequest,
153
+ GetUsersParametersQuery,
154
+ )
155
+ ```
156
+
157
+ - **Using types when calling SDK functions**: Pass request/query models to resource methods.
158
+
159
+ ```python
160
+ from amigo_sdk import AmigoClient
161
+ from amigo_sdk.models import GetConversationsParametersQuery
162
+
163
+ with AmigoClient() as client:
164
+ conversations = client.conversation.get_conversations(
165
+ GetConversationsParametersQuery(limit=20, sort_by=["-created_at"])
166
+ )
167
+ ```
168
+
169
+ - **Parsing returned objects**: Responses are Pydantic models. Access fields directly or convert to dict/JSON.
170
+
171
+ ```python
172
+ # Access fields
173
+ first = conversations.conversations[0]
174
+ print(first.id, first.created_at)
175
+
176
+ # Convert to plain dict for logging/serialization
177
+ print(first.model_dump(mode="json"))
178
+ ```
179
+
114
180
  ## Error Handling
115
181
 
116
182
  The SDK provides typed error handling:
@@ -140,6 +206,20 @@ except Exception as error:
140
206
  print("Unexpected error:", error)
141
207
  ```
142
208
 
209
+ ## Retries
210
+
211
+ The HTTP client includes sensible, configurable retries:
212
+
213
+ - **Defaults**:
214
+
215
+ - max attempts: 3
216
+ - backoff base: 0.25s (exponential with full jitter)
217
+ - max delay per attempt: 30s
218
+ - retry on status: {408, 429, 500, 502, 503, 504}
219
+ - retry on methods: {"GET"}
220
+ - special-case: POST is retried on 429 when `Retry-After` is present
221
+ - 401 triggers a one-time token refresh and immediate retry
222
+
143
223
  ## Development
144
224
 
145
225
  For detailed development setup, testing, and contribution guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
@@ -61,6 +61,7 @@ def main() -> None:
61
61
  ),
62
62
  aliases=aliases,
63
63
  parent_scoped_naming=True,
64
+ collapse_root_models=True,
64
65
  )
65
66
 
66
67
  print(f"✅ Models regenerated → {output_file}")