metaai-sdk 2.3.6__tar.gz → 3.0.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 (53) hide show
  1. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/PKG-INFO +1 -1
  2. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_api/api_server.py +28 -7
  3. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_sdk.egg-info/PKG-INFO +1 -1
  4. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_sdk.egg-info/SOURCES.txt +5 -0
  5. metaai_sdk-3.0.0/test_api_quick.py +179 -0
  6. metaai_sdk-3.0.0/test_comprehensive.py +513 -0
  7. metaai_sdk-3.0.0/test_orientation.py +117 -0
  8. metaai_sdk-3.0.0/test_orientation_all.py +212 -0
  9. metaai_sdk-3.0.0/test_video_orientation.py +121 -0
  10. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/.env.example +0 -0
  11. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/CHANGELOG.md +0 -0
  12. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/CONTRIBUTING.md +0 -0
  13. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/ChatGPT Image Jan 14, 2026, 06_59_02 PM.png +0 -0
  14. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/DEPLOYMENT_FIX.md +0 -0
  15. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/Dockerfile +0 -0
  16. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/IMAGE_UPLOAD_README.md +0 -0
  17. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/IMPLEMENTATION_SUMMARY.md +0 -0
  18. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/LICENSE +0 -0
  19. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/MANIFEST.in +0 -0
  20. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/QUICK_REFERENCE.md +0 -0
  21. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/QUICK_USAGE.md +0 -0
  22. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/README.md +0 -0
  23. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/SECURITY.md +0 -0
  24. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/VIDEO_GENERATION_README.md +0 -0
  25. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/analyze_debug_responses.py +0 -0
  26. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/debug_async_video_test.py +0 -0
  27. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/download.jpg +0 -0
  28. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/enable_debug_logging.py +0 -0
  29. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/examples/complete_workflow_example.py +0 -0
  30. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/examples/image_upload_example.py +0 -0
  31. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/examples/image_workflow_complete.py +0 -0
  32. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/examples/practical_use_cases.py +0 -0
  33. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/examples/simple_example.py +0 -0
  34. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/examples/test_example.py +0 -0
  35. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/examples/video_generation.py +0 -0
  36. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/final_comprehensive_test.py +0 -0
  37. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/meta_ai_debug.log +0 -0
  38. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/pyproject.toml +0 -0
  39. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/quick_video_test.py +0 -0
  40. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/requirements.txt +0 -0
  41. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/setup.cfg +0 -0
  42. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_api/__init__.py +0 -0
  43. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_api/client.py +0 -0
  44. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_api/exceptions.py +0 -0
  45. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_api/image_upload.py +0 -0
  46. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_api/main.py +0 -0
  47. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_api/utils.py +0 -0
  48. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_api/video_generation.py +0 -0
  49. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_sdk.egg-info/dependency_links.txt +0 -0
  50. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_sdk.egg-info/requires.txt +0 -0
  51. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/src/metaai_sdk.egg-info/top_level.txt +0 -0
  52. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/test_endpoints.py +0 -0
  53. {metaai_sdk-2.3.6 → metaai_sdk-3.0.0}/test_image_upload.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaai-sdk
3
- Version: 2.3.6
3
+ Version: 3.0.0
4
4
  Summary: Feature-rich Python SDK for Meta AI - Chat, Image & Video Generation powered by Llama 3
5
5
  Author-email: Ashiq Hussain Mir <imseldrith@gmail.com>
6
6
  License-Expression: MIT
@@ -107,12 +107,14 @@ class ImageRequest(BaseModel):
107
107
  new_conversation: bool = False
108
108
  media_ids: Optional[list] = None
109
109
  attachment_metadata: Optional[dict] = None # {'file_size': int, 'mime_type': str}
110
+ orientation: Optional[str] = None # 'VERTICAL', 'LANDSCAPE' (not HORIZONTAL), or 'SQUARE'
110
111
 
111
112
 
112
113
  class VideoRequest(BaseModel):
113
114
  prompt: str
114
115
  media_ids: Optional[list] = None
