imbrace 1.0.1__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 (110) hide show
  1. imbrace-1.0.1/.env.example +40 -0
  2. imbrace-1.0.1/.gitignore +64 -0
  3. imbrace-1.0.1/PKG-INFO +113 -0
  4. imbrace-1.0.1/README.md +83 -0
  5. imbrace-1.0.1/examples/01_quickstart.py +12 -0
  6. imbrace-1.0.1/examples/02_auth_flow.py +25 -0
  7. imbrace-1.0.1/examples/03_chat_ai.py +34 -0
  8. imbrace-1.0.1/examples/04_channel.py +21 -0
  9. imbrace-1.0.1/examples/05_async.py +40 -0
  10. imbrace-1.0.1/examples/06_document_ai.py +81 -0
  11. imbrace-1.0.1/examples/07_ai_agent.py +246 -0
  12. imbrace-1.0.1/examples/openai_style.py +49 -0
  13. imbrace-1.0.1/pyproject.toml +65 -0
  14. imbrace-1.0.1/scripts/get_access_token.py +234 -0
  15. imbrace-1.0.1/src/imbrace/__init__.py +20 -0
  16. imbrace-1.0.1/src/imbrace/api_key.py +31 -0
  17. imbrace-1.0.1/src/imbrace/async_client.py +184 -0
  18. imbrace-1.0.1/src/imbrace/auth/token_manager.py +28 -0
  19. imbrace-1.0.1/src/imbrace/client.py +197 -0
  20. imbrace-1.0.1/src/imbrace/environments.py +33 -0
  21. imbrace-1.0.1/src/imbrace/exceptions.py +17 -0
  22. imbrace-1.0.1/src/imbrace/http.py +251 -0
  23. imbrace-1.0.1/src/imbrace/resources/__init__.py +33 -0
  24. imbrace-1.0.1/src/imbrace/resources/account.py +63 -0
  25. imbrace-1.0.1/src/imbrace/resources/activepieces.py +309 -0
  26. imbrace-1.0.1/src/imbrace/resources/agent.py +137 -0
  27. imbrace-1.0.1/src/imbrace/resources/ai.py +657 -0
  28. imbrace-1.0.1/src/imbrace/resources/ai_agent.py +471 -0
  29. imbrace-1.0.1/src/imbrace/resources/auth.py +275 -0
  30. imbrace-1.0.1/src/imbrace/resources/boards.py +346 -0
  31. imbrace-1.0.1/src/imbrace/resources/campaigns.py +89 -0
  32. imbrace-1.0.1/src/imbrace/resources/categories.py +56 -0
  33. imbrace-1.0.1/src/imbrace/resources/channel.py +394 -0
  34. imbrace-1.0.1/src/imbrace/resources/chat_ai.py +490 -0
  35. imbrace-1.0.1/src/imbrace/resources/contacts.py +183 -0
  36. imbrace-1.0.1/src/imbrace/resources/conversations.py +138 -0
  37. imbrace-1.0.1/src/imbrace/resources/data_files.py +66 -0
  38. imbrace-1.0.1/src/imbrace/resources/file_service.py +168 -0
  39. imbrace-1.0.1/src/imbrace/resources/folders.py +63 -0
  40. imbrace-1.0.1/src/imbrace/resources/health.py +23 -0
  41. imbrace-1.0.1/src/imbrace/resources/ips.py +73 -0
  42. imbrace-1.0.1/src/imbrace/resources/license.py +19 -0
  43. imbrace-1.0.1/src/imbrace/resources/marketplace.py +117 -0
  44. imbrace-1.0.1/src/imbrace/resources/message_suggestion.py +28 -0
  45. imbrace-1.0.1/src/imbrace/resources/messages.py +83 -0
  46. imbrace-1.0.1/src/imbrace/resources/organizations.py +60 -0
  47. imbrace-1.0.1/src/imbrace/resources/outbounds.py +35 -0
  48. imbrace-1.0.1/src/imbrace/resources/platform.py +425 -0
  49. imbrace-1.0.1/src/imbrace/resources/predict.py +28 -0
  50. imbrace-1.0.1/src/imbrace/resources/schedule.py +42 -0
  51. imbrace-1.0.1/src/imbrace/resources/sessions.py +66 -0
  52. imbrace-1.0.1/src/imbrace/resources/settings.py +107 -0
  53. imbrace-1.0.1/src/imbrace/resources/teams.py +117 -0
  54. imbrace-1.0.1/src/imbrace/resources/touchpoints.py +63 -0
  55. imbrace-1.0.1/src/imbrace/resources/workflows.py +43 -0
  56. imbrace-1.0.1/src/imbrace/service_registry.py +57 -0
  57. imbrace-1.0.1/src/imbrace/types/__init__.py +27 -0
  58. imbrace-1.0.1/src/imbrace/types/agent.py +41 -0
  59. imbrace-1.0.1/src/imbrace/types/ai.py +77 -0
  60. imbrace-1.0.1/src/imbrace/types/auth.py +101 -0
  61. imbrace-1.0.1/src/imbrace/types/channel.py +43 -0
  62. imbrace-1.0.1/src/imbrace/types/common.py +28 -0
  63. imbrace-1.0.1/src/imbrace/types/ips.py +39 -0
  64. imbrace-1.0.1/src/imbrace/types/marketplace.py +57 -0
  65. imbrace-1.0.1/src/imbrace/types/platform.py +39 -0
  66. imbrace-1.0.1/src/imbrace/types/session.py +48 -0
  67. imbrace-1.0.1/tests/integration/__init__.py +0 -0
  68. imbrace-1.0.1/tests/integration/conftest.py +138 -0
  69. imbrace-1.0.1/tests/integration/test_access_token.py +211 -0
  70. imbrace-1.0.1/tests/integration/test_init.py +45 -0
  71. imbrace-1.0.1/tests/integration/test_server_routing.py +117 -0
  72. imbrace-1.0.1/tests/local/test_activepieces.py +277 -0
  73. imbrace-1.0.1/tests/local/test_ai.py +401 -0
  74. imbrace-1.0.1/tests/local/test_ai_agent.py +246 -0
  75. imbrace-1.0.1/tests/local/test_boards.py +261 -0
  76. imbrace-1.0.1/tests/local/test_campaign.py +126 -0
  77. imbrace-1.0.1/tests/local/test_document_ai.py +125 -0
  78. imbrace-1.0.1/tests/local/test_knowledgehub.py +235 -0
  79. imbrace-1.0.1/tests/local/test_local.py +109 -0
  80. imbrace-1.0.1/tests/local/test_marketplace.py +139 -0
  81. imbrace-1.0.1/tests/local/test_quickstart.py +26 -0
  82. imbrace-1.0.1/tests/local/test_stream_chat.py +45 -0
  83. imbrace-1.0.1/tests/local/test_workflows.py +82 -0
  84. imbrace-1.0.1/tests/unit/__init__.py +0 -0
  85. imbrace-1.0.1/tests/unit/resources/__init__.py +0 -0
  86. imbrace-1.0.1/tests/unit/resources/test_account.py +23 -0
  87. imbrace-1.0.1/tests/unit/resources/test_agent.py +42 -0
  88. imbrace-1.0.1/tests/unit/resources/test_ai.py +44 -0
  89. imbrace-1.0.1/tests/unit/resources/test_auth.py +93 -0
  90. imbrace-1.0.1/tests/unit/resources/test_boards.py +40 -0
  91. imbrace-1.0.1/tests/unit/resources/test_campaigns.py +97 -0
  92. imbrace-1.0.1/tests/unit/resources/test_categories.py +37 -0
  93. imbrace-1.0.1/tests/unit/resources/test_channel.py +89 -0
  94. imbrace-1.0.1/tests/unit/resources/test_contacts.py +47 -0
  95. imbrace-1.0.1/tests/unit/resources/test_conversations.py +41 -0
  96. imbrace-1.0.1/tests/unit/resources/test_health.py +26 -0
  97. imbrace-1.0.1/tests/unit/resources/test_ips.py +29 -0
  98. imbrace-1.0.1/tests/unit/resources/test_marketplace.py +47 -0
  99. imbrace-1.0.1/tests/unit/resources/test_message_suggestion.py +31 -0
  100. imbrace-1.0.1/tests/unit/resources/test_messages.py +29 -0
  101. imbrace-1.0.1/tests/unit/resources/test_organizations.py +29 -0
  102. imbrace-1.0.1/tests/unit/resources/test_platform.py +54 -0
  103. imbrace-1.0.1/tests/unit/resources/test_predict.py +31 -0
  104. imbrace-1.0.1/tests/unit/resources/test_sessions.py +34 -0
  105. imbrace-1.0.1/tests/unit/resources/test_settings.py +42 -0
  106. imbrace-1.0.1/tests/unit/resources/test_teams.py +41 -0
  107. imbrace-1.0.1/tests/unit/resources/test_workflows.py +26 -0
  108. imbrace-1.0.1/tests/unit/test_client.py +38 -0
  109. imbrace-1.0.1/tests/unit/test_exceptions.py +12 -0
  110. imbrace-1.0.1/tests/unit/test_http.py +69 -0
