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.
@@ -166,7 +166,7 @@ class AsyncConversationResource:
166
166
  ) -> ConversationRecommendResponsesForInteractionResponse:
167
167
  """Recommend responses for an interaction."""
168
168
  response = await self._http.request(
169
- "GET",
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
- "GET",
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(
@@ -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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amigo_sdk
3
- Version: 0.96.0
3
+ Version: 0.98.0
4
4
  Summary: Amigo AI Python SDK
5
5
  Author: Amigo AI
6
6
  License-File: LICENSE
@@ -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,,