wiil-python 0.0.3__py3-none-any.whl → 0.0.4__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.
- wiil/models/business_mgt/service_appointment.py +4 -16
- wiil/resources/service_mgt/__init__.py +15 -3
- wiil/resources/service_mgt/dynamic_agent_status.py +10 -1
- wiil/resources/service_mgt/dynamic_phone_agent.py +251 -53
- wiil/resources/service_mgt/dynamic_web_agent.py +264 -54
- wiil/resources/service_mgt/provisioning_configs.py +231 -21
- wiil/resources/service_mgt/support_models.py +31 -0
- {wiil_python-0.0.3.dist-info → wiil_python-0.0.4.dist-info}/METADATA +1 -1
- {wiil_python-0.0.3.dist-info → wiil_python-0.0.4.dist-info}/RECORD +11 -11
- {wiil_python-0.0.3.dist-info → wiil_python-0.0.4.dist-info}/WHEEL +0 -0
- {wiil_python-0.0.3.dist-info → wiil_python-0.0.4.dist-info}/top_level.txt +0 -0
|
@@ -6,7 +6,7 @@ calendar integration and service provider assignment.
|
|
|
6
6
|
|
|
7
7
|
from typing import Optional
|
|
8
8
|
|
|
9
|
-
from pydantic import BaseModel as PydanticBaseModel
|
|
9
|
+
from pydantic import BaseModel as PydanticBaseModel
|
|
10
10
|
from pydantic import ConfigDict, EmailStr, Field
|
|
11
11
|
|
|
12
12
|
from wiil.models.base import BaseModel
|
|
@@ -154,12 +154,9 @@ class CreateServiceAppointment(PydanticBaseModel):
|
|
|
154
154
|
create_data = CreateServiceAppointment(
|
|
155
155
|
business_service_id="service_123",
|
|
156
156
|
customer_id="cust_456",
|
|
157
|
-
customer_name="Jane Smith",
|
|
158
|
-
customer_email="jane@example.com",
|
|
159
157
|
start_time=1234567890,
|
|
160
158
|
duration=45,
|
|
161
|
-
total_price=75.00
|
|
162
|
-
status=AppointmentStatus.PENDING
|
|
159
|
+
total_price=75.00
|
|
163
160
|
)
|
|
164
161
|
```
|
|
165
162
|
"""
|
|
@@ -172,19 +169,15 @@ class CreateServiceAppointment(PydanticBaseModel):
|
|
|
172
169
|
|
|
173
170
|
business_service_id: str = Field(..., alias="businessServiceId")
|
|
174
171
|
customer_id: str = Field(..., alias="customerId")
|
|
175
|
-
customer_name: Optional[str] = Field(None, alias="customerName")
|
|
176
|
-
customer_email: Optional[EmailStr] = Field(None, alias="customerEmail")
|
|
177
172
|
start_time: int = Field(..., alias="startTime")
|
|
178
173
|
end_time: Optional[int] = Field(None, alias="endTime")
|
|
179
|
-
duration: Optional[int] = Field(
|
|
180
|
-
total_price: Optional[float] = Field(
|
|
174
|
+
duration: Optional[int] = Field(None, gt=0)
|
|
175
|
+
total_price: Optional[float] = Field(None, ge=0, alias="totalPrice")
|
|
181
176
|
deposit_paid: float = Field(0.0, ge=0, alias="depositPaid")
|
|
182
|
-
status: AppointmentStatus = AppointmentStatus.PENDING
|
|
183
177
|
assigned_user_account_id: Optional[str] = Field(None, alias="assignedUserAccountId")
|
|
184
178
|
calendar_id: Optional[str] = Field(None, alias="calendarId")
|
|
185
179
|
calendar_event_id: Optional[str] = Field(None, alias="calendarEventId")
|
|
186
180
|
calendar_provider: Optional[CalendarProvider] = Field(None, alias="calendarProvider")
|
|
187
|
-
service_conversation_config_id: Optional[str] = Field(None, alias="serviceConversationConfigId")
|
|
188
181
|
|
|
189
182
|
|
|
190
183
|
class UpdateServiceAppointment(PydanticBaseModel):
|
|
@@ -196,7 +189,6 @@ class UpdateServiceAppointment(PydanticBaseModel):
|
|
|
196
189
|
```python
|
|
197
190
|
update_data = UpdateServiceAppointment(
|
|
198
191
|
id="appt_123",
|
|
199
|
-
status=AppointmentStatus.COMPLETED,
|
|
200
192
|
end_time=1234567950
|
|
201
193
|
)
|
|
202
194
|
```
|
|
@@ -211,17 +203,13 @@ class UpdateServiceAppointment(PydanticBaseModel):
|
|
|
211
203
|
id: str
|
|
212
204
|
business_service_id: Optional[str] = Field(None, alias="businessServiceId")
|
|
213
205
|
customer_id: Optional[str] = Field(None, alias="customerId")
|
|
214
|
-
customer_name: Optional[str] = Field(None, alias="customerName")
|
|
215
|
-
customer_email: Optional[EmailStr] = Field(None, alias="customerEmail")
|
|
216
206
|
start_time: Optional[int] = Field(None, alias="startTime")
|
|
217
207
|
end_time: Optional[int] = Field(None, alias="endTime")
|
|
218
208
|
duration: Optional[int] = Field(None, gt=0)
|
|
219
209
|
total_price: Optional[float] = Field(None, ge=0, alias="totalPrice")
|
|
220
210
|
deposit_paid: Optional[float] = Field(None, ge=0, alias="depositPaid")
|
|
221
|
-
status: Optional[AppointmentStatus] = None
|
|
222
211
|
assigned_user_account_id: Optional[str] = Field(None, alias="assignedUserAccountId")
|
|
223
212
|
calendar_id: Optional[str] = Field(None, alias="calendarId")
|
|
224
213
|
calendar_event_id: Optional[str] = Field(None, alias="calendarEventId")
|
|
225
214
|
calendar_provider: Optional[CalendarProvider] = Field(None, alias="calendarProvider")
|
|
226
215
|
cancel_reason: Optional[str] = Field(None, alias="cancelReason")
|
|
227
|
-
service_conversation_config_id: Optional[str] = Field(None, alias="serviceConversationConfigId")
|
|
@@ -19,9 +19,18 @@ from wiil.resources.service_mgt.translation_sessions import TranslationSessionsR
|
|
|
19
19
|
from wiil.resources.service_mgt.knowledge_sources import KnowledgeSourcesResource
|
|
20
20
|
from wiil.resources.service_mgt.support_models import SupportModelsResource
|
|
21
21
|
from wiil.resources.service_mgt.telephony_provider import TelephonyProviderResource
|
|
22
|
-
from wiil.resources.service_mgt.dynamic_agent_status import
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
from wiil.resources.service_mgt.dynamic_agent_status import (
|
|
23
|
+
DynamicAgentStatusResource,
|
|
24
|
+
PollTimeoutError,
|
|
25
|
+
)
|
|
26
|
+
from wiil.resources.service_mgt.dynamic_web_agent import (
|
|
27
|
+
DynamicWebAgentResource,
|
|
28
|
+
WebAgentCreateOptions,
|
|
29
|
+
)
|
|
30
|
+
from wiil.resources.service_mgt.dynamic_phone_agent import (
|
|
31
|
+
DynamicPhoneAgentResource,
|
|
32
|
+
PhoneAgentCreateOptions,
|
|
33
|
+
)
|
|
25
34
|
|
|
26
35
|
__all__ = [
|
|
27
36
|
'AgentConfigurationsResource',
|
|
@@ -36,6 +45,9 @@ __all__ = [
|
|
|
36
45
|
'SupportModelsResource',
|
|
37
46
|
'TelephonyProviderResource',
|
|
38
47
|
'DynamicAgentStatusResource',
|
|
48
|
+
'PollTimeoutError',
|
|
39
49
|
'DynamicWebAgentResource',
|
|
50
|
+
'WebAgentCreateOptions',
|
|
40
51
|
'DynamicPhoneAgentResource',
|
|
52
|
+
'PhoneAgentCreateOptions',
|
|
41
53
|
]
|
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
from wiil.client.http_client import HttpClient
|
|
4
4
|
from wiil.models.service_mgt.dynamic_setup import (
|
|
5
|
+
DynamicAgentProcessingState,
|
|
5
6
|
DynamicAgentSetupResult,
|
|
6
7
|
)
|
|
7
8
|
|
|
8
9
|
|
|
10
|
+
class PollTimeoutError(Exception):
|
|
11
|
+
"""Raised when polling times out before completion."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, message: str, last_state: DynamicAgentProcessingState):
|
|
14
|
+
super().__init__(message)
|
|
15
|
+
self.last_state = last_state
|
|
16
|
+
|
|
17
|
+
|
|
9
18
|
class DynamicAgentStatusResource:
|
|
10
19
|
"""Resource class for checking dynamic agent setup status.
|
|
11
20
|
|
|
@@ -32,4 +41,4 @@ class DynamicAgentStatusResource:
|
|
|
32
41
|
)
|
|
33
42
|
|
|
34
43
|
|
|
35
|
-
__all__ = ['DynamicAgentStatusResource']
|
|
44
|
+
__all__ = ['DynamicAgentStatusResource', 'PollTimeoutError']
|
|
@@ -1,74 +1,190 @@
|
|
|
1
|
-
"""Dynamic Phone Agent resource for
|
|
1
|
+
"""Dynamic Phone Agent resource for phone-based AI agents."""
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
from
|
|
3
|
+
import time
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Callable, Optional
|
|
5
6
|
|
|
6
7
|
from wiil.client.http_client import HttpClient
|
|
8
|
+
from wiil.errors import WiilValidationError
|
|
7
9
|
from wiil.models.service_mgt.dynamic_setup import (
|
|
10
|
+
DynamicAgentProcessingState,
|
|
8
11
|
DynamicPhoneAgentSetup,
|
|
9
12
|
DynamicPhoneAgentSetupResult,
|
|
13
|
+
DynamicSTTModelConfiguration,
|
|
14
|
+
DynamicTTSModelConfiguration,
|
|
10
15
|
UpdateDynamicPhoneAgent,
|
|
11
16
|
)
|
|
12
|
-
from wiil.
|
|
17
|
+
from wiil.resources.service_mgt.dynamic_agent_status import PollTimeoutError
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class PhoneAgentCreateOptions:
|
|
22
|
+
"""Options for configuring agent creation behavior."""
|
|
23
|
+
|
|
24
|
+
poll_until_complete: bool = True
|
|
25
|
+
"""Whether to poll until setup completes."""
|
|
26
|
+
|
|
27
|
+
poll_interval: float = 5.0
|
|
28
|
+
"""Polling interval in seconds."""
|
|
29
|
+
|
|
30
|
+
poll_timeout: float = 120.0
|
|
31
|
+
"""Maximum wait time in seconds before timing out."""
|
|
32
|
+
|
|
33
|
+
on_progress: Optional[Callable[[DynamicAgentProcessingState], None]] = None
|
|
34
|
+
"""Callback invoked on each poll with the current processing state."""
|
|
35
|
+
|
|
36
|
+
silent: bool = False
|
|
37
|
+
"""Whether to suppress console logging."""
|
|
13
38
|
|
|
14
39
|
|
|
15
40
|
class DynamicPhoneAgentResource:
|
|
16
|
-
"""Resource class for managing dynamic phone
|
|
41
|
+
"""Resource class for managing dynamic phone agent provisioning.
|
|
42
|
+
|
|
43
|
+
Provides methods for creating and updating dynamic phone agent
|
|
44
|
+
configurations. Dynamic phone agents enable AI-powered phone
|
|
45
|
+
interactions with configurable STT and TTS capabilities.
|
|
17
46
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
47
|
+
Example:
|
|
48
|
+
>>> from wiil.models.type_definitions import (
|
|
49
|
+
... AgentCapabilities,
|
|
50
|
+
... AgentRoleTemplateIdentifier,
|
|
51
|
+
... )
|
|
52
|
+
>>>
|
|
53
|
+
>>> client = WiilClient(api_key='your-api-key')
|
|
54
|
+
>>>
|
|
55
|
+
>>> # Create with polling (waits for completion)
|
|
56
|
+
>>> result = client.dynamic_phone_agent.create(
|
|
57
|
+
... DynamicPhoneAgentSetup(
|
|
58
|
+
... assistant_name='Alex',
|
|
59
|
+
... capabilities=[AgentCapabilities.APPOINTMENT_MANAGEMENT],
|
|
60
|
+
... role_template_identifier=(
|
|
61
|
+
... AgentRoleTemplateIdentifier.CUSTOMER_SUPPORT_GENERAL
|
|
62
|
+
... ),
|
|
63
|
+
... )
|
|
64
|
+
... )
|
|
65
|
+
>>>
|
|
66
|
+
>>> # Create without waiting
|
|
67
|
+
>>> result = client.dynamic_phone_agent.create(
|
|
68
|
+
... data,
|
|
69
|
+
... options=PhoneAgentCreateOptions(poll_until_complete=False)
|
|
70
|
+
... )
|
|
21
71
|
"""
|
|
22
72
|
|
|
23
73
|
def __init__(self, http: HttpClient):
|
|
24
74
|
self._http = http
|
|
25
|
-
self._base_path = '/dynamic-phone-agent'
|
|
75
|
+
self._base_path = '/dynamic-setup/phone-agent'
|
|
76
|
+
self._status_path = '/dynamic-setup'
|
|
26
77
|
|
|
27
78
|
def create(
|
|
28
79
|
self,
|
|
29
|
-
data: DynamicPhoneAgentSetup
|
|
80
|
+
data: DynamicPhoneAgentSetup,
|
|
81
|
+
options: Optional[PhoneAgentCreateOptions] = None
|
|
30
82
|
) -> DynamicPhoneAgentSetupResult:
|
|
31
|
-
"""Create a new dynamic phone agent.
|
|
83
|
+
"""Create and provision a new dynamic phone agent.
|
|
32
84
|
|
|
33
85
|
Args:
|
|
34
|
-
data: Phone agent
|
|
86
|
+
data: Phone agent configuration data
|
|
87
|
+
options: Creation options for polling and logging behavior
|
|
35
88
|
|
|
36
89
|
Returns:
|
|
37
|
-
The setup result
|
|
90
|
+
The setup result including provisioned phone number
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
WiilValidationError: When validation fails or model not supported
|
|
94
|
+
WiilAPIError: When the API returns an error
|
|
95
|
+
PollTimeoutError: When polling times out before completion
|
|
38
96
|
"""
|
|
39
|
-
|
|
97
|
+
opts = options or PhoneAgentCreateOptions()
|
|
98
|
+
start_time = time.time()
|
|
99
|
+
agent_name = data.assistant_name
|
|
100
|
+
|
|
101
|
+
# Validate model configurations before proceeding
|
|
102
|
+
self._validate_model_configurations(
|
|
103
|
+
data.stt_configuration,
|
|
104
|
+
data.tts_configuration
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Log initial creation
|
|
108
|
+
if not opts.silent:
|
|
109
|
+
self._log(f'Creating agent "{agent_name}"...')
|
|
110
|
+
|
|
111
|
+
# Create the agent
|
|
112
|
+
initial_result = self._http.post(
|
|
40
113
|
self._base_path,
|
|
41
114
|
data.model_dump(by_alias=True, exclude_none=True),
|
|
42
115
|
schema=DynamicPhoneAgentSetup,
|
|
43
116
|
response_model=DynamicPhoneAgentSetupResult
|
|
44
117
|
)
|
|
45
118
|
|
|
46
|
-
|
|
47
|
-
|
|
119
|
+
# If not polling, return immediately
|
|
120
|
+
if not opts.poll_until_complete:
|
|
121
|
+
if not opts.silent:
|
|
122
|
+
self._log(f'Setup initiated (ID: {initial_result.id})')
|
|
123
|
+
return initial_result
|
|
48
124
|
|
|
49
|
-
|
|
50
|
-
|
|
125
|
+
# Check if already complete
|
|
126
|
+
if initial_result.processing_state.status in ('completed', 'failed'):
|
|
127
|
+
self._log_final_result(initial_result, start_time, opts.silent)
|
|
128
|
+
return initial_result
|
|
51
129
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
130
|
+
# Poll until complete
|
|
131
|
+
while True:
|
|
132
|
+
result = self._http.get(
|
|
133
|
+
f'{self._status_path}/{initial_result.id}',
|
|
134
|
+
response_model=DynamicPhoneAgentSetupResult
|
|
135
|
+
)
|
|
136
|
+
last_state = result.processing_state
|
|
137
|
+
|
|
138
|
+
# Log progress
|
|
139
|
+
if not opts.silent:
|
|
140
|
+
self._log_progress(last_state)
|
|
141
|
+
|
|
142
|
+
# Invoke callback
|
|
143
|
+
if opts.on_progress:
|
|
144
|
+
opts.on_progress(last_state)
|
|
145
|
+
|
|
146
|
+
# Check for terminal states
|
|
147
|
+
if last_state.status in ('completed', 'failed'):
|
|
148
|
+
self._log_final_result(result, start_time, opts.silent)
|
|
149
|
+
return result
|
|
150
|
+
|
|
151
|
+
# Check for timeout
|
|
152
|
+
elapsed = time.time() - start_time
|
|
153
|
+
if elapsed >= opts.poll_timeout:
|
|
154
|
+
if not opts.silent:
|
|
155
|
+
self._log(f'Timeout after {self._format_duration(elapsed)}')
|
|
156
|
+
msg = (
|
|
157
|
+
f'Polling timed out after {opts.poll_timeout}s. '
|
|
158
|
+
f'Last status: {last_state.status} '
|
|
159
|
+
f'at {last_state.progress_percentage}%'
|
|
160
|
+
)
|
|
161
|
+
raise PollTimeoutError(msg, last_state)
|
|
162
|
+
|
|
163
|
+
# Wait before next poll
|
|
164
|
+
time.sleep(opts.poll_interval)
|
|
59
165
|
|
|
60
166
|
def update(
|
|
61
167
|
self,
|
|
62
168
|
data: UpdateDynamicPhoneAgent
|
|
63
169
|
) -> DynamicPhoneAgentSetupResult:
|
|
64
|
-
"""Update an existing dynamic phone agent.
|
|
170
|
+
"""Update an existing dynamic phone agent configuration.
|
|
65
171
|
|
|
66
172
|
Args:
|
|
67
173
|
data: Phone agent update data (must include id)
|
|
68
174
|
|
|
69
175
|
Returns:
|
|
70
176
|
The updated phone agent setup result
|
|
177
|
+
|
|
178
|
+
Raises:
|
|
179
|
+
WiilValidationError: When input validation fails
|
|
180
|
+
WiilAPIError: When phone agent is not found or API error
|
|
71
181
|
"""
|
|
182
|
+
# Validate model configurations before proceeding
|
|
183
|
+
self._validate_model_configurations(
|
|
184
|
+
data.stt_configuration,
|
|
185
|
+
data.tts_configuration
|
|
186
|
+
)
|
|
187
|
+
|
|
72
188
|
return self._http.patch(
|
|
73
189
|
self._base_path,
|
|
74
190
|
data.model_dump(by_alias=True, exclude_none=True),
|
|
@@ -76,39 +192,121 @@ class DynamicPhoneAgentResource:
|
|
|
76
192
|
response_model=DynamicPhoneAgentSetupResult
|
|
77
193
|
)
|
|
78
194
|
|
|
79
|
-
def
|
|
80
|
-
|
|
195
|
+
def _validate_model_configurations(
|
|
196
|
+
self,
|
|
197
|
+
stt_config: Optional[DynamicSTTModelConfiguration],
|
|
198
|
+
tts_config: Optional[DynamicTTSModelConfiguration]
|
|
199
|
+
) -> None:
|
|
200
|
+
"""Validate STT and TTS model configs against support registry."""
|
|
201
|
+
has_stt = (
|
|
202
|
+
stt_config
|
|
203
|
+
and stt_config.provider_type
|
|
204
|
+
and stt_config.provider_model_id
|
|
205
|
+
)
|
|
206
|
+
if has_stt:
|
|
207
|
+
self._validate_model(
|
|
208
|
+
stt_config.provider_type,
|
|
209
|
+
stt_config.provider_model_id,
|
|
210
|
+
'STT'
|
|
211
|
+
)
|
|
81
212
|
|
|
82
|
-
|
|
83
|
-
|
|
213
|
+
has_tts = (
|
|
214
|
+
tts_config
|
|
215
|
+
and tts_config.provider_type
|
|
216
|
+
and tts_config.provider_model_id
|
|
217
|
+
)
|
|
218
|
+
if has_tts:
|
|
219
|
+
self._validate_model(
|
|
220
|
+
tts_config.provider_type,
|
|
221
|
+
tts_config.provider_model_id,
|
|
222
|
+
'TTS'
|
|
223
|
+
)
|
|
84
224
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
225
|
+
def _validate_model(
|
|
226
|
+
self,
|
|
227
|
+
provider_type: str,
|
|
228
|
+
provider_model_id: str,
|
|
229
|
+
model_type: str
|
|
230
|
+
) -> None:
|
|
231
|
+
"""Validate a single model against the support registry."""
|
|
232
|
+
is_supported = self._http.get(
|
|
233
|
+
f'/support-models/supports/{provider_type}/{provider_model_id}',
|
|
234
|
+
response_model=bool
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
if not is_supported:
|
|
238
|
+
msg = (
|
|
239
|
+
f'Unsupported {model_type} model: '
|
|
240
|
+
f'{provider_type}/{provider_model_id}. '
|
|
241
|
+
f'Verify the model is available in the support registry.'
|
|
242
|
+
)
|
|
243
|
+
raise WiilValidationError(msg)
|
|
244
|
+
|
|
245
|
+
def _log(self, message: str) -> None:
|
|
246
|
+
"""Log a message with agent context."""
|
|
247
|
+
print(f'[Phone Agent] {message}')
|
|
89
248
|
|
|
90
|
-
def
|
|
249
|
+
def _log_progress(self, state: DynamicAgentProcessingState) -> None:
|
|
250
|
+
"""Log progress with a visual progress bar."""
|
|
251
|
+
bar = self._create_progress_bar(state.progress_percentage)
|
|
252
|
+
status_msg = state.message or self._get_status_message(state.status)
|
|
253
|
+
pct = state.progress_percentage
|
|
254
|
+
print(f'[Phone Agent] {bar} {pct}% | {status_msg}')
|
|
255
|
+
|
|
256
|
+
def _log_final_result(
|
|
91
257
|
self,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
258
|
+
result: DynamicPhoneAgentSetupResult,
|
|
259
|
+
start_time: float,
|
|
260
|
+
silent: bool
|
|
261
|
+
) -> None:
|
|
262
|
+
"""Log the final result with summary."""
|
|
263
|
+
if silent:
|
|
264
|
+
return
|
|
95
265
|
|
|
96
|
-
|
|
97
|
-
|
|
266
|
+
elapsed = time.time() - start_time
|
|
267
|
+
duration = self._format_duration(elapsed)
|
|
98
268
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
"""
|
|
102
|
-
query_params: Dict[str, Any] = {}
|
|
103
|
-
if params:
|
|
104
|
-
query_params['page'] = params.page
|
|
105
|
-
query_params['pageSize'] = params.page_size
|
|
106
|
-
|
|
107
|
-
query_string = f'?{urlencode(query_params)}' if query_params else ''
|
|
108
|
-
return self._http.get(
|
|
109
|
-
f'{self._base_path}{query_string}',
|
|
110
|
-
response_model=PaginatedResult[DynamicPhoneAgentSetupResult]
|
|
269
|
+
is_success = (
|
|
270
|
+
result.processing_state.status == 'completed' and result.success
|
|
111
271
|
)
|
|
272
|
+
if is_success:
|
|
273
|
+
bar = self._create_progress_bar(100)
|
|
274
|
+
print(f'[Phone Agent] {bar} 100% | Setup complete')
|
|
275
|
+
print(f'[Phone Agent] Ready in {duration}')
|
|
276
|
+
if result.phone_number:
|
|
277
|
+
print(f' -> Phone: {result.phone_number}')
|
|
278
|
+
if result.agent_configuration_id:
|
|
279
|
+
print(f' -> Agent ID: {result.agent_configuration_id}')
|
|
280
|
+
if result.instruction_configuration_id:
|
|
281
|
+
inst_id = result.instruction_configuration_id
|
|
282
|
+
print(f' -> Instruction ID: {inst_id}')
|
|
283
|
+
else:
|
|
284
|
+
print(f'[Phone Agent] Setup failed after {duration}')
|
|
285
|
+
if result.error_message:
|
|
286
|
+
print(f' -> Error: {result.error_message}')
|
|
287
|
+
|
|
288
|
+
def _create_progress_bar(self, percentage: int) -> str:
|
|
289
|
+
"""Create a visual progress bar."""
|
|
290
|
+
total = 20
|
|
291
|
+
filled = round((percentage / 100) * total)
|
|
292
|
+
empty = total - filled
|
|
293
|
+
return '█' * filled + '░' * empty
|
|
294
|
+
|
|
295
|
+
def _get_status_message(self, status: str) -> str:
|
|
296
|
+
"""Get a human-readable status message."""
|
|
297
|
+
messages = {
|
|
298
|
+
'pending': 'Initializing...',
|
|
299
|
+
'in_progress': 'Processing...',
|
|
300
|
+
'completed': 'Setup complete',
|
|
301
|
+
'failed': 'Setup failed',
|
|
302
|
+
}
|
|
303
|
+
return messages.get(status, status)
|
|
304
|
+
|
|
305
|
+
def _format_duration(self, seconds: float) -> str:
|
|
306
|
+
"""Format duration in human-readable form."""
|
|
307
|
+
if seconds < 1:
|
|
308
|
+
return f'{int(seconds * 1000)}ms'
|
|
309
|
+
return f'{seconds:.1f}s'
|
|
112
310
|
|
|
113
311
|
|
|
114
|
-
__all__ = ['DynamicPhoneAgentResource']
|
|
312
|
+
__all__ = ['DynamicPhoneAgentResource', 'PhoneAgentCreateOptions']
|
|
@@ -1,68 +1,195 @@
|
|
|
1
|
-
"""Dynamic Web Agent resource for
|
|
1
|
+
"""Dynamic Web Agent resource for web-based AI agents."""
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
from
|
|
3
|
+
import time
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Callable, Optional
|
|
5
6
|
|
|
6
7
|
from wiil.client.http_client import HttpClient
|
|
8
|
+
from wiil.errors import WiilValidationError
|
|
7
9
|
from wiil.models.service_mgt.dynamic_setup import (
|
|
10
|
+
DynamicAgentProcessingState,
|
|
11
|
+
DynamicSTTModelConfiguration,
|
|
12
|
+
DynamicTTSModelConfiguration,
|
|
8
13
|
DynamicWebAgentSetup,
|
|
9
14
|
DynamicWebAgentSetupResult,
|
|
10
15
|
UpdateDynamicWebAgent,
|
|
11
16
|
)
|
|
12
|
-
from wiil.
|
|
17
|
+
from wiil.resources.service_mgt.dynamic_agent_status import PollTimeoutError
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class WebAgentCreateOptions:
|
|
22
|
+
"""Options for configuring agent creation behavior."""
|
|
23
|
+
|
|
24
|
+
poll_until_complete: bool = True
|
|
25
|
+
"""Whether to poll until setup completes."""
|
|
26
|
+
|
|
27
|
+
poll_interval: float = 5.0
|
|
28
|
+
"""Polling interval in seconds."""
|
|
29
|
+
|
|
30
|
+
poll_timeout: float = 120.0
|
|
31
|
+
"""Maximum wait time in seconds before timing out."""
|
|
32
|
+
|
|
33
|
+
on_progress: Optional[Callable[[DynamicAgentProcessingState], None]] = None
|
|
34
|
+
"""Callback invoked on each poll with the current processing state."""
|
|
35
|
+
|
|
36
|
+
silent: bool = False
|
|
37
|
+
"""Whether to suppress console logging."""
|
|
13
38
|
|
|
14
39
|
|
|
15
40
|
class DynamicWebAgentResource:
|
|
16
|
-
"""Resource class for managing dynamic web
|
|
41
|
+
"""Resource class for managing dynamic web agent provisioning.
|
|
42
|
+
|
|
43
|
+
Provides methods for creating and updating dynamic web agent
|
|
44
|
+
configurations. Dynamic web agents enable AI-powered web
|
|
45
|
+
interactions with configurable STT and TTS capabilities.
|
|
46
|
+
Setup results include integration snippets for websites.
|
|
17
47
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
48
|
+
Example:
|
|
49
|
+
>>> from wiil.models.type_definitions import (
|
|
50
|
+
... AgentCapabilities,
|
|
51
|
+
... AgentRoleTemplateIdentifier,
|
|
52
|
+
... OttCommunicationType,
|
|
53
|
+
... )
|
|
54
|
+
>>>
|
|
55
|
+
>>> client = WiilClient(api_key='your-api-key')
|
|
56
|
+
>>>
|
|
57
|
+
>>> # Create with polling (waits for completion)
|
|
58
|
+
>>> result = client.dynamic_web_agent.create(
|
|
59
|
+
... DynamicWebAgentSetup(
|
|
60
|
+
... assistant_name='Emma',
|
|
61
|
+
... website_url='https://example.com',
|
|
62
|
+
... communication_type=OttCommunicationType.TEXT,
|
|
63
|
+
... capabilities=[AgentCapabilities.APPOINTMENT_MANAGEMENT],
|
|
64
|
+
... role_template_identifier=(
|
|
65
|
+
... AgentRoleTemplateIdentifier.CUSTOMER_SUPPORT_GENERAL
|
|
66
|
+
... ),
|
|
67
|
+
... )
|
|
68
|
+
... )
|
|
69
|
+
>>> print('Integration snippets:', result.integration_snippets)
|
|
70
|
+
>>>
|
|
71
|
+
>>> # Create without waiting
|
|
72
|
+
>>> result = client.dynamic_web_agent.create(
|
|
73
|
+
... data,
|
|
74
|
+
... options=WebAgentCreateOptions(poll_until_complete=False)
|
|
75
|
+
... )
|
|
21
76
|
"""
|
|
22
77
|
|
|
23
78
|
def __init__(self, http: HttpClient):
|
|
24
79
|
self._http = http
|
|
25
|
-
self._base_path = '/dynamic-web-agent'
|
|
80
|
+
self._base_path = '/dynamic-setup/web-agent'
|
|
81
|
+
self._status_path = '/dynamic-setup'
|
|
26
82
|
|
|
27
|
-
def create(
|
|
28
|
-
|
|
83
|
+
def create(
|
|
84
|
+
self,
|
|
85
|
+
data: DynamicWebAgentSetup,
|
|
86
|
+
options: Optional[WebAgentCreateOptions] = None
|
|
87
|
+
) -> DynamicWebAgentSetupResult:
|
|
88
|
+
"""Create and provision a new dynamic web agent.
|
|
29
89
|
|
|
30
90
|
Args:
|
|
31
|
-
data: Web agent
|
|
91
|
+
data: Web agent configuration data
|
|
92
|
+
options: Creation options for polling and logging behavior
|
|
32
93
|
|
|
33
94
|
Returns:
|
|
34
|
-
The setup result
|
|
95
|
+
The setup result including integration snippets
|
|
96
|
+
|
|
97
|
+
Raises:
|
|
98
|
+
WiilValidationError: When validation fails or model not supported
|
|
99
|
+
WiilAPIError: When the API returns an error
|
|
100
|
+
PollTimeoutError: When polling times out before completion
|
|
35
101
|
"""
|
|
36
|
-
|
|
102
|
+
opts = options or WebAgentCreateOptions()
|
|
103
|
+
start_time = time.time()
|
|
104
|
+
agent_name = data.assistant_name
|
|
105
|
+
|
|
106
|
+
# Validate model configurations before proceeding
|
|
107
|
+
self._validate_model_configurations(
|
|
108
|
+
data.stt_configuration,
|
|
109
|
+
data.tts_configuration
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Log initial creation
|
|
113
|
+
if not opts.silent:
|
|
114
|
+
self._log(f'Creating agent "{agent_name}"...')
|
|
115
|
+
|
|
116
|
+
# Create the agent
|
|
117
|
+
initial_result = self._http.post(
|
|
37
118
|
self._base_path,
|
|
38
119
|
data.model_dump(by_alias=True, exclude_none=True),
|
|
39
120
|
schema=DynamicWebAgentSetup,
|
|
40
121
|
response_model=DynamicWebAgentSetupResult
|
|
41
122
|
)
|
|
42
123
|
|
|
43
|
-
|
|
44
|
-
|
|
124
|
+
# If not polling, return immediately
|
|
125
|
+
if not opts.poll_until_complete:
|
|
126
|
+
if not opts.silent:
|
|
127
|
+
self._log(f'Setup initiated (ID: {initial_result.id})')
|
|
128
|
+
return initial_result
|
|
45
129
|
|
|
46
|
-
|
|
47
|
-
|
|
130
|
+
# Check if already complete
|
|
131
|
+
if initial_result.processing_state.status in ('completed', 'failed'):
|
|
132
|
+
self._log_final_result(initial_result, start_time, opts.silent)
|
|
133
|
+
return initial_result
|
|
48
134
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
135
|
+
# Poll until complete
|
|
136
|
+
while True:
|
|
137
|
+
result = self._http.get(
|
|
138
|
+
f'{self._status_path}/{initial_result.id}',
|
|
139
|
+
response_model=DynamicWebAgentSetupResult
|
|
140
|
+
)
|
|
141
|
+
last_state = result.processing_state
|
|
142
|
+
|
|
143
|
+
# Log progress
|
|
144
|
+
if not opts.silent:
|
|
145
|
+
self._log_progress(last_state)
|
|
146
|
+
|
|
147
|
+
# Invoke callback
|
|
148
|
+
if opts.on_progress:
|
|
149
|
+
opts.on_progress(last_state)
|
|
150
|
+
|
|
151
|
+
# Check for terminal states
|
|
152
|
+
if last_state.status in ('completed', 'failed'):
|
|
153
|
+
self._log_final_result(result, start_time, opts.silent)
|
|
154
|
+
return result
|
|
155
|
+
|
|
156
|
+
# Check for timeout
|
|
157
|
+
elapsed = time.time() - start_time
|
|
158
|
+
if elapsed >= opts.poll_timeout:
|
|
159
|
+
if not opts.silent:
|
|
160
|
+
self._log(f'Timeout after {self._format_duration(elapsed)}')
|
|
161
|
+
msg = (
|
|
162
|
+
f'Polling timed out after {opts.poll_timeout}s. '
|
|
163
|
+
f'Last status: {last_state.status} '
|
|
164
|
+
f'at {last_state.progress_percentage}%'
|
|
165
|
+
)
|
|
166
|
+
raise PollTimeoutError(msg, last_state)
|
|
56
167
|
|
|
57
|
-
|
|
58
|
-
|
|
168
|
+
# Wait before next poll
|
|
169
|
+
time.sleep(opts.poll_interval)
|
|
170
|
+
|
|
171
|
+
def update(
|
|
172
|
+
self,
|
|
173
|
+
data: UpdateDynamicWebAgent
|
|
174
|
+
) -> DynamicWebAgentSetupResult:
|
|
175
|
+
"""Update an existing dynamic web agent configuration.
|
|
59
176
|
|
|
60
177
|
Args:
|
|
61
178
|
data: Web agent update data (must include id)
|
|
62
179
|
|
|
63
180
|
Returns:
|
|
64
181
|
The updated web agent setup result
|
|
182
|
+
|
|
183
|
+
Raises:
|
|
184
|
+
WiilValidationError: When input validation fails
|
|
185
|
+
WiilAPIError: When web agent is not found or API error
|
|
65
186
|
"""
|
|
187
|
+
# Validate model configurations before proceeding
|
|
188
|
+
self._validate_model_configurations(
|
|
189
|
+
data.stt_configuration,
|
|
190
|
+
data.tts_configuration
|
|
191
|
+
)
|
|
192
|
+
|
|
66
193
|
return self._http.patch(
|
|
67
194
|
self._base_path,
|
|
68
195
|
data.model_dump(by_alias=True, exclude_none=True),
|
|
@@ -70,39 +197,122 @@ class DynamicWebAgentResource:
|
|
|
70
197
|
response_model=DynamicWebAgentSetupResult
|
|
71
198
|
)
|
|
72
199
|
|
|
73
|
-
def
|
|
74
|
-
|
|
200
|
+
def _validate_model_configurations(
|
|
201
|
+
self,
|
|
202
|
+
stt_config: Optional[DynamicSTTModelConfiguration],
|
|
203
|
+
tts_config: Optional[DynamicTTSModelConfiguration]
|
|
204
|
+
) -> None:
|
|
205
|
+
"""Validate STT and TTS model configs against support registry."""
|
|
206
|
+
has_stt = (
|
|
207
|
+
stt_config
|
|
208
|
+
and stt_config.provider_type
|
|
209
|
+
and stt_config.provider_model_id
|
|
210
|
+
)
|
|
211
|
+
if has_stt:
|
|
212
|
+
self._validate_model(
|
|
213
|
+
stt_config.provider_type,
|
|
214
|
+
stt_config.provider_model_id,
|
|
215
|
+
'STT'
|
|
216
|
+
)
|
|
75
217
|
|
|
76
|
-
|
|
77
|
-
|
|
218
|
+
has_tts = (
|
|
219
|
+
tts_config
|
|
220
|
+
and tts_config.provider_type
|
|
221
|
+
and tts_config.provider_model_id
|
|
222
|
+
)
|
|
223
|
+
if has_tts:
|
|
224
|
+
self._validate_model(
|
|
225
|
+
tts_config.provider_type,
|
|
226
|
+
tts_config.provider_model_id,
|
|
227
|
+
'TTS'
|
|
228
|
+
)
|
|
78
229
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
230
|
+
def _validate_model(
|
|
231
|
+
self,
|
|
232
|
+
provider_type: str,
|
|
233
|
+
provider_model_id: str,
|
|
234
|
+
model_type: str
|
|
235
|
+
) -> None:
|
|
236
|
+
"""Validate a single model against the support registry."""
|
|
237
|
+
is_supported = self._http.get(
|
|
238
|
+
f'/support-models/supports/{provider_type}/{provider_model_id}',
|
|
239
|
+
response_model=bool
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
if not is_supported:
|
|
243
|
+
msg = (
|
|
244
|
+
f'Unsupported {model_type} model: '
|
|
245
|
+
f'{provider_type}/{provider_model_id}. '
|
|
246
|
+
f'Verify the model is available in the support registry.'
|
|
247
|
+
)
|
|
248
|
+
raise WiilValidationError(msg)
|
|
83
249
|
|
|
84
|
-
def
|
|
250
|
+
def _log(self, message: str) -> None:
|
|
251
|
+
"""Log a message with agent context."""
|
|
252
|
+
print(f'[Web Agent] {message}')
|
|
253
|
+
|
|
254
|
+
def _log_progress(self, state: DynamicAgentProcessingState) -> None:
|
|
255
|
+
"""Log progress with a visual progress bar."""
|
|
256
|
+
bar = self._create_progress_bar(state.progress_percentage)
|
|
257
|
+
status_msg = state.message or self._get_status_message(state.status)
|
|
258
|
+
pct = state.progress_percentage
|
|
259
|
+
print(f'[Web Agent] {bar} {pct}% | {status_msg}')
|
|
260
|
+
|
|
261
|
+
def _log_final_result(
|
|
85
262
|
self,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
263
|
+
result: DynamicWebAgentSetupResult,
|
|
264
|
+
start_time: float,
|
|
265
|
+
silent: bool
|
|
266
|
+
) -> None:
|
|
267
|
+
"""Log the final result with summary."""
|
|
268
|
+
if silent:
|
|
269
|
+
return
|
|
89
270
|
|
|
90
|
-
|
|
91
|
-
|
|
271
|
+
elapsed = time.time() - start_time
|
|
272
|
+
duration = self._format_duration(elapsed)
|
|
92
273
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
"""
|
|
96
|
-
query_params: Dict[str, Any] = {}
|
|
97
|
-
if params:
|
|
98
|
-
query_params['page'] = params.page
|
|
99
|
-
query_params['pageSize'] = params.page_size
|
|
100
|
-
|
|
101
|
-
query_string = f'?{urlencode(query_params)}' if query_params else ''
|
|
102
|
-
return self._http.get(
|
|
103
|
-
f'{self._base_path}{query_string}',
|
|
104
|
-
response_model=PaginatedResult[DynamicWebAgentSetupResult]
|
|
274
|
+
is_success = (
|
|
275
|
+
result.processing_state.status == 'completed' and result.success
|
|
105
276
|
)
|
|
277
|
+
if is_success:
|
|
278
|
+
bar = self._create_progress_bar(100)
|
|
279
|
+
print(f'[Web Agent] {bar} 100% | Setup complete')
|
|
280
|
+
print(f'[Web Agent] Ready in {duration}')
|
|
281
|
+
if result.agent_configuration_id:
|
|
282
|
+
print(f' -> Agent ID: {result.agent_configuration_id}')
|
|
283
|
+
if result.instruction_configuration_id:
|
|
284
|
+
inst_id = result.instruction_configuration_id
|
|
285
|
+
print(f' -> Instruction ID: {inst_id}')
|
|
286
|
+
if result.integration_snippets:
|
|
287
|
+
count = len(result.integration_snippets)
|
|
288
|
+
print(f' -> Integration snippets: {count} available')
|
|
289
|
+
else:
|
|
290
|
+
print(f'[Web Agent] Setup failed after {duration}')
|
|
291
|
+
if result.error_message:
|
|
292
|
+
print(f' -> Error: {result.error_message}')
|
|
293
|
+
|
|
294
|
+
def _create_progress_bar(self, percentage: int) -> str:
|
|
295
|
+
"""Create a visual progress bar."""
|
|
296
|
+
total = 20
|
|
297
|
+
filled = round((percentage / 100) * total)
|
|
298
|
+
empty = total - filled
|
|
299
|
+
return '█' * filled + '░' * empty
|
|
300
|
+
|
|
301
|
+
def _get_status_message(self, status: str) -> str:
|
|
302
|
+
"""Get a human-readable status message."""
|
|
303
|
+
messages = {
|
|
304
|
+
'pending': 'Initializing...',
|
|
305
|
+
'in_progress': 'Processing...',
|
|
306
|
+
'completed': 'Setup complete',
|
|
307
|
+
'failed': 'Setup failed',
|
|
308
|
+
}
|
|
309
|
+
return messages.get(status, status)
|
|
310
|
+
|
|
311
|
+
def _format_duration(self, seconds: float) -> str:
|
|
312
|
+
"""Format duration in human-readable form."""
|
|
313
|
+
if seconds < 1:
|
|
314
|
+
return f'{int(seconds * 1000)}ms'
|
|
315
|
+
return f'{seconds:.1f}s'
|
|
106
316
|
|
|
107
317
|
|
|
108
|
-
__all__ = ['DynamicWebAgentResource']
|
|
318
|
+
__all__ = ['DynamicWebAgentResource', 'WebAgentCreateOptions']
|
|
@@ -1,30 +1,60 @@
|
|
|
1
|
-
"""Provisioning Configurations resource for managing provisioning
|
|
1
|
+
"""Provisioning Configurations resource for managing provisioning configs."""
|
|
2
2
|
|
|
3
|
-
from typing import
|
|
4
|
-
from urllib.parse import urlencode
|
|
3
|
+
from typing import Optional, Union
|
|
5
4
|
|
|
6
5
|
from wiil.client.http_client import HttpClient
|
|
6
|
+
from wiil.errors import WiilValidationError
|
|
7
7
|
from wiil.models.service_mgt import (
|
|
8
8
|
CreateProvisioningConfig,
|
|
9
|
+
CreateTranslationChainConfig,
|
|
10
|
+
DynamicModelConfiguration,
|
|
11
|
+
DynamicSTTModelConfiguration,
|
|
12
|
+
DynamicTTSModelConfiguration,
|
|
9
13
|
ProvisioningConfigChain,
|
|
14
|
+
TranslationChainConfig,
|
|
10
15
|
UpdateProvisioningConfig,
|
|
11
16
|
)
|
|
12
17
|
from wiil.types import PaginatedResult, PaginationRequest
|
|
13
18
|
|
|
14
19
|
|
|
15
20
|
class ProvisioningConfigurationsResource:
|
|
16
|
-
"""Resource class for managing provisioning configurations
|
|
21
|
+
"""Resource class for managing provisioning configurations.
|
|
17
22
|
|
|
18
23
|
Provides methods for creating, retrieving, updating, deleting, and listing
|
|
19
24
|
provisioning configurations. Provisioning configurations define processing
|
|
20
25
|
chains and translation configurations for AI deployments.
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
>>> client = WiilClient(api_key='your-api-key')
|
|
29
|
+
>>>
|
|
30
|
+
>>> # Create a new provisioning configuration
|
|
31
|
+
>>> config = client.provisioning_configs.create(
|
|
32
|
+
... CreateProvisioningConfig(
|
|
33
|
+
... chain_name='customer-support-chain',
|
|
34
|
+
... stt_config=DynamicSTTModelConfiguration(...),
|
|
35
|
+
... processing_config=DynamicModelConfiguration(...),
|
|
36
|
+
... tts_config=DynamicTTSModelConfiguration(...),
|
|
37
|
+
... )
|
|
38
|
+
... )
|
|
39
|
+
>>>
|
|
40
|
+
>>> # Get by chain name
|
|
41
|
+
>>> config = client.provisioning_configs.get_by_chain_name('my-chain')
|
|
42
|
+
>>>
|
|
43
|
+
>>> # List provisioning chains
|
|
44
|
+
>>> chains = client.provisioning_configs.list_provisioning_chains()
|
|
45
|
+
>>>
|
|
46
|
+
>>> # List translation chains
|
|
47
|
+
>>> trans = client.provisioning_configs.list_translation_chains()
|
|
21
48
|
"""
|
|
22
49
|
|
|
23
50
|
def __init__(self, http: HttpClient):
|
|
24
51
|
self._http = http
|
|
25
52
|
self._base_path = '/provisioning-configurations'
|
|
26
53
|
|
|
27
|
-
def create(
|
|
54
|
+
def create(
|
|
55
|
+
self,
|
|
56
|
+
data: CreateProvisioningConfig
|
|
57
|
+
) -> ProvisioningConfigChain:
|
|
28
58
|
"""Create a new provisioning configuration chain.
|
|
29
59
|
|
|
30
60
|
Args:
|
|
@@ -32,7 +62,17 @@ class ProvisioningConfigurationsResource:
|
|
|
32
62
|
|
|
33
63
|
Returns:
|
|
34
64
|
The created provisioning configuration chain
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
WiilValidationError: When validation fails or model not supported
|
|
68
|
+
WiilAPIError: When the API returns an error
|
|
35
69
|
"""
|
|
70
|
+
self._validate_model_configurations(
|
|
71
|
+
data.stt_config,
|
|
72
|
+
data.processing_config,
|
|
73
|
+
data.tts_config
|
|
74
|
+
)
|
|
75
|
+
|
|
36
76
|
return self._http.post(
|
|
37
77
|
self._base_path,
|
|
38
78
|
data.model_dump(by_alias=True, exclude_none=True),
|
|
@@ -40,21 +80,79 @@ class ProvisioningConfigurationsResource:
|
|
|
40
80
|
response_model=ProvisioningConfigChain
|
|
41
81
|
)
|
|
42
82
|
|
|
43
|
-
def
|
|
44
|
-
|
|
83
|
+
def create_translation(
|
|
84
|
+
self,
|
|
85
|
+
data: CreateTranslationChainConfig
|
|
86
|
+
) -> TranslationChainConfig:
|
|
87
|
+
"""Create a new translation configuration chain.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
data: Translation configuration chain data
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
The created translation configuration chain
|
|
94
|
+
|
|
95
|
+
Raises:
|
|
96
|
+
WiilValidationError: When validation fails or model not supported
|
|
97
|
+
WiilAPIError: When the API returns an error
|
|
98
|
+
"""
|
|
99
|
+
self._validate_model_configurations(
|
|
100
|
+
data.stt_config,
|
|
101
|
+
data.processing_config,
|
|
102
|
+
data.tts_config
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
return self._http.post(
|
|
106
|
+
self._base_path,
|
|
107
|
+
data.model_dump(by_alias=True, exclude_none=True),
|
|
108
|
+
schema=CreateTranslationChainConfig,
|
|
109
|
+
response_model=TranslationChainConfig
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def get(
|
|
113
|
+
self,
|
|
114
|
+
config_id: str
|
|
115
|
+
) -> Union[ProvisioningConfigChain, TranslationChainConfig]:
|
|
116
|
+
"""Retrieve a provisioning configuration by ID.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
config_id: Provisioning configuration ID
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
The provisioning configuration chain or translation chain
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
WiilAPIError: When configuration is not found or API error
|
|
126
|
+
"""
|
|
45
127
|
return self._http.get(
|
|
46
128
|
f'{self._base_path}/{config_id}',
|
|
47
129
|
response_model=ProvisioningConfigChain
|
|
48
130
|
)
|
|
49
131
|
|
|
50
|
-
def get_by_chain_name(
|
|
51
|
-
|
|
132
|
+
def get_by_chain_name(
|
|
133
|
+
self,
|
|
134
|
+
chain_name: str
|
|
135
|
+
) -> Union[ProvisioningConfigChain, TranslationChainConfig]:
|
|
136
|
+
"""Retrieve a provisioning configuration by chain name.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
chain_name: Chain name
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
The provisioning configuration chain or translation chain
|
|
143
|
+
|
|
144
|
+
Raises:
|
|
145
|
+
WiilAPIError: When configuration is not found or API error
|
|
146
|
+
"""
|
|
52
147
|
return self._http.get(
|
|
53
148
|
f'{self._base_path}/by-chain-name/{chain_name}',
|
|
54
149
|
response_model=ProvisioningConfigChain
|
|
55
150
|
)
|
|
56
151
|
|
|
57
|
-
def update(
|
|
152
|
+
def update(
|
|
153
|
+
self,
|
|
154
|
+
data: UpdateProvisioningConfig
|
|
155
|
+
) -> ProvisioningConfigChain:
|
|
58
156
|
"""Update an existing provisioning configuration.
|
|
59
157
|
|
|
60
158
|
Args:
|
|
@@ -62,7 +160,17 @@ class ProvisioningConfigurationsResource:
|
|
|
62
160
|
|
|
63
161
|
Returns:
|
|
64
162
|
The updated provisioning configuration chain
|
|
163
|
+
|
|
164
|
+
Raises:
|
|
165
|
+
WiilValidationError: When validation fails or model not supported
|
|
166
|
+
WiilAPIError: When configuration is not found or API error
|
|
65
167
|
"""
|
|
168
|
+
self._validate_model_configurations(
|
|
169
|
+
data.stt_config,
|
|
170
|
+
data.processing_config,
|
|
171
|
+
data.tts_config
|
|
172
|
+
)
|
|
173
|
+
|
|
66
174
|
return self._http.patch(
|
|
67
175
|
self._base_path,
|
|
68
176
|
data.model_dump(by_alias=True, exclude_none=True),
|
|
@@ -71,14 +179,24 @@ class ProvisioningConfigurationsResource:
|
|
|
71
179
|
)
|
|
72
180
|
|
|
73
181
|
def delete(self, config_id: str) -> bool:
|
|
74
|
-
"""Delete a provisioning configuration.
|
|
182
|
+
"""Delete a provisioning configuration.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
config_id: Provisioning configuration ID
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
True if deletion was successful
|
|
189
|
+
|
|
190
|
+
Raises:
|
|
191
|
+
WiilAPIError: When configuration is not found or API error
|
|
192
|
+
"""
|
|
75
193
|
return self._http.delete(f'{self._base_path}/{config_id}')
|
|
76
194
|
|
|
77
195
|
def list(
|
|
78
196
|
self,
|
|
79
197
|
params: Optional[PaginationRequest] = None,
|
|
80
198
|
include_deleted: Optional[bool] = None
|
|
81
|
-
) -> PaginatedResult[ProvisioningConfigChain]:
|
|
199
|
+
) -> PaginatedResult[Union[ProvisioningConfigChain, TranslationChainConfig]]:
|
|
82
200
|
"""List all provisioning configurations with pagination.
|
|
83
201
|
|
|
84
202
|
Args:
|
|
@@ -88,14 +206,16 @@ class ProvisioningConfigurationsResource:
|
|
|
88
206
|
Returns:
|
|
89
207
|
Paginated list of provisioning configurations
|
|
90
208
|
"""
|
|
91
|
-
|
|
209
|
+
query_parts = []
|
|
92
210
|
if params:
|
|
93
|
-
|
|
94
|
-
|
|
211
|
+
if params.page:
|
|
212
|
+
query_parts.append(f'page={params.page}')
|
|
213
|
+
if params.page_size:
|
|
214
|
+
query_parts.append(f'pageSize={params.page_size}')
|
|
95
215
|
if include_deleted is not None:
|
|
96
|
-
|
|
216
|
+
query_parts.append(f'includeDeleted={str(include_deleted).lower()}')
|
|
97
217
|
|
|
98
|
-
query_string =
|
|
218
|
+
query_string = '?' + '&'.join(query_parts) if query_parts else ''
|
|
99
219
|
return self._http.get(
|
|
100
220
|
f'{self._base_path}{query_string}',
|
|
101
221
|
response_model=PaginatedResult[ProvisioningConfigChain]
|
|
@@ -113,16 +233,106 @@ class ProvisioningConfigurationsResource:
|
|
|
113
233
|
Returns:
|
|
114
234
|
Paginated list of provisioning configuration chains
|
|
115
235
|
"""
|
|
116
|
-
|
|
236
|
+
query_parts = []
|
|
117
237
|
if params:
|
|
118
|
-
|
|
119
|
-
|
|
238
|
+
if params.page:
|
|
239
|
+
query_parts.append(f'page={params.page}')
|
|
240
|
+
if params.page_size:
|
|
241
|
+
query_parts.append(f'pageSize={params.page_size}')
|
|
120
242
|
|
|
121
|
-
query_string =
|
|
243
|
+
query_string = '?' + '&'.join(query_parts) if query_parts else ''
|
|
122
244
|
return self._http.get(
|
|
123
245
|
f'{self._base_path}/provisioning{query_string}',
|
|
124
246
|
response_model=PaginatedResult[ProvisioningConfigChain]
|
|
125
247
|
)
|
|
126
248
|
|
|
249
|
+
def list_translation_chains(
|
|
250
|
+
self,
|
|
251
|
+
params: Optional[PaginationRequest] = None
|
|
252
|
+
) -> PaginatedResult[TranslationChainConfig]:
|
|
253
|
+
"""List translation configuration chains with pagination.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
params: Pagination parameters
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
Paginated list of translation configuration chains
|
|
260
|
+
"""
|
|
261
|
+
query_parts = []
|
|
262
|
+
if params:
|
|
263
|
+
if params.page:
|
|
264
|
+
query_parts.append(f'page={params.page}')
|
|
265
|
+
if params.page_size:
|
|
266
|
+
query_parts.append(f'pageSize={params.page_size}')
|
|
267
|
+
|
|
268
|
+
query_string = '?' + '&'.join(query_parts) if query_parts else ''
|
|
269
|
+
return self._http.get(
|
|
270
|
+
f'{self._base_path}/translations{query_string}',
|
|
271
|
+
response_model=PaginatedResult[TranslationChainConfig]
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
def _validate_model_configurations(
|
|
275
|
+
self,
|
|
276
|
+
stt_config: Optional[DynamicSTTModelConfiguration],
|
|
277
|
+
processing_config: Optional[DynamicModelConfiguration],
|
|
278
|
+
tts_config: Optional[DynamicTTSModelConfiguration]
|
|
279
|
+
) -> None:
|
|
280
|
+
"""Validate STT, Processing, and TTS model configs."""
|
|
281
|
+
has_stt = (
|
|
282
|
+
stt_config
|
|
283
|
+
and stt_config.provider_type
|
|
284
|
+
and stt_config.provider_model_id
|
|
285
|
+
)
|
|
286
|
+
if has_stt:
|
|
287
|
+
self._validate_model(
|
|
288
|
+
stt_config.provider_type,
|
|
289
|
+
stt_config.provider_model_id,
|
|
290
|
+
'STT'
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
has_processing = (
|
|
294
|
+
processing_config
|
|
295
|
+
and processing_config.provider_type
|
|
296
|
+
and processing_config.provider_model_id
|
|
297
|
+
)
|
|
298
|
+
if has_processing:
|
|
299
|
+
self._validate_model(
|
|
300
|
+
processing_config.provider_type,
|
|
301
|
+
processing_config.provider_model_id,
|
|
302
|
+
'Processing'
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
has_tts = (
|
|
306
|
+
tts_config
|
|
307
|
+
and tts_config.provider_type
|
|
308
|
+
and tts_config.provider_model_id
|
|
309
|
+
)
|
|
310
|
+
if has_tts:
|
|
311
|
+
self._validate_model(
|
|
312
|
+
tts_config.provider_type,
|
|
313
|
+
tts_config.provider_model_id,
|
|
314
|
+
'TTS'
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
def _validate_model(
|
|
318
|
+
self,
|
|
319
|
+
provider_type: str,
|
|
320
|
+
provider_model_id: str,
|
|
321
|
+
model_type: str
|
|
322
|
+
) -> None:
|
|
323
|
+
"""Validate a single model against the support registry."""
|
|
324
|
+
is_supported = self._http.get(
|
|
325
|
+
f'/support-models/supports/{provider_type}/{provider_model_id}',
|
|
326
|
+
response_model=bool
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
if not is_supported:
|
|
330
|
+
msg = (
|
|
331
|
+
f'Unsupported {model_type} model: '
|
|
332
|
+
f'{provider_type}/{provider_model_id}. '
|
|
333
|
+
f'Verify the model is available in the support registry.'
|
|
334
|
+
)
|
|
335
|
+
raise WiilValidationError(msg)
|
|
336
|
+
|
|
127
337
|
|
|
128
338
|
__all__ = ['ProvisioningConfigurationsResource']
|
|
@@ -295,5 +295,36 @@ class SupportModelsResource:
|
|
|
295
295
|
response_model=WiilSupportModel
|
|
296
296
|
)
|
|
297
297
|
|
|
298
|
+
def is_supported(
|
|
299
|
+
self,
|
|
300
|
+
proprietor: str,
|
|
301
|
+
provider_model_id: str
|
|
302
|
+
) -> bool:
|
|
303
|
+
"""Check if a model is supported by proprietor and provider model ID.
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
proprietor: Model proprietor (e.g., 'OpenAI', 'Anthropic', 'Deepgram')
|
|
307
|
+
provider_model_id: Provider-specific model identifier (e.g., 'gpt-4-turbo')
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
True if the model is supported, False otherwise
|
|
311
|
+
|
|
312
|
+
Raises:
|
|
313
|
+
WiilAPIError: When the API returns an error
|
|
314
|
+
WiilNetworkError: When network communication fails
|
|
315
|
+
|
|
316
|
+
Example:
|
|
317
|
+
>>> # Check if a specific model is supported
|
|
318
|
+
>>> is_supported = client.support_models.is_supported('OpenAI', 'gpt-4-turbo')
|
|
319
|
+
>>> if is_supported:
|
|
320
|
+
... print('Model is supported')
|
|
321
|
+
>>> else:
|
|
322
|
+
... print('Model is not supported')
|
|
323
|
+
"""
|
|
324
|
+
return self._http.get(
|
|
325
|
+
f'{self._base_path}/supports/{proprietor}/{provider_model_id}',
|
|
326
|
+
response_model=bool
|
|
327
|
+
)
|
|
328
|
+
|
|
298
329
|
|
|
299
330
|
__all__ = ['SupportModelsResource']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wiil-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: Official Python SDK for WIIL Platform - AI-powered conversational services for intelligent customer interactions, voice processing, real-time translation, and business management
|
|
5
5
|
Author-email: WIIL <dev-support@wiil.io>
|
|
6
6
|
License: MIT
|
|
@@ -32,7 +32,7 @@ wiil/models/business_mgt/property_config.py,sha256=8WEo15nrwZ5TuywwZhjHYFLCQFtm7
|
|
|
32
32
|
wiil/models/business_mgt/property_inquiry.py,sha256=-b0TF_IkyGngz70c1J25BXTq38_XErWT_AT0ZIbkNKE,13424
|
|
33
33
|
wiil/models/business_mgt/reservation.py,sha256=VB0K0H-t4Boxnc1llV0UlTVGF5tAM6mrLi-LGqxSKds,11243
|
|
34
34
|
wiil/models/business_mgt/reservation_resource.py,sha256=zaM2kdcVUPnRFPfbKm3vgfRz96qdjCSX3wiYxuHZGAo,11207
|
|
35
|
-
wiil/models/business_mgt/service_appointment.py,sha256=
|
|
35
|
+
wiil/models/business_mgt/service_appointment.py,sha256=7H0bKx5utYa5SaT66ghr16WiiSJnwfY6ShbU8aNsdS0,7678
|
|
36
36
|
wiil/models/business_mgt/service_config.py,sha256=XiOLJheAOvz8up2Mc5Dl0GYUwVn1IxI2JhLQSVmoqv4,6294
|
|
37
37
|
wiil/models/business_mgt/service_person.py,sha256=QOGTjtUYhiWSitUGo_VdfvduQnOdukRP7h6Eg0wWuQc,3024
|
|
38
38
|
wiil/models/conversation/__init__.py,sha256=J_JngMg-IBUDQL5a_s-7UKiGx0E4WoDr8fJkJod_-yI,2496
|
|
@@ -84,19 +84,19 @@ wiil/resources/business_mgt/property_inquiry.py,sha256=AxYqP9WWsQIVTneuWu0-TmkHS
|
|
|
84
84
|
wiil/resources/business_mgt/reservation_resources.py,sha256=zcWCoFJvAX1tbFQCMIQAjJjKUsl1TBCeGedpq8rxjNk,5240
|
|
85
85
|
wiil/resources/business_mgt/reservations.py,sha256=f4JoZDeusXUa9CTe2heY8jPkK-AZmCe0J-WaLl4hhsA,5927
|
|
86
86
|
wiil/resources/business_mgt/service_appointments.py,sha256=w-75Y3xOt7bSGyiJsvTS5Mad13MPMblPtFBcY85KovM,4828
|
|
87
|
-
wiil/resources/service_mgt/__init__.py,sha256=
|
|
87
|
+
wiil/resources/service_mgt/__init__.py,sha256=tmAhy3YrMwykNqzsAAWHlBHXhejv9QmsLBjB22XvZ8c,2077
|
|
88
88
|
wiil/resources/service_mgt/agent_configs.py,sha256=1rGjV3-maYy0vbGKu4J5sWSrrXojgJ9gjFkDBPDQ3IU,3034
|
|
89
89
|
wiil/resources/service_mgt/conversation_configs.py,sha256=Fhlqz0dRg0iiM5PVdfI7yLs4oRfgouo4_nQYk9DSfEM,1913
|
|
90
90
|
wiil/resources/service_mgt/deployment_channels.py,sha256=rw7dMasphgyR8fTcqaPGfVnLLvMH0EB-MBVqhQE4Do8,4504
|
|
91
91
|
wiil/resources/service_mgt/deployment_configs.py,sha256=OJynzPRNUbLBNzHgaRbUhaBN8ozENXBtS-yWzPILDvg,6153
|
|
92
|
-
wiil/resources/service_mgt/dynamic_agent_status.py,sha256=
|
|
93
|
-
wiil/resources/service_mgt/dynamic_phone_agent.py,sha256=
|
|
94
|
-
wiil/resources/service_mgt/dynamic_web_agent.py,sha256=
|
|
92
|
+
wiil/resources/service_mgt/dynamic_agent_status.py,sha256=Ksx1RtiZB3zxV3KjygCqIdVSFSq0rJyq1XHTht-Z5q8,1381
|
|
93
|
+
wiil/resources/service_mgt/dynamic_phone_agent.py,sha256=_agPadUIFqKDRJ6SgV26d06OvGPfIIrdTLTk2XFBLJg,11002
|
|
94
|
+
wiil/resources/service_mgt/dynamic_web_agent.py,sha256=gwewZU1ColpLVZ0CGlnRUW_MZjCSLq6vTaG7E25hBFU,11290
|
|
95
95
|
wiil/resources/service_mgt/instruction_configs.py,sha256=uTIiRiEkHXtfekbO8m9kYPbfcBk2LP4crAjFU4UANOE,3655
|
|
96
96
|
wiil/resources/service_mgt/knowledge_sources.py,sha256=I7kTf7mf6bW59Sm4iq4HrQbVraASsnySVTP67qeCSGM,1754
|
|
97
97
|
wiil/resources/service_mgt/phone_configs.py,sha256=8Vwq6C2HateV-w1jkxziyaXccL2xSKCxGc8aZCn9Mdg,3084
|
|
98
|
-
wiil/resources/service_mgt/provisioning_configs.py,sha256=
|
|
99
|
-
wiil/resources/service_mgt/support_models.py,sha256=
|
|
98
|
+
wiil/resources/service_mgt/provisioning_configs.py,sha256=DnppwQ7Y7nBKiRukYJZ1o8OuYsX7dfckgyl_wFldmlE,11179
|
|
99
|
+
wiil/resources/service_mgt/support_models.py,sha256=itiiyEpkbAJw12XX6px8Q0fkwx2piBpI0GkxwiLaH7Y,12410
|
|
100
100
|
wiil/resources/service_mgt/telephony_provider.py,sha256=VOqp7eXj9mee0YzIrWvdv8Dgwhc9jhcn7bRxtxvIzdE,8037
|
|
101
101
|
wiil/resources/service_mgt/translation_sessions.py,sha256=GALso78qvQbMWI7mzc3BZ6FmPkb7k-jJfuguYws06e8,1809
|
|
102
102
|
wiil/services/__init__.py,sha256=lZZQj2KpsExUrt4dKmSsBxH4_HMnaPkJBpT1txUZmNU,758
|
|
@@ -114,7 +114,7 @@ wiil/types/knowledge_types.py,sha256=DUVh8VbzUMljo0DQg1BjBdXReWHMX1yKmjoXIDWOLXM
|
|
|
114
114
|
wiil/types/paginated_quest.py,sha256=SMnCvPbiWe0df13nxmQfEFa_bXeg7DzGuN-Ah1eNYO0,1785
|
|
115
115
|
wiil/types/paginated_result.py,sha256=nCbHbPsjbnuwFjtLd7RBLezlKY0S3CfYVxASB2gTUl0,5311
|
|
116
116
|
wiil/types/service_types.py,sha256=-F41Nb_95uuZf3Jau8IETpgcbzHzmC3M8ysy93UXMEI,5091
|
|
117
|
-
wiil_python-0.0.
|
|
118
|
-
wiil_python-0.0.
|
|
119
|
-
wiil_python-0.0.
|
|
120
|
-
wiil_python-0.0.
|
|
117
|
+
wiil_python-0.0.4.dist-info/METADATA,sha256=O5Iv07egaTCVOR980LyiLW9qIB6kh1BI_dMorRKXO6U,19073
|
|
118
|
+
wiil_python-0.0.4.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
119
|
+
wiil_python-0.0.4.dist-info/top_level.txt,sha256=8CizIxlMF7XuxJQVlzf2UMy2JH4f0-hYO5fntuRQkx4,5
|
|
120
|
+
wiil_python-0.0.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|