@@ -0,0 +1,40 @@
1
+ # === IMBRACE SDK CONFIGURATION (Python) ===
2
+
3
+ # 1. Environment Selection
4
+ # Options: develop | sandbox | stable (default)
5
+ IMBRACE_ENV=develop
6
+
7
+ # 2. Gateway URL Override (Optional)
8
+ # SDK will automatically use the correct gateway based on IMBRACE_ENV.
9
+ # Use this ONLY if you want to override it (e.g., local development).
10
+ # develop: https://app-gateway.dev.imbrace.co
11
+ # sandbox: https://app-gateway.sandbox.imbrace.co
12
+ # stable: https://app-gateway.imbrace.co
13
+ IMBRACE_GATEWAY_URL=
14
+ # IMBRACE_GATEWAY_URL=
15
+ # 3. Authentication (Server-side)
16
+ # Get your API key from Imbrace Portal or via Auth API
17
+ IMBRACE_API_KEY=your_api_key_here
18
+
19
+ # 4. Authentication (Client-side / Optional)
20
+ # Use this if you are using JWT/OAuth token instead of API Key
21
+ # IMBRACE_ACCESS_TOKEN=your_jwt_token_here
22
+
23
+ # 5. Organization Context (Optional)
24
+ # Set this to automatically include x-organization-id in all requests
25
+ IMBRACE_ORGANIZATION_ID=your_org_id_here
26
+
27
+ # 6. Test Credentials (Integration Tests)
28
+ # Legacy OTP account (get_access_token.py):
29
+ IMBRACE_TEST_EMAIL=your_test_email@imbrace.co
30
+ IMBRACE_TEST_PASSWORD=your_otp_account_password
31
+
32
+ # Platform account — used for JWT Bearer mode test (password sign_in):
33
+ # Register at /platform/v1/login/sign_up, verify email, then set here.
34
+ # IMBRACE_PLATFORM_EMAIL=your_platform_email@example.com
35
+ # IMBRACE_PLATFORM_PASSWORD=YourPassword@123
36
+
37
+ # 7. Additional Flags (Optional)
38
+ # Check health of the gateway upon client initialization (Sync & Async)
39
+ IMBRACE_CHECK_HEALTH=false
40
+ IMBRACE_TIMEOUT=30
@@ -0,0 +1,64 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.pyd
6
+ .Python
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ .eggs/
11
+ .pytest_cache/
12
+ .coverage
13
+ htmlcov/
14
+ *.egg
15
+
16
+ # Virtual environments
17
+ .venv/
18
+ venv/
19
+ env/
20
+
21
+ # Secrets
22
+ .env
23
+ *.env.local
24
+
25
+ # TypeScript / Node
26
+ node_modules/
27
+ dist/
28
+ *.js.map
29
+ *.d.ts.map
30
+ *.tsbuildinfo
31
+
32
+ # Logs
33
+ *.log
34
+ npm-debug.log*
35
+
36
+ # OS
37
+ .DS_Store
38
+ Thumbs.db
39
+
40
+ # IDE
41
+ .vscode/
42
+ .idea/
43
+
44
+ # Claude local settings
45
+ .claude/settings.local.json
46
+
47
+ #document
48
+ app-gateway
49
+ new-frontend
50
+ opencode
51
+ !website/src/content/docs/
52
+ file-service
53
+ chat-ai
54
+ # test-local-pkg
55
+ # test-npm-pkg
56
+ docs2
57
+
58
+ #Claude
59
+ .claude/
60
+ .claude/commands/
61
+ .claude/referances/
62
+ .claude/skill/
63
+ .claude/skill/skill.md
64
+ .claude/skill/skill.yaml
imbrace-1.0.1/PKG-INFO ADDED
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.4
2
+ Name: imbrace
3
+ Version: 1.0.1
4
+ Summary: Official Python SDK for Imbrace — dual auth (API Key + Access Token)
5
+ Project-URL: Homepage, https://imbrace.co
6
+ Project-URL: Repository, https://github.com/imbrace/sdk
7
+ Project-URL: Documentation, https://docs.imbrace.co/sdk/python
8
+ Author-email: Imbrace Team <dev@imbrace.co>
9
+ License: MIT
10
+ Keywords: api,automation,imbrace,sdk
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.9
20
+ Requires-Dist: httpx>=0.27.0
21
+ Requires-Dist: pydantic>=2.0.0
22
+ Requires-Dist: python-dotenv>=1.0.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: mypy>=1.10.0; extra == 'dev'
25
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
26
+ Requires-Dist: pytest-httpx>=0.30.0; extra == 'dev'
27
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
28
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Imbrace Python SDK
32
+
33
+ Official Python client for the Imbrace Gateway. Supports sync and async.
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ pip install imbrace
39
+ ```
40
+
41
+ ## Quick Start
42
+
43
+ ### API Key — server-side scripts, Celery tasks
44
+
45
+ ```python
46
+ from imbrace import ImbraceClient
47
+
48
+ client = ImbraceClient(api_key="sk-xxx...")
49
+
50
+ me = client.platform.get_me()
51
+ ```
52
+
53
+ ### Access Token — after user login
54
+
55
+ ```python
56
+ client = ImbraceClient(access_token="acc_xxxxxxxxxxxxx")
57
+ ```
58
+
59
+ ### OTP Login Flow
60
+
61
+ ```python
62
+ client = ImbraceClient()
63
+
64
+ client.request_otp("user@example.com")
65
+ client.login_with_otp("user@example.com", "123456")
66
+
67
+ # all subsequent calls are authenticated
68
+ me = client.platform.get_me()
69
+ ```
70
+
71
+ ### Async Client
72
+
73
+ ```python
74
+ from imbrace import AsyncImbraceClient
75
+
76
+ async with AsyncImbraceClient(api_key="sk-xxx...") as client:
77
+ me = await client.platform.get_me()
78
+ ```
79
+
80
+ ## Error Handling
81
+
82
+ ```python
83
+ from imbrace import AuthError, ApiError, NetworkError
84
+
85
+ try:
86
+ client.platform.get_me()
87
+ except AuthError:
88
+ print("Invalid credentials")
89
+ except ApiError as e:
90
+ print(f"[{e.status_code}] {e}")
91
+ except NetworkError:
92
+ print("Gateway unreachable")
93
+ ```
94
+
95
+ ## Environment Variables
96
+
97
+ | Variable | Description |
98
+ | --- | --- |
99
+ | `IMBRACE_API_KEY` | API key (server-side auth) |
100
+ | `IMBRACE_GATEWAY_URL` | Override gateway URL (default: `https://app-gatewayv2.imbrace.co`) |
101
+ | `IMBRACE_ENV` | Environment preset: `develop`, `sandbox`, `stable` (default: `stable`) |
102
+
103
+ ## Development
104
+
105
+ ```bash
106
+ pip install -e ".[dev]"
107
+ pytest # unit tests
108
+ pytest tests/integration # integration tests (requires IMBRACE_API_KEY)
109
+ ```
110
+
111
+ ## Resources
112
+
113
+ Full resource reference: **[sdk.imbrace.co/python/resources](https://sdk.imbrace.co/python/resources)**
@@ -0,0 +1,83 @@
1
+ # Imbrace Python SDK
2
+
3
+ Official Python client for the Imbrace Gateway. Supports sync and async.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install imbrace
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### API Key — server-side scripts, Celery tasks
14
+
15
+ ```python
16
+ from imbrace import ImbraceClient
17
+
18
+ client = ImbraceClient(api_key="sk-xxx...")
19
+
20
+ me = client.platform.get_me()
21
+ ```
22
+
23
+ ### Access Token — after user login
24
+
25
+ ```python
26
+ client = ImbraceClient(access_token="acc_xxxxxxxxxxxxx")
27
+ ```
28
+
29
+ ### OTP Login Flow
30
+
31
+ ```python
32
+ client = ImbraceClient()
33
+
34
+ client.request_otp("user@example.com")
35
+ client.login_with_otp("user@example.com", "123456")
36
+
37
+ # all subsequent calls are authenticated
38
+ me = client.platform.get_me()
39
+ ```
40
+
41
+ ### Async Client
42
+
43
+ ```python
44
+ from imbrace import AsyncImbraceClient
45
+
46
+ async with AsyncImbraceClient(api_key="sk-xxx...") as client:
47
+ me = await client.platform.get_me()
48
+ ```
49
+
50
+ ## Error Handling
51
+
52
+ ```python
53
+ from imbrace import AuthError, ApiError, NetworkError
54
+
55
+ try:
56
+ client.platform.get_me()
57
+ except AuthError:
58
+ print("Invalid credentials")
59
+ except ApiError as e:
60
+ print(f"[{e.status_code}] {e}")
61
+ except NetworkError:
62
+ print("Gateway unreachable")
63
+ ```
64
+
65
+ ## Environment Variables
66
+
67
+ | Variable | Description |
68
+ | --- | --- |
69
+ | `IMBRACE_API_KEY` | API key (server-side auth) |
70
+ | `IMBRACE_GATEWAY_URL` | Override gateway URL (default: `https://app-gatewayv2.imbrace.co`) |
71
+ | `IMBRACE_ENV` | Environment preset: `develop`, `sandbox`, `stable` (default: `stable`) |
72
+
73
+ ## Development
74
+
75
+ ```bash
76
+ pip install -e ".[dev]"
77
+ pytest # unit tests
78
+ pytest tests/integration # integration tests (requires IMBRACE_API_KEY)
79
+ ```
80
+
81
+ ## Resources
82
+
83
+ Full resource reference: **[sdk.imbrace.co/python/resources](https://sdk.imbrace.co/python/resources)**
@@ -0,0 +1,12 @@
1
+ import os
2
+ from imbrace import ImbraceClient
3
+
4
+ client = ImbraceClient(
5
+ api_key=os.environ["IMBRACE_API_KEY"],
6
+ env="stable",
7
+ )
8
+
9
+ channels = client.channel.list()
10
+ print("Channels:", channels)
11
+
12
+ client.close()
@@ -0,0 +1,25 @@
1
+ import os
2
+ from imbrace import ImbraceClient
3
+
4
+ # Step 1: sign in with email + password to get an access token
5
+ bootstrap = ImbraceClient(env="stable")
6
+ result = bootstrap.auth.sign_in(
7
+ email=os.environ["IMBRACE_EMAIL"],
8
+ password=os.environ["IMBRACE_PASSWORD"],
9
+ )
10
+ bootstrap.close()
11
+
12
+ access_token = result["accessToken"]
13
+ org_id = os.environ["IMBRACE_ORG_ID"]
14
+
15
+ # Step 2: use the SDK with the scoped access token
16
+ client = ImbraceClient(
17
+ access_token=access_token,
18
+ organization_id=org_id,
19
+ env="stable",
20
+ )
21
+
22
+ me = client.platform.get_me()
23
+ print("Logged in as:", me)
24
+
25
+ client.close()
@@ -0,0 +1,34 @@
1
+ import os
2
+ from imbrace import ImbraceClient
3
+
4
+ client = ImbraceClient(
5
+ access_token=os.environ["IMBRACE_ACCESS_TOKEN"],
6
+ env="stable",
7
+ )
8
+
9
+ # List available models
10
+ models = client.chat_ai.list_models()
11
+ print("Models:", [m["id"] for m in models.get("data", [])])
12
+
13
+ # Chat completion
14
+ response = client.chat_ai.chat({
15
+ "model": "gpt-4o",
16
+ "messages": [
17
+ {"role": "system", "content": "You are a helpful assistant."},
18
+ {"role": "user", "content": "Summarize iMBRACE in one sentence."},
19
+ ],
20
+ })
21
+ print("AI:", response["choices"][0]["message"]["content"])
22
+
23
+ # Manage chats
24
+ chats = client.chat_ai.list_chats()
25
+ print("Existing chats:", len(chats))
26
+
27
+ new_chat = client.chat_ai.create_chat({"title": "SDK Demo Chat"})
28
+ print("Created chat:", new_chat.get("id"))
29
+
30
+ # Manage knowledge bases
31
+ knowledge_list = client.chat_ai.list_knowledge()
32
+ print("Knowledge bases:", len(knowledge_list))
33
+
34
+ client.close()
@@ -0,0 +1,21 @@
1
+ import os
2
+ from imbrace import ImbraceClient
3
+
4
+ client = ImbraceClient(
5
+ access_token=os.environ["IMBRACE_ACCESS_TOKEN"],
6
+ env="stable",
7
+ )
8
+
9
+ # List channels
10
+ channels = client.channel.list()
11
+ print("Channels:", channels)
12
+
13
+ # List conversations
14
+ conversations = client.conversations.list(limit=10)
15
+ print("Conversations:", conversations)
16
+
17
+ # Send a text message (must be called inside an active conversation context)
18
+ msg = client.messages.send(type="text", text="Hello from iMBRACE SDK!")
19
+ print("Sent:", msg)
20
+
21
+ client.close()
@@ -0,0 +1,40 @@
1
+ import asyncio
2
+ import os
3
+ from imbrace import AsyncImbraceClient
4
+
5
+ async def main():
6
+ async with AsyncImbraceClient(
7
+ access_token=os.environ["IMBRACE_ACCESS_TOKEN"],
8
+ organization_id=os.environ.get("IMBRACE_ORG_ID"),
9
+ env="stable",
10
+ ) as client:
11
+ # Fire parallel requests
12
+ channels, conversations = await asyncio.gather(
13
+ client.channel.list(),
14
+ client.conversations.list(limit=10),
15
+ )
16
+ print("Channels:", channels)
17
+ print("Conversations:", conversations)
18
+
19
+ # Chat AI completion
20
+ response = await client.chat_ai.chat({
21
+ "model": "gpt-4o",
22
+ "messages": [{"role": "user", "content": "Hello!"}],
23
+ })
24
+ print("AI:", response["choices"][0]["message"]["content"])
25
+
26
+ # AI streaming via ai resource (uses CompletionInput)
27
+ from imbrace.types.ai import CompletionInput, CompletionMessage
28
+
29
+ print("Streaming:")
30
+ async for chunk in client.ai.stream(
31
+ CompletionInput(
32
+ model="gpt-4o",
33
+ messages=[CompletionMessage(role="user", content="Count to 3.")],
34
+ )
35
+ ):
36
+ content = chunk.choices[0].delta.content or ""
37
+ print(content, end="", flush=True)
38
+ print()
39
+
40
+ asyncio.run(main())
@@ -0,0 +1,81 @@
1
+ """
2
+ Document AI example — runs against prodv2 gateway.
3
+ Usage: python examples/06_document_ai.py
4
+ """
5
+
6
+ import os
7
+ import json
8
+ from imbrace import ImbraceClient
9
+
10
+ ACCESS_TOKEN = os.environ.get("IMBRACE_ACCESS_TOKEN", "acc_c8c27f3b-e147-4735-b641-61e8d3706692")
11
+ GATEWAY = os.environ.get("IMBRACE_GATEWAY_URL", "https://app-gatewayv2.imbrace.co")
12
+ ORG_ID = os.environ.get("IMBRACE_ORG_ID", "org_8d2a2d53-20ef-4c54-8aa9-aadec5963b5c")
13
+
14
+ # Small Chinese VAT invoice image — publicly accessible on prodv2
15
+ TEST_IMAGE_URL = "https://app-gatewayv2.imbrace.co/files/download/118615471-5b33f600-b7f3-11eb-94a1-78e635e66558.png"
16
+
17
+ client = ImbraceClient(access_token=ACCESS_TOKEN, gateway=GATEWAY, organization_id=ORG_ID)
18
+
19
+ passed, failed, skipped = 0, 0, 0
20
+
21
+ def ok(label, detail=""):
22
+ global passed
23
+ print(f" ✓ {label}{f' → {str(detail)[:120]}' if detail else ''}")
24
+ passed += 1
25
+
26
+ def fail(label, err):
27
+ global failed
28
+ print(f" ✗ {label}: {str(err)[:120]}")
29
+ failed += 1
30
+
31
+ def skip(label, reason):
32
+ global skipped
33
+ print(f" - {label} (skipped: {reason})")
34
+ skipped += 1
35
+
36
+ # ─────────────────────────────────────────────────────────────────────────────
37
+ # List providers (document AI model source)
38
+ # ─────────────────────────────────────────────────────────────────────────────
39
+
40
+ print("\n[1] List document AI providers")
41
+ vision_model = None
42
+ try:
43
+ providers = client.chat_ai.list_document_models()
44
+ all_models = [m for p in providers for m in p.get("models", [])]
45
+ vision_models = [m for m in all_models if m.get("is_vision_available") and "image" not in m["name"]]
46
+ # prefer gpt-4o for document reading
47
+ vision_model = next((m["name"] for m in vision_models if m["name"] == "gpt-4o"), None) \
48
+ or next((m["name"] for m in vision_models if m["name"].startswith("gpt-4")), None) \
49
+ or (vision_models[0]["name"] if vision_models else None)
50
+ ok("list_document_models()", f"{len(providers)} providers, {len(all_models)} models, {len(vision_models)} vision-capable")
51
+ except Exception as e:
52
+ fail("list_document_models()", e)
53
+
54
+ # ─────────────────────────────────────────────────────────────────────────────
55
+ # Process document — vision model from provider
56
+ # ─────────────────────────────────────────────────────────────────────────────
57
+
58
+ print("\n[2] Process document with vision model from provider")
59
+ if not vision_model:
60
+ skip("process_document()", "no vision-capable model found in configured providers")
61
+ else:
62
+ try:
63
+ res = client.chat_ai.process_document(
64
+ model_name=vision_model,
65
+ url=TEST_IMAGE_URL,
66
+ organization_id=ORG_ID,
67
+ )
68
+ if not res.get("success"):
69
+ raise Exception(json.dumps(res))
70
+ keys = list(res.get("data", {}).keys())
71
+ ok(f"process_document() {vision_model}", f"extracted keys: {', '.join(keys)}")
72
+ except Exception as e:
73
+ fail(f"process_document() {vision_model}", e)
74
+
75
+ # ─────────────────────────────────────────────────────────────────────────────
76
+
77
+ client.close()
78
+ print(f"\n{'─' * 55}")
79
+ print(f" {passed} passed | {failed} failed | {skipped} skipped")
80
+ if failed > 0:
81
+ raise SystemExit(1)