amigo_sdk 0.96.0__py3-none-any.whl → 0.98.0__py3-none-any.whl
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.
- amigo_sdk/__init__.py +1 -1
- amigo_sdk/generated/model.py +6108 -1746
- amigo_sdk/resources/conversation.py +2 -2
- amigo_sdk/resources/user.py +16 -0
- {amigo_sdk-0.96.0.dist-info → amigo_sdk-0.98.0.dist-info}/METADATA +1 -1
- amigo_sdk-0.98.0.dist-info/RECORD +22 -0
- scripts/__init__.py +0 -0
- scripts/aliases.json +5 -0
- scripts/check.py +102 -0
- scripts/gen_models.py +122 -0
- amigo_sdk-0.96.0.dist-info/RECORD +0 -18
- {amigo_sdk-0.96.0.dist-info → amigo_sdk-0.98.0.dist-info}/WHEEL +0 -0
- {amigo_sdk-0.96.0.dist-info → amigo_sdk-0.98.0.dist-info}/entry_points.txt +0 -0
- {amigo_sdk-0.96.0.dist-info → amigo_sdk-0.98.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -166,7 +166,7 @@ class AsyncConversationResource:
|
|
|
166
166
|
) -> ConversationRecommendResponsesForInteractionResponse:
|
|
167
167
|
"""Recommend responses for an interaction."""
|
|
168
168
|
response = await self._http.request(
|
|
169
|
-
"
|
|
169
|
+
"POST",
|
|
170
170
|
f"/v1/{self._organization_id}/conversation/{conversation_id}/interaction/{interaction_id}/recommend_responses",
|
|
171
171
|
)
|
|
172
172
|
return ConversationRecommendResponsesForInteractionResponse.model_validate_json(
|
|
@@ -321,7 +321,7 @@ class ConversationResource:
|
|
|
321
321
|
self, conversation_id: str, interaction_id: str
|
|
322
322
|
) -> ConversationRecommendResponsesForInteractionResponse:
|
|
323
323
|
response = self._http.request(
|
|
324
|
-
"
|
|
324
|
+
"POST",
|
|
325
325
|
f"/v1/{self._organization_id}/conversation/{conversation_id}/interaction/{interaction_id}/recommend_responses",
|
|
326
326
|
)
|
|
327
327
|
return ConversationRecommendResponsesForInteractionResponse.model_validate_json(
|
amigo_sdk/resources/user.py
CHANGED
|
@@ -2,6 +2,7 @@ from amigo_sdk.generated.model import (
|
|
|
2
2
|
GetUsersParametersQuery,
|
|
3
3
|
UserCreateInvitedUserRequest,
|
|
4
4
|
UserCreateInvitedUserResponse,
|
|
5
|
+
UserGetUserModelResponse,
|
|
5
6
|
UserGetUsersResponse,
|
|
6
7
|
UserUpdateUserInfoRequest,
|
|
7
8
|
)
|
|
@@ -54,6 +55,14 @@ class AsyncUserResource:
|
|
|
54
55
|
json=body.model_dump(mode="json", exclude_none=True),
|
|
55
56
|
)
|
|
56
57
|
|
|
58
|
+
async def get_user_model(self, user_id: str) -> UserGetUserModelResponse:
|
|
59
|
+
"""Get the latest user model for a user."""
|
|
60
|
+
response = await self._http.request(
|
|
61
|
+
"GET",
|
|
62
|
+
f"/v1/{self._organization_id}/user/{user_id}/user_model",
|
|
63
|
+
)
|
|
64
|
+
return UserGetUserModelResponse.model_validate_json(response.text)
|
|
65
|
+
|
|
57
66
|
|
|
58
67
|
class UserResource:
|
|
59
68
|
"""User resource (synchronous)."""
|
|
@@ -93,3 +102,10 @@ class UserResource:
|
|
|
93
102
|
f"/v1/{self._organization_id}/user/{user_id}",
|
|
94
103
|
json=body.model_dump(mode="json", exclude_none=True),
|
|
95
104
|
)
|
|
105
|
+
|
|
106
|
+
def get_user_model(self, user_id: str) -> UserGetUserModelResponse:
|
|
107
|
+
response = self._http.request(
|
|
108
|
+
"GET",
|
|
109
|
+
f"/v1/{self._organization_id}/user/{user_id}/user_model",
|
|
110
|
+
)
|
|
111
|
+
return UserGetUserModelResponse.model_validate_json(response.text)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
scripts/aliases.json,sha256=c1_bkZyvNDQ8iMrKtUuZQqdP87GdLnRPrb3wjX533eQ,322
|
|
3
|
+
scripts/check.py,sha256=ikFavw1IjX51FNjO-kIzXjYdep3on0dKZHYvPElPFtc,2872
|
|
4
|
+
scripts/gen_models.py,sha256=c4J_gHYQIBL3CcKg5z8oUusLvPePytfvLdZ7STHBcNk,3553
|
|
5
|
+
amigo_sdk/__init__.py,sha256=SKegkSGR5Jguo83Iqy3NO1YcX0ctgzamLo5mVpq0ens,139
|
|
6
|
+
amigo_sdk/_retry_utils.py,sha256=VbA_Uwv268J80d11R9XfnCjZiV-NwE1aXRsSlRjjRio,2108
|
|
7
|
+
amigo_sdk/auth.py,sha256=WaM9PcEcnaC6CzNsgRKueHkdSAxNbRylzpR_3Q6guQ0,1765
|
|
8
|
+
amigo_sdk/config.py,sha256=0eZIo-hcJ8ODftKAr-mwB-FGJxGO5PT5T4dRpyWPqAg,1491
|
|
9
|
+
amigo_sdk/errors.py,sha256=Yn12AxIQ6zE9jnGLWO0MUVbBsmw77Kzh82AijyreOkA,4818
|
|
10
|
+
amigo_sdk/http_client.py,sha256=tfMXHqMTmlz2ja7aJhOVgbwAiJNlKCzPcK4UGNqXHO8,13488
|
|
11
|
+
amigo_sdk/models.py,sha256=V-G6iL43_ZNOPDcatCJCSszGWGz-nzp_RSyGNm-rBAc,45
|
|
12
|
+
amigo_sdk/sdk_client.py,sha256=5nj8hzjHSFRs9JMNabdYIhQAcFE2G1jI_r7SHVGr9No,6106
|
|
13
|
+
amigo_sdk/generated/model.py,sha256=TF46V7sugZT_tQcTCYghnb1SjpbCYj74tY__yPQL_Cw,446306
|
|
14
|
+
amigo_sdk/resources/conversation.py,sha256=X47PbPA6NqdkqXgxAPOjlO1E0W7t695tn1tPWSikMOk,14807
|
|
15
|
+
amigo_sdk/resources/organization.py,sha256=yX4UlOHNegRzFW4gCJrCxjiLCAGnGegasjviR1yad_Q,1211
|
|
16
|
+
amigo_sdk/resources/service.py,sha256=t1iA3nS9co-wuR-x5jBhAXXTWfMeGsLwfQcLycwVrCA,1536
|
|
17
|
+
amigo_sdk/resources/user.py,sha256=P14lN-3fmIvELUjn_vpSaYpNsK-xd8zNmUV_KfcZPAU,4138
|
|
18
|
+
amigo_sdk-0.98.0.dist-info/METADATA,sha256=VuYRbvGyFOV6VDvOLKheyRe7m16wXwrY4FLRBBtmL3A,8499
|
|
19
|
+
amigo_sdk-0.98.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
20
|
+
amigo_sdk-0.98.0.dist-info/entry_points.txt,sha256=ivKZ8S9W6SH796zUDHeM-qHodrwmkmUItophi-jJWK0,82
|
|
21
|
+
amigo_sdk-0.98.0.dist-info/licenses/LICENSE,sha256=tx3FiTVbGxwBUOxQbNh05AAQlC2jd5hGvNpIkSfVbCo,1062
|
|
22
|
+
amigo_sdk-0.98.0.dist-info/RECORD,,
|
scripts/__init__.py
ADDED
|
File without changes
|
scripts/aliases.json
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
{
|
|
2
|
+
"#/components/schemas/amigo_lib__pydantic__base_model__StrippedNonemptyString__1": "NonEmptyString",
|
|
3
|
+
"#/components/schemas/amigo_lib__pydantic__base_model__StrippedNonemptyString__2": "NonEmptyStringMax256",
|
|
4
|
+
"#/components/schemas/amigo_lib__pydantic__base_model__StrippedNonemptyString__3": "NonEmptyStringMax3"
|
|
5
|
+
}
|
scripts/check.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Development check script - runs formatting, linting, and tests.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python scripts/check.py # Run all checks
|
|
7
|
+
python scripts/check.py --fix # Run all checks and auto-fix issues
|
|
8
|
+
python scripts/check.py --fast # Skip tests (format + lint only)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run_command(cmd: list[str], description: str) -> bool:
|
|
18
|
+
"""Run a command and return True if successful."""
|
|
19
|
+
print(f"🔍 {description}...")
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
result = subprocess.run(
|
|
23
|
+
cmd, capture_output=True, text=True, cwd=Path(__file__).parent.parent
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if result.returncode == 0:
|
|
27
|
+
print(f"✅ {description} - PASSED")
|
|
28
|
+
if result.stdout:
|
|
29
|
+
print(f" {result.stdout.strip()}")
|
|
30
|
+
return True
|
|
31
|
+
else:
|
|
32
|
+
print(f"❌ {description} - FAILED")
|
|
33
|
+
if result.stdout:
|
|
34
|
+
print(f" stdout: {result.stdout.strip()}")
|
|
35
|
+
if result.stderr:
|
|
36
|
+
print(f" stderr: {result.stderr.strip()}")
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
except Exception as e:
|
|
40
|
+
print(f"❌ {description} - ERROR: {e}")
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def main():
|
|
45
|
+
parser = argparse.ArgumentParser(description="Run development checks")
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--fix", action="store_true", help="Auto-fix linting and formatting issues"
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"--fast", action="store_true", help="Skip tests (format + lint only)"
|
|
51
|
+
)
|
|
52
|
+
args = parser.parse_args()
|
|
53
|
+
|
|
54
|
+
print("🚀 Running development checks...\n")
|
|
55
|
+
|
|
56
|
+
all_passed = True
|
|
57
|
+
|
|
58
|
+
# 1. Format check or fix
|
|
59
|
+
if args.fix:
|
|
60
|
+
success = run_command(["ruff", "format", "."], "Code formatting (auto-fix)")
|
|
61
|
+
else:
|
|
62
|
+
success = run_command(
|
|
63
|
+
["ruff", "format", "--check", "."], "Code formatting check"
|
|
64
|
+
)
|
|
65
|
+
all_passed &= success
|
|
66
|
+
|
|
67
|
+
print()
|
|
68
|
+
|
|
69
|
+
# 2. Lint check or fix
|
|
70
|
+
if args.fix:
|
|
71
|
+
success = run_command(["ruff", "check", ".", "--fix"], "Linting (auto-fix)")
|
|
72
|
+
else:
|
|
73
|
+
success = run_command(["ruff", "check", "."], "Linting check")
|
|
74
|
+
all_passed &= success
|
|
75
|
+
|
|
76
|
+
print()
|
|
77
|
+
|
|
78
|
+
# 3. Tests (unless --fast)
|
|
79
|
+
if not args.fast:
|
|
80
|
+
success = run_command(
|
|
81
|
+
["pytest", "--cov=src", "--cov-report=term", "-v"],
|
|
82
|
+
"Test suite with coverage",
|
|
83
|
+
)
|
|
84
|
+
all_passed &= success
|
|
85
|
+
print()
|
|
86
|
+
|
|
87
|
+
# Summary
|
|
88
|
+
print("=" * 50)
|
|
89
|
+
if all_passed:
|
|
90
|
+
print("🎉 All checks PASSED! Ready to commit.")
|
|
91
|
+
if args.fast:
|
|
92
|
+
print("💡 Run without --fast to include tests.")
|
|
93
|
+
sys.exit(0)
|
|
94
|
+
else:
|
|
95
|
+
print("💥 Some checks FAILED!")
|
|
96
|
+
if not args.fix:
|
|
97
|
+
print("💡 Try running with --fix to auto-fix formatting/linting issues.")
|
|
98
|
+
sys.exit(1)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
if __name__ == "__main__":
|
|
102
|
+
main()
|
scripts/gen_models.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
from datamodel_code_generator import (
|
|
6
|
+
DataModelType,
|
|
7
|
+
InputFileType,
|
|
8
|
+
OpenAPIScope,
|
|
9
|
+
generate,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
# Prefixes to strip from schema names (API-specific internal paths)
|
|
13
|
+
STRIP_PREFIXES = [
|
|
14
|
+
"src__app__endpoints__",
|
|
15
|
+
"src__app__amigo__",
|
|
16
|
+
"amigo_lib__",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def strip_prefixes_from_schema(spec: dict) -> dict:
|
|
21
|
+
"""
|
|
22
|
+
Pre-process the OpenAPI spec to strip internal prefixes from schema names.
|
|
23
|
+
This allows the code generator's built-in name sanitization to work correctly.
|
|
24
|
+
"""
|
|
25
|
+
schemas = spec.get("components", {}).get("schemas", {})
|
|
26
|
+
if not schemas:
|
|
27
|
+
return spec
|
|
28
|
+
|
|
29
|
+
# Build a mapping of old names to new names
|
|
30
|
+
rename_map: dict[str, str] = {}
|
|
31
|
+
for name in schemas:
|
|
32
|
+
new_name = name
|
|
33
|
+
for prefix in STRIP_PREFIXES:
|
|
34
|
+
if new_name.startswith(prefix):
|
|
35
|
+
new_name = new_name[len(prefix) :]
|
|
36
|
+
break
|
|
37
|
+
if new_name != name:
|
|
38
|
+
rename_map[name] = new_name
|
|
39
|
+
|
|
40
|
+
if not rename_map:
|
|
41
|
+
return spec
|
|
42
|
+
|
|
43
|
+
# Rename schemas
|
|
44
|
+
new_schemas = {}
|
|
45
|
+
for name, schema in schemas.items():
|
|
46
|
+
new_name = rename_map.get(name, name)
|
|
47
|
+
new_schemas[new_name] = schema
|
|
48
|
+
spec["components"]["schemas"] = new_schemas
|
|
49
|
+
|
|
50
|
+
# Update all $ref pointers throughout the spec
|
|
51
|
+
def update_refs(obj):
|
|
52
|
+
if isinstance(obj, dict):
|
|
53
|
+
if "$ref" in obj:
|
|
54
|
+
ref = obj["$ref"]
|
|
55
|
+
for old, new in rename_map.items():
|
|
56
|
+
old_ref = f"#/components/schemas/{old}"
|
|
57
|
+
new_ref = f"#/components/schemas/{new}"
|
|
58
|
+
if ref == old_ref:
|
|
59
|
+
obj["$ref"] = new_ref
|
|
60
|
+
break
|
|
61
|
+
for value in obj.values():
|
|
62
|
+
update_refs(value)
|
|
63
|
+
elif isinstance(obj, list):
|
|
64
|
+
for item in obj:
|
|
65
|
+
update_refs(item)
|
|
66
|
+
|
|
67
|
+
update_refs(spec)
|
|
68
|
+
return spec
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def main() -> None:
|
|
72
|
+
schema_url = "https://api.amigo.ai/v1/openapi.json"
|
|
73
|
+
root = Path(__file__).parent.parent
|
|
74
|
+
out_dir = root / "src" / "amigo_sdk" / "generated"
|
|
75
|
+
output_file = out_dir / "model.py"
|
|
76
|
+
aliases_path = root / "scripts" / "aliases.json"
|
|
77
|
+
|
|
78
|
+
# Create the generated directory if it doesn't exist
|
|
79
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
80
|
+
|
|
81
|
+
# Remove existing model.py if it exists
|
|
82
|
+
if output_file.exists():
|
|
83
|
+
output_file.unlink()
|
|
84
|
+
|
|
85
|
+
# Fetch the OpenAPI schema from the remote URL
|
|
86
|
+
print(f"Fetching OpenAPI schema from {schema_url}...")
|
|
87
|
+
response = httpx.get(schema_url)
|
|
88
|
+
response.raise_for_status()
|
|
89
|
+
spec = response.json()
|
|
90
|
+
|
|
91
|
+
# Pre-process: strip internal prefixes from schema names
|
|
92
|
+
spec = strip_prefixes_from_schema(spec)
|
|
93
|
+
|
|
94
|
+
# Load aliases as a mapping (Python API expects a dict)
|
|
95
|
+
aliases: dict[str, str] = {}
|
|
96
|
+
if aliases_path.exists():
|
|
97
|
+
aliases = json.loads(aliases_path.read_text())
|
|
98
|
+
|
|
99
|
+
generate(
|
|
100
|
+
json.dumps(spec),
|
|
101
|
+
input_file_type=InputFileType.OpenAPI,
|
|
102
|
+
output=output_file,
|
|
103
|
+
output_model_type=DataModelType.PydanticV2BaseModel,
|
|
104
|
+
openapi_scopes=[
|
|
105
|
+
OpenAPIScope.Schemas,
|
|
106
|
+
OpenAPIScope.Parameters,
|
|
107
|
+
OpenAPIScope.Paths,
|
|
108
|
+
OpenAPIScope.Tags,
|
|
109
|
+
],
|
|
110
|
+
snake_case_field=True,
|
|
111
|
+
field_constraints=True,
|
|
112
|
+
use_operation_id_as_name=True,
|
|
113
|
+
reuse_model=True,
|
|
114
|
+
aliases=aliases,
|
|
115
|
+
collapse_root_models=True,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
print(f"✅ Models regenerated → {output_file}")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
main()
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
amigo_sdk/__init__.py,sha256=sF3mjc_jLenRVw_Lr-cNIbXd2JWMQ1OMx_-MV72EB7A,139
|
|
2
|
-
amigo_sdk/_retry_utils.py,sha256=VbA_Uwv268J80d11R9XfnCjZiV-NwE1aXRsSlRjjRio,2108
|
|
3
|
-
amigo_sdk/auth.py,sha256=WaM9PcEcnaC6CzNsgRKueHkdSAxNbRylzpR_3Q6guQ0,1765
|
|
4
|
-
amigo_sdk/config.py,sha256=0eZIo-hcJ8ODftKAr-mwB-FGJxGO5PT5T4dRpyWPqAg,1491
|
|
5
|
-
amigo_sdk/errors.py,sha256=Yn12AxIQ6zE9jnGLWO0MUVbBsmw77Kzh82AijyreOkA,4818
|
|
6
|
-
amigo_sdk/http_client.py,sha256=tfMXHqMTmlz2ja7aJhOVgbwAiJNlKCzPcK4UGNqXHO8,13488
|
|
7
|
-
amigo_sdk/models.py,sha256=V-G6iL43_ZNOPDcatCJCSszGWGz-nzp_RSyGNm-rBAc,45
|
|
8
|
-
amigo_sdk/sdk_client.py,sha256=5nj8hzjHSFRs9JMNabdYIhQAcFE2G1jI_r7SHVGr9No,6106
|
|
9
|
-
amigo_sdk/generated/model.py,sha256=2BP-cnNJ7NxNptpVcZt0iyIqT3NEwV17UFQZONKgGUs,424265
|
|
10
|
-
amigo_sdk/resources/conversation.py,sha256=u4kOx5LPbhX92L41UnmPmaF9TkQA5bGev8N00dMoP9I,14805
|
|
11
|
-
amigo_sdk/resources/organization.py,sha256=yX4UlOHNegRzFW4gCJrCxjiLCAGnGegasjviR1yad_Q,1211
|
|
12
|
-
amigo_sdk/resources/service.py,sha256=t1iA3nS9co-wuR-x5jBhAXXTWfMeGsLwfQcLycwVrCA,1536
|
|
13
|
-
amigo_sdk/resources/user.py,sha256=zikijiuGXgmkBVtrldor6XQGQK6jWXonDvNFuQs6XK4,3472
|
|
14
|
-
amigo_sdk-0.96.0.dist-info/METADATA,sha256=cgjyoSbW_5RTUWDBWCjqt6nlB1lTm8Xg2H64fulhn2g,8499
|
|
15
|
-
amigo_sdk-0.96.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
16
|
-
amigo_sdk-0.96.0.dist-info/entry_points.txt,sha256=ivKZ8S9W6SH796zUDHeM-qHodrwmkmUItophi-jJWK0,82
|
|
17
|
-
amigo_sdk-0.96.0.dist-info/licenses/LICENSE,sha256=tx3FiTVbGxwBUOxQbNh05AAQlC2jd5hGvNpIkSfVbCo,1062
|
|
18
|
-
amigo_sdk-0.96.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|