115
116
  attachment_metadata: Optional[dict] = None # {'file_size': int, 'mime_type': str}
117
+ orientation: Optional[str] = None # 'VERTICAL', 'LANDSCAPE', or 'SQUARE'
116
118
  wait_before_poll: int = Field(10, ge=0, le=60)
117
119
  max_attempts: int = Field(30, ge=1, le=60)
118
120
  wait_seconds: int = Field(5, ge=1, le=30)
@@ -206,7 +208,14 @@ async def chat(body: ChatRequest, cookies: Dict[str, str] = Depends(get_cookies)
206
208
  raise HTTPException(status_code=400, detail="Streaming not supported via HTTP JSON; set stream=false")
207
209
  ai = MetaAI(cookies=cookies, proxy=_get_proxies())
208
210
  try:
209
- return cast(Dict[str, Any], ai.prompt(body.message, stream=False, new_conversation=body.new_conversation, media_ids=body.media_ids, attachment_metadata=body.attachment_metadata))
211
+ return cast(Dict[str, Any], await run_in_threadpool(
212
+ ai.prompt,
213
+ body.message,
214
+ stream=False,
215
+ new_conversation=body.new_conversation,
216
+ media_ids=body.media_ids,
217
+ attachment_metadata=body.attachment_metadata
218
+ ))
210
219
  except Exception as exc: # noqa: BLE001
211
220
  await cache.refresh_after_error()
212
221
  raise HTTPException(status_code=502, detail=str(exc)) from exc
@@ -218,13 +227,15 @@ async def image(body: ImageRequest, cookies: Dict[str, str] = Depends(get_cookie
218
227
  try:
219
228
  # Automatically prepend "generate image of" to the prompt
220
229
  prompt = f"generate image of {body.prompt}" if not body.prompt.lower().startswith(("generate image", "create image")) else body.prompt
221
- return cast(Dict[str, Any], ai.prompt(
222
- prompt,
223
- stream=False,
224
- new_conversation=body.new_conversation,
225
- media_ids=body.media_ids,
230
+ return cast(Dict[str, Any], await run_in_threadpool(
231
+ ai.prompt,
232
+ prompt,
233
+ stream=False,
234
+ new_conversation=body.new_conversation,
235
+ media_ids=body.media_ids,
226
236
  attachment_metadata=body.attachment_metadata,
227
- is_image_generation=True # Image generation uses DISCOVER entrypoint
237
+ is_image_generation=True, # Image generation uses DISCOVER entrypoint
238
+ orientation=body.orientation # Support VERTICAL, HORIZONTAL, SQUARE
228
239
  ))
229
240
  except Exception as exc: # noqa: BLE001
230
241
  await cache.refresh_after_error()
@@ -233,6 +244,10 @@ async def image(body: ImageRequest, cookies: Dict[str, str] = Depends(get_cookie
233
244
 
234
245
  @app.post("/video")
235
246
  async def video(body: VideoRequest, cookies: Dict[str, str] = Depends(get_cookies)) -> Dict[str, Any]:
247
+ # Force refresh cookies before video generation for best results
248
+ await cache.refresh_if_needed(force=True)
249
+ cookies = await cache.snapshot()
250
+
236
251
  ai = MetaAI(cookies=cookies, proxy=_get_proxies())
237
252
  try:
238
253
  # Automatically prepend "generate a video" to the prompt
@@ -242,6 +257,7 @@ async def video(body: VideoRequest, cookies: Dict[str, str] = Depends(get_cookie
242
257
  prompt,
243
258
  body.media_ids,
244
259
  body.attachment_metadata,
260
+ body.orientation,
245
261
  body.wait_before_poll,
246
262
  body.max_attempts,
247
263
  body.wait_seconds,
@@ -254,6 +270,10 @@ async def video(body: VideoRequest, cookies: Dict[str, str] = Depends(get_cookie
254
270
 
255
271
  @app.post("/video/async")
256
272
  async def video_async(body: VideoRequest, cookies: Dict[str, str] = Depends(get_cookies)) -> Dict[str, str]:
273
+ # Force refresh cookies before video generation
274
+ await cache.refresh_if_needed(force=True)
275
+ cookies = await cache.snapshot()
276
+
257
277
  job = await jobs.create()
258
278
  asyncio.create_task(_run_video_job(job.job_id, body, cookies))
259
279
  return {"job_id": job.job_id, "status": "pending"}
@@ -322,6 +342,7 @@ async def _run_video_job(job_id: str, body: VideoRequest, cookies: Dict[str, str
322
342
  body.prompt,
323
343
  body.media_ids,
324
344
  body.attachment_metadata,
345
+ body.orientation,
325
346
  body.wait_before_poll,
326
347
  body.max_attempts,
327
348
  body.wait_seconds,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaai-sdk
3
- Version: 2.3.6
3
+ Version: 3.0.0
4
4
  Summary: Feature-rich Python SDK for Meta AI - Chat, Image & Video Generation powered by Llama 3
5
5
  Author-email: Ashiq Hussain Mir <imseldrith@gmail.com>
6
6
  License-Expression: MIT
@@ -22,8 +22,13 @@ meta_ai_debug.log
22
22
  pyproject.toml
23
23
  quick_video_test.py
24
24
  requirements.txt
25
+ test_api_quick.py
26
+ test_comprehensive.py
25
27
  test_endpoints.py
26
28
  test_image_upload.py
29
+ test_orientation.py
30
+ test_orientation_all.py
31
+ test_video_orientation.py
27
32
  examples/complete_workflow_example.py
28
33
  examples/image_upload_example.py
29
34
  examples/image_workflow_complete.py
@@ -0,0 +1,179 @@
1
+ """
2
+ Quick API test with timeout handling
3
+ """
4
+
5
+ import requests
6
+ import json
7
+
8
+ API_URL = "http://localhost:8000"
9
+ TIMEOUT = 120 # 2 minutes timeout for each request
10
+
11
+ def test_health():
12
+ """Test health check endpoint"""
13
+ print("\n" + "="*70)
14
+ print("TEST: Health Check")
15
+ print("="*70)
16
+ try:
17
+ response = requests.get(f"{API_URL}/healthz", timeout=5)
18
+ print(f"✓ Status: {response.status_code}")
19
+ print(f" Response: {response.json()}")
20
+ return True
21
+ except Exception as e:
22
+ print(f"✗ Error: {e}")
23
+ return False
24
+
25
+ def test_chat():
26
+ """Test basic chat endpoint"""
27
+ print("\n" + "="*70)
28
+ print("TEST: Chat Endpoint (Simple)")
29
+ print("="*70)
30
+ try:
31
+ payload = {
32
+ "message": "What is 2+2?",
33
+ "stream": False,
34
+ "new_conversation": True
35
+ }
36
+ print(f"Request: {payload}")
37
+ response = requests.post(
38
+ f"{API_URL}/chat",
39
+ headers={"Content-Type": "application/json"},
40
+ json=payload,
41
+ timeout=TIMEOUT
42
+ )
43
+ print(f"✓ Status: {response.status_code}")
44
+ if response.status_code == 200:
45
+ result = response.json()
46
+ print(f" Message: {result.get('message', 'No message')[:200]}")
47
+ return True
48
+ else:
49
+ print(f" Error: {response.text}")
50
+ return False
51
+ except requests.Timeout:
52
+ print(f"✗ Timeout after {TIMEOUT}s")
53
+ return False
54
+ except Exception as e:
55
+ print(f"✗ Error: {e}")
56
+ return False
57
+
58
+ def test_upload():
59
+ """Test image upload endpoint"""
60
+ print("\n" + "="*70)
61
+ print("TEST: Image Upload")
62
+ print("="*70)
63
+
64
+ import os
65
+ from pathlib import Path
66
+
67
+ # Find an image to upload
68
+ image_path = r"C:\Users\spike\Downloads\meta-ai-api-main\ChatGPT Image Jan 14, 2026, 06_59_02 PM.png"
69
+
70
+ if not os.path.exists(image_path):
71
+ print(f"✗ Image not found: {image_path}")
72
+ return False, None
73
+
74
+ try:
75
+ with open(image_path, 'rb') as f:
76
+ files = {'file': f}
77
+ response = requests.post(
78
+ f"{API_URL}/upload",
79
+ files=files,
80
+ timeout=TIMEOUT
81
+ )
82
+
83
+ print(f"✓ Status: {response.status_code}")
84
+ if response.status_code == 200:
85
+ result = response.json()
86
+ media_id = result.get('media_id')
87
+ print(f" Media ID: {media_id}")
88
+ print(f" File Size: {result.get('file_size')} bytes")
89
+ print(f" MIME Type: {result.get('mime_type')}")
90
+ metadata = {
91
+ 'file_size': result.get('file_size'),
92
+ 'mime_type': result.get('mime_type')
93
+ }
94
+ return True, (media_id, metadata)
95
+ else:
96
+ print(f" Error: {response.text}")
97
+ return False, None
98
+ except Exception as e:
99
+ print(f"✗ Error: {e}")
100
+ return False, None
101
+
102
+ def test_image_generation():
103
+ """Test image generation endpoint"""
104
+ print("\n" + "="*70)
105
+ print("TEST: Image Generation")
106
+ print("="*70)
107
+ try:
108
+ payload = {
109
+ "prompt": "a cute cat wearing sunglasses",
110
+ "new_conversation": True
111
+ }
112
+ print(f"Request: {payload}")
113
+ response = requests.post(
114
+ f"{API_URL}/image",
115
+ headers={"Content-Type": "application/json"},
116
+ json=payload,
117
+ timeout=TIMEOUT
118
+ )
119
+ print(f"✓ Status: {response.status_code}")
120
+ if response.status_code == 200:
121
+ result = response.json()
122
+ print(f" Message: {result.get('message', 'No message')[:200]}")
123
+ media = result.get('media', [])
124
+ print(f" Media count: {len(media)}")
125
+ for i, m in enumerate(media[:2], 1):
126
+ print(f" {i}. {m.get('url', 'No URL')[:80]}...")
127
+ return True
128
+ else:
129
+ print(f" Error: {response.text}")
130
+ return False
131
+ except requests.Timeout:
132
+ print(f"✗ Timeout after {TIMEOUT}s")
133
+ return False
134
+ except Exception as e:
135
+ print(f"✗ Error: {e}")
136
+ return False
137
+
138
+ def main():
139
+ """Run all tests"""
140
+ print("\n" + "+"*70)
141
+ print(" API QUICK TEST SUITE")
142
+ print("+"*70)
143
+ print(f"\nAPI URL: {API_URL}")
144
+ print(f"Timeout: {TIMEOUT}s per request\n")
145
+
146
+ results = {}
147
+
148
+ # Test 1: Health
149
+ results['health'] = test_health()
150
+
151
+ # Test 2: Chat
152
+ results['chat'] = test_chat()
153
+
154
+ # Test 3: Upload
155
+ upload_success, upload_data = test_upload()
156
+ results['upload'] = upload_success
157
+
158
+ # Test 4: Image Generation
159
+ results['image'] = test_image_generation()
160
+
161
+ # Summary
162
+ print("\n" + "="*70)
163
+ print("SUMMARY")
164
+ print("="*70)
165
+ for test_name, passed in results.items():
166
+ status = "✓ PASS" if passed else "✗ FAIL"
167
+ print(f"{test_name.ljust(20)}: {status}")
168
+
169
+ total = len(results)
170
+ passed = sum(results.values())
171
+ print(f"\nTotal: {passed}/{total} tests passed")
172
+
173
+ if passed == total:
174
+ print("\n✓ All tests passed!")
175
+ else:
176
+ print(f"\n✗ {total - passed} test(s) failed")
177
+
178
+ if __name__ == "__main__":
179
+ main()